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();
// });
//}
}
}