CellTriggersTool.cs (8640B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // The Command & Conquer Map Editor and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // The Command & Conquer Map Editor and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 using MobiusEditor.Controls; 16 using MobiusEditor.Event; 17 using MobiusEditor.Interface; 18 using MobiusEditor.Model; 19 using MobiusEditor.Utility; 20 using MobiusEditor.Widgets; 21 using System.Collections.Generic; 22 using System.Drawing; 23 using System.Windows.Forms; 24 25 namespace MobiusEditor.Tools 26 { 27 public class CellTriggersTool : ViewTool 28 { 29 private readonly ComboBox triggerCombo; 30 31 private readonly Dictionary<int, CellTrigger> undoCellTriggers = new Dictionary<int, CellTrigger>(); 32 private readonly Dictionary<int, CellTrigger> redoCellTriggers = new Dictionary<int, CellTrigger>(); 33 34 private bool placementMode; 35 36 public CellTriggersTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, ComboBox triggerCombo, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url) 37 : base(mapPanel, layers, statusLbl, plugin, url) 38 { 39 this.mapPanel.MouseDown += MapPanel_MouseDown; 40 this.mapPanel.MouseUp += MapPanel_MouseUp; 41 this.mapPanel.MouseMove += MapPanel_MouseMove; 42 (this.mapPanel as Control).KeyDown += WaypointsTool_KeyDown; 43 (this.mapPanel as Control).KeyUp += WaypointsTool_KeyUp; 44 45 this.triggerCombo = triggerCombo; 46 47 navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged; 48 49 UpdateStatus(); 50 } 51 52 private void MapPanel_MouseDown(object sender, MouseEventArgs e) 53 { 54 if (placementMode) 55 { 56 if (e.Button == MouseButtons.Left) 57 { 58 SetCellTrigger(navigationWidget.MouseCell); 59 } 60 else if (e.Button == MouseButtons.Right) 61 { 62 RemoveCellTrigger(navigationWidget.MouseCell); 63 } 64 } 65 else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right)) 66 { 67 PickCellTrigger(navigationWidget.MouseCell); 68 } 69 } 70 71 private void MapPanel_MouseUp(object sender, MouseEventArgs e) 72 { 73 if ((undoCellTriggers.Count > 0) || (redoCellTriggers.Count > 0)) 74 { 75 CommitChange(); 76 } 77 } 78 79 private void WaypointsTool_KeyDown(object sender, KeyEventArgs e) 80 { 81 if (e.KeyCode == Keys.ShiftKey) 82 { 83 EnterPlacementMode(); 84 } 85 } 86 87 private void WaypointsTool_KeyUp(object sender, KeyEventArgs e) 88 { 89 if (e.KeyCode == Keys.ShiftKey) 90 { 91 ExitPlacementMode(); 92 } 93 } 94 95 private void MapPanel_MouseMove(object sender, MouseEventArgs e) 96 { 97 if (!placementMode && (Control.ModifierKeys == Keys.Shift)) 98 { 99 EnterPlacementMode(); 100 } 101 else if (placementMode && (Control.ModifierKeys == Keys.None)) 102 { 103 ExitPlacementMode(); 104 } 105 106 107 } 108 109 private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e) 110 { 111 if (placementMode) 112 { 113 if (Control.MouseButtons == MouseButtons.Left) 114 { 115 SetCellTrigger(e.NewCell); 116 } 117 else if (Control.MouseButtons == MouseButtons.Right) 118 { 119 RemoveCellTrigger(e.NewCell); 120 } 121 } 122 } 123 124 private void SetCellTrigger(Point location) 125 { 126 if (map.Metrics.GetCell(location, out int cell)) 127 { 128 if (map.CellTriggers[cell] == null) 129 { 130 if (!undoCellTriggers.ContainsKey(cell)) 131 { 132 undoCellTriggers[cell] = map.CellTriggers[cell]; 133 } 134 135 var cellTrigger = new CellTrigger { Trigger = triggerCombo.SelectedItem as string }; 136 map.CellTriggers[cell] = cellTrigger; 137 redoCellTriggers[cell] = cellTrigger; 138 139 mapPanel.Invalidate(); 140 141 plugin.Dirty = true; 142 } 143 } 144 } 145 146 private void RemoveCellTrigger(Point location) 147 { 148 if (map.Metrics.GetCell(location, out int cell)) 149 { 150 var cellTrigger = map.CellTriggers[cell]; 151 if (cellTrigger != null) 152 { 153 if (!undoCellTriggers.ContainsKey(cell)) 154 { 155 undoCellTriggers[cell] = map.CellTriggers[cell]; 156 } 157 158 map.CellTriggers[cell] = null; 159 redoCellTriggers[cell] = null; 160 161 mapPanel.Invalidate(); 162 163 plugin.Dirty = true; 164 } 165 } 166 } 167 168 private void EnterPlacementMode() 169 { 170 if (placementMode) 171 { 172 return; 173 } 174 175 placementMode = true; 176 177 UpdateStatus(); 178 } 179 180 private void ExitPlacementMode() 181 { 182 if (!placementMode) 183 { 184 return; 185 } 186 187 placementMode = false; 188 189 UpdateStatus(); 190 } 191 192 private void PickCellTrigger(Point location) 193 { 194 if (map.Metrics.GetCell(location, out int cell)) 195 { 196 var cellTrigger = map.CellTriggers[cell]; 197 if (cellTrigger != null) 198 { 199 triggerCombo.SelectedItem = cellTrigger.Trigger; 200 } 201 } 202 } 203 204 private void CommitChange() 205 { 206 var undoCellTriggers2 = new Dictionary<int, CellTrigger>(undoCellTriggers); 207 void undoAction(UndoRedoEventArgs e) 208 { 209 foreach (var kv in undoCellTriggers2) 210 { 211 e.Map.CellTriggers[kv.Key] = kv.Value; 212 } 213 e.MapPanel.Invalidate(); 214 } 215 216 var redoCellTriggers2 = new Dictionary<int, CellTrigger>(redoCellTriggers); 217 void redoAction(UndoRedoEventArgs e) 218 { 219 foreach (var kv in redoCellTriggers2) 220 { 221 e.Map.CellTriggers[kv.Key] = kv.Value; 222 } 223 e.MapPanel.Invalidate(); 224 } 225 226 undoCellTriggers.Clear(); 227 redoCellTriggers.Clear(); 228 229 url.Track(undoAction, redoAction); 230 } 231 232 private void UpdateStatus() 233 { 234 if (placementMode) 235 { 236 statusLbl.Text = "Left-Click to set cell trigger, Right-Click to clear cell trigger"; 237 } 238 else 239 { 240 statusLbl.Text = "Shift to enter placement mode, Left-Click or Right-Click to pick cell trigger"; 241 } 242 } 243 244 #region IDisposable Support 245 private bool disposedValue = false; 246 247 protected override void Dispose(bool disposing) 248 { 249 if (!disposedValue) 250 { 251 if (disposing) 252 { 253 mapPanel.MouseDown -= MapPanel_MouseDown; 254 mapPanel.MouseUp -= MapPanel_MouseUp; 255 mapPanel.MouseMove -= MapPanel_MouseMove; 256 (mapPanel as Control).KeyDown -= WaypointsTool_KeyDown; 257 (mapPanel as Control).KeyUp -= WaypointsTool_KeyUp; 258 259 navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged; 260 } 261 disposedValue = true; 262 } 263 264 base.Dispose(disposing); 265 } 266 #endregion 267 } 268 }