Commit Graph

8852 Commits

Author SHA1 Message Date
robtfm
b641aa0ecf
separate border colors (#18682)
# Objective

allow specifying the left/top/right/bottom border colors separately for
ui elements

fixes #14773

## Solution

- change `BorderColor` to 
```rs
pub struct BorderColor {
    pub left: Color,
    pub top: Color,
    pub right: Color,
    pub bottom: Color,
}
```
- generate one ui node per distinct border color, set flags for the
active borders
- render only the active borders

i chose to do this rather than adding multiple colors to the
ExtractedUiNode in order to minimize the impact for the common case
where all border colors are the same.

## Testing

modified the `borders` example to use separate colors:


![image](https://github.com/user-attachments/assets/5d9a4492-429a-4ee1-9656-215511886164)

the behaviour is a bit weird but it mirrors html/css border behaviour.

---

## Migration:

To keep the existing behaviour, just change `BorderColor(color)` into
`BorderColor::all(color)`.

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
2025-05-26 16:57:13 +00:00
Emerson Coskey
fb2d79ad60
Better macro errors for get_struct_fields (#17639)
# Objective

- Currently, the error span for `get_struct_field` when encountering an
enum or union points to the macro invocation, rather than the `enum` or
`union` token. It also doesn't mention which macro reported the error.

## Solution

- Report the correct error span
- Add parameter for passing in the name of the macro invocation

## Testing

Bevy compiles fine with this change

## Migration Guide

```rs
// before
let fields = get_struct_fields(&ast.data);

// after
let fields = get_struct_fields(&ast.data, "derive(Bundle)");
```

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-05-26 16:57:03 +00:00
Periwink
f33074116b
Make SystemChangeTick Clone (#18991)
# Objective

It can be useful to store the `SystemChangeTick` for a given System. I
wanted to copy them but I noticed that it doesn't implement Clone.
2025-05-26 15:43:06 +00:00
Ben Frankel
475b5a8557
Improve visibility of debug picking node (#18990)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/18989.

## Solution

Add `GlobalZIndex(i32::MAX)`,
`BackgroundColor(Color::BLACK.with_alpha(0.75))`, and some padding.

## Testing

Ran `cargo run --example debug_picking`:


![2025-04-30_1745997924_1280x720](https://github.com/user-attachments/assets/4bd39897-f4ab-4d4d-850b-1b885284b072)

Before this PR:


![2025-04-29_1745972540_1280x720](https://github.com/user-attachments/assets/9c8649f4-0f06-4d4d-8fed-ac20e0d5366e)
2025-05-26 15:39:49 +00:00
Tim
4924cf5828
Remove upcasting methods + Cleanup interned label code (#18984)
Hiya!

# Objective

- Remove upcasting methods that are no longer necessary since Rust 1.86.
- Cleanup the interned label code.
 
## Notes
- I didn't try to remove the upcasting methods from `bevy_reflect`, as
there appears to be some complexity related to remote type reflection.
- There are likely some other upcasting methods floating around.

## Testing
I ran the `breakout` example to check that the hashing/eq
implementations of the labels are still correct.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-05-26 15:38:12 +00:00
Jakob Hellermann
93b8f9a303
bevy_ecs: forward type_id in InfallibleSystemWrapper (#18931)
similar to https://github.com/bevyengine/bevy/pull/12030

# Objective

`bevy_mod_debugdump` uses the `SystemTypeSet::system_type` to look up
constrains like `(system_1, system_2.after(system_1))`. For that it
needs to find the type id in `schedule.graph().systems()`

Now with systems being wrapped in an `InfallibleSystemWrapper` this
association was no longer possible.

## Solution

By forwarding the type id in `InfallibleSystemWrapper`,
`bevy_mod_debugdump` can resolve the dependencies as before, and the
wrapper is an unnoticable implementation detail.

## Testing

- `cargo test -p bevy_ecs`
I'm not sure what exactly could break otherwise.
2025-05-26 15:33:05 +00:00
Saladin
af874a58c3
Added explicit dependencies for Arch Linux (#10386)
As I run bevy in a apx container, the default dependencies are bare
minimum.. because of which I was able to find the explicit dependencies
required for bevy. 👍 the same shall also be applicable for the other
distributions but I will have to figure out explicit ones for them and
might open a PR for them later.

# Objective

- Have explicit dependencies listed for a bare minimum system /
container

## Solution

- Running bevy in a bare minimum apx / distrobox container.

---

## Changelog

- Added explicit dependency instructions for Arch Linux

Co-authored-by: SHuRiKeN <40650341+shuriken1812@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-05-26 15:32:48 +00:00
Sébastien Job
2b8bf45f0d
Fix BRP query failing when specifying missing/invalid components (#18871)
# Objective

- Fixes #18869.

## Solution

The issue was the `?` after a `Result` raising the error, instead of
treating it.
Instead it is handled with `ok`, `and_then`, `map` ...

_Edit: I added the following logic._
On `bevy/query` remote requests, when `strict` is false:
- Unregistered components in `option` and `without` are ignored.
- Unregistered components in `has` are considered absent from the
entity.
- Unregistered components in `components` and `with` result in an empty
response since they specify hard requirements.

I made the `get_component_ids` function return a
`AnyhowResult<(Vec<(TypeId, ComponentId)>, Vec<String>)>` instead of the
previous `AnyhowResult<Vec<(TypeId, ComponentId)>>`; that is I added the
list of unregistered components.

## Testing

I tested changes using the same procedure as in the linked issue:
```sh
cargo run --example server --features="bevy_remote"
```
In another terminal:
```sh
# Not strict:
$ curl -X POST http://localhost:15702 -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", "method": "bevy/query", "id": 0, "params": { "data": { "components": [ "foo::bar::MyComponent" ] } } }'
{"jsonrpc":"2.0","id":0,"result":[]}

# Strict:
$ curl -X POST http://localhost:15702 -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", "method": "bevy/query", "id": 0, "params": { "data": { "components": [ "foo::bar::MyComponent" ] }, "strict": true } }'
{"jsonrpc":"2.0","id":0,"error":{"code":-23402,"message":"Component `foo::bar::MyComponent` isn't registered or used in the world"}}
```
2025-05-26 15:26:46 +00:00
ickshonpe
c8872c7665
Allow access to font atlases (#18851)
# Objective
It's not possible atm for third-party crates to create their own text
systems that use the existing cosmic-text `FontSystem` and font atlases.

## Solution
Make `FontFaceInfo`, `TextPipeline::map_handle_to_font_id`, and
`load_font_fontdb` public so third-party crates can access and update
the existing font atlases
2025-05-26 15:22:56 +00:00
ickshonpe
3edacb5e46
Enable accessibility features for the button example (#18749)
# Objective

Accessibility features don't work with the UI `button` example because
`InputFocus` must be set for the accessibility systems to recognise the
button.

Fixes #18760

## Solution

* Set the button entity as the `InputFocus` when it is hovered or
pressed.
* Call `set_changed` on the `Button` component when the button's state
changes to hovered or pressed (the accessibility system's only update
the button's state when the `Button` component is marked as changed).

## Testing

Install NVDA, it should say "hover" when the button is hovered and
"pressed" when the button is pressed.

The bounds of the accessibility node are reported incorrectly. I thought
we fixed this, I'll take another look at it. It's not a problem with
this PR.
2025-05-26 15:19:55 +00:00
Greeble
ed0266b5a6
Fix glTF importer wrongly ignoring sampler filters (#19118)
## Objective

Fix #19114.

## Solution

#17875 changed the glTF importer to make sure that sampler filters are
linear when anisotropic filtering is enabled - this is required by
`wgpu`. But the condition was mistakenly inverted, so it forces the
filtering to linear when anisotropic filtering is _not_ enabled.

## Testing

```
cargo run --example color_grading
cargo run --example testbed_3d
```
2025-05-26 13:20:03 +00:00
Ben Frankel
3d9fc5ca10
Register some types (#19361)
# Objective

Fill in some `Reflect` and `app.register_type` gaps.

I only really wanted `GlobalZIndex` but figured I'd fill in a few others
as well.
2025-05-26 02:30:07 +00:00
Zachary Harrold
3d3746e5d0
Simplify bevy_utils Features (#19090)
# Objective

Now that `bevy_platform::cfg` is merged, we can start tidying up
features. This PR starts with `bevy_utils`.

## Solution

- Removed `serde` and `critical-section` features (they were just
re-exports of `bevy_platform` anyway)
- Removed `std`, `alloc` features, relying on `bevy_platform::cfg` to
check for availability.
- Added `parallel` feature to provide access to the `Parallel` type.
- Moved the `HashMap` type aliases into `map.rs` for better
organisation.

## Testing

- CI
2025-05-24 01:46:11 +00:00
oracle58
d7cab93495
Add debug build option to build-wasm-example (#19312)
## Objective

- Add a `--debug` flag to `build-wasm-example` to support debug builds
for WebGL2/WebGPU targets.
- Fixes #18464

## Solution
- Added `--debug` flag to build Wasm examples in debug mode.
- Default remains release mode if `--debug` is not specified.
- Updated documentation to describe the new flag and usage.

## Testing
- Verified debug and release builds for WebGL2 and WebGPU respectively.
- Confirmed wasm artifacts are placed in the correct target dir for each
build profile:
  - Debug: `target/wasm32-unknown-unknown/debug/examples/`
  - Release: `target/wasm32-unknown-unknown/release/examples/`
- Confirmed wasm-bindgen output is written to:
`examples/wasm/target/debug` , `examples/wasm/target/release`
- Haven't actually tested running the example

| Backend | Profile | Artifacts written | Build success    |
|---------|---------|-------------------|------------------|
| webgl2 | debug | ✓ | ✓ |
| webgl2 | release | ✓ | ✓ |
| webpgu | debug | ✓ | ✓ |
| webpgu | release | ✓ | ✓ |

### Examples

**Debug**
```
$ cargo run -p build-wasm-example -- --api webgl2 --debug load_gltf
```
```
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 02s
wasm-bindgen --out-dir examples/wasm/target/debug --out-name wasm_example --target web target/wasm32-unknown-unknown/debug/examples/load_gltf.wasm
```

**Release**
```
$ cargo run -p build-wasm-example -- --api webgl2 load_gltf`
```
```
Finished `release` profile [optimized] target(s) in 1m 08s
wasm-bindgen --out-dir examples/wasm/target/release --out-name wasm_example --target web target/wasm32-unknown-unknown/release/examples/load_gltf.wasm
```

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-05-24 01:43:57 +00:00
DaoLendaye
cf3f26f10b
Add GltfMeshName component and Deref implementations (#19331)
Stores mesh names from glTF files in GltfMeshName component rather than
Name component, making both GltfMeshName and GltfMaterialName behave
like strings via Deref.

# Objective

Fixed the side effects of #19287
Fixes Examples that modify gltf materials are broken #19322

## Solution

Add GltfMeshName component and Deref implementations

Stores mesh names from glTF files in GltfMeshName component rather than
Name component, making both GltfMeshName and GltfMaterialName behave
like strings via Deref.


## Testing

cargo run --example depth_of_field
cargo run --example lightmaps
cargo run --example mixed_lighting
They are consistent with the situation before the error occurred.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-05-23 20:56:48 +00:00
Lucas Franca
d3012df755
Expose LogDiagnosticsState (#19323)
# Objective

Closes #19175 
Make `LogDiagnosticsState` public to be able to edit its filters

## Solution

Make `LogDiagnosticsState` public and add methods to allow editing the
duration and filter

## Testing

`cargo run -p ci`

## Showcase

Updated `log_diagnostics` example

![image](https://github.com/user-attachments/assets/25bc00f3-40e2-4b4a-b90b-137cc1f307a5)
2025-05-23 20:56:36 +00:00
NonbinaryCoder
f95287ca9b
Diagnostic reset sum ema (#19337)
# Objective

Fix incorrect average returned by `Diagnostic` after `clear_history` is
called.

## Solution

Reset sum and ema values in `Diagnostic::clear_history`.

## Testing

I have added a cargo test for `Diagnostic::clear_history` that checks
average and smoothed average. This test passes, and should not be
platform dependent.
2025-05-22 19:04:24 +00:00
theotherphil
88e73f8eda
Fix one-character typo in SystemParam docs (#19338)
# Objective

Remove errant "a" from docs.

(I'm assuming that this sort of trivial fix is easy enough to merge that
it's worth doing, but let me know if you'd prefer me to not bother.)
2025-05-22 18:54:02 +00:00
Lucas
e2d087551e
feat: derive Serialize on Childof (#19336)
# Objective

allow serialization / deserialization on the `ChildOf` entity, for
example in network usage.
my usage was for the bevy_replicon crate, to replicate `ChildOf`.

## Solution

same implementation of serde as other types in the bevy repo

---------

Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
2025-05-22 18:30:14 +00:00
Kevin Reid
870ad21238
Add documentation and examples of [ScheduleLabel] usage. (#19329)
## Objective

Add documentation useful to users of `bevy_ecs` not also using `App`.

Fixes #19270.

## Solution

* Add explanation of labels to `Schedule` documentation.
* Add example of `derive(ScheduleLabel)` to `trait ScheduleLabel`.
* Add a third example to `Schedule` which demonstrates using a schedule
via label instead of owning it directly.
* Add further explanation and links to `World::add_schedule()`, and
`World::run_schedule()`.

## Testing

Reviewed generated documentation.

Please review this documentation carefully for correctness, as I have
little experience with `bevy_ecs` and I am adding this information
because it would have helped my own past confusion, but I may still be
wrong about how things should be done.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: theotherphil <phil.j.ellison@gmail.com>
2025-05-22 15:55:35 +00:00
stevehello166
c9e69ac65e
Rename Condition to SystemCondition` (#19328)
# Objective
Fixes #19120 

## Solution
Use the find and replace token feature in VSCode to replace all the
`Condition`s with `SystemCondition`s. Then look through all the
documentation with find and replace to replace all the `Condition`s
there.

## Testing

- Did you test these changes? If so, how?
Yes, used cargo clippy, cargo build and cargo test.
- Are there any parts that need more testing?
Nope
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
By compiling and running bevy
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Shouldn't be, but Fedora Linux with KDE Wayland
2025-05-22 15:50:19 +00:00
atlv
031fa25ff6
fix(picking): Location is not a Component anymore. (#19306)
# Objective

- Fixes #17390

## Solution

- Remove Component derive

## Testing

- cargo clippy
2025-05-22 01:33:01 +00:00
ickshonpe
2b59ab8e2d
Fix Anchor component inconsistancies (#18393)
## Objective

Fix the misleading 2d anchor API where `Anchor` is a component and
required by `Text2d` but is stored on a field for sprites.

Fixes #18367

## Solution

Remove the `anchor` field from `Sprite` and require `Anchor` instead.

## Migration Guide

The `anchor` field has been removed from `Sprite`. Instead the `Anchor`
component is now a required component on `Sprite`.
2025-05-21 15:32:04 +00:00
ickshonpe
bf20c630a8
UI Node Gradients (#18139)
# Objective

Allowing drawing of UI nodes with a gradient instead of a flat color.

## Solution

The are three gradient structs corresponding to the three types of
gradients supported: `LinearGradient`, `ConicGradient` and
`RadialGradient`. These are then wrapped in a `Gradient` enum
discriminator which has `Linear`, `Conic` and `Radial` variants.

Each gradient type consists of the geometric properties for that
gradient and a list of color stops.
Color stops consist of a color, a position or angle and an optional
hint. If no position is specified for a stop, it's evenly spaced between
the previous and following stops. Color stop positions are absolute, if
you specify a list of stops:
```vec![vec![ColorStop::new(RED, Val::Percent(90.), ColorStop::new(Color::GREEN, Val::Percent(10.))```
the colors will be reordered and the gradient will transition from green at 10% to red at 90%. 

Colors are interpolated between the stops in SRGB space. The hint is a normalized value that can be used to shift the mid-point where the colors are mixed 50-50.  between the stop with the hint and the following stop.

For sharp stops with no interpolated transition, place two stops at the same position.

`ConicGradient`s and RadialGradient`s have a center which is set using the new `Position` type. `Position` consists of a normalized (relative to the UI node) `Vec2` anchor point and a responsive x, y offset.

To draw a UI node with a gradient you insert the components `BackgroundGradient` and `BorderGradient`, which both newtype a vector of `Gradient`s. If you set a background color, the background color is drawn first and the gradient(s) are drawn on top.

The implementation is deliberately simple and self contained. The shader draws the gradient in multiple passes which is quite inefficient for gradients with a very large number of color stops. It's simple though and there won't be any compatibility issues. We could make gradients a specialization for `UiPipeline` but I used a separate pipeline plugin for now to ensure that these changes don't break anything. 

#### Not supported in this PR
* Interpolation in other color spaces besides SRGB. 
* Images and text: This would need some breaking changes like a `UiColor` enum type with `Color` and `Gradient` variants, to enable `BorderColor`, `TextColor`, `BackgroundColor` and `ImageNode::color` to take either a `Color` or a gradient.
* Repeating gradients

## Testing

Includes three examples that can be used for testing:
```
cargo run --example linear_gradients
cargo run --example stacked_gradients
cargo run --example radial_gradients
```

Most of the code except the components API is contained within the `bevy_ui/src/render/linear_gradients` module.
There are no changes to any existing systems or plugins except for the addition of the gradients rendering systems to the render world schedule and the `Val` changes from #18164 . 

## Showcase

![gradients](https://github.com/user-attachments/assets/a09c5bb2-f9dc-4bc5-9d17-21a6338519d3)
![stacked](https://github.com/user-attachments/assets/7a1ad28e-8ae0-41d5-85b2-aa62647aef03)
![rad](https://github.com/user-attachments/assets/48609cf1-52aa-453c-afba-3b4845f3ddec)

Conic gradients can be used to draw simple pie charts like in CSS:
![PIE](https://github.com/user-attachments/assets/4594b96f-52ab-4974-911a-16d065d213bc)
2025-05-20 14:45:22 +00:00
DaoLendaye
c62ca1a0d3
Use material name for mesh entity's Name when available (#19287)
# Objective

Fixes #19286

## Solution

Use material name for mesh entity's Name when available

## Testing

Test code, modified from examples/load_gltf.rs
```rust
//! Loads and renders a glTF file as a scene.

use bevy::{gltf::GltfMaterialName, prelude::*, scene::SceneInstanceReady};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_observer(on_scene_load)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
    ));

    commands.spawn((DirectionalLight {
        shadows_enabled: true,
        ..default()
    },));

    commands.spawn(SceneRoot(asset_server.load(
        GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"),
    )));
}

fn on_scene_load(
    trigger: Trigger<SceneInstanceReady>,
    children: Query<&Children>,
    names: Query<&Name>,
    material_names: Query<&GltfMaterialName>,
) {
    let target = trigger.target();

    for child in children.iter_descendants(target) {
        let name = if let Ok(name) = names.get(child) {
            Some(name.to_string())
        } else {
            None
        };
        let material_name = if let Ok(name) = material_names.get(child) {
            Some(name.0.clone())
        } else {
            None
        };

        info!("Entity name:{:?} | material name:{:?}", name, material_name);
    }
}
```

---

## Showcase

Run log:
<img width="859" alt="Image"
src="https://github.com/user-attachments/assets/87daddf3-31e6-41f8-9be2-4b292da9b75a"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Greeble <166992735+greeble-dev@users.noreply.github.com>
2025-05-20 14:45:04 +00:00
Lucas Franca
55edb0b476
Fix warnings and errors reported on Rust beta (#19294)
# Objective

Fixes errors and warnings on this week's Rust beta pipeline 
*
https://github.com/bevyengine/bevy/issues/18748#issuecomment-2890820218
2025-05-19 23:56:48 +00:00
Eero Lehtinen
17914943a3
Fix spot light shadow glitches (#19273)
# Objective

Spot light shadows are still broken after fixing point lights in #19265

## Solution

Fix spot lights in the same way, just using the spot light specific
visible entities component. I also changed the query to be directly in
the render world instead of being extracted to be more accurate.

## Testing

Tested with the same code but changing `PointLight` to `SpotLight`.
2025-05-19 19:42:09 +00:00
theotherphil
70e6a9010d
Add missing words in Traversal doc comment (#19298)
# Objective

Minor docs fix - add missing "is responsible".
2025-05-19 19:34:59 +00:00
theotherphil
fe16624d3c
Add boilerplate docs for PointerHits::new and HitData::new (#19259)
# Objective

Add documentation for the last two functions in bevy_picking that are
missing them.

## Solution

Add boilerplate "Constructs an X" to `PointerHits::new()` and
`HitData::new()`.

This form of no-information documentation of `new()` functions is used
in several places in the repo, and @alice-i-cecile agreed that this is a
reasonable approach - the params are already documented on the fields
within the struct definition.

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2025-05-19 19:22:07 +00:00
ickshonpe
37b16d869d
Remove YAxisOrientation from bevy_text (#19077)
# Objective

Been looking for simplifications in the text systems as part of the text
input changes.

This enum isn't very helpful I think. We can remove it and the
associated parameters and instead just negate the glyph's y-offsets in
`extract_text2d_sprite`.

## Solution

Remove the `YAxisOrientation` enum and parameters. 
Queue text sprites relative to the top-left in `extract_text2d_sprite`
and negate the glyph's y-offset.

## Testing

The `text2d` example can be used for testing:
```
cargo run --example text2d
```
2025-05-19 19:17:20 +00:00
SpecificProtagonist
e7e9973c80
Per world error handler (#18810)
# Objective

[see original
comment](https://github.com/bevyengine/bevy/pull/18801#issuecomment-2796981745)
> Alternately, could we store it on the World instead of a global? I
think we have a World nearby whenever we call default_error_handler().
That would avoid the need for atomics or locks, since we could do
ordinary reads and writes to the World.

Global error handlers don't actually need to be global – per world is
enough. This allows using different handlers for different worlds and
also removes the restrictions on changing the handler only once.

## Solution

Each `World` can now store its own error handler in a resource.

For convenience, you can also set the default error handler for an
`App`, which applies it to the worlds of all `SubApp`s. The old behavior
of only being able to set the error handler once is kept for apps.

We also don't need the `configurable_error_handler` feature anymore now.

## Testing

New/adjusted tests for failing schedule systems & observers.

---

## Showcase

```rust
App::new()
    .set_error_handler(info)
    …
```
2025-05-19 01:35:07 +00:00
atlv
45ba5b9f03
refactor(render): cleanup add_import_to_composer (#19269)
# Objective

- Reduce nesting

## Solution

- Refactor

## Testing

- `bevy run --example=3d_scene web --open`
2025-05-18 06:30:38 +00:00
Eero Lehtinen
2db103708a
Make sure prepass notices changes in alpha mode (#19170)
# Objective

Fixes #19150

## Solution

Normally the `validate_cached_entity` in 

86cc02dca2/crates/bevy_pbr/src/prepass/mod.rs (L1109-L1126)
marks unchanged entites as clean, which makes them remain in the phase.

If a material is changed to an `alpha_mode` that isn't supposed to be
added to the prepass pipeline, the specialization system just
`continue`s and doesn't indicate to the cache that the entity is not
clean anymore.

I made these invalid entities get removed from the pipeline cache so
that they are correctly not marked clean and then removed from the
phase.

## Testing

Tested with the example code from the issue.
2025-05-18 06:28:30 +00:00
Eero Lehtinen
4d1b045855
Fix point light shadow glitches (#19265)
# Objective

Fixes #18945

## Solution

Entities that are not visible in any view (camera or light), get their
render meshes removed. When they become visible somewhere again, the
meshes get recreated and assigned possibly different ids.

Point/spot light visible entities weren't cleared when the lights
themseves went out of view, which caused them to try to queue these fake
visible entities for rendering every frame. The shadow phase cache
usually flushes non visible entites, but because of this bug it never
flushed them and continued to queue meshes with outdated ids.

The simple solution is to every frame clear all visible entities for all
point/spot lights that may or may not be visible. The visible entities
get repopulated directly afterwards. I also renamed the
`global_point_lights` to `global_visible_clusterable` to make it clear
that it includes only visible things.

## Testing

- Tested with the code from the issue.
2025-05-18 06:24:37 +00:00
atlv
eed1dc428b
fix(render): transitive shader imports now work consistently on web (#19266)
# Objective

- transitive shader imports sometimes fail to load silently and return
Ok
- Fixes #19226

## Solution

- Don't return Ok, return the appropriate error code which will retry
the load later when the dependencies load

## Testing

- `bevy run --example=3d_scene web --open`


Note: this is was theoretically a problem before the hot reloading PR,
but probably extremely unlikely to occur.
2025-05-17 19:03:47 +00:00
Niklas Eicker
6397a28bbf
Pin nightly due to miri issue (#19253)
# Objective

The required miri check is currently failing due to rust-lang/miri#4323
Let's pin nightly to yesterday to not be blocked today.

## Solution

- Pinned nightly to `nightly-2025-05-16`

## Testing

- Let's see if the pipeline is green on this PR :D
2025-05-17 11:24:20 +00:00
atlv
139515278c
Use embedded_asset to load PBR shaders (#19137)
# Objective

- Get in-engine shader hot reloading working

## Solution

- Adopt #12009
- Cut back on everything possible to land an MVP: we only hot-reload PBR
in deferred shading mode. This is to minimize the diff and avoid merge
hell. The rest shall come in followups.

## Testing

- `cargo run --example pbr --features="embedded_watcher"` and edit some
pbr shader code
2025-05-16 05:47:34 +00:00
atlv
415ffa5028
clippy: expect large variants and other small fixes (#19222)
# Objective

- Fix CI

## Solution

- Expect new lint
- See #19220

## Testing

- cargo clippy
2025-05-15 22:29:59 +00:00
mgi388
01d2b8571c
Remove dead states code from bevy_ecs (#19210)
`bevy_ecs` was meant to have the `States` and `SubStates`
`proc_macro_derive`s removed when the separate `bevy_state` [was
created](https://github.com/bevyengine/bevy/issues/13216) but they were
missed.
2025-05-14 13:19:20 +00:00
atlv
673e70c72e
Fix specular cutoff on lights with radius overlapping with mesh (#19157)
# Objective

- Fixes #13318

## Solution

- Clamp a dot product to be positive to avoid choosing a `centerToRay`
which is not on the ray but behind it.

## Testing

- Repro in #13318

Main:
<img width="963" alt="{DA2A2B99-27C7-4A76-83B6-CCB70FB57CAD}"
src="https://github.com/user-attachments/assets/afae8001-48ee-4762-9522-e247bbe3577a"
/>

This PR:
<img width="963" alt="{2C4BC3E7-C6A6-4736-A916-0366FBB618DA}"
src="https://github.com/user-attachments/assets/5bea4162-0b58-4df0-bf22-09fcb27dc167"
/>

Eevee reference:

![329697008-ff28a5f3-27f3-4e98-9cee-d836a6c76aee](https://github.com/user-attachments/assets/a1b566ab-16ee-40d3-a0b6-ad179ca0fe3a)
2025-05-12 19:14:13 +00:00
Daniel Gallups
eb0f4f76ba
Fix: Provide CPU mesh processing with MaterialBindingId (#19083)
# Objective
Fixes #19027

## Solution
Query for the material binding id if using fallback CPU processing

## Testing
I've honestly no clue how to test for this, and I imagine that this
isn't entirely failsafe :( but would highly appreciate a suggestion!

To verify this works, please run the the texture.rs example using WebGL
2.

Additionally, I'm extremely naive about the nuances of pbr. This PR is
essentially to kinda *get the ball rolling* of sorts. Thanks :)

---------

Co-authored-by: Gilles Henaux <ghx_github_priv@fastmail.com>
Co-authored-by: charlotte <charlotte.c.mcelwain@gmail.com>
2025-05-12 18:11:14 +00:00
atlv
ddc9f41519
fix windows wasm embedded assets (#19139)
# Objective

- Fix #14246

## Solution

- If building for wasm windows, add a bit of code that replaces `\\`
with `/` in the `file!()` arg

## Testing

- Used MRE https://github.com/janhohenheim/asset-crash

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-05-12 10:10:32 +00:00
Jordan Dominion
86cc02dca2
Fix macro pollution in SystemParam derive (#19155)
# Objective

Fixes #19130 

## Solution

Fully quality `Result::Ok` so as to not accidentally invoke the anyhow
function of the same name

## Testing

Tested on this minimal repro with and without change.

main.rs
```rs
use anyhow::Ok;
use bevy::ecs::system::SystemParam;

#[derive(SystemParam)]
pub struct SomeParams;

fn main() {
}
```
Cargo.toml
```toml
[package]
name = "bevy-playground"
version = "0.1.0"
edition = "2024"

[dependencies]
anyhow = "1.0.98"
bevy = { path = "../bevy" }
```
2025-05-10 02:45:25 +00:00
databasedav
95470df3c8
fix .insert_related index bound (#19134)
# Objective

resolves #19092

## Solution

- remove the `.saturating_sub` from the index transformation
- add `.saturating_add` to the internal offset calculation

## Testing

- added regression test, confirming 0 index order + testing max bound
2025-05-09 17:10:54 +00:00
urben1680
732b2e0c79
Track spawn Tick of entities, offer methods, query data SpawnDetails and query filter Spawned (#19047)
# Objective

In my own project I was encountering the issue to find out which
entities were spawned after applying commands. I began maintaining a
vector of all entities with generational information before and after
applying the command and diffing it. This was awfully complicated though
and has no constant complexity but grows with the number of entities.

## Solution

Looking at `EntyMeta` it seemed obvious to me that struct can track the
tick just as it does with `MaybeLocation`, updated from the same call.
After that it became almost a given to also introduce query data
`SpawnDetails` which offers methods to get the spawn tick and location,
and query filter `Spawned` that filters entities out that were not
spawned since the last run.

## Testing

I expanded a few tests and added new ones, though maybe I forgot a group
of tests that should be extended too. I basically searched `bevy_ecs`
for mentions of `Changed` and `Added` to see where the tests and docs
are.

Benchmarks of spawn/despawn can be found
[here](https://github.com/bevyengine/bevy/pull/19047#issuecomment-2852181374).

---

## Showcase

From the added docs, systems with equal complexity since the filter is
not archetypal:
```rs
fn system1(q: Query<Entity, Spawned>) {
    for entity in &q { /* entity spawned */ }
}

fn system2(query: Query<(Entity, SpawnDetails)>) {
    for (entity, spawned) in &query {
        if spawned.is_spawned() { /* entity spawned */ }
    }
}
```

`SpawnedDetails` has a few more methods:

```rs
fn print_spawn_details(query: Query<(Entity, SpawnDetails)>) {
    for (entity, spawn_details) in &query {
        if spawn_details.is_spawned() {
            print!("new ");
        }
        println!(
            "entity {:?} spawned at {:?} by {:?}",
            entity,
            spawn_details.spawned_at(),
            spawn_details.spawned_by()
        );        
    }
}
```

## Changes

No public api was changed, I only added to it. That is why I added no
migration guide.

- query data `SpawnDetails`
- query filter `Spawned`
- method `Entities::entity_get_spawned_or_despawned_at`
- method `EntityRef::spawned_at`
- method `EntityMut::spawned_at`
- method `EntityWorldMut::spawned_at`
- method `UnsafeEntityCell::spawned_at`
- method `FilteredEntityRef::spawned_at`
- method `FilteredEntityMut::spawned_at`
- method `EntityRefExcept::spawned_at`
- method `EntityMutExcept::spawned_at`

---------

Co-authored-by: Eagster <79881080+ElliottjPierce@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-05-08 14:57:33 +00:00
Eagster
12aba64900
Make entity generation a new type and remove identifier (#19121)
# Objective

This is a followup to #18704 . There's lots more followup work, but this
is the minimum to unblock #18670, etc.

This direction has been given the green light by Alice
[here](https://github.com/bevyengine/bevy/pull/18704#issuecomment-2853368129).

## Solution

I could have split this over multiple PRs, but I figured skipping
straight here would be easiest for everyone and would unblock things the
quickest.

This removes the now no longer needed `identifier` module and makes
`Entity::generation` go from `NonZeroU32` to `struct
EntityGeneration(u32)`.

## Testing

CI

---------

Co-authored-by: Mark Nokalt <marknokalt@live.com>
2025-05-08 04:03:05 +00:00
Eagster
0b4858726c
Make entity::index non max (#18704)
# Objective

There are two problems this aims to solve. 

First, `Entity::index` is currently a `u32`. That means there are
`u32::MAX + 1` possible entities. Not only is that awkward, but it also
make `Entity` allocation more difficult. I discovered this while working
on remote entity reservation, but even on main, `Entities` doesn't
handle the `u32::MAX + 1` entity very well. It can not be batch reserved
because that iterator uses exclusive ranges, which has a maximum upper
bound of `u32::MAX - 1`. In other words, having `u32::MAX` as a valid
index can be thought of as a bug right now. We either need to make that
invalid (this PR), which makes Entity allocation cleaner and makes
remote reservation easier (because the length only needs to be u32
instead of u64, which, in atomics is a big deal), or we need to take
another pass at `Entities` to make it handle the `u32::MAX` index
properly.

Second, `TableRow`, `ArchetypeRow` and `EntityIndex` (a type alias for
u32) all have `u32` as the underlying type. That means using these as
the index type in a `SparseSet` uses 64 bits for the sparse list because
it stores `Option<IndexType>`. By using `NonMaxU32` here, we cut the
memory of that list in half. To my knowledge, `EntityIndex` is the only
thing that would really benefit from this niche. `TableRow` and
`ArchetypeRow` I think are not stored in an `Option` in bulk. But if
they ever are, this would help. Additionally this ensures
`TableRow::INVALID` and `ArchetypeRow::INVALID` never conflict with an
actual row, which in a nice bonus.

As a related note, if we do components as entities where `ComponentId`
becomes `Entity`, the the `SparseSet<ComponentId>` will see a similar
memory improvement too.

## Solution

Create a new type `EntityRow` that wraps `NonMaxU32`, similar to
`TableRow` and `ArchetypeRow`.
Change `Entity::index` to this type.

## Downsides

`NonMax` is implemented as a `NonZero` with a binary inversion. That
means accessing and storing the value takes one more instruction. I
don't think that's a big deal, but it's worth mentioning.

As a consequence, `to_bits` uses `transmute` to skip the inversion which
keeps it a nop. But that also means that ordering has now flipped. In
other words, higher indices are considered less than lower indices. I
don't think that's a problem, but it's also worth mentioning.

## Alternatives

We could keep the index as a u32 type and just document that `u32::MAX`
is invalid, modifying `Entities` to ensure it never gets handed out.
(But that's not enforced by the type system.) We could still take
advantage of the niche here in `ComponentSparseSet`. We'd just need some
unsafe manual conversions, which is probably fine, but opens up the
possibility for correctness problems later.

We could change `Entities` to fully support the `u32::MAX` index. (But
that makes `Entities` more complex and potentially slightly slower.)

## Testing

- CI
- A few tests were changed because they depend on different ordering and
`to_bits` values.

## Future Work

- It might be worth removing the niche on `Entity::generation` since
there is now a different niche.
- We could move `Entity::generation` into it's own type too for clarity.
- We should change `ComponentSparseSet` to take advantage of the new
niche. (This PR doesn't change that yet.)
- Consider removing or updating `Identifier`. This is only used for
`Entity`, so it might be worth combining since `Entity` is now more
unique.

---------

Co-authored-by: atlv <email@atlasdostal.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2025-05-07 18:20:30 +00:00
Chris Russell
9e2bd8ac18
Generic SystemParam impls for Option and Result (#18766)
# Objective

Provide a generic `impl SystemParam for Option<P>` that uses system
parameter validation. This immediately gives useful impls for params
like `EventReader` and `GizmosState` that are defined in terms of `Res`.
It also allows third-party system parameters to be usable with `Option`,
which was previously impossible due to orphan rules.

Note that this is a behavior change for `Option<Single>`. It currently
fails validation if there are multiple matching entities, but with this
change it will pass validation and produce `None`.

Also provide an impl for `Result<P, SystemParamValidationError>`. This
allows systems to inspect the error if necessary, either for bubbling it
up or for checking the `skipped` flag.

Fixes #12634
Fixes #14949
Related to #18516

## Solution

Add generic `SystemParam` impls for `Option` and `Result`, and remove
the impls for specific types.

Update documentation and `fallible_params` example with the new
semantics for `Option<Single>`.
2025-05-07 18:20:08 +00:00
Periwink
60ea43d01d
Add system ticks to EntityRef/Mut WorldQuery (#19115)
# Objective

- Fixes a subset of https://github.com/bevyengine/bevy/issues/13735 by
making `EntityRef`, `EntityMut` + similar WorldQueries use the system's
change ticks when being created from within a system.
In particular, this means that `entity_ref.get_ref::<T>()` will use the
correct change ticks (the ones from the system), which matches the
behaviour of querying for `Ref<T>` directly in the system parameters.

## Solution

- Implements the solution described by
https://github.com/bevyengine/bevy/issues/13735#issuecomment-2652482918
which is to add change ticks to the `UnsafeEntityCell`

## Testing

- Added a unit test that is close to what users would encounter: before
this PR the `Added`/`Changed` filters on `Ref`s created from `EntityRef`
are incorrect.
2025-05-07 18:19:35 +00:00
Zachary Harrold
63e78fe489
Deprecated Begone! 0.16 Cleanup (#19108)
# Objective

A fair few items were deprecated in 0.16. Let's delete them now that
we're in the 0.17 development cycle!

## Solution

- Deleted items marked deprecated in 0.16.

## Testing

- CI

---

## Notes

I'm making the assumption that _everything_ deprecated in 0.16 should be
removed in 0.17. That may be a false assumption in certain cases. Please
check the items to be removed to see if there are any exceptions we
should keep around for another cycle!
2025-05-07 18:17:41 +00:00