Browse Source

Copy and paste support for commands

master
chrisgregan 10 years ago
parent
commit
7f5ed8e0cf
  1. 31
      Assets/Fungus/FungusScript/Editor/CommandEditor.cs
  2. 44
      Assets/Fungus/FungusScript/Editor/CommandListAdaptor.cs
  3. 1
      Assets/Fungus/FungusScript/Editor/FungusScriptWindow.cs
  4. 215
      Assets/Fungus/FungusScript/Editor/SequenceEditor.cs
  5. 2
      Assets/Fungus/FungusScript/Editor/VariableListAdaptor.cs
  6. 6
      Assets/Fungus/FungusScript/Scripts/Command.cs
  7. 64
      Assets/Fungus/FungusScript/Scripts/CommandCopyBuffer.cs
  8. 8
      Assets/Fungus/FungusScript/Scripts/CommandCopyBuffer.cs.meta
  9. 6
      Assets/Fungus/FungusScript/Scripts/FungusScript.cs

31
Assets/Fungus/FungusScript/Editor/CommandEditor.cs

@ -86,14 +86,6 @@ namespace Fungus
t.enabled = enabled;
}
if (fungusScript != null)
{
if (GUILayout.Button("Copy", EditorStyles.miniButton))
{
fungusScript.copyCommand = t;
}
}
GUILayout.EndHorizontal();
GUI.backgroundColor = Color.white;
@ -118,29 +110,6 @@ namespace Fungus
DrawDefaultInspector();
}
static public Command PasteCommand(Command copyCommand, Sequence sequence)
{
if (sequence == null)
{
return null;
}
System.Type type = copyCommand.GetType();
Component copy = Undo.AddComponent(sequence.gameObject, type);
System.Reflection.FieldInfo[] fields = type.GetFields();
foreach (System.Reflection.FieldInfo field in fields)
{
field.SetValue(copy, field.GetValue(copyCommand));
}
Undo.RecordObject(sequence, "Paste Command");
Command newCommand = copy as Command;
sequence.commandList.Add(newCommand);
return newCommand;
}
static public void ObjectField<T>(SerializedProperty property, GUIContent label, GUIContent nullLabel, List<T> objectList) where T : MonoBehaviour
{
if (property == null)

44
Assets/Fungus/FungusScript/Editor/CommandListAdaptor.cs

@ -106,7 +106,14 @@ namespace Fungus
// Add the command as a new component
Sequence parentSequence = command.GetComponent<Sequence>();
Command newCommand = CommandEditor.PasteCommand(command, parentSequence);
System.Type type = command.GetType();
Command newCommand = Undo.AddComponent(parentSequence.gameObject, type) as Command;
System.Reflection.FieldInfo[] fields = type.GetFields();
foreach (System.Reflection.FieldInfo field in fields)
{
field.SetValue(newCommand, field.GetValue(command));
}
_arrayProperty.InsertArrayElementAtIndex(index);
_arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = newCommand;
@ -166,8 +173,8 @@ namespace Fungus
error = true;
}
bool selected = (Application.isPlaying && command.IsExecuting()) ||
(!Application.isPlaying && fungusScript.selectedCommand == command);
bool highlight = (Application.isPlaying && command.IsExecuting()) ||
(!Application.isPlaying && fungusScript.selectedCommand == command);
float indentSize = 20;
for (int i = 0; i < command.indentLevel; ++i)
@ -196,7 +203,7 @@ namespace Fungus
Rect summaryRect = buttonRect;
summaryRect.x += buttonWidth - 1;
summaryRect.width = position.width - buttonWidth - indentWidth - 15;
summaryRect.width = position.width - buttonWidth - indentWidth - 23;
if (!Application.isPlaying &&
Event.current.type == EventType.MouseDown &&
@ -214,7 +221,7 @@ namespace Fungus
}
Color summaryBackgroundColor = Color.white;
if (selected)
if (highlight)
{
summaryBackgroundColor = Color.green;
buttonBackgroundColor = Color.green;
@ -234,7 +241,7 @@ namespace Fungus
GUIStyle summaryStyle = new GUIStyle(EditorStyles.miniButtonRight);
summaryStyle.alignment = TextAnchor.MiddleLeft;
if (error && !selected)
if (error && !highlight)
{
summaryStyle.normal.textColor = Color.white;
}
@ -244,16 +251,23 @@ namespace Fungus
GUI.backgroundColor = Color.white;
Rect menuRect = summaryRect;
menuRect.x += menuRect.width + 2;
menuRect.y = position.y + 1;
menuRect.width = 18;
menuRect.height = position.height;
GUIStyle menuButtonStyle = new GUIStyle(EditorStyles.popup);
if (GUI.Button(menuRect, new GUIContent("", "Select command type"), menuButtonStyle))
if (!Application.isPlaying)
{
ShowCommandMenu(index, fungusScript.selectedSequence);
Rect menuRect = summaryRect;
menuRect.x += menuRect.width + 4;
menuRect.y = position.y + 1;
menuRect.width = 22;
menuRect.height = position.height;
GUIStyle menuButtonStyle = new GUIStyle("Foldout");
if (GUI.Button(menuRect, new GUIContent("", "Select command type"), menuButtonStyle))
{
ShowCommandMenu(index, fungusScript.selectedSequence);
}
Rect selectRect = position;
selectRect.x -= 19;
selectRect.width = 20;
command.selected = EditorGUI.Toggle(selectRect, command.selected);
}
}

