# Objective
- This PR adds a new stress test called `many_materials` to benchmark
the rendering performance of many animated materials.
- Fixes#11588
- This PR continues the work started in the previous PR #11592, which
was closed due to inactivity.
## Solution
- Created a new example (`examples/stress_tests/many_materials.rs`) that
renders a grid of cubes with animated materials.
- The size of the grid can be configured using the `-n` command-line
argument (or `--grid-size`). The default grid size is 10x10.
- The materials animate by cycling through colors in the HSL color
space.
## Testing
- I have tested these changes locally on my Linux machine.
- Reviewers can test the changes by running the example with different
grid sizes and observing the performance (FPS, frame time).
- I have not tested on other platforms (macOS, Windows, wasm), but I
expect it to work as the code uses standard Bevy features.
---
## Showcase
<details>
<summary>Click to view showcase</summary>

</details>
# Objective
- Trouble remembering the difference between `OnAdd` and `OnInsert` for
triggers. Would like a better doc for those triggers so it appears in my
editor tooltip.
## Solution
- Clarify docs for OnAdd, OnInsert, OnRemove, OnReplace. Based on
comments in the
[component_hook.rs](https://github.com/bevyengine/bevy/blob/main/examples/ecs/component_hooks.rs#L73)
example.
## Testing
- None, small doc fix.
# Objective
Some collections are more efficient to construct when we know that every
element is unique in advance.
We have `EntitySetIterator`s from #16547, but currently no API to safely
make use of them this way.
## Solution
Add `FromEntitySetIterator` as a subtrait to `FromIterator`, and
implement it for the `EntityHashSet`/`hashbrown::HashSet` types.
To match the normal `FromIterator`, we also add a
`EntitySetIterator::collect_set` method.
It'd be better if these methods could shadow `from_iter` and `collect`
completely, but https://github.com/rust-lang/rust/issues/89151 is needed
for that.
While currently only `HashSet`s implement this trait, future
`UniqueEntityVec`/`UniqueEntitySlice` functionality comes with more
implementors.
Because `HashMap`s are collected from tuples instead of singular types,
implementing this same optimization for them is more complex, and has to
be done separately.
## Showcase
This is basically a free speedup for collecting `EntityHashSet`s!
```rust
pub fn collect_milk_dippers(dippers: Query<Entity, (With<Milk>, With<Cookies>)>) {
dippers.iter().collect_set::<EntityHashSet>();
// or
EntityHashSet::from_entity_set_iter(dippers);
}
---------
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
# Objective
- Make `CustomCursor::Image` easier to work with by splitting the enum
variants off into `CustomCursorImage` and `CustomCursorUrl` structs and
deriving `Default` on those structs.
- Refs #17276.
## Testing
- Ran two examples: `cargo run --example custom_cursor_image
--features=custom_cursor` and `cargo run --example window_settings
--features=custom_cursor`
- CI.
---
## Migration Guide
The `CustomCursor` enum's variants now hold instances of
`CustomCursorImage` or `CustomCursorUrl`. Update your uses of
`CustomCursor` accordingly.
# Objective
The `is_empty` checks that are meant to stop zero-sized uinodes from
being extracted are missing from `extract_uinode_background_colors`,
`extract_uinode_images` and `extract_ui_material_nodes`.
## Solution
Put them back.
Implement procedural atmospheric scattering from [Sebastien Hillaire's
2020 paper](https://sebh.github.io/publications/egsr2020.pdf). This
approach should scale well even down to mobile hardware, and is
physically accurate.
## Co-author: @mate-h
He helped massively with getting this over the finish line, ensuring
everything was physically correct, correcting several places where I had
misunderstood or misapplied the paper, and improving the performance in
several places as well. Thanks!
## Credits
@aevyrie: helped find numerous bugs and improve the example to best show
off this feature :)
Built off of @mtsr's original branch, which handled the transmittance
lut (arguably the most important part)
## Showcase:


## For followup
- Integrate with pcwalton's volumetrics code
- refactor/reorganize for better integration with other effects
- have atmosphere transmittance affect directional lights
- add support for generating skybox/environment map
---------
Co-authored-by: Emerson Coskey <56370779+EmersonCoskey@users.noreply.github.com>
Co-authored-by: atlv <email@atlasdostal.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: Emerson Coskey <coskey@emerlabs.net>
Co-authored-by: Máté Homolya <mate.homolya@gmail.com>
# Objective
- Fix typo in `spin/portable-atomic` feature.
## Solution
- Replace with `spin/portable_atomic`
## Testing
- CI
---
## Notes
This is a very annoying design choice the `spin` developers made.
Because the _crate_ is called `portable-atomic` and is optional, Cargo
automatically registers the feature `portable-atomic`. But the
maintainers use `portable_atomic` for their _feature_ which enables the
support. Sneaks through CI because it's a valid feature and will only
cause breakage on atomically challenged platforms (which we currently
aren't testing in CI).
Should we test atomically challenged in CI? Right now I don't think so,
at least not until we've made "normal" `no_std` CI better with the main
`bevy` crate as the test-case rather than each individual crate.
# Objective
Make the examples look more uniform and more polished.
following the issue #17167
## Solution
- [x] Added a minimal UI explaining how to interact with the examples
only when needed.
- [x] Used the same notation for interactions ex : "Up Arrow: Move
Forward \nLeft / Right Arrow: Turn"
- [x] Set the color to
[GRAY](https://github.com/bevyengine/bevy/pull/17237#discussion_r1907560092)
when it's not visible enough
- [x] Changed some colors to be easy on the eyes
- [x] removed the //camera comment
- [x] Unified the use of capital letters in the examples.
- [x] Simplified the mesh2d_arc offset calculations.
...
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
- Contributes to #16877
## Solution
- Moved `hashbrown`, `foldhash`, and related types out of `bevy_utils`
and into `bevy_platform_support`
- Refactored the above to match the layout of these types in `std`.
- Updated crates as required.
## Testing
- CI
---
## Migration Guide
- The following items were moved out of `bevy_utils` and into
`bevy_platform_support::hash`:
- `FixedState`
- `DefaultHasher`
- `RandomState`
- `FixedHasher`
- `Hashed`
- `PassHash`
- `PassHasher`
- `NoOpHash`
- The following items were moved out of `bevy_utils` and into
`bevy_platform_support::collections`:
- `HashMap`
- `HashSet`
- `bevy_utils::hashbrown` has been removed. Instead, import from
`bevy_platform_support::collections` _or_ take a dependency on
`hashbrown` directly.
- `bevy_utils::Entry` has been removed. Instead, import from
`bevy_platform_support::collections::hash_map` or
`bevy_platform_support::collections::hash_set` as appropriate.
- All of the above equally apply to `bevy::utils` and
`bevy::platform_support`.
## Notes
- I left `PreHashMap`, `PreHashMapExt`, and `TypeIdMap` in `bevy_utils`
as they might be candidates for micro-crating. They can always be moved
into `bevy_platform_support` at a later date if desired.
# Objective
- Contributes to #16877
## Solution
- Expanded `bevy_platform_support::sync` module to provide
API-compatible replacements for `std` items such as `RwLock`, `Mutex`,
and `OnceLock`.
- Removed `spin` from all crates except `bevy_platform_support`.
## Testing
- CI
---
## Notes
- The sync primitives, while verbose, entirely rely on `spin` for their
implementation requiring no `unsafe` and not changing the status-quo on
_how_ locks actually work within Bevy. This is just a refactoring to
consolidate the "hacks" and workarounds required to get a consistent
experience when either using `std::sync` or `spin`.
- I have opted to rely on `std::sync` for `std` compatible locks,
maintaining the status quo. However, now that we have these locks
factored out into the own module, it would be trivial to investigate
alternate locking backends, such as `parking_lot`.
- API for these locking types is entirely based on `std`. I have
implemented methods and types which aren't currently in use within Bevy
(e.g., `LazyLock` and `Once`) for the sake of completeness. As the
standard library is highly stable, I don't expect the Bevy and `std`
implementations to drift apart much if at all.
---------
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
The UI can only target a single view and doesn't support `RenderLayers`,
so there doesn't seem to be any need for UI nodes to require
`ViewVisibility` and `VisibilityClass`.
Fixes#17400
## Solution
Remove the `ViewVisibility` and `VisibilityClass` component requires
from `Node` and change the visibility queries to only query for
`InheritedVisibility`.
## Testing
```cargo run --example many_buttons --release --features "trace_tracy"```
Yellow is this PR, red is main.
`bevy_render::view::visibility::reset_view_visibility`
<img width="531" alt="reset-view" src="https://github.com/user-attachments/assets/a44b215d-96bf-43ec-8669-31530ff98eae" />
`bevy_render::view::visibility::check_visibility`
<img width="445" alt="view_visibility" src="https://github.com/user-attachments/assets/fa111757-da91-434d-88e4-80bdfa29374f" />
Right now, we always include distance fog in the shader, which is
unfortunate as it's complex code and is rare. This commit changes it to
be a `#define` instead. I haven't confirmed that removing distance fog
meaningfully reduces VGPR usage, but it can't hurt.
# Objective
Dependabot tried up update this earlier, but it was noticed that this
broke wasm builds. A new release has happened since then which includes
a fix for that.
Here's the
[changelog](https://github.com/smol-rs/async-broadcast/blob/master/CHANGELOG.md).
Closes#11830
## Solution
Use `async-broadcast` `0.7.2`.
## Testing
I ran a few some examples involving assets on macos / wasm.
# Objective
Fixes#17457
## Solution
#[derive(FromWorld)] now works with enums by specifying which variant
should be used.
## Showcase
```rust
#[Derive(FromWorld)]
enum Game {
#[from_world]
Playing,
Stopped
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
Make `Mesh::merge` more resilient to use.
Currently, it's difficult to make sure `Mesh::merge` will not panic
(we'd have to check if all attributes are compatible).
- I'd appreciate it for utility function to convert different mesh
representations such as:
https://github.com/dimforge/bevy_rapier/pull/628.
## Solution
- Make `Mesh::merge` return a `Result`.
## Testing
- It builds
## Migration Guide
- `Mesh::merge` now returns a `Result<(), MeshMergeError>`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Greeble <166992735+greeble-dev@users.noreply.github.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
The doc comment for `Node::flex_basis` which refers to a`size` field
that was replaced by individual `width` and `height` fields sometime
ago.
## Solution
Refer to the individual fields instead.
# Objective
- Make the function signature for `ComponentHook` less verbose
## Solution
- Refactored `Entity`, `ComponentId`, and `Option<&Location>` into a new
`HookContext` struct.
## Testing
- CI
---
## Migration Guide
Update the function signatures for your component hooks to only take 2
arguments, `world` and `context`. Note that because `HookContext` is
plain data with all members public, you can use de-structuring to
simplify migration.
```rust
// Before
fn my_hook(
mut world: DeferredWorld,
entity: Entity,
component_id: ComponentId,
) { ... }
// After
fn my_hook(
mut world: DeferredWorld,
HookContext { entity, component_id, caller }: HookContext,
) { ... }
```
Likewise, if you were discarding certain parameters, you can use `..` in
the de-structuring:
```rust
// Before
fn my_hook(
mut world: DeferredWorld,
entity: Entity,
_: ComponentId,
) { ... }
// After
fn my_hook(
mut world: DeferredWorld,
HookContext { entity, .. }: HookContext,
) { ... }
```
# Objective
- Fix issue @mockersf identified with `example-showcase` where time was
not being received correctly from the render world.
## Solution
- Refactored to ensure `TimeReceiver` is always cleared even if it isn't
being used in the main world.
## Testing
- `cargo run -p example-showcase -- --page 1 --per-page 1 run
--screenshot-frame 200 --fixed-frame-time 0.0125 --stop-frame 450
--in-ci --show-logs`
# Objective
Alternative to #9660, which is outdated since "required components"
landed.
Fixes#9655
## Solution
This is a different approach than the linked PR, slotting the warning
into an existing check for zero or negative font sizes in the text
pipeline.
## Testing
Replaced a font size with `0.0` in `examples/ui/text.rs`.
```
2025-01-22T23:26:08.239688Z INFO bevy_winit::system: Creating new window App (0v1)
2025-01-22T23:26:08.617505Z WARN bevy_text::pipeline: Text span 10v1 has a font size <= 0.0. Nothing will be displayed.
```
# Objective
- Contributes to #15460
## Solution
- Switched `tracing` for `log` for the atomically challenged platforms
- Setup feature flags as required
- Added to `compile-check-no-std` CI task
- Made `crossbeam-channel` optional depending on `std`.
## Testing
- CI
---
## Notes
- `crossbeam-channel` provides a MPMC channel type which isn't readily
replicable in `no_std`, and is only used for a `bevy_render`
integration. As such, I've feature-gated the `TimeReceiver` and
`TimeSender` types.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#14708
Also fixes some commands not updating tracked location.
## Solution
`ObserverTrigger` has a new `caller` field with the
`track_change_detection` feature;
hooks take an additional caller parameter (which is `Some(…)` or `None`
depending on the feature).
## Testing
See the new tests in `src/observer/mod.rs`
---
## Showcase
Observers now know from where they were triggered (if
`track_change_detection` is enabled):
```rust
world.observe(move |trigger: Trigger<OnAdd, Foo>| {
println!("Added Foo from {}", trigger.caller());
});
```
## Migration
- hooks now take an additional `Option<&'static Location>` argument
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Contributes to #15460
## Solution
- Switched `tracing` for `log` for the atomically challenged platforms
- Setup feature flags as required
- Added to `compile-check-no-std` CI task
## Testing
- CI
---
## Notes
- _Very_ easy one this time. Most of the changes here are just feature
definitions and documentation within the `Cargo.toml`
# Objective
Add reflection support to more `glam` `Vec` types, specifically
* I8Vec2
* I8Vec3
* I8Vec4
* U8Vec2
* U8Vec3
* U8Vec4
* I16Vec2
* I16Vec3
* I16Vec4
* U16Vec2
* U16Vec3
* U16Vec4
I needed to do this because I'm using various of these in my Bevy types,
and due to the orphan rules, I can't make these impls locally.
## Solution
Used `impl_reflect!` like for the existing types.
## Testing
This should not require additional testing, though I have verified that
reflection now works for these types in my own project.
This commit makes Bevy use change detection to only update
`RenderMaterialInstances` and `RenderMeshMaterialIds` when meshes have
been added, changed, or removed. `extract_mesh_materials`, the system
that extracts these, now follows the pattern that
`extract_meshes_for_gpu_building` established.
This improves frame time of `many_cubes` from 3.9ms to approximately
3.1ms, which slightly surpasses the performance of Bevy 0.14.
(Resubmitted from #16878 to clean up history.)

---------
Co-authored-by: Charlotte McElwain <charlotte.c.mcelwain@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
## Objective
Most `try` methods on `World` return a `Result`, but `try_despawn` and
`try_insert_batch` don't. Since Bevy's error handling is advancing,
these should be brought in line.
## Solution
- Added `TryDespawnError` and `TryInsertBatchError`.
- `try_despawn`, `try_insert_batch`, and `try_insert_batch_if_new` now
return their respective errors.
- Fixed slightly incorrect behavior in `try_insert_batch_with_caller`.
- The method was always meant to continue with the rest of the batch if
an entity was missing, but that only worked after the first entity; if
the first entity was missing, the method would exit early. This has been
resolved.
## Migration Guide
- `World::try_despawn` now returns a `Result` rather than a `bool`.
- `World::try_insert_batch` and `World::try_insert_batch_if_new` now
return a `Result` where they previously returned nothing.
# Objective
`bevy_ecs`'s `system` module is something of a grab bag, and *very*
large. This is particularly true for the `system_param` module, which is
more than 2k lines long!
While it could be defensible to put `Res` and `ResMut` there (lol no
they're in change_detection.rs, obviously), it doesn't make any sense to
put the `Resource` trait there. This is confusing to navigate (and
painful to work on and review).
## Solution
- Create a root level `bevy_ecs/resource.rs` module to mirror
`bevy_ecs/component.rs`
- move the `Resource` trait to that module
- move the `Resource` derive macro to that module as well (Rust really
likes when you pun on the names of the derive macro and trait and put
them in the same path)
- fix all of the imports
## Notes to reviewers
- We could probably move more stuff into here, but I wanted to keep this
PR as small as possible given the absurd level of import changes.
- This PR is ground work for my upcoming attempts to store resource data
on components (resources-as-entities). Splitting this code out will make
the work and review a bit easier, and is the sort of overdue refactor
that's good to do as part of more meaningful work.
## Testing
cargo build works!
## Migration Guide
`bevy_ecs::system::Resource` has been moved to
`bevy_ecs::resource::Resource`.
# Objective
While being able to quickly add / remove components down a tree is
broadly useful (material changing!), it's particularly necessary when
combined with the newly added #13120.
## Solution
Write four methods: covering both adding and removal on both
`EntityWorldMut` and `EntityCommands`.
These methods are generic over the `RelationshipTarget`, thanks to the
freshly merged relations 🎉
## Testing
I've added a simple unit test for these methods.
---------
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
# Objective
After #17398, Bevy now has relations! We don't teach users how to make /
work with these in the examples yet though, but we definitely should.
## Solution
- Add a simple abstract example that goes over defining, spawning,
traversing and removing a custom relations.
- ~~Add `Relationship` and `RelationshipTarget` to the prelude: the
trait methods are really helpful here.~~
- this causes subtle ambiguities with method names and weird compiler
errors. Not doing it here!
- Clean up related documentation that I referenced when writing this
example.
## Testing
`cargo run --example relationships`
## Notes to reviewers
1. Yes, I know that the cycle detection code could be more efficient. I
decided to reduce the caching to avoid distracting from the broader
point of "here's how you traverse relationships".
2. Instead of using an `App`, I've decide to use
`World::run_system_once` + system functions defined inside of `main` to
do something closer to literate programming.
---------
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
Fixes#17412
## Objective
`Parent` uses the "has a X" naming convention. There is increasing
sentiment that we should use the "is a X" naming convention for
relationships (following #17398). This leaves `Children` as-is because
there is prevailing sentiment that `Children` is clearer than `ParentOf`
in many cases (especially when treating it like a collection).
This renames `Parent` to `ChildOf`.
This is just the implementation PR. To discuss the path forward, do so
in #17412.
## Migration Guide
- The `Parent` component has been renamed to `ChildOf`.
# Objective
Fixes#17416
## Solution
I just included ReflectFromReflect in all macros and implementations. I
think this should be ok, at least it compiles properly and does fix the
errors in my test code.
## Testing
I generated a DynamicMap and tried to convert it into a concrete
`HashMap` as a `Box<dyn Reflect>`. Without my fix, it doesn't work,
because this line panics:
```rust
let rfr = ty.data::<ReflectFromReflect>().unwrap();
```
where `ty` is the `TypeRegistration` for the (matching) `HashMap`.
I don't know why `ReflectFromReflect` wasn't included everywhere, I
assume that it was an oversight and not an architecture decision I'm not
aware of.
# Migration Guide
The hasher in reflected `HashMap`s and `HashSet`s now have to implement
`Default`. This is the case for the ones provided by Bevy already, and
is generally a sensible thing to do.
# Objective
Some usecases in the ecosystems are blocked by the inability to stop
bevy internals and third party plugins from touching their entities.
However the specifics of a general purpose entity disabling system are
controversial and further complicated by hierarchies. We can partially
unblock these usecases with an opt-in approach: default query filters.
## Solution
- Introduce DefaultQueryFilters, these filters are automatically applied
to queries that don't otherwise mention the filtered component.
- End users and third party plugins can register default filters and are
responsible for handling entities they have hidden this way.
- Extra features can be left for after user feedback
- The default value could later include official ways to hide entities
---
## Changelog
- Add DefaultQueryFilters
# Objective
Diagnostics for labels don't suggest how to best implement them.
```
error[E0277]: the trait bound `Label: ScheduleLabel` is not satisfied
--> src/main.rs:15:35
|
15 | let mut sched = Schedule::new(Label);
| ------------- ^^^^^ the trait `ScheduleLabel` is not implemented for `Label`
| |
| required by a bound introduced by this call
|
= help: the trait `ScheduleLabel` is implemented for `Interned<(dyn ScheduleLabel + 'static)>`
note: required by a bound in `bevy_ecs::schedule::Schedule::new`
--> /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/schedule/schedule.rs:297:28
|
297 | pub fn new(label: impl ScheduleLabel) -> Self {
| ^^^^^^^^^^^^^ required by this bound in `Schedule::new`
```
## Solution
`diagnostics::on_unimplemented` and `diagnostics::do_not_recommend`
## Showcase
New error message:
```
error[E0277]: the trait bound `Label: ScheduleLabel` is not satisfied
--> src/main.rs:15:35
|
15 | let mut sched = Schedule::new(Label);
| ------------- ^^^^^ the trait `ScheduleLabel` is not implemented for `Label`
| |
| required by a bound introduced by this call
|
= note: consider annotating `Label` with `#[derive(ScheduleLabel)]`
note: required by a bound in `bevy_ecs::schedule::Schedule::new`
--> /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/schedule/schedule.rs:297:28
|
297 | pub fn new(label: impl ScheduleLabel) -> Self {
| ^^^^^^^^^^^^^ required by this bound in `Schedule::new`
```
docs: enhance documentation in `query.rs` to clarify borrowing rules.
Please, let me know if you don't agree with the wording.. There is
always room for improvement.
Tested locally and it looks like this:

---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#14970
## Solution
It seems the clamp call in `ui.wgsl` had the parameters order incorrect.
## Testing
Tested using examples/ui in native and my current project in wasm - both
in linux.
Could use some help with testing in other platforms.
---
# Objective
Noticed while doing #17449, I had left these `DerefMut` impls in.
Obtaining mutable references to those inner iterator types allows for
`mem::swap`, which can be used to swap an incorrectly behaving instance
into the wrappers.
## Solution
Remove them!
# Objective
The existing `RelationshipSourceCollection` uses `Vec` as the only
possible backing for our relationships. While a reasonable choice,
benchmarking use cases might reveal that a different data type is better
or faster.
For example:
- Not all relationships require a stable ordering between the
relationship sources (i.e. children). In cases where we a) have many
such relations and b) don't care about the ordering between them, a hash
set is likely a better datastructure than a `Vec`.
- The number of children-like entities may be small on average, and a
`smallvec` may be faster
## Solution
- Implement `RelationshipSourceCollection` for `EntityHashSet`, our
custom entity-optimized `HashSet`.
-~~Implement `DoubleEndedIterator` for `EntityHashSet` to make things
compile.~~
- This implementation was cursed and very surprising.
- Instead, by moving the iterator type on `RelationshipSourceCollection`
from an erased RPTIT to an explicit associated type we can add a trait
bound on the offending methods!
- Implement `RelationshipSourceCollection` for `SmallVec`
## Testing
I've added a pair of new tests to make sure this pattern compiles
successfully in practice!
## Migration Guide
`EntityHashSet` and `EntityHashMap` are no longer re-exported in
`bevy_ecs::entity` directly. If you were not using `bevy_ecs` / `bevy`'s
`prelude`, you can access them through their now-public modules,
`hash_set` and `hash_map` instead.
## Notes to reviewers
The `EntityHashSet::Iter` type needs to be public for this impl to be
allowed. I initially renamed it to something that wasn't ambiguous and
re-exported it, but as @Victoronz pointed out, that was somewhat
unidiomatic.
In
1a8564898f,
I instead made the `entity_hash_set` public (and its `entity_hash_set`)
sister public, and removed the re-export. I prefer this design (give me
module docs please), but it leads to a lot of churn in this PR.
Let me know which you'd prefer, and if you'd like me to split that
change out into its own micro PR.
# Objective
The gltf-json crate seems like it strips/adds an `_` when doing the name
comparison for custom vertex attributes.
* gltf-json
[add](88e719d5de/gltf-json/src/mesh.rs (L341))
* gltf-json
[strip](88e719d5de/gltf-json/src/mesh.rs (L298C12-L298C42))
* [bevy's
handling](b66c3ceb0e/crates/bevy_gltf/src/vertex_attributes.rs (L273-L276))
seems like it uses the non-underscore'd version.
The bevy example gltf:
[barycentric.gltf](b66c3ceb0e/assets/models/barycentric/barycentric.gltf),
includes two underscores: `__BARYCENTRIC` in the gltf file, resulting in
needing `_BARYCENTRIC` (one underscore) as the attribute name in Bevy.
This extra underscore is redundant and does not appear if exporting from
blender, which only requires a single underscore to trigger the
attribute export.
I'm not sure if we want to change the example itself (maybe there's a
reason it has two underscores, I couldn't find a reason), but a docs
comment would help.
## Solution
add docs detailing the behavior
# Objective
Make the `animated_mesh` example more intuitive and easier for the user
to extend.
# Solution
The `animated_mesh` example shows how to spawn a single mesh and play a
single animation. The original code is roughly:
1. In `setup_mesh_and_animation`, spawn an entity with a SceneRoot that
will load and spawn the mesh. Also record the animation to play as a
resource.
2. Use `play_animation_once_loaded` to detect when any animation players
are spawned, then play the animation from the resource.
When I used this example as a starting point for my own app, I hit a
wall when trying to spawn multiple meshes with different animations.
`play_animation_once_loaded` tells me an animation player spawned
somewhere, but how do I get from there to the right animation? The
entity it runs on is spawned by the scene so I can't attach any data to
it?
The new code takes a different approach. Instead of a global resource,
the animation is recorded as a component on the entity with the
SceneRoot. Instead of detecting animation players spawning wherever, an
observer is attached to that specific entity.
This feels more intuitive and localised, and I think most users will
work out how to get from there to different animations and meshes. The
downside is more lines of code, and the "find the animation players"
part still feels a bit magical and inefficient.
# Side Notes
- The solution was mostly stolen from
https://github.com/bevyengine/bevy/issues/14852#issuecomment-2481401769.
- The example still feels too complicated.
- "Why do I have to make this graph to play one animation?"
- "Why can't I choose and play the animation in one step and avoid this
temporary component?"
- I think this requires engine changes.
- I originally started on a separate example of multiple meshes
([branch](https://github.com/bevyengine/bevy/compare/main...greeble-dev:bevy:animated-mesh-multiple)).
- I decided that the user could probably work this out themselves from
the single animation example.
- But maybe still worth following through.
# Testing
`cargo run --example animated_mesh`
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
`Text2d` ignores `TextBounds` when calculating the offset for text
aligment.
On main a text entity positioned in the center of the window with center
justification and 600px horizontal text bounds isn't centered like it
should be but shifted off to the right:
<img width="305" alt="hellox"
src="https://github.com/user-attachments/assets/8896c6f0-1b9f-4633-9c12-1de6eff5f3e1"
/>
(second example in the testing section below)
Fixes#14266
I already had a PR in review for this (#14270) but it used post layout
adjustment (which we want to avoid) and ignored `TextBounds`.
## Solution
* If `TextBounds` are present for an axis, use them instead of the size
of the computed text layout size to calculate the offset.
* Adjust the vertical offset of text so it's top is aligned with the top
of the texts bounding rect (when present).
## Testing
```
use bevy::prelude::*;
use bevy::color::palettes;
use bevy::sprite::Anchor;
use bevy::text::TextBounds;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.run();
}
fn example(commands: &mut Commands, dest: Vec3, justify: JustifyText) {
commands.spawn((
Sprite {
color: palettes::css::YELLOW.into(),
custom_size: Some(10. * Vec2::ONE),
anchor: Anchor::Center,
..Default::default()
},
Transform::from_translation(dest),
));
for a in [
Anchor::TopLeft,
Anchor::TopRight,
Anchor::BottomRight,
Anchor::BottomLeft,
] {
commands.spawn((
Text2d(format!("L R\n{:?}\n{:?}", a, justify)),
TextFont {
font_size: 14.0,
..default()
},
TextLayout {
justify,
..Default::default()
},
TextBounds::new(300., 75.),
Transform::from_translation(dest + Vec3::Z),
a,
));
}
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d::default());
for (i, j) in [
JustifyText::Left,
JustifyText::Right,
JustifyText::Center,
JustifyText::Justified,
]
.into_iter()
.enumerate()
{
example(&mut commands, (300. - 150. * i as f32) * Vec3::Y, j);
}
commands.spawn(Sprite {
color: palettes::css::YELLOW.into(),
custom_size: Some(10. * Vec2::ONE),
anchor: Anchor::Center,
..Default::default()
});
}
```
<img width="566" alt="cap"
src="https://github.com/user-attachments/assets/e6a98fa5-80b2-4380-a9b7-155bb49635b8"
/>
This probably looks really confusing but it should make sense if you
imagine each block of text surrounded by a 300x75 rectangle that is
anchored to the center of the yellow square.
#
```
use bevy::prelude::*;
use bevy::sprite::Anchor;
use bevy::text::TextBounds;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d::default());
commands.spawn((
Text2d::new("hello"),
TextFont {
font_size: 60.0,
..default()
},
TextLayout::new_with_justify(JustifyText::Center),
TextBounds::new(600., 200.),
Anchor::Center,
));
}
```
<img width="338" alt="hello"
src="https://github.com/user-attachments/assets/e5e89364-afda-4baa-aca8-df4cdacbb4ed"
/>
The text being above the center is intended. When `TextBounds` are
present, the text block's offset is calculated using its `TextBounds`
not the layout size returned by cosmic-text.
#
Probably we should add a vertical alignment setting for Text2d. Didn't
do it here as this is intended for a 0.15.2 release.
simple derive macro for `FromWorld`. Going to be needed for composable
pipeline specializers but probably a nice thing to have regardless
## Testing
simple manual testing, nothing seemed to blow up. I'm no proc macro pro
though, so there's a chance I've mishandled spans somewhere or
something.
# Objective
- Contributes to #16877
## Solution
- Initial creation of `bevy_platform_support` crate.
- Moved `bevy_utils::Instant` into new `bevy_platform_support` crate.
- Moved `portable-atomic`, `portable-atomic-util`, and
`critical-section` into new `bevy_platform_support` crate.
## Testing
- CI
---
## Showcase
Instead of needing code like this to import an `Arc`:
```rust
#[cfg(feature = "portable-atomic")]
use portable_atomic_util::Arc;
#[cfg(not(feature = "portable-atomic"))]
use alloc::sync::Arc;
```
We can now use:
```rust
use bevy_platform_support::sync::Arc;
```
This applies to many other types, but the goal is overall the same:
allowing crates to use `std`-like types without the boilerplate of
conditional compilation and platform-dependencies.
## Migration Guide
- Replace imports of `bevy_utils::Instant` with
`bevy_platform_support::time::Instant`
- Replace imports of `bevy::utils::Instant` with
`bevy::platform_support::time::Instant`
## Notes
- `bevy_platform_support` hasn't been reserved on `crates.io`
- ~~`bevy_platform_support` is not re-exported from `bevy` at this time.
It may be worthwhile exporting this crate, but I am unsure of a
reasonable name to export it under (`platform_support` may be a bit
wordy for user-facing).~~
- I've included an implementation of `Instant` which is suitable for
`no_std` platforms that are not Wasm for the sake of eliminating feature
gates around its use. It may be a controversial inclusion, so I'm happy
to remove it if required.
- There are many other items (`spin`, `bevy_utils::Sync(Unsafe)Cell`,
etc.) which should be added to this crate. I have kept the initial scope
small to demonstrate utility without making this too unwieldy.
---------
Co-authored-by: TimJentzsch <TimJentzsch@users.noreply.github.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
Fixes#17164
## Solution
- Switch to `ubuntu-latest`
- Remove `libegl1-mesa`. It seems that whatever this was providing is
now covered by other deps or their deps?
## Testing
Tested [over here](https://github.com/rparrett/bevy/pull/21) by
commenting out workflow `if` condition.
Makes use of `std` explicit, simplifying a possible `no_std` port.
# Objective
- Contributes to #15460
- Simplify future `no_std` work on `bevy_asset`
## Solution
- Add `#![no_std]` to switch to `core::prelude` instead of
`std::prelude`
## Testing
- CI
---
## Notes
This is entirely a change around the names of imports and has no impact
on functionality. This just reduces the quantity of changes involved in
the (likely more controversial) `no_std`-ification of `bevy_asset`.
Fixes#17397.
Also renamed all variants into present-tense.
## Migration Guide
- `PointerAction::Pressed` has been seperated into two variants,
`PointerAction::Press` and `PointerAction::Release`.
- `PointerAction::Moved` has been renamed to `PointerAction::Move`.
- `PointerAction::Canceled` has been renamed to `PointerAction::Cancel`.