protected virtual void HandleSelectionBox(Flowchart flowchart) { if (Event.current.button == 0 && Event.current.modifiers != EventModifiers.Alt && !(UnityEditor.Tools.current == Tool.View && UnityEditor.Tools.viewTool == ViewTool.Pan)) { switch (Event.current.type) { case EventType.MouseDown: if (!mouseOverVariables) { startSelectionBoxPosition = Event.current.mousePosition; mouseDownSelectionState = new List<Block>(flowchart.SelectedBlocks); Event.current.Use(); } break; case EventType.MouseDrag: if (startSelectionBoxPosition.x >= 0 && startSelectionBoxPosition.y >= 0) { var topLeft = Vector2.Min(startSelectionBoxPosition, Event.current.mousePosition); var bottomRight = Vector2.Max(startSelectionBoxPosition, Event.current.mousePosition); selectionBox = Rect.MinMaxRect(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); Rect zoomSelectionBox = selectionBox; zoomSelectionBox.position -= flowchart.ScrollPos * flowchart.Zoom; zoomSelectionBox.position /= flowchart.Zoom; zoomSelectionBox.size /= flowchart.Zoom; foreach (var block in flowchart.GetComponents<Block>()) { if (zoomSelectionBox.Overlaps(block._NodeRect)) { if (mouseDownSelectionState.Contains(block)) { flowchart.SelectedBlocks.Remove(block); } else { flowchart.AddSelectedBlock(block); } } else if (mouseDownSelectionState.Contains(block)) { flowchart.AddSelectedBlock(block); } else { flowchart.SelectedBlocks.Remove(block); } } } Event.current.Use(); break; } if (Event.current.rawType == EventType.MouseUp) { selectionBox.size = Vector2.zero; selectionBox.position = -Vector2.one; startSelectionBoxPosition = selectionBox.position; var tempList = new List<Block>(flowchart.SelectedBlocks); flowchart.SelectedBlocks = mouseDownSelectionState; Undo.RecordObject(flowchart, "Select"); flowchart.SelectedBlocks = tempList; if (flowchart.SelectedBlock != null) { SetBlockForInspector(flowchart, flowchart.SelectedBlock); } } } }
protected virtual void ExecuteCommands(Flowchart flowchart) { if (Event.current.type == EventType.ExecuteCommand) { switch (Event.current.commandName) { case "Copy": Copy(flowchart); Event.current.Use(); break; case "Cut": Cut(flowchart); Event.current.Use(); break; case "Paste": Paste(flowchart, position.center - position.position); Event.current.Use(); break; case "Delete": DeleteBlocks(flowchart.SelectedBlocks); Event.current.Use(); break; case "Duplicate": Duplicate(flowchart); Event.current.Use(); break; case "SelectAll": Undo.RecordObject(flowchart, "Selection"); flowchart.ClearSelectedBlocks(); foreach (var block in flowchart.GetComponents<Block>()) { flowchart.AddSelectedBlock(block); } Event.current.Use(); break; case "Find": blockPopupSelection = 0; EditorGUI.FocusTextInControl(searchFieldName); Event.current.Use(); break; } } }
protected virtual void DrawFlowchartView(Flowchart flowchart) { Block[] blocks = flowchart.GetComponents<Block>(); foreach (var block in blocks) { var node = block as Node; if (node == null) { continue; } var newRect = new Rect(); newRect.xMin = Mathf.Min(flowchart.ScrollViewRect.xMin, node._NodeRect.xMin - 400); newRect.xMax = Mathf.Max(flowchart.ScrollViewRect.xMax, node._NodeRect.xMax + 400); newRect.yMin = Mathf.Min(flowchart.ScrollViewRect.yMin, node._NodeRect.yMin - 400); newRect.yMax = Mathf.Max(flowchart.ScrollViewRect.yMax, node._NodeRect.yMax + 400); flowchart.ScrollViewRect = newRect; } // Draw background color / drop shadow if (Event.current.type == EventType.Repaint) { UnityEditor.Graphs.Styles.graphBackground.Draw( new Rect(0, 17, position.width, position.height - 17), false, false, false, false ); } // Calc rect for script view Rect scriptViewRect = new Rect(0, 0, this.position.width / flowchart.Zoom, this.position.height / flowchart.Zoom); // Update right click start outside of EditorZoomArea if (Event.current.button == 1) { if (Event.current.type == EventType.MouseDown) { rightClickDown = Event.current.mousePosition; } else if (Event.current.type == EventType.MouseDrag) { if (Vector2.Distance(rightClickDown, Event.current.mousePosition) > rightClickTolerance) { rightClickDown = -Vector2.one; } } } EditorZoomArea.Begin(flowchart.Zoom, scriptViewRect); if (Event.current.type == EventType.Repaint) { DrawGrid(flowchart); } // The center of the Flowchart depends on the block positions and window dimensions, so we calculate it // here in the FlowchartWindow class and store it on the Flowchart object for use later. if (flowchart != null && blocks.Length > 0) { CalcFlowchartCenter(flowchart, blocks); } // Draw connections foreach (var block in blocks) { DrawConnections(flowchart, block, false); } foreach (var block in blocks) { DrawConnections(flowchart, block, true); } GUIStyle windowStyle = new GUIStyle(); windowStyle.stretchHeight = true; BeginWindows(); windowBlockMap.Clear(); bool useEvent = false; bool endDrag = false; for (int i = 0; i < blocks.Length; ++i) { var block = blocks[i]; float nodeWidthA = nodeStyle.CalcSize(new GUIContent(block.BlockName)).x + 10; float nodeWidthB = 0f; if (block._EventHandler != null) { nodeWidthB = nodeStyle.CalcSize(new GUIContent(block._EventHandler.GetSummary())).x + 10; } if (Event.current.button == 0) { Rect tempRect = block._NodeRect; tempRect.width = Mathf.Max(Mathf.Max(nodeWidthA, nodeWidthB), 120); tempRect.height = 40; if (dragWindowId > -1 && flowchart.SelectedBlocks.Contains(block)) { if (Event.current.type == EventType.MouseDrag) { tempRect.x += Event.current.delta.x; tempRect.y += Event.current.delta.y; forceRepaintCount = 6; useEvent = true; } else if (Event.current.rawType == EventType.MouseUp) { Vector2 newPos = new Vector2(tempRect.x, tempRect.y); tempRect.x = startDragPosition.x + (newPos.x - blocks[dragWindowId]._NodeRect.position.x); tempRect.y = startDragPosition.y + (newPos.y - blocks[dragWindowId]._NodeRect.position.y); block._NodeRect = tempRect; Undo.RecordObject(block, "Node Position"); tempRect.x = newPos.x; tempRect.y = newPos.y; forceRepaintCount = 6; useEvent = true; endDrag = true; } } block._NodeRect = tempRect; } Rect windowRect = new Rect(block._NodeRect); windowRect.x += flowchart.ScrollPos.x; windowRect.y += flowchart.ScrollPos.y; GUILayout.Window(i, windowRect, DrawWindow, "", windowStyle); GUI.backgroundColor = Color.white; windowBlockMap.Add(block); } dragWindowId = endDrag ? -1 : dragWindowId; if (useEvent) { Event.current.Use(); } EndWindows(); // Draw Event Handler labels foreach (var block in blocks) { if (block._EventHandler != null) { string handlerLabel = ""; EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(block._EventHandler.GetType()); if (info != null) { handlerLabel = "<" + info.EventHandlerName + "> "; } GUIStyle handlerStyle = new GUIStyle(EditorStyles.whiteLabel); handlerStyle.wordWrap = true; handlerStyle.margin.top = 0; handlerStyle.margin.bottom = 0; handlerStyle.alignment = TextAnchor.MiddleCenter; Rect rect = new Rect(block._NodeRect); rect.height = handlerStyle.CalcHeight(new GUIContent(handlerLabel), block._NodeRect.width); rect.x += flowchart.ScrollPos.x; rect.y += flowchart.ScrollPos.y - rect.height; GUI.Label(rect, handlerLabel, handlerStyle); } } // Draw play icons beside all executing blocks if (Application.isPlaying) { foreach (var b in blocks) { if (b.IsExecuting()) { b.ExecutingIconTimer = Time.realtimeSinceStartup + FungusConstants.ExecutingIconFadeTime; b.ActiveCommand.ExecutingIconTimer = Time.realtimeSinceStartup + FungusConstants.ExecutingIconFadeTime; forceRepaintCount = 6; } if (b.ExecutingIconTimer > Time.realtimeSinceStartup) { Rect rect = new Rect(b._NodeRect); rect.x += flowchart.ScrollPos.x - 37; rect.y += flowchart.ScrollPos.y + 3; rect.width = 34; rect.height = 34; if (!b.IsExecuting()) { float alpha = (b.ExecutingIconTimer - Time.realtimeSinceStartup) / FungusConstants.ExecutingIconFadeTime; alpha = Mathf.Clamp01(alpha); GUI.color = new Color(1f, 1f, 1f, alpha); } if (GUI.Button(rect, FungusEditorResources.PlayBig, new GUIStyle())) { SelectBlock(flowchart, b); } GUI.color = Color.white; } } } PanAndZoom(flowchart); EditorZoomArea.End(); // Handle right click up outside of EditorZoomArea to avoid strange offsets if (Event.current.type == EventType.MouseUp && Event.current.button == 1 && rightClickDown != -Vector2.one && !mouseOverVariables) { var menu = new GenericMenu(); var mousePosition = rightClickDown; Block hitBlock = null; foreach (var block in blocks) { if (block._NodeRect.Contains(rightClickDown / flowchart.Zoom - flowchart.ScrollPos)) { hitBlock = block; break; } } // Clicked on a block if (hitBlock != null) { flowchart.AddSelectedBlock(hitBlock); // Use a copy because flowchart.SelectedBlocks gets modified var blockList = new List<Block>(flowchart.SelectedBlocks); menu.AddItem(new GUIContent ("Copy"), false, () => Copy(flowchart)); menu.AddItem(new GUIContent ("Cut"), false, () => Cut(flowchart)); menu.AddItem(new GUIContent ("Duplicate"), false, () => Duplicate(flowchart)); menu.AddItem(new GUIContent ("Delete"), false, DeleteBlocks, blockList); } // Clicked on empty space in grid else { DeselectAll(flowchart); menu.AddItem(new GUIContent("Add Block"), false, () => CreateBlock(flowchart, mousePosition / flowchart.Zoom - flowchart.ScrollPos)); if (copyList.Count > 0) { menu.AddItem(new GUIContent("Paste"), false, () => Paste(flowchart, mousePosition)); } else { menu.AddDisabledItem(new GUIContent("Paste")); } } var menuRect = new Rect(); menuRect.position = new Vector2(mousePosition.x, mousePosition.y - 12f); menu.DropDown(menuRect); Event.current.Use(); } // If event has yet to be used and user isn't multiselecting or panning, clear selection bool validModifier = Event.current.alt || GetAppendModifierDown(); if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && !validModifier) { DeselectAll(flowchart); } // Draw selection box if (startSelectionBoxPosition.x >= 0 && startSelectionBoxPosition.y >= 0) { GUI.Box(selectionBox, "", (GUIStyle) "SelectionRect"); forceRepaintCount = 6; } }
public static Block CreateBlock(Flowchart flowchart, Vector2 position) { Block newBlock = flowchart.CreateBlock(position); Undo.RegisterCreatedObjectUndo(newBlock, "New Block"); // Use AddSelected instead of Select for when multiple blocks are duplicated flowchart.AddSelectedBlock(newBlock); SetBlockForInspector(flowchart, newBlock); return newBlock; }