/// <summary>
        /// Creates a working copy of the specified nodeCanvas, and optionally also of it's associated editorStates.
        /// This breaks the link of this object to any stored assets and references. That means, that all changes to this object will have to be explicitly saved.
        /// </summary>
        public static NodeCanvas CreateWorkingCopy(NodeCanvas nodeCanvas, bool editorStates)
        {
            nodeCanvas.Validate();
            nodeCanvas = Clone(nodeCanvas);

            // Take each SO, make a clone of it and store both versions in the respective list
            // This will only iterate over the 'source instances'
            List <ScriptableObject> allSOs    = new List <ScriptableObject> ();
            List <ScriptableObject> clonedSOs = new List <ScriptableObject> ();

            for (int nodeCnt = 0; nodeCnt < nodeCanvas.nodes.Count; nodeCnt++)
            {
                Node node = nodeCanvas.nodes[nodeCnt];
                node.FixNode();
                node.CheckNodeKnobMigration();

                // Clone Node and additional scriptableObjects
                Node clonedNode = AddClonedSO(allSOs, clonedSOs, node);
                AddClonedSOs(allSOs, clonedSOs, clonedNode.GetScriptableObjects());

                foreach (NodeKnob knob in clonedNode.nodeKnobs)
                {                 // Clone NodeKnobs and additional scriptableObjects
                    if (knob == null)
                    {
                        continue;
                    }
                    AddClonedSO(allSOs, clonedSOs, knob);
                    AddClonedSOs(allSOs, clonedSOs, knob.GetScriptableObjects());
                }
            }

            // Replace every reference to any of the initial SOs of the first list with the respective clones of the second list
            for (int nodeCnt = 0; nodeCnt < nodeCanvas.nodes.Count; nodeCnt++)
            {             // Clone Nodes, structural content and additional scriptableObjects
                Node node = nodeCanvas.nodes[nodeCnt];
                // Replace node and additional ScriptableObjects
                Node clonedNode = nodeCanvas.nodes[nodeCnt] = ReplaceSO(allSOs, clonedSOs, node);
                clonedNode.CopyScriptableObjects((ScriptableObject so) => ReplaceSO(allSOs, clonedSOs, so));

                // We're going to restore these from NodeKnobs, no need to Replace muliple times
                clonedNode.Inputs  = new List <NodeInput> ();
                clonedNode.Outputs = new List <NodeOutput> ();
                for (int knobCnt = 0; knobCnt < clonedNode.nodeKnobs.Count; knobCnt++)
                {                 // Clone generic NodeKnobs
                    NodeKnob knob = clonedNode.nodeKnobs[knobCnt] = ReplaceSO(allSOs, clonedSOs, clonedNode.nodeKnobs[knobCnt]);
                    if (knob == null)
                    {
                        continue;
                    }
                    knob.body = clonedNode;
                    // Replace additional scriptableObjects in the NodeKnob
                    knob.CopyScriptableObjects((ScriptableObject so) => ReplaceSO(allSOs, clonedSOs, so));
                    // Add it into Inputs/Outputs again
                    if (knob is NodeInput)
                    {
                        clonedNode.Inputs.Add(knob as NodeInput);
                    }
                    else if (knob is NodeOutput)
                    {
                        clonedNode.Outputs.Add(knob as NodeOutput);
                    }
                }
            }

            if (editorStates)
            {
                nodeCanvas.editorStates = CreateWorkingCopy(nodeCanvas.editorStates, nodeCanvas);
                foreach (NodeEditorState state in nodeCanvas.editorStates)
                {
                    state.selectedNode = ReplaceSO(allSOs, clonedSOs, state.selectedNode);
                }
            }
            else
            {
                foreach (NodeEditorState state in nodeCanvas.editorStates)
                {
                    state.selectedNode = null;
                }
            }

            return(nodeCanvas);
        }