No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FlowStateWidget.cs 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor;
  5. using UnityEngine;
  6. namespace Unity.VisualScripting
  7. {
  8. [Widget(typeof(FlowState))]
  9. public sealed class FlowStateWidget : NesterStateWidget<FlowState>, IDragAndDropHandler
  10. {
  11. public FlowStateWidget(StateCanvas canvas, FlowState state) : base(canvas, state)
  12. {
  13. state.nest.beforeGraphChange += BeforeGraphChange;
  14. state.nest.afterGraphChange += AfterGraphChange;
  15. if (state.nest.graph != null)
  16. {
  17. state.nest.graph.elements.CollectionChanged += CacheEventLinesOnUnityThread;
  18. }
  19. }
  20. public override void Dispose()
  21. {
  22. base.Dispose();
  23. state.nest.beforeGraphChange -= BeforeGraphChange;
  24. state.nest.afterGraphChange -= AfterGraphChange;
  25. }
  26. private void BeforeGraphChange()
  27. {
  28. if (state.nest.graph != null)
  29. {
  30. state.nest.graph.elements.CollectionChanged -= CacheEventLinesOnUnityThread;
  31. }
  32. }
  33. private void AfterGraphChange()
  34. {
  35. CacheEventLinesOnUnityThread();
  36. if (state.nest.graph != null)
  37. {
  38. state.nest.graph.elements.CollectionChanged += CacheEventLinesOnUnityThread;
  39. }
  40. }
  41. #region Model
  42. private List<EventLine> eventLines { get; } = new List<EventLine>();
  43. private void CacheEventLinesOnUnityThread()
  44. {
  45. UnityAPI.Async(CacheEventLines);
  46. }
  47. private void CacheEventLines()
  48. {
  49. eventLines.Clear();
  50. if (state.nest.graph != null)
  51. {
  52. eventLines.AddRange(state.nest.graph.units
  53. .OfType<IEventUnit>()
  54. .Select(e => e.GetType())
  55. .Distinct()
  56. .Select(eventType => new EventLine(eventType))
  57. .OrderBy(eventLine => eventLine.content.text));
  58. }
  59. Reposition();
  60. }
  61. protected override void CacheItemFirstTime()
  62. {
  63. base.CacheItemFirstTime();
  64. CacheEventLines();
  65. }
  66. #endregion
  67. #region Positioning
  68. public Dictionary<EventLine, Rect> eventLinesPositions { get; } = new Dictionary<EventLine, Rect>();
  69. public override void CachePosition()
  70. {
  71. base.CachePosition();
  72. eventLinesPositions.Clear();
  73. var y = contentInnerPosition.y;
  74. foreach (var eventLine in eventLines)
  75. {
  76. var eventLinePosition = new Rect
  77. (
  78. contentInnerPosition.x,
  79. y,
  80. contentInnerPosition.width,
  81. eventLine.GetHeight(contentInnerPosition.width)
  82. );
  83. eventLinesPositions.Add(eventLine, eventLinePosition);
  84. y += eventLinePosition.height;
  85. }
  86. }
  87. protected override float GetContentHeight(float width)
  88. {
  89. var eventLinesHeight = 0f;
  90. foreach (var eventLine in eventLines)
  91. {
  92. eventLinesHeight += eventLine.GetHeight(width);
  93. }
  94. return eventLinesHeight;
  95. }
  96. #endregion
  97. #region Drawing
  98. protected override bool showContent => eventLines.Count > 0;
  99. protected override void DrawContent()
  100. {
  101. foreach (var eventLine in eventLines)
  102. {
  103. eventLine.Draw(eventLinesPositions[eventLine]);
  104. }
  105. }
  106. #endregion
  107. #region Drag & Drop
  108. public DragAndDropVisualMode dragAndDropVisualMode => DragAndDropVisualMode.Generic;
  109. public bool AcceptsDragAndDrop()
  110. {
  111. return DragAndDropUtility.Is<ScriptGraphAsset>();
  112. }
  113. public void PerformDragAndDrop()
  114. {
  115. UndoUtility.RecordEditedObject("Drag & Drop Macro");
  116. state.nest.source = GraphSource.Macro;
  117. state.nest.macro = DragAndDropUtility.Get<ScriptGraphAsset>();
  118. state.nest.embed = null;
  119. GUI.changed = true;
  120. }
  121. public void UpdateDragAndDrop() { }
  122. public void DrawDragAndDropPreview()
  123. {
  124. GraphGUI.DrawDragAndDropPreviewLabel(new Vector2(edgePosition.x, outerPosition.yMax), "Replace with: " + DragAndDropUtility.Get<ScriptGraphAsset>().name, typeof(ScriptGraphAsset).Icon());
  125. }
  126. public void ExitDragAndDrop() { }
  127. #endregion
  128. public new static class Styles
  129. {
  130. static Styles()
  131. {
  132. eventLine = new GUIStyle(EditorStyles.label);
  133. eventLine.wordWrap = true;
  134. eventLine.imagePosition = ImagePosition.TextOnly; // The icon is drawn manually
  135. eventLine.padding = new RectOffset(0, 0, 3, 3);
  136. }
  137. public static readonly GUIStyle eventLine;
  138. public static readonly float spaceAroundLineIcon = 5;
  139. }
  140. public class EventLine
  141. {
  142. public EventLine(Type eventType)
  143. {
  144. content = new GUIContent(BoltFlowNameUtility.UnitTitle(eventType, false, true), eventType.Icon()?[IconSize.Small]);
  145. }
  146. public GUIContent content { get; }
  147. public float GetHeight(float width)
  148. {
  149. var labelWidth = width - Styles.spaceAroundLineIcon - IconSize.Small - Styles.spaceAroundLineIcon;
  150. return Styles.eventLine.CalcHeight(content, labelWidth);
  151. }
  152. public void Draw(Rect position)
  153. {
  154. var iconPosition = new Rect
  155. (
  156. position.x + Styles.spaceAroundLineIcon,
  157. position.y + Styles.eventLine.padding.top - 1,
  158. IconSize.Small,
  159. IconSize.Small
  160. );
  161. var labelPosition = new Rect
  162. (
  163. iconPosition.xMax + Styles.spaceAroundLineIcon,
  164. position.y,
  165. position.width - Styles.spaceAroundLineIcon - iconPosition.width - Styles.spaceAroundLineIcon,
  166. position.height
  167. );
  168. if (content.image != null)
  169. {
  170. GUI.DrawTexture(iconPosition, content.image);
  171. }
  172. GUI.Label(labelPosition, content, Styles.eventLine);
  173. }
  174. }
  175. }
  176. }