Make the Condition trait generic (#8721)
				
					
				
			# Objective The `Condition` trait is only implemented for systems and system functions that take no input. This can make it awkward to write conditions that are intended to be used with system piping. ## Solution Add an `In` generic to the trait. It defaults to `()`. --- ## Changelog - Made the `Condition` trait generic over system inputs.
This commit is contained in:
		
							parent
							
								
									5b0f21c773
								
							
						
					
					
						commit
						233b26cc17
					
				@ -8,13 +8,55 @@ use crate::system::{CombinatorSystem, Combine, IntoSystem, ReadOnlySystem, Syste
 | 
			
		||||
use crate::world::unsafe_world_cell::UnsafeWorldCell;
 | 
			
		||||
use crate::world::World;
 | 
			
		||||
 | 
			
		||||
pub type BoxedCondition = Box<dyn ReadOnlySystem<In = (), Out = bool>>;
 | 
			
		||||
pub type BoxedCondition<In = ()> = Box<dyn ReadOnlySystem<In = In, Out = bool>>;
 | 
			
		||||
 | 
			
		||||
/// A system that determines if one or more scheduled systems should run.
 | 
			
		||||
///
 | 
			
		||||
/// Implemented for functions and closures that convert into [`System<In=(), Out=bool>`](crate::system::System)
 | 
			
		||||
/// Implemented for functions and closures that convert into [`System<Out=bool>`](crate::system::System)
 | 
			
		||||
/// with [read-only](crate::system::ReadOnlySystemParam) parameters.
 | 
			
		||||
pub trait Condition<Marker>: sealed::Condition<Marker> {
 | 
			
		||||
///
 | 
			
		||||
/// # Examples
 | 
			
		||||
/// A condition that returns true every other time it's called.
 | 
			
		||||
/// ```
 | 
			
		||||
/// # use bevy_ecs::prelude::*;
 | 
			
		||||
/// fn every_other_time() -> impl Condition<()> {
 | 
			
		||||
///     IntoSystem::into_system(|mut flag: Local<bool>| {
 | 
			
		||||
///         *flag = !*flag;
 | 
			
		||||
///         *flag
 | 
			
		||||
///     })
 | 
			
		||||
/// }
 | 
			
		||||
///
 | 
			
		||||
/// # #[derive(Resource)] struct DidRun(bool);
 | 
			
		||||
/// # fn my_system(mut did_run: ResMut<DidRun>) { did_run.0 = true; }
 | 
			
		||||
/// # let mut schedule = Schedule::new();
 | 
			
		||||
/// schedule.add_systems(my_system.run_if(every_other_time()));
 | 
			
		||||
/// # let mut world = World::new();
 | 
			
		||||
/// # world.insert_resource(DidRun(false));
 | 
			
		||||
/// # schedule.run(&mut world);
 | 
			
		||||
/// # assert!(world.resource::<DidRun>().0);
 | 
			
		||||
/// # world.insert_resource(DidRun(false));
 | 
			
		||||
/// # schedule.run(&mut world);
 | 
			
		||||
/// # assert!(!world.resource::<DidRun>().0);
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
/// A condition that takes a bool as an input and returns it unchanged.
 | 
			
		||||
///
 | 
			
		||||
/// ```
 | 
			
		||||
/// # use bevy_ecs::prelude::*;
 | 
			
		||||
/// fn identity() -> impl Condition<(), bool> {
 | 
			
		||||
///     IntoSystem::into_system(|In(x)| x)
 | 
			
		||||
/// }
 | 
			
		||||
///
 | 
			
		||||
/// # fn always_true() -> bool { true }
 | 
			
		||||
/// # let mut schedule = Schedule::new();
 | 
			
		||||
/// # #[derive(Resource)] struct DidRun(bool);
 | 
			
		||||
/// # fn my_system(mut did_run: ResMut<DidRun>) { did_run.0 = true; }
 | 
			
		||||
/// schedule.add_systems(my_system.run_if(always_true.pipe(identity())));
 | 
			
		||||
/// # let mut world = World::new();
 | 
			
		||||
/// # world.insert_resource(DidRun(false));
 | 
			
		||||
/// # schedule.run(&mut world);
 | 
			
		||||
/// # assert!(world.resource::<DidRun>().0);
 | 
			
		||||
pub trait Condition<Marker, In = ()>: sealed::Condition<Marker, In> {
 | 
			
		||||
    /// Returns a new run condition that only returns `true`
 | 
			
		||||
    /// if both this one and the passed `and_then` return `true`.
 | 
			
		||||
    ///
 | 
			
		||||
@ -59,7 +101,7 @@ pub trait Condition<Marker>: sealed::Condition<Marker> {
 | 
			
		||||
    /// Note that in this case, it's better to just use the run condition [`resource_exists_and_equals`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// [`resource_exists_and_equals`]: common_conditions::resource_exists_and_equals
 | 
			
		||||
    fn and_then<M, C: Condition<M>>(self, and_then: C) -> AndThen<Self::System, C::System> {
 | 
			
		||||
    fn and_then<M, C: Condition<M, In>>(self, and_then: C) -> AndThen<Self::System, C::System> {
 | 
			
		||||
        let a = IntoSystem::into_system(self);
 | 
			
		||||
        let b = IntoSystem::into_system(and_then);
 | 
			
		||||
        let name = format!("{} && {}", a.name(), b.name());
 | 
			
		||||
@ -106,7 +148,7 @@ pub trait Condition<Marker>: sealed::Condition<Marker> {
 | 
			
		||||
    /// # app.run(&mut world);
 | 
			
		||||
    /// # assert!(world.resource::<C>().0);
 | 
			
		||||
    /// ```
 | 
			
		||||
    fn or_else<M, C: Condition<M>>(self, or_else: C) -> OrElse<Self::System, C::System> {
 | 
			
		||||
    fn or_else<M, C: Condition<M, In>>(self, or_else: C) -> OrElse<Self::System, C::System> {
 | 
			
		||||
        let a = IntoSystem::into_system(self);
 | 
			
		||||
        let b = IntoSystem::into_system(or_else);
 | 
			
		||||
        let name = format!("{} || {}", a.name(), b.name());
 | 
			
		||||
@ -114,22 +156,22 @@ pub trait Condition<Marker>: sealed::Condition<Marker> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<Marker, F> Condition<Marker> for F where F: sealed::Condition<Marker> {}
 | 
			
		||||
impl<Marker, In, F> Condition<Marker, In> for F where F: sealed::Condition<Marker, In> {}
 | 
			
		||||
 | 
			
		||||
mod sealed {
 | 
			
		||||
    use crate::system::{IntoSystem, ReadOnlySystem};
 | 
			
		||||
 | 
			
		||||
    pub trait Condition<Marker>:
 | 
			
		||||
        IntoSystem<(), bool, Marker, System = Self::ReadOnlySystem>
 | 
			
		||||
    pub trait Condition<Marker, In>:
 | 
			
		||||
        IntoSystem<In, bool, Marker, System = Self::ReadOnlySystem>
 | 
			
		||||
    {
 | 
			
		||||
        // This associated type is necessary to let the compiler
 | 
			
		||||
        // know that `Self::System` is `ReadOnlySystem`.
 | 
			
		||||
        type ReadOnlySystem: ReadOnlySystem<In = (), Out = bool>;
 | 
			
		||||
        type ReadOnlySystem: ReadOnlySystem<In = In, Out = bool>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    impl<Marker, F> Condition<Marker> for F
 | 
			
		||||
    impl<Marker, In, F> Condition<Marker, In> for F
 | 
			
		||||
    where
 | 
			
		||||
        F: IntoSystem<(), bool, Marker>,
 | 
			
		||||
        F: IntoSystem<In, bool, Marker>,
 | 
			
		||||
        F::System: ReadOnlySystem,
 | 
			
		||||
    {
 | 
			
		||||
        type ReadOnlySystem = F::System;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user