Tanoda
Undo.cs
Go to the documentation of this file.
1using UnityEngine;
2using System.Collections;
3using System.Collections.Generic;
4using System.Linq;
5
6namespace GILES
7{
15 {
20 protected class UndoState
21 {
22 // A summary of the undo action.
23 public string message;
24
25 // The object that is targeted by this action.
26 public IUndo target;
27
28 // A collection of values representing the state of `target`. Will by passed to IUndo::ApplyState.
29 public Hashtable values;
30
34 public UndoState(IUndo target, string msg)
35 {
36 this.target = target;
37 this.message = msg;
38 this.values = target.RecordState();
39 }
40
44 public void Apply()
45 {
47 }
48
52 public override string ToString()
53 {
54 return message;
55 }
56 }
57
58 public Callback undoPerformed = null;
59 public Callback redoPerformed = null;
62
66 public static void AddUndoPerformedListener(Callback callback)
67 {
68 if(instance.undoPerformed != null)
69 instance.undoPerformed += callback;
70 else
71 instance.undoPerformed = callback;
72 }
73
77 public static void AddRedoPerformedListener(Callback callback)
78 {
79 if(instance.redoPerformed != null)
80 instance.redoPerformed += callback;
81 else
82 instance.redoPerformed = callback;
83 }
84
85 [SerializeField] private Stack<List<UndoState>> undoStack = new Stack<List<UndoState>>();
86 [SerializeField] private Stack<List<UndoState>> redoStack = new Stack<List<UndoState>>();
87
91 public static string PrintUndoStack()
92 {
93 return instance.PrintStack(instance.undoStack);
94 }
95
99 public static string PrintRedoStack()
100 {
101 return instance.PrintStack(instance.redoStack);
102 }
103
107 private string PrintStack(Stack<List<UndoState>> stack)
108 {
109 System.Text.StringBuilder sb = new System.Text.StringBuilder();
110
111 foreach(List<UndoState> collection in stack)
112 {
113 foreach(UndoState state in collection)
114 {
115 sb.AppendLine(state.ToString());
116 break;
117 }
118
119 sb.AppendLine("-----");
120 }
121
122 return sb.ToString();
123 }
124
125 [SerializeField] UndoState currentUndo, currentRedo;
126
127 private void PushUndo(List<UndoState> state)
128 {
129 currentUndo = state[0];
130 undoStack.Push(state);
131
132 if(undoStackModified != null)
134 }
135
136 private void PushRedo(List<UndoState> state)
137 {
138 currentRedo = state[0];
139 redoStack.Push(state);
140
141 if(redoStackModified != null)
143 }
144
145 private List<UndoState> PopUndo()
146 {
147 List<UndoState> states = Pop(undoStack);
148
149 if(states == null || undoStack.Count < 1)
150 currentUndo = null;
151 else
152 currentUndo = ((List<UndoState>)undoStack.Peek())[0];
153
154 if(undoStackModified != null)
156
157 return states;
158 }
159
160 private List<UndoState> PopRedo()
161 {
162 List<UndoState> states = Pop(redoStack);
163
164 if(states == null || redoStack.Count < 1)
165 currentRedo = null;
166 else
167 currentRedo = ((List<UndoState>)redoStack.Peek())[0];
168
169 if(redoStackModified != null)
171
172 return states;
173 }
174
175 private List<UndoState> Pop(Stack<List<UndoState>> stack)
176 {
177 if(stack.Count > 0)
178 return (List<UndoState>) stack.Pop();
179 else
180 return null;
181 }
182
183 private static void ClearStack(Stack<List<UndoState>> stack)
184 {
185 foreach(List<UndoState> commands in stack)
186 foreach(UndoState state in commands)
187 state.target.OnExitScope();
188
189 stack.Clear();
190 }
191
196 public static string GetCurrentUndo()
197 {
198 return instance.currentUndo == null ? "" : instance.currentUndo.message;
199 }
200
204 public static string GetCurrentRedo()
205 {
206 return instance.currentRedo == null ? "" : instance.currentRedo.message;
207 }
208
214 public static void RegisterState(IUndo target, string message)
215 {
216 ClearStack(instance.redoStack);
217 instance.currentRedo = null;
218 instance.PushUndo(new List<UndoState>() { new UndoState(target, message) });
219 }
220
226 public static void RegisterStates(IEnumerable<IUndo> targets, string message)
227 {
228 ClearStack(instance.redoStack);
229 instance.currentRedo = null;
230 List<UndoState> states = targets.Select(x => new UndoState(x, message)).ToList();
231 instance.PushUndo(states);
232 }
233
237 public static void PerformUndo()
238 {
239 List<UndoState> states = instance.PopUndo();
240
241 if(states == null)
242 return;
243
244 instance.PushRedo(states.Select(x => new UndoState(x.target, x.message)).ToList());
245
246 foreach(UndoState state in states)
247 {
248 state.Apply();
249 }
250
251 if( instance.undoPerformed != null )
252 instance.undoPerformed();
253 }
254
259 public static void PerformRedo()
260 {
261 List<UndoState> states = instance.PopRedo();
262
263 if( states == null )
264 return;
265
266 instance.PushUndo(states.Select(x => new UndoState(x.target, x.message)).ToList());
267
268 foreach(UndoState state in states)
269 state.Apply();
270
271 if( instance.redoPerformed != null )
272 instance.redoPerformed();
273 }
274 }
275}
UndoState(IUndo target, string msg)
Definition: Undo.cs:34
void Apply()
Definition: Undo.cs:44
string message
Definition: Undo.cs:23
override string ToString()
Definition: Undo.cs:52
Hashtable values
Definition: Undo.cs:29
static void AddRedoPerformedListener(Callback callback)
Definition: Undo.cs:77
static string PrintRedoStack()
Definition: Undo.cs:99
static string PrintUndoStack()
Definition: Undo.cs:91
static void AddUndoPerformedListener(Callback callback)
Definition: Undo.cs:66
Callback redoPerformed
Definition: Undo.cs:59
Callback undoStackModified
Definition: Undo.cs:60
static string GetCurrentRedo()
Definition: Undo.cs:204
static void PerformUndo()
Definition: Undo.cs:237
Callback undoPerformed
Definition: Undo.cs:58
static void PerformRedo()
Definition: Undo.cs:259
static string GetCurrentUndo()
Definition: Undo.cs:196
Callback redoStackModified
Definition: Undo.cs:61
static void RegisterStates(IEnumerable< IUndo > targets, string message)
Definition: Undo.cs:226
static void RegisterState(IUndo target, string message)
Definition: Undo.cs:214
void ApplyState(Hashtable values)
Hashtable RecordState()
delegate void Callback()