Browse Source

Display UnityEvent properties

CommandEditors are now only created / destroyed when needed instead of
every frame (much more efficient too).
Workarounds for compatibility issues with ReorderableList and
UnityEvent rendering. Selection rectangle now obscures the built-in
grabber on reorderable list and shift selection changes now happen on
next frame instead of immediately.

As a side effect, the shift selection logic is now more straightforward.
master
chrisgregan 10 years ago
parent
commit
74483ec24a
  1. 68
      Assets/Fungus/Flowchart/Editor/BlockInspector.cs
  2. 131
      Assets/Fungus/Flowchart/Editor/CommandListAdaptor.cs

68
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<Command, CommandEditor> cachedCommandEditors = new Dictionary<Command, CommandEditor>();
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)

131
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)
}

Loading…
Cancel
Save