Simplify system piping and make it more flexible (#8377)

# Objective

- Currently, it is not possible to call `.pipe` on a system that takes
any input other than `()`.
- The `IntoPipeSystem` trait is currently very difficult to parse due to
its use of generics.

## Solution

Remove the `IntoPipeSystem` trait, and move the `pipe` method to
`IntoSystem`.

---

## Changelog

- System piping has been made more flexible: it is now possible to call
`.pipe` on a system that takes an input.

## Migration Guide

The `IntoPipeSystem` trait has been removed, and the `pipe` method has
been moved to the `IntoSystem` trait.

```rust

// Before:
use bevy_ecs::system::IntoPipeSystem;
schedule.add_systems(first.pipe(second));

// After:
use bevy_ecs::system::IntoSystem;
schedule.add_systems(first.pipe(second));
```
This commit is contained in:
JoJoJet 2023-04-17 12:08:32 -04:00 committed by GitHub
parent 65292fd559
commit b03b7b557e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 42 deletions

View File

@ -46,8 +46,8 @@ pub mod prelude {
system::{ system::{
adapter as system_adapter, adapter as system_adapter,
adapter::{dbg, error, ignore, info, unwrap, warn}, adapter::{dbg, error, ignore, info, unwrap, warn},
Commands, Deferred, In, IntoPipeSystem, IntoSystem, Local, NonSend, NonSendMut, Commands, Deferred, In, IntoSystem, Local, NonSend, NonSendMut, ParallelCommands,
ParallelCommands, ParamSet, Query, Res, ResMut, Resource, System, SystemParamFunction, ParamSet, Query, Res, ResMut, Resource, System, SystemParamFunction,
}, },
world::{FromWorld, World}, world::{FromWorld, World},
}; };

View File

@ -10,7 +10,7 @@ use crate::{
use bevy_utils::all_tuples; use bevy_utils::all_tuples;
use std::{any::TypeId, borrow::Cow, marker::PhantomData}; use std::{any::TypeId, borrow::Cow, marker::PhantomData};
use super::ReadOnlySystem; use super::{PipeSystem, ReadOnlySystem};
/// The metadata of a [`System`]. /// The metadata of a [`System`].
#[derive(Clone)] #[derive(Clone)]
@ -329,6 +329,20 @@ pub trait IntoSystem<In, Out, Marker>: Sized {
type System: System<In = In, Out = Out>; type System: System<In = In, Out = Out>;
/// Turns this value into its corresponding [`System`]. /// Turns this value into its corresponding [`System`].
fn into_system(this: Self) -> Self::System; fn into_system(this: Self) -> Self::System;
/// Pass the output of this system `A` into a second system `B`, creating a new compound system.
///
/// The second system must have `In<T>` as its first parameter, where `T`
/// is the return type of the first system.
fn pipe<B, Final, MarkerB>(self, system: B) -> PipeSystem<Self::System, B::System>
where
B: IntoSystem<Out, Final, MarkerB>,
{
let system_a = IntoSystem::into_system(self);
let system_b = IntoSystem::into_system(system);
let name = format!("Pipe({}, {})", system_a.name(), system_b.name());
PipeSystem::new(system_a, system_b, Cow::Owned(name))
}
} }
// Systems implicitly implement IntoSystem // Systems implicitly implement IntoSystem

View File

@ -1,5 +1,4 @@
use crate::system::{IntoSystem, System}; use crate::system::System;
use std::borrow::Cow;
use super::{CombinatorSystem, Combine}; use super::{CombinatorSystem, Combine};
@ -65,37 +64,6 @@ where
} }
} }
/// An extension trait providing the [`IntoPipeSystem::pipe`] method to pass input from one system into the next.
///
/// The first system must have return type `T`
/// and the second system must have [`In<T>`](crate::system::In) as its first system parameter.
///
/// This trait is blanket implemented for all system pairs that fulfill the type requirements.
///
/// See [`PipeSystem`].
pub trait IntoPipeSystem<ParamA, Payload, SystemB, ParamB, Out>:
IntoSystem<(), Payload, ParamA> + Sized
where
SystemB: IntoSystem<Payload, Out, ParamB>,
{
/// Pass the output of this system `A` into a second system `B`, creating a new compound system.
fn pipe(self, system: SystemB) -> PipeSystem<Self::System, SystemB::System>;
}
impl<SystemA, ParamA, Payload, SystemB, ParamB, Out>
IntoPipeSystem<ParamA, Payload, SystemB, ParamB, Out> for SystemA
where
SystemA: IntoSystem<(), Payload, ParamA>,
SystemB: IntoSystem<Payload, Out, ParamB>,
{
fn pipe(self, system: SystemB) -> PipeSystem<SystemA::System, SystemB::System> {
let system_a = IntoSystem::into_system(self);
let system_b = IntoSystem::into_system(system);
let name = format!("Pipe({}, {})", system_a.name(), system_b.name());
PipeSystem::new(system_a, system_b, Cow::Owned(name))
}
}
/// A collection of common adapters for [piping](super::PipeSystem) the result of a system. /// A collection of common adapters for [piping](super::PipeSystem) the result of a system.
pub mod adapter { pub mod adapter {
use crate::system::In; use crate::system::In;
@ -313,7 +281,7 @@ mod tests {
use bevy_utils::default; use bevy_utils::default;
use super::adapter::*; use super::adapter::*;
use crate::{self as bevy_ecs, prelude::*, system::PipeSystem}; use crate::{self as bevy_ecs, prelude::*};
#[test] #[test]
fn assert_systems() { fn assert_systems() {
@ -384,11 +352,7 @@ mod tests {
let mut world = World::new(); let mut world = World::new();
world.init_resource::<Flag>(); world.init_resource::<Flag>();
let mut sys = PipeSystem::new( let mut sys = first.pipe(second);
IntoSystem::into_system(first),
IntoSystem::into_system(second),
"".into(),
);
sys.initialize(&mut world); sys.initialize(&mut world);
sys.run(default(), &mut world); sys.run(default(), &mut world);