|
|
|
@ -36,9 +36,14 @@ namespace Fungus.EditorUtils
|
|
|
|
|
protected Texture2D addTexture; |
|
|
|
|
|
|
|
|
|
protected Rect selectionBox; |
|
|
|
|
protected Vector2 startSelectionBoxPosition = new Vector2(-1.0f, -1.0f); |
|
|
|
|
protected Vector2 startSelectionBoxPosition = -Vector2.one; |
|
|
|
|
protected List<Block> mouseDownSelectionState = new List<Block>(); |
|
|
|
|
|
|
|
|
|
// Context Click occurs on MouseDown which interferes with panning |
|
|
|
|
// Track right click positions manually to show menus on MouseUp |
|
|
|
|
protected Vector2 rightClickDown = -Vector2.one; |
|
|
|
|
protected readonly float rightClickTolerance = 5f; |
|
|
|
|
|
|
|
|
|
[MenuItem("Tools/Fungus/Flowchart Window")] |
|
|
|
|
static void Init() |
|
|
|
|
{ |
|
|
|
@ -156,6 +161,9 @@ namespace Fungus.EditorUtils
|
|
|
|
|
|
|
|
|
|
if (isSelected) |
|
|
|
|
{ |
|
|
|
|
// Deselect |
|
|
|
|
flowchart.SelectedBlocks.Remove(deleteBlock); |
|
|
|
|
|
|
|
|
|
// Revert to showing properties for the Flowchart |
|
|
|
|
Selection.activeGameObject = flowchart.gameObject; |
|
|
|
|
} |
|
|
|
@ -168,6 +176,9 @@ namespace Fungus.EditorUtils
|
|
|
|
|
// Handle selection box events after block and overlay events |
|
|
|
|
HandleSelectionBox(flowchart); |
|
|
|
|
|
|
|
|
|
ValidateCommands(flowchart); |
|
|
|
|
ExecuteCommands(flowchart); |
|
|
|
|
|
|
|
|
|
if (forceRepaintCount > 0) |
|
|
|
|
{ |
|
|
|
|
// Redraw on next frame to get crisp refresh rate |
|
|
|
@ -197,7 +208,10 @@ namespace Fungus.EditorUtils
|
|
|
|
|
); |
|
|
|
|
GUILayout.Label(flowchart.Zoom.ToString("0.0#x"), EditorStyles.miniLabel, GUILayout.Width(30)); |
|
|
|
|
|
|
|
|
|
DoZoom(flowchart, newZoom - flowchart.Zoom, Vector2.one * 0.5f); |
|
|
|
|
if (newZoom != flowchart.Zoom) |
|
|
|
|
{ |
|
|
|
|
DoZoom(flowchart, newZoom - flowchart.Zoom, Vector2.one * 0.5f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (GUILayout.Button("Center", EditorStyles.toolbarButton)) |
|
|
|
|
{ |
|
|
|
@ -288,6 +302,22 @@ namespace Fungus.EditorUtils
|
|
|
|
|
// 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); |
|
|
|
|
|
|
|
|
|
DrawGrid(flowchart); |
|
|
|
@ -296,7 +326,10 @@ namespace Fungus.EditorUtils
|
|
|
|
|
|
|
|
|
|
// 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. |
|
|
|
|
CalcFlowchartCenter(flowchart, blocks); |
|
|
|
|
if (flowchart != null && blocks.Length > 0) |
|
|
|
|
{ |
|
|
|
|
CalcFlowchartCenter(flowchart, blocks); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Draw connections |
|
|
|
|
foreach (var block in blocks) |
|
|
|
@ -456,14 +489,50 @@ namespace Fungus.EditorUtils
|
|
|
|
|
|
|
|
|
|
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 ("Duplicate"), false, DuplicateBlocks, blockList); |
|
|
|
|
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)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
Undo.RecordObject(flowchart, "Deselect"); |
|
|
|
|
flowchart.ClearSelectedCommands(); |
|
|
|
|
flowchart.ClearSelectedBlocks(); |
|
|
|
|
Selection.activeGameObject = flowchart.gameObject; |
|
|
|
|
DeselectAll(flowchart); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Draw selection box |
|
|
|
@ -474,12 +543,11 @@ namespace Fungus.EditorUtils
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public virtual void CalcFlowchartCenter(Flowchart flowchart, Block[] blocks) |
|
|
|
|
public virtual Vector2 GetBlockCenter(Flowchart flowchart, Block[] blocks) |
|
|
|
|
{ |
|
|
|
|
if (flowchart == null || |
|
|
|
|
blocks.Count() == 0) |
|
|
|
|
if (blocks.Length == 0) |
|
|
|
|
{ |
|
|
|
|
return; |
|
|
|
|
return Vector2.zero; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Vector2 min = blocks[0]._NodeRect.min; |
|
|
|
@ -493,8 +561,12 @@ namespace Fungus.EditorUtils
|
|
|
|
|
max.y = Mathf.Max(max.y, block._NodeRect.center.y); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Vector2 center = (min + max) * -0.5f; |
|
|
|
|
return (min + max) * 0.5f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public virtual void CalcFlowchartCenter(Flowchart flowchart, Block[] blocks) |
|
|
|
|
{ |
|
|
|
|
var center = -GetBlockCenter(flowchart, blocks); |
|
|
|
|
center.x += position.width * 0.5f / flowchart.Zoom; |
|
|
|
|
center.y += position.height * 0.5f / flowchart.Zoom; |
|
|
|
|
|
|
|
|
@ -559,7 +631,7 @@ namespace Fungus.EditorUtils
|
|
|
|
|
if (Event.current.rawType == EventType.MouseUp) |
|
|
|
|
{ |
|
|
|
|
selectionBox.size = Vector2.zero; |
|
|
|
|
selectionBox.position = Vector2.one * -1; |
|
|
|
|
selectionBox.position = -Vector2.one; |
|
|
|
|
startSelectionBoxPosition = selectionBox.position; |
|
|
|
|
|
|
|
|
|
var tempList = new List<Block>(flowchart.SelectedBlocks); |
|
|
|
@ -689,6 +761,14 @@ namespace Fungus.EditorUtils
|
|
|
|
|
SetBlockForInspector(flowchart, block); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual void DeselectAll(Flowchart flowchart) |
|
|
|
|
{ |
|
|
|
|
Undo.RecordObject(flowchart, "Deselect"); |
|
|
|
|
flowchart.ClearSelectedCommands(); |
|
|
|
|
flowchart.ClearSelectedBlocks(); |
|
|
|
|
Selection.activeGameObject = flowchart.gameObject; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static Block CreateBlock(Flowchart flowchart, Vector2 position) |
|
|
|
|
{ |
|
|
|
|
Block newBlock = flowchart.CreateBlock(position); |
|
|
|
@ -701,18 +781,6 @@ namespace Fungus.EditorUtils
|
|
|
|
|
return newBlock; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual void DeleteBlock(Flowchart flowchart, Block block) |
|
|
|
|
{ |
|
|
|
|
var commandList = block.CommandList; |
|
|
|
|
foreach (var command in commandList) |
|
|
|
|
{ |
|
|
|
|
Undo.DestroyObjectImmediate(command); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Undo.DestroyObjectImmediate((Block)block); |
|
|
|
|
flowchart.ClearSelectedCommands(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual void DrawWindow(int windowId) |
|
|
|
|
{ |
|
|
|
|
var block = windowBlockMap[windowId]; |
|
|
|
@ -854,20 +922,6 @@ namespace Fungus.EditorUtils
|
|
|
|
|
descriptionStyle.wordWrap = true; |
|
|
|
|
GUILayout.Label(block.Description, descriptionStyle); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (Event.current.type == EventType.ContextClick) |
|
|
|
|
{ |
|
|
|
|
flowchart.AddSelectedBlock(block); |
|
|
|
|
|
|
|
|
|
GenericMenu menu = new GenericMenu (); |
|
|
|
|
|
|
|
|
|
// Use a copy because flowchart.SelectedBlocks gets modified |
|
|
|
|
var blockList = new List<Block>(flowchart.SelectedBlocks); |
|
|
|
|
menu.AddItem(new GUIContent ("Duplicate"), false, DuplicateBlocks, blockList); |
|
|
|
|
menu.AddItem(new GUIContent ("Delete"), false, DeleteBlocks, blockList); |
|
|
|
|
|
|
|
|
|
menu.ShowAsContext(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual void DrawConnections(Flowchart flowchart, Block block, bool highlightedOnly) |
|
|
|
@ -989,6 +1043,11 @@ namespace Fungus.EditorUtils
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected static void DuplicateBlocks(object obj) |
|
|
|
|
{ |
|
|
|
|
DuplicateBlocks(obj, new Vector2(20, 0)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected static void DuplicateBlocks(object obj, Vector2 offset) |
|
|
|
|
{ |
|
|
|
|
var flowchart = GetFlowchart(); |
|
|
|
|
|
|
|
|
@ -999,9 +1058,7 @@ namespace Fungus.EditorUtils
|
|
|
|
|
|
|
|
|
|
foreach (var block in blocks) |
|
|
|
|
{ |
|
|
|
|
Vector2 newPosition = new Vector2(block._NodeRect.position.x + |
|
|
|
|
block._NodeRect.width + 20, |
|
|
|
|
block._NodeRect.y); |
|
|
|
|
Vector2 newPosition = block._NodeRect.position + offset; |
|
|
|
|
|
|
|
|
|
Block oldBlock = block; |
|
|
|
|
|
|
|
|
@ -1087,9 +1144,57 @@ namespace Fungus.EditorUtils
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual bool GetAppendModifierDown() |
|
|
|
|
protected virtual bool GetAppendModifierDown() |
|
|
|
|
{ |
|
|
|
|
return Event.current.shift || EditorGUI.actionKey; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual void ValidateCommands(Flowchart flowchart) |
|
|
|
|
{ |
|
|
|
|
if (Event.current.type == EventType.ValidateCommand) |
|
|
|
|
{ |
|
|
|
|
var c = Event.current.commandName; |
|
|
|
|
if (c == "Delete" || c == "Duplicate") |
|
|
|
|
{ |
|
|
|
|
if (flowchart.SelectedBlocks.Count > 0) |
|
|
|
|
{ |
|
|
|
|
Event.current.Use(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (c == "SelectAll") |
|
|
|
|
{ |
|
|
|
|
Event.current.Use(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected virtual void ExecuteCommands(Flowchart flowchart) |
|
|
|
|
{ |
|
|
|
|
if (Event.current.type == EventType.ExecuteCommand) |
|
|
|
|
{ |
|
|
|
|
switch (Event.current.commandName) |
|
|
|
|
{ |
|
|
|
|
case "Delete": |
|
|
|
|
DeleteBlocks(flowchart.SelectedBlocks); |
|
|
|
|
Event.current.Use(); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case "Duplicate": |
|
|
|
|
DuplicateBlocks(new List<Block>(flowchart.SelectedBlocks)); |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |