# Objective
- Make it possible to know *what* changed your component or resource.
- Common need when debugging, when you want to know the last code
location that mutated a value in the ECS.
- This feature would be very useful for the editor alongside system
stepping.
## Solution
- Adds the caller location to column data.
- Mutations now `track_caller` all the way up to the public API.
- Commands that invoke these functions immediately call
`Location::caller`, and pass this into the functions, instead of the
functions themselves attempting to get the caller. This would not work
for commands which are deferred, as the commands are executed by the
scheduler, not the user's code.
## Testing
- The `component_change_detection` example now shows where the component
was mutated:
```
2024-07-28T06:57:48.946022Z INFO component_change_detection: Entity { index: 1, generation: 1 }: New value: MyComponent(0.0)
2024-07-28T06:57:49.004371Z INFO component_change_detection: Entity { index: 1, generation: 1 }: New value: MyComponent(1.0)
2024-07-28T06:57:49.012738Z WARN component_change_detection: Change detected!
-> value: Ref(MyComponent(1.0))
-> added: false
-> changed: true
-> changed by: examples/ecs/component_change_detection.rs:36:23
```
- It's also possible to inspect change location from a debugger:
<img width="608" alt="image"
src="https://github.com/user-attachments/assets/c90ecc7a-0462-457a-80ae-42e7f5d346b4">
---
## Changelog
- Added source locations to ECS change detection behind the
`track_change_detection` flag.
## Migration Guide
- Added `changed_by` field to many internal ECS functions used with
change detection when the `track_change_detection` feature flag is
enabled. Use Location::caller() to provide the source of the function
call.
---------
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
- In #12965 I broke CI (sorry!)
- The command was tested locally, but somehow the yaml formatting messed
it up
- I hate yaml
## Solution
- It should now use the correct formatting
- I hope
- I wish there was a straightforward way to test github actions locally
# Objective
Optimize the cloning process for Access-related structs in the ECS
system, specifically targeting the `clone_from` method.
Previously, profiling showed that 1% of CPU time was spent in
`FixedBitSet`'s `drop_in_place`, due to the default `clone_from`
implementation:
```rust
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}
```
This implementation causes unnecessary allocations and deallocations.
However, [FixedBitSet provides a more optimized clone_from
method](https://github.com/petgraph/fixedbitset/blob/master/src/lib.rs#L1445-L1465)
that avoids these allocations and utilizes SIMD instructions for better
performance.
This PR aims to leverage the optimized clone_from method of FixedBitSet
and implement custom clone_from methods for Access-related structs to
take full advantage of this optimization. By doing so, we expect to
significantly reduce CPU time spent on cloning operations and improve
overall system performance.
![image](https://github.com/user-attachments/assets/7526a5c5-c75b-4a9a-b8d2-891f64fd553b)
## Solution
- Implemented custom `clone` and `clone_from` methods for `Access`,
`FilteredAccess`, `AccessFilters`, and `FilteredAccessSet` structs.
- Removed `#[derive(Clone)]` and manually implemented `Clone` trait to
use optimized `clone_from` method from `FixedBitSet`.
- Added unit tests for cloning and `clone_from` methods to ensure
correctness.
## Testing
- Conducted performance testing comparing the original and optimized
versions.
- Measured CPU time consumption for the `clone_from` method:
- Original version: 1.34% of CPU time
- Optimized version: 0.338% of CPU time
- Compared FPS before and after the changes (results may vary depending
on the run):
Before optimization:
```
2024-07-28T12:49:11.864019Z INFO bevy diagnostic: fps : 213.489463 (avg 214.502488)
2024-07-28T12:49:11.864037Z INFO bevy diagnostic: frame_time : 4.704746ms (avg 4.682251ms)
2024-07-28T12:49:11.864042Z INFO bevy diagnostic: frame_count: 7947.000000 (avg 7887.500000)
```
![image](https://github.com/user-attachments/assets/7865a365-0569-4b46-814a-964779d90973)
After optimization:
```
2024-07-28T12:29:42.705738Z INFO bevy diagnostic: fps : 220.273721 (avg 220.912227)
2024-07-28T12:29:42.705762Z INFO bevy diagnostic: frame_time : 4.559127ms (avg 4.544905ms)
2024-07-28T12:29:42.705769Z INFO bevy diagnostic: frame_count: 7596.000000 (avg 7536.500000)
```
![image](https://github.com/user-attachments/assets/8dd96908-86d0-4850-8e29-f80176a005d6)
---
Reviewers can test these changes by running `cargo run --release
--example ssr`
# Objective
Fixes https://github.com/bevyengine/bevy-website/issues/1558
Followup to #12348
For the website pages extra link, it needs kebab case for the category
name and a trailing forward slash to make the link for the Bevy website
correct and not have unnecessary redirections.
## Solution
Changes the category name to kebab case for the extra link, and adds a
trailing forward slash to the link.
## Testing
I have tested these changes.
Clone my fork with the changes in `bevy-website/generate-wasm-examples/`
then `cd bevy && git switch bevy-website/1558_fix_beautify_example_links
&& cd ..` and then `./generate_wasm_examples.sh` to generate examples.
Afterwards runs `zola serve` and go to `http://127.0.0.1:1111/examples`
and hover over or inspect the cards links / anchors to see that the link
is now correct, click on any of the cards to see that there is no
redirects.
# Objective
The `ui_layout_system` relies on change detection to sync parent-child
relation to taffy. The children need to by synced before node removal to
avoid trying to set deleted nodes as children (due to how the different
queries collect entities). This however may leave nodes that were
removed set as children to other nodes in special cases.
Fixes#11385
## Solution
The solution is simply to re-sync the changed children after the nodes
are removed.
## Testing
Tested with `sickle_ui` where docking zone highlights would end up
glitched when docking was done in a certain manner:
- run the `docking_zone_splits` example
- pop out a tab from the top
- dock the floating panel in the center right
- grab another tab and try to hover the original static docking zone:
the highlight is semi-stuck
- (NOTE: sometimes it worked even without the fix due to scheduling
order not producing the bugged query results)
After the fix, the issue is no longer present.
NOTE: The performance impact should be minimal, as the child sync relies
on change detection. The change detection was also the reason the parent
nodes remained "stuck" with the phantom children if no other update were
done to them.
# Objective
Clarify that `StatesPlugin` is a prerequisite for state code.
Closes#14329 .
Edit: am I missing a way to link `DefaultPlugins` correctly other than
using the URL? I guess I expected to be able to refer to it with
`bevy::prelude::DefaultPlugins` or some such 🤔
# Objective
Use the new `AccumulatedMouseMotion` and `AccumulatedMouseScroll`
resources in place of mouse event handling.
I left the `mouse_input_events` example alone, since by its nature it
demonstrates event detection.
Fixes#14066
## Testing
Ran each example locally before and after changes.
# Objective
Previously, this area of bevy_math used raw translation and rotations to
encode isometries, which did not exist earlier. The goal of this PR is
to make the codebase of bevy_math more harmonious by using actual
isometries (`Isometry2d`/`Isometry3d`) in these places instead — this
will hopefully make the interfaces more digestible for end-users, in
addition to facilitating conversions.
For instance, together with the addition of #14478, this means that a
bounding box for a collider with an isometric `Transform` can be
computed as
```rust
collider.aabb_3d(collider_transform.to_isometry())
```
instead of using manual destructuring.
## Solution
- The traits `Bounded2d` and `Bounded3d` now use `Isometry2d` and
`Isometry3d` (respectively) instead of `translation` and `rotation`
parameters; e.g.:
```rust
/// A trait with methods that return 3D bounding volumes for a shape.
pub trait Bounded3d {
/// Get an axis-aligned bounding box for the shape translated and
rotated by the given isometry.
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d;
/// Get a bounding sphere for the shape translated and rotated by the
given isometry.
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere;
}
```
- Similarly, the `from_point_cloud` constructors for axis-aligned
bounding boxes and bounding circles/spheres now take isometries instead
of separate `translation` and `rotation`; e.g.:
```rust
/// Computes the smallest [`Aabb3d`] containing the given set of points,
/// transformed by the rotation and translation of the given isometry.
///
/// # Panics
///
/// Panics if the given set of points is empty.
#[inline(always)]
pub fn from_point_cloud(
isometry: Isometry3d,
points: impl Iterator<Item = impl Into<Vec3A>>,
) -> Aabb3d { //... }
```
This has a couple additional results:
1. The end-user no longer interacts directly with `Into<Vec3A>` or
`Into<Rot2>` parameters; these conversions all happen earlier now,
inside the isometry types.
2. Similarly, almost all intermediate `Vec3 -> Vec3A` conversions have
been eliminated from the `Bounded3d` implementations for primitives.
This probably has some performance benefit, but I have not measured it
as of now.
## Testing
Existing unit tests help ensure that nothing has been broken in the
refactor.
---
## Migration Guide
The `Bounded2d` and `Bounded3d` traits now take `Isometry2d` and
`Isometry3d` parameters (respectively) instead of separate translation
and rotation arguments. Existing calls to `aabb_2d`, `bounding_circle`,
`aabb_3d`, and `bounding_sphere` will have to be changed to use
isometries instead. A straightforward conversion is to refactor just by
calling `Isometry2d/3d::new`, as follows:
```rust
// Old:
let aabb = my_shape.aabb_2d(my_translation, my_rotation);
// New:
let aabb = my_shape.aabb_2d(Isometry2d::new(my_translation, my_rotation));
```
However, if the old translation and rotation are 3d
translation/rotations originating from a `Transform` or
`GlobalTransform`, then `to_isometry` may be used instead. For example:
```rust
// Old:
let bounding_sphere = my_shape.bounding_sphere(shape_transform.translation, shape_transform.rotation);
// New:
let bounding_sphere = my_shape.bounding_sphere(shape_transform.to_isometry());
```
This discussion also applies to the `from_point_cloud` construction
method of `Aabb2d`/`BoundingCircle`/`Aabb3d`/`BoundingSphere`, which has
similarly been altered to use isometries.
# Objective
When depending on the `bevy_ui` crate specifically and using the
`serialize` feature flag, the compilation fails due to `bevy_math` not
having the serialize flag enabled.
## Solution
Added the `serialize` flag to the `bevy_math` dependency when using that
flag on `bevy_ui`.
## Testing
Tested by adding `bevy_math = { version = "0.14", features =
["serialize"] }` on a small Bevy library to ensure compilation was
successful.
Fixes#14418
Note that this does not add AtomicPtr, which would need its own special
casing support, just the regular value types.
Also, I was forced to be opinionated about which Ordering to use, so I
chose SeqCst as the strictest by default.
# Objective
Previously, our cubic spline constructors would produce
`CubicCurve`/`RationalCurve` output with no data when they themselves
didn't hold enough control points to produce a well-formed curve.
Attempting to sample the resulting empty "curves" (e.g. by calling
`CubicCurve::position`) would crash the program (😓).
The objectives of this PR are:
1. Ensure that the curve output of `bevy_math`'s spline constructions
are never invalid as data.
2. Provide a type-level guarantee that `CubicCurve` and `RationalCurve`
actually function as curves.
## Solution
This has a few pieces. Firstly, the curve generator traits
`CubicGenerator`, `CyclicCubicGenerator`, and `RationalGenerator` are
now fallible — they have associated error types, and the
curve-generation functions are allowed to fail:
```rust
/// Implement this on cubic splines that can generate a cubic curve from their spline parameters.
pub trait CubicGenerator<P: VectorSpace> {
/// An error type indicating why construction might fail.
type Error;
/// Build a [`CubicCurve`] by computing the interpolation coefficients for each curve segment.
fn to_curve(&self) -> Result<CubicCurve<P>, Self::Error>;
}
```
All existing spline constructions use this together with errors that
indicate when they didn't have the right control data and provide curves
which have at least one segment whenever they return an `Ok` variant.
Next, `CubicCurve` and `RationalCurve` have been blessed with a
guarantee that their internal array of segments (`segments`) is never
empty. In particular, this field is no longer public, so that invalid
curves cannot be built using struct instantiation syntax. To compensate
for this shortfall for users (in particular library authors who might
want to implement their own generators), there is a new method
`from_segments` on these for constructing a curve from a list of
segments, failing if the list is empty:
```rust
/// Create a new curve from a collection of segments. If the collection of segments is empty,
/// a curve cannot be built and `None` will be returned instead.
pub fn from_segments(segments: impl Into<Vec<CubicSegment<P>>>) -> Option<Self> { //... }
```
All existing methods on `CyclicCurve` and `CubicCurve` maintain the
invariant, so the direct construction of invalid values by users is
impossible.
## Testing
Run unit tests from `bevy_math::cubic_splines`. Additionally, run the
`cubic_splines` example and try to get it to crash using small numbers
of control points: it uses the fallible constructors directly, so if
invalid data is ever constructed, it is basically guaranteed to crash.
---
## Migration Guide
The `to_curve` method on Bevy's cubic splines is now fallible (returning
a `Result`), meaning that any existing calls will need to be updated by
handling the possibility of an error variant.
Similarly, any custom implementation of `CubicGenerator` or
`RationalGenerator` will need to be amended to include an `Error` type
and be made fallible itself.
Finally, the fields of `CubicCurve` and `RationalCurve` are now private,
so any direct constructions of these structs from segments will need to
be replaced with the new `CubicCurve::from_segments` and
`RationalCurve::from_segments` methods.
---
## Design
The main thing to justify here is the choice for the curve internals to
remain the same. After all, if they were able to cause crashes in the
first place, it's worth wondering why safeguards weren't put in place on
the types themselves to prevent that.
My view on this is that the problem was really that the internals of
these methods implicitly relied on the assumption that the value they
were operating on was *actually a curve*, when this wasn't actually
guaranteed. Now, it's possible to make a bunch of small changes inside
the curve struct methods to account for that, but I think that's worse
than just guaranteeing that the data is valid upstream — sampling is
about as hot a code path as we're going to get in this area, and hitting
an additional branch every time it happens just to check that the struct
contains valid data is probably a waste of resources.
Another way of phrasing this is that even if we're only interested in
solving the crashes, the curve's validity needs to be checked at some
point, and it's almost certainly better to do this once at the point of
construction than every time the curve is sampled.
In cases where the control data is supplied dynamically, users would
already have to deal with empty curve outputs basically not working.
Anecdotally, I ran into this while writing the `cubic_splines` example,
and I think the diff illustrates the improvement pretty nicely — the
code no longer has to anticipate whether the output will be good or not;
it just has to handle the `Result`.
The cost of all this, of course, is that we have to guarantee that the
new invariant is actually maintained whenever we extend the API.
However, for the most part, I don't expect users to want to do much
surgery on the internals of their curves anyway.
# Objective
- The implementation of `update_component_access` for `AnyOf`/`Or` is
kinda weird due to special casing the first filter, let's simplify it;
- Fundamentally we want to fold/reduce the various filters using an OR
operation, however in order to do a proper fold we need a neutral
element for the initial accumulator, which for OR is FALSE. However we
didn't have a way to create a `FilteredAccess` value corresponding to
FALSE and thus the only option was reducing, which special cases the
first element as being the initial accumulator.
This is an alternative to https://github.com/bevyengine/bevy/pull/14026
## Solution
- Introduce `FilteredAccess::empty` as a way to create a
`FilteredAccess` corresponding to the logical proposition FALSE;
- Use it as the initial accumulator for the above operations, allowing
to handle all the elements to fold in the same way.
---
## Migration Guide
- The behaviour of `AnyOf<()>` and `Or<()>` has been changed to match no
archetypes rather than all archetypes to naturally match the
corresponding logical operation. Consider replacing them with `()`
instead.
# Objective
- Fix issue #2611
## Solution
- Add `--generate-link-to-definition` to all the `rustdoc-args` arrays
in the `Cargo.toml`s (for docs.rs)
- Add `--generate-link-to-definition` to the `RUSTDOCFLAGS` environment
variable in the docs workflow (for dev-docs.bevyengine.org)
- Document all the workspace crates in the docs workflow (needed because
otherwise only the source code of the `bevy` package will be included,
making the argument useless)
- I think this also fixes#3662, since it fixes the bug on
dev-docs.bevyengine.org, while on docs.rs it has been fixed for a while
on their side.
---
## Changelog
- The source code viewer on docs.rs now includes links to the
definitions.
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.23.2 to
1.23.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
releases</a>.</em></p>
<blockquote>
<h2>v1.23.5</h2>
<h2>[1.23.5] - 2024-07-25</h2>
<h3>Features</h3>
<ul>
<li><em>(config)</em> Store config in <code>Cargo.toml</code></li>
</ul>
<h2>v1.23.4</h2>
<h2>[1.23.4] - 2024-07-25</h2>
<h3>Fixes</h3>
<ul>
<li>Don't correct <code>countr_one</code> in C++</li>
</ul>
<h2>v1.23.3</h2>
<h2>[1.23.3] - 2024-07-22</h2>
<h3>Fixes</h3>
<ul>
<li>Fix <code>Dockerfile</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
changelog</a>.</em></p>
<blockquote>
<h2>[1.23.5] - 2024-07-25</h2>
<h3>Features</h3>
<ul>
<li><em>(config)</em> Store config in <code>Cargo.toml</code></li>
</ul>
<h2>[1.23.4] - 2024-07-25</h2>
<h3>Fixes</h3>
<ul>
<li>Don't correct <code>countr_one</code> in C++</li>
</ul>
<h2>[1.23.3] - 2024-07-22</h2>
<h3>Fixes</h3>
<ul>
<li>Fix <code>Dockerfile</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="c7af4712ed"><code>c7af471</code></a>
chore: Release</li>
<li><a
href="240053aa96"><code>240053a</code></a>
docs: Update changelog</li>
<li><a
href="d74fc5d53c"><code>d74fc5d</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1063">#1063</a>
from epage/cargo</li>
<li><a
href="d5453cc46c"><code>d5453cc</code></a>
feat(config): Load config from Cargo.toml</li>
<li><a
href="95f556a918"><code>95f556a</code></a>
refactor(config): Be more direct</li>
<li><a
href="626b4f71db"><code>626b4f7</code></a>
refactor(config): Centralize pyproject.toml value</li>
<li><a
href="ba52e2886f"><code>ba52e28</code></a>
chore: Release</li>
<li><a
href="4284499017"><code>4284499</code></a>
docs: Update changelog</li>
<li><a
href="7461343b85"><code>7461343</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1062">#1062</a>
from epage/cpp</li>
<li><a
href="5aa093dc25"><code>5aa093d</code></a>
fix(dict): Don't correct countr_one</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-ci/typos/compare/v1.23.2...v1.23.5">compare
view</a></li>
</ul>
</details>
<br />
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.23.2&new-version=1.23.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# Objective
- `bevy_render` depends on `image 0.25` but uses `image::ImageReader`
which was added only in `image 0.25.2`
- users that have `image 0.25` in their `Cargo.lock` and update to the
latest `bevy_render` may thus get a compilation due to this (at least I
did)
## Solution
- Properly set the correct minimum version of `image` that `bevy_render`
depends on.
# Objective
- `SystemId`'s `Debug` implementation includes its `entity` field twice.
- This was likely an oversight in #11019, since before that PR the
second field was the `PhantomData` one.
## Solution
- Only include it once
Alternatively, this could be changed to match the struct representation
of `SystemId`, thus instructing the formatter to print a named struct
and including the `PhantomData` field.
# Objective
Fix a memory leak in `TextureCache` caused by the internal HashMap never
having unused entries cleared.
This isn't a giant memory leak, given the unused entries are simply
empty vectors. Though, if someone goes and resizes a window a bunch, it
can lead to hundreds/thousands of TextureDescriptor keys adding up in
the hashmap – which isn't ideal.
## Solution
- Only retain hashmap entries that still have textures.
- I also added an `is_empty()` method to `TextureCache`, which is useful
for 3rd-party higher-level caches that might have individual caches by
view entity or texture type, for example.
## Testing
- Verified the examples still work (this is a trivial change)
# Objective
- `bevy_winit` fails to build with just the `serialize` feature.
- Caught by [`flag-frenzy`](https://github.com/TheBevyFlock/flag-frenzy)
in [this
run](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/10087486444/job/27891723948),
using the new, nuanced configuration system!
## Solution
- It was failing because `bevy_winit` did not pass the `serialize` flag
to two of its dependencies: `bevy_input` and `bevy_window`.
- To fix this, add these crates to the feature flag.
## Testing
```bash
# On Linux, you must also specify a backend: `x11` or `wayland`.
# You can do this with `-F serialize,x11`, etc.
cargo check -p bevy_winit --no-default-features -F serialize
```
# Objective
- Fix a confusing panic when the viewport width is non-zero and the
height is 0, `prepare_bloom_textures` tries to create a `4294967295x1`
texture.
## Solution
- Avoid dividing by zero
- Apps still crash after this, but now on a more reasonable error about
the zero-size viewport
## Testing
- I isolated and tested the math. A height of 0 sets `mip_height_ratio`
to `inf`, causing the width to explode if it isn't also 0
# Objective
- `bevy_gltf` does not build with only the
`pbr_multi_layer_material_textures` or `pbr_anisotropy_texture`
features.
- Caught by [`flag-frenzy`](https://github.com/TheBevyFlock/flag-frenzy)
in [this
run](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/10087486444/job/27891723948).
## Solution
- This error was due to the feature not enabling the corresponding
feature in `bevy_pbr`. Adding these flags as a dependency fixes this
error.
## Testing
The following commands fail on `main`, but pass with this PR:
```bash
cargo check -p bevy_gltf --no-default-features -F pbr_multi_layer_material_textures
cargo check -p bevy_gltf --no-default-features -F pbr_anisotropy_texture
```
# Objective
- Made `ViewUniform` fields public so that 3rd-parties can create this
uniform. This is useful for custom pipelines that use custom views (e.g.
views buffered by a particular amount, for example).
# Objective
- Not including bevy's default font shouldn't result in code not
compiling anymore.
- Games may want to load their own default font into the default
`Handle<Font>` and not include bevy's default font, but still use these
convenience impls (https://github.com/bevyengine/bevy/issues/12192
currently makes this a bit inconvenient, but it does work).
## Solution
- Include these impls unconditionally.
- Slightly expand the comment on the `font` field to indicate that a
custom font can be used to override the default font.
- (drive-by: add `#[reflect(Default)]` on `TextSection`, since it was
missing a way to construct it via reflection)
# Objective
- Currently `bevy_ptr::{Ptr, PtrMut}` have `From` implementations from
references.
- These implementations impose an implicit `Sized` bound so `bevy_ptr`
types cannot be created from references to slices and trait objects.
- I ran into this trying to use `Ptr<'static>` as an untyped `&'static
dyn Any`, and [had to work around
it](f32b41512c/src/registry.rs (L214-L219)).
## Solution
- Relax the `Sized` bound on the relevant `From` implementations.
# Objective
- Before this fix, the view query in `prepare_mesh2d_view_bind_groups`
matched all views – leading to 2D view bind groups being prepared for 3D
cameras.
## Solution
- Added `With<Camera2d>` to the views query.
## Testing
- Verified the examples still work.
# Objective
Allow interoperation between `Isometry3d` and the transform types from
bevy_transform. At least in the short term, the primary goal is to allow
the extraction of isometries from transform components by users.
## Solution
- Add explicit `from_isometry`/`to_isometry` methods to `Transform`.
- Add explicit `from_isometry`/`to_isometry` methods to
`GlobalTransform`. The former is hidden (primarily for internal use),
and the latter has the caveats originating in
[`Affine3A::to_scale_rotation_translation`](https://docs.rs/glam/latest/glam/f32/struct.Affine3A.html#method.to_scale_rotation_translation).
- Implement the `TransformPoint` trait for `Isometry3d`.
# Objective
Fix erroneous hue mixing in `Lcha` and `Oklcha`. Purple + Red == Green
is the current behavior.
## Solution
Use `crate::color_ops::lerp_hue` to handle the wrap-around at 360
degrees, the same way that `Hsla`, `Hsva`, and `Hwba` do it.
## Testing
Game jamming, but tested that the workaround below produces
correct-looking colors in my jam game.
# Objective
- meshlet example has broken since #14273
## Solution
- disable msaa in meshlet example
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
I just wanted to inspect `HashSet`s in `bevy-inspector-egui` but I
noticed that it didn't work for some reason. A few minutes later I found
myself looking into the bevy reflect impls noticing that `HashSet`s have
been covered only rudimentary up until now.
## Solution
I'm not sure if this is overkill (especially the first bullet), but
here's a list of the changes:
- created a whole new trait and enum variants for `ReflectRef` and the
like called `Set`
- mostly oriented myself at the `Map` trait and made the necessary
changes until RA was happy
- create macro `impl_reflect_for_hashset!` and call it on `std::HashSet`
and `hashbrown::HashSet`
Extra notes:
- no `get_mut` or `get_mut_at` mirroring the `std::HashSet`
- `insert[_boxed]` and `remove` return `bool` mirroring `std::HashSet`,
additionally that bool is reflect as I thought that would be how we
handle things in bevy reflect, but I'm not sure on this
- ser/de are handled via `SeqAccess`
- I'm not sure about the general deduplication property of this impl of
`Set` that is generally expected? I'm also not sure yet if `Map` does
provide this. This mainly refers to the `Dynamic[...]` structs
- I'm not sure if there are other methods missing from the `trait`, I
felt like `contains` or the set-operations (union/diff/...) could've
been helpful, but I wanted to get out the bare minimum for feedback
first
---
## Changelog
### Added
- `Set` trait for `bevy_reflect`
### Changed
- `std::collections::HashSet` and `bevy_utils::hashbrown::HashSet` now
implement a more complete set of reflect functionalities instead of
"just" `reflect_value`
- `TypeInfo` contains a new variant `Set` that contains `SetInfo`
- `ReflectKind` contains a new variant `Set`
- `ReflectRef` contains a new variant `Set`
- `ReflectMut` contains a new variant `Set`
- `ReflectOwned` contains a new variant `Set`
## Migration Guide
- The new `Set` variants on the enums listed in the change section
should probably be considered by people working with this level of the
lib
### Help wanted!
I'm not sure if this change is able to break code. From my understanding
it shouldn't since we just add functionality but I'm not sure yet if
theres anything missing from my impl that would be normally provided by
`impl_reflect_value!`
# Objective
- Fixes#14453
## Solution
- Added BorderRadius to ImageBundle
## Testing
- Did you test these changes? If so, how?
- Tested on a random picture I found in the examples and it added a
border radius.
- Are there any parts that need more testing?
- I don't fink so.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Apply a border radius to a random picture.
# Objective
When using observers you might want to know what the difference is
between `OnAdd` vs `OnReplace` vs `OnInsert` etc. It's not obvious where
to look (`component_hooks.rs`). Added intradoc links for easier
disambiguation.
# Objective
The method `World::increment_change_tick` currently takes `&self` as the
method receiver, which is semantically strange. Even though the interior
mutability is sound, the existence of this method is strange since we
tend to think of `&World` as being a read-only snapshot of a world, not
an aliasable reference to a world with mutability. For those purposes,
we have `UnsafeWorldCell`.
## Solution
Change the method signature to take `&mut self`. Use exclusive access to
remove the need for atomic adds, which makes the method slightly more
efficient. Redirect users to [`UnsafeWorldCell::increment_change_tick`]
if they need to increment the world's change tick from an aliased
context.
In practice I don't think there will be many breakages, if any. In cases
where you need to call `increment_change_tick`, you usually already have
either `&mut World` or `UnsafeWorldCell`.
---
## Migration Guide
The method `World::increment_change_tick` now requires `&mut self`
instead of `&self`. If you need to call this method but do not have
mutable access to the world, consider using
`world.as_unsafe_world_cell_readonly().increment_change_tick()`, which
does the same thing, but is less efficient than the method on `World`
due to requiring atomic synchronization.
```rust
fn my_system(world: &World) {
// Before
world.increment_change_tick();
// After
world.as_unsafe_world_cell_readonly().increment_change_tick();
}
```
# Objective
Sometimes one wants to retrieve a `&dyn Reflect` for an entity's
component, which so far required multiple, non-obvious steps and
`unsafe`-code.
The docs for
[`MutUntyped`](https://docs.rs/bevy/latest/bevy/ecs/change_detection/struct.MutUntyped.html#method.map_unchanged)
contain an example of the unsafe part.
## Solution
This PR adds the two methods:
```rust
// immutable variant
World::get_reflect(&self, entity: Entity, type_id: TypeId) -> Result<&dyn Reflect, GetComponentReflectError>
// mutable variant
World::get_reflect_mut(&mut self, entity: Entity, type_id: TypeId) -> Result<Mut<'_, dyn Reflect>, GetComponentReflectError>
```
which take care of the necessary steps, check required invariants etc.,
and contain the unsafety so the caller doesn't have to deal with it.
## Testing
- Did you test these changes? If so, how?
- Added tests and a doc test, also (successfully) ran `cargo run -p ci`.
- Are there any parts that need more testing?
- Could add tests for each individual error variant, but it's not
required imo.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Run `cargo test --doc --package bevy_ecs --all-features --
world::World::get_reflect --show-output` for the doctest
- Run `cargo test --package bevy_ecs --lib --all-features --
world::tests::reflect_tests --show-output` for the unittests
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
- Don't think it's relevant, but tested on 64bit linux (only).
---
## Showcase
Copy of the doctest example which gives a good overview of what this
enables:
```rust
use bevy_ecs::prelude::*;
use bevy_reflect::Reflect;
use std::any::TypeId;
// define a `Component` and derive `Reflect` for it
#[derive(Component, Reflect)]
struct MyComponent;
// create a `World` for this example
let mut world = World::new();
// Note: This is usually handled by `App::register_type()`, but this example can not use `App`.
world.init_resource::<AppTypeRegistry>();
world.get_resource_mut::<AppTypeRegistry>().unwrap().write().register::<MyComponent>();
// spawn an entity with a `MyComponent`
let entity = world.spawn(MyComponent).id();
// retrieve a reflected reference to the entity's `MyComponent`
let comp_reflected: &dyn Reflect = world.get_reflect(entity, TypeId::of::<MyComponent>()).unwrap();
// make sure we got the expected type
assert!(comp_reflected.is::<MyComponent>());
```
## Migration Guide
No breaking changes, but users can use the new methods if they did it
manually before.
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
Derive `Hash` for `KeyboardInput`.
## Problem
I was [writing code](https://github.com/joshka/bevy_ratatui/pull/13) to
take `crossterm` events and republish them as bevy input events. One
scenario requires I check if the same key press was happening
repeatedly; in a regular terminal we don't get key released events, so I
was simulating them.
I was surprised to find that I couldn't put `KeyboardInput` into a
`HashSet`.
## Work Around
My work around was to add a new type that implemented Hash.
```rust
#[derive(Deref, DerefMut, PartialEq, Eq)]
struct KeyInput(KeyboardInput);
impl Hash for KeyInput {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.key_code.hash(state);
self.logical_key.hash(state);
self.state.hash(state);
self.window.hash(state);
}
}
```
## Solution
A better solution since all members of `KeyboardInput` implement `Hash`
is to have it derive `Hash` as well.
## Testing
My newtype solution works for its purpose.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
# Objective
- Some types here were not constructible via reflection, and some were
missing fairly obvious `Default` values.
- Some types used `#[reflect_value]` for some unstated reason, making
them opaque to reflection-based code.
## Solution
- Add and reflect some `Default` impls, and stop using
`#[reflect_value]`.
# Objective
- It's possible to have errors in a draw command, but these errors are
ignored
## Solution
- Return a result with the error
## Changelog
Renamed `RenderCommandResult::Failure` to `RenderCommandResult::Skip`
Added a `reason` string parameter to `RenderCommandResult::Failure`
## Migration Guide
If you were using `RenderCommandResult::Failure` to just ignore an error
and retry later, use `RenderCommandResult::Skip` instead.
This wasn't intentional, but this PR should also help with
https://github.com/bevyengine/bevy/issues/12660 since we can turn a few
unwraps into error messages now.
---------
Co-authored-by: Charlotte McElwain <charlotte.c.mcelwain@gmail.com>
# Objective
Simplify Bevy-provided functions that return a condition-satisfying
closure instead of just being the condition.
## Solution
Become the condition.
## Testing
I did not test. Game jamming. Hopefully CI passes.
---
## Migration Guide
Some run conditions have been simplified.
```rust
// Before:
app.add_systems(Update, (
system_0.run_if(run_once()),
system_1.run_if(resource_changed_or_removed::<T>()),
system_2.run_if(resource_removed::<T>()),
system_3.run_if(on_event::<T>()),
system_4.run_if(any_component_removed::<T>()),
));
// After:
app.add_systems(Update, (
system_0.run_if(run_once),
system_1.run_if(resource_changed_or_removed::<T>),
system_2.run_if(resource_removed::<T>),
system_3.run_if(on_event::<T>),
system_4.run_if(any_component_removed::<T>),
));
```
# Objective
- `bevy_ui` does not build without the `bevy_text` feature due to
improper feature gating.
- Specifically, `MeasureArgs<'a>` had an unused lifetime `'a` without
`bevy_text` enabled. This is because it stores a reference to a
`cosmic_text::FontSystem`.
- This was caught by `flag-frenzy` in [this
run](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/10024258523/job/27706132250).
## Solution
- Add a `PhantomData` to `MeasureArgs<'a>` in order to maintain its
lifetime argument.
- I also named it `font_system`, after the feature-gated argument that
actually needs a lifetime, for usability. Please comment if you have a
better solution!
- Move some unused imports to be behind the `bevy_text` feature gate.
## Testing
```bash
# Fails on main.
cargo check -p bevy_ui --no-default-features
# Succeeds on main.
cargo check -p bevy_ui --no-default-features -F bevy_text
```
---
## Migration Guide
**This is not a breaking change for users migrating from 0.14, since
`MeasureArgs` did not exist then.**
When the `bevy_text` feature is disabled for `bevy_ui`, the type of the
`MeasureArgs::font_system` field is now a `PhantomData` instead of being
removed entirely. This is in order to keep the lifetime parameter, even
though it is unused without text being enabled.
# Objective
Fixes#13910
When a transition is over, the animation is stopped. There was a race
condition; if an animation was started while it also had an active
transition, the transition ending would then incorrectly stop the newly
added animation.
## Solution
When starting an animation, cancel any previous transition for the same
animation.
## Testing
The changes were tested manually, mainly by using the `animated_fox`
example. I also tested with changes from
https://github.com/bevyengine/bevy/pull/13909.
I'd like to have an unit test for this as well, but it seems quite
complex to do, as I'm not sure how I would detect an incorrectly paused
animation.
Reviewers can follow the instructions in #13910 to reproduce.
Tested on macos 14.4 (M3 processor) Should be platform-independent,
though.
Currently `TextureFormat::Astc` can't be programmatically constructed
without importing wgpu in addition to bevy.
# Objective
Allow programmatic construction of `TextureFormat::Astc` with no
additional imports required.
## Solution
Exported the two component enums `AstcBlock` and `AstcChannel` used in
`TextureFormat::Astc` construction.
## Testing
I did not test this, the change seemed pretty safe. :)
# Objective
- Enables use cases where third-party crates would want to use the
default font as well [see linebender's
use](https://github.com/linebender/bevy_vello/pull/66)
## Solution
- Uses `include_bytes` macro and make it `pub`
---------
Co-authored-by: Spencer C. Imbleau <spencer@imbleau.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
# Objective
Fixes a performance issue when you have 1000s of entities in a bevy
hierarchy without transforms.
This was prominently happening in `bevy_ecs_tilemap`.
## Solution
Filter out entities that don't have a global transform.
## Testing
CI
We should test some other way...
## Migration Guide
- To avoid surprising performance pitfalls, `Transform` /
`GlobalTransform` propagation is no longer performed down through
hierarchies where intermediate parent are missing a `GlobalTransform`.
To restore the previous behavior, add `GlobalTransform::default` to
intermediate entities.
The "uberbuffers" PR #14257 caused some examples to fail intermittently
for different reasons:
1. `morph_targets` could fail because vertex displacements for morph
targets are keyed off the vertex index. With buffer packing, the vertex
index can vary based on the position in the buffer, which caused the
morph targets to be potentially incorrect. The solution is to include
the first vertex index with the `MeshUniform` (and `MeshInputUniform` if
GPU preprocessing is in use), so that the shader can calculate the true
vertex index before performing the morph operation. This results in
wasted space in `MeshUniform`, which is unfortunate, but we'll soon be
filling in the padding with the ID of the material when bindless
textures land, so this had to happen sooner or later anyhow.
Including the vertex index in the `MeshInputUniform` caused an ordering
problem. The `MeshInputUniform` was created during the extraction phase,
before the allocations occurred, so the extraction logic didn't know
where the mesh vertex data was going to end up. The solution is to move
the `MeshInputUniform` creation (the `collect_meshes_for_gpu_building`
system) to after the allocations phase. This should be better for
parallelism anyhow, because it allows the extraction phase to finish
quicker. It's also something we'll have to do for bindless in any event.
2. The `lines` and `fog_volumes` examples could fail because their
custom drawing nodes weren't updated to supply the vertex and index
offsets in their `draw_indexed` and `draw` calls. This commit fixes this
oversight.
Fixes#14366.
# Objective
- Optimize the `propagate_recursive` function in the transform system to
reduce CPU usage.
- Addresses performance bottleneck in transform propagation, especially
for scenes with complex hierarchies.
## Solution
- Avoided unnecessary cloning of `global_transform` when creating the
tuple in the `propagate_recursive` function.
- Used `as_ref()` method on `Mut<GlobalTransform>` when passing it to
the recursive call, avoiding an extra dereference.
- These changes significantly reduced the CPU usage of this function
from 4.91% to 1.16% of self function time.
## Testing
- Performance testing was conducted using the Hotspot GUI tool,
comparing CPU usage before and after the changes.
- `cargo run --release --example many_foxes`
- Tested on Fedora Linux.
---
## Showcase
Here are the PERF GUI results showing the improvement in CPU usage:
### Before
![image](https://github.com/user-attachments/assets/b5c52800-710b-4793-bf75-33e3eb1d2083)
### After
![image](https://github.com/user-attachments/assets/654a4feb-924c-41c8-8ff9-3a1027bd28b9)
As we can see, the CPU usage for the `propagate_recursive` function has
been reduced from 4.91% to 1.16%, resulting in a significant performance
improvement.
## Migration Guide
This change does not introduce any breaking changes. Users of the Bevy
engine will automatically benefit from this performance improvement
without needing to modify their code.