Thanks to visit codestin.com
Credit goes to docs.rs

bevy_ecs/system/
input.rs

1use core::ops::{Deref, DerefMut};
2
3use variadics_please::all_tuples;
4
5use crate::{bundle::Bundle, event::Event, prelude::On, system::System};
6
7/// Trait for types that can be used as input to [`System`]s.
8///
9/// Provided implementations are:
10/// - `()`: No input
11/// - [`In<T>`]: For values
12/// - [`InRef<T>`]: For read-only references to values
13/// - [`InMut<T>`]: For mutable references to values
14/// - [`On<E, B>`]: For [`ObserverSystem`]s
15/// - [`StaticSystemInput<I>`]: For arbitrary [`SystemInput`]s in generic contexts
16/// - Tuples of [`SystemInput`]s up to 8 elements
17///
18/// For advanced usecases, you can implement this trait for your own types.
19///
20/// # Examples
21///
22/// ## Tuples of [`SystemInput`]s
23///
24/// ```
25/// use bevy_ecs::prelude::*;
26///
27/// fn add((InMut(a), In(b)): (InMut<usize>, In<usize>)) {
28///     *a += b;
29/// }
30/// # let mut world = World::new();
31/// # let mut add = IntoSystem::into_system(add);
32/// # add.initialize(&mut world);
33/// # let mut a = 12;
34/// # let b = 24;
35/// # add.run((&mut a, b), &mut world);
36/// # assert_eq!(a, 36);
37/// ```
38///
39/// [`ObserverSystem`]: crate::system::ObserverSystem
40pub trait SystemInput: Sized {
41    /// The wrapper input type that is defined as the first argument to [`FunctionSystem`]s.
42    ///
43    /// [`FunctionSystem`]: crate::system::FunctionSystem
44    type Param<'i>: SystemInput;
45    /// The inner input type that is passed to functions that run systems,
46    /// such as [`System::run`].
47    ///
48    /// [`System::run`]: crate::system::System::run
49    type Inner<'i>;
50
51    /// Converts a [`SystemInput::Inner`] into a [`SystemInput::Param`].
52    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_>;
53}
54
55/// Shorthand way to get the [`System::In`] for a [`System`] as a [`SystemInput::Inner`].
56pub type SystemIn<'a, S> = <<S as System>::In as SystemInput>::Inner<'a>;
57
58/// A [`SystemInput`] type which denotes that a [`System`] receives
59/// an input value of type `T` from its caller.
60///
61/// [`System`]s may take an optional input which they require to be passed to them when they
62/// are being [`run`](System::run). For [`FunctionSystem`]s the input may be marked
63/// with this `In` type, but only the first param of a function may be tagged as an input. This also
64/// means a system can only have one or zero input parameters.
65///
66/// See [`SystemInput`] to learn more about system inputs in general.
67///
68/// # Examples
69///
70/// Here is a simple example of a system that takes a [`usize`] and returns the square of it.
71///
72/// ```
73/// # use bevy_ecs::prelude::*;
74/// #
75/// fn square(In(input): In<usize>) -> usize {
76///     input * input
77/// }
78///
79/// let mut world = World::new();
80/// let mut square_system = IntoSystem::into_system(square);
81/// square_system.initialize(&mut world);
82///
83/// assert_eq!(square_system.run(12, &mut world).unwrap(), 144);
84/// ```
85///
86/// [`SystemParam`]: crate::system::SystemParam
87/// [`FunctionSystem`]: crate::system::FunctionSystem
88#[derive(Debug)]
89pub struct In<T>(pub T);
90
91impl<T: 'static> SystemInput for In<T> {
92    type Param<'i> = In<T>;
93    type Inner<'i> = T;
94
95    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
96        In(this)
97    }
98}
99
100impl<T> Deref for In<T> {
101    type Target = T;
102
103    fn deref(&self) -> &Self::Target {
104        &self.0
105    }
106}
107
108impl<T> DerefMut for In<T> {
109    fn deref_mut(&mut self) -> &mut Self::Target {
110        &mut self.0
111    }
112}
113
114/// A [`SystemInput`] type which denotes that a [`System`] receives
115/// a read-only reference to a value of type `T` from its caller.
116///
117/// This is similar to [`In`] but takes a reference to a value instead of the value itself.
118/// See [`InMut`] for the mutable version.
119///
120/// See [`SystemInput`] to learn more about system inputs in general.
121///
122/// # Examples
123///
124/// Here is a simple example of a system that logs the passed in message.
125///
126/// ```
127/// # use bevy_ecs::prelude::*;
128/// # use std::fmt::Write as _;
129/// #
130/// #[derive(Resource, Default)]
131/// struct Log(String);
132///
133/// fn log(InRef(msg): InRef<str>, mut log: ResMut<Log>) {
134///     writeln!(log.0, "{}", msg).unwrap();
135/// }
136///
137/// let mut world = World::new();
138/// world.init_resource::<Log>();
139/// let mut log_system = IntoSystem::into_system(log);
140/// log_system.initialize(&mut world);
141///
142/// log_system.run("Hello, world!", &mut world);
143/// # assert_eq!(world.get_resource::<Log>().unwrap().0, "Hello, world!\n");
144/// ```
145///
146/// [`SystemParam`]: crate::system::SystemParam
147#[derive(Debug)]
148pub struct InRef<'i, T: ?Sized>(pub &'i T);
149
150impl<T: ?Sized + 'static> SystemInput for InRef<'_, T> {
151    type Param<'i> = InRef<'i, T>;
152    type Inner<'i> = &'i T;
153
154    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
155        InRef(this)
156    }
157}
158
159impl<'i, T: ?Sized> Deref for InRef<'i, T> {
160    type Target = T;
161
162    fn deref(&self) -> &Self::Target {
163        self.0
164    }
165}
166
167/// A [`SystemInput`] type which denotes that a [`System`] receives
168/// a mutable reference to a value of type `T` from its caller.
169///
170/// This is similar to [`In`] but takes a mutable reference to a value instead of the value itself.
171/// See [`InRef`] for the read-only version.
172///
173/// See [`SystemInput`] to learn more about system inputs in general.
174///
175/// # Examples
176///
177/// Here is a simple example of a system that takes a `&mut usize` and squares it.
178///
179/// ```
180/// # use bevy_ecs::prelude::*;
181/// #
182/// fn square(InMut(input): InMut<usize>) {
183///     *input *= *input;
184/// }
185///
186/// let mut world = World::new();
187/// let mut square_system = IntoSystem::into_system(square);
188/// square_system.initialize(&mut world);
189///     
190/// let mut value = 12;
191/// square_system.run(&mut value, &mut world);
192/// assert_eq!(value, 144);
193/// ```
194///
195/// [`SystemParam`]: crate::system::SystemParam
196#[derive(Debug)]
197pub struct InMut<'a, T: ?Sized>(pub &'a mut T);
198
199impl<T: ?Sized + 'static> SystemInput for InMut<'_, T> {
200    type Param<'i> = InMut<'i, T>;
201    type Inner<'i> = &'i mut T;
202
203    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
204        InMut(this)
205    }
206}
207
208impl<'i, T: ?Sized> Deref for InMut<'i, T> {
209    type Target = T;
210
211    fn deref(&self) -> &Self::Target {
212        self.0
213    }
214}
215
216impl<'i, T: ?Sized> DerefMut for InMut<'i, T> {
217    fn deref_mut(&mut self) -> &mut Self::Target {
218        self.0
219    }
220}
221
222/// Used for [`ObserverSystem`]s.
223///
224/// [`ObserverSystem`]: crate::system::ObserverSystem
225impl<E: Event, B: Bundle> SystemInput for On<'_, '_, E, B> {
226    // Note: the fact that we must use a shared lifetime here is
227    // a key piece of the complicated safety story documented above
228    // the `&mut E::Trigger<'_>` cast in `observer_system_runner` and in
229    // the `On` implementation.
230    type Param<'i> = On<'i, 'i, E, B>;
231    type Inner<'i> = On<'i, 'i, E, B>;
232
233    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
234        this
235    }
236}
237
238/// A helper for using [`SystemInput`]s in generic contexts.
239///
240/// This type is a [`SystemInput`] adapter which always has
241/// `Self::Param == Self` (ignoring lifetimes for brevity),
242/// no matter the argument [`SystemInput`] (`I`).
243///
244/// This makes it useful for having arbitrary [`SystemInput`]s in
245/// function systems.
246///
247/// See [`SystemInput`] to learn more about system inputs in general.
248pub struct StaticSystemInput<'a, I: SystemInput>(pub I::Inner<'a>);
249
250impl<'a, I: SystemInput> SystemInput for StaticSystemInput<'a, I> {
251    type Param<'i> = StaticSystemInput<'i, I>;
252    type Inner<'i> = I::Inner<'i>;
253
254    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
255        StaticSystemInput(this)
256    }
257}
258
259macro_rules! impl_system_input_tuple {
260    ($(#[$meta:meta])* $($name:ident),*) => {
261        $(#[$meta])*
262        impl<$($name: SystemInput),*> SystemInput for ($($name,)*) {
263            type Param<'i> = ($($name::Param<'i>,)*);
264            type Inner<'i> = ($($name::Inner<'i>,)*);
265
266            #[expect(
267                clippy::allow_attributes,
268                reason = "This is in a macro; as such, the below lints may not always apply."
269            )]
270            #[allow(
271                non_snake_case,
272                reason = "Certain variable names are provided by the caller, not by us."
273            )]
274            #[allow(
275                clippy::unused_unit,
276                reason = "Zero-length tuples won't have anything to wrap."
277            )]
278            fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
279                let ($($name,)*) = this;
280                ($($name::wrap($name),)*)
281            }
282        }
283    };
284}
285
286all_tuples!(
287    #[doc(fake_variadic)]
288    impl_system_input_tuple,
289    0,
290    8,
291    I
292);
293
294#[cfg(test)]
295mod tests {
296    use crate::{
297        system::{In, InMut, InRef, IntoSystem, System},
298        world::World,
299    };
300
301    #[test]
302    fn two_tuple() {
303        fn by_value((In(a), In(b)): (In<usize>, In<usize>)) -> usize {
304            a + b
305        }
306        fn by_ref((InRef(a), InRef(b)): (InRef<usize>, InRef<usize>)) -> usize {
307            *a + *b
308        }
309        fn by_mut((InMut(a), In(b)): (InMut<usize>, In<usize>)) {
310            *a += b;
311        }
312
313        let mut world = World::new();
314        let mut by_value = IntoSystem::into_system(by_value);
315        let mut by_ref = IntoSystem::into_system(by_ref);
316        let mut by_mut = IntoSystem::into_system(by_mut);
317
318        by_value.initialize(&mut world);
319        by_ref.initialize(&mut world);
320        by_mut.initialize(&mut world);
321
322        let mut a = 12;
323        let b = 24;
324
325        assert_eq!(by_value.run((a, b), &mut world).unwrap(), 36);
326        assert_eq!(by_ref.run((&a, &b), &mut world).unwrap(), 36);
327        by_mut.run((&mut a, b), &mut world).unwrap();
328        assert_eq!(a, 36);
329    }
330}