예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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;
        }