Commit Graph

8045 Commits

Author SHA1 Message Date
Greeble
c96949dabe
Improve the animated_mesh example (#17328)
# Objective

Building upon https://github.com/bevyengine/bevy/pull/17191, improve the
`animated_mesh` example by removing code, adding comments, and making
the example more c&p'able.

## Solution

- Split the setup function in two to clarify what the example is
demonstrating.
    - `setup_mesh_and_animation` is the demonstration.
    - `setup_camera_and_environment` just sets up the example app.
- Changed the animation playing to use `AnimationPlayer` directly
instead of creating `AnimationTransitions`.
    - This appears sufficient when only playing a single animation.
- Added a comment pointing users to an example of multiple animations.
- Changed the animation to be the run cycle.
- I think it got accidentally changed to the idle in
[#17191](https://github.com/bevyengine/bevy/pull/17191), so this is
reverting back to the original.
- Note that we can improve it to select the animation by name if
[#16529](https://github.com/bevyengine/bevy/pull/16529) lands.
- Renamed `FOX_PATH` to a more neutral `GLTF_PATH`.
- Updated the example descriptions to mention the fox.
- This adds a little character and hints that the example involves
character animation.
- Removed a seemingly redundant `AnimationGraphHandle` component.
- Removed an unnecessary `clone()`.
- Added various comments.

## Notes

- A draft of this PR was discussed on Discord:
https://discord.com/channels/691052431525675048/1326910663972618302/1326920498663133348
- There was discord discussion on whether a component is "inserted
onto", "inserted into" or "added to" an entity.
- "Added to" is most common in code and docs, and seems best to me. But
it awkwardly differs from the name of `EntityCommands::insert`.
    - This PR prefers "added to".
- I plan to follow up this PR with similar changes to the
`animated_mesh_control` and `animated_mesh_events` examples.
    - But I could roll them into this PR if requested.

## Testing

`cargo run --example animated_mesh`

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 01:10:50 +00:00
ickshonpe
b90329aef5
update_text2d_layout creates new font atlases when the primary window is closed (#7849)
# Objective

Necessary conditions:
* Scale factor != 1
* Text is being displayed with Text2d
* The primary window is closed on a frame where the text or text's
bounds are modified.

Then when `update_text2d_layout` runs, it finds no primary window and
assumes a scale factor of 1.
The previous scale_factor was not equal to 1 and the text pipeline's old
font atlases were created for a non-1 scale factor, so it creates new
font atlases even though the app is closing.

The bug was first identified in #6666

## Minimal Example

```rust
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                present_mode: bevy:🪟:PresentMode::Immediate,
                ..Default::default()
            }),
            ..default()
        }))
        .insert_resource(UiScale { scale: std::f64::consts::PI })
        .add_startup_system(setup)
        .add_system(update)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle::default());
    commands.spawn(Text2dBundle {
        text: Text {
            sections: (0..10).map(|i| TextSection {
                value: i.to_string(),
                style: TextStyle {
                    font: asset_server.load("fonts/FiraSans-Bold.ttf"),
                    font_size: (10 + i) as f32,
                    color: Color::WHITE,
                }
            }).collect(),
            ..Default::default()            
        },
        ..Default::default()
    });
}

fn update(mut text: Query<&mut Text>) {
    for mut text in text.iter_mut() {
        text.set_changed();
    }
}
```
## Output
On closing the window you'll see the warning (if you don't, increase the
number of text sections):
```
WARN bevy_text::glyph_brush: warning[B0005]: Number of font atlases has exceeded the maximum of 16. Performance and memory usage may suffer.
```
The app should only create font atlases on startup, but it doesn't
display this warning until after you close the window

## Solution

Skip `update_text_layout` when there is no primary window.

## Changelog
* If no primary window is found, skip `update_text2d_layout`.
* Added a `Local` flag `skipped` to `update_text2d_layout`. This should
ensure there are no edge cases where text might not get drawn at all.

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 01:01:31 +00:00
Alexis "spectria.limina" Horizon
4dfa87798f
Add std derives to SystemParam types (#16785)
# Objective

- Use `Clone` on `SystemParam`, when applicable, in a generic context.

## Solution

-  Add some derives

## Testing

- I ran `cargo test` once.
- I didn't even look at the output.

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 00:30:51 +00:00
Greeble
83b2265673
Fix bevy_time tests occasionally failing on optimised Windows builds (#17349)
# Objective

Fix the `bevy_time` unit tests occasionally failing on optimised Windows
builds.

# Background

I noticed that the `bevy_time` unit tests would fail ~50% of the time
after enabling `opt-level=1` in config.toml, or adding `--release` to
cargo test.

```
> cargo test -p bevy_time --release

thread 'real::test::test_update' panicked at crates\bevy_time\src\real.rs:164:9:
assertion `left != right` failed
  left: Some(Instant { t: 9458.0756664s })
 right: Some(Instant { t: 9458.0756664s })
 ```

Disabling optimisations would fix the issue, as would switching from Windows to Linux.

The failing path is roughly:

```rust
let mut time = Time::<Real>::new(Instant::now());
time.update();
time.update();
assert_ne!(time.last_update(), time.first_update());
```

Which kinda boils down to:

```rust
let left = Instant::now();
let right = Instant::now();
assert_ne!(left, right);
```

So the failure seems legit, since there's no guarantee that `Instant::now()` increases between calls.

I suspect it only triggers with a combination of Windows + fast CPU + optimisations (Windows has a lower resolution clock than Linux/MacOS). That would explain why it doesn't fail on the Bevy Github CI (optimisations disabled, and I'm guessing the runner CPUs are clocked lower).

# Solution

Make sure `Instant::now()` has increased before calling `time.update()`.

I also considered:

1. Change the unit tests to accept `Instant:now()` not increasing.
    - In retrospect this is maybe the better change?
    - There's other unit tests that cover time increasing.
    - Could also add a deterministic test for zero delta updates.
    - I can switch the PR to this if desired.
2. Avoid any paths that hit `Instant::now()` in unit tests.
    - Arguably unit tests should always be deterministic.
    - But that would mean a bunch of paths aren't tested.

## Testing

`cargo test -p bevy_time --release`

## System Info

`os: "Windows 10 Pro", kernel: "19045", cpu: "AMD Ryzen 9 7900 12-Core Processor", core_count: "12", memory: "63.2 GiB"`

Also tested on same computer with Linux pop-os 6.9.3.

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 00:30:07 +00:00
Patrick Walton
141b7673ab
Key render phases off the main world view entity, not the render world view entity. (#16942)
We won't be able to retain render phases from frame to frame if the keys
are unstable. It's not as simple as simply keying off the main world
entity, however, because some main world entities extract to multiple
render world entities. For example, directional lights extract to
multiple shadow cascades, and point lights extract to one view per
cubemap face. Therefore, we key off a new type, `RetainedViewEntity`,
which contains the main entity plus a *subview ID*.

This is part of the preparation for retained bins.

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
2025-01-12 20:24:17 +00:00
Rob Parrett
f0047899d7
Allow users to customize history length in FrameTimeDiagnosticsPlugin (#17259)
# Objective

I have an application where I'd like to measure average frame rate over
the entire life of the application, and it would be handy if I could
just configure this on the existing `FrameTimeDiagnosticsPlugin`.

Probably fixes #10948?

## Solution

Add `max_history_length` to `FrameTimeDiagnosticsPlugin`, and because
`smoothing_factor` seems to be based on history length, add that too.

## Discussion

I'm not totally sure that `DEFAULT_MAX_HISTORY_LENGTH` is a great
default for `FrameTimeDiagnosticsPlugin` (or any diagnostic?). That's
1/3 of a second at typical game frame rates. Moreover, the default print
interval for `LogDiagnosticsPlugin` is 1 second. So when the two are
combined, you are printing the average over the last third of the
duration between now and the previous print, which seems a bit wonky.
(related: #11429)

I'm pretty sure this default value discussed and the current value
wasn't totally arbitrary though.

Maybe it would be nice for `Diagnostic` to have a
`with_max_history_length_and_also_calculate_a_good_default_smoothing_factor`
method? And then make an explicit smoothing factor in
`FrameTimeDiagnosticsPlugin` optional?

Or add a `new(max_history_length: usize)` method to
`FrameTimeDiagnosticsPlugin` that sets a reasonable default
`smoothing_factor`? edit: This one seems like a no-brainer, doing it.

## Alternatives

It's really easy to roll your own `FrameTimeDiagnosticsPlugin`, but that
might not be super interoperable with, for example, third party FPS
overlays. Still, might be the right call.

## Testing

`cargo run --example many_sprites` (modified to use a custom
`max_history_length`)

## Migration Guide

`FrameTimeDiagnosticsPlugin` now contains two fields. Use
`FrameTimeDiagnosticsPlugin::default()` to match Bevy's previous
behavior or, for example, `FrameTimeDiagnosticsPlugin::new(60)` to
configure it.
2025-01-12 18:18:14 +00:00
JMS55
bb0a82b9a7
Higher quality bicubic lightmap sampling (#16740)
# Objective
- Closes https://github.com/bevyengine/bevy/issues/14322.

## Solution
- Implement fast 4-sample bicubic filtering based on this shader toy
https://www.shadertoy.com/view/4df3Dn, with a small speedup from a ghost
of tushima presentation.

## Testing

- Did you test these changes? If so, how?
  - Ran on lightmapped example. Practically no difference in that scene.
- Are there any parts that need more testing?
  - Lightmapping a better scene.

## Changelog
- Lightmaps now have a higher quality bicubic sampling method (off by
default).

---------

Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
2025-01-12 05:40:30 +00:00
AlephCubed
e808fbe987
Renamed members of ParamWarnPolicy to reflect new behaviour. (#17311)
- `Once` renamed to `Warn`.
- `param_warn_once()` renamed to `warn_param_missing()`.
- `never_param_warn()` renamed to `ignore_param_missing()`.

Also includes changes to the documentation of the above methods.

Fixes #17262.

## Migration Guide
- `ParamWarnPolicy::Once` has been renamed to `ParamWarnPolicy::Warn`.
- `ParamWarnPolicy::param_warn_once` has been renamed to
`ParamWarnPolicy::warn_param_missing`.
- `ParamWarnPolicy::never_param_warn` has been renamed to
`ParamWarnPolicy::ignore_param_missing`.
2025-01-12 05:40:04 +00:00
SpecificProtagonist
f5d38f30cc
Fix entity does not exist message on index reuse (#17264)
# Objective

With the `track_location` feature, the error message of trying to
acquire an entity that was despawned pointed to the wrong line if the
entity index has been reused.

## Showcase

```rust
use bevy_ecs::prelude::*;

fn main() {
    let mut world = World::new();
    let e = world.spawn_empty().id();
    world.despawn(e);
    world.flush();
    let _ = world.spawn_empty();
    world.entity(e);
}
```
Old message:
```
Entity 0v1 was despawned by src/main.rs:8:19
```
New message:
```
Entity 0v1 does not exist (its index has been reused)
```
2025-01-12 05:39:54 +00:00
Antony
02bb151889
Rename PickingBehavior to Pickable (#17266)
# Objective

PR #17225 allowed for sprite picking to be opt-in. After some
discussion, it was agreed that `PickingBehavior` should be used to
opt-in to sprite picking behavior for entities. This leads to
`PickingBehavior` having two purposes: mark an entity for use in a
backend, and describe how it should be picked. Discussion led to the
name `Pickable`making more sense (also: this is what the component was
named before upstreaming).

A follow-up pass will be made after this PR to unify backends.

## Solution

Replace all instances of `PickingBehavior` and `picking_behavior` with
`Pickable` and `pickable`, respectively.

## Testing

CI

## Migration Guide

Change all instances of `PickingBehavior` to `Pickable`.
2025-01-12 05:36:52 +00:00
ickshonpe
8ac1f8ccdc
Rename UI camera_entity fields (#17243)
# Objective

The `camera_entity` field on the extracted uinode structs holds the
render world entity that has the extracted camera components
corresponding to the target camera world entity. It should be renamed so
that it's clear it isn't the target camera world entity itself.

## Solution

Rename the `camera_entity` field on each of the extracted UI item
structs to `extracted_camera_entity`.
2025-01-12 05:32:08 +00:00
MichiRecRoom
447108b2a4
Downgrade clippy::allow_attributes and clippy::allow_attributes_without_reason to warn (#17320)
# Objective
I realized that setting these to `deny` may have been a little
aggressive - especially since we upgrade warnings to denies in CI.

## Solution
Downgrades these lints to `warn`, so that compiles can work locally. CI
will still treat these as denies.
2025-01-12 05:28:26 +00:00
MichiRecRoom
62a3077061
bevy_picking: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17302)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_picking` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_picking` was run,
and no errors were encountered.
2025-01-12 01:27:11 +00:00
MichiRecRoom
39a514637d
bevy_remote: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17303)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_remote` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_remote` was run, and
no errors were encountered.
2025-01-12 01:26:59 +00:00
MichiRecRoom
900509bec0
bevy_utils: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17305)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_utils` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_utils` was run, and
no errors were encountered.
2025-01-12 01:26:44 +00:00
MichiRecRoom
db4c6c3be7
bevy_internal: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17306)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_internal` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_internal` was run,
and no errors were encountered.
2025-01-12 01:26:23 +00:00
AlephCubed
6063887be2
Feature gate bevy_reflect in bevy_image. (#17313)
Fixes #17294.
2025-01-12 01:24:34 +00:00
Rob Parrett
5c0e13f29b
Fix text alignment for unbounded text (#17270)
# Objective

Fixes #16783

## Solution

Works around a `cosmic-text` bug or limitation by triggering a re-layout
with the calculated width from the first layout run. See linked issue.

Credit to @ickshonpe for the clever solution.

## Performance

This has a significant performance impact only on unbounded text that
are not `JustifyText::Left`, which is still a bit of a bummer because
text2d performance in 0.15.1 is already not great. But this seems better
than alignment not working.

||many_text2d nfc re|many_text2d nfc re center|
|-|-|-|
|unbounded-layout-no-fix|3.06|3.10|
|unbounded-layout-fix|3.05  -0.2%|2.71 🟥 -12.5%|

## Testing

I added a centered text to the `text2d` example.

`cargo run --example text2d`

We should look at other text examples and stress tests. I haven't tested
as thoroughly as I would like, so help testing that this doesn't break
something in UI would be appreciated.
2025-01-11 05:45:32 +00:00
ickshonpe
51c3bf24b7
custom_ui_material border fix (#17282)
# Objective

The order of the border edges in `UiVertexOutput` is left, right, top,
bottom but in `custom_ui_material` the selectors switch them so left is
right and top is bottom.

## Solution

Reverse the conditions so that the correct border values are selected.
2025-01-11 05:45:20 +00:00
MichiRecRoom
bab5a1026c
bevy_image: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17289)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_image` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_image` was run, and no errors were
encountered.

I could not run the above command with `--all-features` due to some
compilation errors with `bevy_core_pipeline` and `bevy_math` - but
hopefully CI catches anything I missed.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-11 04:11:07 +00:00
Zachary Harrold
14aeaa3c06
Improve Compiler Errors for bevy_tasks (#17296)
# Objective

- Fixes #17287

## Solution

- Added a dummy `LocalExecutor` (un)implementation to suppress
irrelevant errors.
- Added explicit `compiler_error!` when _not_ selecting either the
`async_executor` or `edge_executor` features

## Testing

- CI
2025-01-11 02:35:09 +00:00
MichiRecRoom
fa64e0f28d
bevy_image now enables reflection on bevy_math (#17293)
# Objective
`bevy_image` appears to expect `bevy_math` to have reflection enabled.
If you attempt to build `bevy_image` without another dependency enabling
the `bevy_math/bevy_reflect` feature, then `bevy_image` will fail to
compile.

## Solution
Ideally, `bevy_image` would feature-gate all of its reflection behind a
new feature. However, for the sake of getting compilation fixed
immediately, I'm opting to specify the `bevy_math/bevy_reflect` feature
in `bevy_image`'s `Cargo.toml`.

Perhaps an upcoming PR can remove the forced `bevy_math/bevy_reflect`
feature, in favor of feature-gating `bevy_image`'s reflecton.

## Testing
`cargo clippy --package bevy_image` was ran, and no longer returns the
compilation errors that it did before.
2025-01-10 23:51:51 +00:00
Rob Parrett
b77e3ef33a
Fix a few typos (#17292)
# Objective

Stumbled upon a `from <-> form` transposition while reviewing a PR,
thought it was interesting, and went down a bit of a rabbit hole.

## Solution

Fix em
2025-01-10 22:48:30 +00:00
Matty Weatherley
a5279d340d
Make bevy_remote feature enable serialize feature (#17260)
# Objective

`bevy_remote`'s reflection deserialization basically requires
`ReflectDeserialize` registrations in order to work correctly. In the
context of `bevy` (the library), this means that using `bevy_remote`
without using the `serialize` feature is a footgun, since
`#[reflect(Serialize)]` etc. are gated behind this feature.

The goal of this PR is to avoid this mistake by default.

## Solution

Make the `bevy_remote` feature enable the `serialize` feature, so that
it works as expected.

---

## Migration Guide

The `bevy_remote` feature of `bevy` now enables the `serialize` feature
automatically. If you wish to use `bevy_remote` without enabling the
`serialize` feature for Bevy subcrates, you must import `bevy_remote` on
its own.
2025-01-10 20:31:41 +00:00
Benjamin Brienen
454dd27922
Add documentation to DynamicStorageBuffer to clarify purpose (#17228)
# Objective

Fixes #15052

## Solution

Add sentence from @JMS55

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2025-01-10 19:47:53 +00:00
MichiRecRoom
081fe4f7ee
bevy_state: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17288)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_state` in line with the new restrictions.

## Testing
Rust-analyzer did not return any errors once the deny was added.
2025-01-10 19:44:49 +00:00
MichiRecRoom
6650931adf
bevy_scene: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17278)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_scene` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_scene` was run, and
no errors were encountered.
2025-01-10 19:40:19 +00:00
MichiRecRoom
df38d1a907
bevy_pbr: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17277)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_pbr` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_pbr` was run, and no errors were
encountered.
2025-01-10 19:40:07 +00:00
MichiRecRoom
8a82a0c83e
bevy_gltf: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17280)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gltf` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_gltf` was run, and
no errors were encountered.
2025-01-10 19:39:21 +00:00
MichiRecRoom
fec382d2b8
bevy_text: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17285)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_text` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_text` was run, and
no errors were encountered.
2025-01-10 19:38:12 +00:00
MichiRecRoom
b617ec0e5c
bevy_transform: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17284)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_transform` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_transform` was run,
and no errors were encountered.
2025-01-10 19:38:05 +00:00
MichiRecRoom
4340533538
bevy_hierarchy: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17286)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_hierarchy` in line with the new restrictions.

## Testing
Rust-analyzer did not discern any errors.
2025-01-10 19:37:58 +00:00
MichiRecRoom
f1dcd701bd
bevy_gizmos: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17281)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gizmos` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_gizmos` was run, and
no errors were encountered.
2025-01-10 19:36:10 +00:00
Rob Parrett
ec795a20a3
Minor TextPipeline cleanup (#17274)
# Objective

Both `set_metrics` and `set_size` **can** trigger text re-layout and
re-shaping, if the values provided are different form what is already in
the `Buffer`.

## Solution

Combine the `set_metrics` and `set_size` calls.

This might be a small optimization in some situations, maybe when both
font size and text bounds change in the same frame, or when spawning new
text.

I did measure a ~500 microsecond improvement in `text_system` for
`many_buttons --respawn`, but that may have just been noise.
2025-01-10 06:56:36 +00:00
Carter Anderson
4bca7f1b6d
Improved Command Errors (#17215)
# Objective

Rework / build on #17043 to simplify the implementation. #17043 should
be merged first, and the diff from this PR will get much nicer after it
is merged (this PR is net negative LOC).

## Solution

1. Command and EntityCommand have been vastly simplified. No more marker
components. Just one function.
2. Command and EntityCommand are now generic on the return type. This
enables result-less commands to exist, and allows us to statically
distinguish between fallible and infallible commands, which allows us to
skip the "error handling overhead" for cases that don't need it.
3. There are now only two command queue variants: `queue` and
`queue_fallible`. `queue` accepts commands with no return type.
`queue_fallible` accepts commands that return a Result (specifically,
one that returns an error that can convert to
`bevy_ecs::result::Error`).
4. I've added the concept of the "default error handler", which is used
by `queue_fallible`. This is a simple direct call to the `panic()` error
handler by default. Users that want to override this can enable the
`configurable_error_handler` cargo feature, then initialize the
GLOBAL_ERROR_HANDLER value on startup. This is behind a flag because
there might be minor overhead with `OnceLock` and I'm guessing this will
be a niche feature. We can also do perf testing with OnceLock if someone
really wants it to be used unconditionally, but I don't personally feel
the need to do that.
5. I removed the "temporary error handler" on Commands (and all code
associated with it). It added more branching, made Commands bigger /
more expensive to initialize (note that we construct it at high
frequencies / treat it like a pointer type), made the code harder to
follow, and introduced a bunch of additional functions. We instead rely
on the new default error handler used in `queue_fallible` for most
things. In the event that a custom handler is required,
`handle_error_with` can be used.
6. EntityCommand now _only_ supports functions that take
`EntityWorldMut` (and all existing entity commands have been ported).
Removing the marker component from EntityCommand hinged on this change,
but I strongly believe this is for the best anyway, as this sets the
stage for more efficient batched entity commands.
7. I added `EntityWorldMut::resource` and the other variants for more
ergonomic resource access on `EntityWorldMut` (removes the need for
entity.world_scope, which also incurs entity-lookup overhead).

## Open Questions

1. I believe we could merge `queue` and `queue_fallible` into a single
`queue` which accepts both fallible and infallible commands (via the
introduction of a `QueueCommand` trait). Is this desirable?
2025-01-10 04:15:50 +00:00
Alice Cecile
145f5f4394
Add a simple directional UI navigation example (#17224)
# Objective

Gamepad / directional navigation needs an example, for both teaching and
testing purposes.

## Solution

- Add a simple grid-based example.
- Fix an intermittent panic caused by a race condition with bevy_a11y
- Clean up small issues noticed in bevy_input_focus


![image](https://github.com/user-attachments/assets/3a924255-0cd6-44a5-9bb7-b2c400a22d7e)

## To do: this PR

- [x] figure out why "enter" isn't doing anything
- [x] change button color on interaction rather than printing
- [x] add on-screen directions
- [x] move to an asymmetric grid to catch bugs
- [x] ~~fix colors not resetting on button press~~ lol this is mostly
just a problem with hacking `Interaction` for this
- [x] swap to using observers + bubbling, rather than `Interaction`

## To do: future work

- when I increase the button size, such that there is no line break, the
text on the buttons is no longer centered :( EDIT: this is
https://github.com/bevyengine/bevy/issues/16783
- add gamepad stick navigation
- add tools to find the nearest populated quadrant to make diagonal
inputs work
- add a `add_edges` method to `DirectionalNavigationMap`
- add a `add_grid` method to `DirectionalNavigationMap`
- make the example's layout more complex and realistic
- add tools to automatically generate this list
- add button shake on failed navigation rather than printing an error
- make Pressed events easier to mock: default fields, PointerId::Focus

## Testing

`cargo run --example directional_navigation`

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-01-09 21:15:28 +00:00
Antony
0a9740c18f
Make sprite picking opt-in (#17225)
# Objective

Fixes #16903.

## Solution

- Make sprite picking opt-in by requiring a new `SpritePickingCamera`
component for cameras and usage of a new `Pickable` component for
entities.
- Update the `sprite_picking` example to reflect these changes.
- Some reflection cleanup (I hope that's ok).

## Testing

Ran the `sprite_picking` example

## Open Questions

<del>
   <ul>
    <li>Is the name `SpritePickable` appropriate?</li>
    <li>Should `SpritePickable` be in `bevy_sprite::prelude?</li>
  </ul> 
</del>

## Migration Guide

The sprite picking backend is now strictly opt-in using the
`SpritePickingCamera` and `Pickable` components. You should add the
`Pickable` component any entities that you want sprite picking to be
enabled for, and mark their respective cameras with
`SpritePickingCamera`.
2025-01-09 18:11:44 +00:00
mgi388
b20e23dd41
Add compile-time dyn compatible checks for DynEq, DynHash (#17254)
# Objective

- Shrink `bevy_utils` more.
- Refs #11478

## Solution

- Removes `assert_object_safe` from `bevy_utils` by using a compile time
check instead.

## Testing

- CI.

---

## Migration Guide

`assert_object_safe` is no longer exported by `bevy_utils`. Instead, you
can write a compile time check that your trait is "dyn compatible":

```rust
/// Assert MyTrait is dyn compatible
const _: Option<Box<dyn MyTrait>> = None;
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-09 07:30:54 +00:00
MichiRecRoom
3742e621ef
Allow clippy::too_many_arguments to lint without warnings (#17249)
# Objective
Many instances of `clippy::too_many_arguments` linting happen to be on
systems - functions which we don't call manually, and thus there's not
much reason to worry about the argument count.

## Solution
Allow `clippy::too_many_arguments` globally, and remove all lint
attributes related to it.
2025-01-09 07:26:15 +00:00
DaoLendaye
7b56a1aa98
If there is no movement, DragStart is not triggered. (#17233)
# Objective

Fixed the issue where DragStart was triggered even when there was no
movement
https://github.com/bevyengine/bevy/issues/17230

## Solution

- When position delta is zero, don't trigger DragStart events, DragStart
is not triggered, so DragEnd is not triggered either. Everything is
fine.

## Testing

- tested with the code from the issue

---

## Migration Guide

> Fix the missing part of Drag
https://github.com/bevyengine/bevy/pull/16950
2025-01-09 07:17:56 +00:00
MichiRecRoom
9f1b8b4769
bevy_time: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17210)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_time` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
`cargo clippy`, `cargo clippy --package bevy_time` and `cargo test
--package bevy_time` were run, and no errors were encountered.
2025-01-09 06:29:42 +00:00
MichiRecRoom
e0d3270c06
bevy_mesh: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17218)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_mesh` in line with the new restrictions.

## Testing
`cargo clippy --tests` and `cargo test --package bevy_mesh` were run,
and no errors were encountered.
2025-01-09 06:29:36 +00:00
MichiRecRoom
2403487239
bevy_winit: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17232)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_winit` in line with the new restrictions.

## Testing
`cargo clippy --tests` was run, and no errors were encountered.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-09 06:29:29 +00:00
ickshonpe
532bb15489
extract_shadows responsive coords fix (#17236)
# Objective

`extract_shadows` uses the render world entity corresponding to the
extracted camera when it queries the main world for the camera to get
the viewport size for the responsive viewport coords resolution and
fails. This means that viewport coords get resolved based on a viewport
size of zero.

## Solution

Use the main world camera entity.
2025-01-09 06:29:09 +00:00
AlephCubed
3ce8b284d5
Added docs about MinimalPlugins looping as fast as possible. (#17241)
This also includes suggestions and an example on how to limit the loop
speed.
Fixes #17147.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-01-09 06:28:06 +00:00
MichiRecRoom
00e82496d4
bevy_log: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17246)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_log` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_log` was run, and no errors were
encountered.
2025-01-09 06:26:04 +00:00
MichiRecRoom
53077b9316
bevy_gilrs: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17245)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gilrs` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_gilrs` was run, and no errors were
encountered.
2025-01-09 06:25:45 +00:00
MichiRecRoom
8e51b326b5
Cleanup instances of #[allow(clippy::type_complexity)] (#17248)
# Objective
I never realized `clippy::type_complexity` was an allowed lint - I've
been assuming it'd generate a warning when performing my linting PRs.

## Solution
Removes any instances of `#[allow(clippy::type_complexity)]` and
`#[expect(clippy::type_complexity)]`

## Testing
`cargo clippy` ran without errors or warnings.
2025-01-09 06:25:20 +00:00
MichiRecRoom
71cd5f813e
Fix up the reason given for a couple of too_many_arguments lints (#17251)
# Objective
In my crusade to give every lint attribute a reason, it appears I got
too complacent and copy-pasted this expect onto non-system functions.

## Solution
Fix up the reason on those non-system functions

## Testing
N/A
2025-01-09 02:39:10 +00:00
MichiRecRoom
789c5e31fa
bevy_input: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17242)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_input` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_input` was run, and no errors were
encountered.
2025-01-08 20:42:50 +00:00