private bool ReopenCurrentGraph()
        {
            if (GraphTabs.Count == 0)
            {
                return(false);
            }
            GraphTab activeTab = GraphTabs[GraphTabs.Count - 1];
            Graph    graph     = activeTab.IsRootTab ? activeTab.Graph : activeTab.SubGraphNode.SubGraph;

            if (graph == null)
            {
                GraphTabs.Clear();
                return(false);
            }

            OpenGraph(graph, false, false, false, false);

            //remove any node, that has been soft deleted, from the graph's Nodes list
            foreach (Node deletedNode in DeletedNodes)
            {
                if (!CurrentGraph.Nodes.Contains(deletedNode))
                {
                    continue;
                }
                CurrentGraph.Nodes.Remove(deletedNode);
                CurrentGraph.SetDirty(false);
            }

            GraphEvent.Send(GraphEvent.EventType.EVENT_GRAPH_OPENED);

            m_graphAssetPath = AssetDatabase.GetAssetPath(CurrentGraph);

            return(true);
        }
Exemple #2
0
        public void RemoveSocket(Socket socket, bool recordUndo, bool saveAssets = false, bool ignoreCanDeleteSocketFlag = false)
        {
            if (!ignoreCanDeleteSocketFlag && !NodesDatabase[socket.NodeId].CanDeleteSocket(socket))
            {
                return;
            }
            if (recordUndo)
            {
                RecordUndo(UILabels.Delete + " " + UILabels.Socket);
            }
            DisconnectSocket(socket, false);
            PointsDatabase.Remove(socket.Id);
            SocketsDatabase.Remove(socket.Id);
            Node node = NodesDatabase[socket.NodeId];

            if (node == null)
            {
                return;               //sanity check
            }
            if (socket.IsInput)
            {
                node.InputSockets.Remove(socket);
            }
            if (socket.IsOutput)
            {
                node.OutputSockets.Remove(socket);
            }
            EditorUtility.SetDirty(node);
            CurrentGraph.SetDirty(saveAssets);
            GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_UPDATED, socket.NodeId);
        }
Exemple #3
0
        public void DisconnectSocket(Socket socket, bool recordUndo, bool saveAssets = false)
        {
            if (!socket.IsConnected)
            {
                return;
            }

            if (recordUndo)
            {
                RecordUndo(GraphAction.Disconnect.ToString());
            }
            List <string> socketConnectionIds = socket.GetConnectionIds();

            foreach (string connectionId in socketConnectionIds)
            {
                if (!ConnectionsDatabase.ContainsKey(connectionId))
                {
                    continue;
                }
                VirtualConnection vc = ConnectionsDatabase[connectionId];
                vc.OutputSocket.RemoveConnection(connectionId);
                vc.InputSocket.RemoveConnection(connectionId);
                EditorUtility.SetDirty(vc.OutputNode);
                EditorUtility.SetDirty(vc.InputNode);
                ConnectionsDatabase.Remove(connectionId);
            }

            CurrentGraph.SetDirty(saveAssets);
            GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_DISCONNECTED, socket.NodeId);
        }
Exemple #4
0
        private void ReorderSocketMove(Socket socket, bool moveUp, bool recordUndo, bool saveAssets = false)
        {
            if (socket == null)
            {
                return;
            }
            if (!socket.CanBeReordered)
            {
                return;
            }
            Node node = NodesDatabase[socket.NodeId];

            if (node == null)
            {
                return;
            }
            List <Socket> sockets     = socket.IsInput ? node.InputSockets : node.OutputSockets;
            int           socketIndex = sockets.IndexOf(socket);

            if (moveUp && socketIndex == 0)
            {
                return;                                              //moving up and this is the first socket - it cannot go up in the sockets order
            }
            if (!moveUp && socketIndex == sockets.Count - 1)
            {
                return;                                              //moving down and this is the last socket - it cannot go down in the sockets order
            }
            if (recordUndo)
            {
                RecordUndo(moveUp ? UILabels.MoveUp : UILabels.MoveDown);
            }
            if (moveUp) //MOVE UP
            {
                Socket previousSocket = sockets[socketIndex - 1];
                sockets[socketIndex - 1] = new Socket(socket);
                sockets[socketIndex]     = new Socket(previousSocket);
            }
            else //MOVE DOWN
            {
                Socket nextSocket = sockets[socketIndex + 1];
                sockets[socketIndex + 1] = new Socket(socket);
                sockets[socketIndex]     = new Socket(nextSocket);
            }

            EditorUtility.SetDirty(node);
            CurrentGraph.SetDirty(saveAssets);
            ConstructGraphGUI();
            RecalculateAllPointRects();
            GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_UPDATED, socket.NodeId);
        }
