diff --git a/Scripts/Node.cs b/Scripts/Node.cs index f27af6a..bf7f32e 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -63,6 +63,9 @@ namespace XNode { protected void OnEnable() { UpdateStaticPorts(); Init(); + if (graph != null && !graph.CopyInProgress) { + OnEnableOverride(); + } } /// Update static ports to reflect class fields. This happens automatically on enable. @@ -73,6 +76,18 @@ namespace XNode { /// Initialize node. Called on creation. protected virtual void Init() { } + + /// + /// Initialize node. Called on creation and after clone in the correct order. + /// + // Implementation note: This method is called after a node has been instantiated, and also + // called directly when cloning a full graph. This simply calls Init(), which cannot be + // called from outside, as it is protected, not public, and making it public would break + // existing code. + public virtual void OnEnableOverride() { + Init(); + } + /// Checks all connections for invalid references, and removes them. public void VerifyConnections() { foreach (NodePort port in Ports) port.VerifyConnections(); diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs index d6d766c..fd3dfdb 100644 --- a/Scripts/NodeGraph.cs +++ b/Scripts/NodeGraph.cs @@ -11,6 +11,11 @@ namespace XNode { /// See: [SerializeField] public List nodes = new List(); + // Non serialized flag to indicate a copy operation is currently underway. + // This stops nodes from calling OnEnableOverride before we updated the + // graph reference. + public bool CopyInProgress { get; protected set; } + /// Add a node to the graph by type public T AddNode() where T : Node { return AddNode(typeof(T)) as T; @@ -21,16 +26,24 @@ namespace XNode { Node node = ScriptableObject.CreateInstance(type) as Node; nodes.Add(node); node.graph = this; + node.OnEnableOverride(); return node; } /// Creates a copy of the original node in the graph public virtual Node CopyNode(Node original) { - Node node = ScriptableObject.Instantiate(original); - node.ClearConnections(); - nodes.Add(node); - node.graph = this; - return node; + this.CopyInProgress = true; + try { + Node node = ScriptableObject.Instantiate(original); + node.ClearConnections(); + nodes.Add(node); + node.graph = this; + node.OnEnableOverride(); + return node; + } + finally { + this.CopyInProgress = false; + } } /// Safely remove a node and all its connections @@ -55,20 +68,34 @@ namespace XNode { public XNode.NodeGraph Copy() { // Instantiate a new nodegraph instance NodeGraph graph = Instantiate(this); - // Instantiate all nodes inside the graph - for (int i = 0; i < nodes.Count; i++) { - if (nodes[i] == null) continue; - Node node = Instantiate(nodes[i]) as Node; - node.graph = graph; - graph.nodes[i] = node; - } - - // Redirect all connections - for (int i = 0; i < graph.nodes.Count; i++) { - if (graph.nodes[i] == null) continue; - foreach (NodePort port in graph.nodes[i].Ports) { - port.Redirect(nodes, graph.nodes); + graph.CopyInProgress = true; + try { + // Instantiate all nodes inside the graph + for (int i = 0; i < nodes.Count; i++) { + if (nodes[i] == null) continue; + Node node = Instantiate(nodes[i]) as Node; + node.graph = graph; + graph.nodes[i] = node; } + + // Redirect all connections + for (int i = 0; i < graph.nodes.Count; i++) { + if (graph.nodes[i] == null) continue; + foreach (NodePort port in graph.nodes[i].Ports) { + port.Redirect(nodes, graph.nodes); + } + } + + // Call the Enable notifier, which was not fired during the + // normal instantiation. + for (int i = 0; i < graph.nodes.Count; i++) { + var node = graph.nodes[i]; + if (node == null) continue; + node.OnEnableOverride(); + } + } + finally { + graph.CopyInProgress = false; } return graph;