using Sirenix.Utilities; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEditor; using UnityEditor.Experimental.GraphView; using UnityEngine; using UnityEngine.UIElements; namespace Ether { /// /// 节点视图底图 /// public class EtherNodeGraphViewer : GraphView { public Action OnNodeSelected; public new class UxmlFactory : UxmlFactory { } EtherNodeGraph graph; public EtherNodeGraph Graph { get { return graph; } } public EtherNodeGraphViewer() { Insert(0, new GridBackground()); ContentZoomer contentZoomer = new ContentZoomer(); contentZoomer.minScale = 0.15f; contentZoomer.maxScale = 2f; this.AddManipulator(contentZoomer); //缩放 this.AddManipulator(new ContentDragger()); //拖拽 this.AddManipulator(new SelectionDragger()); //点击拖拽 this.AddManipulator(new RectangleSelector()); //框选 var styleSheet = AssetDatabase.LoadAssetAtPath("Assets/Ether/Package/EtherNode/Editor/UI/NodeTreeViewer.uss"); styleSheets.Add(styleSheet); Undo.undoRedoPerformed += OnUndoRedo; EventCenter.AddListener("EtherNodeEditorDeleteNode", () => { PopulateView(graph); }); } /// /// 右键点击菜单 /// public override void BuildContextualMenu(ContextualMenuPopulateEvent evt) { evt.menu.ClearItems(); //var types = TypeCache.GetTypesDerivedFrom(tree.GetNodeType()); Type nodeType = graph.GetNodeType(); var types = CommonTools.GetChildTypes(nodeType); Vector2 createPosition = (evt.currentTarget as VisualElement).ChangeCoordinatesTo(contentViewContainer, evt.localMousePosition); List<(EtherNodeMenuNameAttribute, Type)> list = new List<(EtherNodeMenuNameAttribute, Type)>(); foreach (var type in types) { if (!type.IsAbstract) { EtherNodeMenuNameAttribute attr = type.GetAttribute(); if (attr == null) { attr = new EtherNodeMenuNameAttribute(type.Name, 999); } list.Add((attr, type)); } } list.Sort((a, b) => { return b.Item1.order.CompareTo(a.Item1.order); }); if (list.Count > 0) { foreach (var tuple in list) { evt.menu.AppendAction($"创建{tuple.Item1.menuName}", (a) => CreateNode(tuple.Item2, createPosition)); } } } private void OnUndoRedo() { PopulateView(graph); AssetDatabase.SaveAssets(); } private void CreateNode(Type type, Vector2 createPos) { if (graph == null) { return; } EtherNode node = graph.CreateNode(type, createPos); CreateNodeView(node); } private void CreateNodeView(EtherNode node) { EtherNodeView nodeView = new EtherNodeView(node); nodeView.OnNodeSelected = OnNodeSelected; EtherNodeGraphViewer nodeGraphViewer = this; AddElement(nodeView); Undo.undoRedoPerformed += () => { PopulateView(graph); }; } internal void PopulateView(EtherNodeGraph tree) { this.graph = tree; graphViewChanged -= OnGraphViewChange; DeleteElements(graphElements); graphViewChanged += OnGraphViewChange; tree.allNodeDic.ForEach(n => { CreateNodeView(n.Value); }); tree.allNodeDic.ForEach(n => { var children = tree.GetChildren(n.Value); children.ForEach(c => { EtherNodeView parentView = FindNodeView(n.Value); EtherNodeView childView = FindNodeView(c); Edge edge = parentView.output.ConnectTo(childView.input); AddElement(edge); }); }); } private GraphViewChange OnGraphViewChange(GraphViewChange graphViewChange) { if (graphViewChange.elementsToRemove != null) { graphViewChange.elementsToRemove.ForEach(elem => { EtherNodeView nodeView = elem as EtherNodeView; if (nodeView != null) { graph.DeleteNode(nodeView.node); } Edge edge = elem as Edge; if (edge != null) { EtherNodeView parentView = edge.output.node as EtherNodeView; EtherNodeView childView = edge.input.node as EtherNodeView; graph.RemoveChild(parentView.node, childView.node); } }); } if (graphViewChange.edgesToCreate != null) { graphViewChange.edgesToCreate.ForEach(edge => { EtherNodeView parentView = edge.output.node as EtherNodeView; EtherNodeView childView = edge.input.node as EtherNodeView; graph.AddChild(parentView.node, childView.node); }); } return graphViewChange; } private EtherNodeView FindNodeView(EtherNode node) { return GetNodeByGuid(node.guid) as EtherNodeView; } public override List GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter) { return ports.ToList().Where(endport => endport.direction != startPort.direction && endport.node != startPort.node).ToList(); } //public void UpdateNodeStates() //{ // nodes.ForEach(n => // { // EtherNodeView view = n as EtherNodeView; // view.SetNodeState(); // }); //} } }