/// <summary> /// Saves the current canvas to the cache /// </summary> public void SaveCache() { #if CACHE if (!useCache) { return; } if (!nodeCanvas || nodeCanvas.GetType() == typeof(NodeCanvas)) { return; } UnityEditor.EditorUtility.SetDirty(nodeCanvas); if (editorState != null) { UnityEditor.EditorUtility.SetDirty(editorState); } lastCacheTime = UnityEditor.EditorApplication.timeSinceStartup; nodeCanvas.editorStates = new NodeEditorState[] { editorState }; if (nodeCanvas.livesInScene || nodeCanvas.allowSceneSaveOnly) { NodeEditorSaveManager.SaveSceneNodeCanvas("lastSession", ref nodeCanvas, cacheWorkingCopy); } else { NodeEditorSaveManager.SaveNodeCanvas(lastSessionPath, ref nodeCanvas, cacheWorkingCopy, true); } #endif }
/// <summary> /// Creates a new cache save file for the currently loaded canvas /// Only called when a new canvas is created or loaded /// </summary> public void SaveCache() { #if UNITY_EDITOR if (!useCache) { return; } if (!nodeCanvas || nodeCanvas.GetType() == typeof(NodeCanvas)) { return; } UnityEditor.EditorUtility.SetDirty(nodeCanvas); if (editorState != null) { UnityEditor.EditorUtility.SetDirty(editorState); } #if !EDITOR_CACHE_ASSET lastCacheTime = UnityEditor.EditorApplication.timeSinceStartup; #endif nodeCanvas.editorStates = new NodeEditorState[] { editorState }; if (nodeCanvas.livesInScene) { NodeEditorSaveManager.SaveSceneNodeCanvas("lastSession", ref nodeCanvas, cacheWorkingCopy); } else { NodeEditorSaveManager.SaveNodeCanvas(lastSessionPath, nodeCanvas, cacheWorkingCopy, true); } CheckCurrentCache(); #endif }
public static NodeCanvasTypeData getCanvasTypeData(NodeCanvas canvas) { NodeCanvasTypeData data; CanvasTypes.TryGetValue(canvas.GetType(), out data); return(data); }
/// <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> /// Creates a node of the specified ID at pos on the specified canvas, optionally auto-connecting the specified output to a matching input /// silent disables any events, init specifies whether OnCreate should be called /// </summary> public static Node Create(string nodeID, Vector2 pos, NodeCanvas hostCanvas, ConnectionPort connectingPort = null, bool silent = false, bool init = true) { if (string.IsNullOrEmpty(nodeID) || hostCanvas == null) { throw new ArgumentException(); } if (!NodeCanvasManager.CheckCanvasCompability(nodeID, hostCanvas.GetType())) { throw new UnityException("Cannot create Node with ID '" + nodeID + "' as it is not compatible with the current canavs type (" + hostCanvas.GetType().ToString() + ")!"); } if (!hostCanvas.CanAddNode(nodeID)) { throw new UnityException("Cannot create Node with ID '" + nodeID + "' on the current canvas of type (" + hostCanvas.GetType().ToString() + ")!"); } // Create node from data NodeTypeData data = NodeTypes.getNodeData(nodeID); Node node = (Node)CreateInstance(data.type); if (node == null) { return(null); } // Init node state node.name = node.Title; node.autoSize = node.DefaultSize; node.position = pos; node.Canvas = hostCanvas; ConnectionPortManager.UpdateConnectionPorts(node); if (init) { node.OnCreate(); } if (connectingPort != null) { // Handle auto-connection and link the output to the first compatible input for (int i = 0; i < node.connectionPorts.Count; i++) { if (node.connectionPorts[i].TryApplyConnection(connectingPort, silent)) { break; } } } // Add node to host canvas hostCanvas.nodes.Add(node); if (!silent) { // Callbacks hostCanvas.OnNodeChange(connectingPort != null ? connectingPort.body : node); NodeEditorCallbacks.IssueOnAddNode(node); hostCanvas.Validate(); NodeEditor.RepaintClients(); } return(node); }
private static void DeCafList(ref List <Node> displayedNodes, NodeCanvas canvas) { for (int i = 0; i < displayedNodes.Count; i++) { if (!NodeTypes.nodes[displayedNodes[i]].typeOfNodeCanvas.Contains(canvas.GetType())) { displayedNodes.RemoveAt(i); i--; } } }
/// <summary> /// Converts the type of the canvas to the specified type. /// </summary> public static NodeCanvas ConvertCanvasType(NodeCanvas canvas, Type newType) { NodeCanvas convertedCanvas = canvas; if (canvas.GetType() != newType && newType != typeof(NodeCanvas) && newType.IsSubclassOf(typeof(NodeCanvas))) { canvas = NodeEditorSaveManager.CreateWorkingCopy(canvas, true); convertedCanvas = NodeCanvas.CreateCanvas(newType); convertedCanvas.nodes = canvas.nodes; convertedCanvas.editorStates = canvas.editorStates; convertedCanvas.Validate(); } return(convertedCanvas); }
/// <summary> /// Overwrites canvas with the contents of canvasData, so that all references to canvas will be remained, but both canvases are still seperate. /// Only works in the editor! /// </summary> public static void OverwriteCanvas(ref NodeCanvas targetCanvas, NodeCanvas canvasData) { #if UNITY_EDITOR if (canvasData == null) { throw new System.ArgumentNullException("Cannot overwrite canvas as data is null!"); } if (targetCanvas == null) { targetCanvas = NodeCanvas.CreateCanvas(canvasData.GetType()); } UnityEditor.EditorUtility.CopySerialized(canvasData, targetCanvas); targetCanvas.name = canvasData.name; #else throw new System.NotSupportedException("Cannot overwrite canvas in player!"); #endif }
/// <summary> /// Saves the current canvas to the cache /// </summary> public void SaveCache(bool crashSafe = true) { #if CACHE if (!useCache) { return; } if (!nodeCanvas || nodeCanvas.GetType() == typeof(NodeCanvas)) { return; } UnityEditor.EditorUtility.SetDirty(nodeCanvas); if (editorState != null) { UnityEditor.EditorUtility.SetDirty(editorState); } lastCacheTime = UnityEditor.EditorApplication.timeSinceStartup; nodeCanvas.editorStates = new NodeEditorState[] { editorState }; if (nodeCanvas.livesInScene || nodeCanvas.allowSceneSaveOnly) { NodeEditorSaveManager.SaveSceneNodeCanvas("lastSession", ref nodeCanvas, cacheWorkingCopy); } else if (crashSafe) { NodeEditorSaveManager.SaveNodeCanvas(lastSessionPath, ref nodeCanvas, cacheWorkingCopy, true); } if (cacheMemorySODump) { // Functionality for asset saves only if (nodeCanvas.livesInScene || nodeCanvas.allowSceneSaveOnly) { // Delete for scene save so that next cache load, correct lastSession is used UnityEditor.AssetDatabase.DeleteAsset(SOMemoryDumpPath); } else { // Dump all SOs used in this session (even if deleted) in this file to keep them alive for undo NodeEditorUndoActions.CompleteSOMemoryDump(nodeCanvas); NodeEditorSaveManager.ScriptableObjectReferenceDump(nodeCanvas.SOMemoryDump, SOMemoryDumpPath, false); } } #endif }
/// <summary> /// Converts the given canvas to the specified type /// </summary> public static NodeCanvas ConvertCanvasType(NodeCanvas canvas, Type newType) { NodeCanvas convertedCanvas = canvas; if (canvas.GetType() != newType && newType.IsSubclassOf(typeof(NodeCanvas))) { canvas.Validate(); canvas = NodeEditorSaveManager.CreateWorkingCopy(canvas); convertedCanvas = NodeCanvas.CreateCanvas(newType); convertedCanvas.nodes = canvas.nodes; convertedCanvas.groups = canvas.groups; convertedCanvas.editorStates = canvas.editorStates; for (int i = 0; i < convertedCanvas.nodes.Count; i++) { if (!CheckCanvasCompability(convertedCanvas.nodes[i].GetID, newType)) { // Check if nodes is even compatible with the canvas, if not delete it convertedCanvas.nodes[i].Delete(); i--; } } convertedCanvas.Validate(); } return(convertedCanvas); }
/// <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> /// Creates a node of the specified ID at pos on the specified canvas, optionally auto-connecting the specified output to a matching input /// silent disables any events, init specifies whether OnCreate should be called /// </summary> public static Node Create(string nodeID, Vector2 pos, NodeCanvas hostCanvas, ConnectionPort connectingPort = null, bool silent = false, bool init = true) { if (string.IsNullOrEmpty(nodeID) || hostCanvas == null) { throw new ArgumentException(); } if (!NodeCanvasManager.CheckCanvasCompability(nodeID, hostCanvas.GetType())) { throw new UnityException("Cannot create Node with ID '" + nodeID + "' as it is not compatible with the current canavs type (" + hostCanvas.GetType().ToString() + ")!"); } if (!hostCanvas.CanAddNode(nodeID)) { throw new UnityException("Cannot create Node with ID '" + nodeID + "' on the current canvas of type (" + hostCanvas.GetType().ToString() + ")!"); } // Create node from data NodeTypeData data = NodeTypes.getNodeData(nodeID); Node node = (Node)CreateInstance(data.type); if (node == null) { return(null); } // Init node state node.canvas = hostCanvas; node.name = node.Title; node.autoSize = node.DefaultSize; node.position = pos; ConnectionPortManager.UpdateConnectionPorts(node); if (init) { node.OnCreate(); } if (connectingPort != null) { // Handle auto-connection and link the output to the first compatible input for (int i = 0; i < node.connectionPorts.Count; i++) { if (node.connectionPorts[i].TryApplyConnection(connectingPort, true)) { break; } } } // Add node to host canvas hostCanvas.nodes.Add(node); if (!silent) { // Callbacks hostCanvas.OnNodeChange(connectingPort != null ? connectingPort.body : node); NodeEditorCallbacks.IssueOnAddNode(node); hostCanvas.Validate(); NodeEditor.RepaintClients(); } #if UNITY_EDITOR if (!silent) { List <ConnectionPort> connectedPorts = new List <ConnectionPort>(); foreach (ConnectionPort port in node.connectionPorts) { // 'Encode' connected ports in one list (double level cannot be serialized) foreach (ConnectionPort conn in port.connections) { connectedPorts.Add(conn); } connectedPorts.Add(null); } Node createdNode = node; UndoPro.UndoProManager.RecordOperation( () => NodeEditorUndoActions.ReinstateNode(createdNode, connectedPorts), () => NodeEditorUndoActions.RemoveNode(createdNode), "Create Node"); // Make sure the new node is in the memory dump NodeEditorUndoActions.CompleteSOMemoryDump(hostCanvas); } #endif return(node); }
/// <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); }
/// <summary> /// Saves the nodeCanvas in the current scene under the specified name along with the specified editorStates or, if specified, their working copies /// If also stored as an asset, it will loose the reference to the asset first /// </summary> public static void SaveSceneNodeCanvas(string saveName, ref NodeCanvas nodeCanvas, bool createWorkingCopy, bool safeOverwrite = true) { if (string.IsNullOrEmpty(saveName)) { Debug.LogError("Cannot save Canvas to scene: No save name specified!"); return; } 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 #if UNITY_EDITOR // Make sure the canvas has no reference to an asset || UnityEditor.AssetDatabase.Contains(nodeCanvas) #endif ) { //Debug.LogWarning ("Forced to create working copy of '" + saveName + "' when saving to scene because it already exists as an asset!"); nodeCanvas = CreateWorkingCopy(nodeCanvas, true); } else { nodeCanvas.Validate(true); } nodeCanvas.livesInScene = true; nodeCanvas.name = saveName; nodeCanvas.OnBeforeSavingCanvas(); nodeCanvas.UpdateSource("SCENE/" + saveName); NodeCanvas savedCanvas = nodeCanvas; // Preprocess canvas ProcessCanvas(ref savedCanvas, createWorkingCopy); // Get the saveHolder and store the canvas NodeCanvasSceneSave sceneSave; #if UNITY_EDITOR if ((sceneSave = FindSceneSave(saveName)) != null && safeOverwrite) // OVERWRITE { OverwriteCanvas(ref sceneSave.savedNodeCanvas, savedCanvas); } else { if (sceneSave == null) { sceneSave = CreateSceneSave(saveName); } sceneSave.savedNodeCanvas = savedCanvas; } if (!Application.isPlaying) { #if UNITY_5_3_OR_NEWER UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene()); #else UnityEditor.EditorApplication.MarkSceneDirty(); #endif } #else sceneSave = FindOrCreateSceneSave(saveName); sceneSave.savedNodeCanvas = savedCanvas; #endif #if UNITY_EDITOR UnityEditor.EditorUtility.SetDirty(sceneSaveHolder); #endif }
/// <summary> /// Creates a copy of the specified node at pos on the specified canvas, optionally auto-connecting the specified output to a matching input /// silent disables any events /// </summary> public static Node CreateCopy(Node toCopy, Vector2 pos, NodeCanvas hostCanvas, ConnectionPort connectingPort = null, bool silent = false) { if (toCopy == null || hostCanvas == null) { throw new ArgumentException(); } if (!NodeCanvasManager.CheckCanvasCompability(toCopy.GetID, hostCanvas.GetType())) { throw new UnityException("Cannot create Node with ID '" + toCopy.GetID + "' as it is not compatible with the current canvas type (" + hostCanvas.GetType().ToString() + ")!"); } if (!hostCanvas.CanAddNode(toCopy.GetID)) { throw new UnityException("Cannot create Node with ID '" + toCopy.GetID + "' on the current canvas of type (" + hostCanvas.GetType().ToString() + ")!"); } Node node = ScriptableObject.Instantiate(toCopy); //Clone static connection ports foreach (ConnectionPortDeclaration portDecl in ConnectionPortManager.GetPortDeclarationEnumerator(node, true)) { ConnectionPort port = (ConnectionPort)portDecl.portField.GetValue(node); port = portDecl.portInfo.CreateNew(node); portDecl.portField.SetValue(node, port); } //Clone dynamic connection ports for (int i = 0; i < node.dynamicConnectionPorts.Count; ++i) { node.dynamicConnectionPorts[i] = ScriptableObject.Instantiate(node.dynamicConnectionPorts[i]); node.dynamicConnectionPorts[i].body = node; node.dynamicConnectionPorts[i].ClearConnections(); } ConnectionPortManager.UpdateRepresentativePortLists(node); //Clone child SOs System.Func <ScriptableObject, ScriptableObject> copySOs = (ScriptableObject so) => ScriptableObject.Instantiate(so);; node.CopyScriptableObjects(copySOs); if (node == null) { return(null); } // Init node state node.name = node.Title; node.autoSize = node.DefaultSize; node.position = pos; ConnectionPortManager.UpdateConnectionPorts(node); if (connectingPort != null) { // Handle auto-connection and link the output to the first compatible input for (int i = 0; i < node.connectionPorts.Count; i++) { if (node.connectionPorts[i].TryApplyConnection(connectingPort, silent)) { break; } } } // Add node to host canvas hostCanvas.nodes.Add(node); if (!silent) { // Callbacks hostCanvas.OnNodeChange(connectingPort != null ? connectingPort.body : node); NodeEditorCallbacks.IssueOnAddNode(node); hostCanvas.Validate(); NodeEditor.RepaintClients(); } return(node); }
/// <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 }
public static bool CheckCanvasCompability(string nodeID, NodeCanvas canvas) { NodeData data = NodeTypes.getNodeData(nodeID); return(data.limitToCanvasTypes == null || data.limitToCanvasTypes.Length == 0 || data.limitToCanvasTypes.Contains(canvas.GetType())); }