bevy_cobweb/react/
react_component.rs1use crate::prelude::*;
3
4use bevy::prelude::*;
6use bevy::ecs::system::SystemParam;
7
8use core::ops::Deref;
10use std::any::type_name;
11
12pub trait ReactComponent: Send + Sync + 'static {}
18
19#[derive(Component)]
25pub struct React<C: ReactComponent>
26{
27 pub(crate) entity : Entity,
28 pub(crate) component : C,
29}
30
31impl<C: ReactComponent> React<C>
32{
33 pub fn new_unsafe(component: C) -> Self
35 {
36 Self{ entity: Entity::PLACEHOLDER, component }
37 }
38
39 pub fn get(&self) -> &C
41 {
42 &self.component
43 }
44
45 pub fn get_mut<'a>(&'a mut self, c: &mut Commands) -> &'a mut C
47 {
48 c.syscall(self.entity, ReactCache::schedule_mutation_reaction::<C>);
49 &mut self.component
50 }
51
52 pub fn trigger_mutation(entity: Entity, world: &mut World)
54 {
55 world.syscall(entity, ReactCache::schedule_mutation_reaction::<C>);
56 }
57
58 pub fn get_noreact(&mut self) -> &mut C
60 {
61 &mut self.component
62 }
63
64 pub fn set_if_neq(&mut self, c: &mut Commands, new: C) -> Option<C>
68 where
69 C: PartialEq
70 {
71 if new == self.component { return None; }
72
73 c.syscall(self.entity, ReactCache::schedule_mutation_reaction::<C>);
74 let old = std::mem::replace(&mut self.component, new);
75 Some(old)
76 }
77
78 pub fn take(self) -> C
80 {
81 self.component
82 }
83}
84
85impl<C: ReactComponent> Deref for React<C>
86{
87 type Target = C;
88
89 fn deref(&self) -> &C
90 {
91 &self.component
92 }
93}
94
95#[derive(SystemParam)]
101pub struct Reactive<'w, 's, T: ReactComponent>
102{
103 components: Query<'w, 's, (Entity, &'static React<T>)>,
104}
105
106impl<'w, 's, T: ReactComponent> Reactive<'w, 's, T>
107{
108 pub fn get(&self, entity: Entity) -> Result<&T, CobwebReactError>
112 {
113 let t = type_name::<T>();
114 self.components.get(entity).map(|(_, c)| c.get()).map_err(|_| CobwebReactError::Reactive(entity, t))
115 }
116
117 pub fn single(&self) -> (Entity, &T)
123 {
124 let (e, x) = self.components.single().unwrap();
125 (e, x.get())
126 }
127}
128
129#[derive(SystemParam)]
135pub struct ReactiveMut<'w, 's, T: ReactComponent>
136{
137 components: Query<'w, 's, (Entity, &'static mut React<T>)>,
138}
139
140impl<'w, 's, T: ReactComponent> ReactiveMut<'w, 's, T>
141{
142 pub fn get(&self, entity: Entity) -> Result<&T, CobwebReactError>
146 {
147 let t = type_name::<T>();
148 self.components.get(entity).map(|(_, c)| c.get()).map_err(|_| CobwebReactError::ReactiveMut(entity, t))
149 }
150
151 pub fn single(&self) -> (Entity, &T)
157 {
158 let (e, x) = self.components.single().unwrap();
159 (e, x.get())
160 }
161
162 pub fn get_mut(&mut self, c: &mut Commands, entity: Entity) -> Result<&mut T, CobwebReactError>
166 {
167 let t = type_name::<T>();
168 let (_, x) = self.components.get_mut(entity).map_err(|_| CobwebReactError::ReactiveMut(entity, t))?;
169 Ok(x.into_inner().get_mut(c))
170 }
171
172 pub fn single_mut(&mut self, c: &mut Commands) -> (Entity, &mut T)
178 {
179 let (e, x) = self.components.single_mut().unwrap();
180 (e, x.into_inner().get_mut(c))
181 }
182
183 pub fn get_noreact(&mut self, entity: Entity) -> Result<&mut T, CobwebReactError>
187 {
188 let t = type_name::<T>();
189 let (_, x) = self.components.get_mut(entity).map_err(|_| CobwebReactError::ReactiveMut(entity, t))?;
190 Ok(x.into_inner().get_noreact())
191 }
192
193 pub fn single_noreact(&mut self) -> (Entity, &mut T)
199 {
200 let (e, x) = self.components.single_mut().unwrap();
201 (e, x.into_inner().get_noreact())
202 }
203
204 pub fn set_if_neq(&mut self, c: &mut Commands, entity: Entity, new: T) -> Option<T>
208 where
209 T: PartialEq
210 {
211 let (_, mut x) = self.components.get_mut(entity).ok()?;
212 (*x).set_if_neq(c, new)
213 }
214
215 pub fn set_single_if_not_eq(&mut self, c: &mut Commands, new: T) -> (Entity, Option<T>)
221 where
222 T: PartialEq
223 {
224 let (e, mut x) = self.components.single_mut().unwrap();
225 (e, (*x).set_if_neq(c, new))
226 }
227}
228
229