bevy_ecs/system/
schedule_system.rs

1use bevy_utils::prelude::DebugName;
2
3use crate::{
4    component::{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        self.system.run_unsafe(&mut self.value, world)
70    }
71
72    #[cfg(feature = "hotpatching")]
73    #[inline]
74    fn refresh_hotpatch(&mut self) {
75        self.system.refresh_hotpatch();
76    }
77
78    fn apply_deferred(&mut self, world: &mut World) {
79        self.system.apply_deferred(world);
80    }
81
82    fn queue_deferred(&mut self, world: DeferredWorld) {
83        self.system.queue_deferred(world);
84    }
85
86    unsafe fn validate_param_unsafe(
87        &mut self,
88        world: UnsafeWorldCell,
89    ) -> Result<(), SystemParamValidationError> {
90        self.system.validate_param_unsafe(world)
91    }
92
93    fn initialize(&mut self, world: &mut World) -> FilteredAccessSet {
94        self.system.initialize(world)
95    }
96
97    fn check_change_tick(&mut self, check: CheckChangeTicks) {
98        self.system.check_change_tick(check);
99    }
100
101    fn get_last_run(&self) -> Tick {
102        self.system.get_last_run()
103    }
104
105    fn set_last_run(&mut self, last_run: Tick) {
106        self.system.set_last_run(last_run);
107    }
108}
109
110/// Constructed in [`IntoSystem::with_input_from`].
111pub struct WithInputFromWrapper<S, T> {
112    system: S,
113    value: Option<T>,
114}
115
116impl<S, T> WithInputFromWrapper<S, T>
117where
118    for<'i> S: System<In: SystemInput<Inner<'i> = &'i mut T>>,
119    T: Send + Sync + 'static,
120{
121    /// Wraps the given system.
122    pub fn new<M>(system: impl IntoSystem<S::In, S::Out, M, System = S>) -> Self {
123        Self {
124            system: IntoSystem::into_system(system),
125            value: None,
126        }
127    }
128
129    /// Returns a reference to the input value, if it has been initialized.
130    pub fn value(&self) -> Option<&T> {
131        self.value.as_ref()
132    }
133
134    /// Returns a mutable reference to the input value, if it has been initialized.
135    pub fn value_mut(&mut self) -> Option<&mut T> {
136        self.value.as_mut()
137    }
138}
139
140impl<S, T> System for WithInputFromWrapper<S, T>
141where
142    for<'i> S: System<In: SystemInput<Inner<'i> = &'i mut T>>,
143    T: FromWorld + Send + Sync + 'static,
144{
145    type In = ();
146    type Out = S::Out;
147
148    fn name(&self) -> DebugName {
149        self.system.name()
150    }
151
152    #[inline]
153    fn flags(&self) -> SystemStateFlags {
154        self.system.flags()
155    }
156
157    unsafe fn run_unsafe(
158        &mut self,
159        _input: SystemIn<'_, Self>,
160        world: UnsafeWorldCell,
161    ) -> Result<Self::Out, RunSystemError> {
162        let value = self
163            .value
164            .as_mut()
165            .expect("System input value was not found. Did you forget to initialize the system before running it?");
166        self.system.run_unsafe(value, world)
167    }
168
169    #[cfg(feature = "hotpatching")]
170    #[inline]
171    fn refresh_hotpatch(&mut self) {
172        self.system.refresh_hotpatch();
173    }
174
175    fn apply_deferred(&mut self, world: &mut World) {
176        self.system.apply_deferred(world);
177    }
178
179    fn queue_deferred(&mut self, world: DeferredWorld) {
180        self.system.queue_deferred(world);
181    }
182
183    unsafe fn validate_param_unsafe(
184        &mut self,
185        world: UnsafeWorldCell,
186    ) -> Result<(), SystemParamValidationError> {
187        self.system.validate_param_unsafe(world)
188    }
189
190    fn initialize(&mut self, world: &mut World) -> FilteredAccessSet {
191        if self.value.is_none() {
192            self.value = Some(T::from_world(world));
193        }
194        self.system.initialize(world)
195    }
196
197    fn check_change_tick(&mut self, check: CheckChangeTicks) {
198        self.system.check_change_tick(check);
199    }
200
201    fn get_last_run(&self) -> Tick {
202        self.system.get_last_run()
203    }
204
205    fn set_last_run(&mut self, last_run: Tick) {
206        self.system.set_last_run(last_run);
207    }
208}
209
210/// Type alias for a `BoxedSystem` that a `Schedule` can store.
211pub type ScheduleSystem = BoxedSystem<(), ()>;