-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
QueryState::new_with_state #6240
Conversation
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 example is great, but we probably also want a third query_state initialization showing how to init filter state.
Awesome work; thanks for the prompt response. This is a niche feature, but I think it will be useful as part of our "dynamic components" story. |
No problem, your prompt response is much more appreciated :) With this feature it is already possible to make a dynamic query by implementing |
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 not qualified enough to review the Bevy query internals yet/anymore, but I seem to remember needing this in my now very old scripting API/PR, so.., 👍 😁
Yep, I mostly wanted to hear if you thought it was useful :) The implementation is trivial, and the docs are great. |
I expect this is incredibly unsound as-is since it would let you construct a Having a way to do the goal of this PR does seem useful for dynamic queries and I think relations could make use of this too. |
Nice catch @BoxyUwU! While there is nothing unsafe that this function does, indeed we can incorrectly cast types as a consequence. There are two ways I see that this can be resolved.
|
The former is definitely safer. This would be a one time cost paid during system / query initialization, correct? |
no, |
Made the method unsafe and added the appropriate safety comment |
Currently the bevy/crates/bevy_ecs/src/storage/blob_vec.rs Lines 141 to 144 in d38a8df
As I understand it, the point of the struct ComponentIdQuery(ComponentId);
struct ComponentIdQueryMut(ComponentId);
impl WorldQuery for ComponentIdQuery {
type Item = Ptr<'_>;
...
}
impl WorldQuery for ComponentIdQueryMut {
type Item = (PtrMut<'_>, &mut Ticks);
...
} is that currently trait WorldQuery: WorldQueryGats {
type State;
+ type Config;
- fn init_state(world: &mut World) -> Self::State;
+ fn init_state(world: &mut World, config: Self::Config) -> Self::State;
} where the current implementors set Then you can add impls of let query = QueryState<Vec<ComponentIdQuery>>::new_with_config(vec![my_component_id_1, my_component_id_2]); |
It's sort of difficult because this method is only unsafe when querying component references, but I reordered the safety comment to more strongly word the requirements for safety.
This is exactly right! However, this isn't the only use, one could likely implement world query for Your solution is definitely an improvement, however, I would like to prioritize minimal changes with this PR. Dynamic query work is still up for discussion on how it should be implemented, and I would like to avoid establishing any future design directions, and instead, work with the API surface as it is available today. |
e104365
to
6cbbb9d
Compare
I disagree with this, worldquery impls should be able to rely on the state being created from their own If the above is true then this API is also kind of Not Great, I would much prefer the solution @jakobhellermann proposes with a |
The problem I see is that I've tried the implementation suggested and it results in a lot of extra type constraints that need to be managed across the codebase, and due to the above, severely restricts the reusability of existing implementations.
Due to this restriction on While I agree that queries should be able to rely on their |
Yeah, the |
I think one could argue that having a default here is equally dangerous as providing the state outright, due to the potential implications of accidentally using a It results in a situation where you don't know whether The added benefit of this PR would be that you can avoid the added complication of manipulating type bounds. |
I posted a PR of my proposal: #6390 |
ae570b0
to
767efee
Compare
Improved doc comment Further improved doc Make QueryState::new_with_state unsafe Reorder safety comment Relax safety comment
767efee
to
d3dfbfa
Compare
Resolved by #9774 |
Objective
Allows providing state to
QueryState
which requires input other thanWorldQuery::init_state(&mut World)
to be constructed.This allows the user to provide a custom state such as
ComponentId
for dynamic queries which cannot be derived from the type definition.Solution
Create new method
QueryState::new_with_state
, which is now called byQueryState::new
usingWorldQuery::init_state
.