Skip to content

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

Closed
Dessix wants to merge 4 commits intobevyengine:mainfrom
Dessix:set-if-differz
Closed

[Merged by Bors] - Add set_if_neq method to DetectChanges trait (Rebased)#6853
Dessix wants to merge 4 commits intobevyengine:mainfrom
Dessix:set-if-differz

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 targeted 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 targeted 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