1use crate::reflect::{ComponentSnapshot, SnapshotKind, restore_component, snapshot_component};
7use nightshade::prelude::{Entity, World};
8
9struct Change {
10 entity: Entity,
11 kind: SnapshotKind,
12 snapshot: ComponentSnapshot,
13}
14
15#[derive(Default)]
19pub struct UndoStack {
20 undo: Vec<Vec<Change>>,
21 redo: Vec<Vec<Change>>,
22 pending: Vec<Change>,
23}
24
25impl UndoStack {
26 pub fn new() -> Self {
28 Self::default()
29 }
30
31 pub fn capture(&mut self, world: &World, entity: Entity, kind: SnapshotKind) {
35 if let Some(snapshot) = snapshot_component(world, entity, kind) {
36 self.pending.push(Change {
37 entity,
38 kind,
39 snapshot,
40 });
41 }
42 }
43
44 pub fn commit(&mut self) {
48 if self.pending.is_empty() {
49 return;
50 }
51 let transaction = std::mem::take(&mut self.pending);
52 self.undo.push(transaction);
53 self.redo.clear();
54 }
55
56 pub fn undo(&mut self, world: &mut World) -> bool {
60 let Some(transaction) = self.undo.pop() else {
61 return false;
62 };
63 let mut redo_transaction = Vec::with_capacity(transaction.len());
64 for change in &transaction {
65 if let Some(current) = snapshot_component(world, change.entity, change.kind) {
66 redo_transaction.push(Change {
67 entity: change.entity,
68 kind: change.kind,
69 snapshot: current,
70 });
71 }
72 restore_component(&change.snapshot, world, change.entity);
73 }
74 self.redo.push(redo_transaction);
75 true
76 }
77
78 pub fn redo(&mut self, world: &mut World) -> bool {
81 let Some(transaction) = self.redo.pop() else {
82 return false;
83 };
84 let mut undo_transaction = Vec::with_capacity(transaction.len());
85 for change in &transaction {
86 if let Some(current) = snapshot_component(world, change.entity, change.kind) {
87 undo_transaction.push(Change {
88 entity: change.entity,
89 kind: change.kind,
90 snapshot: current,
91 });
92 }
93 restore_component(&change.snapshot, world, change.entity);
94 }
95 self.undo.push(undo_transaction);
96 true
97 }
98
99 pub fn can_undo(&self) -> bool {
101 !self.undo.is_empty()
102 }
103
104 pub fn can_redo(&self) -> bool {
106 !self.redo.is_empty()
107 }
108
109 pub fn clear(&mut self) {
111 self.undo.clear();
112 self.redo.clear();
113 self.pending.clear();
114 }
115}