-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Impl system condition combinators for Result
-ful run conditions
#19580
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
base: main
Are you sure you want to change the base?
Conversation
Result
-ful run conditions
@urben1680 want to review this one too? |
I think Regarding the When this leaves Draft I do a proper review. 👍 |
@urben1680 PR is ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would only like to see a change about the not
return type becoming anonymous, the other things do not bother me enough. 😄
pub fn not<Marker, In, Out, C>( | ||
condition: C, | ||
) -> AdapterSystem<fn(bool) -> bool, C::ConditionSystem> | ||
where | ||
TOut: core::ops::Not, | ||
T: IntoSystem<(), TOut, Marker>, | ||
In: SystemInput, | ||
C: SystemCondition<Marker, In, Out>, | ||
{ | ||
let condition = IntoSystem::into_system(condition); | ||
let name = format!("!{}", condition.name()); | ||
NotSystem::new(super::NotMarker, condition, name.into()) | ||
let f: fn(bool) -> bool = |x| !x; | ||
IntoSystem::into_system(condition.into_condition_system().map(f)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can return an impl SystemCondition<(), In>
here so you don't need to turn that mapping function into a function pointer which requires slower dynamic dispatch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning impl SystemCondition<(), In>
caused the compiler to complain about a missing Clone
bound. I finally went another way. Using the approach in NotSystem
of defining a helper type, I removed the use of a function pointer. I also reworked on the implementations of SystemCondition
to remove function pointers there as well.
/// Invokes [`Not`] with the output of another system. | ||
/// | ||
/// See [`common_conditions::not`] for examples. | ||
pub type NotSystem<S> = AdapterSystem<NotMarker, S>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why this explicit type was needed and why it needed to be public when all other methods returned impl ...
.
I think there are two alternatives here:
- Write a migration guide that this type alias is gone.
- Stick to the explicit type returned by
not
and change this to this: (maybe with a#[deprecated]
as it is unused in the engine now)
type NotSystem<T, In = (), Out = bool> = AdapterSystem<fn(bool) -> bool, <T as SystemCondition<(), In, Out>>::ConditionSystem>;
I strongly prefer 1, also because I think 2 does not technically resemble the original NotSystem
alias depending on how exotic the system output were with that Not
impl. I am not even sure 2. works.
But I am fine with not do anything here as I assume nobody used this alias.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why this was needed either. I wrote the migration guide. I also removed a line in the documentation example of trait Adapt
.
@@ -1214,7 +1232,7 @@ where | |||
fn combine( | |||
input: <Self::In as SystemInput>::Inner<'_>, | |||
a: impl FnOnce(SystemIn<'_, A>) -> A::Out, | |||
b: impl FnOnce(SystemIn<'_, A>) -> B::Out, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, was this ever working? If not, was this ever used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, this was only ever used in conjunction with run_if
which only accepts a system with In = ()
. So this never came into play as this is always called with In = ()
for both systems A and B. But this might change in the future so we may as well correct it now.
counter *= 3 * 7 * 13 * 17 * 23 * 29; | ||
assert_eq!(world.resource::<Counter>().0, counter); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests are ridiculous because who reads them must first understand that these primes can only multiply to the correct value if the expected conditions ran. But all previous tests here look like that so I guess it is fine. I just wanted to say it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted. I thought the intent was clear and it is concise this way.
// This associated type is necessary to let the compiler | ||
// know that `Self::System` is `ReadOnlySystem`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this comment needs to be added on every impl. You can also make it a proper doc of this associated type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. That's better. I'll make a proper doc and add one as well for the other associated type.
This PR seems to fix #19527 |
…led::SystemCondition
…on' into impl_system_condition
@@ -16,7 +16,6 @@ use crate::{ | |||
/// 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`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not()
cannot accept any system whose output is Not
anymore so this is not a manual implementation of it anymore.
/// Used with [`AdapterSystem`] to inverse the `bool` returned by the system. | ||
#[doc(hidden)] | ||
#[derive(Clone, Copy)] | ||
pub struct InverseBoolAdapter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This used to be NotMarker
. It's now outputting a bool
instead of a Not
. Thought the name bad.
Co-authored-by: urben1680 <[email protected]>
Note that #19145 would address the same issue with an incompatible approach, by making all systems return |
Objective
This is a follow-up of #19553.
I missed something. Right now the combinators (
and
,or
, ...) only work with conditions returningbool
. The same goes forcondition_changed
,condition_changed_to
andnot
. The objective is to fix that to allow conditions returningResult<(), BevyError>
andResult<bool, BevyError>
to use these methods as well.Solution
It's essentially just about calling
into_condition_system()
in the methods. I just have a problem fornot
because it's implemented differently than the others. Currentlynot
can accept any system whose output implementNot
. That's a problem for systems returningResult<(), BevyError>
orResult<bool, BevyError>
. I see mostly two options:not
.not
to accept only run conditions. This waynot
could accept the new run conditions but not any system whose output implementsNot
.I would say the second solution has more upsides than downsides because
not
withNot
feels more niche than use cases ofnot
with the new conditionsrun_if
but notnot
is confusing)Not
you can still dosystem.map(|x| !x)
but I may be missing something. What do you think ?
Testing
I also added a simple test for all the missing methods.