Browse Source

FlowchartWindow perf improvements

Only draw connections that are on screen
Limit repaint to when changes in block execution or previous execution happen rather forcing every frame
master
desktop-maesty/steve 6 years ago
parent
commit
4f37234f69
  1. 193
      Assets/Fungus/Scripts/Editor/FlowchartWindow.cs

193
Assets/Fungus/Scripts/Editor/FlowchartWindow.cs

@ -104,6 +104,74 @@ namespace Fungus.EditorUtils
internal Texture2D offTexture; internal Texture2D offTexture;
} }
/// <summary>
/// Helper class to maintain list of blocks that are currently executing when the game is running in editor
/// </summary>
protected class ExecutingBlocks
{
internal List<Block> areExecuting = new List<Block>(),
wereExecuting = new List<Block>(),
workspace = new List<Block>();
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<BlockCopy> copyList = new List<BlockCopy>(); protected List<BlockCopy> copyList = new List<BlockCopy>();
public static List<Block> deleteList = new List<Block>(); public static List<Block> deleteList = new List<Block>();
protected Vector2 startDragPosition; protected Vector2 startDragPosition;
@ -139,6 +207,7 @@ namespace Fungus.EditorUtils
private bool filterStale = true; private bool filterStale = true;
private bool wasControl; private bool wasControl;
private ExecutingBlocks executingBlocks = new ExecutingBlocks();
[MenuItem("Tools/Fungus/Flowchart Window")] [MenuItem("Tools/Fungus/Flowchart Window")]
static void Init() static void Init()
@ -164,6 +233,27 @@ namespace Fungus.EditorUtils
wantsMouseMove = true; // For hover selection in block search popup wantsMouseMove = true; // For hover selection in block search popup
UpdateBlockCollection(); 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() protected void UpdateBlockCollection()
@ -429,35 +519,35 @@ namespace Fungus.EditorUtils
mouseDownSelectionState.Clear(); 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(); flowchart = GetFlowchart();
if (flowchart == null)
{
GUILayout.Label("No Flowchart scene object selected");
return;
}
//target has changed, so clear the blockinspector //target has changed, so clear the blockinspector
if (flowchart != prevFlowchart) if (flowchart != prevFlowchart)
{ {
blockInspector = null; blockInspector = null;
prevFlowchart = flowchart; prevFlowchart = flowchart;
executingBlocks.ClearAll();
UpdateBlockCollection(); UpdateBlockCollection();
Repaint(); Repaint();
return; return true;
} }
return false;
DeleteBlocks(); }
////blocks = flowchart.GetComponents<Block>(); protected virtual void OnGUI()
//if (prevBlockCount != blocks.Length) {
// filterStale = true; // 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(); UpdateFilteredBlocks();
@ -1054,8 +1144,7 @@ namespace Fungus.EditorUtils
// Draw play icons beside all executing blocks // Draw play icons beside all executing blocks
if (Application.isPlaying) if (Application.isPlaying)
{ {
//greedy repaint for now var emptyStyle = new GUIStyle();
Repaint();
//cache these once as they can end up being called thousands of times per frame otherwise //cache these once as they can end up being called thousands of times per frame otherwise
var curRealTime = Time.realtimeSinceStartup; var curRealTime = Time.realtimeSinceStartup;
@ -1063,40 +1152,40 @@ namespace Fungus.EditorUtils
for (int i = 0; i < blocks.Length; ++i) for (int i = 0; i < blocks.Length; ++i)
{ {
var b = blocks[i]; var b = blocks[i];
var bIsExec = b.IsExecuting(); DrawExecutingBlockIcon(b,
if (bIsExec) scriptViewRect,
{ (b.ExecutingIconTimer - curRealTime) / FungusConstants.ExecutingIconFadeTime,
b.ExecutingIconTimer = fadeTimer; emptyStyle);
b.ActiveCommand.ExecutingIconTimer = fadeTimer; }
} GUI.color = Color.white;
}
if (b.ExecutingIconTimer > curRealTime) EditorZoomArea.End();
{ }
Rect rect = new Rect(b._NodeRect);
rect.x += flowchart.ScrollPos.x - 37; private void DrawExecutingBlockIcon(Block b, Rect scriptViewRect, float alpha, GUIStyle style)
rect.y += flowchart.ScrollPos.y + 3; {
rect.width = 34; if (alpha <= 0)
rect.height = 34; return;
if (!bIsExec) Rect rect = new Rect(b._NodeRect);
{
float alpha = (b.ExecutingIconTimer - curRealTime) / FungusConstants.ExecutingIconFadeTime;
alpha = Mathf.Clamp01(alpha);
GUI.color = new Color(1f, 1f, 1f, alpha);
}
if (GUI.Button(rect, FungusEditorResources.PlayBig, new GUIStyle())) rect.x += flowchart.ScrollPos.x - 37;
{ rect.y += flowchart.ScrollPos.y + 3;
SelectBlock(b); 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() private Rect CalcFlowchartWindowViewRect()
@ -1218,6 +1307,9 @@ namespace Fungus.EditorUtils
bool blockIsSelected = flowchart.SelectedBlock == block; bool blockIsSelected = flowchart.SelectedBlock == block;
Rect scriptViewRect = CalcFlowchartWindowViewRect();
var commandList = block.CommandList; var commandList = block.CommandList;
foreach (var command in commandList) foreach (var command in commandList)
{ {
@ -1259,7 +1351,14 @@ namespace Fungus.EditorUtils
endRect.x += flowchart.ScrollPos.x; endRect.x += flowchart.ScrollPos.x;
endRect.y += flowchart.ScrollPos.y; 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);
} }
} }
} }

Loading…
Cancel
Save