StateChartEditorWindow.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEditor;
  6. namespace StateChartEditor{
  7. public class StateChartEditorWindow : EditorWindow
  8. {
  9. Vector2 current_mouse_position = Vector3.zero;
  10. Vector2 mouse_converted = Vector3.zero;
  11. List<Node> states = new List<Node>();
  12. List<Edge> edges = new List<Edge>();
  13. Rect draw_area;
  14. Rect tool_area;
  15. Rect total_draw_area = new Rect(0,0,0,0);
  16. Vector2 scroll_position = Vector2.zero;
  17. Rect without_scroll_bars;
  18. Node selected = null;
  19. public bool mouse_is_down { get; private set; }
  20. public bool get_mouse_outside_window { get; private set; }
  21. bool dragging = false;
  22. enum TopMode { Select ,
  23. Connect,
  24. Draw};
  25. enum DrawMode { Basic,
  26. Composite};
  27. string[] top_mode_string_array = Enum.GetValues(typeof(TopMode)).Cast<TopMode>().Select(value => ( Enum.GetName(typeof(TopMode), value))).ToArray();
  28. string[] draw_mode_string_array = Enum.GetValues(typeof(DrawMode)).Cast<DrawMode>().Select(value => ( Enum.GetName(typeof(DrawMode), value))).ToArray();
  29. int selected_top_mode = (int)TopMode.Select;
  30. int selected_draw_mode = (int)DrawMode.Basic;
  31. [MenuItem("Window/StateChartEditor")]
  32. public static void Init()
  33. {
  34. StateChartEditorWindow window = (StateChartEditorWindow) EditorWindow.GetWindow(typeof(StateChartEditorWindow),false);
  35. window.wantsMouseMove = true;
  36. window.title = "StateChart Editor";
  37. //UnityEngine.Object.DontDestroyOnLoad( window );
  38. }
  39. public StateChartEditorWindow()
  40. {
  41. this.mouse_is_down = false;
  42. this.get_mouse_outside_window = false;
  43. }
  44. private void drawStateChart()
  45. {
  46. for(int i = 0; i < states.Count; i++){
  47. if (!states[i].selected){
  48. states[i].draw();
  49. }
  50. }
  51. if(selected != null){
  52. selected.draw ();
  53. }
  54. DrawEdges();
  55. }
  56. public Vector2 convertCoordsToChart(Vector2 coords){
  57. return coords - this.draw_area.TopLeft() + this.total_draw_area.TopLeft () + this.scroll_position;
  58. }
  59. /// <summary>
  60. /// If scrollbars are added to the draw area, we don't want to use clicks on the scrollbars.
  61. /// So a new Rect gets created for checking clicks, taking into account the scrollbars.
  62. /// </summary>
  63. private void calculateWithoutScrollBars()
  64. {
  65. this.without_scroll_bars = new Rect (this.draw_area.x,
  66. this.draw_area.y,
  67. this.draw_area.width,
  68. this.draw_area.height);
  69. if (this.total_draw_area.width > this.draw_area.width){
  70. this.without_scroll_bars.width -= GUI.skin.GetStyle("verticalscrollbar").fixedWidth;
  71. }
  72. if (this.total_draw_area.height > this.draw_area.height){
  73. this.without_scroll_bars.height -= GUI.skin.GetStyle("horizontalscrollbar").fixedHeight;
  74. }
  75. }
  76. private void handleEvents()
  77. {
  78. this.calculateWithoutScrollBars();
  79. if (Event.current.button == 0)
  80. {
  81. if(Event.current.type == EventType.MouseDown)
  82. {
  83. this.mouse_is_down = true;
  84. checkDrawAreaLeftClick();
  85. this.get_mouse_outside_window = true;
  86. }
  87. else if(Event.current.rawType == EventType.MouseUp)
  88. {
  89. this.mouse_is_down = false;
  90. this.dragging = false;
  91. }
  92. else if (Event.current.type == EventType.mouseDrag && (this.dragging))
  93. {
  94. this.selected.move(Event.current.delta);
  95. Event.current.Use();
  96. }
  97. }
  98. }
  99. public void unSelect()
  100. {
  101. if(selected != null)
  102. {
  103. selected.unSelect();
  104. selected = null;
  105. }
  106. }
  107. private void checkDrawAreaLeftClick()
  108. {
  109. if (this.without_scroll_bars.Contains(this.current_mouse_position) )
  110. {
  111. //Modes that make use of the previous selection
  112. if (this.selected_top_mode == (int)TopMode.Connect)
  113. {
  114. Node clicked = this.catchNodeClick();
  115. if(clicked != null && selected != null)
  116. {
  117. this.addEdge(selected,clicked);
  118. unSelect ();
  119. }
  120. else if(clicked != null)
  121. {
  122. clicked.setSelected();
  123. selected = clicked;
  124. }
  125. return;
  126. }
  127. //Previous selection no longer needed
  128. this.unSelect ();
  129. if (this.selected_top_mode == (int)TopMode.Select )
  130. {
  131. Node clicked = this.catchNodeClick();
  132. if(clicked != null)
  133. {
  134. clicked.setSelected();
  135. this.selected = clicked;
  136. this.dragging = true;
  137. }
  138. }
  139. else if(this.selected_top_mode == (int)TopMode.Draw)
  140. {
  141. this.states.Add( new Node(this.mouse_converted,"State" + (states.Count).ToString() ));
  142. Event.current.Use();
  143. }
  144. }
  145. }
  146. public void addEdge(Node start, Node end)
  147. {
  148. Debug.Log ("edge added");
  149. Edge newEdge = new Edge(start,end);
  150. start.addOutput(newEdge);
  151. end.addInput(newEdge);
  152. this.edges.Add (newEdge);
  153. }
  154. private Node catchNodeClick()
  155. {
  156. for(int i = 0; i < states.Count; i++)
  157. {
  158. if (states[i].checkMouseOver(this.mouse_converted))
  159. return states[i];
  160. }
  161. return null;
  162. }
  163. private void drawToolArea()
  164. {
  165. GUILayout.BeginArea (this.tool_area,"","box");
  166. GUILayout.BeginVertical();
  167. this.selected_top_mode = GUILayout.SelectionGrid(this.selected_top_mode, this.top_mode_string_array, 1);
  168. if (this.selected_top_mode == (int)TopMode.Draw)
  169. this.selected_draw_mode = GUILayout.SelectionGrid(this.selected_draw_mode, this.draw_mode_string_array, 2, "toggle");
  170. GUILayout.EndVertical();
  171. GUILayout.EndArea ();
  172. }
  173. private void drawDrawArea()
  174. {
  175. this.calculateScreen ();
  176. this.scroll_position = GUI.BeginScrollView (this.draw_area, this.scroll_position, this.total_draw_area);
  177. this.drawStateChart();
  178. GUI.EndScrollView();
  179. }
  180. public void OnGUI()
  181. {
  182. this.current_mouse_position.x = Event.current.mousePosition.x;
  183. this.current_mouse_position.y = Event.current.mousePosition.y;
  184. this.mouse_converted = convertCoordsToChart(this.current_mouse_position);
  185. this.tool_area = new Rect(0,0,200,Screen.height-22);
  186. this.draw_area = new Rect(200,0,Screen.width-200,Screen.height-22);
  187. this.handleEvents ();
  188. this.drawToolArea();
  189. this.drawDrawArea();
  190. }
  191. private void calculateScreen()
  192. {
  193. float xMin = 0;
  194. float yMin = 0;
  195. float xMax = this.draw_area.width;
  196. float yMax = this.draw_area.height;
  197. foreach(var state in states)
  198. {
  199. if (state.rect.xMin < xMin) xMin = state.rect.xMin;
  200. if (state.rect.yMin < yMin) yMin = state.rect.yMin;
  201. if (state.rect.xMax > xMax) xMax = state.rect.xMax;
  202. if (state.rect.yMax > yMax) yMax = state.rect.yMax;
  203. }
  204. this.total_draw_area.Set (xMin,yMin,xMax-xMin, yMax-yMin);
  205. }
  206. private void DrawEdges()
  207. {
  208. for(int i = 0; i < edges.Count; i++)
  209. edges[i].draw();
  210. if (this.selected != null && this.selected_top_mode == (int)TopMode.Connect)
  211. MyTools.drawLine(selected.getPos(), this.mouse_converted);
  212. //Handles.EndGUI();
  213. }
  214. private void moveAutonomous()
  215. {
  216. if (!this.dragging && this.selected != null)
  217. this.selected.move( new Vector2(1,1));
  218. }
  219. public void Update()
  220. {
  221. this.moveAutonomous();
  222. this.Repaint ();
  223. }
  224. }
  225. }