/// <summary> /// Saves the the given NodeCanvas along with the given NodeEditorStates if specified as a new asset, optionally as working copies /// </summary> public static void SaveNodeCanvas(string path, NodeCanvas nodeCanvas, bool createWorkingCopy) { #if !UNITY_EDITOR throw new System.NotImplementedException(); #endif if (string.IsNullOrEmpty(path)) { throw new UnityException("Cannot save NodeCanvas: No spath specified to save the NodeCanvas " + (nodeCanvas != null? nodeCanvas.name : "") + " to!"); } if (nodeCanvas == null) { throw new UnityException("Cannot save NodeCanvas: The specified NodeCanvas that should be saved to path " + path + " is null!"); } if (nodeCanvas.livesInScene) { Debug.LogWarning("Attempting to save scene canvas " + nodeCanvas.name + " to an asset, scene object references will be broken!" + (!createWorkingCopy? " No workingCopy is going to be created, so your scene save is broken, too!" : "")); } #if UNITY_EDITOR if (!createWorkingCopy && UnityEditor.AssetDatabase.Contains(nodeCanvas) && UnityEditor.AssetDatabase.GetAssetPath(nodeCanvas) != path) { Debug.LogError("Trying to create a duplicate save file for '" + nodeCanvas.name + "'! Forcing to create a working copy!"); createWorkingCopy = true; } #endif nodeCanvas.livesInScene = false; nodeCanvas.Validate(); #if UNITY_EDITOR // Preprocess the canvas if (createWorkingCopy) { nodeCanvas = CreateWorkingCopy(nodeCanvas, true); Compress(ref nodeCanvas); } // Write canvas and editorStates UnityEditor.AssetDatabase.CreateAsset(nodeCanvas, path); AddSubAssets(nodeCanvas.editorStates, nodeCanvas); // Write nodes + contents foreach (Node node in nodeCanvas.nodes) { // Write node and additional scriptable objects AddSubAsset(node, nodeCanvas); AddSubAssets(node.GetScriptableObjects(), node); foreach (NodeKnob knob in node.nodeKnobs) { // Write knobs and their additional scriptable objects AddSubAsset(knob, node); AddSubAssets(knob.GetScriptableObjects(), knob); } } UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); #else // TODO: Node Editor: Need to implement ingame-saving (Resources, AsssetBundles, ... won't work) #endif NodeEditorCallbacks.IssueOnSaveCanvas(nodeCanvas); }
/// <summary> /// Saves the the specified NodeCanvas as a new asset at path, optionally as a working copy and overwriting any existing save at path /// </summary> public static void SaveNodeCanvas(string path, ref NodeCanvas nodeCanvas) { if (string.IsNullOrEmpty(path)) { throw new System.ArgumentNullException("Cannot save NodeCanvas: No path specified!"); } if (nodeCanvas == null) { throw new System.ArgumentNullException("Cannot save NodeCanvas: The specified NodeCanvas that should be saved to path '" + path + "' is null!"); } if (nodeCanvas.GetType() == typeof(NodeCanvas)) { throw new System.ArgumentException( "Cannot save NodeCanvas: The NodeCanvas has no explicit type! Please convert it to a valid sub-type of NodeCanvas!"); } nodeCanvas.Validate(); if (!UnityEditor.AssetDatabase.Contains(nodeCanvas)) { UnityEditor.AssetDatabase.CreateAsset(nodeCanvas, path); } PurifyCanvas(path); UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); NodeEditorCallbacks.IssueOnSaveCanvas(nodeCanvas); }
/// <summary> /// Saves the current node canvas as a new asset and links optional editorStates with it /// </summary> public static void SaveNodeCanvas(NodeCanvas nodeCanvas, string path, params NodeEditorState[] editorStates) { if (String.IsNullOrEmpty(path)) { return; } nodeCanvas = GetWorkingCopy(nodeCanvas); for (int stateCnt = 0; stateCnt < editorStates.Length; stateCnt++) { editorStates[stateCnt] = GetWorkingCopy(editorStates[stateCnt], nodeCanvas); } #if UNITY_EDITOR UnityEditor.AssetDatabase.CreateAsset(nodeCanvas, path); foreach (NodeEditorState editorState in editorStates) { UnityEditor.AssetDatabase.AddObjectToAsset(editorState, nodeCanvas); editorState.hideFlags = HideFlags.HideInHierarchy; } for (int nodeCnt = 0; nodeCnt < nodeCanvas.nodes.Count; nodeCnt++) { // Add every node and every of it's inputs/outputs into the file. // Results in a big mess but there's no other way (like a hierarchy) Node node = nodeCanvas.nodes [nodeCnt]; UnityEditor.AssetDatabase.AddObjectToAsset(node, nodeCanvas); node.hideFlags = HideFlags.HideInHierarchy; for (int inCnt = 0; inCnt < node.Inputs.Count; inCnt++) { UnityEditor.AssetDatabase.AddObjectToAsset(node.Inputs [inCnt], node); node.Inputs [inCnt].hideFlags = HideFlags.HideInHierarchy; } for (int outCnt = 0; outCnt < node.Outputs.Count; outCnt++) { UnityEditor.AssetDatabase.AddObjectToAsset(node.Outputs [outCnt], node); node.Outputs [outCnt].hideFlags = HideFlags.HideInHierarchy; } for (int transCnt = 0; transCnt < node.transitions.Count; transCnt++) { UnityEditor.AssetDatabase.AddObjectToAsset(node.transitions [transCnt], node); node.transitions [transCnt].hideFlags = HideFlags.HideInHierarchy; } } UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); #else // TODO: Node Editor: Need to implement ingame-saving (Resources, AsssetBundles, ... won't work) #endif NodeEditorCallbacks.IssueOnSaveCanvas(nodeCanvas); }
private static void SaveCanvas(NodeEditorInputInfo info) { if (info.inputEvent.type == EventType.Layout) { return; } #if UNITY_EDITOR NodeEditorState state = info.editorState; if (!string.IsNullOrEmpty(state.canvas.savePath)) { NodeEditorSaveManager.SaveNodeCanvas(state.canvas.savePath, ref state.canvas, true); EditorWindow.focusedWindow.ShowNotification(new GUIContent("Canvas Saved!")); NodeEditorCallbacks.IssueOnSaveCanvas(state.canvas); } else { EditorWindow.focusedWindow.ShowNotification(new GUIContent("No save location found. Use 'Save As' [Ctrl+Alt+S]")); } #endif info.inputEvent.Use(); }
/// <summary> /// Saves the the specified NodeCanvas as a new asset at path, optionally as a working copy and overwriting any existing save at path /// </summary> public static void SaveNodeCanvas(string path, ref NodeCanvas nodeCanvas, bool createWorkingCopy = false, bool safeOverwrite = true) { #if !UNITY_EDITOR throw new System.NotImplementedException(); #else if (string.IsNullOrEmpty(path)) { throw new System.ArgumentNullException("Cannot save NodeCanvas: No path specified!"); } if (nodeCanvas == null) { throw new System.ArgumentNullException("Cannot save NodeCanvas: The specified NodeCanvas that should be saved to path '" + path + "' is null!"); } if (nodeCanvas.GetType() == typeof(NodeCanvas)) { throw new System.ArgumentException("Cannot save NodeCanvas: The NodeCanvas has no explicit type! Please convert it to a valid sub-type of NodeCanvas!"); } if (nodeCanvas.allowSceneSaveOnly) { throw new System.InvalidOperationException("Cannot save NodeCanvas: NodeCanvas is marked to contain scene data and cannot be saved as an asset!"); } nodeCanvas.Validate(); if (nodeCanvas.livesInScene) { Debug.LogWarning("Attempting to save scene canvas '" + nodeCanvas.name + "' to an asset, references to scene object may be broken!" + (!createWorkingCopy? " Forcing creation of working copy!" : "")); createWorkingCopy = true; } if (UnityEditor.AssetDatabase.Contains(nodeCanvas) && UnityEditor.AssetDatabase.GetAssetPath(nodeCanvas) != path) { Debug.LogWarning("Trying to create a duplicate save file for '" + nodeCanvas.name + "'! Forcing creation of working copy!"); nodeCanvas = CreateWorkingCopy(nodeCanvas); } // Prepare and update source path of the canvas path = ResourceManager.PreparePath(path); nodeCanvas.UpdateSource(path); // Preprocess the canvas NodeCanvas processedCanvas = nodeCanvas; processedCanvas.OnBeforeSavingCanvas(); if (createWorkingCopy) { processedCanvas = CreateWorkingCopy(processedCanvas); } // Differenciate canvasSave as the canvas asset and nodeCanvas as the source incase an existing save has been overwritten NodeCanvas canvasSave = processedCanvas; NodeCanvas prevSave; if (safeOverwrite && (prevSave = ResourceManager.LoadResource <NodeCanvas> (path)) != null && prevSave.GetType() == canvasSave.GetType()) { // OVERWRITE: Delete contents of old save Object[] subAssets = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path); for (int i = 0; i < subAssets.Length; i++) { // Delete all subassets except the main canvas to preserve references if (subAssets[i] != prevSave) { Object.DestroyImmediate(subAssets[i], true); } } // Overwrite main canvas OverwriteCanvas(ref prevSave, processedCanvas); canvasSave = prevSave; } else { // Write main canvas UnityEditor.AssetDatabase.DeleteAsset(path); UnityEditor.AssetDatabase.CreateAsset(processedCanvas, path); } // Write editorStates AddSubAssets(processedCanvas.editorStates, canvasSave); // Write nodes + contents foreach (Node node in processedCanvas.nodes) { // Write node and additional scriptable objects AddSubAsset(node, canvasSave); AddSubAssets(node.GetScriptableObjects(), node); // Make sure all node ports are included in the representative connectionPorts list ConnectionPortManager.UpdatePortLists(node); foreach (ConnectionPort port in node.connectionPorts) { AddSubAsset(port, node); } } XProfile.Begin("-"); UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); XProfile.End(true); NodeEditorCallbacks.IssueOnSaveCanvas(canvasSave); #endif }
/// <summary> /// Saves the nodeCanvas in the current scene under the specified name, optionally as a working copy and overwriting any existing save at path /// If the specified canvas is stored as an asset, the saved canvas will loose the reference to the asset /// </summary> public static void SaveSceneNodeCanvas(string saveName, ref NodeCanvas nodeCanvas, bool createWorkingCopy, bool safeOverwrite = true) { if (string.IsNullOrEmpty(saveName)) { throw new System.ArgumentNullException("Cannot save Canvas to scene: No save name specified!"); } if (nodeCanvas == null) { throw new System.ArgumentNullException("Cannot save NodeCanvas: The specified NodeCanvas that should be saved as '" + saveName + "' is null!"); } if (nodeCanvas.GetType() == typeof(NodeCanvas)) { throw new System.ArgumentException("Cannot save NodeCanvas: The NodeCanvas has no explicit type! Please convert it to a valid sub-type of NodeCanvas!"); } if (saveName.StartsWith("SCENE/")) { saveName = saveName.Substring(6); } nodeCanvas.Validate(); if (!nodeCanvas.livesInScene #if UNITY_EDITOR // Make sure the canvas has no reference to an asset || UnityEditor.AssetDatabase.Contains(nodeCanvas) #endif ) { Debug.LogWarning("Creating scene save '" + nodeCanvas.name + "' for canvas saved as an asset! Forcing creation of working copy!"); nodeCanvas = CreateWorkingCopy(nodeCanvas); } // Update the source of the canvas nodeCanvas.UpdateSource("SCENE/" + saveName); // Preprocess the canvas NodeCanvas processedCanvas = nodeCanvas; processedCanvas.OnBeforeSavingCanvas(); if (createWorkingCopy) { processedCanvas = CreateWorkingCopy(processedCanvas); } // Get the saveHolder and store the canvas NodeCanvas savedCanvas = processedCanvas; NodeCanvasSceneSave sceneSave = FindSceneSave(saveName, true); #if UNITY_EDITOR if (sceneSave.savedNodeCanvas != null && safeOverwrite && sceneSave.savedNodeCanvas.GetType() == savedCanvas.GetType()) // OVERWRITE { OverwriteCanvas(ref sceneSave.savedNodeCanvas, savedCanvas); } if (!Application.isPlaying) { // Set Dirty UnityEditor.EditorUtility.SetDirty(sceneSave.gameObject); #if UNITY_5_3_OR_NEWER || UNITY_5_3 UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(sceneSave.gameObject.scene); #else UnityEditor.EditorApplication.MarkSceneDirty(); #endif } #endif sceneSave.savedNodeCanvas = savedCanvas; NodeEditorCallbacks.IssueOnSaveCanvas(savedCanvas); }
/// <summary> /// Saves the the specified NodeCanvas as a new asset at path, optionally as a working copy and overwriting any existing save at path /// </summary> public static void SaveNodeCanvas(string path, ref NodeCanvas nodeCanvas, bool createWorkingCopy, bool safeOverwrite = true) { #if !UNITY_EDITOR throw new System.NotImplementedException(); // TODO: Node Editor: Need to implement ingame-saving (Resources, AsssetBundles, ... won't work) #endif if (string.IsNullOrEmpty(path)) { throw new System.ArgumentNullException("Cannot save NodeCanvas: No path specified!"); } if (nodeCanvas == null) { throw new System.ArgumentNullException("Cannot save NodeCanvas: The specified NodeCanvas that should be saved to path '" + path + "' is null!"); } if (nodeCanvas.GetType() == typeof(NodeCanvas)) { throw new System.ArgumentException("Cannot save NodeCanvas: The NodeCanvas has no explicit type! Please convert it to a valid sub-type of NodeCanvas!"); } if (nodeCanvas.livesInScene) { Debug.LogWarning("Attempting to save scene canvas '" + nodeCanvas.name + "' to an asset, references to scene object may be broken!" + (!createWorkingCopy? " Forcing creation of working copy!" : "")); createWorkingCopy = true; } #if UNITY_EDITOR if (UnityEditor.AssetDatabase.Contains(nodeCanvas) && UnityEditor.AssetDatabase.GetAssetPath(nodeCanvas) != path) { Debug.LogWarning("Trying to create a duplicate save file for '" + nodeCanvas.name + "'! Forcing creation of working copy!"); ProcessCanvas(ref nodeCanvas, true); } #endif #if UNITY_EDITOR // Prepare and update source path of the canvas path = ResourceManager.PreparePath(path); nodeCanvas.UpdateSource(path); // Preprocess the canvas NodeCanvas processedCanvas = nodeCanvas; processedCanvas.OnBeforeSavingCanvas(); ProcessCanvas(ref processedCanvas, createWorkingCopy); // Differenciate canvasSave as the canvas asset and nodeCanvas as the source incase an existing save has been overwritten NodeCanvas canvasSave = processedCanvas; NodeCanvas prevSave; if (safeOverwrite && (prevSave = ResourceManager.LoadResource <NodeCanvas> (path)) != null && prevSave.GetType() == canvasSave.GetType()) { // OVERWRITE: Delete contents of old save for (int nodeCnt = 0; nodeCnt < prevSave.nodes.Count; nodeCnt++) { Node node = prevSave.nodes[nodeCnt]; for (int knobCnt = 0; knobCnt < node.nodeKnobs.Count; knobCnt++) { if (node.nodeKnobs[knobCnt] != null) { Object.DestroyImmediate(node.nodeKnobs[knobCnt], true); } } Object.DestroyImmediate(node, true); } for (int i = 0; i < prevSave.editorStates.Length; i++) { if (prevSave.editorStates[i] != null) { Object.DestroyImmediate(prevSave.editorStates[i], true); } } // Overwrite main canvas OverwriteCanvas(ref prevSave, processedCanvas); canvasSave = prevSave; } else { // Write main canvas UnityEditor.AssetDatabase.CreateAsset(processedCanvas, path); } // Write editorStates AddSubAssets(processedCanvas.editorStates, canvasSave); // Write nodes + contents foreach (Node node in processedCanvas.nodes) { // Write node and additional scriptable objects AddSubAsset(node, canvasSave); AddSubAssets(node.GetScriptableObjects(), node); foreach (NodeKnob knob in node.nodeKnobs) { AddSubAsset(knob, node); } } //UnityEditor.AssetDatabase.SaveAssets (); //UnityEditor.AssetDatabase.Refresh (); NodeEditorCallbacks.IssueOnSaveCanvas(canvasSave); #endif }
/// <summary> /// Saves the the given NodeCanvas or, if specified, a working copy of it, as a new asset along with working copies, if specified, of the given NodeEditorStates /// </summary> public static void SaveNodeCanvas(string path, bool createWorkingCopy, NodeCanvas nodeCanvas, params NodeEditorState[] editorStates) { if (string.IsNullOrEmpty(path)) { throw new UnityException("Cannot save NodeCanvas: No spath specified to save the NodeCanvas " + (nodeCanvas != null? nodeCanvas.name : "") + " to!"); } if (nodeCanvas == null) { throw new UnityException("Cannot save NodeCanvas: The specified NodeCanvas that should be saved to path " + path + " is null!"); } for (int stateCnt = 0; stateCnt < editorStates.Length; stateCnt++) { if (editorStates[stateCnt] == null) { Debug.LogError("A NodeEditorState that should be saved to path " + path + " is null!"); } } path = path.Replace(Application.dataPath, "Assets"); #if UNITY_EDITOR if (createWorkingCopy) { // Copy canvas and editorStates CreateWorkingCopy(ref nodeCanvas, editorStates, true); } // Write canvas and editorStates UnityEditor.AssetDatabase.CreateAsset(nodeCanvas, path); for (int stateCnt = 0; stateCnt < editorStates.Length; stateCnt++) { if (editorStates[stateCnt] != null) { AddSubAsset(editorStates[stateCnt], nodeCanvas); } } // Write nodes + contents for (int nodeCnt = 0; nodeCnt < nodeCanvas.nodes.Count; nodeCnt++) { // Every node and each ScriptableObject in it Node node = nodeCanvas.nodes [nodeCnt]; AddSubAsset(node, nodeCanvas); for (int knobCnt = 0; knobCnt < node.nodeKnobs.Count; knobCnt++) { AddSubAsset(node.nodeKnobs [knobCnt], node); } for (int transCnt = 0; transCnt < node.transitions.Count; transCnt++) { if (node.transitions[transCnt].startNode == node) { AddSubAsset(node.transitions [transCnt], node); // Debug.Log ("Did save Transition " + node.transitions [transCnt].name + " because its Node " + node.name + " is the start node!"); } // else // Debug.Log ("Did NOT save Transition " + node.transitions [transCnt].name + " because its Node " + node.name + " is NOT the start node (" + (node.transitions[transCnt].startNode != null? node.transitions[transCnt].startNode.name : "Null") + ")!"); } } UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); #else // TODO: Node Editor: Need to implement ingame-saving (Resources, AsssetBundles, ... won't work) #endif NodeEditorCallbacks.IssueOnSaveCanvas(nodeCanvas); }
/// <summary> /// Saves the the given NodeCanvas or, if specified, a working copy of it, as a new asset along with working copies, if specified, of the given NodeEditorStates /// </summary> public static void SaveNodeCanvas(string path, bool createWorkingCopy, NodeCanvas nodeCanvas, params NodeEditorState[] editorStates) { if (string.IsNullOrEmpty(path)) { throw new UnityException("Cannot save NodeCanvas: No spath specified to save the NodeCanvas " + (nodeCanvas != null? nodeCanvas.name : "") + " to!"); } if (nodeCanvas == null) { throw new UnityException("Cannot save NodeCanvas: The specified NodeCanvas that should be saved to path " + path + " is null!"); } foreach (NodeEditorState state in editorStates) { if (state == null) { Debug.LogError("A NodeEditorState that should be saved to path " + path + " is null!"); } } path = path.Replace(Application.dataPath, "Assets"); #if UNITY_EDITOR if (createWorkingCopy) { // Copy canvas and editorStates CreateWorkingCopy(ref nodeCanvas, editorStates, true); } // Write canvas and editorStates UnityEditor.AssetDatabase.CreateAsset(nodeCanvas, path); foreach (NodeEditorState state in editorStates) { if (state != null) { AddSubAsset(state, nodeCanvas); } } // Write nodes + contents foreach (Node node in nodeCanvas.nodes) { // Every node and each ScriptableObject in it AddSubAsset(node, nodeCanvas); foreach (NodeKnob knob in node.nodeKnobs) { AddSubAsset(knob, node); // Add additional scriptableObjects ScriptableObject[] additionalKnobSOs = knob.GetScriptableObjects(); foreach (ScriptableObject so in additionalKnobSOs) { AddSubAsset(so, knob); } } // Add additional scriptableObjects ScriptableObject[] additionalNodeSOs = node.GetScriptableObjects(); foreach (ScriptableObject so in additionalNodeSOs) { AddSubAsset(so, node); } } UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); #else // TODO: Node Editor: Need to implement ingame-saving (Resources, AsssetBundles, ... won't work) #endif NodeEditorCallbacks.IssueOnSaveCanvas(nodeCanvas); }
/// <summary> /// Saves the the given NodeCanvas along with the given NodeEditorStates if specified as a new asset, optionally as working copies /// </summary> public static void SaveNodeCanvas(string path, NodeCanvas nodeCanvas, bool createWorkingCopy, bool safeOverwrite = true) { #if !UNITY_EDITOR throw new System.NotImplementedException(); #endif if (string.IsNullOrEmpty(path) || !path.StartsWith("Assets")) { throw new UnityException("Cannot save NodeCanvas: Invalid path specified: '" + path + "'!"); } if (nodeCanvas == null) { throw new UnityException("Cannot save NodeCanvas: The specified NodeCanvas that should be saved to path " + path + " is null!"); } if (nodeCanvas.GetType() == typeof(NodeCanvas)) { throw new UnityException("Cannot save NodeCanvas: The NodeCanvas has no explicit type: '" + nodeCanvas.GetType().ToString() + "'. Please convert it to a valid type!"); } if (nodeCanvas.livesInScene) { Debug.LogWarning("Attempting to save scene canvas " + nodeCanvas.name + " to an asset, scene object references may be broken!" + (!createWorkingCopy? " No workingCopy is going to be created, so your scene save is broken, too!" : "")); } #if UNITY_EDITOR if (!createWorkingCopy && UnityEditor.AssetDatabase.Contains(nodeCanvas) && UnityEditor.AssetDatabase.GetAssetPath(nodeCanvas) != path) { Debug.LogError("Trying to create a duplicate save file for '" + nodeCanvas.name + "'! Forcing to create a working copy!"); createWorkingCopy = true; } #endif path = ResourceManager.PreparePath(path); nodeCanvas.OnBeforeSavingCanvas(); NodeCanvas canvasSave = nodeCanvas; #if UNITY_EDITOR nodeCanvas.UpdateSource(path); // Preprocess the canvas ProcessCanvas(ref nodeCanvas, createWorkingCopy); nodeCanvas.livesInScene = false; canvasSave = nodeCanvas; NodeCanvas prevSave; if (safeOverwrite && (prevSave = ResourceManager.LoadResource <NodeCanvas> (path)) != null && prevSave.GetType() == canvasSave.GetType()) // OVERWRITE { // Delete contents of old save for (int nodeCnt = 0; nodeCnt < prevSave.nodes.Count; nodeCnt++) { Node node = prevSave.nodes[nodeCnt]; for (int knobCnt = 0; knobCnt < node.nodeKnobs.Count; knobCnt++) { if (node.nodeKnobs[knobCnt] != null) { Object.DestroyImmediate(node.nodeKnobs[knobCnt], true); } } Object.DestroyImmediate(node, true); } for (int i = 0; i < prevSave.editorStates.Length; i++) { if (prevSave.editorStates[i] != null) { Object.DestroyImmediate(prevSave.editorStates[i], true); } } // Overwrite main canvas OverwriteCanvas(ref prevSave, nodeCanvas); canvasSave = prevSave; } else { // Write main canvas UnityEditor.AssetDatabase.CreateAsset(nodeCanvas, path); } // Write editorStates AddSubAssets(nodeCanvas.editorStates, canvasSave); // Write nodes + contents foreach (Node node in nodeCanvas.nodes) { // Write node and additional scriptable objects AddSubAsset(node, canvasSave); AddSubAssets(node.GetScriptableObjects(), node); foreach (NodeKnob knob in node.nodeKnobs) { // Write knobs and their additional scriptable objects AddSubAsset(knob, node); AddSubAssets(knob.GetScriptableObjects(), knob); } } //UnityEditor.AssetDatabase.SaveAssets (); //UnityEditor.AssetDatabase.Refresh (); #else // TODO: Node Editor: Need to implement ingame-saving (Resources, AsssetBundles, ... won't work) #endif NodeEditorCallbacks.IssueOnSaveCanvas(canvasSave); }