BaseStackNodeView.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. using UnityEditor.Experimental.GraphView;
  2. using UnityEngine;
  3. using UnityEditor;
  4. using UnityEditor.UIElements;
  5. using UnityEngine.UIElements;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. namespace GraphProcessor
  9. {
  10. /// <summary>
  11. /// Stack node view implementation, can be used to stack multiple node inside a context like VFX graph does.
  12. /// </summary>
  13. public class BaseStackNodeView : StackNode
  14. {
  15. public delegate void ReorderNodeAction(BaseNodeView nodeView, int oldIndex, int newIndex);
  16. /// <summary>
  17. /// StackNode data from the graph
  18. /// </summary>
  19. protected internal BaseStackNode stackNode;
  20. protected BaseGraphView owner;
  21. readonly string styleSheet = "GraphProcessorStyles/BaseStackNodeView";
  22. /// <summary>Triggered when a node is re-ordered in the stack.</summary>
  23. public event ReorderNodeAction onNodeReordered;
  24. public BaseStackNodeView(BaseStackNode stackNode)
  25. {
  26. this.stackNode = stackNode;
  27. styleSheets.Add(Resources.Load<StyleSheet>(styleSheet));
  28. }
  29. /// <inheritdoc />
  30. protected override void OnSeparatorContextualMenuEvent(ContextualMenuPopulateEvent evt, int separatorIndex)
  31. {
  32. // TODO: write the context menu for stack node
  33. }
  34. /// <summary>
  35. /// Called after the StackNode have been added to the graph view
  36. /// </summary>
  37. public virtual void Initialize(BaseGraphView graphView)
  38. {
  39. owner = graphView;
  40. headerContainer.Add(new Label(stackNode.title));
  41. SetPosition(new Rect(stackNode.position, Vector2.one));
  42. InitializeInnerNodes();
  43. }
  44. void InitializeInnerNodes()
  45. {
  46. int i = 0;
  47. // Sanitize the GUID list in case some nodes were removed
  48. stackNode.nodeGUIDs.RemoveAll(nodeGUID =>
  49. {
  50. if (owner.graph.nodesPerGUID.ContainsKey(nodeGUID))
  51. {
  52. var node = owner.graph.nodesPerGUID[nodeGUID];
  53. var view = owner.nodeViewsPerNode[node];
  54. view.AddToClassList("stack-child__" + i);
  55. i++;
  56. AddElement(view);
  57. return false;
  58. }
  59. else
  60. {
  61. return true; // remove the entry as the GUID doesn't exist anymore
  62. }
  63. });
  64. }
  65. /// <inheritdoc />
  66. public override void SetPosition(Rect newPos)
  67. {
  68. base.SetPosition(newPos);
  69. stackNode.position = newPos.position;
  70. }
  71. /// <inheritdoc />
  72. protected override bool AcceptsElement(GraphElement element, ref int proposedIndex, int maxIndex)
  73. {
  74. bool accept = base.AcceptsElement(element, ref proposedIndex, maxIndex);
  75. if (accept && element is BaseNodeView nodeView)
  76. {
  77. var index = Mathf.Clamp(proposedIndex, 0, stackNode.nodeGUIDs.Count - 1);
  78. int oldIndex = stackNode.nodeGUIDs.FindIndex(g => g == nodeView.nodeTarget.GUID);
  79. if (oldIndex != -1)
  80. {
  81. stackNode.nodeGUIDs.Remove(nodeView.nodeTarget.GUID);
  82. if (oldIndex != index)
  83. onNodeReordered?.Invoke(nodeView, oldIndex, index);
  84. }
  85. stackNode.nodeGUIDs.Insert(index, nodeView.nodeTarget.GUID);
  86. }
  87. return accept;
  88. }
  89. public override bool DragLeave(DragLeaveEvent evt, IEnumerable<ISelectable> selection, IDropTarget leftTarget, ISelection dragSource)
  90. {
  91. foreach (var elem in selection)
  92. {
  93. if (elem is BaseNodeView nodeView)
  94. stackNode.nodeGUIDs.Remove(nodeView.nodeTarget.GUID);
  95. }
  96. return base.DragLeave(evt, selection, leftTarget, dragSource);
  97. }
  98. }
  99. }