diff --git a/Assets/Fungus/Flowchart/Editor/BlockInspector.cs b/Assets/Fungus/Flowchart/Editor/BlockInspector.cs index d40b1186..0f1f180f 100644 --- a/Assets/Fungus/Flowchart/Editor/BlockInspector.cs +++ b/Assets/Fungus/Flowchart/Editor/BlockInspector.cs @@ -2,6 +2,7 @@ using UnityEngine; using UnityEngine.Serialization; using UnityEditor; using System.Collections; +using System.Collections.Generic; namespace Fungus { @@ -26,6 +27,23 @@ namespace Fungus protected bool resize = false; protected float topPanelHeight = 50; + // Cache the block and command editors so we only create and destroy them + // when a different block / command is selected. + protected BlockEditor activeBlockEditor; + protected CommandEditor activeCommandEditor; + protected Command activeCommand; // Command currently being inspected + + // Cached command editors to avoid creating / destroying editors more than necessary + protected Dictionary cachedCommandEditors = new Dictionary(); + + protected void OnDisable() + { + foreach (CommandEditor commandEditor in cachedCommandEditors.Values) + { + DestroyImmediate(commandEditor); + } + } + public override void OnInspectorGUI () { BlockInspector blockInspector = target as BlockInspector; @@ -38,15 +56,21 @@ namespace Fungus Flowchart flowchart = block.GetFlowchart(); - BlockEditor blockEditor = Editor.CreateEditor(block) as BlockEditor; - blockEditor.DrawBlockName(flowchart); + if (activeBlockEditor == null || + block != activeBlockEditor.target) + { + DestroyImmediate(activeBlockEditor); + activeBlockEditor = Editor.CreateEditor(block) as BlockEditor; + } + + activeBlockEditor.DrawBlockName(flowchart); // Using a custom rect area to get the correct 5px indent for the scroll views Rect blockRect = new Rect(5, topPanelHeight, Screen.width - 6, Screen.height - 70); GUILayout.BeginArea(blockRect); blockScrollPos = GUILayout.BeginScrollView(blockScrollPos, GUILayout.Height(flowchart.blockViewHeight)); - blockEditor.DrawBlockGUI(flowchart); + activeBlockEditor.DrawBlockGUI(flowchart); GUILayout.EndScrollView(); Command inspectCommand = null; @@ -61,23 +85,49 @@ namespace Fungus { GUILayout.EndArea(); Repaint(); - DestroyImmediate(blockEditor); return; } + // Only change the activeCommand at the start of the GUI call sequence + if (Event.current.type == EventType.Layout) + { + activeCommand = inspectCommand; + } + + DrawCommandUI(flowchart, inspectCommand); + } + + public void DrawCommandUI(Flowchart flowchart, Command inspectCommand) + { ResizeScrollView(flowchart); GUILayout.Space(7); - blockEditor.DrawButtonToolbar(); + activeBlockEditor.DrawButtonToolbar(); commandScrollPos = GUILayout.BeginScrollView(commandScrollPos); if (inspectCommand != null) { - CommandEditor commandEditor = Editor.CreateEditor(inspectCommand) as CommandEditor; - commandEditor.DrawCommandInspectorGUI(); - DestroyImmediate(commandEditor); + if (activeCommandEditor == null || + inspectCommand != activeCommandEditor.target) + { + // See if we have a cached version of the command editor already, + // if not then create a new one. + if (cachedCommandEditors.ContainsKey(inspectCommand)) + { + activeCommandEditor = cachedCommandEditors[inspectCommand]; + } + else + { + activeCommandEditor = Editor.CreateEditor(inspectCommand) as CommandEditor; + cachedCommandEditors[inspectCommand] = activeCommandEditor; + } + } + if (activeCommandEditor != null) + { + activeCommandEditor.DrawCommandInspectorGUI(); + } } GUILayout.EndScrollView(); @@ -97,8 +147,6 @@ namespace Fungus GUI.color = Color.white; Repaint(); - - DestroyImmediate(blockEditor); } private void ResizeScrollView(Flowchart flowchart) diff --git a/Assets/Fungus/Flowchart/Editor/CommandListAdaptor.cs b/Assets/Fungus/Flowchart/Editor/CommandListAdaptor.cs index fee4bb6b..39217fe6 100644 --- a/Assets/Fungus/Flowchart/Editor/CommandListAdaptor.cs +++ b/Assets/Fungus/Flowchart/Editor/CommandListAdaptor.cs @@ -18,11 +18,7 @@ namespace Fungus public float fixedItemHeight; public Rect nodeRect = new Rect(); - - public static bool pinShiftToTop; - public static int firstSelectedIndex = 0; - public static int lastSelectedIndex = 0; - + public SerializedProperty this[int index] { get { return _arrayProperty.GetArrayElementAtIndex(index); } } @@ -247,11 +243,20 @@ namespace Fungus commandLabelRect.y -= 2; commandLabelRect.width -= (indentSize * command.indentLevel - 22); commandLabelRect.height += 5; - + + // There's a weird incompatibility between the Reorderable list control used for the command list and + // the UnityEvent list control used in some commands. In play mode, if you click on the reordering grabber + // for a command in the list it causes the UnityEvent list to spew null exception errors. + // The workaround for now is to hide the reordering grabber from mouse clicks by extending the command + // selection rectangle to cover it. We are planning to totally replace the command list display system. + Rect clickRect = position; + clickRect.x -= 20; + clickRect.width += 20; + // Select command via left click if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && - position.Contains(Event.current.mousePosition)) + clickRect.Contains(Event.current.mousePosition)) { if (flowchart.selectedCommands.Contains(command) && Event.current.button == 0) { @@ -259,84 +264,104 @@ namespace Fungus // Command key and shift key is not pressed if (!EditorGUI.actionKey && !Event.current.shift) { - flowchart.selectedCommands.Remove(command); - flowchart.ClearSelectedCommands(); + BlockEditor.actionList.Add ( delegate { + flowchart.selectedCommands.Remove(command); + flowchart.ClearSelectedCommands(); + }); } // Command key pressed if (EditorGUI.actionKey) { - flowchart.selectedCommands.Remove(command); - } - // Shift key pressed - if (Event.current.shift) - { - flowchart.ClearSelectedCommands(); - if (pinShiftToTop) - { - for (int i = firstSelectedIndex; i < index+1; ++i) - { - flowchart.AddSelectedCommand(flowchart.selectedBlock.commandList[i]); - } - } - else - { - for (int i = index; i < lastSelectedIndex+1; ++i) - { - flowchart.AddSelectedCommand(flowchart.selectedBlock.commandList[i]); - } - } + BlockEditor.actionList.Add ( delegate { + flowchart.selectedCommands.Remove(command); + }); + Event.current.Use(); } } else { + bool shift = Event.current.shift; + // Left click and no command key - if (!Event.current.shift && !EditorGUI.actionKey && Event.current.button == 0) + if (!shift && !EditorGUI.actionKey && Event.current.button == 0) { - flowchart.ClearSelectedCommands(); + BlockEditor.actionList.Add ( delegate { + flowchart.ClearSelectedCommands(); + }); + Event.current.Use(); } - flowchart.AddSelectedCommand(command); - - bool firstSelectedCommandFound = false; + + BlockEditor.actionList.Add ( delegate { + flowchart.AddSelectedCommand(command); + }); + + // Find first and last selected commands + int firstSelectedIndex = -1; + int lastSelectedIndex = -1; if (flowchart.selectedCommands.Count > 0) { if ( flowchart.selectedBlock != null) { for (int i = 0; i < flowchart.selectedBlock.commandList.Count; i++) { - Command commandInBlock = flowchart.selectedBlock.commandList[i]; - + Command commandInBlock = flowchart.selectedBlock.commandList[i]; + foreach (Command selectedCommand in flowchart.selectedCommands) + { + if (commandInBlock == selectedCommand) + { + firstSelectedIndex = i; + break; + } + } + } + for (int i = flowchart.selectedBlock.commandList.Count - 1; i >=0; i--) + { + Command commandInBlock = flowchart.selectedBlock.commandList[i]; foreach (Command selectedCommand in flowchart.selectedCommands) { if (commandInBlock == selectedCommand) { - if (!firstSelectedCommandFound) - { - firstSelectedIndex = i; - firstSelectedCommandFound = true; - } lastSelectedIndex = i; + break; } } } } } - - if (Event.current.shift) + + if (shift) { - for (int i = firstSelectedIndex; i < lastSelectedIndex; ++i) + int currentIndex = command.commandIndex; + if (firstSelectedIndex == -1 || + lastSelectedIndex == -1) { - flowchart.AddSelectedCommand(flowchart.selectedBlock.commandList[i]); + // No selected command found - select entire list + firstSelectedIndex = 0; + lastSelectedIndex = currentIndex; + } + else + { + if (currentIndex < firstSelectedIndex) + { + firstSelectedIndex = currentIndex; + } + if (currentIndex > lastSelectedIndex) + { + lastSelectedIndex = currentIndex; + } + } + + for (int i = Math.Min(firstSelectedIndex, lastSelectedIndex); i < Math.Max(firstSelectedIndex, lastSelectedIndex); ++i) + { + Command selectedCommand = flowchart.selectedBlock.commandList[i]; + BlockEditor.actionList.Add ( delegate { + flowchart.AddSelectedCommand(selectedCommand); + }); } } - if (index == firstSelectedIndex) - { - pinShiftToTop = false; - } - else if (index == lastSelectedIndex) - { - pinShiftToTop = true; - } + + Event.current.Use(); } GUIUtility.keyboardControl = 0; // Fix for textarea not refeshing (change focus) }