crossflow/buffer/
buffer_gate.rs1use bevy_ecs::{
19 change_detection::Mut,
20 prelude::{Commands, Entity, Query},
21 query::QueryEntityError,
22 system::SystemParam,
23};
24
25use crate::{AnyBufferKey, Gate, GateState, NotifyBufferUpdate};
26
27#[derive(SystemParam)]
35pub struct BufferGateAccess<'w, 's> {
36 query: Query<'w, 's, &'static GateState>,
37}
38
39impl<'w, 's> BufferGateAccess<'w, 's> {
40 pub fn get<'a>(
41 &'a self,
42 key: impl Into<AnyBufferKey>,
43 ) -> Result<BufferGateView<'a>, QueryEntityError> {
44 let key: AnyBufferKey = key.into();
45 let session = key.session();
46 self.query
47 .get(key.id())
48 .map(|gate| BufferGateView { gate, session })
49 }
50}
51
52pub struct BufferGateView<'a> {
54 pub(crate) gate: &'a GateState,
55 pub(crate) session: Entity,
56}
57
58impl<'a> BufferGateView<'a> {
59 pub fn gate(&self) -> Gate {
61 self.gate
64 .map
65 .get(&self.session)
66 .copied()
67 .unwrap_or(Gate::Open)
68 }
69}
70
71#[derive(SystemParam)]
79pub struct BufferGateAccessMut<'w, 's> {
80 query: Query<'w, 's, &'static mut GateState>,
81 commands: Commands<'w, 's>,
82}
83
84impl<'w, 's> BufferGateAccessMut<'w, 's> {
85 pub fn get<'a>(
86 &'a self,
87 key: impl Into<AnyBufferKey>,
88 ) -> Result<BufferGateView<'a>, QueryEntityError> {
89 let key: AnyBufferKey = key.into();
90 let session = key.session();
91 self.query
92 .get(key.id())
93 .map(|gate| BufferGateView { gate, session })
94 }
95
96 pub fn get_mut<'a>(
97 &'a mut self,
98 key: impl Into<AnyBufferKey>,
99 ) -> Result<BufferGateMut<'w, 's, 'a>, QueryEntityError> {
100 let key: AnyBufferKey = key.into();
101 let buffer = key.id();
102 let session = key.session();
103 let accessor = key.tag.accessor;
104 self.query
105 .get_mut(buffer)
106 .map(|gate| BufferGateMut::new(gate, buffer, session, accessor, &mut self.commands))
107 }
108}
109
110pub struct BufferGateMut<'w, 's, 'a> {
112 gate: Mut<'a, GateState>,
113 buffer: Entity,
114 session: Entity,
115 accessor: Option<Entity>,
116 commands: &'a mut Commands<'w, 's>,
117 modified: bool,
118}
119
120impl<'w, 's, 'a> BufferGateMut<'w, 's, 'a> {
121 pub fn allow_closed_loops(mut self) -> Self {
123 self.accessor = None;
124 self
125 }
126
127 pub fn get(&self) -> Gate {
129 self.gate
130 .map
131 .get(&self.session)
132 .copied()
133 .unwrap_or(Gate::Open)
134 }
135
136 pub fn open_gate(&mut self) {
138 if let Some(gate) = self.gate.map.get_mut(&self.session) {
139 if *gate != Gate::Open {
140 *gate = Gate::Open;
141 self.modified = true;
142 }
143 }
144 }
145
146 pub fn close_gate(&mut self) {
148 if let Some(gate) = self.gate.map.get_mut(&self.session) {
149 *gate = Gate::Closed;
150 }
153 }
154
155 pub fn gate_action(&mut self, action: Gate) {
157 match action {
158 Gate::Open => self.open_gate(),
159 Gate::Closed => self.close_gate(),
160 }
161 }
162
163 fn new(
164 gate: Mut<'a, GateState>,
165 buffer: Entity,
166 session: Entity,
167 accessor: Entity,
168 commands: &'a mut Commands<'w, 's>,
169 ) -> Self {
170 Self {
171 gate,
172 buffer,
173 session,
174 accessor: Some(accessor),
175 commands,
176 modified: false,
177 }
178 }
179}
180
181impl<'w, 's, 'a> Drop for BufferGateMut<'w, 's, 'a> {
182 fn drop(&mut self) {
183 if self.modified {
184 self.commands.queue(NotifyBufferUpdate::new(
185 self.buffer,
186 self.session,
187 self.accessor,
188 ));
189 }
190 }
191}