pub trait SystemParamFunction<In, Out, Param, Marker>: 'static + Send + Syncwhere
    Param: SystemParam,
{ fn run(
        &mut self,
        input: In,
        param_value: <<Param as SystemParam>::Fetch as SystemParamFetch<'_, '_>>::Item
    ) -> Out; }
Expand description

A trait implemented for all functions that can be used as Systems.

This trait can be useful for making your own systems which accept other systems, sometimes called higher order systems.

This should be used in combination with ParamSet when calling other systems within your system. Using ParamSet in this case avoids SystemParam collisions.

Example

To create something like PipeSystem, but in entirely safe code.

use std::num::ParseIntError;

use bevy_ecs::prelude::*;
use bevy_ecs::system::{SystemParam, SystemParamItem};

// Unfortunately, we need all of these generics. `A` is the first system, with its
// parameters and marker type required for coherence. `B` is the second system, and
// the other generics are for the input/output types of `A` and `B`.
/// Pipe creates a new system which calls `a`, then calls `b` with the output of `a`
pub fn pipe<AIn, Shared, BOut, A, AParam, AMarker, B, BParam, BMarker>(
    mut a: A,
    mut b: B,
) -> impl FnMut(In<AIn>, ParamSet<(SystemParamItem<AParam>, SystemParamItem<BParam>)>) -> BOut
where
    // We need A and B to be systems, add those bounds
    A: SystemParamFunction<AIn, Shared, AParam, AMarker>,
    B: SystemParamFunction<Shared, BOut, BParam, BMarker>,
    AParam: SystemParam,
    BParam: SystemParam,
{
    // The type of `params` is inferred based on the return of this function above
    move |In(a_in), mut params| {
        let shared = a.run(a_in, params.p0());
        b.run(shared, params.p1())
    }
}

// Usage example for `pipe`:
fn main() {
    let mut world = World::default();
    world.insert_resource(Message("42".to_string()));

    // pipe the `parse_message_system`'s output into the `filter_system`s input
    let mut piped_system = IntoSystem::into_system(pipe(parse_message, filter));
    piped_system.initialize(&mut world);
    assert_eq!(piped_system.run((), &mut world), Some(42));
}

#[derive(Resource)]
struct Message(String);

fn parse_message(message: Res<Message>) -> Result<usize, ParseIntError> {
    message.0.parse::<usize>()
}

fn filter(In(result): In<Result<usize, ParseIntError>>) -> Option<usize> {
    result.ok().filter(|&n| n < 100)
}

Required Methods§

Implementors§