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

[Merged by Bors] - Add set_if_neq method to DetectChanges trait (Rebased) #6853

Closed
wants to merge 4 commits into from

Conversation

Dessix
Copy link
Contributor

@Dessix Dessix commented Dec 5, 2022

Objective

Change detection can be spuriously triggered by setting a field to the same value as before. As a result, a common pattern is to write:

if *foo != value {
  *foo = value;
}

This is confusing to read, and heavy on boilerplate.

Adopted from #5373, but untangled and rebased to current bevy/main.

Solution

1. Add a method to the `DetectChanges` trait that implements this boilerplate when the appropriate trait bounds are met.

2. Document this minor footgun, and point users to it.

Changelog

* added the `set_if_neq` method to avoid triggering change detection when the new and previous values are equal. This will work on both components and resources.

Migration Guide

If you are manually checking if a component or resource's value is equal to its new value before setting it to avoid triggering change detection, migrate to the clearer and more convenient set_if_neq method.

Context

Related to #2363 as it avoids triggering change detection, but not a complete solution (as it still requires triggering it when real changes are made).

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use labels Dec 5, 2022
Copy link
Member

@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.

Thanks! I have no idea how it got so tangled.

@Dessix
Copy link
Contributor Author

Dessix commented Dec 5, 2022

Thanks! I have no idea how it got so tangled.

Something about how GitHub does sequential non-linear merges, I think. It was an unusually tangled rebase for sure.

@mockersf
Copy link
Member

mockersf commented Dec 5, 2022

Is it set_if_differs as in the PR title, or set_if_neq as in the code?

@Dessix Dessix changed the title Add set_if_differs method to DetectChanges trait (Rebased) Add set_if_neq method to DetectChanges trait (Rebased) Dec 5, 2022
@Dessix
Copy link
Contributor Author

Dessix commented Dec 5, 2022

Is it set_if_differs as in the PR title, or set_if_neq as in the code?

@mockersf I had quoted the original PR name prior to updating it. I've altered this one to match the content.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Dec 11, 2022
@alice-i-cecile
Copy link
Member

bors r+

bors bot pushed a commit that referenced this pull request Dec 11, 2022
# Objective

Change detection can be spuriously triggered by setting a field to the same value as before. As a result, a common pattern is to write:

```rust
if *foo != value {
  *foo = value;
}
```

This is confusing to read, and heavy on boilerplate.

Adopted from #5373, but untangled and rebased to current `bevy/main`.

## Solution

    1. Add a method to the `DetectChanges` trait that implements this boilerplate when the appropriate trait bounds are met.

    2. Document this minor footgun, and point users to it.


## Changelog

    * added the `set_if_neq` method to avoid triggering change detection when the new and previous values are equal. This will work on both components and resources.


## Migration Guide

If you are manually checking if a component or resource's value is equal to its new value before setting it to avoid triggering change detection, migrate to the clearer and more convenient `set_if_neq` method.
## Context

Related to #2363 as it avoids triggering change detection, but not a complete solution (as it still requires triggering it when real changes are made).



Co-authored-by: Zoey <Dessix@Dessix.net>
@bors bors bot changed the title Add set_if_neq method to DetectChanges trait (Rebased) [Merged by Bors] - Add set_if_neq method to DetectChanges trait (Rebased) Dec 11, 2022
@bors bors bot closed this Dec 11, 2022
@james7132 james7132 added this to the 0.10 milestone Dec 12, 2022
bors bot pushed a commit that referenced this pull request Jan 6, 2023
# Objective

- The doctest for `Mut::map_unchanged` uses a fake function `set_if_not_equal` to demonstrate usage.
- Now that #6853 has been merged, we can use `Mut::set_if_neq` directly instead of mocking it.
james7132 pushed a commit to james7132/bevy that referenced this pull request Jan 21, 2023
# Objective

- The doctest for `Mut::map_unchanged` uses a fake function `set_if_not_equal` to demonstrate usage.
- Now that bevyengine#6853 has been merged, we can use `Mut::set_if_neq` directly instead of mocking it.
alradish pushed a commit to alradish/bevy that referenced this pull request Jan 22, 2023
…e#6853)

# Objective

Change detection can be spuriously triggered by setting a field to the same value as before. As a result, a common pattern is to write:

```rust
if *foo != value {
  *foo = value;
}
```

This is confusing to read, and heavy on boilerplate.

Adopted from bevyengine#5373, but untangled and rebased to current `bevy/main`.