1
Assets/Fungus/FungusScript/Editor/FungusScriptWindow.cs

@ -37,6 +37,7 @@ namespace Fungus
Sequence sequence = newSequenceGO.AddComponent<Sequence>();
fungusScript.startSequence = sequence;
fungusScript.selectedSequence = sequence;
Undo.RegisterCreatedObjectUndo(newFungusScriptGO, "Create Fungus Script");
}
// Implementing this method causes the padlock image to display on the window

215
Assets/Fungus/FungusScript/Editor/SequenceEditor.cs

@ -48,37 +48,37 @@ namespace Fungus
ReorderableListGUI.Title("Command Sequence");
SerializedProperty commandListProperty = serializedObject.FindProperty("commandList");
CommandListAdaptor adaptor = new CommandListAdaptor(commandListProperty, 0);
ReorderableListControl.DrawControlFromState(adaptor, null, 0);
ReorderableListControl.DrawControlFromState(adaptor, null, ReorderableListFlags.HideRemoveButtons);
if (Application.isPlaying)
if (!Application.isPlaying)
{
serializedObject.ApplyModifiedProperties();
return;
}
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (fungusScript.copyCommand != null)
{
if (GUILayout.Button("Paste"))
Rect copyMenuRect = GUILayoutUtility.GetLastRect();
copyMenuRect.y += copyMenuRect.height - 17;
copyMenuRect.width = 24;
copyMenuRect.height = 18;
if (GUI.Button(copyMenuRect, "", new GUIStyle("DropDown")))
{
fungusScript.selectedCommand = CommandEditor.PasteCommand(fungusScript.copyCommand, fungusScript.selectedSequence);
ShowCopyMenu();
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if (fungusScript.selectedCommand != null)
{
CommandInfoAttribute infoAttr = CommandEditor.GetCommandInfo(fungusScript.selectedCommand.GetType());
if (infoAttr != null)
{
EditorGUILayout.HelpBox(infoAttr.HelpText, MessageType.Info);
EditorGUILayout.HelpBox(infoAttr.CommandName + ":\n" + infoAttr.HelpText, MessageType.Info, true);
}
}
// Need to expand to fill space or else reorderable list width changes if no command is selected
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
}
@ -168,6 +168,189 @@ namespace Fungus
return result;
}
protected void ShowCopyMenu()
{
bool showCut = false;
bool showCopy = false;
bool showDelete = false;
bool showPaste = false;
Sequence sequence = target as Sequence;
foreach (Command command in sequence.commandList)
{
if (command.selected)
{
showCut = true;
showCopy = true;
showDelete = true;
}
}
CommandCopyBuffer commandCopyBuffer = CommandCopyBuffer.GetInstance();
if (commandCopyBuffer.HasCommands())
{
showPaste = true;
}
GenericMenu commandMenu = new GenericMenu();
commandMenu.AddItem (new GUIContent ("Select All"), false, SelectAll);
commandMenu.AddItem (new GUIContent ("Select None"), false, SelectNone);
commandMenu.AddSeparator("");
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.ShowAsContext();
}
protected virtual void SelectAll()
{
Sequence sequence = target as Sequence;
foreach (Command command in sequence.commandList)
{
Undo.RecordObject(command, "Select All");
command.selected = true;
}
}
protected virtual void SelectNone()
{
Sequence sequence = target as Sequence;
FungusScript fungusScript = sequence.GetFungusScript();
if (fungusScript != null)
{
Undo.RecordObject(fungusScript, "Select None");
fungusScript.selectedCommand = null;
}
foreach (Command command in sequence.commandList)
{
Undo.RecordObject(command, "Select None");
command.selected = false;
}
}
protected virtual void Cut()
{
Copy();
Delete();
}
protected virtual void Copy()
{
Sequence sequence = target as Sequence;
CommandCopyBuffer commandCopyBuffer = CommandCopyBuffer.GetInstance();
commandCopyBuffer.Clear();
foreach (Command command in sequence.commandList)
{
if (command.selected)
{
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));
}
newCommand.selected = false;
}
}
}
protected virtual void Paste()
{
CommandCopyBuffer commandCopyBuffer = CommandCopyBuffer.GetInstance();
Sequence sequence = target as Sequence;
FungusScript fungusScript = sequence.GetFungusScript();
// Find where to paste commands in sequence (either at end or after selected command)
int pasteIndex = sequence.commandList.Count;
if (fungusScript.selectedCommand != null)
{
for (int i = 0; i < sequence.commandList.Count; ++i)
{
Command command = sequence.commandList[i];
if (fungusScript.selectedCommand == command)
{
pasteIndex = i + 1;
break;
}
}
}
foreach (Command command in commandCopyBuffer.GetCommands())
{
System.Type type = command.GetType();
Command newCommand = Undo.AddComponent(sequence.gameObject, type) as Command;
System.Reflection.FieldInfo[] fields = type.GetFields();
foreach (System.Reflection.FieldInfo field in fields)
{
field.SetValue(newCommand, field.GetValue(command));
}
newCommand.selected = false;
Undo.RecordObject(sequence, "Paste");
sequence.commandList.Insert(pasteIndex++, newCommand);
}
}
protected virtual void Delete()
{
Sequence sequence = target as Sequence;
for (int i = sequence.commandList.Count - 1; i >= 0; --i)
{
Command command = sequence.commandList[i];
if (command != null &&
command.selected)
{
Undo.DestroyObjectImmediate(command);
Undo.RecordObject(sequence, "Delete");
sequence.commandList.RemoveAt(i);
}
}
}
}
}

