diff --git a/TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs b/TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs index 67f3053..d907b4b 100644 --- a/TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs +++ b/TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs @@ -9,6 +9,10 @@ namespace TNodeCore.Editor.NodeGraphView{ public void AddTNode(NodeData nodeData, Rect rect); public void RemoveTNode(NodeData nodeData); + public void AddLink(NodeLink nodeLink); + + public void RemoveLink(NodeLink nodeLink); + public bool TestMode{ get; set; } public void CreateBlackboard(); diff --git a/TNode/TNodeCore/Editor/Serialization/NodeDataWrapper.cs b/TNode/TNodeCore/Editor/Serialization/NodeDataWrapper.cs index da587d2..07be82e 100644 --- a/TNode/TNodeCore/Editor/Serialization/NodeDataWrapper.cs +++ b/TNode/TNodeCore/Editor/Serialization/NodeDataWrapper.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using TNodeCore.Runtime; using TNodeCore.Runtime.Models; +using UnityEditor; using UnityEngine; namespace TNodeCore.Editor.Serialization{ diff --git a/TNode/TNodeCore/Runtime/Models/BlackboardDragNodeData.cs b/TNode/TNodeCore/Runtime/Models/BlackboardDragNodeData.cs index 08b21bb..fc81710 100644 --- a/TNode/TNodeCore/Runtime/Models/BlackboardDragNodeData.cs +++ b/TNode/TNodeCore/Runtime/Models/BlackboardDragNodeData.cs @@ -31,7 +31,6 @@ namespace TNodeCore.Runtime.Models{ } else{ var split = BlackDragData.Split('.'); - Debug.Log(blackDragData); var index = int.Parse(split[1]); return BlackboardData.GetListValue(split[0],index); diff --git a/TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs b/TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs index 7cf100a..a595919 100644 --- a/TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs +++ b/TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs @@ -11,6 +11,7 @@ using TNodeCore.Editor; using TNodeCore.Editor.Blackboard; using TNodeCore.Editor.EditorPersistence; using TNodeCore.Editor.NodeGraphView; +using TNodeCore.Editor.Serialization; using TNodeCore.Editor.Tools.NodeCreator; using TNodeCore.Runtime.Components; using TNodeCore.Runtime.Models; @@ -34,9 +35,6 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ private Dictionary _nodeDict = new(); private IBlackboardView _blackboard; private bool _runtimeGraphUpdate; - - - public T Data{ get{ return _data; } set{ @@ -95,7 +93,6 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ }, name = "HintLabel" }; - visualElement.RegisterCallback((evt) => { //check if the dragged object is a graph data or a Game Object contains a runtime graph var res = DragAndDrop.objectReferences; @@ -202,6 +199,16 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ CheckDataAfterInit(); OnGraphViewCreate(); + + BuildUndo(); + } + + private void BuildUndo(){ + Undo.undoRedoPerformed+=UndoRedoPerformed; + } + + private void UndoRedoPerformed(){ + ResetGraphView(); } public virtual void AfterEditorLoadGraphView(){ @@ -284,8 +291,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ } #endregion - - + public void ResetGraphView(){ //Clear all nodes @@ -295,8 +301,8 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ foreach (var edge in edges){ RemoveElement(edge); } - if (_nodeDict == null) throw new ArgumentNullException(nameof(_nodeDict)); + foreach (var dataNode in _data.NodeDictionary.Values){ if(dataNode==null) continue; @@ -317,7 +323,6 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ } } - foreach (var edge in _data.NodeLinks){ var inputNode = _data.NodeDictionary[edge.inPort.nodeDataId]; var outputNode = _data.NodeDictionary[edge.outPort.nodeDataId]; @@ -509,7 +514,10 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ nodeViewInterface.SetNodeData(nodeData); } _nodeDict.Add(nodeData.id, nodeView); - + if (_data.NodeDictionary.ContainsKey(nodeData.id) == false){ + Undo.RegisterCompleteObjectUndo(_data,"Node Creation"); + _data.NodeDictionary.Add(nodeData.id,nodeData); + } //register an callback ,when right click context menu nodeView.RegisterCallback(evt => { var menu = new GenericMenu(); @@ -521,12 +529,11 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ }); menu.ShowAsContext(); }); - } } public void RemoveTNode(NodeData nodeData){ - + Undo.RegisterCompleteObjectUndo(_data,"Node deletion"); _data.NodeDictionary.Remove(nodeData.id); var nodeView = _nodeDict[nodeData.id]; _nodeDict.Remove(nodeData.id); @@ -536,9 +543,20 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ RemoveElement(edge); } } + //TODO: rect x,y move to node region Owner.graphEditorData.graphElementsData.RemoveAll(x => x.guid == nodeData.id); } + public void AddLink(NodeLink nodeLink){ + Undo.RegisterCompleteObjectUndo(_data,"node linked"); + _data.NodeLinks.Add(nodeLink); + } + + public void RemoveLink(NodeLink nodeLink){ + Undo.RegisterCompleteObjectUndo(_data,"node unlinked"); + _data.NodeLinks.Remove(nodeLink); + } + public bool TestMode{ get; set; } public void CreateBlackboard(){ @@ -549,7 +567,6 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ Add(castedBlackboard); Rect blackboardPos = new Rect(0,0,300,700); castedBlackboard?.SetPosition(blackboardPos); - OnDataChanged+= (sender, e) => { BlackboardUpdate(); }; } @@ -580,6 +597,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ _runtimeGraphUpdate = true; } + public Action AfterRuntimeGraphUpdate{ get; set; } #endregion diff --git a/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs b/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs index c2f245b..c36a3b1 100644 --- a/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs +++ b/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Reflection; using TNode.TNodeGraphViewImpl.Editor.Inspector; +using TNode.TNodeGraphViewImpl.Editor.Ports; using TNodeCore.Editor.NodeGraphView; using TNodeCore.Editor.Serialization; using TNodeCore.Runtime; @@ -105,8 +106,11 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{ foreach (var propertyInfo in propertyInfos){ if (propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true).FirstOrDefault() is OutputAttribute attribute){ - - Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,attribute.Multiple?Port.Capacity.Multi:Port.Capacity.Single,BuildPortType(attribute,propertyInfo)); + + Port port = new CustomPort(Orientation.Horizontal, Direction.Output, + attribute.Multiple ? Port.Capacity.Multi : Port.Capacity.Single, + BuildPortType(attribute, propertyInfo)); + this.outputContainer.Add(port); var portName = ObjectNames.NicifyVariableName(BuildPortName(attribute,propertyInfo)); port.portName = portName; @@ -116,7 +120,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{ } foreach (var propertyInfo in propertyInfos){ if(propertyInfo.GetCustomAttributes(typeof(InputAttribute),true).FirstOrDefault() is InputAttribute attribute){ - Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,attribute.Multiple?Port.Capacity.Multi:Port.Capacity.Single,BuildPortType(attribute,propertyInfo)); + Port port = new CustomPort(Orientation.Horizontal, Direction.Input,attribute.Multiple?Port.Capacity.Multi:Port.Capacity.Single,BuildPortType(attribute,propertyInfo)); this.inputContainer.Add(port); var portName = BuildPortName(attribute,propertyInfo); port.portName = portName; diff --git a/TNode/TNodeGraphViewImpl/Editor/Ports.meta b/TNode/TNodeGraphViewImpl/Editor/Ports.meta new file mode 100644 index 0000000..676dc5f --- /dev/null +++ b/TNode/TNodeGraphViewImpl/Editor/Ports.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9f4128d4bc36443c96ee4211e158baa9 +timeCreated: 1659434777 \ No newline at end of file diff --git a/TNode/TNodeGraphViewImpl/Editor/Ports/CustomPort.cs b/TNode/TNodeGraphViewImpl/Editor/Ports/CustomPort.cs new file mode 100644 index 0000000..13a2129 --- /dev/null +++ b/TNode/TNodeGraphViewImpl/Editor/Ports/CustomPort.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TNode.TNodeGraphViewImpl.Editor.NodeViews; +using TNodeCore.Editor.NodeGraphView; +using TNodeCore.Runtime.Models; +using UnityEditor.Experimental.GraphView; +using UnityEngine.UIElements; + +namespace TNode.TNodeGraphViewImpl.Editor.Ports{ + public class CustomPort:UnityEditor.Experimental.GraphView.Port{ + public CustomPort(Orientation portOrientation, Direction portDirection, Capacity portCapacity, Type type) : base(portOrientation, portDirection, portCapacity, type){ + m_EdgeConnector = new EdgeConnector(new CustomEdgeConnectorListener()); + this.AddManipulator(m_EdgeConnector); + } + } + + public class CustomEdgeConnectorListener : IEdgeConnectorListener{ + private GraphViewChange m_GraphViewChange; + private List m_EdgesToCreate; + private List m_EdgesToDelete; + + public CustomEdgeConnectorListener(){ + this.m_EdgesToCreate = new List(); + this.m_EdgesToDelete = new List(); + this.m_GraphViewChange.edgesToCreate = this.m_EdgesToCreate; + } + + public NodeLink FromEdgeToNodeLink(GraphData graphData, Edge edge){ + var inputNode = edge.input.node; + var outputNode = edge.output.node; + var links = graphData.NodeLinks.Where(x=>x.inPort.portEntryName==edge.input.name && x.outPort.portEntryName==edge.output.name); + return links.FirstOrDefault(); + } + + public NodeLink MakeNodeLink(Edge edge){ + var inputNode = edge.input.node as IBaseNodeView; + if (inputNode == null) return null; + var outputNode = edge.output.node as IBaseNodeView; + if (outputNode == null) return null; + var link = new NodeLink(new PortInfo{ + nodeDataId = inputNode.GetNodeData().id, + portEntryName = edge.input.name + + }, new PortInfo(){ + nodeDataId = outputNode.GetNodeData().id, + portEntryName = edge.output.name + }); + return link; + } + public void OnDropOutsidePort(Edge edge, UnityEngine.Vector2 position){ + + } + public void OnDrop(UnityEditor.Experimental.GraphView.GraphView graphView, Edge edge){ + this.m_EdgesToCreate.Clear(); + this.m_EdgesToCreate.Add(edge); + this.m_EdgesToDelete.Clear(); + if (edge.input.capacity == Port.Capacity.Single){ + foreach (Edge connection in edge.input.connections){ + if (connection != edge) + this.m_EdgesToDelete.Add((GraphElement) connection); + } + } + + if (edge.output.capacity == Port.Capacity.Single){ + foreach (Edge connection in edge.output.connections){ + if (connection != edge) + this.m_EdgesToDelete.Add(connection); + } + } + + var baseDataGraphView = (IBaseDataGraphView) graphView; + if (m_EdgesToDelete.Count > 0){ + graphView.DeleteElements(this.m_EdgesToDelete); + baseDataGraphView.RemoveLink(FromEdgeToNodeLink(baseDataGraphView.GetGraphData(), edge)); + } + + List edgesToCreate = this.m_EdgesToCreate; + if (graphView.graphViewChanged != null) + edgesToCreate = graphView.graphViewChanged(this.m_GraphViewChange).edgesToCreate; + foreach (Edge edge1 in edgesToCreate){ + graphView.AddElement(edge1); + edge.input.Connect(edge1); + edge.output.Connect(edge1); + baseDataGraphView.AddLink(MakeNodeLink(edge1)); + } + + } + } + +} \ No newline at end of file diff --git a/TNode/TNodeGraphViewImpl/Editor/Ports/CustomPort.cs.meta b/TNode/TNodeGraphViewImpl/Editor/Ports/CustomPort.cs.meta new file mode 100644 index 0000000..52abde6 --- /dev/null +++ b/TNode/TNodeGraphViewImpl/Editor/Ports/CustomPort.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 58d8d7075ebe42db93c65332b02afa0d +timeCreated: 1659434790 \ No newline at end of file diff --git a/TNode/TNodeGraphViewImpl/Editor/Search/NodeSearchWindowProvider.cs b/TNode/TNodeGraphViewImpl/Editor/Search/NodeSearchWindowProvider.cs index 388eaa7..642aeef 100644 --- a/TNode/TNodeGraphViewImpl/Editor/Search/NodeSearchWindowProvider.cs +++ b/TNode/TNodeGraphViewImpl/Editor/Search/NodeSearchWindowProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using TNode.TNodeGraphViewImpl.Editor.Cache; using TNodeCore.Editor.NodeGraphView; +using TNodeCore.Editor.Serialization; using TNodeCore.Editor.Tools.NodeCreator; using TNodeCore.Runtime.Models; using UnityEditor; @@ -62,5 +63,11 @@ namespace TNode.TNodeGraphViewImpl.Editor.Search{ } return false; } + + private void UndoCreateNodePerformed(){ + + } + + } } \ No newline at end of file