diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs index 792631a..61b5d8e 100644 --- a/Scripts/Editor/NodeEditorAction.cs +++ b/Scripts/Editor/NodeEditorAction.cs @@ -15,7 +15,7 @@ namespace XNodeEditor { private bool IsHoveringPort { get { return hoveredPort != null; } } private bool IsHoveringNode { get { return hoveredNode != null; } } private bool IsHoveringReroute { get { return hoveredReroute.port != null; } } - private XNode.Node hoveredNode = null; + private XNode.INode hoveredNode = null; [NonSerialized] private XNode.NodePort hoveredPort = null; [NonSerialized] private XNode.NodePort draggedOutput = null; [NonSerialized] private XNode.NodePort draggedOutputTarget = null; @@ -81,8 +81,8 @@ namespace XNodeEditor { Vector2 mousePos = WindowToGridPosition(e.mousePosition); // Move selected nodes with offset for (int i = 0; i < Selection.objects.Length; i++) { - if (Selection.objects[i] is XNode.Node) { - XNode.Node node = Selection.objects[i] as XNode.Node; + if (Selection.objects[i] is XNode.INode) { + XNode.INode node = Selection.objects[i] as XNode.INode; Vector2 initial = node.position; node.position = mousePos + dragOffset[i]; if (gridSnap) { @@ -151,7 +151,7 @@ namespace XNodeEditor { } else { hoveredPort.VerifyConnections(); if (hoveredPort.IsConnected) { - XNode.Node node = hoveredPort.node; + XNode.INode node = hoveredPort.node; XNode.NodePort output = hoveredPort.Connection; int outputConnectionIndex = output.GetConnectionIndex(hoveredPort); draggedOutputReroutes = output.GetReroutePoints(outputConnectionIndex); @@ -206,7 +206,7 @@ namespace XNodeEditor { if (IsDraggingPort) { //If connection is valid, save it if (draggedOutputTarget != null) { - XNode.Node node = draggedOutputTarget.node; + XNode.INode node = draggedOutputTarget.node; if (graph.nodes.Count != 0) draggedOutput.Connect(draggedOutputTarget); // ConnectionIndex can be -1 if the connection is removed instantly after creation @@ -223,8 +223,8 @@ namespace XNodeEditor { EditorUtility.SetDirty(graph); if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); } else if (currentActivity == NodeActivity.DragNode) { - IEnumerable nodes = Selection.objects.Where(x => x is XNode.Node).Select(x => x as XNode.Node); - foreach (XNode.Node node in nodes) EditorUtility.SetDirty(node); + IEnumerable nodes = Selection.objects.Where(x => x is XNode.INode).Select(x => x as XNode.INode); + foreach (XNode.INode node in nodes) EditorUtility.SetDirty(node); if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); } else if (!IsHoveringNode) { // If click outside node, release field focus @@ -328,8 +328,8 @@ namespace XNodeEditor { dragOffset = new Vector2[Selection.objects.Length + selectedReroutes.Count]; // Selected nodes for (int i = 0; i < Selection.objects.Length; i++) { - if (Selection.objects[i] is XNode.Node) { - XNode.Node node = Selection.objects[i] as XNode.Node; + if (Selection.objects[i] is XNode.INode) { + XNode.INode node = Selection.objects[i] as XNode.INode; dragOffset[i] = node.position - WindowToGridPosition(current.mousePosition); } } diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs index a575c8d..4d01065 100644 --- a/Scripts/Editor/NodeEditorWindow.cs +++ b/Scripts/Editor/NodeEditorWindow.cs @@ -15,7 +15,7 @@ namespace XNodeEditor { [SerializeField] private Rect[] _rects = new Rect[0]; [System.Serializable] private class NodePortReference { - [SerializeField] private XNode.Node _node; + [SerializeField] private UnityEngine.Object _node; [SerializeField] private string _name; public NodePortReference(XNode.NodePort nodePort) { @@ -27,7 +27,7 @@ namespace XNodeEditor { if (_node == null) { return null; } - return _node.GetPort(_name); + return (_node as XNode.INode).GetPort(_name); } } diff --git a/Scripts/Interfaces.meta b/Scripts/Interfaces.meta new file mode 100644 index 0000000..49160c9 --- /dev/null +++ b/Scripts/Interfaces.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ac61dc94b559a5243bbfb2368d301f2a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Interfaces/INode.cs b/Scripts/Interfaces/INode.cs new file mode 100644 index 0000000..bfbe1e5 --- /dev/null +++ b/Scripts/Interfaces/INode.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace XNode { + public interface INode { + string name { get; set; } + INodeGraph Graph { get; } + Vector2 Position { get; set; } + object GetValue(NodePort port); + bool HasPort(string fieldName); + NodePort GetPort(string fieldName); + void UpdateStaticPorts(); + IEnumerable Ports { get; } + IEnumerable Outputs { get; } + IEnumerable Inputs { get; } + IEnumerable InstancePorts { get; } + NodePort AddInstanceOutput(Type type, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, string fieldName = null); + NodePort AddInstanceInput(Type type, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, string fieldName = null); + NodePort GetInputPort(string fieldName); + NodePort GetOutputPort(string fieldName); + void OnCreateConnection(NodePort from, NodePort to); + void OnRemoveConnection(NodePort port); + void ClearConnections(); + void RemoveInstancePort(string fieldName); + } +} \ No newline at end of file diff --git a/Scripts/Interfaces/INode.cs.meta b/Scripts/Interfaces/INode.cs.meta new file mode 100644 index 0000000..07eb54f --- /dev/null +++ b/Scripts/Interfaces/INode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f38ad625580bbf445aa3885c5ec3c5af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Interfaces/INodeGraph.cs b/Scripts/Interfaces/INodeGraph.cs new file mode 100644 index 0000000..39e3c7f --- /dev/null +++ b/Scripts/Interfaces/INodeGraph.cs @@ -0,0 +1,13 @@ +using System; + +namespace XNode { + /// Used by advanced extensions that need to alter the base classes of NodeGraphs + public interface INodeGraph { + int NodesCount { get; } + void MoveNodeToTop(INode node); + INode[] GetNodes(); + INode AddNode(Type type); + INode CopyNode(INode original); + void RemoveNode(INode node); + } +} \ No newline at end of file diff --git a/Scripts/Interfaces/INodeGraph.cs.meta b/Scripts/Interfaces/INodeGraph.cs.meta new file mode 100644 index 0000000..0656a1a --- /dev/null +++ b/Scripts/Interfaces/INodeGraph.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e5821d1c7c3ead04c8da1e04ed850a3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Node.cs b/Scripts/Node.cs index a16a234..7ba963a 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -23,7 +23,7 @@ namespace XNode { /// /// [Serializable] - public abstract class Node : ScriptableObject { + public abstract class Node : ScriptableObject, XNode.INode { /// Used by and to determine when to display the field value associated with a public enum ShowBackingValue { /// Never show the backing value @@ -105,7 +105,9 @@ namespace XNode { /// Iterate over all dynamic inputs on this node. public IEnumerable DynamicInputs { get { foreach (NodePort port in Ports) { if (port.IsDynamic && port.IsInput) yield return port; } } } /// Parent - [SerializeField] public NodeGraph graph; + public NodeGraph Graph { get { return graph; } } + /// Parent + [SerializeField] private NodeGraph graph; /// Position on the [SerializeField] public Vector2 position; /// It is recommended not to modify these at hand. Instead, see and @@ -368,4 +370,4 @@ namespace XNode { } } } -} +} \ No newline at end of file