Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.29.4 to
1.29.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.29.5</h2>
<h2>[1.29.5] - 2025-01-30</h2>
<h3>Internal</h3>
<ul>
<li>Update a dependency</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.29.5] - 2025-01-30</h2>
<h3>Internal</h3>
<ul>
<li>Update a dependency</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="11ca4583f2"><code>11ca458</code></a>
chore: Release</li>
<li><a
href="99fd37f157"><code>99fd37f</code></a>
docs: Update changelog</li>
<li><a
href="4f604f6eff"><code>4f604f6</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1220">#1220</a>
from epage/w7</li>
<li><a
href="ba04a1a0fd"><code>ba04a1a</code></a>
perf: Remove ErrMode overhead</li>
<li><a
href="60452b5a81"><code>60452b5</code></a>
chore: Update to Winnow 0.7</li>
<li><a
href="4c22f194b5"><code>4c22f19</code></a>
refactor: Migrate from Parser to ModalParser</li>
<li><a
href="7830eb8730"><code>7830eb8</code></a>
refactor: Resolve deprecations</li>
<li><a
href="07f1292e29"><code>07f1292</code></a>
chore: Upgrade to Winnow 0.6.26</li>
<li><a
href="3683264986"><code>3683264</code></a>
chore(deps): Update Rust Stable to v1.84 (<a
href="https://redirect.github.com/crate-ci/typos/issues/1216">#1216</a>)</li>
<li><a
href="2ed38e07fc"><code>2ed38e0</code></a>
chore(deps): Update Rust crate bstr to v1.11.3 (<a
href="https://redirect.github.com/crate-ci/typos/issues/1202">#1202</a>)</li>
<li>See full diff in <a
href="https://github.com/crate-ci/typos/compare/v1.29.4...v1.29.5">compare
view</a></li>
</ul>
</details>
<br />
[](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
```
cargo test --package bevy_ecs --lib --all-features
```
fails to compile, with output like
> error[E0433]: failed to resolve: could not find `Serialize` in `serde`
> --> crates/bevy_ecs/src/entity/index_set.rs:14:69
> |
> 14 | #[cfg_attr(feature = "serialize", derive(serde::Deserialize,
serde::Serialize))]
> | ^^^^^^^^^ could not find `Serialize` in `serde`
> |
> note: found an item that was configured out
> -->
/home/alice/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.217/src/lib.rs:343:37
> |
> 343 | pub use serde_derive::{Deserialize, Serialize};
> | ^^^^^^^^^
> note: the item is gated behind the `serde_derive` feature
> -->
/home/alice/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.217/src/lib.rs:341:7
> |
> 341 | #[cfg(feature = "serde_derive")]
> | ^^^^^^^^^^^^^^^^^^^^^^^^
## Solution
Add the required feature flags and get bevy_ecs compiling standalone
corrctly.
## Testing
The command above now compiles succesfully. Note that several system
stepping tests are failing, and were not being tested in CI. That's a
different PR's problem though.
# Objective
Currently, `prepare_sprite_image_bind_group` spawns sprite batches onto
an individual representative entity of the batch. This poses significant
problems for multi-camera setups, since an entity may appear in multiple
phase instances.
## Solution
Instead, move batches into a resource that is keyed off the view and the
representative entity. Long term we should switch to mesh2d and use the
existing BinnedRenderPhase functionality rather than naively queueing
into transparent and doing our own ad-hoc batching logic.
Fixes#16867, #17351
## Testing
Tested repros in above issues.
# Objective
We have default query filters now, but there is no first-party marker
for entity disabling yet
Fixes#17458
## Solution
Add the marker, cool recursive features and/or potential hook changes
should be follow up work
## Testing
Added a unit test to check that the new marker is enabled by default
# Objective
Expose accessor functions to the `ObserverDescriptor`, so that users can
use the `Observer` component to inspect what the observer is watching.
This would be useful for me, I don't think there's any reason to hide
these.
# Objective
- Fix off by one error introduced in
https://github.com/bevyengine/bevy/pull/17540 causing:
```
Cursor image StrongHandle<Image>{ id: Index(AssetIndex { generation: 0, index: 3 }), path: Some(cursors/kenney_crosshairPack/Tilesheet/crosshairs_tilesheet_white.png) } is invalid: The specified hotspot (64, 64) is outside the image bounds (64x64).
```
- First PR commit and run shows the bug:
https://github.com/bevyengine/bevy/actions/runs/13009405866/job/36283507530?pr=17571
- Second PR commit fixes it.
## Solution
- Hotspot coordinates are 0-indexed, so we need to subtract 1 from the
width and height.
## Testing
- Fix the tests which included the off-by-one error in their expected
values.
- Consolidate the tests into a single test for brevity.
- Test round trip transform to ensure we can "undo" to get back to the
original value.
- Add a specific bounds test.
- Ran the example again and observed there are no more error logs:
`cargo run --example custom_cursor_image --features=custom_cursor`.
# Objective
- Make working with `bevy_time` more ergonomic in `no_std` environments.
Currently `bevy_time` expects the getter in environments where time
can't be obtained automatically via the instruction set or the standard
library to be of type `*mut fn() -> Duration`.
[`fn()`](https://doc.rust-lang.org/beta/std/primitive.fn.html) is
already a function pointer, so `*mut fn()` is a _pointer to a function
pointer_. This is harder to use and error prone since creating a pointer
out of something like `&mut fn() -> Duration` when the lifetime of the
reference isn't static will lead to an undefined behavior once the
reference is freed
## Solution
- Accept a `fn() -> Duration` instead
## Testing
- I made a whole game on the Playdate that relies on `bevy_time`
heavily, see:
[bevydate_time](1b4f02adcd/src/lib.rs (L510-L546))
for usage of the Instant's getter.
---
## Showcase
<details>
<summary>Click to view showcase</summary>
https://github.com/user-attachments/assets/f687847f-6b62-4322-95f3-c908ada3db30
</details>
## Migration Guide
This is a breaking change but it's not for people coming from Bevy v0.15
### Small thank you note
Thanks to my friend https://github.com/repnop for helping me understand
how to deal with function pointers in `unsafe` environments
Co-authored-by: Wesley Norris <repnop@repnop.dev>
# Objective
Follow-up to #17615.
Bevy's entity collection types like `EntityHashSet` no longer implement
serde's `Serialize` and `Deserialize` after becoming newtypes instead of
type aliases in #16912. This broke some types that support serde for me
in Avian.
I also missed creating const constructors for `EntityIndexMap` and
`EntityIndexSet` in #17615. Oops!
## Solution
Implement `Serialize` and `Deserialize` for Bevy's entity collection
types, and add const constructors for `EntityIndexMap` and
`EntityIndexSet`.
I didn't implement `ReflectSerialize` or `ReflectDeserialize` here,
because I had some trouble fixing the resulting errors, and they were
not implemented previously either.
# Objective
- Linking to a specific AsBindGroup attribute is hard because it doesn't
use any headers and all the docs is in a giant block
## Solution
- Make each attribute it's own sub-header so they can be easily linked
---
## Showcase
Here's what the rustdoc output looks like with this change

## Notes
I kept the bullet point so the text is still indented like before. Not
sure if we should keep that or not
# Objective
- `ValArithmeticError` contains a typo, and one of it's variants is not
used
## Solution
- Rename `NonEvaluateable::NonEvaluateable ` variant to
`NonEvaluateable::NonEvaluable`.
- Remove variant `ValArithmeticError:: NonIdenticalVariants`.
## Testing
- `cargo run -p ci`
---
## Migration Guide
- `ValArithmeticError::NonEvaluateable` has been renamed to
`NonEvaluateable::NonEvaluable`
- `ValArithmeticError::NonIdenticalVariants ` has been removed
# Objective
- We kind of missed out on implementing the `Ease` trait for some
objects like `Isometry2D` and `Isometry3D` even though it makes sense
and isn't that hard
- Fixes#17539
## Testing
- wrote some minimal tests
- ~~noticed that quat easing isn't working as expected yet~~ I just
confused degrees and radians once again 🙈
# Objective
For most UI node entities there's a 1-to-1 mapping from the entity to
its associated Taffy node. Root UI nodes are an exception though, their
corresponding Taffy node in the Taffy tree is also given a parent that
represents the viewport. These viewport Taffy nodes are not removed when
a root UI node is despawned.
Parenting of an existing root UI node with an associated viewport Taffy
node also results in the leak of the viewport node.
These tests fail if added to the `layout` module's tests on the main
branch:
```rust
#[test]
fn no_viewport_node_leak_on_root_despawned() {
let (mut world, mut ui_schedule) = setup_ui_test_world();
let ui_root_entity = world.spawn(Node::default()).id();
// The UI schedule synchronizes Bevy UI's internal `TaffyTree` with the
// main world's tree of `Node` entities.
ui_schedule.run(&mut world);
// Two taffy nodes are added to the internal `TaffyTree` for each root UI entity.
// An implicit taffy node representing the viewport and a taffy node corresponding to the
// root UI entity which is parented to the viewport taffy node.
assert_eq!(
world.resource_mut::<UiSurface>().taffy.total_node_count(),
2
);
world.despawn(ui_root_entity);
// The UI schedule removes both the taffy node corresponding to `ui_root_entity` and its
// parent viewport node.
ui_schedule.run(&mut world);
// Both taffy nodes should now be removed from the internal `TaffyTree`
assert_eq!(
world.resource_mut::<UiSurface>().taffy.total_node_count(),
0
);
}
#[test]
fn no_viewport_node_leak_on_parented_root() {
let (mut world, mut ui_schedule) = setup_ui_test_world();
let ui_root_entity_1 = world.spawn(Node::default()).id();
let ui_root_entity_2 = world.spawn(Node::default()).id();
ui_schedule.run(&mut world);
// There are two UI root entities. Each root taffy node is given it's own viewport node parent,
// so a total of four taffy nodes are added to the `TaffyTree` by the UI schedule.
assert_eq!(
world.resource_mut::<UiSurface>().taffy.total_node_count(),
4
);
// Parent `ui_root_entity_2` onto `ui_root_entity_1` so now only `ui_root_entity_1` is a
// UI root entity.
world
.entity_mut(ui_root_entity_1)
.add_child(ui_root_entity_2);
// Now there is only one root node so the second viewport node is removed by
// the UI schedule.
ui_schedule.run(&mut world);
// There is only one viewport node now, so the `TaffyTree` contains 3 nodes in total.
assert_eq!(
world.resource_mut::<UiSurface>().taffy.total_node_count(),
3
);
}
```
Fixes#17594
## Solution
Change the `UiSurface::entity_to_taffy` to map to `LayoutNode`s. A
`LayoutNode` has a `viewport_id: Option<taffy::NodeId>` field which is
the id of the corresponding implicit "viewport" node if the node is a
root UI node, otherwise it is `None`. When removing or parenting nodes
this field is checked and the implicit viewport node is removed if
present.
## Testing
There are two new tests in `bevy_ui::layout::tests` included with this
PR:
* `no_viewport_node_leak_on_root_despawned`
* `no_viewport_node_leak_on_parented_root`
# Objective
Fix this comment in `queue_sprites`:
```
// batch_range and dynamic_offset will be calculated in prepare_sprites.
```
`Transparent2d` no longer has a `dynamic_offset` field and the
`batch_range` is calculated in `prepare_sprite_image_bind_groups` now.
# Objective
Fixes#17561
## Solution
The anti-aliasing function used by the UI fragment shader is this:
```wgsl
fn antialias(distance: f32) -> f32 {
return saturate(0.5 - distance); // saturate clamps between 0 and 1
}
```
The returned value is multiplied with the alpha channel value to get the
anti-aliasing effect.
The `distance` is a signed distance value. A positive `distance` means
we are outside the shape we're drawing and a negative `distance` means
we are on the inside.
So with `distance` at `0` (on the edge of the shape):
```
antialias(0) = saturate(0.5 - 0) = saturate(0.5) = 0.5
```
but we want it to be `1` at this point, so the entire interior of the
shape is given a solid colour, and then decrease as the signed distance
increases.
So in this PR we change it to:
```wgsl
fn antialias(distance: f32) -> f32 {
return saturate(1. - distance);
}
```
Then:
```
antialias(-0.5) = saturate(1 - (-1)) = saturate(2) = 1
antialias(1) = saturate(1 - 0) = 1
antialias(0.5) = saturate(1 - 0.5) = 0.5
antialias(1) = saturate(1 - 1) = 0
```
as desired.
## Testing
```cargo run --example button```
On main:
<img width="400" alt="bleg" src="https://github.com/user-attachments/assets/314994cb-4529-479d-b179-18e5c25f75bc" />
With this PR:
<img width="400" alt="bbwhite" src="https://github.com/user-attachments/assets/072f481d-8b67-4fae-9a5f-765090d1713f" />
Modified the `button` example to draw a white background to make the bleeding more obvious.
The code added in #14343 seems to be trying to ensure that a `Handle`
for each glTF node exists by topologically sorting the directed graph of
glTF nodes containing edges from parent to child and from skin to joint.
Unfortunately, such a graph can contain cycles, as there's no guarantee
that joints are descendants of nodes with the skin. In particular, glTF
exported from Maya using the popular babylon.js export plugin create
skins attached to nodes that animate their parent nodes. This was
causing the topological sort code to enter an infinite loop.
Assuming that the intent of the topological sort is indeed to ensure
that `Handle`s exist for each glTF node before populating them, there's
a better mechanism for this: `LoadContext::get_label_handle`. This is
the documented way to obtain a handle for a node before populating it,
obviating the need for a topological sort. This patch replaces the
topological sort with a pre-pass that uses
`LoadContext::get_label_handle` to get handles for each `Node` before
populating them. This fixes the problem with Maya rigs, in addition to
making the code simpler and faster.
I realized there wasn't a test for this yet and figured it would be
trivial to add. Why not? Unless there was a test for this, and I just
missed it?
I appreciate the unique error message it gives and wanted to make sure
it doesn't get broken at some point. Or worse, endlessly recurse.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- make CI a bit faster without losing anything
## Solution
- Always disable incremental compilation. This was done in a few jobs,
just do it everywhere
- Also disable debug info. This should reduce target folder a bit,
reducing cache size and upload duration
# Objective
- Improve CI when testing rendering by having smarter testbeds
## Solution
- CI testing no longer need a config file and will run with a default
config if not found
- It is now possible to give a name to a screenshot instead of just a
frame number
- 2d and 3d testbeds are now driven from code
- a new system in testbed will watch for state changed
- on state changed, trigger a screenshot 100 frames after (so that the
scene has time to render) with the name of the scene
- when the screenshot is taken (`Captured` component has been removed),
switch scene
- this means less setup to run a testbed (no need for a config file),
screenshots have better names, and it's faster as we don't wait 100
frames for the screenshot to be taken
## Testing
- `cargo run --example testbed_2d --features bevy_ci_testing`
# Objective
- Also support `f16` values when getting and setting colors.
## Solution
- Use the `half` crate to work with `f16` until it's in stable Rust.
# Objective
#16912 turned `EntityHashMap` and `EntityHashSet` into proper newtypes
instead of type aliases. However, this removed the ability to create
these collections in const contexts; previously, you could use
`EntityHashSet::with_hasher(EntityHash)`, but it doesn't exist anymore.
## Solution
Make `EntityHashMap::new` and `EntityHashSet::new` const methods.
# Objective
Pass the correct location to triggers when despawning entities.
`EntityWorldMut::despawn_with_caller()` currently passes
`Location::caller()` to some triggers instead of the `caller` parameter
it was passed. As `despawn_with_caller()` is not `#[track_caller]`, this
means the location will always be reported as `despawn_with_caller()`
itself.
## Solution
Pass `caller` instead of `Location::caller()`.
Adding these allows using `DetectChangesMut::set_if_neq` to only update
the values when needed. Currently you need to get the inner values first
(`String` and `Color`), to do any equality checks.
---------
Signed-off-by: Jean Mertz <git@jeanmertz.com>
# Objective
Fixes#17508
`bevy_color::Color` constructors don't have docs explaining the valid
range for the values passed.
## Solution
I've mostly copied the docs from the respective underlying type's docs,
because that seemed most consistent and accurate.
# Objective
The new `DeserializeWithRegistry` trait in 0.15 was designed to be used
with reflection, and so has a `trait DeserializeWithRegistry:
PartialReflect` bound. However, this bound is not actually necessary for
the trait to function properly. And this `PartialReflect` bound already
exists on:
```rs
impl<T: PartialReflect + for<'de> DeserializeWithRegistry<'de>> FromType<T>
for ReflectDeserializeWithRegistry
```
So there is no point in constraining the trait itself with this bound as
well.
This lets me use `DeserializeWithRegistry` with non-`Reflect` types,
which I want to do to avoid making a bunch of `FooDeserializer` structs
and `impl DeserializeSeed` on them.
## Solution
Removes this unnecessary bound.
## Testing
Trivial change, does not break compilation or `bevy_reflect` tests.
## Migration Guide
`DeserializeWithRegistry` types are no longer guaranteed to be
`PartialReflect` as well. If you were relying on this type bound, you
should add it to your own bounds manually.
```diff
- impl<T: DeserializeWithRegistry> Foo for T { .. }
+ impl<T: DeserializeWithRegistry + PartialReflect> Foo for T { .. }
```
This allows you to continue chaining method calls after calling
`EntityCommands::entry`:
```rust
commands
.entity(player.entity)
.entry::<Level>()
// Modify the component if it exists
.and_modify(|mut lvl| lvl.0 += 1)
// Otherwise insert a default value
.or_insert(Level(0))
// Return the EntityCommands for the entity
.entity()
// And continue chaining method calls
.insert(Name::new("Player"));
```
---------
Signed-off-by: Jean Mertz <git@jeanmertz.com>
# Objective
Two more optimisations for UI extraction:
* We only need to query for the camera's render entity when the target
camera changes. If the target camera is the same as for the previous UI
node we can use the previous render entity.
* The cheap checks for visibility and zero size should be performed
first before the camera queries.
## Solution
Add a new system param `UiCameraMap` that resolves the correct render
camera entity and only queries when necessary.
<img width="506" alt="tracee"
src="https://github.com/user-attachments/assets/f57d1e0d-f3a7-49ee-8287-4f01ffc8ba24"
/>
I don't like the `UiCameraMap` + `UiCameraMapper` implementation very
much, maybe someone else can suggest a better construction.
This is partly motivated by #16942 which adds further indirection and
these changes would ameliorate that performance regression.
# Objective
In #16547, we added `EntitySet`s/`EntitySetIterator`s. We can know
whenever an iterator only contains unique entities, however we do not
yet have the ability to collect and reuse these without either the
unsafe `UniqueEntityIter::from_iterator_unchecked`, or the expensive
`HashSet::from_iter`.
An important piece for being able to do this is a `Vec` that maintains
the uniqueness property, can be collected into, and is itself
`EntitySet`.
A lot of entity collections are already intended to be "unique", but
have no way of expressing that when stored, other than using an
aforementioned `HashSet`. Such a type helps by limiting or even removing
the need for unsafe on the user side when not using a validated `Set`
type, and makes it easier to interface with other infrastructure like
f.e. `RelationshipSourceCollection`s.
## Solution
We implement `UniqueEntityVec`.
This is a wrapper around `Vec`, that only ever contains unique elements.
It mirrors the API of `Vec`, however restricts any mutation as to not
violate the uniqueness guarantee. Meaning:
- Any inherent method which can introduce new elements or mutate
existing ones is now unsafe, f.e.: `insert`, `retain_mut`
- Methods that are impossible to use safely are omitted, f.e.: `fill`,
`extend_from_within`
A handful of the unsafe methods can do element-wise mutation
(`retain_mut`, `dedup_by`), which can be an unwind safety hazard were
the element-wise operation to panic. For those methods, we require that
each individual execution of the operation upholds uniqueness, not just
the entire method as a whole.
To be safe for mutable usage, slicing and the associated slice methods
require a matching `UniqueEntitySlice` type , which we leave for a
follow-up PR.
Because this type will deref into the `UniqueEntitySlice` type, we also
offer the immutable `Vec` methods on this type (which only amount to a
handful). "as inner" functionality is covered by additional
`as_vec`/`as_mut_vec` methods + `AsRef`/`Borrow` trait impls.
Like `UniqueEntityIter::from_iterator_unchecked`, this type has a
`from_vec_unchecked` method as well.
The canonical way to safely obtain this type however is via
`EntitySetIterator::collect_set` or
`UniqueEntityVec::from_entity_set_iter`. Like mentioned in #17513, these
are named suboptimally until supertrait item shadowing arrives, since a
normal `collect` will still run equality checks.
# Objective
This makes the `Image::get_color_at_3d` and `Image::set_color_at_3d`
methods work with 2D images with more than one layer.
## Solution
- The Z coordinate is interpreted as the layer number.
## Testing
- Added a test: `get_set_pixel_2d_with_layers`.
# Objective
- As discussed in
https://github.com/bevyengine/bevy/issues/17276#issuecomment-2611203714,
we should transform the cursor's hotspot if the user is asking for the
image to be flipped.
- This becomes more important when a `scale` transform option exists.
It's harder for users to transform the hotspot themselves when using
`scale` because they'd need to look up the image to get its dimensions.
Instead, we let Bevy handle the hotspot transforms and make the
`hotspot` field the "original/source" hotspot.
- Refs #17276.
## Solution
- When the image needs to be transformed, also transform the hotspot. If
the image does not need to be transformed (i.e. fast path), no hotspot
transformation is applied.
## Testing
- Ran the example: `cargo run --example custom_cursor_image
--features=custom_cursor`.
- Add unit tests for the hotspot transform function.
- I also ran the example I have in my `bevy_cursor_kit` crate, which I
think is a good illustration of the reason for this PR.
- In the following videos, there is an arrow pointing up. The button
hover event fires as I move the mouse over it.
- When I press `Y`, the cursor flips.
- In the first video, on `bevy@main` **before** this PR, notice how the
hotspot is wrong after flipping and no longer hovering the button. The
arrow head and hotspot are no longer synced.
- In the second video, on the branch of **this** PR, notice how the
hotspot gets flipped as soon as I press `Y` and the cursor arrow head is
in the correct position on the screen and still hovering the button.
Speaking back to the objective listed at the start: The user originally
defined the _source_ hotspot for the arrow. Later, they decide they want
to flip the cursor vertically: It's nice that Bevy can automatically
flip the _source_ hotspot for them at the same time it flips the
_source_ image.
First video (main):
https://github.com/user-attachments/assets/1955048c-2f85-4951-bfd6-f0e7cfef0cf8
Second video (this PR):
https://github.com/user-attachments/assets/73cb9095-ecb5-4bfd-af5b-9f772e92bd16
# Objective
The bounding_2d example was originally placed in 2d_rendering because
there was no folder for bounding or math, but now that this folder exist
it makes no sense for it to be here.
## Solution
Move the example
## Testing
I ran the example
# Objective
Fixes#16628
## Solution
Matrices were being applied in the wrong order.
## Testing
Ran `skybox` example with rotations applied to the `Skybox` on the `x`,
`y`, and `z` axis (one at a time).
e.g.
```rust
Skybox {
image: skybox_handle.clone(),
brightness: 1000.0,
rotation: Quat::from_rotation_y(-45.0_f32.to_radians()),
}
```
## Showcase
[Screencast_20250121_151232.webm](https://github.com/user-attachments/assets/3df68714-f5f1-4d8c-8e08-cbab525a8bda)
# Objective
- Correct a mistake in the rustdoc for bevy_ecs::world::World.
## Solution
- The rustdoc wrongly stated that "Each component can have up to one
instance of each component type.". This sentence should presumably be
"Each *Entity* can have up to one instance of each component type.".
Applying this change makes the prior sentence "Each [`Entity`] has a set
of components." redundant.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Minor improvement to the render_resource doc comments; specifically, the
gpu buffer types
- makes them consistently reference each other
- reorders them to be alphabetical
- removes duplicated entries
## Objective
Bevy 0.15 introduced new method in `Material2d` trait- `alpha_mode`.
Before that when new material was created it had alpha blending, now it
does not.
## Solution
While I am okay with it, it could be useful to add the new trait method
implementation to one of the samples so users are more aware of it.
---------
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
The `ArgList::push` family of methods consume `self` and return a new
`ArgList` which means they can't be used with `&mut ArgList` references.
```rust
fn foo(args: &mut ArgList) {
args.push_owned(47_i32); // doesn't work :(
}
```
It's typical for `push` methods on other existing types to take `&mut
self`.
## Solution
Renamed the existing push methods to `with_arg`, `with_ref` etc and
added new `push` methods which take `&mut self`.
## Migration Guide
Uses of the `ArgList::push` methods should be replaced with the `with`
counterpart.
<details>
| old | new |
| --- | --- |
| push_arg | with_arg |
| push_ref | with_ref |
| push_mut | with_mut |
| push_owned | with_owned |
| push_boxed | with_boxed |
</details>
# Objective
The various `Query::sort()` methods have a lot of duplicated code
between them, including some unsafe code. Reduce the duplication to make
the code easier to read and maintain.
## Solution
Extract the duplicated code to a private method, and pass in the sorting
strategy as a closure.
## Testing
I used `cargo-show-asm` to verify that the closures were inlined, but I
didn't run anything through a profiler. The `sort()` method itself even
had identical assembly before and after this change, although the others
did not.
# Objective
I wrote a box shadow UI material naively thinking I could use the border
widths attribute to hold the border radius but it
doesn't work as the border widths are automatically set in the
extraction function. Need to send border radius to the shader seperately
for it to be viable.
## Solution
Add a `border_radius` vertex attribute to the ui material.
This PR also removes the normalization of border widths for custom UI
materials. The regular UI shader doesn't do this so it's a bit confusing
and means you can't use the logic from `ui.wgsl` in your custom UI
materials.
## Testing / Showcase
Made a change to the `ui_material` example to display border radius:
```cargo run --example ui_material```
<img width="569" alt="corners" src="https://github.com/user-attachments/assets/36412736-a9ee-4042-aadd-68b9cafb17cb" />
Unfortunately, Apple platforms don't have enough texture bindings to
properly support clustered decals. This should be fixed once `wgpu` has
first-class bindless texture support. In the meantime, we disable them.
Closes#17553.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>