/// <summary> Return false for nodes that can't be removed </summary> public virtual bool CanRemove(xNode.Node node) { // Check graph attributes to see if this node is required Type graphType = target.GetType(); xNode.NodeGraph.RequireNodeAttribute[] attribs = Array.ConvertAll( graphType.GetCustomAttributes(typeof(xNode.NodeGraph.RequireNodeAttribute), true), x => x as xNode.NodeGraph.RequireNodeAttribute); if (attribs.Any(x => x.Requires(node.GetType()))) { if (target.nodes.Count(x => x.GetType() == node.GetType()) <= 1) { return(false); } } return(true); }
/// <summary> Automatically delete Node sub-assets before deleting their script. /// This is important to do, because you can't delete null sub assets. /// <para/> For another workaround, see: https://gitlab.com/RotaryHeart-UnityShare/subassetmissingscriptdelete </summary> private static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions options) { // Skip processing anything without the .cs extension if (Path.GetExtension(path) != ".cs") { return(AssetDeleteResult.DidNotDelete); } // Get the object that is requested for deletion UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath <UnityEngine.Object> (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 == null || (scriptType != typeof(xNode.Node) && !scriptType.IsSubclassOf(typeof(xNode.Node)))) { return(AssetDeleteResult.DidNotDelete); } // 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); for (int k = 0; k < objs.Length; k++) { xNode.Node node = objs[k] as xNode.Node; if (node.GetType() == scriptType) { if (node != null && node.graph != null) { // 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); }
private void InsertDuplicateNodes(xNode.Node[] nodes, Vector2 topLeft) { if (nodes == null || nodes.Length == 0) { return; } // Get top-left node Vector2 topLeftNode = nodes.Select(x => x.position) .Aggregate((x, y) => new Vector2(Mathf.Min(x.x, y.x), Mathf.Min(x.y, y.y))); Vector2 offset = topLeft - topLeftNode; UnityEngine.Object[] newNodes = new UnityEngine.Object[nodes.Length]; Dictionary <xNode.Node, xNode.Node> substitutes = new Dictionary <xNode.Node, xNode.Node>(); for (int i = 0; i < nodes.Length; i++) { xNode.Node srcNode = nodes[i]; if (srcNode == null) { continue; } // Check if user is allowed to add more of given node type xNode.Node.DisallowMultipleNodesAttribute disallowAttrib; Type nodeType = srcNode.GetType(); if (NodeEditorUtilities.GetAttrib(nodeType, out disallowAttrib)) { int typeCount = this.graph.nodes.Count(x => x.GetType() == nodeType); if (typeCount >= disallowAttrib.max) { continue; } } xNode.Node newNode = this.graphEditor.CopyNode(srcNode); substitutes.Add(srcNode, newNode); newNode.position = srcNode.position + offset; newNodes[i] = newNode; } // Walk through the selected nodes again, recreate connections, using the new nodes for (int i = 0; i < nodes.Length; i++) { xNode.Node srcNode = nodes[i]; if (srcNode == null) { continue; } foreach (xNode.NodePort port in srcNode.Ports) { for (int c = 0; c < port.ConnectionCount; c++) { xNode.NodePort inputPort = port.Direction == xNode.NodePort.IO.Input ? port : port.GetConnection(c); xNode.NodePort outputPort = port.Direction == xNode.NodePort.IO.Output ? port : port.GetConnection(c); xNode.Node newNodeIn, newNodeOut; if (substitutes.TryGetValue(inputPort.node, out newNodeIn) && substitutes.TryGetValue(outputPort.node, out newNodeOut)) { newNodeIn.UpdatePorts(); newNodeOut.UpdatePorts(); inputPort = newNodeIn.GetInputPort(inputPort.fieldName); outputPort = newNodeOut.GetOutputPort(outputPort.fieldName); } if (!inputPort.IsConnectedTo(outputPort)) { inputPort.Connect(outputPort); } } } } EditorUtility.SetDirty(this.graph); // Select the new nodes Selection.objects = newNodes; }