Add system.map(...)
for transforming the output of a system (#8526)
# Objective Any time we wish to transform the output of a system, we currently use system piping to do so: ```rust my_system.pipe(|In(x)| do_something(x)) ``` Unfortunately, system piping is not a zero cost abstraction. Each call to `.pipe` requires allocating two extra access sets: one for the second system and one for the combined accesses of both systems. This also adds extra work to each call to `update_archetype_component_access`, which stacks as one adds multiple layers of system piping. ## Solution Add the `AdapterSystem` abstraction: similar to `CombinatorSystem`, this allows you to implement a trait to generically control how a system is run and how its inputs and outputs are processed. Unlike `CombinatorSystem`, this does not have any overhead when computing world accesses which makes it ideal for simple operations such as inverting or ignoring the output of a system. Add the extension method `.map(...)`: this is similar to `.pipe(...)`, only it accepts a closure as an argument instead of an `In<T>` system. ```rust my_system.map(do_something) ``` This has the added benefit of making system names less messy: a system that ignores its output will just be called `my_system`, instead of `Pipe(my_system, ignore)` --- ## Changelog TODO ## Migration Guide The `system_adapter` functions have been deprecated: use `.map` instead, which is a lightweight alternative to `.pipe`. ```rust // Before: my_system.pipe(system_adapter::ignore) my_system.pipe(system_adapter::unwrap) my_system.pipe(system_adapter::new(T::from)) // After: my_system.map(std::mem::drop) my_system.map(Result::unwrap) my_system.map(T::from) // Before: my_system.pipe(system_adapter::info) my_system.pipe(system_adapter::dbg) my_system.pipe(system_adapter::warn) my_system.pipe(system_adapter::error) // After: my_system.map(bevy_utils::info) my_system.map(bevy_utils::dbg) my_system.map(bevy_utils::warn) my_system.map(bevy_utils::error) ``` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
aa489eced0
commit
474b55a29c
@ -30,6 +30,10 @@ pub mod prelude {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(feature = "bevy_reflect")]
|
#[cfg(feature = "bevy_reflect")]
|
||||||
pub use crate::reflect::{AppTypeRegistry, ReflectComponent, ReflectResource};
|
pub use crate::reflect::{AppTypeRegistry, ReflectComponent, ReflectResource};
|
||||||
|
#[allow(deprecated)]
|
||||||
|
pub use crate::system::adapter::{
|
||||||
|
self as system_adapter, dbg, error, ignore, info, unwrap, warn,
|
||||||
|
};
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
bundle::Bundle,
|
bundle::Bundle,
|
||||||
@ -45,8 +49,6 @@ pub mod prelude {
|
|||||||
OnEnter, OnExit, OnTransition, Schedule, Schedules, State, States, SystemSet,
|
OnEnter, OnExit, OnTransition, Schedule, Schedules, State, States, SystemSet,
|
||||||
},
|
},
|
||||||
system::{
|
system::{
|
||||||
adapter as system_adapter,
|
|
||||||
adapter::{dbg, error, ignore, info, unwrap, warn},
|
|
||||||
Commands, Deferred, In, IntoSystem, Local, NonSend, NonSendMut, ParallelCommands,
|
Commands, Deferred, In, IntoSystem, Local, NonSend, NonSendMut, ParallelCommands,
|
||||||
ParamSet, Query, ReadOnlySystem, Res, ResMut, Resource, System, SystemParamFunction,
|
ParamSet, Query, ReadOnlySystem, Res, ResMut, Resource, System, SystemParamFunction,
|
||||||
},
|
},
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
use std::any::TypeId;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::ops::Not;
|
use std::ops::Not;
|
||||||
|
|
||||||
use crate::component::{self, ComponentId};
|
use crate::system::{
|
||||||
use crate::query::Access;
|
Adapt, AdapterSystem, CombinatorSystem, Combine, IntoSystem, ReadOnlySystem, System,
|
||||||
use crate::system::{CombinatorSystem, Combine, IntoSystem, ReadOnlySystem, System};
|
};
|
||||||
use crate::world::unsafe_world_cell::UnsafeWorldCell;
|
|
||||||
use crate::world::World;
|
|
||||||
|
|
||||||
/// A type-erased run condition stored in a [`Box`].
|
/// A type-erased run condition stored in a [`Box`].
|
||||||
pub type BoxedCondition<In = ()> = Box<dyn ReadOnlySystem<In = In, Out = bool>>;
|
pub type BoxedCondition<In = ()> = Box<dyn ReadOnlySystem<In = In, Out = bool>>;
|
||||||
@ -181,8 +178,6 @@ mod sealed {
|
|||||||
|
|
||||||
/// A collection of [run conditions](Condition) that may be useful in any bevy app.
|
/// A collection of [run conditions](Condition) that may be useful in any bevy app.
|
||||||
pub mod common_conditions {
|
pub mod common_conditions {
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use super::NotSystem;
|
use super::NotSystem;
|
||||||
use crate::{
|
use crate::{
|
||||||
change_detection::DetectChanges,
|
change_detection::DetectChanges,
|
||||||
@ -987,96 +982,30 @@ pub mod common_conditions {
|
|||||||
{
|
{
|
||||||
let condition = IntoSystem::into_system(condition);
|
let condition = IntoSystem::into_system(condition);
|
||||||
let name = format!("!{}", condition.name());
|
let name = format!("!{}", condition.name());
|
||||||
NotSystem::<T::System> {
|
NotSystem::new(super::NotMarker, condition, name.into())
|
||||||
condition,
|
|
||||||
name: Cow::Owned(name),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invokes [`Not`] with the output of another system.
|
/// Invokes [`Not`] with the output of another system.
|
||||||
///
|
///
|
||||||
/// See [`common_conditions::not`] for examples.
|
/// See [`common_conditions::not`] for examples.
|
||||||
#[derive(Clone)]
|
pub type NotSystem<T> = AdapterSystem<NotMarker, T>;
|
||||||
pub struct NotSystem<T: System>
|
|
||||||
where
|
/// Used with [`AdapterSystem`] to negate the output of a system via the [`Not`] operator.
|
||||||
T::Out: Not,
|
#[doc(hidden)]
|
||||||
{
|
#[derive(Clone, Copy)]
|
||||||
condition: T,
|
pub struct NotMarker;
|
||||||
name: Cow<'static, str>,
|
|
||||||
}
|
impl<T: System> Adapt<T> for NotMarker
|
||||||
impl<T: System> System for NotSystem<T>
|
|
||||||
where
|
where
|
||||||
T::Out: Not,
|
T::Out: Not,
|
||||||
{
|
{
|
||||||
type In = T::In;
|
type In = T::In;
|
||||||
type Out = <T::Out as Not>::Output;
|
type Out = <T::Out as Not>::Output;
|
||||||
|
|
||||||
fn name(&self) -> Cow<'static, str> {
|
fn adapt(&mut self, input: Self::In, run_system: impl FnOnce(T::In) -> T::Out) -> Self::Out {
|
||||||
self.name.clone()
|
!run_system(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_id(&self) -> TypeId {
|
|
||||||
TypeId::of::<T>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn component_access(&self) -> &Access<ComponentId> {
|
|
||||||
self.condition.component_access()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn archetype_component_access(&self) -> &Access<crate::archetype::ArchetypeComponentId> {
|
|
||||||
self.condition.archetype_component_access()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_send(&self) -> bool {
|
|
||||||
self.condition.is_send()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_exclusive(&self) -> bool {
|
|
||||||
self.condition.is_exclusive()
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn run_unsafe(&mut self, input: Self::In, world: UnsafeWorldCell) -> Self::Out {
|
|
||||||
// SAFETY: The inner condition system asserts its own safety.
|
|
||||||
!self.condition.run_unsafe(input, world)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&mut self, input: Self::In, world: &mut World) -> Self::Out {
|
|
||||||
!self.condition.run(input, world)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply_deferred(&mut self, world: &mut World) {
|
|
||||||
self.condition.apply_deferred(world);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn initialize(&mut self, world: &mut World) {
|
|
||||||
self.condition.initialize(world);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_archetype_component_access(&mut self, world: UnsafeWorldCell) {
|
|
||||||
self.condition.update_archetype_component_access(world);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_change_tick(&mut self, change_tick: component::Tick) {
|
|
||||||
self.condition.check_change_tick(change_tick);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_last_run(&self) -> component::Tick {
|
|
||||||
self.condition.get_last_run()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_last_run(&mut self, last_run: component::Tick) {
|
|
||||||
self.condition.set_last_run(last_run);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: This trait is only implemented when the inner system is read-only.
|
|
||||||
// The `Not` condition does not modify access, and thus cannot transform a read-only system into one that is not.
|
|
||||||
unsafe impl<T> ReadOnlySystem for NotSystem<T>
|
|
||||||
where
|
|
||||||
T: ReadOnlySystem,
|
|
||||||
T::Out: Not,
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Combines the outputs of two systems using the `&&` operator.
|
/// Combines the outputs of two systems using the `&&` operator.
|
||||||
|
170
crates/bevy_ecs/src/system/adapter_system.rs
Normal file
170
crates/bevy_ecs/src/system/adapter_system.rs
Normal file
@ -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 {
|
||||||
|
/// 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> {
|
||||||
|
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 {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
@ -102,6 +102,7 @@
|
|||||||
//! - All tuples between 1 to 16 elements where each element implements [`SystemParam`]
|
//! - All tuples between 1 to 16 elements where each element implements [`SystemParam`]
|
||||||
//! - [`()` (unit primitive type)](https://doc.rust-lang.org/stable/std/primitive.unit.html)
|
//! - [`()` (unit primitive type)](https://doc.rust-lang.org/stable/std/primitive.unit.html)
|
||||||
|
|
||||||
|
mod adapter_system;
|
||||||
mod combinator;
|
mod combinator;
|
||||||
mod commands;
|
mod commands;
|
||||||
mod exclusive_function_system;
|
mod exclusive_function_system;
|
||||||
@ -114,6 +115,7 @@ mod system_param;
|
|||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
pub use adapter_system::*;
|
||||||
pub use combinator::*;
|
pub use combinator::*;
|
||||||
pub use commands::*;
|
pub use commands::*;
|
||||||
pub use exclusive_function_system::*;
|
pub use exclusive_function_system::*;
|
||||||
@ -162,6 +164,34 @@ pub trait IntoSystem<In, Out, Marker>: Sized {
|
|||||||
let name = format!("Pipe({}, {})", system_a.name(), system_b.name());
|
let name = format!("Pipe({}, {})", system_a.name(), system_b.name());
|
||||||
PipeSystem::new(system_a, system_b, Cow::Owned(name))
|
PipeSystem::new(system_a, system_b, Cow::Owned(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pass the output of this system into the passed function `f`, creating a new system that
|
||||||
|
/// outputs the value returned from the function.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_ecs::prelude::*;
|
||||||
|
/// # let mut schedule = Schedule::new();
|
||||||
|
/// // Ignores the output of a system that may fail.
|
||||||
|
/// schedule.add_systems(my_system.map(std::mem::drop));
|
||||||
|
/// # let mut world = World::new();
|
||||||
|
/// # world.insert_resource(T);
|
||||||
|
/// # schedule.run(&mut world);
|
||||||
|
///
|
||||||
|
/// # #[derive(Resource)] struct T;
|
||||||
|
/// # type Err = ();
|
||||||
|
/// fn my_system(res: Res<T>) -> Result<(), Err> {
|
||||||
|
/// // ...
|
||||||
|
/// # Err(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
fn map<T, F>(self, f: F) -> AdapterSystem<F, Self::System>
|
||||||
|
where
|
||||||
|
F: Send + Sync + 'static + FnMut(Out) -> T,
|
||||||
|
{
|
||||||
|
let system = Self::into_system(self);
|
||||||
|
let name = system.name();
|
||||||
|
AdapterSystem::new(f, system, name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All systems implicitly implement IntoSystem.
|
// All systems implicitly implement IntoSystem.
|
||||||
@ -201,6 +231,7 @@ impl<T: System> IntoSystem<T::In, T::Out, ()> for T {
|
|||||||
pub struct In<In>(pub In);
|
pub struct In<In>(pub In);
|
||||||
|
|
||||||
/// A collection of common adapters for [piping](crate::system::PipeSystem) the result of a system.
|
/// A collection of common adapters for [piping](crate::system::PipeSystem) the result of a system.
|
||||||
|
#[deprecated = "this form of system adapter has been deprecated in favor of `system.map(...)`"]
|
||||||
pub mod adapter {
|
pub mod adapter {
|
||||||
use crate::system::In;
|
use crate::system::In;
|
||||||
use bevy_utils::tracing;
|
use bevy_utils::tracing;
|
||||||
@ -223,6 +254,7 @@ pub mod adapter {
|
|||||||
/// println!("{x:?}");
|
/// println!("{x:?}");
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[deprecated = "use `.map(...)` instead"]
|
||||||
pub fn new<T, U>(mut f: impl FnMut(T) -> U) -> impl FnMut(In<T>) -> U {
|
pub fn new<T, U>(mut f: impl FnMut(T) -> U) -> impl FnMut(In<T>) -> U {
|
||||||
move |In(x)| f(x)
|
move |In(x)| f(x)
|
||||||
}
|
}
|
||||||
@ -260,6 +292,7 @@ pub mod adapter {
|
|||||||
/// # fn open_file(name: &str) -> Result<&'static str, std::io::Error>
|
/// # fn open_file(name: &str) -> Result<&'static str, std::io::Error>
|
||||||
/// # { Ok("hello world") }
|
/// # { Ok("hello world") }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[deprecated = "use `.map(Result::unwrap)` instead"]
|
||||||
pub fn unwrap<T, E: Debug>(In(res): In<Result<T, E>>) -> T {
|
pub fn unwrap<T, E: Debug>(In(res): In<Result<T, E>>) -> T {
|
||||||
res.unwrap()
|
res.unwrap()
|
||||||
}
|
}
|
||||||
@ -287,6 +320,7 @@ pub mod adapter {
|
|||||||
/// "42".to_string()
|
/// "42".to_string()
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[deprecated = "use `.map(bevy_utils::info)` instead"]
|
||||||
pub fn info<T: Debug>(In(data): In<T>) {
|
pub fn info<T: Debug>(In(data): In<T>) {
|
||||||
tracing::info!("{:?}", data);
|
tracing::info!("{:?}", data);
|
||||||
}
|
}
|
||||||
@ -314,6 +348,7 @@ pub mod adapter {
|
|||||||
/// Ok("42".parse()?)
|
/// Ok("42".parse()?)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[deprecated = "use `.map(bevy_utils::dbg)` instead"]
|
||||||
pub fn dbg<T: Debug>(In(data): In<T>) {
|
pub fn dbg<T: Debug>(In(data): In<T>) {
|
||||||
tracing::debug!("{:?}", data);
|
tracing::debug!("{:?}", data);
|
||||||
}
|
}
|
||||||
@ -341,6 +376,7 @@ pub mod adapter {
|
|||||||
/// Err("Got to rusty?".to_string())
|
/// Err("Got to rusty?".to_string())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[deprecated = "use `.map(bevy_utils::warn)` instead"]
|
||||||
pub fn warn<E: Debug>(In(res): In<Result<(), E>>) {
|
pub fn warn<E: Debug>(In(res): In<Result<(), E>>) {
|
||||||
if let Err(warn) = res {
|
if let Err(warn) = res {
|
||||||
tracing::warn!("{:?}", warn);
|
tracing::warn!("{:?}", warn);
|
||||||
@ -369,6 +405,7 @@ pub mod adapter {
|
|||||||
/// Err("Some error".to_owned())
|
/// Err("Some error".to_owned())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[deprecated = "use `.map(bevy_utils::error)` instead"]
|
||||||
pub fn error<E: Debug>(In(res): In<Result<(), E>>) {
|
pub fn error<E: Debug>(In(res): In<Result<(), E>>) {
|
||||||
if let Err(error) = res {
|
if let Err(error) = res {
|
||||||
tracing::error!("{:?}", error);
|
tracing::error!("{:?}", error);
|
||||||
@ -409,6 +446,7 @@ pub mod adapter {
|
|||||||
/// Some(())
|
/// Some(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[deprecated = "use `.map(std::mem::drop)` instead"]
|
||||||
pub fn ignore<T>(In(_): In<T>) {}
|
pub fn ignore<T>(In(_): In<T>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,7 +548,7 @@ mod tests {
|
|||||||
Schedule,
|
Schedule,
|
||||||
},
|
},
|
||||||
system::{
|
system::{
|
||||||
adapter::new, Commands, In, IntoSystem, Local, NonSend, NonSendMut, ParamSet, Query,
|
Commands, In, IntoSystem, Local, NonSend, NonSendMut, ParamSet, Query,
|
||||||
QueryComponentError, Res, ResMut, Resource, System, SystemState,
|
QueryComponentError, Res, ResMut, Resource, System, SystemState,
|
||||||
},
|
},
|
||||||
world::{FromWorld, World},
|
world::{FromWorld, World},
|
||||||
@ -1785,10 +1823,10 @@ mod tests {
|
|||||||
!val
|
!val
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_is_system(returning::<Result<u32, std::io::Error>>.pipe(unwrap));
|
assert_is_system(returning::<Result<u32, std::io::Error>>.map(Result::unwrap));
|
||||||
assert_is_system(returning::<Option<()>>.pipe(ignore));
|
assert_is_system(returning::<Option<()>>.map(std::mem::drop));
|
||||||
assert_is_system(returning::<&str>.pipe(new(u64::from_str)).pipe(unwrap));
|
assert_is_system(returning::<&str>.map(u64::from_str).map(Result::unwrap));
|
||||||
assert_is_system(exclusive_in_out::<(), Result<(), std::io::Error>>.pipe(error));
|
assert_is_system(exclusive_in_out::<(), Result<(), std::io::Error>>.map(bevy_utils::error));
|
||||||
assert_is_system(returning::<bool>.pipe(exclusive_in_out::<bool, ()>));
|
assert_is_system(returning::<bool>.pipe(exclusive_in_out::<bool, ()>));
|
||||||
|
|
||||||
returning::<()>.run_if(returning::<bool>.pipe(not));
|
returning::<()>.run_if(returning::<bool>.pipe(not));
|
||||||
|
@ -298,6 +298,30 @@ impl<F: FnOnce()> Drop for OnDrop<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calls the [`tracing::info!`] macro on a value.
|
||||||
|
pub fn info<T: Debug>(data: T) {
|
||||||
|
tracing::info!("{:?}", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calls the [`tracing::debug!`] macro on a value.
|
||||||
|
pub fn dbg<T: Debug>(data: T) {
|
||||||
|
tracing::debug!("{:?}", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes a [`Result`] by calling the [`tracing::warn!`] macro in case of an [`Err`] value.
|
||||||
|
pub fn warn<E: Debug>(result: Result<(), E>) {
|
||||||
|
if let Err(warn) = result {
|
||||||
|
tracing::warn!("{:?}", warn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes a [`Result`] by calling the [`tracing::error!`] macro in case of an [`Err`] value.
|
||||||
|
pub fn error<E: Debug>(result: Result<(), E>) {
|
||||||
|
if let Err(error) = result {
|
||||||
|
tracing::error!("{:?}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Like [`tracing::trace`], but conditional on cargo feature `detailed_trace`.
|
/// Like [`tracing::trace`], but conditional on cargo feature `detailed_trace`.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! detailed_trace {
|
macro_rules! detailed_trace {
|
||||||
|
@ -5,7 +5,7 @@ use bevy::prelude::*;
|
|||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
|
|
||||||
use bevy::log::LogPlugin;
|
use bevy::log::LogPlugin;
|
||||||
use bevy::utils::tracing::Level;
|
use bevy::utils::{dbg, error, info, tracing::Level, warn};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -19,11 +19,11 @@ fn main() {
|
|||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
parse_message_system.pipe(handler_system),
|
parse_message_system.pipe(handler_system),
|
||||||
data_pipe_system.pipe(info),
|
data_pipe_system.map(info),
|
||||||
parse_message_system.pipe(dbg),
|
parse_message_system.map(dbg),
|
||||||
warning_pipe_system.pipe(warn),
|
warning_pipe_system.map(warn),
|
||||||
parse_error_message_system.pipe(error),
|
parse_error_message_system.map(error),
|
||||||
parse_message_system.pipe(ignore),
|
parse_message_system.map(std::mem::drop),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.run();
|
.run();
|
||||||
|
Loading…
Reference in New Issue
Block a user