193 lines
6.4 KiB
C#
193 lines
6.4 KiB
C#
|
|
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
|
|
{
|
|
/// <summary>
|
|
/// 节点视图底图
|
|
/// </summary>
|
|
public class EtherNodeGraphViewer : GraphView
|
|
{
|
|
public Action<EtherNodeView> OnNodeSelected;
|
|
|
|
public new class UxmlFactory : UxmlFactory<EtherNodeGraphViewer, GraphView.UxmlTraits> { }
|
|
|
|
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<StyleSheet>("Assets/Ether/Package/EtherNode/Editor/UI/NodeTreeViewer.uss");
|
|
styleSheets.Add(styleSheet);
|
|
Undo.undoRedoPerformed += OnUndoRedo;
|
|
|
|
EventCenter.AddListener("EtherNodeEditorDeleteNode", () => { PopulateView(graph); });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 右键点击菜单
|
|
/// </summary>
|
|
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<EtherNodeMenuNameAttribute>();
|
|
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<Port> 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();
|
|
// });
|
|
//}
|
|
|
|
}
|
|
}
|