-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
QuerySingle
family of system params
#15476
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
Conversation
The generated |
7896012
to
125002a
Compare
4bd9cd3
to
1b84446
Compare
unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam | ||
for Option<QuerySingle<'a, D, 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 wonder if now that we have validate_param
we could use it to write a generic impl<S: SystemParam> SystemParam for Option<S>
. This could be tackled in a separate PR though.
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 every Option<P>
makes sense, like Option<Query>
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.
Also, infinitely nested Option
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.
Right, though maybe this could be solved with a marker trait for those system parameters for which Option
can make sense.
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.
If there is a decent way to derive it I'm down.
There are some cases where Option
needs some specialized code, like in QuerySingle
state.as_readonly().get_single_unchecked_manual( | ||
world, | ||
system_meta.last_run, | ||
world.change_tick(), |
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.
Are we sure this is the change tick that will be used for calling get_param
, or an equivalent one for what matters to it? If so could you write a comment explaining why that's the case?
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.
Practically yes, this happens to be the exact tick that is received by get_param
, but there are not validation mechanisms/contract for that.
Currently only executors use validate_param
and since the validation and running happens one after another, this is the correct change tick.
For run_systems
and observers this also shouldn't be a problem.
While I can make validate_param
accept a change_tick
, the problem is that the tick used by get_param
is generated inside run_unsafe
, so we'd still need to uphold this "contract" of calling them back-to-back.
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'm open for docs/mechanisms on making this better, I'm not sure how to go about 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.
It won't always be exactly the same tick, because the multi-threaded executor will call validate_param
and then spawn a task to run the system and call get_param
at some later point. Another system could start in between and increment the current tick.
I think it will be equivalent, though. Any components read by this param can't be written by another system in between the calls, so they can't have an added
or changed
tick in between the two change_tick
values.
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.
Okay, I'll try to thoroughly document this in validate_param
7509d02
to
9d0ab0f
Compare
for QuerySingle<'a, D, F> | ||
{ | ||
type State = QueryState<D, F>; | ||
type Item<'w, 's> = QuerySingle<'w, D, 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.
Why isn't this just <D as QueryData>::Item
? I think that would improve the ergonomics and complexity quite a bit?
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.
The ergonomics comment got removed, CI told me to remove unnecessary syntax which made it way better.
<D as WorldQuery>::Item
is not a SystemParam
so that's one issue with this.
Another would be, if SystemParam
returns anything else than itself with changed lifetimes, it won't fit as the system argument.
fn my_system(q: QuerySingle<Entity>) { ... }
// imaginary executor code
let q: <Entity as WorldQuery>::Item = QuerySingle<Entity>::get_param(world);
system(q); // Expected `QuerySingle` got `<Entity as WorldQuery>::Item`
# Objective Add the following system params: - `QuerySingle<D, F>` - Valid if only one matching entity exists, - `Option<QuerySingle<D, F>>` - Valid if zero or one matching entity exists. As @chescock pointed out, we don't need `Mut` variants. Fixes: bevyengine#15264 ## Solution Implement the type and both variants of system params. Also implement `ReadOnlySystemParam` for readonly queries. Added a new ECS example `fallible_params` which showcases `SingleQuery` usage. In the future we might want to add `NonEmptyQuery`, `NonEmptyEventReader` and `Res` to it (or maybe just stop at mentioning it). ## Testing Tested with the example. There is a lot of warning spam so we might want to implement bevyengine#15391.
Thank you to everyone involved with the authoring or reviewing of this PR! This work is relatively important and needs release notes! Head over to bevyengine/bevy-website#1701 if you'd like to help out. |
Objective
Add the following system params:
QuerySingle<D, F>
- Valid if only one matching entity exists,Option<QuerySingle<D, F>>
- Valid if zero or one matching entity exists.As @chescock pointed out, we don't need
Mut
variants.Fixes: #15264
Solution
Implement the type and both variants of system params.
Also implement
ReadOnlySystemParam
for readonly queries.Added a new ECS example
fallible_params
which showcasesSingleQuery
usage.In the future we might want to add
NonEmptyQuery
,NonEmptyEventReader
andRes
to it (or maybe just stop at mentioning it).Testing
Tested with the example.
There is a lot of warning spam so we might want to implement #15391.