rustapi/docks/
tiles_editor_undo.rs1use crate::prelude::*;
2use theframework::prelude::*;
3
4#[derive(Clone, Debug)]
6pub enum TileEditorUndoAtom {
7 TileEdit(Uuid, rusterix::Tile, rusterix::Tile),
9 TextureEdit(PixelEditingContext, rusterix::Texture, rusterix::Texture),
11 AvatarAnchorEdit(
13 PixelEditingContext,
14 Option<(i16, i16)>,
15 Option<(i16, i16)>,
16 Option<(i16, i16)>,
17 Option<(i16, i16)>,
18 ),
19}
20
21impl TileEditorUndoAtom {
22 pub fn undo(&self, project: &mut Project, _ui: &mut TheUI, ctx: &mut TheContext) {
23 match self {
24 TileEditorUndoAtom::TileEdit(tile_id, prev, _) => {
25 if let Some(tile) = project.tiles.get_mut(tile_id) {
26 *tile = prev.clone();
27
28 ctx.ui.send(TheEvent::Custom(
30 TheId::named("Tile Picked"),
31 TheValue::Id(tile.id),
32 ));
33
34 ctx.ui.send(TheEvent::Custom(
36 TheId::named("Update Tilepicker"),
37 TheValue::Empty,
38 ));
39 }
40 }
41 TileEditorUndoAtom::TextureEdit(editing_ctx, prev, _) => {
42 if let Some(texture) = project.get_editing_texture_mut(editing_ctx) {
43 *texture = prev.clone();
44 }
45 Self::send_editing_context_update(editing_ctx, ctx);
46 }
47 TileEditorUndoAtom::AvatarAnchorEdit(editing_ctx, prev_main, prev_off, _, _) => {
48 if let Some(frame) = project.get_editing_avatar_frame_mut(editing_ctx) {
49 frame.weapon_main_anchor = *prev_main;
50 frame.weapon_off_anchor = *prev_off;
51 }
52 Self::send_editing_context_update(editing_ctx, ctx);
53 }
54 }
55 }
56
57 pub fn redo(&self, project: &mut Project, _ui: &mut TheUI, ctx: &mut TheContext) {
58 match self {
59 TileEditorUndoAtom::TileEdit(tile_id, _, next) => {
60 if let Some(tile) = project.tiles.get_mut(tile_id) {
61 if !tile.textures.is_empty() {
62 *tile = next.clone();
63
64 ctx.ui.send(TheEvent::Custom(
66 TheId::named("Tile Picked"),
67 TheValue::Id(tile.id),
68 ));
69
70 ctx.ui.send(TheEvent::Custom(
72 TheId::named("Update Tilepicker"),
73 TheValue::Empty,
74 ));
75 }
76 }
77 }
78 TileEditorUndoAtom::TextureEdit(editing_ctx, _, next) => {
79 if let Some(texture) = project.get_editing_texture_mut(editing_ctx) {
80 *texture = next.clone();
81 }
82 Self::send_editing_context_update(editing_ctx, ctx);
83 }
84 TileEditorUndoAtom::AvatarAnchorEdit(editing_ctx, _, _, next_main, next_off) => {
85 if let Some(frame) = project.get_editing_avatar_frame_mut(editing_ctx) {
86 frame.weapon_main_anchor = *next_main;
87 frame.weapon_off_anchor = *next_off;
88 }
89 Self::send_editing_context_update(editing_ctx, ctx);
90 }
91 }
92 }
93
94 fn send_editing_context_update(editing_ctx: &PixelEditingContext, ctx: &mut TheContext) {
96 match editing_ctx {
97 PixelEditingContext::None => {}
98 PixelEditingContext::Tile(tile_id, _) => {
99 ctx.ui.send(TheEvent::Custom(
100 TheId::named("Tile Updated"),
101 TheValue::Id(*tile_id),
102 ));
103 ctx.ui.send(TheEvent::Custom(
104 TheId::named("Update Tilepicker"),
105 TheValue::Empty,
106 ));
107 }
108 PixelEditingContext::AvatarFrame(..) => {
109 ctx.ui.send(TheEvent::Custom(
110 TheId::named("Editing Texture Updated"),
111 TheValue::Empty,
112 ));
113 }
114 }
115 }
116}
117
118#[derive(Clone, Debug)]
120pub struct TileEditorUndo {
121 pub stack: Vec<TileEditorUndoAtom>,
122 pub index: isize,
123}
124
125impl Default for TileEditorUndo {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131impl TileEditorUndo {
132 pub fn new() -> Self {
133 Self {
134 stack: vec![],
135 index: -1,
136 }
137 }
138
139 pub fn is_empty(&self) -> bool {
140 self.stack.is_empty()
141 }
142
143 pub fn clear(&mut self) {
144 self.stack = vec![];
145 self.index = -1;
146 }
147
148 pub fn has_undo(&self) -> bool {
149 self.index >= 0
150 }
151
152 pub fn has_redo(&self) -> bool {
153 self.index >= -1 && self.index < self.stack.len() as isize - 1
154 }
155
156 pub fn has_changes(&self) -> bool {
157 self.index >= 0
159 }
160
161 pub fn add(&mut self, atom: TileEditorUndoAtom) {
162 let to_remove = self.stack.len() as isize - self.index - 1;
164 for _i in 0..to_remove {
165 self.stack.pop();
166 }
167 self.stack.push(atom);
168 self.index += 1;
169 }
170
171 pub fn undo(&mut self, project: &mut Project, ui: &mut TheUI, ctx: &mut TheContext) {
172 if self.index >= 0 {
173 self.stack[self.index as usize].undo(project, ui, ctx);
174 self.index -= 1;
175 }
176 }
177
178 pub fn redo(&mut self, project: &mut Project, ui: &mut TheUI, ctx: &mut TheContext) {
179 if self.index < self.stack.len() as isize - 1 {
180 self.index += 1;
181 self.stack[self.index as usize].redo(project, ui, ctx);
182 }
183 }
184
185 pub fn truncate_to_limit(&mut self, limit: usize) {
186 if self.stack.len() > limit {
187 let excess = self.stack.len() - limit;
188 self.stack.drain(0..excess);
189 self.index -= excess as isize;
190 if self.index < -1 {
191 self.index = -1;
192 }
193 }
194 }
195}