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); }
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); }
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); }
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); }
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(); }
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); }
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); }
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); }
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 }
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 }
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); }