diff --git a/Assets/Fungus/Scripts/Editor/FlowchartWindow.cs b/Assets/Fungus/Scripts/Editor/FlowchartWindow.cs index acb78c14..0438749c 100644 --- a/Assets/Fungus/Scripts/Editor/FlowchartWindow.cs +++ b/Assets/Fungus/Scripts/Editor/FlowchartWindow.cs @@ -104,6 +104,74 @@ namespace Fungus.EditorUtils internal Texture2D offTexture; } + /// + /// Helper class to maintain list of blocks that are currently executing when the game is running in editor + /// + protected class ExecutingBlocks + { + internal List areExecuting = new List(), + wereExecuting = new List(), + workspace = new List(); + + internal bool isChangeDetected { get; set; } + + private float lastFade; + + internal void ProcessAllBlocks(Block[] blocks) + { + isChangeDetected = false; + workspace.Clear(); + //cache these once as they can end up being called thousands of times per frame otherwise + var curRealTime = Time.realtimeSinceStartup; + var fadeTimer = curRealTime + FungusConstants.ExecutingIconFadeTime; + for (int i = 0; i < blocks.Length; ++i) + { + var b = blocks[i]; + var bIsExec = b.IsExecuting(); + if (bIsExec) + { + b.ExecutingIconTimer = fadeTimer; + b.ActiveCommand.ExecutingIconTimer = fadeTimer; + workspace.Add(b); + } + } + + if(areExecuting.Count != workspace.Count || !WorkspaceMatchesExeucting()) + { + wereExecuting.Clear(); + wereExecuting.AddRange(areExecuting); + areExecuting.Clear(); + areExecuting.AddRange(workspace); + isChangeDetected = true; + lastFade = fadeTimer; + } + } + + internal bool WorkspaceMatchesExeucting() + { + for (int i = 0; i < areExecuting.Count; i++) + { + if (areExecuting[i] != workspace[i]) + return false; + } + return true; + } + + internal bool IsAnimFadeoutNeed() + { + return (lastFade - Time.realtimeSinceStartup) >= 0; + } + + internal void ClearAll() + { + areExecuting.Clear(); + wereExecuting.Clear(); + workspace.Clear(); + isChangeDetected = true; + lastFade = 0; + } + } + protected List copyList = new List(); public static List deleteList = new List(); protected Vector2 startDragPosition; @@ -139,6 +207,7 @@ namespace Fungus.EditorUtils private bool filterStale = true; private bool wasControl; + private ExecutingBlocks executingBlocks = new ExecutingBlocks(); [MenuItem("Tools/Fungus/Flowchart Window")] static void Init() @@ -164,6 +233,27 @@ namespace Fungus.EditorUtils wantsMouseMove = true; // For hover selection in block search popup UpdateBlockCollection(); + + + EditorApplication.update += OnEditorUpdate; + } + + + protected virtual void OnDisable() + { + EditorApplication.update -= OnEditorUpdate; + } + + void OnEditorUpdate() + { + HandleFlowchartSelectionChange(); + + if (Application.isPlaying) + { + executingBlocks.ProcessAllBlocks(blocks); + if (executingBlocks.isChangeDetected || executingBlocks.IsAnimFadeoutNeed()) + Repaint(); + } } protected void UpdateBlockCollection() @@ -429,35 +519,35 @@ namespace Fungus.EditorUtils mouseDownSelectionState.Clear(); } - protected virtual void OnGUI() + internal bool HandleFlowchartSelectionChange() { - // TODO: avoid calling some of these methods in OnGUI because it should be possible - // to only call them when the window is initialized or a new flowchart is selected, etc. flowchart = GetFlowchart(); - - if (flowchart == null) - { - GUILayout.Label("No Flowchart scene object selected"); - return; - } - //target has changed, so clear the blockinspector if (flowchart != prevFlowchart) { blockInspector = null; prevFlowchart = flowchart; + executingBlocks.ClearAll(); UpdateBlockCollection(); Repaint(); - return; + return true; } - - DeleteBlocks(); + return false; + } - ////blocks = flowchart.GetComponents(); - //if (prevBlockCount != blocks.Length) - // filterStale = true; + protected virtual void OnGUI() + { + // TODO: avoid calling some of these methods in OnGUI because it should be possible + // to only call them when the window is initialized or a new flowchart is selected, etc. + if (HandleFlowchartSelectionChange()) return; - //prevBlockCount = blocks.Length; + if (flowchart == null) + { + GUILayout.Label("No Flowchart scene object selected"); + return; + } + + DeleteBlocks(); UpdateFilteredBlocks(); @@ -1054,8 +1144,7 @@ namespace Fungus.EditorUtils // Draw play icons beside all executing blocks if (Application.isPlaying) { - //greedy repaint for now - Repaint(); + var emptyStyle = new GUIStyle(); //cache these once as they can end up being called thousands of times per frame otherwise var curRealTime = Time.realtimeSinceStartup; @@ -1063,40 +1152,40 @@ namespace Fungus.EditorUtils for (int i = 0; i < blocks.Length; ++i) { var b = blocks[i]; - var bIsExec = b.IsExecuting(); - if (bIsExec) - { - b.ExecutingIconTimer = fadeTimer; - b.ActiveCommand.ExecutingIconTimer = fadeTimer; - } + DrawExecutingBlockIcon(b, + scriptViewRect, + (b.ExecutingIconTimer - curRealTime) / FungusConstants.ExecutingIconFadeTime, + emptyStyle); + } + GUI.color = Color.white; + } - if (b.ExecutingIconTimer > curRealTime) - { - Rect rect = new Rect(b._NodeRect); + EditorZoomArea.End(); + } - rect.x += flowchart.ScrollPos.x - 37; - rect.y += flowchart.ScrollPos.y + 3; - rect.width = 34; - rect.height = 34; + private void DrawExecutingBlockIcon(Block b, Rect scriptViewRect, float alpha, GUIStyle style) + { + if (alpha <= 0) + return; - if (!bIsExec) - { - float alpha = (b.ExecutingIconTimer - curRealTime) / FungusConstants.ExecutingIconFadeTime; - alpha = Mathf.Clamp01(alpha); - GUI.color = new Color(1f, 1f, 1f, alpha); - } + Rect rect = new Rect(b._NodeRect); - if (GUI.Button(rect, FungusEditorResources.PlayBig, new GUIStyle())) - { - SelectBlock(b); - } + rect.x += flowchart.ScrollPos.x - 37; + rect.y += flowchart.ScrollPos.y + 3; + rect.width = 34; + rect.height = 34; - GUI.color = Color.white; - } + if (scriptViewRect.Overlaps(rect)) + { + GUI.color = new Color(1f, 1f, 1f, alpha); + + if (GUI.Button(rect, FungusEditorResources.PlayBig, style)) + { + SelectBlock(b); } - } - EditorZoomArea.End(); + GUI.color = Color.white; + } } private Rect CalcFlowchartWindowViewRect() @@ -1218,6 +1307,9 @@ namespace Fungus.EditorUtils bool blockIsSelected = flowchart.SelectedBlock == block; + + Rect scriptViewRect = CalcFlowchartWindowViewRect(); + var commandList = block.CommandList; foreach (var command in commandList) { @@ -1259,7 +1351,14 @@ namespace Fungus.EditorUtils endRect.x += flowchart.ScrollPos.x; endRect.y += flowchart.ScrollPos.y; - DrawRectConnection(startRect, endRect, highlight); + Rect boundRect = new Rect(); + boundRect.xMin = Mathf.Min(startRect.xMin, endRect.xMin); + boundRect.xMax = Mathf.Max(startRect.xMax, endRect.xMax); + boundRect.yMin = Mathf.Min(startRect.yMin, endRect.yMin); + boundRect.yMax = Mathf.Max(startRect.yMax, endRect.yMax); + + if (boundRect.Overlaps(scriptViewRect)) + DrawRectConnection(startRect, endRect, highlight); } } }