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

Implement WorldQuery and QueryData for Mut #13329

Closed
Themayu opened this issue May 11, 2024 · 3 comments · Fixed by #13338
Closed

Implement WorldQuery and QueryData for Mut #13329

Themayu opened this issue May 11, 2024 · 3 comments · Fixed by #13338
Labels
A-ECS Entities, components, systems, and events C-Enhancement A new feature D-Straightforward Simple bug fixes and API improvements, docs, test and examples X-Contentious There are nontrivial implications that should be thought through

Comments

@Themayu
Copy link
Contributor

Themayu commented May 11, 2024

This is an alternative means of achieving the goals of #12920.

What problem does this solve or what need does it fill?

Currently, the QueryData derive macro transforms fields of the type &'static mut T to Mut<'w, T> when generating the item type for the query. However, the readonly item type continues to use &'w T as the reference type. This makes it impossible to use change detection on the readonly form of mutable queries.

As an example from my code:

#[derive(QueryData)]
#[query_data(mutable)]
pub struct TextBoxQuery {
    pub data: &'static mut TextBox,
    pub style: &'static mut TextBoxStyle,
    pub text_style: &'static mut TextBoxTextStyle,
}

// derive(QueryData) output
pub struct TextBoxQueryItem<'w> {
    pub data: Mut<'w, TextBox>,
    pub style: Mut<'w, TextBoxStyle>,
    pub text_style: Mut<'w, TextBoxTextStyle>,
}

pub struct TextBoxQueryReadOnlyItem<'w> {
    pub data: &'w TextBox,
    pub style: &'w TextBoxStyle,
    pub text_style: &'w TextBoxTextStyle,
}

What solution would you like?

In #12920, I proposed extending the QueryData derive to add a detect_changes option that would make the derive macro emit Ref<T> instead of Self::ReadOnly when it encounters a &mut T. I've since realised a simpler way of handling the problem: implement WorldQuery and QueryData for Mut<T> directly, setting its ReadOnly type alias to Ref<T>.

I realised this alternate solution during an unstructured discussion in the #ecs_dev Discord channel where some additional questions were brought up.

This would allow for opting into change detection in the readonly form of the query without requiring extension of the derive macro itself, by defining a field as Mut<'_, T> instead of &'_ mut T:

#[derive(QueryData)]
#[query_data(mutable)]
pub struct TextBoxQuery {
    pub data: Mut<'static, TextBox>,
    pub style: &'static mut TextBoxStyle,
    pub text_style: &'static mut TextBoxTextStyle,
}

// derive(QueryData) output
pub struct TextBoxQueryItem<'w> {
    pub data: Mut<'w, TextBox>,
    pub style: Mut<'w, TextBoxStyle>, // this seems confusing, so I was hesitant to bring the idea up at first
    pub text_style: Mut<'w, TextBoxTextStyle>,
}

pub struct TextBoxQueryReadOnlyItem<'w> {
    pub data: Ref<'w, TextBox>,
    pub style: &'w TextBoxStyle,
    pub text_style: &'w TextBoxTextStyle,
}

What alternative(s) have you considered?

Continue with #12920, which has proven difficult to even begin implementing.

@Themayu Themayu added C-Enhancement A new feature S-Needs-Triage This issue needs to be labelled labels May 11, 2024
@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events X-Contentious There are nontrivial implications that should be thought through D-Straightforward Simple bug fixes and API improvements, docs, test and examples and removed S-Needs-Triage This issue needs to be labelled labels May 12, 2024
@alice-i-cecile
Copy link
Member

I prefer this solution to the problem.

@Themayu
Copy link
Contributor Author

Themayu commented May 12, 2024

Implementation-wise, would it be sufficient to copy the implementations on &mut T, with a single change to the ReadOnly associated type?

@alice-i-cecile
Copy link
Member

I believe that should work. I'd like to see a doc comment on the implementation that explains why this exists, and a doc test that demonstrates the intended use.

github-merge-queue bot pushed a commit that referenced this issue May 14, 2024
# Objective

Provides a `WorldQuery` implementation on `Mut<T>` that forwards to the
implementation on `&mut T`, and give users a way to opt-in to change
detection in auto-generated `QueryData::ReadOnly` types.

Fixes #13329.

## Solution

I implemented `WorldQuery` on `Mut<'w, T>` as a forwarding
implementation to `&mut T`, setting the `QueryData::ReadOnly` associated
type to `Ref<'w, T>`. This provides users the ability to explicitly
opt-in to change detection in the read-only forms of queries.

## Testing

A documentation test was added to `Mut` showcasing the new
functionality.

---

## Changelog

### Added

- Added an implementation of `WorldQuery` and `QueryData` on
`bevy_ecs::change_detection::Mut`.
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-Enhancement A new feature D-Straightforward Simple bug fixes and API improvements, docs, test and examples X-Contentious There are nontrivial implications that should be thought through
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants