# Objective
- Please see #16647 for the full reasoning behind this change.
## Solution
- Create the `bench!` macro, which generates the name of the benchmark
at compile time.
Migrating is a single line change, and it will automatically update if
you move the benchmark to a different module:
```diff
+ use benches::bench;
fn my_benchmark(c: &mut Criterion) {
- c.bench_function("my_benchmark", |b| {});
+ c.bench_function(bench!("my_benchmark"), |b| {});
}
```
- Migrate all reflection benchmarks to use `bench!`.
- Fix a few places where `black_box()` or Criterion is misused.
## Testing
```sh
cd benches
# Will take a long time!
cargo bench --bench reflect
# List out the names of all reflection benchmarks, to ensure I didn't miss anything.
cargo bench --bench reflect -- --list
# Check for linter warnings.
cargo clippy --bench reflect
# Run each benchmark once.
cargo test --bench reflect
```
# Objective
ensure that `animate_targets` runs **before**
`bevy_render::mesh::inherit_weights` to address the one-frame delay
Fixes#16554
## Solution
switch ordering constraints from `after` to `before`
## Testing
ran bevy_animation tests and the animated_fox example on MacOS
# Objective
Resolve#16745
## Solution
Provide a way to map `AppTypeRegistry` types into a JSON Schema that can
be used in other applications. I took code from
https://github.com/kaosat-dev/Blenvy as a starting point, cleaned up and
adapter more for `bevy_remote` needs. Based on feedback and needs it
could be improved, I could add some filtering options, etc.
## Testing
- I was comparing results with the ones from code in `blenvy`
- There is added unit test, could be added more
- I was testing it in my game with this code:
```rust
fn types_to_file(world: &mut World) {
use bevy_remote::builtin_methods::export_registry_types;
let Ok(Ok(types_schema)) = world.run_system_cached_with(export_registry_types, None) else {
return;
};
let registry_save_path = std::path::Path::new("assets").join("registry.json");
let writer =
std::fs::File::create(registry_save_path).expect("should have created schema file");
serde_json::to_writer_pretty(writer, &types_schema).expect("Failed to save types to file");
}
```
It can be run by adding it at startup
```rust
app.add_systems(Startup, types_to_file);
```
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
A previous PR, #14599, attempted to enable lightmaps in deferred mode,
but it still used the `OpaqueNoLightmap3dBinKey`, which meant that it
would be broken if multiple lightmaps were used. This commit fixes that
issue, and allows bindless lightmaps to work with deferred rendering as
well.
# Objective
Fixes#16978
While testing, discovered that the morph weight interface in
`scene_viewer` has been broken for a while (panics when loaded model has
morph weights), probably since #15591. Fixed that too.
While testing, saw example text in morph interface with [wrong
padding](https://bevyengine.org/learn/contribute/helping-out/creating-examples/#visual-guidelines).
Fixed that too. Left the small font size because there may be a lot of
morphs to display, so that seems intentional.
## Solution
Use normal queries and bail early
## Testing
Morph interface can be tested with
```
cargo run --example scene_viewer assets/models/animated/MorphStressTest.gltf
```
## Discussion
I noticed that this fix is different than what is happening in #16976.
Feel free to discard this for an alternative fix. I opened this anyway
to document the issue with morph weight display.
This is on top of #16966 which is required to test.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
- Running example `load_gltf` when not using bindless gives this error
```
ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
error: no definition in scope for identifier: 'slot'
┌─ crates/bevy_pbr/src/render/pbr_fragment.wgsl:153:13
│
153 │ slot,
│ ^^^^ unknown identifier
│
= no definition in scope for identifier: 'slot'
```
- since https://github.com/bevyengine/bevy/pull/16825
## Solution
- Set `slot` to the expected value when not mindless
- Also use it for `uv_b`
## Testing
- Run example `load_gltf` on a Mac or in wasm
# Objective
Fixes#16850
## Solution
Add a new function `SubApp::take_extract()`, similar to
`Option::take()`, which allows stealing the currently installed extract
function of a sub-app, with the intent to replace it with a custom one
calling the original one via `set_extract()`.
This pattern enables registering a custom "world sync" function similar
to the existing one `entity_sync_system()`, to run custom world sync
logic with mutable access to both the main and render worlds.
## Testing
`cargo r -p ci` currently doesn't build locally, event after upgrading
rustc to latest and doing a `cargo update`.
# Objective
Make it so that users can ease between tuples of easeable values.
## Solution
Use `variadics_please`'s `all_tuples_enumerated` macro to generate code
that creates these trait implementations. For two elements, the result
looks like this:
```rust
impl<T0: Ease, T1: Ease> Ease for (T0, T1) {
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
let curve_tuple = (
<T0 as Ease>::interpolating_curve_unbounded(start.0, end.0),
<T1 as Ease>::interpolating_curve_unbounded(start.1, end.1),
);
FunctionCurve::new(Interval::EVERYWHERE, move |t| {
(
curve_tuple.0.sample_unchecked(t),
curve_tuple.1.sample_unchecked(t),
)
})
}
}
```
## Testing
It compiles, and I futzed about with some manual examples, which seem to
work as expected.
---
## Showcase
Easing curves now support easing tuples of values that can themselves be
eased. For example:
```rust
// Easing between two `(Vec3, Quat)` values:
let easing_curve = EasingCurve::new(
(vec3(0.0, 0.0, 0.0), Quat::from_rotation_z(-FRAC_PI_2)),
(vec3(1.0, 1.0, 1.0), Quat::from_rotation_z(FRAC_PI_2)),
EaseFunction::ExponentialInOut
);
```
# Objective
- To fix the benches panicking on `main`
## Solution
- It appears that systems requiring access to a non-existing `Res` now
causes a panic
- Some of the benches run systems that access resources that have not
been inserted into the world
- I have made it so that those resources are inserted into the world
## Testing
- I ran all the ecs benches and they all run without panicking
Co-authored-by: Oliver Maskery <oliver@wellplayed.games>
# Objective
Almost all of the `*InOut` easing functions are not actually smooth
(`SineInOut` is the one exception).
Because they're defined piecewise, they jump from accelerating upwards
to accelerating downwards, causing infinite jerk at t=½.
## Solution
This PR adds the well-known
[smoothstep](https://registry.khronos.org/OpenGL-Refpages/gl4/html/smoothstep.xhtml),
as well as its higher-degree version
[smootherstep](https://en.wikipedia.org/wiki/Smoothstep#Variations), as
easing functions.
Mathematically, these are the classic [Hermite
interpolation](https://en.wikipedia.org/wiki/Hermite_interpolation)
results:
- for smoothstep, the cubic with velocity zero at both ends
- for smootherstep, the quintic with velocity zero *and acceleration
zero* at both ends
And because they're simple polynomials, there's no branching and thus
they don't have the acceleration jump in the middle.
I also added some more information and cross-linking to the
documentation for these and some of the other easing functions, to help
clarify why one might want to use these over other existing ones. In
particular, I suspect that if people are willing to pay for a quintic
they might prefer `SmootherStep` to `QuinticInOut`.
For consistency with how everything else has triples, I added
`Smooth(er)Step{In,Out}` as well, in case people want to run the `In`
and `Out` versions separately for some reason. Qualitatively they're not
hugely different from `Quadratic{In,Out}` or `Cubic{In,Out}`, though, so
could be removed if you'd rather. They're low cost to keep, though, and
convenient for testing.
## Testing
These are simple polynomials, so their coefficients can be read directly
from the Horner's method implementation and compared to the reference
materials. The tests from #16910 were updated to also test these 6 new
easing functions, ensuring basic behaviour, plus one was updated to
better check that the InOut versions of things match their rescaled In
and Out versions.
Even small changes like
```diff
- (((2.5 + (-1.875 + 0.375*t) * t) * t) * t) * t
+ (((2.5 + (-1.85 + 0.375*t) * t) * t) * t) * t
```
are caught by multiple tests this way.
If you want to confirm them visually, here are the 6 new ones graphed:
<https://www.desmos.com/calculator/2d3ofujhry>

---
## Migration Guide
This version of bevy marks `EaseFunction` as `#[non_exhaustive]` to that
future changes to add more easing functions will be non-breaking. If you
were exhaustively matching that enum -- which you probably weren't --
you'll need to add a catch-all (`_ =>`) arm to cover unknown easing
functions.
# Objective
With the introduction of bevy_input_focus, the uses of "focus" in
bevy_picking are quite confusing and make searching hard.
Users will intuitively think these concepts are related, but they
actually aren't.
## Solution
Rename / rephrase all uses of "focus" in bevy_picking to refer to
"hover", since this is ultimately related to creating the `HoverMap`.
## Migration Guide
Various terms related to "focus" in `bevy_picking` have been renamed to
refer to "hover" to avoid confusion with `bevy_input_focus`. In
particular:
- The `update_focus` system has been renamed to `generate_hovermap`
- `PickSet::Focus` and `PostFocus` have been renamed to `Hover` and
`PostHover`
- The `bevy_picking::focus` module has been renamed to
`bevy_picking::hover`
- The `is_focus_enabled` field on `PickingPlugin` has been renamed to
`is_hover_enabled`
- The `focus_should_run` run condition has been renamed to
`hover_should_run`
# Objective
`SubApps` is visible within the documentation for `bevy_app`. However,
no way of accessing the `SubApps` field in `App` is currently available.
## Solution
Expose two new functions, `App::sub_apps()` and `App::sub_apps_mut()`,
which give immutable and mutable access to `SubApps` respectively.
The other solution is to hide `SubApps`, which I submitted as a PR at
<https://github.com/bevyengine/bevy/pull/16953>.
## Testing
Because of the simplicity of the changes, I only tested by compiling
`bevy_app` - which compiled successfully.
Note: `SubApps`, and its corresponding field on `App`, are not used
outside of `bevy_app` - which means that compiling the other crates is
not necessary.
# Objective
- Fixes#16571
## Solution
- When position delta is zero, don't trigger `Drag` or `DragOver` events
## Testing
- tested with the code from the issue
# Objective
- Fixes#16563
- Make sure bevy_image is available when needed
## Solution
- Add a new feature for `bevy_image`
- Also enable the `bevy_image` feature in `bevy_internal` for all
features that use `bevy_image` themselves
# Objective
bevy_reflect is a big part of bevy_math's dependency footprint, and is
often not useful when using bevy_math standalone (as I often do). The
goal with this PR is to avoid pulling in those dependencies by default
without compromising the usability of bevy_math types within Bevy
proper.
## Solution
`bevy_reflect` has been removed from default features of `bevy_math`.
However, the feature is enabled by `bevy_internal`, so that
`bevy_reflect` is enabled when `bevy_math` is used through `bevy`.
Philosophically, if there were a feature flag toggling reflection on
`bevy` globally, then whether `bevy_math` enabled `bevy_reflect` itself
would depend on that, but that doesn't exist for the time being.
## Testing
It compiles :)
## Migration Guide
`bevy_reflect` has been made a non-default feature of `bevy_math`. (It
is still enabled when `bevy_math` is used through `bevy`.) You may need
to enable this feature if you are using `bevy_math` on its own and
desire for the types it exports to implement `Reflect` and other
reflection traits.
## Objective
I believe these started as structs, back when that was how commands had
to be implemented. Now they just hide implementation details.
## Solution
Remove the helper functions and move each implementation into its
respective method, except for the ones that actually reduce code
duplication.
This PR simply exposes Bevy PBR's
`TONEMAPPING_LUT_TEXTURE_BINDING_INDEX` and
`TONEMAPPING_LUT_SAMPLER_BINDING_INDEX`.
# Objective
Alongside #16932, this is the last required change to be able to replace
Bevy's built-in deferred lighting pass with a custom one based on the
original logic.
Fixes a crash when using deferred rendering but disabling the default
deferred lighting plugin.
# The Issue
The `ScreenSpaceReflectionsPlugin` references
`NodePbr::DeferredLightingPass`, which hasn't been added when
`PbrPlugin::add_default_deferred_lighting_plugin` is `false`.
This yields the following crash:
```
thread 'main' panicked at /Users/marius/Documents/dev/bevy/crates/bevy_render/src/render_graph/graph.rs:155:26:
InvalidNode(DeferredLightingPass)
stack backtrace:
0: rust_begin_unwind
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/std/src/panicking.rs:665:5
1: core::panicking::panic_fmt
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:74:14
2: bevy_render::render_graph::graph::RenderGraph::add_node_edges
at /Users/marius/Documents/dev/bevy/crates/bevy_render/src/render_graph/graph.rs:155:26
3: <bevy_app::sub_app::SubApp as bevy_render::render_graph::app::RenderGraphApp>::add_render_graph_edges
at /Users/marius/Documents/dev/bevy/crates/bevy_render/src/render_graph/app.rs:66:13
4: <bevy_pbr::ssr::ScreenSpaceReflectionsPlugin as bevy_app::plugin::Plugin>::finish
at /Users/marius/Documents/dev/bevy/crates/bevy_pbr/src/ssr/mod.rs:234:9
5: bevy_app::app::App::finish
at /Users/marius/Documents/dev/bevy/crates/bevy_app/src/app.rs:255:13
6: bevy_winit::state::winit_runner
at /Users/marius/Documents/dev/bevy/crates/bevy_winit/src/state.rs:859:9
7: core::ops::function::FnOnce::call_once
at /Users/marius/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
8: core::ops::function::FnOnce::call_once{{vtable.shim}}
at /Users/marius/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
9: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
at /Users/marius/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2454:9
10: bevy_app::app::App::run
at /Users/marius/Documents/dev/bevy/crates/bevy_app/src/app.rs:184:9
11: bevy_deferred_test::main
at ./src/main.rs:9:5
12: core::ops::function::FnOnce::call_once
at /Users/marius/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
```
### Minimal reproduction example:
```rust
use bevy::core_pipeline::prepass::{DeferredPrepass, DepthPrepass};
use bevy::pbr::{DefaultOpaqueRendererMethod, PbrPlugin, ScreenSpaceReflections};
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(PbrPlugin {
add_default_deferred_lighting_plugin: false,
..default()
}))
.add_systems(Startup, setup)
.insert_resource(DefaultOpaqueRendererMethod::deferred())
.run();
}
/// set up a camera
fn setup(
mut commands: Commands
) {
// camera
commands.spawn((
Camera3d::default(),
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
DepthPrepass,
DeferredPrepass,
ScreenSpaceReflections::default(),
));
}
```
# The Fix
When no node under the default lighting node's label exists, this label
isn't added to the SSR's graph node edges. It's good to keep the
SSRPlugin enabled, this way, users can plug in their own lighting
system, which I have successfully done on top of this PR.
# Workarounds
A current workaround for this issue is to re-use Bevy's
`NodePbr::DeferredLightingPass` as the label for your own custom
lighting pass node.
# Objective
Now that `variadics_please` has a 1.1 release, we can re-implement the
original solution.
## Solution
Copy-paste the code from the [original
PR](https://github.com/bevyengine/bevy/pull/15931) branch :)
# Objective
This PR implements `FromStr` for `Val`, so developers can parse values
like `10px` and `50%`
## Testing
Added tests for this. I think they cover pretty much everything, and
it's a fairly simple unit test.
## Limitations
Currently the following float values are not parsed:
- `inf`, `-inf`, `+infinity`, `NaN`
- `2.5E10`, `2.5e10`, `2.5E-10`
For my use case this is perfectly fine but other developers might want
to support these values
# Objective
Some types like `RenderEntity` and `MainEntity` are just wrappers around
`Entity`, so they should be able to implement
`EntityBorrow`/`TrustedEntityBorrow`. This allows using them with
`EntitySet` functionality.
The `EntityRef` family are more than direct wrappers around `Entity`,
but can still benefit from being unique in a collection.
## Solution
Implement `EntityBorrow` and `TrustedEntityBorrow` for simple `Entity`
newtypes and `EntityRef` types.
These impls are an explicit decision to have the `EntityRef` types
compare like just `Entity`.
`EntityWorldMut` is omitted from this impl, because it explicitly
contains a `&mut World` as well, and we do not ever use more than one at
a time.
Add `EntityBorrow` to the `bevy_ecs` prelude.
## Migration Guide
`NormalizedWindowRef::entity` has been replaced with an
`EntityBorrow::entity` impl.
And add a bunch of tests to show that all the monotonic easing functions
have roughly the expected shape.
# Objective
The `EaseFunction::Exponential*` variants aren't actually smooth as
currently implemented, because they jump by about 1‰ at the
start/end/both.
- Fixes#16676
- Subsumes #16675
## Solution
This PR slightly tweaks the shifting and scaling of all three variants
to ensure they hit (0, 0) and (1, 1) exactly while gradually
transitioning between them.
Graph demonstration of the new easing function definitions:
<https://www.desmos.com/calculator/qoc5raus2z>

(Yes, they look completely identical to the previous ones at that scale.
[Here's a zoomed-in
comparison](https://www.desmos.com/calculator/ken6nk89of) between the
old and the new if you prefer.)
The approach taken was to keep the core 2¹⁰ᵗ shape, but to [ask
WolframAlpha](https://www.wolframalpha.com/input?i=solve+over+the+reals%3A+pow%282%2C+10-A%29+-+pow%282%2C+-A%29%3D+1)
what scaling factor to use such that f(1)-f(0)=1, then shift the curve
down so that goes from zero to one instead of ¹/₁₀₂₃ to ¹⁰²⁴/₁₀₂₃.
## Testing
I've included in this PR a bunch of general tests for all monotonic
easing functions to ensure they hit (0, 0) to (1, 1), that the InOut
functions hit (½, ½), and that they have the expected convexity.
You can also see by inspection that the difference is small. The change
for `exponential_in` is from `exp2(10 * t - 10)` to `exp2(10 * t -
9.99859…) - 0.0009775171…`.
The problem for `exponential_in(0)` is also simple to see without a
calculator: 2⁻¹⁰ is obviously not zero, but with the new definition
`exp2(-LOG2_1023) - FRAC_1_1023` => `1/(exp2(LOG2_1023)) - FRAC_1_1023`
=> `FRAC_1_1023 - FRAC_1_1023` => `0`.
---
## Migration Guide
This release of bevy slightly tweaked the definitions of
`EaseFunction::ExponentialIn`, `EaseFunction::ExponentialOut`, and
`EaseFunction::ExponentialInOut`. The previous definitions had small
discontinuities, while the new ones are slightly rescaled to be
continuous. For the output values that changed, that change was less
than 0.001, so visually you might not even notice the difference.
However, if you depended on them for determinism, you'll need to define
your own curves with the previous definitions.
---------
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
# Objective
Allow users to enable or disable layout rounding for specific UI nodes
and their descendants.
Fixes#16731
## Solution
New component `LayoutConfig` that can be added to any UiNode entity.
Setting the `use_rounding` field of `LayoutConfig` determines if the
Node and its descendants should be given rounded or unrounded
coordinates.
## Testing
Not tested this extensively but it seems to work and it's not very
complicated.
This really basic test app returns fractional coords:
```rust
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, report)
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn((
Node {
left: Val::Px(0.1),
width: Val::Px(100.1),
height: Val::Px(100.1),
..Default::default()
},
LayoutConfig { use_rounding: false },
));
}
fn report(node: Query<(Ref<ComputedNode>, &GlobalTransform)>) {
for (c, g) in node.iter() {
if c.is_changed() {
println!("{:#?}", c);
println!("position = {:?}", g.to_scale_rotation_translation().2);
}
}
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
# Objective
Fixes: #16578
## Solution
This is a patch fix, proper fix requires a breaking change.
Added `Panic` enum variant and using is as the system meta default.
Warn once behavior can be enabled same way disabling panic (originally
disabling wans) is.
To fix an issue with the current architecture, where **all** combinator
system params get checked together,
combinator systems only check params of the first system.
This will result in old, panicking behavior on subsequent systems and
will be fixed in 0.16.
## Testing
Ran unit tests and `fallible_params` example.
---------
Co-authored-by: François Mockers <mockersf@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Revert the retry queue for stuck meshlet groups that couldn't simplify
added in https://github.com/bevyengine/bevy/pull/15886.
It was a hack that didn't really work, that was intended to help solve
meshlets getting stuck and never getting simplified further. The actual
solution is a new DAG building algorithm that I have coming in a
followup PR. With that PR, there will be no need for the retry queue, as
meshlets will rarely ever get stuck (I checked, the code never gets
called). I split this off into it's own PR for easier reviewing.
Meshlet IDs during building are back to being relative to the overall
list of meshlets across all LODs, instead of starting at 0 for the first
meshlet in the simplification queue for the current LOD, regardless of
how many meshlets there are in the asset total.
Not going to bother to regenerate the bunny asset for this PR.
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.28.3 to
1.28.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
releases</a>.</em></p>
<blockquote>
<h2>v1.28.4</h2>
<h2>[1.28.4] - 2024-12-16</h2>
<h3>Features</h3>
<ul>
<li><code>--format sarif</code> support</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
changelog</a>.</em></p>
<blockquote>
<h2>[1.28.4] - 2024-12-16</h2>
<h3>Features</h3>
<ul>
<li><code>--format sarif</code> support</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9d89015957"><code>9d89015</code></a>
chore: Release</li>
<li><a
href="6b24563a99"><code>6b24563</code></a>
chore: Release</li>
<li><a
href="bd0a2769ae"><code>bd0a276</code></a>
docs: Update changelog</li>
<li><a
href="370109dd4d"><code>370109d</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1047">#1047</a>
from Zxilly/sarif</li>
<li><a
href="63908449a7"><code>6390844</code></a>
feat: Implement sarif format reporter</li>
<li><a
href="32b96444b9"><code>32b9644</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1169">#1169</a>
from klensy/deps</li>
<li><a
href="720258f60b"><code>720258f</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1176">#1176</a>
from Ghaniyyat05/master</li>
<li><a
href="a42904ad6e"><code>a42904a</code></a>
Update README.md</li>
<li><a
href="0169b9b9e8"><code>0169b9b</code></a>
fix: Remove some unused deps</li>
<li>See full diff in <a
href="https://github.com/crate-ci/typos/compare/v1.28.3...v1.28.4">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# Objective
- To fix a tiny bug in `bevy_ecs::storage::Tables` that, in one case,
means it accidentally allocates an additional "empty" `Table`, resulting
in two "empty" `Table`s:
- The one pre-allocated empty table at index 0 whose index is designed
to match up with `TableId::empty()`
- One extra empty table, at some non-0 index, that does not match up
with `TableId::empty()`.
- This PR aims to prevent this extraneous `Table`, ensuring that
entities with no components in table-storage reliably have their
archetype's table ID be equal to `TableId::empty()`.
## Solution
### Background
The issue occurs because:
- `Tables` contains:
- `tables: Vec<Table>` - The set of all `Table`s allocated in the world.
- `table_ids: HashMap<Box<[ComponentId]>, TableId>` - An index to
rapidly lookup the `Table` in `tables` by a set of `ComponentId`s.
- When `Tables` is constructed it pre-populates the `tables` `Vec` with
an empty `Table`.
- This ensures that the first entry (index 0) is always the `Table` for
entities with no components in table storage.
- In particular, `TableId::empty()` is a utility that returns a
`TableId` of `0`.
- However, the `table_ids` map is not initialised to associate an empty
`[ComponentId]` with `TableId` `0`.
- This means, the first time a structural change tries to access a
`Table` for an archetype with 0 table components:
- `Tables::get_id_or_insert` is used to retrieve the target `Table`
- The function attempts to lookup the entry in the `table_ids` `HashMap`
whose key is the empty `ComponentId` set
- The empty `Table` created at startup won't be found, because it was
never inserted into `table_ids`
- It will instead create a new table, insert it into the `HashMap`
(preventing further instances of this issue), and return it.
### Changes
- I considered simply initialising the `table_ids` `HashMap` to know
about the pre-allocated `Table`
- However, I ended up using the proposed solution discussed on Discord
[#ecs-dev](https://discord.com/channels/691052431525675048/749335865876021248/1320430933152759958):
- Make `Tables::get_id_or_insert` simply early-exit if the requested
`component_ids` was empty.
- This avoids unnecessarily hashing the empty slice and looking it up in
the `HashMap`.
- The `table_ids` `HashMap` is not exposed outside this struct, and is
only used within `get_id_or_insert`, so it seems wasteful to defensively
populate it with the empty `Table`.
## Testing
This is my first Bevy contribution, so I don't really know the processes
that well. That said:
- I have introduced a little test that exercises the original issue and
shows that it is now resolved.
- I have run the `bevy_ecs` tests locally, so I have reasonable
confidence I haven't broken that.
- I haven't run any further test suites, mostly as when I tried to run
test suites for the whole project it filled my entire SSD with >600GB of
target directory output 😱😱😱
This commit fixes the following regressions:
1. Transmission-specific calls to shader lighting functions didn't pass
the `enable_diffuse` parameter, breaking the `transmission` example.
2. The combination of bindless `StandardMaterial` and bindless lightmaps
caused us to blow past the 128 texture limit on M1/M2 chips in some
cases, in particular the `depth_of_field` example.
https://github.com/gfx-rs/wgpu/issues/3334 should fix this, but in the
meantime this patch reduces the number of bindless lightmaps from 16 to
4 in order to stay under the limit.
3. The renderer was crashing on startup on Adreno 610 chips. This PR
simply disables bindless on Adreno 610 and lower.
# Objective
- Our benchmarks and `compile_fail` tests lag behind the rest of the
engine because they are not in the Cargo workspace, so not checked by
CI.
- Fixes#16801, please see it for further context!
## Solution
- Add benchmarks and `compile_fail` tests to the Cargo workspace.
- Fix any leftover formatting issues and documentation.
## Testing
- I think CI should catch most things!
## Questions
<details>
<summary>Outdated issue I was having with function reflection being
optional</summary>
The `reflection_types` example is failing in Rust-Analyzer for me, but
not a normal check.
```rust
error[E0004]: non-exhaustive patterns: `ReflectRef::Function(_)` not covered
--> examples/reflection/reflection_types.rs:81:11
|
81 | match value.reflect_ref() {
| ^^^^^^^^^^^^^^^^^^^ pattern `ReflectRef::Function(_)` not covered
|
note: `ReflectRef<'_>` defined here
--> /Users/bdeep/dev/bevy/bevy/crates/bevy_reflect/src/kind.rs:178:1
|
178 | pub enum ReflectRef<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^
...
188 | Function(&'a dyn Function),
| -------- not covered
= note: the matched value is of type `ReflectRef<'_>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
126 ~ ReflectRef::Opaque(_) => {},
127 + ReflectRef::Function(_) => todo!()
|
```
I think it is because the following line is feature-gated:
cc0f6a8db4/examples/reflection/reflection_types.rs (L117-L122)
My theory for why this is happening is because the benchmarks enabled
`bevy_reflect`'s `function` feature, which gets merged with the rest of
the features when RA checks the workspace, but the `#[cfg(...)]` gate in
the example isn't detecting it:
cc0f6a8db4/benches/Cargo.toml (L19)
Any thoughts on how to fix this? It's not blocking, since the example
still compiles as normal, but it's just RA and the command `cargo check
--workspace --all-targets` appears to fail.
</summary>
# Objective
`EntityHashMap` and `EntityHashSet` iterators do not implement
`EntitySetIterator`.
## Solution
Make them newtypes instead of aliases. The methods that create the
iterators can then produce their own newtypes that carry the `Hasher`
generic and implement `EntitySetIterator`. Functionality remains the
same otherwise.
There are some other small benefits, f.e. the removal of `with_hasher`
associated functions, and the ability to implement more traits
ourselves.
`MainEntityHashMap` and `MainEntityHashSet` are currently left as the
previous type aliases, because supporting general `TrustedEntityBorrow`
hashing is more complex. However, it can also be done.
## Testing
Pre-existing `EntityHashMap` tests.
## Migration Guide
Users of `with_hasher` and `with_capacity_and_hasher` on
`EntityHashMap`/`Set` must now use `new` and `with_capacity`
respectively.
If the non-newtyped versions are required, they can be obtained via
`Deref`, `DerefMut` or `into_inner` calls.
# Objective
Add a benchmark that captures performance with a removed UI layout where
the root node is set to `Display::None`.
# Solution
Added a `display-none` commandline argument to the `many_buttons`
example. When used `display-none` sets the `display` field of the root
node to `Display::None`.
# Testing
```
cargo run --example many_buttons -- --display-none
```
Which displays nothing, as desired.
This reverts commit 58a73924eb.
# Objective
This is causing local `cargo run -p ci` runs to fail on `stable` Rust
when used locally. Fixes#16871.
## Solution
Revert #16147. We shouldn't have merged this until we had a full
solution (I missed a Controversial tag, sorry!).
## Testing
`cargo run -p ci` fails for me before this change in the reported
fashion. After this reversion, it passes.
# Objective
- Fixes#16892
## Solution
- Removed `TypeRegistryPlugin` (`Name` is now automatically registered
with a default `App`)
- Moved `TaskPoolPlugin` to `bevy_app`
- Moved `FrameCountPlugin` to `bevy_diagnostic`
- Deleted now-empty `bevy_core`
## Testing
- CI
## Migration Guide
- `TypeRegistryPlugin` no longer exists. If you can't use a default
`App` but still need `Name` registered, do so manually with
`app.register_type::<Name>()`.
- References to `TaskPoolPlugin` and associated types will need to
import it from `bevy_app` instead of `bevy_core`
- References to `FrameCountPlugin` and associated types will need to
import it from `bevy_diagnostic` instead of `bevy_core`
## Notes
This strategy was agreed upon by Cart and several other members in
[Discord](https://discord.com/channels/691052431525675048/692572690833473578/1319137218312278077).
# Objective
- Contributes to #16892
## Solution
- Moved `Name` and `NameOrEntity` into `bevy_ecs::name`, and added them
to the prelude.
## Testing
- CI
## Migration Guide
If you were importing `Name` or `NameOrEntity` from `bevy_core`, instead
import from `bevy_ecs::name`.
---------
Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
# Objective
The `SetInputFocus` trait is not very useful: we're just setting a
resource's value.
This is a very common and simple pattern, so we should expose it
directly to users rather than creating confusing indirection.
## Solution
Remove the `SetInputFocus` trait and migrate existing uses to just
modify the `InputFocus` resource. The helper methods on that type make
this nicer than before :)
P.S. This is non-breaking as bevy_input_focus has not yet shipped.
## Testing
Code compiles! CI will check the existing unit tests.
# Objective
The docs for InputFocusVisible could do a better job explaining how the
resource is intended to be used.
## Solution
Add more detail and do an editing pass. Link to the `IsFocused` trait
for breadcrumbs too.
# Objective
- Contributes to #15460
## Solution
- Added the following features:
- `std` (default)
- `bevy_tasks` (default)
- `downcast ` (default)
- `portable-atomic`
- `critical-section`
- `downcast` and `bevy_tasks` are now optional dependencies for
`bevy_app`.
## Testing
- CI
- Personal UEFI and Raspberry Pi Pico demo applications compile and run
against this branch
## Draft Release Notes
Bevy's application framework now supports `no_std` platforms.
Following up on `bevy_ecs` gaining `no_std` support, `bevy_app` extends
the functionality available on these targets to include the powerful
`App` and `Plugin` abstractions. With this, library authors now have the
option of making their plugins `no_std` compatible, or even offering
plugins specifically to improve Bevy on certain embedded platforms!
To start making a `no_std` compatible plugin, simply disable default
features when including `bevy_app`:
```toml
[dependencies]
bevy_app = { version = "0.16", default-features = false }
```
We encourage library authors to do this anyway, as it can also help with
compile times and binary size on all platforms.
Keep an eye out for future `no_std` updates as we continue to improve
the parity between `std` and `no_std`. We look forward to seeing what
kinds of applications are now possible with Bevy!
## Notes
- `downcast-rs` is optional as it isn't compatible with
`portable-atomic`. I will investigate making a PR upstream to add
support for this functionality, as it should be very straightforward.
- In line with the `bevy_ecs` no-std-ification, I've added documentation
to all features, and grouped them as well.
- ~~Creating this PR in draft while CI runs and so I can polish before
review.~~
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fixes#16873
## Solution
- Added `GizmoLineStyle::Dashed {gap_scale, line_scale}`
- The `gap_scale` and `line_scale` describe the lengths of the gaps and
visible line-segments in terms of line-widths. For example, if
`gap_scale == 1.0` and `line_scale == 3.0` the gaps are square and the
the visible segments are three line-widths long.
- The new `GizmoLineStyle` can be used both in 3D and 2D and with both
perspective and orthographic cameras.
- Updated the `2d_gizmos` and `3d_gizmos` examples to include the new
line-style.
- Display a warning, when using negative `gap_scale` or `line_scale`.
- Notably, `Hash` and `Eq` are manually implemented for `GizmoLineStyle`
since both are not implemented for `f32` which prevents deriving these
traits for `GizmoLineStyle`.
## Testing
- The results can be verified visually
---
## Showcase
The following images depict dashed lines with `gap_scale == 3.0` and
`line_scale == 5.0` in perspective 3D and orthographic 2D.


---------
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
# Objective
`bevy_input_focus` needs some love before we ship it to users. There's a
few missing helper methods, the docs could be improved, and `AutoFocus`
should be more generally available.
## Solution
The changes here are broken down by commit, and should generally be
uncontroversial. The ones to focus on during review are:
- Make navigate take a & InputFocus argument: this makes the intended
pattern clearer to users
- Remove TabGroup requirement from `AutoFocus`: I want auto-focusing
even with gamepad-style focus navigation!
- Handle case where tab group is None more gracefully: I think we can
try harder to provide something usable, and shouldn't just fail to
navigate
## Testing
The `tab_navigation` example continues to work.
# Objective
#16132 introduced entity cloning functionality, and while it works and
is useful, it can be made faster. This is the promised follow-up to
improve performance.
## Solution
**PREFACE**: This is my first time writing `unsafe` in rust and I have
only vague idea about what I'm doing. I would encourage reviewers to
scrutinize `unsafe` parts in particular.
The solution is to clone component data to an intermediate buffer and
use `EntityWorldMut::insert_by_ids` to insert components without
additional archetype moves.
To facilitate this, `EntityCloner::clone_entity` now reads all
components of the source entity and provides clone handlers with the
ability to read component data straight from component storage using
`read_source_component` and write to an intermediate buffer using
`write_target_component`. `ComponentId` is used to check that requested
type corresponds to the type available on source entity.
Reflect-based handler is a little trickier to pull of: we only have
`&dyn Reflect` and no direct access to the underlying data.
`ReflectFromPtr` can be used to get `&dyn Reflect` from concrete
component data, but to write it we need to create a clone of the
underlying data using `Reflect`. For this reason only components that
have `ReflectDefault` or `ReflectFromReflect` or `ReflectFromWorld` can
be cloned, all other components will be skipped. The good news is that
this is actually only a temporary limitation: once #13432 lands we will
be able to clone component without requiring one of these `type data`s.
This PR also introduces `entity_cloning` benchmark to better compare
changes between the PR and main, you can see the results in the
**showcase** section.
## Testing
- All previous tests passing
- Added test for fast reflect clone path (temporary, will be removed
after reflection-based cloning lands)
- Ran miri
## Showcase
Here's a table demonstrating the improvement:
| **benchmark** | **main, avg** | **PR, avg** | **change, avg** |
| ----------------------- | ------------- | ----------- |
--------------- |
| many components reflect | 18.505 µs | 2.1351 µs | -89.095% |
| hierarchy wide reflect* | 22.778 ms | 4.1875 ms | -81.616% |
| hierarchy tall reflect* | 107.24 µs | 26.322 µs | -77.141% |
| hierarchy many reflect | 78.533 ms | 9.7415 ms | -87.596% |
| many components clone | 1.3633 µs | 758.17 ns | -45.937% |
| hierarchy wide clone* | 2.7716 ms | 3.3411 ms | +20.546% |
| hierarchy tall clone* | 17.646 µs | 20.190 µs | +17.379% |
| hierarchy many clone | 5.8779 ms | 4.2650 ms | -27.439% |
*: these benchmarks have entities with only 1 component
## Considerations
Once #10154 is resolved a large part of the functionality in this PR
will probably become obsolete. It might still be a little bit faster
than using command batching, but the complexity might not be worth it.
## Migration Guide
- `&EntityCloner` in component clone handlers is changed to `&mut
ComponentCloneCtx` to better separate data.
- Changed `EntityCloneHandler` from enum to struct and added convenience
functions to add default clone and reflect handler more easily.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
Simplify the code by using `macro_rules` instead of a proc macro where
possible.
## Solution
Replace `impl_param_set` proc macro with a `macro_rules` macro.
# Objective
The new `bevy_input_focus` crates has a tool to bubble input events up
the entity hierarchy, ending with the window, based on the currently
focused entity. Right now though, this only works for keyboard events!
Both `bevy_ui` buttons and `bevy_egui` should hook into this system
(primarily for contextual hotkeys), and we would like to drive
`leafwing_input_manager` via these events, to help resolve longstanding
pain around "absorbing" / "consuming" inputs based on focus. In order to
make that work properly though, we need gamepad support!
## Solution
The logic backing this has been changed to be generic for any cloneable
event types, and the machinery to make use of this externally has been
made `pub`.
Within the engine itself, I've added support for gamepad button and
scroll events, but nothing else. Mouse button / touch bubbling is
handled via bevy_picking, and mouse / gamepad motion doesn't really make
sense to bubble.
## Testing
The `tab_navigation` example continues to work, and CI is green.
## Future Work
I would like to add more complex UI examples to stress test this, but
not here please.
We should take advantage of the bubbled mouse scrolling when defining
scrolled widgets.
# Objective
In current Bevy, it is very inconvenient to mutably retrieve a
user-provided list of entities more than one element at a time.
If the list contains any duplicate entities, we risk mutable aliasing.
Users of `Query::iter_many_mut` do not have access to `Iterator` trait,
and thus miss out on common functionality, for instance collecting their
`QueryManyIter`.
We can circumvent this issue with validation, however that entails
checking every entity against all others for inequality, or utilizing an
`EntityHashSet`. Even if an entity list remains unchanged, this
validation is/would have to be redone every time we wish to fetch with
the list.
This presents a lot of wasted work, as we often trivially know an entity
list to be unique f.e.: `QueryIter` will fetch every `Entity` once and
only once.
As more things become entities – assets, components, queries – this
issue will become more pronounced.
`get_many`/`many`/`iter_many`/`par_iter_many`-like functionality is all
affected.
## Solution
The solution this PR proposes is to introduce functionality built around
a new trait: `EntitySet`.
The goal is to preserve the property of "uniqueness" in a list wherever
possible, and then rely on it as a bound within new `*_many_unique`
methods to avoid the need for validation.
This is achieved using `Iterator`:
`EntitySet` is blanket implemented for any `T` that implements
`IntoIterator<IntoIter: EntitySetIterator>`.
`EntitySetIterator` is the unsafe trait that actually guarantees an
iterator to be "unique" via its safety contract.
We define an "Iterator over unique entities" as: "No two entities
returned by the iterator may compare equal."
For iterators that cannot return more than 1 element, this is trivially
true.
Whether an iterator can satisfy this is up to the `EntitySetIterator`
implementor to ensure, hence the unsafe.
However, this is not yet a complete solution. Looking at the signature
of `iter_many`, we find that `IntoIterator::Item` is not `Entity`, but
is instead bounded by the `Borrow<Entity>` trait. That is because
iteration without consuming the collection will often yield us
references, not owned items.
`Borrow<Entity>` presents an issue: The `Borrow` docs state that `x = y`
should equal `x.borrow() = y.borrow()`, but unsafe cannot rely on this
for soundness. We run into similar problems with other trait
implementations of any `Borrow<Entity>` type: `PartialEq`, `Eq`,
`PartialOrd`, `Ord`, `Hash`, `Clone`, `Borrow`, and `BorrowMut`.
This PR solves this with the unsafe `TrustedEntityBorrow` trait:
Any implementor promises that the behavior of the aforementioned traits
matches that of the underlying entity.
While `Borrow<Entity>` was the inspiration, we use our own counterpart
trait `EntityBorrow` as the supertrait to `TrustedEntityBorrow`, so we
can circumvent the limitations of the existing `Borrow<T>` blanket
impls.
All together, these traits allow us to implement `*_many_unique`
functionality with a lone `EntitySet` bound.
`EntitySetIterator` is implemented for all the std iterators and
iterator adapters that guarantee or preserve uniqueness, so we can
filter, skip, take, step, reverse, ... our unique entity iterators
without worry!
Sadly, current `HashSet` iterators do not carry the necessary type
information with them to determine whether the source `HashSet` produces
logic errors; A malicious `Hasher` could compromise a `HashSet`.
`HashSet` iteration is generally discouraged in the first place, so we
also exclude the set operation iterators, even though they do carry the
`Hasher` type parameter.
`BTreeSet` implements `EntitySet` without any problems.
If an iterator type cannot guarantee uniqueness at compile time, then a
user can still attach `EntitySetIterator` to an individual instance of
that type via `UniqueEntityIter::from_iterator_unchecked`.
With this, custom types can use `UniqueEntityIter<I>` as their
`IntoIterator::IntoIter` type, if necessary.
This PR is focused on the base concept, and expansions on it are left
for follow-up PRs. See "Potential Future Work" below.
## Testing
Doctests on `iter_many_unique`/`iter_many_unique_mut` + 2 tests in
entity_set.rs.
## Showcase
```rust
// Before:
fn system(player_list: Res<SomeUniquePlayerList>, players: Query<&mut Player>) {
let value = 0;
while let Some(player) = players.iter_many_mut(player_list).fetch_next() {
value += mem::take(player.value_mut())
}
}
// After:
fn system(player_list: Res<SomeUniquePlayerList>, players: Query<&mut Player>) {
let value = players
.iter_many_unique_mut(player_list)
.map(|player| mem::take(player.value_mut()))
.sum();
}
```
## Changelog
- added `EntityBorrow`, `TrustedEntityBorrow`, `EntitySet` and
`EntitySetIterator` traits
- added `iter_many_unique`, `iter_many_unique_mut`,
`iter_many_unique_unsafe` methods on `Query`
- added `iter_many_unique`, `iter_many_unique_mut`,
`iter_many_unique_manual` and `iter_many_unique_unchecked_manual`
methods on `QueryState`
- added corresponding `QueryManyUniqueIter`
- added `UniqueEntityIter`
## Migration Guide
Any custom type used as a `Borrow<Entity>` entity list item for an
`iter_many` method now has to implement `EntityBorrow` instead. Any type
that implements `Borrow<Entity>` can trivially implement `EntityBorrow`.
## Potential Future Work
- `ToEntitySet` trait for converting any entity iterator into an
`EntitySetIterator`
- `EntityIndexSet/Map` to tie in hashing with `EntitySet`
- add `EntityIndexSetSlice/MapSlice`
- requires: `EntityIndexSet/Map`
- Implementing `par_iter_many_unique_mut` for parallel mutable iteration
- requires: `par_iter_many`
- allow collecting into `UniqueEntityVec` to store entity sets
- add `UniqueEntitySlice`s
- Doesn't require, but should be done after: `UniqueEntityVec`
- add `UniqueEntityArray`s
- Doesn't require, but should be done after: `UniqueEntitySlice`
- `get_many_unique`/`many_unique` methods
- requires: `UniqueEntityArray`
- `World::entity_unique` to match `World::entity` methods
- Doesn't require, but makes sense after:
`get_many_unique`/`many_unique`
- implement `TrustedEntityBorrow` for the `EntityRef` family
- Doesn't require, but makes sense after: `UniqueEntityVec`