private static void DrawNode(UTNodeEditorModel editorModel, UTNode node, NodeDrawingPhase phase) { if (phase == NodeDrawingPhase.DrawNodes) { var style = UTEditorResources.GraphNodeStyle; if (node.Data is UTAutomationPlanNoteEntry) { style = UTEditorResources.GraphCommentStyle; if (editorModel.SelectedNodes.Contains(node)) { style = UTEditorResources.GraphCommentSelectedStyle; } } else { if (editorModel.SelectedNodes.Contains(node)) { style = UTEditorResources.GraphNodeSelectedStyle; } if (node == editorModel.HighlightedNode) { style = UTEditorResources.GraphNodeHighlightStyle; } } GUI.Box(node.Bounds, "", style); if (editorModel.IsFirstNode(node)) { GUI.DrawTexture(node.IndicatorBounds, UTEditorResources.FirstNodeTexture); } if (node.Data is UTAutomationPlanPlanEntry) { GUI.DrawTexture(node.SecondaryIndicatorBounds, UTEditorResources.ExecutePlanTexture); } } foreach (var connector in node.Connectors) { if (phase == NodeDrawingPhase.DrawNodes) { GUI.Label(connector.labelPosition, connector.label, connector.labelStyle); GUI.Box(connector.connectorPosition, "", connector.isConnected ? UTEditorResources.GraphNodeConnectorStyle : UTEditorResources.GraphNodeConnectorStyleEmpty); } if (phase == NodeDrawingPhase.DrawLines) { var targetNode = editorModel.GetReferencedNode(node, connector.property); if (targetNode != null) { UTLineUtils.DrawLine(connector.connectorPosition.center, targetNode.Bounds.center); } } } if (phase == NodeDrawingPhase.DrawNodes) { GUI.Label(node.Bounds, node.Label, UTEditorResources.GraphNodeHeaderStyle); if (!string.IsNullOrEmpty(node.Text)) { GUI.Label(node.TextBounds, node.Text, UTEditorResources.GraphNodeTextStyle); } } }
public static UTNodeEditorData NodeEditor(UTNodeEditorData editorData, UTNodeEditorModel editorModel, params GUILayoutOption[] options) { Rect inRect = EditorGUILayout.BeginHorizontal(options); int controlId = GUIUtility.GetControlID(ControlHint, FocusType.Passive); UTNodeEditorState state = (UTNodeEditorState)GUIUtility.GetStateObject(typeof(UTNodeEditorState), controlId); if (editorData == null) { editorData = new UTNodeEditorData(); } var evt = Event.current; var currentEventType = evt.type; // reset drag and drop state if (currentEventType == EventType.DragUpdated || currentEventType == EventType.DragPerform || currentEventType == EventType.DragExited) { state.isDropTarget = false; } if (currentEventType == EventType.Repaint) { UTEditorResources.GraphBackgroundStyle.Draw(inRect, false, false, false, false); } if (editorModel.HighlightedNode != null) { editorData.scrollPosition = Vector2.MoveTowards(editorData.scrollPosition, editorModel.HighlightedNode.Bounds.center, 2f); } editorData.scrollPosition = EditorGUILayout.BeginScrollView(editorData.scrollPosition); Vector2 mousePosition = evt.mousePosition; Vector2 requiredSize = CalculateRequiredSize(editorModel); // allocate space within the scroll view GUILayoutUtility.GetRect(requiredSize.x, requiredSize.y); DrawNodes(editorModel); if (state.sourceConnector != null) { UTLineUtils.DrawLine(state.sourceConnector.connectorPosition.center, state.lastMousePosition); } // we need to get it here as well so we get events limited to the scroll view. evt = Event.current; currentEventType = evt.type; if (editorModel.HasPlan) { switch (currentEventType) { case EventType.Repaint: if (state.isDrawingSelection) { var selectionRect = ToRect(evt.mousePosition, state.lastMousePosition); GUI.Box(selectionRect, ""); } break; case EventType.ContextClick: if (GUIUtility.hotControl != 0 && GUIUtility.hotControl != controlId) { break; } GUIUtility.hotControl = controlId; ShowPopup(evt, editorModel); evt.Use(); break; case EventType.MouseUp: if (GUIUtility.hotControl != 0 && GUIUtility.hotControl != controlId) { break; } if (evt.button == 0) { if (state.isDrawingSelection) { state.isDrawingSelection = false; var theRect = ToRect(evt.mousePosition, state.lastMousePosition); if (evt.alt) { editorModel.SelectNodesInRect(theRect, UTNodeEditorModel.SelectionMode.Subtract); } else if (evt.shift) { editorModel.SelectNodesInRect(theRect, UTNodeEditorModel.SelectionMode.Add); } else { editorModel.SelectNodesInRect(theRect, UTNodeEditorModel.SelectionMode.Replace); } } else { if (state.hotNode != null && state.sourceConnector != null) { if (state.hotNode != state.sourceConnector.owner && !(state.hotNode.Data is UTAutomationPlanNoteEntry)) { editorModel.AddConnection(state.sourceConnector, state.hotNode); } } if (state.delayedSelectionMode) { if (evt.alt) { editorModel.SelectNode(state.hotNode, UTNodeEditorModel.SelectionMode.Subtract); } else { editorModel.SelectNode(state.hotNode, UTNodeEditorModel.SelectionMode.Replace); } } state.delayedSelectionMode = false; state.hotNode = null; state.sourceConnector = null; } // release lock if required GUIUtility.hotControl = 0; evt.Use(); } break; case EventType.MouseDown: if (GUIUtility.hotControl != 0 && GUIUtility.hotControl != controlId) { break; } GUIUtility.hotControl = controlId; if (evt.button == 0) //left click, only { if (state.sourceConnector == null) { state.sourceConnector = GetConnectorUnderMouse(editorModel, evt.mousePosition); state.lastMousePosition = evt.mousePosition; } if (state.sourceConnector == null) { state.hotNode = GetNodeUnderMouse(editorModel, evt.mousePosition); if (state.hotNode != null) { if (editorModel.SelectedNodes.Contains(state.hotNode)) { state.delayedSelectionMode = true; } else { if (evt.alt) { editorModel.SelectNode(state.hotNode, UTNodeEditorModel.SelectionMode.Subtract); } else if (evt.shift) { editorModel.SelectNode(state.hotNode, UTNodeEditorModel.SelectionMode.Add); } else { editorModel.SelectNode(state.hotNode, UTNodeEditorModel.SelectionMode.Replace); } } } else { // start selection rect state.lastMousePosition = evt.mousePosition; state.isDrawingSelection = true; } } state.dragThresholdReached = false; evt.Use(); } break; case EventType.MouseDrag: if (GUIUtility.hotControl != 0 && GUIUtility.hotControl != controlId) { break; } var connector = state.sourceConnector; if (connector != null) { state.lastMousePosition = evt.mousePosition; state.hotNode = GetNodeUnderMouse(editorModel, evt.mousePosition); evt.Use(); break; } var node = state.hotNode; if (node != null && connector == null) { if (!state.dragThresholdReached) { state.dragThresholdReached = (evt.mousePosition - state.lastMousePosition).magnitude > 3; if (state.dragThresholdReached) { editorModel.StartMovingNodes(); } } else { var theDelta = evt.delta; if (theDelta.x < 0 || theDelta.y < 0) { foreach (var aNode in editorModel.SelectedNodes) { if (theDelta.x < 0 && aNode.Bounds.x < (Mathf.Abs(theDelta.x))) { theDelta.x = -aNode.Bounds.x; } if (theDelta.y < 0 && aNode.Bounds.y < (Mathf.Abs(theDelta.y))) { theDelta.y = -aNode.Bounds.y; } } } foreach (var aNode in editorModel.SelectedNodes) { var newX = aNode.Bounds.x + theDelta.x; var newY = aNode.Bounds.y + theDelta.y; aNode.Bounds = new Rect(newX, newY, aNode.Bounds.width, aNode.Bounds.height); } } evt.Use(); } if (state.isDrawingSelection) { HandleUtility.Repaint(); } state.delayedSelectionMode = false; break; case EventType.DragUpdated: case EventType.DragPerform: if (editorData.IsDropSupported) { if (editorData.DropTarget.CanDrop()) { state.isDropTarget = true; if (currentEventType == EventType.DragPerform) { editorData.DropTarget.AcceptDrop(mousePosition); } } if (state.isDropTarget) { DragAndDrop.activeControlID = controlId; evt.Use(); } } break; case EventType.KeyDown: var delete = false; if (Application.platform == RuntimePlatform.OSXEditor) { if (evt.keyCode == KeyCode.Backspace && evt.command) { delete = true; } } else { if (evt.keyCode == KeyCode.Delete && evt.shift) { delete = true; } } if (delete) { editorModel.DeleteNodes(editorModel.SelectedNodes); } break; } } EditorGUILayout.EndScrollView(); EditorGUILayout.EndHorizontal(); return(editorData); }