bevy_ecs/system/
schedule_system.rs

1use bevy_utils::prelude::DebugName;
2
3use crate::{
4    change_detection::{CheckChangeTicks, Tick},
5    error::Result,
6    query::FilteredAccessSet,
7    system::{input::SystemIn, BoxedSystem, RunSystemError, System, SystemInput},
8    world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FromWorld, World},
9};
10
11use super::{IntoSystem, SystemParamValidationError, SystemStateFlags};
12
13/// See [`IntoSystem::with_input`] for details.
14pub struct WithInputWrapper<S, T>
15where
16    for<'i> S: System<In: SystemInput<Inner<'i> = &'i mut T>>,
17    T: Send + Sync + 'static,
18{
19    system: S,
20    value: T,
21}
22
23impl<S, T> WithInputWrapper<S, T>
24where
25    for<'i> S: System<In: SystemInput<Inner<'i> = &'i mut T>>,
26    T: Send + Sync + 'static,
27{
28    /// Wraps the given system with the given input value.
29    pub fn new<M>(system: impl IntoSystem<S::In, S::Out, M, System = S>, value: T) -> Self {
30        Self {
31            system: IntoSystem::into_system(system),
32            value,
33        }
34    }
35
36    /// Returns a reference to the input value.
37    pub fn value(&self) -> &T {
38        &self.value
39    }
40
41    /// Returns a mutable reference to the input value.
42    pub fn value_mut(&mut self) -> &mut T {
43        &mut self.value
44    }
45}
46
47impl<S, T> System for WithInputWrapper<S, T>
48where
49    for<'i> S: System<In: SystemInput<Inner<'i> = &'i mut T>>,
50    T: Send + Sync + 'static,
51{
52    type In = ();
53    type Out = S::Out;
54
55    fn name(&self) -> DebugName {
56        self.system.name()
57    }
58
59    #[inline]
60    fn flags(&self) -> SystemStateFlags {
61        self.system.flags()
62    }
63
64    unsafe fn run_unsafe(
65        &mut self,
66        _input: SystemIn<'_, Self>,
67        world: UnsafeWorldCell,
68    ) -> Result<Self::Out, RunSystemError> {
69        // SAFETY: Upheld by caller
70        unsafe { self.system.run_unsafe(&mut self.value, world) }
71    }
72
73    #[cfg(feature = "hotpatching")]
74    #[inline]
75    fn refresh_hotpatch(&mut self) {
76        self.system.refresh_hotpatch();
77    }
78
79    fn apply_deferred(&mut self, world: &mut World) {
80        self.system.apply_deferred(world);
81    }
82
83    fn queue_deferred(&mut self, world: DeferredWorld) {
84        self.system.queue_deferred(world);
85    }
86
87    unsafe fn validate_param_unsafe(
88        &mut self,
89        world: UnsafeWorldCell,
90    ) -> Result<(), SystemParamValidationError> {
91        // SAFETY: Upheld by caller
92        unsafe { self.system.validate_param_unsafe(world) }
93    }
94
95    fn initialize(&mut self, world: &mut World) -> FilteredAccessSet {
96        self.system.initialize(world)
97    }
98
99    fn check_change_tick(&mut self, check: CheckChangeTicks) {
100        self.system.check_change_tick(check);
101    }
102
103    fn get_last_run(&self) -> Tick {
104        self.system.get_last_run()
105    }
106
107    fn set_last_run(&mut self, last_run: Tick) {
108        self.system.set_last_run(last_run);
109    }
110}
111
112/// Constructed in [`IntoSystem::with_input_from`].
113pub struct WithInputFromWrapper<S, T> {
114    system: S,
115    value: Option<T>,
116}
117
118impl<S, T> WithInputFromWrapper<S, T>
119where
120    for<'i> S: System<In: SystemInput<Inner<'i> = &'i mut T>>,
121    T: Send + Sync + 'static,
122{
123    /// Wraps the given system.
124    pub fn new<M>(system: impl IntoSystem<S::In, S::Out, M, System = S>) -> Self {
125        Self {
126            system: IntoSystem::into_system(system),
127            value: None,
128        }
129    }
130
131    /// Returns a reference to the input value, if it has been initialized.
132    pub fn value(&self) -> Option<&T> {
133        self.value.as_ref()
134    }
135
136    /// Returns a mutable reference to the input value, if it has been initialized.
137    pub fn value_mut(&mut self) -> Option<&mut T> {
138        self.value.as_mut()
139    }
140}
141
142impl<S, T> System for WithInputFromWrapper<S, T>
143where
144    for<'i> S: System<In: SystemInput<Inner<'i> = &'i mut T>>,
145    T: FromWorld + Send + Sync + 'static,
146{
147    type In = ();
148    type Out = S::Out;
149
150    fn name(&self) -> DebugName {
151        self.system.name()
152    }
153
154    #[inline]
155    fn flags(&self) -> SystemStateFlags {
156        self.system.flags()
157    }
158
159    unsafe fn run_unsafe(
160        &mut self,
161        _input: SystemIn<'_, Self>,
162        world: UnsafeWorldCell,
163    ) -> Result<Self::Out, RunSystemError> {
164        let value = self
165            .value
166            .as_mut()
167            .expect("System input value was not found. Did you forget to initialize the system before running it?");
168        // SAFETY: Upheld by caller
169        unsafe { self.system.run_unsafe(value, world) }
170    }
171
172    #[cfg(feature = "hotpatching")]
173    #[inline]
174    fn refresh_hotpatch(&mut self) {
175        self.system.refresh_hotpatch();
176    }
177
178    fn apply_deferred(&mut self, world: &mut World) {
179        self.system.apply_deferred(world);
180    }
181
182    fn queue_deferred(&mut self, world: DeferredWorld) {
183        self.system.queue_deferred(world);
184    }
185
186    unsafe fn validate_param_unsafe(
187        &mut self,
188        world: UnsafeWorldCell,
189    ) -> Result<(), SystemParamValidationError> {
190        // SAFETY: Upheld by caller
191        unsafe { self.system.validate_param_unsafe(world) }
192    }
193
194    fn initialize(&mut self, world: &mut World) -> FilteredAccessSet {
195        if self.value.is_none() {
196            self.value = Some(T::from_world(world));
197        }
198        self.system.initialize(world)
199    }
200
201    fn check_change_tick(&mut self, check: CheckChangeTicks) {
202        self.system.check_change_tick(check);
203    }
204
205    fn get_last_run(&self) -> Tick {
206        self.system.get_last_run()
207    }
208
209    fn set_last_run(&mut self, last_run: Tick) {
210        self.system.set_last_run(last_run);
211    }
212}
213
214/// Type alias for a `BoxedSystem` that a `Schedule` can store.
215pub type ScheduleSystem = BoxedSystem<(), ()>;