CellTriggersTool.cs 8.4 KB

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