|
|
|
using UnityEditor;
|
|
|
|
using UnityEditorInternal;
|
|
|
|
using UnityEngine;
|
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using Rotorz.ReorderableList;
|
|
|
|
|
|
|
|
namespace Fungus
|
|
|
|
{
|
|
|
|
|
|
|
|
[CustomEditor (typeof(Sequence))]
|
|
|
|
public class SequenceEditor : Editor
|
|
|
|
{
|
|
|
|
protected class SetEventHandlerOperation
|
|
|
|
{
|
|
|
|
public Sequence sequence;
|
|
|
|
public Type eventHandlerType;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected class AddCommandOperation
|
|
|
|
{
|
|
|
|
public Sequence sequence;
|
|
|
|
public Type commandType;
|
|
|
|
public int index;
|
|
|
|
}
|
|
|
|
|
|
|
|
public virtual void DrawSequenceName(FungusScript fungusScript)
|
|
|
|
{
|
|
|
|
serializedObject.Update();
|
|
|
|
|
|
|
|
SerializedProperty sequenceNameProperty = serializedObject.FindProperty("sequenceName");
|
|
|
|
Rect sequenceLabelRect = new Rect(45, 5, 120, 16);
|
|
|
|
EditorGUI.LabelField(sequenceLabelRect, new GUIContent("Sequence Name"));
|
|
|
|
Rect sequenceNameRect = new Rect(45, 21, 180, 16);
|
|
|
|
EditorGUI.PropertyField(sequenceNameRect, sequenceNameProperty, new GUIContent(""));
|
|
|
|
|
|
|
|
// Ensure sequence name is unique for this Fungus Script
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
string uniqueName = fungusScript.GetUniqueSequenceKey(sequenceNameProperty.stringValue, sequence);
|
|
|
|
if (uniqueName != sequence.sequenceName)
|
|
|
|
{
|
|
|
|
sequenceNameProperty.stringValue = uniqueName;
|
|
|
|
}
|
|
|
|
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
}
|
|
|
|
|
|
|
|
public virtual void DrawSequenceGUI(FungusScript fungusScript)
|
|
|
|
{
|
|
|
|
serializedObject.Update();
|
|
|
|
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
|
|
|
|
SerializedProperty commandListProperty = serializedObject.FindProperty("commandList");
|
|
|
|
|
|
|
|
if (sequence == fungusScript.selectedSequence)
|
|
|
|
{
|
|
|
|
SerializedProperty descriptionProp = serializedObject.FindProperty("description");
|
|
|
|
EditorGUILayout.PropertyField(descriptionProp);
|
|
|
|
|
|
|
|
SerializedProperty runSlowInEditorProp = serializedObject.FindProperty("runSlowInEditor");
|
|
|
|
EditorGUILayout.PropertyField(runSlowInEditorProp);
|
|
|
|
|
|
|
|
DrawEventHandlerGUI(fungusScript);
|
|
|
|
|
|
|
|
UpdateIndentLevels(sequence);
|
|
|
|
|
|
|
|
// Make sure each command has a reference to its parent sequence
|
|
|
|
foreach (Command command in sequence.commandList)
|
|
|
|
{
|
|
|
|
if (command == null) // Will be deleted from the list later on
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
command.parentSequence = sequence;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReorderableListGUI.Title("Commands");
|
|
|
|
CommandListAdaptor adaptor = new CommandListAdaptor(commandListProperty, 0);
|
|
|
|
adaptor.nodeRect = sequence.nodeRect;
|
|
|
|
|
|
|
|
ReorderableListFlags flags = ReorderableListFlags.HideAddButton | ReorderableListFlags.HideRemoveButtons | ReorderableListFlags.DisableContextMenu;
|
|
|
|
|
|
|
|
ReorderableListControl.DrawControlFromState(adaptor, null, flags);
|
|
|
|
|
|
|
|
if (Event.current.type == EventType.ContextClick)
|
|
|
|
{
|
|
|
|
ShowContextMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GUIUtility.keyboardControl == 0) //Only call keyboard shortcuts when not typing in a text field
|
|
|
|
{
|
|
|
|
Event e = Event.current;
|
|
|
|
|
|
|
|
// Copy keyboard shortcut
|
|
|
|
if (e.type == EventType.ValidateCommand && e.commandName == "Copy")
|
|
|
|
{
|
|
|
|
if (fungusScript.selectedCommands.Count > 0)
|
|
|
|
{
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.type == EventType.ExecuteCommand && e.commandName == "Copy")
|
|
|
|
{
|
|
|
|
Copy();
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cut keyboard shortcut
|
|
|
|
if (e.type == EventType.ValidateCommand && e.commandName == "Cut")
|
|
|
|
{
|
|
|
|
if (fungusScript.selectedCommands.Count > 0)
|
|
|
|
{
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.type == EventType.ExecuteCommand && e.commandName == "Cut")
|
|
|
|
{
|
|
|
|
Cut();
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Paste keyboard shortcut
|
|
|
|
if (e.type == EventType.ValidateCommand && e.commandName == "Paste")
|
|
|
|
{
|
|
|
|
CommandCopyBuffer commandCopyBuffer = CommandCopyBuffer.GetInstance();
|
|
|
|
if (commandCopyBuffer.HasCommands())
|
|
|
|
{
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.type == EventType.ExecuteCommand && e.commandName == "Paste")
|
|
|
|
{
|
|
|
|
Paste();
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Duplicate keyboard shortcut
|
|
|
|
if (e.type == EventType.ValidateCommand && e.commandName == "Duplicate")
|
|
|
|
{
|
|
|
|
if (fungusScript.selectedCommands.Count > 0)
|
|
|
|
{
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.type == EventType.ExecuteCommand && e.commandName == "Duplicate")
|
|
|
|
{
|
|
|
|
Copy();
|
|
|
|
Paste();
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete keyboard shortcut
|
|
|
|
if (e.type == EventType.ValidateCommand && e.commandName == "Delete")
|
|
|
|
{
|
|
|
|
if (fungusScript.selectedCommands.Count > 0)
|
|
|
|
{
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.type == EventType.ExecuteCommand && e.commandName == "Delete")
|
|
|
|
{
|
|
|
|
Delete();
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
|
|
|
|
// SelectAll keyboard shortcut
|
|
|
|
if (e.type == EventType.ValidateCommand && e.commandName == "SelectAll")
|
|
|
|
{
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.type == EventType.ExecuteCommand && e.commandName == "SelectAll")
|
|
|
|
{
|
|
|
|
SelectAll();
|
|
|
|
e.Use();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove any null entries in the command list.
|
|
|
|
// This can happen when a command class is deleted or renamed.
|
|
|
|
for (int i = commandListProperty.arraySize - 1; i >= 0; --i)
|
|
|
|
{
|
|
|
|
SerializedProperty commandProperty = commandListProperty.GetArrayElementAtIndex(i);
|
|
|
|
if (commandProperty.objectReferenceValue == null)
|
|
|
|
{
|
|
|
|
commandListProperty.DeleteArrayElementAtIndex(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
}
|
|
|
|
|
|
|
|
public virtual void DrawButtonToolbar()
|
|
|
|
{
|
|
|
|
GUILayout.BeginHorizontal();
|
|
|
|
|
|
|
|
// Previous Command
|
|
|
|
if ((Event.current.type == EventType.keyDown) && (Event.current.keyCode == KeyCode.PageUp))
|
|
|
|
{
|
|
|
|
SelectPrevious();
|
|
|
|
GUI.FocusControl("dummycontrol");
|
|
|
|
Event.current.Use();
|
|
|
|
}
|
|
|
|
// Next Command
|
|
|
|
if ((Event.current.type == EventType.keyDown) && (Event.current.keyCode == KeyCode.PageDown))
|
|
|
|
{
|
|
|
|
SelectNext();
|
|
|
|
GUI.FocusControl("dummycontrol");
|
|
|
|
Event.current.Use();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Up Button
|
|
|
|
Texture2D upIcon = Resources.Load("Icons/up") as Texture2D;
|
|
|
|
if (GUILayout.Button(upIcon))
|
|
|
|
{
|
|
|
|
SelectPrevious();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Down Button
|
|
|
|
Texture2D downIcon = Resources.Load("Icons/down") as Texture2D;
|
|
|
|
if (GUILayout.Button(downIcon))
|
|
|
|
{
|
|
|
|
SelectNext();
|
|
|
|
}
|
|
|
|
|
|
|
|
GUILayout.FlexibleSpace();
|
|
|
|
|
|
|
|
// Add Button
|
|
|
|
Texture2D addIcon = Resources.Load("Icons/add") as Texture2D;
|
|
|
|
if (GUILayout.Button(addIcon))
|
|
|
|
{
|
|
|
|
ShowCommandMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Duplicate Button
|
|
|
|
Texture2D duplicateIcon = Resources.Load("Icons/duplicate") as Texture2D;
|
|
|
|
if (GUILayout.Button(duplicateIcon))
|
|
|
|
{
|
|
|
|
Copy();
|
|
|
|
Paste();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete Button
|
|
|
|
Texture2D deleteIcon = Resources.Load("Icons/delete") as Texture2D;
|
|
|
|
if (GUILayout.Button(deleteIcon))
|
|
|
|
{
|
|
|
|
Delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
GUILayout.EndHorizontal();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void DrawEventHandlerGUI(FungusScript fungusScript)
|
|
|
|
{
|
|
|
|
// Show available Event Handlers in a drop down list with type of current
|
|
|
|
// event handler selected.
|
|
|
|
List<System.Type> eventHandlerTypes = EditorExtensions.FindDerivedTypes(typeof(EventHandler)).ToList();
|
|
|
|
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
System.Type currentType = null;
|
|
|
|
if (sequence.eventHandler != null)
|
|
|
|
{
|
|
|
|
currentType = sequence.eventHandler.GetType();
|
|
|
|
}
|
|
|
|
|
|
|
|
string currentHandlerName = "<None>";
|
|
|
|
if (currentType != null)
|
|
|
|
{
|
|
|
|
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(currentType);
|
|
|
|
currentHandlerName = info.EventHandlerName;
|
|
|
|
}
|
|
|
|
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
|
|
EditorGUILayout.PrefixLabel(new GUIContent("Execute On Event"));
|
|
|
|
if (GUILayout.Button(new GUIContent(currentHandlerName), EditorStyles.popup))
|
|
|
|
{
|
|
|
|
SetEventHandlerOperation noneOperation = new SetEventHandlerOperation();
|
|
|
|
noneOperation.sequence = sequence;
|
|
|
|
noneOperation.eventHandlerType = null;
|
|
|
|
|
|
|
|
GenericMenu eventHandlerMenu = new GenericMenu();
|
|
|
|
eventHandlerMenu.AddItem(new GUIContent("None"), false, OnSelectEventHandler, noneOperation);
|
|
|
|
|
|
|
|
// Add event handlers with no category first
|
|
|
|
foreach (System.Type type in eventHandlerTypes)
|
|
|
|
{
|
|
|
|
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(type);
|
|
|
|
if (info.Category.Length == 0)
|
|
|
|
{
|
|
|
|
SetEventHandlerOperation operation = new SetEventHandlerOperation();
|
|
|
|
operation.sequence = sequence;
|
|
|
|
operation.eventHandlerType = type;
|
|
|
|
|
|
|
|
eventHandlerMenu.AddItem(new GUIContent(info.EventHandlerName), false, OnSelectEventHandler, operation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add event handlers with a category afterwards
|
|
|
|
foreach (System.Type type in eventHandlerTypes)
|
|
|
|
{
|
|
|
|
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(type);
|
|
|
|
if (info.Category.Length > 0)
|
|
|
|
{
|
|
|
|
SetEventHandlerOperation operation = new SetEventHandlerOperation();
|
|
|
|
operation.sequence = sequence;
|
|
|
|
operation.eventHandlerType = type;
|
|
|
|
string typeName = info.Category + "/" + info.EventHandlerName;
|
|
|
|
eventHandlerMenu.AddItem(new GUIContent(typeName), false, OnSelectEventHandler, operation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
eventHandlerMenu.ShowAsContext();
|
|
|
|
}
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
|
|
|
|
if (sequence.eventHandler != null)
|
|
|
|
{
|
|
|
|
EventHandlerEditor eventHandlerEditor = Editor.CreateEditor(sequence.eventHandler) as EventHandlerEditor;
|
|
|
|
eventHandlerEditor.DrawInspectorGUI();
|
|
|
|
DestroyImmediate(eventHandlerEditor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void OnSelectEventHandler(object obj)
|
|
|
|
{
|
|
|
|
SetEventHandlerOperation operation = obj as SetEventHandlerOperation;
|
|
|
|
Sequence sequence = operation.sequence;
|
|
|
|
System.Type selectedType = operation.eventHandlerType;
|
|
|
|
if (sequence == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Undo.RecordObject(sequence, "Set Start Event");
|
|
|
|
|
|
|
|
if (sequence.eventHandler != null)
|
|
|
|
{
|
|
|
|
Undo.DestroyObjectImmediate(sequence.eventHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selectedType != null)
|
|
|
|
{
|
|
|
|
EventHandler newHandler = Undo.AddComponent(sequence.gameObject, selectedType) as EventHandler;
|
|
|
|
newHandler.parentSequence = sequence;
|
|
|
|
sequence.eventHandler = newHandler;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual void UpdateIndentLevels(Sequence sequence)
|
|
|
|
{
|
|
|
|
int indentLevel = 0;
|
|
|
|
foreach(Command command in sequence.commandList)
|
|
|
|
{
|
|
|
|
if (command == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (command.CloseBlock())
|
|
|
|
{
|
|
|
|
indentLevel--;
|
|
|
|
}
|
|
|
|
command.indentLevel = Math.Max(indentLevel, 0);
|
|
|
|
|
|
|
|
if (command.OpenBlock())
|
|
|
|
{
|
|
|
|
indentLevel++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static public void SequenceField(SerializedProperty property, GUIContent label, GUIContent nullLabel, FungusScript fungusScript)
|
|
|
|
{
|
|
|
|
if (fungusScript == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sequence sequence = property.objectReferenceValue as Sequence;
|
|
|
|
|
|
|
|
// Build dictionary of child sequences
|
|
|
|
List<GUIContent> sequenceNames = new List<GUIContent>();
|
|
|
|
|
|
|
|
int selectedIndex = 0;
|
|
|
|
sequenceNames.Add(nullLabel);
|
|
|
|
Sequence[] sequences = fungusScript.GetComponentsInChildren<Sequence>(true);
|
|
|
|
for (int i = 0; i < sequences.Length; ++i)
|
|
|
|
{
|
|
|
|
sequenceNames.Add(new GUIContent(sequences[i].sequenceName));
|
|
|
|
|
|
|
|
if (sequence == sequences[i])
|
|
|
|
{
|
|
|
|
selectedIndex = i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
selectedIndex = EditorGUILayout.Popup(label, selectedIndex, sequenceNames.ToArray());
|
|
|
|
if (selectedIndex == 0)
|
|
|
|
{
|
|
|
|
sequence = null; // Option 'None'
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sequence = sequences[selectedIndex - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
property.objectReferenceValue = sequence;
|
|
|
|
}
|
|
|
|
|
|
|
|
static public Sequence SequenceField(Rect position, GUIContent nullLabel, FungusScript fungusScript, Sequence sequence)
|
|
|
|
{
|
|
|
|
if (fungusScript == null)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sequence result = sequence;
|
|
|
|
|
|
|
|
// Build dictionary of child sequences
|
|
|
|
List<GUIContent> sequenceNames = new List<GUIContent>();
|
|
|
|
|
|
|
|
int selectedIndex = 0;
|
|
|
|
sequenceNames.Add(nullLabel);
|
|
|
|
Sequence[] sequences = fungusScript.GetComponentsInChildren<Sequence>();
|
|
|
|
for (int i = 0; i < sequences.Length; ++i)
|
|
|
|
{
|
|
|
|
sequenceNames.Add(new GUIContent(sequences[i].name));
|
|
|
|
|
|
|
|
if (sequence == sequences[i])
|
|
|
|
{
|
|
|
|
selectedIndex = i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
selectedIndex = EditorGUI.Popup(position, selectedIndex, sequenceNames.ToArray());
|
|
|
|
if (selectedIndex == 0)
|
|
|
|
{
|
|
|
|
result = null; // Option 'None'
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = sequences[selectedIndex - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compare delegate for sorting the list of command attributes
|
|
|
|
protected static int CompareCommandAttributes(KeyValuePair<System.Type, CommandInfoAttribute> x, KeyValuePair<System.Type, CommandInfoAttribute> y)
|
|
|
|
{
|
|
|
|
int compare = (x.Value.Category.CompareTo(y.Value.Category));
|
|
|
|
if (compare == 0)
|
|
|
|
{
|
|
|
|
compare = (x.Value.CommandName.CompareTo(y.Value.CommandName));
|
|
|
|
}
|
|
|
|
return compare;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShowCommandMenu()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
// Use index of last selected command in list, or end of list if nothing selected.
|
|
|
|
int index = -1;
|
|
|
|
foreach (Command command in fungusScript.selectedCommands)
|
|
|
|
{
|
|
|
|
if (command.commandIndex + 1 > index)
|
|
|
|
{
|
|
|
|
index = command.commandIndex + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (index == -1)
|
|
|
|
{
|
|
|
|
index = sequence.commandList.Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
GenericMenu commandMenu = new GenericMenu();
|
|
|
|
|
|
|
|
// Build menu list
|
|
|
|
List<System.Type> menuTypes = EditorExtensions.FindDerivedTypes(typeof(Command)).ToList();
|
|
|
|
List<KeyValuePair<System.Type, CommandInfoAttribute>> filteredAttributes = GetFilteredCommandInfoAttribute(menuTypes);
|
|
|
|
|
|
|
|
filteredAttributes.Sort( CompareCommandAttributes );
|
|
|
|
|
|
|
|
foreach(var keyPair in filteredAttributes)
|
|
|
|
{
|
|
|
|
AddCommandOperation commandOperation = new AddCommandOperation();
|
|
|
|
|
|
|
|
commandOperation.sequence = sequence;
|
|
|
|
commandOperation.commandType = keyPair.Key;
|
|
|
|
commandOperation.index = index;
|
|
|
|
|
|
|
|
GUIContent menuItem;
|
|
|
|
if (keyPair.Value.Category == "")
|
|
|
|
{
|
|
|
|
menuItem = new GUIContent(keyPair.Value.CommandName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
menuItem = new GUIContent (keyPair.Value.Category + "/" + keyPair.Value.CommandName);
|
|
|
|
}
|
|
|
|
|
|
|
|
commandMenu.AddItem(menuItem, false, AddCommandCallback, commandOperation);
|
|
|
|
}
|
|
|
|
|
|
|
|
commandMenu.ShowAsContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected static List<KeyValuePair<System.Type,CommandInfoAttribute>> GetFilteredCommandInfoAttribute(List<System.Type> menuTypes)
|
|
|
|
{
|
|
|
|
Dictionary<string, KeyValuePair<System.Type, CommandInfoAttribute>> filteredAttributes = new Dictionary<string, KeyValuePair<System.Type, CommandInfoAttribute>>();
|
|
|
|
|
|
|
|
foreach (System.Type type in menuTypes)
|
|
|
|
{
|
|
|
|
object[] attributes = type.GetCustomAttributes(false);
|
|
|
|
foreach (object obj in attributes)
|
|
|
|
{
|
|
|
|
CommandInfoAttribute infoAttr = obj as CommandInfoAttribute;
|
|
|
|
if (infoAttr != null)
|
|
|
|
{
|
|
|
|
string dictionaryName = string.Format("{0}/{1}", infoAttr.Category, infoAttr.CommandName);
|
|
|
|
|
|
|
|
int existingItemPriority = -1;
|
|
|
|
if (filteredAttributes.ContainsKey(dictionaryName))
|
|
|
|
{
|
|
|
|
existingItemPriority = filteredAttributes[dictionaryName].Value.Priority;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (infoAttr.Priority > existingItemPriority)
|
|
|
|
{
|
|
|
|
KeyValuePair<System.Type, CommandInfoAttribute> keyValuePair = new KeyValuePair<System.Type, CommandInfoAttribute>(type, infoAttr);
|
|
|
|
filteredAttributes[dictionaryName] = keyValuePair;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return filteredAttributes.Values.ToList<KeyValuePair<System.Type,CommandInfoAttribute>>();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected static void AddCommandCallback(object obj)
|
|
|
|
{
|
|
|
|
AddCommandOperation commandOperation = obj as AddCommandOperation;
|
|
|
|
|
|
|
|
Sequence sequence = commandOperation.sequence;
|
|
|
|
if (sequence == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
fungusScript.ClearSelectedCommands();
|
|
|
|
|
|
|
|
Command newCommand = Undo.AddComponent(sequence.gameObject, commandOperation.commandType) as Command;
|
|
|
|
sequence.GetFungusScript().AddSelectedCommand(newCommand);
|
|
|
|
newCommand.parentSequence = sequence;
|
|
|
|
newCommand.commandId = fungusScript.NextCommandId();
|
|
|
|
|
|
|
|
// Let command know it has just been added to the sequence
|
|
|
|
newCommand.OnCommandAdded(sequence);
|
|
|
|
|
|
|
|
Undo.RecordObject(sequence, "Set command type");
|
|
|
|
if (commandOperation.index < sequence.commandList.Count - 1)
|
|
|
|
{
|
|
|
|
sequence.commandList.Insert(commandOperation.index, newCommand);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sequence.commandList.Add(newCommand);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ShowContextMenu()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
if (fungusScript == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool showCut = false;
|
|
|
|
bool showCopy = false;
|
|
|
|
bool showDelete = false;
|
|
|
|
bool showPaste = false;
|
|
|
|
|
|
|
|
if (fungusScript.selectedCommands.Count > 0)
|
|
|
|
{
|
|
|
|
showCut = true;
|
|
|
|
showCopy = true;
|
|
|
|
showDelete = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
CommandCopyBuffer commandCopyBuffer = CommandCopyBuffer.GetInstance();
|
|
|
|
|
|
|
|
if (commandCopyBuffer.HasCommands())
|
|
|
|
{
|
|
|
|
showPaste = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
GenericMenu commandMenu = new GenericMenu();
|
|
|
|
|
|
|
|
if (showCut)
|
|
|
|
{
|
|
|
|
commandMenu.AddItem (new GUIContent ("Cut"), false, Cut);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
commandMenu.AddDisabledItem(new GUIContent ("Cut"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (showCopy)
|
|
|
|
{
|
|
|
|
commandMenu.AddItem (new GUIContent ("Copy"), false, Copy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
commandMenu.AddDisabledItem(new GUIContent ("Copy"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (showPaste)
|
|
|
|
{
|
|
|
|
commandMenu.AddItem (new GUIContent ("Paste"), false, Paste);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
commandMenu.AddDisabledItem(new GUIContent ("Paste"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (showDelete)
|
|
|
|
{
|
|
|
|
commandMenu.AddItem (new GUIContent ("Delete"), false, Delete);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
commandMenu.AddDisabledItem(new GUIContent ("Delete"));
|
|
|
|
}
|
|
|
|
|
|
|
|
commandMenu.AddSeparator("");
|
|
|
|
|
|
|
|
commandMenu.AddItem (new GUIContent ("Select All"), false, SelectAll);
|
|
|
|
commandMenu.AddItem (new GUIContent ("Select None"), false, SelectNone);
|
|
|
|
|
|
|
|
commandMenu.ShowAsContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void SelectAll()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
if (fungusScript == null ||
|
|
|
|
fungusScript.selectedSequence == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fungusScript.ClearSelectedCommands();
|
|
|
|
Undo.RecordObject(fungusScript, "Select All");
|
|
|
|
foreach (Command command in fungusScript.selectedSequence.commandList)
|
|
|
|
{
|
|
|
|
fungusScript.AddSelectedCommand(command);
|
|
|
|
}
|
|
|
|
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void SelectNone()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
if (fungusScript == null ||
|
|
|
|
fungusScript.selectedSequence == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Undo.RecordObject(fungusScript, "Select None");
|
|
|
|
fungusScript.ClearSelectedCommands();
|
|
|
|
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void Cut()
|
|
|
|
{
|
|
|
|
Copy();
|
|
|
|
Delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void Copy()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
if (fungusScript == null ||
|
|
|
|
fungusScript.selectedSequence == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CommandCopyBuffer commandCopyBuffer = CommandCopyBuffer.GetInstance();
|
|
|
|
commandCopyBuffer.Clear();
|
|
|
|
|
|
|
|
// Scan through all commands in execution order to see if each needs to be copied
|
|
|
|
foreach (Command command in fungusScript.selectedSequence.commandList)
|
|
|
|
{
|
|
|
|
if (fungusScript.selectedCommands.Contains(command))
|
|
|
|
{
|
|
|
|
System.Type type = command.GetType();
|
|
|
|
Command newCommand = Undo.AddComponent(commandCopyBuffer.gameObject, type) as Command;
|
|
|
|
System.Reflection.FieldInfo[] fields = type.GetFields();
|
|
|
|
foreach (System.Reflection.FieldInfo field in fields)
|
|
|
|
{
|
|
|
|
field.SetValue(newCommand, field.GetValue(command));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void Paste()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
if (fungusScript == null ||
|
|
|
|
fungusScript.selectedSequence == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CommandCopyBuffer commandCopyBuffer = CommandCopyBuffer.GetInstance();
|
|
|
|
|
|
|
|
// Find where to paste commands in sequence (either at end or after last selected command)
|
|
|
|
int pasteIndex = fungusScript.selectedSequence.commandList.Count;
|
|
|
|
if (fungusScript.selectedCommands.Count > 0)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < fungusScript.selectedSequence.commandList.Count; ++i)
|
|
|
|
{
|
|
|
|
Command command = fungusScript.selectedSequence.commandList[i];
|
|
|
|
|
|
|
|
foreach (Command selectedCommand in fungusScript.selectedCommands)
|
|
|
|
{
|
|
|
|
if (command == selectedCommand)
|
|
|
|
{
|
|
|
|
pasteIndex = i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (Command command in commandCopyBuffer.GetCommands())
|
|
|
|
{
|
|
|
|
// Using the Editor copy / paste functionality instead instead of reflection
|
|
|
|
// because this does a deep copy of the command properties.
|
|
|
|
if (ComponentUtility.CopyComponent(command))
|
|
|
|
{
|
|
|
|
if (ComponentUtility.PasteComponentAsNew(fungusScript.gameObject))
|
|
|
|
{
|
|
|
|
Command[] commands = fungusScript.GetComponents<Command>();
|
|
|
|
Command pastedCommand = commands.Last<Command>();
|
|
|
|
if (pastedCommand != null)
|
|
|
|
{
|
|
|
|
pastedCommand.commandId = fungusScript.NextCommandId();
|
|
|
|
fungusScript.selectedSequence.commandList.Insert(pasteIndex++, pastedCommand);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This stops the user pasting the command manually into another game object.
|
|
|
|
ComponentUtility.CopyComponent(fungusScript.transform);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void Delete()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
if (fungusScript == null ||
|
|
|
|
fungusScript.selectedSequence == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int lastSelectedIndex = 0;
|
|
|
|
for (int i = fungusScript.selectedSequence.commandList.Count - 1; i >= 0; --i)
|
|
|
|
{
|
|
|
|
Command command = fungusScript.selectedSequence.commandList[i];
|
|
|
|
foreach (Command selectedCommand in fungusScript.selectedCommands)
|
|
|
|
{
|
|
|
|
if (command == selectedCommand)
|
|
|
|
{
|
|
|
|
command.OnCommandRemoved(sequence);
|
|
|
|
|
|
|
|
Undo.RecordObject(fungusScript.selectedSequence, "Delete");
|
|
|
|
fungusScript.selectedSequence.commandList.RemoveAt(i);
|
|
|
|
Undo.DestroyObjectImmediate(command);
|
|
|
|
lastSelectedIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Undo.RecordObject(fungusScript, "Delete");
|
|
|
|
fungusScript.ClearSelectedCommands();
|
|
|
|
|
|
|
|
if (lastSelectedIndex < fungusScript.selectedSequence.commandList.Count)
|
|
|
|
{
|
|
|
|
Command nextCommand = fungusScript.selectedSequence.commandList[lastSelectedIndex];
|
|
|
|
sequence.GetFungusScript().AddSelectedCommand(nextCommand);
|
|
|
|
}
|
|
|
|
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void SelectPrevious()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
int firstSelectedIndex = fungusScript.selectedSequence.commandList.Count;
|
|
|
|
bool firstSelectedCommandFound = false;
|
|
|
|
if (fungusScript.selectedCommands.Count > 0)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < fungusScript.selectedSequence.commandList.Count; i++)
|
|
|
|
{
|
|
|
|
Command commandInSequence = fungusScript.selectedSequence.commandList[i];
|
|
|
|
|
|
|
|
foreach (Command selectedCommand in fungusScript.selectedCommands)
|
|
|
|
{
|
|
|
|
if (commandInSequence == selectedCommand)
|
|
|
|
{
|
|
|
|
if (!firstSelectedCommandFound)
|
|
|
|
{
|
|
|
|
firstSelectedIndex = i;
|
|
|
|
firstSelectedCommandFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (firstSelectedCommandFound)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (firstSelectedIndex > 0)
|
|
|
|
{
|
|
|
|
fungusScript.ClearSelectedCommands();
|
|
|
|
fungusScript.AddSelectedCommand(fungusScript.selectedSequence.commandList[firstSelectedIndex-1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
protected void SelectNext()
|
|
|
|
{
|
|
|
|
Sequence sequence = target as Sequence;
|
|
|
|
FungusScript fungusScript = sequence.GetFungusScript();
|
|
|
|
|
|
|
|
int lastSelectedIndex = -1;
|
|
|
|
if (fungusScript.selectedCommands.Count > 0)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < fungusScript.selectedSequence.commandList.Count; i++)
|
|
|
|
{
|
|
|
|
Command commandInSequence = fungusScript.selectedSequence.commandList[i];
|
|
|
|
|
|
|
|
foreach (Command selectedCommand in fungusScript.selectedCommands)
|
|
|
|
{
|
|
|
|
if (commandInSequence == selectedCommand)
|
|
|
|
{
|
|
|
|
lastSelectedIndex = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lastSelectedIndex < fungusScript.selectedSequence.commandList.Count-1)
|
|
|
|
{
|
|
|
|
fungusScript.ClearSelectedCommands();
|
|
|
|
fungusScript.AddSelectedCommand(fungusScript.selectedSequence.commandList[lastSelectedIndex+1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|