2
Assets/Fungus/FungusScript/Editor/VariableListAdaptor.cs

@ -210,7 +210,7 @@ namespace Fungus
GUI.Label(valueRect, type);
scope = (VariableScope)EditorGUI.EnumPopup(scopeRect, variable.scope);
// To access properties in a monobehavior, you have new a SerializedObject
// To access properties in a monobehavior, you have to new a SerializedObject
// http://answers.unity3d.com/questions/629803/findrelativeproperty-never-worked-for-me-how-does.html
SerializedObject variableObject = new SerializedObject(this[index].objectReferenceValue);
SerializedProperty keyProp = variableObject.FindProperty("key");

6
Assets/Fungus/FungusScript/Scripts/Command.cs

@ -19,8 +19,7 @@ namespace Fungus
public string CommandName { get; set; }
public string HelpText { get; set; }
}
[RequireComponent(typeof(Sequence))]
public class Command : MonoBehaviour
{
[HideInInspector]
@ -29,6 +28,9 @@ namespace Fungus
[HideInInspector]
public int indentLevel;
[HideInInspector]
public bool selected;
public virtual Sequence GetSequence()
{
return gameObject.GetComponent<Sequence>();

64
Assets/Fungus/FungusScript/Scripts/CommandCopyBuffer.cs

@ -0,0 +1,64 @@
using UnityEngine;
using System.Collections;
namespace Fungus
{
public class CommandCopyBuffer : Sequence
{
protected static CommandCopyBuffer instance;
/**
* Returns the CommandCopyBuffer singleton instance.
* Will create a CommandCopyBuffer game object if none currently exists.
*/
static public CommandCopyBuffer GetInstance()
{
if (instance == null)
{
// Static variables are not serialized (e.g. when playing in the editor)
// We need to reaquire the static reference to the game object in this case
GameObject go = GameObject.Find("_CommandCopyBuffer");
if (go != null)
{
instance = go.GetComponent<CommandCopyBuffer>();
}
else
{
go = new GameObject("_CommandCopyBuffer");
instance = go.AddComponent<CommandCopyBuffer>();
go.hideFlags = HideFlags.HideInHierarchy;
}
}
return instance;
}
protected virtual void Start()
{
if (Application.isPlaying)
{
Destroy(this.gameObject);
}
}
public virtual bool HasCommands()
{
return GetCommands().Length > 0;
}
public virtual Command[] GetCommands()
{
return GetComponents<Command>();
}
public virtual void Clear()
{
foreach (Command command in GetCommands())
{
DestroyImmediate(command);
}
}
}
}

8
Assets/Fungus/FungusScript/Scripts/CommandCopyBuffer.cs.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 28859462f29464188bb29cc9f1f6e92c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

6
Assets/Fungus/FungusScript/Scripts/FungusScript.cs

@ -19,12 +19,6 @@ namespace Fungus
[System.NonSerialized]
public Sequence executingSequence;
/**
* Copy and paste buffer for command objects.
*/
[System.NonSerialized]
public Command copyCommand;
/**
* Scroll position of Fungus Script editor window (map view).
*/

Loading…
Cancel
Save