Exemple #5
0
        private void SoftDeleteNode(Node node, bool recordUndo, bool saveAssets)
        {
            if (!node.CanBeDeleted)
            {
                return;
            }
            switch (node.NodeType)
            {
            case NodeType.Start:
            case NodeType.Enter:
            case NodeType.Exit:
                return;
            }

            if (recordUndo)
            {
                RecordUndo("Delete Node");
            }

            foreach (VirtualConnection connection in ConnectionsDatabase.Values)
            {
                if (connection.InputNode == node)
                {
                    connection.OutputSocket.DisconnectFromNode(node.Id);
                    EditorUtility.SetDirty(connection.OutputNode);
                }

                if (connection.OutputNode == node)
                {
                    connection.InputSocket.DisconnectFromNode(node.Id);
                    EditorUtility.SetDirty(connection.InputNode);
                }
            }

            WindowSettings.DeletedNodes.Add(node);
            CurrentGraph.Nodes.Remove(node);

            if (WindowSettings.SelectedNodes.Contains(node))
            {
                WindowSettings.SelectedNodes.Remove(node);
            }

            CurrentGraph.SetDirty(saveAssets);
            WindowSettings.SetDirty(false);

            ConstructGraphGUI();
        }
Exemple #6
0
 private void ClearNodeConnections(Node node, bool recordUndo, bool saveAssets = false)
 {
     if (recordUndo)
     {
         RecordUndo(GraphAction.Disconnect.ToString());
     }
     foreach (Socket inputSocket in node.InputSockets)
     {
         DisconnectSocket(inputSocket, false);
     }
     foreach (Socket outputSocket in node.OutputSockets)
     {
         DisconnectSocket(outputSocket, false);
     }
     EditorUtility.SetDirty(node);
     CurrentGraph.SetDirty(saveAssets);
     GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_DISCONNECTED, node.Id);
 }
Exemple #7
0
        private void CreateNodeInTheOpenedGraph(Type type, Vector2 worldPosition, bool recordUndo, bool saveAssets = false)
        {
            Node node = GraphUtils.CreateNode(CurrentGraph, type, worldPosition);

            if (recordUndo)
            {
                RecordUndo("Create " + type.Name);                                                     //record undo for the creation of this node
            }
            CurrentGraph.Nodes.Add(node);                                                              //add the new node reference to the graph's nodes list
            if (!EditorUtility.IsPersistent(node))
            {
                AssetDatabase.AddObjectToAsset(node, CurrentGraph);                                    //if the node does not have an asset file -> crete it and nest it under the graph asset file
            }
            switch (node.NodeType)
            {
            case NodeType.General:
            case NodeType.SubGraph:
                //AUTO CONNECT the new node TO either the START or ENTER node - if the start or enter nodes are not connected
                Node startOrEnterNode = CurrentGraph.GetStartOrEnterNode();
                if (startOrEnterNode != null &&                                                  //if we have a start or enter node
                    !startOrEnterNode.OutputSockets[0].IsConnected &&                            //that is NOT connected
                    node.InputSockets != null &&                                                 //and its inputSockets list is NOT null (sanity check)
                    node.InputSockets.Count > 0)                                                 //and it has at least one input socket (again... sanity check)
                {
                    ConnectSockets(startOrEnterNode.OutputSockets[0], node.InputSockets[0]);     //connect the new created node with the Start or Enter node
                }
                break;
            }

            EditorUtility.SetDirty(node);                                             //mark the new node as dirty
            CurrentGraph.SetDirty(saveAssets);                                        //set the graph dirty
            if (recordUndo)
            {
                GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_CREATED);             //notify the system the a node has been created
            }
            SelectNodes(new List <Node> {
                node
            }, false, false);                                                           //select the newly created node
            WindowSettings.SetDirty(false);
        }
