@@ -13,7 +13,7 @@ use crate::{
1313use anyhow:: Result ;
1414use winit:: {
1515 dpi:: PhysicalSize ,
16- event:: { ElementState , Event , KeyEvent , MouseButton , WindowEvent } ,
16+ event:: { ElementState , Event , KeyEvent , Modifiers , MouseButton , WindowEvent } ,
1717 event_loop:: EventLoop ,
1818 keyboard:: { KeyCode , PhysicalKey } ,
1919 window:: { CursorIcon , Window , WindowBuilder } ,
@@ -30,7 +30,8 @@ pub struct AppState<'a> {
3030 pub feature_uniform : FeatureUniform ,
3131 pub draw_uniform : DrawUniform ,
3232 pub mouse_state : MouseState ,
33- pub shape_stack : RevisionStack ,
33+ pub revision_stack : RevisionStack ,
34+ pub modifiers : Modifiers ,
3435
3536 pub image_shader : Shader ,
3637 pub shape_shader : Shader ,
@@ -91,7 +92,8 @@ impl<'a> AppState<'a> {
9192 ) ;
9293
9394 let mouse_state = MouseState :: default ( ) ;
94- let shape_stack = RevisionStack :: new ( ) ;
95+ let revision_stack = RevisionStack :: default ( ) ;
96+ let modifiers = Modifiers :: default ( ) ;
9597
9698 Ok ( Self {
9799 gpu_allocator,
@@ -100,7 +102,8 @@ impl<'a> AppState<'a> {
100102 feature_uniform,
101103 draw_uniform,
102104 mouse_state,
103- shape_stack,
105+ revision_stack,
106+ modifiers,
104107 image_shader,
105108 shape_shader,
106109 shape_render_texture,
@@ -159,7 +162,7 @@ impl<'a> AppState<'a> {
159162 let normalized_radius =
160163 radius / ( self . size . width . min ( self . size . height ) as f32 ) ;
161164
162- self . shape_stack . push ( Shape :: Circle {
165+ self . revision_stack . push_shape ( Shape :: Circle {
163166 x : normalized_x,
164167 y : normalized_y,
165168 radius : normalized_radius,
@@ -180,24 +183,25 @@ impl<'a> AppState<'a> {
180183 let normalized_x = mouse_x / self . size . width as f32 ;
181184 let normalized_y = mouse_y / self . size . height as f32 ;
182185
183- if let Some ( circle_index) = self . shape_stack . find_shape_at_point (
184- normalized_x,
185- normalized_y,
186- self . size . width ,
187- self . size . height ,
188- ) {
186+ if let Some ( circle_index) =
187+ self . revision_stack . shape_stack . find_shape_at_point (
188+ normalized_x,
189+ normalized_y,
190+ self . size . width ,
191+ self . size . height ,
192+ )
193+ {
189194 // Found a circle - select it and start dragging
190195 self . mouse_state . set_selected_shape ( Some ( circle_index) ) ;
191196 self . mouse_state . set_dragging_shape ( true ) ;
192197
193198 // Calculate offset from circle center to mouse position
194- if let Some ( Shape :: Circle { x, y, .. } ) =
195- self . shape_stack . shapes ( ) . get ( circle_index)
196- {
197- let offset_x = normalized_x - x;
198- let offset_y = normalized_y - y;
199- self . mouse_state . set_drag_offset ( ( offset_x, offset_y) ) ;
200- }
199+ let Shape :: Circle { x, y, .. } =
200+ self . revision_stack . shape_stack . get_unchecked ( circle_index) ;
201+
202+ let offset_x = normalized_x - x;
203+ let offset_y = normalized_y - y;
204+ self . mouse_state . set_drag_offset ( ( offset_x, offset_y) ) ;
201205 } else {
202206 // Clicked on empty space - deselect any selected circle
203207 self . mouse_state . set_selected_shape ( None ) ;
@@ -234,13 +238,20 @@ impl<'a> AppState<'a> {
234238 let new_y = normalized_y - offset_y;
235239
236240 // Move the circle to the new position
237- self . shape_stack . move_shape ( selected_index, new_x, new_y) ;
241+ self . revision_stack . shape_stack . move_shape (
242+ selected_index,
243+ new_x,
244+ new_y,
245+ ) ;
238246 }
239247 }
240248 }
241249
242250 self . mouse_state . update_position ( x, y) ;
243251 }
252+ WindowEvent :: ModifiersChanged ( new_modifiers) => {
253+ self . modifiers = * new_modifiers;
254+ }
244255 WindowEvent :: KeyboardInput {
245256 event :
246257 KeyEvent {
@@ -305,11 +316,22 @@ impl<'a> AppState<'a> {
305316 | ( KeyCode :: Backspace , ElementState :: Pressed ) => {
306317 // Delete the selected circle
307318 if let Some ( selected_index) = self . mouse_state . selected_shape ( ) {
308- self . shape_stack . remove_shape ( selected_index) ;
319+ self . revision_stack . shape_stack . remove_shape ( selected_index) ;
309320 self . mouse_state . set_selected_shape ( None ) ;
310321 self . mouse_state . set_dragging_shape ( false ) ;
311322 }
312323 }
324+ ( KeyCode :: KeyZ , ElementState :: Pressed ) => {
325+ #[ cfg( target_os = "macos" ) ]
326+ if self . modifiers . state ( ) . super_key ( ) {
327+ self . revision_stack . undo ( ) ;
328+ }
329+
330+ #[ cfg( not( target_os = "macos" ) ) ]
331+ if self . modifiers . state ( ) . control_key ( ) {
332+ self . revision_stack . undo ( ) ;
333+ }
334+ }
313335 _ => return false ,
314336 } ,
315337 _ => return false ,
@@ -331,8 +353,7 @@ impl<'a> AppState<'a> {
331353 }
332354
333355 fn update_shape_data ( & mut self ) {
334- let shapes = self . shape_stack . shapes ( ) ;
335- let num_circles = shapes. len ( ) . min ( MAX_CIRCLES ) ;
356+ let num_circles = self . revision_stack . shape_stack . len ( ) . min ( MAX_CIRCLES ) ;
336357
337358 self . shape_uniform . set_num_circles ( num_circles as u32 ) ;
338359 self . shape_uniform
@@ -345,7 +366,14 @@ impl<'a> AppState<'a> {
345366
346367 // Update circle storage buffer
347368 let mut circle_data = vec ! [ CircleData :: default ( ) ; MAX_CIRCLES ] ;
348- for ( i, shape) in shapes. iter ( ) . take ( MAX_CIRCLES ) . enumerate ( ) {
369+ for ( i, ( _, shape) ) in self
370+ . revision_stack
371+ . shape_stack
372+ . shapes ( )
373+ . into_iter ( )
374+ . take ( MAX_CIRCLES )
375+ . enumerate ( )
376+ {
349377 circle_data[ i] = CircleData :: from ( shape) ;
350378 }
351379
0 commit comments