1 /*
2 Copyright © 2020, Luna Nielsen
3 Distributed under the 2-Clause BSD License, see LICENSE file.
4
5 Authors: Luna Nielsen
6 */
7 module engine.core.astack;
8 import std.exception;
9
10 /**
11 A stack of actions performed in the game
12
13 Actions can be undone and redone.
14 Pushing a new action to the stack will overwrite actions past the current top cursor.
15 */
16 class ActionStack(ActionT) {
17 private:
18 ActionT[] stack;
19 size_t top;
20
21 public:
22
23 /**
24 Push an action to the stack
25
26 Returns the resulting top of the stack
27 */
28 ActionT push(ActionT item) {
29
30 // First remove any elements in the undo/redo chain after our top
31 stack.length = top+1;
32
33 // Move the top up one element
34 top++;
35
36 // Add new item
37 stack ~= item;
38 return stack[$-1];
39 }
40
41 /**
42 Get the current top of the stack
43 */
44 ActionT get() {
45 enforce(stack.length > 0, "ActionStack is empty.");
46 return stack[top];
47 }
48
49 /**
50 Undo an action
51
52 Returns the resulting top of the stack
53 */
54 ActionT undo() {
55 enforce(stack.length > 0, "ActionStack is empty.");
56 if (top > 0) top--;
57 return stack[top];
58 }
59
60 /**
61 Redo an action
62
63 Returns the resulting top of the stack
64 */
65 ActionT redo() {
66 enforce(stack.length > 0, "ActionStack is empty.");
67 if (top < stack.length) top++;
68 return stack[top];
69 }
70
71 /**
72 Clear the action stack
73 */
74 void clear() {
75 top = 0;
76 stack.length = 0;
77 }
78
79 /**
80 Gets whether the action stack is empty.
81 */
82 bool empty() {
83 return stack.length == 0;
84 }
85
86 /**
87 Returns true if there's any actions left to undo
88 */
89 bool canUndo() {
90 return top > 0;
91 }
92
93 /**
94 Returns true if there's any actions left to redo
95 */
96 bool canRedo() {
97 return top < stack.length;
98 }
99 }