Exemple #8
0
        private void DisconnectVirtualPoint(VirtualPoint virtualPoint, bool recordUndo, bool saveAssets = false)
        {
            if (!virtualPoint.Socket.IsConnected)
            {
                return;
            }
            if (!virtualPoint.IsConnected)
            {
                return;
            }

            if (recordUndo)
            {
                RecordUndo(GraphAction.Disconnect.ToString());
            }

            var connections = new List <VirtualConnection>();

            foreach (VirtualConnection connection in ConnectionsDatabase.Values)
            {
                if (connection.InputVirtualPoint == virtualPoint || connection.OutputVirtualPoint == virtualPoint)
                {
                    connections.Add(connection);
                }
            }

            foreach (VirtualConnection vc in connections)
            {
                vc.OutputSocket.RemoveConnection(vc.ConnectionId);
                vc.InputSocket.RemoveConnection(vc.ConnectionId);
                EditorUtility.SetDirty(vc.OutputNode);
                EditorUtility.SetDirty(vc.InputNode);
                ConnectionsDatabase.Remove(vc.ConnectionId);
            }

            CurrentGraph.SetDirty(saveAssets);
            GraphEvent.Send(GraphEvent.EventType.EVENT_CONNECTION_DELETED);
        }
Exemple #9
0
        private static void DeleteUnreferencedAssetNodes()
        {
            if (CurrentGraph == null)
            {
                return;                                                                                     //check that the graph is not null
            }
            Object[] objects = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(CurrentGraph)); //load all of the graph sub assets
            if (objects == null)
            {
                return;                                                                                     //make sure they are not null
            }
            List <Node> foundNodes = objects.OfType <Node>().ToList();                                      //create a temp list of all the found sub assets node

            if (CurrentGraph.Nodes == null)
            {
                CurrentGraph.Nodes = new List <Node>();                                                     //sanity check
            }
            bool saveGraph = false;                                                                         //mark true if any sub asset was destroyed

            foreach (Node node in foundNodes)
            {
                if (CurrentGraph.Nodes.Contains(node))
                {
                    continue;                                    //node reference was FOUND in the Nodes list -> continue
                }
                DestroyImmediate(node, true);                    //node reference was NOT FOUND in the Nodes list -> destroy the asset (it was probably soft deleted)
                saveGraph = true;                                //mark true in order to set the graph dirty and save it
            }

            WindowSettings.DeletedNodes.Clear();
            if (!saveGraph)
            {
                return;             //if no sub asset was destroyed -> stop here
            }
            WindowSettings.SetDirty(false);
            CurrentGraph.SetDirty(true); //save the graph
        }
