-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Add system.map(...) for transforming the output of a system
#8526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
c6ac8ca
derive `Clone + Copy` for `SyncCell`
joseph-gio 80deaaa
add a module for generic system adapters
joseph-gio c64b4c3
add the `.map` extension method for systems
joseph-gio f04f52f
remove the manual implementation of `NotSystem`
joseph-gio 16c10f9
deprecate old system adapters
joseph-gio 79e6f33
deprecate tracing adapters and add alternatives to `bevy_utils`
joseph-gio 7c8732a
fix formatting for CI
joseph-gio 31d0a2f
fix deprecated imports
joseph-gio 2c56d51
fix a deprecated example
joseph-gio ac0a9d9
fix a doctest
joseph-gio 4ddbdfd
don't derive clone and copy for SyncCell
joseph-gio 03482f0
don't use SyncCell for adapter markers
joseph-gio 7e55336
Merge remote-tracking branch 'upstream/main' into system-mapping
joseph-gio bb21630
Merge remote-tracking branch 'upstream/main' into system-mapping
joseph-gio 343c876
remove redundant 'static bounds
joseph-gio 1bfe0c4
Apply suggestions from code review
joseph-gio 5a27505
add docs to `NotMarker`
joseph-gio 0d19083
Merge remote-tracking branch 'upstream/main' into system-mapping
joseph-gio 5544133
`apply_buffers` -> `apply_deferred`
joseph-gio 21edbaf
`&World` -> `UnsafeWorldCell`
joseph-gio ac17f4e
require `Send + Sync` closures for`.map`
joseph-gio 0dcd7d9
use `TypeId::of::<Self>`
joseph-gio 0e99ade
add docs to `AdapterSystem::new`
joseph-gio 4eaa384
allow system adapters to modify system names
joseph-gio 365f1ea
add docs to `Adapt`
joseph-gio 1ba3698
fix the doctest
joseph-gio d67e905
make system names consistent with `CombinatorSystem`
joseph-gio fe955b0
fix the doctest again
joseph-gio d0b1e20
remove extra whitespace
joseph-gio 1e52dfc
move an attribute under documentation
joseph-gio f0a1386
deprecate the adapter module at the top level
joseph-gio 740f803
Merge branch 'main' into system-mapping
alice-i-cecile File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| use std::borrow::Cow; | ||
|
|
||
| use super::{ReadOnlySystem, System}; | ||
| use crate::world::unsafe_world_cell::UnsafeWorldCell; | ||
|
|
||
| /// Customizes the behavior of an [`AdapterSystem`] | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// # use bevy_ecs::prelude::*; | ||
| /// use bevy_ecs::system::{Adapt, AdapterSystem}; | ||
| /// | ||
| /// // A system adapter that inverts the result of a system. | ||
| /// // NOTE: Instead of manually implementing this, you can just use `bevy_ecs::schedule::common_conditions::not`. | ||
| /// pub type NotSystem<S> = AdapterSystem<NotMarker, S>; | ||
| /// | ||
| /// // This struct is used to customize the behavior of our adapter. | ||
| /// pub struct NotMarker; | ||
| /// | ||
| /// impl<S> Adapt<S> for NotMarker | ||
| /// where | ||
| /// S: System, | ||
| /// S::Out: std::ops::Not, | ||
| /// { | ||
| /// type In = S::In; | ||
| /// type Out = <S::Out as std::ops::Not>::Output; | ||
| /// | ||
| /// fn adapt( | ||
| /// &mut self, | ||
| /// input: Self::In, | ||
| /// run_system: impl FnOnce(S::In) -> S::Out, | ||
| /// ) -> Self::Out { | ||
| /// !run_system(input) | ||
| /// } | ||
| /// } | ||
| /// # let mut world = World::new(); | ||
| /// # let mut system = NotSystem::new(NotMarker, IntoSystem::into_system(|| false), "".into()); | ||
| /// # system.initialize(&mut world); | ||
| /// # assert!(system.run((), &mut world)); | ||
| /// ``` | ||
| pub trait Adapt<S: System>: Send + Sync + 'static { | ||
joseph-gio marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /// The [input](System::In) type for an [`AdapterSystem`]. | ||
| type In; | ||
| /// The [output](System::Out) type for an [`AdapterSystem`]. | ||
| type Out; | ||
|
|
||
| /// When used in an [`AdapterSystem`], this function customizes how the system | ||
| /// is run and how its inputs/outputs are adapted. | ||
| fn adapt(&mut self, input: Self::In, run_system: impl FnOnce(S::In) -> S::Out) -> Self::Out; | ||
| } | ||
|
|
||
| /// A [`System`] that takes the output of `S` and transforms it by applying `Func` to it. | ||
| #[derive(Clone)] | ||
| pub struct AdapterSystem<Func, S> { | ||
joseph-gio marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| func: Func, | ||
| system: S, | ||
| name: Cow<'static, str>, | ||
| } | ||
|
|
||
| impl<Func, S> AdapterSystem<Func, S> | ||
| where | ||
| Func: Adapt<S>, | ||
| S: System, | ||
| { | ||
| /// Creates a new [`System`] that uses `func` to adapt `system`, via the [`Adapt`] trait. | ||
| pub const fn new(func: Func, system: S, name: Cow<'static, str>) -> Self { | ||
| Self { func, system, name } | ||
| } | ||
| } | ||
|
|
||
| impl<Func, S> System for AdapterSystem<Func, S> | ||
| where | ||
| Func: Adapt<S>, | ||
| S: System, | ||
| { | ||
| type In = Func::In; | ||
| type Out = Func::Out; | ||
|
|
||
| fn name(&self) -> Cow<'static, str> { | ||
| self.name.clone() | ||
| } | ||
|
|
||
| fn type_id(&self) -> std::any::TypeId { | ||
joseph-gio marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| std::any::TypeId::of::<Self>() | ||
| } | ||
|
|
||
| fn component_access(&self) -> &crate::query::Access<crate::component::ComponentId> { | ||
| self.system.component_access() | ||
| } | ||
|
|
||
| #[inline] | ||
| fn archetype_component_access( | ||
| &self, | ||
| ) -> &crate::query::Access<crate::archetype::ArchetypeComponentId> { | ||
| self.system.archetype_component_access() | ||
| } | ||
|
|
||
| fn is_send(&self) -> bool { | ||
| self.system.is_send() | ||
| } | ||
|
|
||
| fn is_exclusive(&self) -> bool { | ||
| self.system.is_exclusive() | ||
| } | ||
|
|
||
| #[inline] | ||
| unsafe fn run_unsafe(&mut self, input: Self::In, world: UnsafeWorldCell) -> Self::Out { | ||
| // SAFETY: `system.run_unsafe` has the same invariants as `self.run_unsafe`. | ||
| self.func | ||
| .adapt(input, |input| self.system.run_unsafe(input, world)) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn run(&mut self, input: Self::In, world: &mut crate::prelude::World) -> Self::Out { | ||
| self.func | ||
| .adapt(input, |input| self.system.run(input, world)) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn apply_deferred(&mut self, world: &mut crate::prelude::World) { | ||
| self.system.apply_deferred(world); | ||
| } | ||
|
|
||
| fn initialize(&mut self, world: &mut crate::prelude::World) { | ||
| self.system.initialize(world); | ||
| } | ||
|
|
||
| #[inline] | ||
| fn update_archetype_component_access(&mut self, world: UnsafeWorldCell) { | ||
| self.system.update_archetype_component_access(world); | ||
| } | ||
|
|
||
| fn check_change_tick(&mut self, change_tick: crate::component::Tick) { | ||
| self.system.check_change_tick(change_tick); | ||
| } | ||
|
|
||
| fn get_last_run(&self) -> crate::component::Tick { | ||
| self.system.get_last_run() | ||
| } | ||
|
|
||
| fn set_last_run(&mut self, last_run: crate::component::Tick) { | ||
| self.system.set_last_run(last_run); | ||
| } | ||
|
|
||
| fn default_system_sets(&self) -> Vec<Box<dyn crate::schedule::SystemSet>> { | ||
| self.system.default_system_sets() | ||
| } | ||
| } | ||
|
|
||
| // SAFETY: The inner system is read-only. | ||
| unsafe impl<Func, S> ReadOnlySystem for AdapterSystem<Func, S> | ||
| where | ||
| Func: Adapt<S>, | ||
| S: ReadOnlySystem, | ||
| { | ||
| } | ||
|
|
||
| impl<F, S, Out> Adapt<S> for F | ||
| where | ||
| S: System, | ||
| F: Send + Sync + 'static + FnMut(S::Out) -> Out, | ||
| { | ||
| type In = S::In; | ||
| type Out = Out; | ||
|
|
||
| fn adapt(&mut self, input: S::In, run_system: impl FnOnce(S::In) -> S::Out) -> Out { | ||
| self(run_system(input)) | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.