1use bevy::app::{App, Update};
2use bevy::prelude::{Event, EventReader, EventWriter, IntoSystemConfigs, ResMut};
3use crate::{CommitReservationsEvent, DecrementCounterEvent, UndoRegisteredArea};
4use crate::request::RequestUndoEvent;
5use crate::reserve::{ReserveCounter, UndoReservedArea, UndoReserveEvent};
6use crate::undo_event::UndoEvent;
7
8
9pub trait AppUndoEx {
10 fn add_undo_event<T: Event + Clone>(&mut self) -> &mut App;
15}
16
17
18impl AppUndoEx for App {
19 fn add_undo_event<E: Event + Clone>(&mut self) -> &mut App {
20 self.add_event::<E>();
21 self.add_event::<UndoEvent<E>>();
22 self.add_event::<UndoReserveEvent<E>>();
23 self.init_resource::<UndoRegisteredArea<E>>();
24 self.init_resource::<UndoRegisteredArea<UndoReserveEvent<E>>>();
25 self.init_resource::<UndoReservedArea<E>>();
26 self.init_resource::<ReserveCounter>();
27 self.add_systems(Update, (
28 register_all_reserved_events_system::<E>,
29 push_undo_event_system::<E>,
30 pop_undo_event_system::<E>,
31 pop_undo_event_system::<E>,
32 pop_undo_event_system::<UndoReserveEvent<E>>,
33 reserve_event_system::<E>
34 ).chain());
35 self
36 }
37}
38
39
40fn register_all_reserved_events_system<E: Event + Clone>(
41 mut er: EventReader<CommitReservationsEvent>,
42 mut preserve: ResMut<UndoReservedArea<E>>,
43 mut registered_reserve_event_area: ResMut<UndoRegisteredArea<UndoReserveEvent<E>>>,
44) {
45 if let Some(CommitReservationsEvent(counter)) = er.iter().next() {
46 while let Some(event) = preserve.pop() {
47 registered_reserve_event_area.push(UndoEvent {
48 inner: event.clone(),
49 no: **counter + event.reserve_no,
50 });
51 }
52 }
53}
54
55
56fn push_undo_event_system<E: Event + Clone>(
57 mut er: EventReader<UndoEvent<E>>,
58 mut registered_area: ResMut<UndoRegisteredArea<E>>,
59) {
60 for e in er.iter() {
61 registered_area.push(e.clone());
62 }
63}
64
65
66fn pop_undo_event_system<E: Event + Clone>(
67 mut er: EventReader<RequestUndoEvent>,
68 mut ew: EventWriter<E>,
69 mut decrement_writer: EventWriter<DecrementCounterEvent>,
70 mut registered_area: ResMut<UndoRegisteredArea<E>>,
71) {
72 for RequestUndoEvent(counter) in er.iter() {
73 while let Some(undo) = registered_area.pop_if_has_latest(counter) {
74 ew.send(undo);
75 decrement_writer.send(DecrementCounterEvent);
76 }
77 }
78}
79
80
81fn reserve_event_system<E: Event + Clone>(
82 mut er: EventReader<UndoReserveEvent<E>>,
83 mut ew: EventWriter<E>,
84 mut registered_area: ResMut<UndoRegisteredArea<UndoReserveEvent<E>>>,
85 mut decrement_writer: EventWriter<DecrementCounterEvent>,
86) {
87 if er.is_empty() {
88 return;
89 }
90
91 for event in er.iter() {
92 ew.send(event.inner.clone());
93 if event.reserve_no == 1{
94 return;
95 }
96 }
97
98 while let Some(event) = registered_area.pop() {
99 ew.send(event.inner.clone());
100 decrement_writer.send(DecrementCounterEvent);
101 if event.reserve_no == 1{
102 return;
103 }
104 }
105}
106
107