From 0c6466f0b6e80a47f89f8054d7e98e91a5c72ed6 Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Sun, 7 Jan 2018 23:32:16 +0100 Subject: [PATCH 1/2] Documentation --- Scripts/Node.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Scripts/Node.cs b/Scripts/Node.cs index 9cc7bb3e..7a9f3399 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -3,9 +3,28 @@ using UnityEngine; namespace XNode { - /// Base class for all nodes + /// + /// Base class for all nodes + /// + /// + /// Classes extending this class will be considered as valid nodes by xNode. + /// + /// [System.Serializable] + /// public class Adder : Node { + /// [Input] public float a; + /// [Input] public float b; + /// [Output] public float result; + /// + /// // GetValue should be overridden to return a value for any specified output port + /// public override object GetValue(NodePort port) { + /// return a + b; + /// } + /// } + /// + /// [Serializable] public abstract class Node : ScriptableObject { + /// Used by and to determine when to display the field value associated with a public enum ShowBackingValue { /// Never show the backing value Never, From 6e649dcc24f086aa7ee5eff558851ada5f99d9bc Mon Sep 17 00:00:00 2001 From: Thor Kramer Brigsted Date: Mon, 8 Jan 2018 14:34:54 +0100 Subject: [PATCH 2/2] Automatically relink renamed Node scripts --- Scripts/Editor/NodeEditorAssetModProcessor.cs | 52 ++++++++++++++----- Scripts/Editor/NodeEditorGUI.cs | 3 +- Scripts/Node.cs | 14 ++++- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/Scripts/Editor/NodeEditorAssetModProcessor.cs b/Scripts/Editor/NodeEditorAssetModProcessor.cs index bf858bce..61a2518c 100644 --- a/Scripts/Editor/NodeEditorAssetModProcessor.cs +++ b/Scripts/Editor/NodeEditorAssetModProcessor.cs @@ -2,34 +2,58 @@ using UnityEngine; namespace XNodeEditor { - public class NodeEditorAssetModProcessor : UnityEditor.AssetModificationProcessor { - public static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions options) { - UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(path); + /// Deals with modified assets + class NodeEditorAssetModProcessor : UnityEditor.AssetModificationProcessor { + /// Automatically delete Node sub-assets before deleting their script. + /// This is important to do, because you can't delete null sub assets. + private static AssetDeleteResult OnWillDeleteAsset (string path, RemoveAssetOptions options) { + // Get the object that is requested for deletion + UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath (path); + + // If we aren't deleting a script, return if (!(obj is UnityEditor.MonoScript)) return AssetDeleteResult.DidNotDelete; + // Check script type. Return if deleting a non-node script UnityEditor.MonoScript script = obj as UnityEditor.MonoScript; - System.Type scriptType = script.GetClass(); - - if (scriptType != typeof(XNode.Node) && !scriptType.IsSubclassOf(typeof(XNode.Node))) return AssetDeleteResult.DidNotDelete; + System.Type scriptType = script.GetClass (); + if (scriptType != typeof (XNode.Node) && !scriptType.IsSubclassOf (typeof (XNode.Node))) return AssetDeleteResult.DidNotDelete; - //Find ScriptableObjects using this script - string[] guids = AssetDatabase.FindAssets("t:" + scriptType); + // Find all ScriptableObjects using this script + string[] guids = AssetDatabase.FindAssets ("t:" + scriptType); for (int i = 0; i < guids.Length; i++) { - string assetpath = AssetDatabase.GUIDToAssetPath(guids[i]); - Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(assetpath); + 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; - if (node.GetType() == scriptType) { + if (node.GetType () == scriptType) { if (node != null && node.graph != null) { - Debug.LogWarning(node.name + " of " + node.graph + " depended on deleted script and has been removed automatically.", node.graph); - node.graph.RemoveNode(node); + // Delete the node and notify the user + Debug.LogWarning (node.name + " of " + node.graph + " depended on deleted script and has been removed automatically.", node.graph); + node.graph.RemoveNode (node); } } } - } + // We didn't actually delete the script. Tell the internal system to carry on with normal deletion procedure return AssetDeleteResult.DidNotDelete; } + + /// Automatically re-add loose node assets to the Graph node list + [InitializeOnLoadMethod] + private static void OnReloadEditor () { + // Find all NodeGraph assets + string[] guids = AssetDatabase.FindAssets ("t:" + typeof (XNode.NodeGraph)); + for (int i = 0; i < guids.Length; i++) { + string assetpath = AssetDatabase.GUIDToAssetPath (guids[i]); + XNode.NodeGraph graph = AssetDatabase.LoadAssetAtPath (assetpath, typeof (XNode.NodeGraph)) as XNode.NodeGraph; + graph.nodes.RemoveAll(x => x == null); //Remove null items + 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); + } + } + } } } \ No newline at end of file diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index e405a2e4..f8ab6d5c 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -193,7 +193,8 @@ private void DrawNodes() { //Save guiColor so we can revert it Color guiColor = GUI.color; for (int n = 0; n < graph.nodes.Count; n++) { - while (graph.nodes[n] == null) graph.nodes.RemoveAt(n); + // Skip null nodes. The user could be in the process of renaming scripts, so removing them at this point is not advisable. + if (graph.nodes[n] == null) continue; if (n >= graph.nodes.Count) return; XNode.Node node = graph.nodes[n]; diff --git a/Scripts/Node.cs b/Scripts/Node.cs index 7a9f3399..2dc979b5 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -67,16 +67,26 @@ public void VerifyConnections() { } #region Instance Ports - /// Returns input port at index + /// Convenience function. + /// + /// + /// public NodePort AddInstanceInput(Type type, string fieldName = null) { return AddInstancePort(type, NodePort.IO.Input, fieldName); } - /// Returns input port at index + /// Convenience function. + /// + /// + /// public NodePort AddInstanceOutput(Type type, string fieldName = null) { return AddInstancePort(type, NodePort.IO.Output, fieldName); } + /// Add a dynamic, serialized port to this node. + /// + /// + /// private NodePort AddInstancePort(Type type, NodePort.IO direction, string fieldName = null) { if (fieldName == null) { fieldName = "instanceInput_0";