# Objective
Add interpolation in HSL and HSV colour spaces for UI gradients.
## Solution
Added new variants to `InterpolationColorSpace`: `Hsl`, `HslLong`,
`Hsv`, and `HsvLong`, along with mix functions to the `gradients` shader
for each of them.
#### Limitations
* Didn't include increasing and decreasing path support, it's not
essential and can be done in a follow up if someone feels like it.
* The colour conversions should really be performed before the colours
are sent to the shader but it would need more changes and performance is
good enough for now.
## Testing
```cargo run --example gradients```
## Objective
Fixes#19884.
## Solution
- Add an internal entity command `insert_with`, which takes a function
returning a component and checks if the component would actually be
inserted before invoking the function.
- Add the same check to `insert_from_world`, since it's a similar
situation.
- Update the `or_insert_with`, `or_try_insert_with`, and `or_default`
methods on `EntityEntryCommands` to use the new command.
Since the function/closure returning the component now needs to be sent
into the command (rather than being invoked before the command is
created), the function now has `Send + 'static` bounds. Pretty typical
for command stuff, but I don't know how/if it'll affect existing users.
---------
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
With the Bevy CLI, we now have an easy way to locally test if examples
work on the web.
We should start to explicitly document why examples don't work on the
web to keep track and to ensure that as many examples are enabled as
possible.
## Solution
- Go through the examples with `wasm = false` and check if they really
don't work
- If they don't work, try to figure out why by looking through the code
and announcement posts (we need better docs for this please) and add a
comment explaining it
- The `lightmap` example seemed to work without problems, so I enabled
it
## Testing
Install the [Bevy CLI](https://github.com/TheBevyFlock/bevy_cli) and
run:
```
bevy run --example={example_name} web --open
```
# Future Work
- There are about 100 more examples with `wasm = false` that also need
to be documeneted
- Also improve the documentation on the related features/plugins/types
to make it easier for users to determine what they can use
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
To implement fmt::Display for the direction types. The reason that this
would be a good addition is that I often find myself using println! to
debug things with directions and adding the extra ":?" was getting a
little annoying. It would also be better for any potential CLI apps that
might need to output a direction.
## Solution
Copied glam's implementation of Display for each length of direction.
I.E Vec3's display for Dir3.
## Testing
- Did you test these changes? If so, how?
Yes, I wrote a little script that printed out the different directions
and compared it to their vector counterparts.
Here it is if anyone's interested
```
use bevy_math::*;
fn main() {
let dir2 = Dir2::from_xy(0.0, 1.0).unwrap();
let dir3 = Dir3::from_xyz(0.0, 1.0, 0.0).unwrap();
let dir3a = Dir3A::from_xyz(0.0, 1.0, 0.0).unwrap();
let dir4 = Dir4::from_xyzw(0.0, 1.0, 0.0, 0.0).unwrap();
let vec2 = Vec2::new(0.0, 1.0);
let vec3 = Vec3::new(0.0, 1.0, 0.0);
let vec4 = Vec4::new(0.0, 1.0, 0.0, 1.0);
println!("{dir2} {dir3} {dir3a} {dir4}");
println!("{vec2}, {vec3}, {vec4}")
}
```
- Are there any parts that need more testing?
Perhaps
# Objective
#19649 introduced new `*_if_new` and `*_by_bundle_id_*` variations to
`EntityClonerBuilder` filtering functionality, which resulted in
increase in method permutations - there are now 8 allow variants to
support various id types and 2 different insert modes.
## Solution
This PR introduces a new trait `FilterableIds` to unify all id types and
their `IntoIterator` implementations, which is somewhat similar to
`WorldEntityFetch`. It supports `TypeId`, `ComponentId` and `BundleId`,
allowing us to reduce the number of `allow` methods to 4: `allow`,
`allow_if_new`, `allow_by_ids`, `allow_by_ids_if_new`. The function
signature is a bit less readable now, but the docs mention types that
can be passed in.
## Testing
All existing tests pass, performance is unchanged.
---------
Co-authored-by: urben1680 <55257931+urben1680@users.noreply.github.com>
# Objective
There is a pattern that appears in multiple places, involving
`reflect_clone`, followed by `take`, followed by `map_err` that produces
a `FailedDowncast` in a particular form.
## Solution
Introduces `reflect_clone_and_take`, which factors out the repeated
code.
## Testing
`cargo run -p ci`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
All the derived reflection methods currently have multiple trait bounds
on non-generic field types, which serve no purpose. The are emitted
because "emit bounds on all fields" is easier than "emit bounds on
fields that need them". But improving things isn't too hard.
Similarly, lots of useless `Any + Send + Sync` bounds exist on
non-generic types.
Helps a lot with #19873.
## Solution
Remove the unnecessary bounds by only emitting them if the relevant type
is generic.
## Testing
I used `cargo expand` to confirm the unnecessary bounds are no longer
produced.
`-Zmacro-stats` output tells me this reduces the size of the `Reflect`
code produced for `bevy_ui` by 21.2%.
Fixes#19594
The exact problem is described in that issue.
I improved the docs to guide anyone who has the the same issue I had.
I kept myself minimal, since the problem is relatively niche, hopefully
it will be enough if anyone else has that problem
I noticed that the `SpatialListener` asks to have a `Transform`
attached. It seemed weird that we didnt just use a require macro, so i
went ahead and did that
I also tweaked the system that plays audio to use a `&GlobalTransform`
instead of an `Option<&GlobalTransform>`
[Explanation](https://bevyengine.org/learn/contribute/helping-out/explaining-examples/)
for the 3d shapes example.
This shares a lot of detail with the [2d
shapes](https://github.com/bevyengine/bevy/pull/19211) example, so it's
similar in structure. The explanation for why asset handles are not
components has been copied over for now with minor adjustment, I'll do
another editing pass on this to make it match the surrounding context
and focus before taking it out of drafts.
---------
Co-authored-by: theotherphil <phil.j.ellison@gmail.com>
Co-authored-by: Carter Weinberg <weinbergcarter@gmail.com>
# Objective
`PickingPlugin` and `PointerInputPlugin` were kinda weird being both a
plugin and a resource.
## Solution
Extract the resource functionality of `PickingPlugin` and
`PointerInputPlugin` into new resources
## Testing
`mesh_picking` and `sprite_picking`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
# Objective
- Fixes#13872 (also mentioned in #17167)
## Solution
- Added conditional padding fields to the shader uniform
## Alternatives
### 1- Use a UVec4
Replace the `u32` field in `MyExtension` by a `UVec4` and only use the
`x` coordinate.
(This was the original approach, but for consistency with the rest of
the codebase, separate padding fields seem to be preferred)
### 2- Don't fix it, unlist it
While the fix is quite simple, it does muddy the waters a tiny bit due
to `quantize_steps` now being a UVec4 instead of a simple u32. We could
simply remove this example from the examples that support WebGL2.
## Testing
- Ran the example locally on WebGL2 (and native Vulkan) successfully
## Objective
Add a test that would have caught #16929 and #18712.
## Solution
The PR adds a `test_invalid_skinned_mesh` example that creates various
valid and invalid skinned meshes. This is designed to catch panics via
CI, and can be inspected visually. It also tests skinned meshes + motion
blur.

The screenshot shows all the tests, but two are currently disabled as
they cause panics. #18074 will re-enable them.
### Concerns
- The test is not currently suitable for screenshot comparison.
- I didn't add the test to CI. I'm a bit unsure if this should be part
of the PR or a follow up discussion.
- Visual inspection requires understanding why some meshes are
deliberately broken and what that looks like.
- I wasn't sure about naming conventions. I put `test` in the name so
it's not confused with a real example.
## Testing
```
cargo run --example test_invalid_skinned_mesh
```
Tested on Win10/Nvidia, across Vulkan, WebGL/Chrome, WebGPU/Chrome.
# Objective
- It's not clear what changes are needed to the shader to convert the
example to 2D.
- If you leave the shader unchanged you get a very confusing error (see
linked issue).
- Fixes#14077
## Solution
A separate example probably isn't needed as there is little difference
between 3D and 2D, but a note saying what changes are needed to the
shader would make it a lot easier.
Let me know if you think it is also worth adding some notes to the rust
file, but it is mostly trivial changes such as changing `Mesh3d` to
`Mesh2d`. I have left the original code in comments next to the changes
in the gist linked at the bottom if you wish to compare.
## Testing
- I just spent a long time working it out the hard way. This would have
made it a lot quicker.
- I have tested the 2D version of the shader with the changes explained
in the suggested comment and it works as expected.
- For testing purposes [here is a complete working 2D
example](https://gist.github.com/nickyfahey/647e2a2c45e695f24e288432b811dfc2).
(note that as per the original example the shader file needs to go in
'assets/shaders/')
# Objective
- nice bevy::camera bevy::mesh bevy::light imports
- skip bevy_light in 2d
## Solution
- add optional crates to internal
- make light only included when building pbr
## Testing
- 3d_scene
# Objective
Fixes#16525Fixes#19710
## Solution
Not allocating a mesh if it is empty.
## Testing
I tested using the following minimum repro from #16525
```rust
use bevy::{asset::RenderAssetUsages, prelude::*, render::mesh::PrimitiveTopology};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands.spawn(Camera2d);
let mesh = Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetUsages::default(),
);
commands.spawn((
Mesh2d(meshes.add(mesh)),
MeshMaterial2d(materials.add(Color::hsl(180.0, 0.95, 0.7))),
));
}
```
I was able to test on webgl2 and windows native and the issue seems to
be resolved. I am not familiar with how mesh rendering works and feel
like just skipping meshes should cause issues but I did not notice any.
# Objective
- Fixes#19910.
## Solution
- First, allow extraction function to be FnMut instead of Fn. FnMut is a
superset of Fn anyway, and we only ever call this function once at a
time (we would never call this in parallel for different pairs of worlds
or something).
- Run the `RenderStartup` schedule in the extract function with a flag
to only do it once.
- Remove all the `MainRender` stuff.
One sad part here is that now the `RenderStartup` blocks extraction. So
for pipelined rendering, our simulation will be blocked on the first
frame while we set up all the rendering resources. I don't see this as a
big loss though since A) that is fundamentally what we want here -
extraction **has to** run after `RenderStartup`, and the only way to do
better is to somehow run `RenderStartup` in parallel with the first
simulation frame, and B) without `RenderStartup` the **entire** app was
blocked on initializing render resources during Plugin construction - so
we're not really losing anything here.
## Testing
- I ran the `custom_post_processing` example (which was ported to use
`RenderStartup` in #19886) and it still works.
# Objective
- the fast inverse sqrt trick hasnt been useful on modern hardware for
over a decade now
## Solution
- just use sqrt, modern hardware has a dedicated instruction which will
outperform approximations both in efficiency and accuracy
## Testing
- ran `atmosphere`
# Objective
- make lights usable without bevy_render
## Solution
- make a new crate for lights to live in
## Testing
- 3d_scene, lighting, volumetric_fog, ssr, transmission, pcss,
light_textures
Note: no breaking changes because of re-exports, except for light
textures, which were introduced this cycle so it doesn't matter anyways
# Objective
- Calculating gradients in variable-termination loop is bad, and we dont
need to here
## Solution
- Sample mip 0 always
## Testing
- volumetric_fog example
# Objective
- prepare bevy_light for split
- make struct named better
- put it where it belongs
## Solution
- do those things
## Testing
- 3d_scene, lighting
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- prepare bevy_light for split
## Solution
- split render world extract related cluster code from main world ecs
stuff
re-exports make this not breaking
# Objective
- for smallvec some crates specify default features false, other dont.
turns out we dont need them
## Solution
- remove
## Testing
- 3d_scene
# Objective
- prepare bevy_light for split
## Solution
- extract cascade module (this is not strictly necessary for bevy_light)
- clean up imports to be less globby and tangled
- move light specific stuff into light modules
- move light system and type init from pbr into new LightPlugin
## Testing
- 3d_scene, lighting
NOTE TO REVIEWERS: it may help to review commits independently.
# Objective
- Make bevy_light possible by making it possible to split out
clusterable into bevy_camera
## Solution
- move ClusteredDecal to cluster module
- Depends on #19957 (because of the imports shuffling around) (draft
until thats merged)
## Testing
- 3d_scene runs
Note: no breaking changes thanks to re-exports
# Objective
- Make bevy_light possible
## Solution
- Move non-light stuff out of light module (its a marker for whether a
material should cast shadows: thats a material property not a light
property)
## Testing
- 3d_scene runs
# Objective
- Make bevy_light possible
## Solution
- Move some stuff it needs out of somewhere it cant depend on. Plus it
makes sense, cubemap stuff goes next to cubemap stuff.
## Testing
- 3d_scene runs
Note: no breaking changes thanks to re-exports
# Objective
- Make bevy_light possible by making it possible to split out
clusterable into bevy_camera
## Solution
- Move some stuff so i can split it out cleanly.
## Testing
- 3d_scene runs
# Objective
- Make bevy_light possible by making it possible to split out
clusterable into bevy_camera
## Solution
- Move cubemap stuff next to cubemap stuff.
## Testing
- 3d_scene runs
Note: no breaking changes thanks to re-exports
# Objective
- Make bevy_light possible
## Solution
- Move some stuff it needs out of somewhere it cant depend on. Plus it
makes sense, spotlight stuff goes in spotlight file.
## Testing
- 3d_scene runs
Note: no breaking changes thanks to re-exports
# Objective
- Make bevy_light possible by making it possible to split out
clusterable into bevy_camera
## Solution
- Use a resource to store cluster settings instead of recalculating it
every time from the render adapter/device
## Testing
- 3d_scene runs
# Objective
- define scenes without bevy_render
## Solution
- Move Camera2d/3d components out of bevy_core_pipeline
## Testing
- 3d_scene runs fine
Note: no breaking changes thanks to re-exports
# Objective
- Make bevy_light possible
## Solution
- Move some stuff it needs out of somewhere it cant depend on. Plus it
makes sense, visibility stuff goes in visibility.
## Testing
- 3d_scene runs
Note: no breaking changes thanks to re-exports
# Objective
- Progress towards #19887.
## Solution
- Convert `FromWorld` impls into systems that run in `RenderStartup`.
- Move `UiPipeline` init to `build_ui_render` instead of doing it
separately in `finish`.
Note: I am making several of these systems pub so that users could order
their systems relative to them. This is to match the fact that these
types previously were FromWorld so users could initialize them.
## Testing
- Ran `ui_material`, `ui_texture_slice`, `box_shadow`, and `gradients`
examples and it still worked.
# Objective
- get closer to being able to load gltfs without using bevy_render
## Solution
- Split bevy_camera out of bevy_render
- Builds on #19943
- Im sorry for the big diff, i tried to minimize it as much as i can by
using re-exports. This also prevents most breaking changes, but there
are still a couple.
## Testing
- 3d_scene looks good
# Objective
- The usage of ComponentId is quite confusing: events are not
components. By newtyping this, we can prevent stupid mistakes, avoid
leaking internal details and make the code clearer for users and engine
devs reading it.
- Adopts https://github.com/bevyengine/bevy/pull/19755
---------
Co-authored-by: oscar-benderstone <oscarbenderstone@gmail.com>
Co-authored-by: Oscar Bender-Stone <88625129+oscar-benderstone@users.noreply.github.com>
# Objective
- I accidentally left a `register_component_hooks` without actually
adding a hook and didnt notice
## Solution
- mark it must_use so it doesnt happen to other people (maybe this is
just skill issue on me though)
# Objective
- another step towards splitting out bevy_camera, this is needed by
visibility systems
## Solution
- move mesh stuff into mesh place
## Testing
- 3d_scene looks fine
No migration needed because of the re-export, that can be another PR
after i split bevy_camera
# Objective
Move Bevy UI's rendering into a dedicated crate.
Motivations:
* Allow the UI renderer to be used with other UI frameworks than
`bevy_ui`.
* Allow for using alternative renderers like Vello with `bevy_ui`.
* It's difficult for rendering contributors to make changes and
improvements to the UI renderer as it requires in-depth knowledge of the
UI implementation.
## Solution
Move the `render` and `ui_material` modules from `bevy_ui` into a new
crate `bevy_ui_render`.
## Testing
Important examples to check are `testbed_ui`, `testbed_full_ui`,
`ui_material`, `viewport_node` and `gradients`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
The generated `GetTypeRegistration::get_type_registration` method has an
unnecessary `allow(unused_mut)` attribute. It used to be necessary
because it was possible for `registration` to not be modified, but now
there is always at least one modification.
## Solution
Remove the attribute.
## Testing
I checked the `cargo expand` output.