Commit Graph

2912 Commits

Author SHA1 Message Date
Chris Hain d9d6f52ee2 Fix Visibility component having no effect on infinite grid (#24723)
# Objective

The custom render phase for infinite grid did not clear invisible or
despawned meshes before rendering, meaning the Visibility component had
no effect on the InfiniteGrid component when it was changed.

## Solution

Added a removal pass in the infinite_grid render queue.

## Testing

'toggle_visibilty' system added to the infinite_grid example.

Co-authored-by: Christopher Hain <8527064+chris-a-h@users.noreply.github.com>
2026-06-23 17:32:24 +00:00
Kristoffer Søholm 097fc03ce5 bevy_text: give swash a stable font id (#24710)
# Objective

Disclaimer: AI was used to find/triage the issue, but I spent quite a
bit of time verifying everything. I am not a text rendering exptert
though.

While investigating the performance regression fixed in
https://github.com/bevyengine/bevy/pull/24663 in my own project, I
stumbled upon another one related to caching and font hinting.

As mentioned in
https://docs.rs/swash/latest/swash/struct.FontRef.html#owning-your-fonts,
using the `FontRef` constructors implicitly generates new `CacheKey`
instances, which breaks the internal caching layer. Using the scale
builder without giving an id does this internally, which is a bit of a
footgun. I believe `cosmic_text` handled this before, and that this is a
regression from the move to `parley`.

When running `many_text2d --hinting` the startup time went from 7s to
500ms. I couldn't get a good tracy screenshot running with `--recompute`
because the fps on main is too low. Note that the measurements are based
on main before #24663.

<img width="745" height="324" alt="screenshot-2026-06-22-165610"
src="https://github.com/user-attachments/assets/62881ddb-84eb-4b20-b26e-8d305c3bb99a"
/>
<img width="634" height="527" alt="screenshot-2026-06-22-165624"
src="https://github.com/user-attachments/assets/96a38ef4-d51a-4c5e-a518-2596b212e1f6"
/>

## Solution

Give the builder a stable font id. Someone should confirm if this is
indeed a valid ID to give to swash, or if I forgot to take some
feature(s) into account.

I also added a `hinting` flag to `many_text2d` that I used for testing,
seems useful to keep.

## Testing

Ran `many_text2d`, saw better performance and that the text looked
similar.
2026-06-23 03:30:04 +00:00
JMS55 fa0d6101f5 Solari: Add DLSS-RR toggle to example (#24667)
# Objective
- Make it easier to switch between denoised and non-denoised mode in the
solari example for development purposes

## Solution

- Add a toggle
2026-06-22 19:07:18 +00:00
Talin 4b0579b18d Add scrubbing / dragging to number_input widget. (#24636)
# Objective

Part of #19236 

This PR is a near-total rewrite of the feathers number input widget.
This version adds the ability to edit the value by dragging,
behaviorally similar to the widgets in Blender.

## Features

* Click to edit textually
* Drag to adjust
* Adaptive drag speed heuristic
* Conditional slider bar (only appears if soft limits are specified)
* Soft and hard limits (ref. [Blender
documentation](https://docs.blender.org/manual/en/latest/interface/controls/buttons/fields.html#number-fields))
* Precision and step options
* Cursor shape changing
* Support for different number formats: f32, f64, i32, i64

## Backwards compatibility

The method for programmatically updating the edited value has changed to
be more consistent with other widgets - instead of sending an event, you
now insert a `NumberInputValue` component with the new value.

## Testing

- extensive manual testing via a new example, `feathers_number_input`.

## Additional Information

Things left to do:

* Visible increment / decrement arrows (only for fields with no soft
limit)
* Support for unit conversions and units display (meters, centimeters,
degrees, etc.)
* The theme colors are not final; there's some debate about whether we
will need to implement multiple thematic variations of this widget in
order to maintain sufficient contrast against different backgrounds.
* Accessibility support needs work.
* The example has some placeholder labels that we supposed to mirror the
input value, but that has not been finished.
* Does not enable drag capturing in CursorOption because bevy_picking
doesn't work with captured pointers.

Note: because of the complexity of this widget, it does not use the
"slider" headless widget, and instead is based on the `EditableText`
component, with slider-like behaviors layered on top.

Also, this widget pretty much subsumes all of the functionality of the
feathers slider, making the latter unnecessary. The only advantage of
`FeathersSlider` is that, since it only supports `f32`, it has a simpler
API.

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-06-21 21:18:58 +00:00
ickshonpe 5baf00085d Text performance regression fix (#24663)
# Objective

Text layout updates take much longer than in 0.18.

## Solution

`update_text_layout_info` was building a new Swash `Scaler` for every
run.

Instead, only build a new `Scaler` when it is needed to rasterize new
glyphs.

Also added a `clear` method to `FontAtlasSets`. This is used by the
`many_text` example with the `--clear-font-atlases` arg to bench glyph
rasterization.

## Testing

Includes a new text benchmark `many_text`:

```
cargo run --example many_text --release
```

On my computer on main it reports ~35fps, with this branch ~130fps.
2026-06-21 19:44:14 +00:00
ickshonpe 8ce450bd98 Another text measurement fix (#24669)
# Objective

Text is wrapped to fit inside the node's content box but the node is
sized as though the text isn't wrapped.

Fixes #24664

## Solution

Subtract the total of the horizontal padding and border insets.

## Testing

Added the replication from #24664 to `testbed_ui`'s `TextWrap` scene:
```
cargo run --example testbed_ui -- textwrap
```

<img width="500" alt="image"
src="https://github.com/user-attachments/assets/e37884d1-7ae6-4aab-b16f-c5af004f5556"
/>

---

The other examples, particularly `text_debug`, shouldn't demonstrate any
changes.

---------

Co-authored-by: Dimitrios Loukadakis <dloukadakis@users.noreply.github.com>
2026-06-21 07:30:04 +00:00
Dan Aloni 7496e1b639 light: add SunDisk::MARS preset for Mars atmosphere (#24618)
In the atmosphere example we can change between Earth and Mars, but the
size of the sun does not change. This somewhat bothered me from an
astronomical accuarcy.

This commit introduces a new `SunDisk::MARS` constant to accurately
represent the sun’s apparent size when viewed from Mars. The
implementation updates the documentation and adds the corresponding
constant with an angular size of ~21 arcminutes (0.00615 radians).

Key modifications:

- Added `SunDisk::MARS` constant in `directional_light.rs`
- Updated documentation to reference the new Mars preset
- Modified `atmosphere` example to switch sun disk alongside atmosphere
presets

I tested this manually.

---------

Co-authored-by: Máté Homolya <mate.homolya@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-06-17 17:46:34 +00:00
Jeb Brooks ea06f80230 Optionally allow FeathersColorSwatch to partially display opaque value (#24639)
This adds properties to the `FeathersColorSwatch` SceneComponent to
allow specifying a percentage of the swatch to remain opaque. This is
useful for color-pickers and generally handling colors with alpha
channels.

The property value will default to 0% so no migration guide is needed.

# Objective

- Allow a single `FeathersColorSwatch` to display the selected color
with and without its alpha channel.

## Solution

- Adds `FeathersColorSwatchProps` to allow dedicating a percentage of
the swatch area to the opaque color value

## Testing

Updated the `feathers_gallery` example to display the `rgba` color
swatch with 30% dedicated to the opaque color.

---

## Showcase

<img width="1280" height="720" alt="Screenshot_2026-06-15_21-09-53"
src="https://github.com/user-attachments/assets/1b3405f5-973b-42fb-abd5-b08c39c59cb6"
/>
2026-06-17 05:18:25 +00:00
Luo Zhihao 0d00c9109f Fix nightly clippy and clippy::result_large_err again (#24624)
# Objective

#24206 boxes the large error in `GltfError` but it's not sufficient
after https://github.com/rust-lang/rust-clippy/issues/17070 is fixed.

## Solution

Box `AssetLoadError::RequestedHandleTypeMismatch` so that it is reduced
to 120 bytes which is below 128 bytes.

Also fix some other trivial clippy warnings.

## Testing

Use the latest nightly clippy which has
https://github.com/rust-lang/rust-clippy/issues/17070 fixed:
```
cargo +nightly clippy --workspace --all-features --all-targets -- -D warnings
```
2026-06-17 04:40:59 +00:00
Carter Anderson a3fa0c2c8f Rename Preferences to Settings in the appropriate places (#24613)
# Objective

`bevy_settings` currently conflates "settings" and "preferences" in a
number of places. The name of the framework itself is Bevy Settings, so
anything that drives general "settings" behaviors should use "settings"
terminology. For example, `PreferencesPlugin` should be `SettingsPlugin`
because it handles _all_ `SettingsGroup` types (regardless of their
"scope" such as "preferences.toml").

## Solution

Use "settings" instead of "preferences" in the appropriate places. I've
also removed the custom `ExitAfterSave` commands in the examples as they
are unnecessary.

This should land in 0.19 because we haven't published this API yet and
getting naming right is important.

---------

Co-authored-by: Dave Waggoner <waggoner.dave@gmail.com>
Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-06-17 04:28:56 +00:00
ickshonpe 736d2b0a9e multiline_text_input example pop up justify menu (#24584)
# Objective

Add a way to change the justification for the text input in the
multiline_text_input example.

## Solution

Add a pop up menu that lets you set justify.
2026-06-11 03:36:18 +00:00
ickshonpe e52d2c5c53 Justify the inputs in the multiple_text_inputs example (#24583)
# Objective

Make the `multiple_text_inputs` example a bit more useful by giving each
text input a different justification, which should help with debugging
cursor behaviour.

## Solution

Add an input for each `Justify` variant along with a column on the left
labelling the justification it is using.

## Showcase

<img width="1798" height="750" alt="inputs-justified"
src="https://github.com/user-attachments/assets/324c1cd4-b6a1-4c0f-ad1a-38cd28867704"
/>
2026-06-10 17:57:58 +00:00
shunkie fd4f66fc36 Rename variable in custom_loop example (#24578)
# Objective

Rename `app_exit_reader` to `app_exit_writer` for clarity.

Co-authored-by: shunkie <iishunkie@gamil.com>
2026-06-10 03:34:23 +00:00
Greeble 10e9ec77fb Add mesh compression and motion blur to scene viewer (#24570)
## Objective

Allow testing more features in the `scene_viewer` example. 

## Solution

Add mesh compression and motion blur options to the command line.
Ideally the mesh compression would allow control over individual
attributes, but this is enough for basic smoke testing.

```rust
/// enable mesh attribute compression
#[argh(switch)]
mesh_attribute_compression: bool,
/// enable mesh index compression
#[argh(switch)]
mesh_index_compression: bool,
/// enable motion blur
#[argh(switch)]
motion_blur: bool,
/// set the motion blur shutter angle
#[argh(option)]
motion_blur_shutter_angle: Option<f32>,
```

## Testing

```sh
# Mesh compression
cargo run --example scene_viewer --features "free_camera bevy_dev_tools" -- --mesh-attribute-compression --mesh-index-compression

# Motion blur
cargo run --example scene_viewer --features "free_camera bevy_dev_tools" -- "assets//models/animated/Fox.glb" --motion-blur --motion-blur-shutter-angle 10
```
2026-06-09 20:13:14 +00:00
Azural Champagne 6561ee9d46 Replace MouseScrollUnit::SCROLL_UNIT_CONVERSION_FACTOR with a Resource (#24512)
# Objective

Fixes #24508

## Solution

Replace `MouseScrollUnit` with a Resource of the same name and remove it
from the structs and events related to scrolling. More work still needs
to be done to make sure that the value in `MouseScrollUnit` is actually
respected

## Testing

- Running standard test suite/ci as well as related examples to make
sure that they haven't broken
2026-06-09 04:48:31 +00:00
Talin 6588a8e7ef Modal dialog box for feathers (#24559)
# Objective

Part of #19236 

## Solution

Modal Dialog boxes

## Testing

Manual testing in feathers gallery

## Showcase

<img width="386" height="210" alt="feathers_dialog"
src="https://github.com/user-attachments/assets/9759db07-e1f6-4497-bc73-c8bb05798b1d"
/>
2026-06-09 00:51:04 +00:00
Gino Valente 468acae854 bevy_reflect: Register type data by path in reflect macro attribute (#24551)
# Objective

Currently, type data needs to be in-scope when using
`#[reflect(SomeType)]`. This can be mildly annoying when reflection is
behind a feature since you need to duplicate the check at both the
import and the usage:

```rust
#[cfg(feature = "reflection")]
use bevy_reflect::Reflect;
#[cfg(feature = "reflection")]
use crate::reflect::ReflectSomeType;

#[cfg_attr(feature = "reflection", derive(Reflect), reflect(SomeType))]
struct MyType;
```

You may also notice that it can be somewhat confusing that we import
`ReflectSomeType` but write `reflect(SomeType)`. This is unfortunately
due to a limitation in Rust, but it would be nice if users had the
option at least of writing `reflect(ReflectSomeType)`—if only for
consistency.

## Solution

This PR enables registering type data via path rather than just
identifier.

```rust
#[cfg(feature = "reflection")]
use bevy_reflect::Reflect;

#[cfg_attr(feature = "reflection", derive(Reflect), reflect(crate::reflect::SomeType))]
struct MyType;
```

Additionally, type data can now also be given by their
`Reflect`-prefixed name.

```rust
// Will register `super::reflect::ReflectSomeData` for `MyType`
#[derive(Reflect)]
#[reflect(super::reflect::SomeData)]
struct MyType;

// Will register `super::reflect::ReflectSomeData` for `MyOtherType`
#[derive(Reflect)]
#[reflect(super::reflect::ReflectSomeData)]
struct MyOtherType;
```

## Testing

I added a unit test to ensure things compile correctly and both register
the same data.

---

## Showcase

Registering type data via the reflection derive macro can now be done by
path:

```rust
#[derive(Reflect)]
// Will register `crate::equipment::ReflectEquippable` for `Sword`
#[reflect(crate::equipment::Equippable)]
struct Sword(i32);
```

Additionally, you may optionally used the `Reflect`-prefixed type name
that the macro normally generates automatically:

```rust
#[derive(Reflect)]
// Will still register `crate::equipment::ReflectEquippable` for `Sword`
#[reflect(crate::equipment::ReflectEquippable)]
struct Sword(i32);
```
2026-06-09 00:39:17 +00:00
Griffin 77aa53b74e Fix large scene mip map generator material change detection trigger (#24532)
https://github.com/bevyengine/bevy/pull/22460 broke the material change
detection trigger in the large scenes mip map generator plugin.

## Testing

Ran the test_image example in mipmap_generator and the bistro scene and
textures with mip maps were shown as expected after this fix.
2026-06-09 00:31:09 +00:00
Visse 6f270d4776 Expose pipeline constants to materials (#24502)
# Objective

Allow materials to use pipeline constants ([pipeline-overridable
constants](https://www.w3.org/TR/WGSL/#override-decls)).
They are already available in wgpu, but bevy didn't expose them.

## Solution

Expose constants in `RenderPipelineDescriptor` &
`ComputePipelineDescriptor`, allowing materials to specify them in their
specilize function.

**Note:** I had to remove the `Eq` derive from
`ComputePipelineDescriptor`, `VertexState` and `FragmentState`, due to
the new f64 field. It was already a bit inconsistent with
`RenderPipelineDescriptor` not having it.

## Testing
- Ran `cargo check`
- Created an example & ran it
- Couldn't run `cargo test` due to it taking looots of disk space to
run, but I have a hard time seeing it break something at runtime

## Showcase

See the added example, where pipeline constants are used to change the
`LEVELS` override in WGSL.
<img width="760" height="289" alt="Screenshot from 2026-05-31 09-46-05"
src="https://github.com/user-attachments/assets/6902757c-aea4-4b91-9ff0-e653ce4c3448"
/>
2026-06-09 00:06:01 +00:00
Talin 9a35b6a237 Feathers scrollbar and list view. (#24092)
# Objective

Part of #19236 

## Solution

Implementation of scrollbars and list views for Feathers.

## Testing

Manual testing:
* click to select
* wheel scrolling
* tab and keyboard navigation

## Showcase

<img width="380" height="182" alt="listbox"
src="https://github.com/user-attachments/assets/d3f902cd-0c73-475f-806b-d6ccb5ea3cac"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-06-07 02:10:38 +00:00
Jay f7f50d1a75 Fix IME text input wrapping (#23932) (#24421)
The IME support example configures its editable text field as a
single visible input, but the text layout still used default soft
wrapping. When the cursor moved through long text, wrapped visual lines
could appear as disconnected text segments.

Set the example input to use `TextLayout::no_wrap()`, matching the
other single-line text input examples while still allowing explicit
newlines.

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

```sh
cargo check --example ime_support --features system_font_discovery
```
2026-06-06 18:29:22 +00:00
Elabajaba b2b7b452c3 Rename the PbrNeutral tonemapper to KhronosPbrNeutral and improve the docs. (#24530)
# Objective

`PbrNeutral` is poorly named as it implies it's a good default neutral
tonemapper when it really isn't. The docs also don't really describe how
it looks visually unlike the doc comments on the other tonemappers.

## Solution

Rename `PbrNeutral` to `KhronosPbrNeutral` to make it more clear that
it's specifically the Khronos Pbr Neutral tonemapper and not a generic
neutral pbr tonemapper, and improve the docs to better describe it and
essentially recommend against it.
2026-06-05 19:40:06 +00:00
Aceeri ab14619d19 Add some whitespace to custom_phase_item docs (#24529)
# Objective
Tried reading the custom_phase_item docs and it took me a solid 10s to
figure out what it was saying. I think the monospace-ness + no
whitespace + em dash just tripped me up

## Solution
Just add whitespace around it.

## Testing
Eyeballs perceived the subpixel rendered font and gave more dopamine
with a lack of subpixels between characters.
2026-06-04 14:46:46 +00:00
ickshonpe 457b91808a More consistant Font asset resolution and change detection (#24362)
# Objective

- When `FontSource` resolution fails because an asset isn't yet loaded,
it doesn't attempt to reresolve the `FontSource` again the next frame.
- When a `Font` asset is removed, its font data is not unloaded from
Parley's font database
- The results from font lookups can be inconsistant when using `Handle`s
to identify a font.

Fixes #24356

## Solution

* In `load_font_assets_into_font_collection`, register each font twice,
once with an internal asset-specific alias for handle lookups and once
using its embedded family name.
* Use `set_changed` on `TextFont` to trigger chain detection, instead of
the `needs_rerender` flag on `TextBlock`. Schedule
`load_font_assets_into_collection` to run before
`detect_text_needs_rerender`, otherwise this would delay updates for a
frame.
* Store the changed family ids and asset paths, and set any `TextFont`s
that refer to them as changed.
* Don't update the measure funcs in `update_editable_text_content_size`
on font asset changes. Instead rely on the narrower `TextFont` change
detection, which is sufficient now because
`load_font_assets_into_font_collection` marks affected `TextFont`
components as changed when newly loaded font assets can affect font
resolution.
* Removed the mutable deref of `EditableText` at the start of
`update_editable_text_styles`. The editor is only mutable accessed if
updates to the styles need to be made.
* On unloading a font rebuild the whole font database, minus the
unloaded fonts, remap any generic families and relayout all text.
* Keep a copy of the registered generic families in `FontCx`, so they
can be remapped after unloading a font.

## Testing

```rust
use bevy::{
    feathers::{controls::FeathersNumberInput, FeathersPlugins},
    prelude::*,
};

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, FeathersPlugins))
        .add_systems(Startup, setup)
        .add_systems(Update, spawn_number_input)
        .run();
}

fn setup(mut commands: Commands) {
    // ui camera
    commands.spawn(Camera2d);
}

fn spawn_number_input(mut commands: Commands, mut is_spawned: Local<bool>) {
    if *is_spawned {
        return;
    }
    *is_spawned = true;
    commands.spawn_scene(bsn! {
        Node {
            margin: UiRect::all(auto())
        }
        Outline
        Children [
        :FeathersNumberInput Node { width: px(200) }
        ]
    });
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-06-04 04:55:04 +00:00
Carter Anderson c516bd8f48 bsn: support inline macros in field value position (#24524)
# Objective

`bsn!` currently requires surrounding macros in "field value position"
with `{}`:
```rust
bsn! {
  Foo { value: {vec![ 100, 200 ]} }
}
```
This is annoying!

## Solution

Support macros in field-value-position:

```rust
bsn! {
  Foo { value: vec![ 100, 200 ] }
}
```

## Testing

- Added a test that checks that this works
- Ported bsn! examples to use this
2026-06-04 00:28:58 +00:00
Luo Zhihao 7517c61ecd Add options to lower precision/compressed vertex buffer (#21926)
# Objective

Resolves #21902.

## Solution

This PR adopts a relatively transparent approach to reduce the GPU
vertex buffer size. On CPU-side mesh can still use uncompressed Float32
data, and users are not required to insert compressed vertex formats.
The vertex data is automatically processed into
lower-precision/octahedral encoded data when uploading to the GPU.

To enable vertex attribute compression, just set the
`attribute_compression` field of Mesh, or set
`mesh_attribute_compression` of GltfLoaderSettings. If enabled, normal
and tangent will be octahedral encoded Unorm16x2, uv0, uv1, joint weight
and color will be corresponding Unorm16 or Float16. I also provide
Unorm8x4 for vertex color if hdr isn't needed.

Update 2026-2-16

Removed previous approach that automatically compresses vertex buffer
according to flags when uploading to GPU. Instead, I added
`compressed_mesh` method to Mesh to construct compressed Mesh ahead of
time. GltfLoader can also opt-in mesh compressing when loading. I also
add an option to convert indices to u16, though I believe blender gltf
exporter already uses u16 indices when possible.


## Testing

Run `many_cubes`, `many_foxes`, `many_morph_targets` with
`--vertex-compression` to test 3d.
Run `bevymark` with `sprite_mesh` to test 2d, because `SpriteMesh` uses
compressed quad mesh now.

---------

Co-authored-by: Greeble <166992735+greeble-dev@users.noreply.github.com>
2026-06-02 03:22:56 +00:00
Ed Swartz ead9883d5d Account for MouseScrollUnit in projection_zoom example. (#24457)
# Objective

- Fix the feel of the `projection_zoom` example on macOS using a
trackpad. Otherwise the zoom is ~100x faster than when using a mouse
wheel.
- No bug logged.

## Solution

- Copied logic from from the `free_camera` / `pan_camera` modules to use
the conversion to `MouseScrollWheel::SCROLL_UNIT_CONVERSION_FACTOR` when
the accumulated mouse wheel input came from `MouseScrollUnit::Lines`
rather than `MouseScrollUnit::Pixels`.

## Testing

- Tested on Linux and macOS using a mouse and trackpad.
2026-06-02 01:01:24 +00:00
DavidCrossman 7c77ecd576 Fix documentation typos (#24446)
# Objective

Fix typos and other small issues in the documentation. I can drop the
changes to `bevy_reflect`'s and `bevy_anti_alias`'s crate descriptions
if it's a problem.
2026-06-02 00:52:42 +00:00
Mira 18d106d26a Pass panics to the fallback error handler (#24240)
# Objective

Currently, a panic (whether from engine or user code, as there is little
distinction) takes down the entire app with it. Instead the user should
be able to decide how the error is handled. This is currently not
possible except by writing your own executor and setting it for all
relevant schedules.

See for comparison Godot's policy on exceptions:

> ### [Why does Godot not use
exceptions?](https://docs.godotengine.org/en/stable/about/faq.html#why-does-godot-not-use-exceptions)
> 
> We believe games should not crash, no matter what. If an unexpected
situation happens, Godot > will print an error (which can be traced even
to script), but then it will try to recover as > gracefully as possible
and keep going.

Unity will also log an error and then continue if user code throws an
exception. I believe Unreal does too for exceptions coming from
Blueprints. Similarly, many web servers will respond with an error to a
request that threw an exception, but will not crash the server itself.

This PR does not enable this behavior by default, but makes it
user-configurable.

Also fixes #19109
Also (I think) fixes #7434

## Solution

Instead of rethrowing panics, hand them to the `FallbackErrorHandler`.

If the panic was thrown by an error handler in the first place, we don't
need to pass it back to a handler again. I've added a way for the error
handler to signal that it's the source of the panic.

The constructed error is created without a backtrace, as the default
panic handler already prints it when instructed to via
`RUST_LIB_BACKTRACE`/`RUST_BACKTRACE`.

Panics will not be turned into errors on `no_std` projects.

Potential work for a future PR:
- if a error handler has been specified with e.g. `queue_handled`, use
this error handler instead of the fallback error handler
- if a command panics, still apply the remaining commands in the buffer?

## Testing

See added `panic_to_error` test

---------

Co-authored-by: Gonçalo Rica Pais da Silva <bluefinger@gmail.com>
2026-06-01 19:35:45 +00:00
laund 9ed66d7a06 bsn: throw error when using caching syntax on unsupported scene entries (#24473)
# Objective

Implement changes discussed with cart around erroring when using caching
syntax where its not implemented.


## Solution

Throw a compile error, in a way which is easy to remove once caching
exists/works for more cases.

Also contains a commit to alleviate trait errors which will (from my
experience writing this PR and fixing them in bevy) arise from fixing
this for existing bsn code. This commit can be dropped if not desired.
This would ideally be fixed upstream so this workaround can be removed:
https://github.com/rust-lang/rust/issues/141258#issuecomment-4565897810

Note: The error caused by this workaround is far from ideal. It
initially looks like a method call is missing, but ultimately the
hint/advice *is* correct
<img width="1982" height="477" alt="image"
src="https://github.com/user-attachments/assets/879f7630-ada8-4e63-9c59-80be466f37cf"
/>


## Testing

- `cargo test -p bevy_scene --lib`
- `cargo check`

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-29 23:07:39 +00:00
Kristoffer Søholm adc18d7fb5 Rename SortedRenderPhase add to add_retained (#24404)
# Objective

In #22966 the semantics of the `add` method on `SortedRenderPhase` was
changed from the items being cleared at the end of the frame, to items
being retained until they are removed. A new `add_transient` method was
added with the old functionality, but this is a big migration hazard
because it's a major semantic change that doesn't give any compiler
errors or warnings.

I discovered this after updating `bevy_vector_shapes` to the RC and
seeing drawings not being cleared properly.

## Solution

Rename `add` to `add_retained` both for clarity and to make old uses not
compile, so the affected users will know to look in the migration guide.

A sentence about this should be added to the migration guide if/when
this is backported to the 0.19 release branch.

## Testing

It compiles (hopefully).
2026-05-28 20:50:16 +00:00
Greeble 3cc7161f5f Deprecate AssetId::invalid() (#24392)
## Objective

Progress #19024 (removing UUID handles). Even if UUID handles end up
sticking around, there's an argument for deprecating
`AssetId::invalid()` in the name of simplicity and robustness.

## Solution

Remove the last remaining case of `AssetId::invalid()` in the
`custom_phase_item` example. The example only used it as a placeholder
value, so `AssetId::default()` is fine.

```diff
 Opaque3dBinKey {
-    asset_id: AssetId::<Mesh>::invalid().untyped(),
+    asset_id: AssetId::<Mesh>::default().untyped(),
 }
```

## Testing

```sh
cargo run --example custom_phase_item
```
2026-05-23 15:20:34 +00:00
IceSentry 654bcde0ed Add merge_all_mesh_3d to world_asset_helpers (#23710)
# Objective

- bevy_city needed a way to merge all the `Mesh3d` from a `WorldAsset`.
Instead of keeping that function hidden inside bevy_city we can make it
public

## Solution

- Add `world_asset_helpers` to `bevy_dev_tools`. It's in
`bevy_dev_tools` because it depends on multiple different parts of bevy
and that's the only crate that users can use that already depends on a
lot of things.
- Add `marge_all_mesh_3d()` to `world_asset_helpers`
- Update bevy_city to use that helper

## Testing

- I ran bevy_city and the meshes were merged like they should

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-22 15:03:18 +00:00
Doonv 3f401d1507 Update examples to use Image::new_target_texture instead of manual image creation when possible (#23715)
# Objective

Fix #19101. (Kinda, this is not the exact solution proposed in that
issue, but it still shortens most of the examples)

## Solution

Most of the images created in examples are for use in render targets.
`Image::new_target_texture` is made for exactly that and significantly
shortens the image creation process.

## Testing

I tested all the examples I changed and they seem to work fine.

--- 

btw for some reason most of the examples use
`TextureFormat::Bgra8UnormSrgb` while the documentation for
`Image::new_target_texture` recommends `TextureFormat::Rgba8UnormSrgb`
for SDR images. What's up with that?

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-22 14:33:16 +00:00
bytemuck 055f0f51af Added register_boxed_system to Commands. (#24213)
# Objective

Fixes #24017 

## Solution

Added `register_boxed_system` to `Commands`.

## Testing

- Modified `callbacks` example to show our new `register_boxed_system`
method.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2026-05-22 14:21:58 +00:00
charlotte 🌸 d1b1980733 Add ReadbackOnce component to help one-shot readbacks. (#23845)
Users are sometimes confused about the fact that the `Readback`
component will fire multiple observers (once per every frame it exists
in the main world). This new `ReadbackOnce` component helps a bit with
the ux of spawning a readback that only fires once.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-22 13:41:31 +00:00
Rostyslav Toch 98639670f5 Add many_meshlet_materials stress test example (#23792)
# Objective

- Introduce a dedicated example to measure performance overhead when
dealing with a high number of meshlet instances and unique materials.

## Solution

- Added a new example `many_meshlet_materials` that spawns a
configurable grid of meshlet bunnies.

## Testing

- `SystemInfo { os: "Linux (CachyOS Linux rolling)", kernel:
"6.19.10-1-cachyos", cpu: "AMD Ryzen 7 5800H with Radeon Graphics",
core_count: "8", memory: "15.0 GiB" }`
- `AdapterInfo { name: "AMD Radeon Graphics (RADV RENOIR)", vendor:
4098, device: 5688, device_type: IntegratedGpu, device_pci_bus_id:
"0000:03:00.0", driver: "radv", driver_info: "Mesa 26.0.3-arch2.2",
backend: Vulkan, subgroup_min_size: 64, subgroup_max_size: 64,
transient_saves_memory: false }`
- `cargo run --features=meshlet,https --release --example
many_meshlet_materials`

---

## Showcase

Example works perfectly with 5x5 grid.

<img width="1024" height="599" alt="image"
src="https://github.com/user-attachments/assets/948b42b7-e88e-4a91-9fb7-f1c1b4d27e32"
/>

The issue begins when grid count increases to 10x10. Meshes start
flickering.

<img width="1024" height="598" alt="image"
src="https://github.com/user-attachments/assets/055df47f-39dc-41bc-be05-1978ec352e3a"
/>

With 50x50 meshes, the whole screen flickers.

<img width="1024" height="595" alt="image"
src="https://github.com/user-attachments/assets/7d685a2b-7389-43fe-b04e-a5987136f459"
/>

When running with unique materials, performance significantly drops on
my hardware.

<img width="2224" height="1298" alt="image"
src="https://github.com/user-attachments/assets/8d5b4677-7851-4234-9467-992f8db62a9d"
/>

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2026-05-22 12:13:26 +00:00
ickshonpe dbfa384182 Only select all on input focus with SelectAllOnFocus (#24278)
# Objective

Only select all on focus with `SelectAllOnFocus`. 
It should be possible to have single line inputs without automatic
select all on focus.

## Solution

Remove the automatic select all on focus for single line inputs from
`on_focus_select_all`.
2026-05-22 10:40:46 +00:00
laund 5897ed605b BSN: changing prefixes for Template and SceneComponent to allow removing confusing "inheritance" concept (#24367)
# Objective

Changes discussed with cart:
- `:` will not be called "inheritance" anymore, but instead "cacheable"
(name not final)
- the Template patching prefix changes `@` -> `~`
- the SceneComponent prefix changes `:` -> `@`
- the `:` prefix is allowed in front of `@SceneComponent` as well,
marking it as being cached

>> me: do we forbid caching of functions which take an argument?

> cart: We should forbid it until we support it, and I don't plan on
supporting this in the short term, as it adds new controversial design
aspects to the system (building a mapping from parameters to cached
scenes, ensuring the parameters are all hashable, etc).

Link to the discord thread, specifically my [recap
message](https://discord.com/channels/691052431525675048/1264881140007702558/1506422311056576702).

The exact reasoning is in the linked discord discussion, but the tldr
is:
"Inheritance" as a term for the ":" syntax didn't really fit what bsn
was doing, since scenes without `:` produce the same result. All `:` is,
is a way to say "cache this pls" with the design of bsn imposing the
limitation that only the first scene can be cached

That was all fine, except for one case: Disambiguating SceneComponents
from normal components. So if we redefine `:` to just mean "caching" we
needed to untangle it from SceneComponents. That means disambiguating
SceneComponents needed a different syntax, and the decision ended up
being to take the @ prefix from the *much* less common `@Template`
usecase, since `SceneComponent {@prop: val}` already used @ as well and
introduce a new prefix to replace `@Template` instead, replacing it with
`~Template`.

## Solution

Implement these changes in macros.

Notably, this *still* doesn't implement/enable caching right now.  

Most docs are updated, except for the big blocks in
`bevy_scene/src/lib.rs` and `bevy_scene/macros/src/lib.rs` since i've
been working on reworking those on another branch and didn't want to
duplicate whats already been a lot of work and likely to be a bunch more

## Testing

- [x] `bevy_scene` tests passing
- [x] `cargo check --workspace` and `cargo check --workspace --examples`
passing

Since this PR does not yet enable caching, I think passing the current
tests should be enough.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2026-05-21 15:37:35 +00:00
Christophe Dehais 5ec83e1185 Improve Order Independent Transparency example (#22781)
# Objectives

- Use a cleaner UI inspired by other examples
- Add a scene with custom material to fix #20297 

## Testing

Running the example
 ## Showcase 
<details>
<summary>Click to view showcase</summary>
<img width="872" height="732" alt="Screenshot From 2026-02-06 11-35-19"
src="https://github.com/user-attachments/assets/cc294c33-bb53-4ed4-9dce-7558f3bb8fee"
/>
<img width="872" height="732" alt="Screenshot From 2026-02-06 11-35-30"
src="https://github.com/user-attachments/assets/c2b79651-c99e-4bcc-8089-518d11631b9f"
/>
</details>

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-21 15:13:25 +00:00
Luo Zhihao d5a0cf4f1e Change ShaderDefVal to use Cow<'static, str> (#24209)
# Objective

Fixes #24036

## Solution

Replace String with Cow<'static, str> in ShaderDefVal.

## Testing

CI
2026-05-21 14:34:41 +00:00
Schmarni 2c3bdfdd25 Implement Premultiplied Alpha for OIT (#22821)
# Objective

- Allow rendering objects with `AlphaMode::Premultiplied` and
`AlphaMode::Add` while using Order Independent Transparency.
- Fixes #20373.

## Solution

- Store Premultiplied color in the OIT buffer and premultiply in the
case of `AlphaMode::Blend`, this shouldn't have any downsides since
blending was done with premultiplied alpha anyway.
- It might be useful to actively break the `oit_draw` signature by
adding a `premultiply` bool to ensure that shader authors are aware of
the changed meaning of the `color` argument.

## Testing

- These changes have been tested by running the modified
`order_independent_transparency` example, an older version of these
changes has been in use in a project i work on.

---

## Showcase

Here the Red Sphere uses `AlphaMode::Blend`, the Blue Sphere
`AlphaMode::Add` and the Green Sphere `AlphaMode::Premultiplied`.

<img width="1270" height="708" alt="bevy-oit-example"
src="https://github.com/user-attachments/assets/282d7083-458f-4ecd-b098-20b3539de796"
/>

---------

Signed-off-by: Schmarni <marnistromer@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-21 14:01:32 +00:00
GHowe 2837e0372d Expose ssao radius (#24267)
Expose the SSAO sampling radius as a public configuration option on
  ScreenSpaceAmbientOcclusion.

Right now Bevy exposes SSAO quality and constant object thickness, but
the effect
radius is still hardcoded internally in the SSAO shader. That makes it
impossible for
  users to tune the size of the occlusion effect from app code.

  ## Solution

Add a radius: f32 field to ScreenSpaceAmbientOcclusion and preserve
existing behavior
  by defaulting it to the shader’s previous hardcoded value.

To wire that through cleanly, the SSAO render path now uploads a small
SSAO settings
uniform containing both radius and constant_object_thickness, and the
SSAO shader
  reads settings.radius instead of a hardcoded constant.

The SSAO example was also updated to expose the new setting
interactively so the
  feature is discoverable and easy to validate.

  ## Testing

  I tested this by:

  - Running cargo check -p bevy_pbr --quiet
  - Building and running cargo build --example ssao
- Launching target/debug/examples/ssao and verifying the example starts
successfully
- Verifying that the new radius control can be adjusted interactively in
the example
    with Left / Right

  Parts that could use more testing:

  - Visual validation across a wider range of scenes and camera scales
  - Broader GPU/platform coverage, since I only tested locally

  How reviewers can test this:

  1. Run cargo build --example ssao
  2. Launch target/debug/examples/ssao
  3. Use Left / Right to decrease/increase SSAO radius
4. Confirm that larger values produce broader occlusion while the
default matches
     existing behavior

  Platform tested:

  - Linux (EndeavourOS)

  Platforms not tested:

  - Windows
  - macOS
  - Web targets
2026-05-21 12:50:06 +00:00
ickshonpe 6dca76afcf FixedNode (#24323)
# Objective

Allow UI elements to be positioned relative to the viewport rather than
their parent element.

Fixes #9564

## Solution

- New UI marker component `FixedNode`. Requires `Node` and
`OverrideClip`.
- `FixedNode` entities are treated as UI roots in layout, even if they
have a parent.
- `FixedNode`s don't inherit their parent's layout, clipping or
transform context.
- During the taffy layout updates children with `FixedNode` are skipped.
- Added a couple of basic helper functions to `UiSurface`, mainly there
to make the tests a little less painful.
- Added a fairly comprehensive range of new tests, including tests with
`GhostNode`s.
- In the Taffy layout (stored in `UiSurface`) there is nothing to
distinguish `FixedNode`s and root nodes, so they are treated identically
during updates.

--

The original suggestion was to implement it as a `PositionType::Fixed`
variant that could used with `Node`, but I think that would be much more
complicated without support from Taffy. Being able to just directly
query for and filter out `FixedNode` entities directly makes the
implementation much simpler and more efficient.

## Testing

Basic example which shows events bubbling up to the parent from the
fixed node:

```
cargo run --example fixed_node
```

There are also a number of new tests in the `layout` module.

```
cargo test -p bevy_ui --lib --features ghost_nodes
```

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2026-05-21 11:08:44 +00:00
Ethan Uppal b556c9d6d5 Fix rounding in the pixel_grid_snap example (#24358)
# Objective

Fixes #24350 

## Solution

I replaced `round` with `floor` as mentioned in the issue.

## Testing

- Did you test these changes? If so, how?

I ran the program on my computer and observed the change.

- Are there any parts that need more testing?

Perhaps other display sizes need testing, but theoretically the math
should be correct. This is my first PR, so I might have missed
something.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

Compare the clipping on window sizes that are a multiple of the canvas's
resolution to those that are not.

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

I tested on macOS; I cannot test on any other platform.

---

## Showcase

<details>
  <summary>Click to view showcase</summary>

<img width="1728" height="1117" alt="Screenshot 2026-05-19 at 3 14
25 AM"
src="https://github.com/user-attachments/assets/1da0b3f1-1f04-4dbe-bbb2-a14a237ff1a7"
/>
<img width="1728" height="1117" alt="Screenshot 2026-05-19 at 12 50
52 AM"
src="https://github.com/user-attachments/assets/a8fc835e-7b32-49ad-916b-a55c4be1d38f"
/>

</details>

Signed-off-by: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com>
2026-05-21 11:07:47 +00:00
KategoryBee c046ff2816 Fix switching between earth/mars in atmosphere example (#24349)
# Objective

The keys for switching between earth and mars atmospheres in the
atmosphere example currently do nothing. This change restores the
functionality.

I'm guessing the issue is from the Atmosphere component changing from
using `Transform` to `GlobalTransform` directly in
`Atmosphere::set_default_transform`. The example is expecting to iterate
over a `Transform`, never finds one, and thus never changes the
atmosphere.

## Solution

Change the example to modify `GlobalTransform` instead of `Transform`. 

It may be preferable to modify the example to insert a `Transform` in
set-up. Let me know if this is the case and i'll update the PR.

## Testing

- Tested by running the atmosphere example, hitting the 3 and 4 keys and
seeing sufficiently earth and mars like atmospheres, as well as messages
in the console.
2026-05-21 10:40:10 +00:00
ickshonpe 649586a47d Add an overflow-flip argument to many_buttons (#24244)
# Objective

Add an option enabling clipping on the button nodes in `many_buttons`.

To help identify any performance regressions due to UI clipping changes.

## Solution

Add an option that sets overflow to clip for all the button nodes in
`testbed_ui`.
2026-05-21 10:23:42 +00:00
ickshonpe a382a230a2 multiple_text_input example layout fixes (#24294)
# Objective

These are meant to be single line inputs, but:

<img width="1552" height="954" alt="image"
src="https://github.com/user-attachments/assets/5e7ab2c7-9bb2-46cd-9a42-bca36b933837"
/>

A mess!

## Solution

1. Add `TextLayout::no_wrap()` to each input and their outputs.
2. Add an intermediate node wrapping each output node applying clipping
to hide the overflow.

<img width="1608" height="489" alt="fixed-inputs"
src="https://github.com/user-attachments/assets/22dc436c-e677-4b1f-a569-d3a9c9effc1c"
/>

## Testing

```
cargo run --example multiple_text_inputs  --features="system_clipboard"
```
2026-05-21 10:16:40 +00:00
ickshonpe 7500b6c5aa text_input example clean up (#24297)
# Objective

Clean up the `text_input` example a bit.

## Solution

- Removed some unneeded style constraints.
- Disable newlines, disable wrapping, and set a responsive width for the
inputs.
- Submit on Enter, not Ctrl + Enter.
- Center the example using an auto margin.

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-05-21 10:16:23 +00:00
ickshonpe 7af4723083 ime_support example clean up (#24296)
# Objective

Little bit of clean up for the `ime_support` example.

## Solution

* Use `row_gap` on the parent for spacing instead of setting individual
margins on the children.
* Give the text input node a fixed height and allow newlines.

## Testing

```
cargo run --example ime_support --features="system_font_discovery"
```
2026-05-21 10:13:03 +00:00