# Objective
Fixes#9509
## Solution
We use the assumption, that enum types are uppercase in contrast to
module names.
[`collapse_type_name`](crates/bevy_util/src/short_names) is now
retaining the second last segment, if it starts with a uppercase
character.
---------
Co-authored-by: Emi <emanuel.boehm@gmail.com>
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
- Fixes#9533
## Solution
* Added `Val::ZERO` as a constant which is defined as `Val::Px(0.)`.
* Added manual `PartialEq` implementation for `Val` which allows any
zero value to equal any other zero value. E.g., `Val::Px(0.) ==
Val::Percent(0.)` etc. This is technically a breaking change, as
`Val::Px(0.) == Val::Percent(0.)` now equals `true` instead of `false`
(as an example)
* Replaced instances of `Val::Px(0.)`, `Val::Percent(0.)`, etc. with
`Val::ZERO`
* Fixed `bevy_ui::layout::convert::tests::test_convert_from` test to
account for Taffy not equating `Points(0.)` and `Percent(0.)`. These
tests now use `assert_eq!(...)` instead of `assert!(matches!(...))`
which gives easier to diagnose error messages.
# Objective
All delimiter symbols used by the path parser are ASCII, this means we
can entirely ignore UTF8 handling. This may improve performance.
## Solution
Instead of storing the path as an `&str` + the parser offset, and
reading the path using `&self.path[self.offset..]`, we store the parser
state in a `&[u8]`. This allows two optimizations:
1. Avoid UTF8 checking on `&self.path[self.offset..]`
2. Avoid any kind of bound checking, since the length of what is left to
read is stored in the `&[u8]`'s reference metadata, and is assumed valid
by the compiler.
This is a major improvement when comparing to the previous parser.
1. `access_following` and `next_token` now inline in `PathParser::next`
2. Benchmarking show a 20% performance increase (#9364)
Please note that while we ignore UTF-8 handling, **utf-8 is still
supported**. This is because we only handle "at the edges" what happens
exactly before and after a recognized `SYMBOL`. utf-8 is handled
transparently beyond that.
# Objective
- Unify the `ParsedPath` and `GetPath` APIs. They weirdly didn't play
well together.
- Make `ParsedPath` and `GetPath` API easier to use
## Solution
- Add the `ReflectPath` trait.
- `GetPath` methods now accept an `impl ReflectPath<'a>` instead of a
`&'a str`, this mean it also can accepts a `&ParsedPath`
- Make `GetPath: Reflect` and use default impl for `Reflect` types.
- Add `GetPath` and `ReflectPath` to the `bevy_reflect` prelude
---
## Changelog
- Add the `ReflectPath` trait.
- `GetPath` methods now accept an `impl ReflectPath<'a>` instead of a
`&'a str`, this mean it also can accept a `&ParsedPath`
- Make `GetPath: Reflect` and use default impl for `Reflect` types.
- Add `GetPath` and `ReflectPath` to the `bevy_reflect` prelude
## Migration Guide
`GetPath` now requires `Reflect`. This reduces a lot of boilerplate on
bevy's side. If you were implementing manually `GetPath` on your own
type, please get in touch!
`ParsedPath::element[_mut]` isn't an inherent method of `ParsedPath`,
you must now import `ReflectPath`. This is only relevant if you weren't
importing the bevy prelude.
```diff
-use bevy::reflect::ParsedPath;
+use bevy::reflect::{ParsedPath, ReflectPath};
parsed_path.element(reflect_type).unwrap()
parsed_path.element(reflect_type).unwrap()
# Objective
[Rust 1.72.0](https://blog.rust-lang.org/2023/08/24/Rust-1.72.0.html) is
now stable.
# Notes
- `let-else` formatting has arrived!
- I chose to allow `explicit_iter_loop` due to
https://github.com/rust-lang/rust-clippy/issues/11074.
We didn't hit any of the false positives that prevent compilation, but
fixing this did produce a lot of the "symbol soup" mentioned, e.g. `for
image in &mut *image_events {`.
Happy to undo this if there's consensus the other way.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- Fixes#9552
## Solution
- Only n_pixels bytes of data was being copied instead of 1 byte per
component, i.e. n_pixels * 4
---
## Changelog
- Fixed: loading of Rgb8 ktx2 files.
# Objective
- Fix blender gltf imports with emissive materials
- Progress towards https://github.com/bevyengine/bevy/issues/5178
## Solution
- Upgrade to gltf-rs 1.3 supporiting
[KHR_materials_emissive_strength](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md)
---
## Changelog
- GLTF files using `emissiveStrength` (such as those exported by
blender) are now supported
## Migration Guide
- The GLTF asset loader will now factor in `emissiveStrength` when
converting to Bevy's `StandardMaterial::emissive`. Blender will export
emissive materials using this field. Remove the field from your GLTF
files or manually modify your materials post-asset-load to match how
Bevy would load these files in previous versions.
# Objective
Fixes incorrect docs in `bevy_ui` for `JustifyItems` and `JustifySelf`.
## Solution
`JustifyItems` and `JustifySelf` target the main axis and not the cross
axis.
# Objective
`round_ties_up` checks the predicate:
```rust
0. <= value || value.fract() != 0.5
```
which is meant to determine if the value is negative with a fractional
part of `0.5`.
However given a negative value, `fract` returns a negative fraction so
the predicate is true for all numeric values and `ceil` is never called.
## Solution
Changed the predicate to `value.fract() != -0.5` and added a test.
Also improved the comments a bit.
# Objective
- A few of the `const DEFAULT` properties of the grid feature are not
marked as pub. This is an issue because it means you can't have a
`const` `Style` declaration anymore. Most of the existing properties are
already pub.
## Solution
- add the missing pub
# Objective
- Wireframe currently don't display since #9416
- There is an error
```
2023-08-20T10:06:54.190347Z ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
error: no definition in scope for identifier: 'vertex_no_morph'
┌─ crates/bevy_pbr/src/render/wireframe.wgsl:26:94
│
26 │ let model = bevy_pbr::mesh_functions::get_model_matrix(vertex_no_morph.instance_index);
│ ^^^^^^^^^^^^^^^ unknown identifier
│
= no definition in scope for identifier: 'vertex_no_morph'
```
## Solution
- Use the correct identifier
# Objective
- Resolves https://github.com/bevyengine/bevy/issues/9440
## Solution
- Remove the doc string mentioning the position of a `NodeBundle`, since
the doc string for the `style` component already explains this ability.
# Objective
- When spawning a window, it will be white until the GPU is ready to
draw the app. To avoid this, we can make the window invisible and then
make it visible once the gpu is ready. Unfortunately, the visible flag
is not available to users.
## Solution
- Let users change the visible flag
## Notes
This is only user controlled. It would be nice if it was done
automatically by bevy instead but I want to keep this PR simple.
# Objective
PR #6360 changed `TaskPoolOptions` so it is no longer used as a
Resource, but didn't remove the `Resource` derive.
## Solution
Remove the Resource derive from `TaskPoolOptions`, as it is no longer
needed. Also add a Debug derive, because it didn't have it before.
---
## Changelog
- `TaskPoolOptions` no longer derives Resource, and `TaskPoolOptions` &
`TaskPoolThreadAssignmentPolicy` now derive Debug.
## Migration Guide
If for some reason anyone is still using `TaskPoolOptions` as a
Resource, they would now have to use a wrapper type:
```rust
#[derive(Resource)]
pub struct MyTaskPoolOptions(pub TaskPoolOptions);
```
# Objective
Add `GamepadButtonInput` event
Resolves#8988
## Solution
- Add `GamepadButtonInput` type
- Emit `GamepadButtonInput` events whenever `Input<GamepadButton>` is
written to
- Update example
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
Fixes#9488
## Solution
Set point light radius to always be 0.0. Reading this value from glTF
would require using application specific extras property.
---
## Changelog
### Fixed
- #9488 Point Lights use Range for Radius when importing from GLTF
# Objective
Allow users to specify the power preference when selecting a wgpu
adapter, which is useful for testing or workaround purposes, and makes
the behaviour consistent with the already present check for
`WGPU_BACKEND`.
## Solution
In `WgpuSettings::default()`, allow users to specify the
`WGPU_POWER_PREF` to affect the wgpu adapter choice.
# Objective
fix#9452
when multiple assets are queued to a preregistered loader, only one gets
unblocked when the real loader is registered.
## Solution
i thought async_channel receivers worked like broadcast channels, but in
fact the notification is only received by a single receiver, so only a
single waiting asset is unblocked. close the sender instead so that all
blocked receivers are unblocked.
If a line has one point behind the camera(near plane) then it would
deform or, if the `depth_bias` setting was set to a negative value,
disappear.
## Solution
The issue is that performing a perspective divide does not work
correctly for points behind the near plane and a perspective divide is
used inside the shader to define the line width in screen space.
The solution is to perform near plane clipping manually inside the
shader before the perspective divide is done.
# Objective
Fixes#9455
This change has probably been forgotten in
https://github.com/bevyengine/bevy/pull/8306.
## Solution
Remove the inversion of the Y axis when propagates window change back to
winit.
# Objective
Inconvenient initialization of `UiScale`
## Solution
Change `UiScale` to a tuple struct
## Migration Guide
Replace initialization of `UiScale` like ```UiScale { scale: 1.0 }```
with ```UiScale(1.0)```
# Objective
- Fixes part of #9021
## Solution
- Joint mesh are in format `Unorm8x4` in some gltf file, but Bevy
expects a `Float32x4`. Converts them. Also converts `Unorm16x4`
- According to gltf spec:
https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes
> WEIGHTS_n: float, or normalized unsigned byte, or normalized unsigned
short
# Objective
Fix#9089
## Solution
Don't try to draw lines with less than 2 vertices. These would not be
visible either way.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- Currently, (AFAIC, accidentally) after registering an event for a
Gilrs button event, we ignore all subsequent events for the same button
in the same frame, because we don't update our filter. This is rare, but
I noticed it while adding gamepad support to a terminal app rendering at
15fps.
- Related to #4664, but does not quite fix it.
## Solution
- Move the edit to the `Axis<GamepadButton>` resource to when we read
the events from Gilrs.
# Objective
Closes#9115, replaces #9117.
## Solution
Emit event when scene is ready.
---
## Changelog
### Added
- `SceneInstanceReady` event when scene becomes ready.
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/9250
## Changelog
- Move scene spawner systems to a new SpawnScene schedule which is after
Update and before PostUpdate (schedule order:
[PreUpdate][Update][SpawnScene][PostUpdate])
## Migration Guide
- Move scene spawner systems to a new SpawnScene schedule which is after
Update and before PostUpdate (schedule order:
[PreUpdate][Update][SpawnScene][PostUpdate]), you might remove system
ordering code related to scene spawning as the execution order has been
guaranteed by bevy engine.
---------
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
Updates the requirements on
[tracy-client](https://github.com/nagisa/rust_tracy_client) to permit
the latest version.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="f38da93ff1"><code>f38da93</code></a>
Test with 1.63.0 for MSRV</li>
<li><a
href="3621e20ccd"><code>3621e20</code></a>
tracing-client-sys: 0.21.1</li>
<li><a
href="bccf04b152"><code>bccf04b</code></a>
tracing-tracy: 0.10.3</li>
<li><a
href="bff27b5218"><code>bff27b5</code></a>
tracy-client: 0.15.2 -> 0.16.0 + fix auto update</li>
<li><a
href="9ed943bd6b"><code>9ed943b</code></a>
Add safe GPU API</li>
<li><a
href="60443cc55c"><code>60443cc</code></a>
Benches fell out of sync</li>
<li><a
href="c346a10998"><code>c346a10</code></a>
Fix version table typo</li>
<li><a
href="0763d2d16c"><code>0763d2d</code></a>
Bump MSRV to 1.60.0</li>
<li><a
href="d483998d48"><code>d483998</code></a>
Update Tracy client bindings to v0.9.1</li>
<li><a
href="dce363444f"><code>dce3634</code></a>
client-sys: 0.20.0, client: 0.15.1, tracing: 0.10.2</li>
<li>Additional commits viewable in <a
href="https://github.com/nagisa/rust_tracy_client/compare/tracy-client-v0.15.0...tracy-client-v0.16.0">compare
view</a></li>
</ul>
</details>
<br />
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
- Significantly reduce the size of MeshUniform by only including
necessary data.
## Solution
Local to world, model transforms are affine. This means they only need a
4x3 matrix to represent them.
`MeshUniform` stores the current, and previous model transforms, and the
inverse transpose of the current model transform, all as 4x4 matrices.
Instead we can store the current, and previous model transforms as 4x3
matrices, and we only need the upper-left 3x3 part of the inverse
transpose of the current model transform. This change allows us to
reduce the serialized MeshUniform size from 208 bytes to 144 bytes,
which is over a 30% saving in data to serialize, and VRAM bandwidth and
space.
## Benchmarks
On an M1 Max, running `many_cubes -- sphere`, main is in yellow, this PR
is in red:
<img width="1484" alt="Screenshot 2023-08-11 at 02 36 43"
src="https://github.com/bevyengine/bevy/assets/302146/7d99c7b3-f2bb-4004-a8d0-4c00f755cb0d">
A reduction in frame time of ~14%.
---
## Changelog
- Changed: Redefined `MeshUniform` to improve performance by using 4x3
affine transforms and reconstructing 4x4 matrices in the shader. Helper
functions were added to `bevy_pbr::mesh_functions` to unpack the data.
`affine_to_square` converts the packed 4x3 in 3x4 matrix data to a 4x4
matrix. `mat2x4_f32_to_mat3x3` converts the 3x3 in mat2x4 + f32 matrix
data back into a 3x3.
## Migration Guide
Shader code before:
```
var model = mesh[instance_index].model;
```
Shader code after:
```
#import bevy_pbr::mesh_functions affine_to_square
var model = affine_to_square(mesh[instance_index].model);
```
# Objective
- When loading gltf files during app creation (for example using a
FromWorld impl and adding that as a resource), no loader was found.
- As the gltf loader can load compressed formats, it needs to know what
the GPU supports so it's not available at app creation time.
## Solution
alternative to #9426
- add functionality to preregister the loader. loading assets with
matching extensions will block until a real loader is registered.
- preregister "gltf" and "glb".
- prereigster image formats.
the way this is set up, if a set of extensions are all registered with a
single preregistration call, then later a loader is added that matches
some of the extensions, assets using the remaining extensions will then
fail. i think that should work well for image formats that we don't know
are supported until later.
While being nobody other's issue as far I can tell, I want to create a
trait I plan to implement on `App` where more than one schedule is
modified.
My workaround so far was working with a closure that returns an
`ExecutorKind` from a match of the method variable.
It makes it easier for me to being able to clone `ExecutorKind` and I
don't see this being controversial for others working with Bevy.
I did nothing more than adding `Clone` to the derived traits, no
migration guide needed.
(If this worked out then the GitHub editor is not too shabby.)
# Objective
Bevy prefers `mod.rs` inside `module_name` files over `module_name.rs`
collocated with `module_name`. In `bevy_render`, it seems the `window`
modules didn't follow this convention
## Solution
- Follow the `mod.rs` convention.
# Objective
- Fixes#9324
- Audio sinks used to have a custom drop implementation to detach the
sinks because it was not required to keep a reference to it
- With the new audio api, a reference is kept as a component of an
entity
## Solution
- Remove that custom drop implementation, and the option wrapping that
was required for it.
# Objective
Just like
[`set_if_neq`](https://docs.rs/bevy_ecs/latest/bevy_ecs/change_detection/trait.DetectChangesMut.html#method.set_if_neq),
being able to express the "I don't want to unnecessarily trigger the
change detection" but with the ability to handle the previous value if
change occurs.
## Solution
Add `replace_if_neq` to `DetectChangesMut`.
---
## Changelog
- Added `DetectChangesMut::replace_if_neq`: like `set_if_neq` change the
value only if the new value if different from the current one, but
return the previous value if the change occurs.
# Objective
I found it very difficult to understand how bevy tasks work, and I
concluded that the documentation should be improved for beginners like
me.
## Solution
These changes to the documentation were written from my beginner's
perspective after
some extremely helpful explanations by nil on Discord.
I am not familiar enough with rustdoc yet; when looking at the source, I
found the documentation at the very top of `usages.rs` helpful, but I
don't know where they are rendered. They should probably be linked to
from the main `bevy_tasks` README.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Mike <mike.hsu@gmail.com>
# Objective
In `bevy_sprite`, the `Anchor` type is not `Copy`. It makes interacting
with it more difficult than necessary.
## Solution
Derive `Copy` on it. The rust API guidelines are that you should derive
`Copy` when possible.
<https://rust-lang.github.io/api-guidelines/interoperability.html#types-eagerly-implement-common-traits-c-common-traits>
Regardless, `Anchor` is a very small `enum` which warrants `Copy`.
---
## Changelog
- In `bevy_sprite` `Anchor` is now `Copy`.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Need this for a custom `AnimationPlayer` that I tick in `FixedUpdate`
# Objective
- Need access to an animation clip's `paths` from outside the module
## Solution
- Add a getter method to return a reference to `paths`
---------
Co-authored-by: Tristan Guichaoua <33934311+tguichaoua@users.noreply.github.com>
Add a `RunSystem` extension trait to allow for immediate execution of
systems on a `World` for debugging and/or testing purposes.
# Objective
Fixes#6184
Initially, I made this CL as `ApplyCommands`. After a discussion with
@cart , we decided a more generic implementation would be better to
support all systems. This is the new revised CL. Sorry for the long
delay! 😅
This CL allows users to do this:
```rust
use bevy::prelude::*;
use bevy::ecs::system::RunSystem;
struct T(usize);
impl Resource for T {}
fn system(In(n): In<usize>, mut commands: Commands) -> usize {
commands.insert_resource(T(n));
n + 1
}
let mut world = World::default();
let n = world.run_system_with(1, system);
assert_eq!(n, 2);
assert_eq!(world.resource::<T>().0, 1);
```
## Solution
This is implemented as a trait extension and not included in any
preludes to ensure it's being used consciously.
Internally, it just initializes and runs a systems, and applies any
deferred parameters all "in place".
The trait has 2 functions (one of which calls the other by default):
- `run_system_with` is the general implementation, which allows user to
pass system input parameters
- `run_system` is the ergonomic wrapper for systems with no input
parameter (to avoid having the user pass `()` as input).
~~Additionally, this trait is also implemented for `&mut App`. I added
this mainly for ergonomics (`app.run_system` vs.
`app.world.run_system`).~~ (Removed based on feedback)
---------
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
# Objective
Add possibility to use the glam's swizzles traits without having to
manually import them.
```diff
use bevy::prelude::*;
- use bevy::math::Vec3Swizzles;
fn foo(x: Vec3) {
let y: Vec2 = x.xy();
}
```
## Solution
Add the swizzles traits to bevy's prelude.
---
## Changelog
- `Vec2Swizzles`, `Vec3Swizzles` and `Vec4Swizzles` are now part of the
prelude.
# Objective
Fixes#9094
## Solution
Takes a bit from
[this](https://github.com/bevyengine/bevy/issues/9094#issuecomment-1629333851)
comment as well as a
[comment](https://discord.com/channels/691052431525675048/1002362493634629796/1128024873260810271)
from @soqb.
This allows users to opt-out of the `TypePath` implementation that is
automatically generated by the `Reflect` derive macro, allowing custom
`TypePath` implementations.
```rust
#[derive(Reflect)]
#[reflect(type_path = false)]
struct Foo<T> {
#[reflect(ignore)]
_marker: PhantomData<T>,
}
struct NotTypePath;
impl<T: 'static> TypePath for Foo<T> {
fn type_path() -> &'static str {
std::any::type_name::<Self>()
}
fn short_type_path() -> &'static str {
static CELL: GenericTypePathCell = GenericTypePathCell::new();
CELL.get_or_insert::<Self, _>(|| {
bevy_utils::get_short_name(std::any::type_name::<Self>())
})
}
fn crate_name() -> Option<&'static str> {
Some("my_crate")
}
fn module_path() -> Option<&'static str> {
Some("my_crate::foo")
}
fn type_ident() -> Option<&'static str> {
Some("Foo")
}
}
// Can use `TypePath`
let _ = <Foo<NotTypePath> as TypePath>::type_path();
// Can register the type
let mut registry = TypeRegistry::default();
registry.register::<Foo<NotTypePath>>();
```
#### Type Path Stability
The stability of type paths mainly come into play during serialization.
If a type is moved between builds, an unstable type path may become
invalid.
Users that opt-out of `TypePath` and rely on something like
`std::any::type_name` as in the example above, should be aware that this
solution removes the stability guarantees. Deserialization thus expects
that type to never move. If it does, then the serialized type paths will
need to be updated accordingly.
If a user depends on stability, they will need to implement that
stability logic manually (probably by looking at the expanded output of
a typical `Reflect`/`TypePath` derive). This could be difficult for type
parameters that don't/can't implement `TypePath`, and will need to make
heavy use of string parsing and manipulation to achieve the same effect
(alternatively, they can choose to simply exclude any type parameter
that doesn't implement `TypePath`).
---
## Changelog
- Added the `#[reflect(type_path = false)]` attribute to opt out of the
`TypePath` impl when deriving `Reflect`
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Update a camera's frustum only when needed.
- Maybe a performance gain from not having to compute frusta when not
needed, at the cost of change detection (?)
- Making "fighting" with `update_frusta` less tedious, see
https://github.com/bevyengine/bevy/issues/9077 and
https://discord.com/channels/691052431525675048/743663924229963868/1127566087966433322
## Solution
Add change detection filter for `GlobalTransform` or `T:
CameraProjection` in `update_frusta`, since those are the cases when the
frustum needs to be updated.
## Note
I don't think a migration guide and changelog are needed, but I'm not
100% sure, I could put something like "if you're fighting against
`update_frusta`, you can do it only when there is a change to
`GlobalTransform` or `CameraProjection` now", what do you think? It's
not really a breaking change with a normal use case.
naga and wgpu should polyfill WGSL instance_index functionality where it
is not available in GLSL. Until that is done, we can work around it in
bevy using a push constant which is converted to a uniform by naga and
wgpu.
# Objective
- Fixes#9375
## Solution
- Use a push constant to pass in the base instance to the shader on
WebGL2 so that base instance + gl_InstanceID is used to correctly
represent the instance index.
## TODO
- [ ] Benchmark vs per-object dynamic offset MeshUniform as this will
now push a uniform value per-draw as well as update the dynamic offset
per-batch.
- [x] Test on DX12 AMD/NVIDIA to check that this PR does not regress any
problems that were observed there. (@Elabajaba @robtfm were testing that
last time - help appreciated. <3 )
---
## Changelog
- Added: `bevy_render::instance_index` shader import which includes a
workaround for the lack of a WGSL `instance_index` polyfill for WebGL2
in naga and wgpu for the time being. It uses a push_constant which gets
converted to a plain uniform by naga and wgpu.
## Migration Guide
Shader code before:
```
struct Vertex {
@builtin(instance_index) instance_index: u32,
...
}
@vertex
fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
...
var model = mesh[vertex_no_morph.instance_index].model;
```
After:
```
#import bevy_render::instance_index
struct Vertex {
@builtin(instance_index) instance_index: u32,
...
}
@vertex
fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
...
var model = mesh[bevy_render::instance_index::get_instance_index(vertex_no_morph.instance_index)].model;
```
# Objective
The default for `ContentSize` should have the `measure_func` field set
to `None`, instead of a fixed size of zero. This means that until a
measure func is set the size of the UI node will be determined by its
`Style` constraints. This is preferable as it allows users to specify
the space the Node should take up in the layout while waiting for
content to load.
## Solution
Derive `Default` for `ContentSize`.
The PR also adds a `fixed_size` helper function to make it a bit easier
to access the old behaviour.
## Changelog
* Derived `Default` for `ContentSize`
* Added a `fixed_size` helper function to `ContentSize` that creates a
new `ContentSize` with a `MeasureFunc` that always returns the same
value, regardless of layout constraints.
## Migration Guide
The default for `ContentSize` now sets its `measure_func` to `None`,
instead of a fixed size measure that returns `Vec2::ZERO`.
The helper function `fixed_size` can be called with
`ContentSize::fixed_size(Vec2::ZERO)` to get the previous behaviour.
# Objective
It seems the behavior of field attributes was accidentally broken at
some point. Take the following code:
```rust
#[derive(Reflect)]
struct Foo {
#[reflect(ignore, default)]
value: usize
}
```
The above code should simply mark `value` as ignored and specify a
default behavior. However, what this actually does is discard both.
That's especially a problem when we don't want the field to be be given
a `Reflect` or `FromReflect` bound (which is why we ignore it in the
first place).
This only happens when the attributes are combined into one. The
following code works properly:
```rust
#[derive(Reflect)]
struct Foo {
#[reflect(ignore)]
#[reflect(default)]
value: usize
}
```
## Solution
Cleaned up the field attribute parsing logic to support combined field
attributes.
---
## Changelog
- Fixed a bug where `Reflect` derive attributes on fields are not able
to be combined into a single attribute
# Objective
- Follow up to #8887
- The parsing code in `bevy_reflect/src/path/mod.rs` could also do with
some cleanup
## Solution
- Create the `parse.rs` module, move all parsing code to this module
- The parsing errors also now keep track of the whole parsed string, and
are much more fine-grained
### Detailed changes
- Move `PathParser` to `parse.rs` submodule
- Rename `token_to_access` to `access_following` (yep, goes from 132
lines to 16)
- Move parsing tests into the `parse.rs` file
# Objective
The doc comment for `text_system` is not quite correct. It implies that
a new `TextLayoutInfo` is generated on changes to `Text` and `Style`.
While changes to those components might indirectly trigger a
regeneration of the text layout, `text_system` itself only queries for
changes to `Node`
Also added details to `measure_text_system`'s doc comments explaining
how it reacts to changes.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- `bevy_tasks` emits warnings under certain conditions
When I run `cargo clippy -p bevy_tasks` the warning doesn't show up,
while if I run it with `cargo clippy -p bevy_asset` the warning shows
up.
## Solution
- Fix the warnings.
## Longer term solution
We should probably fix CI so that those warnings do not slip through.
But that's not the goal of this PR.
# Objective
This doc comment for the `set` method of `ContentSize`:
```
Set a `Measure` for this function
```
doesn't seem to make sense, `ContentSize` is not a function.
# Solution
Replace it.
# Objective
When an `AudioSink` is removed from an entity, the audio player will
automatically start any `AudioSource` still attached, which normally is
the one used to start playback in the first place.
## Solution
Long story short, the default behavior is restarting the audio, and this
commit documents that.
---
## Changelog
Fixed documentation on `AudioSink` to clarify removal behavior.
# Objective
shader defs associated with a shader via `load_internal_asset!` or
`Shader::from_xxx_with_defs` were being accidentally ignored for
top-level shaders.
## Solution
include the defs for top level shaders.
# Objective
- Fixes#9114
## Solution
Inside `ScheduleGraph::build_schedule()` the variable `node_count =
self.systems.len() + self.system_sets.len()` is used to calculate the
indices for the `reachable` bitset derived from `self.hierarchy.graph`.
However, the number of nodes inside `self.hierarchy.graph` does not
always correspond to `self.systems.len() + self.system_sets.len()` when
`ambiguous_with` is used, because an ambiguous set is added to
`system_sets` (because we need an `NodeId` for the ambiguity graph)
without adding a node to `self.hierarchy`.
In this PR, we rename `node_count` to the more descriptive name
`hg_node_count` and set it to `self.hierarchy.graph.node_count()`.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
Fixes#9113
## Solution
disable `multi-threaded` default feature
## Migration Guide
The `multi-threaded` feature in `bevy_ecs` and `bevy_tasks` is no longer
enabled by default. However, this remains a default feature for the
umbrella `bevy` crate. If you depend on `bevy_ecs` or `bevy_tasks`
directly, you should consider enabling this to allow systems to run in
parallel.
Fixes#5856. Fixes#8080. Fixes#9040.
# Objective
We need to limit the update rate of games whose windows are not visible
(minimized or completely occluded). Compositors typically ignore the
VSync settings of windows that aren't visible. That, combined with the
lack of rendering work, results in a scenario where an app becomes
completely CPU-bound and starts updating without limit.
There are currently three update modes.
- `Continuous` updates an app as often as possible.
- `Reactive` updates when new window or device events have appeared, a
timer expires, or a redraw is requested.
- `ReactiveLowPower` is the same as `Reactive` except it ignores device
events (e.g. general mouse movement).
The problem is that the default "game" settings are set to `Contiuous`
even when no windows are visible.
### More Context
- https://github.com/libsdl-org/SDL/issues/1871
- https://github.com/glfw/glfw/issues/680
- https://github.com/godotengine/godot/issues/19741
- https://github.com/godotengine/godot/issues/64708
## Solution
Change the default "unfocused" `UpdateMode` for games to
`ReactiveLowPower` just like desktop apps. This way, even when the
window is occluded, the app still updates at a sensible rate or if
something about the window changes. I chose 20Hz arbitrarily.
# Objective
The `lifetimeless` module has been a source of confusion for bevy users
for a while now.
## Solution
Add a couple paragraph explaining that, yes, you can use one of the type
alias safely, without ever leaking any memory.
Redo of #7590 since I messed up my branch.
# Objective
- Revise docs.
- Refactor event loop code a little bit to make it easier to follow.
## Solution
- Do the above.
---
### Migration Guide
- `UpdateMode::Reactive { max_wait: .. }` -> `UpdateMode::Reactive {
wait: .. }`
- `UpdateMode::ReactiveLowPower { max_wait: .. }` ->
`UpdateMode::ReactiveLowPower { wait: .. }`
---------
Co-authored-by: Sélène Amanita <134181069+Selene-Amanita@users.noreply.github.com>
# Objective
Remove the `With<Parent>` query filter from the `parent_node_query`
parameter of the `bevy_ui::render::extract_uinode_borders` function.
This is a bug, the query is only used to retrieve the size of the
current node's parent. We don't care if that parent node has a `Parent`
or not.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- Fixes#9138
## Solution
- Calling `Camera2dBundle::default()` will now result in a
`Camera2dBundle` with `Vec3::ZERO` transform, `far` value of `1000.` and
`near` value of `-1000.`.
- This will enable the rendering of 2d entities in negative z space by
default.
- I did not modify `new_with_far` as moving the camera to `Vec3::ZERO`
in that function will cause entities in the positive z space to become
hidden without further changes. And the further changes cannot be
applied without it being a breaking change.
# Objective
Glam 0.24 added new glam types (```I64Vec``` and ```U64Vec```). However
these are not reflectable unlike the other glam types
## Solution
Implement reflect for these new types
---
## Changelog
Implements reflect with the impl_reflect_struct macro on ```I64Vec2```,
```I64Vec3```, ```I64Vec4```, ```U64Vec2```, ```U64Vec3```, and
```U64Vec4``` types
# Objective
- Repeat in `Gizmos` that they are drawned in immediate mode, which is
said at the module level but not here, and detail what it means.
- Clarify for every method of `Gizmos` that they should be called for
every frame.
- Clarify which methods belong to 3D or 2D space (kinda obvious for 2D
but still)
The first time I used gizmos I didn't understand how they work and was
confused as to why nothing showed up.
---------
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- In bevy_polyline, we discovered an issue that happens when line width
is smaller than 1.0 and using perspective. It would sometimes end up
negative or NaN. I'm not entirely sure _why_ it happens.
## Solution
- Make sure the width doesn't go below 0 before multiplying it with the
alpha
# Notes
Here's a link to the bevy_polyline issue
https://github.com/ForesightMiningSoftwareCorporation/bevy_polyline/issues/46
I'm not sure if the solution is correct but it solved the issue in my
testing.
Co-authored-by: François <mockersf@gmail.com>
# Objective
This PR continues https://github.com/bevyengine/bevy/pull/8885
It aims to improve the `Mesh` documentation in the following ways:
- Put everything at the "top level" instead of the "impl".
- Explain better what is a Mesh, how it can be created, and that it can
be edited.
- Explain it can be used with a `Material`, and mention
`StandardMaterial`, `PbrBundle`, `ColorMaterial`, and
`ColorMesh2dBundle` since those cover most cases
- Mention the glTF/Bevy vocabulary discrepancy for "Mesh"
- Add an image for the example
- Various nitpicky modifications
## Note
- The image I added is 90.3ko which I think is small enough?
- Since rustdoc doesn't allow cross-reference not in dependencies of a
subcrate [yet](https://github.com/rust-lang/rust/issues/74481), I have a
lot of backtick references that are not links :(
- Since rustdoc doesn't allow linking to code in the crate (?) I put
link to github directly.
- Since rustdoc doesn't allow embed images in doc
[yet](https://github.com/rust-lang/rust/issues/32104), maybe
[soon](https://github.com/rust-lang/rfcs/pull/3397), I had to put only a
link to the image. I don't think it's worth adding
[embed_doc_image](https://docs.rs/embed-doc-image/latest/embed_doc_image/)
as a dependency for this.
# Objective
- Fix shader_material_glsl example
## Solution
- Expose the `PER_OBJECT_BUFFER_BATCH_SIZE` shader def through the
default `MeshPipeline` specialization.
- Make use of it in the `custom_material.vert` shader to access the mesh
binding.
---
## Changelog
- Added: Exposed the `PER_OBJECT_BUFFER_BATCH_SIZE` shader def through
the default `MeshPipeline` specialization to use in custom shaders not
using bevy_pbr::mesh_bindings that still want to use the mesh binding in
some way.
# Objective
- The `path` module was getting fairly large.
- The code in `AccessRef::read_element` and mut equivalent was very
complex and difficult to understand.
- The `ReflectPathError` had a lot of variants, and was difficult to
read.
## Solution
- Split the file in two, `access` now has its own module
- Rewrite the `read_element` methods, they were ~200 lines long, they
are now ~70 lines long — I didn't change any of the logic. It's really
just the same code, but error handling is separated.
- Split the `ReflectPathError` error
- Merge `AccessRef` and `Access`
- A few other changes that aim to reduce code complexity
### Fully detailed change list
- `Display` impl of `ParsedPath` now includes prefix dots — this allows
simplifying its implementation, and IMO `.path.to.field` is a better way
to express a "path" than `path.to.field` which could suggest we are
reading the `to` field of a variable named `path`
- Add a test to check that dot prefixes and other are correctly parsed —
Until now, no test contained a prefixing dot
- Merge `Access` and `AccessRef`, using a `Cow<'a, str>`. Generated code
seems to agree with this decision (`ParsedPath::parse` sheds 5% of
instructions)
- Remove `Access::as_ref` since there is no such thing as an `AccessRef`
anymore.
- Rename `AccessRef::to_owned` into `AccessRef::into_owned()` since it
takes ownership of `self` now.
- Add a `parse_static` that doesn't allocate new strings for named
fields!
- Add a section about path reflection in the `bevy_reflect` crate root
doc — I saw a few people that weren't aware of path reflection, so I
thought it was pertinent to add it to the root doc
- a lot of nits
- rename `index` to `offset` when it refers to offset in the path string
— There is no more confusion with the other kind of indices in this
context, also it's a common naming convention for parsing.
- Make a dedicated enum for parsing errors
- rename the `read_element` methods to `element` — shorter, but also
`read_element_mut` was a fairly poor name
- The error values now not only contain the expected type but also the
actual type.
- Remove lifetimes that could be inferred from the `GetPath` trait
methods.
---
## Change log
- Added the `ParsedPath::parse_static` method, avoids allocating when
parsing `&'static str`.
## Migration Guide
If you were matching on the `Err(ReflectPathError)` value returned by
`GetPath` and `ParsedPath` methods, now only the parse-related errors
and the offset are publicly accessible. You can always use the
`fmt::Display` to get a clear error message, but if you need
programmatic access to the error types, please open an issue.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
- attempt to clarify with better docstrings the default behaviour of
WindowPlugin and the component type it accepts.
# Objective
- I'm new to Rust and Bevy, I got a bit confused about how to customise
some window parameters (title, height, width etc) and while the docs do
show the struct code for that field `Option<Window>` I was a bit of a
doofus and skipped that to read the docstring entry for `primary_window`
and then the `Window` component directly which aren't linked together.
This is a minor improvement which I think will help in-case others, like
me, have a doofus moment.
---------
Co-authored-by: Sélène Amanita <134181069+Selene-Amanita@users.noreply.github.com>
# Objective
This PR updates the name of the enum variant used in the docs for
`OrthographicProjection`.
## Solution
- Change the outdated 'WindowScale` to `WindowSize`.
# Objective
- Reduce the number of rebindings to enable batching of draw commands
## Solution
- Use the new `GpuArrayBuffer` for `MeshUniform` data to store all
`MeshUniform` data in arrays within fewer bindings
- Sort opaque/alpha mask prepass, opaque/alpha mask main, and shadow
phases also by the batch per-object data binding dynamic offset to
improve performance on WebGL2.
---
## Changelog
- Changed: Per-object `MeshUniform` data is now managed by
`GpuArrayBuffer` as arrays in buffers that need to be indexed into.
## Migration Guide
Accessing the `model` member of an individual mesh object's shader
`Mesh` struct the old way where each `MeshUniform` was stored at its own
dynamic offset:
```rust
struct Vertex {
@location(0) position: vec3<f32>,
};
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = mesh_position_local_to_clip(
mesh.model,
vec4<f32>(vertex.position, 1.0)
);
return out;
}
```
The new way where one needs to index into the array of `Mesh`es for the
batch:
```rust
struct Vertex {
@builtin(instance_index) instance_index: u32,
@location(0) position: vec3<f32>,
};
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = mesh_position_local_to_clip(
mesh[vertex.instance_index].model,
vec4<f32>(vertex.position, 1.0)
);
return out;
}
```
Note that using the instance_index is the default way to pass the
per-object index into the shader, but if you wish to do custom rendering
approaches you can pass it in however you like.
---------
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
# Objective
My attempt at implementing #7515
## Solution
Added struct `Pitch` and implemented on it `Source` trait.
## Changelog
### Added
- File pitch.rs to bevy_audio crate
- Struct `Pitch` and type aliases for `AudioSourceBundle<Pitch>` and
`SpatialAudioSourceBundle<Pitch>`
- New example showing how to use `PitchBundle`
### Changed
- `AudioPlugin` now adds system for `Pitch` audio
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
The previous formatting didn't render as you'd expect, with 'For CSS
Grid containers' getting adopted by the prior bullet point. Rather than
fixing that directly I opted for a slight reformatting for consistency
with other fields, notably left/right/top/bottom.
# Objective
Fixes#9298 - Default window title leaks "bevy" context
## Solution
I just replaced the literal string "Bevy App" with "App" in Window's
Default trait implementation.
# Objective
Cloning a `WorldQuery` type's "fetch" struct was made unsafe in #5593,
by adding the `unsafe fn clone_fetch` to `WorldQuery`. However, as that
method's documentation explains, it is not the right place to put the
safety invariant:
> While calling this method on its own cannot cause UB it is marked
`unsafe` as the caller must ensure that the returned value is not used
in any way that would cause two `QueryItem<Self>` for the same
`archetype_index` or `table_row` to be alive at the same time.
You can clone a fetch struct all you want and it will never cause
undefined behavior -- in order for something to go wrong, you need to
improperly call `WorldQuery::fetch` with it (which is marked unsafe).
Additionally, making it unsafe to clone a fetch struct does not even
prevent undefined behavior, since there are other ways to incorrectly
use a fetch struct. For example, you could just call fetch more than
once for the same entity, which is not currently forbidden by any
documented invariants.
## Solution
Document a safety invariant on `WorldQuery::fetch` that requires the
caller to not create aliased `WorldQueryItem`s for mutable types. Remove
the `clone_fetch` function, and add the bound `Fetch: Clone` instead.
---
## Changelog
- Removed the associated function `WorldQuery::clone_fetch`, and added a
`Clone` bound to `WorldQuery::Fetch`.
## Migration Guide
### `fetch` invariants
The function `WorldQuery::fetch` has had the following safety invariant
added:
> If this type does not implement `ReadOnlyWorldQuery`, then the caller
must ensure that it is impossible for more than one `Self::Item` to
exist for the same entity at any given time.
This invariant was always required for soundness, but was previously
undocumented. If you called this function manually anywhere, you should
check to make sure that this invariant is not violated.
### Removed `clone_fetch`
The function `WorldQuery::clone_fetch` has been removed. The associated
type `WorldQuery::Fetch` now has the bound `Clone`.
Before:
```rust
struct MyFetch<'w> { ... }
unsafe impl WorldQuery for MyQuery {
...
type Fetch<'w> = MyFetch<'w>
unsafe fn clone_fetch<'w>(fetch: &Self::Fetch<'w>) -> Self::Fetch<'w> {
MyFetch {
field1: fetch.field1,
field2: fetch.field2.clone(),
...
}
}
}
```
After:
```rust
#[derive(Clone)]
struct MyFetch<'w> { ... }
unsafe impl WorldQuery for MyQuery {
...
type Fetch<'w> = MyFetch<'w>;
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes https://github.com/bevyengine/bevy/issues/9234
re-breaks: The issues that were linked in #9169
## Solution
Revert the PR that broke tonemapping/postprocessing/etc.
Any passes that are post msaa resolve need to use the main textures, not
the msaa texture.
## Changelog
Idk what to put here since it's a revert.
# Objective
Fixes#9097
## Solution
Reorder the `ExtractSchedule` so that the `extract_text_uinodes` and
`extract_uinode_borders` systems are run after `extract_atlas_uinodes`.
## Changelog
`bevy_ui::render`:
* Added the `ExtractAtlasNode` variant to `RenderUiSystem`.
* Changed `ExtractSchedule` so that `extract_uinode_borders` and
`extract_text_uinodes` run after `extract_atlas_uinodes`.
This is not used directly within the rendering code.
# Objective
- Remove extraneous dependency on `wgpu-hal` as it is not used.
## Solution
- The dependency has been removed and should have no externally visible
impact.
# Objective
The `QueryParIter::for_each_mut` function is required when doing
parallel iteration with mutable queries.
This results in an unfortunate stutter:
`query.par_iter_mut().par_for_each_mut()` ('mut' is repeated).
## Solution
- Make `for_each` compatible with mutable queries, and deprecate
`for_each_mut`. In order to prevent `for_each` from being called
multiple times in parallel, we take ownership of the QueryParIter.
---
## Changelog
- `QueryParIter::for_each` is now compatible with mutable queries.
`for_each_mut` has been deprecated as it is now redundant.
## Migration Guide
The method `QueryParIter::for_each_mut` has been deprecated and is no
longer functional. Use `for_each` instead, which now supports mutable
queries.
```rust
// Before:
query.par_iter_mut().for_each_mut(|x| ...);
// After:
query.par_iter_mut().for_each(|x| ...);
```
The method `QueryParIter::for_each` now takes ownership of the
`QueryParIter`, rather than taking a shared reference.
```rust
// Before:
let par_iter = my_query.par_iter().batching_strategy(my_batching_strategy);
par_iter.for_each(|x| {
// ...Do stuff with x...
par_iter.for_each(|y| {
// ...Do nested stuff with y...
});
});
// After:
my_query.par_iter().batching_strategy(my_batching_strategy).for_each(|x| {
// ...Do stuff with x...
my_query.par_iter().batching_strategy(my_batching_strategy).for_each(|y| {
// ...Do nested stuff with y...
});
});
```
# Objective
Fixes#9121
Context:
- `ImageTextureLoader` depends on `RenderDevice` to work out which
compressed image formats it can support
- `RenderDevice` is initialised by `RenderPlugin`
- https://github.com/bevyengine/bevy/pull/8336 made `RenderPlugin`
initialisation async
- This caused `RenderDevice` to be missing at the time of
`ImageTextureLoader` initialisation, which in turn meant UASTC encoded
ktx2 textures were being converted to unsupported formats, and thus
caused panics
## Solution
- Delay `ImageTextureLoader` initialisation
---
## Changelog
- Moved `ImageTextureLoader` initialisation from `ImagePlugin::build()`
to `ImagePlugin::finish()`
- Default to `CompressedImageFormats::NONE` if `RenderDevice` resource
is missing
---------
Co-authored-by: 66OJ66 <hi0obxud@anonaddy.me>
### **Adopted #6430**
# Objective
`MutUntyped` is the untyped variant of `Mut<T>` that stores a `PtrMut`
instead of a `&mut T`. Working with a `MutUntyped` is a bit annoying,
because as soon you want to use the ptr e.g. as a `&mut dyn Reflect` you
cannot use a type like `Mut<dyn Reflect>` but instead need to carry
around a `&mut dyn Reflect` and a `impl FnMut()` to mark the value as
changed.
## Solution
* Provide a method `map_unchanged` to turn a `MutUntyped` into a
`Mut<T>` by mapping the `PtrMut<'a>` to a `&'a mut T`
This can be used like this:
```rust
// SAFETY: ptr is of type `u8`
let val: Mut<u8> = mut_untyped.map_unchanged(|ptr| unsafe { ptr.deref_mut::<u8>() });
// SAFETY: from the context it is known that `ReflectFromPtr` was made for the type of the `MutUntyped`
let val: Mut<dyn Reflect> = mut_untyped.map_unchanged(|ptr| unsafe { reflect_from_ptr.as_reflect_ptr_mut(ptr) });
```
Note that nothing prevents you from doing
```rust
mut_untyped.map_unchanged(|ptr| &mut ());
```
or using any other mutable reference you can get, but IMO that is fine
since that will only result in a `Mut` that will dereference to that
value and mark the original value as changed. The lifetimes here prevent
anything bad from happening.
## Alternatives
1. Make `Ticks` public and provide a method to get construct a `Mut`
from `Ticks` and `&mut T`. More powerful and more easy to misuse.
2. Do nothing. People can still do everything they want, but they need
to pass (`&mut dyn Reflect, impl FnMut() + '_)` around instead of
`Mut<dyn Reflect>`
## Changelog
- add `MutUntyped::map_unchanged` to turn a `MutUntyped` into its typed
counterpart
---------
Co-authored-by: Jakob Hellermann <jakob.hellermann@protonmail.com>
Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
# Objective
Fix#8936.
## Solution
Stop using `unwrap` in the core pipelined rendering logic flow.
Separately also scoped the `sub app` span to just running the render app
instead of including the blocking send.
Current unknowns: should we use `std::panic::catch_unwind` around
running the render app? Other engine threads use it defensively, but
we're letting it bubble up here, and a user-created panic could cause a
deadlock if it kills the thread.
---
## Changelog
Fixed: Pipelined rendering should no longer have spurious panics upon
app exit.
# Objective
Implements #9082 but with an option to toggle minimize and close buttons
too.
## Solution
- Added an `enabled_buttons` member to the `Window` struct through which
users can enable or disable specific window control buttons.
---
## Changelog
- Added an `enabled_buttons` member to the `Window` struct through which
users can enable or disable specific window control buttons.
- Added a new system to the `window_settings` example which demonstrates
the toggling functionality.
---
## Migration guide
- Added an `enabled_buttons` member to the `Window` struct through which
users can enable or disable specific window control buttons.
# Objective
Currently the panic message if a duplicate plugin is added isn't really
helpful or at least can be made more useful if it includes the location
where the plugin was added a second time.
## Solution
Add `track_caller` to `add_plugins` and it's called dependencies.
# Objective
This attempts to make the new IRect and URect structs in bevy_math more
similar to the existing Rect struct.
## Solution
Add reflect implementations for IRect and URect, since one already
exists for Rect.
# Objective
- #8960 isn't optimal for very distinct AABB colors, it can be improved
## Solution
We want a function that maps sequential values (entities concurrently
living in a scene _usually_ have ids that are sequential) into very
different colors (the hue component of the color, to be specific)
What we are looking for is a [so-called "low discrepancy"
sequence](https://en.wikipedia.org/wiki/Low-discrepancy_sequence). ie: a
function `f` such as for integers in a given range (eg: 101, 102, 103…),
`f(i)` returns a rational number in the [0..1] range, such as `|f(i) -
f(i±1)| ≈ 0.5` (maximum difference of images for neighboring preimages)
AHash is a good random hasher, but it has relatively high discrepancy,
so we need something else.
Known good low discrepancy sequences are:
#### The [Van Der Corput
sequence](https://en.wikipedia.org/wiki/Van_der_Corput_sequence)
<details><summary>Rust implementation</summary>
```rust
fn van_der_corput(bits: u64) -> f32 {
let leading_zeros = if bits == 0 { 0 } else { bits.leading_zeros() };
let nominator = bits.reverse_bits() >> leading_zeros;
let denominator = bits.next_power_of_two();
nominator as f32 / denominator as f32
}
```
</details>
#### The [Gold Kronecker
sequence](https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/)
<details><summary>Rust implementation</summary>
Note that the implementation suggested in the linked post assumes
floats, we have integers
```rust
fn gold_kronecker(bits: u64) -> f32 {
const U64_MAX_F: f32 = u64::MAX as f32;
// (u64::MAX / Φ) rounded down
const FRAC_U64MAX_GOLDEN_RATIO: u64 = 11400714819323198485;
bits.wrapping_mul(FRAC_U64MAX_GOLDEN_RATIO) as f32 / U64_MAX_F
}
```
</details>
### Comparison of the sequences
So they are both pretty good. Both only have a single (!) division and
two `u32 as f32` conversions.
- Kronecker is resilient to regular sequence (eg: 100, 102, 104, 106)
while this kills Van Der Corput (consider that potentially one entity
out of two spawned might be a mesh)
I made a small app to compare the two sequences, available at:
https://gist.github.com/nicopap/5dd9bd6700c6a9a9cf90c9199941883e
At the top, we have Van Der Corput, at the bottom we have the Gold
Kronecker. In the video, we spawn a vertical line at the position on
screen where the x coordinate is the image of the sequence. The
preimages are 1,2,3,4,… The ideal algorithm would always have the
largest possible gap between each line (imagine the screen x coordinate
as the color hue):
https://github.com/bevyengine/bevy/assets/26321040/349aa8f8-f669-43ba-9842-f9a46945e25c
Here, we repeat the experiment, but with with `entity.to_bits()` instead
of a sequence:
https://github.com/bevyengine/bevy/assets/26321040/516cea27-7135-4daa-a4e7-edfd1781d119
Notice how Van Der Corput tend to bunch the lines on a single side of
the screen. This is because we always skip odd-numbered entities.
Gold Kronecker seems always worse than Van Der Corput, but it is
resilient to finicky stuff like entity indices being multiples of a
number rather than purely sequential, so I prefer it over Van Der
Corput, since we can't really predict how distributed the entity indices
will be.
### Chosen implementation
You'll notice this PR's implementation is not the Golden ratio-based
Kronecker sequence as described in
[tueoqs](https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/).
Why?
tueoqs R function multiplies a rational/float and takes the fractional
part of the result `(x/Φ) % 1`. We start with an integer `u32`. So
instead of converting into float and dividing by Φ (mod 1) we directly
divide by Φ as integer (mod 2³²) both operations are equivalent, the
integer division (which is actually a multiplication by `u32::MAX / Φ`)
is probably faster.
## Acknowledgements
- `inspi` on discord linked me to
https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/
and the wikipedia article.
- [this blog
post](https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/)
for the idea of multiplying the `u32` rather than the `f32`.
- `nakedible` for suggesting the `index()` over `to_bits()` which
considerably reduces generated code (goes from 50 to 11 instructions)
# Objective
- Add a type for uploading a Rust `Vec<T>` to a GPU `array<T>`.
- Makes progress towards https://github.com/bevyengine/bevy/issues/89.
## Solution
- Port @superdump's `BatchedUniformBuffer` to bevy main, as a fallback
for WebGL2, which doesn't support storage buffers.
- Rather than getting an `array<T>` in a shader, you get an `array<T,
N>`, and have to rebind every N elements via dynamic offsets.
- Add `GpuArrayBuffer` to abstract over
`StorageBuffer<Vec<T>>`/`BatchedUniformBuffer`.
## Future Work
Add a shader macro kinda thing to abstract over the following
automatically:
https://github.com/bevyengine/bevy/pull/8204#pullrequestreview-1396911727
---
## Changelog
* Added `GpuArrayBuffer`, `GpuComponentArrayBufferPlugin`,
`GpuArrayBufferable`, and `GpuArrayBufferIndex` types.
* Added `DynamicUniformBuffer::new_with_alignment()`.
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
Co-authored-by: Vincent <9408210+konsolas@users.noreply.github.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>