# Objective
Fix#18546 by adding a variant to `MergeMeshError`, for incompatible
primitive topologies.
## Solution
Made `MergeMeshError` into an enum with two variants;
`IncompatibleVertexAttributes` and `IncompatiblePrimitiveTopology`.
Added an if statement in `Mesh::merge` to check if the
`primitive_topology` field of `self` matches `other`.
Also renamed `MergeMeshError` to `MeshMergeError` to align with the two
other `MeshSomethingError`'s.
## Testing
Didn't do any.
# Objective
The ECS code to do with Observers was recently refactored to use an
`EventKey` newtype. On reading through the PR, I was a bit confused that
sometimes a variable called `event` refers to an `Event` and sometimes
it refers to an `EventKey`. I think the code is clearer when `event`
refers to an `Event` and `event_key` refers to an `EventKey`.
## Solution
This PR renames some uses of `event` to `event_key`.
## Testing
- Did you test these changes? If so, how?
I ran `cargo run -p ci -- tests`
- Are there any parts that need more testing?
No
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
No.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Probably not relevant, but MacOS.
---------
Co-authored-by: Steve Alexander <steve.alexander@priva.com>
# Objective
Improvement of the documentation for SystemParam derive section so that
it mentions how to use a Query<&SomeComponent> as a SystemParam for a
struct that should have #[derive(SystemParam)].
## Solution
Added the documentation
---
## Showcase
the previous documentation
```rust
Query<'w, 's, Entity>,
Res<'w, SomeResource>,
ResMut<'w, SomeOtherResource>,
Local<'s, u8>,
Commands<'w, 's>,
EventReader<'w, 's, SomeEvent>,
EventWriter<'w, SomeEvent>
```
the new documentation
```rust
Query<'w, 's, Entity>,
Query<'w, 's, &'static SomeComponent>, <================== the new thing
Res<'w, SomeResource>,
ResMut<'w, SomeOtherResource>,
Local<'s, u8>,
Commands<'w, 's>,
EventReader<'w, 's, SomeEvent>,
EventWriter<'w, SomeEvent>
```
# Objective
- Fixes#20008 - Preconvert colors before sending them to the UI
gradients shader for better performance
## Solution
- Modified `prepare_gradient` in `gradient.rs` to convert colors from
`LinearRgba` to `Srgba` on the CPU before sending to the GPU
- Updated the gradient shader to remove per-pixel color space
conversions since colors are now pre-converted
- Added documentation to clarify that vertex colors are in sRGB space
This optimization reduces the number of power operations per pixel from
3 to 1:
- **Before**: Convert start color to sRGB, convert end color to sRGB,
mix, convert back to linear (3 pow operations per pixel)
- **After**: Colors pre-converted on CPU, mix in sRGB space, convert
back to linear (1 pow operation per pixel)
## Testing
- Verified that the UI gradient examples (`cargo run --example
gradients`) compile and render correctly
- The visual output should remain identical while performance improves,
especially for large gradient areas
- Changes maintain the same color interpolation behavior (mixing in sRGB
space)
To test:
1. Run `cargo run --example gradients` or `cargo run --example
stacked_gradients`
2. Verify gradients render correctly
---------
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
# Objective
- Add an easy way to finish a Timer
## Solution
- Tick the timer by the remaining time
## Testing
I have not tested, but it should work
---
## Showcase
```rust
let mut timer = Timer::from_seconds(1.5, TimerMode::Once);
timer.finish();
assert_eq!(timer.remaining(), Duration::from_secs(0))
```
---------
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
#### Goals
* Stop layout updates from overwriting `ScrollPosition`.
* Make `ScrollPosition` respect scale factor.
* Automatically allocate space for a scrollbar on an axis when
`OverflowAxis::Scroll` is set.
#### Non-Goals
* Overflow-auto support (I was certain Taffy had this already, but
apparently I was hallucinating).
* Implement any sort of scrollbar widgets.
* Stability (not needed because no overflow-auto support).
* Maybe in the future we could make a `ScrollbarWidth` enum to more
closely match the CSS API with its auto/narrow/none options. For now
`scrollbar_width` is just an `f32` which matches Taffy's API.
## Solution
* Layout updates no longer overwrite `ScrollPosition`'s value.
* Added the field `scrollbar_width: f32` to `Node`. This is sent to
`Taffy` which will automatically allocate space for scrollbars with this
width in the layout as needed.
* Added the fields `scrollbar_width: f32` and `scroll_position: Vec2` to
`ComputedNode`. These are updated automatically during layout.
* `ScrollPosition` now respects scale factor.
* `ScrollPosition` is no longer automatically added to every UI node
entity by `ui_layout_system`. If every node needs it, it should just be
required by (or be a field on) `Node`. Not sure if that's necessary or
not.
## Testing
For testing you can look at:
* The `scrollbars` example, which should work as before.
* The new example `drag_to_scroll`.
* The `scroll` example which automatically allocates space for
scrollbars on the left hand scrolling list. Did not implement actual
scrollbars so you'll just see a gap atm.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Since we are planning to remove the need to derive both `Event` and
`EntityEvent` in 0.17 either way, I'm choosing to do the easy thing in
this PR so we can get the churn out of the way early.
Context from
[discord](https://discordapp.com/channels/691052431525675048/1383928409784193024/1393463673137401946).
Related to, and will conflict slightly with #20101.
## Solution
- Derive `Event` as part of the `EntityEvent` derive
- Remove any `Event` derives that were made unnecessary
- Update release notes
# Objective
- Progress towards #19887.
## Solution
- Convert `FromWorld` impls into systems.
- Run those systems in `RenderStartup`.
## Testing
- Ran `bloom_3d`, `auto_exposure`, `depth_of_field`, `motion_blur`,
`skybox`, `post_processing`, and `tonemapping` examples and they all
work :)
# Objective
- Progress towards #19887.
## Solution
- Convert FromWorld implementations into systems.
- Move any resource "manipulation" from `Plugin::finish` to systems.
- Add `after` dependencies to any uses of these resources (basically all
`SpritePipeline`).
## Testing
- Ran the `sprite`, and `mesh2d_manual` example and it worked.
# Objective
- Part of #20115
We want to encapsulate each part of `ScheduleGraph` into its own
specific struct to make parts of it easier to reuse and maintain.
## Solution
- Pulled `ScheduleGraph::systems` and `ScheduleGraph::system_conditions`
into a `Systems` struct and added a field for this new struct to
`ScheduleGraph`
- Broke up `ScheduleGraph::uninit` into `Systems::uninit` and
`SystemSets::uninit` to eliminate `ScheduleGraph`'s direct field access
of these types
- Removed node and condition accessors from `ScheduleGraph`; the same
operations are now available on `Systems` and `SystemSets` instead
(accessible via their `pub` fields on `ScheduleGraph`)
- Moved `Systems`, `SystemSets`, `SystemNode`, `SystemWithAccess`, and
`ConditionWithAccess` into a separate file.
## Testing
Added two new tests covering the API surface of `Systems` and
`SystemSets`, respectively.
---------
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
- Improve usability of read-only systems.
## Solution
- Added `on_unimplemented` diagnostics for types/functions that aren't
read-only systems.
- Added `BoxedReadOnlySystem` type alias, similar to `BoxedSystem`.
## Testing
Can/should we test these diagnostics?
# Objective
Fix#18079
## Solution
- `EntityCloner` can now move components that don't have `Clone` or
`Reflect` implementation.
- Components with `ComponentCloneBehavior::Ignore` will not be moved.
- Components with `ComponentCloneBehavior::Custom` will be cloned using
their defined `ComponentCloneFn` and then removed from the source entity
to respect their `queue_deferred` logic.
- Relationships still need to be `Clone` or `Reflect` to be movable.
- Custom relationship data is now correctly preserved when cloned or
moved using `EntityCloner`.
## Testing
- Added new tests for moving components
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
The names of the variants of `InterpolationColorSpace` don't match the
corresponding `Color` variants, which could be potentially confusing.
For instance, `Color` has an `Oklaba` variant, in
`InterpolationColorSpace` it's called `OkLab`.
## Solution
Rename variants of `InterpolationColorSpace` to mirror the variants of
Color.
# Objective
Fixes https://github.com/bevyengine/bevy/issues/19535. Improve
interoperability of type documentation to make it easier for users to
find related types
## Solution
- Add a reference to
[`ComponentIdFor`](crate::component::ComponentIdFor) in the
`component_id` function documentation in
`crates/bevy_ecs/src/world/mod.rs`
- Add a reference to [`ComponentIdFor`](super::ComponentIdFor) in the
`component_id` function documentation in
`crates/bevy_ecs/src/component/info.rs`
## Testing
- Verify documentation generation: `cargo doc`
- Check the validity of cross-reference links in the documentation
- Confirm that the documentation generated by rustdoc can correctly jump
to the type definition of `ComponentIdFor`
# Objective
Three impls are generated for each of these traits when the
`reflect_functions` feature is enabled.
Helps with #19873.
## Solution
Two of the three (the `&T` and `&mut T` ones) can be avoided by instead
providing blanket impls. The impl for `T` remains.
## Testing
I checked the output via `cargo expand`.
According to `-Zmacro-stats`, the size of the `Reflect` code generate
for `bevy_ui` drops by 10.4%.
# Objective
- Progress towards #19887.
- I am avoiding dealing with the `occlusion_culling` example since it is
kinda annoying to resolve nicely (I will do so in another PR).
## Solution
- Rewrite these examples to replace FromWorld implementations with
systems and other resource changes with systems as well.
## Testing
- All the changed examples have been tested and still work.
# Objective
- Clean up usage of BlitPipeline
## Solution
- add `create_bind_group` method
- adjust some field and variable names for clarity
## Testing
- ran 3d_scene
# Objective
Implement `Clone` for `IntoPipeSystem`, allowing for `T: IntoSystem +
Clone` patterns.
## Precedence
Same clone implementation/docs as `CombinatorSystem`
# Objective
> I think we should axe the shared `Event` trait entirely
It doesn't serve any functional purpose, and I don't think it's useful
pedagogically
@alice-i-cecile on discord
## Solution
- Remove `Event` as a supertrait of `BufferedEvent`
- Remove any `Event` derives that were made unnecessary
- Update release notes
---------
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
# Objective
Since I originally wrote this example, many people on Discord have asked
me specifically how to handle camera movement in and around fixed
timesteps. I had to write that information up maaaany times, so I
believe this is an area where the example falls short of.
## Solution
Let's port the example to 3D, where we can better showcase how to handle
the camera. The knowledge is trivially transferable to 2D :)
Also, we don't need to average out continuous input. Just using the last
one is fine in practice. Still, we need to keep around the
`AccumulatedInput` resource for things like jumping.
## Testing
https://github.com/user-attachments/assets/c1306d36-1f94-43b6-b8f6-af1cbb622698
## Notes
- The current implementation is extremely faithful to how it will look
like in practice when writing a 3D game using e.g. Avian. With the
exception that Avian does the part with the actual physics of course
- I'd love to showcase how to map sequences of inputs to fixed updates,
but winit does not export timestamps
- I'd also like to showcase instantaneous inputs like activating a boost
or shooting a laser, but that would make the example even bigger
- Not locking the cursor because doing so correctly on Wasm in the
current Bevy version is not trivial at all
---------
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
Fix lightmapped materials not respecting the
AmbientLight::affects_lightmapped_meshes setting.
NOTE: This only makes the setting work on the forward renderer. Making
it work on the deferred renderer would probably require encoding more
information in the g-buffer or similar. Please advise if I missed some
obvious way to get it working on deferred.
## Solution
- Make ambient light conditionally applied depending on the
affects_lightmapped_meshes setting when material mesh i lightmapped
- Remove what looks to be leftover `Lights` (wgsl) members:
`environment_map_smallest_specular_mip_level`,
`environment_map_intensity`. (These where not present in the rust
equivalent `GpuLights` and was not used in the wgsl code)
## Open Questions
- Ambient light is also blended into the transmitted light if
`DIFFUSE_TRANSMISSION` is enabled on the material. Should that also be
guarded by the same conditional as the indirect contribution?
## Testing
Ran a modified version of the lightmaps example, where there is a bright
red ambient light added and the small cube do not have a lightmap added
(To be able to see ambient light applied to meshes without lightmaps)
---
## Showcase
### Main: Lightmap example with bright red ambient, small box have no
lightmap
<img width="613" height="601" alt="Main"
src="https://github.com/user-attachments/assets/a3f206d7-5a1e-4590-8c40-69d5c6e06ce0"
/>
(All meshes get ambient light even when `affects_lightmapped_meshes =
false`)
### This PR: Lightmap example with bright red ambient, small box have no
lightmap
<img width="612" height="602" alt="With fix"
src="https://github.com/user-attachments/assets/d1a149a5-8994-4572-909f-8788ba2c38fc"
/>
(Only the small box get ambient light when `affects_lightmapped_meshes =
false`)
Fixes objects being lit by environment map light not having the
anisotropy effect applied correctly. The contribution of light from the
environment map with anisotropy is calculated but immediately discarded.
Instead what is applied is the regular environment map contribution
(calculated without anisotropy) that happen right after.
This patch fixes the logic here to what I think is the intended one.
Only calculate contribution once, with or without anisotropy depending
on shader specialization.
## Solution
- Properly apply normal modification if anisotropy is enabled.
- Remove duplicate environment map light calculation
## Testing
Tested this by running the anisotropy example and comparing main vs PR
results. See images below.
---
## Showcase
Main:
<img width="580" height="503" alt="Main-AnisoEnabled"
src="https://github.com/user-attachments/assets/47471a12-60cd-48ba-a32e-60086b6d162a"
/>
PR:
<img width="592" height="509" alt="WithFix-AnisoEnabled"
src="https://github.com/user-attachments/assets/e1f6b82c-1bac-40e1-8925-3abece05f406"
/>
</details>