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); }
private void UpdateSwitchBackModeState(bool value) { if (value) { if (TargetNode.InputSockets == null || TargetNode.InputSockets.Count == 0) { TargetNode.AddInputSocket(ConnectionMode.Multiple, typeof(PassthroughConnection), false, false); } } else { if (TargetNode.InputSockets != null && TargetNode.InputSockets.Count > 0) { if (TargetNode.FirstInputSocket != null && TargetNode.FirstInputSocket.IsConnected) { GraphEvent.DisconnectSocket(TargetNode.FirstInputSocket); } TargetNode.InputSockets.Clear(); } NodeUpdated = true; } }
private void OpenGraph(Graph graph, bool closeCurrentlyOpenedGraph, bool clearGraphTabs, bool centerAllNodesInWindow, bool recordUndo = true) { if (graph == null) { return; } if (CurrentGraph == graph) { return; } if (closeCurrentlyOpenedGraph) { CloseCurrentGraph(clearGraphTabs); } if (recordUndo) { RecordUndo("Open Graph"); } WindowSettings.AddGraphToRecentlyOpenedGraphs(graph); CurrentGraph = graph; GraphUtils.CheckAndCreateAnyMissingSystemNodes(graph); ConstructGraphGUI(); if (centerAllNodesInWindow) { CenterAllNodesInWindow(); } // Undo.IncrementCurrentGroup(); // Undo.SetCurrentGroupName(m_graphAssetName); SetView(View.Graph); Repaint(); GraphEvent.Send(GraphEvent.EventType.EVENT_GRAPH_OPENED); m_graphAssetPath = AssetDatabase.GetAssetPath(CurrentGraph); }
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); }
Node NodeLifecycle(Node node, GraphEvent ev) { return(ev.Match <Node>() .Case <CreateVertex, Node>(cv => { var newObj = Object.Instantiate(vertexModel); newObj.transform.SetParent(vertexModel.transform.parent); // Name changes var labels = new Subject <string>(); labels.Subscribe(label => { node.gameObject.GetComponentsInChildren <TextMesh>().ToList().ForEach(text => text.text = label); }); // When edges come var edges = new Subject <EdgeController>(); edges.Take(1).Subscribe(edge => { var other = edge.vertexA == newObj ? edge.vertexB : edge.vertexA; newObj.transform.position = other.transform.position + (other.transform.position + new Vector3(Random.value - 0.5f, Random.value - 0.5f, Random.value - 0.5f)).normalized; newObj.SetActive(true); }); return nodes[cv.id] = new Node( id: cv.id, gameObject: newObj, labels: labels, edges: edges ); }) .Case <CreateEdge, Node>(ce => { var newObj = Object.Instantiate(edgeModel); newObj.SetActive(true); newObj.transform.SetParent(edgeModel.transform.parent); var edge = newObj.GetComponent <EdgeController>(); var nodeA = nodes[ce.sourceId]; var nodeB = nodes[ce.targetId]; edge.vertexA = nodeA.gameObject; edge.vertexB = nodeB.gameObject; nodeA.edges.OnNext(edge); nodeB.edges.OnNext(edge); return nodes[ce.id] = new Node( id: ce.id, gameObject: newObj ); }) .Case <UpdateValue, Node>(uv => { if (uv.name == "name") { node.gameObject.GetComponentsInChildren <TextMesh>().ToList().ForEach(text => text.text = (string)uv.value); } return node; }) .Default(node) .result); }
protected void SendGraphEventNodeUpdated() { if (!NodeUpdated) { return; } GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_UPDATED, GetProperty(PropertyName.m_id).stringValue); NodeUpdated = false; }
private static void SaveGraph() { AssetDatabase.SaveAssets(); GraphEvent.Send(GraphEvent.EventType.EVENT_SAVED_ASSETS); if (CurrentGraph == null) { return; } CurrentGraph.IsDirty = false; }
private async Task LoadScheduleAsync() { IsBusy = true; _events = PopulateScheduleCalendar(); try { var startDateTime = DateTime.Today; var endDateTime = startDateTime.AddMonths(AppSettings.ScheduleMonths); var result = await _calendarService.GetCarpoolEventsAsync(startDateTime, endDateTime); HasEvents = result.Any(); if (result != null) { foreach (var ev in result.CurrentPage .Where(e => e.Body.Content.Contains(AppSettings.CarpoolEventBody))) { var graphEvent = new GraphEvent(ev); var scheduleGraphEvent = _events.FirstOrDefault(e => e.Key.Date.Equals(graphEvent.StartDate.Date))?.FirstOrDefault(); if (scheduleGraphEvent != null) { if (graphEvent.BodyPreview.Contains("Pickup")) { scheduleGraphEvent.To = graphEvent; } else { scheduleGraphEvent.From = graphEvent; } } } } } catch (ServiceException) { await _dialogService.ShowAlertAsync("Calendar unavailable, please check your office365 subscription.", "Service error", "Ok"); } catch { if (!IsConnected) { await _dialogService.ShowAlertAsync("No network connection, please check your internet.", "Service unavailable", "Ok"); } else { await _dialogService.ShowAlertAsync("An error occured", "Unexpected error", "Try again"); } } finally { Events = _events; IsBusy = false; } }
protected void DrawAddSocketButton(SocketDirection direction, ConnectionMode connectionMode, Type valueType) { var area = new Rect(6, DynamicHeight, Node.GetWidth() - 12, NodySettings.Instance.SocketHeight); DynamicHeight += area.height; //Update HEIGHT if (ZoomedBeyondSocketDrawThreshold) { return; } bool isInput = direction == SocketDirection.Input; Color iconColor = DGUI.Colors.IconColor(isInput ? DGUI.Colors.GetDColor(DGUI.Colors.NodyInputColorName) : DGUI.Colors.GetDColor(DGUI.Colors.NodyOutputColorName)).WithAlpha(NodySettings.Instance.NormalOpacity); var iconRect = new Rect(area.x + area.width / 2 - NodySettings.Instance.NodeAddSocketButtonSize / 2, area.y + area.height / 2 - NodySettings.Instance.NodeAddSocketButtonSize / 2, NodySettings.Instance.NodeAddSocketButtonSize, NodySettings.Instance.NodeAddSocketButtonSize); var hoveredIconRect = new Rect(iconRect.x - iconRect.width * 0.4f / 2, iconRect.y - iconRect.height * 0.4f / 2, iconRect.width * 1.4f, iconRect.height * 1.4f); bool mouseIsOverButton = hoveredIconRect.Contains(Event.current.mousePosition); if (mouseIsOverButton) { iconColor.a = NodySettings.Instance.HoverOpacity; } Color color = GUI.color; GUI.color = iconColor; if (GUI.Button(mouseIsOverButton ? hoveredIconRect : iconRect, GUIContent.none, NodeIconPlus)) { Undo.RecordObject(Node, "Add " + direction + " Socket"); if (isInput) { Node.AddInputSocket(connectionMode, valueType, true, true); } else { Node.AddOutputSocket(connectionMode, valueType, true, true); } GraphEvent.Send(GraphEvent.EventType.EVENT_SOCKET_CREATED, Node.Id); } GUI.color = color; }
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 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); }
/// <summary> Triggered when an UndoRedo action has been performed </summary> private void UndoRedoPerformed() { // if (CurrentGraph != null) // { // //if any node that has been soft deleted has been bought back via the undo / redo operation -> we need to remove it from the soft delete database // foreach (Node node in CurrentGraph.Nodes) //look through the node references list that the graph has // if (EditorSettings.DeletedNodes.Contains(node)) //check if any node id, that is currently referenced, if it's also in the soft delete list (the one recovered from editor prefs) // { // EditorSettings.DeletedNodes.Remove(node); //if a nose was found -> remove it from the soft delete nodes list in order to prevent the node deletion when entering play mode, or closing the graph // EditorSettings.SetDirty(false); // } // // CurrentGraph.SetGraphDirty(); //mark graph dirty // } ValidateDatabases(); //makes sure there are no invalid entries in the databases ConstructGraphGUI(); //recalculates the GUI m_initialDragNodePositions.Clear(); //clears any currently dragged nodes UpdateNodesSelectedState(WindowSettings.SelectedNodes); //updates all the nodes selected state GraphEvent.Send(GraphEvent.EventType.EVENT_UNDO_REDO_PERFORMED); Repaint(); //does a quick repaint }
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); }
/// <summary> Connect two sockets </summary> /// <param name="graph"> Parent graph </param> /// <param name="outputSocket"> Output Socket</param> /// <param name="inputSocket"> Input Socket </param> /// <param name="saveAssets"> Perform AssetDatabase.Save </param> public static void ConnectSockets(Graph graph, Socket outputSocket, Socket inputSocket, bool saveAssets = false) { // if (outputSocket.OverrideConnection) DisconnectSocket(outputSocket, false); // if (inputSocket.OverrideConnection) DisconnectSocket(inputSocket, false); if (outputSocket.OverrideConnection) { outputSocket.Disconnect(); GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_DISCONNECTED, outputSocket.NodeId); } if (inputSocket.OverrideConnection) { inputSocket.Disconnect(); GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_DISCONNECTED, inputSocket.NodeId); } var connection = new Connection(outputSocket, inputSocket); outputSocket.Connections.Add(connection); inputSocket.Connections.Add(connection); graph.SetDirty(saveAssets); GraphEvent.Send(GraphEvent.EventType.EVENT_CONNECTION_ESTABLISHED); }
protected override void OnNodeGUI() { DrawNodeBody(); if (TargetNode.SwitchBackMode) { if (TargetNode.InputSockets == null || TargetNode.InputSockets.Count == 0) { TargetNode.AddInputSocket(ConnectionMode.Multiple, typeof(PassthroughConnection), false, false); GraphEvent.ConstructGraph(); GraphEvent.RecalculateAllPoints(); } DrawSocketsList(Node.InputSockets); } else { if (TargetNode.InputSockets != null && TargetNode.InputSockets.Count > 0) { if (TargetNode.FirstInputSocket != null && TargetNode.FirstInputSocket.IsConnected) { GraphEvent.DisconnectSocket(TargetNode.FirstInputSocket); } TargetNode.InputSockets.Clear(); GraphEvent.ConstructGraph(); GraphEvent.RecalculateAllPoints(); } } DrawSocketsList(Node.OutputSockets); DrawActionDescription(); }
protected override void OnGraphEvent(GraphEvent graphEvent) { UpdateNodeData(); }
private void UpdateSocketValue(Socket socket, UIConnection value) { UIConnection.SetValue(socket, value); GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_UPDATED, TargetNode.Id); }
/// <summary> /// /// </summary> /// <param name="engine"></param> /// <returns></returns> Workflow Load(CWFEngine engine) { using (var xmlReader = XmlReader.Create(_workflowMemento.WorkflowFilePath)) { var xmlNameTable = xmlReader.NameTable; if (xmlNameTable != null) { _workflowMemento.XmlNamespaceManager = new XmlNamespaceManager(xmlNameTable); _workflowMemento.XmlNamespaceManager.AddNamespace("wf", "urn:cwf-schema"); } else { throw new Exception("xmlNameTable of " + _workflowMemento.WorkflowFilePath + " is null"); } // Loading settings var xdoc = XDocument.Load(_workflowMemento.WorkflowFilePath); XDocument XDoc = xdoc; XNamespaceWf = "urn:cwf-schema"; _workflowMemento.Id = int.Parse(GetWorkflowAttribute(xdoc, "id")); _workflowMemento.Name = GetWorkflowAttribute(xdoc, "name"); _workflowMemento.Description = GetWorkflowAttribute(xdoc, "description"); _workflowMemento.LaunchType = (LaunchType)Enum.Parse(typeof(LaunchType), GetWorkflowSetting(xdoc, "launchType"), true); if (_workflowMemento.LaunchType == LaunchType.Periodic) { _workflowMemento.Period = TimeSpan.Parse(GetWorkflowSetting(xdoc, "period")); } _workflowMemento.IsEnabled = bool.Parse(GetWorkflowSetting(xdoc, "enabled")); //create state token try { var typename = GetWorkflowSetting(xdoc, "statemachinetype"); _workflowMemento.StateToken = CreateStateToken(typename); InitializeTransitionDefinitionBuilder(xdoc); Logger.Info($"Instantiated State token"); } catch (FileNotFoundException fnfe) { Logger.Error($"A required library was not found: {fnfe.FileName}"); } catch (Exception e) { Logger.Error($"Exception on creating state machine token: {e.ToString()}"); return(null); } if (xdoc.Root != null) { var xExecutionGraph = xdoc.Root.Element(XNamespaceWf + Sym.ACTIVITY_SETUP); IsExecutionGraphEmpty = xExecutionGraph == null || !xExecutionGraph.Elements().Any(); } var wf = new Workflow(engine, _workflowMemento); // Loading tasks var activities = new List <Activity>(); foreach (var xTaskElement in xdoc.XPathSelectElements("/wf:Workflow/wf:Activities/wf:Activity", _workflowMemento.XmlNamespaceManager)) { var xAttribute = xTaskElement.Attribute("name"); if (xAttribute != null) { var name = xAttribute.Value; ActivityMemento activityMemento = ParseActivity(xTaskElement, wf); Activity activity = LoadActivityInstance(name, activityMemento); activities.Add(activity); } else { throw new Exception("Name attribute of the task " + xTaskElement + " does not exist."); } } wf.Activities = activities.ToArray(); //read all transition definitions var transitionList = new List <Transition>(); foreach (var xTaskElement in xdoc.XPathSelectElements("/wf:Workflow/wf:Transitions/wf:Transition", _workflowMemento.XmlNamespaceManager)) { var xAttributeId = xTaskElement.Attribute("id"); var xAttributeFrom = xTaskElement.Attribute("from"); var xAttributeTo = xTaskElement.Attribute("to"); var xAttributeCondition = xTaskElement.Attribute("condition"); int id = int.Parse(xAttributeId.Value); int from = int.Parse(xAttributeFrom.Value); int to = int.Parse(xAttributeTo.Value); string condition = xAttributeCondition?.Value; var genericType = typeof(Transition <>).MakeGenericType(_stateType); var transition = (Transition)Activator.CreateInstance(genericType, new object[] { id, from, to, condition }); OnTransitionDefinitionInXml(transition); transitionList.Add(transition); Logger.Info(transition.ToString()); } wf.Transitions = transitionList.ToArray(); var d = CompileAndGetMethodInfos(); LinkTransitionsToCompiledConditions(wf.Transitions, d); // Loading execution graph var xExectionGraph = xdoc.XPathSelectElement("/wf:Workflow/wf:ActivitySetup", _workflowMemento.XmlNamespaceManager); if (xExectionGraph != null) { var taskNodes = GetTaskNodes(xExectionGraph); // Check startup node, parallel tasks and infinite loops if (taskNodes.Any()) { if (CheckStartupNode(taskNodes) == false) { Logger.Trace("Startup node with parentId=-1 not found in ExecutionGraph execution graph."); throw new Exception(); } } if (CheckParallelTasks(taskNodes)) { Logger.Trace("Parallel tasks execution detected in ExecutionGraph execution graph."); } CheckInfiniteLoop(taskNodes, "Infinite loop detected in ExecutionGraph execution graph."); // OnSuccess GraphEvent onSuccess = null; var xOnSuccess = xExectionGraph.XPathSelectElement("wf:OnSuccess", _workflowMemento.XmlNamespaceManager); if (xOnSuccess != null) { var onSuccessNodes = GetTaskNodes(xOnSuccess); if (CheckStartupNode(onSuccessNodes) == false) { Logger.Trace("Startup node with parentId=-1 not found in OnSuccess execution graph."); throw new Exception(); } if (CheckParallelTasks(onSuccessNodes)) { Logger.Trace("Parallel tasks execution detected in OnSuccess execution graph."); } CheckInfiniteLoop(onSuccessNodes, "Infinite loop detected in OnSuccess execution graph."); onSuccess = new GraphEvent(onSuccessNodes); } // OnWarning GraphEvent onWarning = null; var xOnWarning = xExectionGraph.XPathSelectElement("wf:OnWarning", _workflowMemento.XmlNamespaceManager); if (xOnWarning != null) { var onWarningNodes = GetTaskNodes(xOnWarning); if (CheckStartupNode(onWarningNodes) == false) { Logger.Trace("Startup node with parentId=-1 not found in OnWarning execution graph."); throw new Exception(); } if (CheckParallelTasks(onWarningNodes)) { Logger.Trace("Parallel tasks execution detected in OnSuccess execution graph."); } CheckInfiniteLoop(onWarningNodes, "Infinite loop detected in OnWarning execution graph."); onWarning = new GraphEvent(onWarningNodes); } // OnError GraphEvent onError = null; var xOnError = xExectionGraph.XPathSelectElement("wf:OnError", _workflowMemento.XmlNamespaceManager); if (xOnError != null) { var onErrorNodes = GetTaskNodes(xOnError); if (CheckStartupNode(onErrorNodes) == false) { Logger.Trace("Startup node with parentId=-1 not found in OnError execution graph."); return(null); } if (CheckParallelTasks(onErrorNodes)) { Logger.Trace("Parallel tasks execution detected in OnError execution graph."); } CheckInfiniteLoop(onErrorNodes, "Infinite loop detected in OnError execution graph."); onError = new GraphEvent(onErrorNodes); } wf.ActivitySetup = new Graph(taskNodes, onSuccess, onWarning, onError); } return(wf); } }
protected virtual void OnGraphEvent(GraphEvent graphEvent) { UpdateNodeData(); }
/// <summary> Called when object becomes enabled and active </summary> protected virtual void OnEnable() { LoadSerializedProperty(); InitAnimBool(); GraphEvent.AddReceiver(OnGraphEvent); }
/// <summary> Called when object becomes disabled and inactive </summary> protected virtual void OnDisable() { GraphEvent.RemoveReceiver(OnGraphEvent); }
private void HandleMouseLeftClicks() { Event current = Event.current; if (!current.isMouse) { return; } if (current.button != 0) { return; } if (current.type == EventType.MouseDown) { //left mouse button is down and the space key is down as well -> enter panning mode if (m_spaceKeyDown) { m_mode = GraphMode.Pan; current.Use(); return; } if (m_altKeyPressed) //delete mode { BaseNodeGUI nodeGUI = GetNodeGUIOfDeleteButtonAtWorldPosition(CurrentMousePosition); if (nodeGUI != null) { SoftDeleteNode(nodeGUI.Node, true, false); current.Use(); return; } } //pressed left mouse button over a socket point -> but we have at least two nodes selected -> do not allow starting any connections if (WindowSettings.SelectedNodes.Count < 2) { if (m_currentHoveredVirtualPoint != null) { // if (current.alt) if (m_altKeyPressed) { //pressed left mouse button over a socket virtual point while holding down Alt -> Disconnect Virtual Point DisconnectVirtualPoint(m_currentHoveredVirtualPoint, true); } else { //pressed left mouse button over a socket connection point -> it's a possible start of a connection m_activeSocket = m_currentHoveredVirtualPoint.Socket; //set the socket as the active socket m_mode = GraphMode.Connect; //set the graph in connection mode } current.Use(); return; } Socket socket = GetSocketAtWorldPositionFromHoverRect(CurrentMousePosition); if (socket != null) { // if (current.alt) if (m_altKeyPressed) { //pressed left mouse button over a socket while holding down Alt -> Remove Socket RemoveSocket(socket, true); } else { //pressed left mouse button over a socket -> it's a possible start of a connection m_activeSocket = socket; //set the socket as the active socket m_mode = GraphMode.Connect; //set the graph in connection mode } current.Use(); return; } } //pressed left mouse button over a node -> check to see if it's inside the header (if no node is currently selected) or it just over a node (if at least 2 nodes are selected) if (m_currentHoveredNode != null) { if (GetNodeGridRect(m_currentHoveredNode).Contains(CurrentMousePosition) || //if mouse is inside node -> allow dragging WindowSettings.SelectedNodes.Count > 1) //OR if there are at least 2 nodes selected -> allow dragging from any point on the node { //pressed left mouse button over a node -> select/deselect it if (current.shift || current.control || current.command) //if using modifiers -> create custom selection { SelectNodes(new List <Node> { m_currentHoveredNode }, true, true); //add/remove the node to/from selection } else if (!WindowSettings.SelectedNodes.Contains(m_currentHoveredNode)) //we may have a selection and we do not want to override it in order to be able to start dragging { SelectNodes(new List <Node> { m_currentHoveredNode }, false, true); //select this node only } //allow dragging ONLY IF the mouse is over a selected node //in the previous lines we only checked if it's over a node, but not if the node we are hovering over is currently selected if (WindowSettings.SelectedNodes.Contains(m_currentHoveredNode)) { if (Selection.activeObject != m_currentHoveredNode) { Selection.activeObject = m_currentHoveredNode; //select the node } //pressed left mouse button over a node -> it's a possible start drag PrepareToDragSelectedNodes(CurrentMousePosition); m_mode = GraphMode.Drag; } } current.Use(); return; } //pressed left mouse button over nothing -> it's a possible start selection PrepareToCreateSelectionBox(CurrentMousePosition); current.Use(); return; } if (current.type == EventType.MouseDrag) { //left mouse click is dragging and the graph is in panning mode if (m_mode == GraphMode.Pan) { //check that the space key is held down -> otherwise exit pan mode if (!m_spaceKeyDown) { m_mode = GraphMode.None; } else { DoPanning(current); } current.Use(); return; } //mouse left click is dragging a connection if (m_mode == GraphMode.Connect) { if (m_currentHoveredSocket != null) //mouse is over a socket -> color the line to green if connection is possible or red otherwise { m_createConnectionLineColor = m_activeSocket.CanConnect(m_currentHoveredSocket) ? Color.green : Color.red; } else if (m_currentHoveredVirtualPoint != null) //mouse is over a socket connection point -> color the line to green if connection is possible or red otherwise { m_createConnectionLineColor = m_activeSocket.CanConnect(m_currentHoveredVirtualPoint.Socket) ? Color.green : Color.red; } else //mouse is not over anything connectable -> show the connection point color to look for { m_createConnectionLineColor = m_activeSocket.IsInput ? DGUI.Colors.GetDColor(DGUI.Colors.NodyOutputColorName).Normal //source socket is input -> looking for an output socket -> color the line to the output color : DGUI.Colors.GetDColor(DGUI.Colors.NodyInputColorName).Normal; //source socket is output -> looking for an input socket -> color the line to the input color } current.Use(); return; } //mouse left click is dragging one or more nodes if (m_mode == GraphMode.Drag) // && GUIUtility.hotControl == dragNodesControlId) { m_isDraggingAnimBool.target = false; RecordUndo("Move Nodes"); UpdateSelectedNodesWhileDragging(); current.Use(); return; } //mouse left click is dragging and creating a selection box <- we know this because the the mouse is not over a point nor a node if (m_startSelectPoint != null) { m_mode = GraphMode.Select; } if (m_mode == GraphMode.Select) { UpdateSelectionBox(CurrentMousePosition); UpdateSelectBoxSelectedNodesWhileSelecting(current); UpdateNodesSelectedState(m_selectedNodesWhileSelecting); current.Use(); return; } } if (current.type == EventType.MouseUp) { if (RegisteredDoubleClick) { if (m_previousHoveredNode != null) { NodesGUIsDatabase[m_previousHoveredNode.Id].OnDoubleClick(this); } } //lifted left mouse button and was panning (space key was/is down) -> reset graph to idle if (m_mode == GraphMode.Pan) { m_mode = GraphMode.None; current.Use(); return; } //lifted left mouse button and was dragging -> reset graph to idle if (m_mode == GraphMode.Drag) { m_initialDragNodePositions.Clear(); m_isDraggingAnimBool.target = true; m_mode = GraphMode.None; current.Use(); return; } //lifted left mouse button and was selecting via selection box -> end selections and reset graph to idle mode if (m_mode == GraphMode.Select) { EndDragSelectedNodes(); m_mode = GraphMode.None; current.Use(); return; } //check if this happened over another socket or connection point if (m_currentHoveredSocket != null) { //lifted left mouse button over a socket if (m_activeSocket != null && //if there is an active socket m_activeSocket != m_currentHoveredSocket && //and it's not this one m_activeSocket.CanConnect(m_currentHoveredSocket)) //and the two sockets can get connected { ConnectSockets(m_activeSocket, m_currentHoveredSocket); //connect the two sockets } else //this was a failed connection attempt { GraphEvent.Send(GraphEvent.EventType.EVENT_CONNECTING_END); //send a graph event } m_activeSocket = null; //clear the active socket m_mode = GraphMode.None; //set the graph in idle mode current.Use(); return; } if (m_currentHoveredVirtualPoint != null) { //lifted left mouse button over a socket connection point if (m_activeSocket != null && //if there is an active socket m_activeSocket != m_currentHoveredVirtualPoint.Socket && //and it's not this one m_activeSocket.CanConnect(m_currentHoveredVirtualPoint.Socket)) //and the two sockets can get connected { ConnectSockets(m_activeSocket, m_currentHoveredVirtualPoint.Socket); //connect the two sockets } else //this was a failed connection attempt { GraphEvent.Send(GraphEvent.EventType.EVENT_CONNECTING_END); //send a graph event } m_activeSocket = null; //clear the active socket m_mode = GraphMode.None; //set the graph in idle mode current.Use(); return; } //it a connecting process was under way -> clear it //lifted left mouse button, but no virtual point was under the mouse position if (m_mode == GraphMode.Connect) { m_activeSocket = null; //clear the active socket m_mode = GraphMode.None; //set the graph in idle mode } Node node = GetNodeAtWorldPosition(CurrentMousePosition); if (node != null) { m_mode = GraphMode.None; //set the graph in idle mode current.Use(); return; } //lifted mouse left button over nothing -> deselect all and select the graph itself ExecuteGraphAction(GraphAction.DeselectAll); //deselect all nodes and select the graph itself m_mode = GraphMode.None; //set the graph in idle mode current.Use(); return; } //check if the developer released the left mouse button outside of the graph window if (current.rawType == EventType.MouseUp || current.rawType == EventType.MouseLeaveWindow) { switch (m_mode) { case GraphMode.Select: EndDragSelectedNodes(); m_mode = GraphMode.None; current.Use(); break; } } }
private void HandleOnGraphEvent(GraphEvent graphEvent) { // DDebug.Log("GraphEvent: " + graphEvent.eventType); switch (graphEvent.eventType) { case GraphEvent.EventType.EVENT_NONE: break; case GraphEvent.EventType.EVENT_CONNECTING_BEGIN: break; case GraphEvent.EventType.EVENT_CONNECTING_END: ConstructGraphGUI(); break; case GraphEvent.EventType.EVENT_CONNECTION_ESTABLISHED: ConstructGraphGUI(); break; case GraphEvent.EventType.EVENT_NODE_CREATED: ConstructGraphGUI(); RecalculateAllPointRects(); break; case GraphEvent.EventType.EVENT_NODE_DELETED: ConstructGraphGUI(); break; case GraphEvent.EventType.EVENT_NODE_UPDATED: ConstructGraphGUI(); RecalculateAllPointRects(); break; case GraphEvent.EventType.EVENT_NODE_CLICKED: break; case GraphEvent.EventType.EVENT_SOCKET_CREATED: ConstructGraphGUI(); RecalculateAllPointRects(); break; case GraphEvent.EventType.EVENT_SOCKET_ADDED: break; case GraphEvent.EventType.EVENT_SOCKET_REMOVED: break; case GraphEvent.EventType.EVENT_SOCKET_CLEARED_CONNECTIONS: ConstructGraphGUI(); break; case GraphEvent.EventType.EVENT_CONNECTION_CREATED: break; case GraphEvent.EventType.EVENT_CONNECTION_TAPPED: break; case GraphEvent.EventType.EVENT_CONNECTION_DELETED: ConstructGraphGUI(); break; case GraphEvent.EventType.EVENT_RECORD_UNDO: break; case GraphEvent.EventType.EVENT_SAVED_ASSETS: break; case GraphEvent.EventType.EVENT_NODE_DISCONNECTED: ConstructGraphGUI(); break; case GraphEvent.EventType.EVENT_GRAPH_OPENED: ConstructGraphGUI(); RecalculateAllPointRects(); break; case GraphEvent.EventType.EVENT_UNDO_REDO_PERFORMED: RecalculateAllPointRects(); break; default: throw new ArgumentOutOfRangeException(); } switch (graphEvent.commandType) { case GraphEvent.CommandType.NONE: break; case GraphEvent.CommandType.CONSTRUCT_GRAPH: ConstructGraphGUI(); break; case GraphEvent.CommandType.RECALCULATE_ALL_POINTS: RecalculateAllPointRects(); break; case GraphEvent.CommandType.DISCONNECT_SOCKET: DisconnectSocket(graphEvent.sourceSocket, true); break; } Repaint(); }
/// <summary> Returns TRUE if it creates a StartNode in the given target graph. Note that if the graph is a sub-graph or if it already has a StartNode, it will return FALSE </summary> /// <param name="graph"> Target graph </param> public static void CreateStartNode(Graph graph) { //Check the graph for system nodes Node startNode = graph.GetStartNode(); Node enterNode = graph.GetEnterNode(); Node exitNode = graph.GetExitNode(); bool startNodeWasCreated = false; if (startNode == null) { startNode = CreateNode(graph, typeof(StartNode), Vector2.zero); //create start node graph.Nodes.Add(startNode); //add start node to Nodes list if (!EditorUtility.IsPersistent(startNode)) { AssetDatabase.AddObjectToAsset(startNode, graph); //create the asset file for the node and attach it to the graph asset file } startNodeWasCreated = true; } if (enterNode != null) //this graph has an enter node -> it needs to be deleted { //because start node was created and enter node is not null -> set start node position as the enter node position if (startNodeWasCreated) { startNode.SetPosition(enterNode.GetPosition()); } if (enterNode.IsConnected()) //disconnect enter node { string targetSocketId = enterNode.OutputSockets[0].Connections[0].InputSocketId; Node targetNode = graph.GetNodeById(enterNode.OutputSockets[0].Connections[0].InputNodeId); if (targetNode != null) //make sure a node connected to the EnterNode is not null (sanity check) { targetNode.GetSocketFromId(targetSocketId).DisconnectFromNode(enterNode.Id); if (startNodeWasCreated) //because start node was created -> connect it to the same node enter node was connected { ConnectSockets(graph, startNode.OutputSockets[0], targetNode.GetSocketFromId(targetSocketId)); } } } if (graph.Nodes.Contains(enterNode)) { graph.Nodes.Remove(enterNode); //remove enter node from Nodes list } Object.DestroyImmediate(enterNode, true); //destroy enter node asset } if (exitNode != null) //this graph has an exit node -> it needs to be deleted { if (exitNode.IsConnected()) //disconnect exit node { for (int i = exitNode.InputSockets[0].Connections.Count - 1; i >= 0; i--) { Connection connection = exitNode.InputSockets[0].Connections[i]; Node connectedNode = graph.GetNodeById(connection.OutputNodeId); exitNode.InputSockets[0].DisconnectFromNode(connection.OutputNodeId); if (connectedNode != null) { connectedNode.GetSocketFromId(connection.OutputSocketId).DisconnectFromNode(exitNode.Id); } } } if (graph.Nodes.Contains(exitNode)) { graph.Nodes.Remove(exitNode); //remove exit node from Nodes list } Object.DestroyImmediate(exitNode, true); //destroy exit node asset } graph.IsSubGraph = false; //update graph type graph.SetDirty(false); //set the graph as dirty GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_CREATED); //StartNode has been created }
/// <summary> Returns TRUE if it creates an Enter and/or an Exit node in the given target graph. Note that if the graph is a graph or if it already has an Enter and an Exit nodes, it will return FALSE </summary> /// <param name="graph"> Target Graph </param> public static void CreateEnterAndExitNodes(Graph graph) { const float spaceBetweenNodes = 24f; //Check the graph for system nodes Node startNode = graph.GetStartNode(); Node enterNode = graph.GetEnterNode(); Node exitNode = graph.GetExitNode(); bool enterNodeWasCreated = false; if (enterNode == null) { enterNode = CreateNode(graph, typeof(EnterNode), Vector2.zero); //create enter node graph.Nodes.Add(enterNode); //add start node to Nodes list if (!EditorUtility.IsPersistent(enterNode)) { AssetDatabase.AddObjectToAsset(enterNode, graph); //create the asset file for the node and attach it to the graph asset file } enterNodeWasCreated = true; } if (startNode != null) { //because enter node was created and start node is not null -> set enter node position as the start node position if (enterNodeWasCreated) { enterNode.SetPosition(startNode.GetPosition()); } if (startNode.IsConnected()) //disconnect start node { string targetSocketId = startNode.OutputSockets[0].Connections[0].InputSocketId; Node targetNode = graph.GetNodeById(startNode.OutputSockets[0].Connections[0].InputNodeId); if (targetNode != null) //make sure a node connected to the StartNode is not null (sanity check) { targetNode.GetSocketFromId(targetSocketId).DisconnectFromNode(startNode.Id); ConnectSockets(graph, enterNode.OutputSockets[0], targetNode.GetSocketFromId(targetSocketId)); } } if (graph.Nodes.Contains(startNode)) { graph.Nodes.Remove(startNode); //remove start node from Nodes list } Object.DestroyImmediate(startNode, true); //destroy enter node asset } if (exitNode == null) { exitNode = CreateNode(graph, typeof(ExitNode), new Vector2(enterNode.GetX() + NodySettings.Instance.ExitNodeWidth * 2 + spaceBetweenNodes, enterNode.GetY() + NodySettings.Instance.NodeHeaderHeight / 2)); graph.Nodes.Add(exitNode); //add exit node to Nodes kist if (!EditorUtility.IsPersistent(exitNode)) { AssetDatabase.AddObjectToAsset(exitNode, graph); //create the asset file for the node and attach it to the graph asset file } } graph.IsSubGraph = true; //update graph type graph.SetDirty(false); //set the graph as dirty GraphEvent.Send(GraphEvent.EventType.EVENT_NODE_CREATED); //EnterNode and/or ExitNode has/have been created }
private async Task ItemSelectedAsync(GraphEvent graphEvent) { await NavigationService.NavigateToAsync <ScheduleDetailViewModel>(graphEvent); }
public EffectGraphEventArgs(GraphEvent what) { What = what; }
private void DrawGraphTabs() { if (GraphTabs.Count == 0) { return; //if no tabs have been opened stop here -> do not draw anything } int clickedTabIndex = -1; //index of the clicked tab float tabWidth = NodySettings.Instance.GraphTabMaximumWidth; //get the tab max width float tabsCount = GraphTabs.Count; //count the tabs bool calculateTabWith = true; //start dynamic tab width calculations while (calculateTabWith) { float totalSpaceWidth = tabsCount * 2 * NodySettings.Instance.GraphTabElementSpacing; float totalDividersWidth = (tabsCount - 1) * NodySettings.Instance.GraphTabDividerWidth; float totalTabsAvailableWidth = GraphTabsRect.width - totalSpaceWidth - totalDividersWidth; float calculatedTabWidth = totalTabsAvailableWidth / tabsCount; if (calculatedTabWidth > NodySettings.Instance.GraphTabMaximumWidth) { calculateTabWith = false; tabWidth = NodySettings.Instance.GraphTabMaximumWidth; } else if (calculatedTabWidth >= NodySettings.Instance.GraphTabMinimumWidth) { calculateTabWith = false; tabWidth = calculatedTabWidth; } else { tabsCount--; } } float x = GraphTabsRect.x; //Start drawing the tabs GUILayout.Space(DGUI.Properties.Space()); GUILayout.BeginHorizontal(); { GUILayout.Space(NodySettings.Instance.GraphTabElementSpacing); x += NodySettings.Instance.GraphTabElementSpacing; for (int index = 0; index < tabsCount; index++) { if (index > 0) { float dividerHeight = NodySettings.Instance.GraphTabsAreaHeight - NodySettings.Instance.GraphTabElementSpacing * 3; GUILayout.BeginVertical(GUILayout.Height(GraphTabsRect.height)); { GUILayout.Space((GraphTabsRect.height - dividerHeight) / 2 - DGUI.Properties.Space()); Color color = GUI.color; GUI.color = DGUI.Colors.TextColor(DGUI.Colors.DisabledTextColorName).WithAlpha(color.a * 0.4f); GUILayout.Label(GUIContent.none, DGUI.Properties.White, GUILayout.Width(NodySettings.Instance.GraphTabDividerWidth), GUILayout.Height(dividerHeight)); GUI.color = color; } GUILayout.EndVertical(); GUILayout.Space(NodySettings.Instance.GraphTabElementSpacing); x += NodySettings.Instance.GraphTabElementSpacing; x += NodySettings.Instance.GraphTabDividerWidth; x += NodySettings.Instance.GraphTabElementSpacing; } GraphTab graphTab = GraphTabs[index]; var buttonRect = new Rect(x, GraphTabsRect.y + NodySettings.Instance.GraphTabElementSpacing, tabWidth, GraphTabsRect.height - 2 * NodySettings.Instance.GraphTabElementSpacing); GUI.color = InitialGUIColor; if (index < tabsCount - 1) { GUI.color = GUI.color.WithAlpha(DGUI.Utility.IsProSkin ? 0.6f : 0.8f); } if (graphTab.DrawButton(buttonRect)) { if (graphTab.IsRootTab && graphTab.Graph != null && CurrentGraph != graphTab.Graph) { OpenGraph(graphTab.Graph, true, false, false); } else if (!graphTab.IsRootTab && graphTab.SubGraphNode != null && graphTab.SubGraphNode.SubGraph != null && CurrentGraph != graphTab.SubGraphNode.SubGraph) { OpenGraph(graphTab.SubGraphNode.SubGraph, true, false, false); } CurrentZoom = graphTab.Zoom; CurrentPanOffset = graphTab.PanOffset; SelectedNodes = new List <Node>(graphTab.SelectedNodes); clickedTabIndex = index; GraphEvent.Send(GraphEvent.EventType.EVENT_GRAPH_OPENED); break; } GUILayout.Space(tabWidth); x += tabWidth; } GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); if (clickedTabIndex == -1) { return; } for (int i = GraphTabs.Count - 1; i >= 0; i--) { if (i > clickedTabIndex) { GraphTabs.RemoveAt(i); } } }