Skip to content

Commit 45c65de

Browse files
authored
Merge pull request #165 from mjavaly/cpimhoff/editor-undo-support
Editor Undo Support
2 parents 57876af + 1f0f05e commit 45c65de

11 files changed

+212
-75
lines changed

Project/Assets/Editor/CustomInspectors/AnnotationInteractionEditor.cs

+55-13
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,22 @@ public class AnnotationInteractionEditor : Editor {
99
bool showRichText = true;
1010
Annotation annotation;
1111

12-
13-
public override void OnInspectorGUI()
12+
public void Awake()
1413
{
1514
annotation = (Annotation)target;
15+
}
1616

17+
public override void OnInspectorGUI()
18+
{
1719
// select type
1820
string[] typeOptions = new string[] { "Summary Annotation", "Area Annotation" };
19-
annotation.annotationType= EditorGUILayout.Popup("Annotation Type", annotation.annotationType, typeOptions);
21+
EditorGUI.BeginChangeCheck();
22+
int _annotationType = EditorGUILayout.Popup("Annotation Type", annotation.annotationType, typeOptions);
23+
if (EditorGUI.EndChangeCheck())
24+
{
25+
Undo.RecordObject(annotation, "Change Annotation Type");
26+
annotation.annotationType = _annotationType;
27+
}
2028

2129
// warnings
2230
if (annotation.annotationType == (int)AnnotationTypes.AREA)
@@ -38,9 +46,15 @@ public override void OnInspectorGUI()
3846
int previousType = annotation.importType;
3947

4048
string[] importOptions = new string[] { "No Full Annotation", "Import Text File", "Write in Inspector" };
41-
annotation.importType = EditorGUILayout.Popup("Import Method", annotation.importType, importOptions);
4249

50+
EditorGUI.BeginChangeCheck();
51+
int _importType = EditorGUILayout.Popup("Import Method", annotation.importType, importOptions);
4352
//checks with user, then resets full annotation information
53+
if (EditorGUI.EndChangeCheck())
54+
{
55+
Undo.RecordObject(annotation, "Change Annotation Type");
56+
annotation.importType = _importType;
57+
}
4458
if (previousType != 0 && annotation.importType == (int)ImportTypes.NONE)
4559
{
4660
if (EditorUtility.DisplayDialog("Reset", "WARNING: Switching back to 'No Full Annotation' will cause any curent information to be lost...",
@@ -66,25 +80,35 @@ public override void OnInspectorGUI()
6680
{
6781
DisplayWriteInInspector();
6882
}
69-
70-
if (GUI.changed) {
71-
EditorUtility.SetDirty(annotation);
72-
}
7383
}
7484

7585
void DisplaySetLargeSummary()
7686
{
7787
GUIStyle textAreaStyle = new GUIStyle(GUI.skin.textArea);
7888
textAreaStyle.wordWrap = true;
7989
GUILayout.Label("Annotation Summary Text:");
80-
annotation.summary = GUILayout.TextArea(annotation.summary, 250, textAreaStyle, GUILayout.Height(75),
90+
91+
EditorGUI.BeginChangeCheck();
92+
string _summary = GUILayout.TextArea(annotation.summary, 250, textAreaStyle, GUILayout.Height(75),
8193
GUILayout.Width(EditorGUIUtility.currentViewWidth - 40), GUILayout.ExpandWidth(false));
94+
if (EditorGUI.EndChangeCheck())
95+
{
96+
Undo.RecordObject(annotation, "Change Annotation Summary");
97+
annotation.summary = _summary;
98+
}
8299
}
83100

84101
void DisplaySetAreaInteractionSummary()
85102
{
86103
GUILayout.Label("Annotation Name:");
87-
annotation.summary = GUILayout.TextField(annotation.summary, 40);
104+
105+
EditorGUI.BeginChangeCheck();
106+
string _summary = GUILayout.TextField(annotation.summary, 40);
107+
if (EditorGUI.EndChangeCheck())
108+
{
109+
Undo.RecordObject(annotation, "Change Area Annotation Name");
110+
annotation.summary = _summary;
111+
}
88112
}
89113

90114
/// <summary>
@@ -130,6 +154,8 @@ void ImportFileButton()
130154

131155
if (absolutePath.StartsWith(Application.dataPath))
132156
{
157+
Undo.RecordObject(annotation, "Change Annotation Text File");
158+
133159
annotation.textFilePath = "Assets" + absolutePath.Substring(Application.dataPath.Length);
134160
annotation.textFile = AssetDatabase.LoadAssetAtPath<TextAsset>(annotation.textFilePath);
135161
if (annotation.textFile != null)
@@ -163,15 +189,27 @@ void DisplayWriteInInspector()
163189
textAreaStyle.richText = false;
164190
}
165191

166-
annotation.text = EditorGUILayout.TextArea(annotation.text, textAreaStyle, GUILayout.Height(100),
192+
EditorGUI.BeginChangeCheck();
193+
string _text = EditorGUILayout.TextArea(annotation.text, textAreaStyle, GUILayout.Height(100),
167194
GUILayout.Width(EditorGUIUtility.currentViewWidth - 40), GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(false));
195+
if (EditorGUI.EndChangeCheck())
196+
{
197+
Undo.RecordObject(annotation, "Change Annotation Content");
198+
annotation.text = _text;
199+
}
168200

169201
GUILayout.BeginHorizontal();
170202
GUILayout.FlexibleSpace();
171203
SaveTextFileButton();
172204
GUILayout.EndHorizontal();
173205

174-
annotation.includeImages = EditorGUILayout.Toggle("Include Images:", annotation.includeImages);
206+
EditorGUI.BeginChangeCheck();
207+
bool _includeImages = EditorGUILayout.Toggle("Include Images:", annotation.includeImages);
208+
if (EditorGUI.EndChangeCheck())
209+
{
210+
Undo.RecordObject(annotation, "Change Annotation Images Folder");
211+
annotation.includeImages = _includeImages;
212+
}
175213

176214
if (annotation.includeImages)
177215
{
@@ -198,6 +236,7 @@ void GetImagePath()
198236

199237
if (absolutePath.StartsWith(Application.dataPath))
200238
{
239+
Undo.RecordObject(annotation, "Change Annotation Images Folder");
201240
annotation.imagePath = "Assets" + absolutePath.Substring(Application.dataPath.Length) + Path.DirectorySeparatorChar;
202241
}
203242
else
@@ -225,10 +264,13 @@ void SaveTextFileButton()
225264
{
226265
File.WriteAllText(path, annotation.text);
227266

267+
// We need to enlist an UNDO here, or else the changes to the annotation won't be saved.
268+
// We can undo the annotation's binding to the file, but not the actual file creation.
269+
Undo.RecordObject(annotation, "Save Annotation to File");
270+
228271
//Links annotation file to newly saved file
229272
annotation.textFilePath = "Assets" + path.Substring(Application.dataPath.Length);
230273
annotation.textFile = AssetDatabase.LoadAssetAtPath<TextAsset>(annotation.textFilePath);
231-
232274
}
233275
catch (Exception e)
234276
{
Binary file not shown.

Project/Assets/Editor/CustomInspectors/AudioInteractionEditor.cs

+24-6
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,41 @@ public class AudioInteractionEditor : Editor {
88
AudioInteraction audio;
99
bool customAudioSource;
1010

11-
public override void OnInspectorGUI()
11+
public void Awake()
1212
{
1313
this.audio = (AudioInteraction)target;
1414

15-
audio.repeatable = EditorGUILayout.Toggle ("Replayable?", audio.repeatable);
16-
audio.audioClip = (AudioClip)EditorGUILayout.ObjectField ("Audio Clip", audio.audioClip, typeof(AudioClip), true);
15+
// initialize synthesized property
16+
this.customAudioSource = false;
17+
if (this.audio.audioSource != null)
18+
{
19+
this.customAudioSource = true;
20+
}
21+
}
22+
23+
public override void OnInspectorGUI()
24+
{
25+
// Configuration:
26+
bool _repeatable = EditorGUILayout.Toggle ("Replayable?", audio.repeatable);
27+
AudioClip _audioClip = (AudioClip)EditorGUILayout.ObjectField ("Audio Clip", audio.audioClip, typeof(AudioClip), true);
1728

29+
AudioSource _audioSource = null;
1830
customAudioSource = EditorGUILayout.Toggle ("Different Audio Source?", customAudioSource);
1931
if (customAudioSource)
2032
{
21-
audio.audioSource = (AudioSource)EditorGUILayout.ObjectField ("Audio Source", audio.audioSource, typeof(AudioSource), true);
33+
_audioSource = (AudioSource)EditorGUILayout.ObjectField ("Audio Source", audio.audioSource, typeof(AudioSource), true);
2234
}
2335

24-
this.DrawWarnings ();
36+
// Save:
2537
if (GUI.changed) {
26-
EditorUtility.SetDirty(audio);
38+
Undo.RecordObject(audio, "Modify Audio Interaction");
39+
audio.repeatable = _repeatable;
40+
audio.audioClip = _audioClip;
41+
audio.audioSource = _audioSource;
2742
}
43+
44+
// Warnings (after properties have been updated):
45+
this.DrawWarnings();
2846
}
2947

3048
public void DrawWarnings()

Project/Assets/Editor/CustomInspectors/ComponentToggleInteractionEditor.cs

+14-5
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,26 @@ public class ComponentToggleInteractionEditor : Editor {
66

77
ComponentToggleInteraction componentToggle;
88

9-
public override void OnInspectorGUI ()
9+
public void Awake()
1010
{
1111
this.componentToggle = (ComponentToggleInteraction)target;
12+
}
1213

13-
componentToggle.repeatable = EditorGUILayout.Toggle ("Repeatable?", componentToggle.repeatable);
14-
componentToggle.target = PrairieGUI.drawObjectList<Behaviour> ("Behaviours To Toggle:", componentToggle.target);
14+
public override void OnInspectorGUI ()
15+
{
16+
// Configuration:
17+
bool _repeatable = EditorGUILayout.Toggle ("Repeatable?", componentToggle.repeatable);
18+
Behaviour[] _targets = PrairieGUI.drawObjectList<Behaviour> ("Behaviours To Toggle:", componentToggle.target);
1519

16-
this.DrawWarnings();
20+
// Save:
1721
if (GUI.changed) {
18-
EditorUtility.SetDirty(componentToggle);
22+
Undo.RecordObject(componentToggle, "Modify Component Toggle");
23+
componentToggle.repeatable = _repeatable;
24+
componentToggle.target = _targets;
1925
}
26+
27+
// Warnings (after properties have been updated):
28+
this.DrawWarnings();
2029
}
2130

2231
public void DrawWarnings()

Project/Assets/Editor/CustomInspectors/FirstPersonInteractorEditor.cs

+13-6
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,29 @@ public class FirstPersonInteractorEditor : Editor {
77

88
FirstPersonInteractor player;
99

10-
public override void OnInspectorGUI ()
10+
public void Awake()
1111
{
1212
player = (FirstPersonInteractor)target;
13+
}
1314

15+
public override void OnInspectorGUI ()
16+
{
1417
// Principle Configuration:
1518
GUIContent rangeLabel = new GUIContent("Interaction Range", "The max distance a player can be from an object and interact with it.");
16-
player.interactionRange = EditorGUILayout.FloatField(rangeLabel, player.interactionRange);
19+
float _interactionRange = EditorGUILayout.FloatField(rangeLabel, player.interactionRange);
1720

1821
GUIContent annotationsLabel = new GUIContent("Enable Annotations", "If disabled, historical annotations are not shown in game.");
19-
player.annotationsEnabled = EditorGUILayout.Toggle(annotationsLabel, player.annotationsEnabled);
22+
bool _annotationsEnabled = EditorGUILayout.Toggle(annotationsLabel, player.annotationsEnabled);
2023

21-
// Warnings:
22-
this.DrawWarnings ();
24+
// Save:
2325
if (GUI.changed) {
24-
EditorUtility.SetDirty(player);
26+
Undo.RecordObject(player, "Modify Player");
27+
player.interactionRange = _interactionRange;
28+
player.annotationsEnabled = _annotationsEnabled;
2529
}
30+
31+
// Warnings:
32+
this.DrawWarnings ();
2633
}
2734

2835
public void DrawWarnings()

Project/Assets/Editor/CustomInspectors/PromptEditor.cs

+45-12
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ public class PromptEditor : Editor {
88

99
Prompt prompt;
1010

11+
public void Awake()
12+
{
13+
this.prompt = (Prompt) target;
14+
}
15+
1116
public override void OnInspectorGUI ()
1217
{
13-
prompt = (Prompt)target;
14-
1518
if (prompt.isTwinePrompt)
1619
{
1720
TwinePromptGUI();
@@ -20,16 +23,19 @@ public override void OnInspectorGUI ()
2023
{
2124
SimplePromptGUI();
2225
}
23-
24-
if (GUI.changed) {
25-
EditorUtility.SetDirty(prompt);
26-
}
2726
}
2827

2928
public void SimplePromptGUI(bool cyclicAllowed = true)
3029
{
3130
GUIContent label = new GUIContent ("Prompt Text", "Text displayed when a player can interact with this object.");
32-
prompt.firstPrompt = EditorGUILayout.TextField (label, prompt.firstPrompt);
31+
EditorGUI.BeginChangeCheck();
32+
string _firstPrompt = EditorGUILayout.TextField (label, prompt.firstPrompt);
33+
if (EditorGUI.EndChangeCheck())
34+
{
35+
// first prompt was edited
36+
Undo.RecordObject(prompt, "Change Prompt");
37+
prompt.firstPrompt = _firstPrompt;
38+
}
3339

3440
if (string.IsNullOrEmpty(prompt.firstPrompt.Trim()))
3541
{
@@ -40,11 +46,26 @@ public void SimplePromptGUI(bool cyclicAllowed = true)
4046
if (!cyclicAllowed) { return; } // guard statement
4147

4248
GUIContent cyclicLabel = new GUIContent("Cyclic Prompt", "Does this prompt have two cycling values? (i.e. open, close)");
43-
prompt.isCyclic = EditorGUILayout.Toggle(cyclicLabel, prompt.isCyclic);
49+
EditorGUI.BeginChangeCheck();
50+
bool _isCyclic = EditorGUILayout.Toggle(cyclicLabel, prompt.isCyclic);
51+
if (EditorGUI.EndChangeCheck())
52+
{
53+
Undo.RecordObject(prompt, "Modify Prompt");
54+
prompt.isCyclic = _isCyclic;
55+
}
56+
4457
if (prompt.isCyclic)
4558
{
4659
GUIContent secondLabel = new GUIContent("Second Prompt", "Second prompt to display, will toggle between this and first prompt.");
47-
prompt.secondPrompt = EditorGUILayout.TextField(secondLabel, prompt.secondPrompt);
60+
EditorGUI.BeginChangeCheck();
61+
string _secondPrompt = EditorGUILayout.TextField(secondLabel, prompt.secondPrompt);
62+
if (EditorGUI.EndChangeCheck())
63+
{
64+
// second prompt was edited
65+
Undo.RecordObject(prompt, "Change Prompt");
66+
prompt.secondPrompt = _secondPrompt;
67+
}
68+
4869
if (string.IsNullOrEmpty(prompt.secondPrompt.Trim()))
4970
{
5071
PrairieGUI.hintLabel("Second prompt will be ignored.");
@@ -67,9 +88,15 @@ public void TwinePromptGUI()
6788
if (twineNodeNames.Count == 1)
6889
{
6990
// use the simple prompt GUI without allowing for cycles
91+
EditorGUI.BeginChangeCheck();
7092
SimplePromptGUI(cyclicAllowed: false);
71-
// bind the result from simple GUI back to the twine based key
72-
prompt.twinePrompts.Set(twineNodeNames[0], prompt.firstPrompt);
93+
if (EditorGUI.EndChangeCheck())
94+
{
95+
// bind the result from simple GUI back to the twine based key
96+
prompt.twinePrompts.Set(twineNodeNames[0], prompt.firstPrompt);
97+
// since this is effectivally a reflection of the data modified, we do
98+
// not need to create a seperate undo event
99+
}
73100
// do not fall through into the dictionary input
74101
return;
75102
}
@@ -86,8 +113,14 @@ public void TwinePromptGUI()
86113
}
87114

88115
GUIContent label = new GUIContent (nodeName, "Text displayed when a player can progress the story to this twine node.");
116+
117+
EditorGUI.BeginChangeCheck();
89118
string newPromptText = EditorGUILayout.TextField(label, previousValue);
90-
this.prompt.twinePrompts.Set (nodeName, newPromptText);
119+
if (EditorGUI.EndChangeCheck())
120+
{
121+
Undo.RecordObject(prompt, "Change Prompt");
122+
this.prompt.twinePrompts.Set (nodeName, newPromptText);
123+
}
91124
}
92125
}
93126

Project/Assets/Editor/CustomInspectors/SwivelEditor.cs

+9-3
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@ public class SwivelEditor : Editor {
77

88
Swivel swivel;
99

10+
public void Awake()
11+
{
12+
this.swivel = (Swivel) target;
13+
}
14+
1015
public override void OnInspectorGUI()
1116
{
12-
swivel = (Swivel)target;
13-
swivel.openFromLeft = EditorGUILayout.Toggle (new GUIContent("Open from left?", "Door opens from right by default, check this box to open it from the left."), swivel.openFromLeft);
17+
bool _openFromLeft = EditorGUILayout.Toggle (new GUIContent("Open from left?", "Door opens from right by default, check this box to open it from the left."), swivel.openFromLeft);
18+
1419
if (GUI.changed) {
15-
EditorUtility.SetDirty(swivel);
20+
Undo.RecordObject(swivel, "Modify Swivel");
21+
swivel.openFromLeft = _openFromLeft;
1622
}
1723
}
1824
}

0 commit comments

Comments
 (0)