Exemple #10
0
        private void SoftDeleteNodes(List <Node> nodes, bool recordUndo, bool saveAssets)
        {
            if (nodes == null || nodes.Count == 0)
            {
                return;
            }
            nodes = nodes.Where(n => n != null).ToList();

            if (recordUndo)
            {
                RecordUndo("Delete Nodes");
            }

            //disconnect all the nodes that need to be deleted
            foreach (Node node in nodes)
            {
                if (!CanDeleteNode(node))
                {
                    continue;
                }

                foreach (VirtualConnection connection in ConnectionsDatabase.Values)
                {
                    if (node == null || connection == null)
                    {
                        continue;
                    }

                    if (connection.InputNode == node && connection.OutputSocket != null)
                    {
                        connection.OutputSocket.DisconnectFromNode(node.Id);
                        EditorUtility.SetDirty(connection.OutputNode);
                    }

                    if (connection.OutputNode == node && connection.InputSocket != null)
                    {
                        connection.InputSocket.DisconnectFromNode(node.Id);
                        EditorUtility.SetDirty(connection.InputNode);
                    }
                }
            }

            //at this point the nodes have been disconnected
            //'delete' the nodes by adding them the the DeletedNodes list
            foreach (Node node in nodes)
            {
                if (node == null)
                {
                    continue;
                }
                if (!CanDeleteNode(node))
                {
                    continue;
                }
                WindowSettings.DeletedNodes.Add(node);
                CurrentGraph.Nodes.Remove(node);
            }

            DeselectAll(false);                //deselect any selected nodes
            CurrentGraph.SetDirty(saveAssets); //mark the graph as dirty
            WindowSettings.SetDirty(false);    //mark the editor settings as dirty
            ConstructGraphGUI();               //invalidate all the databases and reconstruct the GUI
        }
