WaypointsTool.cs (7510B)
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; 22 using System.Drawing; 23 using System.Linq; 24 using System.Windows.Forms; 25 26 namespace MobiusEditor.Tools 27 { 28 public class WaypointsTool : ViewTool 29 { 30 private readonly ComboBox waypointCombo; 31 32 private (Waypoint waypoint, int? cell)? undoWaypoint; 33 private (Waypoint waypoint, int? cell)? redoWaypoint; 34 35 private bool placementMode; 36 37 public WaypointsTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, ComboBox waypointCombo, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url) 38 : base(mapPanel, layers, statusLbl, plugin, url) 39 { 40 this.mapPanel.MouseDown += MapPanel_MouseDown; 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.waypointCombo = waypointCombo; 46 47 UpdateStatus(); 48 } 49 50 private void MapPanel_MouseDown(object sender, MouseEventArgs e) 51 { 52 if (placementMode) 53 { 54 if (e.Button == MouseButtons.Left) 55 { 56 SetWaypoint(navigationWidget.MouseCell); 57 } 58 else if (e.Button == MouseButtons.Right) 59 { 60 RemoveWaypoint(navigationWidget.MouseCell); 61 } 62 } 63 else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right)) 64 { 65 PickWaypoint(navigationWidget.MouseCell); 66 } 67 } 68 69 private void WaypointsTool_KeyDown(object sender, KeyEventArgs e) 70 { 71 if (e.KeyCode == Keys.ShiftKey) 72 { 73 EnterPlacementMode(); 74 } 75 } 76 77 private void WaypointsTool_KeyUp(object sender, KeyEventArgs e) 78 { 79 if (e.KeyCode == Keys.ShiftKey) 80 { 81 ExitPlacementMode(); 82 } 83 } 84 85 private void MapPanel_MouseMove(object sender, MouseEventArgs e) 86 { 87 if (!placementMode && (Control.ModifierKeys == Keys.Shift)) 88 { 89 EnterPlacementMode(); 90 } 91 else if (placementMode && (Control.ModifierKeys == Keys.None)) 92 { 93 ExitPlacementMode(); 94 } 95 } 96 97 private void SetWaypoint(Point location) 98 { 99 if (map.Metrics.GetCell(location, out int cell)) 100 { 101 var waypoint = map.Waypoints[waypointCombo.SelectedIndex]; 102 if (waypoint.Cell != cell) 103 { 104 if (undoWaypoint == null) 105 { 106 undoWaypoint = (waypoint, waypoint.Cell); 107 } 108 else if (undoWaypoint.Value.cell == cell) 109 { 110 undoWaypoint = null; 111 } 112 113 waypoint.Cell = cell; 114 redoWaypoint = (waypoint, waypoint.Cell); 115 116 CommitChange(); 117 118 mapPanel.Invalidate(); 119 120 plugin.Dirty = true; 121 } 122 } 123 } 124 125 private void RemoveWaypoint(Point location) 126 { 127 if (map.Metrics.GetCell(location, out int cell)) 128 { 129 var waypoint = map.Waypoints.Where(w => w.Cell == cell).FirstOrDefault(); 130 if (waypoint != null) 131 { 132 if (undoWaypoint == null) 133 { 134 undoWaypoint = (waypoint, waypoint.Cell); 135 } 136 137 waypoint.Cell = null; 138 redoWaypoint = (waypoint, null); 139 140 CommitChange(); 141 142 mapPanel.Invalidate(); 143 144 plugin.Dirty = true; 145 } 146 } 147 } 148 149 private void EnterPlacementMode() 150 { 151 if (placementMode) 152 { 153 return; 154 } 155 156 placementMode = true; 157 158 UpdateStatus(); 159 } 160 161 private void ExitPlacementMode() 162 { 163 if (!placementMode) 164 { 165 return; 166 } 167 168 placementMode = false; 169 170 UpdateStatus(); 171 } 172 173 private void PickWaypoint(Point location) 174 { 175 if (map.Metrics.GetCell(location, out int cell)) 176 { 177 for (var i = 0; i < map.Waypoints.Length; ++i) 178 { 179 if (map.Waypoints[i].Cell == cell) 180 { 181 waypointCombo.SelectedIndex = i; 182 break; 183 } 184 } 185 } 186 } 187 188 private void CommitChange() 189 { 190 var undoWaypoint2 = undoWaypoint; 191 void undoAction(UndoRedoEventArgs e) 192 { 193 undoWaypoint2.Value.waypoint.Cell = undoWaypoint2.Value.cell; 194 mapPanel.Invalidate(); 195 } 196 197 var redoWaypoint2 = redoWaypoint; 198 void redoAction(UndoRedoEventArgs e) 199 { 200 redoWaypoint2.Value.waypoint.Cell = redoWaypoint2.Value.cell; 201 mapPanel.Invalidate(); 202 } 203 204 undoWaypoint = null; 205 redoWaypoint = null; 206 207 url.Track(undoAction, redoAction); 208 } 209 210 private void UpdateStatus() 211 { 212 if (placementMode) 213 { 214 statusLbl.Text = "Left-Click to set cell waypoint, Right-Click to clear cell waypoint"; 215 } 216 else 217 { 218 statusLbl.Text = "Shift to enter placement mode, Left-Click or Right-Click to pick cell waypoint"; 219 } 220 } 221 222 #region IDisposable Support 223 private bool disposedValue = false; 224 225 protected override void Dispose(bool disposing) 226 { 227 if (!disposedValue) 228 { 229 if (disposing) 230 { 231 mapPanel.MouseDown -= MapPanel_MouseDown; 232 mapPanel.MouseMove -= MapPanel_MouseMove; 233 (mapPanel as Control).KeyDown -= WaypointsTool_KeyDown; 234 (mapPanel as Control).KeyUp -= WaypointsTool_KeyUp; 235 } 236 disposedValue = true; 237 } 238 239 base.Dispose(disposing); 240 } 241 #endregion 242 } 243 }