Skip to content
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

Add a RelatedTo filter for querying relations #17649

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

alice-i-cecile
Copy link
Member

@alice-i-cecile alice-i-cecile commented Feb 2, 2025

Objective

Looking for entities that have a parent (or other relationship) where the parent meets some filter is a common task.

Part of #17647.

Solution

Make it easier by adding a RelatedTo type which implements QueryFilter.

Tasks:

  • create the basic type
  • successfully implement WorldQuery and QueryFilter
  • add comprehensive tests
  • extend documentation
  • ensure tests pass and implementation is correct

Testing

I've added a number of unit tests (and a simple doc test) checking this implementation against various forms of query filters.

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Complex Quite challenging from either a design or technical perspective. Ask for help! D-Unsafe Touches with unsafe code in some way S-Needs-Help The author needs help finishing this PR. labels Feb 2, 2025
@alice-i-cecile
Copy link
Member Author

Currently, WorldQuery::shrink is complaining about:

lifetime may not live long enough
consider adding the following bound: 'wshort: 'wlong

And WorldQuery::fetch is complaining about:

lifetime may not live long enough
consider adding the following bound: 'wshort: 'wlong
requirement occurs because of the type RelatedToFetch<'_, R, F>, which makes the generic argument '_ invariant
the struct RelatedToFetch<'w, R, F> is invariant over the parameter 'w
see https://doc.rust-lang.org/nomicon/subtyping.html for more information about variance

Obviously, neither of those suggestions are good ('short must be less than 'long!), but I'm not immediately sure how to fix it.

@chescock
Copy link
Contributor

chescock commented Feb 3, 2025

Currently, WorldQuery::shrink is complaining about:

lifetime may not live long enough
consider adding the following bound: 'wshort: 'wlong

And WorldQuery::fetch is complaining about:

I think you need to call F::shrink(item) and do something like

RelatedToFetch { 
  relation_fetch: <&R>::shrink_fetch(fetch.relation_fetch),
  filter_fetch: F::shrink_fetch(fetch.filter_fetch),
}

The implementations that have concrete types can just return item and fetch because the compiler knows the concrete types are covariant. Here we have associated types on generic parameters, so the compiler assumes they might be invariant and we have to call the shrink methods explicitly.

})
}

fn matches_component_set(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the test pattern, I suspect that this method is wrong, but I can't figure out why.

Copy link
Member Author

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I think I've figured out the core of what's going wrong here and why some tests pass but others fail. Take this with a grain of salt and correct me: I'm not particularly familiar with manual implementations of WorldQuery.

The key pair of tests to look at is related_to_with (fails) and related_to_with_same_archetype (passes?!).

In order for WorldQuery::fetch to work correctly, we must first set the table / archetype correctly, via WorldQuery::set_table. Unfortunately, the right table is different based on whether we're looking at the base entity (e.g. child) or the target entity (e.g. parent). This means that the case demonstrated in the related_to_with component fails to match the right archetype, and QueryFilter::filter_fetch / WorldQuery::fetch is never called at all. I tested this by sticking a panic in the fetch method: it's not hit for the failing tests.

However, when we share components between the base and target entities, we can accidentally look at the right archetypes, and then WorldQuery::fetch functions as intended.

As for the fix, I'm really not sure. WorldQuery is really designed to operate on only a single entity at once, hence the set_archetype / set_table design. We could relax that, but I worry that the performance characteristics would be untenable. We can find out though!

We could instead swap this over to a SystemParam type, but that's really not much better than the existing query helpers: the WorldQuery impl here / in the linked issue are key to the power and ergonomics.

P.S. I don't think that the API as designed here would work with archetypal relations either 🤔 The core problem is that we need to look at a different table halfway through WorldQuery::fetch, and that method doesn't have access to the parameters required to call set_archetype and/or set_table.

@alice-i-cecile alice-i-cecile added S-Blocked This cannot move forward until something else changes and removed S-Needs-Help The author needs help finishing this PR. labels Feb 3, 2025
github-merge-queue bot pushed a commit that referenced this pull request Feb 3, 2025
# Objective

While working on #17649, I found the docs for `WorldQuery` and the
related traits frustratingly vague.

## Solution

Clarify them and add some more tangible advice.

Also fix a copy-pasted typo in related comments.

---------

Co-authored-by: James O'Brien <[email protected]>
mrchantey pushed a commit to mrchantey/bevy that referenced this pull request Feb 4, 2025
# Objective

While working on bevyengine#17649, I found the docs for `WorldQuery` and the
related traits frustratingly vague.

## Solution

Clarify them and add some more tangible advice.

Also fix a copy-pasted typo in related comments.

---------

Co-authored-by: James O'Brien <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Complex Quite challenging from either a design or technical perspective. Ask for help! D-Unsafe Touches with unsafe code in some way S-Blocked This cannot move forward until something else changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants