logo
pub trait SystemParamFunction<In, Out, Param, Marker>: 'static + Send + Sync where
    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 ChainSystem, 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`.
/// Chain creates a new system which calls `a`, then calls `b` with the output of `a`
pub fn chain<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 `chain`:
fn main() {
    let mut world = World::default();
    world.insert_resource(Message("42".to_string()));

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

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