diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs index 91d92d0..cb0edb5 100644 --- a/Scripts/Editor/NodeEditor.cs +++ b/Scripts/Editor/NodeEditor.cs @@ -7,11 +7,11 @@ using UnityEngine; namespace XNodeEditor { /// Base class to derive custom Node editors from. Use this to create your own custom inspectors and editors for your nodes. - [CustomNodeEditor(typeof(XNode.Node))] - public class NodeEditor : XNodeEditor.Internal.NodeEditorBase { + [CustomNodeEditor(typeof(XNode.INode))] + public class NodeEditor : XNodeEditor.Internal.NodeEditorBase { /// Fires every whenever a node was modified through the editor - public static Action onUpdateNode; + public static Action onUpdateNode; public static Dictionary portPositions; public virtual void OnHeaderGUI() { @@ -67,9 +67,9 @@ namespace XNodeEditor { /// Add items for the context menu when right-clicking this node. Override to add custom menu items. public virtual void AddContextMenuItems(GenericMenu menu) { // Actions if only one node is selected - if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { - XNode.Node node = Selection.activeObject as XNode.Node; - menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node)); + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.INode) { + XNode.INode node = Selection.activeObject as XNode.INode; + menu.AddItem(new GUIContent("Move To Top"), false, () => node.Graph.MoveNodeToTop(node)); menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode); } @@ -78,8 +78,8 @@ namespace XNodeEditor { menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes); // Custom sctions if only one node is selected - if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { - XNode.Node node = Selection.activeObject as XNode.Node; + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.INode) { + XNode.INode node = Selection.activeObject as XNode.INode; NodeEditorWindow.AddCustomContextMenuItems(menu, node); } } @@ -93,7 +93,7 @@ namespace XNodeEditor { [AttributeUsage(AttributeTargets.Class)] public class CustomNodeEditorAttribute : Attribute, - XNodeEditor.Internal.NodeEditorBase.INodeEditorAttrib { + XNodeEditor.Internal.NodeEditorBase.INodeEditorAttrib { private Type inspectedType; /// Tells a NodeEditor which Node type it is an editor for /// Type that this editor can edit diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs index 61b5d8e..2172b3e 100644 --- a/Scripts/Editor/NodeEditorAction.cs +++ b/Scripts/Editor/NodeEditorAction.cs @@ -83,15 +83,17 @@ namespace XNodeEditor { for (int i = 0; i < Selection.objects.Length; i++) { 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]; + Vector2 initial = node.Position; + node.Position = mousePos + dragOffset[i]; if (gridSnap) { - node.position.x = (Mathf.Round((node.position.x + 8) / 16) * 16) - 8; - node.position.y = (Mathf.Round((node.position.y + 8) / 16) * 16) - 8; + Vector2 position = node.Position; + position.x = (Mathf.Round((node.Position.x + 8) / 16) * 16) - 8; + position.y = (Mathf.Round((node.Position.y + 8) / 16) * 16) - 8; + node.Position = position; } // Offset portConnectionPoints instantly if a node is dragged so they aren't delayed by a frame. - Vector2 offset = node.position - initial; + Vector2 offset = node.Position - initial; if (offset.sqrMagnitude > 0) { foreach (XNode.NodePort output in node.Outputs) { Rect rect; @@ -163,7 +165,7 @@ namespace XNodeEditor { } } else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) { // If mousedown on node header, select or deselect - if (!Selection.Contains(hoveredNode)) { + if (!Selection.Contains((UnityEngine.Object)hoveredNode)) { SelectNode(hoveredNode, e.control || e.shift); if (!e.control && !e.shift) selectedReroutes.Clear(); } else if (e.control || e.shift) DeselectNode(hoveredNode); @@ -243,7 +245,7 @@ namespace XNodeEditor { // Double click to center node if (isDoubleClick) { Vector2 nodeDimension = nodeSizes.ContainsKey(hoveredNode) ? nodeSizes[hoveredNode] / 2 : Vector2.zero; - panOffset = -hoveredNode.position - nodeDimension; + panOffset = -hoverednode.Position - nodeDimension; } } @@ -267,7 +269,7 @@ namespace XNodeEditor { } else if (IsHoveringPort) { ShowPortContextMenu(hoveredPort); } else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) { - if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode, false); + if (!Selection.Contains((UnityEngine.Object)hoveredNode)) SelectNode(hoveredNode, false); GenericMenu menu = new GenericMenu(); NodeEditor.GetEditor(hoveredNode, this).AddContextMenuItems(menu); menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); @@ -330,7 +332,7 @@ namespace XNodeEditor { for (int i = 0; i < Selection.objects.Length; i++) { if (Selection.objects[i] is XNode.INode) { XNode.INode node = Selection.objects[i] as XNode.INode; - dragOffset[i] = node.position - WindowToGridPosition(current.mousePosition); + dragOffset[i] = node.Position - WindowToGridPosition(current.mousePosition); } } @@ -355,8 +357,8 @@ namespace XNodeEditor { } selectedReroutes.Clear(); foreach (UnityEngine.Object item in Selection.objects) { - if (item is XNode.Node) { - XNode.Node node = item as XNode.Node; + if (item is XNode.INode) { + XNode.INode node = item as XNode.INode; graphEditor.RemoveNode(node); } } @@ -364,8 +366,8 @@ namespace XNodeEditor { /// Initiate a rename on the currently selected node public void RenameSelectedNode() { - if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { - XNode.Node node = Selection.activeObject as XNode.Node; + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.INode) { + XNode.INode node = Selection.activeObject as XNode.INode; Vector2 size; if (nodeSizes.TryGetValue(node, out size)) { RenamePopup.Show(Selection.activeObject, size.x); @@ -375,41 +377,32 @@ namespace XNodeEditor { } } - /// Draw this node on top of other nodes by placing it last in the graph.nodes list - public void MoveNodeToTop(XNode.Node node) { - int index; - while ((index = graph.nodes.IndexOf(node)) != graph.nodes.Count - 1) { - graph.nodes[index] = graph.nodes[index + 1]; - graph.nodes[index + 1] = node; - } - } - /// Duplicate selected nodes and select the duplicates public void DuplicateSelectedNodes() { UnityEngine.Object[] newNodes = new UnityEngine.Object[Selection.objects.Length]; - Dictionary substitutes = new Dictionary(); + Dictionary substitutes = new Dictionary(); for (int i = 0; i < Selection.objects.Length; i++) { - if (Selection.objects[i] is XNode.Node) { - XNode.Node srcNode = Selection.objects[i] as XNode.Node; - if (srcNode.graph != graph) continue; // ignore nodes selected in another graph - XNode.Node newNode = graphEditor.CopyNode(srcNode); + if (Selection.objects[i] is XNode.INode) { + XNode.INode srcNode = Selection.objects[i] as XNode.INode; + if (srcNode.Graph != graph) continue; // ignore nodes selected in another graph + XNode.INode newNode = graphEditor.CopyNode(srcNode); substitutes.Add(srcNode, newNode); - newNode.position = srcNode.position + new Vector2(30, 30); + newnode.Position = srcnode.Position + new Vector2(30, 30); newNodes[i] = newNode; } } // Walk through the selected nodes again, recreate connections, using the new nodes for (int i = 0; i < Selection.objects.Length; i++) { - if (Selection.objects[i] is XNode.Node) { - XNode.Node srcNode = Selection.objects[i] as XNode.Node; + if (Selection.objects[i] is XNode.INode) { + XNode.INode srcNode = Selection.objects[i] as XNode.INode; if (srcNode.graph != graph) continue; // ignore nodes selected in another graph foreach (XNode.NodePort port in srcNode.Ports) { for (int c = 0; c < port.ConnectionCount; c++) { XNode.NodePort inputPort = port.direction == XNode.NodePort.IO.Input ? port : port.GetConnection(c); XNode.NodePort outputPort = port.direction == XNode.NodePort.IO.Output ? port : port.GetConnection(c); - XNode.Node newNodeIn, newNodeOut; + XNode.INode newNodeIn, newNodeOut; if (substitutes.TryGetValue(inputPort.node, out newNodeIn) && substitutes.TryGetValue(outputPort.node, out newNodeOut)) { newNodeIn.UpdateStaticPorts(); newNodeOut.UpdateStaticPorts(); @@ -459,10 +452,10 @@ namespace XNodeEditor { } } - bool IsHoveringTitle(XNode.Node node) { + bool IsHoveringTitle(XNode.INode node) { Vector2 mousePos = Event.current.mousePosition; //Get node position - Vector2 nodePos = GridToWindowPosition(node.position); + Vector2 nodePos = GridToWindowPosition(node.Position); float width; Vector2 size; if (nodeSizes.TryGetValue(node, out size)) width = size.x; diff --git a/Scripts/Editor/NodeEditorAssetModProcessor.cs b/Scripts/Editor/NodeEditorAssetModProcessor.cs index bd76116..97b46c4 100644 --- a/Scripts/Editor/NodeEditorAssetModProcessor.cs +++ b/Scripts/Editor/NodeEditorAssetModProcessor.cs @@ -17,7 +17,7 @@ namespace XNodeEditor { // Check script type. Return if deleting a non-node script UnityEditor.MonoScript script = obj as UnityEditor.MonoScript; System.Type scriptType = script.GetClass (); - if (scriptType == null || (scriptType != typeof (XNode.Node) && !scriptType.IsSubclassOf (typeof (XNode.Node)))) return AssetDeleteResult.DidNotDelete; + if (scriptType == null || (scriptType != typeof (XNode.INode) && !scriptType.IsSubclassOf (typeof (XNode.INode)))) return AssetDeleteResult.DidNotDelete; // Find all ScriptableObjects using this script string[] guids = AssetDatabase.FindAssets ("t:" + scriptType); @@ -25,7 +25,7 @@ namespace XNodeEditor { string assetpath = AssetDatabase.GUIDToAssetPath (guids[i]); Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath (assetpath); for (int k = 0; k < objs.Length; k++) { - XNode.Node node = objs[k] as XNode.Node; + XNode.INode node = objs[k] as XNode.INode; if (node.GetType () == scriptType) { if (node != null && node.graph != null) { // Delete the node and notify the user @@ -51,7 +51,7 @@ namespace XNodeEditor { Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath (assetpath); // Ensure that all sub node assets are present in the graph node list for (int u = 0; u < objs.Length; u++) { - if (!graph.nodes.Contains (objs[u] as XNode.Node)) graph.nodes.Add(objs[u] as XNode.Node); + if (!graph.nodes.Contains (objs[u] as XNode.INode)) graph.nodes.Add(objs[u] as XNode.INode); } } } diff --git a/Scripts/Editor/NodeEditorBase.cs b/Scripts/Editor/NodeEditorBase.cs index 7846d81..b701f66 100644 --- a/Scripts/Editor/NodeEditorBase.cs +++ b/Scripts/Editor/NodeEditorBase.cs @@ -9,8 +9,8 @@ namespace XNodeEditor.Internal { /// Handles caching of custom editor classes and their target types. Accessible with GetEditor(Type type) /// Editor Type. Should be the type of the deriving script itself (eg. NodeEditor) /// Attribute Type. The attribute used to connect with the runtime type (eg. CustomNodeEditorAttribute) - /// Runtime Type. The ScriptableObject this can be an editor for (eg. Node) - public abstract class NodeEditorBase : Editor where A : Attribute, NodeEditorBase.INodeEditorAttrib where T : NodeEditorBase where K : ScriptableObject { + /// Runtime Type. The Object this can be an editor for (eg. Node) + public abstract class NodeEditorBase : Editor where A : Attribute, NodeEditorBase.INodeEditorAttrib where T : NodeEditorBase where K : UnityEngine.Object { /// Custom editors defined with [CustomNodeEditor] private static Dictionary editorTypes; private static Dictionary editors = new Dictionary(); diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index c773571..d33c1a3 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -303,8 +303,8 @@ namespace XNodeEditor { NodeEditor.portPositions = new Dictionary(); - //Get node position - Vector2 nodePos = GridToWindowPositionNoClipped(node.position); + //Get node.Position + Vector2 nodePos = GridToWindowPositionNoClipped(node.Position); GUILayout.BeginArea(new Rect(nodePos, new Vector2(nodeEditor.GetWidth(), 4000))); @@ -349,7 +349,7 @@ namespace XNodeEditor { foreach (var kvp in NodeEditor.portPositions) { Vector2 portHandlePos = kvp.Value; - portHandlePos += node.position; + portHandlePos += node.Position; Rect rect = new Rect(portHandlePos.x - 8, portHandlePos.y - 8, 16, 16); if (portConnectionPoints.ContainsKey(kvp.Key)) portConnectionPoints[kvp.Key] = rect; else portConnectionPoints.Add(kvp.Key, rect); @@ -400,7 +400,7 @@ namespace XNodeEditor { private bool ShouldBeCulled(XNode.Node node) { - Vector2 nodePos = GridToWindowPositionNoClipped(node.position); + Vector2 nodePos = GridToWindowPositionNoClipped(node.Position); if (nodePos.x / _zoom > position.width) return true; // Right else if (nodePos.y / _zoom > position.height) return true; // Bottom else if (nodeSizes.ContainsKey(node)) { diff --git a/Scripts/Editor/NodeEditorGUILayout.cs b/Scripts/Editor/NodeEditorGUILayout.cs index 1826107..a84a061 100644 --- a/Scripts/Editor/NodeEditorGUILayout.cs +++ b/Scripts/Editor/NodeEditorGUILayout.cs @@ -22,7 +22,7 @@ namespace XNodeEditor { /// Make a field for a serialized property. Automatically displays relevant node port. public static void PropertyField(SerializedProperty property, GUIContent label, bool includeChildren = true, params GUILayoutOption[] options) { if (property == null) throw new NullReferenceException(); - XNode.Node node = property.serializedObject.targetObject as XNode.Node; + XNode.INode node = property.serializedObject.targetObject as XNode.INode; XNode.NodePort port = node.GetPort(property.name); PropertyField(property, label, port, includeChildren); } @@ -285,7 +285,7 @@ namespace XNodeEditor { /// Connection type of added dynamic ports /// Called on the list on creation. Use this if you want to customize the created ReorderableList public static void DynamicPortList(string fieldName, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, XNode.Node.TypeConstraint typeConstraint = XNode.Node.TypeConstraint.None, Action onCreation = null) { - XNode.Node node = serializedObject.targetObject as XNode.Node; + XNode.INode node = serializedObject.targetObject as XNode.INode; var indexedPorts = node.DynamicPorts.Select(x => { string[] split = x.fieldName.Split(' '); @@ -315,9 +315,9 @@ namespace XNodeEditor { list.DoLayoutList(); } - private static ReorderableList CreateReorderableList(string fieldName, List dynamicPorts, SerializedProperty arrayData, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType, XNode.Node.TypeConstraint typeConstraint, Action onCreation) { + private static ReorderableList CreateReorderableList(string fieldName, List dynamicPorts, SerializedProperty arrayData, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.INode.ConnectionType connectionType, XNode.INode.TypeConstraint typeConstraint, Action onCreation) { bool hasArrayData = arrayData != null && arrayData.isArray; - XNode.Node node = serializedObject.targetObject as XNode.Node; + XNode.INode node = serializedObject.targetObject as XNode.INode; ReorderableList list = new ReorderableList(dynamicPorts, null, true, true, true, true); string label = arrayData != null ? arrayData.displayName : ObjectNames.NicifyVariableName(fieldName); @@ -404,7 +404,7 @@ namespace XNodeEditor { int i = 0; while (node.HasPort(newName)) newName = fieldName + " " + (++i); - if (io == XNode.NodePort.IO.Output) node.AddDynamicOutput(type, connectionType, XNode.Node.TypeConstraint.None, newName); + if (io == XNode.NodePort.IO.Output) node.AddDynamicOutput(type, connectionType, XNode.INode.TypeConstraint.None, newName); else node.AddDynamicInput(type, connectionType, typeConstraint, newName); serializedObject.Update(); EditorUtility.SetDirty(node); diff --git a/Scripts/Editor/NodeEditorReflection.cs b/Scripts/Editor/NodeEditorReflection.cs index 6f7813d..7bf1fc6 100644 --- a/Scripts/Editor/NodeEditorReflection.cs +++ b/Scripts/Editor/NodeEditorReflection.cs @@ -47,7 +47,7 @@ namespace XNodeEditor { UnityEngine.Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(assetpath); // Loop through graph asset and search for nodes (nodes exist inside the graph asset as sub-assets) for (int k = 0; k < objs.Length; k++) { - XNode.Node node = objs[k] as XNode.Node; + XNode.INode node = objs[k] as XNode.INode; if (node != null) node.UpdateStaticPorts(); } } @@ -55,15 +55,15 @@ namespace XNodeEditor { public static Type[] GetNodeTypes() { //Get all classes deriving from Node via reflection - return GetDerivedTypes(typeof(XNode.Node)); + return GetDerivedTypes(typeof(XNode.INode)); } public static Dictionary GetNodeTint() { Dictionary tints = new Dictionary(); for (int i = 0; i < nodeTypes.Length; i++) { - var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.Node.NodeTintAttribute), true); + var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.INode.NodeTintAttribute), true); if (attribs == null || attribs.Length == 0) continue; - XNode.Node.NodeTintAttribute attrib = attribs[0] as XNode.Node.NodeTintAttribute; + XNode.INode.NodeTintAttribute attrib = attribs[0] as XNode.INode.NodeTintAttribute; tints.Add(nodeTypes[i], attrib.color); } return tints; @@ -72,9 +72,9 @@ namespace XNodeEditor { public static Dictionary GetNodeWidth() { Dictionary widths = new Dictionary(); for (int i = 0; i < nodeTypes.Length; i++) { - var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.Node.NodeWidthAttribute), true); + var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.INode.NodeWidthAttribute), true); if (attribs == null || attribs.Length == 0) continue; - XNode.Node.NodeWidthAttribute attrib = attribs[0] as XNode.Node.NodeWidthAttribute; + XNode.INode.NodeWidthAttribute attrib = attribs[0] as XNode.INode.NodeWidthAttribute; widths.Add(nodeTypes[i], attrib.width); } return widths; @@ -85,7 +85,7 @@ namespace XNodeEditor { // If we can't find field in the first run, it's probably a private field in a base class. FieldInfo field = type.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); // Search base classes for private fields only. Public fields are found above - while (field == null && (type = type.BaseType) != typeof(XNode.Node)) field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); + while (field == null && (type = type.BaseType) != typeof(XNode.INode)) field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); return field; } diff --git a/Scripts/Editor/NodeEditorResources.cs b/Scripts/Editor/NodeEditorResources.cs index 0a84e0a..d3ee007 100644 --- a/Scripts/Editor/NodeEditorResources.cs +++ b/Scripts/Editor/NodeEditorResources.cs @@ -8,7 +8,7 @@ namespace XNodeEditor { private static Texture2D _dot; public static Texture2D dotOuter { get { return _dotOuter != null ? _dotOuter : _dotOuter = Resources.Load("xnode_dot_outer"); } } private static Texture2D _dotOuter; - public static Texture2D nodeBody { get { return _nodeBody != null ? _nodeBody : _nodeBody = Resources.Load("xnode_node"); } } + public static Texture2D nodeBody { get { return _nodeBody != null ? _nodeBody : _nodeBody = Resources.Load("XNode.INode"); } } private static Texture2D _nodeBody; public static Texture2D nodeHighlight { get { return _nodeHighlight != null ? _nodeHighlight : _nodeHighlight = Resources.Load("xnode_node_highlight"); } } private static Texture2D _nodeHighlight; diff --git a/Scripts/Editor/NodeEditorUtilities.cs b/Scripts/Editor/NodeEditorUtilities.cs index 18e295f..6f4dd8b 100644 --- a/Scripts/Editor/NodeEditorUtilities.cs +++ b/Scripts/Editor/NodeEditorUtilities.cs @@ -134,7 +134,7 @@ namespace XNodeEditor { } /// Creates a new C# Class. - [MenuItem("Assets/Create/xNode/Node C# Script", false, 89)] + [MenuItem("Assets/Create/XNode.INode C# Script", false, 89)] private static void CreateNode() { string[] guids = AssetDatabase.FindAssets("xNode_NodeTemplate.cs"); if (guids.Length == 0) { diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs index 4d01065..85a5045 100644 --- a/Scripts/Editor/NodeEditorWindow.cs +++ b/Scripts/Editor/NodeEditorWindow.cs @@ -8,7 +8,7 @@ namespace XNodeEditor { public partial class NodeEditorWindow : EditorWindow { public static NodeEditorWindow current; - /// Stores node positions for all nodePorts. + /// Stores node.Positions for all nodePorts. public Dictionary portConnectionPoints { get { return _portConnectionPoints; } } private Dictionary _portConnectionPoints = new Dictionary(); [SerializeField] private NodePortReference[] _references = new NodePortReference[0]; @@ -56,9 +56,9 @@ namespace XNodeEditor { } } - public Dictionary nodeSizes { get { return _nodeSizes; } } - private Dictionary _nodeSizes = new Dictionary(); - public XNode.NodeGraph graph; + public Dictionary nodeSizes { get { return _nodeSizes; } } + private Dictionary _nodeSizes = new Dictionary(); + public XNode.INodeGraph graph; public Vector2 panOffset { get { return _panOffset; } set { _panOffset = value; Repaint(); } } private Vector2 _panOffset; public float zoom { get { return _zoom; } set { _zoom = Mathf.Clamp(value, 1f, NodeEditorPreferences.GetSettings().zoomOutLimit); Repaint(); } } @@ -78,7 +78,7 @@ namespace XNodeEditor { /// Handle Selection Change events private static void OnSelectionChanged() { - XNode.NodeGraph nodeGraph = Selection.activeObject as XNode.NodeGraph; + XNode.INodeGraph nodeGraph = Selection.activeObject as XNode.INodeGraph; if (nodeGraph && !AssetDatabase.Contains(nodeGraph)) { Open(nodeGraph); } @@ -113,7 +113,7 @@ namespace XNodeEditor { string path = EditorUtility.SaveFilePanelInProject("Save NodeGraph", "NewNodeGraph", "asset", ""); if (string.IsNullOrEmpty(path)) return; else { - XNode.NodeGraph existingGraph = AssetDatabase.LoadAssetAtPath(path); + XNode.INodeGraph existingGraph = AssetDatabase.LoadAssetAtPath(path); if (existingGraph != null) AssetDatabase.DeleteAsset(path); AssetDatabase.CreateAsset(graph, path); EditorUtility.SetDirty(graph); @@ -152,7 +152,7 @@ namespace XNodeEditor { return new Vector2(xOffset, yOffset); } - public void SelectNode(XNode.Node node, bool add) { + public void SelectNode(XNode.INode node, bool add) { if (add) { List selection = new List(Selection.objects); selection.Add(node); @@ -160,7 +160,7 @@ namespace XNodeEditor { } else Selection.objects = new Object[] { node }; } - public void DeselectNode(XNode.Node node) { + public void DeselectNode(XNode.INode node) { List selection = new List(Selection.objects); selection.Remove(node); Selection.objects = selection.ToArray(); @@ -168,7 +168,7 @@ namespace XNodeEditor { [OnOpenAsset(0)] public static bool OnOpen(int instanceID, int line) { - XNode.NodeGraph nodeGraph = EditorUtility.InstanceIDToObject(instanceID) as XNode.NodeGraph; + XNode.INodeGraph nodeGraph = EditorUtility.InstanceIDToObject(instanceID) as XNode.INodeGraph; if (nodeGraph != null) { Open(nodeGraph); return true; @@ -177,7 +177,7 @@ namespace XNodeEditor { } /// Open the provided graph in the NodeEditor - public static void Open(XNode.NodeGraph graph) { + public static void Open(XNode.INodeGraph graph) { if (!graph) return; NodeEditorWindow w = GetWindow(typeof(NodeEditorWindow), false, "xNode", true) as NodeEditorWindow; diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs index 8a9d2f0..cbed33a 100644 --- a/Scripts/Editor/NodeGraphEditor.cs +++ b/Scripts/Editor/NodeGraphEditor.cs @@ -34,7 +34,7 @@ namespace XNodeEditor { /// Returns context node menu path. Null or empty strings for hidden nodes. public virtual string GetNodeMenuName(Type type) { //Check if type has the CreateNodeMenuAttribute - XNode.Node.CreateNodeMenuAttribute attrib; + XNode.INode.CreateNodeMenuAttribute attrib; if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path return attrib.menuName; else // Return generated path @@ -70,8 +70,8 @@ namespace XNodeEditor { /// Create a node and save it in the graph asset public virtual void CreateNode(Type type, Vector2 position) { - XNode.Node node = target.AddNode(type); - node.position = position; + XNode.INode node = target.AddNode(type); + node.Position = position; if (string.IsNullOrEmpty(node.name)) node.name = UnityEditor.ObjectNames.NicifyVariableName(type.Name); AssetDatabase.AddObjectToAsset(node, target); if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); @@ -79,8 +79,8 @@ namespace XNodeEditor { } /// Creates a copy of the original node in the graph - public XNode.Node CopyNode(XNode.Node original) { - XNode.Node node = target.CopyNode(original); + public XNode.INode CopyNode(XNode.INode original) { + XNode.INode node = target.CopyNode(original); node.name = original.name; AssetDatabase.AddObjectToAsset(node, target); if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); @@ -88,7 +88,7 @@ namespace XNodeEditor { } /// Safely remove a node and all its connections. - public void RemoveNode(XNode.Node node) { + public void RemoveNode(XNode.INode node) { UnityEngine.Object.DestroyImmediate(node, true); target.RemoveNode(node); if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); diff --git a/Scripts/Editor/Resources/ScriptTemplates/xNode_NodeTemplate.cs.txt b/Scripts/Editor/Resources/ScriptTemplates/xNode_NodeTemplate.cs.txt index 144d9e1..caded4a 100644 --- a/Scripts/Editor/Resources/ScriptTemplates/xNode_NodeTemplate.cs.txt +++ b/Scripts/Editor/Resources/ScriptTemplates/xNode_NodeTemplate.cs.txt @@ -5,7 +5,12 @@ using XNode; public class #SCRIPTNAME# : Node { - // Use OnEnable for initialization + // Reset is called on creation + private void Reset() { + #NOTRIM# + } + + // OnEnable is called on load private void OnEnable() { #NOTRIM# } diff --git a/Scripts/Interfaces/INode.cs b/Scripts/Interfaces/INode.cs index 82dc762..bc96440 100644 --- a/Scripts/Interfaces/INode.cs +++ b/Scripts/Interfaces/INode.cs @@ -4,7 +4,7 @@ using UnityEngine; namespace XNode { public interface INode { - string name { get; set; } + string Name { get; set; } INodeGraph Graph { get; } Vector2 Position { get; set; } object GetValue(NodePort port); @@ -15,8 +15,8 @@ namespace XNode { IEnumerable Outputs { get; } IEnumerable Inputs { get; } IEnumerable InstancePorts { get; } - NodePort AddDynamicOutput(Type type, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = Node.TypeConstraint.None, string fieldName = null); - NodePort AddDynamicInput(Type type, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = Node.TypeConstraint.None, string fieldName = null); + NodePort AddDynamicPort(Type type, NodePort.IO direction, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = Node.TypeConstraint.None, string fieldName = null); + NodePort RemoveDynamicPort(string fieldName); NodePort GetInputPort(string fieldName); NodePort GetOutputPort(string fieldName); void OnCreateConnection(NodePort from, NodePort to); diff --git a/Scripts/Interfaces/INodeGraph.cs b/Scripts/Interfaces/INodeGraph.cs index 39e3c7f..962afa0 100644 --- a/Scripts/Interfaces/INodeGraph.cs +++ b/Scripts/Interfaces/INodeGraph.cs @@ -1,11 +1,11 @@ using System; +using System.Collections.Generic; 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(); + IEnumerable Nodes { get; } INode AddNode(Type type); INode CopyNode(INode original); void RemoveNode(INode node); diff --git a/Scripts/Node.cs b/Scripts/Node.cs index c9fb68b..2fe4968 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -92,6 +92,12 @@ namespace XNode { } #endregion +#region Interface implementation + string INode.Name { get { return name; } set { name = value; } } + INodeGraph INode.Graph { get { return graph; } } + Vector2 INode.Position { get { return position; } set { position = value; } } +#endregion + /// Iterate over all ports on this node. public IEnumerable Ports { get { foreach (NodePort port in ports.Values) yield return port; } } /// Iterate over all outputs on this node. @@ -105,9 +111,7 @@ 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 - public INodeGraph Graph { get { return graph; } } - /// Parent - [SerializeField] private NodeGraph graph; + [SerializeField] public NodeGraph graph; /// Position on the [SerializeField] public Vector2 position; /// It is recommended not to modify these at hand. Instead, see and @@ -136,20 +140,20 @@ namespace XNode { /// /// public NodePort AddDynamicInput(Type type, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) { - return AddDynamicPort(type, NodePort.IO.Input, connectionType, typeConstraint, fieldName); + return ((INode)this).AddDynamicPort(type, NodePort.IO.Input, connectionType, typeConstraint, fieldName); } /// Convenience function. /// /// public NodePort AddDynamicOutput(Type type, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) { - return AddDynamicPort(type, NodePort.IO.Output, connectionType, typeConstraint, fieldName); + return ((INode)this).AddDynamicPort(type, NodePort.IO.Output, connectionType, typeConstraint, fieldName); } /// Add a dynamic, serialized port to this node. /// /// - private NodePort AddDynamicPort(Type type, NodePort.IO direction, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) { + NodePort INode.AddDynamicPort(Type type, NodePort.IO direction, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) { if (fieldName == null) { fieldName = "dynamicInput_0"; int i = 0; diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs index a310727..7cebce3 100644 --- a/Scripts/NodeGraph.cs +++ b/Scripts/NodeGraph.cs @@ -11,11 +11,28 @@ namespace XNode { /// See: [SerializeField] public List nodes = new List(); +#region Interface implementation + IEnumerable INodeGraph.Nodes { get { foreach (Node node in nodes) yield return node; } } + INode INodeGraph.AddNode(Type type) { return AddNode(type); } + void INodeGraph.MoveNodeToTop(INode node) { MoveNodeToTop(node as Node); } + INode INodeGraph.CopyNode(INode original) { return CopyNode(original as Node); } + void INodeGraph.RemoveNode(INode node) { RemoveNode(node as Node); } +#endregion + /// Add a node to the graph by type (convenience method - will call the System.Type version) public T AddNode() where T : Node { return AddNode(typeof(T)) as T; } + /// Draw this node on top of other nodes by placing it last in the graph.nodes list + public void MoveNodeToTop(XNode.Node node) { + int index; + while ((index = nodes.IndexOf(node as Node)) != nodes.Count - 1) { + nodes[index] = nodes[index + 1]; + nodes[index + 1] = node as Node; + } + } + /// Add a node to the graph by type public virtual Node AddNode(Type type) { Node.graphHotfix = this;