Exemple #11
0
        private void PasteNodes()
        {
            if (!WindowSettings.CanPasteNodes)
            {
                return;                                                     //paste operation cannot work if no nodes have been added to the 'virtual clipboard'
            }
            for (int i = WindowSettings.CopiedNodes.Count - 1; i >= 0; i--) //remove any null nodes
            {
                if (WindowSettings.CopiedNodes[i] == null)
                {
                    WindowSettings.CopiedNodes.RemoveAt(i);
                }
            }

            if (!WindowSettings.CanPasteNodes)
            {
                return;                                //paste operation cannot work if no not null nodes are left to be copied
            }
            //create current nodes list
            var copyNodes = new List <Node>();

            //get the first node to the left
            Node    firstNodeToTheLeft = null;
            Vector2 firstNodePosition  = Vector2.zero;

            foreach (Node node in WindowSettings.CopiedNodes)
            {
                if (node == null)
                {
                    continue;
                }
                if (firstNodeToTheLeft == null)
                {
                    firstNodeToTheLeft = node;
                    firstNodePosition  = node.GetPosition();
                }

                if (!(node.GetX() < firstNodePosition.x))
                {
                    continue;
                }
                firstNodeToTheLeft = node;
                firstNodePosition  = node.GetPosition();
            }

            foreach (Node node in WindowSettings.CopiedNodes)
            {
                Node original = node;

                if (original == null)
                {
                    continue;
                }
                Node copy = CreateNodeCopy(original);

                copy.hideFlags = original.hideFlags;

                Vector2 offsetFromFirstNodePosition = Vector2.zero;

                if (original != firstNodeToTheLeft)
                {
                    offsetFromFirstNodePosition = firstNodePosition - copy.GetPosition();
                }

                copy.SetPosition(WorldToGridPosition(CurrentMousePosition));
                copy.SetPosition(copy.GetPosition() - new Vector2(copy.GetWidth() / 2, NodySettings.Instance.NodeHeaderHeight / 2));
                copy.SetPosition(copy.GetPosition() - offsetFromFirstNodePosition);

                copyNodes.Add(copy);
                if (!EditorUtility.IsPersistent(copy))
                {
                    AssetDatabase.AddObjectToAsset(copy, CurrentGraph);
                }
                CurrentGraph.SetDirty(false);
            }

            //create current sockets list
            var copySockets = new List <Socket>();

            foreach (Node copyNode in copyNodes)
            {
                copySockets.AddRange(copyNode.InputSockets);
                copySockets.AddRange(copyNode.OutputSockets);
            }

            //create current connections list
            var copyConnections = new List <Connection>();

            foreach (Socket copySocket in copySockets)
            {
                foreach (Connection copyConnection in copySocket.Connections)
                {
                    copyConnections.Add(copyConnection);
                }
            }

            //generate new connection ids
            foreach (Connection copyConnection in copyConnections)
            {
                string oldConnectionId = copyConnection.Id;                     //save previous connection id
                string newConnectionId = copyConnection.GenerateNewId();        //save new conenction id

                foreach (Socket socket in copySockets)                          //go through each socket
                {
                    foreach (Connection socketConnection in socket.Connections) //go through each socket's connections
                    {
                        if (socketConnection.Id == oldConnectionId)
                        {
                            socketConnection.Id = newConnectionId; //update the connection id
                        }
                    }
                }
            }

            //generate new socket ids
            foreach (Socket copySocket in copySockets)
            {
                string oldSocketId = copySocket.Id;                //save previous socket id
                string newSocketId = copySocket.GenerateNewId();   //save new socket id

                foreach (Connection connection in copyConnections) //update all the connection socket ids
                {
                    if (connection.InputSocketId == oldSocketId)
                    {
                        connection.InputSocketId = newSocketId;
                    }
                    if (connection.OutputSocketId == oldSocketId)
                    {
                        connection.OutputSocketId = newSocketId;
                    }
                }
            }

            //generate new node ids
            foreach (Node copyNode in copyNodes)
            {
                string oldNodeId = copyNode.Id;                                   //save previous node id
                string newNodeId = copyNode.GenerateNewId();                      //save new node id

                foreach (Socket copySocket in copySockets)                        //go through all the sockets
                {
                    if (copySocket.NodeId == oldNodeId)                           //check that the current node id is equal the the old node id
                    {
                        copySocket.NodeId = newNodeId;                            //update the node id
                    }
                    foreach (Connection copyConnection in copySocket.Connections) //update all the connection node ids
                    {
                        if (copyConnection.OutputNodeId == oldNodeId)
                        {
                            copyConnection.OutputNodeId = newNodeId;
                        }
                        if (copyConnection.InputNodeId == oldNodeId)
                        {
                            copyConnection.InputNodeId = newNodeId;
                        }
                    }
                }
            }

            //a list of all the copied nodes ids is needed in order to be able to keep the connections between the copied nodes and remove any 'outside' connections
            var copiedNodesIds = new List <string>(); //create a list of all the copied nodes ids (list contains the newly generated ids)
            foreach (Node copyNode in copyNodes)
            {
                copiedNodesIds.Add(copyNode.Id);
            }

            foreach (Socket copySocket in copySockets)
            {
                for (int i = copySocket.Connections.Count - 1; i >= 0; i--)
                {
                    Connection c = copySocket.Connections[i];
                    //remove any connection that is made with a node outside the copied nodes list
                    //keep the connections between the copied nodes and remove any 'outside' connections
                    if (copiedNodesIds.Contains(c.InputNodeId) && copiedNodesIds.Contains(c.OutputNodeId))
                    {
                        continue;
                    }
                    copySocket.Connections.RemoveAt(i);
                }
            }

            //record undo for paste
            RecordUndo("Paste Nodes");

            //add the references of the pasted nodes to the graph's nodes list
            //do it in reverse order in order to be sorted on top of all the other nodes
            var nodesList = new List <Node>(copyNodes);
            nodesList.AddRange(CurrentGraph.Nodes);
            CurrentGraph.Nodes = nodesList;

            //add the node asset files under the graph asset
            foreach (Node copiedNode in copyNodes)
            {
                if (!EditorUtility.IsPersistent(copiedNode))
                {
                    AssetDatabase.AddObjectToAsset(copiedNode, CurrentGraph);
                }
                EditorUtility.SetDirty(copiedNode);
            }

            //mark the graph as dirty in order to be able to save the changes
            CurrentGraph.SetDirty(false);

            //reconstruct the databases in order to draw
            ConstructGraphGUI();
            RecalculateAllPointRects();

            //Select the pasted nodes
            SelectNodes(copyNodes, false, false);

            //Paste completed -> clear clipboard
            WindowSettings.CopiedNodes.Clear();
            WindowSettings.SetDirty(false);
        }