## Solution

    1. Add a method to the `DetectChanges` trait that implements this boilerplate when the appropriate trait bounds are met.

    2. Document this minor footgun, and point users to it.


## Changelog

    * added the `set_if_neq` method to avoid triggering change detection when the new and previous values are equal. This will work on both components and resources.


## Migration Guide

If you are manually checking if a component or resource's value is equal to its new value before setting it to avoid triggering change detection, migrate to the clearer and more convenient `set_if_neq` method.
## Context

Related to bevyengine#2363 as it avoids triggering change detection, but not a complete solution (as it still requires triggering it when real changes are made).



Co-authored-by: Zoey <Dessix@Dessix.net>
alradish pushed a commit to alradish/bevy that referenced this pull request Jan 22, 2023
# Objective

- The doctest for `Mut::map_unchanged` uses a fake function `set_if_not_equal` to demonstrate usage.
- Now that bevyengine#6853 has been merged, we can use `Mut::set_if_neq` directly instead of mocking it.
ItsDoot pushed a commit to ItsDoot/bevy that referenced this pull request Feb 1, 2023
…e#6853)

# Objective

Change detection can be spuriously triggered by setting a field to the same value as before. As a result, a common pattern is to write:

```rust
if *foo != value {
  *foo = value;
}
```

This is confusing to read, and heavy on boilerplate.

Adopted from bevyengine#5373, but untangled and rebased to current `bevy/main`.

## Solution

    1. Add a method to the `DetectChanges` trait that implements this boilerplate when the appropriate trait bounds are met.

    2. Document this minor footgun, and point users to it.


## Changelog

    * added the `set_if_neq` method to avoid triggering change detection when the new and previous values are equal. This will work on both components and resources.


## Migration Guide

If you are manually checking if a component or resource's value is equal to its new value before setting it to avoid triggering change detection, migrate to the clearer and more convenient `set_if_neq` method.
## Context

Related to bevyengine#2363 as it avoids triggering change detection, but not a complete solution (as it still requires triggering it when real changes are made).



Co-authored-by: Zoey <Dessix@Dessix.net>
ItsDoot pushed a commit to ItsDoot/bevy that referenced this pull request Feb 1, 2023
# Objective

- The doctest for `Mut::map_unchanged` uses a fake function `set_if_not_equal` to demonstrate usage.
- Now that bevyengine#6853 has been merged, we can use `Mut::set_if_neq` directly instead of mocking it.
bors bot pushed a commit that referenced this pull request Feb 15, 2023
# Objective

While porting my crate `bevy_trait_query` to bevy 0.10, I ran into an issue with the `DetectChangesMut` trait. Due to the way that the `set_if_neq` method (added in #6853) is implemented, you are forced to write a nonsense implementation of it for dynamically sized types. This edge case shows up when implementing trait queries, since `DetectChangesMut` is implemented for `Mut<dyn Trait>`.

## Solution

Simplify the generics for `set_if_neq` and add the `where Self::Target: Sized` trait bound to it. Add a default implementation so implementers don't need to implement a method with nonsensical trait bounds.
myreprise1 pushed a commit to myreprise1/bevy that referenced this pull request Feb 16, 2023
# Objective

While porting my crate `bevy_trait_query` to bevy 0.10, I ran into an issue with the `DetectChangesMut` trait. Due to the way that the `set_if_neq` method (added in bevyengine#6853) is implemented, you are forced to write a nonsense implementation of it for dynamically sized types. This edge case shows up when implementing trait queries, since `DetectChangesMut` is implemented for `Mut<dyn Trait>`.

## Solution

Simplify the generics for `set_if_neq` and add the `where Self::Target: Sized` trait bound to it. Add a default implementation so implementers don't need to implement a method with nonsensical trait bounds.
myreprise1 pushed a commit to myreprise1/bevy that referenced this pull request Feb 16, 2023
# Objective

While porting my crate `bevy_trait_query` to bevy 0.10, I ran into an issue with the `DetectChangesMut` trait. Due to the way that the `set_if_neq` method (added in bevyengine#6853) is implemented, you are forced to write a nonsense implementation of it for dynamically sized types. This edge case shows up when implementing trait queries, since `DetectChangesMut` is implemented for `Mut<dyn Trait>`.

## Solution

Simplify the generics for `set_if_neq` and add the `where Self::Target: Sized` trait bound to it. Add a default implementation so implementers don't need to implement a method with nonsensical trait bounds.
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 simple quality-of-life change that makes Bevy easier to use S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants