bevy_ecs/system/
input.rs

1use core::ops::{Deref, DerefMut};
2
3use crate::{bundle::Bundle, prelude::Trigger, system::System};
4
5/// Trait for types that can be used as input to [`System`]s.
6///
7/// Provided implementations are:
8/// - `()`: No input
9/// - [`In<T>`]: For values
10/// - [`InRef<T>`]: For read-only references to values
11/// - [`InMut<T>`]: For mutable references to values
12/// - [`Trigger<E, B>`]: For [`ObserverSystem`]s
13/// - [`StaticSystemInput<I>`]: For arbitrary [`SystemInput`]s in generic contexts
14///
15/// [`ObserverSystem`]: crate::system::ObserverSystem
16pub trait SystemInput: Sized {
17    /// The wrapper input type that is defined as the first argument to [`FunctionSystem`]s.
18    ///
19    /// [`FunctionSystem`]: crate::system::FunctionSystem
20    type Param<'i>: SystemInput;
21    /// The inner input type that is passed to functions that run systems,
22    /// such as [`System::run`].
23    ///
24    /// [`System::run`]: crate::system::System::run
25    type Inner<'i>;
26
27    /// Converts a [`SystemInput::Inner`] into a [`SystemInput::Param`].
28    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_>;
29}
30
31/// Shorthand way to get the [`System::In`] for a [`System`] as a [`SystemInput::Inner`].
32pub type SystemIn<'a, S> = <<S as System>::In as SystemInput>::Inner<'a>;
33
34/// [`SystemInput`] type for systems that take no input.
35impl SystemInput for () {
36    type Param<'i> = ();
37    type Inner<'i> = ();
38
39    fn wrap(_this: Self::Inner<'_>) -> Self::Param<'_> {}
40}
41
42/// A [`SystemInput`] type which denotes that a [`System`] receives
43/// an input value of type `T` from its caller.
44///
45/// [`System`]s may take an optional input which they require to be passed to them when they
46/// are being [`run`](System::run). For [`FunctionSystem`]s the input may be marked
47/// with this `In` type, but only the first param of a function may be tagged as an input. This also
48/// means a system can only have one or zero input parameters.
49///
50/// # Examples
51///
52/// Here is a simple example of a system that takes a [`usize`] and returns the square of it.
53///
54/// ```
55/// # use bevy_ecs::prelude::*;
56/// #
57/// fn square(In(input): In<usize>) -> usize {
58///     input * input
59/// }
60///
61/// let mut world = World::new();
62/// let mut square_system = IntoSystem::into_system(square);
63/// square_system.initialize(&mut world);
64///
65/// assert_eq!(square_system.run(12, &mut world), 144);
66/// ```
67///
68/// [`SystemParam`]: crate::system::SystemParam
69/// [`FunctionSystem`]: crate::system::FunctionSystem
70#[derive(Debug)]
71pub struct In<T>(pub T);
72
73impl<T: 'static> SystemInput for In<T> {
74    type Param<'i> = In<T>;
75    type Inner<'i> = T;
76
77    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
78        In(this)
79    }
80}
81
82impl<T> Deref for In<T> {
83    type Target = T;
84
85    fn deref(&self) -> &Self::Target {
86        &self.0
87    }
88}
89
90impl<T> DerefMut for In<T> {
91    fn deref_mut(&mut self) -> &mut Self::Target {
92        &mut self.0
93    }
94}
95
96/// A [`SystemInput`] type which denotes that a [`System`] receives
97/// a read-only reference to a value of type `T` from its caller.
98///
99/// This is similar to [`In`] but takes a reference to a value instead of the value itself.
100/// See [`InMut`] for the mutable version.
101///
102/// # Examples
103///
104/// Here is a simple example of a system that logs the passed in message.
105///
106/// ```
107/// # use bevy_ecs::prelude::*;
108/// # use std::fmt::Write as _;
109/// #
110/// #[derive(Resource, Default)]
111/// struct Log(String);
112///
113/// fn log(InRef(msg): InRef<str>, mut log: ResMut<Log>) {
114///     writeln!(log.0, "{}", msg).unwrap();
115/// }
116///
117/// let mut world = World::new();
118/// world.init_resource::<Log>();
119/// let mut log_system = IntoSystem::into_system(log);
120/// log_system.initialize(&mut world);
121///
122/// log_system.run("Hello, world!", &mut world);
123/// # assert_eq!(world.get_resource::<Log>().unwrap().0, "Hello, world!\n");
124/// ```
125///
126/// [`SystemParam`]: crate::system::SystemParam
127#[derive(Debug)]
128pub struct InRef<'i, T: ?Sized>(pub &'i T);
129
130impl<T: ?Sized + 'static> SystemInput for InRef<'_, T> {
131    type Param<'i> = InRef<'i, T>;
132    type Inner<'i> = &'i T;
133
134    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
135        InRef(this)
136    }
137}
138
139impl<'i, T: ?Sized> Deref for InRef<'i, T> {
140    type Target = T;
141
142    fn deref(&self) -> &Self::Target {
143        self.0
144    }
145}
146
147/// A [`SystemInput`] type which denotes that a [`System`] receives
148/// a mutable reference to a value of type `T` from its caller.
149///
150/// This is similar to [`In`] but takes a mutable reference to a value instead of the value itself.
151/// See [`InRef`] for the read-only version.
152///
153/// # Examples
154///
155/// Here is a simple example of a system that takes a `&mut usize` and squares it.
156///
157/// ```
158/// # use bevy_ecs::prelude::*;
159/// #
160/// fn square(InMut(input): InMut<usize>) {
161///     *input *= *input;
162/// }
163///
164/// let mut world = World::new();
165/// let mut square_system = IntoSystem::into_system(square);
166/// square_system.initialize(&mut world);
167///     
168/// let mut value = 12;
169/// square_system.run(&mut value, &mut world);
170/// assert_eq!(value, 144);
171/// ```
172///
173/// [`SystemParam`]: crate::system::SystemParam
174#[derive(Debug)]
175pub struct InMut<'a, T: ?Sized>(pub &'a mut T);
176
177impl<T: ?Sized + 'static> SystemInput for InMut<'_, T> {
178    type Param<'i> = InMut<'i, T>;
179    type Inner<'i> = &'i mut T;
180
181    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
182        InMut(this)
183    }
184}
185
186impl<'i, T: ?Sized> Deref for InMut<'i, T> {
187    type Target = T;
188
189    fn deref(&self) -> &Self::Target {
190        self.0
191    }
192}
193
194impl<'i, T: ?Sized> DerefMut for InMut<'i, T> {
195    fn deref_mut(&mut self) -> &mut Self::Target {
196        self.0
197    }
198}
199
200/// Used for [`ObserverSystem`]s.
201///
202/// [`ObserverSystem`]: crate::system::ObserverSystem
203impl<E: 'static, B: Bundle> SystemInput for Trigger<'_, E, B> {
204    type Param<'i> = Trigger<'i, E, B>;
205    type Inner<'i> = Trigger<'i, E, B>;
206
207    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
208        this
209    }
210}
211
212/// A helper for using [`SystemInput`]s in generic contexts.
213///
214/// This type is a [`SystemInput`] adapter which always has
215/// `Self::Param == Self` (ignoring lifetimes for brevity),
216/// no matter the argument [`SystemInput`] (`I`).
217///
218/// This makes it useful for having arbitrary [`SystemInput`]s in
219/// function systems.
220pub struct StaticSystemInput<'a, I: SystemInput>(pub I::Inner<'a>);
221
222impl<'a, I: SystemInput> SystemInput for StaticSystemInput<'a, I> {
223    type Param<'i> = StaticSystemInput<'i, I>;
224    type Inner<'i> = I::Inner<'i>;
225
226    fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
227        StaticSystemInput(this)
228    }
229}