# Objective
Sometimes when despawning a ui node in the PostUpdate schedule it
panics. This is because both a despawn command and insert command are
being run on the same entity.
See this example code:
```rs
use bevy::{prelude::*, ui::UiSystem};
#[derive(Resource)]
struct SliceSquare(Handle<Image>);
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, create_ui)
.add_systems(PostUpdate, despawn_nine_slice.after(UiSystem::Layout))
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
commands.insert_resource(SliceSquare(asset_server.load("textures/slice_square.png")));
}
fn create_ui(mut commands: Commands, slice_square: Res<SliceSquare>) {
commands.spawn((
NodeBundle {
style: Style {
width: Val::Px(200.),
height: Val::Px(200.),
..default()
},
background_color: Color::WHITE.into(),
..default()
},
UiImage::new(slice_square.0.clone()),
ImageScaleMode::Sliced(TextureSlicer {
border: BorderRect::square(220.),
center_scale_mode: SliceScaleMode::Stretch,
sides_scale_mode: SliceScaleMode::Stretch,
max_corner_scale: 1.,
}),
));
}
fn despawn_nine_slice(mut commands: Commands, mut slices: Query<Entity, With<ImageScaleMode>>) {
for entity in slices.iter_mut() {
commands.entity(entity).despawn_recursive();
}
}
```
This code spawns a UiNode with a sliced image scale mode, and despawns
it in the same frame. The
bevy_ui::texture_slice::compute_slices_on_image_change system tries to
insert the ComputedTextureSlices component on that node, but that entity
is already despawned causing this error:
```md
error[B0003]: Could not insert a bundle (of type `bevy_ui::texture_slice::ComputedTextureSlices`) for entity Entity { index: 2, generation: 3 } because it doesn't
exist in this World. See: https://bevyengine.org/learn/errors/#b0003
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic when applying buffers for system `bevy_ui::texture_slice::compute_slices_on_image_change`!
Encountered a panic in system `bevy_ecs::schedule::executor::apply_deferred`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
```
Note that you might have to run the code a few times before this error
appears.
## Solution
Use try_insert instead of insert for non critical inserts in the bevy_ui
crate.
## Some notes
In a lot of cases it does not makes much sense to despawn ui nodes after
the layout system has finished. Except maybe if you delete the root ui
node of a tree. I personally encountered this issue in bevy `0.13.2`
with a system that was running before the layout system. And in `0.13.2`
the `compute_slices_on_image_change` system was also running before the
layout system. But now it runs after the layout system. So the only way
that this bug appears now is if you despawn ui nodes after the layout
system. So I am not 100% sure if using try_insert in this system is the
best option. But personally I still think it is better then the program
panicking.
However the `update_children_target_camera` system does still run before
the layout system. So I do think it might still be able to panic when ui
nodes are despawned before the layout system. Though I haven't been able
to verify that.
# Objective
- General clenup of the primitives in `bevy_math`
- Add `eccentricity()` to `Ellipse`
## Solution
- Moved `Bounded3d` implementation for `Triangle3d` to the `bounded`
module
- Added `eccentricity()` to `Ellipse`
- `Ellipse::semi_major()` and `::semi_minor()` now accept `&self`
instead of `self`
- `Triangle3d::is_degenerate()` actually uses `f32::EPSILON` as
documented
- Added tests for `Triangle3d`-maths
---------
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: Miles Silberling-Cook <nth.tensor@gmail.com>
# Objective
Make visibility system ordering explicit. Fixes#12953.
## Solution
Specify `CheckVisibility` happens after all other `VisibilitySystems`
sets have happened.
---------
Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
# Objective
Missing docs
## Solution
Add docs paraphrased from the Cart's mouth:
https://discord.com/channels/691052431525675048/691052431974465548/1172305792154738759
> It follows the natural "results" of right handed y-up. The default
camera will face "forward" in -Z, with +X being "right". The RH y-up
setup is reasonably common. Thats why I asked for existing examples.I
think we should appeal to the masses here / see how other RH Y-up 3D
packages / engines handle this
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
# Objective
When trying to be generic over `Material + Default`, the lack of a
`Default` impl for `ExtendedMaterial`, even when both of its components
implement `Default`, is problematic. I think was probably just
overlooked.
## Solution
Impl `Default` if the material and extension both impl `Default`.
---
## Changelog
## Migration Guide
# Objective
Related to #12981
Presently, there is a footgun where we allow non-normalized vectors to
be passed in the `axis` parameters of `Transform::rotate_axis` and
`Transform::rotate_local_axis`. These methods invoke
`Quat::from_axis_angle` which expects the vector to be normalized. This
PR aims to address this.
## Solution
Require `Dir3`-valued `axis` parameters for these functions so that the
vector's normalization can be enforced at type-level.
---
## Migration Guide
All calls to `Transform::rotate_axis` and `Transform::rotate_local_axis`
will need to be updated to use a `Dir3` for the `axis` parameter rather
than a `Vec3`. For a general input, this means calling `Dir3::new` and
handling the `Result`, but if the previous vector is already known to be
normalized, `Dir3::new_unchecked` can be called instead. Note that
literals like `Vec3::X` also have corresponding `Dir3` literals; e.g.
`Dir3::X`, `Dir3::NEG_Y` and so on.
---
## Discussion
This axis input is unambigiously a direction instead of a vector, and
that should probably be reflected and enforced by the function
signature. In previous cases where we used, e.g., `impl TryInto<Dir3>`,
the associated methods already implemented (and required!) additional
fall-back logic, since the input is conceptually more complicated than
merely specifying an axis. In this case, I think it's fairly
cut-and-dry, and I'm pretty sure these methods just predate our
direction types.
# Objective
As described in #12467, Bevy does not have any spans for any of the
tasks scheduled onto the IO and async compute task pools.
## Solution
Instrument all asset loads and asset processing. Since this change is
restricted to asset tasks, it does not completely solve #12467, but it
does mean we can record the asset path in the trace.
![image](https://github.com/bevyengine/bevy/assets/8494645/59faee63-1f69-40af-bf47-312c4d67d1e2)
---
## Changelog
Tracing will now include spans for asset loading and asset processing.
glTF files that contain lights currently panic when loaded into Bevy,
because Bevy tries to reflect on `Cascades`, which accidentally wasn't
registered.
`EntityHashSet` doesn't seem to implement `Reflect` which seems weird!
Especially since `EntityHashMap` implements `Reflect`.
This PR just added an extra `impl_reflect_value!` for `EntityHashSet`
and this seems to do the trick.
I left out doing the same for `StableHashSet` since it's marked as
deprecated.
---
I'm really wondering what was the issue here. If anyone can explain why
`EntityHashSet` can't use the `Reflect` impl of `bevy_utils::HashSet`
similar to how it's the case with the `...HashMap`s I'd be interested!
# Objective
- Fixes#12976
## Solution
This one is a doozy.
- Run `cargo +beta clippy --workspace --all-targets --all-features` and
fix all issues
- This includes:
- Moving inner attributes to be outer attributes, when the item in
question has both inner and outer attributes
- Use `ptr::from_ref` in more scenarios
- Extend the valid idents list used by `clippy:doc_markdown` with more
names
- Use `Clone::clone_from` when possible
- Remove redundant `ron` import
- Add backticks to **so many** identifiers and items
- I'm sorry whoever has to review this
---
## Changelog
- Added links to more identifiers in documentation.
# Objective
Improve the code quality of the multithreaded executor.
## Solution
* Remove some unused variables.
* Use `Mutex::get_mut` where applicable instead of locking.
* Use a `startup_systems` FixedBitset to pre-compute the starting
systems instead of building it bit-by-bit on startup.
* Instead of using `FixedBitset::clear` and `FixedBitset::union_with`,
use `FixedBitset::clone_from` instead, which does only a single copy and
will not allocate if the target bitset has a large enough allocation.
* Replace the `Mutex` around `Conditions` with `SyncUnsafeCell`, and add
a `Context::try_lock` that forces it to be synchronized fetched
alongside the executor lock.
This might produce minimal performance gains, but the focus here is on
the code quality improvements.
# Objective
Fixes#12408 .
Fixes#12680.
## Solution
- Recaclulated anchor from dimensions of sprite to dimension of each
part of it (each part contains its own anchor)
[Alpha to coverage] (A2C) replaces alpha blending with a
hardware-specific multisample coverage mask when multisample
antialiasing is in use. It's a simple form of [order-independent
transparency] that relies on MSAA. ["Anti-aliased Alpha Test: The
Esoteric Alpha To Coverage"] is a good summary of the motivation for and
best practices relating to A2C.
This commit implements alpha to coverage support as a new variant for
`AlphaMode`. You can supply `AlphaMode::AlphaToCoverage` as the
`alpha_mode` field in `StandardMaterial` to use it. When in use, the
standard material shader automatically applies the texture filtering
method from ["Anti-aliased Alpha Test: The Esoteric Alpha To Coverage"].
Objects with alpha-to-coverage materials are binned in the opaque pass,
as they're fully order-independent.
The `transparency_3d` example has been updated to feature an object with
alpha to coverage. Happily, the example was already using MSAA.
This is part of #2223, as far as I can tell.
[Alpha to coverage]: https://en.wikipedia.org/wiki/Alpha_to_coverage
[order-independent transparency]:
https://en.wikipedia.org/wiki/Order-independent_transparency
["Anti-aliased Alpha Test: The Esoteric Alpha To Coverage"]:
https://bgolus.medium.com/anti-aliased-alpha-test-the-esoteric-alpha-to-coverage-8b177335ae4f
---
## Changelog
### Added
* The `AlphaMode` enum now supports `AlphaToCoverage`, to provide
limited order-independent transparency when multisample antialiasing is
in use.
# Objective
- ~~This PR adds more flexible versions of `set_if_neq` and
`replace_if_neq` to only compare and update certain fields of a
components which is not just a newtype~~
- https://github.com/bevyengine/bevy/pull/12919#issuecomment-2048049786
gave a good solution to the original problem, so let's update the docs
so that this is easier to find
## Solution
- ~~Add `set_if_neq_with` and `replace_if_neq_with` which take an
accessor closure to access the relevant field~~
---
In a recent project, a scenario emerged that required careful
consideration regarding change detection without compromising
performance. The context involves a component that maintains a
collection of `Vec<Vec2>` representing a horizontal surface, alongside a
height field. When the height is updated, there are a few approaches to
consider:
1. Clone the collection of points to utilize the existing `set_if_neq`
method.
2. Inline and adjust the `set_if_neq` code specifically for this
scenario.
3. (Consider splitting the component into more granular components.)
It's worth noting that the third option might be the most suitable in
most cases.
A similar situation arises with the Bevy internal Transform component,
which includes fields for translation, rotation, and scale. These fields
are relatively small (`Vec3` or `Quat` with 3 or 4 `f32` values), but
the creation of a single pointer (`usize`) might be more efficient than
copying the data of the other fields. This is speculative, and insights
from others could be valuable.
Questions remain:
- Is it feasible to develop a more flexible API, and what might that
entail?
- Is there general interest in this change?
There's no hard feelings if this idea or the PR is ultimately rejected.
I just wanted to put this idea out there and hope that this might be
beneficial to others and that feedback could be valuable before
abandoning the idea.
# Objective
- `cargo run --release --example bevymark -- --benchmark --waves 160
--per-wave 1000 --mode mesh2d` runs slower and slower over time due to
`no_gpu_preprocessing::write_batched_instance_buffer<bevy_sprite::mesh2d::mesh::Mesh2dPipeline>`
taking longer and longer because the `BatchedInstanceBuffer` is not
cleared
## Solution
- Split the `clear_batched_instance_buffers` system into CPU and GPU
versions
- Use the CPU version for 2D meshes
# Objective
Fixes a crash when transcoding one- or two-channel KTX2 textures
## Solution
transcoded array has been pre-allocated up to levels.len using a macros.
Rgb8 transcoding already uses that and addresses transcoded array by an
index. R8UnormSrgb and Rg8UnormSrgb were pushing on top of the
transcoded vec, resulting in first levels.len() vectors to stay empty,
and second levels.len() levels actually being transcoded, which then
resulted in out of bounds read when copying levels to gpu
# Objective
- `cargo check --workspace` appears to merge features and dependencies
together, so it does not catch some issues where dependencies are not
properly feature-gated.
- The issues **are** caught, though, by running `cd $crate && cargo
check`.
## Solution
- Manually check each crate for issues.
```shell
# Script used
for i in crates/bevy_* do
pushd $i
cargo check
popd
done
```
- `bevy_color` had an issue where it used `#[derive(Pod, Zeroable)]`
without using `bytemuck`'s `derive` feature.
- The `FpsOverlayPlugin` in `bevy_dev_tools` uses `bevy_ui`'s
`bevy_text` integration without properly enabling `bevy_text` as a
feature.
- `bevy_gizmos`'s `light` module was not properly feature-gated behind
`bevy_pbr`.
- ~~Lights appear to only be implemented in `bevy_pbr` and not
`bevy_sprite`, so I think this is the right call. Can I get a
confirmation by a gizmos person?~~ Confirmed :)
- `bevy_gltf` imported `SmallVec`, but only used it if `bevy_animation`
was enabled.
- There was another issue, but it was more challenging to solve than the
`smallvec` one. Run `cargo check -p bevy_gltf` and it will raise an
issue about `animation_roots`.
<details>
<summary><code>bevy_gltf</code> errors</summary>
```shell
error[E0425]: cannot find value `animation_roots` in this scope
--> crates/bevy_gltf/src/loader.rs:608:26
|
608 | &animation_roots,
| ^^^^^^^^^^^^^^^ not found in this scope
warning: variable does not need to be mutable
--> crates/bevy_gltf/src/loader.rs:1015:5
|
1015 | mut animation_context: Option<AnimationContext>,
| ----^^^^^^^^^^^^^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
For more information about this error, try `rustc --explain E0425`.
warning: `bevy_gltf` (lib) generated 1 warning
error: could not compile `bevy_gltf` (lib) due to 1 previous error; 1 warning emitted
```
</details>
---
## Changelog
- Fixed `bevy_color`, `bevy_dev_tools`, and `bevy_gizmos` so they can
now compile by themselves.
# Objective
i downloaded a random model from sketchfab
(https://sketchfab.com/3d-models/dragon-glass-fe00cb0ecaca4e4595874b70de7e116b)
to fiddle with bevy and encountered a panic when attempted to play
animations:
```
thread 'Compute Task Pool (3)' panicked at /home/username/code/bevy/crates/bevy_animation/src/lib.rs:848:58:
index out of bounds: the len is 40 but the index is 40
```
"Animation / Animated Fox"
(5caf085dac/examples/animation/animated_fox.rs)
example can be used for reproduction. to reproduce download a model from
sketchfab (link above) and load it instead of loading fox.glb, keep only
`dragon_glass.glb#Animation0` and remove `1` and `2` -> run and wait 1-2
seconds for crash to happen.
## Solution
correct keyframe indexing, i guess
`ExtractComponentPlugin` doesn't check to make sure the component is
actually present unless it's in the `QueryFilter`. This meant we placed
it everywhere. This regressed performance on many examples, such as
`many_cubes`.
Fixes#12956.
# Objective
The system task span is pretty consistent in how much time it uses, so
all it adds is overhead/additional bandwidth when profiling.
## Solution
Remove it.
`Sprite`, `Text`, and `Handle<MeshletMesh>` were types of renderable
entities that the new segregated visible entity system didn't handle, so
they didn't appear.
Because `bevy_text` depends on `bevy_sprite`, and the visibility
computation of text happens in the latter crate, I had to introduce a
new marker component, `SpriteSource`. `SpriteSource` marks entities that
aren't themselves sprites but become sprites during rendering. I added
this component to `Text2dBundle`. Unfortunately, this is technically a
breaking change, although I suspect it won't break anybody in practice
except perhaps editors.
Fixes#12935.
## Changelog
### Changed
* `Text2dBundle` now includes a new marker component, `SpriteSource`.
Bevy uses this internally to optimize visibility calculation.
## Migration Guide
* `Text` now requires a `SpriteSource` marker component in order to
appear. This component has been added to `Text2dBundle`.
# Objective
Improve performance scalability when adding new event types to a Bevy
app. Currently, just using Bevy in the default configuration, all apps
spend upwards of 100+us in the `First` schedule, every app tick,
evaluating if it should update events or not, even if events are not
being used for that particular frame, and this scales with the number of
Events registered in the app.
## Solution
As `Events::update` is guaranteed `O(1)` by just checking if a
resource's value, swapping two Vecs, and then clearing one of them, the
actual cost of running `event_update_system` is *very* cheap. The
overhead of doing system dependency injection, task scheduling ,and the
multithreaded executor outweighs the cost of running the system by a
large margin.
Create an `EventRegistry` resource that keeps a number of function
pointers that update each event. Replace the per-event type
`event_update_system` with a singular exclusive system uses the
`EventRegistry` to update all events instead. Update `SubApp::add_event`
to use `EventRegistry` instead.
## Performance
This speeds reduces the cost of the `First` schedule in both many_foxes
and many_cubes by over 80%. Note this is with system spans on. The
majority of this is now context-switching costs from launching
`time_system`, which should be mostly eliminated with #12869.
![image](https://github.com/bevyengine/bevy/assets/3137680/037624be-21a2-4dc2-a42f-9d0bfa3e9b4a)
The actual `event_update_system` is usually *very* short, using only a
few microseconds on average.
![image](https://github.com/bevyengine/bevy/assets/3137680/01ff1689-3595-49b6-8f09-5c44bcf903e8)
---
## Changelog
TODO
## Migration Guide
TODO
---------
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- I daily drive nightly Rust when developing Bevy, so I notice when new
warnings are raised by `cargo check` and Clippy.
- `cargo +nightly clippy` raises a few of these new warnings.
## Solution
- Fix most warnings from `cargo +nightly clippy`
- I skipped the docs-related warnings because some were covered by
#12692.
- Use `Clone::clone_from` in applicable scenarios, which can sometimes
avoid an extra allocation.
- Implement `Default` for structs that have a `pub const fn new() ->
Self` method.
- Fix an occurrence where generic constraints were defined in both `<C:
Trait>` and `where C: Trait`.
- Removed generic constraints that were implied by the `Bundle` trait.
---
## Changelog
- `BatchingStrategy`, `NonGenericTypeCell`, and `GenericTypeCell` now
implement `Default`.
This commit splits `VisibleEntities::entities` into four separate lists:
one for lights, one for 2D meshes, one for 3D meshes, and one for UI
elements. This allows `queue_material_meshes` and similar methods to
avoid examining entities that are obviously irrelevant. In particular,
this separation helps scenes with many skinned meshes, as the individual
bones are considered visible entities but have no rendered appearance.
Internally, `VisibleEntities::entities` is a `HashMap` from the `TypeId`
representing a `QueryFilter` to the appropriate `Entity` list. I had to
do this because `VisibleEntities` is located within an upstream crate
from the crates that provide lights (`bevy_pbr`) and 2D meshes
(`bevy_sprite`). As an added benefit, this setup allows apps to provide
their own types of renderable components, by simply adding a specialized
`check_visibility` to the schedule.
This provides a 16.23% end-to-end speedup on `many_foxes` with 10,000
foxes (24.06 ms/frame to 20.70 ms/frame).
## Migration guide
* `check_visibility` and `VisibleEntities` now store the four types of
renderable entities--2D meshes, 3D meshes, lights, and UI
elements--separately. If your custom rendering code examines
`VisibleEntities`, it will now need to specify which type of entity it's
interested in using the `WithMesh2d`, `WithMesh`, `WithLight`, and
`WithNode` types respectively. If your app introduces a new type of
renderable entity, you'll need to add an explicit call to
`check_visibility` to the schedule to accommodate your new component or
components.
## Analysis
`many_foxes`, 10,000 foxes: `main`:
![Screenshot 2024-03-31
114444](https://github.com/bevyengine/bevy/assets/157897/16ecb2ff-6e04-46c0-a4b0-b2fde2084bad)
`many_foxes`, 10,000 foxes, this branch:
![Screenshot 2024-03-31
114256](https://github.com/bevyengine/bevy/assets/157897/94dedae4-bd00-45b2-9aaf-dfc237004ddb)
`queue_material_meshes` (yellow = this branch, red = `main`):
![Screenshot 2024-03-31
114637](https://github.com/bevyengine/bevy/assets/157897/f90912bd-45bd-42c4-bd74-57d98a0f036e)
`queue_shadows` (yellow = this branch, red = `main`):
![Screenshot 2024-03-31
114607](https://github.com/bevyengine/bevy/assets/157897/6ce693e3-20c0-4234-8ec9-a6f191299e2d)
# Objective
-
[`clippy::ref_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#/ref_as_ptr)
prevents you from directly casting references to pointers, requiring you
to use `std::ptr::from_ref` instead. This prevents you from accidentally
converting an immutable reference into a mutable pointer (`&x as *mut
T`).
- Follow up to #11818, now that our [`rust-version` is
1.77](11817f4ba4/Cargo.toml (L14)).
## Solution
- Enable lint and fix all warnings.
I ported the two existing PCF techniques to the cubemap domain as best I
could. Generally, the technique is to create a 2D orthonormal basis
using Gram-Schmidt normalization, then apply the technique over that
basis. The results look fine, though the shadow bias often needs
adjusting.
For comparison, Unity uses a 4-tap pattern for PCF on point lights of
(1, 1, 1), (-1, -1, 1), (-1, 1, -1), (1, -1, -1). I tried this but
didn't like the look, so I went with the design above, which ports the
2D techniques to the 3D domain. There's surprisingly little material on
point light PCF.
I've gone through every example using point lights and verified that the
shadow maps look fine, adjusting biases as necessary.
Fixes#3628.
---
## Changelog
### Added
* Shadows from point lights now support percentage-closer filtering
(PCF), and as a result look less aliased.
### Changed
* `ShadowFilteringMethod::Castano13` and
`ShadowFilteringMethod::Jimenez14` have been renamed to
`ShadowFilteringMethod::Gaussian` and `ShadowFilteringMethod::Temporal`
respectively.
## Migration Guide
* `ShadowFilteringMethod::Castano13` and
`ShadowFilteringMethod::Jimenez14` have been renamed to
`ShadowFilteringMethod::Gaussian` and `ShadowFilteringMethod::Temporal`
respectively.
# Objective
Fixes#11996
The deprecated shape Quad's flip field role migrated to
StandardMaterial's flip/flipped methods
## Solution
flip/flipping methods of StandardMaterial is applicable to any mesh
---
## Changelog
- Added flip and flipped methods to the StandardMaterial implementation
- Added FLIP_HORIZONTAL, FLIP_VERTICAL, FLIP_X, FLIP_Y, FLIP_Z constants
## Migration Guide
Instead of using `Quad::flip` field, call `flipped(true, false)` method
on the StandardMaterial instance when adding the mesh.
---------
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Currently, `MeshUniform`s are rather large: 160 bytes. They're also
somewhat expensive to compute, because they involve taking the inverse
of a 3x4 matrix. Finally, if a mesh is present in multiple views, that
mesh will have a separate `MeshUniform` for each and every view, which
is wasteful.
This commit fixes these issues by introducing the concept of a *mesh
input uniform* and adding a *mesh uniform building* compute shader pass.
The `MeshInputUniform` is simply the minimum amount of data needed for
the GPU to compute the full `MeshUniform`. Most of this data is just the
transform and is therefore only 64 bytes. `MeshInputUniform`s are
computed during the *extraction* phase, much like skins are today, in
order to avoid needlessly copying transforms around on CPU. (In fact,
the render app has been changed to only store the translation of each
mesh; it no longer cares about any other part of the transform, which is
stored only on the GPU and the main world.) Before rendering, the
`build_mesh_uniforms` pass runs to expand the `MeshInputUniform`s to the
full `MeshUniform`.
The mesh uniform building pass does the following, all on GPU:
1. Copy the appropriate fields of the `MeshInputUniform` to the
`MeshUniform` slot. If a single mesh is present in multiple views, this
effectively duplicates it into each view.
2. Compute the inverse transpose of the model transform, used for
transforming normals.
3. If applicable, copy the mesh's transform from the previous frame for
TAA. To support this, we double-buffer the `MeshInputUniform`s over two
frames and swap the buffers each frame. The `MeshInputUniform`s for the
current frame contain the index of that mesh's `MeshInputUniform` for
the previous frame.
This commit produces wins in virtually every CPU part of the pipeline:
`extract_meshes`, `queue_material_meshes`,
`batch_and_prepare_render_phase`, and especially
`write_batched_instance_buffer` are all faster. Shrinking the amount of
CPU data that has to be shuffled around speeds up the entire rendering
process.
| Benchmark | This branch | `main` | Speedup |
|------------------------|-------------|---------|---------|
| `many_cubes -nfc` | 17.259 | 24.529 | 42.12% |
| `many_cubes -nfc -vpi` | 302.116 | 312.123 | 3.31% |
| `many_foxes` | 3.227 | 3.515 | 8.92% |
Because mesh uniform building requires compute shader, and WebGL 2 has
no compute shader, the existing CPU mesh uniform building code has been
left as-is. Many types now have both CPU mesh uniform building and GPU
mesh uniform building modes. Developers can opt into the old CPU mesh
uniform building by setting the `use_gpu_uniform_builder` option on
`PbrPlugin` to `false`.
Below are graphs of the CPU portions of `many-cubes
--no-frustum-culling`. Yellow is this branch, red is `main`.
`extract_meshes`:
![Screenshot 2024-04-02
124842](https://github.com/bevyengine/bevy/assets/157897/a6748ea4-dd05-47b6-9254-45d07d33cb10)
It's notable that we get a small win even though we're now writing to a
GPU buffer.
`queue_material_meshes`:
![Screenshot 2024-04-02
124911](https://github.com/bevyengine/bevy/assets/157897/ecb44d78-65dc-448d-ba85-2de91aa2ad94)
There's a bit of a regression here; not sure what's causing it. In any
case it's very outweighed by the other gains.
`batch_and_prepare_render_phase`:
![Screenshot 2024-04-02
125123](https://github.com/bevyengine/bevy/assets/157897/4e20fc86-f9dd-4e5c-8623-837e4258f435)
There's a huge win here, enough to make batching basically drop off the
profile.
`write_batched_instance_buffer`:
![Screenshot 2024-04-02
125237](https://github.com/bevyengine/bevy/assets/157897/401a5c32-9dc1-4991-996d-eb1cac6014b2)
There's a massive improvement here, as expected. Note that a lot of it
simply comes from the fact that `MeshInputUniform` is `Pod`. (This isn't
a maintainability problem in my view because `MeshInputUniform` is so
simple: just 16 tightly-packed words.)
## Changelog
### Added
* Per-mesh instance data is now generated on GPU with a compute shader
instead of CPU, resulting in rendering performance improvements on
platforms where compute shaders are supported.
## Migration guide
* Custom render phases now need multiple systems beyond just
`batch_and_prepare_render_phase`. Code that was previously creating
custom render phases should now add a `BinnedRenderPhasePlugin` or
`SortedRenderPhasePlugin` as appropriate instead of directly adding
`batch_and_prepare_render_phase`.
# Objective
- Fixes#12905.
## Solution
- Use proper code `` tags for `TaskPoolBuilder::thread_name`.
- Remove leftover documentation in `TaskPool` referencing the deleted
`TaskPoolInner` struct.
- It may be possible to rephrase this, but I do not know enough about
the task pool to write something. (cc @james7132 who made the change
removing `TaskPoolInner`.)
- Ignore a buggy rustdoc lint that thinks `App` is already in scope for
`UpdateMode` doc. (Extracted from #12692.)
# Objective
- All gizmos APIs besides `gizmos.primitive_3d` use `impl Into<Color>`
as their type for `color`.
## Solution
- This PR changes `primitive_3d()` to use `impl Into<Color>` aswell.
# Objective
- Replace `RenderMaterials` / `RenderMaterials2d` / `RenderUiMaterials`
with `RenderAssets` to enable implementing changes to one thing,
`RenderAssets`, that applies to all use cases rather than duplicating
changes everywhere for multiple things that should be one thing.
- Adopts #8149
## Solution
- Make RenderAsset generic over the destination type rather than the
source type as in #8149
- Use `RenderAssets<PreparedMaterial<M>>` etc for render materials
---
## Changelog
- Changed:
- The `RenderAsset` trait is now implemented on the destination type.
Its `SourceAsset` associated type refers to the type of the source
asset.
- `RenderMaterials`, `RenderMaterials2d`, and `RenderUiMaterials` have
been replaced by `RenderAssets<PreparedMaterial<M>>` and similar.
## Migration Guide
- `RenderAsset` is now implemented for the destination type rather that
the source asset type. The source asset type is now the `RenderAsset`
trait's `SourceAsset` associated type.
# Objective
- Ongoing work for #10572
- Implement the `Meshable` trait for `Triangle3d`, allowing 3d triangle
primitives to produce meshes.
## Solution
The `Meshable` trait for `Triangle3d` directly produces a `Mesh`, much
like that of `Triangle2d`. The mesh consists only of a single triangle
(the triangle itself), and its vertex data consists of:
- Vertex positions, which are the triangle's vertices themselves (i.e.
the triangle provides its own coordinates in mesh space directly)
- Normals, which are all the normal of the triangle itself
- Indices, which are directly inferred from the vertex order (note that
this is slightly different than `Triangle2d` which, because of its lower
dimension, has an orientation which can be corrected for so that it
always faces "the right way")
- UV coordinates, which are produced as follows:
1. The first coordinate is coincident with the `ab` direction of the
triangle.
2. The second coordinate maps to be perpendicular to the first in mesh
space, so that the UV-mapping is skew-free.
3. The UV-coordinates map to the smallest rectangle possible containing
the triangle, given the preceding constraints.
Here is a visual demonstration; here, the `ab` direction of the triangle
is horizontal, left to right — the point `c` moves, expanding the
bounding rectangle of the triangle when it pushes past `a` or `b`:
<img width="1440" alt="Screenshot 2024-03-23 at 5 36 01 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/bef4d786-7b82-4207-abd4-ac4557d0f8b8">
<img width="1440" alt="Screenshot 2024-03-23 at 5 38 12 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/c0f72b8f-8e70-46fa-a750-2041ba6dfb78">
<img width="1440" alt="Screenshot 2024-03-23 at 5 37 15 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/db287e4f-2b0b-4fd4-8d71-88f4e7a03b7c">
The UV-mapping of `Triangle2d` has also been changed to use the same
logic.
---
## Changelog
- Implemented `Meshable` for `Triangle3d`.
- Changed UV-mapping of `Triangle2d` to match that of `Triangle3d`.
## Migration Guide
The UV-mapping of `Triangle2d` has changed with this PR; the main
difference is that the UVs are no longer dependent on the triangle's
absolute coordinates, but instead follow translations of the triangle
itself in its definition. If you depended on the old UV-coordinates for
`Triangle2d`, then you will have to update affected areas to use the new
ones which, briefly, can be described as follows:
- The first coordinate is parallel to the line between the first two
vertices of the triangle.
- The second coordinate is orthogonal to this, pointing in the direction
of the third point.
Generally speaking, this means that the first two points will have
coordinates `[_, 0.]`, while the third coordinate will be `[_, 1.]`,
with the exact values depending on the position of the third point
relative to the first two. For acute triangles, the first two vertices
always have UV-coordinates `[0., 0.]` and `[1., 0.]` respectively. For
obtuse triangles, the third point will have coordinate `[0., 1.]` or
`[1., 1.]`, with the coordinate of one of the two other points shifting
to maintain proportionality.
For example:
- The default `Triangle2d` has UV-coordinates `[0., 0.]`, `[0., 1.]`,
[`0.5, 1.]`.
- The triangle with vertices `vec2(0., 0.)`, `vec2(1., 0.)`, `vec2(2.,
1.)` has UV-coordinates `[0., 0.]`, `[0.5, 0.]`, `[1., 1.]`.
- The triangle with vertices `vec2(0., 0.)`, `vec2(1., 0.)`, `vec2(-2.,
1.)` has UV-coordinates `[2./3., 0.]`, `[1., 0.]`, `[0., 1.]`.
## Discussion
### Design considerations
1. There are a number of ways to UV-map a triangle (at least two of
which are fairly natural); for instance, we could instead declare the
second axis to be essentially `bc` so that the vertices are always `[0.,
0.]`, `[0., 1.]`, and `[1., 0.]`. I chose this method instead because it
is skew-free, so that the sampling from textures has only bilinear
scaling. I think this is better for cases where a relatively "uniform"
texture is mapped to the triangle, but it's possible that we might want
to support the other thing in the future. Thankfully, we already have
the capability of easily expanding to do that with Builders if the need
arises. This could also allow us to provide things like barycentric
subdivision.
2. Presently, the mesh-creation code for `Triangle3d` is set up to never
fail, even in the case that the triangle is degenerate. I have mixed
feelings about this, but none of our other primitive meshes fail, so I
decided to take the same approach. Maybe this is something that could be
worth revisiting in the future across the board.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jakub Marcowski <37378746+Chubercik@users.noreply.github.com>
# Objective
Minimize the number of dependencies low in the tree.
## Solution
* Remove the dependency on rustc-hash in bevy_ecs (not used) and
bevy_macro_utils (only used in one spot).
* Deduplicate the dependency on `sha1_smol` with the existing blake3
dependency already being used for bevy_asset.
* Remove the unused `ron` dependency on `bevy_app`
* Make the `serde` dependency for `bevy_ecs` optional. It's only used
for serializing Entity.
* Change the `wgpu` dependency to `wgpu-types`, and make it optional for
`bevy_color`.
* Remove the unused `thread-local` dependency on `bevy_render`.
* Make multiple dependencies for `bevy_tasks` optional and enabled only
when running with the `multi-threaded` feature. Preferably they'd be
disabled all the time on wasm, but I couldn't find a clean way to do
this.
---
## Changelog
TODO
## Migration Guide
TODO
Fixed a bug where skybox ddsfile would crash from wgpu while trying to
read past the file buffer.
Added a unit-test to prevent regression.
Bumped ddsfile dependency version to 0.5.2
# Objective
Prevents a crash when loading dds skybox.
## Solution
ddsfile already automatically sets array layers to be 6 for skyboxes.
Removed bevy's extra *= 6 multiplication.
---
This is a copy of
[#12598](https://github.com/bevyengine/bevy/pull/12598) ... I made that
one off of main and wasn't able to make more pull requests without
making a new branch.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
- Fix a potential out-of-bounds access in the `pbr_functions.wgsl`
shader.
## Solution
- Correctly compute the `GpuLights::directional_lights` array length.
## Comments
I think this solves this comment in the code, but need someone to test
it:
```rust
//NOTE: When running bevy on Adreno GPU chipsets in WebGL, any value above 1 will result in a crash
// when loading the wgsl "pbr_functions.wgsl" in the function apply_fog.
```
# Objective
- Attempts to solve two items from
https://github.com/bevyengine/bevy/issues/11478.
## Solution
- Moved `intern` module from `bevy_utils` into `bevy_ecs` crate and
updated all relevant imports.
- Moved `label` module from `bevy_utils` into `bevy_ecs` crate and
updated all relevant imports.
---
## Migration Guide
- Replace `bevy_utils::define_label` imports with
`bevy_ecs::define_label` imports.
- Replace `bevy_utils:🏷️:DynEq` imports with
`bevy_ecs:🏷️:DynEq` imports.
- Replace `bevy_utils:🏷️:DynHash` imports with
`bevy_ecs:🏷️:DynHash` imports.
- Replace `bevy_utils::intern::Interned` imports with
`bevy_ecs::intern::Interned` imports.
- Replace `bevy_utils::intern::Internable` imports with
`bevy_ecs::intern::Internable` imports.
- Replace `bevy_utils::intern::Interner` imports with
`bevy_ecs::intern::Interner` imports.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Make `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` work with `EntityMut` too (currently they only
work with the more restricting `EntityWorldMut`);
- Note: support for the `Filtered*` variants has been left out since the
conversion in that case is more expensive. Let me know if I should add
support for them too.
## Solution
- Make `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` take an `impl Into<EntityMut<'a>>`;
- Make the corresponding `*Fns` function pointers take a `EntityMut`.
---
## Changelog
- `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` now accept `EntityMut` as well
## Migration Guide
- `ReflectComponentFns`'s `apply` and `reflect_mut` fields now take
`EntityMut` instead of `&mut EntityWorldMut`
- `ReflectBundleFns`'s `apply` field now takes `EntityMut` instead of
`&mut EntityWorldMut`
# Objective
- Upload previous frame's inverse_view matrix to the GPU for use with
https://github.com/bevyengine/bevy/pull/12898.
---
## Changelog
- Added `prepass_bindings::previous_view_uniforms.inverse_view`.
- Renamed `prepass_bindings::previous_view_proj` to
`prepass_bindings::previous_view_uniforms.view_proj`.
- Renamed `PreviousViewProjectionUniformOffset` to
`PreviousViewUniformOffset`.
- Renamed `PreviousViewProjection` to `PreviousViewData`.
## Migration Guide
- Renamed `prepass_bindings::previous_view_proj` to
`prepass_bindings::previous_view_uniforms.view_proj`.
- Renamed `PreviousViewProjectionUniformOffset` to
`PreviousViewUniformOffset`.
- Renamed `PreviousViewProjection` to `PreviousViewData`.
# Objective
make morph targets and tonemapping more tolerant of delayed image
loading.
neither of these actually fail currently unless using a bespoke loader
(and even then it would be rare), but i am working on adding throttling
for asset gpu uploads (as a stopgap until we can do proper asset
streaming) and they break with that.
## Solution
when a mesh with morph targets is uploaded to the gpu, the prepare
function uploads the morph target texture if it's available, otherwise
it uploads without morph targets. this is generally fine as long as
morph targets are typically loaded from bytes (in gltf loader), but may
fail for a custom loader if the asset server async-loads the target
texture and the texture is not available yet. the mesh fails to render
and doesn't update when the image is loaded
-> if morph targets are specified but not ready yet, retry mesh upload
next frame
tonemapping `unwrap`s on the lookup table image. this is never a problem
since the image is added via `include_bytes!`, but could be a problem in
future with asset gpu throttling/streaming.
-> if the lookup texture is not yet available, use a fallback
-> in the node, check if the fallback was used before caching the bind
group
# Objective
- Implement `From<&'w mut EntityMut>` for `EntityMut<'w>`;
- Make it possible to pass `&mut EntityMut` where `impl Into<EntityMut>`
is required;
- Helps with #12895.
## Solution
- Implement `From<&'w mut EntityMut>` for `EntityMut<'w>`
---
## Changelog
- `EntityMut<'w>` now implements `From<&'w mut EntityMut>`
# Objective
- When viewport is set to the same size as the window on creation, when
adjusting to SizedFullscreen, the window may be smaller than the
viewport for a moment, which caused the arguments to be invalid and
panic.
- Fixes#12000.
## Solution
- The fix consists of matching the size of the viewport to the lower
size of the window ( if the x value of the window is lower, I update
only the x value of the viewport, same for the y value). Also added a
test to show that it does not panic anymore.
---
# Objective
- #12791 broke example `irradiance_volumes`
- Fixes#12876
```
wgpu error: Validation Error
Caused by:
In Device::create_render_pipeline
note: label = `pbr_opaque_mesh_pipeline`
Color state [0] is invalid
Sample count 8 is not supported by format Rgba8UnormSrgb on this device. The WebGPU spec guarentees [1, 4] samples are supported by this format. With the TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES feature your device supports [1, 2, 4].
```
## Solution
- Shift bits a bit more
# Objective
- Add a way to easily get currently waiting pipelines IDs.
## Solution
- Added a method to get waiting pipelines `CachedPipelineId`.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
Since BufferVec was first introduced, `bytemuck` has added additional
traits with fewer restrictions than `Pod`. Within BufferVec, we only
rely on the constraints of `bytemuck::cast_slice` to a `u8` slice, which
now only requires `T: NoUninit` which is a strict superset of `Pod`
types.
## Solution
Change out the `Pod` generic type constraint with `NoUninit`. Also
taking the opportunity to substitute `cast_slice` with
`must_cast_slice`, which avoids a runtime panic in place of a compile
time failure if `T` cannot be used.
---
## Changelog
Changed: `BufferVec` now supports working with types containing
`NoUninit` but not `Pod` members.
Changed: `BufferVec` will now fail to compile if used with a type that
cannot be safely read from. Most notably, this includes ZSTs, which
would previously always panic at runtime.
# Objective
Augment Bevy's random sampling capabilities by providing good tools for
producing random directions and rotations.
## Solution
The `rand` crate has a natural tool for providing `Distribution`s whose
output is a type that doesn't require any additional data to sample
values — namely,
[`Standard`](https://docs.rs/rand/latest/rand/distributions/struct.Standard.html).
Here, our existing `ShapeSample` implementations have been put to good
use in providing these, resulting in patterns like the following:
```rust
// Using thread-local rng
let random_direction1: Dir3 = random();
// Using an explicit rng
let random_direction2: Dir3 = rng.gen();
// Using an explicit rng coupled explicitly with Standard
let random_directions: Vec<Dir3> = rng.sample_iter(Standard).take(5).collect();
```
Furthermore, we have introduced a trait `FromRng` which provides sugar
for `rng.gen()` that is more namespace-friendly (in this author's
opinion):
```rust
let random_direction = Dir3::from_rng(rng);
```
The types this has been implemented for are `Dir2`, `Dir3`, `Dir3A`, and
`Quat`. Notably, `Quat` uses `glam`'s implementation rather than an
in-house one, and as a result, `bevy_math`'s "rand" feature now enables
that of `glam`.
---
## Changelog
- Created `standard` submodule in `sampling` to hold implementations and
other items related to the `Standard` distribution.
- "rand" feature of `bevy_math` now enables that of `glam`.
---
## Discussion
From a quick glance at `Quat`'s distribution implementation in `glam`, I
am a bit suspicious, since it is simple and doesn't match any algorithm
that I came across in my research. I will do a little more digging as a
follow-up to this and see if it's actually uniform (maybe even using
those tools I wrote — what a thrill).
As an aside, I'd also like to say that I think
[`Distribution`](https://docs.rs/rand/latest/rand/distributions/trait.Distribution.html)
is really, really good. It integrates with distributions provided
externally (e.g. in `rand` itself and its extensions) along with doing a
good job of isolating the source of randomness, so that output can be
reliably reproduced if need be. Finally, `Distribution::sample_iter` is
quite good for ergonomically acquiring lots of random values. At one
point I found myself writing traits to describe random sampling and
essentially reinvented this one. I just think it's good, and I think
it's worth centralizing around to a significant extent.
# Objective
See https://github.com/gfx-rs/wgpu/issues/5488 for context and
rationale.
## Solution
- Disables `wgpu::Features::RAY_QUERY` and
`wgpu::Features::RAY_TRACING_ACCELERATION_STRUCTURE` by default. They
must be explicitly opted into now.
---
## Changelog
- Disables `wgpu::Features::RAY_QUERY` and
`wgpu::Features::RAY_TRACING_ACCELERATION_STRUCTURE` by default. They
must be explicitly opted into now.
## Migration Guide
- If you need `wgpu::Features::RAY_QUERY` or
`wgpu::Features::RAY_TRACING_ACCELERATION_STRUCTURE`, enable them
explicitly using `WgpuSettings::features`
# Objective
- Fix#7303
- bevy would spawn a lot of tasks in parallel iteration when it matchs a
large storage and many small storage ,it significantly increase the
overhead of schedule.
## Solution
- collect small storage into one task
# Objective
Fix#11931
## Solution
- Make stepping a non-default feature
- Adjust documentation and examples
- In particular, make the breakout example not show the stepping prompt
if compiled without the feature (shows a log message instead)
---
## Changelog
- Removed `bevy_debug_stepping` from default features
## Migration Guide
The system-by-system stepping feature is now disabled by default; to use
it, enable the `bevy_debug_stepping` feature explicitly:
```toml
[dependencies]
bevy = { version = "0.14", features = ["bevy_debug_stepping"] }
```
Code using
[`Stepping`](https://docs.rs/bevy/latest/bevy/ecs/schedule/struct.Stepping.html)
will still compile with the feature disabled, but will print a runtime
error message to the console if the application attempts to enable
stepping.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
A help thread on discord asked how to use signed URLs for assets. This
currently fails because the query parameters are included in the
extension, which causes no suitable loader to be found:
```
Failed to load asset 'http://localhost:4566/dev/1711921849174.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=%2F20240331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240331T230145Z&X-Amz-Expires=900&X-Amz-Signature=64855e731c279fa01063568e37095562ef74e09387c881bd3e3604181d0cc108&X-Amz-SignedHeaders=host&x-id=GetObject' with asset loader 'bevy_render::texture::image_loader::ImageLoader':
Could not load texture file: Error reading image file localhost:4566/dev/1711921849174.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=%2F20240331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240331T230145Z&X-Amz-Expires=900&X-Amz-Signature=64855e731c279fa01063568e37095562ef74e09387c881bd3e3604181d0cc108&X-Amz-SignedHeaders=host&x-id=GetObject: invalid image extension: jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=%2F20240331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240331T230145Z&X-Amz-Expires=900&X-Amz-Signature=64855e731c279fa01063568e37095562ef74e09387c881bd3e3604181d0cc108&X-Amz-SignedHeaders=host&x-id=GetObject, this is an error in `bevy_render`.
```
## Solution
Make `get_full_extension` remove everything after the first `?`
character.
If this is accepted then it should also be documented in `AssetPath`
that extensions cannot include question marks.
An alternative is to special case this handling only for wasm, but that
would be annoying for the
[bevy_web_asset](https://github.com/johanhelsing/bevy_web_asset) plugin,
and in my opinion also just more confusing overall.
# Objective
- Remove `close_on_esc`
- For context about why we are removing it see:
[discord](https://discordapp.com/channels/691052431525675048/692572690833473578/1225075194524073985)
## Migration Guide
- Users who added `close_on_esc` in their application will have to
replace it with their own solution.
```rust
pub fn close_on_esc(
mut commands: Commands,
focused_windows: Query<(Entity, &Window)>,
input: Res<ButtonInput<KeyCode>>,
) {
for (window, focus) in focused_windows.iter() {
if !focus.focused {
continue;
}
if input.just_pressed(KeyCode::Escape) {
commands.entity(window).despawn();
}
}
}
```
# Objective
- Add `remove_by_id` method to `EntityWorldMut` and `EntityCommands`
- This is a duplicate of the awesome work by @mateuseap, last updated
04/09/23 - #9663
- I'm opening a second one to ensure the feature makes it into `0.14`
- Fixes#9261
## Solution
Almost identical to #9663 with three exceptions
- Uses a closure instead of struct for commands, consistent with other
similar commands
- Does not refactor `EntityCommands::insert`, so no migration guide
- `EntityWorldMut::remove_by_id` is now safe containing unsafe blocks, I
think thats what @SkiFire13 was indicating should happen [in this
comment](https://github.com/bevyengine/bevy/pull/9663#discussion_r1314307525)
## Changelog
- Added `EntityWorldMut::remove_by_id` method and its tests.
- Added `EntityCommands::remove_by_id` method and its tests.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Closes#12019
- Related to #4955
- Useful for dev_tools and networking
## Solution
- Create `World::iter_resources()` and `World::iter_resources_mut()`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
Just updating docs for the arc gizmo so that the argument documentation
matches the order of the function arguments.
Also added docs for the color argument.
# Objective
- Improve docs
## Solution
- Moved the radius argument to the end of the argument list to match the
function
---
## Changelog
> N/A
## Migration Guide
> N/A
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
- As @james7132 said [on
Discord](https://discord.com/channels/691052431525675048/692572690833473578/1224626740773523536),
the `close_on_esc` system is forcing `bevy_window` to depend on
`bevy_input`.
- `close_on_esc` is not likely to be used in production, so it arguably
does not have a place in `bevy_window`.
## Solution
- As suggested by @afonsolage, move `close_on_esc` into
`bevy_dev_tools`.
- Add an example to the documentation too.
- Remove `bevy_window`'s dependency on `bevy_input`.
- Add `bevy_reflect`'s `smol_str` feature to `bevy_window` because it
was implicitly depended upon with `bevy_input` before it was removed.
- Remove any usage of `close_on_esc` from the examples.
- `bevy_dev_tools` is not enabled by default. I personally find it
frustrating to run examples with additional features, so I opted to
remove it entirely.
- This is up for discussion if you have an alternate solution.
---
## Changelog
- Moved `bevy_window::close_on_esc` to `bevy_dev_tools::close_on_esc`.
- Removed usage of `bevy_dev_tools::close_on_esc` from all examples.
## Migration Guide
`bevy_window::close_on_esc` has been moved to
`bevy_dev_tools::close_on_esc`. You will first need to enable
`bevy_dev_tools` as a feature in your `Cargo.toml`:
```toml
[dependencies]
bevy = { version = "0.14", features = ["bevy_dev_tools"] }
```
Finally, modify any imports to use `bevy_dev_tools` instead:
```rust
// Old:
// use bevy:🪟:close_on_esc;
// New:
use bevy::dev_tools::close_on_esc;
App::new()
.add_systems(Update, close_on_esc)
// ...
.run();
```
# Objective
- Since #10811,Bevy uses `assert `in the hot path of iteration. The
`for_each `method has an assert in the outer loop to help the compiler
remove unnecessary branching in the internal loop.
- However , ` for` style iterations do not receive the same treatment.
it still have a branch check in the internal loop, which could
potentially hurt performance.
## Solution
- use `TableRow::from_u32 ` instead of ` TableRow::from_usize` to avoid
unnecessary branch.
Before
![image](https://github.com/bevyengine/bevy/assets/45868716/f6d2a1ac-2129-48ff-97bf-d86713ddeaaf)
After
----------------------------------------------------------------------------
![image](https://github.com/bevyengine/bevy/assets/45868716/bfe5a9ee-ba6c-4a80-85b0-1c6d43adfe8c)
# Objective
`AspectRatio` is a newtype of `f32`, so it can implement basic traits;
`Copy`, `Clone`, `Debug`, `PartialEq` and `PartialOrd`.
## Solution
Derive basic traits for `AspectRatio`.
This is 1 of 5 iterative PR's that affect bevy_ui/layout
---
# Objective
- Extract `UiSurface` into its own file to make diffs in future PR's
easier to digest
## Solution
- Moved `UiSurface` to its own file
This commit makes the following optimizations:
## `MeshPipelineKey`/`BaseMeshPipelineKey` split
`MeshPipelineKey` has been split into `BaseMeshPipelineKey`, which lives
in `bevy_render` and `MeshPipelineKey`, which lives in `bevy_pbr`.
Conceptually, `BaseMeshPipelineKey` is a superclass of
`MeshPipelineKey`. For `BaseMeshPipelineKey`, the bits start at the
highest (most significant) bit and grow downward toward the lowest bit;
for `MeshPipelineKey`, the bits start at the lowest bit and grow upward
toward the highest bit. This prevents them from colliding.
The goal of this is to avoid having to reassemble bits of the pipeline
key for every mesh every frame. Instead, we can just use a bitwise or
operation to combine the pieces that make up a `MeshPipelineKey`.
## `specialize_slow`
Previously, all of `specialize()` was marked as `#[inline]`. This
bloated `queue_material_meshes` unnecessarily, as a large chunk of it
ended up being a slow path that was rarely hit. This commit refactors
the function to move the slow path to `specialize_slow()`.
Together, these two changes shave about 5% off `queue_material_meshes`:
![Screenshot 2024-03-29
130002](https://github.com/bevyengine/bevy/assets/157897/a7e5a994-a807-4328-b314-9003429dcdd2)
## Migration Guide
- The `primitive_topology` field on `GpuMesh` is now an accessor method:
`GpuMesh::primitive_topology()`.
- For performance reasons, `MeshPipelineKey` has been split into
`BaseMeshPipelineKey`, which lives in `bevy_render`, and
`MeshPipelineKey`, which lives in `bevy_pbr`. These two should be
combined with bitwise-or to produce the final `MeshPipelineKey`.
# Objective
Related to #10572
Allow the `Annulus` primitive to be meshed.
## Solution
We introduce a `Meshable` structure, `AnnulusMeshBuilder`, which allows
the `Annulus` primitive to be meshed, leaving optional configuration of
the number of angular sudivisions to the user. Here is a picture of the
annulus's UV-mapping:
<img width="1440" alt="Screenshot 2024-03-26 at 10 39 48 AM"
src="https://github.com/bevyengine/bevy/assets/2975848/b170291d-cba7-441b-90ee-2ad6841eaedb">
Other features are essentially identical to the implementations for
`Circle`/`Ellipse`.
---
## Changelog
- Introduced `AnnulusMeshBuilder`
- Implemented `Meshable` for `Annulus` with `Output =
AnnulusMeshBuilder`
- Implemented `From<Annulus>` and `From<AnnulusMeshBuilder>` for `Mesh`
- Added `impl_reflect!` declaration for `Annulus` and `Triangle3d` in
`bevy_reflect`
---
## Discussion
### Design considerations
The only interesting wrinkle here is that the existing UV-mapping of
`Ellipse` (and hence of `Circle` and `RegularPolygon`) is non-radial
(it's skew-free, created by situating the mesh in a bounding rectangle),
so the UV-mapping of `Annulus` doesn't limit to that of `Circle` as its
inner radius tends to zero, for instance. I don't see this as a real
issue for `Annulus`, which should almost certainly have this kind of
UV-mapping, but I think we ought to at least consider allowing mesh
configuration for `Circle`/`Ellipse` that performs radial UV-mapping
instead. (In these cases in particular, it would be especially easy,
since we wouldn't need a different parameter set in the builder.)
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- #10572
There is no 3D primitive available for the common shape of a tetrahedron
(3-simplex).
## Solution
This PR introduces a new type to the existing math primitives:
- `Tetrahedron`: a polyhedron composed of four triangular faces, six
straight edges, and four vertices
---
## Changelog
### Added
- `Tetrahedron` primitive to the `bevy_math` crate
- `Tetrahedron` tests (`area`, `volume` methods)
- `impl_reflect!` declaration for `Tetrahedron` in the `bevy_reflect`
crate
# Objective
Fixes#12442
## Solution
Change `process_touch_event` to not update previous_position /
previous_force, and change it once per frame in
`touch_screen_input_system`.
# Objective
Sometimes it's useful to iterate over removed entities. For example, in
my library
[bevy_replicon](https://github.com/projectharmonia/bevy_replicon) I need
it to iterate over all removals to replicate them over the network.
Right now we do lookups, but it would be more convenient and faster to
just iterate over all removals.
## Solution
Add `RemovedComponentEvents::iter`.
---
## Changelog
### Added
- `RemovedComponentEvents::iter` to iterate over all removed components.
---------
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
# Objective
- There are several redundant imports in the tests and examples that are
not caught by CI because additional flags need to be passed.
## Solution
- Run `cargo check --workspace --tests` and `cargo check --workspace
--examples`, then fix all warnings.
- Add `test-check` to CI, which will be run in the check-compiles job.
This should catch future warnings for tests. Examples are already
checked, but I'm not yet sure why they weren't caught.
## Discussion
- Should the `--tests` and `--examples` flags be added to CI, so this is
caught in the future?
- If so, #12818 will need to be merged first. It was also a warning
raised by checking the examples, but I chose to split off into a
separate PR.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
There are currently 2 different warning messages that are logged when
resizing on Linux with Nvidia drivers (introduced in
70c69cdd51).
Fixes#12830
## Solution
Generalize both to say:
```Couldn't get swap chain texture. This often happens with the NVIDIA drivers on Linux. It can be safely ignored.```
# Objective
- Since #12453, `DeterministicRenderingConfig` doesn't do anything
## Solution
- Remove it
---
## Migration Guide
- Removed `DeterministicRenderingConfig`. There shouldn't be any z
fighting anymore in the rendering even without setting
`stable_sort_z_fighting`
# Objective
- The `bundles` parameter in `insert_or_spawn_batch` method has
inconsistent naming with docs (e.g. `bundles_iter`) since #11107.
## Solution
- Replace `bundles` with `bundles_iter`, as `bundles_iter` is more
expressive to its type.
# Objective
Make it easy for crates.io / lib.rs users or automated tools to find the
repository of `bevy_utils_proc_macros`
## Solution
Add the `repository` field to the `Cargo.toml` of
`bevy_utils_proc_macros`
# Objective
This is a necessary precursor to #9122 (this was split from that PR to
reduce the amount of code to review all at once).
Moving `!Send` resource ownership to `App` will make it unambiguously
`!Send`. `SubApp` must be `Send`, so it can't wrap `App`.
## Solution
Refactor `App` and `SubApp` to not have a recursive relationship. Since
`SubApp` no longer wraps `App`, once `!Send` resources are moved out of
`World` and into `App`, `SubApp` will become unambiguously `Send`.
There could be less code duplication between `App` and `SubApp`, but
that would break `App` method chaining.
## Changelog
- `SubApp` no longer wraps `App`.
- `App` fields are no longer publicly accessible.
- `App` can no longer be converted into a `SubApp`.
- Various methods now return references to a `SubApp` instead of an
`App`.
## Migration Guide
- To construct a sub-app, use `SubApp::new()`. `App` can no longer
convert into `SubApp`.
- If you implemented a trait for `App`, you may want to implement it for
`SubApp` as well.
- If you're accessing `app.world` directly, you now have to use
`app.world()` and `app.world_mut()`.
- `App::sub_app` now returns `&SubApp`.
- `App::sub_app_mut` now returns `&mut SubApp`.
- `App::get_sub_app` now returns `Option<&SubApp>.`
- `App::get_sub_app_mut` now returns `Option<&mut SubApp>.`
# Objective
Fix crashing on Linux with latest stable Nvidia 550 driver when
resizing. The crash happens at startup with some setups.
Fixes#12199
I think this would be nice to get into 0.13.1
## Solution
Ignore `wgpu::SurfaceError::Outdated` always on this platform+driver.
It looks like Nvidia considered the previous behaviour of not returning
this error a bug:
"Fixed a bug where vkAcquireNextImageKHR() was not returning
VK_ERROR_OUT_OF_DATE_KHR when it should with WSI X11 swapchains"
(https://www.nvidia.com/Download/driverResults.aspx/218826/en-us/)
What I gather from this is that the surface was outdated on previous
drivers too, but they just didn't report it as an error. So behaviour
shouldn't change.
In the issue conversation we experimented with calling `continue` when
this error happens, but I found that it results in some small issues
like bevy_egui scale not updating with the window sometimes. Just doing
nothing seems to work better.
## Changelog
- Fixed crashing on Linux with Nvidia 550 driver when resizing the
window
## Migration Guide
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
For some asset loaders, it can be useful not to read the entire asset
file and just read a specific region of a file. For this, we need a way
to seek at a specific position inside the file
## Solution
I added support for `AsyncSeek` to `Reader`. In my case, I want to only
read a part of a file, and for that I need to seek to a specific point.
## Migration Guide
Every custom reader (which previously only needed the `AsyncRead` trait
implemented) now also needs to implement the `AsyncSeek` trait to add
the seek capability.
# Objective
- Fix#12746
- When users despawn a scene, the `InstanceId` within `spawned_scenes`
and `spawned_dynamic_scenes` is not removed, causing a potential memory
leak
## Solution
- `spawned_scenes` field was never used, and I removed it
- Add a component remove hook for `Handle<DynamicScene>`, and when the
`Handle<DynamicScene>` component is removed, delete the corresponding
`InstanceId` from `spawned_dynamic_scenes`
- Fixes #[12762](https://github.com/bevyengine/bevy/issues/12762).
## Migration Guide
- `Quat` no longer implements `VectorSpace` as unit quaternions don't
actually form proper vector spaces. If you're absolutely certain that
what you're doing is correct, convert the `Quat` into a `Vec4` and
perform the operations before converting back.
# Objective
Other than the exposed functions for reading matched tables and
archetypes, a `QueryState` does not actually need both internal Vecs for
storing matched archetypes and tables. In practice, it will only use one
of the two depending on if it uses dense or archetypal iteration.
Same vein as #12474. The goal is to reduce the memory overhead of using
queries, which Bevy itself, ecosystem plugins, and end users are already
fairly liberally using.
## Solution
Add `StorageId`, which is a union over `TableId` and `ArchetypeId`, and
store only one of the two at runtime. Read the slice as if it was one ID
depending on whether the query is dense or not.
This follows in the same vein as #5085; however, this one directly
impacts heap memory usage at runtime, while #5085 primarily targeted
transient pointers that might not actually exist at runtime.
---
## Changelog
Changed: `QueryState::matched_tables` now returns an iterator instead of
a reference to a slice.
Changed: `QueryState::matched_archetypes` now returns an iterator
instead of a reference to a slice.
## Migration Guide
`QueryState::matched_tables` and `QueryState::matched_archetypes` does
not return a reference to a slice, but an iterator instead. You may need
to use iterator combinators or collect them into a Vec to use it as a
slice.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Speed up CPU-side rendering.
## Solution
Use `QueryIter::for_each` and `Mut::bypass_change_detection` to minimize
the total amount of data being written and allow autovectorization to
speed up iteration.
## Performance
Tested against the default `many_cubes`, this results in greater than
15x speed up: 281us -> 18.4us.
![image](https://github.com/bevyengine/bevy/assets/3137680/18369285-843e-4eb6-9716-c99c6f5ea4e2)
As `ViewVisibility::HIDDEN` just wraps false, this is likely just
degenerating into `memset(0)`s on the tables.
Today, we sort all entities added to all phases, even the phases that
don't strictly need sorting, such as the opaque and shadow phases. This
results in a performance loss because our `PhaseItem`s are rather large
in memory, so sorting is slow. Additionally, determining the boundaries
of batches is an O(n) process.
This commit makes Bevy instead applicable place phase items into *bins*
keyed by *bin keys*, which have the invariant that everything in the
same bin is potentially batchable. This makes determining batch
boundaries O(1), because everything in the same bin can be batched.
Instead of sorting each entity, we now sort only the bin keys. This
drops the sorting time to near-zero on workloads with few bins like
`many_cubes --no-frustum-culling`. Memory usage is improved too, with
batch boundaries and dynamic indices now implicit instead of explicit.
The improved memory usage results in a significant win even on
unbatchable workloads like `many_cubes --no-frustum-culling
--vary-material-data-per-instance`, presumably due to cache effects.
Not all phases can be binned; some, such as transparent and transmissive
phases, must still be sorted. To handle this, this commit splits
`PhaseItem` into `BinnedPhaseItem` and `SortedPhaseItem`. Most of the
logic that today deals with `PhaseItem`s has been moved to
`SortedPhaseItem`. `BinnedPhaseItem` has the new logic.
Frame time results (in ms/frame) are as follows:
| Benchmark | `binning` | `main` | Speedup |
| ------------------------ | --------- | ------- | ------- |
| `many_cubes -nfc -vpi` | 232.179 | 312.123 | 34.43% |
| `many_cubes -nfc` | 25.874 | 30.117 | 16.40% |
| `many_foxes` | 3.276 | 3.515 | 7.30% |
(`-nfc` is short for `--no-frustum-culling`; `-vpi` is short for
`--vary-per-instance`.)
---
## Changelog
### Changed
* Render phases have been split into binned and sorted phases. Binned
phases, such as the common opaque phase, achieve improved CPU
performance by avoiding the sorting step.
## Migration Guide
- `PhaseItem` has been split into `BinnedPhaseItem` and
`SortedPhaseItem`. If your code has custom `PhaseItem`s, you will need
to migrate them to one of these two types. `SortedPhaseItem` requires
the fewest code changes, but you may want to pick `BinnedPhaseItem` if
your phase doesn't require sorting, as that enables higher performance.
## Tracy graphs
`many-cubes --no-frustum-culling`, `main` branch:
<img width="1064" alt="Screenshot 2024-03-12 180037"
src="https://github.com/bevyengine/bevy/assets/157897/e1180ce8-8e89-46d2-85e3-f59f72109a55">
`many-cubes --no-frustum-culling`, this branch:
<img width="1064" alt="Screenshot 2024-03-12 180011"
src="https://github.com/bevyengine/bevy/assets/157897/0899f036-6075-44c5-a972-44d95895f46c">
You can see that `batch_and_prepare_binned_render_phase` is a much
smaller fraction of the time. Zooming in on that function, with yellow
being this branch and red being `main`, we see:
<img width="1064" alt="Screenshot 2024-03-12 175832"
src="https://github.com/bevyengine/bevy/assets/157897/0dfc8d3f-49f4-496e-8825-a66e64d356d0">
The binning happens in `queue_material_meshes`. Again with yellow being
this branch and red being `main`:
<img width="1064" alt="Screenshot 2024-03-12 175755"
src="https://github.com/bevyengine/bevy/assets/157897/b9b20dc1-11c8-400c-a6cc-1c2e09c1bb96">
We can see that there is a small regression in `queue_material_meshes`
performance, but it's not nearly enough to outweigh the large gains in
`batch_and_prepare_binned_render_phase`.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
This commit changes the `StandardMaterialKey` to be based on a set of
bitflags instead of a structure. We hash it every frame for every mesh,
and `#[derive(Hash)]` doesn't generate particularly efficient code for
large structures full of small types. Packing it into a single `u64`
therefore results in a roughly 10% speedup in `queue_material_meshes` on
`many_cubes --no-frustum-culling`.
![Screenshot 2024-03-29
075124](https://github.com/bevyengine/bevy/assets/157897/78afcab6-b616-489b-8243-da9a117f606c)
# Objective
Wireframes are currently supported for 3D meshes using the
`WireframePlugin` in `bevy_pbr`. This PR adds the same functionality for
2D meshes.
Closes#5881.
## Solution
Since there's no easy way to share material implementations between 2D,
3D, and UI, this is mostly a straight copy and rename from the original
plugin into `bevy_sprite`.
<img width="1392" alt="image"
src="https://github.com/bevyengine/bevy/assets/3961616/7aca156f-448a-4c7e-89b8-0a72c5919769">
---
## Changelog
- Added `Wireframe2dPlugin` and related types to support 2D wireframes.
- Added an example to demonstrate how to use 2D wireframes
---------
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
- Allow cloning `WinitSettings`. I use this in
[bevy_worldswap](https://github.com/UkoeHB/bevy_worldswap) when
synchronizing secondary app window state.
## Solution
- Add `Clone` to `WinitSettings`.
---
## Changelog
- Added `Clone` to `WinitSettings`.
# Objective
- Reduce the size of `create_windows` and isolate accessibility setup
logic.
## Solution
- Move accessibility setup for new windows to the `accessibility`
module.
## Comments
This is a small refactor, no behavior changes.
# Objective
- Disabling some plugins causes a crash due to ambiguities relying in
feature flags and not checking if both plugins are enabled causing code
like this to crash:
`app.add_plugins(DefaultPlugins.build().disable::<AnimationPlugin>())`
## Solution
- Check if plugins were added before ambiguities.
- Move bevy_gizmos ambiguities from bevy_internal to bevy_gizmos since
they already depend on them.
# Objective
Fixes#12752. Fixes#12750. Document the runtime complexity of all of
the `O(1)` operations on the individual APIs.
## Solution
* Mirror `Query::contains` onto `QueryState::contains`
* Make `QueryState::as_nop` pub(crate)
* Make `NopWorldQuery` pub(crate)
* Document all of the O(1) operations on Query and QueryState.
# Objective
Fixes#12727. All parts that `PersistentGpuBuffer` interact with should
be 100% safe both on the CPU and the GPU: `Queue::write_buffer_with`
zeroes out the slice being written to and when uploading to the GPU, and
all slice writes are bounds checked on the CPU side.
## Solution
Make `PersistentGpuBufferable` a safe trait. Enforce it's correct
implementation via assertions. Re-enable `forbid(unsafe_code)` on
`bevy_pbr`.
# Objective
- A scene usually gets created using the `SceneBundle` or
`DynamicSceneBundle`. This means that the scene's entities get added as
children of the root entity (the entity on which the `SceneBundle` gets
added)
- When the scene gets deleted using the `SceneSpawner`, the scene's
entities are deleted, but the `Children` component of the root entity
doesn't get updated. This means that the hierarchy becomes unsound, with
Children linking to non-existing components.
## Solution
- Update the `despawn_sync` logic to also update the `Children` from any
parents of the scene, if there are any
- Adds a test where a Scene gets despawned and checks for dangling
Children references on the parent. The test fails on `main` but works
here.
## Alternative implementations
- One option could be to add a `parent: Option<Entity>` on the
[InstanceInfo](df15cd7dcc/crates/bevy_scene/src/scene_spawner.rs (L27))
struct that tracks if the SceneInstance was added as a child of a root
entity
# Objective
When I wrote #12747 I neglected to translate random samples from
triangles back to the point where they originated, so they would be
sampled near the origin instead of at the actual triangle location.
## Solution
Translate by the first vertex location so that the samples follow the
actual triangle.
# Objective
Fixes#12392, fixes#12393, and fixes#11387. Implement QueryData for
Archetype and EntityLocation.
## Solution
Add impls for both of the types.
---
## Changelog
Added: `&Archetype` now implements `QueryData`
Added: `EntityLocation` now implements `QueryData`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Closes https://github.com/bevyengine/bevy/pull/12415
## Solution
- Refactored code that was changed/deprecated in `image` 0.25.
- Please review this PR carefully since I'm just making the changes
without any context or deep knowledge of the module.
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
Fix#12728. Fix unsoundnesss from unhandled null characters in Android
logs.
## Solution
Use `CString` instead of using formatted Strings. Properly document the
safety invariants of the FFI call.
# Objective
- Move `PanicHandlerPlugin` into `bevy_app`
- Fixes#12603 .
## Solution
- I moved the `bevy_panic_handler` into `bevy_app`
- Copy pasted `bevy_panic_handler`'s lib.rs into a separate module in
`bevy_app` as a `panic_handler.rs` module file and added the
`PanicHandlerPlugin` in lib.rs of `bevy_app`
- added the dependency into `cargo.toml`
## Review notes
- I probably want some feedback if I imported App and Plugin correctly
in `panic_handler.rs` line 10 and 11.
- As of yet I have not deleted `bevy_panic_handler` crate, wanted to get
a check if I added it correctly.
- Once validated that my move was correct, I'll probably have to remove
the panic handler find default plugins which I probably need some help
to find.
- And then remove bevy panic_handler and making sure ci passes.
- This is my first issue for contributing to bevy so let me know if I am
doing anything wrong.
## tools context
- rust is 1.76 version
- Windows 11
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Avoid unbounded HashMap growth for opening/closing windows.
## Solution
- Remove map entry in `WinitWindows::remove_window`.
## Migration Guide
- `WinitWindows::get_window_entity` now returns `None` after a window is
closed, instead of a dead entity.
---
## Comments
The comment this PR replaces was added in
https://github.com/bevyengine/bevy/pull/3575. Since `get_window_entity`
now returns an `Entity` instead of a `WindowId`, this no longer seems
useful. Note that `get_window_entity` is only used
[here](56bcbb0975/crates/bevy_winit/src/lib.rs (L436)),
immediately followed by a warning if the entity returned doesn't exist.
# Objective
- Fixes#12677
## Solution
Updated documentation to make it explicit that enabling the appropriate
optional features is required to use the supported audio file format, as
well as provided link to the Bevy docs listing the optional features.
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
## Problem
- A mutable borrow of a handle cannot be directly turned into an AssetId
with `.into()`. You must do a reborrow `&*my_handle`.
## Solution
- Add an impl for From<&mut Handle> to AssetId and UntypedAssetId.
# Objective
Previously, the `Point` trait, which abstracts all of the operations of
a real vector space, was sitting in the submodule of `bevy_math` for
cubic splines. However, the trait has broader applications than merely
cubic splines, and we should use it when possible to avoid code
duplication when performing vector operations.
## Solution
`Point` has been moved into a new submodule in `bevy_math` named
`common_traits`. Furthermore, it has been renamed to `VectorSpace`,
which is more descriptive, and an additional trait `NormedVectorSpace`
has been introduced to expand the API to cover situations involving
geometry in addition to algebra. Additionally, `VectorSpace` itself now
requires a `ZERO` constant and `Neg`. It also supports a `lerp` function
as an automatic trait method.
Here is what that looks like:
```rust
/// A type that supports the mathematical operations of a real vector space, irrespective of dimension.
/// In particular, this means that the implementing type supports:
/// - Scalar multiplication and division on the right by elements of `f32`
/// - Negation
/// - Addition and subtraction
/// - Zero
///
/// Within the limitations of floating point arithmetic, all the following are required to hold:
/// - (Associativity of addition) For all `u, v, w: Self`, `(u + v) + w == u + (v + w)`.
/// - (Commutativity of addition) For all `u, v: Self`, `u + v == v + u`.
/// - (Additive identity) For all `v: Self`, `v + Self::ZERO == v`.
/// - (Additive inverse) For all `v: Self`, `v - v == v + (-v) == Self::ZERO`.
/// - (Compatibility of multiplication) For all `a, b: f32`, `v: Self`, `v * (a * b) == (v * a) * b`.
/// - (Multiplicative identity) For all `v: Self`, `v * 1.0 == v`.
/// - (Distributivity for vector addition) For all `a: f32`, `u, v: Self`, `(u + v) * a == u * a + v * a`.
/// - (Distributivity for scalar addition) For all `a, b: f32`, `v: Self`, `v * (a + b) == v * a + v * b`.
///
/// Note that, because implementing types use floating point arithmetic, they are not required to actually
/// implement `PartialEq` or `Eq`.
pub trait VectorSpace:
Mul<f32, Output = Self>
+ Div<f32, Output = Self>
+ Add<Self, Output = Self>
+ Sub<Self, Output = Self>
+ Neg
+ Default
+ Debug
+ Clone
+ Copy
{
/// The zero vector, which is the identity of addition for the vector space type.
const ZERO: Self;
/// Perform vector space linear interpolation between this element and another, based
/// on the parameter `t`. When `t` is `0`, `self` is recovered. When `t` is `1`, `rhs`
/// is recovered.
///
/// Note that the value of `t` is not clamped by this function, so interpolating outside
/// of the interval `[0,1]` is allowed.
#[inline]
fn lerp(&self, rhs: Self, t: f32) -> Self {
*self * (1. - t) + rhs * t
}
}
```
```rust
/// A type that supports the operations of a normed vector space; i.e. a norm operation in addition
/// to those of [`VectorSpace`]. Specifically, the implementor must guarantee that the following
/// relationships hold, within the limitations of floating point arithmetic:
/// - (Nonnegativity) For all `v: Self`, `v.norm() >= 0.0`.
/// - (Positive definiteness) For all `v: Self`, `v.norm() == 0.0` implies `v == Self::ZERO`.
/// - (Absolute homogeneity) For all `c: f32`, `v: Self`, `(v * c).norm() == v.norm() * c.abs()`.
/// - (Triangle inequality) For all `v, w: Self`, `(v + w).norm() <= v.norm() + w.norm()`.
///
/// Note that, because implementing types use floating point arithmetic, they are not required to actually
/// implement `PartialEq` or `Eq`.
pub trait NormedVectorSpace: VectorSpace {
/// The size of this element. The return value should always be nonnegative.
fn norm(self) -> f32;
/// The squared norm of this element. Computing this is often faster than computing
/// [`NormedVectorSpace::norm`].
#[inline]
fn norm_squared(self) -> f32 {
self.norm() * self.norm()
}
/// The distance between this element and another, as determined by the norm.
#[inline]
fn distance(self, rhs: Self) -> f32 {
(rhs - self).norm()
}
/// The squared distance between this element and another, as determined by the norm. Note that
/// this is often faster to compute in practice than [`NormedVectorSpace::distance`].
#[inline]
fn distance_squared(self, rhs: Self) -> f32 {
(rhs - self).norm_squared()
}
}
```
Furthermore, this PR also demonstrates the use of the
`NormedVectorSpace` combined API to implement `ShapeSample` for
`Triangle2d` and `Triangle3d` simultaneously. Such deduplication is one
of the drivers for developing these APIs.
---
## Changelog
- `Point` from `cubic_splines` becomes `VectorSpace`, exported as
`bevy::math::VectorSpace`.
- `VectorSpace` requires `Neg` and `VectorSpace::ZERO` in addition to
its existing prerequisites.
- Introduced public traits `bevy::math::NormedVectorSpace` for generic
geometry tasks involving vectors.
- Implemented `ShapeSample` for `Triangle2d` and `Triangle3d`.
## Migration Guide
Since `Point` no longer exists, any projects using it must switch to
`bevy::math::VectorSpace`. Additionally, third-party implementations of
this trait now require the `Neg` trait; the constant `VectorSpace::ZERO`
must be provided as well.
---
## Discussion
### Design considerations
Originally, the `NormedVectorSpace::norm` method was part of a separate
trait `Normed`. However, I think that was probably too broad and, more
importantly, the semantics of having it in `NormedVectorSpace` are much
clearer.
As it currently stands, the API exposed here is pretty minimal, and
there is definitely a lot more that we could do, but there are more
questions to answer along the way. As a silly example, we could
implement `NormedVectorSpace::length` as an alias for
`NormedVectorSpace::norm`, but this overlaps with methods in all of the
glam types, so we would want to make sure that the implementations are
effectively identical (for what it's worth, I think they are already).
### Future directions
One example of something that could belong in the `NormedVectorSpace`
API is normalization. Actually, such a thing previously existed on this
branch before I decided to shelve it because of concerns with namespace
collision. It looked like this:
```rust
/// This element, but normalized to norm 1 if possible. Returns an error when the reciprocal of
/// the element's norm is not finite.
#[inline]
#[must_use]
fn normalize(&self) -> Result<Self, NonNormalizableError> {
let reciprocal = 1.0 / self.norm();
if reciprocal.is_finite() {
Ok(*self * reciprocal)
} else {
Err(NonNormalizableError { reciprocal })
}
}
/// An error indicating that an element of a [`NormedVectorSpace`] was non-normalizable due to having
/// non-finite norm-reciprocal.
#[derive(Debug, Error)]
#[error("Element with norm reciprocal {reciprocal} cannot be normalized")]
pub struct NonNormalizableError {
reciprocal: f32
}
```
With this kind of thing in hand, it might be worth considering
eventually making the passage from vectors to directions fully generic
by employing a wrapper type. (Of course, for our concrete types, we
would leave the existing names in place as aliases.) That is, something
like:
```rust
pub struct NormOne<T>
where T: NormedVectorSpace { //... }
```
Utterly separately, the reason that I implemented `ShapeSample` for
`Triangle2d`/`Triangle3d` was to prototype uniform sampling of abstract
meshes, so that's also a future direction.
---------
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
Adopted from and closes https://github.com/bevyengine/bevy/pull/9914 by
@djeedai
# Objective
Fix the use of `TypeRegistry` instead of `TypeRegistryArc` in dynamic
scene and its serializer.
Rename `DynamicScene::serialize_ron()` into `serialize()` to highlight
the fact this is not about serializing to RON specifically, but rather
about serializing to the official Bevy scene format (`.scn` /
`.scn.ron`) which the `SceneLoader` can deserialize (and which happens
to be based in RON, but that not the object here). Also make the link
with the documentation of `SceneLoader` so users understand the full
serializing cycle of a Bevy dynamic scene.
Document `SceneSerializer` with an example showing how to serialize to a
custom format (here: RON), which is easily transposed to serializing
into any other format.
Fixes#9520
## Changelog
### Changed
* `SceneSerializer` and all related serializing helper types now take a
`&TypeRegistry` instead of a `&TypeRegistryArc`. ([SceneSerializer
needlessly uses specifically
&TypeRegistryArc #9520](https://github.com/bevyengine/bevy/issues/9520))
* `DynamicScene::serialize_ron()` was renamed to `serialize()`.
## Migration Guide
* `SceneSerializer` and all related serializing helper types now take a
`&TypeRegistry` instead of a `&TypeRegistryArc`. You can upgrade by
getting the former from the latter with `TypeRegistryArc::read()`,
_e.g._
```diff
let registry_arc: TypeRegistryArc = [...];
- let serializer = SceneSerializer(&scene, ®istry_arc);
+ let registry = registry_arc.read();
+ let serializer = SceneSerializer(&scene, ®istry);
```
* Rename `DynamicScene::serialize_ron()` to `serialize()`.
---------
Co-authored-by: Jerome Humbert <djeedai@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
Since it is common to store a pair of width and height as `Vec2`, it
would be useful to have an easy way to instantiate `AspectRatio` from
`Vec2`.
## Solution
Add `impl From<Vec2> for AspectRatio`.
---
## Changelog
- Added `impl From<Vec2> for AspectRatio`
# Objective
Fixes `cargo test -p bevy_math` as in #12729.
## Solution
As described in
[message](https://github.com/bevyengine/bevy/issues/12729#issuecomment-2022197944)
Added workaround `bevy_math = { path = ".", version = "0.14.0-dev",
features = ["approx"] }` to `bevy_math`'s `dev-dependencies`
---------
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
# Objective
- Fixes#12712
## Solution
- Move the `float_ord.rs` file to `bevy_math`
- Change any `bevy_utils::FloatOrd` statements to `bevy_math::FloatOrd`
---
## Changelog
- Moved `FloatOrd` from `bevy_utils` to `bevy_math`
## Migration Guide
- References to `bevy_utils::FloatOrd` should be changed to
`bevy_math::FloatOrd`
# Objective
Resolves#3824. `unsafe` code should be the exception, not the norm in
Rust. It's obviously needed for various use cases as it's interfacing
with platforms and essentially running the borrow checker at runtime in
the ECS, but the touted benefits of Bevy is that we are able to heavily
leverage Rust's safety, and we should be holding ourselves accountable
to that by minimizing our unsafe footprint.
## Solution
Deny `unsafe_code` workspace wide. Add explicit exceptions for the
following crates, and forbid it in almost all of the others.
* bevy_ecs - Obvious given how much unsafe is needed to achieve
performant results
* bevy_ptr - Works with raw pointers, even more low level than bevy_ecs.
* bevy_render - due to needing to integrate with wgpu
* bevy_window - due to needing to integrate with raw_window_handle
* bevy_utils - Several unsafe utilities used by bevy_ecs. Ideally moved
into bevy_ecs instead of made publicly usable.
* bevy_reflect - Required for the unsafe type casting it's doing.
* bevy_transform - for the parallel transform propagation
* bevy_gizmos - For the SystemParam impls it has.
* bevy_assets - To support reflection. Might not be required, not 100%
sure yet.
* bevy_mikktspace - due to being a conversion from a C library. Pending
safe rewrite.
* bevy_dynamic_plugin - Inherently unsafe due to the dynamic loading
nature.
Several uses of unsafe were rewritten, as they did not need to be using
them:
* bevy_text - a case of `Option::unchecked` could be rewritten as a
normal for loop and match instead of an iterator.
* bevy_color - the Pod/Zeroable implementations were replaceable with
bytemuck's derive macros.
# Objective
- `FloatOrd` currently has a different comparison behavior between its
derived `PartialOrd` impl and manually implemented `Ord` impl (The
[`Ord` doc](https://doc.rust-lang.org/std/cmp/trait.Ord.html) says this
is a logic error). This might be a problem for some `std`
containers/algorithms if they rely on both matching, and a footgun for
Bevy users.
## Solution
- Replace the `PartialEq` and `Ord` impls of `FloatOrd` with some
equivalent ones producing [better
assembly.](https://godbolt.org/z/jaWbjnMKx)
- Manually derive `PartialOrd` with the same behavior as `Ord`,
implement the comparison operators.
- Add some tests.
I first tried using a match-based implementation similar to the
`PartialOrd` impl [of the
std](https://doc.rust-lang.org/src/core/cmp.rs.html#1457) (with added
NaN ordering) but I couldn't get it to produce non-branching assembly.
The current implementation is based on [the one from the `ordered_float`
crate](3641f59e31/src/lib.rs (L121)),
adapted since it uses a different ordering. Should this be mentionned
somewhere in the code?
---
## Changelog
### Fixed
- `FloatOrd` now uses the same ordering for its `PartialOrd` and `Ord`
implementations.
## Migration Guide
- If you were depending on the `PartialOrd` behaviour of `FloatOrd`, it
has changed from matching `f32` to matching `FloatOrd`'s `Ord` ordering,
never returning `None`.
# Objective
We have `ReflectSerializer` and `TypedReflectSerializer`. The former is
the one users will most often use since the latter takes a bit more
effort to deserialize.
However, our deserializers are named `UntypedReflectDeserializer` and
`TypedReflectDeserializer`. There is no obvious indication that
`UntypedReflectDeserializer` must be used with `ReflectSerializer` since
the names don't quite match up.
## Solution
Rename `UntypedReflectDeserializer` back to `ReflectDeserializer`
(initially changed as part of #5723).
Also update the docs for both deserializers (as they were pretty out of
date) and include doc examples.
I also updated the docs for the serializers, too, just so that
everything is consistent.
---
## Changelog
- Renamed `UntypedReflectDeserializer` to `ReflectDeserializer`
- Updated docs for `ReflectDeserializer`, `TypedReflectDeserializer`,
`ReflectSerializer`, and `TypedReflectSerializer`
## Migration Guide
`UntypedReflectDeserializer` has been renamed to `ReflectDeserializer`.
Usages will need to be updated accordingly.
```diff
- let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
+ let reflect_deserializer = ReflectDeserializer::new(®istry);
```
# Objective
- Be more explicit in the name of the module for the ui debug overlay
- Avoid confusion and possible overlap with new overlays
## Solution
- Rename `debug_overlay` to `ui_debug_overlay`
# Objective
CI is currently broken because of `DiagnosticsRecorder` not being Send
and Sync as required by Resource.
## Solution
Wrap `DiagnosticsRecorder` internally with a `WgpuWrapper`.
# Objective
- #10572
There is no 2D primitive available for the common shape of an annulus
(ring).
## Solution
This PR introduces a new type to the existing math primitives:
- `Annulus`: the region between two concentric circles
---
## Changelog
### Added
- `Annulus` primitive to the `bevy_math` crate
- `Annulus` tests (`diameter`, `thickness`, `area`, `perimeter` and
`closest_point` methods)
---------
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
I found that some .rs files are unnecessarily executable.
Rust source files may start with a shebang-like statement `#!`, so let's
make sure they are not executable just in case.
Here is the result of the `find` commend that lists executable .rs files
as of main branch `86bd648`.
```console
$ find -name \*.rs -type f -executable
./crates/bevy_gizmos/src/lib.rs
./crates/bevy_tasks/src/lib.rs
./crates/bevy_time/src/lib.rs
./crates/bevy_transform/src/lib.rs
./src/lib.rs
```
It appears that the permissions of those files were originally 644, but
were unexpectedly changed to 755 by commit
52e3f2007b.
## Solution
Make them not executable by using this command;
`find -name \*.rs -type f -executable -exec chmod --verbose a-x -- {}
\+`
# Objective
Fix the regression for Root Node's Layout behavior introduced in
https://github.com/bevyengine/bevy/pull/12268
- Add regression test for Root Node Layout's behaving as they did before
0.13.1
- Restore pre 0.13.1 Root Node Layout behavior (fixes
https://github.com/bevyengine/bevy/issues/12624)
## Solution
This implements [@nicoburns suggestion
](https://discord.com/channels/691052431525675048/743663673393938453/1221593626476548146),
where instead of adding the camera to the taffy node tree, we revert
back to adding a new "parent" node for each root node while maintaining
their relationship with the camera.
> If you can do the ecs change detection to move the node to the correct
Taffy instance for the camera then you should also be able to move it to
a `Vec` of root nodes for that camera.
---
## Changelog
Fixed https://github.com/bevyengine/bevy/issues/12624 - Restores pre
0.13.1 Root Node Layout behavior
## Migration Guide
If you were affected by the 0.13.1 regression and added `position_type:
Absolute` to all your root nodes you might be able to reclaim some LOC
by removing them now that the 0.13 behavior is restored.
# Objective
- Adds line styles to bevy gizmos, suggestion of #9400
- Currently solid and dotted lines are implemented but this can easily
be extended to support dashed lines as well if that is wanted.
## Solution
- Adds the enum `GizmoLineStyle` and uses it in each `GizmoConfig` to
configure the style of the line.
- Each "dot" in a dotted line has the same width and height as the
`line_width` of the corresponding line.
---
## Changelog
- Added `GizmoLineStyle` to `bevy_gizmos`
- Added a `line_style: GizmoLineStyle ` attribute to `GizmoConfig`
- Updated the `lines.wgsl` shader and the pipelines accordingly.
## Migration Guide
- Any manually created `GizmoConfig` must now include the `line_style`
attribute
## Additional information
Some pretty pictures :)
This is the 3d_gizmos example with/without `line_perspective`:
<img width="1440" alt="Screenshot 2024-03-09 at 23 25 53"
src="https://github.com/bevyengine/bevy/assets/62256001/b1b97311-e78d-4de3-8dfe-9e48a35bb27d">
<img width="1440" alt="Screenshot 2024-03-09 at 23 25 39"
src="https://github.com/bevyengine/bevy/assets/62256001/50ee8ecb-5290-484d-ba36-7fd028374f7f">
And the 2d example:
<img width="1440" alt="Screenshot 2024-03-09 at 23 25 06"
src="https://github.com/bevyengine/bevy/assets/62256001/4452168f-d605-4333-bfa5-5461d268b132">
---------
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
# Objective
This gets Bevy building on Wasm when the `atomics` flag is enabled. This
does not yet multithread Bevy itself, but it allows Bevy users to use a
crate like `wasm_thread` to spawn their own threads and manually
parallelize work. This is a first step towards resolving #4078 . Also
fixes#9304.
This provides a foothold so that Bevy contributors can begin to think
about multithreaded Wasm's constraints and Bevy can work towards changes
to get the engine itself multithreaded.
Some flags need to be set on the Rust compiler when compiling for Wasm
multithreading. Here's what my build script looks like, with the correct
flags set, to test out Bevy examples on web:
```bash
set -e
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals' \
cargo build --example breakout --target wasm32-unknown-unknown -Z build-std=std,panic_abort --release
wasm-bindgen --out-name wasm_example \
--out-dir examples/wasm/target \
--target web target/wasm32-unknown-unknown/release/examples/breakout.wasm
devserver --header Cross-Origin-Opener-Policy='same-origin' --header Cross-Origin-Embedder-Policy='require-corp' --path examples/wasm
```
A few notes:
1. `cpal` crashes immediately when the `atomics` flag is set. That is
patched in https://github.com/RustAudio/cpal/pull/837, but not yet in
the latest crates.io release.
That can be temporarily worked around by patching Cpal like so:
```toml
[patch.crates-io]
cpal = { git = "https://github.com/RustAudio/cpal" }
```
2. When testing out `wasm_thread` you need to enable the `es_modules`
feature.
## Solution
The largest obstacle to compiling Bevy with `atomics` on web is that
`wgpu` types are _not_ Send and Sync. Longer term Bevy will need an
approach to handle that, but in the near term Bevy is already configured
to be single-threaded on web.
Therefor it is enough to wrap `wgpu` types in a
`send_wrapper::SendWrapper` that _is_ Send / Sync, but panics if
accessed off the `wgpu` thread.
---
## Changelog
- `wgpu` types that are not `Send` are wrapped in
`send_wrapper::SendWrapper` on Wasm + 'atomics'
- CommandBuffers are not generated in parallel on Wasm + 'atomics'
## Questions
- Bevy should probably add CI checks to make sure this doesn't regress.
Should that go in this PR or a separate PR? **Edit:** Added checks to
build Wasm with atomics
---------
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: daxpedda <daxpedda@gmail.com>
Co-authored-by: François <francois.mockers@vleue.com>
# Objective
This PR fixes#12125
## Solution
The logic in this PR was borrowed from gloo-net and essentially probes
the global Javascript context to see if we are in a window or a worker
before calling `fetch_with_str`.
---------
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
# Objective
Currently the built docs only shows the logo and favicon for the top
level `bevy` crate. This makes views like
https://docs.rs/bevy_ecs/latest/bevy_ecs/ look potentially unrelated to
the project at first glance.
## Solution
Reproduce the docs attributes for every crate that Bevy publishes.
Ideally this would be done with some workspace level Cargo.toml control,
but AFAICT, such support does not exist.
# Objective
Make it easy to get the ids of all the components in a bundle (and
initialise any components not yet initialised). This is fairly similar
to the `Bundle::get_component_ids()` method added in the observers PR
however that will return none for any non-initialised components. This
is exactly the API space covered by `Bundle::component_ids()` however
that isn't possible to call outside of `bevy_ecs` as it requires `&mut
Components` and `&mut Storages`.
## Solution
Added `World.init_bundle<B: Bundle>()` which similarly to
`init_component` and `init_resource`, initialises all components in the
bundle and returns a vector of their component ids.
---
## Changelog
Added the method `init_bundle` to `World` as a counterpart to
`init_component` and `init_resource`.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Add serialize feature to bevy_color
- "Fixes #12527".
## Solution
- Added feature for serialization
---
## Changelog
- Serde serialization is now optional, with flag 'serialize'
## Migration Guide
- If user wants color data structures to be serializable, then
application needs to be build with flag 'serialize'
# Objective
- Tiny PR to clarify that `self.world.bundles.init_info::<T>` must have
been called so that the BundleInfo is present in the World
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
We already collect a lot of system information on startup when possible
but we don't make this information available. With the upcoming work on
a diagnostic overlay it would be useful to be able to display this
information.
## Solution
Make the already existing SystemInfo a Resource
---
## Changelog
Added `SystemInfo` Resource
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Afonso Lage <lage.afonso@gmail.com>
# Objective
get_asset_paths tries to check whether a folder is empty, and if so
delete it. However rather than checking whether any subfolder contains
files it checks whether _all_ subfolders have files.
Also cleanup various BoxedFutures in async recursive functions like
these, rust 1.77 now allows recursive async functions (albeit still by
boxing), hurray! This is a followup to #12550 (sorta). More BoxedFuture
stuff can be removed now that rust 1.77 is out, which can use async
recursive functions! This is mainly just cleaner code wise - the
recursion still boxes the future so not much to win there.
PR is mainly whitespace changes so do disable whitespace diffs for
easier review.
# Objective
Follow up from PR #12369 to extract lighting structs from light/mod.rs
into their own file.
Part of the Purdue Refactoring Team's goals issue #12349
## Solution
- Moved PointLight from light/mod.rs to light/point_light.rs
- Moved SpotLight from light/mod.rs to light/spot_light.rs
- Moved DirectionalLight from light/mod.rs to light/directional_light.rs
# Objective
Remove color specialization from `SpritePipeline` after it became
useless in #9597
## Solution
Removed the `COLORED` flag from the pipeline key and removed the
specializing the pipeline over it.
---
## Changelog
### Removed
- `SpritePipelineKey` no longer contains the `COLORED` flag. The flag
has had no effect on how the pipeline operates for a while.
## Migration Guide
- The raw values for the `HDR`, `TONEMAP_IN_SHADER` and `DEBAND_DITHER`
flags have changed, so if you were constructing the pipeline key from
raw `u32`s you'll have to account for that.
# Objective
I was reading some of the Archetype and Bundle code and was getting
confused a little bit in some places (is the `archetype_id` in
`AddBundle` the source or the target archetype id?).
Small PR that adds some docstrings to make it easier for first-time
readers.
# Objective
* Adopted #12025 to fix merge conflicts
* In some cases we used manual impls for certain types, though they are
(at least, now) unnecessary.
## Solution
* Use macros and reflecting-by-value to avoid this clutter.
* Though there were linker issues with Reflect and the CowArc in
AssetPath (see https://github.com/bevyengine/bevy/issues/9747), I
checked these are resolved by using #[reflect_value].
---------
Co-authored-by: soqb <cb.setho@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Clarify that `ButtonInput::just_release` and
`ButtonInput::just_pressed` don't imply information about the state of
`ButtonInput::pressed` or their counterparts.
Fixes#12600
## Solution
Removed Into<AssetId<T>> for Handle<T> as proposed in Issue
conversation, fixed dependent code
## Migration guide
If you use passing Handle by value as AssetId, you should pass reference
or call .id() method on it
Before (0.13):
`assets.insert(handle, value);`
After (0.14):
`assets.insert(&handle, value);`
or
`assets.insert(handle.id(), value);`
# Objective
- Implements maths and `Animatable` for `Srgba` as suggested
[here](https://github.com/bevyengine/bevy/issues/12617#issuecomment-2013494774).
## Solution
- Implements `Animatable` and maths for `Srgba` just like their
implemented for other colors.
---
## Changelog
- Updated the example to mention `Srgba`.
## Migration Guide
- The previously existing implementation of mul/div for `Srgba` did not
modify `alpha` but these operations do modify `alpha` now. Users need to
be aware of this change.
# Objective
- Allow registering of systems from Commands with
`Commands::register_one_shot_system`
- Make registering of one shot systems more easy
## Solution
- Add the Command `RegisterSystem` for Commands use.
- Creation of SystemId based on lazy insertion of the System
- Changed the privacy of the fields in SystemId so Commands can return
the SystemId
---
## Changelog
### Added
- Added command `RegisterSystem`
- Added function `Commands::register_one_shot_system`
- Added function `App::register_one_shot_system`
### Changed
- Changed the privacy and the type of struct tuple to regular struct of
SystemId
## Migration Guide
- Changed SystemId fields from tuple struct to a normal struct
If you want to access the entity field, you should use
`SystemId::entity` instead of `SystemId::0`
## Showcase
> Before, if you wanted to register a system with `Commands`, you would
need to do:
```rust
commands.add(|world: &mut World| {
let id = world.register_system(your_system);
// You would need to insert the SystemId inside an entity or similar
})
```
> Now, you can:
```rust
let id = commands.register_one_shot_system(your_system);
// Do what you want with the Id
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Pablo Reinhardt <pabloreinhardt@gmail.com>
# Context
[GitHub Discussion
Link](https://github.com/bevyengine/bevy/discussions/12506)
# Objective
- **Clarity:** More explicit representation of a common geometric
primitive.
- **Convenience:** Provide methods tailored to 3D triangles (area,
perimeters, etc.).
## Solution
- Adding the `Triangle3d` primitive into the `bevy_math` crate.
---
## Changelog
### Added
- `Triangle3d` primitive to the `bevy_math` crate
### Changed
- `Triangle2d::reverse`: the first and last vertices are swapped instead
of the second and third.
---------
Co-authored-by: Miles Silberling-Cook <NthTensor@users.noreply.github.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
I'm reading through the ecs query code for the first time, and updating
the docs:
- fixed some typos
- added some docs about things I was confused about (in particular what
the difference between `matches_component_set` and
`update_component_access` was)
# Objective
Fixes#12200 .
## Solution
I added a Hue Trait with the rotate_hue method to enable hue rotation.
Additionally, I modified the implementation of animations in the
animated_material sample.
---
## Changelog
- Added a `Hue` trait to `bevy_color/src/color_ops.rs`.
- Added the `Hue` trait implementation to `Hsla`, `Hsva`, `Hwba`,
`Lcha`, and `Oklcha`.
- Updated animated_material sample.
## Migration Guide
Users of Oklcha need to change their usage to use the with_hue method
instead of the with_h method.
---------
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fixes#12202
## Solution
- Implements `Animatable` for all color types implementing arithmetic
operations.
- the colors returned by `Animatable`s methods are already clamped.
- Adds a `color_animation.rs` example.
- Implements the `*Assign` operators for color types that already had
the corresponding operators. This is just a 'nice to have' and I am
happy to remove this if it's not wanted.
---
## Changelog
- `bevy_animation` now depends on `bevy_color`.
- `LinearRgba`, `Laba`, `Oklaba` and `Xyza` implement `Animatable`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
# Objective
- It can be useful to have access to the path of the current asset being
processed, for example if you want to need a second file that is
relative to the current file being processed.
## Solution
- I added a `path()` function to the `ProcessContext`
# Objective
- Fixes#12570
## Solution
Previously, cardinal splines constructed by `CubicCardinalSpline` would
leave out their endpoints when constructing the cubic curve segments
connecting their points. (See the linked issue for details.)
Now, cardinal splines include the endpoints. For instance, the provided
usage example
```rust
let points = [
vec2(-1.0, -20.0),
vec2(3.0, 2.0),
vec2(5.0, 3.0),
vec2(9.0, 8.0),
];
let cardinal = CubicCardinalSpline::new(0.3, points).to_curve();
let positions: Vec<_> = cardinal.iter_positions(100).collect();
```
will actually produce a spline that connects all four of these points
instead of just the middle two "interior" points.
Internally, this is achieved by duplicating the endpoints of the vector
of control points before performing the construction of the associated
`CubicCurve`. This amounts to specifying that the tangents at the
endpoints `P_0` and `P_n` (say) should be parallel to `P_1 - P_0` and
`P_n - P_{n-1}`.
---
## Migration Guide
Any users relying on the old behavior of `CubicCardinalSpline` will have
to truncate any parametrizations they used in order to access a curve
identical to the one they had previously. This would be done by chopping
off a unit-distance segment from each end of the parametrizing interval.
For instance, if a user's existing code looks as follows
```rust
fn interpolate(t: f32) -> Vec2 {
let points = [
vec2(-1.0, -20.0),
vec2(3.0, 2.0),
vec2(5.0, 3.0),
vec2(9.0, 8.0),
];
let my_curve = CubicCardinalSpline::new(0.3, points).to_curve();
my_curve.position(t)
}
```
then in order to obtain similar behavior, `t` will need to be shifted up
by 1, since the output of `CubicCardinalSpline::to_curve` has introduced
a new segment in the interval [0,1], displacing the old segment from
[0,1] to [1,2]:
```rust
fn interpolate(t: f32) -> Vec2 {
let points = [
vec2(-1.0, -20.0),
vec2(3.0, 2.0),
vec2(5.0, 3.0),
vec2(9.0, 8.0),
];
let my_curve = CubicCardinalSpline::new(0.3, points).to_curve();
my_curve.position(t+1)
}
```
(Note that this does not provide identical output for values of `t`
outside of the interval [0,1].)
On the other hand, any user who was specifying additional endpoint
tangents simply to get the curve to pass through the right points (i.e.
not requiring exactly the same output) can simply omit the endpoints
that were being supplied only for control purposes.
---
## Discussion
### Design considerations
This is one of the two approaches outlined in #12570 — in this PR, we
are basically declaring that the docs are right and the implementation
was flawed.
One semi-interesting question is how the endpoint tangents actually
ought to be defined when we include them, and another option considered
was mirroring the control points adjacent to the endpoints instead of
duplicating them, which would have had the advantage that the expected
length of the corresponding difference should be more similar to that of
the other difference-tangents, provided that the points are equally
spaced.
In this PR, the duplication method (which produces smaller tangents) was
chosen for a couple reasons:
- It seems to be more standard
- It is exceptionally simple to implement
- I was a little concerned that the aforementioned alternative would
result in some over-extrapolation
### An annoyance
If you look at the code, you'll see I was unable to find a satisfactory
way of doing this without allocating a new vector. This doesn't seem
like a big problem given the context, but it does bother me. In
particular, if there is some easy parallel to `slice::windows` for
iterators that doesn't pull in an external dependency, I would love to
know about it.
# Objective
Lets say I have the following `.meta` file:
```RON
(
meta_format_version: "1.0",
asset: Ignore,
)
```
When a file is inside the `assets` directory and processing is enabled,
the processor will copy the file into `imported_assets` although it
should be ignored and therefore not copied.
## Solution
- I added a simple check that does not copy the assets if the
AssetAction is `Ignore`.
## Migration Guide
- The public `ProcessResult` enum now has a `ProcessResult::Ignore`
variant that must be handled.
# Objective
Fix Pr CI failing over dead code in tests and main branch CI failing
over a missing semicolon. Fixes#12620.
## Solution
Add dead_code annotations and a semicolon.
# Objective
- #12500 use the primary window resolution to do all its calculation.
This means bad support for multiple windows or multiple ui camera
## Solution
- Use camera driven UI (https://github.com/bevyengine/bevy/pull/10559)
# Objective
- since #12500, text is a little bit more gray in UI
## Solution
- don't multiply color by alpha. I think this was done in the original
PR (#8973) for shadows which were not added in #12500
# Objective
- Currently the fps_overlay affects any other ui node spawned. This
should not happen
## Solution
- Use position absolute and a ZIndex of `i32::MAX - 32`
- I also modified the example a little bit to center it correctly. It
only worked previously because the overlay was pushing it down. I also
took the opportunity to simplify the text spawning code a little bit.
# Objective
- #12500 broke images and background colors in UI. Try examples
`overflow`, `ui_scaling` or `ui_texture_atlas`
## Solution
- Makes the component `BorderRadius` optional in the query, as it's not
always present. Use `[0.; 4]` as border radius in the extracted node
when none was found
# Objective
Fixes#12224.
## Solution
- Expand `with_` methods for the `Oklch` to their full names.
- Expand `l` to `lightness` in `Oklaba` comments.
## Migration Guide
The following methods have been renamed for the `Oklch` color space:
- `with_l` -> `with_lightness`.
- `with_c` -> `with_chroma`.
- `with_h` -> `with_hue`.
# Objective
- Many types in bevy_render doesn't reflect Default even if it could.
## Solution
- Reflect it.
---
---------
Co-authored-by: Pablo Reinhardt <pabloreinhardt@gmail.com>
# Objective
- Fixes#12202
## Solution
- This PR implements componentwise (including alpha) addition,
subtraction and scalar multiplication/division for some color types.
- The mentioned color types are `Laba`, `Oklaba`, `LinearRgba` and
`Xyza` as all of them are either physically or perceptually linear as
mentioned by @alice-i-cecile in the issue.
---
## Changelog
- Scalar mul/div for `LinearRgba` may modify alpha now.
## Migration Guide
- Users of scalar mul/div for `LinearRgba` need to be aware of the
change and maybe use the `.clamp()` methods or manually set the `alpha`
channel.
# Objective
Implements border radius for UI nodes. Adopted from #8973, but excludes
shadows.
## Solution
- Add a component `BorderRadius` which contains a radius value for each
corner of the UI node.
- Use a fragment shader to generate the rounded corners using a signed
distance function.
<img width="50%"
src="https://github.com/bevyengine/bevy/assets/26204416/16b2ba95-e274-4ce7-adb2-34cc41a776a5"></img>
## Changelog
- `BorderRadius`: New component that holds the border radius values.
- `NodeBundle` & `ButtonBundle`: Added a `border_radius: BorderRadius`
field.
- `extract_uinode_borders`: Stripped down, most of the work is done in
the shader now. Borders are no longer assembled from multiple rects,
instead the shader uses a signed distance function to draw the border.
- `UiVertex`: Added size, border and radius fields.
- `UiPipeline`: Added three vertex attributes to the vertex buffer
layout, to accept the UI node's size, border thickness and border
radius.
- Examples: Added rounded corners to the UI element in the `button`
example, and a `rounded_borders` example.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
# Objective
- Allow configuring of platform-specific panic handlers.
- Remove the silent overwrite of the WASM panic handler
- Closes#12546
## Solution
- Separates the panic handler to a new plugin, `PanicHandlerPlugin`.
- `PanicHandlerPlugin` was added to `DefaultPlugins`.
- Can be disabled on `DefaultPlugins`, in the case someone needs to
configure custom panic handlers.
---
## Changelog
### Added
- A `PanicHandlerPlugin` was added to the `DefaultPlugins`, which now
sets sensible target-specific panic handlers.
### Changed
- On WASM, the panic stack trace was output to the console through the
`BevyLogPlugin`. Since this was separated out into `PanicHandlerPlugin`,
you may need to add the new `PanicHandlerPlugin` (included in
`DefaultPlugins`).
## Migration Guide
- If you used `MinimalPlugins` with `LogPlugin` for a WASM-target build,
you will need to add the new `PanicHandlerPlugin` to set the panic
behavior to output to the console. Otherwise, you will see the default
panic handler (opaque, `unreachable` errors in the console).
# Objective
- This is an adopted version of #10420
- The objective is to help debugging the Ui layout tree with helpful
outlines, that can be easily enabled/disabled
## Solution
- Like #10420, the solution is using the bevy_gizmos in outlining the
nodes
---
## Changelog
### Added
- Added debug_overlay mod to `bevy_dev_tools`
- Added bevy_ui_debug feature to `bevy_dev_tools`
## How to use
- The user must use `bevy_dev_tools` feature in TOML
- The user must use the plugin UiDebugPlugin, that can be found on
`bevy::dev_tools::debug_overlay`
- Finally, to enable the function, the user must set
`UiDebugOptions::enabled` to true
Someone can easily toggle the function with something like:
```rust
fn toggle_overlay(input: Res<ButtonInput<KeyCode>>, options: ResMut<UiDebugOptions>) {
if input.just_pressed(KeyCode::Space) {
// The toggle method will enable if disabled and disable if enabled
options.toggle();
}
}
```
Note that this feature can be disabled from dev_tools, as its in fact
behind a default feature there, being the feature bevy_ui_debug.
# Limitations
Currently, due to limitations with gizmos itself, it's not possible to
support this feature to more the one window, so this tool is limited to
the primary window only.
# Showcase
![image](https://github.com/bevyengine/bevy/assets/126117294/ce9d70e6-0a57-4fa9-9753-ff5a9d82c009)
Ui example with debug_overlay enabled
![image](https://github.com/bevyengine/bevy/assets/126117294/e945015c-5bab-4d7f-9273-472aabaf25a9)
And disabled
---------
Co-authored-by: Nicola Papale <nico@nicopap.ch>
Co-authored-by: Pablo Reinhardt <pabloreinhardt@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Give Bevy a well-designed built-in color palette for users to use while
prototyping or authoring Bevy examples.
## Solution
Generate
([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f7b3a3002fb7727db15c1197e0a1a373),
[gist](https://gist.github.com/rust-play/f7b3a3002fb7727db15c1197e0a1a373))
consts from [Tailwind](https://tailwindcss.com/docs/customizing-colors)
(mit license) json.
## Discussion
Are there other popular alternatives we should be looking at? Something
new and fancy involving a really long acronym like CIELUVLCh? I'm not a
tailwind user or color expert, but I really like the way it's broken up
into distinct but plentiful hue and lightness groups.
It beats needing some shades of red, scrolling through the [current
palette](https://docs.rs/bevy/latest/bevy/prelude/enum.Color.html),
choosing a few of `CRIMSON`, `MAROON`, `RED`, `TOMATO` at random and
calling it a day.
The best information I was able to dig up about the Tailwind palette is
from this thread:
https://twitter.com/steveschoger/status/1303795136703410180. Here are
some key excerpts:
> Tried to the "perceptually uniform" thing for Tailwind UI.
> Ultimately, it just resulted in a bunch of useless shades for colors
like yellow and green that are inherently brighter.
> With that said you're guaranteed to get a contrast ratio of 4.5:1 when
using any 700 shade (in some cases 600) on a 100 shade of the same hue.
> We just spent a lot of time looking at sites to figure out which
colors are popular and tried to fill all the gaps.
> Even the lime green is questionable but felt there needed to be
something in between the jump from yellow to green 😅
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Simplify implementing some asset traits without Box::pin(async move{})
shenanigans.
Fixes (in part) https://github.com/bevyengine/bevy/issues/11308
## Solution
Use async-fn in traits when possible in all traits. Traits with return
position impl trait are not object safe however, and as AssetReader and
AssetWriter are both used with dynamic dispatch, you need a Boxed
version of these futures anyway.
In the future, Rust is [adding
](https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html)proc
macros to generate these traits automatically, and at some point in the
future dyn traits should 'just work'. Until then.... this seemed liked
the right approach given more ErasedXXX already exist, but, no clue if
there's plans here! Especially since these are public now, it's a bit of
an unfortunate API, and means this is a breaking change.
In theory this saves some performance when these traits are used with
static dispatch, but, seems like most code paths go through dynamic
dispatch, which boxes anyway.
I also suspect a bunch of the lifetime annotations on these function
could be simplified now as the BoxedFuture was often the only thing
returned which needed a lifetime annotation, but I'm not touching that
for now as traits + lifetimes can be so tricky.
This is a revival of
[pull/11362](https://github.com/bevyengine/bevy/pull/11362) after a
spectacular merge f*ckup, with updates to the latest Bevy. Just to recap
some discussion:
- Overall this seems like a win for code quality, especially when
implementing these traits, but a loss for having to deal with ErasedXXX
variants.
- `ConditionalSend` was the preferred name for the trait that might be
Send, to deal with wasm platforms.
- When reviewing be sure to disable whitespace difference, as that's 95%
of the PR.
## Changelog
- AssetReader, AssetWriter, AssetLoader, AssetSaver and Process now use
async-fn in traits rather than boxed futures.
## Migration Guide
- Custom implementations of AssetReader, AssetWriter, AssetLoader,
AssetSaver and Process should switch to async fn rather than returning a
bevy_utils::BoxedFuture.
- Simultaniously, to use dynamic dispatch on these traits you should
instead use dyn ErasedXXX.
# Objective
- Not all materials need shadow, but a queue_shadows system is always
added to the `Render` schedule and executed
## Solution
- Make a setting for shadows, it defaults to true
## Changelog
- Added `shadows_enabled` setting to `MaterialPlugin`
## Migration Guide
- `MaterialPlugin` now has a `shadows_enabled` setting, if you didn't
spawn the plugin using `::default()` or `..default()`, you'll need to
set it. `shadows_enabled: true` is the same behavior as the previous
version, and also the default value.
# Objective
Currently in order to retrieve the inner values from direction types is
that you need to use the `Deref` trait or `From`/`Into`. `Deref` that is
currently implemented is an anti-pattern that I believe should be less
relied upon.
This pull-request add getters for retrieving the inner values for
direction types.
Advantages of getters:
- Let rust-analyzer to list out available methods for users to
understand better to on how to get the inner value. (This happens to me.
I really don't know how to get the value until I look through the source
code.)
- They are simple.
- Generally won't be ambiguous in most context. Traits such as
`From`/`Into` will require fully qualified syntax from time to time.
- Unsurprising result.
Disadvantages of getters:
- More verbose
Advantages of deref polymorphism:
- You reduce boilerplate for getting the value and call inner methods
by:
```rust
let dir = Dir3::new(Vec3::UP).unwrap();
// getting value
let value = *dir;
// instead of using getters
let value = dir.vec3();
// calling methods for the inner vector
dir.xy();
// instead of using getters
dir.vec3().xy();
```
Disadvantages of deref polymorphism:
- When under more level of indirection, it will requires more
dereferencing which will get ugly in some part:
```rust
// getting value
let value = **dir;
// instead of using getters
let value = dir.vec3();
// calling methods for the inner vector
dir.xy();
// instead of using getters
dir.vec3().xy();
```
[More detail
here](https://rust-unofficial.github.io/patterns/anti_patterns/deref.html).
Edit: Update information for From/Into trait.
Edit: Advantages and disadvantages.
## Solution
Add `vec2` method for Dir2.
Add `vec3` method for Dir3.
Add `vec3a` method for Dir3A.
# Objective
prevent gpu buffer allocations when running `as_bind_group` for assets
with texture dependencies that are not yet available.
## Solution
reorder the binding creation so that fallible items are created first.
# Objective
Resolves#12431.
## Solution
Added a `skip_taskbar` field to the `Window` struct (defaults to
`false`). Used in `create_windows` if the target OS is Windows.
Updates the requirements on
[base64](https://github.com/marshallpierce/rust-base64) to permit the
latest version.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md">base64's
changelog</a>.</em></p>
<blockquote>
<h1>0.22.0</h1>
<ul>
<li><code>DecodeSliceError::OutputSliceTooSmall</code> is now
conservative rather than precise. That is, the error will only occur if
the decoded output <em>cannot</em> fit, meaning that
<code>Engine::decode_slice</code> can now be used with exactly-sized
output slices. As part of this, <code>Engine::internal_decode</code> now
returns <code>DecodeSliceError</code> instead of
<code>DecodeError</code>, but that is not expected to affect any
external callers.</li>
<li><code>DecodeError::InvalidLength</code> now refers specifically to
the <em>number of valid symbols</em> being invalid (i.e. <code>len % 4
== 1</code>), rather than just the number of input bytes. This avoids
confusing scenarios when based on interpretation you could make a case
for either <code>InvalidLength</code> or <code>InvalidByte</code> being
appropriate.</li>
<li>Decoding is somewhat faster (5-10%)</li>
</ul>
<h1>0.21.7</h1>
<ul>
<li>Support getting an alphabet's contents as a str via
<code>Alphabet::as_str()</code></li>
</ul>
<h1>0.21.6</h1>
<ul>
<li>Improved introductory documentation and example</li>
</ul>
<h1>0.21.5</h1>
<ul>
<li>Add <code>Debug</code> and <code>Clone</code> impls for the general
purpose Engine</li>
</ul>
<h1>0.21.4</h1>
<ul>
<li>Make <code>encoded_len</code> <code>const</code>, allowing the
creation of arrays sized to encode compile-time-known data lengths</li>
</ul>
<h1>0.21.3</h1>
<ul>
<li>Implement <code>source</code> instead of <code>cause</code> on Error
types</li>
<li>Roll back MSRV to 1.48.0 so Debian can continue to live in a time
warp</li>
<li>Slightly faster chunked encoding for short inputs</li>
<li>Decrease binary size</li>
</ul>
<h1>0.21.2</h1>
<ul>
<li>Rollback MSRV to 1.57.0 -- only dev dependencies need 1.60, not the
main code</li>
</ul>
<h1>0.21.1</h1>
<ul>
<li>Remove the possibility of panicking during decoded length
calculations</li>
<li><code>DecoderReader</code> no longer sometimes erroneously ignores
padding <a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/226">#226</a></li>
</ul>
<h2>Breaking changes</h2>
<ul>
<li><code>Engine.internal_decode</code> return type changed</li>
<li>Update MSRV to 1.60.0</li>
</ul>
<h1>0.21.0</h1>
<h2>Migration</h2>
<h3>Functions</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="5d70ba7576"><code>5d70ba7</code></a>
Merge pull request <a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/269">#269</a>
from marshallpierce/mp/decode-precisely</li>
<li><a
href="efb6c006c7"><code>efb6c00</code></a>
Release notes</li>
<li><a
href="2b91084a31"><code>2b91084</code></a>
Add some tests to boost coverage</li>
<li><a
href="9e9c7abe65"><code>9e9c7ab</code></a>
Engine::internal_decode now returns DecodeSliceError</li>
<li><a
href="a8a60f43c5"><code>a8a60f4</code></a>
Decode main loop improvements</li>
<li><a
href="a25be0667c"><code>a25be06</code></a>
Simplify leftover output writes</li>
<li><a
href="9979cc33bb"><code>9979cc3</code></a>
Keep morsels as separate bytes</li>
<li><a
href="37670c5ec2"><code>37670c5</code></a>
Bump dev toolchain version (<a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/268">#268</a>)</li>
<li><a
href="9652c78773"><code>9652c78</code></a>
v0.21.7</li>
<li><a
href="08deccf703"><code>08deccf</code></a>
provide as_str() method to return the alphabet characters (<a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/264">#264</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/marshallpierce/rust-base64/compare/v0.21.5...v0.22.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
Fixes#12549. WorldCell's support of everything a World can do is
incomplete, and represents an alternative, potentially confusing, and
less performant way of pulling multiple fetches from a `World`. The
typical approach is to use `SystemState` for a runtime cached and safe
way, or `UnsafeWorldCell` if the use of `unsafe` is tolerable.
## Solution
Remove it!
---
## Changelog
Removed: `WorldCell`
Removed: `World::cell`
## Migration Guide
`WorldCell` has been removed. If you were using it to fetch multiple
distinct values from a `&mut World`, use `SystemState` by calling
`SystemState::get` instead. Alternatively, if `SystemState` cannot be
used, `UnsafeWorldCell` can instead be used in unsafe contexts.
# Objective
- working with UI components in Bevy, I found myself wanting some of
these common traits, like `PartialEq` for comparing simple types
## Solution
- I added only (hopefully) uncontroversial `derive`s for some common UI
types
Note that many types, unfortunately, can't have `PartialEq` `derive`d
for them, because they contain `f32`s and / or `Vec`s.
# Objective
I wanted to have reflection for BinaryHeap for a personal project.
I'm running into some issues:
- I wanted to represent BinaryHeap as a reflect::List type since it's
essentially a wrapper around a Vec, however there's no public way to
access the underlying Vec, which makes it hard to implement the
reflect::List methods. I have omitted the reflect::List methods for
now.. I'm not sure if that's a blocker?
- what would be the alternatives? Simply not implement `reflect::List`?
It is possible to implement `FromReflect` without it. Would the type be
`Struct` then?
---------
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
# Objective
Provide component access to `&'w T`, `Ref<'w, T>`, `Mut<'w, T>`,
`Ptr<'w>` and `MutUntyped<'w>` from `EntityMut<'w>`/`EntityWorldMut<'w>`
with the world `'w` lifetime instead of `'_`.
Fixes#12417
## Solution
Add `into_` prefixed methods for `EntityMut<'w>`/`EntityWorldMut<'w>`
that consume `self` and returns component access with the world `'w`
lifetime unlike the `get_` prefixed methods that takes `&'a self` and
returns component access with `'a` lifetime.
Methods implemented:
- EntityMut::into_borrow
- EntityMut::into_ref
- EntityMut::into_mut
- EntityMut::into_borrow_by_id
- EntityMut::into_mut_by_id
- EntityWorldMut::into_borrow
- EntityWorldMut::into_ref
- EntityWorldMut::into_mut
- EntityWorldMut::into_borrow_by_id
- EntityWorldMut::into_mut_by_id
# Objective
fix#12344
## Solution
use existing machinery in track_assets to determine if the asset is
unused before firing Asset::Unused event
~~most extract functions use `AssetEvent::Removed` to schedule deletion
of render world resources. `RenderAssetPlugin` was using
`AssetEvent::Unused` instead.
`Unused` fires when the last strong handle is dropped, even if a new one
is created. `Removed` only fires when a new one is not created.
as far as i can see, `Unused` is the same as `Removed` except for this
"feature", and that it also fires early if all handles for a loading
asset are dropped (`Removed` fires after the loading completes). note
that in that case, processing based on `Loaded` won't have been done
anyway.
i think we should get rid of `Unused` completely, it is not currently
used anywhere (except here, previously) and i think using it is probably
always a mistake.
i also am not sure why we keep loading assets that have been dropped
while loading, we should probably drop the loader task as well and
remove immediately.~~
# Objective
Whenever a nodes size gets changed, its texture slices get updated a
frame later. This results in visual glitches when animating the size of
a node with a texture slice. See this video:
[Screencast from 17-03-24
14:53:13.webm](https://github.com/bevyengine/bevy/assets/46689298/64e711f7-a1ec-41e3-b119-dc8d7e1a7669)
## Solution
Compute texture slices after the layout system has finished.
# Objective
- Resolves#12463
## Solution
- Added `ClampColor`
Due to consistency, `is_within_bounds` is a method of `ClampColor`, like
`is_fully_transparent` is a method of `Alpha`
---
## Changelog
### Added
- `ClampColor` trait
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
It's useful to have access to render pipeline statistics, since they
provide more information than FPS alone. For example, the number of
drawn triangles can be used to debug culling and LODs. The number of
fragment shader invocations can provide a more stable alternative metric
than GPU elapsed time.
See also: Render node GPU timing overlay #8067, which doesn't provide
pipeline statistics, but adds a nice overlay.
## Solution
Add `RenderDiagnosticsPlugin`, which enables collecting pipeline
statistics and CPU & GPU timings.
---
## Changelog
- Add `RenderDiagnosticsPlugin`
- Add `RenderContext::diagnostic_recorder` method
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
`QueryState::archetype_component_access` is only really ever used to
extend `SystemMeta`'s. It can be removed to save some memory for every
`Query` in an app.
## Solution
* Remove it.
* Have `new_archetype` pass in a `&mut Access<ArchetypeComponentId>`
instead and pull it from `SystemMeta` directly.
* Split `QueryState::new` from `QueryState::new_with_access` and a
common `QueryState::new_uninitialized`.
* Split `new_archetype` into an internal and public version. Call the
internal version in `update_archetypes`.
This should make it faster to construct new QueryStates, and by proxy
lenses and joins as well.
`matched_tables` also similarly is only used to deduplicate inserting
into `matched_table_ids`. If we can find another efficient way to do so,
it might also be worth removing.
The [generated
assembly](https://github.com/james7132/bevy_asm_tests/compare/main...remove-query-state-archetype-component-access#diff-496530101f0b16e495b7e9b77c0e906ae3068c8adb69ed36c92d5a1be5a9efbe)
reflects this well, with all of the access related updates in
`QueryState` being removed.
---
## Changelog
Removed: `QueryState::archetype_component_access`.
Changed: `QueryState::new_archetype` now takes a `&mut
Access<ArchetypeComponentId>` argument, which will be updated with the
new accesses.
Changed: `QueryState::update_archetype_component_access` now takes a
`&mut Access<ArchetypeComponentId>` argument, which will be updated with
the new accesses.
## Migration Guide
TODO
# Objective
Improve code quality involving fixedbitset.
## Solution
Update to fixedbitset 0.5. Use the new `grow_and_insert` function
instead of `grow` and `insert` functions separately.
This should also speed up most of the set operations involving
fixedbitset. They should be ~2x faster, but testing this against the
stress tests seems to show little to no difference. The multithreaded
executor doesn't seem to be all that much faster in many_cubes and
many_foxes. These use cases are likely dominated by other operations or
the bitsets aren't big enough to make them the bottleneck.
This introduces a duplicate dependency due to petgraph and wgpu, but the
former may take some time to update.
## Changelog
Removed: `Access::grow`
## Migration Guide
`Access::grow` has been removed. It's no longer needed. Remove all
references to it.
# Objective
Make `Transform` APIs more ergonomic by allowing users to pass `Dir3` as
an argument where a direction is needed. Fixes#12481.
## Solution
Accept `impl TryInto<Dir3>` instead of `Vec3` for direction/axis
arguments in `Transform` APIs
---
## Changelog
The following `Transform` methods now accept an `impl TryInto<Dir3>`
argument where they previously accepted directions as `Vec3`:
* `Transform::{look_to,looking_to}`
* `Transform::{look_at,looking_at}`
* `Transform::{align,aligned_by}`
## Migration Guide
This is not a breaking change since the arguments were previously `Vec3`
which already implements `TryInto<Dir3>`, and behavior is unchanged.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
# Objective
- Even if we have `Laba` and `Oklcha` colorspaces using lightness as the
L field name, `Oklaba` doesn't do the same
- The shorthand function for creating a new color should be named
`Oklaba::lab`, but is named `lch`
## Solution
- Rename field l in `Oklaba` to lightness
- Rename `Oklaba::lch` to `Oklaba::lab`
---
## Changelog
### Changed
- Changed name in l field in `Oklaba` to lightness
- Changed method name `Oklaba::lch` to `Oklaba::lab`
## Migration Guide
If you were creating a Oklaba instance directly, instead of using L, you
should use lightness
```rust
// Before
let oklaba = Oklaba { l: 1., ..Default::default() };
// Now
let oklaba = Oklaba { lightness: 1., ..Default::default() };
```
if you were using the function `Oklaba::lch`, now the method is named
`Oklaba::lab`
# Objective
Give easy methods for uniform point sampling in a variety of primitive
shapes (particularly useful for circles and spheres) because in a lot of
cases its quite easy to get wrong (non-uniform).
## Solution
Added the `ShapeSample` trait to `bevy_math` and implemented it for
`Circle`, `Sphere`, `Rectangle`, `Cuboid`, `Cylinder`, `Capsule2d` and
`Capsule3d`. There are a few other shapes it would be reasonable to
implement for like `Triangle`, `Ellipse` and `Torus` but I'm not
immediately sure how these would be implemented (other than rejection
which could be the best method, and could be more performant than some
of the solutions in this pr I'm not sure). This exposes the
`sample_volume` and `sample_surface` methods to get both a random point
from its interior or its surface. EDIT: Renamed `sample_volume` to
`sample_interior` and `sample_surface` to `sample_boundary`
This brings in `rand` as a default optional dependency (without default
features), and the methods take `&mut impl Rng` which allows them to use
any random source implementing `RngCore`.
---
## Changelog
### Added
Added the methods `sample_interior` and `sample_boundary` to a variety
of primitive shapes providing easy uniform point sampling.
# Objective
assets that don't load before they get removed are retried forever,
causing buffer churn and slowdown.
## Solution
stop trying to prepare dead assets.
# Objective
Originally proposed as part of #8973. Adds `with_` methods for each side
of `UiRect`
## Solution
Add `with_left`, `with_right`, `with_top`, `with_bottom` to `UiRect`.
# Objective
Add reflect for `std::any::TypeId`.
I couldn't add ReflectSerialize/ReflectDeserialize for it, it was giving
me an error. I don't really understand why, since it works for
`std::path::PathBuf`.
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
# Objective
Fixes#12480
by removing the explicit mention of equally sized triangles from the doc
for icospheres
Co-authored-by: Emi <emanuel.boehm@gmail.com>
# Objective
Fixes#12139
## Solution
- Derive `Debug` impl for `Entity`
- Add impl `Display` for `Entity`
- Add `entity_display` test to check the output contains all required
info
I decided to go with `0v0|1234` format as opposed to the `0v0[1234]`
which was initially discussed in the issue.
My rationale for this is that `[1234]` may be confused for index values,
which may be common in logs, and so searching for entities by text would
become harder. I figured `|1234` would help the entity IDs stand out
more.
Additionally, I'm a little concerned that this change is gonna break
existing logging for projects because `Debug` is now going to be a
multi-line output. But maybe this is ok.
We could implement `Debug` to be a single-line output, but then I don't
see why it would be different from `Display` at all.
@alice-i-cecile Let me know if we'd like to make any changes based on
these points.
# Objective
- Closes#11793
- Introduces a general API for aligning local coordinates of Transforms
with given vectors.
## Solution
- We introduce `Transform::align`, which allows a rotation to be
specified by four pieces of alignment data, as explained by the
documentation:
````rust
/// Rotates this [`Transform`] so that the `main_axis` vector, reinterpreted in local coordinates, points
/// in the given `main_direction`, while `secondary_axis` points towards `secondary_direction`.
///
/// For example, if a spaceship model has its nose pointing in the X-direction in its own local coordinates
/// and its dorsal fin pointing in the Y-direction, then `align(Vec3::X, v, Vec3::Y, w)` will make the spaceship's
/// nose point in the direction of `v`, while the dorsal fin does its best to point in the direction `w`.
///
/// More precisely, the [`Transform::rotation`] produced will be such that:
/// * applying it to `main_axis` results in `main_direction`
/// * applying it to `secondary_axis` produces a vector that lies in the half-plane generated by `main_direction` and
/// `secondary_direction` (with positive contribution by `secondary_direction`)
///
/// [`Transform::look_to`] is recovered, for instance, when `main_axis` is `Vec3::NEG_Z` (the [`Transform::forward`]
/// direction in the default orientation) and `secondary_axis` is `Vec3::Y` (the [`Transform::up`] direction in the default
/// orientation). (Failure cases may differ somewhat.)
///
/// In some cases a rotation cannot be constructed. Another axis will be picked in those cases:
/// * if `main_axis` or `main_direction` is zero, `Vec3::X` takes its place
/// * if `secondary_axis` or `secondary_direction` is zero, `Vec3::Y` takes its place
/// * if `main_axis` is parallel with `secondary_axis` or `main_direction` is parallel with `secondary_direction`,
/// a rotation is constructed which takes `main_axis` to `main_direction` along a great circle, ignoring the secondary
/// counterparts
///
/// Example
/// ```
/// # use bevy_math::{Vec3, Quat};
/// # use bevy_transform::components::Transform;
/// let mut t1 = Transform::IDENTITY;
/// let mut t2 = Transform::IDENTITY;
/// t1.align(Vec3::ZERO, Vec3::Z, Vec3::ZERO, Vec3::X);
/// t2.align(Vec3::X, Vec3::Z, Vec3::Y, Vec3::X);
/// assert_eq!(t1.rotation, t2.rotation);
///
/// t1.align(Vec3::X, Vec3::Z, Vec3::X, Vec3::Y);
/// assert_eq!(t1.rotation, Quat::from_rotation_arc(Vec3::X, Vec3::Z));
/// ```
pub fn align(
&mut self,
main_axis: Vec3,
main_direction: Vec3,
secondary_axis: Vec3,
secondary_direction: Vec3,
) { //... }
````
- We introduce `Transform::aligned_by`, the returning-Self version of
`align`:
````rust
pub fn aligned_by(
mut self,
main_axis: Vec3,
main_direction: Vec3,
secondary_axis: Vec3,
secondary_direction: Vec3,
) -> Self { //... }
````
- We introduce an example (examples/transforms/align.rs) that shows the
usage of this API. It is likely to be mathier than most other
`Transform` APIs, so when run, the example demonstrates what the API
does in space:
<img width="1440" alt="Screenshot 2024-03-12 at 11 01 19 AM"
src="https://github.com/bevyengine/bevy/assets/2975848/884b3cc3-cbd9-48ae-8f8c-49a677c59dfe">
---
## Changelog
- Added methods `align`, `aligned_by` to `Transform`.
- Added transforms/align.rs to examples.
---
## Discussion
### On the form of `align`
The original issue linked above suggests an API similar to that of the
existing `Transform::look_to` method:
````rust
pub fn align_to(&mut self, direction: Vec3, up: Vec3) { //... }
````
Not allowing an input axis of some sort that is to be aligned with
`direction` would not really solve the problem in the issue, since the
user could easily be in a scenario where they have to compose with
another rotation on their own (undesirable). This leads to something
like:
````rust
pub fn align_to(&mut self, axis: Vec3, direction: Vec3, up: Vec3) { //... }
````
However, this still has two problems:
- If the vector that the user wants to align is parallel to the Y-axis,
then the API basically does not work (we cannot fully specify a
rotation)
- More generally, it does not give the user the freedom to specify which
direction is to be treated as the local "up" direction, so it fails as a
general alignment API
Specifying both leads us to the present situation, with two local axis
inputs (`main_axis` and `secondary_axis`) and two target directions
(`main_direction` and `secondary_direction`). This might seem a little
cumbersome for general use, but for the time being I stand by the
decision not to expand further without prompting from users. I'll expand
on this below.
### Additional APIs?
Presently, this PR introduces only `align` and `aligned_by`. Other
potentially useful bundles of API surface arrange into a few different
categories:
1. Inferring direction from position, a la `Transform::look_at`, which
might look something like this:
````rust
pub fn align_at(&mut self, axis: Vec3, target: Vec3, up: Vec3) {
self.align(axis, target - self.translation, Vec3::Y, up);
}
````
(This is simple but still runs into issues when the user wants to point
the local Y-axis somewhere.)
2. Filling in some data for the user for common use-cases; e.g.:
````rust
pub fn align_x(&mut self, direction: Vec3, up: Vec3) {
self.align(Vec3::X, direction, Vec3::Y, up);
}
````
(Here, use of the `up` vector doesn't lose any generality, but it might
be less convenient to specify than something else. This does naturally
leave open the question of what `align_y` would look like if we provided
it.)
Morally speaking, I do think that the `up` business is more pertinent
when the intention is to work with cameras, which the `look_at` and
`look_to` APIs seem to cover pretty well. If that's the case, then I'm
not sure what the ideal shape for these API functions would be, since it
seems like a lot of input would have to be baked into the function
definitions. For some cases, this might not be the end of the world:
````rust
pub fn align_x_z(&mut self, direction: Vec3, weak_direction: Vec3) {
self.align(Vec3::X, direction, Vec3::Z, weak_direction);
}
````
(However, this is not symmetrical in x and z, so you'd still need six
API functions just to support the standard positive coordinate axes, and
if you support negative axes then things really start to balloon.)
The reasons that these are not actually produced in this PR are as
follows:
1. Without prompting from actual users in the wild, it is unknown to me
whether these additional APIs would actually see a lot of use. Extending
these to our users in the future would be trivial if we see there is a
demand for something specific from the above-mentioned categories.
2. As discussed above, there are so many permutations of these that
could be provided that trying to do so looks like it risks unduly
ballooning the API surface for this feature.
3. Finally, and most importantly, creating these helper functions in
user-space is trivial, since they all just involve specializing `align`
to particular inputs; e.g.:
````rust
fn align_ship(ship_transform: &mut Transform, nose_direction: Vec3, dorsal_direction: Vec3) {
ship_transform.align(Ship::NOSE, nose_direction, Ship::DORSAL, dorsal_direction);
}
````
With that in mind, I would prefer instead to focus on making the
documentation and examples for a thin API as clear as possible, so that
users can get a grip on the tool and specialize it for their own needs
when they feel the desire to do so.
### `Dir3`?
As in the case of `Transform::look_to` and `Transform::look_at`, the
inputs to this function are, morally speaking, *directions* rather than
vectors (actually, if we're being pedantic, the input is *really really*
a pair of orthonormal frames), so it's worth asking whether we should
really be using `Dir3` as inputs instead of `Vec3`. I opted for `Vec3`
for the following reasons:
1. Specifying a `Dir3` in user-space is just more annoying than
providing a `Vec3`. Even in the most basic cases (e.g. providing a
vector literal), you still have to do error handling or call an unsafe
unwrap in your function invocations.
2. The existing API mentioned above uses `Vec3`, so we are just adhering
to the same thing.
Of course, the use of `Vec3` has its own downsides; it can be argued
that the replacement of zero-vectors with fixed ones (which we do in
`Transform::align` as well as `Transform::look_to`) more-or-less amounts
to failing silently.
### Future steps
The question of additional APIs was addressed above. For me, the main
thing here to handle more immediately is actually just upstreaming this
API (or something similar and slightly mathier) to `glam::Quat`. The
reason that this would be desirable for users is that this API currently
only works with `Transform`s even though all it's actually doing is
specifying a rotation. Upstreaming to `glam::Quat`, properly done, could
buy a lot basically for free, since a number of `Transform` methods take
a rotation as an input. Using these together would require a little bit
of mathematical savvy, but it opens up some good things (e.g.
`Transform::rotate_around`).
# Objective
- Addresses #12462
- When we serialize an enum, deserialize it, then reserialize it, the
correct variant should be selected.
## Solution
- Change `dynamic_enum.set_variant` to
`dynamic_enum.set_variant_with_index` in `EnumVisitor`
# Objective
- Adds 3d grids, suggestion of #9400
## Solution
- Added 3d grids (grids spanning all three dimensions, not flat grids)
to bevy_gizmos
---
## Changelog
- `gizmos.grid(...)` and `gizmos.grid_2d(...)` now return a
`GridBuilder2d`.
- Added `gizmos.grid_3d(...)` which returns a `GridBuilder3d`.
- The difference between them is basically only that `GridBuilder3d`
exposes some methods for configuring the z axis while the 2d version
doesn't.
- Allowed for drawing the outer edges along a specific axis by calling
`.outer_edges_x()`, etc. on the builder.
## Additional information
Please note that I have not added the 3d grid to any example as not to
clutter them.
Here is an image of what the 3d grid looks like:
<img width="1440" alt="Screenshot 2024-03-12 at 02 19 55"
src="https://github.com/bevyengine/bevy/assets/62256001/4cd3b7de-cf2c-4f05-8a79-920a4dd804b8">
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Beginning of refactoring of light.rs in bevy_pbr, as per issue #12349
Create and move light.rs to its own directory, and extract AmbientLight
struct.
## Solution
- moved light.rs to light/mod.rs
- extracted AmbientLight struct to light/ambient_light.rs
# Objective
Fixes#12064
## Solution
Prior to #11326, the "global physical" translation of text was rounded.
After #11326, only the "offset" is being rounded.
This moves things around so that the "global translation" is converted
to physical pixels, rounded, and then converted back to logical pixels,
which is what I believe was happening before / what the comments above
describe.
## Discussion
This seems to work and fix an obvious mistake in some code, but I don't
fully grok the ui / text pipelines / math here.
## Before / After and test example
<details>
<summary>Expand Code</summary>
```rust
use std::f32::consts::FRAC_PI_2;
use bevy::prelude::*;
use bevy_internal:🪟:WindowResolution;
const FONT_SIZE: f32 = 25.0;
const PADDING: f32 = 5.0;
fn main() {
App::new()
.add_plugins(
DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: WindowResolution::default().with_scale_factor_override(1.0),
..default()
}),
..default()
}),
//.set(ImagePlugin::default_nearest()),
)
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
for x in [20.5, 140.0] {
for i in 1..10 {
text(
&mut commands,
font.clone(),
x,
(FONT_SIZE + PADDING) * i as f32,
i,
Quat::default(),
1.0,
);
}
}
for x in [450.5, 700.0] {
for i in 1..10 {
text(
&mut commands,
font.clone(),
x,
((FONT_SIZE * 2.0) + PADDING) * i as f32,
i,
Quat::default(),
2.0,
);
}
}
for y in [400.0, 600.0] {
for i in 1..10 {
text(
&mut commands,
font.clone(),
(FONT_SIZE + PADDING) * i as f32,
y,
i,
Quat::from_rotation_z(FRAC_PI_2),
1.0,
);
}
}
}
fn text(
commands: &mut Commands,
font: Handle<Font>,
x: f32,
y: f32,
i: usize,
rot: Quat,
scale: f32,
) {
let text = (65..(65 + i)).map(|a| a as u8 as char).collect::<String>();
commands.spawn(TextBundle {
style: Style {
position_type: PositionType::Absolute,
left: Val::Px(x),
top: Val::Px(y),
..default()
},
text: Text::from_section(
text,
TextStyle {
font,
font_size: FONT_SIZE,
..default()
},
),
transform: Transform::from_rotation(rot).with_scale(Vec2::splat(scale).extend(1.)),
..default()
});
}
```
</details>
Open both images in new tabs and swap back and forth. Pay attention to
the "A" and "ABCD" lines.
<details>
<summary>Before</summary>
<img width="640" alt="main3"
src="https://github.com/bevyengine/bevy/assets/200550/248d7a55-d06d-433f-80da-1914803c3551">
</details>
<details>
<summary>After</summary>
<img width="640" alt="pr3"
src="https://github.com/bevyengine/bevy/assets/200550/26a9d292-07ae-4af3-b035-e187b2529ace">
</details>
---------
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
`System<f32>` currently does not implement `Eq` even though it should
## Solution
Manually implement `Eq` like other traits are manually implemented
# Objective
To have a user level workaround for #12237.
## Solution
Workaround to the problem is described in:
https://github.com/bevyengine/bevy/issues/12237#issuecomment-1983680632
## Changelog
### Changed
- `CreateWindowParams` type and `create_windows` system from
`bevy_winit` is now public, which allows library authors and game
developers to manually trigger window creation when needed.
# Objective
Fixes#12301. Provide more comprehensive crate level docs for bevy_ptr,
explaining it's methodology and design.
## Solution
Write out said docs.
---------
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Reduce allocations on the UI hot path.
## Solution
- Cache buffers used by the `ui_stack_system`.
## Follow-Up
- `sort_by_key` is potentially-allocating. It might be worthwhile to
include the child index as part of the sort-key and use unstable sort.
# Objective
- Closes#11954
## Solution
Change the load_meshes field in `GltfLoaderSettings` from a bool to
`RenderAssetUsages` flag, and add a new load_materials flag.
Use these to determine where the gLTF mesh and material assets are
retained in memory (if the provided flags are empty, then the assets are
skipped during load).
---
## Migration Guide
When loading gLTF assets with `asset_server.load_with_settings`, use
`RenderAssetUsages` instead of `bool` when setting load_meshes e.g.
```rust
let _ = asset_server.load_with_settings("...", |s: &mut GltfLoaderSettings| {
s.load_meshes = RenderAssetUsages::RENDER_WORLD;
});
```
Use the new load_materials field for controlling material load &
retention behaviour instead of load_meshes.
gLTF .meta files need similar updates e.g
```
load_meshes: true,
```
to
```
load_meshes: ("MAIN_WORLD | RENDER_WORLD"),
```
---------
Co-authored-by: 66OJ66 <hi0obxud@anonaddy.me>
# Objective
Add a `scale_around_center` method to the `BoundingVolume` trait, as per
#12130.
## Solution
Added `scale_around_center` to the `BoundingVolume` trait, implemented
in `Aabb2d`, `Aabb3d`, `BoundingCircle`, and `BoundingSphere` (with
tests).
# Objective
- Fix GamepadEvent::Connection not being sent for devices connected at
startup.
## Solution
- GamepadConnectionEvent was being sent directly for gamepads connected
at startup, which causes consumers of GamepadEvent to not receive those
events.
- Instead send GamepadEvent. The gamepad_event_system splits
GamepadEvent up, so consumers of GamepadConnectionEvent will still
receive the events.
# Objective
- Part of #12351
- Add fps overlay
## Solution
- Create `FpsOverlayPlugin`
- Allow for configuration through resource `FpsOverlayConfig`
- Allow for configuration during runtime
### Preview on default settings
![20240308_22h23m25s_grim](https://github.com/bevyengine/bevy/assets/62356462/33d3d7a9-435e-4e0b-9814-d3274e779a69)
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Adds gizmo line joints, suggestion of #9400
## Solution
- Adds `line_joints: GizmoLineJoint` to `GizmoConfig`. Currently the
following values are supported:
- `GizmoLineJoint::None`: does not draw line joints, same behaviour as
previously
- `GizmoLineJoint::Bevel`: draws a single triangle between the lines
- `GizmoLineJoint::Miter` / 'spiky joints': draws two triangles between
the lines extending them until they meet at a (miter) point.
- NOTE: for very small angles between the lines, which happens
frequently in 3d, the miter point will be very far away from the point
at which the lines meet.
- `GizmoLineJoint::Round(resolution)`: Draw a circle arc between the
lines. The circle is a triangle fan of `resolution` triangles.
---
## Changelog
- Added `GizmoLineJoint`, use that in `GizmoConfig` and added necessary
pipelines and draw commands.
- Added a new `line_joints.wgsl` shader containing three vertex shaders
`vertex_bevel`, `vertex_miter` and `vertex_round` as well as a basic
`fragment` shader.
## Migration Guide
Any manually created `GizmoConfig`s must now set the `.line_joints`
field.
## Known issues
- The way we currently create basic closed shapes like rectangles,
circles, triangles or really any closed 2d shape means that one of the
corners will not be drawn with joints, although that would probably be
expected. (see the triangle in the 2d image)
- This could be somewhat mitigated by introducing line caps or fixed by
adding another segment overlapping the first of the strip. (Maybe in a
followup PR?)
- 3d shapes can look 'off' with line joints (especially bevel) because
wherever 3 or more lines meet one of them may stick out beyond the joint
drawn between the other 2.
- Adding additional lines so that there is a joint between every line at
a corner would fix this but would probably be too computationally
expensive.
- Miter joints are 'unreasonably long' for very small angles between the
lines (the angle is the angle between the lines in screen space). This
is technically correct but distracting and does not feel right,
especially in 3d contexts. I think limiting the length of the miter to
the point at which the lines meet might be a good idea.
- The joints may be drawn with a different gizmo in-between them and
their corresponding lines in 2d. Some sort of z-ordering would probably
be good here, but I believe this may be out of scope for this PR.
## Additional information
Some pretty images :)
<img width="1175" alt="Screenshot 2024-03-02 at 04 53 50"
src="https://github.com/bevyengine/bevy/assets/62256001/58df7e63-9376-4430-8871-32adba0cb53b">
- Note that the top vertex does not have a joint drawn.
<img width="1440" alt="Screenshot 2024-03-02 at 05 03 55"
src="https://github.com/bevyengine/bevy/assets/62256001/137a00cf-cbd4-48c2-a46f-4b47492d4fd9">
Now for a weird video:
https://github.com/bevyengine/bevy/assets/62256001/93026f48-f1d6-46fe-9163-5ab548a3fce4
- The black lines shooting out from the cube are miter joints that get
very long because the lines between which they are drawn are (almost)
collinear in screen space.
---------
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
# Objective
Rotating vectors is a very common task. It is required for a variety of
things both within Bevy itself and in many third party plugins, for
example all over physics and collision detection, and for things like
Bevy's bounding volumes and several gizmo implementations.
For 3D, we can do this using a `Quat`, but for 2D, we do not have a
clear and efficient option. `Mat2` can be used for rotating vectors if
created using `Mat2::from_angle`, but this is not obvious to many users,
it doesn't have many rotation helpers, and the type does not give any
guarantees that it represents a valid rotation.
We should have a proper type for 2D rotations. In addition to allowing
for potential optimization, it would allow us to have a consistent and
explicitly documented representation used throughout the engine, i.e.
counterclockwise and in radians.
## Representation
The mathematical formula for rotating a 2D vector is the following:
```
new_x = x * cos - y * sin
new_y = x * sin + y * cos
```
Here, `sin` and `cos` are the sine and cosine of the rotation angle.
Computing these every time when a vector needs to be rotated can be
expensive, so the rotation shouldn't be just an `f32` angle. Instead, it
is often more efficient to represent the rotation using the sine and
cosine of the angle instead of storing the angle itself. This can be
freely passed around and reused without unnecessary computations.
The two options are either a 2x2 rotation matrix or a unit complex
number where the cosine is the real part and the sine is the imaginary
part. These are equivalent for the most part, but the unit complex
representation is a bit more memory efficient (two `f32`s instead of
four), so I chose that. This is like Nalgebra's
[`UnitComplex`](https://docs.rs/nalgebra/latest/nalgebra/geometry/type.UnitComplex.html)
type, which can be used for the
[`Rotation2`](https://docs.rs/nalgebra/latest/nalgebra/geometry/type.Rotation2.html)
type.
## Implementation
Add a `Rotation2d` type represented as a unit complex number:
```rust
/// A counterclockwise 2D rotation in radians.
///
/// The rotation angle is wrapped to be within the `]-pi, pi]` range.
pub struct Rotation2d {
/// The cosine of the rotation angle in radians.
///
/// This is the real part of the unit complex number representing the rotation.
pub cos: f32,
/// The sine of the rotation angle in radians.
///
/// This is the imaginary part of the unit complex number representing the rotation.
pub sin: f32,
}
```
Using it is similar to using `Quat`, but in 2D:
```rust
let rotation = Rotation2d::radians(PI / 2.0);
// Rotate vector (also works on Direction2d!)
assert_eq!(rotation * Vec2::X, Vec2::Y);
// Get angle as degrees
assert_eq!(rotation.as_degrees(), 90.0);
// Getting sin and cos is free
let (sin, cos) = rotation.sin_cos();
// "Subtract" rotations
let rotation2 = Rotation2d::FRAC_PI_4; // there are constants!
let diff = rotation * rotation2.inverse();
assert_eq!(diff.as_radians(), PI / 4.0);
// This is equivalent to the above
assert_eq!(rotation2.angle_between(rotation), PI / 4.0);
// Lerp
let rotation1 = Rotation2d::IDENTITY;
let rotation2 = Rotation2d::FRAC_PI_2;
let result = rotation1.lerp(rotation2, 0.5);
assert_eq!(result.as_radians(), std::f32::consts::FRAC_PI_4);
// Slerp
let rotation1 = Rotation2d::FRAC_PI_4);
let rotation2 = Rotation2d::degrees(-180.0); // we can use degrees too!
let result = rotation1.slerp(rotation2, 1.0 / 3.0);
assert_eq!(result.as_radians(), std::f32::consts::FRAC_PI_2);
```
There's also a `From<f32>` implementation for `Rotation2d`, which means
that methods can still accept radians as floats if the argument uses
`impl Into<Rotation2d>`. This means that adding `Rotation2d` shouldn't
even be a breaking change.
---
## Changelog
- Added `Rotation2d`
- Bounding volume methods now take an `impl Into<Rotation2d>`
- Gizmo methods with rotation now take an `impl Into<Rotation2d>`
## Future use cases
- Collision detection (a type like this is quite essential considering
how common vector rotations are)
- `Transform` helpers (e.g. return a 2D rotation about the Z axis from a
`Transform`)
- The rotation used for `Transform2d` (#8268)
- More gizmos, maybe meshes... everything in 2D that uses rotation
---------
Co-authored-by: Tristan Guichaoua <33934311+tguichaoua@users.noreply.github.com>
Co-authored-by: Robert Walter <robwalter96@gmail.com>
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
# Objective
- Add a way to combine 2 queries together in a similar way to
`Query::transmute_lens`
- Fixes#1658
## Solution
- Use a similar method to query transmute, but take the intersection of
matched archetypes between the 2 queries and the union of the accesses
to create the new underlying QueryState.
---
## Changelog
- Add query joins
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fix#10876. Improve `Query` and `QueryState`'s docs.
## Solution
Explicitly denote that Query is always guaranteed to return results from
all matching entities once and only once for each entity, and that
iteration order is not guaranteed in any way.
# Objective
Fixes#12402
## Solution
Use `despawn_recursive` instead of `despawn` for despawning
`PlaybackMode::Despawn` audio.
## Migration Guide
`PlaybackSettings::DESPAWN` (`PlaybackMode::Despawn`) now despawns the
audio entity's children as well. If you were relying on the previous
behavior, you may be able to use `PlaybackMode::Remove`, or you may need
to use `PlaybackMode::Once` and manage your audio component lifecycle
manually.
# Objective
- `toml_edit` released a new patch that deprecates `Document`
- this warns when Bevy builds, and CI deny warns
## Solution
- fix deprecation warnings
Updates the requirements on
[ruzstd](https://github.com/KillingSpark/zstd-rs) to permit the latest
version.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/KillingSpark/zstd-rs/releases">ruzstd's
releases</a>.</em></p>
<blockquote>
<h2>Send + Sync for FrameDecoder and optional checksum calculation</h2>
<ul>
<li>The FrameDecoder is now Send + Sync (RingBuffer impls these traits
now)</li>
<li>Hashing content and checking the result against the frame header is
now optional</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/KillingSpark/zstd-rs/blob/master/Changelog.md">ruzstd's
changelog</a>.</em></p>
<blockquote>
<h1>After 0.6.0</h1>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="abc01fa186"><code>abc01fa</code></a>
prepare changelog after version 0.6.0 released</li>
<li><a
href="943f96c97a"><code>943f96c</code></a>
we had a breaking change, bump version to 0.6.0</li>
<li><a
href="e0d32e83b4"><code>e0d32e8</code></a>
bump version to 0.5.1 and update criterion dependency</li>
<li><a
href="a16e38be5c"><code>a16e38b</code></a>
make RingBuffer Send + Sync so that the FrameDecoder is Send + Sync</li>
<li><a
href="4688f442da"><code>4688f44</code></a>
Merge pull request <a
href="https://redirect.github.com/KillingSpark/zstd-rs/issues/54">#54</a>
from a1phyr/add_metadata</li>
<li><a
href="6ab76d53c7"><code>6ab76d5</code></a>
Add crate category and keywords</li>
<li><a
href="f7e99753b9"><code>f7e9975</code></a>
try avoiding node12 github actions</li>
<li><a
href="86f97b84f5"><code>86f97b8</code></a>
fix naming</li>
<li><a
href="ea26ea140a"><code>ea26ea1</code></a>
use cargo-hack to test feature powerset</li>
<li><a
href="1ec35d2a3b"><code>1ec35d2</code></a>
add a changelog</li>
<li>Additional commits viewable in <a
href="https://github.com/KillingSpark/zstd-rs/compare/v0.5.0...v0.6.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
Fixes#10106
Adds a table showing computational complexity, as seen for Query (and
similar to std::collections docs).
## Solution
Add the complexity table
---
## Changelog
- Add complexity table for Input methods
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
Remove Bevy internals from backtraces
## Solution
Executors insert `__rust_begin_short_backtrace` into the callstack
before running a system.
<details>
<summary>Example current output</summary>
```
thread 'Compute Task Pool (3)' panicked at src/main.rs:7:33:
Foo
stack backtrace:
0: rust_begin_unwind
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:647:5
1: core::panicking::panic_fmt
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/panicking.rs:72:14
2: foo::main::{{closure}}
at ./src/main.rs:7:33
3: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/ops/function.rs:294:13
4: <Func as bevy_ecs::system::function_system::SystemParamFunction<fn() .> Out>>::run::call_inner
at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/system/function_system.rs:661:21
5: <Func as bevy_ecs::system::function_system::SystemParamFunction<fn() .> Out>>::run
at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/system/function_system.rs:664:17
6: <bevy_ecs::system::function_system::FunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run_unsafe
at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/system/function_system.rs:504:19
7: bevy_ecs::schedule::executor::multi_threaded::ExecutorState::spawn_system_task::{{closure}}::{{closure}}
at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs:621:26
8: core::ops::function::FnOnce::call_once
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/ops/function.rs:250:5
9: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/panic/unwind_safe.rs:272:9
10: std::panicking::try::do_call
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:554:40
11: __rust_try
12: std::panicking::try
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:518:19
13: std::panic::catch_unwind
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panic.rs:142:14
14: bevy_ecs::schedule::executor::multi_threaded::ExecutorState::spawn_system_task::{{closure}}
at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs:614:23
15: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::future::future::Future>::poll
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/panic/unwind_safe.rs:297:9
16: <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll::{{closure}}
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.2.0/src/future.rs:588:42
17: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/panic/unwind_safe.rs:272:9
18: std::panicking::try::do_call
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:554:40
19: __rust_try
20: std::panicking::try
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:518:19
21: std::panic::catch_unwind
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panic.rs:142:14
22: <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.2.0/src/future.rs:588:9
23: async_executor::Executor::spawn::{{closure}}
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.8.0/src/lib.rs:158:20
24: async_task::raw::RawTask<F,T,S,M>::run::{{closure}}
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-task-4.7.0/src/raw.rs:550:21
25: core::ops::function::FnOnce::call_once
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/ops/function.rs:250:5
26: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/panic/unwind_safe.rs:272:9
27: std::panicking::try::do_call
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:554:40
28: __rust_try
29: std::panicking::try
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:518:19
30: std::panic::catch_unwind
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panic.rs:142:14
31: async_task::raw::RawTask<F,T,S,M>::run
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-task-4.7.0/src/raw.rs:549:23
32: async_task::runnable::Runnable<M>::run
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-task-4.7.0/src/runnable.rs:781:18
33: async_executor::Executor::run::{{closure}}::{{closure}}
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.8.0/src/lib.rs:254:21
34: <futures_lite::future::Or<F1,F2> as core::future::future::Future>::poll
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.2.0/src/future.rs:449:33
35: async_executor::Executor::run::{{closure}}
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.8.0/src/lib.rs:261:32
36: futures_lite::future::block_on::{{closure}}
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.2.0/src/future.rs:99:19
37: std:🧵:local::LocalKey<T>::try_with
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/thread/local.rs:286:16
38: std:🧵:local::LocalKey<T>::with
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/thread/local.rs:262:9
39: futures_lite::future::block_on
at /home/vj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.2.0/src/future.rs:78:5
40: bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}::{{closure}}::{{closure}}
at /home/vj/workspace/rust/bevy/crates/bevy_tasks/src/task_pool.rs:180:37
41: std::panicking::try::do_call
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:554:40
42: __rust_try
43: std::panicking::try
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:518:19
44: std::panic::catch_unwind
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panic.rs:142:14
45: bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}::{{closure}}
at /home/vj/workspace/rust/bevy/crates/bevy_tasks/src/task_pool.rs:174:43
46: std:🧵:local::LocalKey<T>::try_with
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/thread/local.rs:286:16
47: std:🧵:local::LocalKey<T>::with
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/thread/local.rs:262:9
48: bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}
at /home/vj/workspace/rust/bevy/crates/bevy_tasks/src/task_pool.rs:167:25
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `foo::main::{{closure}}`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
get on your knees and beg mommy for forgiveness you pervert~ 💖
```
</details>
<details>
<summary>Example output with this PR</summary>
```
Panic at src/main.rs:7:33:
Foo
stack backtrace:
0: rust_begin_unwind
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/std/src/panicking.rs:647:5
1: core::panicking::panic_fmt
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/panicking.rs:72:14
2: foo::main::{{closure}}
at ./src/main.rs:7:59
3: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
at /rustc/8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6/library/core/src/ops/function.rs:294:13
4: <Func as bevy_ecs::system::function_system::SystemParamFunction<fn() .> Out>>::run::call_inner
at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/system/function_system.rs:661:21
5: <Func as bevy_ecs::system::function_system::SystemParamFunction<fn() .> Out>>::run
at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/system/function_system.rs:664:17
6: <bevy_ecs::system::function_system::FunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run_unsafe
at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/system/function_system.rs:504:19
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `foo::main::{{closure}}`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
```
</details>
Full backtraces (`RUST_BACKTRACE=full`) are unchanged.
## Alternative solutions
Write a custom panic hook. This could potentially let use exclude a few
more callstack frames but requires a dependency on `backtrace` and is
incompatible with user-provided panic hooks.
---
## Changelog
- Backtraces now exclude many Bevy internals (unless
`RUST_BACKTRACE=full` is used)
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
fix occasional crash from commands.insert when quickly spawning and
despawning skinned/morphed meshes
## Solution
use `try_insert` instead of `insert`. if the entity is deleted we don't
mind failing to add the `NoAutomaticBatching` marker.
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/12380
## Solution
- Before #11986 AssetEvents were scheduled after PostUpdate. That pr
moved these into First. This PR moves them into Last which is closer to
how they were scheduled before.
# Objective
- After #12370, ci testing with minimal plugins doesn't hang but it
crash as the resource `ScreenshotManager` doesn't exist
## Solution
- Check if the resource exists
# Objective
Fix missing `TextBundle` (and many others) which are present in the main
crate as default features but optional in the sub-crate. See:
- https://docs.rs/bevy/0.13.0/bevy/ui/node_bundles/index.html
- https://docs.rs/bevy_ui/0.13.0/bevy_ui/node_bundles/index.html
~~There are probably other instances in other crates that I could track
down, but maybe "all-features = true" should be used by default in all
sub-crates? Not sure.~~ (There were many.) I only noticed this because
rust-analyzer's "open docs" features takes me to the sub-crate, not the
main one.
## Solution
Add "all-features = true" to docs.rs metadata for crates that use
features.
## Changelog
### Changed
- Unified features documented on docs.rs between main crate and
sub-crates
# Objective
Provide guidelines for contributing code to `bevy_audio`, with a focus
on the critical sections of the audio engine.
## Changelog
Added to the crate-level documentation comment with a section
introducing audio programming, real-time safety and why it is important
to audio programming, as well as recommendations for some programming
use-cases. The section concludes with links to more resources about
audio programming.
I might have gone overboard with the writeup, but I didn't want to
assume a lot out of potential `bevy_audio` contributors, and so I spent
a bit of time defining terms as simply as I could.
I didn't want to pressure people to do so, but the first link on the
additional resources should really be "required reading" as it goes more
in depth about the why and how of audio programming.
---------
Co-authored-by: Nathan Graule <nathan.graule@arturia.com>
# Objective
`ButtonInput<KeyCode>` documentation is currently incorrect/incomplete,
see #12273.
## Solution
Fix the documentation.
I think in the future we should also stop triggering
`just_pressed`/`just_released` when focus switches between two Bevy
windows, as those functions are independent of the window. It could also
make sense to add individual `ButtonInput<KeyCode>`s per window.
---------
Co-authored-by: Mateusz Wachowiak <mateusz_wachowiak@outlook.com>
# Objective
- Fix#12356
- better isolation of ci testing tools in dev tools instead of being in
various crates
## Solution
- Move the parts doing the work of ci testing to the dev tools
# Objective
- Fix incorrect link in UIMaterial docs
## Solution
- Updated the link
Co-authored-by: Frank Hampus Weslien <frankhampusweslien@google.com>
This is an implementation of RFC #51:
https://github.com/bevyengine/rfcs/blob/main/rfcs/51-animation-composition.md
Note that the implementation strategy is different from the one outlined
in that RFC, because two-phase animation has now landed.
# Objective
Bevy needs animation blending. The RFC for this is [RFC 51].
## Solution
This is an implementation of the RFC. Note that the implementation
strategy is different from the one outlined there, because two-phase
animation has now landed.
This is just a draft to get the conversation started. Currently we're
missing a few things:
- [x] A fully-fleshed-out mechanism for transitions
- [x] A serialization format for `AnimationGraph`s
- [x] Examples are broken, other than `animated_fox`
- [x] Documentation
---
## Changelog
### Added
* The `AnimationPlayer` has been reworked to support blending multiple
animations together through an `AnimationGraph`, and as such will no
longer function unless a `Handle<AnimationGraph>` has been added to the
entity containing the player. See [RFC 51] for more details.
* Transition functionality has moved from the `AnimationPlayer` to a new
component, `AnimationTransitions`, which works in tandem with the
`AnimationGraph`.
## Migration Guide
* `AnimationPlayer`s can no longer play animations by themselves and
need to be paired with a `Handle<AnimationGraph>`. Code that was using
`AnimationPlayer` to play animations will need to create an
`AnimationGraph` asset first, add a node for the clip (or clips) you
want to play, and then supply the index of that node to the
`AnimationPlayer`'s `play` method.
* The `AnimationPlayer::play_with_transition()` method has been removed
and replaced with the `AnimationTransitions` component. If you were
previously using `AnimationPlayer::play_with_transition()`, add all
animations that you were playing to the `AnimationGraph`, and create an
`AnimationTransitions` component to manage the blending between them.
[RFC 51]:
https://github.com/bevyengine/rfcs/blob/main/rfcs/51-animation-composition.md
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
- With the recent lighting changes, the default configuration in the
`bloom_3d` example is less clear what bloom actually does
- See [this
screenshot](4fdb1455d5 (r1494648414))
for a comparison.
- `bloom_3d` additionally uses a for-loop to spawn the spheres, which
can be turned into `commands::spawn_batch` call.
- The text is black, which is difficult to see on the gray background.
## Solution
- Increase emmisive values of materials.
- Set text to white.
## Showcase
Before:
<img width="1392" alt="before"
src="https://github.com/bevyengine/bevy/assets/59022059/757057ad-ed9f-4eed-b135-8e2032fcdeb5">
After:
<img width="1392" alt="image"
src="https://github.com/bevyengine/bevy/assets/59022059/3f9dc7a8-94b2-44b9-8ac3-deef1905221b">
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Make bevy_utils less of a compilation bottleneck. Tackle #11478.
## Solution
* Move all of the directly reexported dependencies and move them to
where they're actually used.
* Remove the UUID utilities that have gone unused since `TypePath` took
over for `TypeUuid`.
* There was also a extraneous bytemuck dependency on `bevy_core` that
has not been used for a long time (since `encase` became the primary way
to prepare GPU buffers).
* Remove the `all_tuples` macro reexport from bevy_ecs since it's
accessible from `bevy_utils`.
---
## Changelog
Removed: Many of the reexports from bevy_utils (petgraph, uuid, nonmax,
smallvec, and thiserror).
Removed: bevy_core's reexports of bytemuck.
## Migration Guide
bevy_utils' reexports of petgraph, uuid, nonmax, smallvec, and thiserror
have been removed.
bevy_core' reexports of bytemuck's types has been removed.
Add them as dependencies in your own crate instead.
# Objective
Fixes#12353
When only `webp` was selected, `ImageLoader` would not be initialized.
That is, users using `default-features = false` would need to add `png`
or `bmp` or something in addition to `webp` in order to use `webp`.
This was also the case for `pnm`.
## Solution
Add `webp` and `pnm` to the list of features that trigger the
initialization of `ImageLoader`.
# Objective
- Resolves#11309
## Solution
- Add `bevy_dev_tools` crate as a default feature.
- Add `DevToolsPlugin` and add it to an app if the `bevy_dev_tools`
feature is enabled.
`bevy_dev_tools` is reserved by @alice-i-cecile, should we wait until it
gets transferred to cart before merging?
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
# Objective
- Fix slightly wrong logic from #11442
- Directional lights should not have a near clip plane
## Solution
- Push near clip out to infinity, so that the frustum normal is still
available if its needed for whatever reason in shader
- also opportunistically nabs a typo
# Objective
Fix#12304. Remove unnecessary type registrations thanks to #4154.
## Solution
Conservatively remove type registrations. Keeping the top level
components, resources, and events, but dropping everything else that is
a type of a member of those types.
# Objective
Following #10756, we're now using raw pointers in BundleInserter and
BundleSpawner. This is primarily to get around the need to split the
borrow on the World, but it leaves a lot to be desired in terms of
safety guarantees. There's no type level guarantee the code can't
dereference a null pointer, and it's restoring them to borrows fairly
liberally within the associated functions.
## Solution
* Replace the pointers with `NonNull` and a new `bevy_ptr::ConstNonNull`
that only allows conversion back to read-only borrows
* Remove the closure to avoid potentially aliasing through the closure
by restructuring the match expression.
* Move all conversions back into borrows as far up as possible to ensure
that the borrow checker is at least locally followed.
# Objective
Fixes#12225
Prior to the `bevy_color` port, `GREEN` used to mean "full green." But
it is now a much darker color matching the css1 spec.
## Solution
Change usages of `basic::GREEN` or `css::GREEN` to `LIME` to restore the
examples to their former colors.
This also removes the duplicate definition of `GREEN` from `css`. (it
was already re-exported from `basic`)
## Note
A lot of these examples could use nicer colors. I'm not trying to do
that here.
"Dark Grey" will be tackled separately and has its own tracking issue.
# Objective
Addresses one of the side-notes in #12225.
Colors in the `basic` palette are inconsistent in a few ways:
- `CYAN` was named `AQUA` in the referenced spec. (an alias was added in
a later spec)
- Colors are defined with e.g. "half green" having a `g` value of `0.5`.
But any spec would have been based on 8-bit color, so `0x80 / 0xFF` or
`128 / 255` or ~`0.502`. This precision is likely meaningful when doing
color math/rounding.
## Solution
Regenerate the colors from
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=37563bedc8858033bd8b8380328c5230
# Objective
- Avoid version mismatch
- When cpal updates oboe in a patch release, this breaks android support
for Bevy
## Solution
- Use the same version of oboe as cpal by relying on it to re-export the
feature
# Objective
Fixes#12310.
#11681 added transformations for bounding volumes, but I accidentally
only added a note in the docs about repeated rotations for `Aabb2d` and
not `Aabb3d`.
## Solution
Copy the docs over to `Aabb3d`.
# Objective
- Describe the objective or issue this PR addresses.
Improve docs around emissive colors --
I couldn't figure out how to increase the emissive strength of
materials, asking on discord @alice-i-cecile told me that color channel
values can go above `1.0` in the case of the `emissive` field. I would
have never figured this out on my own, because [the docs for
emissive](https://docs.rs/bevy/latest/bevy/prelude/struct.StandardMaterial.html#structfield.emissive)
don't mention this possibility, and indeed if you follow the link in the
`emissive` doc [to the `Color`
type](https://docs.rs/bevy/latest/bevy/render/color/enum.Color.html#variants),
you are told that values should be in `[0.0, 1.0]`.
## Solution
- Describe the solution used to achieve the objective above.
Just added a note on the possibility of large color channel values with
example.
# Objective
`initialize_resource<T>` and it's non-send equivalent is only used in
two locations each. Fix#6285.
## Solution
Remove them, replace their calls with their internals. Cut down on a bit
of generic codegen.
This does mean that `initialize_resource_internal` is now `pub(crate)`,
but that's likely OK given that only one variant will remain once
NonSend resources are removed from the World.
# Objective
Follow up to #11600 and #10588https://github.com/bevyengine/bevy/issues/11944 made clear that some
people want to use slicing with texture atlases
## Changelog
* Added support for `TextureAtlas` slicing and tiling.
`SpriteSheetBundle` and `AtlasImageBundle` can now use `ImageScaleMode`
* Added new `ui_texture_atlas_slice` example using a texture sheet
<img width="798" alt="Screenshot 2024-02-23 at 11 58 35"
src="https://github.com/bevyengine/bevy/assets/26703856/47a8b764-127c-4a06-893f-181703777501">
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
# Objective
When doing a final pass for #3362, it appeared that `ComponentStorage`
as a trait, the two types implementing it, and the associated type on
`Component` aren't really necessary anymore. This likely was due to an
earlier constraint on the use of consts in traits, but that definitely
doesn't seem to be a problem in Rust 1.76.
## Solution
Remove them.
---
## Changelog
Changed: `Component::Storage` has been replaced with
`Component::STORAGE_TYPE` as a const.
Removed: `bevy::ecs::component::ComponentStorage` trait
Removed: `bevy::ecs::component::TableStorage` struct
Removed: `bevy::ecs::component::SparseSetStorage` struct
## Migration Guide
If you were manually implementing `Component` instead of using the
derive macro, replace the associated `Storage` associated type with the
`STORAGE_TYPE` const:
```rust
// in Bevy 0.13
impl Component for MyComponent {
type Storage = TableStorage;
}
// in Bevy 0.14
impl Component for MyComponent {
const STORAGE_TYPE: StorageType = StorageType::Table;
}
```
Component is no longer object safe. If you were relying on `&dyn
Component`, `Box<dyn Component>`, etc. please [file an issue
](https://github.com/bevyengine/bevy/issues) to get [this
change](https://github.com/bevyengine/bevy/pull/12311) reverted.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
- Explain it is flushed in the same schedule run (was not obvious to me)
- Point to `apply_deferred` example
- Remove mentions of `System::apply_deferred` and
`Schedule::apply_deferred` which are probably too low level for the most
users
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
cpal has been updated to [0.15.3](https://crates.io/crates/cpal/0.15.3).
we can remove the skip to avoid check for cpal 0.15.2 dependencies in
deny.toml
cpal now uses ndk 8.0 and Oboe 6.0, so we only have a version for
raw-window-handle, version 0.6
## Solution
- Remove temporal fix that skipped the check for the cpal dependency.
- Update oboe to 0.6
Fixes https://github.com/bevyengine/bevy/issues/11917
# Objective
`bevy_utils::Entry` is only useful when using
`BuildHasherDefault<AHasher>`. It would be great if we didn't have to
write out `bevy_utils::hashbrown::hash_map::Entry` whenever we want to
use a different `BuildHasher`, such as when working with
`bevy_utils::TypeIdMap`.
## Solution
Give `bevy_utils::Entry` a new optional type parameter for defining a
custom `BuildHasher`, such as `NoOpHash`. This parameter defaults to
`BuildHasherDefault<AHasher>`— the `BuildHasher` used by
`bevy_utils::HashMap`.
---
## Changelog
- Added an optional third type parameter to `bevy_utils::Entry` to
specify a custom `BuildHasher`
# Objective
Make it straightforward to translate and rotate bounding volumes.
## Solution
Add `translate_by`/`translated_by`, `rotate_by`/`rotated_by`,
`transform_by`/`transformed_by` methods to the `BoundingVolume` trait.
This follows the naming used for mesh transformations (see #11454 and
#11675).
---
## Changelog
- Added `translate_by`/`translated_by`, `rotate_by`/`rotated_by`,
`transform_by`/`transformed_by` methods to the `BoundingVolume` trait
and implemented them for the bounding volumes
- Renamed `Position` associated type to `Translation`
---------
Co-authored-by: Mateusz Wachowiak <mateusz_wachowiak@outlook.com>
# Objective
- The doc example for `World::run_system_with_input` mistakenly
indicates that systems share state
- Some of the doc example code is unnecessary and/or could be cleaned up
## Solution
Replace the incorrect result value for the correct one in the doc
example. I also went with an explicit `assert_eq` check as it presents
the same information but can be validated by CI via doc tests.
Also removed some unnecessary code, such as the `Resource` derives on
`Counter`. In fact, I just replaced `Counter` with a `u8` in the
`Local`. I think it makes the example a little cleaner.
---
## Changelog
- Update docs for `World::run_system` and `World::run_system_with_input`
# Objective
- Fixes#12255
Still needs confirming what the consequences are from having camera
viewport nodes live on the root of the taffy tree.
## Solution
To fix calculating the layouts for UI nodes we need to cleanup the
children previously set whenever `TargetCamera` is updated. This also
maintains a list of taffy camera nodes and cleans them up when removed.
---
## Changelog
Fixed#12255
## Migration Guide
changes affect private structs/members so shouldn't need actions by
engine users.
# Objective
Fixes#12126
Notably this does not appear to fix the console error spam that appears
to be coming from winit, only the performance bug that occurs when
tabbing out and back into the game.
## Solution
The winit event loop starts out as `ControlFlow::Wait` by default. When
switching to `UpdateMode::Reactive` or `UpdateMode::ReactiveLowPower`,
we repeatedly update this to `ControlFlow::WaitUntil(next)`. When
switching back to `UpdateMode::Continuous`, the event loop is
erroneously stuck at the latest `ControlFlow::WaitUntil(next)` that was
issued.
I also changed how we handle `Event::NewEvents` since the `StartCause`
already tells us enough information to make that decision. This came
about my debugging and I left it in as an improvement.
# Objective
Resolves#4154
Currently, registration must all be done manually:
```rust
#[derive(Reflect)]
struct Foo(Bar);
#[derive(Reflect)]
struct Bar(Baz);
#[derive(Reflect)]
struct Baz(usize);
fn main() {
// ...
app
.register_type::<Foo>()
.register_type::<Bar>()
.register_type::<Baz>()
// .register_type::<usize>() <- This one is handled by Bevy, thankfully
// ...
}
```
This can grow really quickly and become very annoying to add, remove,
and update as types change. It would be great if we could help reduce
the number of types that a user must manually implement themselves.
## Solution
As suggested in #4154, this PR adds automatic recursive registration.
Essentially, when a type is registered, it may now also choose to
register additional types along with it using the new
`GetTypeRegistration::register_type_dependencies` trait method.
The `Reflect` derive macro now automatically does this for all fields in
structs, tuple structs, struct variants, and tuple variants. This is
also done for tuples, arrays, `Vec<T>`, `HashMap<K, V>`, and
`Option<T>`.
This allows us to simplify the code above like:
```rust
#[derive(Reflect)]
struct Foo(Bar);
#[derive(Reflect)]
struct Bar(Baz);
#[derive(Reflect)]
struct Baz(usize);
fn main() {
// ...
app.register_type::<Foo>()
// ...
}
```
This automatic registration only occurs if the type has not yet been
registered. If it has been registered, we simply skip it and move to the
next one. This reduces the cost of registration and prevents overwriting
customized registrations.
## Considerations
While this does improve ergonomics on one front, it's important to look
at some of the arguments against adopting a PR like this.
#### Generic Bounds
~~Since we need to be able to register the fields individually, we need
those fields to implement `GetTypeRegistration`. This forces users to
then add this trait as a bound on their generic arguments. This
annoyance could be relieved with something like #5772.~~
This is no longer a major issue as the `Reflect` derive now adds the
`GetTypeRegistration` bound by default. This should technically be okay,
since we already add the `Reflect` bound.
However, this can also be considered a breaking change for manual
implementations that left out a `GetTypeRegistration` impl ~~or for
items that contain dynamic types (e.g. `DynamicStruct`) since those also
do not implement `GetTypeRegistration`~~.
#### Registration Assumptions
By automatically registering fields, users might inadvertently be
relying on certain types to be automatically registered. If `Foo`
auto-registers `Bar`, but `Foo` is later removed from the code, then
anywhere that previously used or relied on `Bar`'s registration would
now fail.
---
## Changelog
- Added recursive type registration to structs, tuple structs, struct
variants, tuple variants, tuples, arrays, `Vec<T>`, `HashMap<K, V>`, and
`Option<T>`
- Added a new trait in the hidden `bevy_reflect::__macro_exports` module
called `RegisterForReflection`
- Added `GetTypeRegistration` impl for
`bevy_render::render_asset::RenderAssetUsages`
## Migration Guide
All types that derive `Reflect` will now automatically add
`GetTypeRegistration` as a bound on all (unignored) fields. This means
that all reflected fields will need to also implement
`GetTypeRegistration`.
If all fields **derive** `Reflect` or are implemented in `bevy_reflect`,
this should not cause any issues. However, manual implementations of
`Reflect` that excluded a `GetTypeRegistration` impl for their type will
need to add one.
```rust
#[derive(Reflect)]
struct Foo<T: FromReflect> {
data: MyCustomType<T>
}
// OLD
impl<T: FromReflect> Reflect for MyCustomType<T> {/* ... */}
// NEW
impl<T: FromReflect + GetTypeRegistration> Reflect for MyCustomType<T> {/* ... */}
impl<T: FromReflect + GetTypeRegistration> GetTypeRegistration for MyCustomType<T> {/* ... */}
```
---------
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: radiish <cb.setho@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Hi, this is a minimal implementation of #12159. I wasn't sure if the
`EventLoopProxy` should be wrapped somewhat to make it more explicit.
# Objective
Minimal implementation of #12159
When using `UpdateMode::Reactive` it is currently not possible to
request a redraw when a long running task is finished or an external
source has new data.
This makes the following possible which will then run an app update once
``` rust
// EventLoopProxy is Send on most architectures
// The EventLoopProxy can also be saved in a thread local for WASM or a static in other architecturecs
pub fn example(proxy: NonSend<EventLoopProxy<()>>) {
let clone: EventLoopProxy<()> = proxy.clone();
thread::spawn(move || {
// do long work
clone.send_event(());
});
}
```
## Solution
By using the EventLoopProxy one can manually send events from external
threads to the event loop as `UserEvent`s.
This simply sets redraw_requested when a `UserEvent` is received.
## Changelog
- Added the ability to request a redraw from an external source
---------
Co-authored-by: Kellner, Robin <Robin.Kellner@vector.com>
# Objective
Correct references to `Input` into `ButtonInput` in the keyboard input
docs since it was renamed in 0.13.
## Solution
Change the type used in the keyboard input docs from `Input` to
`ButtonInput`.
# Objective
`Dir3` and `Dir3A` can be rotated using `Quat`s. However, if enough
floating point error accumulates or (more commonly) the rotation itself
is degenerate (like not normalized), the resulting direction can also
become denormalized.
Currently, with debug assertions enabled, it panics in these cases with
the message `rotated.is_normalized()`. This error message is unclear,
doesn't give information about *how* it is denormalized (like is the
length too large, NaN, or something else), and is overall not very
helpful. Panicking for small-ish error might also be a bit too strict,
and has lead to unwanted crashes in crates like `bevy_xpbd` (although it
has also helped in finding actual bugs).
The error message should be clearer and give more context, and it
shouldn't cause unwanted crashes.
## Solution
Change the `debug_assert!` to a warning for small error with a (squared
length) threshold of 2e-4 and a panic for clear error with a threshold
of 2e-2. The warnings mention the direction type and the length of the
denormalized vector.
Here's what the error and warning look like:
```
Error: `Dir3` is denormalized after rotation. The length is 1.014242.
```
```
Warning: `Dir3A` is denormalized after rotation. The length is 1.0001414.
```
I gave the same treatment to `new_unchecked`:
```
Error: The vector given to `Dir3::new_unchecked` is not normalized. The length is 1.014242.
```
```
Warning: The vector given to `Dir3A::new_unchecked` is not normalized. The length is 1.0001414.
```
---
## Discussion
### Threshold values
The thresholds are somewhat arbitrary. 2e-4 is what Glam uses for the
squared length in `is_normalized` (after I corrected it in
bitshifter/glam-rs#480), and 2e-2 is just what I thought could be a
clear sign of something being critically wrong. I can definitely tune
them if there are better thresholds though.
### Logging
`bevy_math` doesn't have `bevy_log`, so we can't use `warn!` or
`error!`. This is why I made it use just `eprintln!` and `panic!` for
now. Let me know if there's a better way of logging errors in
`bevy_math`.
# Objective
In my library,
[`bevy_dev_console`](https://github.com/doonv/bevy_dev_console) I need
access to `App` within `LogPlugin::update_subscriber` in order to
communicate with the `App` from my custom `Layer`.
## Solution
Give access to `App`.
---
## Changelog
- Added access to `App` within `LogPlugin::update_subscriber`
## Migration Guide
`LogPlugin::update_subscriber` now has a `&mut App` parameter. If you
don't need access to `App`, you can ignore the parameter with an
underscore (`_`).
```diff,rust
- fn update_subscriber(subscriber: BoxedSubscriber) -> BoxedSubscriber {
+ fn update_subscriber(_: &mut App, subscriber: BoxedSubscriber) -> BoxedSubscriber {
Box::new(subscriber.with(CustomLayer))
}
```
# Objective
- Allow users to read window events in the sequence they appeared. This
is important for precise input handling when there are multiple input
events in a single frame (e.g. click and release vs release and click).
## Solution
- Add a mega-enum `WinitEvent` that collects window events, and send
those alongside the existing more granular window events.
---
## Changelog
- Added `WinitEvent` event that aggregates all window events into a
synchronized event stream.
# Objective
Fixes https://github.com/bevyengine/bevy/issues/11157.
## Solution
Stop using `BackgroundColor` as a color tint for `UiImage`. Add a
`UiImage::color` field for color tint instead. Allow a UI node to
simultaneously include a solid-color background and an image, with the
image rendered on top of the background (this is already how it works
for e.g. text).
![2024-02-29_1709239666_563x520](https://github.com/bevyengine/bevy/assets/12173779/ec50c9ef-4c7f-4ab8-a457-d086ce5b3425)
---
## Changelog
- The `BackgroundColor` component now renders a solid-color background
behind `UiImage` instead of tinting its color.
- Removed `BackgroundColor` from `ImageBundle`, `AtlasImageBundle`, and
`ButtonBundle`.
- Added `UiImage::color`.
- Expanded `RenderUiSystem` variants.
- Renamed `bevy_ui::extract_text_uinodes` to `extract_uinodes_text` for
consistency.
## Migration Guide
- `BackgroundColor` no longer tints the color of UI images. Use
`UiImage::color` for that instead.
- For solid color buttons, replace `ButtonBundle { background_color:
my_color.into(), ... }` with `ButtonBundle { image:
UiImage::default().with_color(my_color), ... }`, and update button
interaction systems to use `UiImage::color` instead of `BackgroundColor`
as well.
- `bevy_ui::RenderUiSystem::ExtractNode` has been split into
`ExtractBackgrounds`, `ExtractImages`, `ExtractBorders`, and
`ExtractText`.
- `bevy_ui::extract_uinodes` has been split into
`bevy_ui::extract_uinode_background_colors` and
`bevy_ui::extract_uinode_images`.
- `bevy_ui::extract_text_uinodes` has been renamed to
`extract_uinode_text`.
# Objective
After the `TextureAtlas` changes that landed in 0.13,
`SpriteSheetBundle` is equivalent to `TextureAtlas` + `SpriteBundle` and
`AtlasImageBundle` is equivalent to `TextureAtlas` + `ImageBundle`. As
such, the atlas bundles aren't particularly useful / necessary additions
to the API anymore.
In addition, atlas bundles are inconsistent with `ImageScaleMode` (also
introduced in 0.13) which doesn't have its own version of each image
bundle.
## Solution
Deprecate `SpriteSheetBundle` and `AtlasImageBundle` in favor of
including `TextureAtlas` as a separate component alongside
`SpriteBundle` and `ImageBundle`, respectively.
---
## Changelog
- Deprecated `SpriteSheetBundle` and `AtlasImageBundle`.
## Migration Guide
- `SpriteSheetBundle` has been deprecated. Use `TextureAtlas` alongside
a `SpriteBundle` instead.
- `AtlasImageBundle` has been deprecated. Use `TextureAtlas` alongside
an `ImageBundle` instead.
# Objective
- Part of #9400.
- Add light gizmos for `SpotLight`, `PointLight` and `DirectionalLight`.
## Solution
- Add a `ShowLightGizmo` and its related gizmo group and plugin, that
shows a gizmo for all lights of an entities when inserted on it. Light
display can also be toggled globally through the gizmo config in the
same way it can already be done for `Aabb`s.
- Add distinct segment setters for height and base one `Cone3dBuilder`.
This allow having a properly rounded base without too much edges along
the height. The doc comments explain how to ensure height and base
connect when setting different values.
Gizmo for the three light types without radius with the depth bias set
to -1:
![without-radius](https://github.com/bevyengine/bevy/assets/18357657/699d0154-f367-4727-9b09-8b458d96a0e2)
With Radius:
![with-radius](https://github.com/bevyengine/bevy/assets/18357657/f3af003e-dbba-427a-a305-c5cc1676e340)
Possible future improvements:
- Add a billboarded sprite with a distinct sprite for each light type.
- Display the intensity of the light somehow (no idea how to represent
that apart from some text).
---
## Changelog
### Added
- The new `ShowLightGizmo`, part of the `LightGizmoPlugin` and
configurable globally with `LightGizmoConfigGroup`, allows drawing gizmo
for `PointLight`, `SpotLight` and `DirectionalLight`. The gizmos color
behavior can be controlled with the `LightGizmoColor` member of
`ShowLightGizmo` and `LightGizmoConfigGroup`.
- The cone gizmo builder (`Cone3dBuilder`) now allows setting a
differing number of segments for the base and height.
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
Bevy's `Dir3` and `Dir3A` only implement `Mul<f32>` and not vice versa,
and `Dir2` can not be multiplied by `f32` at all. They all should
implement multiplication both ways, just like Glam's vector types.
## Solution
Implement `Mul<Dir2>`, `Mul<Dir3>`, and `Mul<Dir3A>` for `f32`, and
`Mul<f32>` for `Dir2`.
# Objective
Adoption of #2104 and #11843. The `Option<usize>` wastes 3-7 bytes of
memory per potential entry, and represents a scaling memory overhead as
the ID space grows.
The goal of this PR is to reduce memory usage without significantly
impacting common use cases.
Co-Authored By: @NathanSWard
Co-Authored By: @tygyh
## Solution
Replace `usize` in `SparseSet`'s sparse array with
`nonmax::NonMaxUsize`. NonMaxUsize wraps a NonZeroUsize, and applies a
bitwise NOT to the value when accessing it. This allows the compiler to
niche the value and eliminate the extra padding used for the `Option`
inside the sparse array, while moving the niche value from 0 to
usize::MAX instead.
Checking the [diff in x86 generated
assembly](6e4da653cc),
this change actually results in fewer instructions generated. One
potential downside is that it seems to have moved a load before a
branch, which means we may be incurring a cache miss even if the element
is not there.
Note: unlike #2104 and #11843, this PR only targets the metadata stores
for the ECS and not the component storage itself. Due to #9907 targeting
`Entity::generation` instead of `Entity::index`, `ComponentSparseSet`
storing only up to `u32::MAX` elements would become a correctness issue.
This will come with a cost when inserting items into the SparseSet, as
now there is a potential for a panic. These cost are really only
incurred when constructing a new Table, Archetype, or Resource that has
never been seen before by the World. All operations that are fairly cold
and not on any particular hotpath, even for command application.
---
## Changelog
Changed: `SparseSet` now can only store up to `usize::MAX - 1` elements
instead of `usize::MAX`.
Changed: `SparseSet` now uses 33-50% less memory overhead per stored
item.
Follow up to #11057
Implemented suggestions from reviewers from: a simpler
fit_canvas_to_parent leads to an explicit CSS setting to the canvas.
From my understanding, it has do be set after wgpu creation due to wgpu
overriding the canvas width/height:
4400a58470/examples/src/utils.rs (L68-L74)
# Changelog
- Re-enable a `fit_canvas_to_parent`, it's removal from
https://github.com/bevyengine/bevy/pull/11057 was problematic. Still,
its inner working is more simple than before: bevy doesn't handle its
resizing, winit does.
## Migration Guide
- Cancels the migration from
https://github.com/bevyengine/bevy/pull/11057
# Objective
Fixes https://github.com/bevyengine/bevy/issues/11628
## Migration Guide
`Command` and `CommandQueue` have migrated from `bevy_ecs::system` to
`bevy_ecs::world`, so `use bevy_ecs::world::{Command, CommandQueue};`
when necessary.
# Objective
Fixes#11298. Make the use of bevy_log vs bevy_utils::tracing more
consistent.
## Solution
Replace all uses of bevy_log's logging macros with the reexport from
bevy_utils. Remove bevy_log as a dependency where it's no longer needed
anymore.
Ideally we should just be using tracing directly, but given that all of
these crates are already using bevy_utils, this likely isn't that great
of a loss right now.
# Objective
bevy_ecs has been developed with a de facto assumption that `Entity` is
to be treated as an opaque identifier by external users, and that its
internal representation is readable but in no way guaranteed to be
stable between versions of bevy_ecs.
This hasn't been clear to users, and the functions on the type that
expose its guts speak a different story.
## Solution
Explicitly document the lack of stability here and define internal
representation changes as a non-breaking change under SemVer. Give it
the same treatment that the standard lib gives `TypeId`.
# Objective
While mucking around with batch_and_prepare systems, it became apparent
that `GpuArrayBufferIndex::index` doesn't need to be a NonMaxU32.
## Solution
Replace it with a normal u32.
This likely has some potential perf benefit by avoiding panics and the
NOT operations, but I haven't been able to find any substantial gains,
so this is primarily for code quality.
---
## Changelog
Changed: `GpuArrayBufferIndex::index` is now a u32.
## Migration Guide
`GpuArrayBuferIndex::index` is now a u32 instead of a `NonMaxU32`.
Remove any calls to `NonMaxU32::get` on the member.
# Objective
- Fix mismatch between the `Component` trait method and the `World`
method.
## Solution
- Replace init_component_info with register_component_hooks.
# Objective
This PR unpins `web-sys` so that unrelated projects that have
`bevy_render` in their workspace can finally update their `web-sys`.
More details in and fixes#12246.
## Solution
* Update `wgpu` from 0.19.1 to 0.19.3.
* Remove the `web-sys` pin.
* Update docs and wasm helper to remove the now-stale
`--cfg=web_sys_unstable_apis` Rust flag.
---
## Changelog
Updated `wgpu` to v0.19.3 and removed `web-sys` pin.
This is an implementation within `bevy_window::window` that fixes
#12229.
# Objective
Fixes#12229, allow users to retrieve the window's size and physical
size as Vectors without having to manually construct them using
`height()` and `width()` or `physical_height()` and `physical_width()`
## Solution
As suggested in #12229, created two public functions within `window`:
`size() -> Vec` and `physical_size() -> UVec` that return the needed
Vectors ready-to-go.
### Discussion
My first FOSS PRQ ever, so bear with me a bit. I'm new to this.
- I replaced instances of ```Vec2::new(window.width(),
window.height());``` or `UVec2::new(window.physical_width(),
window.physical_height());` within bevy examples be replaced with their
`size()`/`physical_size()` counterparts?
- Discussion within #12229 still holds: should these also be added to
WindowResolution?
Although we cached hashes of `MeshVertexBufferLayout`, we were paying
the cost of `PartialEq` on `InnerMeshVertexBufferLayout` for every
entity, every frame. This patch changes that logic to place
`MeshVertexBufferLayout`s in `Arc`s so that they can be compared and
hashed by pointer. This results in a 28% speedup in the
`queue_material_meshes` phase of `many_cubes`, with frustum culling
disabled.
Additionally, this patch contains two minor changes:
1. This commit flattens the specialized mesh pipeline cache to one level
of hash tables instead of two. This saves a hash lookup.
2. The example `many_cubes` has been given a `--no-frustum-culling`
flag, to aid in benchmarking.
See the Tracy profile:
<img width="1064" alt="Screenshot 2024-02-29 144406"
src="https://github.com/bevyengine/bevy/assets/157897/18632f1d-1fdd-4ac7-90ed-2d10306b2a1e">
## Migration guide
* Duplicate `MeshVertexBufferLayout`s are now combined into a single
object, `MeshVertexBufferLayoutRef`, which contains an
atomically-reference-counted pointer to the layout. Code that was using
`MeshVertexBufferLayout` may need to be updated to use
`MeshVertexBufferLayoutRef` instead.
# Objective
- Provide a reliable and performant mechanism to allows users to keep
components synchronized with external sources: closing/opening sockets,
updating indexes, debugging etc.
- Implement a generic mechanism to provide mutable access to the world
without allowing structural changes; this will not only be used here but
is a foundational piece for observers, which are key for a performant
implementation of relations.
## Solution
- Implement a new type `DeferredWorld` (naming is not important,
`StaticWorld` is also suitable) that wraps a world pointer and prevents
user code from making any structural changes to the ECS; spawning
entities, creating components, initializing resources etc.
- Add component lifecycle hooks `on_add`, `on_insert` and `on_remove`
that can be assigned callbacks in user code.
---
## Changelog
- Add new `DeferredWorld` type.
- Add new world methods: `register_component::<T>` and
`register_component_with_descriptor`. These differ from `init_component`
in that they provide mutable access to the created `ComponentInfo` but
will panic if the component is already in any archetypes. These
restrictions serve two purposes:
1. Prevent users from defining hooks for components that may already
have associated hooks provided in another plugin. (a use case better
served by observers)
2. Ensure that when an `Archetype` is created it gets the appropriate
flags to early-out when triggering hooks.
- Add methods to `ComponentInfo`: `on_add`, `on_insert` and `on_remove`
to be used to register hooks of the form `fn(DeferredWorld, Entity,
ComponentId)`
- Modify `BundleInserter`, `BundleSpawner` and `EntityWorldMut` to
trigger component hooks when appropriate.
- Add bit flags to `Archetype` indicating whether or not any contained
components have each type of hook, this can be expanded for other flags
as needed.
- Add `component_hooks` example to illustrate usage. Try it out! It's
fun to mash keys.
## Safety
The changes to component insertion, removal and deletion involve a large
amount of unsafe code and it's fair for that to raise some concern. I
have attempted to document it as clearly as possible and have confirmed
that all the hooks examples are accepted by `cargo miri` as not causing
any undefined behavior. The largest issue is in ensuring there are no
outstanding references when passing a `DeferredWorld` to the hooks which
requires some use of raw pointers (as was already happening to some
degree in those places) and I have taken some time to ensure that is the
case but feel free to let me know if I've missed anything.
## Performance
These changes come with a small but measurable performance cost of
between 1-5% on `add_remove` benchmarks and between 1-3% on `insert`
benchmarks. One consideration to be made is the existence of the current
`RemovedComponents` which is on average more costly than the addition of
`on_remove` hooks due to the early-out, however hooks doesn't completely
remove the need for `RemovedComponents` as there is a chance you want to
respond to the removal of a component that already has an `on_remove`
hook defined in another plugin, so I have not removed it here. I do
intend to deprecate it with the introduction of observers in a follow up
PR.
## Discussion Questions
- Currently `DeferredWorld` implements `Deref` to `&World` which makes
sense conceptually, however it does cause some issues with rust-analyzer
providing autocomplete for `&mut World` references which is annoying.
There are alternative implementations that may address this but involve
more code churn so I have attempted them here. The other alternative is
to not implement `Deref` at all but that leads to a large amount of API
duplication.
- `DeferredWorld`, `StaticWorld`, something else?
- In adding support for hooks to `EntityWorldMut` I encountered some
unfortunate difficulties with my desired API. If commands are flushed
after each call i.e. `world.spawn() // flush commands .insert(A) //
flush commands` the entity may be despawned while `EntityWorldMut` still
exists which is invalid. An alternative was then to add
`self.world.flush_commands()` to the drop implementation for
`EntityWorldMut` but that runs into other problems for implementing
functions like `into_unsafe_entity_cell`. For now I have implemented a
`.flush()` which will flush the commands and consume `EntityWorldMut` or
users can manually run `world.flush_commands()` after using
`EntityWorldMut`.
- In order to allowing querying on a deferred world we need
implementations of `WorldQuery` to not break our guarantees of no
structural changes through their `UnsafeWorldCell`. All our
implementations do this, but there isn't currently any safety
documentation specifying what is or isn't allowed for an implementation,
just for the caller, (they also shouldn't be aliasing components they
didn't specify access for etc.) is that something we should start doing?
(see 10752)
Please check out the example `component_hooks` or the tests in
`bundle.rs` for usage examples. I will continue to expand this
description as I go.
See #10839 for a more ergonomic API built on top of this one that isn't
subject to the same restrictions and supports `SystemParam` dependency
injection.
# Objective
- We introduce a gizmo that displays coordinate axes relative to a
Transform*, primarily for debugging purposes.
- See #9400
## Solution
A new method, `Gizmos::axes`, takes a `Transform`* as input and displays
the standard coordinate axes, transformed according to it; its signature
looks like this:
````rust
pub fn axes(&mut self, transform: into TransformPoint, base_length: f32) { //... }
````
If my carefully placed asterisks hadn't already tipped you off, the
argument here is not actually a `Transform` but instead anything which
implements `TransformPoint`, which allows it to work also with
`GlobalTransform` (and also `Mat4` and `Affine3A`, if the user happens
to be hand-rolling transformations in some way).
The `base_length` parameter is a scaling factor applied to the
coordinate vectors before the transformation takes place; in other
words, the caller can use this to help size the coordinate axes
appropriately for the entity that they are attached to.
An example invocation of this method looks something like this:
````rust
fn draw_axes_system(
mut gizmos: Gizmos,
query: Query<&Transform, With<MyMarkerComponent>>,
) {
for &transform in &query {
gizmos.axes(transform, 2.);
}
}
````
The result is the three coordinate axes, X, Y, Z (colored red, green,
and blue, respectively), drawn onto the entity:
<img width="206" alt="Screenshot 2024-02-29 at 2 41 45 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/789d1703-29ae-4295-80ab-b87459cf8037">
Note that, if scaling was applied as part of the given transformation,
it shows up in scaling on the axes as well:
<img width="377" alt="Screenshot 2024-02-29 at 2 43 53 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/6dc1caf4-8b3e-47f7-a86a-8906d870fa72">
---
## Changelog
- Added `Gizmos::axes` in bevy_gizmos/src/arrows.rs
- Fixed a minor issue with `ArrowBuilder::with_tip_length` not correctly
implementing builder style (no external impact)
---
## Discussion
### Design considerations
I feel pretty strongly that having no default length scale is for the
best, at least for the time being, since it's very easy for the length
scale to be too small, leading to the axes being hidden inside the body
of the object they are associated with. That is, if the API instead
looked like this:
````rust
gizmos.axes(transform); // or
gizmos.axes(transform).with_length_scale(3.0);
````
then I think it's a reasonable expectation that the first thing would
"just work" for most applications, and it wouldn't, which would be kind
of a footgun.
### Future steps
There are a few directions that this might expand in the future:
1. Introduce additional options via the standard builder pattern; i.e.
introducing `AxesBuilder<T: TransformPoint>` so that people can
configure the axis colors, normalize all axes to a fixed length
independent of scale deformations, etc.
2. Fold this functionality into a plugin (like AabbGizmoPlugin) so that
the functionality becomes more-or-less automatic based on certain fixed
marker components. This wouldn't be very hard to implement, and it has
the benefit of making the axes more frictionless to use. Furthermore, if
we coupled this to the AABB functionality we already have, we could also
ensure that the plugin automatically sizes the axes (by coupling their
size to the dimensions of the AABB, for example).
3. Implement something similar for 2d. Honestly, I have no idea if this
is desired/useful, but I could probably just implement it in this PR if
that's the case.
# Objective
- As part of the migration process we need to a) see the end effect of
the migration on user ergonomics b) check for serious perf regressions
c) actually migrate the code
- To accomplish this, I'm going to attempt to migrate all of the
remaining user-facing usages of `LegacyColor` in one PR, being careful
to keep a clean commit history.
- Fixes#12056.
## Solution
I've chosen to use the polymorphic `Color` type as our standard
user-facing API.
- [x] Migrate `bevy_gizmos`.
- [x] Take `impl Into<Color>` in all `bevy_gizmos` APIs
- [x] Migrate sprites
- [x] Migrate UI
- [x] Migrate `ColorMaterial`
- [x] Migrate `MaterialMesh2D`
- [x] Migrate fog
- [x] Migrate lights
- [x] Migrate StandardMaterial
- [x] Migrate wireframes
- [x] Migrate clear color
- [x] Migrate text
- [x] Migrate gltf loader
- [x] Register color types for reflection
- [x] Remove `LegacyColor`
- [x] Make sure CI passes
Incidental improvements to ease migration:
- added `Color::srgba_u8`, `Color::srgba_from_array` and friends
- added `set_alpha`, `is_fully_transparent` and `is_fully_opaque` to the
`Alpha` trait
- add and immediately deprecate (lol) `Color::rgb` and friends in favor
of more explicit and consistent `Color::srgb`
- standardized on white and black for most example text colors
- added vector field traits to `LinearRgba`: ~~`Add`, `Sub`,
`AddAssign`, `SubAssign`,~~ `Mul<f32>` and `Div<f32>`. Multiplications
and divisions do not scale alpha. `Add` and `Sub` have been cut from
this PR.
- added `LinearRgba` and `Srgba` `RED/GREEN/BLUE`
- added `LinearRgba_to_f32_array` and `LinearRgba::to_u32`
## Migration Guide
Bevy's color types have changed! Wherever you used a
`bevy::render::Color`, a `bevy::color::Color` is used instead.
These are quite similar! Both are enums storing a color in a specific
color space (or to be more precise, using a specific color model).
However, each of the different color models now has its own type.
TODO...
- `Color::rgba`, `Color::rgb`, `Color::rbga_u8`, `Color::rgb_u8`,
`Color::rgb_from_array` are now `Color::srgba`, `Color::srgb`,
`Color::srgba_u8`, `Color::srgb_u8` and `Color::srgb_from_array`.
- `Color::set_a` and `Color::a` is now `Color::set_alpha` and
`Color::alpha`. These are part of the `Alpha` trait in `bevy_color`.
- `Color::is_fully_transparent` is now part of the `Alpha` trait in
`bevy_color`
- `Color::r`, `Color::set_r`, `Color::with_r` and the equivalents for
`g`, `b` `h`, `s` and `l` have been removed due to causing silent
relatively expensive conversions. Convert your `Color` into the desired
color space, perform your operations there, and then convert it back
into a polymorphic `Color` enum.
- `Color::hex` is now `Srgba::hex`. Call `.into` or construct a
`Color::Srgba` variant manually to convert it.
- `WireframeMaterial`, `ExtractedUiNode`, `ExtractedDirectionalLight`,
`ExtractedPointLight`, `ExtractedSpotLight` and `ExtractedSprite` now
store a `LinearRgba`, rather than a polymorphic `Color`
- `Color::rgb_linear` and `Color::rgba_linear` are now
`Color::linear_rgb` and `Color::linear_rgba`
- The various CSS color constants are no longer stored directly on
`Color`. Instead, they're defined in the `Srgba` color space, and
accessed via `bevy::color::palettes::css`. Call `.into()` on them to
convert them into a `Color` for quick debugging use, and consider using
the much prettier `tailwind` palette for prototyping.
- The `LIME_GREEN` color has been renamed to `LIMEGREEN` to comply with
the standard naming.
- Vector field arithmetic operations on `Color` (add, subtract, multiply
and divide by a f32) have been removed. Instead, convert your colors
into `LinearRgba` space, and perform your operations explicitly there.
This is particularly relevant when working with emissive or HDR colors,
whose color channel values are routinely outside of the ordinary 0 to 1
range.
- `Color::as_linear_rgba_f32` has been removed. Call
`LinearRgba::to_f32_array` instead, converting if needed.
- `Color::as_linear_rgba_u32` has been removed. Call
`LinearRgba::to_u32` instead, converting if needed.
- Several other color conversion methods to transform LCH or HSL colors
into float arrays or `Vec` types have been removed. Please reimplement
these externally or open a PR to re-add them if you found them
particularly useful.
- Various methods on `Color` such as `rgb` or `hsl` to convert the color
into a specific color space have been removed. Convert into
`LinearRgba`, then to the color space of your choice.
- Various implicitly-converting color value methods on `Color` such as
`r`, `g`, `b` or `h` have been removed. Please convert it into the color
space of your choice, then check these properties.
- `Color` no longer implements `AsBindGroup`. Store a `LinearRgba`
internally instead to avoid conversion costs.
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
Co-authored-by: Afonso Lage <lage.afonso@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
# Objective
Just some mild annoyances:
- The `Color::Oklaba`, `Color::Oklcha` and `oklaba::Oklaba` doc comments
were inconsistent with the others
- The crate-level docs didn't include `Oklch` in the list of
representations and misspelt it in a later paragraph
## Solution
- Fix 'em
# Objective
- Cull 2D text outside the view frustum.
- Part of #11081.
## Solution
- Compute AABBs for entities with a `Text2DBundle` to enable culling
them.
`text2d` example with AABB gizmos on the text entities:
https://github.com/bevyengine/bevy/assets/18357657/52ed3ddc-2274-4480-835b-a7cf23338931
---
## Changelog
### Added
- 2D text outside the view are now culled with the
`calculate_bounds_text2d` system adding the necessary AABBs.
# Objective
`bevy_tasks` provides utilities for parallel mapping over slices. It can
be useful to have a chunk index available in the iteration function to
know which part of the original slice is being processed.
## Solution
Adds an index argument to the parallel map functions in `bevy_tasks`.
---
## Changelog
### Changed
- `par_chunk_map`, `par_splat_map`, `par_chunk_map_mut`, and
`par_splat_map_mut` now provide a chunk index during iteration.
## Migration Guide
Functions passed as arguments to `par_chunk_map`, `par_splat_map`,
`par_chunk_map_mut`, and `par_splat_map_mut` must now take an additional
index argument.
# Objective
Split up from #12017, rename Bevy's direction types.
Currently, Bevy has the `Direction2d`, `Direction3d`, and `Direction3dA`
types, which provide a type-level guarantee that their contained vectors
remain normalized. They can be very useful for a lot of APIs for safety,
explicitness, and in some cases performance, as they can sometimes avoid
unnecessary normalizations.
However, many consider them to be inconvenient to use, and opt for
standard vector types like `Vec3` because of this. One reason is that
the direction type names are a bit long and can be annoying to write (of
course you can use autocomplete, but just typing `Vec3` is still nicer),
and in some intances, the extra characters can make formatting worse.
The naming is also inconsistent with Glam's shorter type names, and
results in names like `Direction3dA`, which (in my opinion) are
difficult to read and even a bit ugly.
This PR proposes renaming the types to `Dir2`, `Dir3`, and `Dir3A`.
These names are nice and easy to write, consistent with Glam, and work
well for variants like the SIMD aligned `Dir3A`. As a bonus, it can also
result in nicer formatting in a lot of cases, which can be seen from the
diff of this PR.
Some examples of what it looks like: (copied from #12017)
```rust
// Before
let ray_cast = RayCast2d::new(Vec2::ZERO, Direction2d::X, 5.0);
// After
let ray_cast = RayCast2d::new(Vec2::ZERO, Dir2::X, 5.0);
```
```rust
// Before (an example using Bevy XPBD)
let hit = spatial_query.cast_ray(
Vec3::ZERO,
Direction3d::X,
f32::MAX,
true,
SpatialQueryFilter::default(),
);
// After
let hit = spatial_query.cast_ray(
Vec3::ZERO,
Dir3::X,
f32::MAX,
true,
SpatialQueryFilter::default(),
);
```
```rust
// Before
self.circle(
Vec3::new(0.0, -2.0, 0.0),
Direction3d::Y,
5.0,
Color::TURQUOISE,
);
// After (formatting is collapsed in this case)
self.circle(Vec3::new(0.0, -2.0, 0.0), Dir3::Y, 5.0, Color::TURQUOISE);
```
## Solution
Rename `Direction2d`, `Direction3d`, and `Direction3dA` to `Dir2`,
`Dir3`, and `Dir3A`.
---
## Migration Guide
The `Direction2d` and `Direction3d` types have been renamed to `Dir2`
and `Dir3`.
## Additional Context
This has been brought up on the Discord a few times, and we had a small
[poll](https://discord.com/channels/691052431525675048/1203087353850364004/1212465038711984158)
on this. `Dir2`/`Dir3`/`Dir3A` was quite unanimously chosen as the best
option, but of course it was a very small poll and inconclusive, so
other opinions are certainly welcome too.
---------
Co-authored-by: IceSentry <c.giguere42@gmail.com>
# Objective
- Fixes#12170
## Solution
- Moved the existing `color_from_entity` internals into
`Hsla::sequence_dispersed` which generates a randomly distributed but
deterministic color sequence based.
- Replicated the method for `Lcha` and `Oklcha` as well.
## Examples
### Getting a few colours for a quick palette
```rust
let palette = Hsla::sequence_dispersed().take(5).collect::<Vec<_>>();
/*[
Hsla::hsl(0.0, 1., 0.5),
Hsla::hsl(222.49225, 1., 0.5),
Hsla::hsl(84.984474, 1., 0.5),
Hsla::hsl(307.4767, 1., 0.5),
Hsla::hsl(169.96895, 1., 0.5),
]*/
```
### Getting a colour from an `Entity`
```rust
let color = Oklcha::sequence_dispersed().nth(entity.index() as u32).unwrap();
```
## Notes
This was previously a private function exclusively for `Entity` types.
I've decided it should instead be public and operate on a `u32`
directly, since this function may have broader uses for debugging
purposes.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/11929
- make sysinfo plugin optional
## Solution
- added features to allow for conditional compilation
---
## Migration Guide
- For users who disable default features of bevy and wish to enable the
diagnostic plugin, add `sysinfo_plugin` to your bevy features list.
---------
Co-authored-by: ebola <dev@axiomatic>
Co-authored-by: François <mockersf@gmail.com>
# Objective
fix#12182
- extract (or default) target camera for ui material nodes in the same
way as for other material nodes
- render ui material nodes only to their specified target
# Objective
Improve the `bevy::math::cubic_splines` module by making it more
flexible and adding new curve types.
Closes#10220
## Solution
Added new spline types and improved existing
---
## Changelog
### Added
- `CubicNurbs` rational cubic curve generator, allows setting the knot
vector and weights associated with every point
- `LinearSpline` curve generator, allows generating a linearly
interpolated curve segment
- Ability to push additional cubic segments to `CubicCurve`
- `IntoIterator` and `Extend` implementations for `CubicCurve`
### Changed
- `Point` trait has been implemented for more types: `Quat` and `Vec4`.
- `CubicCurve::coefficients` was moved to `CubicSegment::coefficients`
because the function returns `CubicSegment`, so it seems logical to be
associated with `CubicSegment` instead. The method is still not public.
### Fixed
- `CubicBSpline::new` was referencing Cardinal spline instead of
B-Spline
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
Co-authored-by: Miles Silberling-Cook <nth.tensor@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
- #12165 recently added links to Bevy errors in error messages.
- The links were in the form of `See:
https://bevyengine.org/learn/errors/#b000N`
- B0004 does not have the colon separating `See` and the link, unlike
the rest of the error messages
## Solution
- Add a colon, for consistency :)
# Objective
- More reflection
## Solution
- More. Reflection.
(not sure what bevy's policy on `derive(Debug)` is given that reflection
already lets you accomplish something largely equivalent; maybe
`derive(Reflect)` should generate a `Debug` impl that goes through
`Reflect::debug` unless you opt out?)
# Objective
The `css` contains all of the `basic` colors. Rather than defining them
twice, we can re-export them.
Suggested by @viridia <3
## Solution
- Re-export basic color palette within the css color palette.
- Remove the duplicate colors
- Fix alphabetization of the basic color palette file while I'm here
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
- Complete compatibility with CSS Module 4
## Solution
- Added `Oklcha` which implements the Oklch color model.
- Updated `Color` and `LegacyColor` accordingly.
## Migration Guide
- Convert `Oklcha` to `Oklaba` using the provided `From` implementations
and then handle accordingly.
## Notes
This is the _last_ color space missing from the CSS Module 4 standard,
and is also the one I believe we should recommend users actually work
with for hand-crafting colours. It has all the uniformity benefits of
Oklab combined with the intuition chroma and hue provide (when compared
to a-axis and b-axis parameters).
# Objective
- Implement grid gizmos, suggestion of #9400
## Solution
- Added `gizmos.grid(...) ` and `gizmos.grid_2d(...)`
- The grids may be configured using `.outer_edges(...)` to specify
whether to draw the outer border/edges of the grid and `.skew(...)`to
specify the skew of the grid along the x or y directions.
---
## Changelog
- Added a `grid` module to `bevy_gizmos` containing `gizmos.grid(...) `
and `gizmos.grid_2d(...)` as well as assorted items.
- Updated the `2d_gizmos` and `3d_gizmos` examples to use grids.
## Additional
The 2D and 3D examples now look like this:
<img width="1440" alt="Screenshot 2024-02-20 at 15 09 40"
src="https://github.com/bevyengine/bevy/assets/62256001/ce04191e-d839-4faf-a6e3-49b6bb4b922b">
<img width="1440" alt="Screenshot 2024-02-20 at 15 10 07"
src="https://github.com/bevyengine/bevy/assets/62256001/317459ba-d452-42eb-ae95-7c84cdbd569b">
# Objective
As suggested in #12163 by @cart, we should add convenience constructors
to `bevy_color::Color` to match the existing API (easing migration pain)
and generally improve ergonomics.
## Solution
- Add `const fn Color::rgba(red, green, blue, alpha)` and friends, which
directly construct the appropriate variant.
- Add `const fn Color::rgb(red, green, blue)` and friends, which impute
and alpha value of 1.0.
- Add `const BLACK, WHITE, NONE` to `Color`. These are stored in
`LinearRgba` to reduce pointless conversion costs and inaccuracy.
- Changed the default `Color` from `Srgba::WHITE` to the new linear
equivalent for the same reason.
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
As we start to migrate to `bevy_color` in earnest (#12056), we should
make it visible to Bevy users, and usable in examples.
## Solution
1. Add a prelude to `bevy_color`: I've only excluded the rarely used
`ColorRange` type and the testing-focused color distance module. I
definitely think that some color spaces are less useful than others to
end users, but at the same time the types used there are very unlikely
to conflict with user-facing types.
2. Add `bevy_color` to `bevy_internal` as an optional crate.
3. Re-export `bevy_color`'s prelude as part of `bevy::prelude`.
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
- In #9623 I forgot to change the `FromWorld` requirement for
`ReflectResource`, fix that;
- Fix#12129
## Solution
- Use the same approach as in #9623 to try using `FromReflect` and
falling back to the `ReflectFromWorld` contained in the `TypeRegistry`
provided
- Just reflect `Resource` on `State<S>` since now that's possible
without introducing new bounds.
---
## Changelog
- `ReflectResource`'s `FromType<T>` implementation no longer requires
`T: FromWorld`, but instead now requires `FromReflect`.
- `ReflectResource::insert`, `ReflectResource::apply_or_insert` and
`ReflectResource::copy` now take an extra `&TypeRegistry` parameter.
## Migration Guide
- Users of `#[reflect(Resource)]` will need to also implement/derive
`FromReflect` (should already be the default).
- Users of `#[reflect(Resource)]` may now want to also add `FromWorld`
to the list of reflected traits in case their `FromReflect`
implementation may fail.
- Users of `ReflectResource` will now need to pass a `&TypeRegistry` to
its `insert`, `apply_or_insert` and `copy` methods.
# Objective
`downcast-rs` is not used within bevy_ecs. This is probably a remnant
from before Schedule v3 landed, since stages needed the downcasting.
## Solution
Remove it.
Shows relationships between color spaces and explains what files should
contain which conversions.
# Objective
- Provide documentation for maintainers and users on how color space
conversion is implemented.
## Solution
- Created a mermaid diagram documenting the relationships between
various color spaces. This diagram also includes links to defining
articles, and edges include links to conversion formulae.
- Added a `conversion.md` document which is included in the
documentation of each of the color spaces. This ensures it is readily
visible in all relevant contexts.
## Notes
The diagram is in the Mermaid (`.mmd`) format, and must be converted
into an SVG file (or other image format) prior to use in Rust
documentation. I've included a link to
[mermaid.live](https://mermaid.live) as an option for doing such
conversion in an appropriate README.
Below is a screenshot of the documentation added.
![Capture](https://github.com/bevyengine/bevy/assets/2217286/370a65f2-6dd4-4af7-a99b-3763832d1b8a)
# Objective
`FromWorld` is often used to group loading and creation of assets for
resources.
With this setup, users often end up repetitively calling
`.resource::<AssetServer>` and `.resource_mut::<Assets<T>>`, and may
have difficulties handling lifetimes of the returned references.
## Solution
Add extension methods to `World` to add and load assets, through a new
extension trait defined in `bevy_asset`.
### Other considerations
* This might be a bit too "magic", as it makes implicit the resource
access.
* We could also implement `DirectAssetAccessExt` on `App`, but it didn't
feel necessary, as `FromWorld` is the principal use-case here.
---
## Changelog
* Add the `DirectAssetAccessExt` trait, which adds the `add_asset`,
`load_asset` and `load_asset_with_settings` method to the `World` type.
# Objective
This PR arose as part of the migration process for `bevy_color`: see
#12056.
While examining how `bevy_gizmos` stores color types internally, I found
that rather than storing a `Color` internally, it actually stores a
`[f32;4]` for a linear RGB, type aliased to a `ColorItem`.
While we don't *have* to clean this up to complete the migration, now
that we have explicit strong typing for linear color types we should use
them rather than replicating this idea throughout the codebase.
## Solution
- Added `LinearRgba::NAN`, for when you want to do cursed rendering
things.
- Replaced the internal color representation in `bevy_gizmo`: this was
`ColorItem`, but is now `LinearRgba`.
- `LinearRgba` is now `Pod`, enabling us to use the same fast `bytemuck`
bit twiddling tricks that we were using before. This requires:
1. Forcing `LinearRgba` to be `repr(C)`
2. Implementing `Zeroable`, and unsafe trait which defines what the
struct looks like when all values are zero.
3. Implementing `Pod`, a marker trait with stringent safety requirements
that is required for "plain old data".
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
- LinearRgba is the color type intended for shaders but using it for
shaders is currently not easy because it doesn't implement ShaderType
## Solution
- add encase as a dependency and impl the required traits.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
# Objective
- Improve compatibility with CSS Module 4
- Simplify `Lcha` conversion functions
## Solution
- Added `Laba` which implements the Lab color model.
- Updated `Color` and `LegacyColor` accordingly.
## Migration Guide
- Convert `Laba` to either `Xyza` or `Lcha` using the provided `From`
implementations and then handle accordingly.
## Notes
The Lab color space is a required stepping stone when converting between
XYZ and Lch, therefore we already use the Lab color model, just in an
nameless fashion prone to errors.
This PR also includes a slightly broader refactor of the `From`
implementations between the various colour spaces to better reflect the
graph of definitions. My goal was to keep domain specific knowledge of
each colour space contained to their respective files (e.g., the
`From<Oklaba> for LinearRgba` definition was in `linear_rgba.rs` when it
probably belongs in `oklaba.rs`, since Linear sRGB is a fundamental
space and Oklab is defined in its relation to it)
# Objective
The `AssetIndex` cannot be carried across boundaries that do not allow
explicit rust types.
For context, I ran into this issue while trying to implent an
improvement for bevy_egui which leverages the not-so-new custom loader
API. Passing through a handle directly isn't possible, but instead it
requires stringified URI s. I had to work around the lack of this API s
existance using reflection, which is rather dirty.
## Solution
- Add `to_bits` and `from_bits` functions to `AssetIndex` to allow
moving this type through such boundaries.
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
- Make these types usable in reflection-based workflows.
## Solution
- The usual. Also reflect `Default` and `Component` behaviors so that
the types can be constructed, inserted, and removed.
# Objective
Added reflect support for `std::HashSet`, `BTreeSet` and `BTreeMap`.
The set support is limited to `reflect_value` since that's the level of
support prior art `bevy_util::HashSet` got.
## Changelog
Dropped `Hash` Requirement on `MapInfo` since it's not needed on
`BTreeMap`s.
# Objective
Memory usage optimisation
## Solution
`HashMap` and `HashSet`'s keys are immutable. So using mutable types
like `String`, `Vec<T>`, or `PathBuf` as a key is a waste of memory:
they have an extra `usize` for their capacity and may have spare
capacity.
This PR replaces these types by their immutable equivalents `Box<str>`,
`Box<[T]>`, and `Box<Path>`.
For more context, I recommend watching the [Use Arc Instead of
Vec](https://www.youtube.com/watch?v=A4cKi7PTJSs) video.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Avoid misspellings throughout the codebase by using
[`typos`](https://github.com/crate-ci/typos) in CI
Inspired by https://github.com/gfx-rs/wgpu/pull/5191
Typos is a minimal code speller written in rust that finds and corrects
spelling mistakes among source code.
- Fast enough to run on monorepos
- Low false positives so you can run on PRs
## Solution
- Use
[typos-action](https://github.com/marketplace/actions/typos-action) in
CI
- Add how to use typos in the Contribution Guide
---------
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
- Fixes#12001.
- Note this PR doesn't change any feature flags, however flaky the issue
revealed they are.
## Solution
- Use `FromReflect` to convert proxy types to concrete ones in
`ReflectSerialize::get_serializable`.
- Use `get_represented_type_info() -> type_id()` to get the correct type
id to interact with the registry in
`bevy_reflect::serde::ser::get_serializable`.
---
## Changelog
- Registering `ReflectSerialize` now imposes additional `FromReflect`
and `TypePath` bounds.
## Migration Guide
- If `ReflectSerialize` is registered on a type, but `TypePath` or
`FromReflect` implementations are omitted (perhaps by
`#[reflect(type_path = false)` or `#[reflect(from_reflect = false)]`),
the traits must now be implemented.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
Fix#11845.
## Solution
Remove the `UpdateAssets` and `AssetEvents` schedules. Moved the
`UpdateAssets` systems to `PreUpdate`, and `AssetEvents` systems into
`First`. The former is meant to run before any of the event flushes.
## Future Work
It'd be ideal if we could manually flush the events for assets to avoid
needing two, sort of redundant, systems. This should at least let them
potentially run in parallel with all of the systems in the schedules
they were moved to.
---
## Changelog
Removed: `UpdateAssets` schedule from the main schedule. All systems
have been moved to `PreUpdate`.
Removed: `AssetEvents` schedule from the main schedule. All systems have
been move to `First` with the same system sets.
## Migration Guide
TODO
# Objective
- Partially addresses https://github.com/bevyengine/bevy/issues/11470
(I'd like to add Spatiotemporal Blue Noise in the future, but that's a
bit more controversial).
- Fix cluster_debug_visualization which has not compiled for a while
---
## Changelog
- Added random white noise shader functions to `bevy_pbr::utils`
## Migration Guide
- The `bevy_pbr::utils::random1D` shader function has been replaced by
the similar `bevy_pbr::utils::rand_f`.
# Objective
- During rendering of different gizmo groups, the ordering is random
between executions
## Solution
- Make the ordering stable
- It's using a `TypeIdMap`, its iteration order depends on the insertion
order. so insert when adding a group instead of when adding a gizmo
- Also changed `extract_gizmo_data` to not be group dependent. there
will be only one of those systems, no matter the number of gizmo groups
added
---------
Co-authored-by: pablo-lua <126117294+pablo-lua@users.noreply.github.com>
# Objective
`CameraProjectionPlugin<T>`'s bounds are `T: CameraProjection`. But the
bounds for `CameraProjectionPlugin` implementing `Plugin` are `T:
CameraProjection + Component + GetTypeRegistration`. This means that if
`T` is valid for `CameraProjectionPlugin`'s bounds, but not the plugin
implementation's bounds, then `CameraProjectionPlugin` would not
implement `Plugin`. Which is weird because you'd expect a struct with
`Plugin` in the name to implement `Plugin`.
## Solution
Make `CameraProjectionPlugin<T>`'s bounds `T: CameraProjection +
Component + GetTypeRegistration`. I also rearranged some of the code.
---
## Changelog
- Changed `CameraProjectionPlugin<T>`'s bounds to `T: CameraProjection +
Component + GetTypeRegistration`
## Migration Guide
`CameraProjectionPlugin<T>`'s trait bounds now require `T` to implement
`CameraProjection`, `Component`, and `GetTypeRegistration`. This
shouldn't affect most existing code as `CameraProjectionPlugin<T>` never
implemented `Plugin` unless those bounds were met.
# Objective
Split up from #12017, add an aligned version of `Direction3d` for SIMD,
and move direction types out of `primitives`.
## Solution
Add `Direction3dA` and move direction types into a new `direction`
module.
---
## Migration Guide
The `Direction2d`, `Direction3d`, and `InvalidDirectionError` types have
been moved out of `bevy::math::primitives`.
Before:
```rust
use bevy::math::primitives::Direction3d;
```
After:
```rust
use bevy::math::Direction3d;
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Improve compatibility with CSS Module 4
- Simplify `Hsla` conversion functions
## Solution
- Added `Hsva` which implements the HSV color model.
- Added `Hwba` which implements the HWB color model.
- Updated `Color` and `LegacyColor` accordingly.
## Migration Guide
- Convert `Hsva` / `Hwba` to either `Hsla` or `Srgba` using the provided
`From` implementations and then handle accordingly.
## Notes
While the HSL color space is older than HWB, the formulation for HWB is
more directly related to RGB. Likewise, HSV is more closely related to
HWB than HSL. This makes the conversion of HSL to/from RGB more
naturally represented as the compound operation HSL <-> HSV <-> HWB <->
RGB. All `From` implementations for HSL, HSV, and HWB have been designed
to take the shortest path between itself and the target space.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- We should move towards a consistent use of the new `bevy_color` crate.
- As discussed in #12089, splitting this work up into small pieces makes
it easier to review.
## Solution
- Port all uses of `LegacyColor` in the `bevy_core_pipeline` to
`LinearRgba`
- `LinearRgba` is the correct type to use for internal rendering types
- Added `LinearRgba::BLACK` and `WHITE` (used during migration)
- Add `LinearRgba::grey` to more easily construct balanced grey colors
(used during migration)
- Add a conversion from `LinearRgba` to `wgpu::Color`. The converse was
not done at this time, as this is typically a user error.
I did not change the field type of the clear color on the cameras: as
this is user-facing, this should be done in concert with the other
configurable fields.
## Migration Guide
`ColorAttachment` now stores a `LinearRgba` color, rather than a Bevy
0.13 `Color`.
`set_blend_constant` now takes a `LinearRgba` argument, rather than a
Bevy 0.13 `Color`.
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
Right now when using egui, systems are inserted without any identifier
and to the root. I'd like to name those systems and insert them as
children to a root entity. This helps to keep the editor organized.
## Solution
- Although the `SystemId` is documented as an opaque type, examples
depicted above benefit from tear down of the abstraction.
---
## Changelog
### Added
- Implemented `From<SystemId>` for `Entity`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- followup to https://github.com/bevyengine/bevy/pull/11671
- I forgot to change the alpha masked phases.
## Solution
- Change the sorting for alpha mask phases to sort by pipeline+mesh
instead of distance, for much better batching for alpha masked
materials.
I also fixed some docs that I missed in the previous PR.
---
## Changelog
- Alpha masked materials are now sorted by pipeline and mesh.
Add Archetype::component_count utility method
# Objective
I wanted a method to count components on an archetype without iterating
over them.
## Solution
Added `Archetype::component_count`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
The multi-threaded executor currently runs in a dedicated task on a
single thread. When a system finishes running, it needs to notify that
task and wait for the thread to be available and running before the
executor can process the completion.
See #8304
## Solution
Run the multi-threaded executor at the end of each system task. This
allows it to run immediately instead of needing to wait for the main
thread to wake up. Move the mutable executor state into a separate
struct and wrap it in a mutex so it can be shared among the worker
threads.
While this should be faster in theory, I don't actually know how to
measure the performance impact myself.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: Mike <mike.hsu@gmail.com>
# Objective
Partially address #888. Gilrs is initialized on a separate thread, and
thus conditionally implements `Send`, and all platforms other than Wasm.
This means the `NonSend` resource constraint is likely too conservative.
## Solution
Relax the requirement, and conditionally derive Resource on a wrapper
around it, using `SyncCell` to satisfy the `Sync` requirement on it.
# Objective
- Fixes#12081
## Solution
Passing the `Affine2` as a neatly packed `mat3x2` breaks WebGL with
`drawElementsInstanced: Buffer for uniform block is smaller than
UNIFORM_BLOCK_DATA_SIZE.`
I fixed this by using a `mat3x3` instead.
Alternative solutions that come to mind:
- Pass in a `mat3x2` on non-webgl targets and a `mat3x3` otherwise. I
guess I could use `#ifdef SIXTEEN_BYTE_ALIGNMENT` for this, but it
doesn't seem quite right? This would be more efficient, but decrease
code quality.
- Do something about `UNIFORM_BLOCK_DATA_SIZE`. I don't know how, so I'd
need some guidance here.
@superdump let me know if you'd like me to implement other variants.
Otherwise, I vote for merging this as a quick fix for `main` and then
improving the packing in subsequent PRs :)
## Additional notes
Ideally we should merge this before @JMS55 rebases #10164 so that they
don't have to rebase everything a second time.
# Objective
- Fixes#12068
## Solution
- Split `bevy_render::color::colorspace` across the various space
implementations in `bevy_color` as appropriate.
- Moved `From` implementations involving
`bevy_render::color::LegacyColor` into `bevy_render::color`
## Migration Guide
###
`bevy_render::color::colorspace::SrgbColorSpace::<f32>::linear_to_nonlinear_srgb`
Use `bevy_color::color::gamma_function_inverse`
###
`bevy_render::color::colorspace::SrgbColorSpace::<f32>::nonlinear_to_linear_srgb`
Use `bevy_color::color::gamma_function`
###
`bevy_render::color::colorspace::SrgbColorSpace::<u8>::linear_to_nonlinear_srgb`
Modify the `u8` value to instead be an `f32` (`|x| x as f32 / 255.`),
use `bevy_color::color::gamma_function_inverse`, and back again.
###
`bevy_render::color::colorspace::SrgbColorSpace::<u8>::nonlinear_to_linear_srgb`
Modify the `u8` value to instead be an `f32` (`|x| x as f32 / 255.`),
use `bevy_color::color::gamma_function`, and back again.
###
`bevy_render::color::colorspace::HslRepresentation::hsl_to_nonlinear_srgb`
Use `Hsla`'s implementation of `Into<Srgba>`
###
`bevy_render::color::colorspace::HslRepresentation::nonlinear_srgb_to_hsl`
Use `Srgba`'s implementation of `Into<Hsla>`
###
`bevy_render::color::colorspace::LchRepresentation::lch_to_nonlinear_srgb`
Use `Lcha`'s implementation of `Into<Srgba>`
###
`bevy_render::color::colorspace::LchRepresentation::nonlinear_srgb_to_lch`
Use `Srgba`'s implementation of `Into<Lcha>`
# Objective
- The bloom effect is currently somewhat costly (in terms of GPU time
used), due to using fragment shaders for down- and upscaling (compute
shaders generally perform better for such tasks).
- Additionally, one might have a `BloomSettings` on a camera whose
`intensity` is only occasionally set to a non-zero value (eg. in outside
areas or areas with bright lighting). Currently, the cost of the bloom
shader is always incurred as long as the `BloomSettings` exists.
## Solution
- Bail out of the bloom render node when `intensity == 0.0`, making the
effect free as long as it is turned all the way down.
# Objective
- Fixes#751
## Solution
- Added `PluginGroupBuilder::add_group`, which accepts an owned `impl
PluginGroup` and adds those plugins to self, following
`PluginGroupBuilder::add`'s replacement rules.
- Split `PluginGroupBuilder::upsert_plugin_state` into two functions,
one of the same name, and
`PluginGroupBuilder::upsert_plugin_entry_state` which takes a
`PluginEntry` and `TypeId` directly. This allows for shared behaviour
between `add` and `add_group`.
- Added 2 unit tests documenting the replacement behaviour in
`PluginGroupBuilder::add_group`.
Co-authored-by: François <mockersf@gmail.com>
# Objective
- A tiny nit I noticed; I think the type of these function is
`EntityCommand`, not `Command`
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
# Objective
#7348 added `bevy_utils::Parallel` and replaced the usage of the
`ThreadLocal<Cell<Vec<...>>>` in `check_visibility`, but we were also
using it in `extract_meshes`.
## Solution
Refactor the system to use `Parallel` instead.
# Objective
The physical width and height (pixels) of an image is always integers,
but for `GpuImage` bevy currently stores them as `Vec2` (`f32`).
Switching to `UVec2` makes this more consistent with the [underlying
texture data](https://docs.rs/wgpu/latest/wgpu/struct.Extent3d.html).
I'm not sure if this is worth the change in the surface level API. If
not, feel free to close this PR.
## Solution
- Replace uses of `Vec2` with `UVec2` when referring to texture
dimensions.
- Use integer types for the texture atlas dimensions and sections.
[`Sprite::rect`](a81a2d1da3/crates/bevy_sprite/src/sprite.rs (L29))
remains unchanged, so manually specifying a sub-pixel region of an image
is still possible.
---
## Changelog
- `GpuImage` now stores its size as `UVec2` instead of `Vec2`.
- Texture atlases store their size and sections as `UVec2` and `URect`
respectively.
- `UiImageSize` stores its size as `UVec2`.
## Migration Guide
- Change floating point types (`Vec2`, `Rect`) to their respective
unsigned integer versions (`UVec2`, `URect`) when using `GpuImage`,
`TextureAtlasLayout`, `TextureAtlasBuilder`,
`DynamicAtlasTextureBuilder` or `FontAtlas`.
# Objective
- I hit an issue using the `file_watcher` feature to hot reload assets
for my game. The change in this PR allows me to now hot reload assets.
- The issue stemmed from my project being a multi crate workspace
project structured like so:
```
└── my_game
├── my_game_core
│ ├── src
│ └── assets
├── my_game_editor
│ └── src/main.rs
└── my_game
└── src/main.rs
```
- `my_game_core` is a crate that holds all my game logic and assets
- `my_game` is the crate that creates the binary for my game (depends on
the game logic and assets in `my_game_core`)
- `my_game_editor` is an editor tool for my game (it also depends on the
game logic and assets in `my_game_core`)
Whilst running `my_game` and `my_game_editor` from cargo during
development I would use `AssetPlugin` like so:
```rust
default_plugins.set(AssetPlugin {
watch_for_changes_override: Some(true),
file_path: "../my_game_core/assets".to_string(),
..Default::default()
})
```
This works fine; bevy picks up the assets. However on saving an asset I
would get the following panic from `file_watcher`. It wouldn't kill the
app, but I wouldn't see the asset hot reload:
```
thread 'notify-rs debouncer loop' panicked at /Users/ian/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_asset-0.12.1/src/io/file/file_watcher.rs:48:58:
called `Result::unwrap()` on an `Err` value: StripPrefixError(())
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
## Solution
- The solution is to collapse dot segments in the root asset path
`FileWatcher` is using
- There was already bevy code to do this in `AssetPath`, so I extracted
that code so it could be reused in `FileWatcher`
# Objective
- Simplify `Srgba` hex string parsing using std hex parsing functions
and removing loops in favor of bitwise ops.
This is a follow-up of the `bevy_color` upstream PR review:
https://github.com/bevyengine/bevy/pull/12013#discussion_r1497408114
## Solution
- Reworked `Srgba::hex` to use `from_str_radix` and some bitwise ops;
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
- Sometimes, it is useful to get a `Handle<T>` from an `AssetId<T>`. For
example, when iterating `Assets` to find a specific asset. So much so
that it's possible to do so with `AssetServer::get_id_handle`
- However, `AssetServer::get_id_handle` doesn't work with assets
directly added to `Assets` using `Assets::add`.
- Fixes#12087
## Solution
- Add `Assets::get_strong_handle` to convert an `AssetId` into an
`Handle`
- Document `AssetServer::get_id_handle` to explain its limitation and
point to `get_strong_handle`.
- Add a test for `get_strong_handle`
- Add a `duplicate_handles` field to `Assets` to avoid dropping assets
with a live handle generated by `get_strong_handle` (more reference
counting yay…)
- Fix typos in `Assets` docs
---
## Changelog
- Add `Assets::get_strong_handle` to convert an `AssetId` into an
`Handle`
# Objective
- Add the new `-Zcheck-cfg` checks to catch more warnings
- Fixes#12091
## Solution
- Create a new `cfg-check` to the CI that runs `cargo check -Zcheck-cfg
--workspace` using cargo nightly (and fails if there are warnings)
- Fix all warnings generated by the new check
---
## Changelog
- Remove all redundant imports
- Fix cfg wasm32 targets
- Add 3 dead code exceptions (should StandardColor be unused?)
- Convert ios_simulator to a feature (I'm not sure if this is the right
way to do it, but the check complained before)
## Migration Guide
No breaking changes
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Make `GizmoConfigStore` play well with reflection-based workflows like
editors.
## Solution
- `#[derive(Reflect)]` and call `.register_type()`.
# Objective
The migration process for `bevy_color` (#12013) will be fairly involved:
there will be hundreds of affected files, and a large number of APIs.
## Solution
To allow us to proceed granularly, we're going to keep both
`bevy_color::Color` (new) and `bevy_render::Color` (old) around until
the migration is complete.
However, simply doing this directly is confusing! They're both called
`Color`, making it very hard to tell when a portion of the code has been
ported.
As discussed in #12056, by renaming the old `Color` type, we can make it
easier to gradually migrate over, one API at a time.
## Migration Guide
THIS MIGRATION GUIDE INTENTIONALLY LEFT BLANK.
This change should not be shipped to end users: delete this section in
the final migration guide!
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
Add XYZ colour space. This will be most useful as a conversion step when
working with other (more common) colour spaces. See
[Wikipedia](https://en.wikipedia.org/wiki/CIE_1931_color_space) for
details on this space.
## Solution
- Added `Xyza` to `Color` and as its own type.
---
## Changelog
- Added `Xyza` type.
- Added `Color::Xyza` variant.
## Migration Guide
- `Color` enum now has an additional member, `Xyza`. Convert it to any
other type to handle this case in match statements.
# Objective
- Fix a wrongly named type
## Solution
- Rename it properly
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
Fixes#11821.
## Solution
* Run `System::apply_deferred` in `System::run` after executing the
system.
* Switch to using `System::run_unsafe` in `SingleThreadedExecutor` to
preserve the current behavior.
* Remove the `System::apply_deferred` in `SimpleExecutor` as it's now
redundant.
* Remove the `System::apply_deferred` when running one-shot systems, as
it's now redundant.
---
## Changelog
Changed: `System::run` will now immediately apply deferred system params
after running the system.
## Migration Guide
`System::run` will now always run `System::apply_deferred` immediately
after running the system now. If you were running systems and then
applying their deferred buffers at a later point in time, you can
eliminate the latter.
```rust
// in 0.13
system.run(world);
// .. sometime later ...
system.apply_deferred(world);
// in 0.14
system.run(world);
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Since #9822, `SimpleExecutor` panics when an automatic sync point is
inserted:
```rust
let mut sched = Schedule::default();
sched.set_executor_kind(ExecutorKind::Simple);
sched.add_systems((|_: Commands| (), || ()).chain());
sched.run(&mut World::new());
```
```
System's param_state was not found. Did you forget to initialize this system before running it?
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_ecs::schedule::executor::apply_deferred`!
```
## Solution
Don't try to run the `apply_deferred` system.
# Objective
Fixes Skyboxes on WebGL, which broke in Bevy 0.13 due to the addition of
the `brightness` uniform, when previously the skybox pipeline only had
view and global uniforms.
```ignore
panicked at ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.1/src/backend/wgpu_core.rs:3009:5:
wgpu error: Validation Error
Caused by:
In Device::create_render_pipeline
note: label = `skybox_pipeline`
In the provided shader, the type given for group 0 binding 3 has a size of 4. As the device does not support `DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED`, the type must have a size that is a multiple of 16 bytes.
```
It would be nice if this could be backported to a 0.13.1 patch as well
if possible. I'm needing to rely on my own fork for now.
## Solution
Similar to the Globals uniform solution here:
d31de3f139/crates/bevy_render/src/globals.rs (L59-L60)
I've added 3 conditional fields to `SkyboxUniforms`.
# Objective
`Scope::spawn`, `Scope::spawn_on_external`, and `Scope::spawn_on_scope`
have different signatures depending on whether the `multi-threaded`
feature is enabled. The single-threaded version has a stricter signature
that prevents sending the `Scope` itself to spawned tasks.
## Solution
Changed the lifetime constraints in the single-threaded signatures from
`'env` to `'scope` to match the multi-threaded version.
This was split off from #11906.
# Objective
- Assist Bevy contributors in the creation of `bevy_color` spaces by
ensuring consistent API implementation.
## Solution
Created a `pub(crate)` trait `StandardColor` which has all the
requirements for a typical color space (e.g, `Srgba`, `Color`, etc.).
---
## Changelog
- Implemented traits missing from certain color spaces.
## Migration Guide
_No migration required_
# Objective
Improve code quality and prevent bugs.
## Solution
I removed the unnecessary wildcards from `<LogPlugin as Plugin>::build`.
I also changed the warnings that would occur if the subscriber/logger
was already set into errors.
# Objective
This provides a new set of color types and operations for Bevy.
Fixes: #10986#1402
## Solution
The new crate provides a set of distinct types for various useful color
spaces, along with utilities for manipulating and converting colors.
This is not a breaking change, as no Bevy APIs are modified (yet).
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
When dealing with custom asset sources it can be a bit tricky to get
asset roots combined with relative paths correct.
It's even harder when it isn't mentioned which path was problematic.
## Solution
Mention which path failed for the file watcher.
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
- Fixes#11977 - user defined shaders don't work in wasm
- After investigation, it won't work if the shader is not yet available
when compiling the pipeline on all platforms, for example if you load
many assets
## Solution
- Set the pipeline state to queued when it errs waiting for the shader
so that it's retried
# Objective
- Some properties of public types are private but sometimes it's useful
to be able to set those
## Solution
- Make more stuff pub
---
## Changelog
- `MaterialBindGroupId` internal id is now pub and added a new()
constructor
- `ExtractedPointLight` and `ExtractedDirectionalLight` properties are
now all pub
---------
Co-authored-by: James Liu <contact@jamessliu.com>
This PR closes#11978
# Objective
Fix rendering on iOS Simulators.
iOS Simulator doesn't support the capability CUBE_ARRAY_TEXTURES, since
0.13 this started to make iOS Simulator not render anything with the
following message being outputted:
```
2024-02-19T14:59:34.896266Z ERROR bevy_render::render_resource::pipeline_cache: failed to create shader module: Validation Error
Caused by:
In Device::create_shader_module
Shader validation error:
Type [40] '' is invalid
Capability Capabilities(CUBE_ARRAY_TEXTURES) is required
```
## Solution
- Split up NO_ARRAY_TEXTURES_SUPPORT into both NO_ARRAY_TEXTURES_SUPPORT
and NO_CUBE_ARRAY_TEXTURES_SUPPORT and correctly apply
NO_ARRAY_TEXTURES_SUPPORT for iOS Simulator using the cfg flag
introduced in #10178.
---
## Changelog
### Fixed
- Rendering on iOS Simulator due to missing CUBE_ARRAY_TEXTURES support.
---------
Co-authored-by: Sam Pettersson <sam.pettersson@geoguessr.com>
# Objective
- Taplo in CI is not running. The link used to download taplo doesn't
work anymore.
## Solution
- Compile taplo directly with cargo
- Improve docs a little
- Run taplo
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- The `touch_screen_input_system` system runs on every tick.
- It unconditionally calls `update(&mut self)`, on the `Touches`
resource.
- This blocks the usage of a `resource_changed::<Touches>` run
condition.
## Solution
- Remove `update(&mut self)` as it's only used in this one system, and
in-lining the method implementation removes an indirection to an
ambiguously named method.
- Add conditional checks around the calls to clearing the internal maps.
---------
Signed-off-by: Jean Mertz <git@jeanmertz.com>
# Objective
- Some members of `bevy_dynamic_plugin` are not documented.
- Part of #3492.
## Solution
- Add documentation to members missing it in `bevy_dynamic_plugin`.
- Update existing documentation for clarity and formatting.
---
## Changelog
- Completely document `bevy_dynamic_plugin`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Part of #11590
- Fix `unsafe_op_in_unsafe_fn` for trivial cases in bevy_ecs
## Solution
Fix `unsafe_op_in_unsafe_fn` in bevy_ecs for trivial cases, i.e., add an
`unsafe` block when the safety comment already exists or add a comment
like "The invariants are uphold by the caller".
---------
Co-authored-by: James Liu <contact@jamessliu.com>
## Objective
Always have `some_system.into_system().type_id() ==
some_system.into_system_set().system_type().unwrap()`.
System sets have a `fn system_type() -> Option<TypeId>` that is
implemented by `SystemTypeSet` to returning the TypeId of the system's
function type. This was implemented in
https://github.com/bevyengine/bevy/pull/7715 and is used in
`bevy_mod_debugdump` to handle `.after(function)` constraints.
Back then, `System::type_id` always also returned the type id of the
function item, not of `FunctionSystem<M, F>`.
https://github.com/bevyengine/bevy/pull/11728 changes the behaviour of
`System::type_id` so that it returns the id of the
`FunctionSystem`/`ExclusiveFunctionSystem` wrapper, but it did not
change `SystemTypeSet::system_type`, so doing the lookup breaks in
`bevy_mod_debugdump`.
## Solution
Change `IntoSystemSet` for functions to return a
`SystemTypeSet<FunctionSystem>` /
`SystemTypeSet<ExclusiveFunctionSystem>` instead of `SystemTypeSet<F>`.
# Objective
- Globals are supposed to be available in vertex shader but that was
mistakenly removed in 0.13
## Solution
- Configure the visibility of the globals correctly
Fixes https://github.com/bevyengine/bevy/issues/12015
# Objective
- The file asset source currently creates the `imported_assets/Default`
directory with relative path, which leads to wrongly created directories
when the executable is run with a working directory different from the
project root.
## Solution
- Use the full path instead.
# Objective
This PR adds some missing mime types to the
`ImageFormat::from_mime_type` method. As discussed [in this comment on
the Discord Bevy
community](https://discord.com/channels/691052431525675048/691052431974465548/1209904290227949729):
> It's strange that Bevy supports parsing `ImageFormat::WebP` from a
.webp str extension in the method below, but not from the mime type.
>
> In comparison, the image crate does parse it:
https://github.com/image-rs/image/blob/master/src/image.rs#L170
# Solution
For each of the missing mime types, I added them based on the
`ImageFormat::from_mime_type` of the image crate:
https://github.com/image-rs/image/blob/master/src/image.rs#L209, except
for `ImageFormat::Basis` and `ImageFormat::Ktx2` which are not present
in the image crate, and I ignore if they have a mime type or not*
\* apparently nowadays there is an official mime type: `image/ktx2`
https://www.iana.org/assignments/media-types/image/ktx2
Any feedback is welcome! I thought of refactoring a bit more and
delegating the mime type parsing to the image crate (and possibly the
same for extensions), let me know if that's desired 🙂
Fixes#12016.
Bump version after release
This PR has been auto-generated
Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: François <mockersf@gmail.com>
# Objective
- Closes#11985
## Solution
- alpha.rs has been moved from bevy_pbr into bevy_render; bevy_pbr and
bevy_gltf now access `AlphaMode` through bevy_render.
---
## Migration Guide
In the present implementation, external consumers of `AlphaMode` will
have to access it through bevy_render rather than through bevy_pbr,
changing their import from `bevy_pbr::AlphaMode` to
`bevy_render::alpha::AlphaMode` (or the corresponding glob import from
`bevy_pbr::prelude::*` to `bevy_render::prelude::*`).
## Uncertainties
Some remaining things from this that I am uncertain about:
- Here, the `app.register_type<AlphaMode>()` call has been moved from
`PbrPlugin` to `RenderPlugin`; I'm not sure if this is quite right, and
I was unable to find any direct relationship between `PbrPlugin` and
`RenderPlugin`.
- `AlphaMode` was placed in the prelude of bevy_render. I'm not certain
that this is actually appropriate.
- bevy_pbr does not re-export `AlphaMode`, which makes this a breaking
change for external consumers.
Any of these things could be easily changed; I'm just not confident that
I necessarily adopted the right approach in these (known) ways since
this codebase and ecosystem is quite new to me.
Adopted #8266, so copy-pasting the description from there:
# Objective
Support the KHR_texture_transform extension for the glTF loader.
- Fixes#6335
- Fixes#11869
- Implements part of #11350
- Implements the GLTF part of #399
## Solution
As is, this only supports a single transform. Looking at Godot's source,
they support one transform with an optional second one for detail, AO,
and emission. glTF specifies one per texture. The public domain
materials I looked at seem to share the same transform. So maybe having
just one is acceptable for now. I tried to include a warning if multiple
different transforms exist for the same material.
Note the gltf crate doesn't expose the texture transform for the normal
and occlusion textures, which it should, so I just ignored those for
now. (note by @janhohenheim: this is still the case)
Via `cargo run --release --example scene_viewer
~/src/clone/glTF-Sample-Models/2.0/TextureTransformTest/glTF/TextureTransformTest.gltf`:
![texture_transform](https://user-images.githubusercontent.com/283864/228938298-aa2ef524-555b-411d-9637-fd0dac226fb0.png)
## Changelog
Support for the
[KHR_texture_transform](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform)
extension added. Texture UVs that were scaled, rotated, or offset in a
GLTF are now properly handled.
---------
Co-authored-by: Al McElrath <hello@yrns.org>
Co-authored-by: Kanabenki <lucien.menassol@gmail.com>
# Objective
If multiple cameras render to the same target with MSAA enabled, only
the first and the last camera output will appear in the final output*.
This is because each camera maintains a separate flag to track the
active main texture. The first camera renders to texture A and all
subsequent cameras first write-back from A and then render into texture
B. Hence, camera 3 onwards will overwrite the work of the previous
camera.
\* This would manifest slightly differently if there were other calls to
post_process_write() in a more complex setup.
The is a functional regression from Bevy 0.12.
## Solution
The flag which tracks the active main texture should be shared between
cameras with the same `NormalizedRenderTarget`. Add the
`Arc<AtomicUsize>` to the existing per-target cache.
# Objective
- Save 16 bytes per MeshUniform in uniform/storage buffers.
## Solution
- Reorder members of MeshUniform to capitalise on alignment and size
rules for tighter data packing. Before the size of a MeshUniform was 160
bytes, and after it is 144 bytes, saving 16 bytes of unused padding for
alignment.
---
## Changelog
- Reduced the size of MeshUniform by 16 bytes.
# Objective
The derive macro wasn't doc-commented, so it showed up in the generated
doc as follow:
```rust
#[derive(Asset, TypePath)]
let shader = asset_server.load::<Shader>("embedded://bevy_rock/render/rock.wgsl");
```
Which is very confusing
## Solution
Comment the `derive` attribute as well
# Objective
We deprecated quite a few APIs in 0.13. 0.13 has shipped already. It
should be OK to remove them in 0.14's release. Fixes#4059. Fixes#9011.
## Solution
Remove them.
# Objective
- Some workspace members do not inherit the global lints.
## Solution
- Add a `[lints]` entry for all files returned by `rg
--files-without-match -F "[lints]" **/Cargo.toml`, except the compile
failure tests since these aren't part of the workspace.
- Add some docstrings where needed.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
* Fixes#11932 (performance impact when stepping is disabled)
## Solution
The `Option<FixedBitSet>` argument added to `ScheduleExecutor::run()` in
#8453 caused a measurable performance impact even when stepping is
disabled. This can be seen by the benchmark of running `Schedule:run()`
on an empty schedule in a tight loop
(https://github.com/bevyengine/bevy/issues/11932#issuecomment-1950970236).
I was able to get the same performance results as on 0.12.1 by changing
the argument
`ScheduleExecutor::run()` from `Option<FixedBitSet>` to
`Option<&FixedBitSet>`. The down-side of this change is that
`Schedule::run()` now takes about 6% longer (3.7319 ms vs 3.9855ns) when
stepping is enabled
---
## Changelog
* Change `ScheduleExecutor::run()` `_skipped_systems` from
`Option<FixedBitSet>` to `Option<&FixedBitSet>`
* Added a few benchmarks to measure `Schedule::run()` performance with
various executors
# Objective
- Gltf loader now shows which file is missing pre baked tangents
- Fixes#11831
## Solution
- The file name is shown in the error message
- What changed as a result of this PR?
### Changed:
- Gltf loader now shows which file is missing pre baked tangents
- If this PR is a breaking change (relative to the last release of
Bevy), describe how a user might need to migrate their code to support
these changes
- Simply adding new functionality is not a breaking change.
- Fixing behavior that was definitely a bug, rather than a questionable
design choice is not a breaking change.
# Objective
Currently, the `ambiguous_names` hash set in `TypeRegistry` is used to
keep track of short type names that are ambiguous, and to require the
use of long type names for these types.
However, there's no way for the consumer of `TypeRegistry` to known
whether a given call to `get_with_short_type_path()` or
`get_with_short_type_path_mut()` failed because a type was not
registered at all, or because the short name is ambiguous.
This can be used, for example, for better error reporting to the user by
an editor tool. Here's some code that uses this, from my remote protocol
exploration branch:
```rust
let type_registration = type_registry
.get_with_type_path(component_name)
.or_else(|| registry.get_with_short_type_path(component_name))
.ok_or_else(|| {
if type_registry.is_ambiguous(component_name) {
BrpError::ComponentAmbiguous(component_name.clone())
} else {
BrpError::MissingTypeRegistration(component_name.clone())
}
})?
```
## Solution
- Introduces a `is_ambiguous()` method.
- Also drive-by fixes two documentation comments that had broken links.
---
## Changelog
- Added a `TypeRegistry::is_ambiguous()` method, for checking whether a
given short type path is ambiguous (e.g. `MyType` potentially matching
either `some_crate::MyType` or `another_crate::MyType`)
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- On some devices, UI buttons are not responsive
## Solution
- On device with a slower frame rate, touch event can start and end in
the frame rate
- When looking for a touch position, also look into the `just_pressed`
touches that are not cleared by the end event but only at the end of the
frame
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Implement Debug trait for SpriteBundle and SpriteSheetBundle
It's helpful and other basic bundles like TransformBundle and
VisibilityBundle already implement this trait
# Objective
There's a repeating pattern of `ThreadLocal<Cell<Vec<T>>>` which is very
useful for low overhead, low contention multithreaded queues that have
cropped up in a few places in the engine. This pattern is surprisingly
useful when building deferred mutation across multiple threads, as noted
by it's use in `ParallelCommands`.
However, `ThreadLocal<Cell<Vec<T>>>` is not only a mouthful, it's also
hard to ensure the thread-local queue is replaced after it's been
temporarily removed from the `Cell`.
## Solution
Wrap the pattern into `bevy_utils::Parallel<T>` which codifies the
entire pattern and ensures the user follows the contract. Instead of
fetching indivdual cells, removing the value, mutating it, and replacing
it, `Parallel::get` returns a `ParRef<'a, T>` which contains the
temporarily removed value and a reference back to the cell, and will
write the mutated value back to the cell upon being dropped.
I would like to use this to simplify the remaining part of #4899 that
has not been adopted/merged.
---
## Changelog
TODO
---------
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
# Objective
Bevy's animation system currently does tree traversals based on `Name`
that aren't necessary. Not only do they require in unsafe code because
tree traversals are awkward with parallelism, but they are also somewhat
slow, brittle, and complex, which manifested itself as way too many
queries in #11670.
# Solution
Divide animation into two phases: animation *advancement* and animation
*evaluation*, which run after one another. *Advancement* operates on the
`AnimationPlayer` and sets the current animation time to match the game
time. *Evaluation* operates on all animation bones in the scene in
parallel and sets the transforms and/or morph weights based on the time
and the clip.
To do this, we introduce a new component, `AnimationTarget`, which the
asset loader places on every bone. It contains the ID of the entity
containing the `AnimationPlayer`, as well as a UUID that identifies
which bone in the animation the target corresponds to. In the case of
glTF, the UUID is derived from the full path name to the bone. The rule
that `AnimationTarget`s are descendants of the entity containing
`AnimationPlayer` is now just a convention, not a requirement; this
allows us to eliminate the unsafe code.
# Migration guide
* `AnimationClip` now uses UUIDs instead of hierarchical paths based on
the `Name` component to refer to bones. This has several consequences:
- A new component, `AnimationTarget`, should be placed on each bone that
you wish to animate, in order to specify its UUID and the associated
`AnimationPlayer`. The glTF loader automatically creates these
components as necessary, so most uses of glTF rigs shouldn't need to
change.
- Moving a bone around the tree, or renaming it, no longer prevents an
`AnimationPlayer` from affecting it.
- Dynamically changing the `AnimationPlayer` component will likely
require manual updating of the `AnimationTarget` components.
* Entities with `AnimationPlayer` components may now possess descendants
that also have `AnimationPlayer` components. They may not, however,
animate the same bones.
* As they aren't specific to `TypeId`s,
`bevy_reflect::utility::NoOpTypeIdHash` and
`bevy_reflect::utility::NoOpTypeIdHasher` have been renamed to
`bevy_reflect::utility::NoOpHash` and
`bevy_reflect::utility::NoOpHasher` respectively.
# Objective
- having different field names for `Camera2dBundle` and `Camera3dBundle`
implies that there is something different between these fields when
there is not
## Solution
- rename the field in `Camera3dBundle` to align with `Camera2dBundle`
## Migration Guide
- use the new `deband_dither` field name with `Camera3dBundle`, rather
than the old field name, `dither`
# Objective
Do #11829, but without breaking CI.
## Solution
Update to `toml_edit` v0.22, replace the deprecated function with the
the newer equivalent.
# Objective
Fixes#11964.
## Solution
Adds the `serde` feature to `bitflags` for `bevy_render`. This makes
`bevy_render` compile correctly when used alone.
---
## Changelog
- Fixed an issue where depending on `bevy_render` alone would fail to
compile.
# Objective
Improve code quality and performance
## Solution
Instead of using `plugin.downcast_ref::<T>().is_some()` in
`App::is_plugin_added`, use `plugin.is::<T>()`. Which is more performant
and cleaner.
# Objective
- Fixes#11960
- The compilation of `bevy_core_pipeline` failed with the `dds` feature
enabled
## Solution
- Enable the `dds` feature of `bevy_render` when enabling it for
`bevy_core_pipeline`
# Objective
`update_archetype_component_access` was removed from queries in #9774,
but some documentation still refers to it.
## Solution
Update the documentation. Since a bunch of these were in SAFETY comments
it would be nice if someone who knows the details better could check
that the rest of those comments are still valid.
# Objective
Right now, if you call `embedded_asset` with 2 arguments as a qualified
path it doesn't work (`bevy::asset::embedded_asset!(app, "foo.wgsl")` ->
"cannot find macro `embedded_asset` in this scope")
## Solution
Use `$crate::` in expansion for 2-arg case.
# Objective
- I hated having to do `Cuboid::new(1.0, 1.0, 1.0)` or
`Cuboid::from_size(Vec3::splat(1.0))` when there should be a much easier
way to do this.
## Solution
- Implemented a `from_length()` method that only takes in a single
float, and constructs a primitive of equal size in all directions.
- Ex:
```rs
// These:
Cuboid::new(1.0, 1.0, 1.0);
Cuboid::from_size(Vec3::splat(1.0));
// Are equivalent to this:
Cuboid::from_length(1.0);
```
- For the rest of the changed primitives:
```rs
Rectangle::from_length(1.0);
Plane3d::default().mesh().from_length(1.0);
```
# Objective
Another PR failed CI due to duplicate deps, and I noticed this one in
particular while scanning through the error messages.
I think this was missed in #11082.
## Solution
Bump `encase_derive_impl` dep in `bevy_encase_derive` to same version as
`encase` dep for `bevy_render`.
I spot-checked a few examples, and glanced at the
[changelog](<https://github.com/teoxoy/encase/blob/main/CHANGELOG.md#v070-2024-01-02>)
and I don't think there's anything to be concerned about, but I barely
know what this thing does.
# Objective
Fixes#11908
## Solution
- Remove the `naga_oil` dependency from `bevy_pbr`.
- We were doing a little dance to disable `glsl` support on not-wasm, so
incorporate that dance into `bevy_render`'s `Cargo.toml`.
They cause the number of texture bindings to overflow on those
platforms. Ultimately, we shouldn't unconditionally disable them, but
this fixes a crash blocking 0.13.
Closes#11885.
I did this during the prepass, but I neglected to do it during the
shadow map pass, causing a panic when directional lights with shadows
were enabled with lightmapped meshes present. This patch fixes the
issue.
Closes#11898.
# Objective
- Being able to build for WebGPU
```
error[E0061]: this function takes 1 argument but 3 arguments were supplied
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.1/src/backend/webgpu.rs:375:22
|
375 | let mut mapped = web_sys::GpuDepthStencilState::new(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
376 | map_compare_function(desc.depth_compare),
| ---------------------------------------- unexpected argument of type `GpuCompareFunction`
377 | desc.depth_write_enabled,
| ------------------------ unexpected argument of type `bool`
|
note: associated function defined here
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/web-sys-0.3.68/src/features/gen_GpuDepthStencilState.rs:27:12
|
27 | pub fn new(format: GpuTextureFormat) -> Self {
| ^^^
help: remove the extra arguments
|
376 - map_compare_function(desc.depth_compare),
376 + map_texture_format(desc.format),
|
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.1/src/backend/webgpu.rs:1693:13
|
1693 | web_sys::GpuVertexState::new(desc.vertex.entry_point, &module.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -------------------------
| |
| unexpected argument of type `&str`
| help: remove the extra argument
|
note: associated function defined here
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/web-sys-0.3.68/src/features/gen_GpuVertexState.rs:27:12
|
27 | pub fn new(module: &GpuShaderModule) -> Self {
| ^^^
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.1/src/backend/webgpu.rs:1768:17
|
1768 | web_sys::GpuFragmentState::new(frag.entry_point, &module.0, &targets);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- -------- unexpected argument of type `&js_sys::Array`
| |
| expected `&GpuShaderModule`, found `&str`
|
= note: expected reference `&GpuShaderModule`
found reference `&str`
note: associated function defined here
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/web-sys-0.3.68/src/features/gen_GpuFragmentState.rs:27:12
|
27 | pub fn new(module: &GpuShaderModule, targets: &::wasm_bindgen::JsValue) -> Self {
| ^^^
help: remove the extra argument
|
1768 - web_sys::GpuFragmentState::new(frag.entry_point, &module.0, &targets);
1768 + web_sys::GpuFragmentState::new(/* &GpuShaderModule */, &module.0);
|
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.1/src/backend/webgpu.rs:1793:13
|
1793 | web_sys::GpuProgrammableStage::new(desc.entry_point, &shader_module.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------
| |
| unexpected argument of type `&str`
| help: remove the extra argument
|
note: associated function defined here
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/web-sys-0.3.68/src/features/gen_GpuProgrammableStage.rs:27:12
|
27 | pub fn new(module: &GpuShaderModule) -> Self {
| ^^^
error[E0599]: no method named `write_timestamp` found for struct `GpuCommandEncoder` in the current scope
--> .cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.1/src/backend/webgpu.rs:2505:14
|
2503 | / encoder_data
2504 | | .0
2505 | | .write_timestamp(&query_set_data.0, query_index);
| | -^^^^^^^^^^^^^^^ method not found in `GpuCommandEncoder`
| |_____________|
|
Some errors have detailed explanations: E0061, E0599.
For more information about an error, try `rustc --explain E0061`.
```
## Solution
- `web-sys` doesn't follow semver for the WebGPU APIs as they are
unstable. Force using a compatible version
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
When registering and preregistering asset loaders, there would be a
`warn!` if multiple asset loaders use a given extension, and an `info!`
if multiple asset loaders load the same asset type. Since both of these
situations are individually fine, it was decided that these messages
should be removed.
## Solution
Replace both of these messages with a new `warn!` that notes that if
multiple asset loaders share the same asset type _and_ share extensions,
that the loader must be specified in the `.meta` file for those assets
in order to solve the ambiguity. This is a more useful message, since it
notes when a user must take special action / consideration.
# Objective
Fixes#11846
## Solution
Add a `synchronous_pipeline_compilation ` field to `RenderPlugin`,
defaulting to `false`.
Most of the diff is whitespace.
## Changelog
Added `synchronous_pipeline_compilation ` to `RenderPlugin` for
disabling async pipeline creation.
## Migration Guide
TODO: consider combining this with the guide for #11846
`RenderPlugin` has a new `synchronous_pipeline_compilation ` property.
The default value is `false`. Set this to `true` if you want to retain
the previous synchronous behavior.
---------
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: François <mockersf@gmail.com>
This represents when the user has configured `ClearColorConfig::None` in
their application. If the clear color is `None`, we will always `Load`
instead of attempting to clear the attachment on the first call.
Fixes#11883.
# Objective
The new render graph labels do not (and cannot) implement normal
Reflect, which breaks spawning scenes with cameras (including GLTF
scenes). Likewise, the new `CameraMainTextureUsages` also does not (and
cannot) implement normal Reflect because it uses `wgpu::TextureUsages`
under the hood.
Fixes#11852
## Solution
This implements minimal "reflect value" for `CameraRenderGraph` and
`CameraMainTextureUsages` and registers the types, which satisfies our
spawn logic.
Note that this _does not_ fix scene serialization for these types, which
will require more significant changes. We will especially need to think
about how (and if) "interned labels" will fit into the scene system. For
the purposes of 0.13, I think this is the best we can do. Given that
this serialization issue is prevalent throughout Bevy atm, I'm ok with
adding a couple more to the pile. When we roll out the new scene system,
we will be forced to solve these on a case-by-case basis.
---
## Changelog
- Implement Reflect (value) for `CameraMainTextureUsages` and
`CameraRenderGraph`, and register those types.
# Objective
#10644 introduced nice "statically typed" labels that replace the old
strings. I would like to propose some changes to the names introduced:
* `SubGraph2d` -> `Core2d` and `SubGraph3d` -> `Core3d`. The names of
these graphs have been / should continue to be the "core 2d" graph not
the "sub graph 2d" graph. The crate is called `bevy_core_pipeline`, the
modules are still `core_2d` and `core_3d`, etc.
* `Labels2d` and `Labels3d`, at the very least, should not be plural to
follow naming conventions. A Label enum is not a "collection of labels",
it is a _specific_ Label. However I think `Label2d` and `Label3d` is
significantly less clear than `Node2d` and `Node3d`, so I propose those
changes here. I've done the same for `LabelsPbr` -> `NodePbr` and
`LabelsUi` -> `NodeUi`
Additionally, #10644 accidentally made one of the Camera2dBundle
constructors use the 3D graph instead of the 2D graph. I've fixed that
here.
---
## Changelog
* Renamed `SubGraph2d` -> `Core2d`, `SubGraph3d` -> `Core3d`, `Labels2d`
-> `Node2d`, `Labels3d` -> `Node3d`, `LabelsUi` -> `NodeUi`, `LabelsPbr`
-> `NodePbr`
# Objective
Provide a public replacement for `Into<MeshUniform>` trait impl which
was removed by #10231.
I made use of this in the `bevy_mod_outline` crate and will have to
duplicate this function if it's not accessible.
## Solution
Change the MeshUniform::new() method to be public.
# Objective
After adding configurable exposure, we set the default ev100 value to
`7` (indoor). This brought us out of sync with Blender's configuration
and defaults. This PR changes the default to `9.7` (bright indoor or
very overcast outdoors), as I calibrated in #11577. This feels like a
very reasonable default.
The other changes generally center around tweaking Bevy's lighting
defaults and examples to play nicely with this number, alongside a few
other tweaks and improvements.
Note that for artistic reasons I have reverted some examples, which
changed to directional lights in #11581, back to point lights.
Fixes#11577
---
## Changelog
- Changed `Exposure::ev100` from `7` to `9.7` to better match Blender
- Renamed `ExposureSettings` to `Exposure`
- `Camera3dBundle` now includes `Exposure` for discoverability
- Bumped `FULL_DAYLIGHT ` and `DIRECT_SUNLIGHT` to represent the
middle-to-top of those ranges instead of near the bottom
- Added new `AMBIENT_DAYLIGHT` constant and set that as the new
`DirectionalLight` default illuminance.
- `PointLight` and `SpotLight` now have a default `intensity` of
1,000,000 lumens. This makes them actually useful in the context of the
new "semi-outdoor" exposure and puts them in the "cinema lighting"
category instead of the "common household light" category. They are also
reasonably close to the Blender default.
- `AmbientLight` default has been bumped from `20` to `80`.
## Migration Guide
- The increased `Exposure::ev100` means that all existing 3D lighting
will need to be adjusted to match (DirectionalLights, PointLights,
SpotLights, EnvironmentMapLights, etc). Or alternatively, you can adjust
the `Exposure::ev100` on your cameras to work nicely with your current
lighting values. If you are currently relying on default intensity
values, you might need to change the intensity to achieve the same
effect. Note that in Bevy 0.12, point/spot lights had a different hard
coded ev100 value than directional lights. In Bevy 0.13, they use the
same ev100, so if you have both in your scene, the _scale_ between these
light types has changed and you will likely need to adjust one or both
of them.
# Objective
Fix https://github.com/bevyengine/bevy/issues/11577.
## Solution
Fix the examples, add a few constants to make setting light values
easier, and change the default lighting settings to be more realistic.
(Now designed for an overcast day instead of an indoor environment)
---
I did not include any example-related changes in here.
## Changelogs (not including breaking changes)
### bevy_pbr
- Added `light_consts` module (included in prelude), which contains
common lux and lumen values for lights.
- Added `AmbientLight::NONE` constant, which is an ambient light with a
brightness of 0.
- Added non-EV100 variants for `ExposureSettings`'s EV100 constants,
which allow easier construction of an `ExposureSettings` from a EV100
constant.
## Breaking changes
### bevy_pbr
The several default lighting values were changed:
- `PointLight`'s default `intensity` is now `2000.0`
- `SpotLight`'s default `intensity` is now `2000.0`
- `DirectionalLight`'s default `illuminance` is now
`light_consts::lux::OVERCAST_DAY` (`1000.`)
- `AmbientLight`'s default `brightness` is now `20.0`
# Objective
- The current implementations for `&Visibility == Visibility` and
`Visibility == &Visibility` are ambiguous, so they raise a warning for
being unconditionally recursive.
- `TaskPool`'s `LOCAL_EXECUTOR` thread local calls a `const` constructor
in a non-`const` context.
## Solution
- Make `&Visibility == Visibility` and `Visibility == &Visibility`
implementations use `Visibility == Visibility`.
- Wrap `LocalExecutor::new` in a special `const` block supported by
[`thread_local`](https://doc.rust-lang.org/stable/std/macro.thread_local.html).
---
This lints were found by running:
```shell
$ cargo clippy --workspace
```
There are a few other warnings that were more complicated, so I chose
not to include them in this PR.
<details>
<summary>Here they are...</summary>
```shell
warning: function cannot return without recursing
--> crates/bevy_utils/src/cow_arc.rs:92:5
|
92 | / fn eq(&self, other: &Self) -> bool {
93 | | self.deref().eq(other.deref())
94 | | }
| |_____^
|
note: recursive call site
--> crates/bevy_utils/src/cow_arc.rs:93:9
|
93 | self.deref().eq(other.deref())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: method `get_path` is never used
--> crates/bevy_reflect/src/serde/de.rs:26:8
|
25 | trait StructLikeInfo {
| -------------- method in this trait
26 | fn get_path(&self) -> &str;
| ^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
warning: methods `get_path` and `get_field` are never used
--> crates/bevy_reflect/src/serde/de.rs:34:8
|
33 | trait TupleLikeInfo {
| ------------- methods in this trait
34 | fn get_path(&self) -> &str;
| ^^^^^^^^
35 | fn get_field(&self, index: usize) -> Option<&UnnamedField>;
| ^^^^^^^^^
```
The other warnings are fixed by #11865.
</details>
# Objective
- There are multiple instances of `let Some(x) = ... else { None };`
throughout the project.
- Because `Option<T>` implements
[`Try`](https://doc.rust-lang.org/stable/std/ops/trait.Try.html), it can
use the question mark `?` operator.
## Solution
- Use question mark operator instead of `let Some(x) = ... else { None
}`.
---
There was another PR that did a similar thing a few weeks ago, but I
couldn't find it.
# Objective
I tried using `insert_gizmo_group` to configure my physics gizmos in a
bevy_xpbd example, but was surprised to see that nothing happened. I
found out that the method does *not* overwrite gizmo groups that have
already been initialized (with `init_gizmo_group`). This is unexpected,
since methods like `insert_resource` *do* overwrite.
## Solution
Insert the configuration even if it has already been initialized.
# Objective
`RenderMeshInstance::material_bind_group_id` is only set from
`queue_material_meshes::<M>`. this field is used (only) for determining
batch groups, so some items may be batched incorrectly if they have
never been in the camera's view or if they don't use the Material
abstraction.
in particular, shadow views render more meshes than the main camera, and
currently batch some meshes where the object has never entered the
camera view together. this is quite hard to trigger, but should occur in
a scene with out-of-view alpha-mask materials (so that the material
instance actually affects the shadow) in the path of a light.
this is also a footgun for custom pipelines: failing to set the
material_bind_group_id will result in all meshes being batched together
and all using the closest/furthest material to the camera (depending on
sort order).
## Solution
- queue_shadows now sets the material_bind_group_id correctly
- `MeshPipeline` doesn't attempt to batch meshes if the
material_bind_group_id has not been set. custom pipelines still need to
set this field to take advantage of batching, but will at least render
correctly if it is not set
# Objective
sysinfo was updated to 0.30 in #11071. Ever since then the `cpu` field
of the `SystemInfo` struct that gets printed every time one starts an
bevy app has been empty. This is because the following part of the
sysinfo migration guide was overlooked:
---
### `Cpu` changes
Information like `Cpu::brand`, `Cpu::vendor_id` or `Cpu::frequency` are
not set on the "global" CPU.
---
## Solution
- Get the CPU brand information from a specific CPU instead. In this
case, just choose the first one. It's theoretically possible for
different CPUs to have different names, but in practice this doesn't
really happen I think. Even Intel's newer hybrid processors use a
uniform name for all CPUs in my experience.
- We can use this opportunity to also update our `sysinfo::System`
initialization here to only fetch the information we're interested in.
Make the renamings/changes regarding texture atlases a bit less
confusing by calling `TextureAtlasLayout` a layout, not a texture atlas.
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
It can sometimes be useful to combine several meshes into one. This
allows constructing more complex meshes out of simple primitives without
needing to use a 3D modeling program or entity hierarchies.
This could also be used internally to increase code reuse by using
existing mesh generation logic for e.g. circles and using that in
cylinder mesh generation logic to add the top and bottom of the
cylinder.
**Note**: This is *not* implementing CSGs (Constructive Solid Geometry)
or any boolean operations, as that is much more complex. This is simply
adding the mesh data of another mesh to a mesh.
## Solution
Add a `merge` method to `Mesh`. It appends the vertex attributes and
indices of `other` to `self`, resulting in a `Mesh` that is the
combination of the two.
For example, you could do this:
```rust
let mut cuboid = Mesh::from(shape::Box::default());
let mut cylinder = Mesh::from(shape::Cylinder::default());
let mut torus = Mesh::from(shape::Torus::default());
cuboid.merge(cylinder);
cuboid.merge(torus);
```
This would result in `cuboid` being a `Mesh` that also has the cylinder
mesh and torus mesh. In this case, they would just be placed on top of
each other, but by utilizing #11454 we can transform the cylinder and
torus to get a result like this:
https://github.com/bevyengine/bevy/assets/57632562/557402c6-b896-4aba-bd95-312e7d1b5238
This is just a single entity and a single mesh.
# Objective
- Fixes#11782.
## Solution
- Remove the run condition for `apply_global_wireframe_material`, since
it prevent detecting when meshes are added or the `NoWireframe` marker
component is removed from an entity. Alternatively this could be done by
using a run condition like "added `Handle<Mesh>` or removed
`NoWireframe` or `WireframeConfig` changed" but this seems less clear to
me than directly letting the queries on
`apply_global_wireframe_material` do the filtering.
# Objective
-
[`crossbeam::scope`](https://docs.rs/crossbeam/latest/crossbeam/fn.scope.html)
is soft-deprecated in favor of the standard library's implementation.
## Solution
- Replace reference in `TaskPool`'s docs to mention `std:🧵:scope`
instead.
# Objective
- Fixes#11695
## Solution
- Added `delta: Option<Vec2>` to `bevy_window::CursorMoved`. `delta` is
an `Option` because the `CursorMoved` event does get fired when the
cursor was outside the window area in the last frame. In that case there
is no cursor position from the last frame to compare with the current
cursor position.
---
## Changelog
- Added `delta: Option<Vec2>` to `bevy_window::CursorMoved`.
## Migration Guide
- You need to add `delta` to any manually created `CursorMoved` struct.
---------
Co-authored-by: Kanabenki <lucien.menassol@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Fixes#11638
- See
[here](https://github.com/bevyengine/bevy/issues/11638#issuecomment-1920508465)
for details on the cause of this issue.
## Solution
- Modified `AssetLoaders` to capture possibility of multiple
`AssetLoader` registrations operating on the same `Asset` type, but
different extensions.
- Added an algorithm which will attempt to resolve via `AssetLoader`
name, then `Asset` type, then by extension. If at any point multiple
loaders fit a particular criteria, the next criteria is used as a tie
breaker.
# Objective
At the start of every schedule run, there's currently a guaranteed piece
of overhead as the async executor spawns the MultithreadeExecutor task
onto one of the ComputeTaskPool threads.
## Solution
Poll the executor once to immediately schedule systems without waiting
for the async executor, then spawn the task if and only if the executor
does not immediately terminate.
On a similar note, having the executor task immediately start executing
a system in the same async task might yield similar results over a
broader set of cases. However, this might be more involved, and may need
a solution like #8304.
# Objective
When applying a command, we currently use double indirection for the
world reference `&mut Option<&mut World>`. Since this is used across a
`fn` pointer boundary, this can't get optimized away.
## Solution
Reborrow the world reference and pass `Option<&mut World>` instead.
# Objective
Scheduling low cost systems has significant overhead due to task pool
contention and the extra machinery to schedule and run them. Following
the example of #7728, `asset_events` is good example of this kind of
system, where there is no work to be done when there are no queued asset
events.
## Solution
Put a run condition on it that checks if there are any queued events.
## Performance
Tested against `many_foxes`, we can see a slight improvement in the
total time spent in `UpdateAssets`. Also noted much less volatility due
to not being at the whim of the OS thread scheduler.
![image](https://github.com/bevyengine/bevy/assets/3137680/e0b282bf-27d0-4fe4-81b9-ecd72ab258e5)
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
The code in `bevy_reflect_derive` could use some cleanup.
## Solution
Took some of the changes in #11659 to create a dedicated PR for cleaning
up the field and container attribute logic.
#### Updated Naming
I renamed `ReflectTraits` and `ReflectFieldAttr` to
`ContainerAttributes` and `FieldAttributes`, respectively. I think these
are clearer.
#### Updated Parsing
##### Readability
The parsing logic wasn't too bad before, but it was getting difficult to
read. There was some duplicated logic between `Meta::List` and
`Meta::Path` attributes. Additionally, all the logic was kept inside a
large method.
To simply things, I replaced the nested meta parsing with `ParseStream`
parsing. In my opinion, this is easier to follow since it breaks up the
large match statement into a small set of single-line if statements,
where each if-block contains a single call to the appropriate attribute
parsing method.
##### Flexibility
On top of the added simplicity, this also makes our attribute parsing
much more flexible. It allows us to more elegantly handle custom where
clauses (i.e. `#[reflect(where T: Foo)]`) and it opens the door for more
non-standard attribute syntax (e.g. #11659).
##### Errors
This also allows us to automatically provide certain errors when
parsing. For example, since we can use `stream.lookahead1()`, we get
errors like the following for free:
```
error: expected one of: `ignore`, `skip_serializing`, `default`
--> crates/bevy_reflect/src/lib.rs:1988:23
|
1988 | #[reflect(foo)]
| ^^^
```
---
## Changelog
> [!note]
> All changes are internal to `bevy_reflect_derive` and should not
affect the public API[^1].
- Renamed `ReflectTraits` to `ContainerAttributes`
- Renamed `ReflectMeta::traits` to `ReflectMeta::attrs`
- Renamed `ReflectFieldAttr` to `FieldAttributes`
- Updated parsing logic for field/container attribute parsing
- Now uses a `ParseStream` directly instead of nested meta parsing
- General code cleanup of the field/container attribute modules for
`bevy_reflect_derive`
[^1]: Does not include errors, which may look slightly different.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Bevy's change detection functionality is invaluable for writing robust
apps, but it only works in the context of systems and exclusive systems.
Oftentimes it is necessary to detect changes made in earlier code
without having to place the code in separate systems, but it is not
currently possible to do so since there is no way to set the value of
`World::last_change_tick`.
`World::clear_trackers` allows you to update the change tick, but this
has unintended side effects, since it irreversibly affects the behavior
of change and removal detection for the entire app.
## Solution
Add a method `World::last_change_tick_scope`. This allows you to set
`last_change_tick` to a specific value for a region of code. To ensure
that misuse doesn't break unrelated functions, we restore the world's
original change tick at the end of the provided scope.
### Example
A function that uses this to run an update loop repeatedly, allowing
each iteration of the loop to react to changes made in the previous loop
iteration.
```rust
fn update_loop(
world: &mut World,
mut update_fn: impl FnMut(&mut World) -> std::ops::ControlFlow<()>,
) {
let mut last_change_tick = world.last_change_tick();
// Repeatedly run the update function until it requests a break.
loop {
// Update once.
let control_flow = world.last_change_tick_scope(last_change_tick, |world| {
update_fn(world)
});
// End the loop when the closure returns `ControlFlow::Break`.
if control_flow.is_break() {
break;
}
// Increment the change tick so the next update can detect changes from this update.
last_change_tick = world.change_tick();
world.increment_change_tick();
}
}
```
---
## Changelog
+ Added `World::last_change_tick_scope`, which allows you to specify the
reference for change detection within a certain scope.
# Objective
- Part of #11590.
## Solution
- Fix `unsafe_op_in_unsafe_fn` for `bevy_dynamic_plugin`.
---
## Changelog
- Added further restrictions to the safety requirements of
`bevy_dynamic_plugin::dynamically_load_plugin`.
---
I had a few issues, specifically with the safety comment on
`dynamically_load_plugin`. There are three different unsafe functions
called within the function body, and they all need their own
justification / message.
Also, would it be unsound to call `dynamically_load_plugin` multiple
times on the same file? I feel the documentation needs to be more clear.
# Objective
Reduce the size of `bevy_utils`
(https://github.com/bevyengine/bevy/issues/11478)
## Solution
Move `EntityHash` related types into `bevy_ecs`. This also allows us
access to `Entity`, which means we no longer need `EntityHashMap`'s
first generic argument.
---
## Changelog
- Moved `bevy::utils::{EntityHash, EntityHasher, EntityHashMap,
EntityHashSet}` into `bevy::ecs::entity::hash` .
- Removed `EntityHashMap`'s first generic argument. It is now hardcoded
to always be `Entity`.
## Migration Guide
- Uses of `bevy::utils::{EntityHash, EntityHasher, EntityHashMap,
EntityHashSet}` now have to be imported from `bevy::ecs::entity::hash`.
- Uses of `EntityHashMap` no longer have to specify the first generic
parameter. It is now hardcoded to always be `Entity`.
# Objective
Loading some textures from the days of yonder give me errors cause the
mipmap level is 0
## Solution
Set a minimum of 1
## Changelog
Make mipmap level at least 1
# Objective
Use `GamepadButtonType` with library that requires `Ord`.
## Motivation
`KeyCode` derives `Ord` that I'm using with a trie for recognizing
[input
sequences](https://github.com/shanecelis/bevy-input-sequence/tree/trie).
I would like to do the same for `GamepadButtonType` but am stymied by it
not deriving `Ord`.
## Solution
This PR add derivations PartialOrd and Ord for `GamepadButtonType`.
## Workaround
If deriving `Ord` is not possible, I'd be happy to know how I might
coerce `GamepadButtonType` into a `u32` or something else that is `Ord`,
so I can wrap `GamepadButtonType` in a newtype. I suppose serializing
with serde may work or reflect?
# Objective
- Get rid of unwraps in winit fullscreen handling code, which are the
source of some crashes.
- Fix#11275
## Solution
- Replace the unwraps with warnings. Ignore the fullscreen request, do
nothing instead.
# Objective
It would be useful to be able to inspect a `QueryState`'s accesses so we
can detect when the data it accesses changes without having to iterate
it. However there are two things preventing this:
* These accesses are unnecessarily encapsulated.
* `Has<T>` indirectly accesses `T`, but does not register it.
## Solution
* Expose accesses and matches used by `QueryState`.
* Add the notion of "archetypal" accesses, which are not accessed
directly, but whose presence in an archetype affects a query result.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
I want to keep track of despawned entities.
I am aware of
[`RemovedComponents`](https://docs.rs/bevy/0.12.1/bevy/ecs/prelude/struct.RemovedComponents.html).
However, the docs don't explicitly mention that despawned entities are
also included in this event iterator.
I searched through the bevy tests to find `removal_tracking` in
`crates/bevy_ecs/src/system/mod.rs` that confirmed the behavior:
```rust
...
assert_eq!(
removed_i32.read().collect::<Vec<_>>(),
&[despawned.0],
"despawning causes the correct entity to show up in the 'RemovedComponent' system parameter."
);
...
```
## Solution
- Explicitly mention this behavior in docs.
This fixes a `FIXME` in `extract_meshes` and results in a performance
improvement.
As a result of this change, meshes in the render world might not be
attached to entities anymore. Therefore, the `entity` parameter to
`RenderCommand::render()` is now wrapped in an `Option`. Most
applications that use the render app's ECS can simply unwrap the
`Option`.
Note that for now sprites, gizmos, and UI elements still use the render
world as usual.
## Migration guide
* For efficiency reasons, some meshes in the render world may not have
corresponding `Entity` IDs anymore. As a result, the `entity` parameter
to `RenderCommand::render()` is now wrapped in an `Option`. Custom
rendering code may need to be updated to handle the case in which no
`Entity` exists for an object that is to be rendered.
# Objective
`bevy_utils` only requires aHash 0.8.3, which is broken on Rust 1.7.6:
```
error: could not compile `ahash` (lib) due to 1 previous error
error[E0635]: unknown feature `stdsimd`
```
See https://github.com/tkaitchuck/aHash/issues/200
This is fixed in aHash 0.8.7, so require at least that version
(Cargo.lock is already up to date).
# Objective
The deprecation message of `bevy::render::mesh::shape::Quad` says that
you should use `bevy_math`'s `Quad` instead. But it doesn't exist.
## Solution
Mention the correct primitive: `Rectangle`
> Follow up to #11600 and #10588
@mockersf expressed some [valid
concerns](https://github.com/bevyengine/bevy/pull/11600#issuecomment-1932796498)
about the current system this PR attempts to fix:
The `ComputedTextureSlices` reacts to asset change in both `bevy_sprite`
and `bevy_ui`, meaning that if the `ImageScaleMode` is inserted by
default in the bundles, we will iterate through most 2d items every time
an asset is updated.
# Solution
- `ImageScaleMode` only has two variants: `Sliced` and `Tiled`. I
removed the `Stretched` default
- `ImageScaleMode` is no longer part of any bundle, but the relevant
bundles explain that this additional component can be inserted
This way, the *absence* of `ImageScaleMode` means the image will be
stretched, and its *presence* will include the entity to the various
slicing systems
Optional components in bundles would make this more straigthfoward
# Additional work
Should I add new bundles with the `ImageScaleMode` component ?
# Objective
- Encoding many GPU commands (such as in a renderpass with many draws,
such as the main opaque pass) onto a `wgpu::CommandEncoder` is very
expensive, and takes a long time.
- To improve performance, we want to perform the command encoding for
these heavy passes in parallel.
## Solution
- `RenderContext` can now queue up "command buffer generation tasks"
which are closures that will generate a command buffer when called.
- When finalizing the render context to produce the final list of
command buffers, these tasks are run in parallel on the
`ComputeTaskPool` to produce their corresponding command buffers.
- The general idea is that the node graph will run in serial, but in a
node, instead of doing rendering work, you can add tasks to do render
work in parallel with other node's tasks that get ran at the end of the
graph execution.
## Nodes Parallelized
- `MainOpaquePass3dNode`
- `PrepassNode`
- `DeferredGBufferPrepassNode`
- `ShadowPassNode` (One task per view)
## Future Work
- For large number of draws calls, might be worth further subdividing
passes into 2+ tasks.
- Extend this to UI, 2d, transparent, and transmissive nodes?
- Needs testing - small command buffers are inefficient - it may be
worth reverting to the serial command encoder usage for render phases
with few items.
- All "serial" (traditional) rendering work must finish before parallel
rendering tasks (the new stuff) can start to run.
- There is still only one submission to the graphics queue at the end of
the graph execution. There is still no ability to submit work earlier.
## Performance Improvement
Thanks to @Elabajaba for testing on Bistro.
![image](https://github.com/bevyengine/bevy/assets/47158642/be50dafa-85eb-4da5-a5cd-c0a044f1e76f)
TLDR: Without shadow mapping, this PR has no impact. _With_ shadow
mapping, this PR gives **~40 more fps** than main.
---
## Changelog
- `MainOpaquePass3dNode`, `PrepassNode`, `DeferredGBufferPrepassNode`,
and each shadow map within `ShadowPassNode` are now encoded in parallel,
giving _greatly_ increased CPU performance, mainly when shadow mapping
is enabled.
- Does not work on WASM or AMD+Windows+Vulkan.
- Added `RenderContext::add_command_buffer_generation_task()`.
- `RenderContext::new()` now takes adapter info
- Some render graph and Node related types and methods now have
additional lifetime constraints.
## Migration Guide
`RenderContext::new()` now takes adapter info
- Some render graph and Node related types and methods now have
additional lifetime constraints.
---------
Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
Co-authored-by: François <mockersf@gmail.com>
# Objective
While profiling around to validate the results of #9172, I noticed that
`present_frames` can take a significant amount of time. Digging into the
cause, it seems like we're creating a new `QueryState` from scratch
every frame. This involves scanning the entire World's metadata instead
of just updating its view of the world.
## Solution
Use a `SystemState` argument to cache the `QueryState` to avoid this
construction cost.
## Performance
Against `many_foxes`, this seems to cut the time spent in
`present_frames` by nearly almost 2x. Yellow is this PR, red is main.
![image](https://github.com/bevyengine/bevy/assets/3137680/2b02bbe0-6219-4255-958d-b690e37e7fba)
# Objective
#11431 and #11688 implemented meshing support for Bevy's new geometric
primitives. The next step is to deprecate the shapes in
`bevy_render::mesh::shape` and to later remove them completely for 0.14.
## Solution
Deprecate the shapes and reduce code duplication by utilizing the
primitive meshing API for the old shapes where possible.
Note that some shapes have behavior that can't be exactly reproduced
with the new primitives yet:
- `Box` is more of an AABB with min/max extents
- `Plane` supports a subdivision count
- `Quad` has a `flipped` property
These types have not been changed to utilize the new primitives yet.
---
## Changelog
- Deprecated all shapes in `bevy_render::mesh::shape`
- Changed all examples to use new primitives for meshing
## Migration Guide
Bevy has previously used rendering-specific types like `UVSphere` and
`Quad` for primitive mesh shapes. These have now been deprecated to use
the geometric primitives newly introduced in version 0.13.
Some examples:
```rust
let before = meshes.add(shape::Box::new(5.0, 0.15, 5.0));
let after = meshes.add(Cuboid::new(5.0, 0.15, 5.0));
let before = meshes.add(shape::Quad::default());
let after = meshes.add(Rectangle::default());
let before = meshes.add(shape::Plane::from_size(5.0));
// The surface normal can now also be specified when using `new`
let after = meshes.add(Plane3d::default().mesh().size(5.0, 5.0));
let before = meshes.add(
Mesh::try_from(shape::Icosphere {
radius: 0.5,
subdivisions: 5,
})
.unwrap(),
);
let after = meshes.add(Sphere::new(0.5).mesh().ico(5).unwrap());
```
# Objective
- Try not to drop the render world on the render thread, and drop the
main world after the render world.
- The render world has a drop check that will panic if it is dropped off
the main thread.
## Solution
- Keep track of where the render world is and wait for it to come back
when the channel resource is dropped.
---
## Changelog
- Wait for the render world when the main world is dropped.
## Migration Guide
- If you were using the pipelined rendering channels,
`MainToRenderAppSender` and `RenderToMainAppReceiver`, they have been
combined into the single resource `RenderAppChannels`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Friz64 <friz64@protonmail.com>
> Follow up to #10588
> Closes#11749 (Supersedes #11756)
Enable Texture slicing for the following UI nodes:
- `ImageBundle`
- `ButtonBundle`
<img width="739" alt="Screenshot 2024-01-29 at 13 57 43"
src="https://github.com/bevyengine/bevy/assets/26703856/37675681-74eb-4689-ab42-024310cf3134">
I also added a collection of `fantazy-ui-borders` from
[Kenney's](www.kenney.nl) assets, with the appropriate license (CC).
If it's a problem I can use the same textures as the `sprite_slice`
example
# Work done
Added the `ImageScaleMode` component to the targetted bundles, most of
the logic is directly reused from `bevy_sprite`.
The only additional internal component is the UI specific
`ComputedSlices`, which does the same thing as its spritee equivalent
but adapted to UI code.
Again the slicing is not compatible with `TextureAtlas`, it's something
I need to tackle more deeply in the future
# Fixes
* [x] I noticed that `TextureSlicer::compute_slices` could infinitely
loop if the border was larger that the image half extents, now an error
is triggered and the texture will fallback to being stretched
* [x] I noticed that when using small textures with very small *tiling*
options we could generate hundred of thousands of slices. Now I set a
minimum size of 1 pixel per slice, which is already ridiculously small,
and a warning will be sent at runtime when slice count goes above 1000
* [x] Sprite slicing with `flip_x` or `flip_y` would give incorrect
results, correct flipping is now supported to both sprites and ui image
nodes thanks to @odecay observation
# GPU Alternative
I create a separate branch attempting to implementing 9 slicing and
tiling directly through the `ui.wgsl` fragment shader. It works but
requires sending more data to the GPU:
- slice border
- tiling factors
And more importantly, the actual quad *scale* which is hard to put in
the shader with the current code, so that would be for a later iteration
[`ScheduleLabel`] derive macro uses "ScheduleName" as the trait name by
mistake. This only affects the error message when a user tries to use
the derive macro on a union type. No other code is affected.
# Objective
- This aims to fix#11755
- After #10812 some pipeline compilation can take more time than before
and all call to `get_render_pipeline` should check the result.
## Solution
- Check `get_render_pipeline` call result for msaa_writeback
- I checked that no other call to `get_render_pipeline` in bevy code
base is missng the checking on the result.
Don't try to create a uniform buffer for light probes if there are no
views.
Fixes the panic on examples that have no views, such as
`touch_input_events`.
# Objective
Fix https://github.com/bevyengine/bevy/issues/11657
## Solution
Add a `ReflectKind` enum, add `Reflect::reflect_kind` which returns a
`ReflectKind`, and add `kind` method implementions to `ReflectRef`,
`ReflectMut`, and `ReflectOwned`, which returns a `ReflectKind`.
I also changed `AccessError` to use this new struct instead of it's own
`TypeKind` struct.
---
## Changelog
- Added `ReflectKind`, an enumeration over the kinds of a reflected type
without its data.
- Added `Reflect::reflect_kind` (with default implementation)
- Added implementation for the `kind` method on `ReflectRef`,
`ReflectMut`, and `ReflectOwned` which gives their kind without any
information, as a `ReflectKind`
# Objective
- Fixes#11740
## Solution
- Turned `Mesh::set_indices` into `Mesh::insert_indices` and added
related methods for completeness.
---
## Changelog
- Replaced `Mesh::set_indices(indices: Option<Indices>)` with
`Mesh::insert_indices(indices: Indices)`
- Replaced `Mesh::with_indices(indices: Option<Indices>)` with
`Mesh::with_inserted_indices(indices: Indices)` and
`Mesh::with_removed_indices()` mirroring the API for inserting /
removing attributes.
- Updated the examples and internal uses of the APIs described above.
## Migration Guide
- Use `Mesh::insert_indices` or `Mesh::with_inserted_indices` instead of
`Mesh::set_indices` / `Mesh::with_indices`.
- If you have passed `None` to `Mesh::set_indices` or
`Mesh::with_indices` you should use `Mesh::remove_indices` or
`Mesh::with_removed_indices` instead.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- System `create_surfaces` needs to happen before `prepare_windows` or
we lose one frame at startup
## Solution
- Specify the ordering, remove the set as it doesn't mean anything there
# Objective
Bevy could benefit from *irradiance volumes*, also known as *voxel
global illumination* or simply as light probes (though this term is not
preferred, as multiple techniques can be called light probes).
Irradiance volumes are a form of baked global illumination; they work by
sampling the light at the centers of each voxel within a cuboid. At
runtime, the voxels surrounding the fragment center are sampled and
interpolated to produce indirect diffuse illumination.
## Solution
This is divided into two sections. The first is copied and pasted from
the irradiance volume module documentation and describes the technique.
The second part consists of notes on the implementation.
### Overview
An *irradiance volume* is a cuboid voxel region consisting of
regularly-spaced precomputed samples of diffuse indirect light. They're
ideal if you have a dynamic object such as a character that can move
about
static non-moving geometry such as a level in a game, and you want that
dynamic object to be affected by the light bouncing off that static
geometry.
To use irradiance volumes, you need to precompute, or *bake*, the
indirect
light in your scene. Bevy doesn't currently come with a way to do this.
Fortunately, [Blender] provides a [baking tool] as part of the Eevee
renderer, and its irradiance volumes are compatible with those used by
Bevy.
The [`bevy-baked-gi`] project provides a tool, `export-blender-gi`, that
can
extract the baked irradiance volumes from the Blender `.blend` file and
package them up into a `.ktx2` texture for use by the engine. See the
documentation in the `bevy-baked-gi` project for more details as to this
workflow.
Like all light probes in Bevy, irradiance volumes are 1×1×1 cubes that
can
be arbitrarily scaled, rotated, and positioned in a scene with the
[`bevy_transform::components::Transform`] component. The 3D voxel grid
will
be stretched to fill the interior of the cube, and the illumination from
the
irradiance volume will apply to all fragments within that bounding
region.
Bevy's irradiance volumes are based on Valve's [*ambient cubes*] as used
in
*Half-Life 2* ([Mitchell 2006], slide 27). These encode a single color
of
light from the six 3D cardinal directions and blend the sides together
according to the surface normal.
The primary reason for choosing ambient cubes is to match Blender, so
that
its Eevee renderer can be used for baking. However, they also have some
advantages over the common second-order spherical harmonics approach:
ambient cubes don't suffer from ringing artifacts, they are smaller (6
colors for ambient cubes as opposed to 9 for spherical harmonics), and
evaluation is faster. A smaller basis allows for a denser grid of voxels
with the same storage requirements.
If you wish to use a tool other than `export-blender-gi` to produce the
irradiance volumes, you'll need to pack the irradiance volumes in the
following format. The irradiance volume of resolution *(Rx, Ry, Rz)* is
expected to be a 3D texture of dimensions *(Rx, 2Ry, 3Rz)*. The
unnormalized
texture coordinate *(s, t, p)* of the voxel at coordinate *(x, y, z)*
with
side *S* ∈ *{-X, +X, -Y, +Y, -Z, +Z}* is as follows:
```text
s = x
t = y + ⎰ 0 if S ∈ {-X, -Y, -Z}
⎱ Ry if S ∈ {+X, +Y, +Z}
⎧ 0 if S ∈ {-X, +X}
p = z + ⎨ Rz if S ∈ {-Y, +Y}
⎩ 2Rz if S ∈ {-Z, +Z}
```
Visually, in a left-handed coordinate system with Y up, viewed from the
right, the 3D texture looks like a stacked series of voxel grids, one
for
each cube side, in this order:
| **+X** | **+Y** | **+Z** |
| ------ | ------ | ------ |
| **-X** | **-Y** | **-Z** |
A terminology note: Other engines may refer to irradiance volumes as
*voxel
global illumination*, *VXGI*, or simply as *light probes*. Sometimes
*light
probe* refers to what Bevy calls a reflection probe. In Bevy, *light
probe*
is a generic term that encompasses all cuboid bounding regions that
capture
indirect illumination, whether based on voxels or not.
Note that, if binding arrays aren't supported (e.g. on WebGPU or WebGL
2),
then only the closest irradiance volume to the view will be taken into
account during rendering.
[*ambient cubes*]:
https://advances.realtimerendering.com/s2006/Mitchell-ShadingInValvesSourceEngine.pdf
[Mitchell 2006]:
https://advances.realtimerendering.com/s2006/Mitchell-ShadingInValvesSourceEngine.pdf
[Blender]: http://blender.org/
[baking tool]:
https://docs.blender.org/manual/en/latest/render/eevee/render_settings/indirect_lighting.html
[`bevy-baked-gi`]: https://github.com/pcwalton/bevy-baked-gi
### Implementation notes
This patch generalizes light probes so as to reuse as much code as
possible between irradiance volumes and the existing reflection probes.
This approach was chosen because both techniques share numerous
similarities:
1. Both irradiance volumes and reflection probes are cuboid bounding
regions.
2. Both are responsible for providing baked indirect light.
3. Both techniques involve presenting a variable number of textures to
the shader from which indirect light is sampled. (In the current
implementation, this uses binding arrays.)
4. Both irradiance volumes and reflection probes require gathering and
sorting probes by distance on CPU.
5. Both techniques require the GPU to search through a list of bounding
regions.
6. Both will eventually want to have falloff so that we can smoothly
blend as objects enter and exit the probes' influence ranges. (This is
not implemented yet to keep this patch relatively small and reviewable.)
To do this, we generalize most of the methods in the reflection probes
patch #11366 to be generic over a trait, `LightProbeComponent`. This
trait is implemented by both `EnvironmentMapLight` (for reflection
probes) and `IrradianceVolume` (for irradiance volumes). Using a trait
will allow us to add more types of light probes in the future. In
particular, I highly suspect we will want real-time reflection planes
for mirrors in the future, which can be easily slotted into this
framework.
## Changelog
> This section is optional. If this was a trivial fix, or has no
externally-visible impact, you can delete this section.
### Added
* A new `IrradianceVolume` asset type is available for baked voxelized
light probes. You can bake the global illumination using Blender or
another tool of your choice and use it in Bevy to apply indirect
illumination to dynamic objects.
# Objective
Split up from #11007, fixing most of the remaining work for #10569.
Implement `Meshable` for `Cuboid`, `Sphere`, `Cylinder`, `Capsule`,
`Torus`, and `Plane3d`. This covers all shapes that Bevy has mesh
structs for in `bevy_render::mesh::shapes`.
`Cone` and `ConicalFrustum` are new shapes, so I can add them in a
follow-up, or I could just add them here directly if that's preferrable.
## Solution
Implement `Meshable` for `Cuboid`, `Sphere`, `Cylinder`, `Capsule`,
`Torus`, and `Plane3d`.
The logic is mostly just a copy of the the existing `bevy_render`
shapes, but `Plane3d` has a configurable surface normal that affects the
orientation. Some property names have also been changed to be more
consistent.
The default values differ from the old shapes to make them a bit more
logical:
- Spheres now have a radius of 0.5 instead of 1.0. The default capsule
is equivalent to the default cylinder with the sphere's halves glued on.
- The inner and outer radius of the torus are now 0.5 and 1.0 instead of
0.5 and 1.5 (i.e. the new minor and major radii are 0.25 and 0.75). It's
double the width of the default cuboid, half of its height, and the
default sphere matches the size of the hole.
- `Cuboid` is 1x1x1 by default unlike the dreaded `Box` which is 2x1x1.
Before, with "old" shapes:
![old](https://github.com/bevyengine/bevy/assets/57632562/733f3dda-258c-4491-8152-9829e056a1a3)
Now, with primitive meshing:
![new](https://github.com/bevyengine/bevy/assets/57632562/5a1af14f-bb98-401d-82cf-de8072fea4ec)
I only changed the `3d_shapes` example to use primitives for now. I can
change them all in this PR or a follow-up though, whichever way is
preferrable.
### Sphere API
Spheres have had separate `Icosphere` and `UVSphere` structs, but with
primitives we only have one `Sphere`.
We need to handle this with builders:
```rust
// Existing structs
let ico = Mesh::try_from(Icophere::default()).unwrap();
let uv = Mesh::from(UVSphere::default());
// Primitives
let ico = Sphere::default().mesh().ico(5).unwrap();
let uv = Sphere::default().mesh().uv(32, 18);
```
We could add methods on `Sphere` directly to skip calling `.mesh()`.
I also added a `SphereKind` enum that can be used with the `kind`
method:
```rust
let ico = Sphere::default()
.mesh()
.kind(SphereKind::Ico { subdivisions: 8 })
.build();
```
The default mesh for a `Sphere` is an icosphere with 5 subdivisions
(like the default `Icosphere`).
---
## Changelog
- Implement `Meshable` and `Default` for `Cuboid`, `Sphere`, `Cylinder`,
`Capsule`, `Torus`, and `Plane3d`
- Use primitives in `3d_shapes` example
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- The exported hashtypes are just re-exports from hashbrown, we want to
drop that dependency and (in the future) let the user import their own
choice.
- Fixes#11717
## Solution
- Adding a deprecated tag on the re-exports, so in future releases these
can be safely removed.
# Objective
During my exploratory work on the remote editor, I found a couple of
types that were either not registered, or that were missing
`ReflectDefault`.
## Solution
- Added registration and `ReflectDefault` where applicable
- (Drive by fix) Moved `Option<f32>` registration to `bevy_core` instead
of `bevy_ui`, along with similar types.
---
## Changelog
- Fixed: Registered `FogSettings`, `FogFalloff`,
`ParallaxMappingMethod`, `OpaqueRendererMethod` structs for reflection
- Fixed: Registered `ReflectDefault` trait for `ColorGrading` and
`CascadeShadowConfig` structs
# Objective
Includes the UI node size as a parameter to the UiMaterial shader,
useful for SDF-based rendering, aspect ratio correction and other use
cases.
Fixes#11392
## Solution
Added the node size to the UiMaterial vertex shader params and also to
the data that is passed to the fragment shader.
## Migration Guide
This change should be backwards compatible, using the new field is
optional.
Note to reviewers: render pipelines are a bit outside my comfort zone,
so please make sure I haven't made any mistakes.
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
- Fixes#11679
## Solution
- Added `IntoSystem::system_type_id` which returns the equivalent of
`system.into_system().type_id()` without construction. This allows for
getting the `TypeId` of functions (a function is an unnamed type and
therefore you cannot call `TypeId::of::<apply_deferred::System>()`)
- Added default implementation of `System::type_id` to ensure
consistency between implementations. Some returned `Self`, while others
were returning an inner value instead. This ensures consistency with
`IntoSystem::system_type_id`.
## Migration Guide
If you use `System::type_id()` on function systems (exclusive or not),
ensure you are comparing its value to other `System::type_id()` calls,
or `IntoSystem::system_type_id()`.
This code wont require any changes, because `IntoSystem`'s are directly
compared to each other.
```rust
fn test_system() {}
let type_id = test_system.type_id();
// ...
// No change required
assert_eq!(test_system.type_id(), type_id);
```
Likewise, this code wont, because `System`'s are directly compared.
```rust
fn test_system() {}
let type_id = IntoSystem::into_system(test_system).type_id();
// ...
// No change required
assert_eq!(IntoSystem::into_system(test_system).type_id(), type_id);
```
The below _does_ require a change, since you're comparing a `System`
type to a `IntoSystem` type.
```rust
fn test_system() {}
// Before
assert_eq!(test_system.type_id(), IntoSystem::into_system(test_system).type_id());
// After
assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).type_id());
```
# Objective
- There are too many `NonSendMarker`
https://docs.rs/bevy/0.12.1/bevy/index.html?search=nonsendmarker
- There should be only one
## Solution
- Use the marker type from bevy_core in bevy_render
---
## Migration Guide
- If you were using `bevy::render::view::NonSendMarker` or
`bevy::render::view:🪟:NonSendMarker`, use
`bevy::core::NonSendMarker` instead
# Objective
Bevy does ridiculous amount of drawcalls, and our batching isn't very
effective because we sort by distance and only batch if we get multiple
of the same object in a row. This can give us slightly better GPU
performance when not using the depth prepass (due to less overdraw), but
ends up being massively CPU bottlenecked due to doing thousands of
unnecessary drawcalls.
## Solution
Change the sort functions to sort by pipeline key then by mesh id for
large performance gains in more realistic scenes than our stress tests.
Pipelines changed:
- Opaque3d
- Opaque3dDeferred
- Opaque3dPrepass
![image](https://github.com/bevyengine/bevy/assets/177631/8c355256-ad86-4b47-81a0-f3906797fe7e)
---
## Changelog
- Opaque3d drawing order is now sorted by pipeline and mesh, rather than
by distance. This trades off a bit of GPU time in exchange for massively
better batching in scenes that aren't only drawing huge amounts of a
single object.
# Objective
- Change set of systems as I made a mistake in #11672
- Don't block main when not needed
- Fixes#11235
## Solution
- add a run condition so that the system won't run and block main if not
needed
# Objective
- Some places manually use a `bool` /`AtomicBool` to warn once.
## Solution
- Use the `warn_once` macro which internally creates an `AtomicBool`.
Downside: in some case the warning state would have been reset after
recreating the struct carrying the warn state, whereas now it will
always warn only once per program run (For example, if all
`MeshPipeline`s are dropped or the `World` is recreated for
`Local<bool>`/ a `bool` resource, which shouldn't happen over the course
of a standard `App` run).
---
## Changelog
### Removed
- `FontAtlasWarning` has been removed, but the corresponding warning is
still emitted.
# Objective
We currently over/underpromise hash stability:
- `HashMap`/`HashSet` use `BuildHasherDefault<AHasher>` instead of
`RandomState`. As a result, the hash is stable within the same run.
- [aHash isn't stable between devices (and
versions)](https://github.com/tkaitchuck/ahash?tab=readme-ov-file#goals-and-non-goals),
yet it's used for `StableHashMap`/`StableHashSet`
- the specialized hashmaps are stable
Interestingly, `StableHashMap`/`StableHashSet` aren't used by Bevy
itself (anymore).
## Solution
Add/fix documentation
## Alternatives
For `StableHashMap`/`StableHashSet`:
- remove them
- revive #7107
---
## Changelog
- added iteration stability guarantees for different hashmaps
This is just a minor fix extracted from #11697
A logic error. We tried to close the polygon shape, if the user
specifies an
unclosed polygon. The closing linestring previously didn't close the
polygon
though, but instead added a zero length line at the last coordinate.
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
I wanted to pass in a `String` to `DynamicStruct::insert_boxed` but it
took in a &str. That's fine but I also saw that it immediately converted
the `&str` to a `String`. Which is wasteful.
## Solution
I made `DynamicStruct::insert_boxed` take in a `impl Into<Cow<str>>`.
Same for `DynamicStruct::insert`.
---
## Changelog
- `DynamicStruct::insert_boxed` and `DynamicStruct::insert` now support
taking in anything that implements `impl Into<Cow<str>>`.
# Objective
Send `SceneInstanceReady` only once per scene.
## Solution
I assume that this was not intentional.
So I just changed it to only be sent once per scene.
---
## Changelog
### Fixed
- Fixed `SceneInstanceReady` being emitted for every `Entity` in a
scene.
# Objective
- Pipeline compilation is slow and blocks the frame
- Closes https://github.com/bevyengine/bevy/issues/8224
## Solution
- Compile pipelines in a Task on the AsyncComputeTaskPool
---
## Changelog
- Render/compute pipeline compilation is now done asynchronously over
multiple frames when the multi-threaded feature is enabled and on
non-wasm and non-macOS platforms
- Added `CachedPipelineState::Creating`
- Added `PipelineCache::block_on_render_pipeline()`
- Added `bevy_utils::futures::check_ready`
- Added `bevy_render/multi-threaded` cargo feature
## Migration Guide
- Match on the new `Creating` variant for exhaustive matches of
`CachedPipelineState`
# Objective
- Fixes #4188, make users could set application ID for bevy apps.
## Solution
- Add `name` field to `bevy:🪟:Window`. Specifying this field adds
different properties to the window: application ID on `Wayland`,
`WM_CLASS` on `X11`, or window class name on Windows. It has no effect
on other platforms.
---
## Changelog
### Added
- Add `name` to `bevy:🪟:Window`.
## Migration Guide
- Set the `bevy_window::Window`'s `name` field when needed:
```rust
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "I am a window!".into(),
name: Some("SpaceGameCompany.SpaceShooter".into()),
..default()
}),
..default()
}))
.run();
```
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
Fixes#11653
## Solution
- Just added the formats to the docstring, I played around with having
the format appear in the type somehow so that it didn't need to be
written manually in the docstring but it ended up being more trouble
than it was worth.
Co-authored-by: James Liu <contact@jamessliu.com>
Frustum computation is nontrivial amount of code private in
`update_frusta` system.
Make it public.
This is needed to decide which entities to spawn/despawn in `Update`
based on camera changes. But if `Update` also changed camera, frustum is
not yet recomputed.
Technically it is probably possible to run an iteration of
`update_frusta` system by a user in `Update` schedule after propagating
`GlobalTransform` to the cameras, but it is easier to just compute
frustum manually using API added in this PR.
Also replace two places where this code is used.
---------
Co-authored-by: vero <email@atlasdostal.com>
# Objective
- (Partially) Fixes#9904
- Acts on #9910
## Solution
- Deprecated the relevant methods from `Query`, cascading changes as
required across Bevy.
---
## Changelog
- Deprecated `QueryState::get_component_unchecked_mut` method
- Deprecated `Query::get_component` method
- Deprecated `Query::get_component_mut` method
- Deprecated `Query::component` method
- Deprecated `Query::component_mut` method
- Deprecated `Query::get_component_unchecked_mut` method
## Migration Guide
### `QueryState::get_component_unchecked_mut`
Use `QueryState::get_unchecked_manual` and select for the exact
component based on the structure of the exact query as required.
### `Query::(get_)component(_unchecked)(_mut)`
Use `Query::get` and select for the exact component based on the
structure of the exact query as required.
- For mutable access (`_mut`), use `Query::get_mut`
- For unchecked access (`_unchecked`), use `Query::get_unchecked`
- For panic variants (non-`get_`), add `.unwrap()`
## Notes
- `QueryComponentError` can be removed once these deprecated methods are
also removed. Due to an interaction with `thiserror`'s derive macro, it
is not marked as deprecated.
Use `TypeIdMap<T>` instead of `HashMap<TypeId, T>`
- ~~`TypeIdMap` was in `bevy_ecs`. I've kept it there because of
#11478~~
- ~~I haven't swapped `bevy_reflect` over because it doesn't depend on
`bevy_ecs`, but I'd also be happy with moving `TypeIdMap` to
`bevy_utils` and then adding a dependency to that~~
- ~~this is a slight change in the public API of
`DrawFunctionsInternal`, does this need to go in the changelog?~~
## Changelog
- moved `TypeIdMap` to `bevy_utils`
- changed `DrawFunctionsInternal::indices` to `TypeIdMap`
## Migration Guide
- `TypeIdMap` now lives in `bevy_utils`
- `DrawFunctionsInternal::indices` now uses a `TypeIdMap`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Update `tracing-tracy`.
- Closes#11598.
## Solution
- Bump `tracing-tracy` to 0.11.0 and `tracy-client` alongside it to
0.17.0 to avoid duplicating that dependency in the deps tree.
- `TracyLayer` is now configurable on creation, so use the default
config.
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# Objective
Currently the `missing_docs` lint is allowed-by-default and enabled at
crate level when their documentations is complete (see #3492).
This PR proposes to inverse this logic by making `missing_docs`
warn-by-default and mark crates with imcomplete docs allowed.
## Solution
Makes `missing_docs` warn at workspace level and allowed at crate level
when the docs is imcomplete.
# Objective
- Allow prepare windows to run off of the main thread on all platforms.
- Fixes https://github.com/bevyengine/bevy/issues/9964 on all platforms.
## Solution
- Running `prepare_windows` on the main thread on apple platforms is
only mandatory to create surface, which is only needed during window
creation. Split that part into its own system that happens before
`prepare_windows`
- Tested on macOS and iOS
---
## Changelog
- Allow prepare windows to run off main thread on all platforms.
# Objective
Add interactive system debugging capabilities to bevy, providing
step/break/continue style capabilities to running system schedules.
* Original implementation: #8063
- `ignore_stepping()` everywhere was too much complexity
* Schedule-config & Resource discussion: #8168
- Decided on selective adding of Schedules & Resource-based control
## Solution
Created `Stepping` Resource. This resource can be used to enable
stepping on a per-schedule basis. Systems within schedules can be
individually configured to:
* AlwaysRun: Ignore any stepping state and run every frame
* NeverRun: Never run while stepping is enabled
- this allows for disabling of systems while debugging
* Break: If we're running the full frame, stop before this system is run
Stepping provides two modes of execution that reflect traditional
debuggers:
* Step-based: Only execute one system at a time
* Continue/Break: Run all systems, but stop before running a system
marked as Break
### Demo
https://user-images.githubusercontent.com/857742/233630981-99f3bbda-9ca6-4cc4-a00f-171c4946dc47.mov
Breakout has been modified to use Stepping. The game runs normally for a
couple of seconds, then stepping is enabled and the game appears to
pause. A list of Schedules & Systems appears with a cursor at the first
System in the list. The demo then steps forward full frames using the
spacebar until the ball is about to hit a brick. Then we step system by
system as the ball impacts a brick, showing the cursor moving through
the individual systems. Finally the demo switches back to frame stepping
as the ball changes course.
### Limitations
Due to architectural constraints in bevy, there are some cases systems
stepping will not function as a user would expect.
#### Event-driven systems
Stepping does not support systems that are driven by `Event`s as events
are flushed after 1-2 frames. Although game systems are not running
while stepping, ignored systems are still running every frame, so events
will be flushed.
This presents to the user as stepping the event-driven system never
executes the system. It does execute, but the events have already been
flushed.
This can be resolved by changing event handling to use a buffer for
events, and only dropping an event once all readers have read it.
The work-around to allow these systems to properly execute during
stepping is to have them ignore stepping:
`app.add_systems(event_driven_system.ignore_stepping())`. This was done
in the breakout example to ensure sound played even while stepping.
#### Conditional Systems
When a system is stepped, it is given an opportunity to run. If the
conditions of the system say it should not run, it will not.
Similar to Event-driven systems, if a system is conditional, and that
condition is only true for a very small time window, then stepping the
system may not execute the system. This includes depending on any sort
of external clock.
This exhibits to the user as the system not always running when it is
stepped.
A solution to this limitation is to ensure any conditions are consistent
while stepping is enabled. For example, all systems that modify any
state the condition uses should also enable stepping.
#### State-transition Systems
Stepping is configured on the per-`Schedule` level, requiring the user
to have a `ScheduleLabel`.
To support state-transition systems, bevy generates needed schedules
dynamically. Currently it’s very difficult (if not impossible, I haven’t
verified) for the user to get the labels for these schedules.
Without ready access to the dynamically generated schedules, and a
resolution for the `Event` lifetime, **stepping of the state-transition
systems is not supported**
---
## Changelog
- `Schedule::run()` updated to consult `Stepping` Resource to determine
which Systems to run each frame
- Added `Schedule.label` as a `BoxedSystemLabel`, along with supporting
`Schedule::set_label()` and `Schedule::label()` methods
- `Stepping` needed to know which `Schedule` was running, and prior to
this PR, `Schedule` didn't track its own label
- Would have preferred to add `Schedule::with_label()` and remove
`Schedule::new()`, but this PR touches enough already
- Added calls to `Schedule.set_label()` to `App` and `World` as needed
- Added `Stepping` resource
- Added `Stepping::begin_frame()` system to `MainSchedulePlugin`
- Run before `Main::run_main()`
- Notifies any `Stepping` Resource a new render frame is starting
## Migration Guide
- Add a call to `Schedule::set_label()` for any custom `Schedule`
- This is only required if the `Schedule` will be stepped
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- In #9822 I forgot to disable auto sync points on the Extract Schedule.
We want to do this because the Commands on the Extract Schedule should
be applied on the render thread.
# Objective
- Allow prepare windows to run off of the main thread on platforms that
allow it.
- Fixes https://github.com/bevyengine/bevy/issues/9964 on most
platforms.
## Solution
- Conditionally compile prepare windows for different OS's
- Seems like it's only the call to `create_surface` that needs to run on
the main thread here.
- I've only tested this on windows, but I do see prepare windows running
on other threads.
---
## Changelog
- Allow prepare windows to run off main thread on platforms that allow
it.
# Objective
Allow animation of types other than translation, scale, and rotation on
`Transforms`.
## Solution
Add a base trait for all values that can be animated by the animation
system. This provides the basic operations for sampling and blending
animation values for more than just translation, rotation, and scale.
This implements part of bevyengine/rfcs#51, but is missing the
implementations for `Range<T>` and `Color`. This also does not fully
integrate with the existing `AnimationPlayer` yet, just setting up the
trait.
---------
Co-authored-by: Kirillov Kirill <kirusfg@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: irate <JustTheCoolDude@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
Fix an issue where events are not being dropped after being read. I
believe #10077 introduced this issue. The code currently works as
follows:
1. `EventUpdateSignal` is **shared for all event types**
2. During the fixed update phase, `EventUpdateSignal` is set to true
3. `event_update_system`, **unique per event type**, runs to update
Events<T>
4. `event_update_system` reads value of `EventUpdateSignal` to check if
it should update, and then **resets** the value to false
If there are multiple event types, the first `event_update_system` run
will reset the shared `EventUpdateSignal` signal, preventing other
events from being cleared.
## Solution
I've updated the code to have separate signals per event type and added
a shared signal to notify all systems that the time plugin is installed.
## Changelog
- Fixed bug where events were not being dropped
The PR is in a reviewable state now in the sense that the basic
implementations are there. There are still some ToDos that I'm aware of:
- [x] docs for all the new structs and traits
- [x] implement `Default` and derive other useful traits for the new
structs
- [x] Take a look at the notes again (Do this after a first round of
reviews)
- [x] Take care of the repetition in the circle drawing functions
---
# Objective
- TLDR: This PR enables us to quickly draw all the newly added
primitives from `bevy_math` in immediate mode with gizmos
- Addresses #10571
## Solution
- This implements the first design idea I had that covered everything
that was mentioned in the Issue
https://github.com/bevyengine/bevy/issues/10571#issuecomment-1863646197
---
## Caveats
- I added the `Primitive(2/3)d` impls for `Direction(2/3)d` to make them
work with the current solution. We could impose less strict requirements
for the gizmoable objects and remove the impls afterwards if the
community doesn't like the current approach.
---
## Changelog
- implement capabilities to draw ellipses on the gizmo in general (this
was required to have some code which is able to draw the ellipse
primitive)
- refactored circle drawing code to use the more general ellipse drawing
code to keep code duplication low
- implement `Primitive2d` for `Direction2d` and impl `Primitive3d` for
`Direction3d`
- implement trait to draw primitives with specialized details with
gizmos
- `GizmoPrimitive2d` for all the 2D primitives
- `GizmoPrimitive3d` for all the 3D primitives
- (question while writing this: Does it actually matter if we split this
in 2D and 3D? I guess it could be useful in the future if we do
something based on the main rendering mode even though atm it's kinda
useless)
---
---------
Co-authored-by: nothendev <borodinov.ilya@gmail.com>
# Objective
Glyph positions don't account for padding added to the font texture
atlas, resulting in them being off by one physical pixel in both axis.
## Example
```rust
use bevy::{
prelude::*, window::WindowResolution
};
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: WindowResolution::default().with_scale_factor_override(1.),
..Default::default()
}),
..Default::default()
}))
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
commands.spawn(
TextBundle::from_section(
"QQQQQ",
TextStyle {
font: asset_server.load("FiraMono-Medium.ttf"),
font_size: 14.0,
..default()
},
)
.with_style(Style {
left:Val::Px(10.),
top: Val::Px(10.),
..default()
})
.with_background_color(Color::RED)
);
}
```
<img width="350" alt="QQQQQ-bad"
src="https://github.com/bevyengine/bevy/assets/27962798/6a509aee-64c8-4ee8-a8c1-77ee65355898">
The coordinates are off by one in physical coordinates, not logical. So
the difference only becomes obvious with `UiScale` and the window scale
factor set to low values.
## Solution
Translate glyph positions by -1 in both axes.
<img width="300" alt="QQQQQ-good"
src="https://github.com/bevyengine/bevy/assets/27962798/16e3f6d9-1223-48e0-9fdd-b682a3e8ade4">
---
## Changelog
* Translate the positions for each glyph by -1 in both axes in
`bevy_text::glyph_brush::process_glyphs`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Drawing a `Gizmos::circle` whose normal is derived from a Transform's
local axes now requires converting a Vec3 to a Direction3d and
unwrapping the result, and I think we shold move the conversion into
Bevy.
## Solution
We can make
`Transform::{left,right,up,down,forward,back,local_x,local_y,local_z}`
return a Direction3d, because they know that their results will be of
finite non-zero length (roughly 1.0).
---
## Changelog
`Transform::up()` and similar functions now return `Direction3d` instead
of `Vec3`.
## Migration Guide
Callers of `Transform::up()` and similar functions may have to
dereference the returned `Direction3d` to get to the inner `Vec3`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
- Address #10338
## Solution
- When implementing specular and diffuse transmission, I inadvertently
introduced a performance regression. On high-end hardware it is barely
noticeable, but **for lower-end hardware it can be pretty brutal**. If I
understand it correctly, this is likely due to use of masking by the GPU
to implement control flow, which means that you still pay the price for
the branches you don't take;
- To avoid that, this PR introduces new shader defs (controlled via
`StandardMaterialKey`) that conditionally include the transmission
logic, that way the shader code for both types of transmission isn't
even sent to the GPU if you're not using them;
- This PR also renames ~~`STANDARDMATERIAL_NORMAL_MAP`~~ to
`STANDARD_MATERIAL_NORMAL_MAP` for consistency with the naming
convention used elsewhere in the codebase. (Drive-by fix)
---
## Changelog
- Added new shader defs, set when using transmission in the
`StandardMaterial`:
- `STANDARD_MATERIAL_SPECULAR_TRANSMISSION`;
- `STANDARD_MATERIAL_DIFFUSE_TRANSMISSION`;
- `STANDARD_MATERIAL_SPECULAR_OR_DIFFUSE_TRANSMISSION`.
- Fixed performance regression caused by the introduction of
transmission, by gating transmission shader logic behind the newly
introduced shader defs;
- Renamed ~~`STANDARDMATERIAL_NORMAL_MAP`~~ to
`STANDARD_MATERIAL_NORMAL_MAP` for consistency;
## Migration Guide
- If you were using `#ifdef STANDARDMATERIAL_NORMAL_MAP` on your shader
code, make sure to update the name to `STANDARD_MATERIAL_NORMAL_MAP`;
(with an underscore between `STANDARD` and `MATERIAL`)
# Objective
- `RayTest` vs `AabbCast` and `CircleCast` is inconsistent
## Solution
- Renaming the other two would only make the name more confusing, so we
rename `RayTest2d/3d` to `RayCast2d/3d`
# Objective
- `AssetTransformer` provides an input asset, and output an asset, but
provides no access to the `LabeledAsset`'s created by the `AssetLoader`.
Labeled sub assets are an extremely important piece of many assets, Gltf
in particular, and without them the amount of transformation on an asset
is limited. In order for `AssetTransformer`'s to be useful, they need to
have access to these sub assets.
- LabeledAsset's loaded by `AssetLoader`s are provided to `AssetSaver`s
in the `LoadAndSave` process, but the `LoadTransformAndSave` process
drops these values in the transform stage, and so `AssetSaver` is given
none.
- Fixes#11606
Ideally the AssetTransformer should not ignore labeled sub assets, and
they should be kept at least for the AssetSaver
## Solution
- I created a new struct similar to `SavedAsset` named
`TransformedAsset` which holds the input asset, and the HashMap of
`LabeledAsset`s. The transform function now takes as input a
`TransformedAsset`, and returns a `TransformedAsset::<AssetOutput>`.
This gives the transform function access to the labeled sub assets
created by the `AssetLoader`.
- I also created `TransformedSubAsset` which holds mutable references to
a sub asset and that sub assets HashMap of `LabeledAsset`s. This allows
you to travers the Tree of `LabeledAsset`s by reference relatively
easily.
- The `LoadTransformAndSave` processor was then reworked to use the new
structs, stopping the `LabeledAsset`s from being dropped.
---
## Changelog
- Created TransformedAsset struct and TransformedSubAsset struct.
- Changed `get_untyped_handle` to return a `UntypedHandle` directly
rather than a reference and added `get_handle` as a typed variant in
SavedAsset and TransformedAsset
- Added `SavedAsset::from_transformed` as a constructor from a
`TransformedAsset`
- Switched LoadTransformAndSave process code to work with new
`TransformedAsset` type
- Added a `ProcessError` for `AssetTransformer` in process.rs
- Switched `AssetTransformer::transform` to use `TransformedAsset` as
input and output.
- Switched `AssetTransformer` to use a `BoxedFuture` like `AssetLoader`
and `AssetSaver` to allow for async transformation code.
- Updated AssetTransformer example to use new structure.
# Objective
It's often necessary to rotate directions, but it currently has to be
done like this:
```rust
Direction3d::new_unchecked(quat * *direction)
```
It'd be nice if you could rotate `Direction3d` directly:
```rust
quat * direction
```
## Solution
Implement `Mul<Direction3d>` for `Quat` ~~and the other way around.~~
(Glam doesn't impl `Mul<Quat>` or `MulAssign<Quat>` for `Vec3`)
The quaternion must be a unit quaternion to keep the direction
normalized, so there is a `debug_assert!` to be sure. Almost all `Quat`
constructors produce unit quaternions, so there should only be issues if
doing something like `quat + quat` instead of `quat * quat`, using
`Quat::from_xyzw` directly, or when you have significant enough drift
caused by e.g. physics simulation that doesn't normalize rotation. In
general, these would probably cause unexpected results anyway.
I also moved tests around slightly to make `dim2` and `dim3` more
consistent (`dim3` had *two* separate `test` modules for some reason).
In the future, we'll probably want a `Rotation2d` type that would
support the same for `Direction2d`. I considered implementing
`Mul<Mat2>` for `Direction2d`, but that would probably be more
questionable since `Mat2` isn't as clearly associated with rotations as
`Quat` is.
# Objective
I'm working on a developer console plugin, and I wanted to get a
field/index of a struct/list/tuple. My command parser already parses
member expressions and all that, so I wanted to construct a `ParsedPath`
manually, but it's all private.
## Solution
Make the internals of `ParsedPath` public and add documentation for
everything, and I changed the boxed slice inside `ParsedPath` to a
vector for more flexibility.
I also did a bunch of code cleanup. Improving documentation, error
messages, code, type names, etc.
---
## Changelog
- Added the ability to manually create `ParsedPath`s from their
elements, without the need of string parsing.
- Improved `ReflectPath` error handling.
## Migration Guide
- `bevy::reflect::AccessError` has been refactored.
That should be it I think, everything else that was changed was private
before this PR.
---------
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
- Deriving `Reflect` for some public ChangeDetection/Tick structs in
bevy_ecs
---------
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
# Objective
- Add a basic form of shapecasting for bounding volumes
## Solution
- Implement AabbCast2d, AabbCast3d, BoundingCircleCast, and
BoundingSphereCast
- These are really just raycasts, but they modify the volumes the ray is
casting against
- The tests are slightly simpler, since they just use the raycast code
for the heavy lifting
# Objective
- Addresses **Support processing and loading files without extensions**
from #9714
- Addresses **More runtime loading configuration** from #9714
- Fixes#367
- Fixes#10703
## Solution
`AssetServer::load::<A>` and `AssetServer::load_with_settings::<A>` can
now use the `Asset` type parameter `A` to select a registered
`AssetLoader` without inspecting the provided `AssetPath`. This change
cascades onto `LoadContext::load` and `LoadContext::load_with_settings`.
This allows the loading of assets which have incorrect or ambiguous file
extensions.
```rust
// Allow the type to be inferred by context
let handle = asset_server.load("data/asset_no_extension");
// Hint the type through the handle
let handle: Handle<CustomAsset> = asset_server.load("data/asset_no_extension");
// Explicit through turbofish
let handle = asset_server.load::<CustomAsset>("data/asset_no_extension");
```
Since a single `AssetPath` no longer maps 1:1 with an `Asset`, I've also
modified how assets are loaded to permit multiple asset types to be
loaded from a single path. This allows for two different `AssetLoaders`
(which return different types of assets) to both load a single path (if
requested).
```rust
// Uses GltfLoader
let model = asset_server.load::<Gltf>("cube.gltf");
// Hypothetical Blob loader for data transmission (for example)
let blob = asset_server.load::<Blob>("cube.gltf");
```
As these changes are reflected in the `LoadContext` as well as the
`AssetServer`, custom `AssetLoaders` can also take advantage of this
behaviour to create more complex assets.
---
## Change Log
- Updated `custom_asset` example to demonstrate extension-less assets.
- Added `AssetServer::get_handles_untyped` and Added
`AssetServer::get_path_ids`
## Notes
As a part of that refactor, I chose to store `AssetLoader`s (within
`AssetLoaders`) using a `HashMap<TypeId, ...>` instead of a `Vec<...>`.
My reasoning for this was I needed to add a relationship between `Asset`
`TypeId`s and the `AssetLoader`, so instead of having a `Vec` and a
`HashMap`, I combined the two, removing the `usize` index from the
adjacent maps.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
The whole `Cow<'static, str>` naming for nodes and subgraphs in
`RenderGraph` is a mess.
## Solution
Replaces hardcoded and potentially overlapping strings for nodes and
subgraphs inside `RenderGraph` with bevy's labelsystem.
---
## Changelog
* Two new labels: `RenderLabel` and `RenderSubGraph`.
* Replaced all uses for hardcoded strings with those labels
* Moved `Taa` label from its own mod to all the other `Labels3d`
* `add_render_graph_edges` now needs a tuple of labels
* Moved `ScreenSpaceAmbientOcclusion` label from its own mod with the
`ShadowPass` label to `LabelsPbr`
* Removed `NodeId`
* Renamed `Edges.id()` to `Edges.label()`
* Removed `NodeLabel`
* Changed examples according to the new label system
* Introduced new `RenderLabel`s: `Labels2d`, `Labels3d`, `LabelsPbr`,
`LabelsUi`
* Introduced new `RenderSubGraph`s: `SubGraph2d`, `SubGraph3d`,
`SubGraphUi`
* Removed `Reflect` and `Default` derive from `CameraRenderGraph`
component struct
* Improved some error messages
## Migration Guide
For Nodes and SubGraphs, instead of using hardcoded strings, you now
pass labels, which can be derived with structs and enums.
```rs
// old
#[derive(Default)]
struct MyRenderNode;
impl MyRenderNode {
pub const NAME: &'static str = "my_render_node"
}
render_app
.add_render_graph_node::<ViewNodeRunner<MyRenderNode>>(
core_3d::graph::NAME,
MyRenderNode::NAME,
)
.add_render_graph_edges(
core_3d::graph::NAME,
&[
core_3d::graph::node::TONEMAPPING,
MyRenderNode::NAME,
core_3d::graph::node::END_MAIN_PASS_POST_PROCESSING,
],
);
// new
use bevy::core_pipeline::core_3d::graph::{Labels3d, SubGraph3d};
#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)]
pub struct MyRenderLabel;
#[derive(Default)]
struct MyRenderNode;
render_app
.add_render_graph_node::<ViewNodeRunner<MyRenderNode>>(
SubGraph3d,
MyRenderLabel,
)
.add_render_graph_edges(
SubGraph3d,
(
Labels3d::Tonemapping,
MyRenderLabel,
Labels3d::EndMainPassPostProcessing,
),
);
```
### SubGraphs
#### in `bevy_core_pipeline::core_2d::graph`
| old string-based path | new label |
|-----------------------|-----------|
| `NAME` | `SubGraph2d` |
#### in `bevy_core_pipeline::core_3d::graph`
| old string-based path | new label |
|-----------------------|-----------|
| `NAME` | `SubGraph3d` |
#### in `bevy_ui::render`
| old string-based path | new label |
|-----------------------|-----------|
| `draw_ui_graph::NAME` | `graph::SubGraphUi` |
### Nodes
#### in `bevy_core_pipeline::core_2d::graph`
| old string-based path | new label |
|-----------------------|-----------|
| `node::MSAA_WRITEBACK` | `Labels2d::MsaaWriteback` |
| `node::MAIN_PASS` | `Labels2d::MainPass` |
| `node::BLOOM` | `Labels2d::Bloom` |
| `node::TONEMAPPING` | `Labels2d::Tonemapping` |
| `node::FXAA` | `Labels2d::Fxaa` |
| `node::UPSCALING` | `Labels2d::Upscaling` |
| `node::CONTRAST_ADAPTIVE_SHARPENING` |
`Labels2d::ConstrastAdaptiveSharpening` |
| `node::END_MAIN_PASS_POST_PROCESSING` |
`Labels2d::EndMainPassPostProcessing` |
#### in `bevy_core_pipeline::core_3d::graph`
| old string-based path | new label |
|-----------------------|-----------|
| `node::MSAA_WRITEBACK` | `Labels3d::MsaaWriteback` |
| `node::PREPASS` | `Labels3d::Prepass` |
| `node::DEFERRED_PREPASS` | `Labels3d::DeferredPrepass` |
| `node::COPY_DEFERRED_LIGHTING_ID` | `Labels3d::CopyDeferredLightingId`
|
| `node::END_PREPASSES` | `Labels3d::EndPrepasses` |
| `node::START_MAIN_PASS` | `Labels3d::StartMainPass` |
| `node::MAIN_OPAQUE_PASS` | `Labels3d::MainOpaquePass` |
| `node::MAIN_TRANSMISSIVE_PASS` | `Labels3d::MainTransmissivePass` |
| `node::MAIN_TRANSPARENT_PASS` | `Labels3d::MainTransparentPass` |
| `node::END_MAIN_PASS` | `Labels3d::EndMainPass` |
| `node::BLOOM` | `Labels3d::Bloom` |
| `node::TONEMAPPING` | `Labels3d::Tonemapping` |
| `node::FXAA` | `Labels3d::Fxaa` |
| `node::UPSCALING` | `Labels3d::Upscaling` |
| `node::CONTRAST_ADAPTIVE_SHARPENING` |
`Labels3d::ContrastAdaptiveSharpening` |
| `node::END_MAIN_PASS_POST_PROCESSING` |
`Labels3d::EndMainPassPostProcessing` |
#### in `bevy_core_pipeline`
| old string-based path | new label |
|-----------------------|-----------|
| `taa::draw_3d_graph::node::TAA` | `Labels3d::Taa` |
#### in `bevy_pbr`
| old string-based path | new label |
|-----------------------|-----------|
| `draw_3d_graph::node::SHADOW_PASS` | `LabelsPbr::ShadowPass` |
| `ssao::draw_3d_graph::node::SCREEN_SPACE_AMBIENT_OCCLUSION` |
`LabelsPbr::ScreenSpaceAmbientOcclusion` |
| `deferred::DEFFERED_LIGHTING_PASS` | `LabelsPbr::DeferredLightingPass`
|
#### in `bevy_render`
| old string-based path | new label |
|-----------------------|-----------|
| `main_graph::node::CAMERA_DRIVER` | `graph::CameraDriverLabel` |
#### in `bevy_ui::render`
| old string-based path | new label |
|-----------------------|-----------|
| `draw_ui_graph::node::UI_PASS` | `graph::LabelsUi::UiPass` |
---
## Future work
* Make `NodeSlot`s also use types. Ideally, we have an enum with unit
variants where every variant resembles one slot. Then to make sure you
are using the right slot enum and make rust-analyzer play nicely with
it, we should make an associated type in the `Node` trait. With today's
system, we can introduce 3rd party slots to a node, and i wasnt sure if
this was used, so I didn't do this in this PR.
## Unresolved Questions
When looking at the `post_processing` example, we have a struct for the
label and a struct for the node, this seems like boilerplate and on
discord, @IceSentry (sowy for the ping)
[asked](https://discord.com/channels/691052431525675048/743663924229963868/1175197016947699742)
if a node could automatically introduce a label (or i completely
misunderstood that). The problem with that is, that nodes like
`EmptyNode` exist multiple times *inside the same* (sub)graph, so there
we need extern labels to distinguish between those. Hopefully we can
find a way to reduce boilerplate and still have everything unique. For
EmptyNode, we could maybe make a macro which implements an "empty node"
for a type, but for nodes which contain code and need to be present
multiple times, this could get nasty...
# Objective
- [`thiserror`](https://docs.rs/thiserror/) is used to derive the error
type on `bevy_dynamic_plugin`'s
[`DynamicPluginLoadError`](https://docs.rs/bevy_dynamic_plugin/latest/bevy_dynamic_plugin/enum.DynamicPluginLoadError.html).
- It is an enum where each variant wraps a `libloading` error type.
- `thiserror` supports marking this internal error types as `#[source]`
so it can automatically fill out the
[`Error::source`](https://doc.rust-lang.org/std/error/trait.Error.html#method.source)
method.
- This allows other error handling libraries to get more information
about the error than what Bevy by default provides. It increases
interoperability between libraries.
## Solution
- Mark the internal `libloading::Error` of `DynamicPluginLoadError` with
`#[source]`.
---
## Changelog
- Implemented the
[`Error::source`](https://doc.rust-lang.org/std/error/trait.Error.html#method.source)
method for
[`DynamicPluginLoadError`](https://docs.rs/bevy_dynamic_plugin/latest/bevy_dynamic_plugin/enum.DynamicPluginLoadError.html).
---
Here is the output from `cargo-expand` before and after the change.
```rust
// Before
impl Error for DynamicPluginLoadError {}
```
```rust
// After
impl Error for DynamicPluginLoadError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
use thiserror::__private::AsDynError as _;
match self {
DynamicPluginLoadError::Library { 0: source, .. } => {
Some(source.as_dyn_error())
}
DynamicPluginLoadError::Plugin { 0: source, .. } => {
Some(source.as_dyn_error())
}
}
}
}
```
# Objective
- SavedAsset's iter_labels returns ```&str```, however accessing
LabeledAssets requires ```CowArc<'static, str>```
- Although SavedAsset holds UntypedHandles in its hashmap of
LabeledAssets, they are inaccessible as LabeledAssets are casted to
SavedAsset or ErasedLoadedAsset, which don't contain their
UntypedHandles
- Adresses #11609
## Solution
- Used Trait bounds to allow for either ```CowArc<'static, str>``` or
```&str``` to be used as a label in get_labeled and get_erased_labeled.
- Added method get_untyped_handle to get UntypedHandle from the
LabeledAsset.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- `impl_reflect_struct` doesn't cover tuple structs or enums.
- Problem brought up [on
Discord](https://discord.com/channels/691052431525675048/1002362493634629796/1190623345817960463).
## Solution
- Replaces `impl_reflect_struct` with the new `impl_reflect` which works
for tuple structs and enums too.
---
## Changelog
- Internally in `bevy_reflect_derive`, we have a new `ReflectProvenance`
type which is composed of `ReflectTraitToImpl` and `ReflectSource`.
- `impl_reflect_struct` is gone and totally superseded by
`impl_reflect`.
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
- Allow `HashMap<Cow<'_, T>, _>` to use `&T` as key for `HashMap::get`
- Makes `CowArc` more like `Cow`
## Solution
Implements `Borrow<T>` and `AsRef<T>` for `CowArc<T>`.
# Objective
Right now, all assets in the main world get extracted and prepared in
the render world (if the asset's using the RenderAssetPlugin). This is
unfortunate for two cases:
1. **TextureAtlas** / **FontAtlas**: This one's huge. The individual
`Image` assets that make up the atlas are cloned and prepared
individually when there's no reason for them to be. The atlas textures
are built on the CPU in the main world. *There can be hundreds of images
that get prepared for rendering only not to be used.*
2. If one loads an Image and needs to transform it in a system before
rendering it, kind of like the [decompression
example](https://github.com/bevyengine/bevy/blob/main/examples/asset/asset_decompression.rs#L120),
there's a price paid for extracting & preparing the asset that's not
intended to be rendered yet.
------
* References #10520
* References #1782
## Solution
This changes the `RenderAssetPersistencePolicy` enum to bitflags. I felt
that the objective with the parameter is so similar in nature to wgpu's
[`TextureUsages`](https://docs.rs/wgpu/latest/wgpu/struct.TextureUsages.html)
and
[`BufferUsages`](https://docs.rs/wgpu/latest/wgpu/struct.BufferUsages.html),
that it may as well be just like that.
```rust
// This asset only needs to be in the main world. Don't extract and prepare it.
RenderAssetUsages::MAIN_WORLD
// Keep this asset in the main world and
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD
// This asset is only needed in the render world. Remove it from the asset server once extracted.
RenderAssetUsages::RENDER_WORLD
```
### Alternate Solution
I considered introducing a third field to `RenderAssetPersistencePolicy`
enum:
```rust
enum RenderAssetPersistencePolicy {
/// Keep the asset in the main world after extracting to the render world.
Keep,
/// Remove the asset from the main world after extracting to the render world.
Unload,
/// This doesn't need to be in the render world at all.
NoExtract, // <-----
}
```
Functional, but this seemed like shoehorning. Another option is renaming
the enum to something like:
```rust
enum RenderAssetExtractionPolicy {
/// Extract the asset and keep it in the main world.
Extract,
/// Remove the asset from the main world after extracting to the render world.
ExtractAndUnload,
/// This doesn't need to be in the render world at all.
NoExtract,
}
```
I think this last one could be a good option if the bitflags are too
clunky.
## Migration Guide
* `RenderAssetPersistencePolicy::Keep` → `RenderAssetUsage::MAIN_WORLD |
RenderAssetUsage::RENDER_WORLD` (or `RenderAssetUsage::default()`)
* `RenderAssetPersistencePolicy::Unload` →
`RenderAssetUsage::RENDER_WORLD`
* For types implementing the `RenderAsset` trait, change `fn
persistence_policy(&self) -> RenderAssetPersistencePolicy` to `fn
asset_usage(&self) -> RenderAssetUsages`.
* Change any references to `cpu_persistent_access`
(`RenderAssetPersistencePolicy`) to `asset_usage` (`RenderAssetUsage`).
This applies to `Image`, `Mesh`, and a few other types.
# Objective
- Address a `TODO` item in `bevy_animation`.
## Solution
- Replace the `cubic_spline_interpolation` macro with a function.
The function isn't marked as `#[inline(always)]` but from what I checked
with `cargo asm` it gets inlined (even in debug, unless I explicitly add
`#[inline(never)]`), so this should be identical to the macro. If needed
I can add the attribute.
Updates the requirements on
[erased-serde](https://github.com/dtolnay/erased-serde) to permit the
latest version.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dtolnay/erased-serde/releases">erased-serde's
releases</a>.</em></p>
<blockquote>
<h2>0.4.2</h2>
<ul>
<li>Update proc-macro2 to fix caching issue when using a rustc-wrapper
such as sccache</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8f555a2db2"><code>8f555a2</code></a>
Release 0.4.2</li>
<li><a
href="450a9108fc"><code>450a910</code></a>
Pull in proc-macro2 sccache fix</li>
<li><a
href="4726cdb49d"><code>4726cdb</code></a>
Release 0.4.1</li>
<li><a
href="4e04e70902"><code>4e04e70</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/erased-serde/issues/101">#101</a>
from dtolnay/sererror</li>
<li><a
href="c670c72da5"><code>c670c72</code></a>
Preserve error message of errors originated from Serialize impl</li>
<li><a
href="6893670cca"><code>6893670</code></a>
Ignore box_collection clippy lint</li>
<li><a
href="7ddf6aadd8"><code>7ddf6aa</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/erased-serde/issues/100">#100</a>
from KodrAus/fix/failing-serialize-impl</li>
<li><a
href="8227d20573"><code>8227d20</code></a>
handle the case where a Serialize fails without calling the
Serializer</li>
<li><a
href="160c15393e"><code>160c153</code></a>
Release 0.4.0</li>
<li><a
href="2e48977019"><code>2e48977</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/erased-serde/issues/99">#99</a>
from dtolnay/bench</li>
<li>Additional commits viewable in <a
href="https://github.com/dtolnay/erased-serde/compare/0.3.0...0.4.2">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
Revert the changes to type parameter bounds introduced in #9046,
improves the `#[reflect(where)]` attribute (also from #9046), and adds
the ability to opt out of field bounds.
This is based on suggestions by @soqb and discussion on
[Discord](https://discord.com/channels/691052431525675048/1002362493634629796/1201227833826103427).
## Solution
Reverts the changes to type parameter bounds when deriving `Reflect`,
introduced in #9046. This was originally done as a means of fixing a
recursion issue (#8965). However, as @soqb pointed out, we could achieve
the same result by simply making an opt-out attribute instead of messing
with the type parameter bounds.
This PR has four main changes:
1. Reverts the type parameter bounds from #9046
2. Includes `TypePath` as a default bound for active fields
3. Changes `#reflect(where)]` to be strictly additive
4. Adds `#reflect(no_field_bounds)]` to opt out of field bounds
Change 1 means that, like before, type parameters only receive at most
the `TypePath` bound (if `#[reflect(type_path = false)]` is not present)
and active fields receive the `Reflect` or `FromReflect` bound. And with
Change 2, they will also receive `TypePath` (since it's indirectly
required by `Typed` to construct `NamedField` and `UnnamedField`
instances).
Change 3 was made to make room for Change 4. By splitting out the
responsibility of `#reflect(where)]`, we can use it with or without
`#reflect(no_field_bounds)]` for various use cases.
For example, if we hadn't done this, the following would have failed:
```rust
// Since we're not using `#reflect(no_field_bounds)]`,
// `T::Assoc` is automatically given the required bounds
// of `FromReflect + TypePath`
#[derive(Reflect)]
#[reflect(where T::Assoc: OtherTrait)]
struct Foo<T: MyTrait> {
value: T::Assoc,
}
```
This provides more flexibility to the user while still letting them add
or remove most trait bounds.
And to solve the original recursion issue, we can do:
```rust
#[derive(Reflect)]
#[reflect(no_field_bounds)] // <-- Added
struct Foo {
foo: Vec<Foo>
}
```
#### Bounds
All in all, we now have four sets of trait bounds:
- `Self` gets the bounds `Any + Send + Sync`
- Type parameters get the bound `TypePath`. This can be opted out of
with `#[reflect(type_path = false)]`
- Active fields get the bounds `TypePath` and `FromReflect`/`Reflect`
bounds. This can be opted out of with `#reflect(no_field_bounds)]`
- Custom bounds can be added with `#[reflect(where)]`
---
## Changelog
- Revert some changes #9046
- `#reflect(where)]` is now strictly additive
- Added `#reflect(no_field_bounds)]` attribute to opt out of automatic
field trait bounds when deriving `Reflect`
- Made the `TypePath` requirement on fields when deriving `Reflect` more
explicit
## Migration Guide
> [!important]
> This PR shouldn't be a breaking change relative to the current version
of Bevy (v0.12). And since it removes the breaking parts of #9046, that
PR also won't need a migration guide.
# Objective
Currently, the `Capsule` primitive is technically dimension-agnostic in
that it implements both `Primitive2d` and `Primitive3d`. This seems good
on paper, but it can often be useful to have separate 2D and 3D versions
of primitives.
For example, one might want a two-dimensional capsule mesh. We can't
really implement both 2D and 3D meshing for the same type using the
upcoming `Meshable` trait (see #11431). We also currently don't
implement `Bounded2d` for `Capsule`, see
https://github.com/bevyengine/bevy/pull/11336#issuecomment-1890797788.
Having 2D and 3D separate at a type level is more explicit, and also
more consistent with the existing primitives, as there are no other
types that implement both `Primitive2d` and `Primitive3d` at the same
time.
## Solution
Rename `Capsule` to `Capsule3d` and add `Capsule2d`. `Capsule2d`
implements `Bounded2d`.
For now, I went for `Capsule2d` for the sake of consistency and clarity.
Mathematically the more accurate term would be `Stadium` or `Pill` (see
[Wikipedia](https://en.wikipedia.org/wiki/Stadium_(geometry))), but
those might be less obvious to game devs. For reference, Godot has
[`CapsuleShape2D`](https://docs.godotengine.org/en/stable/classes/class_capsuleshape2d.html).
I can rename it if others think the geometrically correct name is better
though.
---
## Changelog
- Renamed `Capsule` to `Capsule3d`
- Added `Capsule2d` with `Bounded2d` implemented
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#11479
## Solution
- Remove `collide_aabb.rs`
- Re-implement the example-specific collision code in the example,
taking advantage of the new `IntersectsVolume` trait.
## Changelog
- Removed `sprite::collide_aabb::collide` and
`sprite::collide_aabb::Collision`.
## Migration Guide
`sprite::collide_aabb::collide` and `sprite::collide_aabb::Collision`
were removed.
```rust
// Before
let collision = bevy::sprite::collide_aabb::collide(a_pos, a_size, b_pos, b_size);
if collision.is_some() {
// ...
}
// After
let collision = Aabb2d::new(a_pos.truncate(), a_size / 2.)
.intersects(&Aabb2d::new(b_pos.truncate(), b_size / 2.));
if collision {
// ...
}
```
If you were making use `collide_aabb::Collision`, see the new
`collide_with_side` function in the [`breakout`
example](https://bevyengine.org/examples/Games/breakout/).
## Discussion
As discussed in the linked issue, maybe we want to wait on `bevy_sprite`
generally making use of `Aabb2b` so users don't need to construct it
manually. But since they **do** need to construct the bounding circle
for the ball manually, this doesn't seem like a big deal to me.
---------
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
# Objective
When developing my game I realized `extract_clusters` and
`prepare_clusters` systems are taking a lot of time despite me creating
very little lights. Reducing number of clusters from the default 4096 to
2048 or less greatly improved performance and stabilized FPS (~300 ->
1000+). I debugged it and found out that the main reason for this is
cloning `VisiblePointLights` in `extract_clusters` system. It contains
light entities grouped by clusters that they affect. The problem is that
we clone 4096 (assuming the default clusters configuration) vectors
every frame. If many of them happen to be non-empty it starts to be a
bottleneck because there is a lot of heap allocation. It wouldn't be a
problem if we reused those vectors in following frames but we don't.
## Solution
Avoid cloning multiple vectors and instead build a single vector
containing data for all clusters.
I've recorded a trace in `3d_scene` example with disabled v-sync before
and after the change.
Mean FPS went from 424 to 990. Mean time for `extract_clusters` system
was reduced from 210 us to 24 us and `prepare_clusters` from 189 us to
87 us.
![image](https://github.com/bevyengine/bevy/assets/160391/ab66aa9d-1fa7-4993-9827-8be76b530972)
---
## Changelog
- Improved performance of `extract_clusters` and `prepare_clusters`
systems for scenes where lights affect a big part of it.
# Objective
Fixes: https://github.com/bevyengine/bevy/issues/11549
Add a doctest example of what a custom implementation of an
`EntityMapper` would look like.
(need to wait until https://github.com/bevyengine/bevy/pull/11428 is
merged)
---------
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
# Objective
The first part of #10569, split up from #11007.
The goal is to implement meshing support for Bevy's new geometric
primitives, starting with 2D primitives. 3D meshing will be added in a
follow-up, and we can consider removing the old mesh shapes completely.
## Solution
Add a `Meshable` trait that primitives need to implement to support
meshing, as suggested by the
[RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/12-primitive-shapes.md#meshing).
```rust
/// A trait for shapes that can be turned into a [`Mesh`].
pub trait Meshable {
/// The output of [`Self::mesh`]. This can either be a [`Mesh`]
/// or a builder used for creating a [`Mesh`].
type Output;
/// Creates a [`Mesh`] for a shape.
fn mesh(&self) -> Self::Output;
}
```
This PR implements it for the following primitives:
- `Circle`
- `Ellipse`
- `Rectangle`
- `RegularPolygon`
- `Triangle2d`
The `mesh` method typically returns a builder-like struct such as
`CircleMeshBuilder`. This is needed to support shape-specific
configuration for things like mesh resolution or UV configuration:
```rust
meshes.add(Circle { radius: 0.5 }.mesh().resolution(64));
```
Note that if no configuration is needed, you can even skip calling
`mesh` because `From<MyPrimitive>` is implemented for `Mesh`:
```rust
meshes.add(Circle { radius: 0.5 });
```
I also updated the `2d_shapes` example to use primitives, and tweaked
the colors to have better contrast against the dark background.
Before:
![Old 2D
shapes](https://github.com/bevyengine/bevy/assets/57632562/f1d8c2d5-55be-495f-8ed4-5890154b81ca)
After:
![New 2D
shapes](https://github.com/bevyengine/bevy/assets/57632562/f166c013-34b8-4752-800a-5517b284d978)
Here you can see the UVs and different facing directions: (taken from
#11007, so excuse the 3D primitives at the bottom left)
![UVs and facing
directions](https://github.com/bevyengine/bevy/assets/57632562/eaf0be4e-187d-4b6d-8fb8-c996ba295a8a)
---
## Changelog
- Added `bevy_render::mesh::primitives` module
- Added `Meshable` trait and implemented it for:
- `Circle`
- `Ellipse`
- `Rectangle`
- `RegularPolygon`
- `Triangle2d`
- Implemented `Default` and `Copy` for several 2D primitives
- Updated `2d_shapes` example to use primitives
- Tweaked colors in `2d_shapes` example to have better contrast against
the (new-ish) dark background
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Sending and receiving events of the same type in the same system is a
reasonably common need, generally due to event filtering.
- However, actually doing so is non-trivial, as the borrow checker
simultaneous hates mutable and immutable access.
## Solution
- Demonstrate two sensible patterns for doing so.
- Update the `ManualEventReader` docs to be more clear and link to this
example.
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: ickk <git@ickk.io>
# Objective
It can sometimes be useful to transform actual `Mesh` data without
needing to change the `Transform` of an entity. For example, one might
want to spawn a circle mesh facing up instead of facing Z, or to spawn a
mesh slightly offset without needing child entities.
## Solution
Add `transform_by` and `transformed_by` methods to `Mesh`. They take a
`Transform` and apply the translation, rotation, and scale to vertex
positions, and the rotation to normals and tangents.
In the `load_gltf` example, with this system:
```rust
fn transform(time: Res<Time>, mut q: Query<&mut Handle<Mesh>>, mut meshes: ResMut<Assets<Mesh>>) {
let sin = 0.0025 * time.elapsed_seconds().sin();
for mesh_handle in &mut q {
if let Some(mesh) = meshes.get_mut(mesh_handle.clone_weak()) {
let transform =
Transform::from_rotation(Quat::from_rotation_y(0.75 * time.delta_seconds()))
.with_scale(Vec3::splat(1.0 + sin));
mesh.transform_by(transform);
}
}
}
```
it looks like this:
https://github.com/bevyengine/bevy/assets/57632562/60432456-6d28-4d06-9c94-2f4148f5acd5
# Objective
Working towards finishing a part of #10572, this PR adds a ton of math
helpers and useful constructors for primitive shapes. I also tried
fixing some naming inconsistencies.
## Solution
- Add mathematical helpers like `area`, `volume`, `perimeter`,
`RegularPolygon::inradius` and so on, trying to cover all core
mathematical properties of each shape
- Add some constructors like `Rectangle::from_corners`,
`Cuboid::from_corners` and `Plane3d::from_points`
I also derived `PartialEq` for the shapes where it's trivial. Primitives
like `Line2d` and `Segment2d` are not trivial because you could argue
that they would be equal if they had an opposite direction.
All mathematical methods have tests with reference values computed by
hand or with external tools.
## Todo
- [x] Add tests to verify that the values from mathematical helpers are
correct
---------
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
# Objective
Get #11257 changes merged.
I rewrote them one by one checking each to ensure correctness. In
particular, the window rescale logic changes to accomodate mut app
access are double checked. Not all changes have been included as some of
bevy_winit has since changed, and i am not confident including them.
Namely, the `run_app_update_if_should` change.
### Notes to reviewers
Review commits individually, use the "Hide whitespaces" diff display
mode.
## Changelog
* `bevy:🪟:WindowMoved`'s `entity` field has been renamed to
`window`
## Migration Guide
`bevy:🪟:WindowMoved`'s `entity` field has been renamed to
`window`. This is to be more consistent with other windowing events.
Consider changing usage:
```diff
-window_moved.entity
+window_moved.window
```
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- Closes#11490.
- Allow retrieving the current asset watch behavior from the
`AssetServer`.
## Solution
- Add the corresponding getter. (also fixes some trailing whitespace).
A corresponding helper could also be added on the `AssetPlugin` struct
(returning `self.watch_for_changes_override.unwrap_or(cfg!(feature =
"watch"))`), but it seems it isn't a current practice to have actual
methods on the plugin structs appart from the `Plugin` impl.
---
## Changelog
### Added
Added `watching_for_changes` getter on `AssetServer`.
---------
Co-authored-by: Mateusz Wachowiak <mateusz_wachowiak@outlook.com>
# Objective
My motivation are to resolve some of the issues I describe in this
[PR](https://github.com/bevyengine/bevy/issues/11415):
- not being able to easily mapping entities because the current
EntityMapper requires `&mut World` access
- not being able to create my own `EntityMapper` because some components
(`Parent` or `Children`) do not provide any public way of modifying the
inner entities
This PR makes the `MapEntities` trait accept a generic type that
implements `Mapper` to perform the mapping.
This means we don't need to use `EntityMapper` to perform our mapping,
we can use any type that implements `Mapper`. Basically this change is
very similar to what `serde` does. Instead of specifying directly how to
map entities for a given type, we have 2 distinct steps:
- the user implements `MapEntities` to define how the type will be
traversed and which `Entity`s will be mapped
- the `Mapper` defines how the mapping is actually done
This is similar to the distinction between `Serialize` (`MapEntities`)
and `Serializer` (`Mapper`).
This allows networking library to map entities without having to use the
existing `EntityMapper` (which requires `&mut World` access and the use
of `world_scope()`)
## Migration Guide
- The existing `EntityMapper` (notably used to replicate `Scenes` across
different `World`s) has been renamed to `SceneEntityMapper`
- The `MapEntities` trait now works with a generic `EntityMapper`
instead of the specific struct `EntityMapper`.
Calls to `fn map_entities(&mut self, entity_mapper: &mut EntityMapper)`
need to be updated to
`fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M)`
- The new trait `EntityMapper` has been added to the prelude
---------
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
# Objective
- `bevy_ui` fails to compile without `bevy_text` being enabled.
- Fixes#11363.
## Solution
- Add `#[cfg(feature = "bevy_text")]` to all items that require it.
I think this change is honestly a bit ugly, but I can't see any other
way around it. I considered making `bevy_text` required, but we agreed
[on
Discord](https://discord.com/channels/691052431525675048/743663673393938453/1196868117486379148)
that there were some use cases for `bevy_ui` without `bevy_text`. If you
have any ideas that decreases the amount of `#[cfg(...)]`s and
`#[allow(...)]`s, that would be greatly appreciated.
This was tested by running the following commands:
```shell
$ cargo clippy -p bevy_ui
$ cargo clippy -p bevy_ui -F bevy_text
$ cargo run -p ci
```
---
## Changelog
- Fixed `bevy_ui` not compiling without `bevy_text`.
# Objective
Fixes#8965.
#### Background
For convenience and to ensure everything is setup properly, we
automatically add certain bounds to the derived types. The current
implementation does this by taking the types from all active fields and
adding them to the where-clause of the generated impls. I believe this
method was chosen because it won't add bounds to types that are
otherwise ignored.
```rust
#[derive(Reflect)]
struct Foo<T, U: SomeTrait, V> {
t: T,
u: U::Assoc,
#[reflect(ignore)]
v: [V; 2]
}
// Generates something like:
impl<T, U: SomeTrait, V> for Foo<T, U, V>
where
// Active:
T: Reflect,
U::Assoc: Reflect,
// Ignored:
[V; 2]: Send + Sync + Any
{
// ...
}
```
The self-referential type fails because it ends up using _itself_ as a
type bound due to being one of its own active fields.
```rust
#[derive(Reflect)]
struct Foo {
foo: Vec<Foo>
}
// Foo where Vec<Foo>: Reflect -> Vec<T> where T: Reflect -> Foo where Vec<Foo>: Reflect -> ...
```
## Solution
We can't simply parse all field types for the name of our type. That
would be both complex and prone to errors and false-positives. And even
if it wasn't, what would we replace the bound with?
Instead, I opted to go for a solution that only adds the bounds to what
really needs it: the type parameters. While the bounds on concrete types
make errors a bit cleaner, they aren't strictly necessary. This means we
can change our generated where-clause to only add bounds to generic type
parameters.
Doing this, though, returns us back to the problem of over-bounding
parameters that don't need to be bounded. To solve this, I added a new
container attribute (based on
[this](https://github.com/dtolnay/syn/issues/422#issuecomment-406882925)
comment and @nicopap's
[comment](https://github.com/bevyengine/bevy/pull/9046#issuecomment-1623593780))
that allows us to pass in a custom where clause to modify what bounds
are added to these type parameters.
This allows us to do stuff like:
```rust
trait Trait {
type Assoc;
}
// We don't need `T` to be reflectable since we only care about `T::Assoc`.
#[derive(Reflect)]
#[reflect(where T::Assoc: FromReflect)]
struct Foo<T: Trait>(T::Assoc);
#[derive(TypePath)]
struct Bar;
impl Trait for Bar {
type Assoc = usize;
}
#[derive(Reflect)]
struct Baz {
a: Foo<Bar>,
}
```
> **Note**
> I also
[tried](dc139ea34c)
allowing `#[reflect(ignore)]` to be used on the type parameters
themselves, but that proved problematic since the derive macro does not
consume the attribute. This is why I went with the container attribute
approach.
### Alternatives
One alternative could possibly be to just not add reflection bounds
automatically (i.e. only add required bounds like `Send`, `Sync`, `Any`,
and `TypePath`).
The downside here is we add more friction to using reflection, which
already comes with its own set of considerations. This is a potentially
viable option, but we really need to consider whether or not the
ergonomics hit is worth it.
If we did decide to go the more manual route, we should at least
consider something like #5772 to make it easier for users to add the
right bounds (although, this could still become tricky with
`FromReflect` also being automatically derived).
### Open Questions
1. Should we go with this approach or the manual alternative?
2. ~~Should we add a `skip_params` attribute to avoid the `T: 'static`
trick?~~ ~~Decided to go with `custom_where()` as it's the simplest~~
Scratch that, went with a normal where clause
3. ~~`custom_where` bikeshedding?~~ No longer needed since we are using
a normal where clause
### TODO
- [x] Add compile-fail tests
---
## Changelog
- Fixed issue preventing recursive types from deriving `Reflect`
- Changed how where-clause bounds are generated by the `Reflect` derive
macro
- They are now only applied to the type parameters, not to all active
fields
- Added `#[reflect(where T: Trait, U::Assoc: Trait, ...)]` container
attribute
## Migration Guide
When deriving `Reflect`, generic type params that do not need the
automatic reflection bounds (such as `Reflect`) applied to them will
need to opt-out using a custom where clause like: `#[reflect(where T:
Trait, U::Assoc: Trait, ...)]`.
The attribute can define custom bounds only used by the reflection
impls. To simply opt-out all the type params, we can pass in an empty
where clause: `#[reflect(where)]`.
```rust
// BEFORE:
#[derive(Reflect)]
struct Foo<T>(#[reflect(ignore)] T);
// AFTER:
#[derive(Reflect)]
#[reflect(where)]
struct Foo<T>(#[reflect(ignore)] T);
```
---------
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
- Fixes#11569
## Solution
- Add new methods to the Ext Trait
---
## Changelog
### Added
- Added new methods to the trait `AppGizmoBuilder`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Implement common traits on primitives
## Solution
- Derive PartialEq on types that were missing it.
- Derive Copy on small types that were missing it.
- Derive Serialize/Deserialize if the feature on bevy_math is enabled.
- Add a lot of cursed stuff to the bevy_reflect `impls` module.
# Objective
- I wanted this for an example, and I think it's a fundamentally handy
debugging tool (with already public fields).
## Solution
- `derive(Debug)` for `FrameCount`
# Objective
- Fixes#11453
This is a temporary fix. There is PR fixing it (#11460), but I'm not
sure if it's going to be merged before the 0.13 release.
# Objective
- Implement an arc3d API for gizmos
- Solves #11536
## Solution
### `arc_3d`
- The current `arc3d` method on gizmos only takes an angle
- It draws an "standard arc" by default, this is an arc starting at
`Vec3::X`, in the XZ plane, in counter clockwise direction with a normal
that is facing up
- The "standard arc" can be customized with the usual gizmo builder
pattern. This way you'll be able to draw arbitrary arcs
### `short/long_arc_3d_between`
- Given `center`, `from`, `to` draws an arc between `from` and `to`
---
## Changelog
> This section is optional. If this was a trivial fix, or has no
externally-visible impact, you can delete this section.
- Added: `Gizmos::arc3d(&mut self, angle)` method
- Added: `Gizmos::long_arc_3d_between(&mut self, center, from, to)`
method
- Added: `Gizmos::short_arc_3d_between(&mut self, center, from, to)`
method
---
This PR factors out an orthogonal part of another PR as mentioned in
[this
comment](https://github.com/bevyengine/bevy/pull/11072#issuecomment-1883859573)
# Objective
Fixes#11311
## Solution
Adds an example to the documentation for `par_iter_mut`. I didn't add
any examples to `par_iter`, because I couldn't think of a good example
and I figure users can infer that `par_iter` and `par_iter_mut` are
similar.
# Objective
It's sometimes desirable to get a `Res<T>` rather than `&T` from
`World::get_resource`.
Alternative to #9940, partly adresses #9926
## Solution
added additional methods to `World` and `UnsafeWorldCell` to retrieve a
resource wrapped in a `Res`.
- `UnsafeWorldCell::get_resource_ref`
- `World::get_resource_ref`
- `World::resource_ref`
I can change it so `World::resource_mut` returns `ResMut` instead of
`Mut` as well if that's desired, but that could also be added later in a
seperate pr.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Mike <mike.hsu@gmail.com>
Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
# Objective
- Address junk leftover by TypeUuid removal
## Solution
- Get rid of unused deps and imports
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Resolves#11377
## Solution
- Add marker component `IsDefaultUiCamera` that will be choosen first as
the default camera.
If you want the IsDefaultUiCamera default camera to be in another
window, thats now possible.
- `IsDefaultUiCamera` is expected to be within a single Camera, if that
assertion fails, one PrimaryWindow Camera will be choosen.
---
## Changelog
### Added
- Added `IsDefaultUiCamera` marker component.
---------
Co-authored-by: Mateusz Wachowiak <mateusz_wachowiak@outlook.com>
# Objective
Allow TextureAtlasBuilder in AssetLoader.
Fixes#2987
## Solution
- TextureAtlasBuilder no longer hold just AssetIds that are used to
retrieve the actual image data in `finish`, but &Image instead.
- TextureAtlasBuilder now required AssetId only optionally (and it is
only used to retrieve the index from the AssetId in TextureAtlasLayout),
## Issues
- The issue mentioned here
https://github.com/bevyengine/bevy/pull/11474#issuecomment-1904676937
now also extends to the actual atlas texture. In short: Calling
add_texture multiple times for the same texture will lead to duplicate
image data in the atlas texture and additional indices.
If you provide an AssetId we can probably do something to de-duplicate
the entries while keeping insertion order (suggestions welcome on how
exactly). But if you don't then we are out of luck (unless we can and
want to hash the image, which I do not think we want).
---
## Changelog
### Changed
- TextureAtlasBuilder `add_texture` can be called without providing an
AssetId
- TextureAtlasBuilder `finish` no longer takes Assets<Image> and no
longer returns a Handle<Image>
## Migration Guide
- For `add_texture` you need to wrap your AssetId in Some
- `finish` now returns the atlas texture image directly instead of a
handle. Provide the atlas texture to `add` on Assets<Texture> to get a
Handle<Image>
# Objective
allow automatic fixing of bad joint weights.
fix#10447
## Solution
- remove automatic normalization of vertexes with all zero joint
weights.
- add `Mesh::normalize_joint_weights` which fixes zero joint weights,
and also ensures that all weights sum to 1. this is a manual call as it
may be slow to apply to large skinned meshes, and is unnecessary if you
have control over the source assets.
note: this became a more significant problem with 0.12, as weights that
are close to, but not exactly 1 now seem to use `Vec3::ZERO` for the
unspecified weight, where previously they used the entity translation.
# Objective
DXC+DX12 debug builds with an environment map have been broken since
https://github.com/bevyengine/bevy/pull/11366 merged due to an internal
compiler error in DXC. I tracked it down to a single `break` statement
and reported it upstream
(https://github.com/microsoft/DirectXShaderCompiler/issues/6183)
## Solution
Workaround the ICE by setting the for loop index variable to the max
value of the loop to avoid the `break` that's causing the ICE.
This works because it's the last thing in the for loop.
The `reflection_probes` and `pbr` examples both appear to still work
correctly.
# Objective
After #10520, I was experiencing seriously degraded performance that
ended up being due to never-drained `AssetEvent` events causing havoc
inside `extract_render_asset::<A>`. The same events being read over and
over again meant the same assets were being prepared every frame for
eternity. For what it's worth, I was noticing this on a static scene
about every 3rd or so time running my project.
* References #10520
* Fixes#11240
Why these events aren't sometimes drained between frames is beyond me
and perhaps worthy of another investigation, but the approach in this PR
effectively restores the original cached `EventReader` behavior (which
fixes it).
## Solution
I followed the [`CachedSystemState`
example](3a666cab23/crates/bevy_ecs/src/system/function_system.rs (L155))
to make sure that the `EventReader` state is cached between frames like
it used to be when it was an argument of `extract_render_asset::<A>`.
# Objective
Plugins are an incredible tool for encapsulating functionality. They are
low-key one of Bevy's best features. Combined with rust's module and
privacy system, it's a match made in heaven.
The one downside is that they can be a little too verbose to define. 90%
of all plugin definitions look something like this:
```rust
pub struct MyPlugin;
impl Plugin for MyPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<CameraAssets>()
.add_event::<SetCamera>()
.add_systems(Update, (collect_set_camera_events, drive_camera).chain());
}
}
```
Every so often it gets a little spicier:
```rust
pub struct MyGenericPlugin<T>(PhantomData<T>);
impl<T> Default for MyGenericPlugin<T> {
fn default() -> Self { ... }
}
impl<T> Plugin for MyGenericPlugin<T> { ... }
```
This is an annoying amount of boilerplate. Ideally, plugins should be
focused and small in scope, which means any app is going to have a *lot*
of them. Writing a plugin should be as easy as possible, and the *only*
part of this process that carries any meaning is the body of `fn build`.
## Solution
Implement `Plugin` for functions that take `&mut App` as a parameter.
The two examples above now look like this:
```rust
pub fn my_plugin(app: &mut App) {
app.init_resource::<CameraAssets>()
.add_event::<SetCamera>()
.add_systems(Update, (collect_set_camera_events, drive_camera).chain());
}
pub fn my_generic_plugin<T>(app: &mut App) {
// No need for PhantomData, it just works.
}
```
Almost all plugins can be written this way, which I believe will make
bevy code much more attractive. Less boilerplate and less meaningless
indentation. More plugins with smaller scopes.
---
## Changelog
The `Plugin` trait is now implemented for all functions that take `&mut
App` as their only parameter. This is an abbreviated way of defining
plugins with less boilerplate than manually implementing the trait.
---------
Co-authored-by: Federico Rinaldi <gisquerin@gmail.com>
# Objective
Fixes#11533
When `AssetPath`s are created from a string type, they are parsed into
an `AssetSource`, a `Path`, and a `Label`.
The current method of parsing has some unnecessary quirks:
- The presence of a `:` character is assumed to be the start of an asset
source indicator.
- This is not necessarily true. There are valid uses of a `:` character
in an asset path, for example an http source's port such as
`localhost:80`.
- If there are multiple instances of `://`, the last one is assumed to
be the asset source deliminator.
- This has some unexpected behavior. Even in a fully formed path, such
as `http://localhost:80`, the `:` between `localhost` and `80` is
assumed to be the start of an asset source, causing an error since it
does not form the full sequence `://`.
## Solution
Changes the `AssetPath`'s `parse_internal` method to be more permissive.
- Only the exact sequence `://` is taken to be the asset source
deliminator, and only the first one if there are multiple.
- As a consequence, it is no longer possible to detect a malformed asset
source deliminator, and so the corresponding error was removed.
# Objective
https://github.com/bevyengine/bevy/pull/5103 caused a bug where
`Sprite::rect` was ignored by the engine. (Did nothing)
## Solution
My solution changes the way how Bevy calculates the rect, based on this
table:
| `atlas_rect` | `Sprite::rect` | Result |
|--------------|----------------|------------------------------------------------------|
| `None` | `None` | `None` |
| `None` | `Some` | `Sprite::rect` |
| `Some` | `None` | `atlas_rect` |
| `Some` | `Some` | `Sprite::rect` is used, relative to `atlas_rect.min`
|
# Objective
One of a few Bevy Asset improvements I would like to make: #11216.
Currently asset processing and asset saving are handled by the same
trait, `AssetSaver`. This makes it difficult to reuse saving
implementations and impossible to have a single "universal" saver for a
given asset type.
## Solution
This PR splits off the processing portion of `AssetSaver` into
`AssetTransformer`, which is responsible for transforming assets. This
change involves adding the `LoadTransformAndSave` processor, which
utilizes the new API. The `LoadAndSave` still exists since it remains
useful in situations where no "transformation" of the asset is done,
such as when compressing assets.
## Notes:
As an aside, Bikeshedding is welcome on the names. I'm not entirely
convinced by `AssetTransformer`, which was chosen mostly because
`AssetProcessor` is taken. Additionally, `LoadTransformSave` may be
sufficient instead of `LoadTransformAndSave`.
---
## Changelog
### Added
- `AssetTransformer` which is responsible for transforming Assets.
- `LoadTransformAndSave`, a `Process` implementation.
### Changed
- Changed `AssetSaver`'s responsibilities from processing and saving to
just saving.
- Updated `asset_processing` example to use new API.
- Old asset .meta files regenerated with new processor.
# Objective
Keep core dependencies up to date.
## Solution
Update the dependencies.
wgpu 0.19 only supports raw-window-handle (rwh) 0.6, so bumping that was
included in this.
The rwh 0.6 version bump is just the simplest way of doing it. There
might be a way we can take advantage of wgpu's new safe surface creation
api, but I'm not familiar enough with bevy's window management to
untangle it and my attempt ended up being a mess of lifetimes and rustc
complaining about missing trait impls (that were implemented). Thanks to
@MiniaczQ for the (much simpler) rwh 0.6 version bump code.
Unblocks https://github.com/bevyengine/bevy/pull/9172 and
https://github.com/bevyengine/bevy/pull/10812
~~This might be blocked on cpal and oboe updating their ndk versions to
0.8, as they both currently target ndk 0.7 which uses rwh 0.5.2~~ Tested
on android, and everything seems to work correctly (audio properly stops
when minimized, and plays when re-focusing the app).
---
## Changelog
- `wgpu` has been updated to 0.19! The long awaited arcanization has
been merged (for more info, see
https://gfx-rs.github.io/2023/11/24/arcanization.html), and Vulkan
should now be working again on Intel GPUs.
- Targeting WebGPU now requires that you add the new `webgpu` feature
(setting the `RUSTFLAGS` environment variable to
`--cfg=web_sys_unstable_apis` is still required). This feature currently
overrides the `webgl2` feature if you have both enabled (the `webgl2`
feature is enabled by default), so it is not recommended to add it as a
default feature to libraries without putting it behind a flag that
allows library users to opt out of it! In the future we plan on
supporting wasm binaries that can target both webgl2 and webgpu now that
wgpu added support for doing so (see
https://github.com/bevyengine/bevy/issues/11505).
- `raw-window-handle` has been updated to version 0.6.
## Migration Guide
- `bevy_render::instance_index::get_instance_index()` has been removed
as the webgl2 workaround is no longer required as it was fixed upstream
in wgpu. The `BASE_INSTANCE_WORKAROUND` shaderdef has also been removed.
- WebGPU now requires the new `webgpu` feature to be enabled. The
`webgpu` feature currently overrides the `webgl2` feature so you no
longer need to disable all default features and re-add them all when
targeting `webgpu`, but binaries built with both the `webgpu` and
`webgl2` features will only target the webgpu backend, and will only
work on browsers that support WebGPU.
- Places where you conditionally compiled things for webgl2 need to be
updated because of this change, eg:
- `#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]`
becomes `#[cfg(any(not(feature = "webgl") ,not(target_arch = "wasm32"),
feature = "webgpu"))]`
- `#[cfg(all(feature = "webgl", target_arch = "wasm32"))]` becomes
`#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature =
"webgpu")))]`
- `if cfg!(all(feature = "webgl", target_arch = "wasm32"))` becomes `if
cfg!(all(feature = "webgl", target_arch = "wasm32", not(feature =
"webgpu")))`
- `create_texture_with_data` now also takes a `TextureDataOrder`. You
can probably just set this to `TextureDataOrder::default()`
- `TextureFormat`'s `block_size` has been renamed to `block_copy_size`
- See the `wgpu` changelog for anything I might've missed:
https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
Make APIs more consistent and ergonomic by adding a `new` constructor
for `Circle` and `Sphere`.
This could be seen as a redundant "trivial constructor", but in
practise, it seems valuable to me. I have lots of cases where formatting
becomes ugly because of the lack of a constructor, like this:
```rust
Circle {
radius: self.radius(),
}
.contains_local_point(centered_pt)
```
With `new`, it'd be formatted much nicer:
```rust
Circle::new(self.radius()).contains_local_point(centered_pt)
```
Of course, this is just one example, but my circle/sphere definitions
very frequently span three or more lines when they could fit on one.
Adding `new` also increases consistency. `Ellipse` has `new` already,
and so does the mesh version of `Circle`.
## Solution
Add a `new` constructor for `Circle` and `Sphere`.
# Objective
- Fix documentation for `AssetReader::is_directory` (it is currently
exactly the same as docs for `read_directory`)
---------
Co-authored-by: Kanabenki <lucien.menassol@gmail.com>
# Objective
- Some passes recreate a sampler when creating a bind group to be
cached, even if the sampler is always the same.
## Solution
- Store the sampler in the corresponding pipeline resource.
# Objective
While working on #11527 I spotted that the internal field for the label
of a `Schedule` is called `name`. Using `label` seems more in line with
the other naming across Bevy.
## Solution
Renaming the field was straightforward since it's not exposed outside of
the module. This also means a changelog or migration guide isn't
necessary.
# Objective
Fixes#11411
## Solution
- Added a simple example how to create and configure custom schedules
that are run by the `Main` schedule.
- Spot checked some of the API docs used, fixed `App::add_schedule` docs
that referred to a function argument that was removed by #9600.
## Open Questions
- While spot checking the docs, I noticed that the `Schedule` label is
stored in a field called `name` instead of `label`. This seems
unintuitive since the term label is used everywhere else. Should we
change that field name? It was introduced in #9600. If so, I do think
this change would be out of scope for this PR that mainly adds the
example.
# Objective
Rust analyzer kept complaining about a cyclic dependency due to
`bevy_input` having a dev-dependency on `bevy`.
`bevy_input` was also missing `bevy_reflect`'s "smol_str" feature which
it needs to compile on its own.
Fixes#10256
## Solution
Remove the dev-dependency on `bevy` from `bevy_input` since it was only
used to reduce imports for 1 test and 3 doc examples by 1 line each, as
`bevy_input` already has dependencies on everything needed for those
tests and doctests to work.
Add `bevy_reflect`'s "smol_str" feature to `bevy_input`'s dependency
list as it needs it to actually compile.
# Objective
Fixes#10414.
That issue and its comments do a great job of laying out the case for
this.
## Solution
Added an optional `spatial_scale` field to `PlaybackSettings`, which
overrides the default value set on `AudioPlugin`.
## Changelog
- `AudioPlugin::spatial_scale` has been renamed to
`default_spatial_scale`.
- `SpatialScale` is no longer a resource and is wrapped by
`DefaultSpatialScale`.
- Added an optional `spatial_scale` to `PlaybackSettings`.
## Migration Guide
`AudioPlugin::spatial_scale` has been renamed to `default_spatial_scale`
and the default spatial scale can now be overridden on individual audio
sources with `PlaybackSettings::spatial_scale`.
If you were modifying or reading `SpatialScale` at run time, use
`DefaultSpatialScale` instead.
```rust
// before
app.add_plugins(DefaultPlugins.set(AudioPlugin {
spatial_scale: SpatialScale::new(AUDIO_SCALE),
..default()
}));
// after
app.add_plugins(DefaultPlugins.set(AudioPlugin {
default_spatial_scale: SpatialScale::new(AUDIO_SCALE),
..default()
}));
```
# Objective
TypeUuid is deprecated, remove it.
## Migration Guide
Convert any uses of `#[derive(TypeUuid)]` with `#[derive(TypePath]` for
more complex uses see the relevant
[documentation](https://docs.rs/bevy/latest/bevy/prelude/trait.TypePath.html)
for more information.
---------
Co-authored-by: ebola <dev@axiomatic>
# Objective
- Fixes a hurdle encountered when debugging a panic caused by the file
watcher loading a `.gitignore` file, which was hard to debug because
there was no file name in the report, only `asset paths must have
extensions`
## Solution
- Panic with a formatted message that includes the asset path, e.g.
`missing expected extension for asset path .gitignore`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Doonv <58695417+doonv@users.noreply.github.com>
Updates the requirements on
[ruzstd](https://github.com/KillingSpark/zstd-rs) to permit the latest
version.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/KillingSpark/zstd-rs/releases">ruzstd's
releases</a>.</em></p>
<blockquote>
<h2>Even better no_std</h2>
<p>Switching from thiserror to derive_more allows for no_std builds on
stable rust</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/KillingSpark/zstd-rs/blob/master/Changelog.md">ruzstd's
changelog</a>.</em></p>
<blockquote>
<h1>After 0.5.0</h1>
<ul>
<li>Make the hashing checksum optional (thanks to <a
href="https://github.com/tamird"><code>@tamird</code></a>)
<ul>
<li>breaking change as the public API changes based on features</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="e620d2a856"><code>e620d2a</code></a>
Merge pull request <a
href="https://redirect.github.com/KillingSpark/zstd-rs/issues/50">#50</a>
from KillingSpark/remove_thiserror</li>
<li><a
href="9e9d204c63"><code>9e9d204</code></a>
make clippy happy</li>
<li><a
href="f4a6fc0cc1"><code>f4a6fc0</code></a>
bump the version, this is an incompatible change</li>
<li><a
href="64d65b5c4f"><code>64d65b5</code></a>
fix test compile...</li>
<li><a
href="07bbda98c8"><code>07bbda9</code></a>
remove the error_in_core feature and switch the io_nostd to use the
Display t...</li>
<li><a
href="e15eb1e568"><code>e15eb1e</code></a>
Merge pull request <a
href="https://redirect.github.com/KillingSpark/zstd-rs/issues/49">#49</a>
from tamird/clippy</li>
<li><a
href="92a3f2e6b2"><code>92a3f2e</code></a>
Avoid unnecessary cast</li>
<li><a
href="f588d5c362"><code>f588d5c</code></a>
Avoid slow zero-filling initialization</li>
<li><a
href="e79f09876f"><code>e79f098</code></a>
Avoid single-match expression</li>
<li><a
href="c75cc2fbb9"><code>c75cc2f</code></a>
Remove useless assertion</li>
<li>Additional commits viewable in <a
href="https://github.com/KillingSpark/zstd-rs/compare/v0.4.0...v0.5.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
- `AssetPath` implements reflection, but is not registered as a type in
the plugin.
- Fixes#11481.
## Solution
- Register the `AssetPath` type when `AssetPlugin::build` is called.
---
## Changelog
- Registered `AssetPath` type for use in reflection.
# Objective
- `World::get_resource`'s comment on it's `unsafe` usage meant to say
"mutably" but instead said "immutably."
- Fixes#11430.
## Solution
- Replace "immutably" with "mutably."
# Objective
#10946 added bounding volume types and an `IntersectsVolume` trait, but
didn't actually implement intersections between bounding volumes.
This PR implements AABB-AABB, circle-circle / sphere-sphere, and
AABB-circle / AABB-sphere intersections.
## Solution
Implement `IntersectsVolume` for bounding volume pairs. I also added
`closest_point` methods to return the closest point on the surface /
inside of bounding volumes. This is used for AABB-circle / AABB-sphere
intersections.
---------
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
# Objective
TextureAtlases are commonly used to drive animations described as a
consecutive range of indices. The current TextureAtlasBuilder uses the
AssetId of the image to determine the index of the texture in the
TextureAtlas. The AssetId of an Image Asset can change between runs.
The TextureAtlas exposes
[`get_texture_index`](https://docs.rs/bevy/latest/bevy/sprite/struct.TextureAtlas.html#method.get_texture_index)
to get the index from a given AssetId, but this needlessly complicates
the process of creating a simple TextureAtlas animation.
Fixes#2459
## Solution
- Use the (ordered) image_ids of the 'texture to place' vector to
retrieve the packed locations and compose the textures of the
TextureAtlas.
# Objective
It would be convenient to be able to call functions with `Commands` as a
parameter without having to move your own instance of `Commands`. Since
this struct is composed entirely of references, we can easily get an
owned instance of `Commands` by shortening the lifetime.
## Solution
Add `Commands::reborrow`, `EntiyCommands::reborrow`, and
`Deferred::reborrow`, which returns an owned version of themselves with
a shorter lifetime.
Remove unnecessary lifetimes from `EntityCommands`. The `'w` and `'s`
lifetimes only have to be separate for `Commands` because it's used as a
`SystemParam` -- this is not the case for `EntityCommands`.
---
## Changelog
Added `Commands::reborrow`. This is useful if you have `&mut Commands`
but need `Commands`. Also added `EntityCommands::reborrow` and
`Deferred:reborrow` which serve the same purpose.
## Migration Guide
The lifetimes for `EntityCommands` have been simplified.
```rust
// Before (Bevy 0.12)
struct MyStruct<'w, 's, 'a> {
commands: EntityCommands<'w, 's, 'a>,
}
// After (Bevy 0.13)
struct MyStruct<'a> {
commands: EntityCommands<'a>,
}
```
The method `EntityCommands::commands` now returns `Commands` rather than
`&mut Commands`.
```rust
// Before (Bevy 0.12)
let commands = entity_commands.commands();
commands.spawn(...);
// After (Bevy 0.13)
let mut commands = entity_commands.commands();
commands.spawn(...);
```
# Objective
Document a few common cases of which lifetime is required when using
SystemParam Derive
## Solution
Added a table in the doc comment
---------
Co-authored-by: laund <me@laund.moe>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Prep for https://github.com/bevyengine/bevy/pull/10164
- Make deferred_lighting_pass_id a ColorAttachment
- Correctly extract shadow view frusta so that the view uniforms get
populated
- Make some needed things public
- Misc formatting
# Objective
- Extend reflection to the standard library's `Wrapping` and
`Saturating` generic types.
This wasn't my use-case but someone in the discord was surprised that
this wasn't already done. I decided to make a PR because the other
`std::num` items were reflected and if there's a reason to exclude
`Wrapping` and `Saturating`, I am unaware of it.
## Solution
Trivial fix
---
## Changelog
Implemented `Reflect` for `Wrapping<T>` and `Saturating<T>` from
`std::num`.
# Objective
> Can anyone explain to me the reasoning of renaming all the types named
Query to Data. I'm talking about this PR
https://github.com/bevyengine/bevy/pull/10779 It doesn't make sense to
me that a bunch of types that are used to run queries aren't named Query
anymore. Like ViewQuery on the ViewNode is the type of the Query. I
don't really understand the point of the rename, it just seems like it
hides the fact that a query will run based on those types.
[@IceSentry](https://discord.com/channels/691052431525675048/692572690833473578/1184946251431694387)
## Solution
Revert several renames in #10779.
## Changelog
- `ViewNode::ViewData` is now `ViewNode::ViewQuery` again.
## Migration Guide
- This PR amends the migration guide in
https://github.com/bevyengine/bevy/pull/10779
---------
Co-authored-by: atlas dostal <rodol@rivalrebels.com>
# Objective
- Add the ability to describe storage texture bindings when deriving
`AsBindGroup`.
- This is especially valuable for the compute story of bevy which
deserves some extra love imo.
## Solution
- This add the ability to annotate struct fields with a
`#[storage_texture(0)]` annotation.
- Instead of adding specific option parsing for all the image formats
and access modes, I simply accept a token stream and defer checking to
see if the option is valid to the compiler. This still results in useful
and friendly errors and is free to maintain and always compatible with
wgpu changes.
---
## Changelog
- The `#[storage_texture(..)]` annotation is now accepted for fields of
`Handle<Image>` in structs that derive `AsBindGroup`.
- The game_of_life compute shader example has been updated to use
`AsBindGroup` together with `[storage_texture(..)]` to obtain the
`BindGroupLayout`.
## Migration Guide
# Objective
#8219 changed the target type of a `transmute` without changing the one
transmuting from ([see the relevant
diff](55e9ab7c92 (diff-11413fb2eeba97978379d325353d32aa76eefd0af0c8e9b50b7f394ddfda7a26R351-R355))),
making them incompatible. This PR fixes this by changing the initial
type to match the target one (modulo lifetimes).
## Solution
Change the type to be transmuted from to match the one transmuting into
(modulo lifetimes)
# Objective
- This PR makes it so that `ReflectSerialize` and `ReflectDeserialize`
traits are properly derived on `Name`. This avoids having the internal
hash “leak” into the serialization when using reflection.
## Solution
- Added a conditional derive for `ReflectDeserialize` and
`ReflectSerialize` via `#[cfg_attr()]`
---
## Changelog
- `Name` now implements `ReflectDeserialize` and `ReflectSerialize`
whenever the `serialize` feature is enabled.
# Objective
Fix weird visuals when drawing a gizmo with a non-normed normal.
Fixes#11401
## Solution
Just normalize right before we draw. Could do it when constructing the
builder but that seems less consistent.
## Changelog
- gizmos.circle normal is now a Direction3d instead of a Vec3.
## Migration Guide
- Pass a Direction3d for gizmos.circle normal, eg.
`Direction3d::new(vec).unwrap_or(default)` or potentially
`Direction3d::new_unchecked(vec)` if you know your vec is definitely
normalized.
# Objective
- Since #11218, example `asset_processing` fails:
```
thread 'main' panicked at crates/bevy_asset/src/io/source.rs:489:18:
Failed to create file watcher: Error { kind: PathNotFound, paths: ["examples/asset/processing/imported_assets/Default"] }
```
start from a fresh git clone or delete the folder before running to
reproduce, it is in gitignore and should not be present on a fresh run
a657478675/.gitignore (L18)
## Solution
- Auto create the `imported_assets` folder if it is configured
---------
Co-authored-by: Kyle <37520732+nvdaz@users.noreply.github.com>
# Objective
`Direction2d::from_normalized` & `Direction3d::from_normalized` don't
emphasize that importance of the vector being normalized enough.
## Solution
Rename `from_normalized` to `new_unchecked` and add more documentation.
---
`Direction2d` and `Direction3d` were added somewhat recently in
https://github.com/bevyengine/bevy/pull/10466 (after 0.12), so I don't
think documenting the changelog and migration guide is necessary (Since
there is no major previous version to migrate from).
But here it is anyway in case it's needed:
## Changelog
- Renamed `Direction2d::from_normalized` and
`Direction3d::from_normalized` to `new_unchecked`.
## Migration Guide
- Renamed `Direction2d::from_normalized` and
`Direction3d::from_normalized` to `new_unchecked`.
---------
Co-authored-by: Tristan Guichaoua <33934311+tguichaoua@users.noreply.github.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
Currently, the `primitives` module is inside of the prelude for
`bevy_math`, but the actual primitives are not. This requires either
importing the shapes everywhere that uses them, or adding the
`primitives::` prefix:
```rust
let rectangle = meshes.add(primitives::Rectangle::new(5.0, 2.5));
```
(Note: meshing isn't actually implemented yet, but it's in #11431)
The primitives are meant to be used for a variety of tasks across
several crates, like for meshing, bounding volumes, gizmos, colliders,
and so on, so I think having them in the prelude is justified. It would
make several common tasks a lot more ergonomic.
```rust
let rectangle = meshes.add(Rectangle::new(5.0, 2.5));
```
## Solution
Add `primitives::*` to `bevy_math::prelude`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Currently, the only way to create an AABB is to specify its `min` and
`max` coordinates. However, it's often more useful to use the center and
half-size instead.
## Solution
Add `new` constructors for `Aabb2d` and `Aabb3d`.
This:
```rust
let aabb = Aabb3d {
min: center - half_size,
max: center + half_size,
}
```
becomes this:
```rust
let aabb = Aabb3d::new(center, half_size);
```
I also made the usage of "half-extents" vs. "half-size" a bit more
consistent.
# Objective
Currently, the `Ellipse` primitive is represented by a `half_width` and
`half_height`. To improve consistency (similarly to #11434), it might
make more sense to use a `Vec2` `half_size` instead.
Alternatively, to make the elliptical nature clearer, the properties
could also be called `radius_x` and `radius_y`.
Secondly, `Ellipse::new` currently takes a *full* width and height
instead of two radii. I would expect it to take the half-width and
half-height because ellipses and circles are almost always defined using
radii. I wouldn't expect `Circle::new` to take a diameter (if we had
that method).
## Solution
Change `Ellipse` to store a `half_size` and `new` to take the half-width
and half-height.
I also added a `from_size` method similar to `Rectangle::from_size`, and
added the `semi_minor` and `semi_major` helpers to get the
semi-minor/major radius.
# Objective
The `Rectangle` and `Cuboid` primitives currently use different
representations:
```rust
pub struct Rectangle {
/// The half width of the rectangle
pub half_width: f32,
/// The half height of the rectangle
pub half_height: f32,
}
pub struct Cuboid {
/// Half of the width, height and depth of the cuboid
pub half_extents: Vec3,
}
```
The property names and helpers are also inconsistent. `Cuboid` has
`half_extents`, but it also has a method called `from_size`. Most
existing code also uses "size" instead of "extents".
## Solution
Represent both `Rectangle` and `Cuboid` with `half_size` properties.
# Objective
Implements #9216
## Solution
- Replace `DiagnosticId` by `DiagnosticPath`. It's pre-hashed using
`const-fnv1a-hash` crate, so it's possible to create path in const
contexts.
---
## Changelog
- Replaced `DiagnosticId` by `DiagnosticPath`
- Set default history length to 120 measurements (2 seconds on 60 fps).
I've noticed hardcoded constant 20 everywhere and decided to change it
to `DEFAULT_MAX_HISTORY_LENGTH` , which is set to new diagnostics by
default. To override it, use `with_max_history_length`.
## Migration Guide
```diff
- const UNIQUE_DIAG_ID: DiagnosticId = DiagnosticId::from_u128(42);
+ const UNIQUE_DIAG_PATH: DiagnosticPath = DiagnosticPath::const_new("foo/bar");
- Diagnostic::new(UNIQUE_DIAG_ID, "example", 10)
+ Diagnostic::new(UNIQUE_DIAG_PATH).with_max_history_length(10)
- diagnostics.add_measurement(UNIQUE_DIAG_ID, || 42);
+ diagnostics.add_measurement(&UNIQUE_DIAG_ID, || 42);
```
# Objective
- since #9685 ,bevy introduce automatic batching of draw commands,
- `batch_and_prepare_render_phase` take the responsibility for batching
`phaseItem`,
- `GetBatchData` trait is used for indentify each phaseitem how to
batch. it defines a associated type `Data `used for Query to fetch data
from world.
- however,the impl of `GetBatchData ` in bevy always set ` type
Data=Entity` then we acually get following code
`let entity:Entity =query.get(item.entity())` that cause unnecessary
overhead .
## Solution
- remove associated type `Data ` and `Filter` from `GetBatchData `,
- change the type of the `query_item ` parameter in get_batch_data from`
Self::Data` to `Entity`.
- `batch_and_prepare_render_phase ` no longer takes a query using
`F::Data, F::Filter`
- `get_batch_data `now returns `Option<(Self::BufferData,
Option<Self::CompareData>)>`
---
## Performance
based in main merged with #11290
Window 11 ,Intel 13400kf, NV 4070Ti
![image](https://github.com/bevyengine/bevy/assets/45868716/f63b9d98-6aee-4057-a2c7-a2162b2db765)
frame time from 3.34ms to 3 ms, ~ 10%
![image](https://github.com/bevyengine/bevy/assets/45868716/a06eea9c-f79e-4324-8392-8d321560c5ba)
`batch_and_prepare_render_phase` from 800us ~ 400 us
## Migration Guide
trait `GetBatchData` no longer hold associated type `Data `and `Filter`
`get_batch_data` `query_item `type from `Self::Data` to `Entity` and
return `Option<(Self::BufferData, Option<Self::CompareData>)>`
`batch_and_prepare_render_phase` should not have a query
# Objective
Adjust bevy internals to utilize `Option<Res<State<S>>>` instead of
`Res<State<S>>`, to allow for adding/removing states at runtime and
avoid unexpected panics.
As requested here:
https://github.com/bevyengine/bevy/pull/10088#issuecomment-1869185413
---
## Changelog
- Changed the use of `world.resource`/`world.resource_mut` to
`world.get_resource`/`world.get_resource_mut` in the
`run_enter_schedule` and `apply_state_transition` systems and handled
the `None` option.
- `in_state` now returns a ` FnMut(Option<Res<State<S>>>) -> bool +
Clone`, returning `false` if the resource doesn't exist.
- `state_exists_and_equals` was marked as deprecated, and now just runs
and returns `in_state`, since their bevhaviour is now identical
- `state_changed` now takes an `Option<Res<State<S>>>` and returns
`false` if it does not exist.
I would like to remove `state_exists_and_equals` fully, but wanted to
ensure that is acceptable before doing so.
---------
Co-authored-by: Mike <mike.hsu@gmail.com>
# Objective
- `FromType<T>` for `ReflectComponent` and `ReflectBundle` currently
require `T: FromWorld` for two reasons:
- they include a `from_world` method;
- they create dummy `T`s using `FromWorld` and then `apply` a `&dyn
Reflect` to it to simulate `FromReflect`.
- However `FromWorld`/`Default` may be difficult/weird/impractical to
implement, while `FromReflect` is easier and also more natural for the
job.
- See also
https://discord.com/channels/691052431525675048/1146022009554337792
## Solution
- Split `from_world` from `ReflectComponent` and `ReflectBundle` into
its own `ReflectFromWorld` struct.
- Replace the requirement on `FromWorld` in `ReflectComponent` and
`ReflectBundle` with `FromReflect`
---
## Changelog
- `ReflectComponent` and `ReflectBundle` no longer offer a `from_world`
method.
- `ReflectComponent` and `ReflectBundle`'s `FromType<T>` implementation
no longer requires `T: FromWorld`, but now requires `FromReflect`.
- `ReflectComponent::insert`, `ReflectComponent::apply_or_insert` and
`ReflectComponent::copy` now take an extra `&TypeRegistry` parameter.
- There is now a new `ReflectFromWorld` struct.
## Migration Guide
- Existing uses of `ReflectComponent::from_world` and
`ReflectBundle::from_world` will have to be changed to
`ReflectFromWorld::from_world`.
- Users of `#[reflect(Component)]` and `#[reflect(Bundle)]` will need to
also implement/derive `FromReflect`.
- Users of `#[reflect(Component)]` and `#[reflect(Bundle)]` may now want
to also add `FromWorld` to the list of reflected traits in case their
`FromReflect` implementation may fail.
- Users of `ReflectComponent` will now need to pass a `&TypeRegistry` to
its `insert`, `apply_or_insert` and `copy` methods.
This pull request re-submits #10057, which was backed out for breaking
macOS, iOS, and Android. I've tested this version on macOS and Android
and on the iOS simulator.
# Objective
This pull request implements *reflection probes*, which generalize
environment maps to allow for multiple environment maps in the same
scene, each of which has an axis-aligned bounding box. This is a
standard feature of physically-based renderers and was inspired by [the
corresponding feature in Blender's Eevee renderer].
## Solution
This is a minimal implementation of reflection probes that allows
artists to define cuboid bounding regions associated with environment
maps. For every view, on every frame, a system builds up a list of the
nearest 4 reflection probes that are within the view's frustum and
supplies that list to the shader. The PBR fragment shader searches
through the list, finds the first containing reflection probe, and uses
it for indirect lighting, falling back to the view's environment map if
none is found. Both forward and deferred renderers are fully supported.
A reflection probe is an entity with a pair of components, *LightProbe*
and *EnvironmentMapLight* (as well as the standard *SpatialBundle*, to
position it in the world). The *LightProbe* component (along with the
*Transform*) defines the bounding region, while the
*EnvironmentMapLight* component specifies the associated diffuse and
specular cubemaps.
A frequent question is "why two components instead of just one?" The
advantages of this setup are:
1. It's readily extensible to other types of light probes, in particular
*irradiance volumes* (also known as ambient cubes or voxel global
illumination), which use the same approach of bounding cuboids. With a
single component that applies to both reflection probes and irradiance
volumes, we can share the logic that implements falloff and blending
between multiple light probes between both of those features.
2. It reduces duplication between the existing *EnvironmentMapLight* and
these new reflection probes. Systems can treat environment maps attached
to cameras the same way they treat environment maps applied to
reflection probes if they wish.
Internally, we gather up all environment maps in the scene and place
them in a cubemap array. At present, this means that all environment
maps must have the same size, mipmap count, and texture format. A
warning is emitted if this restriction is violated. We could potentially
relax this in the future as part of the automatic mipmap generation
work, which could easily do texture format conversion as part of its
preprocessing.
An easy way to generate reflection probe cubemaps is to bake them in
Blender and use the `export-blender-gi` tool that's part of the
[`bevy-baked-gi`] project. This tool takes a `.blend` file containing
baked cubemaps as input and exports cubemap images, pre-filtered with an
embedded fork of the [glTF IBL Sampler], alongside a corresponding
`.scn.ron` file that the scene spawner can use to recreate the
reflection probes.
Note that this is intentionally a minimal implementation, to aid
reviewability. Known issues are:
* Reflection probes are basically unsupported on WebGL 2, because WebGL
2 has no cubemap arrays. (Strictly speaking, you can have precisely one
reflection probe in the scene if you have no other cubemaps anywhere,
but this isn't very useful.)
* Reflection probes have no falloff, so reflections will abruptly change
when objects move from one bounding region to another.
* As mentioned before, all cubemaps in the world of a given type
(diffuse or specular) must have the same size, format, and mipmap count.
Future work includes:
* Blending between multiple reflection probes.
* A falloff/fade-out region so that reflected objects disappear
gradually instead of vanishing all at once.
* Irradiance volumes for voxel-based global illumination. This should
reuse much of the reflection probe logic, as they're both GI techniques
based on cuboid bounding regions.
* Support for WebGL 2, by breaking batches when reflection probes are
used.
These issues notwithstanding, I think it's best to land this with
roughly the current set of functionality, because this patch is useful
as is and adding everything above would make the pull request
significantly larger and harder to review.
---
## Changelog
### Added
* A new *LightProbe* component is available that specifies a bounding
region that an *EnvironmentMapLight* applies to. The combination of a
*LightProbe* and an *EnvironmentMapLight* offers *reflection probe*
functionality similar to that available in other engines.
[the corresponding feature in Blender's Eevee renderer]:
https://docs.blender.org/manual/en/latest/render/eevee/light_probes/reflection_cubemaps.html
[`bevy-baked-gi`]: https://github.com/pcwalton/bevy-baked-gi
[glTF IBL Sampler]: https://github.com/KhronosGroup/glTF-IBL-Sampler
# Objective
When working within `bevy_ecs`, we can't use the `log_once` macros due
to their placement in `bevy_log` - which depends on `bevy_ecs`. All this
create does is migrate those macros to the `bevy_utils` crate, while
still re-exporting them in `bevy_log`.
created to resolve this:
https://github.com/bevyengine/bevy/pull/11417#discussion_r1458100211
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
After the Gizmos changes, `App::init_gizmos_group` turned into a
important function that for sure mustn't panic. The problem is: the
actual implementation causes a panic if somehow the code is runned
before `GizmoPlugin` was added to the App
- The error occurs here for example:
```rust
fn main() {
App::new()
.init_gizmo_group::<MyGizmoConfig>()
.add_plugins(DefaultPlugins)
.run();
}
#[derive(Default, Reflect, GizmoConfigGroup)]
struct MyGizmoConfig;
```
![image](https://github.com/bevyengine/bevy/assets/126117294/35e75608-0946-4320-8035-00a82562e37e)
## Solution
- Instead of panicking when getting `GizmoConfigStore`, insert the store
in `App::init_gizmos_group` if needed
---
## Changelog
### Changed
- Changed App::init_gizmos_group to insert the resource if it don't
exist
### Removed
- Removed explicit init of `GizmoConfigStore`
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- Some users want to change the default texture usage of the main camera
but they are currently hardcoded
## Solution
- Add a component that is used to configure the main texture usage field
---
## Changelog
Added `CameraMainTextureUsage`
Added `CameraMainTextureUsage` to `Camera3dBundle` and `Camera2dBundle`
## Migration Guide
Add `main_texture_usages: Default::default()` to your camera bundle.
# Notes
Inspired by: #6815
# Objective
- Tests are manually checking whether derived types implement certain
traits. (Specifically in `bevy_reflect.)
- #11182 introduces
[`static_assertions`](https://docs.rs/static_assertions/) to
automatically check this.
- Simplifies `Reflect` test in #11195.
- Closes#11196.
## Solution
- Add `static_assertions` and replace current tests.
---
I wasn't sure whether to remove the existing test or not. What do you
think?
# Objective
- Add methods to get Change Ticks for a given resource by type or
ComponentId
- Fixes#11390
The `is_resource_id_changed` requested in the Issue already exists, this
adds their request for `get_resource_change_ticks`
## Solution
- Added two methods to get change ticks by Type or ComponentId
# Objective
Closes#10570.
#10946 added bounding volume types and traits, but didn't use them for
anything yet. This PR implements `Bounded2d` and `Bounded3d` for Bevy's
primitive shapes.
## Solution
Implement `Bounded2d` and `Bounded3d` for primitive shapes. This allows
computing AABBs and bounding circles/spheres for them.
For most shapes, there are several ways of implementing bounding
volumes. I took inspiration from [Parry's bounding
volumes](https://github.com/dimforge/parry/tree/master/src/bounding_volume),
[Inigo Quilez](http://iquilezles.org/articles/diskbbox/), and figured
out the rest myself using geometry. I tried to comment all slightly
non-trivial or unclear math to make it understandable.
Parry uses support mapping (finding the farthest point in some direction
for convex shapes) for some AABBs like cones, cylinders, and line
segments. This involves several quat operations and normalizations, so I
opted for the simpler and more efficient geometric approaches shown in
[Quilez's article](http://iquilezles.org/articles/diskbbox/).
Below you can see some of the bounding volumes working in 2D and 3D.
Note that I can't conveniently add these examples yet because they use
primitive shape meshing, which is still WIP.
https://github.com/bevyengine/bevy/assets/57632562/4465cbc6-285b-4c71-b62d-a2b3ee16f8b4https://github.com/bevyengine/bevy/assets/57632562/94b4ac84-a092-46d7-b438-ce2e971496a4
---
## Changelog
- Implemented `Bounded2d`/`Bounded3d` for primitive shapes
- Added `from_point_cloud` method for bounding volumes (used by many
bounding implementations)
- Added `point_cloud_2d/3d_center` and `rotate_vec2` utility functions
- Added `RegularPolygon::vertices` method (used in regular polygon AABB
construction)
- Added `Triangle::circumcenter` method (used in triangle bounding
circle construction)
- Added bounding circle/sphere creation from AABBs and vice versa
## Extra
Do we want to implement `Bounded2d` for some "3D-ish" shapes too? For
example, capsules are sort of dimension-agnostic and useful for 2D, so I
think that would be good to implement. But a cylinder in 2D is just a
rectangle, and a cone is a triangle, so they wouldn't make as much sense
to me. A conical frustum would be an isosceles trapezoid, which could be
useful, but I'm not sure if computing the 2D AABB of a 3D frustum makes
semantic sense.
# Objective
This PR aims to implement multiple configs for gizmos as discussed in
#9187.
## Solution
Configs for the new `GizmoConfigGroup`s are stored in a
`GizmoConfigStore` resource and can be accesses using a type based key
or iterated over. This type based key doubles as a standardized location
where plugin authors can put their own configuration not covered by the
standard `GizmoConfig` struct. For example the `AabbGizmoGroup` has a
default color and toggle to show all AABBs. New configs can be
registered using `app.init_gizmo_group::<T>()` during startup.
When requesting the `Gizmos<T>` system parameter the generic type
determines which config is used. The config structs are available
through the `Gizmos` system parameter allowing for easy access while
drawing your gizmos.
Internally, resources and systems used for rendering (up to an including
the extract system) are generic over the type based key and inserted on
registering a new config.
## Alternatives
The configs could be stored as components on entities with markers which
would make better use of the ECS. I also implemented this approach
([here](https://github.com/jeliag/bevy/tree/gizmo-multiconf-comp)) and
believe that the ergonomic benefits of a central config store outweigh
the decreased use of the ECS.
## Unsafe Code
Implementing system parameter by hand is unsafe but seems to be required
to access the config store once and not on every gizmo draw function
call. This is critical for performance. ~Is there a better way to do
this?~
## Future Work
New gizmos (such as #10038, and ideas from #9400) will require custom
configuration structs. Should there be a new custom config for every
gizmo type, or should we group them together in a common configuration?
(for example `EditorGizmoConfig`, or something more fine-grained)
## Changelog
- Added `GizmoConfigStore` resource and `GizmoConfigGroup` trait
- Added `init_gizmo_group` to `App`
- Added early returns to gizmo drawing increasing performance when
gizmos are disabled
- Changed `GizmoConfig` and aabb gizmos to use new `GizmoConfigStore`
- Changed `Gizmos` system parameter to use type based key to retrieve
config
- Changed resources and systems used for gizmo rendering to be generic
over type based key
- Changed examples (3d_gizmos, 2d_gizmos) to showcase new API
## Migration Guide
- `GizmoConfig` is no longer a resource and has to be accessed through
`GizmoConfigStore` resource. The default config group is
`DefaultGizmoGroup`, but consider using your own custom config group if
applicable.
---------
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
This adds events for assets that fail to load along with minor utility
methods to make them useful. This paves the way for users writing their
own error handling and retry systems, plus Bevy including robust retry
handling: #11349.
* Addresses #11288
* Needed for #11349
# Solution
```rust
/// An event emitted when a specific [`Asset`] fails to load.
#[derive(Event, Clone, Debug)]
pub struct AssetLoadFailedEvent<A: Asset> {
pub id: AssetId<A>,
/// The original handle returned when the asset load was requested.
pub handle: Option<Handle<A>>,
/// The asset path that was attempted.
pub path: AssetPath<'static>,
/// Why the asset failed to load.
pub error: AssetLoadError,
}
```
I started implementing `AssetEvent::Failed` like suggested in #11288,
but decided it was better as its own type because:
* I think it makes sense for `AssetEvent` to only refer to assets that
actually exist.
* In order to return `AssetLoadError` in the event (which is useful
information for error handlers that might attempt a retry) we would have
to remove `Copy` from `AssetEvent`.
* There are numerous places in the render app that match against
`AssetEvent`, and I don't think it's worth introducing extra noise about
assets that don't exist.
I also introduced `UntypedAssetLoadErrorEvent`, which is very useful in
places that need to support type flexibility, like an Asset-agnostic
retry plugin.
# Changelog
* **Added:** `AssetLoadFailedEvent<A>`
* **Added**: `UntypedAssetLoadFailedEvent`
* **Added:** `AssetReaderError::Http` for status code information on
HTTP errors. Before this, status codes were only available by parsing
the error message of generic `Io` errors.
* **Added:** `asset_server.get_path_id(path)`. This method simply gets
the asset id for the path. Without this, one was left using
`get_path_handle(path)`, which has the overhead of returning a strong
handle.
* **Fixed**: Made `AssetServer` loads return the same handle for assets
that already exist in a failed state. Now, when you attempt a `load`
that's in a `LoadState::Failed` state, it'll re-use the original asset
id. The advantage of this is that any dependent assets created using the
original handle will "unbreak" if a retry succeeds.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
fix an occasional crash when moving ui root nodes between cameras.
occasionally, updating the TargetCamera of a ui element and then
removing the element causes a crash.
i believe that is because when we assign a child in taffy, the old
parent doesn't remove that child from it's children, so we have:
```
user: create root node N1, camera A
-> layout::set_camera_children(A) :
- create implicit node A1
- assign 1 as child -> taffy.children[A1] = [N1], taffy.parents[1] = A1
user: move root node N1 to camera B
-> layout::set_camera_children(B) :
- create implicit node B1
- assign 1 as child -> taffy.children[A1] = [N1], taffy.children[B1] = [N1], taffy.parents[1] = B1
-> layout::set_camera_children(A) :
- remove implicit node A1 (which still has N1 as a child) ->
-> taffy sets parent[N1] = None ***
-> taffy.children[B1] = [N1], taffy.parents[1] = None
user: remove N1
-> layout::remove_entities(N1)
- since parent[N1] is None, it's not removed from B1 -> taffy.children[B1] = [N1], taffy.parents[1] is removed
-> layout::set_camera_children(B)
- remove implicit node B1
- taffy crash accessing taffy.parents[N1]
```
## Solution
we can work around this by making sure to remove the child from the old
parent if one exists (this pr).
i think a better fix may be for taffy to check in `Taffy::remove` and
only set the child's parent to None if it is currently equal to the node
being removed but i'm not sure if there's an explicit assumption we're
violating here (@nicoburns).
# Objective
- `DynamicUniformBuffer::push` takes an owned `T` but only uses a shared
reference to it
- This in turn requires users of `DynamicUniformBuffer::push` to
potentially unecessarily clone data
## Solution
- Have `DynamicUniformBuffer::push` take a shared reference to `T`
---
## Changelog
- `DynamicUniformBuffer::push` now takes a `&T` instead of `T`
## Migration Guide
- Users of `DynamicUniformBuffer::push` now need to pass references to
`DynamicUniformBuffer::push` (e.g. existing `uniforms.push(value)` will
now become `uniforms.push(&value)`)
# Objective
Expand the existing `Query` API to support more dynamic use cases i.e.
scripting.
## Prior Art
- #6390
- #8308
- #10037
## Solution
- Create a `QueryBuilder` with runtime methods to define the set of
component accesses for a built query.
- Create new `WorldQueryData` implementations `FilteredEntityMut` and
`FilteredEntityRef` as variants of `EntityMut` and `EntityRef` that
provide run time checked access to the components included in a given
query.
- Add new methods to `Query` to create "query lens" with a subset of the
access of the initial query.
### Query Builder
The `QueryBuilder` API allows you to define a query at runtime. At it's
most basic use it will simply create a query with the corresponding type
signature:
```rust
let query = QueryBuilder::<Entity, With<A>>::new(&mut world).build();
// is equivalent to
let query = QueryState::<Entity, With<A>>::new(&mut world);
```
Before calling `.build()` you also have the opportunity to add
additional accesses and filters. Here is a simple example where we add
additional filter terms:
```rust
let entity_a = world.spawn((A(0), B(0))).id();
let entity_b = world.spawn((A(0), C(0))).id();
let mut query_a = QueryBuilder::<Entity>::new(&mut world)
.with::<A>()
.without::<C>()
.build();
assert_eq!(entity_a, query_a.single(&world));
```
This alone is useful in that allows you to decide which archetypes your
query will match at runtime. However it is also very limited, consider a
case like the following:
```rust
let query_a = QueryBuilder::<&A>::new(&mut world)
// Add an additional access
.data::<&B>()
.build();
```
This will grant the query an additional read access to component B
however we have no way of accessing the data while iterating as the type
signature still only includes &A. For an even more concrete example of
this consider dynamic components:
```rust
let query_a = QueryBuilder::<Entity>::new(&mut world)
// Adding a filter is easy since it doesn't need be read later
.with_id(component_id_a)
// How do I access the data of this component?
.ref_id(component_id_b)
.build();
```
With this in mind the `QueryBuilder` API seems somewhat incomplete by
itself, we need some way method of accessing the components dynamically.
So here's one:
### Query Transmutation
If the problem is not having the component in the type signature why not
just add it? This PR also adds transmute methods to `QueryBuilder` and
`QueryState`. Here's a simple example:
```rust
world.spawn(A(0));
world.spawn((A(1), B(0)));
let mut query = QueryBuilder::<()>::new(&mut world)
.with::<B>()
.transmute::<&A>()
.build();
query.iter(&world).for_each(|a| assert_eq!(a.0, 1));
```
The `QueryState` and `QueryBuilder` transmute methods look quite similar
but are different in one respect. Transmuting a builder will always
succeed as it will just add the additional accesses needed for the new
terms if they weren't already included. Transmuting a `QueryState` will
panic in the case that the new type signature would give it access it
didn't already have, for example:
```rust
let query = QueryState::<&A, Option<&B>>::new(&mut world);
/// This is fine, the access for Option<&A> is less restrictive than &A
query.transmute::<Option<&A>>(&world);
/// Oh no, this would allow access to &B on entities that might not have it, so it panics
query.transmute::<&B>(&world);
/// This is right out
query.transmute::<&C>(&world);
```
This is quite an appealing API to also have available on `Query` however
it does pose one additional wrinkle: In order to to change the iterator
we need to create a new `QueryState` to back it. `Query` doesn't own
it's own state though, it just borrows it, so we need a place to borrow
it from. This is why `QueryLens` exists, it is a place to store the new
state so it can be borrowed when you call `.query()` leaving you with an
API like this:
```rust
fn function_that_takes_a_query(query: &Query<&A>) {
// ...
}
fn system(query: Query<(&A, &B)>) {
let lens = query.transmute_lens::<&A>();
let q = lens.query();
function_that_takes_a_query(&q);
}
```
Now you may be thinking: Hey, wait a second, you introduced the problem
with dynamic components and then described a solution that only works
for static components! Ok, you got me, I guess we need a bit more:
### Filtered Entity References
Currently the only way you can access dynamic components on entities
through a query is with either `EntityMut` or `EntityRef`, however these
can access all components and so conflict with all other accesses. This
PR introduces `FilteredEntityMut` and `FilteredEntityRef` as
alternatives that have additional runtime checking to prevent accessing
components that you shouldn't. This way you can build a query with a
`QueryBuilder` and actually access the components you asked for:
```rust
let mut query = QueryBuilder::<FilteredEntityRef>::new(&mut world)
.ref_id(component_id_a)
.with(component_id_b)
.build();
let entity_ref = query.single(&world);
// Returns Some(Ptr) as we have that component and are allowed to read it
let a = entity_ref.get_by_id(component_id_a);
// Will return None even though the entity does have the component, as we are not allowed to read it
let b = entity_ref.get_by_id(component_id_b);
```
For the most part these new structs have the exact same methods as their
non-filtered equivalents.
Putting all of this together we can do some truly dynamic ECS queries,
check out the `dynamic` example to see it in action:
```
Commands:
comp, c Create new components
spawn, s Spawn entities
query, q Query for entities
Enter a command with no parameters for usage.
> c A, B, C, Data 4
Component A created with id: 0
Component B created with id: 1
Component C created with id: 2
Component Data created with id: 3
> s A, B, Data 1
Entity spawned with id: 0v0
> s A, C, Data 0
Entity spawned with id: 1v0
> q &Data
0v0: Data: [1, 0, 0, 0]
1v0: Data: [0, 0, 0, 0]
> q B, &mut Data
0v0: Data: [2, 1, 1, 1]
> q B || C, &Data
0v0: Data: [2, 1, 1, 1]
1v0: Data: [0, 0, 0, 0]
```
## Changelog
- Add new `transmute_lens` methods to `Query`.
- Add new types `QueryBuilder`, `FilteredEntityMut`, `FilteredEntityRef`
and `QueryLens`
- `update_archetype_component_access` has been removed, archetype
component accesses are now determined by the accesses set in
`update_component_access`
- Added method `set_access` to `WorldQuery`, this is called before
`update_component_access` for queries that have a restricted set of
accesses, such as those built by `QueryBuilder` or `QueryLens`. This is
primarily used by the `FilteredEntity*` variants and has an empty trait
implementation.
- Added method `get_state` to `WorldQuery` as a fallible version of
`init_state` when you don't have `&mut World` access.
## Future Work
Improve performance of `FilteredEntityMut` and `FilteredEntityRef`,
currently they have to determine the accesses a query has in a given
archetype during iteration which is far from ideal, especially since we
already did the work when matching the archetype in the first place. To
avoid making more internal API changes I have left it out of this PR.
---------
Co-authored-by: Mike Hsu <mike.hsu@gmail.com>
# Objective
Tried using "embedded_watcher" feature and `embedded_asset!()` from
another crate. The assets embedded fine but were not "watched." The
problem appears to be that checking for the feature was done inside the
macro, so rather than checking if "embedded_watcher" was enabled for
bevy, it would check if it was enabled for the current crate.
## Solution
I extracted the checks for the "embedded_watcher" feature into its own
function called `watched_path()`. No external changes.
### Alternative Solution
An alternative fix would be to not do any feature checking in
`embedded_asset!()` or an extracted function and always send the
full_path to `insert_asset()` where it's promptly dropped when the
feature isn't turned on. That would be simpler.
```
($app: ident, $source_path: expr, $path: expr) => {{
let mut embedded = $app
.world
.resource_mut::<$crate::io::embedded::EmbeddedAssetRegistry>();
let path = $crate::embedded_path!($source_path, $path);
//#[cfg(feature = "embedded_watcher")]
let full_path = std::path::Path::new(file!()).parent().unwrap().join($path);
//#[cfg(not(feature = "embedded_watcher"))]
//let full_path = std::path::PathBuf::new();
embedded.insert_asset(full_path, &path, include_bytes!($path));
}};
```
## Changelog
> Fix embedded_watcher feature to work with external crates
Rebased and finished version of
https://github.com/bevyengine/bevy/pull/8407. Huge thanks to @GitGhillie
for adjusting all the examples, and the many other people who helped
write this PR (@superdump , @coreh , among others) :)
Fixes https://github.com/bevyengine/bevy/issues/8369
---
## Changelog
- Added a `brightness` control to `Skybox`.
- Added an `intensity` control to `EnvironmentMapLight`.
- Added `ExposureSettings` and `PhysicalCameraParameters` for
controlling exposure of 3D cameras.
- Removed the baked-in `DirectionalLight` exposure Bevy previously
hardcoded internally.
## Migration Guide
- If using a `Skybox` or `EnvironmentMapLight`, use the new `brightness`
and `intensity` controls to adjust their strength.
- All 3D scene will now have different apparent brightnesses due to Bevy
implementing proper exposure controls. You will have to adjust the
intensity of your lights and/or your camera exposure via the new
`ExposureSettings` component to compensate.
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: GitGhillie <jillisnoordhoek@gmail.com>
Co-authored-by: Marco Buono <thecoreh@gmail.com>
Co-authored-by: vero <email@atlasdostal.com>
Co-authored-by: atlas dostal <rodol@rivalrebels.com>
# Objective
gltf-rs does its own computations when accessing `transform.matrix()`
which does not use glam types, rendering #11238 useless if people were
to load gltf models and expecting the results to be deterministic across
platforms.
## Solution
Move the computation to bevy side which uses glam types, it was already
used in one place, so I created one common function to handle the two
cases.
The added benefit this has, is that some gltf files can have
translation, rotation and scale directly instead of matrix which skips
the transform computation completely, win-win.
# Objective
> Old MR: #5072
> ~~Associated UI MR: #5070~~
> Adresses #1618
Unify sprite management
## Solution
- Remove the `Handle<Image>` field in `TextureAtlas` which is the main
cause for all the boilerplate
- Remove the redundant `TextureAtlasSprite` component
- Renamed `TextureAtlas` asset to `TextureAtlasLayout`
([suggestion](https://github.com/bevyengine/bevy/pull/5103#discussion_r917281844))
- Add a `TextureAtlas` component, containing the atlas layout handle and
the section index
The difference between this solution and #5072 is that instead of the
`enum` approach is that we can more easily manipulate texture sheets
without any breaking changes for classic `SpriteBundle`s (@mockersf
[comment](https://github.com/bevyengine/bevy/pull/5072#issuecomment-1165836139))
Also, this approach is more *data oriented* extracting the
`Handle<Image>` and avoiding complex texture atlas manipulations to
retrieve the texture in both applicative and engine code.
With this method, the only difference between a `SpriteBundle` and a
`SpriteSheetBundle` is an **additional** component storing the atlas
handle and the index.
~~This solution can be applied to `bevy_ui` as well (see #5070).~~
EDIT: I also applied this solution to Bevy UI
## Changelog
- (**BREAKING**) Removed `TextureAtlasSprite`
- (**BREAKING**) Renamed `TextureAtlas` to `TextureAtlasLayout`
- (**BREAKING**) `SpriteSheetBundle`:
- Uses a `Sprite` instead of a `TextureAtlasSprite` component
- Has a `texture` field containing a `Handle<Image>` like the
`SpriteBundle`
- Has a new `TextureAtlas` component instead of a
`Handle<TextureAtlasLayout>`
- (**BREAKING**) `DynamicTextureAtlasBuilder::add_texture` takes an
additional `&Handle<Image>` parameter
- (**BREAKING**) `TextureAtlasLayout::from_grid` no longer takes a
`Handle<Image>` parameter
- (**BREAKING**) `TextureAtlasBuilder::finish` now returns a
`Result<(TextureAtlasLayout, Handle<Image>), _>`
- `bevy_text`:
- `GlyphAtlasInfo` stores the texture `Handle<Image>`
- `FontAtlas` stores the texture `Handle<Image>`
- `bevy_ui`:
- (**BREAKING**) Removed `UiAtlasImage` , the atlas bundle is now
identical to the `ImageBundle` with an additional `TextureAtlas`
## Migration Guide
* Sprites
```diff
fn my_system(
mut images: ResMut<Assets<Image>>,
- mut atlases: ResMut<Assets<TextureAtlas>>,
+ mut atlases: ResMut<Assets<TextureAtlasLayout>>,
asset_server: Res<AssetServer>
) {
let texture_handle: asset_server.load("my_texture.png");
- let layout = TextureAtlas::from_grid(texture_handle, Vec2::new(25.0, 25.0), 5, 5, None, None);
+ let layout = TextureAtlasLayout::from_grid(Vec2::new(25.0, 25.0), 5, 5, None, None);
let layout_handle = atlases.add(layout);
commands.spawn(SpriteSheetBundle {
- sprite: TextureAtlasSprite::new(0),
- texture_atlas: atlas_handle,
+ atlas: TextureAtlas {
+ layout: layout_handle,
+ index: 0
+ },
+ texture: texture_handle,
..Default::default()
});
}
```
* UI
```diff
fn my_system(
mut images: ResMut<Assets<Image>>,
- mut atlases: ResMut<Assets<TextureAtlas>>,
+ mut atlases: ResMut<Assets<TextureAtlasLayout>>,
asset_server: Res<AssetServer>
) {
let texture_handle: asset_server.load("my_texture.png");
- let layout = TextureAtlas::from_grid(texture_handle, Vec2::new(25.0, 25.0), 5, 5, None, None);
+ let layout = TextureAtlasLayout::from_grid(Vec2::new(25.0, 25.0), 5, 5, None, None);
let layout_handle = atlases.add(layout);
commands.spawn(AtlasImageBundle {
- texture_atlas_image: UiTextureAtlasImage {
- index: 0,
- flip_x: false,
- flip_y: false,
- },
- texture_atlas: atlas_handle,
+ atlas: TextureAtlas {
+ layout: layout_handle,
+ index: 0
+ },
+ image: UiImage {
+ texture: texture_handle,
+ flip_x: false,
+ flip_y: false,
+ },
..Default::default()
});
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
- The
[`build-templated-pages`](4778fbeb65/tools/build-templated-pages)
tool is used to render the Markdown templates in the
[docs-template](4778fbeb65/docs-template)
folder.
- It depends on out outdated version of `toml_edit`.
## Solution
- Bump `toml_edit` to 0.21, disabling all features except `parse`.
# Objective
Add support for presenting each UI tree on a specific window and
viewport, while making as few breaking changes as possible.
This PR is meant to resolve the following issues at once, since they're
all related.
- Fixes#5622
- Fixes#5570
- Fixes#5621
Adopted #5892 , but started over since the current codebase diverged
significantly from the original PR branch. Also, I made a decision to
propagate component to children instead of recursively iterating over
nodes in search for the root.
## Solution
Add a new optional component that can be inserted to UI root nodes and
propagate to children to specify which camera it should render onto.
This is then used to get the render target and the viewport for that UI
tree. Since this component is optional, the default behavior should be
to render onto the single camera (if only one exist) and warn of
ambiguity if multiple cameras exist. This reduces the complexity for
users with just one camera, while giving control in contexts where it
matters.
## Changelog
- Adds `TargetCamera(Entity)` component to specify which camera should a
node tree be rendered into. If only one camera exists, this component is
optional.
- Adds an example of rendering UI to a texture and using it as a
material in a 3D world.
- Fixes recalculation of physical viewport size when target scale factor
changes. This can happen when the window is moved between displays with
different DPI.
- Changes examples to demonstrate assigning UI to different viewports
and windows and make interactions in an offset viewport testable.
- Removes `UiCameraConfig`. UI visibility now can be controlled via
combination of explicit `TargetCamera` and `Visibility` on the root
nodes.
---------
Co-authored-by: davier <bricedavier@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
- Update async channel to v2.
## Solution
- async channel doesn't support `send_blocking` on wasm anymore. So
don't compile the pipelined rendering plugin on wasm anymore.
- Replaces https://github.com/bevyengine/bevy/pull/10405
## Migration Guide
- The `PipelinedRendering` plugin is no longer exported on wasm. If you
are including it in your wasm builds you should remove it.
```rust
#[cfg(all(not(target_arch = "wasm32"))]
app.add_plugins(bevy_render::pipelined_rendering::PipelinedRenderingPlugin);
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Partial fix for #11235
- Fixes#11274
- Fixes#11320
- Fixes#11273
## Solution
- check update mode to trigger redraw request, instead of once a redraw
request has been triggered
- don't ignore device event in case of `Reactive` update mode
- make sure that at least 5 updates are triggered on application start
to ensure everything is correctly initialized
- trigger manual updates instead of relying on redraw requests when
there are no window or they are not visible
> Replaces #5213
# Objective
Implement sprite tiling and [9 slice
scaling](https://en.wikipedia.org/wiki/9-slice_scaling) for
`bevy_sprite`.
Allowing slice scaling and texture tiling.
Basic scaling vs 9 slice scaling:
![Traditional_scaling_vs_9-slice_scaling](https://user-images.githubusercontent.com/26703856/177335801-27f6fa27-c569-4ce6-b0e6-4f54e8f4e80a.svg)
Slicing example:
<img width="481" alt="Screenshot 2022-07-05 at 15 05 49"
src="https://user-images.githubusercontent.com/26703856/177336112-9e961af0-c0af-4197-aec9-430c1170a79d.png">
Tiling example:
<img width="1329" alt="Screenshot 2023-11-16 at 13 53 32"
src="https://github.com/bevyengine/bevy/assets/26703856/14db39b7-d9e0-4bc3-ba0e-b1f2db39ae8f">
# Solution
- `SpriteBundlue` now has a `scale_mode` component storing a
`SpriteScaleMode` enum with three variants:
- `Stretched` (default)
- `Tiled` to have sprites tile horizontally and/or vertically
- `Sliced` allowing 9 slicing the texture and optionally tile some
sections with a `Textureslicer`.
- `bevy_sprite` has two extra systems to compute a
`ComputedTextureSlices` if necessary,:
- One system react to changes on `Sprite`, `Handle<Image>` or
`SpriteScaleMode`
- The other listens to `AssetEvent<Image>` to compute slices on sprites
when the texture is ready or changed
- I updated the `bevy_sprite` extraction stage to extract potentially
multiple textures instead of one, depending on the presence of
`ComputedTextureSlices`
- I added two examples showcasing the slicing and tiling feature.
The addition of `ComputedTextureSlices` as a cache is to avoid querying
the image data, to retrieve its dimensions, every frame in a extract or
prepare stage. Also it reacts to changes so we can have stuff like this
(tiling example):
https://github.com/bevyengine/bevy/assets/26703856/a349a9f3-33c3-471f-8ef4-a0e5dfce3b01
# Related
- [ ] Once #5103 or #10099 is merged I can enable tiling and slicing for
texture sheets as ui
# To discuss
There is an other option, to consider slice/tiling as part of the asset,
using the new asset preprocessing but I have no clue on how to do it.
Also, instead of retrieving the Image dimensions, we could use the same
system as the sprite sheet and have the user give the image dimensions
directly (grid). But I think it's less user friendly
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
Adds support for accessing raw extension data of loaded GLTF assets
## Solution
Via the GLTF loader settings, you can specify whether or not to include
the GLTF source. While not the ideal way of solving this problem,
modeling all of GLTF within Bevy just for extensions adds a lot of
complexity to the way Bevy handles GLTF currently. See the example GLTF
meta file and code
```
(
meta_format_version: "1.0",
asset: Load(
loader: "bevy_gltf::loader::GltfLoader",
settings: (
load_meshes: true,
load_cameras: true,
load_lights: true,
include_source: true,
),
),
)
```
```rs
pub fn load_gltf(mut commands: Commands, assets: Res<AssetServer>) {
let my_gltf = assets.load("test_platform.gltf");
commands.insert_resource(MyAssetPack {
spawned: false,
handle: my_gltf,
});
}
#[derive(Resource)]
pub struct MyAssetPack {
pub spawned: bool,
pub handle: Handle<Gltf>,
}
pub fn spawn_gltf_objects(
mut commands: Commands,
mut my: ResMut<MyAssetPack>,
assets_gltf: Res<Assets<Gltf>>,
) {
// This flag is used to because this system has to be run until the asset is loaded.
// If there's a better way of going about this I am unaware of it.
if my.spawned {
return;
}
if let Some(gltf) = assets_gltf.get(&my.handle) {
info!("spawn");
my.spawned = true;
// spawn the first scene in the file
commands.spawn(SceneBundle {
scene: gltf.scenes[0].clone(),
..Default::default()
});
let source = gltf.source.as_ref().unwrap();
info!("materials count {}", &source.materials().size_hint().0);
info!(
"materials ext is some {}",
&source.materials().next().unwrap().extensions().is_some()
);
}
}
```
---
## Changelog
Added support for GLTF extensions through including raw GLTF source via
loader flag `GltfLoaderSettings::include_source == true`, stored in
`Gltf::source: Option<gltf::Gltf>`
## Migration Guide
This will have issues with "asset migrations", as there is currently no
way for .meta files to be migrated. Attempting to migrate .meta files
without the new flag will yield the following error:
```
bevy_asset::server: Failed to deserialize meta for asset test_platform.gltf: Failed to deserialize asset meta: SpannedError { code: MissingStructField { field: "include_source", outer: Some("GltfLoaderSettings") }, position: Position { line: 9, col: 9 } }
```
This means users who want to migrate their .meta files will have to add
the `include_source: true,` setting to their meta files by hand.
# Objective
The ability to ignore the global volume doesn't seem desirable and
complicates the API.
#7706 added global volume and the ability to ignore it, but there was no
further discussion about whether that's useful. Feel free to discuss
here :)
## Solution
Replace the `Volume` type's functionality with the `VolumeLevel`. Remove
`VolumeLevel`.
I also removed `DerefMut` derive that effectively made the volume `pub`
and actually ensured that the volume isn't set below `0` even in release
builds.
## Migration Guide
The option to ignore the global volume using `Volume::Absolute` has been
removed and `Volume` now stores the volume level directly, removing the
need for the `VolumeLevel` struct.
# Objective
This PR is heavily inspired by
https://github.com/bevyengine/bevy/pull/7682
It aims to solve the same problem: allowing the user to extend the
tracing subscriber with extra layers.
(in my case, I'd like to use `use
metrics_tracing_context::{MetricsLayer, TracingContextLayer};`)
## Solution
I'm proposing a different api where the user has the opportunity to take
the existing `subscriber` and apply any transformations on it.
---
## Changelog
- Added a `update_subscriber` option on the `LogPlugin` that lets the
user modify the `subscriber` (for example to extend it with more tracing
`Layers`
## Migration Guide
> This section is optional. If there are no breaking changes, you can
delete this section.
- Added a new field `update_subscriber` in the `LogPlugin`
---------
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
# Objective
The table [here](https://github.com/nagisa/rust_tracy_client) shows
which versions of [Tracy](https://github.com/wolfpld/tracy) should be
used combined with which Rust deps.
Reading `bevy_log`'s `Cargo.toml` can be slightly confusing since the
exact versions are not picked from the same row.
Reading the produced `Cargo.lock` when building a Bevy example shows
that it's the most recent row that is resolved, but this should be more
clearly understood without needing to check the lock file.
## Solution
- Specify versions from the compatibility table including patch version
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
- `bevy_gizmos` cannot work if both `bevy_sprite` and `bevy_pbr` are
disabled.
- It silently fails to render, making it difficult to debug.
- Fixes#10984
## Solution
- Log an error message when `GizmoPlugin` is registered.
## Alternatives
I chose to log an error message, since it seemed the least intrusive of
potential solutions. Some alternatives include:
- Choosing one dependency as the default, neglecting the other. (#11035)
- Raising a compile error when neither dependency is enabled. ([See my
original
comment](https://github.com/bevyengine/bevy/issues/10984#issuecomment-1873420426))
- Raising a compile warning using a macro hack. ([Pre-RFC - Add
compile_warning!
macro](https://internals.rust-lang.org/t/pre-rfc-add-compile-warning-macro/9370/7?u=bd103))
- Logging a warning instead of an error.
- _This might be the better option. Let me know if I should change it._
---
## Changelog
- `bevy_gizmos` will now log an error if neither `bevy_pbr` nor
`bevy_sprite` are enabled.
# Objective
- Implementing `Default` for
[`CubicCurve`](https://docs.rs/bevy/latest/bevy/math/cubic_splines/struct.CubicCurve.html)
does not make sense because it cannot be mutated after creation.
- Closes#11209.
- Alternative to #11211.
## Solution
- Remove `Default` from `CubicCurve`'s derive statement.
Based off of @mockersf comment
(https://github.com/bevyengine/bevy/pull/11211#issuecomment-1880088036):
> CubicCurve can't be updated once created... I would prefer to remove
the Default impl as it doesn't make sense
---
## Changelog
- Removed the `Default` implementation for `CubicCurve`.
## Migration Guide
- Remove `CubicCurve` from any structs that implement `Default`.
- Wrap `CubicCurve` in a new type and provide your own default.
```rust
#[derive(Deref)]
struct MyCubicCurve<P: Point>(pub CubicCurve<P>);
impl Default for MyCubicCurve<Vec2> {
fn default() -> Self {
let points = [[
vec2(-1.0, -20.0),
vec2(3.0, 2.0),
vec2(5.0, 3.0),
vec2(9.0, 8.0),
]];
Self(CubicBezier::new(points).to_curve())
}
}
```
Based on discussion after #11268 was merged:
Instead of panicking should the impl of `TypeId::hash` change
significantly, have a fallback and detect this in a test.
# Objective
In #11330 I found out that `Parent::get` didn't get inlined, **even with
LTO on**!
This means that just to access a field, we have an instruction cache
invalidation, we will move some registers to the stack, will jump to new
instructions, move the field into a register, then do the same dance in
the other direction to go back to the call site.
## Solution
Mark trivial functions as `#[inline]`.
`inline(always)` may increase compilation time proportional to how many
time the function is called **and the size of the function marked with
`inline`**. Since we mark as `inline` functions that consists in a
single instruction, the cost is absolutely negligible.
I also took the opportunity to `inline` other functions. I'm not as
confident that marking functions calling other functions as `inline`
works similarly to very simple functions, so I used `inline` over
`inline(always)`, which doesn't have the same downsides as
`inline(always)`.
More information on inlining in rust:
https://nnethercote.github.io/perf-book/inlining.html
Not always, but skip it if the new length is smaller.
For context, `path_cache` is a `Vec<Vec<Option<Entity>>>`.
# Objective
Previously, when setting a new length to the `path_cache`, we would:
1. Deallocate all existing `Vec<Option<Entity>>`
2. Deallocate the `path_cache`
3. Allocate a new `Vec<Vec<Option<Entity>>>`, where each item is an
empty `Vec`, and would have to be allocated when pushed to.
This is a lot of allocations!
## Solution
Use
[`Vec::resize_with`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.resize_with).
With this change, what occurs is:
1. We `clear` each `Vec<Option<Entity>>`, keeping the allocation, but
making the memory of each `Vec` re-usable
2. We only append new `Vec` to `path_cache` when it is too small.
* Fixes#11328
### Note on performance
I didn't benchmark it, I just ran a diff on the generated assembly (ran
with `--profile stress-test` and `--native`). I found this PR has 20
less instructions in `apply_animation` (out of 2504).
Though on a purely abstract level, I can deduce this leads to less
allocation.
More information on profiling allocations in rust:
https://nnethercote.github.io/perf-book/heap-allocations.html
## Future work
I think a [jagged vec](https://en.wikipedia.org/wiki/Jagged_array) would
be much more pertinent. Because it allocates everything in a single
contiguous buffer.
This would avoid dancing around allocations, and reduces the overhead of
one `*mut T` and two `usize` per row, also removes indirection,
improving cache efficiency. I think it would both improve code quality
and performance.
# Objective
`TypeId` contains a high-quality hash. Whenever a lookup based on a
`TypeId` is performed (e.g. to insert/remove components), the hash is
run through a second hash function. This is unnecessary.
## Solution
Skip re-hashing `TypeId`s.
In my
[testing](https://gist.github.com/SpecificProtagonist/4b49ad74c6b82b0aedd3b4ea35121be8),
this improves lookup performance consistently by 10%-15% (of course, the
lookup is only a small part of e.g. a bundle insertion).
# Objective
While working on #10832, I found this code very dense and hard to
understand.
I was not confident in my fix (or the correctness of the existing code).
## Solution
Clean up, test and document the code used in the `apply_animation`
system.
I also added a pair of length-related utility methods to `Keyframes` for
easier testing. They seemed generically useful, so I made them pub.
## Changelog
- Added `VariableCurve::find_current_keyframe` method.
- Added `Keyframes::len` and `is_empty` methods.
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
The purpose of this PR is to begin putting together a unified identifier
structure that can be used by entities and later components (as
entities) as well as relationship pairs for relations, to enable all of
these to be able to use the same storages. For the moment, to keep
things small and focused, only `Entity` is being changed to make use of
the new `Identifier` type, keeping `Entity`'s API and
serialization/deserialization the same. Further changes are for
follow-up PRs.
## Solution
`Identifier` is a wrapper around `u64` split into two `u32` segments
with the idea of being generalised to not impose restrictions on
variants. That is for `Entity` to do. Instead, it is a general API for
taking bits to then merge and map into a `u64` integer. It exposes
low/high methods to return the two value portions as `u32` integers,
with then the MSB masked for usage as a type flag, enabling entity kind
discrimination and future activation/deactivation semantics.
The layout in this PR for `Identifier` is described as below, going from
MSB -> LSB.
```
|F| High value | Low value |
|_|_______________________________|________________________________|
|1| 31 | 32 |
F = Bit Flags
```
The high component in this implementation has only 31 bits, but that
still leaves 2^31 or 2,147,483,648 values that can be stored still, more
than enough for any generation/relation kinds/etc usage. The low part is
a full 32-bit index. The flags allow for 1 bit to be used for
entity/pair discrimination, as these have different usages for the
low/high portions of the `Identifier`. More bits can be reserved for
more variants or activation/deactivation purposes, but this currently
has no use in bevy.
More bits could be reserved for future features at the cost of bits for
the high component, so how much to reserve is up for discussion. Also,
naming of the struct and methods are also subject to further
bikeshedding and feedback.
Also, because IDs can have different variants, I wonder if
`Entity::from_bits` needs to return a `Result` instead of potentially
panicking on receiving an invalid ID.
PR is provided as an early WIP to obtain feedback and notes on whether
this approach is viable.
---
## Changelog
### Added
New `Identifier` struct for unifying IDs.
### Changed
`Entity` changed to use new `Identifier`/`IdentifierMask` as the
underlying ID logic.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: vero <email@atlasdostal.com>
# Objective
- It is common to run a system only when the clock is paused or not
paused, but this run condition doesn't exist.
## Solution
- Add the "paused" run condition.
---
## Changelog
- Systems can now be scheduled to run only if the clock is paused or not
using `.run_if(paused())` or `.run_if(not(paused()))`.
---------
Co-authored-by: radiish <cb.setho@gmail.com>
# Objective
Fixes https://github.com/bevyengine/bevy/issues/11222
## Solution
SSAO's sample_mip_level was always giving negative values because it was
in UV space (0..1) when it needed to be in pixel units (0..resolution).
Fixing it so it properly samples lower mip levels when appropriate is a
pretty large speedup (~3.2ms -> ~1ms at 4k, ~507us-> 256us at 1080p on a
6800xt), and I didn't notice any obvious visual quality differences.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Implement bounding volume trait and the 4 types from
https://github.com/bevyengine/bevy/issues/10570. I will add intersection
tests in a future PR.
## Solution
Implement mostly everything as written in the issue, except:
- Intersection is no longer a method on the bounding volumes, but a
separate trait.
- I implemented a `visible_area` since it's the most common usecase to
care about the surface that could collide with cast rays.
- Maybe we want both?
---
## Changelog
- Added bounding volume types to bevy_math
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
In the past `winit:🪟:Window` was not Send + Sync on web.
https://github.com/rust-windowing/winit/pull/2834 made
`winit:🪟:Window` Sync + Send so Bevy's `unsafe impl` is no longer
necessary.
## Solution
Remove the unsafe impls.
# Objective
This dependency is seemingly no longer used directly after #7267.
Unfortunately, this doesn't fix us having versions of `event-listener`
in our tree.
Closes#10654
## Solution
Remove it, see if anything breaks.
# Objective
- Since #11227, Bevy doesn't work on mobile anymore. Windows are not
created.
## Solution
- Create initial window on mobile after the initial `Resume` event.
macOS is included because it's excluded from the other initial window
creation and I didn't want it to feel alone. Also, it makes sense. this
is needed for Android
cfcb6885e3/crates/bevy_winit/src/lib.rs (L152)
- request redraw during plugin initialisation (needed for WebGPU)
- request redraw when receiving `AboutToWait` instead of at the end of
the event handler. request to redraw during a `RedrawRequested` event
are ignored on iOS
# Objective
Issue #10243: rendering multiple triangles in the same place results in
flickering.
## Solution
Considered these alternatives:
- `depth_bias` may not work, because of high number of entities, so
creating a material per entity is practically not possible
- rendering at slightly different positions does not work, because when
camera is far, float rounding causes the same issues (edit: assuming we
have to use the same `depth_bias`)
- considered implementing deterministic operation like
`query.par_iter().flat_map(...).collect()` to be used in
`check_visibility` system (which would solve the issue since query is
deterministic), and could not figure out how to make it as cheap as
current approach with thread-local collectors (#11249)
So adding an option to sort entities after `check_visibility` system
run.
Should not be too bad, because after visibility check, only a handful
entities remain.
This is probably not the only source of non-determinism in Bevy, but
this is one I could find so far. At least it fixes the repro example.
## Changelog
- `DeterministicRenderingConfig` option to enable deterministic
rendering
## Test
<img width="1392" alt="image"
src="https://github.com/bevyengine/bevy/assets/28969/c735bce1-3a71-44cd-8677-c19f6c0ee6bd">
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
I want to run a system once after a given delay.
- First, I tried using the `on_timer` run condition, but it uses a
repeating timer, causing the system to run multiple times.
- Next, I tried combining the `on_timer` with the `run_once` run
condition. However, this causes the timer to *tick* only once, so the
system is never executed.
## Solution
- ~~Replace `on_timer` by `on_time_interval` and `on_real_timer` by
`on_real_time_interval` to clarify the meaning (the old ones are
deprecated to avoid a breaking change).~~ (Reverted according to
feedback)
- Add `once_after_delay` and `once_after_real_delay` to run the system
exactly once after the delay, using `TimerMode::Once`.
- Add `repeating_after_delay` and `repeating_after_real_delay` to run
the system indefinitely after the delay, using `Timer::finished` instead
of `Timer::just_finished`.
---
## Changelog
### Added
- `once_after_delay` and `once_after_real_delay` run conditions to run
the system exactly once after the delay, using `TimerMode::Once`.
- `repeating_after_delay` and `repeating_after_real_delay` run
conditions to run the system indefinitely after the delay, using
`Timer::finished` instead of `Timer::just_finished`.
# Objective
- Implements change described in
https://github.com/bevyengine/bevy/issues/3022
- Goal is to allow Entity to benefit from niche optimization, especially
in the case of Option<Entity> to reduce memory overhead with structures
with empty slots
## Discussion
- First PR attempt: https://github.com/bevyengine/bevy/pull/3029
- Discord:
https://discord.com/channels/691052431525675048/1154573759752183808/1154573764240093224
## Solution
- Change `Entity::generation` from u32 to NonZeroU32 to allow for niche
optimization.
- The reason for changing generation rather than index is so that the
costs are only encountered on Entity free, instead of on Entity alloc
- There was some concern with generations being used, due to there being
some desire to introduce flags. This was more to do with the original
retirement approach, however, in reality even if generations were
reduced to 24-bits, we would still have 16 million generations available
before wrapping and current ideas indicate that we would be using closer
to 4-bits for flags.
- Additionally, another concern was the representation of relationships
where NonZeroU32 prevents us using the full address space, talking with
Joy it seems unlikely to be an issue. The majority of the time these
entity references will be low-index entries (ie. `ChildOf`, `Owes`),
these will be able to be fast lookups, and the remainder of the range
can use slower lookups to map to the address space.
- It has the additional benefit of being less visible to most users,
since generation is only ever really set through `from_bits` type
methods.
- `EntityMeta` was changed to match
- On free, generation now explicitly wraps:
- Originally, generation would panic in debug mode and wrap in release
mode due to using regular ops.
- The first attempt at this PR changed the behavior to "retire" slots
and remove them from use when generations overflowed. This change was
controversial, and likely needs a proper RFC/discussion.
- Wrapping matches current release behaviour, and should therefore be
less controversial.
- Wrapping also more easily migrates to the retirement approach, as
users likely to exhaust the exorbitant supply of generations will code
defensively against aliasing and that defensive code is less likely to
break than code assuming that generations don't wrap.
- We use some unsafe code here when wrapping generations, to avoid
branch on NonZeroU32 construction. It's guaranteed safe due to how we
perform wrapping and it results in significantly smaller ASM code.
- https://godbolt.org/z/6b6hj8PrM
## Migration
- Previous `bevy_scene` serializations have a high likelihood of being
broken, as they contain 0th generation entities.
## Current Issues
- `Entities::reserve_generations` and `EntityMapper` wrap now, even in
debug - although they technically did in release mode already so this
probably isn't a huge issue. It just depends if we need to change
anything here?
---------
Co-authored-by: Natalie Baker <natalie.baker@advancednavigation.com>
Update to `glam` 0.25, `encase` 0.7 and `hexasphere` to 10.0
## Changelog
Added the `FloatExt` trait to the `bevy_math` prelude which adds `lerp`,
`inverse_lerp` and `remap` methods to the `f32` and `f64` types.
# Objective
When you have no idea what to put after `#` when loading an asset, error
message may help.
## Solution
Add all labels to the error message.
## Test plan
Modified `anti_alias` example to put incorrect label, the error is:
```
2024-01-08T07:41:25.462287Z ERROR bevy_asset::server: The file at 'models/FlightHelmet/FlightHelmet.gltf' does not contain the labeled asset 'Rrrr'; it contains the following 25 assets: 'Material0', 'Material1', 'Material2', 'Material3', 'Material4', 'Material5', 'Mesh0', 'Mesh0/Primitive0', 'Mesh1', 'Mesh1/Primitive0', 'Mesh2', 'Mesh2/Primitive0', 'Mesh3', 'Mesh3/Primitive0', 'Mesh4', 'Mesh4/Primitive0', 'Mesh5', 'Mesh5/Primitive0', 'Node0', 'Node1', 'Node2', 'Node3', 'Node4', 'Node5', 'Scene0'
```
# Objective
`Column` unconditionally requires three separate allocations: one for
the data, and two for the tick Vecs. The tick Vecs aren't really needed
for Resources, so we're allocating a bunch of one-element Vecs, and it
costs two extra dereferences when fetching/inserting/removing resources.
## Solution
Drop one level lower in `ResourceData` and directly store a `BlobVec`
and two `UnsafeCell<Tick>`s. This should significantly shrink
`ResourceData` (exchanging 6 usizes for 2 u32s), removes the need to
dereference two separate ticks when inserting/removing/fetching
resources, and can significantly decrease the number of small
allocations the ECS makes by default.
This tentatively might have a non-insignificant impact on the CPU cost
for rendering since we're constantly fetching resources in draw
functions, depending on how aggressively inlined the functions are.
This requires reimplementing some of the unsafe functions that `Column`
wraps, but it also allows us to delete a few Column APIs that were only
used for Resources, so the total amount of unsafe we're maintaining
shouldn't change significantly.
---------
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
# Objective
When creating a normalized direction from a vector, it can be useful to
get both the direction *and* the original length of the vector.
This came up when I was recreating some Parry APIs using bevy_math, and
doing it manually is quite painful. Nalgebra calls this method
[`Unit::try_new_and_get`](https://docs.rs/nalgebra/latest/nalgebra/base/struct.Unit.html#method.try_new_and_get).
## Solution
Add a `new_and_length` method to `Direction2d` and `Direction3d`.
Usage:
```rust
if let Ok((direction, length)) = Direction2d::new_and_length(Vec2::X * 10.0) {
assert_eq!(direction, Vec2::X);
assert_eq!(length, 10.0);
}
```
I'm open to different names, couldn't come up with a perfectly clear one
that isn't too long. My reasoning with the current name is that it's
like using `new` and calling `length` on the original vector.
# Objective
In #9604 we removed the ability to define an `EntityCommand` as
`fn(Entity, &mut World)`. However I have since realized that `fn(Entity,
&mut World)` is an incredibly expressive and powerful way to define a
command for an entity that may or may not exist (`fn(EntityWorldMut)`
only works on entities that are alive).
## Solution
Support `EntityCommand`s in the style of `fn(Entity, &mut World)`, as
well as `fn(EntityWorldMut)`. Use a marker generic on the
`EntityCommand` trait to allow multiple impls.
The second commit in this PR replaces all of the internal command
definitions with ones using `fn` definitions. This is mostly just to
show off how expressive this style of command is -- we can revert this
commit if we'd rather avoid breaking changes.
---
## Changelog
Re-added support for expressively defining an `EntityCommand` as a
function that takes `Entity, &mut World`.
## Migration Guide
All `Command` types in `bevy_ecs`, such as `Spawn`, `SpawnBatch`,
`Insert`, etc., have been made private. Use the equivalent methods on
`Commands` or `EntityCommands` instead.
# Objective
- Make it possible to react to arbitrary state changes
- this will be useful regardless of the other changes to states
currently being discussed
## Solution
- added `StateTransitionEvent<S>` struct
- previously, this would have been impossible:
```rs
#[derive(States, Eq, PartialEq, Hash, Copy, Clone, Default)]
enum MyState {
#[default]
Foo,
Bar(MySubState),
}
enum MySubState {
Spam,
Eggs,
}
app.add_system(Update, on_enter_bar);
fn on_enter_bar(trans: EventReader<StateTransition<MyState>>){
for (befoare, after) in trans.read() {
match before, after {
MyState::Foo, MyState::Bar(_) => info!("detected transition foo => bar");
_, _ => ();
}
}
}
```
---
## Changelog
- Added
- `StateTransitionEvent<S>` - Fired on state changes of `S`
## Migration Guide
N/A no breaking changes
---------
Co-authored-by: Federico Rinaldi <gisquerin@gmail.com>
# Motivation
When spawning entities into a scene, it is very common to create assets
like meshes and materials and to add them via asset handles. A common
setup might look like this:
```rust
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(StandardMaterial::from(Color::RED)),
..default()
});
}
```
Let's take a closer look at the part that adds the assets using `add`.
```rust
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(StandardMaterial::from(Color::RED)),
```
Here, "mesh" and "material" are both repeated three times. It's very
explicit, but I find it to be a bit verbose. In addition to being more
code to read and write, the extra characters can sometimes also lead to
the code being formatted to span multiple lines even though the core
task, adding e.g. a primitive mesh, is extremely simple.
A way to address this is by using `.into()`:
```rust
mesh: meshes.add(shape::Cube { size: 1.0 }.into()),
material: materials.add(Color::RED.into()),
```
This is fine, but from the names and the type of `meshes`, we already
know what the type should be. It's very clear that `Cube` should be
turned into a `Mesh` because of the context it's used in. `.into()` is
just seven characters, but it's so common that it quickly adds up and
gets annoying.
It would be nice if you could skip all of the conversion and let Bevy
handle it for you:
```rust
mesh: meshes.add(shape::Cube { size: 1.0 }),
material: materials.add(Color::RED),
```
# Objective
Make adding assets more ergonomic by making `Assets::add` take an `impl
Into<A>` instead of `A`.
## Solution
`Assets::add` now takes an `impl Into<A>` instead of `A`, so e.g. this
works:
```rust
commands.spawn(PbrBundle {
mesh: meshes.add(shape::Cube { size: 1.0 }),
material: materials.add(Color::RED),
..default()
});
```
I also changed all examples to use this API, which increases consistency
as well because `Mesh::from` and `into` were being used arbitrarily even
in the same file. This also gets rid of some lines of code because
formatting is nicer.
---
## Changelog
- `Assets::add` now takes an `impl Into<A>` instead of `A`
- Examples don't use `T::from(K)` or `K.into()` when adding assets
## Migration Guide
Some `into` calls that worked previously might now be broken because of
the new trait bounds. You need to either remove `into` or perform the
conversion explicitly with `from`:
```rust
// Doesn't compile
let mesh_handle = meshes.add(shape::Cube { size: 1.0 }.into()),
// These compile
let mesh_handle = meshes.add(shape::Cube { size: 1.0 }),
let mesh_handle = meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
```
## Concerns
I believe the primary concerns might be:
1. Is this too implicit?
2. Does this increase codegen bloat?
Previously, the two APIs were using `into` or `from`, and now it's
"nothing" or `from`. You could argue that `into` is slightly more
explicit than "nothing" in cases like the earlier examples where a
`Color` gets converted to e.g. a `StandardMaterial`, but I personally
don't think `into` adds much value even in this case, and you could
still see the actual type from the asset type.
As for codegen bloat, I doubt it adds that much, but I'm not very
familiar with the details of codegen. I personally value the user-facing
code reduction and ergonomics improvements that these changes would
provide, but it might be worth checking the other effects in more
detail.
Another slight concern is migration pain; apps might have a ton of
`into` calls that would need to be removed, and it did take me a while
to do so for Bevy itself (maybe around 20-40 minutes). However, I think
the fact that there *are* so many `into` calls just highlights that the
API could be made nicer, and I'd gladly migrate my own projects for it.
# Objective
This pull request implements *reflection probes*, which generalize
environment maps to allow for multiple environment maps in the same
scene, each of which has an axis-aligned bounding box. This is a
standard feature of physically-based renderers and was inspired by [the
corresponding feature in Blender's Eevee renderer].
## Solution
This is a minimal implementation of reflection probes that allows
artists to define cuboid bounding regions associated with environment
maps. For every view, on every frame, a system builds up a list of the
nearest 4 reflection probes that are within the view's frustum and
supplies that list to the shader. The PBR fragment shader searches
through the list, finds the first containing reflection probe, and uses
it for indirect lighting, falling back to the view's environment map if
none is found. Both forward and deferred renderers are fully supported.
A reflection probe is an entity with a pair of components, *LightProbe*
and *EnvironmentMapLight* (as well as the standard *SpatialBundle*, to
position it in the world). The *LightProbe* component (along with the
*Transform*) defines the bounding region, while the
*EnvironmentMapLight* component specifies the associated diffuse and
specular cubemaps.
A frequent question is "why two components instead of just one?" The
advantages of this setup are:
1. It's readily extensible to other types of light probes, in particular
*irradiance volumes* (also known as ambient cubes or voxel global
illumination), which use the same approach of bounding cuboids. With a
single component that applies to both reflection probes and irradiance
volumes, we can share the logic that implements falloff and blending
between multiple light probes between both of those features.
2. It reduces duplication between the existing *EnvironmentMapLight* and
these new reflection probes. Systems can treat environment maps attached
to cameras the same way they treat environment maps applied to
reflection probes if they wish.
Internally, we gather up all environment maps in the scene and place
them in a cubemap array. At present, this means that all environment
maps must have the same size, mipmap count, and texture format. A
warning is emitted if this restriction is violated. We could potentially
relax this in the future as part of the automatic mipmap generation
work, which could easily do texture format conversion as part of its
preprocessing.
An easy way to generate reflection probe cubemaps is to bake them in
Blender and use the `export-blender-gi` tool that's part of the
[`bevy-baked-gi`] project. This tool takes a `.blend` file containing
baked cubemaps as input and exports cubemap images, pre-filtered with an
embedded fork of the [glTF IBL Sampler], alongside a corresponding
`.scn.ron` file that the scene spawner can use to recreate the
reflection probes.
Note that this is intentionally a minimal implementation, to aid
reviewability. Known issues are:
* Reflection probes are basically unsupported on WebGL 2, because WebGL
2 has no cubemap arrays. (Strictly speaking, you can have precisely one
reflection probe in the scene if you have no other cubemaps anywhere,
but this isn't very useful.)
* Reflection probes have no falloff, so reflections will abruptly change
when objects move from one bounding region to another.
* As mentioned before, all cubemaps in the world of a given type
(diffuse or specular) must have the same size, format, and mipmap count.
Future work includes:
* Blending between multiple reflection probes.
* A falloff/fade-out region so that reflected objects disappear
gradually instead of vanishing all at once.
* Irradiance volumes for voxel-based global illumination. This should
reuse much of the reflection probe logic, as they're both GI techniques
based on cuboid bounding regions.
* Support for WebGL 2, by breaking batches when reflection probes are
used.
These issues notwithstanding, I think it's best to land this with
roughly the current set of functionality, because this patch is useful
as is and adding everything above would make the pull request
significantly larger and harder to review.
---
## Changelog
### Added
* A new *LightProbe* component is available that specifies a bounding
region that an *EnvironmentMapLight* applies to. The combination of a
*LightProbe* and an *EnvironmentMapLight* offers *reflection probe*
functionality similar to that available in other engines.
[the corresponding feature in Blender's Eevee renderer]:
https://docs.blender.org/manual/en/latest/render/eevee/light_probes/reflection_cubemaps.html
[`bevy-baked-gi`]: https://github.com/pcwalton/bevy-baked-gi
[glTF IBL Sampler]: https://github.com/KhronosGroup/glTF-IBL-Sampler
# Objective
`SceneSpawner::spawn_dynamic_sync` currently returns `()` on success,
which is inconsistent with the other `SceneSpawner::spawn_` methods that
all return an `InstanceId`. We need this ID to do useful work with the
newly-created data.
## Solution
Updated `SceneSpawner::spawn_dynamic_sync` to return `Result<InstanceId,
SceneSpawnError>` instead of `Result<(), SceneSpawnError>`
# Objective
Different platforms use their own implementations of several
mathematical functions (especially transcendental functions like sin,
cos, tan, atan, and so on) to provide hardware-level optimization using
intrinsics. This is good for performance, but bad when you expect
consistent outputs across machines.
[`libm`](https://github.com/rust-lang/libm) is a widely used crate that
provides mathematical functions that don't use intrinsics like `std`
functions. This allows bit-for-bit deterministic math across hardware,
which is crucial for things like cross-platform deterministic physics
simulation.
Glam has the `libm` feature for using [`libm` for the
math](d2871a151b/src/f32/math.rs (L35))
in its own types. This would be nice to expose as a feature in
`bevy_math`.
## Solution
Add `libm` feature to `bevy_math`. We could name it something like
`enhanced-determinism`, but this wouldn't be accurate for the rest of
Bevy, so I think just `libm` is more fitting and explicit.
# Objective
- Since #10702, the way bevy updates the window leads to major slowdowns
as seen in
- #11122
- #11220
- Slow is bad, furthermore, _very_ slow is _very_ bad. We should fix
this issue.
## Solution
- Move the app update code into the `Event::WindowEvent { event:
WindowEvent::RedrawRequested }` branch of the event loop.
- Run `window.request_redraw()` When `runner_state.redraw_requested`
- Instead of swapping `ControlFlow` between `Poll` and `Wait`, we always
keep it at `Wait`, and use `window.request_redraw()` to schedule an
immediate call to the event loop.
- `runner_state.redraw_requested` is set to `true` when
`UpdateMode::Continuous` and when a `RequestRedraw` event is received.
- Extract the redraw code into a separate function, because otherwise
I'd go crazy with the indentation level.
- Fix#11122.
## Testing
I tested the WASM builds as follow:
```sh
cargo run -p build-wasm-example -- --api webgl2 bevymark
python -m http.server --directory examples/wasm/ 8080
# Open browser at http://localhost:8080
```
On main, even spawning a couple sprites is super choppy. Even if it says
"300 FPS". While on this branch, it is smooth as butter.
I also found that it fixes all choppiness on window resize (tested on
Linux/X11). This was another issue from #10702 IIRC.
So here is what I tested:
- On `wasm`: `many_foxes` and `bevymark`, with `argh::from_env()`
commented out, otherwise we get a cryptic error.
- Both with `PresentMode::AutoVsync` and `PresentMode::AutoNoVsync`
- On main, it is consistently choppy.
- With this PR, the visible frame rate is consistent with the diagnostic
numbers
- On native (linux/x11) I ran similar tests, making sure that
`AutoVsync` limits to monitor framerate, and `AutoNoVsync` doesn't.
## Future work
Code could be improved, I wanted a quick solution easy to review, but we
really need to make the code more accessible.
- #9768
- ~~**`WinitSettings::desktop_app()` is completely borked.**~~ actually
broken on main as well
### Review guide
Consider enable the non-whitespace diff to see the _real_ change set.
# Objective
When `BlobVec::reserve` is called with an argument causing capacity
overflow, in release build capacity overflow is ignored, and capacity is
decreased.
I'm not sure it is possible to exploit this issue using public API of
`bevy_ecs`, but better fix it anyway.
## Solution
Check for capacity overflow.
# Objective
- Since #10520, assets are unloaded from RAM by default. This breaks a
number of scenario:
- using `load_folder`
- loading a gltf, then going through its mesh to transform them /
compute a collider / ...
- any assets/subassets scenario should be `Keep` as you can't know what
the user will do with the assets
- android suspension, where GPU memory is unloaded
- Alternative to #11202
## Solution
- Keep assets on CPU memory by default
# Objective
- Resolves#10913.
- Extend `Touches` with methods that are implemented on `ButtonInput`.
## Solution
- Add function `clear_just_pressed` that clears the `just_pressed` state
of the touch input.
- Add function `clear_just_released` that clears the `just_released`
state of the touch input.
- Add function `clear_just_canceled` that clears the `just_canceled`
state of the touch input.
- Add function `release` that changes state of the touch input from
`pressed` to `just_released`.
- Add function `release_all` that changes state of every touch input
from `pressed` to `just_released`
- Add function `clear` that clears `just_pressed`, `just_released` and
`just_canceled` data for every input.
- Add function `reset_all` that clears `pressed`, `just_pressed`,
`just_released` and `just_canceled` data for every input.
- Add tests for functions above.
# Objective
- Fix#11117 by implementing `Reflect` for `EntityHashMap`
## Solution
- By implementing `TypePath` for `EntityHash`, Bevy will automatically
implement `Reflect` for `EntityHashMap`
---
## Changelog
- `TypePath` is implemented for `EntityHash`
- A test called `entity_hashmap_should_impl_reflect` was created to
verify that #11117 was solved.
# Objective
In my code I use a lot of images as render targets.
I'd like some convenience methods for working with this type.
## Solution
- Allow `.into()` to construct a `RenderTarget`
- Add `.as_image()`
---
## Changelog
### Added
- `RenderTarget` can be constructed via `.into()` on a `Handle<Image>`
- `RenderTarget` new method: `as_image`
---------
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
- Fixes#11187
## Solution
- Rename the `AddChild` struct to `PushChild`
- Rename the `AddChildInPlace` struct to `PushChildInPlace`
## Migration Guide
The struct `AddChild` has been renamed to `PushChild`, and the struct
`AddChildInPlace` has been renamed to `PushChildInPlace`.
# Objective
- Since #10911, example `button` crashes when clicking the button
```
thread 'main' panicked at .cargo/registry/src/index.crates.io-6f17d22bba15001f/accesskit_consumer-0.16.1/src/tree.rs:139:9:
assertion `left == right` failed
left: 1
right: 0
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_winit::accessibility::update_accessibility_nodes`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
```
## Solution
- Re-add lost negation
# Objective
- Fixes#11119
## Solution
- Creation of the serialize feature to ui
---
## Changelog
### Changed
- Changed all the structs that implement Serialize and Deserialize to
only implement when feature is on
## Migration Guide
- If you want to use serialize and deserialize with types from bevy_ui,
you need to use the feature serialize in your TOML
```toml
[dependencies.bevy]
features = ["serialize"]
```
# Objective
Fixes Gizmos crash due to the persistence policy being set to `Unload`
## Solution
Change it to `Keep`
Co-authored-by: rqg <ranqingguo318@gmail.com>
# Objective
- No point in keeping Meshes/Images in RAM once they're going to be sent
to the GPU, and kept in VRAM. This saves a _significant_ amount of
memory (several GBs) on scenes like bistro.
- References
- https://github.com/bevyengine/bevy/pull/1782
- https://github.com/bevyengine/bevy/pull/8624
## Solution
- Augment RenderAsset with the capability to unload the underlying asset
after extracting to the render world.
- Mesh/Image now have a cpu_persistent_access field. If this field is
RenderAssetPersistencePolicy::Unload, the asset will be unloaded from
Assets<T>.
- A new AssetEvent is sent upon dropping the last strong handle for the
asset, which signals to the RenderAsset to remove the GPU version of the
asset.
---
## Changelog
- Added `AssetEvent::NoLongerUsed` and
`AssetEvent::is_no_longer_used()`. This event is sent when the last
strong handle of an asset is dropped.
- Rewrote the API for `RenderAsset` to allow for unloading the asset
data from the CPU.
- Added `RenderAssetPersistencePolicy`.
- Added `Mesh::cpu_persistent_access` for memory savings when the asset
is not needed except for on the GPU.
- Added `Image::cpu_persistent_access` for memory savings when the asset
is not needed except for on the GPU.
- Added `ImageLoaderSettings::cpu_persistent_access`.
- Added `ExrTextureLoaderSettings`.
- Added `HdrTextureLoaderSettings`.
## Migration Guide
- Asset loaders (GLTF, etc) now load meshes and textures without
`cpu_persistent_access`. These assets will be removed from
`Assets<Mesh>` and `Assets<Image>` once `RenderAssets<Mesh>` and
`RenderAssets<Image>` contain the GPU versions of these assets, in order
to reduce memory usage. If you require access to the asset data from the
CPU in future frames after the GLTF asset has been loaded, modify all
dependent `Mesh` and `Image` assets and set `cpu_persistent_access` to
`RenderAssetPersistencePolicy::Keep`.
- `Mesh` now requires a new `cpu_persistent_access` field. Set it to
`RenderAssetPersistencePolicy::Keep` to mimic the previous behavior.
- `Image` now requires a new `cpu_persistent_access` field. Set it to
`RenderAssetPersistencePolicy::Keep` to mimic the previous behavior.
- `MorphTargetImage::new()` now requires a new `cpu_persistent_access`
parameter. Set it to `RenderAssetPersistencePolicy::Keep` to mimic the
previous behavior.
- `DynamicTextureAtlasBuilder::add_texture()` now requires that the
`TextureAtlas` you pass has an `Image` with `cpu_persistent_access:
RenderAssetPersistencePolicy::Keep`. Ensure you construct the image
properly for the texture atlas.
- The `RenderAsset` trait has significantly changed, and requires
adapting your existing implementations.
- The trait now requires `Clone`.
- The `ExtractedAsset` associated type has been removed (the type itself
is now extracted).
- The signature of `prepare_asset()` is slightly different
- A new `persistence_policy()` method is now required (return
RenderAssetPersistencePolicy::Unload to match the previous behavior).
- Match on the new `NoLongerUsed` variant for exhaustive matches of
`AssetEvent`.
# Objective
- We want to use `static_assertions` to perform precise compile time
checks at testing time. In this PR, we add those checks to make sure
that `EntityHashMap` and `PreHashMap` are `Clone` (and we replace the
more clumsy previous tests)
- Fixes#11181
(will need to be rebased once
https://github.com/bevyengine/bevy/pull/11178 is merged)
---------
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
![Screenshot](https://i.imgur.com/A4KzWFq.png)
# Objective
Lightmaps, textures that store baked global illumination, have been a
mainstay of real-time graphics for decades. Bevy currently has no
support for them, so this pull request implements them.
## Solution
The new `Lightmap` component can be attached to any entity that contains
a `Handle<Mesh>` and a `StandardMaterial`. When present, it will be
applied in the PBR shader. Because multiple lightmaps are frequently
packed into atlases, each lightmap may have its own UV boundaries within
its texture. An `exposure` field is also provided, to control the
brightness of the lightmap.
Note that this PR doesn't provide any way to bake the lightmaps. That
can be done with [The Lightmapper] or another solution, such as Unity's
Bakery.
---
## Changelog
### Added
* A new component, `Lightmap`, is available, for baked global
illumination. If your mesh has a second UV channel (UV1), and you attach
this component to the entity with that mesh, Bevy will apply the texture
referenced in the lightmap.
[The Lightmapper]: https://github.com/Naxela/The_Lightmapper
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This PR is part of a project aimed at improving the API documentation of
`bevy_hierarchy`. Other PRs will be based on this.
This PR in particular is also an experiment in providing a high level
overview of the tools provided by a Bevy plugin/crate. It also provides
general information about universal invariants, so statement repetition
in crate items can be dramatically reduced.
## Other changes
The other PRs of this project that expand on this one:
- #10952
- #10953
- #10954
- #10955
- #10956
- #10957
---------
Co-authored-by: GitGhillie <jillisnoordhoek@gmail.com>
# Objective
- `EntityHashMap`, `EntityHashSet` and `PreHashMap` are currently not
Cloneable because of a missing trivial `Clone` bound for `EntityHash`
and `PreHash`. This PR makes them Cloneable.
(the parent struct `hashbrown::HashMap` requires the `HashBuilder` to be
`Clone` for the `HashMap` to be `Clone`, see:
https://github.com/rust-lang/hashbrown/blob/master/src/map.rs#L195)
## Solution
- Add a `Clone` bound to `PreHash` and `EntityHash`
---------
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
# Objective
`bevy_math` re-exports Glam, but doesn't have a feature for enabling
`approx` for it. Many projects (including some of Bevy's own crates)
need `approx`, and it'd be nice if you didn't have to manually add Glam
to specify the feature for it.
## Solution
Add an `approx` feature to `bevy_math`.
# Objective
I often need a direction along one of the cartesian XYZ axes, and it
currently requires e.g. `Direction2d::from_normalized(Vec2::X)`, which
isn't ideal.
## Solution
Add direction constants that are the same as the ones on Glam types. I
also copied the doc comment format "A unit vector pointing along the ...
axis", but I can change it if there's a better wording for directions.
# Objective
I frequently encounter cases where I need to get the opposite direction.
This currently requires something like
`Direction2d::from_normalized(-*direction)`, which is very inconvenient.
## Solution
Implement `Neg` for `Direction2d` and `Direction3d`.
# Objective
If you have multiple windows, there is no way to determine which window
a `TouchInput` event applies to. This fixes that.
## Solution
- Add the window entity directly to `TouchInput`, just like the other
input events.
- Fixes#6011.
## Migration Guide
+ Add a `window` field when constructing or destructuring a `TouchInput`
struct.
This expands upon https://github.com/bevyengine/bevy/pull/11134.
I found myself needing `tonemapping_pipeline_key` for some custom 2d
draw functions. #11134 exported the 3d version of
`tonemapping_pipeline_key` and this PR exports the 2d version. I also
made `alpha_mode_pipeline_key` public for good measure.
# Objective
When panic handler prints to stdout instead of stderr, I've observed two
outcomes with this PR test #11169:
- Sometimes output is mixed up, so it is not clear where one record ends
and another stards
- Sometimes output is lost
## Solution
Print to stderr.
## Changelog
- Panic handler in `LogPlugin` writes to stderr instead of stdin.
# Objective
`SystemName` might be useful in systems which accept `&mut World`.
## Solution
- `impl ExclusiveSystemParam for SystemName`
- move `SystemName` into a separate file, because it no longer belongs
to a file which defines `SystemParam`
- add a test for new impl, and for existing impl
## Changelog
- `impl ExclusiveSystemParam for SystemName`
Turns out whenever a normal prepass was active (which includes whenever
you use SSAO) we were attempting to read the normals from the prepass
for the specular transmissive material. Since transmissive materials
don't participate in the prepass (unlike opaque materials) we were
reading the normals from “behind” the mesh, producing really weird
visual results.
# Objective
- Fixes#11112.
## Solution
- We introduce a new `READS_VIEW_TRANSMISSION_TEXTURE` mesh pipeline
key;
- We set it whenever the material properties has the
`reads_view_transmission_texture` flag set; (i.e. the material is
transmissive)
- If this key is set we prevent the reading of normals from the prepass,
by not setting the `LOAD_PREPASS_NORMALS` shader def.
---
## Changelog
### Fixed
- Specular transmissive materials no longer attempt to erroneously load
prepass normals, and now work correctly even with the normal prepass
active (e.g. when using SSAO)
# Objective
- Refactor collide code and add tests.
## Solution
- Rebase the changes made in #4485.
Co-authored-by: Eduardo Canellas de Oliveira <eduardo.canellas@bemobi.com>
# Objective
There are a lot of doctests that are `ignore`d for no documented reason.
And that should be fixed.
## Solution
I searched the bevy repo with the regex ` ```[a-z,]*ignore ` in order to
find all `ignore`d doctests. For each one of the `ignore`d doctests, I
did the following steps:
1. Attempt to remove the `ignored` attribute while still passing the
test. I did this by adding hidden dummy structs and imports.
2. If step 1 doesn't work, attempt to replace the `ignored` attribute
with the `no_run` attribute while still passing the test.
3. If step 2 doesn't work, keep the `ignored` attribute but add
documentation for why the `ignored` attribute was added.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
Fixes#11050
Rename ArchetypeEntity::entity to ArchetypeEntity::id to be consistent
with `EntityWorldMut`, `EntityMut` and `EntityRef`.
## Migration Guide
The method `ArchetypeEntity::entity` has been renamed to
`ArchetypeEntity::id`
# Objective
- There is an warning about non snake case on system_param.rs generated
by a macro
## Solution
- Allow non snake case on the function at fault
# Objective
Implement `ExclusiveSystemParam` for `PhantomData`.
For the same reason `SystemParam` impl exists: to simplify writing
generic code.
786abbf3f5/crates/bevy_ecs/src/system/system_param.rs (L1557)
Also for consistency.
## Solution
`impl ExclusiveSystemParam for PhantomData`.
## Changelog
Added: PhantomData<T> now implements ExclusiveSystemParam.
# Objective
Mostly for consistency.
## Solution
```rust
impl ExclusiveSystemParam for WorldId
```
- Also add a test for `SystemParam for WorldId`
## Changelog
Added: Worldd now implements ExclusiveSystemParam.
# Objective
- Custom render passes, or future passes in the engine (such as
https://github.com/bevyengine/bevy/pull/10164) need a better way to know
and indicate to the core passes whether the view color/depth/prepass
attachments have been cleared or not yet this frame, to know if they
should clear it themselves or load it.
## Solution
- For all render targets (depth textures, shadow textures, prepass
textures, main textures) use an atomic bool to track whether or not each
texture has been cleared this frame. Abstracted away in the new
ColorAttachment and DepthAttachment wrappers.
---
## Changelog
- Changed `ViewTarget::get_color_attachment()`, removed arguments.
- Changed `ViewTarget::get_unsampled_color_attachment()`, removed
arguments.
- Removed `Camera3d::clear_color`.
- Removed `Camera2d::clear_color`.
- Added `Camera::clear_color`.
- Added `ExtractedCamera::clear_color`.
- Added `ColorAttachment` and `DepthAttachment` wrappers.
- Moved `ClearColor` and `ClearColorConfig` from
`bevy::core_pipeline::clear_color` to `bevy::render::camera`.
- Core render passes now track when a texture is first bound as an
attachment in order to decide whether to clear or load it.
## Migration Guide
- Remove arguments to `ViewTarget::get_color_attachment()` and
`ViewTarget::get_unsampled_color_attachment()`.
- Configure clear color on `Camera` instead of on `Camera3d` and
`Camera2d`.
- Moved `ClearColor` and `ClearColorConfig` from
`bevy::core_pipeline::clear_color` to `bevy::render::camera`.
- `ViewDepthTexture` must now be created via the `new()` method
---------
Co-authored-by: vero <email@atlasdostal.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fix ci hang, so we can merge pr's again.
## Solution
- switch ppa action to use mesa stable versions
https://launchpad.net/~kisak/+archive/ubuntu/turtle
- use commit from #11123
---------
Co-authored-by: Stepan Koltsov <stepan.koltsov@gmail.com>
# Objective
- Provides an alternate solution to the one implemented in #10791
without breaking changes.
## Solution
- Changes the bounds of macro-generated `TypePath` implementations to
universally ignore the types of fields, rather than use the same bounds
as other implementations. I think this is a more holistic solution than
#10791 because it totally erases the finicky bounds we currently
generate, helping to untangle the reflection trait system.
# Objective
- Make the implementation order consistent between all sources to fit
the order in the trait.
## Solution
- Change the implementation order.
Matches versioning & features from other Cargo.toml files in the
project.
# Objective
Resolves#10932
## Solution
Added smallvec to the bevy_utils cargo.toml and added a line to
re-export the crate. Target version and features set to match what's
used in the other bevy crates.
# Objective
Register and Serialize `Camera3dDepthTextureUsage` and
`ScreenSpaceTransmissionQuality`.
Fixes: #11036
## Solution
Added the relevant derives for reflection and serialization and type
registrations.
# Objective
Outlines are drawn for UI nodes with `Display::None` set and their
descendants. They should not be visible.
## Solution
Make all Nodes with `Display::None` inherit an empty clipping rect,
ensuring that the outlines are not visible.
Fixes#10940
---
## Changelog
* In `update_clipping_system` if a node has `Display::None` set, clip
the entire node and all its descendants by replacing the inherited clip
with a default rect (which is empty)
# Objective
The documentation for the `States` trait contains an error! There is a
single colon missing from `OnExit<T:Variant>`.
## Solution
Replace `OnExit<T:Variant>` with `OnExit<T::Variant>`. (Notice the added
colon.)
---
## Changelog
### Added
- Added missing colon in `States` documentation.
---
Bevy community, you may now rest easy.
The error conditions were not documented, this requires the user to
inspect the source code to know when to expect a `None`.
Error conditions should always be documented, so we document them.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Improves #11052
# Changelog
- Remove `Window::fit_canvas_to_parent`, as its resizing on wasm now
respects its CSS configuration.
## Migration Guide
- Remove uses of `Window::fit_canvas_to_parent` in favor of CSS
properties, for example:
```css
canvas {
width: 100%;
height: 100%;
}
```
# Objective
- After #10336, some gltf files fail to load (examples
custom_gltf_vertex_attribute, gltf_skinned_mesh, ...)
- Fix them
## Solution
- Allow padding in base 64 decoder
# Objective
Fix#10731.
## Solution
Rename `App::add_state<T>(&mut self)` to `init_state`, and add
`App::insert_state<T>(&mut self, state: T)`. I decided on these names
because they are more similar to `init_resource` and `insert_resource`.
I also removed the `States` trait's requirement for `Default`. Instead,
`init_state` requires `FromWorld`.
---
## Changelog
- Renamed `App::add_state` to `init_state`.
- Added `App::insert_state`.
- Removed the `States` trait's requirement for `Default`.
## Migration Guide
- Renamed `App::add_state` to `init_state`.
# Objective
- Update winit dependency to 0.29
## Changelog
### KeyCode changes
- Removed `ScanCode`, as it was [replaced by
KeyCode](https://github.com/rust-windowing/winit/blob/master/CHANGELOG.md#0292).
- `ReceivedCharacter.char` is now a `SmolStr`, [relevant
doc](https://docs.rs/winit/latest/winit/event/struct.KeyEvent.html#structfield.text).
- Changed most `KeyCode` values, and added more.
KeyCode has changed meaning. With this PR, it refers to physical
position on keyboard rather than the printed letter on keyboard keys.
In practice this means:
- On QWERTY keyboard layouts, nothing changes
- On any other keyboard layout, `KeyCode` no longer reflects the label
on key.
- This is "good". In bevy 0.12, when you used WASD for movement, users
with non-QWERTY keyboards couldn't play your game! This was especially
bad for non-latin keyboards. Now, WASD represents the physical keys. A
French player will press the ZQSD keys, which are near each other,
Kyrgyz players will use "Цфыв".
- This is "bad" as well. You can't know in advance what the label of the
key for input is. Your UI says "press WASD to move", even if in reality,
they should be pressing "ZQSD" or "Цфыв". You also no longer can use
`KeyCode` for text inputs. In any case, it was a pretty bad API for text
input. You should use `ReceivedCharacter` now instead.
### Other changes
- Use `web-time` rather than `instant` crate.
(https://github.com/rust-windowing/winit/pull/2836)
- winit did split `run_return` in `run_onDemand` and `pump_events`, I
did the same change in bevy_winit and used `pump_events`.
- Removed `return_from_run` from `WinitSettings` as `winit::run` now
returns on supported platforms.
- I left the example "return_after_run" as I think it's still useful.
- This winit change is done partly to allow to create a new window after
quitting all windows: https://github.com/emilk/egui/issues/1918 ; this
PR doesn't address.
- added `width` and `height` properties in the `canvas` from wasm
example
(https://github.com/bevyengine/bevy/pull/10702#discussion_r1420567168)
## Known regressions (important follow ups?)
- Provide an API for reacting when a specific key from current layout
was released.
- possible solutions: use winit::Key from winit::KeyEvent ; mapping
between KeyCode and Key ; or .
- We don't receive characters through alt+numpad (e.g. alt + 151 = "ù")
anymore ; reproduced on winit example "ime". maybe related to
https://github.com/rust-windowing/winit/issues/2945
- (windows) Window content doesn't refresh at all when resizing. By
reading https://github.com/rust-windowing/winit/issues/2900 ; I suspect
we should just fire a `window.request_redraw();` from `AboutToWait`, and
handle actual redrawing within `RedrawRequested`. I'm not sure how to
move all that code so I'd appreciate it to be a follow up.
- (windows) unreleased winit fix for using set_control_flow in
AboutToWait https://github.com/rust-windowing/winit/issues/3215 ; ⚠️ I'm
not sure what the implications are, but that feels bad 🤔
## Follow up
I'd like to avoid bloating this PR, here are a few follow up tasks
worthy of a separate PR, or new issue to track them once this PR is
closed, as they would either complicate reviews, or at risk of being
controversial:
- remove CanvasParentResizePlugin
(https://github.com/bevyengine/bevy/pull/10702#discussion_r1417068856)
- avoid mentionning explicitly winit in docs from bevy_window ?
- NamedKey integration on bevy_input:
https://github.com/rust-windowing/winit/pull/3143 introduced a new
NamedKey variant. I implemented it only on the converters but we'd
benefit making the same changes to bevy_input.
- Add more info in KeyboardInput
https://github.com/bevyengine/bevy/pull/10702#pullrequestreview-1748336313
- https://github.com/bevyengine/bevy/pull/9905 added a workaround on a
bug allegedly fixed by winit 0.29. We should check if it's still
necessary.
- update to raw_window_handle 0.6
- blocked by wgpu
- Rename `KeyCode` to `PhysicalKeyCode`
https://github.com/bevyengine/bevy/pull/10702#discussion_r1404595015
- remove `instant` dependency, [replaced
by](https://github.com/rust-windowing/winit/pull/2836) `web_time`), we'd
need to update to :
- fastrand >= 2.0
- [`async-executor`](https://github.com/smol-rs/async-executor) >= 1.7
- [`futures-lite`](https://github.com/smol-rs/futures-lite) >= 2.0
- Verify license, see
[discussion](https://github.com/bevyengine/bevy/pull/8745#discussion_r1402439800)
- we might be missing a short notice or description of changes made
- Consider using https://github.com/rust-windowing/cursor-icon directly
rather than vendoring it in bevy.
- investigate [this
unwrap](https://github.com/bevyengine/bevy/pull/8745#discussion_r1387044986)
(`winit_window.canvas().unwrap();`)
- Use more good things about winit's update
- https://github.com/bevyengine/bevy/pull/10689#issuecomment-1823560428
## Migration Guide
This PR should have one.
# Objective
- Update base64 requirement from 0.13.0 to 0.21.5.
- Closes#10317.
## Solution
- Bumped `base64` requirement and manually migrated code to fix a
breaking change after updating.
# Objective
`Has<T>` in some niche cases may behave in an unexpected way.
Specifically, when using `Query::get` on a `Has<T>` with a despawned
entity.
## Solution
Add precision about cases wehre `Query::get` could return an `Err`.
Use `'w` for world lifetime consistently.
When implementing system params, useful to look at how other params are
implemented. `'w` makes it clear it is world, not state.
# Objective
- Fixes#10587, where the `Aabb` component of entities with `Sprite` and
`Handle<Image>` components was not automatically updated when
`Sprite::custom_size` changed.
## Solution
- In the query for entities with `Sprite` components in
`calculate_bounds_2d`, use the `Changed` filter to detect for `Sprites`
that changed as well as sprites that do not have `Aabb` components. As
noted in the issue, this will cause the `Aabb` to be recalculated when
other fields of the `Sprite` component change, but calculating the
`Aabb` for sprites is trivial.
---
## Changelog
- Modified query for entities with `Sprite` components in
`calculate_bounds_2d`, so that entities with `Sprite` components that
changed will also have their AABB recalculated.
# Objective
- Provide way to check whether multiple inputs are pressed.
## Solution
- Add `all_pressed` method that checks if all inputs are currently being
pressed.
# Objective
- Allow checking if a resource has changed by its ComponentId
---
## Changelog
- Added `World::is_resource_changed_by_id()` and
`World::is_resource_added_by_id()`.
# Objective
Being able to do:
```rust
ev_scene_ready.read().next().unwrap();
```
Which currently isn't possible because `SceneInstanceReady` doesn't
implement `Debug`.
## Solution
Implement `Debug` for `SceneInstanceReady`.
---
## Changelog
### Added
- Implement Std traits for `SceneInstanceReady`.
# Objective
- Fix an inconsistency in the calculation of aspect ratio's.
- Fixes#10288
## Solution
- Created an intermediate `AspectRatio` struct, as suggested in the
issue. This is currently just used in any places where aspect ratio
calculations happen, to prevent doing it wrong. In my and @mamekoro 's
opinion, it would be better if this was used instead of a normal `f32`
in various places, but I didn't want to make too many changes to begin
with.
## Migration Guide
- Anywhere where you are currently expecting a f32 when getting aspect
ratios, you will now receive a `AspectRatio` struct. this still holds
the same value.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
The definition of several `QueryState` methods use unnecessary explicit
lifetimes, which adds to visual noise.
## Solution
Elide the lifetimes.
# Objective
- bevy_sprite crate is missing docs for important types. `Sprite` being
undocumented was especially confusing for me even though it is one of
the first types I need to learn.
## Solution
- Improves the situation a little by adding some documentations.
I'm unsure about my understanding of functionality and writing. I'm
happy to be pointed out any mistakes.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Federico Rinaldi <gisquerin@gmail.com>
# Objective
`Instant` and `Duration` from the `instant` crate are exposed in
`bevy_utils` to have a single abstraction for native/wasm.
It would be useful to have the same thing for
[`SystemTime`](https://doc.rust-lang.org/std/time/struct.SystemTime.html).
---
## Changelog
### Added
- `bevy_utils` now re-exposes the `instant::SystemTime` struct
Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
# Objective
- Users are often confused when their command effects are not visible in
the next system. This PR auto inserts sync points if there are deferred
buffers on a system and there are dependents on that system (systems
with after relationships).
- Manual sync points can lead to users adding more than needed and it's
hard for the user to have a global understanding of their system graph
to know which sync points can be merged. However we can easily calculate
which sync points can be merged automatically.
## Solution
1. Add new edge types to allow opting out of new behavior
2. Insert an sync point for each edge whose initial node has deferred
system params.
3. Reuse nodes if they're at the number of sync points away.
* add opt outs for specific edges with `after_ignore_deferred`,
`before_ignore_deferred` and `chain_ignore_deferred`. The
`auto_insert_apply_deferred` boolean on `ScheduleBuildSettings` can be
set to false to opt out for the whole schedule.
## Perf
This has a small negative effect on schedule build times.
```text
group auto-sync main-for-auto-sync
----- ----------- ------------------
build_schedule/1000_schedule 1.06 2.8±0.15s ? ?/sec 1.00 2.7±0.06s ? ?/sec
build_schedule/1000_schedule_noconstraints 1.01 26.2±0.88ms ? ?/sec 1.00 25.8±0.36ms ? ?/sec
build_schedule/100_schedule 1.02 13.1±0.33ms ? ?/sec 1.00 12.9±0.28ms ? ?/sec
build_schedule/100_schedule_noconstraints 1.08 505.3±29.30µs ? ?/sec 1.00 469.4±12.48µs ? ?/sec
build_schedule/500_schedule 1.00 485.5±6.29ms ? ?/sec 1.00 485.5±9.80ms ? ?/sec
build_schedule/500_schedule_noconstraints 1.00 6.8±0.10ms ? ?/sec 1.02 6.9±0.16ms ? ?/sec
```
---
## Changelog
- Auto insert sync points and added `after_ignore_deferred`,
`before_ignore_deferred`, `chain_no_deferred` and
`auto_insert_apply_deferred` APIs to opt out of this behavior
## Migration Guide
- `apply_deferred` points are added automatically when there is ordering
relationship with a system that has deferred parameters like `Commands`.
If you want to opt out of this you can switch from `after`, `before`,
and `chain` to the corresponding `ignore_deferred` API,
`after_ignore_deferred`, `before_ignore_deferred` or
`chain_ignore_deferred` for your system/set ordering.
- You can also set `ScheduleBuildSettings::auto_insert_sync_points` to
`false` if you want to do it for the whole schedule. Note that in this
mode you can still add `apply_deferred` points manually.
- For most manual insertions of `apply_deferred` you should remove them
as they cannot be merged with the automatically inserted points and
might reduce parallelizability of the system graph.
## TODO
- [x] remove any apply_deferred used in the engine
- [x] ~~decide if we should deprecate manually using apply_deferred.~~
We'll still allow inserting manual sync points for now for whatever edge
cases users might have.
- [x] Update migration guide
- [x] rerun schedule build benchmarks
---------
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
# Objective
- Finish the work done in #8942 .
## Solution
- Rebase the changes made in #8942 and fix the issues stopping it from
being merged earlier
---------
Co-authored-by: Thomas <1234328+thmsgntz@users.noreply.github.com>
# Objective
Make direction construction a bit more ergonomic.
## Solution
Add `Direction2d::from_xy` and `Direction3d::from_xyz`, similar to
`Transform::from_xyz`:
```rust
let dir2 = Direction2d::from_xy(0.5, 0.5).unwrap();
let dir3 = Direction3d::from_xyz(0.5, 0.5, 0.5).unwrap();
```
This can be a bit cleaner than using `new`:
```rust
let dir2 = Direction2d::new(Vec2::new(0.5, 0.5)).unwrap();
let dir3 = Direction3d::new(Vec3::new(0.5, 0.5, 0.5)).unwrap();
```
Fixes https://github.com/bevyengine/bevy/issues/10974
# Objective
Duplicate the ordering logic of the `Main` schedule into the `FixedMain`
schedule.
---
## Changelog
- `FixedUpdate` is no longer the main schedule ran in
`RunFixedUpdateLoop`, `FixedMain` has replaced this and has a similar
structure to `Main`.
## Migration Guide
- Usage of `RunFixedUpdateLoop` should be renamed to `RunFixedMainLoop`.
# Objective
Fixes#10968
## Solution
Pull startup schedules from a list of `ScheduleLabel`s in the same way
the update schedules are handled.
---
## Changelog
- Added `MainScheduleOrder::startup_labels` to allow the editing of the
startup schedule order.
## Migration Guide
- Added a new field to `MainScheduleOrder`, `startup_labels`, for
editing the startup schedule order.
# Objective
Keep up to date with wgpu.
## Solution
Update the wgpu version.
Currently blocked on naga_oil updating to naga 0.14 and releasing a new
version.
3d scenes (or maybe any scene with lighting?) currently don't render
anything due to
```
error: naga_oil bug, please file a report: composer failed to build a valid header: Type [2] '' is invalid
= Capability Capabilities(CUBE_ARRAY_TEXTURES) is required
```
I'm not sure what should be passed in for `wgpu::InstanceFlags`, or if we want to make the gles3minorversion configurable (might be useful for debugging?)
Currently blocked on https://github.com/bevyengine/naga_oil/pull/63, and https://github.com/gfx-rs/wgpu/issues/4569 to be fixed upstream in wgpu first.
## Known issues
Amd+windows+vulkan has issues with texture_binding_arrays (see the image [here](https://github.com/bevyengine/bevy/pull/10266#issuecomment-1819946278)), but that'll be fixed in the next wgpu/naga version, and you can just use dx12 as a workaround for now (Amd+linux mesa+vulkan texture_binding_arrays are fixed though).
---
## Changelog
Updated wgpu to 0.18, naga to 0.14.2, and naga_oil to 0.11.
- Windows desktop GL should now be less painful as it no longer requires Angle.
- You can now toggle shader validation and debug information for debug and release builds using `WgpuSettings.instance_flags` and [InstanceFlags](https://docs.rs/wgpu/0.18.0/wgpu/struct.InstanceFlags.html)
## Migration Guide
- `RenderPassDescriptor` `color_attachments` (as well as `RenderPassColorAttachment`, and `RenderPassDepthStencilAttachment`) now use `StoreOp::Store` or `StoreOp::Discard` instead of a `boolean` to declare whether or not they should be stored.
- `RenderPassDescriptor` now have `timestamp_writes` and `occlusion_query_set` fields. These can safely be set to `None`.
- `ComputePassDescriptor` now have a `timestamp_writes` field. This can be set to `None` for now.
- See the [wgpu changelog](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v0180-2023-10-25) for additional details
# Objective
- Make the implementation order consistent between all sources to fit
the order in the trait.
## Solution
- Change the implementation order.
# Objective
A workaround for a webgl issue was introduced in #9383 but one function
for mesh2d was missed.
## Solution
Applied the migration guide from #9383 in
`mesh2d_normal_local_to_world()
Note: I'm not using normals so I have not tested the bug & fix
# Objective
The documentation for `AnimationPlayer::play` mentions a non-existent
`transition_duration` argument from an old iteration of the API. It's
confusing.
## Solution
Remove the offending sentence.
# Objective
Since #10776 split `WorldQuery` to `WorldQueryData` and
`WorldQueryFilter`, it should be clear that the query is actually
composed of two parts. It is not factually correct to call "query" only
the data part. Therefore I suggest to rename the `Q` parameter to `D` in
`Query` and related items.
As far as I know, there shouldn't be breaking changes from renaming
generic type parameters.
## Solution
I used a combination of rust-analyzer go to reference and `Ctrl-F`ing
various patterns to catch as many cases as possible. Hopefully I got
them all. Feel free to check if you're concerned of me having missed
some.
## Notes
This and #10779 have many lines in common, so merging one will cause a
lot of merge conflicts to the other.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- The example in the docs is unsound.
Demo:
```rust
#[derive(Resource)]
struct MyRes(u32);
fn main() {
let mut w = World::new();
w.insert_resource(MyRes(0));
let (mut res, comp) = split_world_access(&mut w);
let mut r1 = res.get_resource_mut::<MyRes>().unwrap();
let mut r2 = res.get_resource_mut::<MyRes>().unwrap();
*r1 = MyRes(1);
*r2 = MyRes(2);
}
```
The API in the example allows aliasing mutable references to the same
resource. Miri also complains when running this.
## Solution
- Change the example API to make the returned `Mut` borrow from the
`OnlyResourceAccessWorld` instead of borrowing from the world via `'w`.
This prevents obtaining more than one `Mut` at the same time from it.
I didn't notice minus where vertices are generated, so could not
understand the order there.
Adding a comment to help the next person who is going to understand Bevy
by reading its code.
# Objective
- Reduce nesting in `process_handle_drop_internal()`.
- Related to #10896.
## Solution
- Use early returns when possible.
- Reduced from 9 levels of indents to 4.
# Objective
add `RenderLayers` awareness to lights. lights default to
`RenderLayers::layer(0)`, and must intersect the camera entity's
`RenderLayers` in order to affect the camera's output.
note that lights already use renderlayers to filter meshes for shadow
casting. this adds filtering lights per view based on intersection of
camera layers and light layers.
fixes#3462
## Solution
PointLights and SpotLights are assigned to individual views in
`assign_lights_to_clusters`, so we simply cull the lights which don't
match the view layers in that function.
DirectionalLights are global, so we
- add the light layers to the `DirectionalLight` struct
- add the view layers to the `ViewUniform` struct
- check for intersection before processing the light in
`apply_pbr_lighting`
potential issue: when mesh/light layers are smaller than the view layers
weird results can occur. e.g:
camera = layers 1+2
light = layers 1
mesh = layers 2
the mesh does not cast shadows wrt the light as (1 & 2) == 0.
the light affects the view as (1+2 & 1) != 0.
the view renders the mesh as (1+2 & 2) != 0.
so the mesh is rendered and lit, but does not cast a shadow.
this could be fixed (so that the light would not affect the mesh in that
view) by adding the light layers to the point and spot light structs,
but i think the setup is pretty unusual, and space is at a premium in
those structs (adding 4 bytes more would reduce the webgl point+spot
light max count to 240 from 256).
I think typical usage is for cameras to have a single layer, and
meshes/lights to maybe have multiple layers to render to e.g. minimaps
as well as primary views.
if there is a good use case for the above setup and we should support
it, please let me know.
---
## Migration Guide
Lights no longer affect all `RenderLayers` by default, now like cameras
and meshes they default to `RenderLayers::layer(0)`. To recover the
previous behaviour and have all lights affect all views, add a
`RenderLayers::all()` component to the light entity.
# Objective
Printing `DynamicStruct` with a debug format does not show the contained
type anymore. For instance, in `examples/reflection/reflection.rs`,
adding `dbg!(&reflect_value);` to line 96 will print:
```rust
[examples/reflection/reflection.rs:96] &reflect_value = DynamicStruct(bevy_reflect::DynamicStruct {
a: 4,
nested: DynamicStruct(bevy_reflect::DynamicStruct {
b: 8,
}),
})
```
## Solution
Show the represented type instead (`reflection::Foo` and
`reflection::Bar` in this case):
```rust
[examples/reflection/reflection.rs:96] &reflect_value = DynamicStruct(reflection::Foo {
a: 4,
nested: DynamicStruct(reflection::Bar {
b: 8,
}),
})
```
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
The `Despawn` command breaks the hierarchy whenever you use it if the
despawned entity has a parent or any children. This is a serious footgun
because the `Despawn` command has the shortest name, the behavior is
unexpected and not likely to be what you want, and the crash that it
causes can be very difficult to track down.
## Solution
Until this can be fixed by relations, add a note mentioning the footgun
in the documentation.
## Solution
`Commands.remove` and `.retain` (because I copied `remove`s doc)
referenced `EntityWorldMut.remove` and `retain` for more detail but the
`Commands` docs are much more detailed (which makes sense because it is
the most common api), so I have instead inverted this so that
`EntityWorldMut` docs link to `Commands`.
I also made `EntityWorldMut.despawn` reference `World.despawn` for more
details, like `Commands.despawn` does.
# Objective
Fixes#5891.
For mikktspace normal maps, normals must be renormalized in vertex
shaders to match the way mikktspace bakes vertex tangents and normal
maps so that the exact inverse process is applied when shading.
However, for invalid normals like `vec3<f32>(0.0, 0.0, 0.0)`, this
normalization causes NaN values, and because it's in the vertex shader,
it affects the entire triangle and causes it to be shaded as black:
![incorrectly shaded
cone](https://github.com/bevyengine/bevy/assets/57632562/3334b3a9-f72a-4a08-853e-8077a346f5c9)
*A cone with a tip that has a vertex normal of [0, 0, 0], causing the
mesh to be shaded as black.*
In some cases, normals of zero are actually *useful*. For example, a
smoothly shaded cone without creases requires the apex vertex normal to
be zero, because there is no singular normal that works correctly, so
the apex shouldn't contribute to the overall shading. Duplicate vertices
for the apex fix some shading issues, but it causes visible creases and
is more expensive. See #5891 and #10298 for more details.
For correctly shaded cones and other similar low-density shapes with
sharp tips, vertex normals of zero can not be normalized in the vertex
shader.
## Solution
Only normalize the vertex normals and tangents in the vertex shader if
the normal isn't [0, 0, 0]. This way, mikktspace normal maps should
still work for everything except the zero normals, and the zero normals
will only be normalized in the fragment shader.
This allows us to render cones correctly:
![smooth cone with some
banding](https://github.com/bevyengine/bevy/assets/57632562/6b36e264-22c6-453b-a6de-c404b314ca1a)
Notice how there is still a weird shadow banding effect in one area. I
noticed that it can be fixed by normalizing
[here](d2614f2d80/crates/bevy_pbr/src/render/pbr_functions.wgsl (L51)),
which produces a perfectly smooth cone without duplicate vertices:
![smooth
cone](https://github.com/bevyengine/bevy/assets/57632562/64f9ad5d-b249-4eae-880b-a1e61e07ae73)
I didn't add this change yet, because it seems a bit arbitrary. I can
add it here if that'd be useful or make another PR though.
# Objective
`update_accessibility_nodes` is one of the most nested functions in the
entire Bevy repository, with a maximum of 9 levels of indentations. This
PR refactors it down to 3 levels of indentations, while improving
readability on other fronts. The result is a function that is actually
understandable at a first glance.
- This is a proof of concept to demonstrate that it is possible to
gradually lower the nesting limit proposed by #10896.
PS: I read AccessKit's documentation, but I don't have experience with
it. Therefore, naming of variables and subroutines may be a bit off.
PS2: I don't know if the test suite covers the functionality of this
system, but since I've spent quite some time on it and the changes were
simple, I'm pretty confident the refactor is functionally equivalent to
the original.
## Solution
I documented each change with a commit, but as a summary I did the
following to reduce nesting:
- I moved from `if-let` blocks to `let-else` statements where
appropriate to reduce rightward shift
- I extracted the closure body to a new function `update_adapter`
- I factored out parts of `update_adapter` into new functions
`queue_node_for_update` and `add_children_nodes`
**Note for reviewers:** GitHub's diff viewer is not the greatest in
showing horizontal code shifts, therefore you may want to use a
different tool like VSCode to review some commits, especially the second
one (anyway, that commit is very straightforward, despite changing many
lines).
# Objective
A nodes outline should be clipped using its own clipping rect, not its
parents.
fixes#10921
## Solution
Clip outlines by the node's own clipping rect, not the parent's.
If you compare the `overflow` ui example in main with this PR, you'll
see that the outlines that appear when you hover above the images are
now clipped along with the images.
---
## Changelog
* Outlines are now clipped using the node's own clipping rect, not the
parent's.
# Objective
- Improve readability.
- Somewhat relates to #10896.
## Solution
- Use early returns to minimize nesting.
- Change `emitter_translation` to use `if let` instead of `map`.
# Objective
The `update_emitter_positions`, and `update_listener_positions` systems
are added for every call to `add_audio_source`.
Instead, add them once in the `AudioPlugin` directly.
Also merged the calls to `add_systems`.
Caught while working on my schedule visualizer c:
# Objective
Test more complex function signatures for exclusive systems, and test
that `StaticSystemParam` is indeed a `SystemParam`.
I mean, it currently works, but might as well add a test for it.
# Objective
- Resolves#10853
## Solution
- ~~Changed the name of `Input` struct to `PressableInput`.~~
- Changed the name of `Input` struct to `ButtonInput`.
## Migration Guide
- Breaking Change: Users need to rename `Input` to `ButtonInput` in
their projects.
# Objective
A better alternative version of #10843.
Currently, Bevy has a single `Ray` struct for 3D. To allow better
interoperability with Bevy's primitive shapes (#10572) and some third
party crates (that handle e.g. spatial queries), it would be very useful
to have separate versions for 2D and 3D respectively.
## Solution
Separate `Ray` into `Ray2d` and `Ray3d`. These new structs also take
advantage of the new primitives by using `Direction2d`/`Direction3d` for
the direction:
```rust
pub struct Ray2d {
pub origin: Vec2,
pub direction: Direction2d,
}
pub struct Ray3d {
pub origin: Vec3,
pub direction: Direction3d,
}
```
and by using `Plane2d`/`Plane3d` in `intersect_plane`:
```rust
impl Ray2d {
// ...
pub fn intersect_plane(&self, plane_origin: Vec2, plane: Plane2d) -> Option<f32> {
// ...
}
}
```
---
## Changelog
### Added
- `Ray2d` and `Ray3d`
- `Ray2d::new` and `Ray3d::new` constructors
- `Plane2d::new` and `Plane3d::new` constructors
### Removed
- Removed `Ray` in favor of `Ray3d`
### Changed
- `direction` is now a `Direction2d`/`Direction3d` instead of a vector,
which provides guaranteed normalization
- `intersect_plane` now takes a `Plane2d`/`Plane3d` instead of just a
vector for the plane normal
- `Direction2d` and `Direction3d` now derive `Serialize` and
`Deserialize` to preserve ray (de)serialization
## Migration Guide
`Ray` has been renamed to `Ray3d`.
### Ray creation
Before:
```rust
Ray {
origin: Vec3::ZERO,
direction: Vec3::new(0.5, 0.6, 0.2).normalize(),
}
```
After:
```rust
// Option 1:
Ray3d {
origin: Vec3::ZERO,
direction: Direction3d::new(Vec3::new(0.5, 0.6, 0.2)).unwrap(),
}
// Option 2:
Ray3d::new(Vec3::ZERO, Vec3::new(0.5, 0.6, 0.2))
```
### Plane intersections
Before:
```rust
let result = ray.intersect_plane(Vec2::X, Vec2::Y);
```
After:
```rust
let result = ray.intersect_plane(Vec2::X, Plane2d::new(Vec2::Y));
```
# Objective
Implement `TryFrom<Vec2>`/`TryFrom<Vec3>` for direction primitives as
considered in #10857.
## Solution
Implement `TryFrom` for the direction primitives.
These are all equivalent:
```rust
let dir2d = Direction2d::try_from(Vec2::new(0.5, 0.5)).unwrap();
let dir2d = Vec2::new(0.5, 0.5).try_into().unwrap(); // (assumes that the type is inferred)
let dir2d = Direction2d::new(Vec2::new(0.5, 0.5)).unwrap();
```
For error cases, an `Err(InvalidDirectionError)` is returned. It
contains the type of failure:
```rust
/// An error indicating that a direction is invalid.
#[derive(Debug, PartialEq)]
pub enum InvalidDirectionError {
/// The length of the direction vector is zero or very close to zero.
Zero,
/// The length of the direction vector is `std::f32::INFINITY`.
Infinite,
/// The length of the direction vector is `NaN`.
NaN,
}
```
# Objective
- Resolves#10784
## Solution
- As @ickshonpe mentioned in #10784, this is intended behavior but could
benefit from mentioning it in docs.
- I'm also thinking about adding a helper function to disable os scaling
such as `disable_os_scaling()`, but not sure if it's needed.
---
## Changelog
> Add a comment about scaling behavior that happens, and point user to
how he can avoid that behavior.
# Objective
Adds `EntityCommands.retain` and `EntityWorldMut.retain` to remove all
components except the given bundle from the entity.
Fixes#10865.
## Solution
I added a private unsafe function in `EntityWorldMut` called
`remove_bundle_info` which performs the shared behaviour of `remove` and
`retain`, namely taking a `BundleInfo` of components to remove, and
removing them from the given entity. Then `retain` simply gets all the
components on the entity and filters them by whether they are in the
bundle it was passed, before passing this `BundleInfo` into
`remove_bundle_info`.
`EntityCommands.retain` just creates a new type `Retain` which runs
`EntityWorldMut.retain` when run.
---
## Changelog
Added `EntityCommands.retain` and `EntityWorldMut.retain`, which remove
all components except the given bundle from the entity, they can also be
used to remove all components by passing `()` as the bundle.
# Objective
The name `TextAlignment` is really deceptive and almost every new user
gets confused about the differences between aligning text with
`TextAlignment`, aligning text with `Style` and aligning text with
anchor (when using `Text2d`).
## Solution
* Rename `TextAlignment` to `JustifyText`. The associated helper methods
are also renamed.
* Improve the doc comments for text explaining explicitly how the
`JustifyText` component affects the arrangement of text.
* Add some extra cases to the `text_debug` example that demonstate the
differences between alignment using `JustifyText` and alignment using
`Style`.
<img width="757" alt="text_debug_2"
src="https://github.com/bevyengine/bevy/assets/27962798/9d53e647-93f9-4bc7-8a20-0d9f783304d2">
---
## Changelog
* `TextAlignment` has been renamed to `JustifyText`
* `TextBundle::with_text_alignment` has been renamed to
`TextBundle::with_text_justify`
* `Text::with_alignment` has been renamed to `Text::with_justify`
* The `text_alignment` field of `TextMeasureInfo` has been renamed to
`justification`
## Migration Guide
* `TextAlignment` has been renamed to `JustifyText`
* `TextBundle::with_text_alignment` has been renamed to
`TextBundle::with_text_justify`
* `Text::with_alignment` has been renamed to `Text::with_justify`
* The `text_alignment` field of `TextMeasureInfo` has been renamed to
`justification`
# Objective
- Fixes#10806
## Solution
Replaced `new` and `index` methods for both `TableRow` and `TableId`
with `from_*` and `as_*` methods. These remove the need to perform
casting at call sites, reducing the total number of casts in the Bevy
codebase. Within these methods, an appropriate `debug_assertion` ensures
the cast will behave in an expected manner (no wrapping, etc.). I am
using a `debug_assertion` instead of an `assert` to reduce any possible
runtime overhead, however minimal. This choice is something I am open to
changing (or leaving up to another PR) if anyone has any strong
arguments for it.
---
## Changelog
- `ComponentSparseSet::sparse` stores a `TableRow` instead of a `u32`
(private change)
- Replaced `TableRow::new` and `TableRow::index` methods with
`TableRow::from_*` and `TableRow::as_*`, with `debug_assertions`
protecting any internal casting.
- Replaced `TableId::new` and `TableId::index` methods with
`TableId::from_*` and `TableId::as_*`, with `debug_assertions`
protecting any internal casting.
- All `TableId` methods are now `const`
## Migration Guide
- `TableRow::new` -> `TableRow::from_usize`
- `TableRow::index` -> `TableRow::as_usize`
- `TableId::new` -> `TableId::from_usize`
- `TableId::index` -> `TableId::as_usize`
---
## Notes
I have chosen to remove the `index` and `new` methods for the following
chain of reasoning:
- Across the codebase, `new` was called with a mixture of `u32` and
`usize` values. Likewise for `index`.
- Choosing `new` to either be `usize` or `u32` would break half of these
call-sites, requiring `as` casting at the site.
- Adding a second method `new_u32` or `new_usize` avoids the above, bu
looks visually inconsistent.
- Therefore, they should be replaced with `from_*` and `as_*` methods
instead.
Worth noting is that by updating `ComponentSparseSet`, there are now
zero instances of interacting with the inner value of `TableRow` as a
`u32`, it is exclusively used as a `usize` value (due to interactions
with methods like `len` and slice indexing). I have left the `as_u32`
and `from_u32` methods as the "proper" constructors/getters.
This removes the `From<Vec2/3>` implementations for the direction types.
It doesn't seem right to have when it only works if the vector is
nonzero and finite and produces NaN otherwise.
Added `Direction2d/3d::new` which uses `Vec2/3::try_normalize` to
guarantee it returns either a valid direction or `None`.
This should make it impossible to create an invalid direction, which I
think was the intention with these types.
# Objective
Fixes#10291
This adds a way to easily log messages once within system which are
called every frame.
## Solution
Opted for a macro-based approach. The fact that the 'once' call is
tracked per call site makes the `log_once!()` macro very versatile and
easy-to-use. I suspect it will be very handy for all of us, but
especially beginners, to get some initial feedback from systems without
spamming up the place!
I've made the macro's return its internal `has_fired` state, for
situations in which that might be useful to know (trigger something else
alongside the log, for example).
Please let me know if I placed the macro's in the right location, and if
you would like me to do something more clever with the macro's
themselves, since its looking quite copy-pastey at the moment. I've
tried ways to replace 5 with 1 macro's, but no success yet.
One downside of this approach is: Say you wish to warn the user if a
resource is invalid. In this situation, the
`resource.is_valid()` check would still be performed every frame:
```rust
fn my_system(my_res: Res<MyResource>) {
if !my_res.is_valid() {
warn_once!("resource is invalid!");
}
}
```
If you want to prevent that, you would still need to introduce a local
boolean. I don't think this is a very big deal, as expensive checks
shouldn't be called every frame in any case.
## Changelog
Added: `trace_once!()`, `debug_once!()`, `info_once!()`, `warn_once!()`,
and `error_once!()` log macros which fire only once per call site.
# Objective
Resolves Issue #10772.
## Solution
Added the deprecated warning for QueryState::for_each_unchecked, as
noted in the comments of PR #6773.
Followed the wording in the deprecation messages for `for_each` and
`for_each_mut`
# Objective
After #6547, `Query::for_each` has been capable of automatic
vectorization on certain queries, which is seeing a notable (>50% CPU
time improvements) for iteration. However, `Query::for_each` isn't
idiomatic Rust, and lacks the flexibility of iterator combinators.
Ideally, `Query::iter` and friends should be able to achieve the same
results. However, this does seem to blocked upstream
(rust-lang/rust#104914) by Rust's loop optimizations.
## Solution
This is an intermediate solution and refactor. This moves the
`Query::for_each` implementation onto the `Iterator::fold`
implementation for `QueryIter` instead. This should result in the same
automatic vectorization optimization on all `Iterator` functions that
internally use fold, including `Iterator::for_each`, `Iterator::count`,
etc.
With this, it should close the gap between the two completely.
Internally, this PR changes `Query::for_each` to use
`query.iter().for_each(..)` instead of the duplicated implementation.
Separately, the duplicate implementations of internal iteration (i.e.
`Query::par_for_each`) now use portions of the current `Query::for_each`
implementation factored out into their own functions.
This also massively cleans up our internal fragmentation of internal
iteration options, deduplicating the iteration code used in `for_each`
and `par_iter().for_each()`.
---
## Changelog
Changed: `Query::for_each`, `Query::for_each_mut`, `Query::for_each`,
and `Query::for_each_mut` have been moved to `QueryIter`'s
`Iterator::for_each` implementation, and still retains their performance
improvements over normal iteration. These APIs are deprecated in 0.13
and will be removed in 0.14.
---------
Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
when loading gltfs we may want to filter the results. in particular, i
need to be able to exclude cameras.
i can do this already by modifying the gltf after load and before
spawning, but it seems like a useful general option.
## Solution
add `GltfLoaderSettings` struct with bool members:
- `load_cameras` : checked before processing camera nodes.
- `load_lights` : checked before processing light nodes
- `load_meshes` : checked before loading meshes, materials and morph
weights
Existing code will work as before. Now you also have the option to
restrict what parts of the gltf are loaded. For example, to load a gltf
but exclude the cameras, replace a call to
`asset_server.load("my.gltf")` with:
```rust
asset_server.load_with_settings(
"my.gltf",
|s: &mut GltfLoaderSettings| {
s.load_cameras = false;
}
);
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#10444
Currently manually removing an asset prevents it from being reloaded
while there are still active handles. Doing so will result in a panic,
because the storage entry has been marked as "empty / None" but the ID
is still assumed to be active by the asset server.
Patterns like `images.remove() -> asset_server.reload()` and
`images.remove() -> images.insert()` would fail if the handle was still
alive.
## Solution
Most of the groundwork for this was already laid in Bevy Asset V2. This
is largely just a matter of splitting out `remove` into two separate
operations:
* `remove_dropped`: remove the stored asset, invalidate the internal
Assets entry (preventing future insertions with the old id), and recycle
the id
* `remove_still_alive`: remove the stored asset, but leave the entry
otherwise untouched (and dont recycle the id).
`remove_still_alive` and `insert` can be called any number of times (in
any order) for an id until `remove_dropped` has been called, which will
invalidate the id.
From a user-facing perspective, there are no API changes and this is non
breaking. The public `Assets::remove` will internally call
`remove_still_alive`. `remove_dropped` can only be called by the
internal "handle management" system.
---
## Changelog
- Fix a bug preventing `Assets::remove` from blocking future inserts for
a specific `AssetIndex`.
# Objective
Fixes https://github.com/bevyengine/bevy/issues/10786
## Solution
The bind_group_layout entries for the prepass were wrong when not all 4
prepass textures were used, as it just zipped [17, 18, 19, 20] with the
smallvec of prepass `bind_group_layout` entries that potentially didn't
contain 4 entries. (eg. if you had a depth and motion vector prepass but
no normal prepass, then depth would be correct but the entry for the
motion vector prepass would be 18 (normal prepass' spot) instead of 19).
Change the prepass `get_bind_group_layout_entries` function to return an
array of `[Option<BindGroupLayoutEntryBuilder>; 4]` and only add the
layout entry if it exists.
# Objective
avoid panics from `calculate_bounds` systems if entities are despawned
in PostUpdate.
there's a running general discussion (#10166) about command panicking.
in the meantime we may as well fix up some cases where it's clear a
failure to insert is safe.
## Solution
change `.insert(aabb)` to `.try_insert(aabb)`
# Objective
> Issue raised on
[Discord](https://discord.com/channels/691052431525675048/1002362493634629796/1179182488787103776)
Currently the following code fails due to a missing `TypePath` bound:
```rust
#[derive(Reflect)] struct Foo<T>(T);
#[derive(Reflect)] struct Bar<T>(Foo<T>);
#[derive(Reflect)] struct Baz<T>(Bar<Foo<T>>);
```
## Solution
Add `TypePath` to the per-field bounds instead of _just_ the generic
type parameter bounds.
### Related Work
It should be noted that #9046 would help make these kinds of issues
easier to work around and/or avoid entirely.
---
## Changelog
- Fixes missing `TypePath` requirement when deriving `Reflect` on nested
generics
# Objective
Fixes#10401
## Solution
* Allow sources to register specific processed/unprocessed watch
warnings.
* Specify per-platform watch warnings. This removes the need to cover
all platform cases in one warning message.
* Only register watch warnings for the _processed_ embedded source, as
warning about watching unprocessed embedded isn't helpful.
---
## Changelog
- Asset sources can now register specific watch warnings.
# Objective
- Shorten paths by removing unnecessary prefixes
## Solution
- Remove the prefixes from many paths which do not need them. Finding
the paths was done automatically using built-in refactoring tools in
Jetbrains RustRover.
# Objective
These type are unavailable to editors and scripting interfaces making
use of reflection.
## Solution
`#[derive(Reflect)]` and call `.register_type` during plugin
initialization.
---
## Changelog
### Added
- Implement `Reflect` for audio-related types, and register them.
# Objective
- Materials should be a more frequent rebind then meshes (due to being
able to use a single vertex buffer, such as in #10164) and therefore
should be in a higher bind group.
---
## Changelog
- For 2d and 3d mesh/material setups (but not UI materials, or other
rendering setups such as gizmos, sprites, or text), mesh data is now in
bind group 1, and material data is now in bind group 2, which is swapped
from how they were before.
## Migration Guide
- Custom 2d and 3d mesh/material shaders should now use bind group 2
`@group(2) @binding(x)` for their bound resources, instead of bind group
1.
- Many internal pieces of rendering code have changed so that mesh data
is now in bind group 1, and material data is now in bind group 2.
Semi-custom rendering setups (that don't use the Material or Material2d
APIs) should adapt to these changes.
# Objective
Keep essentially the same structure of `EntityHasher` from #9903, but
rephrase the multiplication slightly to save an instruction.
cc @superdump
Discord thread:
https://discord.com/channels/691052431525675048/1172033156845674507/1174969772522356756
## Solution
Today, the hash is
```rust
self.hash = i | (i.wrapping_mul(FRAC_U64MAX_PI) << 32);
```
with `i` being `(generation << 32) | index`.
Expanding things out, we get
```rust
i | ( (i * CONST) << 32 )
= (generation << 32) | index | ((((generation << 32) | index) * CONST) << 32)
= (generation << 32) | index | ((index * CONST) << 32) // because the generation overflowed
= (index * CONST | generation) << 32 | index
```
What if we do the same thing, but with `+` instead of `|`? That's almost
the same thing, except that it has carries, which are actually often
better in a hash function anyway, since it doesn't saturate. (`|` can be
dangerous, since once something becomes `-1` it'll stay that, and
there's no mixing available.)
```rust
(index * CONST + generation) << 32 + index
= (CONST << 32 + 1) * index + generation << 32
= (CONST << 32 + 1) * index + (WHATEVER << 32 + generation) << 32 // because the extra overflows and thus can be anything
= (CONST << 32 + 1) * index + ((CONST * generation) << 32 + generation) << 32 // pick "whatever" to be something convenient
= (CONST << 32 + 1) * index + ((CONST << 32 + 1) * generation) << 32
= (CONST << 32 + 1) * index +((CONST << 32 + 1) * (generation << 32)
= (CONST << 32 + 1) * (index + generation << 32)
= (CONST << 32 + 1) * (generation << 32 | index)
= (CONST << 32 + 1) * i
```
So we can do essentially the same thing using a single multiplication
instead of doing multiply-shift-or.
LLVM was already smart enough to merge the shifting into a
multiplication, but this saves the extra `or`:
![image](https://github.com/bevyengine/bevy/assets/18526288/d9396614-2326-4730-abbe-4908c01b5ace)
<https://rust.godbolt.org/z/MEvbz4eo4>
It's a very small change, and often will disappear in load latency
anyway, but it's a couple percent faster in lookups:
![image](https://github.com/bevyengine/bevy/assets/18526288/c365ec85-6adc-4f6d-8fa6-a65146f55a75)
(There was more of an improvement here before #10558, but with `to_bits`
being a single `qword` load now, keeping things mostly as it is turned
out to be better than the bigger changes I'd tried in #10605.)
---
## Changelog
(Probably skip it)
## Migration Guide
(none needed)
# Objective
the pbr prepass vertex shader currently only sets
`VertexOutput::world_position` when deferred or motion prepasses are
enabled.
the field is always in the vertex output so is otherwise undetermined,
and the calculation is very cheap.
## Solution
always set the world position in the pbr prepass vert shader.
# Objective
`GlobalsUniform` provides the current time to shaders, which is useful
for animations. `UiMaterial` is an abstraction that makes it easier to
write custom shaders for UI elements.
This PR makes it possible to use the `GlobalsUniform` in `UiMaterial`
shaders.
## Solution
The `GlobalsUniform` is bound to `@group(0) @binding(1)`. It is
accessible in shaders with:
```wgsl
#import bevy_render::globals::Globals
@group(0) @binding(1)
var<uniform> globals: Globals;
```
---
## Changelog
Added `GlobalsUniform` in `UiMaterial` shaders
## Discussion
Should I modify the existing ui_material example to showcase this?
# Objective
Related to #10612.
Enable the
[`clippy::manual_let_else`](https://rust-lang.github.io/rust-clippy/master/#manual_let_else)
lint as a warning. The `let else` form seems more idiomatic to me than a
`match`/`if else` that either match a pattern or diverge, and from the
clippy doc, the lint doesn't seem to have any possible false positive.
## Solution
Add the lint as warning in `Cargo.toml`, refactor places where the lint
triggers.
# Objective
- Follow up to #9694
## Solution
- Same api as #9694 but adapted for `BindGroupLayoutEntry`
- Use the same `ShaderStages` visibilty for all entries by default
- Add `BindingType` helper function that mirror the wgsl equivalent and
that make writing layouts much simpler.
Before:
```rust
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("post_process_bind_group_layout"),
entries: &[
BindGroupLayoutEntry {
binding: 0,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture {
sample_type: TextureSampleType::Float { filterable: true },
view_dimension: TextureViewDimension::D2,
multisampled: false,
},
count: None,
},
BindGroupLayoutEntry {
binding: 1,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler(SamplerBindingType::Filtering),
count: None,
},
BindGroupLayoutEntry {
binding: 2,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Buffer {
ty: bevy::render::render_resource::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: Some(PostProcessSettings::min_size()),
},
count: None,
},
],
});
```
After:
```rust
let layout = render_device.create_bind_group_layout(
"post_process_bind_group_layout"),
&BindGroupLayoutEntries::sequential(
ShaderStages::FRAGMENT,
(
texture_2d_f32(),
sampler(SamplerBindingType::Filtering),
uniform_buffer(false, Some(PostProcessSettings::min_size())),
),
),
);
```
Here's a more extreme example in bevy_solari:
86dab7f5da
---
## Changelog
- Added `BindGroupLayoutEntries` and all `BindingType` helper functions.
## Migration Guide
`RenderDevice::create_bind_group_layout()` doesn't take a
`BindGroupLayoutDescriptor` anymore. You need to provide the parameters
separately
```rust
// 0.12
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("post_process_bind_group_layout"),
entries: &[
BindGroupLayoutEntry {
// ...
},
],
});
// 0.13
let layout = render_device.create_bind_group_layout(
"post_process_bind_group_layout",
&[
BindGroupLayoutEntry {
// ...
},
],
);
```
## TODO
- [x] implement a `Dynamic` variant
- [x] update the `RenderDevice::create_bind_group_layout()` api to match
the one from `RenderDevice::creat_bind_group()`
- [x] docs
# Objective
- Fixes#7680
- This is an updated for https://github.com/bevyengine/bevy/pull/8899
which had the same objective but fell a long way behind the latest
changes
## Solution
The traits `WorldQueryData : WorldQuery` and `WorldQueryFilter :
WorldQuery` have been added and some of the types and functions from
`WorldQuery` has been moved into them.
`ReadOnlyWorldQuery` has been replaced with `ReadOnlyWorldQueryData`.
`WorldQueryFilter` is safe (as long as `WorldQuery` is implemented
safely).
`WorldQueryData` is unsafe - safely implementing it requires that
`Self::ReadOnly` is a readonly version of `Self` (this used to be a
safety requirement of `WorldQuery`)
The type parameters `Q` and `F` of `Query` must now implement
`WorldQueryData` and `WorldQueryFilter` respectively.
This makes it impossible to accidentally use a filter in the data
position or vice versa which was something that could lead to bugs.
~~Compile failure tests have been added to check this.~~
It was previously sometimes useful to use `Option<With<T>>` in the data
position. Use `Has<T>` instead in these cases.
The `WorldQuery` derive macro has been split into separate derive macros
for `WorldQueryData` and `WorldQueryFilter`.
Previously it was possible to derive both `WorldQuery` for a struct that
had a mixture of data and filter items. This would not work correctly in
some cases but could be a useful pattern in others. *This is no longer
possible.*
---
## Notes
- The changes outside of `bevy_ecs` are all changing type parameters to
the new types, updating the macro use, or replacing `Option<With<T>>`
with `Has<T>`.
- All `WorldQueryData` types always returned `true` for `IS_ARCHETYPAL`
so I moved it to `WorldQueryFilter` and
replaced all calls to it with `true`. That should be the only logic
change outside of the macro generation code.
- `Changed<T>` and `Added<T>` were being generated by a macro that I
have expanded. Happy to revert that if desired.
- The two derive macros share some functions for implementing
`WorldQuery` but the tidiest way I could find to implement them was to
give them a ton of arguments and ask clippy to ignore that.
## Changelog
### Changed
- Split `WorldQuery` into `WorldQueryData` and `WorldQueryFilter` which
now have separate derive macros. It is not possible to derive both for
the same type.
- `Query` now requires that the first type argument implements
`WorldQueryData` and the second implements `WorldQueryFilter`
## Migration Guide
- Update derives
```rust
// old
#[derive(WorldQuery)]
#[world_query(mutable, derive(Debug))]
struct CustomQuery {
entity: Entity,
a: &'static mut ComponentA
}
#[derive(WorldQuery)]
struct QueryFilter {
_c: With<ComponentC>
}
// new
#[derive(WorldQueryData)]
#[world_query_data(mutable, derive(Debug))]
struct CustomQuery {
entity: Entity,
a: &'static mut ComponentA,
}
#[derive(WorldQueryFilter)]
struct QueryFilter {
_c: With<ComponentC>
}
```
- Replace `Option<With<T>>` with `Has<T>`
```rust
/// old
fn my_system(query: Query<(Entity, Option<With<ComponentA>>)>)
{
for (entity, has_a_option) in query.iter(){
let has_a:bool = has_a_option.is_some();
//todo!()
}
}
/// new
fn my_system(query: Query<(Entity, Has<ComponentA>)>)
{
for (entity, has_a) in query.iter(){
//todo!()
}
}
```
- Fix queries which had filters in the data position or vice versa.
```rust
// old
fn my_system(query: Query<(Entity, With<ComponentA>)>)
{
for (entity, _) in query.iter(){
//todo!()
}
}
// new
fn my_system(query: Query<Entity, With<ComponentA>>)
{
for entity in query.iter(){
//todo!()
}
}
// old
fn my_system(query: Query<AnyOf<(&ComponentA, With<ComponentB>)>>)
{
for (entity, _) in query.iter(){
//todo!()
}
}
// new
fn my_system(query: Query<Option<&ComponentA>, Or<(With<ComponentA>, With<ComponentB>)>>)
{
for entity in query.iter(){
//todo!()
}
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Kind of helps #10509
## Solution
Add a line to `prepass.wgsl` that ensure the `instance_index` push
constant is always used on WebGL 2. This is not a full fix, as the
_second_ a custom shader is used that doesn't use the push constant, the
breakage will resurface. We have satisfying medium term and long term
solutions. This is just a short term hack for 0.12.1 that will make more
cases work. See #10509 for more details.
# Objective
- `insert_reflect` relies on `reflect_type_path`, which doesn't gives
the actual type path for object created by `clone_value`, leading to an
unexpected panic. This is a workaround for it.
- Fix#10590
## Solution
- Tries to get type path from `get_represented_type_info` if get failed
from `reflect_type_path`.
---
## Defect remaining
- `get_represented_type_info` implies a shortage on performance than
using `TypeRegistry`.
# Objective
Fixes#10688
There were a number of issues at play:
1. The GLTF loader was not registering Scene dependencies properly. They
were being registered at the root instead of on the scene assets. This
made `LoadedWithDependencies` fire immediately on load.
2. Recursive labeled assets _inside_ of labeled assets were not being
loaded. This only became relevant for scenes after fixing (1) because we
now add labeled assets to the nested scene `LoadContext` instead of the
root load context. I'm surprised nobody has hit this yet. I'm glad I
caught it before somebody hit it.
3. Accessing "loaded with dependencies" state on the Asset Server is
boilerplatey + error prone (because you need to manually query two
states).
## Solution
1. In GltfLoader, use a nested LoadContext for scenes and load
dependencies through that context.
2. In the `AssetServer`, load labeled assets recursively.
3. Added a simple `asset_server.is_loaded_with_dependencies(id)`
I also added some docs to `LoadContext` to help prevent this problem in
the future.
---
## Changelog
- Added `AssetServer::is_loaded_with_dependencies`
- Fixed GLTF Scene dependencies
- Fixed nested labeled assets not being loaded
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fixes#10676, preventing a possible memory leak for commands which
owned resources.
## Solution
Implemented `Drop` for `CommandQueue`. This has been done entirely in
the private API of `CommandQueue`, ensuring no breaking changes. Also
added a unit test, `test_command_queue_inner_drop_early`, based on the
reproduction steps as outlined in #10676.
## Notes
I believe this can be applied to `0.12.1` as well, but I am uncertain of
the process to make that kind of change. Please let me know if there's
anything I can do to help with the back-porting of this change.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Fixes#10157
## Solution
Add `AssetMetaCheck` resource which can configure when/if asset meta
files will be read:
```rust
app
// Never attempts to look up meta files. The default meta configuration will be used for each asset.
.insert_resource(AssetMetaCheck::Never)
.add_plugins(DefaultPlugins)
```
This serves as a band-aid fix for the issue with wasm's
`HttpWasmAssetReader` creating a bunch of requests for non-existent
meta, which can slow down asset loading (by waiting for the 404
response) and creates a bunch of noise in the logs. This also provides a
band-aid fix for the more serious issue of itch.io deployments returning
403 responses, which results in full failure of asset loads.
If users don't want to include meta files for all deployed assets for
web builds, and they aren't using meta files at all, they should set
this to `AssetMetaCheck::Never`.
If users do want to include meta files for specific assets, they can use
`AssetMetaCheck::Paths`, which will only look up meta for those paths.
Currently, this defaults to `AssetMetaCheck::Always`, which makes this
fully non-breaking for the `0.12.1` release. _**However it _is_ worth
discussing making this `AssetMetaCheck::Never` by default**_, given that
I doubt most people are using meta files without the Asset Processor
enabled. This would be a breaking change, but it would make WASM / Itch
deployments work by default, which is a pretty big win imo. The downside
is that people using meta files _without_ processing would need to
manually enable `AssetMetaCheck::Always`, which is also suboptimal.
When in `AssetMetaCheck::Processed`, the meta check resource is ignored,
as processing requires asset meta files to function.
In general, I don't love adding this knob as things should ideally "just
work" in all cases. But this is the reality of the current situation.
---
## Changelog
- Added `AssetMetaCheck` resource, which can configure when/if asset
meta files will be read
# Objective
Resolves#10743.
## Solution
Copied over the documentation written by @stepancheng from PR #10718.
I left out the lines from the doctest where `<()>` is removed, as that
seemed to be the part people couldn't decide on whether to keep or not.
## Objective
Currently, events are dropped after two frames. This cadence wasn't
*chosen* for a specific reason, double buffering just lets events
persist for at least two frames. Events only need to be dropped at a
predictable point so that the event queues don't grow forever (i.e.
events should never cause a memory leak).
Events (and especially input events) need to be observable by systems in
`FixedUpdate`, but as-is events are dropped before those systems even
get a chance to see them.
## Solution
Instead of unconditionally dropping events in `First`, require
`FixedUpdate` to first queue the buffer swap (if the `TimePlugin` has
been installed). This way, events are only dropped after a frame that
runs `FixedUpdate`.
## Future Work
In the same way we have independent copies of `Time` for tracking time
in `Main` and `FixedUpdate`, we will need independent copies of `Input`
for tracking press/release status correctly in `Main` and `FixedUpdate`.
--
Every run of `FixedUpdate` covers a specific timespan. For example, if
the fixed timestep `Δt` is 10ms, the first three `FixedUpdate` runs
cover `[0ms, 10ms)`, `[10ms, 20ms)`, and `[20ms, 30ms)`.
`FixedUpdate` can run many times in one frame. For truly
framerate-independent behavior, each `FixedUpdate` should only see the
events that occurred in its covered timespan, but what happens right now
is the first step in the frame reads all pending events.
Fixing that will require timestamped events.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
forward for bevy user to consume
# Objective
- since winit 0.27 an event WindowOccluded will be produced:
https://docs.rs/winit/latest/winit/event/enum.WindowEvent.html#variant.Occluded
- on ios this is currently the only way to know if an app comes back
from the background which is an important time to to things (like
resetting the badge)
## Solution
- pick up the winit event and forward it to a new `EventWriter`
---
## Changelog
### Added
- new Event `WindowOccluded` added allowing to hook into
`WindowEvent::Occluded` of winit
# Objective
I tried setting `ClearColorConfig` in my app via `Color::FOO.into()`
expecting it to work, but the impl was missing.
## Solution
- Add `impl From<Color> for ClearColorConfig`
- Change examples to use this impl
## Changelog
### Added
- `ClearColorConfig` can be constructed via `.into()` on a `Color`
---------
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
`wgpu` has a helper method `texture.as_image_copy()` for a common
pattern when making a default-like `ImageCopyTexture` from a texture.
This is used in various places in Bevy for texture copy operations, but
it was not used where `write_texture` is called.
## Solution
- Replace struct `ImageCopyTexture` initialization with
`texture.as_image_copy()` where appropriate
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
- Window size, scale and position are not correct on the first execution
of the systems
- Fixes#10407, fixes#10642
## Solution
- Don't run `update` before we get a chance to create the window in
winit
- Finish reverting #9826 after #10389
# Objective
The `generate_composite_uuid` utility function hidden in
`bevy_reflect::__macro_exports` could be generally useful to users.
For example, I previously relied on `Hash` to generate a `u64` to create
a deterministic `HandleId`. In v0.12, `HandleId` has been replaced by
`AssetId` which now requires a `Uuid`, which I could generate with this
function.
## Solution
Relocate `generate_composite_uuid` from `bevy_reflect::__macro_exports`
to `bevy_utils::uuid`.
It is still re-exported under `bevy_reflect::__macro_exports` so there
should not be any breaking changes (although, users should generally not
rely on pseudo-private/hidden modules like `__macro_exports`).
I chose to keep it in `bevy_reflect::__macro_exports` so as to not
clutter up our public API and to reduce the number of changes in this
PR. We could have also marked the export as `#[doc(hidden)]`, but
personally I like that we have a dedicated module for this (makes it
clear what is public and what isn't when just looking at the macro
code).
---
## Changelog
- Moved `generate_composite_uuid` to `bevy_utils::uuid` and made it
public
- Note: it was technically already public, just hidden
# Objective
It is currently impossible to control the relative ordering of two 2D
materials at the same depth. This is required to implement wireframes
for 2D meshes correctly
(https://github.com/bevyengine/bevy/issues/5881).
## Solution
Add a `Material2d::depth_bias` function that mirrors the existing 3D
`Material::depth_bias` function.
(this is pulled out of https://github.com/bevyengine/bevy/pull/10489)
---
## Changelog
### Added
- Added `Material2d::depth_bias`
## Migration Guide
`PreparedMaterial2d` has a new `depth_bias` field. A value of 0.0 can be
used to get the previous behavior.
# Objective
Resolves #10727.
`outline.width` was being assigned to `node.outline_offset` instead of
`outline.offset`.
## Solution
Changed `.width` to `.offset` in line 413.
# Objective
Bevy_hierarchy is very useful for ECS only usages of bevy_ecs, but it
currently pulls in bevy_reflect, bevy_app and bevy_core with no way to
opt out.
## Solution
This PR provides features `bevy_app` and `reflect` that are enabled by
default. If disabled, they should remove these dependencies from
bevy_hierarchy.
---
## Changelog
Added features `bevy_app` and `reflect` to bevy_hierarchy.
# Objective
Updates [`futures-lite`](https://github.com/smol-rs/futures-lite) in
bevy_tasks to the next major version (1 -> 2).
Also removes the duplication of `futures-lite`, as `async-fs` requires v
2, so there are currently 2 copies of futures-lite in the dependency
tree.
Futures-lite has received [a number of
updates](https://github.com/smol-rs/futures-lite/blob/master/CHANGELOG.md)
since bevy's current version `1.4`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Mike <mike.hsu@gmail.com>
# Objective
- Fix#10499
## Solution
- Use `.get_represented_type_info()` module path and type ident instead
of `.reflect_*` module path and type ident when serializing the `Option`
enum
---
## Changelog
- Fix serialization bug
- Add simple test
- Add `serde_json` dev dependency
- Add `serde` with `derive` feature dev dependency (wouldn't compile for
me without it)
---------
Co-authored-by: hank <hank@hank.co.in>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Explain https://github.com/bevyengine/bevy/issues/10625.
This might be obvious to those familiar with Bevy internals, but it
surprised me.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
I incorrectly assumed that moving a system from `Update` to
`FixedUpdate` would simplify logic without hurting performance.
But this is not the case: if there's single-threaded long computation in
the `FixedUpdate`, the machine won't do anything else in parallel with
it. Which might be not what users expect.
So this PR adds a note. But maybe it is obvious, I don't know.
# Objective
fix webgpu+chrome(119) textureSample in non-uniform control flow error
## Solution
modify view transmission texture sampling to use textureSampleLevel.
there are no mips for the view transmission texture, so this doesn't
change the result, but it removes the need for the samples to be in
uniform control flow.
note: in future we may add a mipchain to the transmission texture to
improve the blur effect. if uniformity analysis hasn't improved, this
would require switching to manual derivative calculations (which is
something we plan to do anyway).
## Objective
- Split different types of gizmos into their own files
## Solution
- Move `arc_2d` and `Arc2dBuilder` into `arcs.rs`
- turns out there's no 3d arc function! I'll add one Soon(TM) in another
MR
## Changelog
- Changed
- moved `gizmos::Arc2dBuilder` to `gizmos::arcs::Arc2dBuilder`
## Migration Guide
- `gizmos::Arc2dBuilder` -> `gizmos::arcs::Arc2dBuilder`
# Objective
Problems:
* The clipped, non-visible regions of UI nodes are interactive.
* `RelativeCursorPostion` is set relative to the visible part of the
node. It should be relative to the whole node.
* The `RelativeCursorPostion::mouse_over` method returns `true` when the
mouse is over a clipped part of a node.
fixes#10470
## Solution
Intersect a node's bounding rect with its clipping rect before checking
if it contains the cursor.
Added the field `normalized_visible_node_rect` to
`RelativeCursorPosition`. This is set to the bounds of the unclipped
area of the node rect by `ui_focus_system` expressed in normalized
coordinates relative to the entire node.
Instead of checking if the normalized cursor position lies within a unit
square, it instead checks if it is contained by
`normalized_visible_node_rect`.
Added outlines to the `overflow` example that appear when the cursor is
over the visible part of the images, but not the clipped area.
---
## Changelog
* `ui_focus_system` intersects a node's bounding rect with its clipping
rect before checking if mouse over.
* Added the field `normalized_visible_node_rect` to
`RelativeCursorPosition`. This is set to the bounds of the unclipped
area of the node rect by `ui_focus_system` expressed in normalized
coordinates relative to the entire node.
* `RelativeCursorPostion` is calculated relative to the whole node's
position and size, not only the visible part.
* `RelativeCursorPosition::mouse_over` only returns true when the mouse
is over an unclipped region of the UI node.
* Removed the `Deref` and `DerefMut` derives from
`RelativeCursorPosition` as it is no longer a single field struct.
* Added some outlines to the `overflow` example that respond to
`Interaction` changes.
## Migration Guide
The clipped areas of UI nodes are no longer interactive.
`RelativeCursorPostion` is now calculated relative to the whole node's
position and size, not only the visible part. Its `mouse_over` method
only returns true when the cursor is over an unclipped part of the node.
`RelativeCursorPosition` no longer implements `Deref` and `DerefMut`.
# Objective
- Fixes#10695
## Solution
Fixed obvious blunder in `PartialEq` implementation for
`UntypedAssetId`'s where the `TypeId` was not included in the
comparison. This was not picked up in the unit tests I added because
they only tested over a single asset type.
# Objective
- I've been experimenting with different patterns to try and make async
tasks more convenient. One of the better ones I've found is to return a
command queue to allow for deferred &mut World access. It can be
convenient to check for task completion in a normal system, but it is
hard to do something with the command queue after getting it back. This
pr adds a `append` to Commands. This allows appending the returned
command queue onto the system's commands.
## Solution
- I edited the async compute example to use the new `append`, but not
sure if I should keep the example changed as this might be too
opinionated.
## Future Work
- It would be very easy to pull the pattern used in the example out into
a plugin or a external crate, so users wouldn't have to add the checking
system.
---
## Changelog
- add `append` to `Commands` and `CommandQueue`
# Objective
Enables warning on `clippy::undocumented_unsafe_blocks` across the
workspace rather than only in `bevy_ecs`, `bevy_transform` and
`bevy_utils`. This adds a little awkwardness in a few areas of code that
have trivial safety or explain safety for multiple unsafe blocks with
one comment however automatically prevents these comments from being
missed.
## Solution
This adds `undocumented_unsafe_blocks = "warn"` to the workspace
`Cargo.toml` and fixes / adds a few missed safety comments. I also added
`#[allow(clippy::undocumented_unsafe_blocks)]` where the safety is
explained somewhere above.
There are a couple of safety comments I added I'm not 100% sure about in
`bevy_animation` and `bevy_render/src/view` and I'm not sure about the
use of `#[allow(clippy::undocumented_unsafe_blocks)]` compared to adding
comments like `// SAFETY: See above`.
# Objective
First, some terminology:
- **Minor radius**: The radius of the tube of a torus, i.e. the
"half-thickness"
- **Major radius**: The distance from the center of the tube to the
center of the torus
- **Inner radius**: The radius of the hole (if it exists), `major_radius
- minor_radius`
- **Outer radius**: The radius of the overall shape, `major_radius +
minor_radius`
- **Ring torus**: The familiar donut shape with a hole in the center,
`major_radius > minor_radius`
- **Horn torus**: A torus that doesn't have a hole but also isn't
self-intersecting, `major_radius == minor_radius`
- **Spindle torus**: A self-intersecting torus, `major_radius <
minor_radius`
Different tori from [Wikipedia](https://en.wikipedia.org/wiki/Torus),
where *R* is the major radius and *r* is the minor radius:
![kuva](https://github.com/bevyengine/bevy/assets/57632562/53ead786-2402-43a7-ae8a-5720e6e54dcc)
Currently, Bevy's torus is represented by a `radius` and `ring_radius`.
I believe these correspond to the outer radius and minor radius, but
they are rather confusing and inconsistent names, and they make the
assumption that the torus always has a ring.
I also couldn't find any other big engines using this representation;
[Godot](https://docs.godotengine.org/en/stable/classes/class_torusmesh.html)
and [Unity
ProBuilder](https://docs.unity3d.com/Packages/com.unity.probuilder@4.0/manual/Torus.html)
use the inner and outer radii, while
[Unreal](https://docs.unrealengine.com/5.3/en-US/BlueprintAPI/GeometryScript/Primitives/AppendTorus/)
uses the minor and major radii.
[Blender](https://docs.blender.org/manual/en/latest/modeling/meshes/primitives.html#torus)
supports both, but defaults to minor/major.
Bevy's `Torus` primitive should have an efficient, consistent, clear and
flexible representation, and the current `radius` and `ring_radius`
properties are not ideal for that.
## Solution
Change `Torus` to be represented by a `minor_radius` and `major_radius`.
- Mathematically correct and consistent
- Flexible, not restricted to ring tori
- Computations and conversions are efficient
- `inner_radius = major_radius - minor_radius`
- `outer_radius = major_radius + minor_radius`
- Mathematical formulae for things like area and volume rely on the
minor and major radii, no conversion needed
Perhaps the primary issue with this representation is that "minor
radius" and "major radius" are rather mathematical, and an inner/outer
radius can be more intuitive in some cases. However, this can be
mitigated with constructors and helpers.
# Objective
Make the impl block for RemovedSystem generic so that the methods can be
called for systems that have inputs or outputs.
## Solution
Simply adding generics to the impl block.
# Objective
Adds `.entry` to `EntityWorldMut` with `Entry`, `OccupiedEntry` and
`VacantEntry` for easier in-situ modification, based on `HashMap.entry`.
Fixes#10635
## Solution
This adds the `entry` method to `EntityWorldMut` which returns an
`Entry`. This is an enum of `OccupiedEntry` and `VacantEntry` and has
the methods `and_modify`, `insert_entry`, `or_insert`, `or_insert_with`
and `or_default`. The only difference between `OccupiedEntry` and
`VacantEntry` is the type, they are both a mutable reference to the
`EntityWorldMut` and a marker for the component type, `HashMap` also
stores things to make it quicker to access the data in `OccupiedEntry`
but I wasn't sure if we had anything it would be logical to store to
make accessing/modifying the component faster? As such, the differences
are that `OccupiedEntry` assumes the entity has the component (because
nothing else can have an `EntityWorldMut` so it can't be changed outside
the entry api) and has different methods.
All the methods are based very closely off `hashbrown::HashMap` (because
its easier to read the source of) with a couple of quirks like
`OccupiedEntry.insert` doesn't return the old value because we don't
appear to have an api for mem::replacing components.
---
## Changelog
- Added a new function `EntityWorldMut.entry` which returns an `Entry`,
allowing easier in-situ modification of a component.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
# Objective
- Fixes#10629
- `UntypedAssetId` and `AssetId` (along with `UntypedHandle` and
`Handle`) do not hash to the same values when pointing to the same
`Asset`. Additionally, comparison and conversion between these types
does not follow idiomatic Rust standards.
## Solution
- Added new unit tests to validate/document expected behaviour
- Added trait implementations to make working with Un/Typed values more
ergonomic
- Ensured hashing and comparison between Un/Typed values is consistent
- Removed `From` trait implementations that panic, and replaced them
with `TryFrom`
---
## Changelog
- Ensured `Handle::<A>::hash` and `UntypedHandle::hash` will produce the
same value for the same `Asset`
- Added non-panicing `Handle::<A>::try_typed`
- Added `PartialOrd` to `UntypedHandle` to match `Handle<A>` (this will
return `None` for `UntypedHandles` for differing `Asset` types)
- Added `TryFrom<UntypedHandle>` for `Handle<A>`
- Added `From<Handle<A>>` for `UntypedHandle`
- Removed panicing `From<Untyped...>` implementations. These are
currently unused within the Bevy codebase, and shouldn't be used
externally, hence removal.
- Added cross-implementations of `PartialEq` and `PartialOrd` for
`UntypedHandle` and `Handle<A>` allowing direct comparison when
`TypeId`'s match.
- Near-identical changes to `AssetId` and `UntypedAssetId`
## Migration Guide
If you relied on any of the panicing `From<Untyped...>` implementations,
simply call the existing `typed` methods instead. Alternatively, use the
new `TryFrom` implementation instead to directly expose possible
mistakes.
## Notes
I've made these changes since `Handle` is such a fundamental type to the
entire `Asset` ecosystem within Bevy, and yet it had pretty unclear
behaviour with no direct testing. The fact that hashing untyped vs typed
versions of the same handle would produce different values is something
I expect to cause a very subtle bug for someone else one day.
I haven't included it in this PR to avoid any controversy, but I also
believe the `typed_unchecked` methods should be removed from these
types, or marked as `unsafe`. The `texture_atlas` example currently uses
it, and I believe it is a bad choice. The performance gained by not
type-checking before conversion would be entirely dwarfed by the act of
actually loading an asset and creating its handle anyway. If an end user
is in a tight loop repeatedly calling `typed_unchecked` on an
`UntypedHandle` for the entire runtime of their application, I think the
small performance drop caused by that safety check is ~~a form of cosmic
justice~~ reasonable.
# Objective
- Standardize fmt for toml files
## Solution
- Add [taplo](https://taplo.tamasfe.dev/) to CI (check for fmt and diff
for toml files), for context taplo is used by the most popular extension
in VScode [Even Better
TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml
- Add contribution section to explain toml fmt with taplo.
Now to pass CI you need to run `taplo fmt --option indent_string=" "` or
if you use vscode have the `Even Better TOML` extension with 4 spaces
for indent
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
## Objective
- Give all the intuitive groups of gizmos their own file
- don't be a breaking change
- don't change Gizmos interface
- eventually do arcs too
- future types of gizmos should be in their own files
- see also https://github.com/bevyengine/bevy/issues/9400
## Solution
- Moved `gizmos.circle`, `gizmos.2d_circle`, and assorted helpers into
`circles.rs`
- Can also do arcs in this MR if y'all want; just figured I should do
one thing at a time.
## Changelog
- Changed
- `gizmos::CircleBuilder` moved to `gizmos::circles::Circle2dBuilder`
- `gizmos::Circle2dBuilder` moved to `gizmos::circles::Circle2dBuilder`
## Migration Guide
- change `gizmos::CircleBuilder` to `gizmos::circles::Circle2dBuilder`
- change `gizmos::Circle2dBuilder` to `gizmos::circles::Circle2dBuilder`
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
This PR adds some helpers for `Triangle2d` to work with its winding
order. This could also be extended to polygons (and `Triangle3d` once
it's added).
## Solution
- Add `WindingOrder` enum with `Clockwise`, `Counterclockwise` and
`Invalid` variants
- `Invalid` is for cases where the winding order can not be reliably
computed, i.e. the points lie on a single line and the area is zero
- Add `Triangle2d::winding_order` method that uses a signed surface area
to determine the winding order
- Add `Triangle2d::reverse` method that reverses the winding order by
swapping the second and third vertices
The API looks like this:
```rust
let mut triangle = Triangle2d::new(
Vec2::new(0.0, 2.0),
Vec2::new(-0.5, -1.2),
Vec2::new(-1.0, -1.0),
);
assert_eq!(triangle.winding_order(), WindingOrder::Clockwise);
// Reverse winding order
triangle.reverse();
assert_eq!(triangle.winding_order(), WindingOrder::Counterclockwise);
```
I also added tests to make sure the methods work correctly. For now,
they live in the same file as the primitives.
## Open questions
- Should it be `Counterclockwise` or `CounterClockwise`? The first one
is more correct but perhaps a bit less readable. Counter-clockwise is
also a valid spelling, but it seems to be a lot less common than
counterclockwise.
- Is `WindingOrder::Invalid` a good name? Parry uses
`TriangleOrientation::Degenerate`, but I'm not a huge fan, at least as a
non-native English speaker. Any better suggestions?
- Is `WindingOrder` fine in `bevy_math::primitives`? It's not specific
to a dimension, so I put it there for now.
# Objective
Fix the `bevy_asset/file_watcher` feature in practice depending on
multithreading, while not informing the user of it.
**As I understand it** (I didn't check it), the file watcher feature
depends on spawning a concurrent thread to receive file update events
from the `notify-debouncer-full` crate. But if multithreading is
disabled, that thread will never have time to read the events and
consume them.
- Fixes#10573
## Solution
Add a `compile_error!` causing compilation failure if `file_watcher` is
enabled while `multi-threaded` is disabled.
This is considered better than adding a dependency on `multi-threaded`
on the `file_watcher`, as (according to @mockersf) toggling on/off
`multi-threaded` has a non-zero chance of changing behavior. And we
shouldn't implicitly change behavior. A compilation failure prevents
compilation of code that is invalid, while informing the user of the
steps needed to fix it.
# Objective
- Sometimes it's very useful to know if a `Transform` contains any `NaN`
or infinite values. It's a bit boiler-plate heavy to check translation,
rotation and scale individually.
## Solution
- Add a new method `is_finite` that returns true if, and only if
translation, rotation and scale all are finite.
- It's a natural extension of `Quat::is_finite`, and `Vec3::is_finite`,
which return true if, and only if all their components' `is_finite()`
returns true.
---
## Changelog
- Added `Transform::is_finite`
# Objective
The `map_async` method involves a type `BufferAsyncError`:
https://docs.rs/bevy/latest/bevy/render/render_resource/struct.BufferSlice.html#method.map_async
This type is not re-exported in Bevy, so if a user wants to store a
struct involving this type they have to add wgpu manually to their
manifest.
## Solution
- Re-export wgpu::BufferAsyncError
---
## Changelog
### Added
- Re-export wgpu::BufferAsyncError
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
- Fix adding `#![allow(clippy::type_complexity)]` everywhere. like #9796
## Solution
- Use the new [lints] table that will land in 1.74
(https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#lints)
- inherit lint to the workspace, crates and examples.
```
[lints]
workspace = true
```
## Changelog
- Bump rust version to 1.74
- Enable lints table for the workspace
```toml
[workspace.lints.clippy]
type_complexity = "allow"
```
- Allow type complexity for all crates and examples
```toml
[lints]
workspace = true
```
---------
Co-authored-by: Martín Maita <47983254+mnmaita@users.noreply.github.com>
# Objective
- Follow up on https://github.com/bevyengine/bevy/pull/10519, diving
deeper into optimising `Entity` due to the `derive`d `PartialOrd`
`partial_cmp` not being optimal with codegen:
https://github.com/rust-lang/rust/issues/106107
- Fixes#2346.
## Solution
Given the previous PR's solution and the other existing LLVM codegen
bug, there seemed to be a potential further optimisation possible with
`Entity`. In exploring providing manual `PartialOrd` impl, it turned out
initially that the resulting codegen was not immediately better than the
derived version. However, once `Entity` was given `#[repr(align(8)]`,
the codegen improved remarkably, even more once the fields in `Entity`
were rearranged to correspond to a `u64` layout (Rust doesn't
automatically reorder fields correctly it seems). The field order and
`align(8)` additions also improved `to_bits` codegen to be a single
`mov` op. In turn, this led me to replace the previous
"non-shortcircuiting" impl of `PartialEq::eq` to use direct `to_bits`
comparison.
The result was remarkably better codegen across the board, even for
hastable lookups.
The current baseline codegen is as follows:
https://godbolt.org/z/zTW1h8PnY
Assuming the following example struct that mirrors with the existing
`Entity` definition:
```rust
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
pub struct FakeU64 {
high: u32,
low: u32,
}
```
the output for `to_bits` is as follows:
```
example::FakeU64::to_bits:
shl rdi, 32
mov eax, esi
or rax, rdi
ret
```
Changing the struct to:
```rust
#[derive(Clone, Copy, Eq)]
#[repr(align(8))]
pub struct FakeU64 {
low: u32,
high: u32,
}
```
and providing manual implementations for `PartialEq`/`PartialOrd`/`Ord`,
`to_bits` now optimises to:
```
example::FakeU64::to_bits:
mov rax, rdi
ret
```
The full codegen example for this PR is here for reference:
https://godbolt.org/z/n4Mjx165a
To highlight, `gt` comparison goes from
```
example::greater_than:
cmp edi, edx
jae .LBB3_2
xor eax, eax
ret
.LBB3_2:
setne dl
cmp esi, ecx
seta al
or al, dl
ret
```
to
```
example::greater_than:
cmp rdi, rsi
seta al
ret
```
As explained on Discord by @scottmcm :
>The root issue here, as far as I understand it, is that LLVM's
middle-end is inexplicably unwilling to merge loads if that would make
them under-aligned. It leaves that entirely up to its target-specific
back-end, and thus a bunch of the things that you'd expect it to do that
would fix this just don't happen.
## Benchmarks
Before discussing benchmarks, everything was tested on the following
specs:
AMD Ryzen 7950X 16C/32T CPU
64GB 5200 RAM
AMD RX7900XT 20GB Gfx card
Manjaro KDE on Wayland
I made use of the new entity hashing benchmarks to see how this PR would
improve things there. With the changes in place, I first did an
implementation keeping the existing "non shortcircuit" `PartialEq`
implementation in place, but with the alignment and field ordering
changes, which in the benchmark is the `ord_shortcircuit` column. The
`to_bits` `PartialEq` implementation is the `ord_to_bits` column. The
main_ord column is the current existing baseline from `main` branch.
![Screenshot_20231114_132908](https://github.com/bevyengine/bevy/assets/3116268/cb9090c9-ff74-4cc5-abae-8e4561332261)
My machine is not super set-up for benchmarking, so some results are
within noise, but there's not just a clear improvement between the
non-shortcircuiting implementation, but even further optimisation taking
place with the `to_bits` implementation.
On my machine, a fair number of the stress tests were not showing any
difference (indicating other bottlenecks), but I was able to get a clear
difference with `many_foxes` with a fox count of 10,000:
Test with `cargo run --example many_foxes --features
bevy/trace_tracy,wayland --release -- --count 10000`:
![Screenshot_20231114_144217](https://github.com/bevyengine/bevy/assets/3116268/89bdc21c-7209-43c8-85ae-efbf908bfed3)
On avg, a framerate of about 28-29FPS was improved to 30-32FPS. "This
trace" represents the current PR's perf, while "External trace"
represents the `main` branch baseline.
## Changelog
Changed: micro-optimized Entity align and field ordering as well as
providing manual `PartialOrd`/`Ord` impls to help LLVM optimise further.
## Migration Guide
Any `unsafe` code relying on field ordering of `Entity` or sufficiently
cursed shenanigans should change to reflect the different internal
representation and alignment requirements of `Entity`.
Co-authored-by: james7132 <contact@jamessliu.com>
Co-authored-by: NathanW <nathansward@comcast.net>
Bevy introduced unintentional breaking behaviour along with the v0.12.0
release regarding the `App::set_runner` API. See: #10385, #10389 for
details. We weren't able to catch this before release because this API
is only used internally in one or two places (the very places which
motivated the break).
This commit adds a regression test to help guarantee some expected
behaviour for custom runners, namely that `app::update` won't be called
before the runner has a chance to initialise state.
# Objective
There is no easy way to discard some amount for `Time<Fixed>`'s
overstep. This can be useful for online games when the client receives
information about a tick (which happens when you get a FPS drop or the
ping changes for example) it has not yet processed, it can discard
overstep equal to the number of ticks it can jump ahead.
Currently the workaround would be to create a new `Time<Fixed>` copy the
old timestep, advance it by the overstep amount that would remain after
subtracting the discarded amount, and using `.context_mut()` to
overwrite the old context with the new one. If you overwrite the whole
`Time<Fixed>` or forget to copy over the timestep you can introduce
undesirable side effects.
## Solution
Introduce a `discard_overstep` method, which discards the provided
amount of overstep. It uses satuarting_sub to avoid errors (negative
`Duration`s do not exist).
---
## Changelog
- Added `discard_overstep` function to `Time<Fixed>`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Allow bevy applications that does not have any assets folder to start
from a read-only directory. (typically installed to a systems folder)
Fixes#10613
## Solution
- warn instead of panic when assets folder creation fails.
# Objective
- Currently, in 0.12 there is an issue that it is not possible to build
bevy for Wasm with feature "file_watcher" enabled. It still would not
compile, but now with proper explanation.
- Fixes https://github.com/bevyengine/bevy/issues/10507
## Solution
- Remove `notify-debouncer-full` dependency on WASM platform entirely.
- Compile with "file_watcher" feature now on platform `wasm32` gives
meaningful compile error.
---
## Changelog
### Fixed
- Compile with "file_watcher" feature now on platform `wasm32` gives
meaningful compile error.
# Add and implement constructors for Primitives
- Adds more Primitive types and adds a constructor for almost all of
them
- Works towards finishing #10572
## Solution
- Created new primitives
- Torus
- Conical Frustum
- Cone
- Ellipse
- Implemented constructors (`Primitive::new`) for almost every single
other primitive.
---------
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Handy to have a constant instead of `VolumeLevel::new(0.0)`
- `VolumeLevel::new` is not `const`
## Solution
- Adds a `VolumeLevel::ZERO` constant, which we have for most of our
other types where it makes sense.
---
## Changelog
- Add `VolumeLevel::ZERO`
# Objective
The way `bevy_app` works was changed unnecessarily in #9826 whose
changes should have been specific to `bevy_winit`.
I'm somewhat disappointed that happened and we can see in
https://github.com/bevyengine/bevy/pull/10195 that it made things more
complicated.
Even worse, in #10385 it's clear that this breaks the clean abstraction
over another engine someone built with Bevy!
Fixes#10385.
## Solution
- Move the changes made to `bevy_app` in #9826 to `bevy_winit`
- Revert the changes to `ScheduleRunnerPlugin` and the `run_once` runner
in #10195 as they're no longer necessary.
While this code is breaking relative to `0.12.0`, it reverts the
behavior of `bevy_app` back to how it was in `0.11`.
Due to the nature of the breakage relative to `0.11` I hope this will be
considered for `0.12.1`.
# Objective
- Fix the panic on using Images in UiMaterials due to assets not being
loaded.
- Fixes#10513
## Solution
- add `let else` statement that `return`s or `continue`s instead of
unwrapping, causing a panic.
# Objective
- Fixes#10518
## Solution
I've added a method to `LoadContext`, `load_direct_with_reader`, which
mirrors the behaviour of `load_direct` with a single key difference: it
is provided with the `Reader` by the caller, rather than getting it from
the contained `AssetServer`. This allows for an `AssetLoader` to process
its `Reader` stream, and then directly hand the results off to the
`LoadContext` to handle further loading. The outer `AssetLoader` can
control how the `Reader` is interpreted by providing a relevant
`AssetPath`.
For example, a Gzip decompression loader could process the asset
`images/my_image.png.gz` by decompressing the bytes, then handing the
decompressed result to the `LoadContext` with the new path
`images/my_image.png.gz/my_image.png`. This intuitively reflects the
nature of contained assets, whilst avoiding unintended behaviour, since
the generated path cannot be a real file path (a file and folder of the
same name cannot coexist in most file-systems).
```rust
#[derive(Asset, TypePath)]
pub struct GzAsset {
pub uncompressed: ErasedLoadedAsset,
}
#[derive(Default)]
pub struct GzAssetLoader;
impl AssetLoader for GzAssetLoader {
type Asset = GzAsset;
type Settings = ();
type Error = GzAssetLoaderError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a (),
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
Box::pin(async move {
let compressed_path = load_context.path();
let file_name = compressed_path
.file_name()
.ok_or(GzAssetLoaderError::IndeterminateFilePath)?
.to_string_lossy();
let uncompressed_file_name = file_name
.strip_suffix(".gz")
.ok_or(GzAssetLoaderError::IndeterminateFilePath)?;
let contained_path = compressed_path.join(uncompressed_file_name);
let mut bytes_compressed = Vec::new();
reader.read_to_end(&mut bytes_compressed).await?;
let mut decoder = GzDecoder::new(bytes_compressed.as_slice());
let mut bytes_uncompressed = Vec::new();
decoder.read_to_end(&mut bytes_uncompressed)?;
// Now that we have decompressed the asset, let's pass it back to the
// context to continue loading
let mut reader = VecReader::new(bytes_uncompressed);
let uncompressed = load_context
.load_direct_with_reader(&mut reader, contained_path)
.await?;
Ok(GzAsset { uncompressed })
})
}
fn extensions(&self) -> &[&str] {
&["gz"]
}
}
```
Because this example is so prudent, I've included an
`asset_decompression` example which implements this exact behaviour:
```rust
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_asset::<GzAsset>()
.init_asset_loader::<GzAssetLoader>()
.add_systems(Startup, setup)
.add_systems(Update, decompress::<Image>)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
commands.spawn((
Compressed::<Image> {
compressed: asset_server.load("data/compressed_image.png.gz"),
..default()
},
Sprite::default(),
TransformBundle::default(),
VisibilityBundle::default(),
));
}
fn decompress<A: Asset>(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut compressed_assets: ResMut<Assets<GzAsset>>,
query: Query<(Entity, &Compressed<A>)>,
) {
for (entity, Compressed { compressed, .. }) in query.iter() {
let Some(GzAsset { uncompressed }) = compressed_assets.remove(compressed) else {
continue;
};
let uncompressed = uncompressed.take::<A>().unwrap();
commands
.entity(entity)
.remove::<Compressed<A>>()
.insert(asset_server.add(uncompressed));
}
}
```
A key limitation to this design is how to type the internally loaded
asset, since the example `GzAssetLoader` is unaware of the internal
asset type `A`. As such, in this example I store the contained asset as
an `ErasedLoadedAsset`, and leave it up to the consumer of the `GzAsset`
to handle typing the final result, which is the purpose of the
`decompress` system. This limitation can be worked around by providing
type information to the `GzAssetLoader`, such as `GzAssetLoader<Image,
ImageAssetLoader>`, but this would require registering the asset loader
for every possible decompression target.
Aside from this limitation, nested asset containerisation works as an
end user would expect; if the user registers a `TarAssetLoader`, and a
`GzAssetLoader`, then they can load assets with compound
containerisation, such as `images.tar.gz`.
---
## Changelog
- Added `LoadContext::load_direct_with_reader`
- Added `asset_decompression` example
## Notes
- While I believe my implementation of a Gzip asset loader is
reasonable, I haven't included it as a public feature of `bevy_asset` to
keep the scope of this PR as focussed as possible.
- I have included `flate2` as a `dev-dependency` for the example; it is
not included in the main dependency graph.
# Objective
Addresses #[10438](https://github.com/bevyengine/bevy/issues/10438)
The objective was to include the failing path in the error for the user
to see.
## Solution
Add a `path` field to the `ReadAssetBytesError::Io` variant to expose
the failing path in the error message.
## Migration Guide
- The `ReadAssetBytesError::Io` variant now contains two named fields
instead of converting from `std::io::Error`.
1. `path`: The requested (failing) path (`PathBuf`)
2. `source`: The source `std::io::Error`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fixes#10532
## Solution
I've updated the various `Event` send methods to return the sent
`EventId`(s). Since these methods previously returned nothing, and this
information is cheap to copy, there should be minimal negative
consequences to providing this additional information. In the case of
`send_batch`, an iterator is returned built from `Range` and `Map`,
which only consumes 16 bytes on the stack with no heap allocations for
all batch sizes. As such, the cost of this information is negligible.
These changes are reflected for `EventWriter` and `World`. For `World`,
the return types are optional to account for the possible lack of an
`Events` resource. Again, these methods previously returned no
information, so its inclusion should only be a benefit.
## Usage
Now when sending events, the IDs of those events is available for
immediate use:
```rust
// Example of a request-response system where the requester can track handled requests.
/// A system which can make and track requests
fn requester(
mut requests: EventWriter<Request>,
mut handled: EventReader<Handled>,
mut pending: Local<HashSet<EventId<Request>>>,
) {
// Check status of previous requests
for Handled(id) in handled.read() {
pending.remove(&id);
}
if !pending.is_empty() {
error!("Not all my requests were handled on the previous frame!");
pending.clear();
}
// Send a new request and remember its ID for later
let request_id = requests.send(Request::MyRequest { /* ... */ });
pending.insert(request_id);
}
/// A system which handles requests
fn responder(
mut requests: EventReader<Request>,
mut handled: EventWriter<Handled>,
) {
for (request, id) in requests.read_with_id() {
if handle(request).is_ok() {
handled.send(Handled(id));
}
}
}
```
In the above example, a `requester` system can send request events, and
keep track of which ones are currently pending by `EventId`. Then, a
`responder` system can act on that event, providing the ID as a
reference that the `requester` can use. Before this PR, it was not
trivial for a system sending events to keep track of events by ID. This
is unfortunate, since for a system reading events, it is trivial to
access the ID of a event.
---
## Changelog
- Updated `Events`:
- Added `send_batch`
- Modified `send` to return the sent `EventId`
- Modified `send_default` to return the sent `EventId`
- Updated `EventWriter`
- Modified `send_batch` to return all sent `EventId`s
- Modified `send` to return the sent `EventId`
- Modified `send_default` to return the sent `EventId`
- Updated `World`
- Modified `send_event` to return the sent `EventId` if sent, otherwise
`None`.
- Modified `send_event_default` to return the sent `EventId` if sent,
otherwise `None`.
- Modified `send_event_batch` to return all sent `EventId`s if sent,
otherwise `None`.
- Added unit test `test_send_events_ids` to ensure returned `EventId`s
match the sent `Event`s
- Updated uses of modified methods.
## Migration Guide
### `send` / `send_default` / `send_batch`
For the following methods:
- `Events::send`
- `Events::send_default`
- `Events::send_batch`
- `EventWriter::send`
- `EventWriter::send_default`
- `EventWriter::send_batch`
- `World::send_event`
- `World::send_event_default`
- `World::send_event_batch`
Ensure calls to these methods either handle the returned value, or
suppress the result with `;`.
```rust
// Now fails to compile due to mismatched return type
fn send_my_event(mut events: EventWriter<MyEvent>) {
events.send_default()
}
// Fix
fn send_my_event(mut events: EventWriter<MyEvent>) {
events.send_default();
}
```
This will most likely be noticed within `match` statements:
```rust
// Before
match is_pressed {
true => events.send(PlayerAction::Fire),
// ^--^ No longer returns ()
false => {}
}
// After
match is_pressed {
true => {
events.send(PlayerAction::Fire);
},
false => {}
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
Give us the ability to load untyped assets in AssetLoaders.
## Solution
Basically just copied the code from `load`, but used
`asset_server.load_untyped` instead internally.
## Changelog
Added `load_untyped` method to `LoadContext`
# Objective
- Implement a subset of
https://github.com/bevyengine/rfcs/blob/main/rfcs/12-primitive-shapes.md#feature-name-primitive-shapes
## Solution
- Define a very basic set of primitives in bevy_math
- Assume a 0,0,0 origin for most shapes
- Use radius and half extents to avoid unnecessary computational
overhead wherever they get used
- Provide both Boxed and const generics variants for shapes with
variable sizes
- Boxed is useful if a 3rd party crate wants to use something like
enum-dispatch for all supported primitives
- Const generics is useful when just working on a single primitive, as
it causes no allocs
#### Some discrepancies from the RFC:
- Box was changed to Cuboid, because Box is already used for an alloc
type
- Skipped Cone because it's unclear where the origin should be for
different uses
- Skipped Wedge because it's too niche for an initial PR (we also don't
implement Torus, Pyramid or a Death Star (there's an SDF for that!))
- Skipped Frustum because while it would be a useful math type, it's not
really a common primitive
- Skipped Triangle3d and Quad3d because those are just rotated 2D shapes
## Future steps
- Add more primitives
- Add helper methods to make primitives easier to construct (especially
when half extents are involved)
- Add methods to calculate AABBs for primitives (useful for physics, BVH
construction, for the mesh AABBs, etc)
- Add wrappers for common and cheap operations, like extruding 2D shapes
and translating them
- Use the primitives to generate meshes
- Provide signed distance functions and gradients for primitives (maybe)
---
## Changelog
- Added a collection of primitives to the bevy_math crate
---------
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
Closes#10319
## Changelog
* Added a new `Color::rgba_from_array([f32; 4]) -> Color` method.
* Added a new `Color::rgb_from_array([f32; 3]) -> Color` method.
* Added a new `Color::rgba_linear_from_array([f32; 4]) -> Color` method.
* Added a new `Color::rgb_linear_from_array([f32; 3]) -> Color` method.
* Added a new `Color::hsla_from_array([f32; 4]) -> Color` method.
* Added a new `Color::hsl_from_array([f32; 3]) -> Color` method.
* Added a new `Color::lcha_from_array([f32; 4]) -> Color` method.
* Added a new `Color::lch_from_array([f32; 3]) -> Color` method.
* Added a new `Color::rgba_to_vec4(&self) -> Vec4` method.
* Added a new `Color::rgba_to_array(&self) -> [f32; 4]` method.
* Added a new `Color::rgb_to_vec3(&self) -> Vec3` method.
* Added a new `Color::rgb_to_array(&self) -> [f32; 3]` method.
* Added a new `Color::rgba_linear_to_vec4(&self) -> Vec4` method.
* Added a new `Color::rgba_linear_to_array(&self) -> [f32; 4]` method.
* Added a new `Color::rgb_linear_to_vec3(&self) -> Vec3` method.
* Added a new `Color::rgb_linear_to_array(&self) -> [f32; 3]` method.
* Added a new `Color::hsla_to_vec4(&self) -> Vec4` method.
* Added a new `Color::hsla_to_array(&self) -> [f32; 4]` method.
* Added a new `Color::hsl_to_vec3(&self) -> Vec3` method.
* Added a new `Color::hsl_to_array(&self) -> [f32; 3]` method.
* Added a new `Color::lcha_to_vec4(&self) -> Vec4` method.
* Added a new `Color::lcha_to_array(&self) -> [f32; 4]` method.
* Added a new `Color::lch_to_vec3(&self) -> Vec3` method.
* Added a new `Color::lch_to_array(&self) -> [f32; 3]` method.
## Migration Guide
`Color::from(Vec4)` is now `Color::rgba_from_array(impl Into<[f32; 4]>)`
`Vec4::from(Color)` is now `Color::rgba_to_vec4(&self)`
Before:
```rust
let color_vec4 = Vec4::new(0.5, 0.5, 0.5);
let color_from_vec4 = Color::from(color_vec4);
let color_array = [0.5, 0.5, 0.5];
let color_from_array = Color::from(color_array);
```
After:
```rust
let color_vec4 = Vec4::new(0.5, 0.5, 0.5);
let color_from_vec4 = Color::rgba_from_array(color_vec4);
let color_array = [0.5, 0.5, 0.5];
let color_from_array = Color::rgba_from_array(color_array);
```
# Objective
Close#10504. Improve the development experience for working with scenes
by not requiring the user to specify a matching version of `ron` in
their `Cargo.toml`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- When compiling bevy for both singlethreaded and multithreaded contexts
and using `Task` directly, you can run into errors where you expect a
`Task` to be returned but `FakeTask` is instead. Due to `FakeTask` being
private the only solution is to ignore the return at all however because
it *is* returned that isn't totally clear. The error is confusing and
doesn't provide a solution or help figuring it out.
## Solution
- Made `FakeTask` public and added brief documentation providing a use
(none) that helps guide usage (no usage) of FakeTask.
In gamepad.rs, `ButtonSettings` `is_pressed` and `is_released` are both
private, but their implementations use publicly available values.
Keeping them private forces consumers to unnecessarily re-implement this
logic, so just make them public.
## Objective
- Add an arrow gizmo as suggested by #9400
## Solution
(excuse my Protomen music)
https://github.com/bevyengine/bevy/assets/14184826/192adf24-079f-4a4b-a17b-091e892974ec
Wasn't horribly hard when i remembered i can change coordinate systems
whenever I want. Gave them four tips (as suggested by @alice-i-cecile in
discord) instead of trying to decide what direction the tips should
point.
Made the tip length default to 1/10 of the arrow's length, which looked
good enough to me. Hard-coded the angle from the body to the tips to 45
degrees.
## Still TODO
- [x] actual doc comments
- [x] doctests
- [x] `ArrowBuilder.with_tip_length()`
---
## Changelog
- Added `gizmos.arrow()` and `gizmos.arrow_2d()`
- Added arrows to `2d_gizmos` and `3d_gizmos` examples
## Migration Guide
N/A
---------
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
Allows chained systems taking an `In<_>` input parameter to be run as
one-shot systems. This API was mentioned in #8963.
In addition, `run_system(_with_input)` returns the system output, for
any `'static` output type.
## Solution
A new function, `World::run_system_with_input` allows a `SystemId<I, O>`
to be run by providing an `I` value as input and producing `O` as an
output.
`SystemId<I, O>` is now generic over the input type `I` and output type
`O`, along with the related functions and types `RegisteredSystem`,
`RemovedSystem`, `register_system`, `remove_system`, and
`RegisteredSystemError`. These default to `()`, preserving the existing
API, for all of the public types.
---
## Changelog
- Added `World::run_system_with_input` function to allow one-shot
systems that take `In<_>` input parameters
- Changed `World::run_system` and `World::register_system` to support
systems with return types beyond `()`
- Added `Commands::run_system_with_input` command that schedules a
one-shot system with an `In<_>` input parameter
# Objective
- Ensure ExtendedMaterial can be referenced in bevy_egui_inspector
correctly
## Solution
Add a more manual `TypePath` implementation to work around bugs in the
derive macro.
# Objective
Make sure a camera which has had its render target changed recomputes
its info.
On main, the following is possible:
- System A has an inactive camera with render target set to the default
`Image` (i.e. white 1x1 rgba texture)
Later:
- System B sets the same camera active and sets the `camera.target` to a
newly created `Image`
**Bug**: Since `camera_system` only checks `Modified` and not `Added`
events, the size of the render target is not recomputed, which means the
camera will render with 1x1 size even though the new target is an
entirely different size.
## Solution
- Ensure `camera_system` checks `Added` image assets events
## Changelog
### Fixed
- Cameras which have their render targets changed to a newly created
target with a different size than the previous target will now render
properly
---------
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Afonso Lage <lage.afonso@gmail.com>
Fix a precision issue with in the manual near-clipping function.
This only affected lines that span large distances (starting at 100_000~
units) in my testing.
Fixes#10403
# Objective
- Reduce work from inactive cameras
Tracing was done on the `3d_shapes` example on PR
https://github.com/bevyengine/bevy/pull/10543 .
Doing tracing on a "real" application showed more instances of
unnecessary work.
## Solution
- Skip work on inactive cameras
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
The quality of Bevy's text rendering can vary wildly depending on the
font, font size, pixel alignment and scale factor.
But this situation can be improved dramatically with some small
adjustments.
## Solution
* Text node positions are rounded to the nearest physical pixel before
rendering.
* Each glyph texture has a 1-pixel wide transparent border added along
its edges.
This means font atlases will use more memory because of the extra pixel
of padding for each glyph but it's more than worth it I think (although
glyph size is increased by 2 pixels on both axes, the net increase is 1
pixel as the font texture atlas's padding has been removed).
## Results
Screenshots are from the 'ui' example with a scale factor of 1.5.
Things can get much uglier with the right font and worst scale
factor<sup>tm</sup>.
### before
<img width="300" alt="list-bad-text"
src="https://github.com/bevyengine/bevy/assets/27962798/482b384d-8743-4bae-9a65-468ff1b4c301">
### after
<img width="300" alt="good_list_text"
src="https://github.com/bevyengine/bevy/assets/27962798/34323b0a-f714-47ba-9728-a59804987bc8">
---
## Changelog
* Font texture atlases are no longer padded.
* Each glyph texture has a 1-pixel wide padding added along its edges.
* Text node positions are rounded to the nearest physical pixel before
rendering.
# Objective
Fixes#10436
Alternative to #10465
## Solution
`load_untyped_async` / `load_internal` currently has a bug. In
`load_untyped_async`, we pass None into `load_internal` for the
`UntypedHandle` of the labeled asset path. This results in a call to
`get_or_create_path_handle_untyped` with `loader.asset_type_id()`
This is a new code path that wasn't hit prior to the newly added
`load_untyped` because `load_untyped_async` was a private method only
used in the context of the `load_folder` impl (which doesn't have
labels)
The fix required some refactoring to catch that case and defer handle
retrieval. I have also made `load_untyped_async` public as it is now
"ready for public use" and unlocks new scenarios.
# Objective
Currently, if a large amount of inactive cameras are spawned, they will
immensely slow down performance.
This can be reproduced by adding
```rust
let default_image = images.add(default());
for _ in 0..10000 {
commands.spawn(Camera3dBundle {
camera: Camera {
is_active: false,
target: RenderTarget::Image(default_image.clone()),
..default()
},
..default()
});
}
```
to for example `3d_shapes`.
Using `tracy`, it's clear that preparing view bind groups for all
cameras is still happening.
Also, visibility checks on the extracted views from inactive cameras
also take place.
## Performance gains
The following `tracy` comparisons show the effect of skipping this
unneeded work.
Yellow is Bevy main, red is with the fix.
### Visibility checks
![bevy-visibility-check-savings](https://github.com/bevyengine/bevy/assets/52322338/154a20ce-bd70-487e-a85c-8b993950ea2b)
### Bind group preparation
![bevy-mesh2d-savings](https://github.com/bevyengine/bevy/assets/52322338/a48d8d9a-8c37-4c34-9698-b1b1bf01f070)
## Solution
- Check if the cameras are inactive in the appropriate places, and if so
skip them
## Changelog
### Changed
- Do not extract views from inactive cameras or check visiblity from
their extracted views
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
(This is my first PR here, so I've probably missed some things. Please
let me know what else I should do to help you as a reviewer!)
# Objective
Due to https://github.com/rust-lang/rust/issues/117800, the `derive`'d
`PartialEq::eq` on `Entity` isn't as good as it could be. Since that's
used in hashtable lookup, let's improve it.
## Solution
The derived `PartialEq::eq` short-circuits if the generation doesn't
match. However, having a branch there is sub-optimal, especially on
64-bit systems like x64 that could just load the whole `Entity` in one
load anyway.
Due to complications around `poison` in LLVM and the exact details of
what unsafe code is allowed to do with reference in Rust
(https://github.com/rust-lang/unsafe-code-guidelines/issues/346), LLVM
isn't allowed to completely remove the short-circuiting. `&Entity` is
marked `dereferencable(8)` so LLVM knows it's allowed to *load* all 8
bytes -- and does so -- but it has to assume that the `index` might be
undef/poison if the `generation` doesn't match, and thus while it finds
a way to do it without needing a branch, it has to do something slightly
more complicated than optimal to combine the results. (LLVM is allowed
to change non-short-circuiting code to use branches, but not the other
way around.)
Here's a link showing the codegen today:
<https://rust.godbolt.org/z/9WzjxrY7c>
```rust
#[no_mangle]
pub fn demo_eq_ref(a: &Entity, b: &Entity) -> bool {
a == b
}
```
ends up generating the following assembly:
```asm
demo_eq_ref:
movq xmm0, qword ptr [rdi]
movq xmm1, qword ptr [rsi]
pcmpeqd xmm1, xmm0
pshufd xmm0, xmm1, 80
movmskpd eax, xmm0
cmp eax, 3
sete al
ret
```
(It's usually not this bad in real uses after inlining and LTO, but it
makes a strong demo.)
This PR manually implements `PartialEq::eq` *without* short-circuiting,
and because that tells LLVM that neither the generations nor the index
can be poison, it doesn't need to be so careful and can generate the
"just compare the two 64-bit values" code you'd have probably already
expected:
```asm
demo_eq_ref:
mov rax, qword ptr [rsi]
cmp qword ptr [rdi], rax
sete al
ret
```
Since this doesn't change the representation of `Entity`, if it's
instead passed by *value*, then each `Entity` is two `u32` registers,
and the old and the new code do exactly the same thing. (Other
approaches, like changing `Entity` to be `[u32; 2]` or `u64`, affect
this case.)
This should hopefully merge easily with changes like
https://github.com/bevyengine/bevy/pull/9907 that also want to change
`Entity`.
## Benchmarks
I'm not super-confident that I got my machine fully consistent for
benchmarking, but whether I run the old or the new one first I get
reasonably consistent results.
Here's a fairly typical example of the benchmarks I added in this PR:
![image](https://github.com/bevyengine/bevy/assets/18526288/24226308-4616-4082-b0ff-88fc06285ef1)
Building the sets seems to be basically the same. It's usually reported
as noise, but sometimes I see a few percent slower or faster.
But lookup hits in particular -- since a hit checks that the key is
equal -- consistently shows around 10% improvement.
`cargo run --example many_cubes --features bevy/trace_tracy --release --
--benchmark` showed as slightly faster with this change, though if I had
to bet I'd probably say it's more noise than meaningful (but at least
it's not worse either):
![image](https://github.com/bevyengine/bevy/assets/18526288/58bb8c96-9c45-487f-a5ab-544bbfe9fba0)
This is my first PR here -- and my first time running Tracy -- so please
let me know what else I should run, or run things on your own more
reliable machines to double-check.
---
## Changelog
(probably not worth including)
Changed: micro-optimized `Entity::eq` to help LLVM slightly.
## Migration Guide
(I really hope nobody was using this on uninitialized entities where
sufficiently tortured `unsafe` could could technically notice that this
has changed.)
# Objective
After #9002, it seems that "single shot" animations were broken. When
completing, they would reset to their initial value. Which is generally
not what you want.
- Fixes#10480
## Solution
Avoid `%`-ing the animation after the number of completions exceeds the
specified one. Instead, we early-return. This is also true when the
player is playing in reverse.
---
## Changelog
- Avoid resetting animations after `Repeat::Never` animation completion.
# Objective
Fixes an issue where Bevy will look for `.meta` files in the root of the
server instead of `imported_assets/Default` on the web.
## Solution
`self.root_path.join` was seemingly forgotten in the `read_meta`
function on `HttpWasmAssetReader`, though it was included in the `read`
function. This PR simply adds the missing function call.
# Objective
* In Bevy 0.11 asset loaders used `anyhow::Error` for returning errors.
In Bevy 0.12 `AssetLoader` (and `AssetSaver`) have associated `Error`
type. Unfortunately it's type bounds does not allow `anyhow::Error` to
be used despite migration guide claiming otherwise. This makes migration
to 0.12 more challenging. Solve this by changing type bounds for
associated `Error` type.
* Fix#10350
## Solution
Change associated `Error` type bounds to require `Into<Box<dyn
std::error::Error + Send + Sync + 'static>>` to be implemented instead
of `std::error::Error + Send + Sync + 'static`. Both `anyhow::Error` and
errors generated by `thiserror` seems to be fine with such type bound.
---
## Changelog
### Fixed
* Fixed compatibility with `anyhow::Error` in `AssetLoader` and
`AssetSaver` associated `Error` type
# Objective
Fixes#10439
`Timer::percent()` and `Timer::percent_left()` return values in the
range of 0.0 to 1.0, even though their names contain "percent".
These functions should be renamed for clarity.
## Solution
- Rename `Timer::percent()` to `Timer::fraction()`
- Rename `Timer::percent_left()` to `Timer::fraction_remaining()`
---
## Changelog
### Changed
- Renamed `Timer::percent()` to `Timer::fraction()`
- Renamed `Timer::percent_left()` to `Timer::fraction_remaining()`
## Migration Guide
- `Timer::percent()` has been renamed to `Timer::fraction()`
- `Timer::percent_left()` has been renamed to
`Timer::fraction_remaining()`
# Objective
This is similar to #10439.
`Time::<Fixed>::overstep_percentage()` and
`Time::<Fixed>::overstep_percentage_f64()` returns values from 0.0 to
1.0, but their names use the word "percentage". These function names
make it easy to misunderstand that they return values from 0.0 to 100.0.
To avoid confusion, these functions should be renamed to
"`overstep_fraction(_f64)`".
## Solution
Rename them.
---
## Changelog
### Changed
- Renamed `Time::<Fixed>::overstep_percentage()` to
`Time::<Fixed>::overstep_fraction()`
- Renamed `Time::<Fixed>::overstep_percentage_f64()` to
`Time::<Fixed>::overstep_fraction_f64()`
## Migration Guide
- `Time::<Fixed>::overstep_percentage()` has been renamed to
`Time::<Fixed>::overstep_fraction()`
- `Time::<Fixed>::overstep_percentage_f64()` has been renamed to
`Time::<Fixed>::overstep_fraction_f64()`
# Objective
Hot reloading shader imports on windows is currently broken due to
inconsistent `/` and `\` usage ('/` is used in the user facing APIs and
`\` is produced by notify-rs (and likely other OS apis).
Fixes#10500
## Solution
Standardize import paths when loading a `Shader`. The correct long term
fix is to standardize AssetPath on `/`-only, but this is the right scope
of fix for a patch release.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- `CommandQueue::apply` calculates the address of the end of the
internal buffer as a `usize` rather than as a pointer, requiring two
casts of `cursor` to `usize`. Casting pointers to integers is generally
discouraged and may also prevent optimizations. It's also unnecessary
here.
## Solution
- Calculate the end address as a pointer rather than a `usize`.
Small note:
A trivial translation of the old code to use pointers would have
computed `end_addr` as `cursor.add(self.bytes.len())`, which is not
wrong but is an additional `unsafe` operation that also needs to be
properly documented and proven correct. However this operation is
already implemented in the form of the safe `as_mut_ptr_range`, so I
just used that.
# Objective
- The docs on `AssetPath::try_parse` say that it will return an error
when the string is malformed, but it actually just `.unwrap()`s the
result.
## Solution
- Use `?` instead of unwrapping the result.
# Objective
Calling `RenderDevice::poll` requires an instance of `wgpu::Maintain`,
but the type was not reexported by bevy. Working around it requires
adding a dependency on `wgpu`, since bevy does not reexport the `wgpu`
crate as a whole anywhere.
## Solution
Reexport `wgpu::Maintain` in `render_resource`, where the other wgpu
types are reexported.
# Objective
There is an if statement checking if a node is present in a graph
moments after it explicitly being added.
Unless the edge function has super weird side effects and the tests
don't pass, this is unnecessary.
## Solution
Removed it
# Objective
- Allow registration of one-shot systems when those systems have already
been `Box`ed.
- Needed for `bevy_eventlisteners` which allows adding event listeners
with callbacks in normal systems. The current one shot system
implementation requires systems be registered from an exclusive system,
and that those systems be passed in as types that implement
`IntoSystem`. However, the eventlistener callback crate allows users to
define their callbacks in normal systems, by boxing the system and
deferring initialization to an exclusive system.
## Solution
- Separate the registration of the system from the boxing of the system.
This is non-breaking, and adds a new method.
---
## Changelog
- Added `World::register_boxed_system` to allow registration of
already-boxed one shot systems.
# Objective
Had an issue where I had `VisibilityBundle` inside a bundle that
implements `Clone`, but since `VisibilityBundle` doesn't implement
`Clone` that wasn't possible. This PR fixes that.
## Solution
Implement `Clone` for `VisibilityBundle` by deriving it. And also
`SpatialBundle` too because why not.
---
## Changelog
- Added implementation for `Clone` on `VisibilityBundle` and
`SpatialBundle`.
# Objective
Fix a shader error that happens when using pbr morph targets.
## Solution
Fix the function name in the `prepass.wgsl` shader, which is incorrectly
prefixed with `morph::` (added in
61bad4eb57 (diff-97e4500f0a36bc6206d7b1490c8dd1a69459ee39dc6822eb9b2f7b160865f49fR42)).
This section of the shader is only enabled when using morph targets, so
it seems like there are no tests / examples using it?
# Objective
- Entities with both a `BackgroundColor` and a
`Handle<CustomUiMaterial>` are extracted by both pipelines and results
in entities being overwritten in the render world
- Fixes#10431
## Solution
- Ignore entities with `BackgroundColor` when extracting ui material
entities, and document that limit
# Objective
- There is a specialized hasher for entities:
[`EntityHashMap`](https://docs.rs/bevy/latest/bevy/utils/type.EntityHashMap.html)
- [`EntityMapper`] currently uses a normal `HashMap<Entity, Entity>`
- Fixes#10391
## Solution
- Replace the normal `HashMap` with the more performant `EntityHashMap`
## Questions
- This does change public API. Should a system be implemented to help
migrate code?
- Perhaps an `impl From<HashMap<K, V, S>> for EntityHashMap<K, V>`
- I updated to docs for each function that I changed, but I may have
missed something
---
## Changelog
- Changed `EntityMapper` to use `EntityHashMap` instead of normal
`HashMap`
## Migration Guide
If you are using the following types, update their listed methods to use
the new `EntityHashMap`. `EntityHashMap` has the same methods as the
normal `HashMap`, so you just need to replace the name.
### `EntityMapper`
- `get_map`
- `get_mut_map`
- `new`
- `world_scope`
### `ReflectMapEntities`
- `map_all_entities`
- `map_entities`
- `write_to_world`
### `InstanceInfo`
- `entity_map`
- This is a property, not a method.
---
This is my first time contributing in a while, and I'm not familiar with
the usage of `EntityMapper`. I changed the type definition and fixed all
errors, but there may have been things I've missed. Please keep an eye
out for me!
Preparing next release
This PR has been auto-generated
---------
Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: François <mockersf@gmail.com>
# Objective
- Fixes#10209
- Assets should work in single threaded
## Solution
- In single threaded mode, don't use `async_fs` but fallback on
`std::fs` with a thin layer to mimic the async API
- file `file_asset.rs` is the async imps from `mod.rs`
- file `sync_file_asset.rs` is the same with `async_fs` APIs replaced by
`std::fs`
- which module is used depends on the `multi-threaded` feature
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Fixes a small typo in `bevy_window/src/window.rs`
## Solution
Change `Should be used instead 'scale_factor' when set.` to `Should be
used instead of 'scale_factor' when set.`
# Objective
- Adopt #10239 to get it in time for the release
- Fix accessibility on macOS and linux
## Solution
- call `on_event` from AcccessKit adapter on winit events
---------
Co-authored-by: Nolan Darilek <nolan@thewordnerd.info>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Changes the default clear color to match the code block color on
Bevy's website.
## Solution
- Changed the clear color, updated text in examples to ensure adequate
contrast. Inconsistent usage of white text color set to use the default
color instead, which is already white.
- Additionally, updated the `3d_scene` example to make it look a bit
better, and use bevy's branding colors.
![image](https://github.com/bevyengine/bevy/assets/2632925/540a22c0-826c-4c33-89aa-34905e3e313a)
# Objective
Fixes https://github.com/bevyengine/bevy/issues/9077 (see this issue for
motivations)
## Solution
Implement 1 and 2 of the "How to fix it" section of
https://github.com/bevyengine/bevy/issues/9077
`update_directional_light_cascades` is split into
`clear_directional_light_cascades` and a generic
`build_directional_light_cascades`, to clear once and potentially insert
many times.
---
## Changelog
`DirectionalLight`'s computation is now generic over `CameraProjection`
and can work with custom camera projections.
## Migration Guide
If you have a component `MyCustomProjection` that implements
`CameraProjection`:
- You need to implement a new required associated method,
`get_frustum_corners`, returning an array of the corners of a subset of
the frustum with given `z_near` and `z_far`, in local camera space.
- You can now add the
`build_directional_light_cascades::<MyCustomProjection>` system in
`SimulationLightSystems::UpdateDirectionalLightCascades` after
`clear_directional_light_cascades` for your projection to work with
directional lights.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Bevy's default bias values for directional and spot lights currently
cause significant artifacts. We should fix that so shadows look good by
default!
This is a less controversial/invasive alternative to #10188, which might
enable us to keep the default bias value low, but also has its own sets
of concerns and caveats that make it a risky choice for Bevy 0.12.
## Solution
Bump the default normal bias from `0.6` to `1.8`. There is precedent for
values in this general area as Godot has a default normal bias of `2.0`.
### Before
![image](https://github.com/superdump/bevy/assets/2694663/a5828011-33fc-4427-90ed-f093d7389053)
### After
![image](https://github.com/bevyengine/bevy/assets/2694663/0f2b16b0-c116-41ab-9886-1ace9e00efd6)
## Migration Guide
The default `shadow_normal_bias` value for `DirectionalLight` and
`SpotLight` has changed to accommodate artifacts introduced with the new
shadow PCF changes. It is unlikely (especially given the new PCF shadow
behaviors with these values), but you might need to manually tweak this
value if your scene requires a lower bias and it relied on the previous
default value.
# Objective
Reimplement #8793 on top of the recent rendering changes.
## Solution
The batch creation logic is quite convoluted, but I tested it on enough
examples to convince myself that it works.
The initial value of `batch_image_handle` is changed from
`HandleId::Id(Uuid::nil(), u64::MAX)` to `DEFAULT_IMAGE_HANDLE.id()`,
which allowed me to make the if-block simpler I think.
The default image from `DEFAULT_IMAGE_HANDLE` is always inserted into
`UiImageBindGroups` even if it's not used. I tried to add a check so
that it would be only inserted when there is only one batch using the
default image but this crashed.
---
## Changelog
`prepare_uinodes`
* Changed the initial value of `batch_image_handle` to
`DEFAULT_IMAGE_HANDLE.id()`.
* The default image is added to the UI image bind groups before
assembling the batches.
* A new `UiBatch` isn't created when the next `ExtractedUiNode`s image
is set to `DEFAULT_IMAGE_HANDLE` (unless it is the first item in the UI
phase items list).
# Objective
fix crash / misbehaviour when `DeferredPrepass` is used without
`DepthPrepass`.
- Deferred lighting requires the depth prepass texture to be present, so
that the depth texture is available for binding. without it the deferred
lighting pass will use 0 for depth of all meshes.
- When `DeferredPrepass` is used without other prepass markers, and with
any materials that use `OpaqueRenderMode::Forward`, those entities will
try to queue to the `Opaque3dPrepass` render phase, which doesn't exist,
causing a crash.
## Solution
- check if the prepass phases exist before queueing
- generate prepass textures if `Opaque3dDeferred` is present
- add a note to the DeferredPrepass marker to note that DepthPrepass is
also required by the default deferred lighting pass
- also changed some `With<T>.is_some()`s to `Has<T>`s
# Objective
I was working with forward rendering prepass fragment shaders and ran
into an issue of not being able to access vertex colors in the prepass.
I was able to access vertex colors in regular fragment shaders as well
as in deferred shaders.
## Solution
It seems like this `if` was nested unintentionally as moving it outside
of the `deferred` block works.
---
## Changelog
Enable vertex colors in forward rendering prepass fragment shaders
# Objective
Alternative to #7310
## Solution
Implemented the suggestion from
https://github.com/bevyengine/bevy/pull/7310#discussion_r1083356655
I am guessing that these were originally split as an optimization, but I
am not sure since I believe the original author of the code is the one
speculating about combining them up there.
## Benchmarks
I ran three benchmarks to compare main, this PR, and the approach from
#7310
([updated](https://github.com/rparrett/bevy/commits/rebased-parallel-check-visibility)
to the same commit on main).
This seems to perform slightly better than main in scenarios where most
entities have AABBs, and a bit worse when they don't (`many_lights`).
That seems to make sense to me.
Either way, the difference is ~-20 microseconds in the more common
scenarios or ~+100 microseconds in the less common scenario. I would
speculate that this might perform **very slightly** worse in
single-threaded scenarios.
Benches were run in release mode for 2000 frames while capturing a trace
with tracy.
| bench | commit | check_visibility_system mean μs |
| -- | -- | -- |
| many_cubes | main | 929.5 |
| many_cubes | this | 914.0 |
| many_cubes | 7310 | 1003.5 |
| | |
| many_foxes | main | 191.6 |
| many_foxes | this | 173.2 |
| many_foxes | 7310 | 167.9 |
| | |
| many_lights | main | 619.3 |
| many_lights | this | 703.7 |
| many_lights | 7310 | 842.5 |
## Notes
Technically this behaves slightly differently -- prior to this PR, view
visibility was determined even for entities without `GlobalTransform`. I
don't think this has any practical impact though.
IMO, I don't think we need to do this. But I opened a PR because it
seemed like the handiest way to share the code / benchmarks.
## TODO
I have done some rudimentary testing with the examples above, but I can
do some screenshot diffing if it seems like we want to do this.
# Objective
- Revert #10296
## Solution
- Avoid implementing `Display` without a justification
- `Display` implementation is a guarantee without a direct use, takes
additional time to compile and require work to maintain
- `Debug`, `Reflect` or `Serialize` should cover all needs
# Objective
The `BuildWorldChildren` API was missing several methods that exist in
`BuildChildren`.
## Solution
Added the methods (and tests) for consistency.
# Objective
If we add the stack index to `Node` then we don't need to walk the
`UiStack` repeatedly during extraction.
## Solution
Add a field `stack_index` to `Node`.
Update it in `ui_stack_system`.
Iterate queries directly in the UI's extraction systems.
### Benchmarks
```
cargo run --profile stress-test --features trace_tracy --example many_buttons -- --no-text --no-borders
```
frames (yellow this PR, red main):
<img width="447" alt="frames-per-second"
src="https://github.com/bevyengine/bevy/assets/27962798/385c0ccf-c257-42a2-b736-117542d56eff">
`ui_stack_system`:
<img width="585" alt="ui-stack-system"
src="https://github.com/bevyengine/bevy/assets/27962798/2916cc44-2887-4c3b-a144-13250d84f7d5">
extract schedule:
<img width="469" alt="extract-schedule"
src="https://github.com/bevyengine/bevy/assets/27962798/858d4ab4-d99f-48e8-b153-1c92f51e0743">
---
## Changelog
* Added the field `stack_index` to `Node`.
* `ui_stack_system` updates `Node::stack_index` after a new `UiStack` is
generated.
* The UI's extraction functions iterate a query directly rather than
walking the `UiStack` and doing lookups.
# Objective
<img width="1920" alt="Screenshot 2023-04-26 at 01 07 34"
src="https://user-images.githubusercontent.com/418473/234467578-0f34187b-5863-4ea1-88e9-7a6bb8ce8da3.png">
This PR adds both diffuse and specular light transmission capabilities
to the `StandardMaterial`, with support for screen space refractions.
This enables realistically representing a wide range of real-world
materials, such as:
- Glass; (Including frosted glass)
- Transparent and translucent plastics;
- Various liquids and gels;
- Gemstones;
- Marble;
- Wax;
- Paper;
- Leaves;
- Porcelain.
Unlike existing support for transparency, light transmission does not
rely on fixed function alpha blending, and therefore works with both
`AlphaMode::Opaque` and `AlphaMode::Mask` materials.
## Solution
- Introduces a number of transmission related fields in the
`StandardMaterial`;
- For specular transmission:
- Adds logic to take a view main texture snapshot after the opaque
phase; (in order to perform screen space refractions)
- Introduces a new `Transmissive3d` phase to the renderer, to which all
meshes with `transmission > 0.0` materials are sent.
- Calculates a light exit point (of the approximate mesh volume) using
`ior` and `thickness` properties
- Samples the snapshot texture with an adaptive number of taps across a
`roughness`-controlled radius enabling “blurry” refractions
- For diffuse transmission:
- Approximates transmitted diffuse light by using a second, flipped +
displaced, diffuse-only Lambertian lobe for each light source.
## To Do
- [x] Figure out where `fresnel_mix()` is taking place, if at all, and
where `dielectric_specular` is being calculated, if at all, and update
them to use the `ior` value (Not a blocker, just a nice-to-have for more
correct BSDF)
- To the _best of my knowledge, this is now taking place, after
964340cdd. The fresnel mix is actually "split" into two parts in our
implementation, one `(1 - fresnel(...))` in the transmission, and
`fresnel()` in the light implementations. A surface with more
reflectance now will produce slightly dimmer transmission towards the
grazing angle, as more of the light gets reflected.
- [x] Add `transmission_texture`
- [x] Add `diffuse_transmission_texture`
- [x] Add `thickness_texture`
- [x] Add `attenuation_distance` and `attenuation_color`
- [x] Connect values to glTF loader
- [x] `transmission` and `transmission_texture`
- [x] `thickness` and `thickness_texture`
- [x] `ior`
- [ ] `diffuse_transmission` and `diffuse_transmission_texture` (needs
upstream support in `gltf` crate, not a blocker)
- [x] Add support for multiple screen space refraction “steps”
- [x] Conditionally create no transmission snapshot texture at all if
`steps == 0`
- [x] Conditionally enable/disable screen space refraction transmission
snapshots
- [x] Read from depth pre-pass to prevent refracting pixels in front of
the light exit point
- [x] Use `interleaved_gradient_noise()` function for sampling blur in a
way that benefits from TAA
- [x] Drill down a TAA `#define`, tweak some aspects of the effect
conditionally based on it
- [x] Remove const array that's crashing under HLSL (unless a new `naga`
release with https://github.com/gfx-rs/naga/pull/2496 comes out before
we merge this)
- [ ] Look into alternatives to the `switch` hack for dynamically
indexing the const array (might not be needed, compilers seem to be
decent at expanding it)
- [ ] Add pipeline keys for gating transmission (do we really want/need
this?)
- [x] Tweak some material field/function names?
## A Note on Texture Packing
_This was originally added as a comment to the
`specular_transmission_texture`, `thickness_texture` and
`diffuse_transmission_texture` documentation, I removed it since it was
more confusing than helpful, and will likely be made redundant/will need
to be updated once we have a better infrastructure for preprocessing
assets_
Due to how channels are mapped, you can more efficiently use a single
shared texture image
for configuring the following:
- R - `specular_transmission_texture`
- G - `thickness_texture`
- B - _unused_
- A - `diffuse_transmission_texture`
The `KHR_materials_diffuse_transmission` glTF extension also defines a
`diffuseTransmissionColorTexture`,
that _we don't currently support_. One might choose to pack the
intensity and color textures together,
using RGB for the color and A for the intensity, in which case this
packing advice doesn't really apply.
---
## Changelog
- Added a new `Transmissive3d` render phase for rendering specular
transmissive materials with screen space refractions
- Added rendering support for transmitted environment map light on the
`StandardMaterial` as a fallback for screen space refractions
- Added `diffuse_transmission`, `specular_transmission`, `thickness`,
`ior`, `attenuation_distance` and `attenuation_color` to the
`StandardMaterial`
- Added `diffuse_transmission_texture`, `specular_transmission_texture`,
`thickness_texture` to the `StandardMaterial`, gated behind a new
`pbr_transmission_textures` cargo feature (off by default, for maximum
hardware compatibility)
- Added `Camera3d::screen_space_specular_transmission_steps` for
controlling the number of “layers of transparency” rendered for
transmissive objects
- Added a `TransmittedShadowReceiver` component for enabling shadows in
(diffusely) transmitted light. (disabled by default, as it requires
carefully setting up the `thickness` to avoid self-shadow artifacts)
- Added support for the `KHR_materials_transmission`,
`KHR_materials_ior` and `KHR_materials_volume` glTF extensions
- Renamed items related to temporal jitter for greater consistency
## Migration Guide
- `SsaoPipelineKey::temporal_noise` has been renamed to
`SsaoPipelineKey::temporal_jitter`
- The `TAA` shader def (controlled by the presence of the
`TemporalAntiAliasSettings` component in the camera) has been replaced
with the `TEMPORAL_JITTER` shader def (controlled by the presence of the
`TemporalJitter` component in the camera)
- `MeshPipelineKey::TAA` has been replaced by
`MeshPipelineKey::TEMPORAL_JITTER`
- The `TEMPORAL_NOISE` shader def has been consolidated with
`TEMPORAL_JITTER`
# Objective
- We need to check multiple times if a color is fully transparent, e.g.
for performance optimizations.
- Make code more readable.
- Reduce code duplication, to simplify making changes if needed (e.g. if
we need to take floating point weirdness into account later on).
## Solution
- Introduce a new `Color::is_fully_transparent` helper function to
determine if the alpha of a color is 0.
- Use the helper function in our UI rendering code.
---
## Changelog
- Added `Color::is_fully_transparent` helper function.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
Right now, we flip the `world_normal` in response to `double_sided &&
!is_front`, however when calculating `N` from tangents and the normal
map, we don't flip the normal read from the normal map, which produces
extremely weird results.
## Solution
- Pass `double_sided` and `is_front` flags to the
`apply_normal_mapping()` function and use them to conditionally flip
`Nt`
## Comparison
Note: These are from a custom scene running with the `transmission`
branch, (#8015) I noticed lighting got pretty weird for the back side of
translucent `double_sided` materials whenever I added a normal map.
### Before
<img width="1392" alt="Screenshot 2023-10-31 at 01 26 06"
src="https://github.com/bevyengine/bevy/assets/418473/d5f8c9c3-aca1-4c2f-854d-f0d0fd2fb19a">
### After
<img width="1392" alt="Screenshot 2023-10-31 at 01 25 42"
src="https://github.com/bevyengine/bevy/assets/418473/fa0e1aa2-19ad-4c27-bb08-37299d97971c">
---
## Changelog
- Fixed a bug where `StandardMaterial::double_sided` would interact
incorrectly with normal maps, producing broken results.
# Objective
- Work towards GPU-driven culling
(https://github.com/bevyengine/bevy/pull/10164)
## Solution
- Pass the view frustum to the shader view uniform
---
## Changelog
- View Frustums are now extracted to the render world and made available
to shaders
# Objective
- Address inconsistent term usage in the docs for the alignment
properties for UI nodes. Fixes#10218
- `JustifyContent::Stretch` is missing despite being supported by Taffy,
being as the default value for Grids, so it should be added to Bevy as
well
## Solution
- Consistently provide links to the mdn site for the css equivalent
- Match (mostly) the documentation given on the pub struct and the
underlying enums
- Use the term `items` consistently to refer each child in the container
- Add `JustifyContent::Stretch` and map it to Taffy
## Migration Guide
- The `JustifyContents` enum has been expanded to include
`JustifyContents::Stretch`.
# Objective
Align all error-like types to implement `Error`.
Fixes #10176
## Solution
- Derive `Error` on more types
- Refactor instances of manual implementations that could be derived
This adds thiserror as a dependency to bevy_transform, which might
increase compilation time -- but I don't know of any situation where you
might only use that but not any other crate that pulls in bevy_utils.
The `contributors` example has a `LoadContributorsError` type, but as
it's an example I have not updated it. Doing that would mean either
having a `use bevy_internal::utils::thiserror::Error;` in an example
file, or adding `thiserror` as a dev-dependency to the main `bevy`
crate.
---
## Changelog
- All `…Error` types now implement the `Error` trait
Existing truncation code limits the number of attribute buffers to be
less than or equal to the number of vertices.
Instead the number of elements from each attribute buffer should be
limited to the length of the shortest buffer as mentioned in the earlier
warning.
# Objective
- Fixes#10267
## Solution
- Moves the `.take()` from the outer loop of attribute buffers, to the
inner loop of attribute values.
---
# Objective
`normalize` method that expresses a rectangle relative to a normalized
[0..1] x [0..1] space defined by another rectangle.
Useful for UI and texture atlas calculations etc.
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
- When finding the `CursorIcon` doc, it should be easier to find out
where to use it.
- When saying it is partially copied from the browser, be more clear
about the provenance and link to the spec document.
## Solution
- Link to the example code.
- Link to the CSS3 UI spec document.
Extracted the easy stuff from #8974 .
# Problem
1. Commands from `update_previous_view_projections` would crash when
matching entities were despawned.
2. `TaaPipelineId` and `draw_3d_graph` module were not public.
3. When the motion vectors pointed to pixels that are now off screen, a
smearing artifact could occur.
# Solution
1. Use `try_insert` command instead.
2. Make them public, renaming to `TemporalAntiAliasPipelineId`.
3. Check for this case, and ignore history for pixels that are
off-screen.
# Objective
- Remove special cases where `clippy::doc_markdown` lint is disabled.
## Solution
- Add default values back into `clippy.toml` by adding `".."` to the
list of `doc-valid-idents`.
- Add `"VSync"` and `"WebGL2"` to the list of `doc-valid-idents`.
- Remove all instances where `clippy::doc_markdown` is allowed.
- Fix `max_mip` formatting so that there isn't a warning.
# Objective
- Have more docs for `bevy_text` to avoid reading the source code for
some things.
## Solution
- Add some additional docs.
## Changelog
- `TextSettings.max_font_atlases` in `bevy_text` has been renamed to `
TextSettings.soft_max_font_atlases`.
## Migration Guide
- Usages of `TextSettings.max_font_atlases` from `bevy_text` must be
changed to `TextSettings.soft_max_font_atlases`.
# Situation
- In case of parent without visibility components, the visibility
inheritance of children creates a panic.
## Solution
- Apply same fallback visibility as parent not found instead of panic.
# Objective
Make it obvious why stuff renders pink when rendering stuff with bevy
with `default_features = false` and bevy's default tonemapper
(TonyMcMapFace, it requires a LUT which requires the `tonemapping_luts`,
`ktx2`, and `zstd` features).
Not sure if this should be considered as fixing these issues, but in my
previous PR (https://github.com/bevyengine/bevy/pull/9073, and old
discussions on discord that I only somewhat remember) it seemed like we
didn't want to make ktx2 and zstd required features for
bevy_core_pipeline.
Related https://github.com/bevyengine/bevy/issues/9179
Related https://github.com/bevyengine/bevy/issues/9098
## Solution
This logs an error when a LUT based tonemapper is used without the
`tonemapping_luts` feature enabled, and cleans up the default features a
bit (`tonemapping_luts` now includes the `ktx2` and `zstd` features,
since it panics without them).
Another solution would be to fall back to a non-lut based tonemapper,
but I don't like this solution as then it's not explicitly clear to
users why eg. a library example renders differently than a normal bevy
app (if the library forgot the `tonemapping_luts` feature).
I did remove the `ktx2` and `zstd` features from the list of default
features in Cargo.toml, as I don't believe anything else currently in
bevy relies on them (or at least searching through every hit for `ktx2`
and `zstd` didn't show anything except loading an environment map in
some examples), and they still show up in the `cargo_features` doc as
default features.
---
## Changelog
- The `tonemapping_luts` feature now includes both the `ktx2` and `zstd`
features to avoid a panic when the `tonemapping_luts` feature was enable
without both the `ktx2` and `zstd` feature enabled.
# Objective
- `deferred_rendering` and `load_gltf` fail in WebGPU builds due to
textureSample() being called on the diffuse environment map texture
after non-uniform control flow
## Solution
- The diffuse environment map texture only has one mip, so use
`textureSampleLevel(..., 0.0)` to sample that mip and not require UV
gradient calculation.
# Objective
- Build on the changes in https://github.com/bevyengine/bevy/pull/9982
- Use `ImageSamplerDescriptor` as the "public image sampler descriptor"
interface in all places (for consistency)
- Make it possible to configure textures to use the "default" sampler
(as configured in the `DefaultImageSampler` resource)
- Fix a bug introduced in #9982 that prevents configured samplers from
being used in Basis, KTX2, and DDS textures
---
## Migration Guide
- When using the `Image` API, use `ImageSamplerDescriptor` instead of
`wgpu::SamplerDescriptor`
- If writing custom wgpu renderer features that work with `Image`, call
`&image_sampler.as_wgpu()` to convert to a wgpu descriptor.
# Objective
- Folder handles are not shared. Loading the same folder multiple times
will result in different handles.
- Once folder handles are shared, they can no longer be manually
reloaded, so we should add support for hot-reloading them
## Solution
- Reuse folder handles based on their path
- Trigger a reload of a folder if a file contained in it (or a sub
folder) is added or removed
- This also covers adding/removing/moving sub folders containing files
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Assets v2 does not currently offer a public API to load untyped assets
## Solution
- Wrap the untyped handle in a `LoadedUntypedAsset` asset to offer a
non-blocking load for untyped assets. The user does not need to know the
actual asset type.
- Handles to `LoadedUntypedAsset` have the same path as the wrapped
asset, but their handles are shared using a label.
The user side of `load_untyped` looks like this:
```rust
use bevy::prelude::*;
use bevy_internal::asset::LoadedUntypedAsset;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, check)
.run();
}
#[derive(Resource)]
struct UntypedAsset {
handle: Handle<LoadedUntypedAsset>,
}
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
) {
let handle = asset_server.load_untyped("branding/banner.png");
commands.insert_resource(UntypedAsset { handle });
commands.spawn(Camera2dBundle::default());
}
fn check(
mut commands: Commands,
res: Option<Res<UntypedAsset>>,
assets: Res<Assets<LoadedUntypedAsset>>,
) {
if let Some(untyped_asset) = res {
if let Some(asset) = assets.get(&untyped_asset.handle) {
commands.spawn(SpriteBundle {
texture: asset.handle.clone().typed(),
..default()
});
commands.remove_resource::<UntypedAsset>();
}
}
}
```
---
## Changelog
- `load_untyped` on the asset server now returns a handle to a
`LoadedUntypedAsset` instead of an untyped handle to the asset at the
given path. The untyped handle for the given path can be retrieved from
the `LoadedUntypedAsset` once it is done loading.
## Migration Guide
Whenever possible use the typed API in order to directly get a handle to
your asset. If you do not know the type or need to use `load_untyped`
for a different reason, Bevy 0.12 introduces an additional layer of
indirection. The asset server will return a handle to a
`LoadedUntypedAsset`, which will load in the background. Once it is
loaded, the untyped handle to the asset file can be retrieved from the
`LoadedUntypedAsset`s field `handle`.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Fixes#9395
Alternative to #9415 (See discussion here)
## Solution
Do clamping like
[`fit-content`](https://www.w3.org/TR/css-sizing-3/#column-sizing).
## Notes
I am not sure if this is a valid approach. It doesn't seem to cause any
obvious issues with our existing examples.
# Objective
- Hot reloading doesn't work the first time it is used
## Solution
- Currently, Bevy processor:
1. Create the `imported_assets` folder
2. Setup a watcher on it
3. Clear empty folders, so the `imported_assets` folder is deleted
4. Recreate the `imported_assets` folder and add all the imported assets
- On a first run without an existing `imported_assets` with some
content, hot reloading won't work as step 3 breaks the file watcher
- This PR stops the empty root folder from being deleted
- Also don't setup the processor internal asset server for file
watching, freeing up a thread
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Fixes#9473
## Solution
Added `resolve()` method to AssetPath. This method accepts a relative
asset path string and returns a "full" path that has been resolved
relative to the current (self) path.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
First of all, this PR took heavy inspiration from #7760 and #5715. It
intends to also fix#5569, but with a slightly different approach.
This also fixes#9335 by reexporting `DynEq`.
## Solution
The advantage of this API is that we can intern a value without
allocating for zero-sized-types and for enum variants that have no
fields. This PR does this automatically in the `SystemSet` and
`ScheduleLabel` derive macros for unit structs and fieldless enum
variants. So this should cover many internal and external use cases of
`SystemSet` and `ScheduleLabel`. In these optimal use cases, no memory
will be allocated.
- The interning returns a `Interned<dyn SystemSet>`, which is just a
wrapper around a `&'static dyn SystemSet`.
- `Hash` and `Eq` are implemented in terms of the pointer value of the
reference, similar to my first approach of anonymous system sets in
#7676.
- Therefore, `Interned<T>` does not implement `Borrow<T>`, only `Deref`.
- The debug output of `Interned<T>` is the same as the interned value.
Edit:
- `AppLabel` is now also interned and the old
`derive_label`/`define_label` macros were replaced with the new
interning implementation.
- Anonymous set ids are reused for different `Schedule`s, reducing the
amount of leaked memory.
### Pros
- `InternedSystemSet` and `InternedScheduleLabel` behave very similar to
the current `BoxedSystemSet` and `BoxedScheduleLabel`, but can be copied
without an allocation.
- Many use cases don't allocate at all.
- Very fast lookups and comparisons when using `InternedSystemSet` and
`InternedScheduleLabel`.
- The `intern` module might be usable in other areas.
- `Interned{ScheduleLabel, SystemSet, AppLabel}` does implement
`{ScheduleLabel, SystemSet, AppLabel}`, increasing ergonomics.
### Cons
- Implementors of `SystemSet` and `ScheduleLabel` still need to
implement `Hash` and `Eq` (and `Clone`) for it to work.
## Changelog
### Added
- Added `intern` module to `bevy_utils`.
- Added reexports of `DynEq` to `bevy_ecs` and `bevy_app`.
### Changed
- Replaced `BoxedSystemSet` and `BoxedScheduleLabel` with
`InternedSystemSet` and `InternedScheduleLabel`.
- Replaced `impl AsRef<dyn ScheduleLabel>` with `impl ScheduleLabel`.
- Replaced `AppLabelId` with `InternedAppLabel`.
- Changed `AppLabel` to use `Debug` for error messages.
- Changed `AppLabel` to use interning.
- Changed `define_label`/`derive_label` to use interning.
- Replaced `define_boxed_label`/`derive_boxed_label` with
`define_label`/`derive_label`.
- Changed anonymous set ids to be only unique inside a schedule, not
globally.
- Made interned label types implement their label trait.
### Removed
- Removed `define_boxed_label` and `derive_boxed_label`.
## Migration guide
- Replace `BoxedScheduleLabel` and `Box<dyn ScheduleLabel>` with
`InternedScheduleLabel` or `Interned<dyn ScheduleLabel>`.
- Replace `BoxedSystemSet` and `Box<dyn SystemSet>` with
`InternedSystemSet` or `Interned<dyn SystemSet>`.
- Replace `AppLabelId` with `InternedAppLabel` or `Interned<dyn
AppLabel>`.
- Types manually implementing `ScheduleLabel`, `AppLabel` or `SystemSet`
need to implement:
- `dyn_hash` directly instead of implementing `DynHash`
- `as_dyn_eq`
- Pass labels to `World::try_schedule_scope`, `World::schedule_scope`,
`World::try_run_schedule`. `World::run_schedule`, `Schedules::remove`,
`Schedules::remove_entry`, `Schedules::contains`, `Schedules::get` and
`Schedules::get_mut` by value instead of by reference.
---------
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
When a mesh vertex attribute has a vertex count mismatch, a warning
message is printed with the index of the attribute which did not match.
Change to name the attribute, or fall back to the old behaviour if it
was not a known attribute.
Before:
```
MeshVertexAttributeId(2) has a different vertex count (32) than other attributes (64) in this mesh, all attributes will be truncated to match the smallest.
```
After:
```
Vertex_Uv has a different vertex count (32) than other attributes (64) in this mesh, all attributes will be truncated to match the smallest.
```
## Solution
Name the mesh attribute which had a count mismatch.
## Changelog
- If a mesh vertex attribute has a different count than other vertex
attributes, name the offending attribute using a human readable name
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
- the style of import used by bevy guarantees merge conflicts when any
file change
- This is especially true when import lists are large, such as in
`bevy_pbr`
- Merge conflicts are tricky to resolve. This bogs down rendering PRs
and makes contributing to bevy's rendering system more difficult than it
needs to
## Solution
- Use wildcard imports to replace multiline import list in `bevy_pbr`
I suspect this is controversial, but I'd like to hear alternatives.
Because this is one of many papercuts that makes developing render
features near impossible.
Closes#9946
# Objective
Add a new type mirroring `wgpu::SamplerDescriptor` for
`ImageLoaderSettings` to control how a loaded image should be sampled.
Fix issues with texture sampler descriptors not being set when loading
gltf texture from URI.
## Solution
Add a new `ImageSamplerDescriptor` and its affiliated types that mirrors
`wgpu::SamplerDescriptor`, use it in the image loader settings.
---
## Changelog
### Added
- Added new types `ImageSamplerDescriptor`, `ImageAddressMode`,
`ImageFilterMode`, `ImageCompareFunction` and `ImageSamplerBorderColor`
that mirrors the corresponding wgpu types.
- `ImageLoaderSettings` now carries an `ImageSamplerDescriptor` field
that will be used to determine how the loaded image is sampled, and will
be serialized as part of the image assets `.meta` files.
### Changed
- `Image::from_buffer` now takes the sampler descriptor to use as an
additional parameter.
### Fixed
- Sampler descriptors are set for gltf textures loaded from URI.
# Objective
- Fixes#10250
```
[Log] ERROR crates/bevy_render/src/render_resource/pipeline_cache.rs:823 failed to process shader: (wasm_example.js, line 376)
error: no definition in scope for identifier: 'bevy_pbr::pbr_deferred_functions::unpack_unorm3x4_plus_unorm_20_'
┌─ crates/bevy_pbr/src/deferred/deferred_lighting.wgsl:44:20
│
44 │ frag_coord.z = bevy_pbr::pbr_deferred_functions::unpack_unorm3x4_plus_unorm_20_(deferred_data.b).w;
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown identifier
│
= no definition in scope for identifier: 'bevy_pbr::pbr_deferred_functions::unpack_unorm3x4_plus_unorm_20_'
```
## Solution
- Fix the import path
The "gray" issue is since #9258 on macOS
... at least they're not white anymore
<img width="1294" alt="Screenshot 2023-10-25 at 00 14 11"
src="https://github.com/bevyengine/bevy/assets/8672791/df1a1138-c26c-4417-9b49-a00fbb8561d7">
Updates the requirements on
[async-io](https://github.com/smol-rs/async-io) to permit the latest
version.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/smol-rs/async-io/releases">async-io's
releases</a>.</em></p>
<blockquote>
<h2>v2.0.0</h2>
<ul>
<li><strong>Breaking:</strong> <code>Async::new()</code> now takes types
that implement <code>AsFd</code>/<code>AsSocket</code> instead of
<code>AsRawFd</code>/<code>AsRawSocket</code>, in order to implement I/O
safety. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/142">#142</a>)</li>
<li><strong>Breaking:</strong> <code>Async::get_mut()</code>,
<code>Async::read_with_mut()</code> and
<code>Async::write_with_mut()</code> are now <code>unsafe</code>. The
underlying source is technically "borrowed" by the polling
instance, so moving it out would be unsound. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/142">#142</a>)</li>
<li>Expose miscellaneous <code>kqueue</code> filters in the
<code>os::kqueue</code> module. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/112">#112</a>)</li>
<li>Expose a way to get the underlying <code>Poller</code>'s file
descriptor on Unix. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/125">#125</a>)</li>
<li>Add a new <code>Async::new_nonblocking</code> method to allow users
to avoid duplicating an already nonblocking socket. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/159">#159</a>)</li>
<li>Remove the unused <code>fastrand</code> and <code>memchr</code>
dependencies. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/131">#131</a>)</li>
<li>Use <code>tracing</code> instead of <code>log</code>. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/140">#140</a>)</li>
<li>Support ESP-IDF. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/144">#144</a>)</li>
<li>Optimize the <code>block_on</code> function to reduce allocation,
leading to a slight performance improvement. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/149">#149</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/smol-rs/async-io/blob/master/CHANGELOG.md">async-io's
changelog</a>.</em></p>
<blockquote>
<h1>Version 2.0.0</h1>
<ul>
<li><strong>Breaking:</strong> <code>Async::new()</code> now takes types
that implement <code>AsFd</code>/<code>AsSocket</code> instead of
<code>AsRawFd</code>/<code>AsRawSocket</code>, in order to implement I/O
safety. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/142">#142</a>)</li>
<li><strong>Breaking:</strong> <code>Async::get_mut()</code>,
<code>Async::read_with_mut()</code> and
<code>Async::write_with_mut()</code> are now <code>unsafe</code>. The
underlying source is technically "borrowed" by the polling
instance, so moving it out would be unsound. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/142">#142</a>)</li>
<li>Expose miscellaneous <code>kqueue</code> filters in the
<code>os::kqueue</code> module. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/112">#112</a>)</li>
<li>Expose a way to get the underlying <code>Poller</code>'s file
descriptor on Unix. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/125">#125</a>)</li>
<li>Add a new <code>Async::new_nonblocking</code> method to allow users
to avoid duplicating an already nonblocking socket. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/159">#159</a>)</li>
<li>Remove the unused <code>fastrand</code> and <code>memchr</code>
dependencies. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/131">#131</a>)</li>
<li>Use <code>tracing</code> instead of <code>log</code>. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/140">#140</a>)</li>
<li>Support ESP-IDF. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/144">#144</a>)</li>
<li>Optimize the <code>block_on</code> function to reduce allocation,
leading to a slight performance improvement. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/149">#149</a>)</li>
</ul>
<h1>Version 1.13.0</h1>
<ul>
<li>Use <a
href="https://crates.io/crates/rustix/"><code>rustix</code></a> instead
of <a href="https://crates.io/crates/libc/"><code>libc</code></a>/<a
href="https://crates.io/crates/windows-sys/"><code>windows-sys</code></a>
for system calls (<a
href="https://redirect.github.com/smol-rs/async-io/issues/76">#76</a>)</li>
<li>Add a <code>will_fire</code> method to <code>Timer</code> to test if
it will ever fire (<a
href="https://redirect.github.com/smol-rs/async-io/issues/106">#106</a>)</li>
<li>Reduce syscalls in <code>Async::new</code> (<a
href="https://redirect.github.com/smol-rs/async-io/issues/107">#107</a>)</li>
<li>Improve the drop ergonomics of <code>Readable</code> and
<code>Writable</code> (<a
href="https://redirect.github.com/smol-rs/async-io/issues/109">#109</a>)</li>
<li>Change the "<code>wepoll</code>" in documentation to
"<code>IOCP</code>" (<a
href="https://redirect.github.com/smol-rs/async-io/issues/116">#116</a>)</li>
</ul>
<h1>Version 1.12.0</h1>
<ul>
<li>Switch from <code>winapi</code> to <code>windows-sys</code> (<a
href="https://redirect.github.com/smol-rs/async-io/issues/102">#102</a>)</li>
</ul>
<h1>Version 1.11.0</h1>
<ul>
<li>Update <code>concurrent-queue</code> to v2. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/99">#99</a>)</li>
</ul>
<h1>Version 1.10.0</h1>
<ul>
<li>Remove the dependency on the <code>once_cell</code> crate to restore
the MSRV. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/95">#95</a>)</li>
</ul>
<h1>Version 1.9.0</h1>
<ul>
<li>Fix panic on very large durations. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/87">#87</a>)</li>
<li>Add <code>Timer::never</code> (<a
href="https://redirect.github.com/smol-rs/async-io/issues/87">#87</a>)</li>
</ul>
<h1>Version 1.8.0</h1>
<ul>
<li>Implement I/O safety traits on Rust 1.63+ (<a
href="https://redirect.github.com/smol-rs/async-io/issues/84">#84</a>)</li>
</ul>
<h1>Version 1.7.0</h1>
<ul>
<li>Process timers set for exactly <code>now</code>. (<a
href="https://redirect.github.com/smol-rs/async-io/issues/73">#73</a>)</li>
</ul>
<h1>Version 1.6.0</h1>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="7e89eec4d1"><code>7e89eec</code></a>
v2.0.0</li>
<li><a
href="356431754c"><code>3564317</code></a>
tests: Add test for <a
href="https://redirect.github.com/smol-rs/async-io/issues/154">#154</a></li>
<li><a
href="a5da16f072"><code>a5da16f</code></a>
Expose Async::new_nonblocking</li>
<li><a
href="0f2af634d8"><code>0f2af63</code></a>
Avoid needless set_nonblocking calls</li>
<li><a
href="62e3454f38"><code>62e3454</code></a>
Migrate to Rust 2021 (<a
href="https://redirect.github.com/smol-rs/async-io/issues/160">#160</a>)</li>
<li><a
href="59ee2ea27c"><code>59ee2ea</code></a>
Use set_nonblocking in Async::new on Windows (<a
href="https://redirect.github.com/smol-rs/async-io/issues/157">#157</a>)</li>
<li><a
href="d5bc619021"><code>d5bc619</code></a>
Remove needless as_fd/as_socket calls (<a
href="https://redirect.github.com/smol-rs/async-io/issues/158">#158</a>)</li>
<li><a
href="0b5016e567"><code>0b5016e</code></a>
m: Replace socket2 calls with rustix</li>
<li><a
href="8c3c3bd80b"><code>8c3c3bd</code></a>
m: Optimize block_on by caching Parker and Waker</li>
<li><a
href="1b1466a6c1"><code>1b1466a</code></a>
Update this crate to use the new polling breaking changes (<a
href="https://redirect.github.com/smol-rs/async-io/issues/142">#142</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/smol-rs/async-io/compare/v1.13.0...v2.0.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
A follow-up PR for https://github.com/bevyengine/bevy/pull/10221
## Changelog
Replaced usages of texture_descriptor.size with the helper methods of
`Image` through the entire engine codebase
# Objective
Reduce code duplication and improve APIs of Bevy's [global
taskpools](https://github.com/bevyengine/bevy/blob/main/crates/bevy_tasks/src/usages.rs).
## Solution
- As all three of the global taskpools have identical implementations
and only differ in their identifiers, this PR moves the implementation
into a macro to reduce code duplication.
- The `init` method is renamed to `get_or_init` to more accurately
reflect what it really does.
- Add a new `try_get` method that just returns `None` when the pool is
uninitialized, to complement the other getter methods.
- Minor documentation improvements to accompany the above changes.
---
## Changelog
- Added a new `try_get` method to the global TaskPools
- The global TaskPools' `init` method has been renamed to `get_or_init`
for clarity
- Documentation improvements
## Migration Guide
- Uses of `ComputeTaskPool::init`, `AsyncComputeTaskPool::init` and
`IoTaskPool::init` should be changed to `::get_or_init`.
# Objective
- Handle pausing audio when Android app is suspended
## Solution
- This is the start of application lifetime events. They are mostly
useful on mobile
- Next version of winit should add a few more
- When application is suspended, send an event to notify the
application, and run the schedule one last time before actually
suspending the app
- Audio is now suspended too 🎉https://github.com/bevyengine/bevy/assets/8672791/d74e2e09-ee29-4f40-adf2-36a0c064f94e
---------
Co-authored-by: Marco Buono <418473+coreh@users.noreply.github.com>
# Objective
Fog color was passed to shaders without conversion from sRGB to linear
color space. Because shaders expect colors in linear space this resulted
in wrong color being used. This is most noticeable in open scenes with
dark fog color and clear color set to the same color. In such case
background/clear color (which is properly processed) is going to be
darker than very far objects.
Example:
![image](https://github.com/bevyengine/bevy/assets/160391/89b70d97-b2d0-4bc5-80f4-c9e8b8801c4c)
[bevy-fog-color-bug.zip](https://github.com/bevyengine/bevy/files/13063718/bevy-fog-color-bug.zip)
## Solution
Add missing conversion of fog color to linear color space.
---
## Changelog
* Fixed conversion of fog color
## Migration Guide
- Colors in `FogSettings` struct (`color` and `directional_light_color`)
are now sent to the GPU in linear space. If you were using
`Color::rgb()`/`Color::rgba()` and would like to retain the previous
colors, you can quickly fix it by switching to
`Color::rgb_linear()`/`Color::rgba_linear()`.
# Objective
- After #9826, there are issues on "run once runners"
- example `without_winit` crashes:
```
2023-10-19T22:06:01.810019Z INFO bevy_render::renderer: AdapterInfo { name: "llvmpipe (LLVM 15.0.7, 256 bits)", vendor: 65541, device: 0, device_type: Cpu, driver: "llvmpipe", driver_info: "Mesa 23.2.1 - kisak-mesa PPA (LLVM 15.0.7)", backend: Vulkan }
2023-10-19T22:06:02.860331Z WARN bevy_audio::audio_output: No audio device found.
2023-10-19T22:06:03.215154Z INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Linux 22.04 Ubuntu", kernel: "6.2.0-1014-azure", cpu: "Intel(R) Xeon(R) CPU E5-2673 v3 @ 2.40GHz", core_count: "2", memory: "6.8 GiB" }
thread 'main' panicked at crates/bevy_render/src/pipelined_rendering.rs:91:14:
Unable to get RenderApp. Another plugin may have removed the RenderApp before PipelinedRenderingPlugin
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
- example `headless` runs the app twice with the `run_once` schedule
## Solution
- Expose a more complex state of an app than just "ready"
- Also block adding plugins to an app after it has finished or cleaned
up its plugins as that wouldn't work anyway
## Migration Guide
* `app.ready()` has been replaced by `app.plugins_state()` which will
return more details on the current state of plugins in the app
# Objective
- Replace md5 by another hasher, as suggested in
https://github.com/bevyengine/bevy/pull/8624#discussion_r1359291028
- md5 is not secure, and is slow. use something more secure and faster
## Solution
- Replace md5 by blake3
Putting this PR in the 0.12 as once it's released, changing the hash
algorithm will be a painful breaking change
# Objective
Even at `reflectance == 0.0`, our ambient and environment map light
implementations still produce fresnel/specular highlights.
Such a low `reflectance` value lies outside of the physically possible
range and is already used by our directional, point and spot light
implementations (via the `fresnel()` function) to enable artistic
control, effectively disabling the fresnel "look" for non-physically
realistic materials. Since ambient and environment lights use a
different formulation, they were not honoring this same principle.
This PR aims to bring consistency to all light types, offering the same
fresnel extinguishing control to ambient and environment lights.
Thanks to `@nathanf` for [pointing
out](https://discord.com/channels/691052431525675048/743663924229963868/1164083373514440744)
the [Filament docs section about
this](https://google.github.io/filament/Filament.md.html#lighting/occlusion/specularocclusion).
## Solution
- We use [the same
formulation](ffc572728f/crates/bevy_pbr/src/render/pbr_lighting.wgsl (L99))
already used by the `fresnel()` function in `bevy_pbr::lighting` to
modulate the F90, to modulate the specular component of Ambient and
Environment Map lights.
## Comparison
⚠️ **Modified version of the PBR example for demo purposes, that shows
reflectance (_NOT_ part of this PR)** ⚠️
Also, keep in mind this is a very subtle difference (look for the
fresnel highlights on the lower left spheres, you might need to zoom in.
### Before
<img width="1392" alt="Screenshot 2023-10-18 at 23 02 25"
src="https://github.com/bevyengine/bevy/assets/418473/ec0efb58-9a98-4377-87bc-726a1b0a3ff3">
### After
<img width="1392" alt="Screenshot 2023-10-18 at 23 01 43"
src="https://github.com/bevyengine/bevy/assets/418473/a2809325-5728-405e-af02-9b5779767843">
---
## Changelog
- Ambient and Environment Map lights will now honor values of
`reflectance` that are below the physically possible range (⪅ 0.35) by
extinguishing their fresnel highlights. (Just like point, directional
and spot lights already did.) This allows for more consistent artistic
control and for non-physically realistic looks with all light types.
## Migration Guide
- If Fresnel highlights from Ambient and Environment Map lights are no
longer visible in your materials, make sure you're using a higher,
physically plausible value of `reflectance` (⪆ 0.35).
# Objective
- I want to use the `debug_glam_assert` feature with bevy.
## Solution
- Re-export the feature flag
---
## Changelog
- Re-export `debug_glam_assert` feature flag from glam.
# Objective
Fixes#5101
Alternative to #6511
## Solution
Corrected the behavior for ignored fields in `FromReflect`, which was
previously using the incorrect field indexes.
Similarly, fields marked with `#[reflect(skip_serializing)]` no longer
break when using `FromReflect` after deserialization. This was done by
modifying `SerializationData` to store a function pointer that can later
be used to generate a default instance of the skipped field during
deserialization.
The function pointer points to a function generated by the derive macro
using the behavior designated by `#[reflect(default)]` (or just
`Default` if none provided). The entire output of the macro is now
wrapped in an [unnamed
constant](https://doc.rust-lang.org/stable/reference/items/constant-items.html#unnamed-constant)
which keeps this behavior hygienic.
#### Rationale
The biggest downside to this approach is that it requires fields marked
`#[reflect(skip_serializing)]` to provide the ability to create a
default instance— either via a `Default` impl or by specifying a custom
one. While this isn't great, I think it might be justified by the fact
that we really need to create this value when using `FromReflect` on a
deserialized object. And we need to do this _during_ deserialization
because after that (at least for tuples and tuple structs) we lose
information about which field is which: _"is the value at index 1 in
this `DynamicTupleStruct` the actual value for index 1 or is it really
the value for index 2 since index 1 is skippable...?"_
#### Alternatives
An alternative would be to store `Option<Box<dyn Reflect>>` within
`DynamicTuple` and `DynamicTupleStruct` instead of just `Box<dyn
Reflect>`. This would allow us to insert "empty"/"missing" fields during
deserialization, thus saving the positional information of the skipped
fields. However, this may require changing the API of `Tuple` and
`TupleStruct` such that they can account for their dynamic counterparts
returning `None` for a skipped field. In practice this would probably
mean exposing the `Option`-ness of the dynamics onto implementors via
methods like `Tuple::drain` or `TupleStruct::field`.
Personally, I think requiring `Default` would be better than muddying up
the API to account for these special cases. But I'm open to trying out
this other approach if the community feels that it's better.
---
## Changelog
### Public Changes
#### Fixed
- The behaviors of `#[reflect(ignore)]` and
`#[reflect(skip_serializing)]` are no longer dependent on field order
#### Changed
- Fields marked with `#[reflect(skip_serializing)]` now need to either
implement `Default` or specify a custom default function using
`#[reflect(default = "path::to::some_func")]`
- Deserializing a type with fields marked `#[reflect(skip_serializing)]`
will now include that field initialized to its specified default value
- `SerializationData::new` now takes the new `SkippedField` struct along
with the skipped field index
- Renamed `SerializationData::is_ignored_field` to
`SerializationData::is_field_skipped`
#### Added
- Added `SkippedField` struct
- Added methods `SerializationData::generate_default` and
`SerializationData::iter_skipped`
### Internal Changes
#### Changed
- Replaced `members_to_serialization_denylist` and `BitSet<u32>` with
`SerializationDataDef`
- The `Reflect` derive is more hygienic as it now outputs within an
[unnamed
constant](https://doc.rust-lang.org/stable/reference/items/constant-items.html#unnamed-constant)
- `StructField::index` has been split up into
`StructField::declaration_index` and `StructField::reflection_index`
#### Removed
- Removed `bitset` dependency
## Migration Guide
* Fields marked `#[reflect(skip_serializing)]` now must implement
`Default` or specify a custom default function with `#[reflect(default =
"path::to::some_func")]`
```rust
#[derive(Reflect)]
struct MyStruct {
#[reflect(skip_serializing)]
#[reflect(default = "get_foo_default")]
foo: Foo, // <- `Foo` does not impl `Default` so requires a custom
function
#[reflect(skip_serializing)]
bar: Bar, // <- `Bar` impls `Default`
}
#[derive(Reflect)]
struct Foo(i32);
#[derive(Reflect, Default)]
struct Bar(i32);
fn get_foo_default() -> Foo {
Foo(123)
}
```
* `SerializationData::new` has been changed to expect an iterator of
`(usize, SkippedField)` rather than one of just `usize`
```rust
// BEFORE
SerializationData::new([0, 3].into_iter());
// AFTER
SerializationData::new([
(0, SkippedField::new(field_0_default_fn)),
(3, SkippedField::new(field_3_default_fn)),
].into_iter());
```
* `Serialization::is_ignored_field` has been renamed to
`Serialization::is_field_skipped`
* Fields marked `#[reflect(skip_serializing)]` are now included in
deserialization output. This may affect logic that expected those fields
to be absent.
# Objective
To get the width or height of an image you do:
```rust
self.texture_descriptor.size.{width, height}
```
that is quite verbose.
This PR adds some convenient methods for Image to reduce verbosity.
## Changelog
* Add a `width()` method for getting the width of an image.
* Add a `height()` method for getting the height of an image.
* Rename the `size()` method to `size_f32()`.
* Add a `size()` method for getting the size of an image as u32.
* Renamed the `aspect_2d()` method to `aspect_ratio()`.
## Migration Guide
Replace calls to the `Image::size()` method with `size_f32()`.
Replace calls to the `Image::aspect_2d()` method with `aspect_ratio()`.
# Objective
- Fix#10165
- On iOS simulator on apple silicon Macs, shader validation is going
through the host, but device limits are reported for the device. They
sometimes differ, and cause the validation to crash on something that
should work
```
-[MTLDebugRenderCommandEncoder validateCommonDrawErrors:]:5775: failed assertion `Draw Errors Validation
Fragment Function(fragment_): the offset into the buffer _naga_oil_mod_MJSXM6K7OBRHEOR2NVSXG2C7OZUWK527MJUW4ZDJNZTXG_memberfog that is bound at buffer index 6 must be a multiple of 256 but was set to 448.
```
## Solution
- Add a custom flag when building for the simulator and override the
buffer alignment
# Objective
- Closes#10049.
- Detect DDS texture containing a cubemap or a cubemap array.
## Solution
- When loading a dds texture, the header capabilities are checked for
the cubemap flag. An error is returned if not all faces are provided.
---
## Changelog
### Added
- Added a new texture error `TextureError::IncompleteCubemap`, used for
dds cubemap textures containing less than 6 faces, as that is not
supported on modern graphics APIs.
### Fixed
- DDS cubemaps are now loaded as cubemaps instead of 2D textures.
## Migration Guide
If you are matching on a `TextureError`, you will need to add a new
branch to handle `TextureError::IncompleteCubemap`.
# Objective
While reviewing #10187 I noticed some other mistakes in the UI node
docs.
## Solution
I did a quick proofreading pass and fixed a few things. And of course,
the typo from that other PR.
## Notes
I occasionally insert a period to make a section of doc self-consistent
but didn't go one way or the other on all periods in the file.
---------
Co-authored-by: Noah <noahshomette@gmail.com>
# Objective
Simplify bind group creation code. alternative to (and based on) #9476
## Solution
- Add a `BindGroupEntries` struct that can transparently be used where
`&[BindGroupEntry<'b>]` is required in BindGroupDescriptors.
Allows constructing the descriptor's entries as:
```rust
render_device.create_bind_group(
"my_bind_group",
&my_layout,
&BindGroupEntries::with_indexes((
(2, &my_sampler),
(3, my_uniform),
)),
);
```
instead of
```rust
render_device.create_bind_group(
"my_bind_group",
&my_layout,
&[
BindGroupEntry {
binding: 2,
resource: BindingResource::Sampler(&my_sampler),
},
BindGroupEntry {
binding: 3,
resource: my_uniform,
},
],
);
```
or
```rust
render_device.create_bind_group(
"my_bind_group",
&my_layout,
&BindGroupEntries::sequential((&my_sampler, my_uniform)),
);
```
instead of
```rust
render_device.create_bind_group(
"my_bind_group",
&my_layout,
&[
BindGroupEntry {
binding: 0,
resource: BindingResource::Sampler(&my_sampler),
},
BindGroupEntry {
binding: 1,
resource: my_uniform,
},
],
);
```
the structs has no user facing macros, is tuple-type-based so stack
allocated, and has no noticeable impact on compile time.
- Also adds a `DynamicBindGroupEntries` struct with a similar api that
uses a `Vec` under the hood and allows extending the entries.
- Modifies `RenderDevice::create_bind_group` to take separate arguments
`label`, `layout` and `entries` instead of a `BindGroupDescriptor`
struct. The struct can't be stored due to the internal references, and
with only 3 members arguably does not add enough context to justify
itself.
- Modify the codebase to use the new api and the `BindGroupEntries` /
`DynamicBindGroupEntries` structs where appropriate (whenever the
entries slice contains more than 1 member).
## Migration Guide
- Calls to `RenderDevice::create_bind_group({BindGroupDescriptor {
label, layout, entries })` must be amended to
`RenderDevice::create_bind_group(label, layout, entries)`.
- If `label`s have been specified as `"bind_group_name".into()`, they
need to change to just `"bind_group_name"`. `Some("bind_group_name")`
and `None` will still work, but `Some("bind_group_name")` can optionally
be simplified to just `"bind_group_name"`.
---------
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
- bump naga_oil to 0.10
- update shader imports to use rusty syntax
## Migration Guide
naga_oil 0.10 reworks the import mechanism to support more syntax to
make it more rusty, and test for item use before importing to determine
which imports are modules and which are items, which allows:
- use rust-style imports
```
#import bevy_pbr::{
pbr_functions::{alpha_discard as discard, apply_pbr_lighting},
mesh_bindings,
}
```
- import partial paths:
```
#import part::of::path
...
path::remainder::function();
```
which will call to `part::of::path::remainder::function`
- use fully qualified paths without importing:
```
// #import bevy_pbr::pbr_functions
bevy_pbr::pbr_functions::pbr()
```
- use imported items without qualifying
```
#import bevy_pbr::pbr_functions::pbr
// for backwards compatibility the old style is still supported:
// #import bevy_pbr::pbr_functions pbr
...
pbr()
```
- allows most imported items to end with `_` and numbers (naga_oil#30).
still doesn't allow struct members to end with `_` or numbers but it's
progress.
- the vast majority of existing shader code will work without changes,
but will emit "deprecated" warnings for old-style imports. these can be
suppressed with the `allow-deprecated` feature.
- partly breaks overrides (as far as i'm aware nobody uses these yet) -
now overrides will only be applied if the overriding module is added as
an additional import in the arguments to `Composer::make_naga_module` or
`Composer::add_composable_module`. this is necessary to support
determining whether imports are modules or items.
# Objective
This PR aims to make it so that we don't accidentally go over
`MAX_TEXTURE_IMAGE_UNITS` (in WebGL) or
`maxSampledTexturesPerShaderStage` (in WebGPU), giving us some extra
leeway to add more view bind group textures.
(This PR is extracted from—and unblocks—#8015)
## Solution
- We replace the existing `view_layout` and `view_layout_multisampled`
pair with an array of 32 bind group layouts, generated ahead of time;
- For now, these layouts cover all the possible combinations of:
`multisampled`, `depth_prepass`, `normal_prepass`,
`motion_vector_prepass` and `deferred_prepass`:
- In the future, as @JMS55 pointed out, we can likely take out
`motion_vector_prepass` and `deferred_prepass`, as these are not really
needed for the mesh pipeline and can use separate pipelines. This would
bring the possible combinations down to 8;
- We can also add more "optional" textures as they become needed,
allowing the engine to scale to a wider variety of use cases in lower
end/web environments (e.g. some apps might just want normal and depth
prepasses, others might only want light probes), while still keeping a
high ceiling for high end native environments where more textures are
supported.
- While preallocating bind group layouts is relatively cheap, the number
of combinations grows exponentially, so we should likely limit ourselves
to something like at most 256–1024 total layouts until we find a better
solution (like generating them lazily)
- To make this mechanism a little bit more explicit/discoverable, so
that compatibility with WebGPU/WebGL is not broken by accident, we add a
`MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES` const and warn whenever
the number of textures in the layout crosses it.
- The warning is gated by `#[cfg(debug_assertions)]` and not issued in
release builds;
- We're counting the actual textures in the bind group layout instead of
using some roundabout metric so it should be accurate;
- Right now `MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES` is set to 10
in order to leave 6 textures free for other groups;
- Currently there's no combination that would cause us to go over the
limit, but that will change once #8015 lands.
---
## Changelog
- `MeshPipeline` view bind group layouts now vary based on the current
multisampling and prepass states, saving a couple of texture binding
entries when prepasses are not in use.
## Migration Guide
- `MeshPipeline::view_layout` and
`MeshPipeline::view_layout_multisampled` have been replaced with a
private array to accomodate for variable view bind group layouts. To
obtain a view bind group layout for the current pipeline state, use the
new `MeshPipeline::get_view_layout()` or
`MeshPipeline::get_view_layout_from_key()` methods.
# Objective
Users shouldn't need to change their source code between "development
workflows" and "releasing". Currently, Bevy Asset V2 has two "processed"
asset modes `Processed` (assumes assets are already processed) and
`ProcessedDev` (starts an asset processor and processes assets). This
means that the mode must be changed _in code_ when switching from "app
dev" to "release". Very suboptimal.
We have already removed "runtime opt-in" for hot-reloading. Enabling the
`file_watcher` feature _automatically_ enables file watching in code.
This means deploying a game (without hot reloading enabled) just means
calling `cargo build --release` instead of `cargo run --features
bevy/file_watcher`.
We should adopt this pattern for asset processing.
## Solution
This adds the `asset_processor` feature, which will start the
`AssetProcessor` when an `AssetPlugin` runs in `AssetMode::Processed`.
The "asset processing workflow" is now:
1. Enable `AssetMode::Processed` on `AssetPlugin`
2. When developing, run with the `asset_processor` and `file_watcher`
features
3. When releasing, build without these features.
The `AssetMode::ProcessedDev` mode has been removed.
# Objective
I encountered a problem where I had a plugin `FooPlugin` which did
```rust
impl Plugin for FooPlugin {
fn build(&self, app: &mut App) {
app
.register_asset_source(...); // more stuff after
}
}
```
And when I tried using it, e.g.
```rust
asset_server.load("foo://data/asset.custom");
```
I got an error that `foo` was not recognized as a source.
I found that this is because asset sources must be registered _before_
`AssetPlugin` is added, and I had `FooPlugin` _after_.
## Solution
Add clarifying note about having to register sources before
`AssetPlugin` is added.
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
# Objective
- Provides actionable feedback when users encounter the error in
https://github.com/bevyengine/bevy/issues/10162
- Complements https://github.com/bevyengine/bevy/pull/10186
## Solution
- Log an error when registering an AssetSource after the AssetPlugin has
been built (via DefaultPlugins). This will let users know that their
registration order needs changing
The outputted error message will look like this:
```rust
ERROR bevy_asset::server: 'AssetSourceId::Name(test)' must be registered before `AssetPlugin` (typically added as part of `DefaultPlugins`)
```
---------
Co-authored-by: 66OJ66 <hi0obxud@anonaddy.me>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#10177 .
## Solution
Added a new run condition and tweaked the docs for `on_timer`.
## Changelog
### Added
- `on_real_time_timer` run condition
# Objective
This PR addresses the issue where Bevy displays one or several black
frames before the scene is first rendered. This is particularly
noticeable on iOS, where the black frames disrupt the transition from
the launch screen to the game UI. I have written about my search to
solve this issue on the Bevy discord:
https://discord.com/channels/691052431525675048/1151047604520632352
While I can attest this PR works on both iOS and Linux/Wayland (and even
seems to resolve a slight flicker during startup with the latter as
well), I'm not familiar enough with Bevy to judge the full implications
of these changes. I hope a reviewer or tester can help me confirm
whether this is the right approach, or what might be a cleaner solution
to resolve this issue.
## Solution
I have moved the "startup phase" as well as the plugin finalization into
the `app.run()` function so those things finish synchronously before the
"main schedule" starts. I even move one frame forward as well, using
`app.update()`, to make sure the rendering has caught up with the state
of the finalized plugins as well.
I admit that part of this was achieved through trial-and-error, since
not doing the "startup phase" *before* `app.finish()` resulted in
panics, while not calling an extra `app.update()` didn't fully resolve
the issue.
What I *can* say, is that the iOS launch screen animation works in such
a way that the OS initiates the transition once the framework's
[`didFinishLaunching()`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622921-application)
returns, meaning app developers **must** finish setting up their UI
before that function returns. This is what basically led me on the path
to try to "finish stuff earlier" :)
## Changelog
### Changed
- The startup phase and the first frame are rendered synchronously when
calling `app.run()`, before the "main schedule" is started. This fixes
black frames during the iOS launch transition and possible flickering on
other platforms, but may affect initialization order in your
application.
## Migration Guide
Because of this change, the timing of the first few frames might have
changed, and I think it could be that some things one may expect to be
initialized in a system may no longer be. To be honest, I feel out of my
depth to judge the exact impact here.
# Objective
Add a way to easily compute the up-to-date `GlobalTransform` of an
entity.
## Solution
Add the `TransformHelper`(Name pending) system parameter with the
`compute_global_transform` method that takes an `Entity` and returns a
`GlobalTransform` if successful.
## Changelog
- Added the `TransformHelper` system parameter for computing the
up-to-date `GlobalTransform` of an entity.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Noah <noahshomette@gmail.com>
# Objective
allow extending `Material`s (including the built in `StandardMaterial`)
with custom vertex/fragment shaders and additional data, to easily get
pbr lighting with custom modifications, or otherwise extend a base
material.
# Solution
- added `ExtendedMaterial<B: Material, E: MaterialExtension>` which
contains a base material and a user-defined extension.
- added example `extended_material` showing how to use it
- modified AsBindGroup to have "unprepared" functions that return raw
resources / layout entries so that the extended material can combine
them
note: doesn't currently work with array resources, as i can't figure out
how to make the OwnedBindingResource::get_binding() work, as wgpu
requires a `&'a[&'a TextureView]` and i have a `Vec<TextureView>`.
# Migration Guide
manual implementations of `AsBindGroup` will need to be adjusted, the
changes are pretty straightforward and can be seen in the diff for e.g.
the `texture_binding_array` example.
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
# Objective
deferred doesn't currently run unless one of `DepthPrepass`,
`ForwardPrepass` or `MotionVectorPrepass` is also present on the camera.
## Solution
modify the `queue_prepass_material_meshes` view query to check for any
relevant phase, instead of requiring `Opaque3dPrepass` and
`AlphaMask3dPrepass` to be present
# Objective
- Correct the description of an error type for the scene loader
## Solution
- Correct the description of an error type for the scene loader
# Objective
- This PR aims to make the various `*_PREPASS` shader defs we have
(`NORMAL_PREPASS`, `DEPTH_PREPASS`, `MOTION_VECTORS_PREPASS` AND
`DEFERRED_PREPASS`) easier to use and understand:
- So that their meaning is now consistent across all contexts; (“prepass
X is enabled for the current view”)
- So that they're also consistently set across all contexts.
- It also aims to enable us to (with a follow up PR) to conditionally
gate the `BindGroupEntry` and `BindGroupLayoutEntry` items associated
with these prepasses, saving us up to 4 texture slots in WebGL
(currently globally limited to 16 per shader, regardless of bind groups)
## Solution
- We now consistently set these from `PrepassPipeline`, the
`MeshPipeline` and the `DeferredLightingPipeline`, we also set their
`MeshPipelineKey`s;
- We introduce `PREPASS_PIPELINE`, `MESH_PIPELINE` and
`DEFERRED_LIGHTING_PIPELINE` that can be used to detect where the code
is running, without overloading the meanings of the prepass shader defs;
- We also gate the WGSL functions in `bevy_pbr::prepass_utils` with
`#ifdef`s for their respective shader defs, so that shader code can
provide a fallback whenever they're not available.
- This allows us to conditionally include the bindings for these prepass
textures (My next PR, which will hopefully unblock #8015)
- @robtfm mentioned [these were being used to prevent accessing the same
binding as read/write in the
prepass](https://discord.com/channels/691052431525675048/743663924229963868/1163270458393759814),
however even after reversing the `#ifndef`s I had no issues running the
code, so perhaps the compiler is already smart enough even without tree
shaking to know they're not being used, thanks to `#ifdef
PREPASS_PIPELINE`?
## Comparison
### Before
| Shader Def | `PrepassPipeline` | `MeshPipeline` |
`DeferredLightingPipeline` |
| ------------------------ | ----------------- | -------------- |
-------------------------- |
| `NORMAL_PREPASS` | Yes | No | No |
| `DEPTH_PREPASS` | Yes | No | No |
| `MOTION_VECTORS_PREPASS` | Yes | No | No |
| `DEFERRED_PREPASS` | Yes | No | No |
| View Key | `PrepassPipeline` | `MeshPipeline` |
`DeferredLightingPipeline` |
| ------------------------ | ----------------- | -------------- |
-------------------------- |
| `NORMAL_PREPASS` | Yes | Yes | No |
| `DEPTH_PREPASS` | Yes | No | No |
| `MOTION_VECTORS_PREPASS` | Yes | No | No |
| `DEFERRED_PREPASS` | Yes | Yes\* | No |
\* Accidentally was being set twice, once with only
`deferred_prepass.is_some()` as a condition,
and once with `deferred_p repass.is_some() && !forward` as a condition.
### After
| Shader Def | `PrepassPipeline` | `MeshPipeline` |
`DeferredLightingPipeline` |
| ---------------------------- | ----------------- | --------------- |
-------------------------- |
| `NORMAL_PREPASS` | Yes | Yes | Yes |
| `DEPTH_PREPASS` | Yes | Yes | Yes |
| `MOTION_VECTORS_PREPASS` | Yes | Yes | Yes |
| `DEFERRED_PREPASS` | Yes | Yes | Unconditionally |
| `PREPASS_PIPELINE` | Unconditionally | No | No |
| `MESH_PIPELINE` | No | Unconditionally | No |
| `DEFERRED_LIGHTING_PIPELINE` | No | No | Unconditionally |
| View Key | `PrepassPipeline` | `MeshPipeline` |
`DeferredLightingPipeline` |
| ------------------------ | ----------------- | -------------- |
-------------------------- |
| `NORMAL_PREPASS` | Yes | Yes | Yes |
| `DEPTH_PREPASS` | Yes | Yes | Yes |
| `MOTION_VECTORS_PREPASS` | Yes | Yes | Yes |
| `DEFERRED_PREPASS` | Yes | Yes | Unconditionally |
---
## Changelog
- Cleaned up WGSL `*_PREPASS` shader defs so they're now consistently
used everywhere;
- Introduced `PREPASS_PIPELINE`, `MESH_PIPELINE` and
`DEFERRED_LIGHTING_PIPELINE` WGSL shader defs for conditionally
compiling logic based the current pipeline;
- WGSL functions from `bevy_pbr::prepass_utils` are now guarded with
`#ifdef` based on the currently enabled prepasses;
## Migration Guide
- When using functions from `bevy_pbr::prepass_utils`
(`prepass_depth()`, `prepass_normal()`, `prepass_motion_vector()`) in
contexts where these prepasses might be disabled, you should now wrap
your calls with the appropriate `#ifdef` guards, (`#ifdef
DEPTH_PREPASS`, `#ifdef NORMAL_PREPASS`, `#ifdef MOTION_VECTOR_PREPASS`)
providing fallback logic where applicable.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
Fixes#10086
## Solution
Instead of serializing via `DynamicTypePath::reflect_type_path`, now
uses the `TypePath` found on the `TypeInfo` returned by
`Reflect::get_represented_type_info`.
This issue was happening because the dynamic types implement `TypePath`
themselves and do not (and cannot) forward their proxy's `TypePath`
data. The solution was to access the proxy's type information in order
to get the correct `TypePath` data.
## Changed
- The `Debug` impl for `TypePathTable` now includes output for all
fields.
# Objective
Time clamping happens consistently for apps that load non-trivial
things. While this _is_ an indicator that we should probably try to move
this work to a thread that doesn't block the Update, this is common
enough (and unactionable enough) that I think we should demote it for
now.
```
2023-10-16T18:46:14.918781Z WARN bevy_time::virt: delta time larger than maximum delta, clamping delta to 250ms and skipping 63.649253ms
2023-10-16T18:46:15.178048Z WARN bevy_time::virt: delta time larger than maximum delta, clamping delta to 250ms and skipping 1.71611ms
```
## Solution
Change `warn` to `debug` for this message
# Objective
Closes#10107
The visibility of `bevy::core::update_frame_count` should be `pub` so it
can be used in third-party code like this:
```rust
impl Plugin for MyPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Last, use_frame_count.before(bevy::core::update_frame_count));
}
}
```
## Solution
Make `bevy::core::update_frame_count` public.
---
## Changelog
### Added
- Documentation for `bevy::core::update_frame_count`
### Changed
- Visibility of `bevy::core::update_frame_count` is now `pub`
# Objective
- Added support for newer AMD Radeon cards in the mod.rs file located at
``crates/bevy_render/src/view/window/mod.rs``
## Solution
- All I needed to add was ``name.starts_with("Radeon") ||`` to the
existing code on line 347 of
``crates/bevy_render/src/view/window/mod.rs``
---
## Changelog
- Changed ``crates/bevy_render/src/view/window/mod.rs``
# Objective
Current `FixedTime` and `Time` have several problems. This pull aims to
fix many of them at once.
- If there is a longer pause between app updates, time will jump forward
a lot at once and fixed time will iterate on `FixedUpdate` for a large
number of steps. If the pause is merely seconds, then this will just
mean jerkiness and possible unexpected behaviour in gameplay. If the
pause is hours/days as with OS suspend, the game will appear to freeze
until it has caught up with real time.
- If calculating a fixed step takes longer than specified fixed step
period, the game will enter a death spiral where rendering each frame
takes longer and longer due to more and more fixed step updates being
run per frame and the game appears to freeze.
- There is no way to see current fixed step elapsed time inside fixed
steps. In order to track this, the game designer needs to add a custom
system inside `FixedUpdate` that calculates elapsed or step count in a
resource.
- Access to delta time inside fixed step is `FixedStep::period` rather
than `Time::delta`. This, coupled with the issue that `Time::elapsed`
isn't available at all for fixed steps, makes it that time requiring
systems are either implemented to be run in `FixedUpdate` or `Update`,
but rarely work in both.
- Fixes#8800
- Fixes#8543
- Fixes#7439
- Fixes#5692
## Solution
- Create a generic `Time<T>` clock that has no processing logic but
which can be instantiated for multiple usages. This is also exposed for
users to add custom clocks.
- Create three standard clocks, `Time<Real>`, `Time<Virtual>` and
`Time<Fixed>`, all of which contain their individual logic.
- Create one "default" clock, which is just `Time` (or `Time<()>`),
which will be overwritten from `Time<Virtual>` on each update, and
`Time<Fixed>` inside `FixedUpdate` schedule. This way systems that do
not care specifically which time they track can work both in `Update`
and `FixedUpdate` without changes and the behaviour is intuitive.
- Add `max_delta` to virtual time update, which limits how much can be
added to virtual time by a single update. This fixes both the behaviour
after a long freeze, and also the death spiral by limiting how many
fixed timestep iterations there can be per update. Possible future work
could be adding `max_accumulator` to add a sort of "leaky bucket" time
processing to possibly smooth out jumps in time while keeping frame rate
stable.
- Many minor tweaks and clarifications to the time functions and their
documentation.
## Changelog
- `Time::raw_delta()`, `Time::raw_elapsed()` and related methods are
moved to `Time<Real>::delta()` and `Time<Real>::elapsed()` and now match
`Time` API
- `FixedTime` is now `Time<Fixed>` and matches `Time` API.
- `Time<Fixed>` default timestep is now 64 Hz, or 15625 microseconds.
- `Time` inside `FixedUpdate` now reflects fixed timestep time, making
systems portable between `Update ` and `FixedUpdate`.
- `Time::pause()`, `Time::set_relative_speed()` and related methods must
now be called as `Time<Virtual>::pause()` etc.
- There is a new `max_delta` setting in `Time<Virtual>` that limits how
much the clock can jump by a single update. The default value is 0.25
seconds.
- Removed `on_fixed_timer()` condition as `on_timer()` does the right
thing inside `FixedUpdate` now.
## Migration Guide
- Change all `Res<Time>` instances that access `raw_delta()`,
`raw_elapsed()` and related methods to `Res<Time<Real>>` and `delta()`,
`elapsed()`, etc.
- Change access to `period` from `Res<FixedTime>` to `Res<Time<Fixed>>`
and use `delta()`.
- The default timestep has been changed from 60 Hz to 64 Hz. If you wish
to restore the old behaviour, use
`app.insert_resource(Time::<Fixed>::from_hz(60.0))`.
- Change `app.insert_resource(FixedTime::new(duration))` to
`app.insert_resource(Time::<Fixed>::from_duration(duration))`
- Change `app.insert_resource(FixedTime::new_from_secs(secs))` to
`app.insert_resource(Time::<Fixed>::from_seconds(secs))`
- Change `system.on_fixed_timer(duration)` to
`system.on_timer(duration)`. Timers in systems placed in `FixedUpdate`
schedule automatically use the fixed time clock.
- Change `ResMut<Time>` calls to `pause()`, `is_paused()`,
`set_relative_speed()` and related methods to `ResMut<Time<Virtual>>`
calls. The API is the same, with the exception that `relative_speed()`
will return the actual last ste relative speed, while
`effective_relative_speed()` returns 0.0 if the time is paused and
corresponds to the speed that was set when the update for the current
frame started.
## Todo
- [x] Update pull name and description
- [x] Top level documentation on usage
- [x] Fix examples
- [x] Decide on default `max_delta` value
- [x] Decide naming of the three clocks: is `Real`, `Virtual`, `Fixed`
good?
- [x] Decide if the three clock inner structures should be in prelude
- [x] Decide on best way to configure values at startup: is manually
inserting a new clock instance okay, or should there be config struct
separately?
- [x] Fix links in docs
- [x] Decide what should be public and what not
- [x] Decide how `wrap_period` should be handled when it is changed
- [x] ~~Add toggles to disable setting the clock as default?~~ No,
separate pull if needed.
- [x] Add tests
- [x] Reformat, ensure adheres to conventions etc.
- [x] Build documentation and see that it looks correct
## Contributors
Huge thanks to @alice-i-cecile and @maniwani while building this pull.
It was a shared effort!
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Cameron <51241057+maniwani@users.noreply.github.com>
Co-authored-by: Jerome Humbert <djeedai@gmail.com>
# Objective
Calling `asset_server.load("scene.gltf#SomeLabel")` will silently fail
if `SomeLabel` does not exist.
Referenced in #9714
## Solution
We now detect this case and return an error. I also slightly refactored
`load_internal` to make the logic / dataflow much clearer.
---------
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
# Objective
As called out in #9714, Bevy Asset V2 fails to hot-reload labeled assets
whose source asset has changed (in cases where the root asset is not
alive).
## Solution
Track alive labeled assets for a given source asset and allow hot
reloads in cases where a labeled asset is still alive.
# Objective
- Since #9885, running on an iOS device crashes trying to create the
processed folder
- This only happens on real device, not on the simulator
## Solution
- Setup processed assets only if needed
# Objective
On nightly there is a warning on a missing lifetime:
```bash
warning: `&` without an explicit lifetime name cannot be used here
```
The details are in https://github.com/rust-lang/rust/issues/115010, but
the bottom line is that in associated constants elided lifetimes are no
longer allowed to be implicitly defined.
This fixes the only place where it is missing.
## Solution
- Add explicit `'static` lifetime
# Objective
Currently, the asset loader outputs
```
2023-10-14T15:11:09.328850Z WARN bevy_asset::asset_server: no `AssetLoader` found
```
when user forgets to add an extension to a file. This is very confusing
behaviour, it sounds like there aren't any asset loaders existing.
## Solution
Add an extra message on the end when there are no file extensions.
# Objective
#10105 changed the ssao input color from the material base color to
white. i can't actually see a difference in the example but there should
be one in some cases.
## Solution
change it back.
# Objective
From my understanding, although resources are not meant to be created
and removed at every frame, they are still meant to be created
dynamically during the lifetime of the App.
But because the extract_resource API does not allow optional resources
from the main world, it's impossible to use resources in the render
phase that were not created before the render sub-app itself.
## Solution
Because the ECS engine already allows for system parameters to be
`Option<Res>`, it just had to be added.
---
## Changelog
- Changed
- `extract_resource` now takes an optional main world resource
- Fixed
- `ExtractResourcePlugin` doesn't cause panics anymore if the resource
is not already inserted
This adds support for **Multiple Asset Sources**. You can now register a
named `AssetSource`, which you can load assets from like you normally
would:
```rust
let shader: Handle<Shader> = asset_server.load("custom_source://path/to/shader.wgsl");
```
Notice that `AssetPath` now supports `some_source://` syntax. This can
now be accessed through the `asset_path.source()` accessor.
Asset source names _are not required_. If one is not specified, the
default asset source will be used:
```rust
let shader: Handle<Shader> = asset_server.load("path/to/shader.wgsl");
```
The behavior of the default asset source has not changed. Ex: the
`assets` folder is still the default.
As referenced in #9714
## Why?
**Multiple Asset Sources** enables a number of often-asked-for
scenarios:
* **Loading some assets from other locations on disk**: you could create
a `config` asset source that reads from the OS-default config folder
(not implemented in this PR)
* **Loading some assets from a remote server**: you could register a new
`remote` asset source that reads some assets from a remote http server
(not implemented in this PR)
* **Improved "Binary Embedded" Assets**: we can use this system for
"embedded-in-binary assets", which allows us to replace the old
`load_internal_asset!` approach, which couldn't support asset
processing, didn't support hot-reloading _well_, and didn't make
embedded assets accessible to the `AssetServer` (implemented in this pr)
## Adding New Asset Sources
An `AssetSource` is "just" a collection of `AssetReader`, `AssetWriter`,
and `AssetWatcher` entries. You can configure new asset sources like
this:
```rust
app.register_asset_source(
"other",
AssetSource::build()
.with_reader(|| Box::new(FileAssetReader::new("other")))
)
)
```
Note that `AssetSource` construction _must_ be repeatable, which is why
a closure is accepted.
`AssetSourceBuilder` supports `with_reader`, `with_writer`,
`with_watcher`, `with_processed_reader`, `with_processed_writer`, and
`with_processed_watcher`.
Note that the "asset source" system replaces the old "asset providers"
system.
## Processing Multiple Sources
The `AssetProcessor` now supports multiple asset sources! Processed
assets can refer to assets in other sources and everything "just works".
Each `AssetSource` defines an unprocessed and processed `AssetReader` /
`AssetWriter`.
Currently this is all or nothing for a given `AssetSource`. A given
source is either processed or it is not. Later we might want to add
support for "lazy asset processing", where an `AssetSource` (such as a
remote server) can be configured to only process assets that are
directly referenced by local assets (in order to save local disk space
and avoid doing extra work).
## A new `AssetSource`: `embedded`
One of the big features motivating **Multiple Asset Sources** was
improving our "embedded-in-binary" asset loading. To prove out the
**Multiple Asset Sources** implementation, I chose to build a new
`embedded` `AssetSource`, which replaces the old `load_interal_asset!`
system.
The old `load_internal_asset!` approach had a number of issues:
* The `AssetServer` was not aware of (or capable of loading) internal
assets.
* Because internal assets weren't visible to the `AssetServer`, they
could not be processed (or used by assets that are processed). This
would prevent things "preprocessing shaders that depend on built in Bevy
shaders", which is something we desperately need to start doing.
* Each "internal asset" needed a UUID to be defined in-code to reference
it. This was very manual and toilsome.
The new `embedded` `AssetSource` enables the following pattern:
```rust
// Called in `crates/bevy_pbr/src/render/mesh.rs`
embedded_asset!(app, "mesh.wgsl");
// later in the app
let shader: Handle<Shader> = asset_server.load("embedded://bevy_pbr/render/mesh.wgsl");
```
Notice that this always treats the crate name as the "root path", and it
trims out the `src` path for brevity. This is generally predictable, but
if you need to debug you can use the new `embedded_path!` macro to get a
`PathBuf` that matches the one used by `embedded_asset`.
You can also reference embedded assets in arbitrary assets, such as WGSL
shaders:
```rust
#import "embedded://bevy_pbr/render/mesh.wgsl"
```
This also makes `embedded` assets go through the "normal" asset
lifecycle. They are only loaded when they are actually used!
We are also discussing implicitly converting asset paths to/from shader
modules, so in the future (not in this PR) you might be able to load it
like this:
```rust
#import bevy_pbr::render::mesh::Vertex
```
Compare that to the old system!
```rust
pub const MESH_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(3252377289100772450);
load_internal_asset!(app, MESH_SHADER_HANDLE, "mesh.wgsl", Shader::from_wgsl);
// The mesh asset is the _only_ accessible via MESH_SHADER_HANDLE and _cannot_ be loaded via the AssetServer.
```
## Hot Reloading `embedded`
You can enable `embedded` hot reloading by enabling the
`embedded_watcher` cargo feature:
```
cargo run --features=embedded_watcher
```
## Improved Hot Reloading Workflow
First: the `filesystem_watcher` cargo feature has been renamed to
`file_watcher` for brevity (and to match the `FileAssetReader` naming
convention).
More importantly, hot asset reloading is no longer configured in-code by
default. If you enable any asset watcher feature (such as `file_watcher`
or `rust_source_watcher`), asset watching will be automatically enabled.
This removes the need to _also_ enable hot reloading in your app code.
That means you can replace this:
```rust
app.add_plugins(DefaultPlugins.set(AssetPlugin::default().watch_for_changes()))
```
with this:
```rust
app.add_plugins(DefaultPlugins)
```
If you want to hot reload assets in your app during development, just
run your app like this:
```
cargo run --features=file_watcher
```
This means you can use the same code for development and deployment! To
deploy an app, just don't include the watcher feature
```
cargo build --release
```
My intent is to move to this approach for pretty much all dev workflows.
In a future PR I would like to replace `AssetMode::ProcessedDev` with a
`runtime-processor` cargo feature. We could then group all common "dev"
cargo features under a single `dev` feature:
```sh
# this would enable file_watcher, embedded_watcher, runtime-processor, and more
cargo run --features=dev
```
## AssetMode
`AssetPlugin::Unprocessed`, `AssetPlugin::Processed`, and
`AssetPlugin::ProcessedDev` have been replaced with an `AssetMode` field
on `AssetPlugin`.
```rust
// before
app.add_plugins(DefaultPlugins.set(AssetPlugin::Processed { /* fields here */ })
// after
app.add_plugins(DefaultPlugins.set(AssetPlugin { mode: AssetMode::Processed, ..default() })
```
This aligns `AssetPlugin` with our other struct-like plugins. The old
"source" and "destination" `AssetProvider` fields in the enum variants
have been replaced by the "asset source" system. You no longer need to
configure the AssetPlugin to "point" to custom asset providers.
## AssetServerMode
To improve the implementation of **Multiple Asset Sources**,
`AssetServer` was made aware of whether or not it is using "processed"
or "unprocessed" assets. You can check that like this:
```rust
if asset_server.mode() == AssetServerMode::Processed {
/* do something */
}
```
Note that this refactor should also prepare the way for building "one to
many processed output files", as it makes the server aware of whether it
is loading from processed or unprocessed sources. Meaning we can store
and read processed and unprocessed assets differently!
## AssetPath can now refer to folders
The "file only" restriction has been removed from `AssetPath`. The
`AssetServer::load_folder` API now accepts an `AssetPath` instead of a
`Path`, meaning you can load folders from other asset sources!
## Improved AssetPath Parsing
AssetPath parsing was reworked to support sources, improve error
messages, and to enable parsing with a single pass over the string.
`AssetPath::new` was replaced by `AssetPath::parse` and
`AssetPath::try_parse`.
## AssetWatcher broken out from AssetReader
`AssetReader` is no longer responsible for constructing `AssetWatcher`.
This has been moved to `AssetSourceBuilder`.
## Duplicate Event Debouncing
Asset V2 already debounced duplicate filesystem events, but this was
_input_ events. Multiple input event types can produce the same _output_
`AssetSourceEvent`. Now that we have `embedded_watcher`, which does
expensive file io on events, it made sense to debounce output events
too, so I added that! This will also benefit the AssetProcessor by
preventing integrity checks for duplicate events (and helps keep the
noise down in trace logs).
## Next Steps
* **Port Built-in Shaders**: Currently the primary (and essentially
only) user of `load_interal_asset` in Bevy's source code is "built-in
shaders". I chose not to do that in this PR for a few reasons:
1. We need to add the ability to pass shader defs in to shaders via meta
files. Some shaders (such as MESH_VIEW_TYPES) need to pass shader def
values in that are defined in code.
2. We need to revisit the current shader module naming system. I think
we _probably_ want to imply modules from source structure (at least by
default). Ideally in a way that can losslessly convert asset paths
to/from shader modules (to enable the asset system to resolve modules
using the asset server).
3. I want to keep this change set minimal / get this merged first.
* **Deprecate `load_internal_asset`**: we can't do that until we do (1)
and (2)
* **Relative Asset Paths**: This PR significantly increases the need for
relative asset paths (which was already pretty high). Currently when
loading dependencies, it is assumed to be an absolute path, which means
if in an `AssetLoader` you call `context.load("some/path/image.png")` it
will assume that is the "default" asset source, _even if the current
asset is in a different asset source_. This will cause breakage for
AssetLoaders that are not designed to add the current source to whatever
paths are being used. AssetLoaders should generally not need to be aware
of the name of their current asset source, or need to think about the
"current asset source" generally. We should build apis that support
relative asset paths and then encourage using relative paths as much as
possible (both via api design and docs). Relative paths are also
important because they will allow developers to move folders around
(even across providers) without reprocessing, provided there is no path
breakage.
# Objective
- According to the GLTF spec, it should not be possible to have a non
skinned mesh on a skinned node
> When the node contains skin, all mesh.primitives MUST contain JOINTS_0
and WEIGHTS_0 attributes
>
https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-node
- However, the reverse (a skinned mesh on a non skinned node) is just a
warning, see `NODE_SKINNED_MESH_WITHOUT_SKIN` in
https://github.com/KhronosGroup/glTF-Validator/blob/main/ISSUES.md#linkerror
- This causes a crash in Bevy because the bind group layout is made from
the mesh which is skinned, but filled from the entity which is not
```
thread '<unnamed>' panicked at 'wgpu error: Validation Error
Caused by:
In a RenderPass
note: encoder = `<CommandBuffer-(0, 5, Metal)>`
In a set_bind_group command
note: bind group = `<BindGroup-(27, 1, Metal)>`
Bind group 2 expects 2 dynamic offsets. However 1 dynamic offset were provided.
```
- Blender can export GLTF files with this kind of issues
## Solution
- When a skinned mesh is only used on non skinned nodes, ignore skinned
information from the mesh and warn the user (this is what three.js is
doing)
- When a skinned mesh is used on both skinned and non skinned nodes, log
an error
# Objective
Fixes#9676
Possible alternative to #9708
`Text2dBundles` are not currently drawn because the render-world-only
entities for glyphs that are created in `extract_text2d_sprite` are not
tracked by the per-view `VisibleEntities`.
## Solution
Add an `Option<Entity>` to `ExtractedSprite` that keeps track of the
original entity that caused a "glyph entity" to be created.
Use that in `queue_sprites` if it exists when checking view visibility.
## Benchmarks
Quick benchmarks. Average FPS over 1500 frames.
| bench | before fps | after fps | diff |
|-|-|-|-|
|many_sprites|884.93|879.00|🟡 -0.7%|
|bevymark -- --benchmark --waves 100 --per-wave 1000 --mode
sprite|75.99|75.93|🟡 -0.1%|
|bevymark -- --benchmark --waves 50 --per-wave 1000 --mode
mesh2d|32.85|32.58|🟡 -0.8%|
# Objective
cleanup some pbr shader code. improve shader stage io consistency and
make pbr.wgsl (probably many people's first foray into bevy shader code)
a little more human-readable. also fix a couple of small issues with
deferred rendering.
## Solution
mesh_vertex_output:
- rename to forward_io (to align with prepass_io)
- rename `MeshVertexOutput` to `VertexOutput` (to align with prepass_io)
- move `Vertex` from mesh.wgsl into here (to align with prepass_io)
prepass_io:
- remove `FragmentInput`, use `VertexOutput` directly (to align with
forward_io)
- rename `VertexOutput::clip_position` to `position` (to align with
forward_io)
pbr.wgsl:
- restructure so we don't need `#ifdefs` on the actual entrypoint, use
VertexOutput and FragmentOutput in all cases and use #ifdefs to import
the right struct definitions.
- rearrange to make the flow clearer
- move alpha_discard up from `pbr_functions::pbr` to avoid needing to
call it on some branches and not others
- add a bunch of comments
deferred_lighting:
- move ssao into the `!unlit` block to reflect forward behaviour
correctly
- fix compile error with deferred + premultiply_alpha
## Migration Guide
in custom material shaders:
- `pbr_functions::pbr` no longer calls to
`pbr_functions::alpha_discard`. if you were using the `pbr` function in
a custom shader with alpha mask mode you now also need to call
alpha_discard manually
- rename imports of `bevy_pbr::mesh_vertex_output` to
`bevy_pbr::forward_io`
- rename instances of `MeshVertexOutput` to `VertexOutput`
in custom material prepass shaders:
- rename instances of `VertexOutput::clip_position` to
`VertexOutput::position`
# Objective
Fixes#10069
## Solution
Extracted UI nodes were previously stored in a `SparseSet` and had a
predictable iteration order. UI borders and outlines relied on this. Now
they are stored in a HashMap and that is no longer true.
This adds `entity.index()` to the sort key for `TransparentUi` so that
the iteration order is predictable and the "border entities" that get
spawned during extraction are guaranteed to get drawn after their
respective container nodes again.
I **think** that everything still works for overlapping ui nodes etc,
because the z value / primary sort is still controlled by the "ui
stack."
Text above is just my current understanding. A rendering expert should
check this out.
I will do some more testing when I can.
# Objective
Fixes [#10061]
## Solution
Renamed `RenderInstance` to `ExtractInstance`, `RenderInstances` to
`ExtractedInstances` and `RenderInstancePlugin` to
`ExtractInstancesPlugin`
# Objective
- Add a [Deferred
Renderer](https://en.wikipedia.org/wiki/Deferred_shading) to Bevy.
- This allows subsequent passes to access per pixel material information
before/during shading.
- Accessing this per pixel material information is needed for some
features, like GI. It also makes other features (ex. Decals) simpler to
implement and/or improves their capability. There are multiple
approaches to accomplishing this. The deferred shading approach works
well given the limitations of WebGPU and WebGL2.
Motivation: [I'm working on a GI solution for
Bevy](https://youtu.be/eH1AkL-mwhI)
# Solution
- The deferred renderer is implemented with a prepass and a deferred
lighting pass.
- The prepass renders opaque objects into the Gbuffer attachment
(`Rgba32Uint`). The PBR shader generates a `PbrInput` in mostly the same
way as the forward implementation and then [packs it into the
Gbuffer](ec1465559f/crates/bevy_pbr/src/render/pbr.wgsl (L168)).
- The deferred lighting pass unpacks the `PbrInput` and [feeds it into
the pbr()
function](ec1465559f/crates/bevy_pbr/src/deferred/deferred_lighting.wgsl (L65)),
then outputs the shaded color data.
- There is now a resource
[DefaultOpaqueRendererMethod](ec1465559f/crates/bevy_pbr/src/material.rs (L599))
that can be used to set the default render method for opaque materials.
If materials return `None` from
[opaque_render_method()](ec1465559f/crates/bevy_pbr/src/material.rs (L131))
the `DefaultOpaqueRendererMethod` will be used. Otherwise, custom
materials can also explicitly choose to only support Deferred or Forward
by returning the respective
[OpaqueRendererMethod](ec1465559f/crates/bevy_pbr/src/material.rs (L603))
- Deferred materials can be used seamlessly along with both opaque and
transparent forward rendered materials in the same scene. The [deferred
rendering
example](https://github.com/DGriffin91/bevy/blob/deferred/examples/3d/deferred_rendering.rs)
does this.
- The deferred renderer does not support MSAA. If any deferred materials
are used, MSAA must be disabled. Both TAA and FXAA are supported.
- Deferred rendering supports WebGL2/WebGPU.
## Custom deferred materials
- Custom materials can support both deferred and forward at the same
time. The
[StandardMaterial](ec1465559f/crates/bevy_pbr/src/render/pbr.wgsl (L166))
does this. So does [this
example](https://github.com/DGriffin91/bevy_glowy_orb_tutorial/blob/deferred/assets/shaders/glowy.wgsl#L56).
- Custom deferred materials that require PBR lighting can create a
`PbrInput`, write it to the deferred GBuffer and let it be rendered by
the `PBRDeferredLightingPlugin`.
- Custom deferred materials that require custom lighting have two
options:
1. Use the base_color channel of the `PbrInput` combined with the
`STANDARD_MATERIAL_FLAGS_UNLIT_BIT` flag.
[Example.](https://github.com/DGriffin91/bevy_glowy_orb_tutorial/blob/deferred/assets/shaders/glowy.wgsl#L56)
(If the unlit bit is set, the base_color is stored as RGB9E5 for extra
precision)
2. A Custom Deferred Lighting pass can be created, either overriding the
default, or running in addition. The a depth buffer is used to limit
rendering to only the required fragments for each deferred lighting
pass. Materials can set their respective depth id via the
[deferred_lighting_pass_id](b79182d2a3/crates/bevy_pbr/src/prepass/prepass_io.wgsl (L95))
attachment. The custom deferred lighting pass plugin can then set [its
corresponding
depth](ec1465559f/crates/bevy_pbr/src/deferred/deferred_lighting.wgsl (L37)).
Then with the lighting pass using
[CompareFunction::Equal](ec1465559f/crates/bevy_pbr/src/deferred/mod.rs (L335)),
only the fragments with a depth that equal the corresponding depth
written in the material will be rendered.
Custom deferred lighting plugins can also be created to render the
StandardMaterial. The default deferred lighting plugin can be bypassed
with `DefaultPlugins.set(PBRDeferredLightingPlugin { bypass: true })`
---------
Co-authored-by: nickrart <nickolas.g.russell@gmail.com>
# Objective
While using joysticks for player aiming, I noticed that there was as
`0.05` value snap on the axis. After searching through Bevy's code, I
saw it was the default livezone being at `0.95`. This causes any value
higher to snap to `1.0`. I think `1.0` and `-1.0` would be a better
default, as it gives all values to the joystick arc.
This default livezone stumped me for a bit as I thought either something
was broken or I was doing something wrong.
## Solution
Change the livezone defaults to ` livezone_upperbound: 1.0` and
`livezone_lowerbound: -1.0`.
---
## Migration Guide
If the default 0.05 was relied on, the default or gamepad `AxisSettings`
on the resource `GamepadSettings` will have to be changed.
# Objective
- Fixes#8303
## Solution
- Replaced 1 instance of `OnceBox<T>` with `OnceLock<T>` in
`NonGenericTypeCell`
## Notes
All changes are in the private side of Bevy, and appear to have no
observable change in performance or compilation time. This is purely to
reduce the quantity of direct dependencies in Bevy.
# Objective
- The filter type on the `apply_global_wireframe_material` system had
duplicate filter code and the `clippy::type_complexity` attribute.
## Solution
- Extract the common part of the filter into a type alias
# Objective
- Use the `Material` abstraction for the Wireframes
- Right now this doesn't have many benefits other than simplifying some
of the rendering code
- We can reuse the default vertex shader and avoid rendering
inconsistencies
- The goal is to have a material with a color on each mesh so this
approach will make it easier to implement
- Originally done in https://github.com/bevyengine/bevy/pull/5303 but I
decided to split the Material part to it's own PR and then adding
per-entity colors and globally configurable colors will be a much
simpler diff.
## Solution
- Use the new `Material` abstraction for the Wireframes
## Notes
It's possible this isn't ideal since this adds a
`Handle<WireframeMaterial>` to all the meshes compared to the original
approach that didn't need anything. I didn't notice any performance
impact on my machine.
This might be a surprising usage of `Material` at first, because
intuitively you only have one material per mesh, but the way it's
implemented you can have as many different types of materials as you
want on a mesh.
## Migration Guide
`WireframePipeline` was removed. If you were using it directly, please
create an issue explaining your use case.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Add serde Deserialize and Serialize for structs that doesn't implement
it, even if they could benefit from it
## Solution
- Derive these traits for the structs Style, BackgroundColor,
BorderColor and Outline.
---
Adopted from #8954, co-authored by @pyrotechnick
# Objective
The Bevy ecosystem currently reflects `Quat` via "value" rather than the
more appropriate "struct" strategy. This behaviour is inconsistent to
that of similar types, i.e. `Vec3`. Additionally, employing the "value"
strategy causes instances of `Quat` to be serialised as a sequence `[x,
y, z, w]` rather than structures of shape `{ x, y, z, w }`.
The [comments surrounding the applicable
code](bec299fa6e/crates/bevy_reflect/src/impls/glam.rs (L254))
give context and historical reasons for this discrepancy:
```
// Quat fields are read-only (as of now), and reflection is currently missing
// mechanisms for read-only fields. I doubt those mechanisms would be added,
// so for now quaternions will remain as values. They are represented identically
// to Vec4 and DVec4, so you may use those instead and convert between.
```
This limitation has [since been lifted by the upstream
crate](374625163e),
glam.
## Solution
Migrating the reflect strategy of Quat from "value" to "struct" via
replacing `impl_reflect_value` with `impl_reflect_struct` resolves the
issue.
## Changelog
Migrated `Quat` reflection strategy to "struct" from "value"
Migration Guide
Changed Quat serialization/deserialization from sequences `[x, y, z, w]`
to structures `{ x, y, z, w }`.
---------
Co-authored-by: pyrotechnick <13998+pyrotechnick@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
~~Currently blocked on an upstream bug that causes crashes when
minimizing/resizing on dx12 https://github.com/gfx-rs/wgpu/issues/3967~~
wgpu 0.17.1 is out which fixes it
# Objective
Keep wgpu up to date.
## Solution
Update wgpu and naga_oil.
Currently this depends on an unreleased (and unmerged) branch of
naga_oil, and hasn't been properly tested yet.
The wgpu side of this seems to have been an extremely trivial upgrade
(all the upgrade work seems to be in naga_oil). This also lets us remove
the workarounds for pack/unpack4x8unorm in the SSAO shaders.
Lets us close the dx12 part of
https://github.com/bevyengine/bevy/issues/8888
related: https://github.com/bevyengine/bevy/issues/9304
---
## Changelog
Update to wgpu 0.17 and naga_oil 0.9
# Objective
- This PR aims to make creating meshes a little bit more ergonomic,
specifically by removing the need for intermediate mutable variables.
## Solution
- We add methods that consume the `Mesh` and return a mesh with the
specified changes, so that meshes can be entirely constructed via
builder-style calls, without intermediate variables;
- Methods are flagged with `#[must_use]` to ensure proper use;
- Examples are updated to use the new methods where applicable. Some
examples are kept with the mutating methods so that users can still
easily discover them, and also where the new methods wouldn't really be
an improvement.
## Examples
Before:
```rust
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, vs);
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vns);
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vts);
mesh.set_indices(Some(Indices::U32(tris)));
mesh
```
After:
```rust
Mesh::new(PrimitiveTopology::TriangleList)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vs)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vns)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vts)
.with_indices(Some(Indices::U32(tris)))
```
Before:
```rust
let mut cube = Mesh::from(shape::Cube { size: 1.0 });
cube.generate_tangents().unwrap();
PbrBundle {
mesh: meshes.add(cube),
..default()
}
```
After:
```rust
PbrBundle {
mesh: meshes.add(
Mesh::from(shape::Cube { size: 1.0 })
.with_generated_tangents()
.unwrap(),
),
..default()
}
```
---
## Changelog
- Added consuming builder methods for more ergonomic `Mesh` creation:
`with_inserted_attribute()`, `with_removed_attribute()`,
`with_indices()`, `with_duplicated_vertices()`,
`with_computed_flat_normals()`, `with_generated_tangents()`,
`with_morph_targets()`, `with_morph_target_names()`.
# Objective
Closes#9955.
Use the same interface for all "pure" builder types: taking and
returning `Self` (and not `&mut Self`).
## Solution
Changed `DynamicSceneBuilder`, `SceneFilter` and `TableBuilder` to take
and return `Self`.
## Changelog
### Changed
- `DynamicSceneBuilder` and `SceneBuilder` methods in `bevy_ecs` now
take and return `Self`.
## Migration guide
When using `bevy_ecs::DynamicSceneBuilder` and `bevy_ecs::SceneBuilder`,
instead of binding the builder to a variable, directly use it. Methods
on those types now consume `Self`, so you will need to re-bind the
builder if you don't `build` it immediately.
Before:
```rust
let mut scene_builder = DynamicSceneBuilder::from_world(&world);
let scene = scene_builder.extract_entity(a).extract_entity(b).build();
```
After:
```rust
let scene = DynamicSceneBuilder::from_world(&world)
.extract_entity(a)
.extract_entity(b)
.build();
```
# Objective
Spatial audio was heroically thrown together at the last minute for Bevy
0.10, but right now it's a bit of a pain to use -- users need to
manually update audio sinks with the position of the listener / emitter.
Hopefully the migration guide entry speaks for itself.
## Solution
Add a new `SpatialListener` component and automatically update sinks
with the position of the listener and and emitter.
## Changelog
`SpatialAudioSink`s are now automatically updated with positions of
emitters and listeners.
## Migration Guide
Spatial audio now automatically uses the transform of the `AudioBundle`
and of an entity with a `SpatialListener` component.
If you were manually scaling emitter/listener positions, you can use the
`spatial_scale` field of `AudioPlugin` instead.
```rust
// Old
commands.spawn(
SpatialAudioBundle {
source: asset_server.load("sounds/Windless Slopes.ogg"),
settings: PlaybackSettings::LOOP,
spatial: SpatialSettings::new(listener_position, gap, emitter_position),
},
);
fn update(
emitter_query: Query<(&Transform, &SpatialAudioSink)>,
listener_query: Query<&Transform, With<Listener>>,
) {
let listener = listener_query.single();
for (transform, sink) in &emitter_query {
sink.set_emitter_position(transform.translation);
sink.set_listener_position(*listener, gap);
}
}
// New
commands.spawn((
SpatialBundle::from_transform(Transform::from_translation(emitter_position)),
AudioBundle {
source: asset_server.load("sounds/Windless Slopes.ogg"),
settings: PlaybackSettings::LOOP.with_spatial(true),
},
));
commands.spawn((
SpatialBundle::from_transform(Transform::from_translation(listener_position)),
SpatialListener::new(gap),
));
```
## Discussion
I removed `SpatialAudioBundle` because the `SpatialSettings` component
was made mostly redundant, and without that it was identical to
`AudioBundle`.
`SpatialListener` is a bare component and not a bundle which is feeling
like a maybe a strange choice. That happened from a natural aversion
both to nested bundles and to duplicating `Transform` etc in bundles and
from figuring that it is likely to just be tacked on to some other
bundle (player, head, camera) most of the time.
Let me know what you think about these things / everything else.
---------
Co-authored-by: Mike <mike.hsu@gmail.com>
# Objective
- Followup to #7184.
- ~Deprecate `TypeUuid` and remove its internal references.~ No longer
part of this PR.
- Use `TypePath` for the type registry, and (de)serialisation instead of
`std::any::type_name`.
- Allow accessing type path information behind proxies.
## Solution
- Introduce methods on `TypeInfo` and friends for dynamically querying
type path. These methods supersede the old `type_name` methods.
- Remove `Reflect::type_name` in favor of `DynamicTypePath::type_path`
and `TypeInfo::type_path_table`.
- Switch all uses of `std::any::type_name` in reflection, non-debugging
contexts to use `TypePath`.
---
## Changelog
- Added `TypePathTable` for dynamically accessing methods on `TypePath`
through `TypeInfo` and the type registry.
- Removed `type_name` from all `TypeInfo`-like structs.
- Added `type_path` and `type_path_table` methods to all `TypeInfo`-like
structs.
- Removed `Reflect::type_name` in favor of
`DynamicTypePath::reflect_type_path` and `TypeInfo::type_path`.
- Changed the signature of all `DynamicTypePath` methods to return
strings with a static lifetime.
## Migration Guide
- Rely on `TypePath` instead of `std::any::type_name` for all stability
guarantees and for use in all reflection contexts, this is used through
with one of the following APIs:
- `TypePath::type_path` if you have a concrete type and not a value.
- `DynamicTypePath::reflect_type_path` if you have an `dyn Reflect`
value without a concrete type.
- `TypeInfo::type_path` for use through the registry or if you want to
work with the represented type of a `DynamicFoo`.
- Remove `type_name` from manual `Reflect` implementations.
- Use `type_path` and `type_path_table` in place of `type_name` on
`TypeInfo`-like structs.
- Use `get_with_type_path(_mut)` over `get_with_type_name(_mut)`.
## Note to reviewers
I think if anything we were a little overzealous in merging #7184 and we
should take that extra care here.
In my mind, this is the "point of no return" for `TypePath` and while I
think we all agree on the design, we should carefully consider if the
finer details and current implementations are actually how we want them
moving forward.
For example [this incorrect `TypePath` implementation for
`String`](3fea3c6c0b/crates/bevy_reflect/src/impls/std.rs (L90))
(note that `String` is in the default Rust prelude) snuck in completely
under the radar.
Updates the requirements on [toml_edit](https://github.com/toml-rs/toml)
to permit the latest version.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ed597ebad1"><code>ed597eb</code></a>
chore: Release</li>
<li><a
href="257a0fdc59"><code>257a0fd</code></a>
docs: Update changelog</li>
<li><a
href="4b44f53a31"><code>4b44f53</code></a>
Merge pull request <a
href="https://redirect.github.com/toml-rs/toml/issues/617">#617</a> from
epage/update</li>
<li><a
href="7eaf286110"><code>7eaf286</code></a>
fix(parser): Failed on mixed inline tables</li>
<li><a
href="e1f20378a2"><code>e1f2037</code></a>
test: Verify with latest data</li>
<li><a
href="2f9253c9eb"><code>2f9253c</code></a>
chore: Update toml-test</li>
<li><a
href="c9b481cab5"><code>c9b481c</code></a>
test(toml): Ensure tables are used for validation</li>
<li><a
href="43d7f29cfd"><code>43d7f29</code></a>
Merge pull request <a
href="https://redirect.github.com/toml-rs/toml/issues/615">#615</a> from
toml-rs/renovate/actions-checkout-4.x</li>
<li><a
href="ef9b8372c8"><code>ef9b837</code></a>
chore(deps): update actions/checkout action to v4</li>
<li><a
href="d308188db7"><code>d308188</code></a>
chore: Release</li>
<li>Additional commits viewable in <a
href="https://github.com/toml-rs/toml/compare/v0.19.0...v0.20.2">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
fix#9605
spotlight culling uses an incorrect cluster aabb for orthographic
projections: it does not take into account the near and far cluster
bounds at all.
## Solution
use z_near and z_far to determine cluster aabb in orthographic mode.
i'm not 100% sure this is the only change that's needed, but i am sure
this change is needed, and the example seems to work well now
(CLUSTERED_FORWARD_DEBUG_CLUSTER_LIGHT_COMPLEXITY shows good bounds
around the cone for a variety of orthographic setups).
# Objective
Webgl2 broke when pcf was merged.
Fixes#10048
## Solution
Change the `textureSampleCompareLevel` in shadow_sampling.wgsl to
`textureSampleCompare` to make it work again.
# Objective
Currently, the only way for custom components that participate in
rendering to opt into the higher-performance extraction method in #9903
is to implement the `RenderInstances` data structure and the extraction
logic manually. This is inconvenient compared to the `ExtractComponent`
API.
## Solution
This commit creates a new `RenderInstance` trait that mirrors the
existing `ExtractComponent` method but uses the higher-performance
approach that #9903 uses. Additionally, `RenderInstance` is more
flexible than `ExtractComponent`, because it can extract multiple
components at once. This makes high-performance rendering components
essentially as easy to write as the existing ones based on component
extraction.
---
## Changelog
### Added
A new `RenderInstance` trait is available mirroring `ExtractComponent`,
but using a higher-performance method to extract one or more components
to the render world. If you have custom components that rendering takes
into account, you may consider migration from `ExtractComponent` to
`RenderInstance` for higher performance.
# Objective
- Improve antialiasing for non-point light shadow edges.
- Very partially addresses
https://github.com/bevyengine/bevy/issues/3628.
## Solution
- Implements "The Witness"'s shadow map sampling technique.
- Ported from @superdump's old branch, all credit to them :)
- Implements "Call of Duty: Advanced Warfare"'s stochastic shadow map
sampling technique when the velocity prepass is enabled, for use with
TAA.
- Uses interleaved gradient noise to generate a random angle, and then
averages 8 samples in a spiral pattern, rotated by the random angle.
- I also tried spatiotemporal blue noise, but it was far too noisy to be
filtered by TAA alone. In the future, we should try spatiotemporal blue
noise + a specialized shadow denoiser such as
https://gpuopen.com/fidelityfx-denoiser/#shadow. This approach would
also be useful for hybrid rasterized applications with raytraced
shadows.
- The COD presentation has an interesting temporal dithering of the
noise for use with temporal supersampling that we should revisit when we
get DLSS/FSR/other TSR.
---
## Changelog
* Added `ShadowFilteringMethod`. Improved directional light and
spotlight shadow edges to be less aliased.
## Migration Guide
* Shadows cast by directional lights or spotlights now have smoother
edges. To revert to the old behavior, add
`ShadowFilteringMethod::Hardware2x2` to your cameras.
---------
Co-authored-by: IceSentry <c.giguere42@gmail.com>
Co-authored-by: Daniel Chia <danstryder@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
Co-authored-by: Brandon Dyer <brandondyer64@gmail.com>
Co-authored-by: Edgar Geier <geieredgar@gmail.com>
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
- After https://github.com/bevyengine/bevy/pull/9903, example
`mesh2d_manual` doesn't render anything
## Solution
- Fix the example using the new `RenderMesh2dInstances`
# Objective
- Fix TextureAtlasBuilder padding issue
TextureAtlasBuilder padding is reserved during add_texture() but can
still be changed afterwards. This means that changing padding after the
textures will be wrongly applied, either distorting the textures or
panicking if new padding is higher than texture+old padding.
## Solution
- Delay applying padding until finish()
# Objective
Allow Bevy apps to run without requiring to start from the main thread.
This allows other projects and applications to do things like spawning a
normal or scoped
thread and run Bevy applications there.
The current behaviour if you try this is a panic.
## Solution
Allow this by default on platforms winit supports this behaviour on
(x11, Wayland, Windows).
---
## Changelog
### Added
- Added the ability to start Bevy apps outside of the main thread on
x11, Wayland, Windows
---------
Signed-off-by: Torstein Grindvik <torstein.grindvik@nordicsemi.no>
Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Fixes#8140
## Solution
- Added Explicit Error Typing for `AssetLoader` and `AssetSaver`, which
were the last instances of `anyhow` in use across Bevy.
---
## Changelog
- Added an associated type `Error` to `AssetLoader` and `AssetSaver` for
use with the `load` and `save` methods respectively.
- Changed `ErasedAssetLoader` and `ErasedAssetSaver` `load` and `save`
methods to use `Box<dyn Error + Send + Sync + 'static>` to allow for
arbitrary `Error` types from the non-erased trait variants. Note the
strict requirements match the pre-existing requirements around
`anyhow::Error`.
## Migration Guide
- `anyhow` is no longer exported by `bevy_asset`; Add it to your own
project (if required).
- `AssetLoader` and `AssetSaver` have an associated type `Error`; Define
an appropriate error type (e.g., using `thiserror`), or use a pre-made
error type (e.g., `anyhow::Error`). Note that using `anyhow::Error` is a
drop-in replacement.
- `AssetLoaderError` has been removed; Define a new error type, or use
an alternative (e.g., `anyhow::Error`)
- All the first-party `AssetLoader`'s and `AssetSaver`'s now return
relevant (and narrow) error types instead of a single ambiguous type;
Match over the specific error type, or encapsulate (`Box<dyn>`,
`thiserror`, `anyhow`, etc.)
## Notes
A simpler PR to resolve this issue would simply define a Bevy `Error`
type defined as `Box<dyn std::error::Error + Send + Sync + 'static>`,
but I think this type of error handling should be discouraged when
possible. Since only 2 traits required the use of `anyhow`, it isn't a
substantive body of work to solidify these error types, and remove
`anyhow` entirely. End users are still encouraged to use `anyhow` if
that is their preferred error handling style. Arguably, adding the
`Error` associated type gives more freedom to end-users to decide
whether they want more or less explicit error handling (`anyhow` vs
`thiserror`).
As an aside, I didn't perform any testing on Android or WASM. CI passed
locally, but there may be mistakes for those platforms I missed.
# Objective
assets v2 broke custom shader imports. fix them
## Solution
store handles of any file dependencies in the `Shader` to avoid them
being immediately dropped.
also added a use into the `shader_material` example so that it'll be
harder to break support in future.
# Objective
- Updates for rust 1.73
## Solution
- new doc check for `redundant_explicit_links`
- updated to text for compile fail tests
---
## Changelog
- updates for rust 1.73
# Objective
https://github.com/bevyengine/bevy/pull/7328 introduced an API to
override the global wireframe config. I believe it is flawed for a few
reasons.
This PR uses a non-breaking API. Instead of making the `Wireframe` an
enum I introduced the `NeverRenderWireframe` component. Here's the
reason why I think this is better:
- Easier to migrate since it doesn't change the old behaviour.
Essentially nothing to migrate. Right now this PR is a breaking change
but I don't think it has to be.
- It's similar to other "per mesh" rendering features like
NotShadowCaster/NotShadowReceiver
- It doesn't force new users to also think about global vs not global if
all they want is to render a wireframe
- This would also let you filter at the query definition level instead
of filtering when running the query
## Solution
- Introduce a `NeverRenderWireframe` component that ignores the global
config
---
## Changelog
- Added a `NeverRenderWireframe` component that ignores the global
`WireframeConfig`
# Objective
Add support for drawing outlines outside the borders of UI nodes.
## Solution
Add a new `Outline` component with `width`, `offset` and `color` fields.
Added `outline_width` and `outline_offset` fields to `Node`. This is set
after layout recomputation by the `resolve_outlines_system`.
Properties of outlines:
* Unlike borders, outlines have to be the same width on each edge.
* Outlines do not occupy any space in the layout.
* The `Outline` component won't be added to any of the UI node bundles,
it needs to be inserted separately.
* Outlines are drawn outside the node's border, so they are clipped
using the clipping rect of their entity's parent UI node (if it exists).
* `Val::Percent` outline widths are resolved based on the width of the
outlined UI node.
* The offset of the `Outline` adds space between an outline and the edge
of its node.
I was leaning towards adding an `outline` field to `Style` but a
separate component seems more efficient for queries and change
detection. The `Outline` component isn't added to bundles for the same
reason.
---
## Examples
* This image is from the `borders` example from the Bevy UI examples but
modified to include outlines. The UI nodes are the dark red rectangles,
the bright red rectangles are borders and the white lines offset from
each node are the outlines. The yellow rectangles are separate nodes
contained with the dark red nodes:
<img width="406" alt="outlines"
src="https://github.com/bevyengine/bevy/assets/27962798/4e6f315a-019f-42a4-94ee-cca8e684d64a">
* This is from the same example but using a branch that implements
border-radius. Here the the outlines are in orange and there is no
offset applied. I broke the borders implementation somehow during the
merge, which is why some of the borders from the first screenshot are
missing 😅. The outlines work nicely though (as long as you
can forgive the lack of anti-aliasing):
![image](https://github.com/bevyengine/bevy/assets/27962798/d15560b6-6cd6-42e5-907b-56ccf2ad5e02)
---
## Notes
As I explained above, I don't think the `Outline` component should be
added to UI node bundles. We can have helper functions though, perhaps
something as simple as:
```rust
impl NodeBundle {
pub fn with_outline(self, outline: Outline) -> (Self, Outline) {
(self, outline)
}
}
```
I didn't include anything like this as I wanted to keep the PR's scope
as narrow as possible. Maybe `with_outline` should be in a trait that we
implement for each UI node bundle.
---
## Changelog
Added support for outlines to Bevy UI.
* The `Outline` component adds an outline to a UI node.
* The `outline_width` field added to `Node` holds the resolved width of
the outline, which is set by the `resolve_outlines_system` after layout
recomputation.
* Outlines are drawn by the system `extract_uinode_outlines`.
# Objective
- When I've tested alternative async executors with bevy a common
problem is that they deadlock when we try to run nested scopes. i.e.
running a multithreaded schedule from inside another multithreaded
schedule. This adds a test to bevy_tasks for that so the issue can be
spotted earlier while developing.
## Changelog
- add a test for nested scopes.
# Objective
Fix warnings:
- #[warn(clippy::needless_pass_by_ref_mut)]
- #[warn(elided_lifetimes_in_associated_constant)]
## Solution
- Remove mut
- add &'static
## Errors
```rust
warning: this argument is a mutable reference, but not used mutably
--> crates/bevy_hierarchy/src/child_builder.rs:672:31
|
672 | fn assert_children(world: &mut World, parent: Entity, children: Option<&[Entity]>) {
| ^^^^^^^^^^ help: consider changing to: `&World`
|
= note: this is cfg-gated and may require further changes
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
= note: `#[warn(clippy::needless_pass_by_ref_mut)]` on by default
```
```rust
warning: `&` without an explicit lifetime name cannot be used here
--> examples/shader/post_processing.rs:120:21
|
120 | pub const NAME: &str = "post_process";
| ^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
= note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default
help: use the `'static` lifetime
|
120 | pub const NAME: &'static str = "post_process";
| +++++++
```
# Objective
Allow the user to choose between "Add wireframes to these specific
entities" or "Add wireframes to everything _except_ these specific
entities".
Fixes#7309
# Solution
Make the `Wireframe` component act like an override to the global
configuration.
Having `global` set to `false`, and adding a `Wireframe` with `enable:
true` acts exactly as before.
But now the opposite is also possible: Set `global` to `true` and add a
`Wireframe` with `enable: false` will draw wireframes for everything
_except_ that entity.
Updated the example to show how overriding the global config works.
# Objective
- Fixes#9884
- Add API for ignoring ambiguities on certain resource or components.
## Solution
- Add a `IgnoreSchedulingAmbiguitiy` resource to the world which holds
the `ComponentIds` to be ignored
- Filter out ambiguities with those component id's.
## Changelog
- add `allow_ambiguous_component` and `allow_ambiguous_resource` apis
for ignoring ambiguities
---------
Co-authored-by: Ryan Johnson <ryanj00a@gmail.com>
# Objective
- Finish documenting `bevy_gltf`.
## Solution
- Document the remaining items, add links to the glTF spec where
relevant. Add the `warn(missing_doc)` attribute.
# Objective
- See fewer warnings when running `cargo clippy` locally.
## Solution
- allow `clippy::type_complexity` in more places, which also signals to
users they should do the same.
# Objective
`bevy_a11y` was impossible to integrate into some third-party projects
in part because it insisted on managing the accessibility tree on its
own.
## Solution
The changes in this PR were necessary to get `bevy_egui` working with
Bevy's AccessKit integration. They were tested on a fork of 0.11,
developed against `bevy_egui`, then ported to main and tested against
the `ui` example.
## Changelog
### Changed
* Add `bevy_a11y::ManageAccessibilityUpdates` to indicate whether the
ECS should manage accessibility tree updates.
* Add getter/setter to `bevy_a11y::AccessibilityRequested`.
* Add `bevy_a11y::AccessibilitySystem` `SystemSet` for ordering relative
to accessibility tree updates.
* Upgrade `accesskit` to v0.12.0.
### Fixed
* Correctly set initial accessibility focus to new windows on creation.
## Migration Guide
### Change direct accesses of `AccessibilityRequested` to use
`AccessibilityRequested.::get()`/`AccessibilityRequested::set()`
#### Before
```
use std::sync::atomic::Ordering;
// To access
accessibility_requested.load(Ordering::SeqCst)
// To update
accessibility_requested.store(true, Ordering::SeqCst);
```
#### After
```
// To access
accessibility_requested.get()
// To update
accessibility_requested.set(true);
```
---------
Co-authored-by: StaffEngineer <111751109+StaffEngineer@users.noreply.github.com>
Conventionally, the second UV map (`TEXCOORD1`, `UV1`) is used for
lightmap UVs. This commit allows Bevy to import them, so that a custom
shader that applies lightmaps can use those UVs if desired.
Note that this doesn't actually apply lightmaps to Bevy meshes; that
will be a followup. It does, however, open the door to future Bevy
plugins that implement baked global illumination.
## Changelog
### Added
The Bevy glTF loader now imports a second UV channel (`TEXCOORD1`,
`UV1`) from meshes if present. This can be used by custom shaders to
implement lightmapping.
# Objective
- Handle suspend / resume events on Android without exiting
## Solution
- On suspend: despawn the window, and set the control flow to wait for
events from the OS
- On resume: spawn a new window, and set the control flow to poll
In this video, you can see the Android example being suspended, stopping
receiving events, and working again after being resumed
https://github.com/bevyengine/bevy/assets/8672791/aaaf4b09-ee6a-4a0d-87ad-41f05def7945
Objective
---------
- Since #6742, It is not possible to build an `ArchetypeId` from a
`ArchetypeGeneration`
- This was useful to 3rd party crate extending the base bevy ECS
capabilities, such as [`bevy_ecs_dynamic`] and now
[`bevy_mod_dynamic_query`]
- Making `ArchetypeGeneration` opaque this way made it completely
useless, and removed the ability to limit archetype updates to a subset
of archetypes.
- Making the `index` method on `ArchetypeId` private prevented the use
of bitfields and other optimized data structure to store sets of
archetype ids. (without `transmute`)
This PR is not a simple reversal of the change. It exposes a different
API, rethought to keep the private stuff private and the public stuff
less error-prone.
- Add a `StartRange<ArchetypeGeneration>` `Index` implementation to
`Archetypes`
- Instead of converting the generation into an index, then creating a
ArchetypeId from that index, and indexing `Archetypes` with it, use
directly the old `ArchetypeGeneration` to get the range of new
archetypes.
From careful benchmarking, it seems to also be a performance improvement
(~0-5%) on add_archetypes.
---
Changelog
---------
- Added `impl Index<RangeFrom<ArchetypeGeneration>> for Archetypes` this
allows you to get a slice of newly added archetypes since the last
recorded generation.
- Added `ArchetypeId::index` and `ArchetypeId::new` methods. It should
enable 3rd party crates to use the `Archetypes` API in a meaningful way.
[`bevy_ecs_dynamic`]:
https://github.com/jakobhellermann/bevy_ecs_dynamic/tree/main
[`bevy_mod_dynamic_query`]:
https://github.com/nicopap/bevy_mod_dynamic_query/
---------
Co-authored-by: vero <email@atlasdostal.com>
# Objective
We've done a lot of work to remove the pattern of a `&World` with
interior mutability (#6404, #8833). However, this pattern still persists
within `bevy_ecs` via the `unsafe_world` method.
## Solution
* Make `unsafe_world` private. Adjust any callsites to use
`UnsafeWorldCell` for interior mutability.
* Add `UnsafeWorldCell::removed_components`, since it is always safe to
access the removed components collection through `UnsafeWorldCell`.
## Future Work
Remove/hide `UnsafeWorldCell::world_metadata`, once we have provided
safe ways of accessing all world metadata.
---
## Changelog
+ Added `UnsafeWorldCell::removed_components`, which provides read-only
access to a world's collection of removed components.
# Objective
- Fixes#4610
## Solution
- Replaced all instances of `parking_lot` locks with equivalents from
`std::sync`. Acquiring locks within `std::sync` can fail, so
`.expect("Lock Poisoned")` statements were added where required.
## Comments
In [this
comment](https://github.com/bevyengine/bevy/issues/4610#issuecomment-1592407881),
the lack of deadlock detection was mentioned as a potential reason to
not make this change. From what I can gather, Bevy doesn't appear to be
using this functionality within the engine. Unless it was expected that
a Bevy consumer was expected to enable and use this functionality, it
appears to be a feature lost without consequence.
Unfortunately, `cpal` and `wgpu` both still rely on `parking_lot`,
leaving it in the dependency graph even after this change.
From my basic experimentation, this change doesn't appear to have any
performance impacts, positive or negative. I tested this using
`bevymark` with 50,000 entities and observed 20ms of frame-time before
and after the change. More extensive testing with larger/real projects
should probably be done.
# Objective
`Has<T>` was added to bevy_ecs, but we're still using the
`Option<With<T>>` pattern in multiple locations.
## Solution
Replace them with `Has<T>`.
# Objective
Add a new method so you can do `set_if_neq` with dereferencing
components: `as_deref_mut()`!
## Solution
Added an as_deref_mut method so that we can use `set_if_neq()` without
having to wrap up types for derefencable components
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
# Objective
- Fixes#9363
## Solution
Moved `fq_std` from `bevy_reflect_derive` to `bevy_macro_utils`. This
does make the `FQ*` types public where they were previously private,
which is a change to the public-facing API, but I don't believe a
breaking one. Additionally, I've done a basic QA pass over the
`bevy_macro_utils` crate, adding `deny(unsafe)`, `warn(missing_docs)`,
and documentation where required.
# Objective
Avert a panic when removing resources from Scenes.
### Reproduction Steps
```rust
let mut scene = Scene::new(World::default());
scene.world.init_resource::<Time>();
scene.world.remove_resource::<Time>();
scene.clone_with(&app.resource::<AppTypeRegistry>());
```
### Panic Message
```
thread 'Compute Task Pool (10)' panicked at 'Requested resource bevy_time::time::Time does not exist in the `World`.
Did you forget to add it using `app.insert_resource` / `app.init_resource`?
Resources are also implicitly added via `app.add_event`,
and can be added by plugins.', .../bevy/crates/bevy_ecs/src/reflect/resource.rs:203:52
```
## Solution
Check that the resource actually still exists before copying.
---
## Changelog
- resolved a panic caused by removing resources from scenes
# Objective
Finish documenting `bevy_scene`.
## Solution
Document the remaining items and add a crate-level `warn(missing_doc)`
attribute as for the other crates with completed documentation.
# Objective
`extract_meshes` can easily be one of the most expensive operations in
the blocking extract schedule for 3D apps. It also has no fundamentally
serialized parts and can easily be run across multiple threads. Let's
speed it up by parallelizing it!
## Solution
Use the `ThreadLocal<Cell<Vec<T>>>` approach utilized by #7348 in
conjunction with `Query::par_iter` to build a set of thread-local
queues, and collect them after going wide.
## Performance
Using `cargo run --profile stress-test --features trace_tracy --example
many_cubes`. Yellow is this PR. Red is main.
`extract_meshes`:
![image](https://github.com/bevyengine/bevy/assets/3137680/9d45aa2e-3cfa-4fad-9c08-53498b51a73b)
An average reduction from 1.2ms to 770us is seen, a 41.6% improvement.
Note: this is still not including #9950's changes, so this may actually
result in even faster speedups once that's merged in.
# Objective
- sometimes when bevy shuts down on certain machines the render thread
tries to send the time after the main world has been dropped.
- fixes an error mentioned in a reply in
https://github.com/bevyengine/bevy/issues/9543
---
## Changelog
- ignore disconnected errors from the time channel.
# Objective
The `States::variants` method was once used to construct `OnExit` and
`OnEnter` schedules for every possible value of a given `States` type.
[Since the switch to lazily initialized
schedules](https://github.com/bevyengine/bevy/pull/8028/files#diff-b2fba3a0c86e496085ce7f0e3f1de5960cb754c7d215ed0f087aa556e529f97f),
we no longer need to track every possible value.
This also opens the door to `States` types that aren't enums.
## Solution
- Remove the unused `States::variants` method and its associated type.
- Remove the enum-only restriction on derived States types.
---
## Changelog
- Removed `States::variants` and its associated type.
- Derived `States` can now be datatypes other than enums.
## Migration Guide
- `States::variants` no longer exists. If you relied on this function,
consider using a library that provides enum iterators.
# Objective
I was wondering whether to use `Timer::finished` or
`Timer::just_finished` for my repeating timer. This PR clarifies their
difference (or rather, lack thereof).
## Solution
More docs & examples.
# Objective
- There were a few typos in the project.
- This PR fixes these typos.
## Solution
- Fixing the typos.
Signed-off-by: SADIK KUZU <sadikkuzu@hotmail.com>
# Objective
In order to derive `Asset`s (v2), `TypePath` must also be implemented.
`TypePath` is not currently in the prelude, but given it is *required*
when deriving something that *is* in the prelude, I think it deserves to
be added.
## Solution
Add `TypePath` to `bevy_reflect::prelude`.
# Objective
Text bounds are computed by the layout algorithm using the text's
measurefunc so that text will only wrap after it's used the maximum
amount of available horizontal space.
When the layout size is returned the layout coordinates are rounded and
this sometimes results in the final size of the Node not matching the
size computed with the measurefunc. This means that the text may no
longer fit the horizontal available space and instead wrap onto a new
line. However, no glyphs will be generated for this new line because no
vertical space for the extra line was allocated.
fixes#9874
## Solution
Store both the rounded and unrounded node sizes in `Node`.
Rounding is used to eliminate pixel-wide gaps between nodes that should
be touching edge to edge, but this isn't necessary for text nodes as
they don't have solid edges.
## Changelog
* Added the `rounded_size: Vec2` field to `Node`.
* `text_system` uses the unrounded node size when computing a text
layout.
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
Improve compatibility with macOS Sonoma and Xcode 15.0.
## Solution
- Adds the workaround by @ptxmac to ignore the invalid window sizes
provided by `winit` on macOS 14.0
- This still provides a slightly wrong content size when resizing (it
fails to account for the window title bar, so some content gets clipped
at the bottom) but it's _much better_ than crashing.
- Adds docs on how to work around the `bindgen` bug on Xcode 15.0.
## Related Issues:
- https://github.com/RustAudio/coreaudio-sys/issues/85
- https://github.com/rust-windowing/winit/issues/2876
---
## Changelog
- Added a workaround for a `winit`-related crash under macOS Sonoma
(14.0)
---------
Co-authored-by: Peter Kristensen <peter@ptx.dk>
# Objective
- Improve rendering performance, particularly by avoiding the large
system commands costs of using the ECS in the way that the render world
does.
## Solution
- Define `EntityHasher` that calculates a hash from the
`Entity.to_bits()` by `i | (i.wrapping_mul(0x517cc1b727220a95) << 32)`.
`0x517cc1b727220a95` is something like `u64::MAX / N` for N that gives a
value close to π and that works well for hashing. Thanks for @SkiFire13
for the suggestion and to @nicopap for alternative suggestions and
discussion. This approach comes from `rustc-hash` (a.k.a. `FxHasher`)
with some tweaks for the case of hashing an `Entity`. `FxHasher` and
`SeaHasher` were also tested but were significantly slower.
- Define `EntityHashMap` type that uses the `EntityHashser`
- Use `EntityHashMap<Entity, T>` for render world entity storage,
including:
- `RenderMaterialInstances` - contains the `AssetId<M>` of the material
associated with the entity. Also for 2D.
- `RenderMeshInstances` - contains mesh transforms, flags and properties
about mesh entities. Also for 2D.
- `SkinIndices` and `MorphIndices` - contains the skin and morph index
for an entity, respectively
- `ExtractedSprites`
- `ExtractedUiNodes`
## Benchmarks
All benchmarks have been conducted on an M1 Max connected to AC power.
The tests are run for 1500 frames. The 1000th frame is captured for
comparison to check for visual regressions. There were none.
### 2D Meshes
`bevymark --benchmark --waves 160 --per-wave 1000 --mode mesh2d`
#### `--ordered-z`
This test spawns the 2D meshes with z incrementing back to front, which
is the ideal arrangement allocation order as it matches the sorted
render order which means lookups have a high cache hit rate.
<img width="1112" alt="Screenshot 2023-09-27 at 07 50 45"
src="https://github.com/bevyengine/bevy/assets/302146/e140bc98-7091-4a3b-8ae1-ab75d16d2ccb">
-39.1% median frame time.
#### Random
This test spawns the 2D meshes with random z. This not only makes the
batching and transparent 2D pass lookups get a lot of cache misses, it
also currently means that the meshes are almost certain to not be
batchable.
<img width="1108" alt="Screenshot 2023-09-27 at 07 51 28"
src="https://github.com/bevyengine/bevy/assets/302146/29c2e813-645a-43ce-982a-55df4bf7d8c4">
-7.2% median frame time.
### 3D Meshes
`many_cubes --benchmark`
<img width="1112" alt="Screenshot 2023-09-27 at 07 51 57"
src="https://github.com/bevyengine/bevy/assets/302146/1a729673-3254-4e2a-9072-55e27c69f0fc">
-7.7% median frame time.
### Sprites
**NOTE: On `main` sprites are using `SparseSet<Entity, T>`!**
`bevymark --benchmark --waves 160 --per-wave 1000 --mode sprite`
#### `--ordered-z`
This test spawns the sprites with z incrementing back to front, which is
the ideal arrangement allocation order as it matches the sorted render
order which means lookups have a high cache hit rate.
<img width="1116" alt="Screenshot 2023-09-27 at 07 52 31"
src="https://github.com/bevyengine/bevy/assets/302146/bc8eab90-e375-4d31-b5cd-f55f6f59ab67">
+13.0% median frame time.
#### Random
This test spawns the sprites with random z. This makes the batching and
transparent 2D pass lookups get a lot of cache misses.
<img width="1109" alt="Screenshot 2023-09-27 at 07 53 01"
src="https://github.com/bevyengine/bevy/assets/302146/22073f5d-99a7-49b0-9584-d3ac3eac3033">
+0.6% median frame time.
### UI
**NOTE: On `main` UI is using `SparseSet<Entity, T>`!**
`many_buttons`
<img width="1111" alt="Screenshot 2023-09-27 at 07 53 26"
src="https://github.com/bevyengine/bevy/assets/302146/66afd56d-cbe4-49e7-8b64-2f28f6043d85">
+15.1% median frame time.
## Alternatives
- Cart originally suggested trying out `SparseSet<Entity, T>` and indeed
that is slightly faster under ideal conditions. However,
`PassHashMap<Entity, T>` has better worst case performance when data is
randomly distributed, rather than in sorted render order, and does not
have the worst case memory usage that `SparseSet`'s dense `Vec<usize>`
that maps from the `Entity` index to sparse index into `Vec<T>`. This
dense `Vec` has to be as large as the largest Entity index used with the
`SparseSet`.
- I also tested `PassHashMap<u32, T>`, intending to use `Entity.index()`
as the key, but this proved to sometimes be slower and mostly no
different.
- The only outstanding approach that has not been implemented and tested
is to _not_ clear the render world of its entities each frame. That has
its own problems, though they could perhaps be solved.
- Performance-wise, if the entities and their component data were not
cleared, then they would incur table moves on spawn, and should not
thereafter, rather just their component data would be overwritten.
Ideally we would have a neat way of either updating data in-place via
`&mut T` queries, or inserting components if not present. This would
likely be quite cumbersome to have to remember to do everywhere, but
perhaps it only needs to be done in the more performance-sensitive
systems.
- The main problem to solve however is that we want to both maintain a
mapping between main world entities and render world entities, be able
to run the render app and world in parallel with the main app and world
for pipelined rendering, and at the same time be able to spawn entities
in the render world in such a way that those Entity ids do not collide
with those spawned in the main world. This is potentially quite
solvable, but could well be a lot of ECS work to do it in a way that
makes sense.
---
## Changelog
- Changed: Component data for entities to be drawn are no longer stored
on entities in the render world. Instead, data is stored in a
`EntityHashMap<Entity, T>` in various resources. This brings significant
performance benefits due to the way the render app clears entities every
frame. Resources of most interest are `RenderMeshInstances` and
`RenderMaterialInstances`, and their 2D counterparts.
## Migration Guide
Previously the render app extracted mesh entities and their component
data from the main world and stored them as entities and components in
the render world. Now they are extracted into essentially
`EntityHashMap<Entity, T>` where `T` are structs containing an
appropriate group of data. This means that while extract set systems
will continue to run extract queries against the main world they will
store their data in hash maps. Also, systems in later sets will either
need to look up entities in the available resources such as
`RenderMeshInstances`, or maintain their own `EntityHashMap<Entity, T>`
for their own data.
Before:
```rust
fn queue_custom(
material_meshes: Query<(Entity, &MeshTransforms, &Handle<Mesh>), With<InstanceMaterialData>>,
) {
...
for (entity, mesh_transforms, mesh_handle) in &material_meshes {
...
}
}
```
After:
```rust
fn queue_custom(
render_mesh_instances: Res<RenderMeshInstances>,
instance_entities: Query<Entity, With<InstanceMaterialData>>,
) {
...
for entity in &instance_entities {
let Some(mesh_instance) = render_mesh_instances.get(&entity) else { continue; };
// The mesh handle in `AssetId<Mesh>` form, and the `MeshTransforms` can now
// be found in `mesh_instance` which is a `RenderMeshInstance`
...
}
}
```
---------
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
# Objective
Complete the documentation for `bevy_window`.
## Solution
The `warn(missing_doc)` attribute was only applying to the `cursor`
module as it was declared as an inner attribute. I switched it to an
outer attribute and documented the remaining items.
# Objective
Fixes: #9898
## Solution
Make morph behave like other keyframes, lerping first between start and
end, and then between the current state and the result.
## Changelog
Fixed jerky morph targets
---------
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
Co-authored-by: CGMossa <cgmossa@gmail.com>
# Objective
The scetion for guides about flexbox has a link to grid and the section
for grid has a link to a guide about flexbox.
## Solution
Swapped links for flexbox and grid.
---
This is a duplicate of #9632, it was created since I forgot to make a
new branch when I first made this PR, so I was having trouble resolving
merge conflicts, meaning I had to rebuild my PR.
# Objective
- Allow other plugins to create the renderer resources. An example of
where this would be required is my [OpenXR
plugin](https://github.com/awtterpip/bevy_openxr)
## Solution
- Changed the bevy RenderPlugin to optionally take precreated render
resources instead of a configuration.
## Migration Guide
The `RenderPlugin` now takes a `RenderCreation` enum instead of
`WgpuSettings`. `RenderSettings::default()` returns
`RenderSettings::Automatic(WgpuSettings::default())`. `RenderSettings`
also implements `From<WgpuSettings>`.
```rust
// before
RenderPlugin {
wgpu_settings: WgpuSettings {
...
},
}
// now
RenderPlugin {
render_creation: RenderCreation::Automatic(WgpuSettings {
...
}),
}
// or
RenderPlugin {
render_creation: WgpuSettings {
...
}.into(),
}
```
---------
Co-authored-by: Malek <pocmalek@gmail.com>
Co-authored-by: Robert Swain <robert.swain@gmail.com>
# Objective
Some beginners spend time trying to manually set the position of a
`TextBundle`, without realizing that `Text2dBundle` exists.
## Solution
Mention `Text2dBundle` in the documentation of `TextBundle`.
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
Fixes#9625
## Solution
Adds `async-io` as an optional dependency of `bevy_tasks`. When enabled,
this causes calls to `futures_lite::future::block_on` to be replaced
with calls to `async_io::block_on`.
---
## Changelog
- Added a new `async-io` feature to `bevy_tasks`. When enabled, this
causes `bevy_tasks` to use `async-io`'s implemention of `block_on`
instead of `futures-lite`'s implementation. You should enable this if
you use `async-io` in your application.
# Objective
This is a minimally disruptive version of #8340. I attempted to update
it, but failed due to the scope of the changes added in #8204.
Fixes#8307. Partially addresses #4642. As seen in
https://github.com/bevyengine/bevy/issues/8284, we're actually copying
data twice in Prepare stage systems. Once into a CPU-side intermediate
scratch buffer, and once again into a mapped buffer. This is inefficient
and effectively doubles the time spent and memory allocated to run these
systems.
## Solution
Skip the scratch buffer entirely and use
`wgpu::Queue::write_buffer_with` to directly write data into mapped
buffers.
Separately, this also directly uses
`wgpu::Limits::min_uniform_buffer_offset_alignment` to set up the
alignment when writing to the buffers. Partially addressing the issue
raised in #4642.
Storage buffers and the abstractions built on top of
`DynamicUniformBuffer` will need to come in followup PRs.
This may not have a noticeable performance difference in this PR, as the
only first-party systems affected by this are view related, and likely
are not going to be particularly heavy.
---
## Changelog
Added: `DynamicUniformBuffer::get_writer`.
Added: `DynamicUniformBufferWriter`.
derive `Reflect` to `GlyphAtlasInfo`,`PositionedGlyph` and
`TextLayoutInfo`.
# Objective
- I need reflection gets all components of the `TextBundle` and
`clone_value` it
## Solution
- registry it
# Objective
mesh.rs is infamously large. We could split off unrelated code.
## Solution
Morph targets are very similar to skinning and have their own module. We
move skinned meshes to an independent module like morph targets and give
the systems similar names.
### Open questions
Should the skinning systems and structs stay public?
---
## Migration Guide
Renamed skinning systems, resources and components:
- extract_skinned_meshes -> extract_skins
- prepare_skinned_meshes -> prepare_skins
- SkinnedMeshUniform -> SkinUniform
- SkinnedMeshJoints -> SkinIndex
---------
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: vero <email@atlasdostal.com>
# Objective
Scheduling low cost systems has significant overhead due to task pool
contention and the extra machinery to schedule and run them. Event
update systems are the prime example of a low cost system, requiring a
guaranteed O(1) operation, and there are a *lot* of them.
## Solution
Add a run condition to every event system so they only run when there is
an event in either of it's two internal Vecs.
---
## Changelog
Changed: Event update systems will not run if there are no events to
process.
## Migration Guide
`Events<T>::update_system` has been split off from the the type and can
be found at `bevy_ecs::event::event_update_system`.
---------
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
- Fixes#9707
## Solution
- At large translations (a few thousand units), the precision of
calculating the ray direction from the fragment world position and
camera world position seems to break down. Sampling the cubemap only
needs the ray direction. As such we can use the view space fragment
position, normalise it, rotate it to world space, and use that.
---
## Changelog
- Fixed: Jittery skybox at large translations.
# Objective
- https://github.com/bevyengine/bevy/pull/7609 broke Android support
```
8721 8770 I event crates/bevy_winit/src/system.rs:55: Creating new window "App" (0v0)
8721 8769 I RustStdoutStderr: thread '<unnamed>' panicked at 'Cannot get the native window, it's null and will always be null before Event::Resumed and after Event::Suspended. Make sure you only call this function between those events.', winit-0.28.6/src/platform_impl/android/mod.rs:1058:13
```
## Solution
- Don't create windows on `StartCause::Init` as it's too early
# Objective
- Make it possible to write APIs that require a type or homogenous
storage for both `Children` & `Parent` that is agnostic to edge
direction.
## Solution
- Add a way to get the `Entity` from `Parent` as a slice.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
# Objective
- Implement the foundations of automatic batching/instancing of draw
commands as the next step from #89
- NOTE: More performance improvements will come when more data is
managed and bound in ways that do not require rebinding such as mesh,
material, and texture data.
## Solution
- The core idea for batching of draw commands is to check whether any of
the information that has to be passed when encoding a draw command
changes between two things that are being drawn according to the sorted
render phase order. These should be things like the pipeline, bind
groups and their dynamic offsets, index/vertex buffers, and so on.
- The following assumptions have been made:
- Only entities with prepared assets (pipelines, materials, meshes) are
queued to phases
- View bindings are constant across a phase for a given draw function as
phases are per-view
- `batch_and_prepare_render_phase` is the only system that performs this
batching and has sole responsibility for preparing the per-object data.
As such the mesh binding and dynamic offsets are assumed to only vary as
a result of the `batch_and_prepare_render_phase` system, e.g. due to
having to split data across separate uniform bindings within the same
buffer due to the maximum uniform buffer binding size.
- Implement `GpuArrayBuffer` for `Mesh2dUniform` to store Mesh2dUniform
in arrays in GPU buffers rather than each one being at a dynamic offset
in a uniform buffer. This is the same optimisation that was made for 3D
not long ago.
- Change batch size for a range in `PhaseItem`, adding API for getting
or mutating the range. This is more flexible than a size as the length
of the range can be used in place of the size, but the start and end can
be otherwise whatever is needed.
- Add an optional mesh bind group dynamic offset to `PhaseItem`. This
avoids having to do a massive table move just to insert
`GpuArrayBufferIndex` components.
## Benchmarks
All tests have been run on an M1 Max on AC power. `bevymark` and
`many_cubes` were modified to use 1920x1080 with a scale factor of 1. I
run a script that runs a separate Tracy capture process, and then runs
the bevy example with `--features bevy_ci_testing,trace_tracy` and
`CI_TESTING_CONFIG=../benchmark.ron` with the contents of
`../benchmark.ron`:
```rust
(
exit_after: Some(1500)
)
```
...in order to run each test for 1500 frames.
The recent changes to `many_cubes` and `bevymark` added reproducible
random number generation so that with the same settings, the same rng
will occur. They also added benchmark modes that use a fixed delta time
for animations. Combined this means that the same frames should be
rendered both on main and on the branch.
The graphs compare main (yellow) to this PR (red).
### 3D Mesh `many_cubes --benchmark`
<img width="1411" alt="Screenshot 2023-09-03 at 23 42 10"
src="https://github.com/bevyengine/bevy/assets/302146/2088716a-c918-486c-8129-090b26fd2bc4">
The mesh and material are the same for all instances. This is basically
the best case for the initial batching implementation as it results in 1
draw for the ~11.7k visible meshes. It gives a ~30% reduction in median
frame time.
The 1000th frame is identical using the flip tool:
![flip many_cubes-main-mesh3d many_cubes-batching-mesh3d 67ppd
ldr](https://github.com/bevyengine/bevy/assets/302146/2511f37a-6df8-481a-932f-706ca4de7643)
```
Mean: 0.000000
Weighted median: 0.000000
1st weighted quartile: 0.000000
3rd weighted quartile: 0.000000
Min: 0.000000
Max: 0.000000
Evaluation time: 0.4615 seconds
```
### 3D Mesh `many_cubes --benchmark --material-texture-count 10`
<img width="1404" alt="Screenshot 2023-09-03 at 23 45 18"
src="https://github.com/bevyengine/bevy/assets/302146/5ee9c447-5bd2-45c6-9706-ac5ff8916daf">
This run uses 10 different materials by varying their textures. The
materials are randomly selected, and there is no sorting by material
bind group for opaque 3D so any batching is 'random'. The PR produces a
~5% reduction in median frame time. If we were to sort the opaque phase
by the material bind group, then this should be a lot faster. This
produces about 10.5k draws for the 11.7k visible entities. This makes
sense as randomly selecting from 10 materials gives a chance that two
adjacent entities randomly select the same material and can be batched.
The 1000th frame is identical in flip:
![flip many_cubes-main-mesh3d-mtc10 many_cubes-batching-mesh3d-mtc10
67ppd
ldr](https://github.com/bevyengine/bevy/assets/302146/2b3a8614-9466-4ed8-b50c-d4aa71615dbb)
```
Mean: 0.000000
Weighted median: 0.000000
1st weighted quartile: 0.000000
3rd weighted quartile: 0.000000
Min: 0.000000
Max: 0.000000
Evaluation time: 0.4537 seconds
```
### 3D Mesh `many_cubes --benchmark --vary-per-instance`
<img width="1394" alt="Screenshot 2023-09-03 at 23 48 44"
src="https://github.com/bevyengine/bevy/assets/302146/f02a816b-a444-4c18-a96a-63b5436f3b7f">
This run varies the material data per instance by randomly-generating
its colour. This is the worst case for batching and that it performs
about the same as `main` is a good thing as it demonstrates that the
batching has minimal overhead when dealing with ~11k visible mesh
entities.
The 1000th frame is identical according to flip:
![flip many_cubes-main-mesh3d-vpi many_cubes-batching-mesh3d-vpi 67ppd
ldr](https://github.com/bevyengine/bevy/assets/302146/ac5f5c14-9bda-4d1a-8219-7577d4aac68c)
```
Mean: 0.000000
Weighted median: 0.000000
1st weighted quartile: 0.000000
3rd weighted quartile: 0.000000
Min: 0.000000
Max: 0.000000
Evaluation time: 0.4568 seconds
```
### 2D Mesh `bevymark --benchmark --waves 160 --per-wave 1000 --mode
mesh2d`
<img width="1412" alt="Screenshot 2023-09-03 at 23 59 56"
src="https://github.com/bevyengine/bevy/assets/302146/cb02ae07-237b-4646-ae9f-fda4dafcbad4">
This spawns 160 waves of 1000 quad meshes that are shaded with
ColorMaterial. Each wave has a different material so 160 waves currently
should result in 160 batches. This results in a 50% reduction in median
frame time.
Capturing a screenshot of the 1000th frame main vs PR gives:
![flip bevymark-main-mesh2d bevymark-batching-mesh2d 67ppd
ldr](https://github.com/bevyengine/bevy/assets/302146/80102728-1217-4059-87af-14d05044df40)
```
Mean: 0.001222
Weighted median: 0.750432
1st weighted quartile: 0.453494
3rd weighted quartile: 0.969758
Min: 0.000000
Max: 0.990296
Evaluation time: 0.4255 seconds
```
So they seem to produce the same results. I also double-checked the
number of draws. `main` does 160000 draws, and the PR does 160, as
expected.
### 2D Mesh `bevymark --benchmark --waves 160 --per-wave 1000 --mode
mesh2d --material-texture-count 10`
<img width="1392" alt="Screenshot 2023-09-04 at 00 09 22"
src="https://github.com/bevyengine/bevy/assets/302146/4358da2e-ce32-4134-82df-3ab74c40849c">
This generates 10 textures and generates materials for each of those and
then selects one material per wave. The median frame time is reduced by
50%. Similar to the plain run above, this produces 160 draws on the PR
and 160000 on `main` and the 1000th frame is identical (ignoring the fps
counter text overlay).
![flip bevymark-main-mesh2d-mtc10 bevymark-batching-mesh2d-mtc10 67ppd
ldr](https://github.com/bevyengine/bevy/assets/302146/ebed2822-dce7-426a-858b-b77dc45b986f)
```
Mean: 0.002877
Weighted median: 0.964980
1st weighted quartile: 0.668871
3rd weighted quartile: 0.982749
Min: 0.000000
Max: 0.992377
Evaluation time: 0.4301 seconds
```
### 2D Mesh `bevymark --benchmark --waves 160 --per-wave 1000 --mode
mesh2d --vary-per-instance`
<img width="1396" alt="Screenshot 2023-09-04 at 00 13 53"
src="https://github.com/bevyengine/bevy/assets/302146/b2198b18-3439-47ad-919a-cdabe190facb">
This creates unique materials per instance by randomly-generating the
material's colour. This is the worst case for 2D batching. Somehow, this
PR manages a 7% reduction in median frame time. Both main and this PR
issue 160000 draws.
The 1000th frame is the same:
![flip bevymark-main-mesh2d-vpi bevymark-batching-mesh2d-vpi 67ppd
ldr](https://github.com/bevyengine/bevy/assets/302146/a2ec471c-f576-4a36-a23b-b24b22578b97)
```
Mean: 0.001214
Weighted median: 0.937499
1st weighted quartile: 0.635467
3rd weighted quartile: 0.979085
Min: 0.000000
Max: 0.988971
Evaluation time: 0.4462 seconds
```
### 2D Sprite `bevymark --benchmark --waves 160 --per-wave 1000 --mode
sprite`
<img width="1396" alt="Screenshot 2023-09-04 at 12 21 12"
src="https://github.com/bevyengine/bevy/assets/302146/8b31e915-d6be-4cac-abf5-c6a4da9c3d43">
This just spawns 160 waves of 1000 sprites. There should be and is no
notable difference between main and the PR.
### 2D Sprite `bevymark --benchmark --waves 160 --per-wave 1000 --mode
sprite --material-texture-count 10`
<img width="1389" alt="Screenshot 2023-09-04 at 12 36 08"
src="https://github.com/bevyengine/bevy/assets/302146/45fe8d6d-c901-4062-a349-3693dd044413">
This spawns the sprites selecting a texture at random per instance from
the 10 generated textures. This has no significant change vs main and
shouldn't.
### 2D Sprite `bevymark --benchmark --waves 160 --per-wave 1000 --mode
sprite --vary-per-instance`
<img width="1401" alt="Screenshot 2023-09-04 at 12 29 52"
src="https://github.com/bevyengine/bevy/assets/302146/762c5c60-352e-471f-8dbe-bbf10e24ebd6">
This sets the sprite colour as being unique per instance. This can still
all be drawn using one batch. There should be no difference but the PR
produces median frame times that are 4% higher. Investigation showed no
clear sources of cost, rather a mix of give and take that should not
happen. It seems like noise in the results.
### Summary
| Benchmark | % change in median frame time |
| ------------- | ------------- |
| many_cubes | 🟩 -30% |
| many_cubes 10 materials | 🟩 -5% |
| many_cubes unique materials | 🟩 ~0% |
| bevymark mesh2d | 🟩 -50% |
| bevymark mesh2d 10 materials | 🟩 -50% |
| bevymark mesh2d unique materials | 🟩 -7% |
| bevymark sprite | 🟥 2% |
| bevymark sprite 10 materials | 🟥 0.6% |
| bevymark sprite unique materials | 🟥 4.1% |
---
## Changelog
- Added: 2D and 3D mesh entities that share the same mesh and material
(same textures, same data) are now batched into the same draw command
for better performance.
---------
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
Co-authored-by: Nicola Papale <nico@nicopap.ch>
# Objective
Improve code-gen for `QueryState::validate_world` and
`SystemState::validate_world`.
## Solution
* Move panics into separate, non-inlined functions, to reduce the code
size of the outer methods.
* Mark the panicking functions with `#[cold]` to help the compiler
optimize for the happy path.
* Mark the functions with `#[track_caller]` to make debugging easier.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
Fix a performance regression in the "[bevy vs
pixi](https://github.com/SUPERCILEX/bevy-vs-pixi)" benchmark.
This benchmark seems to have a slightly pathological distribution of `z`
values -- Sprites are spawned with a random `z` value with a child
sprite at `f32::EPSILON` relative to the parent.
See discussion here:
https://github.com/bevyengine/bevy/issues/8100#issuecomment-1726978633
## Solution
Use `radsort` for sorting `Transparent2d` `PhaseItem`s.
Use random `z` values in bevymark to stress the phase sort. Add an
`--ordered-z` option to `bevymark` that uses the old behavior.
## Benchmarks
mac m1 max
| benchmark | fps before | fps after | diff |
| - | - | - | - |
| bevymark --waves 120 --per-wave 1000 --random-z | 42.16 | 47.06 | 🟩
+11.6% |
| bevymark --waves 120 --per-wave 1000 | 52.50 | 52.29 | 🟥 -0.4% |
| bevymark --waves 120 --per-wave 1000 --mode mesh2d --random-z | 9.64 |
10.24 | 🟩 +6.2% |
| bevymark --waves 120 --per-wave 1000 --mode mesh2d | 15.83 | 15.59 | 🟥
-1.5% |
| bevy-vs-pixi | 39.71 | 59.88 | 🟩 +50.1% |
## Discussion
It's possible that `TransparentUi` should also change. We could probably
use `slice::sort_unstable_by_key` with the current sort key though, as
its items are always sorted and unique. I'd prefer to follow up later to
look into that.
Here's a survey of sorts used by other `PhaseItem`s
#### slice::sort_by_key
`Transparent2d`, `TransparentUi`
#### radsort
`Opaque3d`, `AlphaMask3d`, `Transparent3d`, `Opaque3dPrepass`,
`AlphaMask3dPrepass`, `Shadow`
I also tried `slice::sort_unstable_by_key` with a compound sort key
including `Entity`, but it didn't seem as promising and I didn't test it
as thoroughly.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Robert Swain <robert.swain@gmail.com>
# Objective
Some rendering system did heavy use of `if let`, and could be improved
by using `let else`.
## Solution
- Reduce rightward drift by using let-else over if-let
- Extract value-to-key mappings to their own functions so that the
system is less bloated, easier to understand
- Use a `let` binding instead of untupling in closure argument to reduce
indentation
## Note to reviewers
Enable the "no white space diff" for easier viewing.
In the "Files changed" view, click on the little cog right of the "Jump
to" text, on the row where the "Review changes" button is. then enable
the "Hide whitespace" checkbox and click reload.
# Objective
Rename the `num_font_atlases` method of `FontAtlasSet` to `len`.
All the function does is return the number of entries in its hashmap and
the unnatural naming only makes it harder to discover.
---
## Changelog
* Renamed the `num_font_atlases` method of `FontAtlasSet` to `len`.
## Migration Guide
The `num_font_atlases` method of `FontAtlasSet` has been renamed to
`len`.
# Objective
Occasionally, it is useful to pull `ComponentInfo` or
`ComponentDescriptor` out of the `Components` collection so that they
can be inspected without borrowing the whole `World`.
## Solution
Make `ComponentInfo` and `ComponentDescriptor` `Clone`, so that
reflection-heavy code can store them in a side table.
---
## Changelog
- Implement `Clone` for `ComponentInfo` and `ComponentDescriptor`
# Objective
- I spoke with some users in the ECS channel of bevy discord today and
they suggested that I implement a fallible form of .insert for
components.
- In my opinion, it would be nice to have a fallible .insert like
.try_insert (or to just make insert be fallible!) because it was causing
a lot of panics in my game. In my game, I am spawning terrain chunks and
despawning them in the Update loop. However, this was causing bevy_xpbd
to panic because it was trying to .insert some physics components on my
chunks and a race condition meant that its check to see if the entity
exists would pass but then the next execution step it would not exist
and would do an .insert and then panic. This means that there is no way
to avoid a panic with conditionals.
Luckily, bevy_xpbd does not care about inserting these components if the
entity is being deleted and so if there were a .try_insert, like this PR
provides it could use that instead in order to NOT panic.
( My interim solution for my own game has been to run the entity despawn
events in the Last schedule but really this is just a hack and I should
not be expected to manage the scheduling of despawns like this - it
should just be easy and simple. IF it just so happened that bevy_xpbd
ran .inserts in the Last schedule also, this would be an untenable soln
overall )
## Solution
- Describe the solution used to achieve the objective above.
Add a new command named TryInsert (entitycommands.try_insert) which
functions exactly like .insert except if the entity does not exist it
will not panic. Instead, it will log to info. This way, crates that are
attaching components in ways which they do not mind that the entity no
longer exists can just use try_insert instead of insert.
---
## Changelog
## Additional Thoughts
In my opinion, NOT panicing should really be the default and having an
.insert that does panic should be the odd edgecase but removing the
panic! from .insert seems a bit above my paygrade -- although i would
love to see it. My other thought is it would be good for .insert to
return an Option AND not panic but it seems it uses an event bus right
now so that seems to be impossible w the current architecture.
# Objective
- Fixes#9876
## Solution
- Reverted commit `5012a0fd57748ab6f146776368b4cf988bba1eaa` to restore
the previous default values for `OrthographicProjection`.
---
## Migration Guide
- Migration guide steps from #9537 should be removed for next release.
# Objective
Fix a typo introduced by #9497. While drafting the PR, the type was
originally called `VisibleInHierarchy` before I renamed it to
`InheritedVisibility`, but this field got left behind due to a typo.
# Objective
- When adding/removing bindings in large binding lists, git would
generate very difficult-to-read diffs
## Solution
- Move the `@group(X) @binding(Y)` into the same line as the binding
type declaration
# Objective
- `check_visibility` system in `bevy_render` had an
`Option<&NoFrustumCulling>` that could be replaced by `Has`, which is
theoretically faster and semantically more correct.
- It also had some awkward indenting due to very large closure argument
lists.
- Some of the tests could be written more concisely
## Solution
Use `Has`, move the tuple destructuring in a `let` binding, create a
function for the tests.
## Note to reviewers
Enable the "no white space diff" in the diff viewer to have a more
meaningful diff in the `check_visibility` system.
In the "Files changed" view, click on the little cog right of the "Jump
to" text, on the row where the "Review changes" button is. then enable
the "Hide whitespace" checkbox and click reload.
---
## Migration Guide
- The `check_visibility` system's `Option<&NoFrustumCulling>` parameter
has been replaced by `Has<NoFrustumCulling>`, if you were calling it
manually, you should change the type to match it
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
Currently, in bevy, it's valid to do `Query<&mut Foo, Changed<Foo>>`.
This assumes that `filter_fetch` and `fetch` are mutually exclusive,
because of the mutable reference to the tick that `Mut<Foo>` implies and
the reference that `Changed<Foo>` implies. However nothing guarantees
that.
## Solution
Documenting this assumption as a safety invariant is the least thing.
# Objective
`single_threaded_task_pool` emitted a warning:
```
warning: use of `default` to create a unit struct
--> crates/bevy_tasks/src/single_threaded_task_pool.rs:22:25
|
22 | Self(PhantomData::default())
| ^^^^^^^^^^^ help: remove this call to `default`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#default_constructed_unit_structs
= note: `#[warn(clippy::default_constructed_unit_structs)]` on by default
```
## Solution
fix the lint
I'm adopting this ~~child~~ PR.
# Objective
- Working with exclusive world access is not always easy: in many cases,
a standard system or three is more ergonomic to write, and more
modularly maintainable.
- For small, one-off tasks (commonly handled with scripting), running an
event-reader system incurs a small but flat overhead cost and muddies
the schedule.
- Certain forms of logic (e.g. turn-based games) want very fine-grained
linear and/or branching control over logic.
- SystemState is not automatically cached, and so performance can suffer
and change detection breaks.
- Fixes https://github.com/bevyengine/bevy/issues/2192.
- Partial workaround for https://github.com/bevyengine/bevy/issues/279.
## Solution
- Adds a SystemRegistry resource to the World, which stores initialized
systems keyed by their SystemSet.
- Allows users to call world.run_system(my_system) and
commands.run_system(my_system), without re-initializing or losing state
(essential for change detection).
- Add a Callback type to enable convenient use of dynamic one shot
systems and reduce the mental overhead of working with Box<dyn
SystemSet>.
- Allow users to run systems based on their SystemSet, enabling more
complex user-made abstractions.
## Future work
- Parameterized one-shot systems would improve reusability and bring
them closer to events and commands. The API could be something like
run_system_with_input(my_system, my_input) and use the In SystemParam.
- We should evaluate the unification of commands and one-shot systems
since they are two different ways to run logic on demand over a World.
### Prior attempts
- https://github.com/bevyengine/bevy/pull/2234
- https://github.com/bevyengine/bevy/pull/2417
- https://github.com/bevyengine/bevy/pull/4090
- https://github.com/bevyengine/bevy/pull/7999
This PR continues the work done in
https://github.com/bevyengine/bevy/pull/7999.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Federico Rinaldi <gisquerin@gmail.com>
Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Alejandro Pascual Pozo <alejandro.pascual.pozo@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Dmytro Banin <banind@cs.washington.edu>
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
Make `bevy_ui` "root" nodes more intuitive to use/style by:
- Removing the implicit flexbox styling (such as stretch alignment) that
is applied to them, and replacing it with more intuitive CSS Grid
styling (notably with stretch alignment disabled in both axes).
- Making root nodes layout independently of each other. Instead of there
being a single implicit "viewport" node that all root nodes are children
of, there is now an implicit "viewport" node *per root node*. And layout
of each tree is computed separately.
## Solution
- Remove the global implicit viewport node, and instead create an
implicit viewport node for each user-specified root node.
- Keep track of both the user-specified root nodes and the implicit
viewport nodes in a separate `Vec`.
- Use the window's size as the `available_space` parameter to
`Taffy.compute_layout` rather than setting it on the implicit viewport
node (and set the viewport to `height: 100%; width: 100%` to make this
"just work").
---
## Changelog
- Bevy UI now lays out root nodes independently of each other in
separate layout contexts.
- The implicit viewport node (which contains each user-specified root
node) is now `Display::Grid` with `align_items` and `justify_items` both
set to `Start`.
## Migration Guide
- Bevy UI now lays out root nodes independently of each other in
separate layout contexts. If you were relying on your root nodes being
able to affect each other's layouts, then you may need to wrap them in a
single root node.
- The implicit viewport node (which contains each user-specified root
node) is now `Display::Grid` with `align_items` and `justify_items` both
set to `Start`. You may need to add `height: Val::Percent(100.)` to your
root nodes if you were previously relying on being implicitly set.
# Objective
- When initializing the renderer, Bevy currently create a detached task
- This is needed on wasm but not on native
## Solution
- Don't create a detached task on native but block on the future
# Objective
Replace instances of
```rust
for x in collection.iter{_mut}() {
```
with
```rust
for x in &{mut} collection {
```
This also changes CI to no longer suppress this lint. Note that since
this lint only shows up when using clippy in pedantic mode, it was
probably unnecessary to suppress this lint in the first place.
# Objective
- When reading API docs and seeing a reference to `ComponentId`, it
isn't immediately clear how to get one from your `Component`. It could
be made to be more clear.
## Solution
- Improve cross-linking of docs about `ComponentId`
# Objective
The default division for a `usize` rounds down which means the batch
sizes were too small when the `max_size` isn't exactly divisible by the
batch count.
## Solution
Changing the division to round up fixes this which can dramatically
improve performance when using `par_iter`.
I created a small example to proof this out and measured some results. I
don't know if it's worth committing this permanently so I left it out of
the PR for now.
```rust
use std::{thread, time::Duration};
use bevy::{
prelude::*,
window::{PresentMode, WindowPlugin},
};
fn main() {
App::new()
.add_plugins((DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
present_mode: PresentMode::AutoNoVsync,
..default()
}),
..default()
}),))
.add_systems(Startup, spawn)
.add_systems(Update, update_counts)
.run();
}
#[derive(Component, Default, Debug, Clone, Reflect)]
pub struct Count(u32);
fn spawn(mut commands: Commands) {
// Worst case
let tasks = bevy::tasks::available_parallelism() * 5 - 1;
// Best case
// let tasks = bevy::tasks::available_parallelism() * 5 + 1;
for _ in 0..tasks {
commands.spawn(Count(0));
}
}
// changing the bounds of the text will cause a recomputation
fn update_counts(mut count_query: Query<&mut Count>) {
count_query.par_iter_mut().for_each(|mut count| {
count.0 += 1;
thread::sleep(Duration::from_millis(10))
});
}
```
## Results
I ran this four times, with and without the change, with best case
(should favour the old maths) and worst case (should favour the new
maths) task numbers.
### Worst case
Before the change the batches were 9 on each thread, plus the 5
remainder ran on one of the threads in addition. With the change its 10
on each thread apart from one which has 9. The results show a decrease
from ~140ms to ~100ms which matches what you would expect from the maths
(`10 * 10ms` vs `(9 + 4) * 10ms`).
![Screenshot from 2023-09-14
20-24-36](https://github.com/bevyengine/bevy/assets/1353401/82099ee4-83a8-47f4-bb6b-944f1e87a818)
### Best case
Before the change the batches were 10 on each thread, plus the 1
remainder ran on one of the threads in addition. With the change its 11
on each thread apart from one which has 5. The results slightly favour
the new change but are basically identical as the total time is
determined by the worse case which is `11 * 10ms` for both tests.
![Screenshot from 2023-09-14
20-48-51](https://github.com/bevyengine/bevy/assets/1353401/4532211d-ab36-435b-b864-56af3370d90e)
# Objective
according to
[khronos](https://github.com/KhronosGroup/glTF/issues/1697), gltf nodes
with inverted scales should invert the winding order of the mesh data.
this is to allow negative scale to be used for mirrored geometry.
## Solution
in the gltf loader, create a separate material with `cull_mode` set to
`Face::Front` when the node scale is negative.
note/alternatives:
this applies for nodes where the scale is negative at gltf import time.
that seems like enough for the mentioned use case of mirrored geometry.
it doesn't help when scales dynamically go negative at runtime, but you
can always set double sided in that case.
i don't think there's any practical difference between using front-face
culling and setting a clockwise winding order explicitly, but winding
order is supported by wgpu so we could add the field to
StandardMaterial/StandardMaterialKey and set it directly on the pipeline
descriptor if there's a reason to. it wouldn't help with dynamic scale
adjustments anyway, and would still require a separate material.
fixes#4738, probably fixes#7901.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
The reasoning is similar to #8687.
I'm building a dynamic query. Currently, I store the ReflectFromPtr in
my dynamic `Fetch` type.
[See relevant
code](97ba68ae1e/src/fetches.rs (L14-L17))
However, `ReflectFromPtr` is:
- 16 bytes for TypeId
- 8 bytes for the non-mutable function pointer
- 8 bytes for the mutable function pointer
It's a lot, it adds 32 bytes to my base `Fetch` which is only
`ComponendId` (8 bytes) for a total of 40 bytes.
I only need one function per fetch, reducing the total dynamic fetch
size to 16 bytes.
Since I'm querying the components by the ComponendId associated with the
function pointer I'm using, I don't need the TypeId, it's a redundant
check.
In fact, I've difficulties coming up with situations where checking the
TypeId beforehand is relevant. So to me, if ReflectFromPtr makes sense
as a public API, exposing the function pointers also makes sense.
## Solution
- Make the fields public through methods.
---
## Changelog
- Add `from_ptr` and `from_ptr_mut` methods to `ReflectFromPtr` to
access the underlying function pointers
- `ReflectFromPtr::as_reflect_ptr` is now `ReflectFromPtr::as_reflect`
- `ReflectFromPtr::as_reflect_ptr_mut` is now
`ReflectFromPtr::as_reflect_mut`
## Migration guide
- `ReflectFromPtr::as_reflect_ptr` is now `ReflectFromPtr::as_reflect`
- `ReflectFromPtr::as_reflect_ptr_mut` is now
`ReflectFromPtr::as_reflect_mut`
# Objective
If you remove a `ContentSize` component from a Bevy UI entity and then
replace it `ui_layout_system` will remove the measure func from the
internal Taffy layout tree but no new measure func will be generated to
replace it since it's the widget systems that are responsible for
creating their respective measure funcs not `ui_layout_system`. The
widget systems only perform a measure func update on changes to a widget
entity's content. This means that until its content is changed in some
way, no content will be displayed by the node.
### Example
This example spawns a text node which disappears after a few moments
once its `ContentSize` component is replaced.
```rust
use bevy::prelude::*;
use bevy::ui::ContentSize;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, delayed_replacement)
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
commands.spawn(
TextBundle::from_section(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
TextStyle::default(),
)
);
}
// Waits a few frames to make sure the font is loaded and the text's glyph layout has been generated.
fn delayed_replacement(mut commands: Commands, mut count: Local<usize>, query: Query<Entity, With<Style>>) {
*count += 1;
if *count == 10 {
for item in query.iter() {
commands
.entity(item)
.remove::<ContentSize>()
.insert(ContentSize::default());
}
}
}
```
## Solution
Perform `ui_layout_system`'s `ContentSize` removal detection and
resolution first, before the measure func updates.
Then in the widget systems, generate a new `Measure` when a
`ContentSize` component is added to a widget entity.
## Changelog
* `measure_text_system`, `update_image_content_size_system` and
`update_atlas_content_size_system` generate a new `Measure` when a
`ContentSize` component is added.
# Objective
mikktspace tangent generation requires mesh indices, and currently fails
when they are not present. we can just generate them instead.
## Solution
generate the indices.
# Objective
`Val`'s natural place is in the `geometry` module with `UiRect`, not in
`ui_node` with the components.
## Solution
Move `Val` into `geometry`.
# Objective
Rename RemovedComponents::iter/iter_with_id to read/read_with_id to make
it clear that it consume the data
Fixes#9755.
(It's my first pull request, if i've made any mistake, please let me
know)
## Solution
Refactor RemovedComponents::iter/iter_with_id to read/read_with_id
## Changelog
Refactor RemovedComponents::iter/iter_with_id to read/read_with_id
Deprecate RemovedComponents::iter/iter_with_id
Remove IntoIterator implementation
Update removal_detection example accordingly
---
## Migration Guide
Rename calls of RemovedComponents::iter/iter_with_id to
read/read_with_id
Replace IntoIterator iteration (&mut <RemovedComponents>) with .read()
---------
Co-authored-by: denshi_ika <mojang2824@gmail.com>
# Objective
Fixes#9787
## Solution
~~"serialize" feature enables "bevy_asset" now~~
"serialize" feature no longer enables the optional "bevy_scene" feature
if it's not enabled from elsewhere (thanks to @mockersf)
# Objective
The rename is confusing. Each time I import `TypeRegistry` I have to
think at least 10 seconds about how to import it. And I've been working
a lot with bevy reflect, which multiplies the papercut.
In my crates, you can find lots of:
```rust
use bevy::reflect::{TypeRegistryInternal as TypeRegistry};
```
When I "go to definition" on `TypeRegistry` I get to `TypeRegistryArc`.
And when I mean `TypeRegistry` in my function signature, 100% of the
time I mean `TypeRegistry`, not the arc wrapper.
Rust has borrowing, and most use-cases of the TypeRegistry accepts
borrow of the registry, with no need to mutate it.
`TypeRegistryInternal` is also confusing. In bevy crates, it doesn't
exist. The bevy crate documentation often refers to `TypeRegistry` and
link to `TypeRegistryInternal`. It only exists in the bevy re-exports.
It makes it hard to understand which names qualifies which types.
## Solution
Remove the rename, keep the type names as they are in `bevy_reflect`
---
## Changelog
- Remove `TypeRegistry` and `TypeRegistryArc` renames from bevy
`bevy_reflect` re-exports.
## Migration Guide
- `TypeRegistry` as re-exported by the wrapper `bevy` crate is now
`TypeRegistryArc`
- `TypeRegistryInternal` as re-exported by the wrapper `bevy` crate is
now `TypeRegistry`
# Objective
When using `set_if_neq`, sometimes you'd like to know if the new value
was different from the old value so that you can perform some additional
branching.
## Solution
Return a bool from this function, which indicates whether or not the
value was overwritten.
---
## Changelog
* `DetectChangesMut::set_if_neq` now returns a boolean indicating
whether or not the value was changed.
## Migration Guide
The trait method `DetectChangesMut::set_if_neq` now returns a boolean
value indicating whether or not the value was changed. If you were
implementing this function manually, you must now return `true` if the
value was overwritten and `false` if the value was not.
# Objective
Fix#9747
## Solution
Linkers don't like what we're doing with CowArc (I'm guessing it has
something to do with `?Sized`). Weirdly the `Reflect` derive on
`AssetPath` doesn't fail, despite `CowArc` not implementing `Reflect`.
To resolve this, we manually implement "reflect value" for
`AssetPath<'static>`. It sadly cannot use `impl_reflect_value` because
that macro doesn't support static lifetimes.
---------
Co-authored-by: Martin Dickopp <martin@zero-based.org>
# Objective
Add tests for `ui_layout_system` and `UiSurface` to the
`bevy_ui::Layout` module.
## Solution
Spawn a dummy window entity with `Window` and `PrimaryWindow` components
so that `ui_layout_system` can run in a test without a window present.
---
## Changelog
Added tests to the `bevy_ui::layout` module.
# Objective
- I want to associate `TypeData` with `Mesh`, to make it
editable/inspectable in my reflection-based editor. `Mesh` has to
implement `Reflect` for that. The precise reflection behavior does not
matter.
## Solution
- `#[derive(Reflect)]`, ignore fields whose types aren't reflectable.
- Call `App::register_asset_reflect` in the `MeshPlugin`.
---
## Changelog
- `Mesh` now implements `Reflect`.
# Objective
- The tick access methods mention "ticks" (as in: plural). Yet, most of
them only access a single tick.
## Solution
- Rename those methods and fix docs to reflect the singular aspect of
the return values
---
## Migration Guide
The following method names were renamed, from `foo_ticks_bar` to
`foo_tick_bar` (`ticks` is now singular, `tick`):
- `ComponentSparseSet::get_added_ticks` → `get_added_tick`
- `ComponentSparseSet::get_changed_ticks` → `get_changed_tick`
- `Column::get_added_ticks` → `get_added_tick`
- `Column::get_changed_ticks` → `get_changed_tick`
- `Column::get_added_ticks_unchecked` → `get_added_tick_unchecked`
- `Column::get_changed_ticks_unchecked` → `get_changed_tick_unchecked`
# Objective
- Make it possible to snapshot/save states
- Useful for re-using parts of the state system for rollback safe states
- Or to save states with scenes/savegames
## Solution
- Conditionally add the derive if the `bevy_reflect` is enabled
---
## Changelog
- `NextState<S>` and `State<S>` now implement `Reflect` as long as `S`
does.
# Objective
- Fixes#6662
- Wireframe crash for skinned meshes:
```
wgpu error: Validation Error
Caused by:
In Device::create_render_pipeline
note: label = `opaque_mesh_pipeline`
Error matching ShaderStages(VERTEX) shader requirements against the pipeline
Location[4] Uint32x4 interpolated as Some(Flat) with sampling None is not provided by the previous stage outputs
Input is not provided by the earlier stage in the pipeline
```
- Wireframe crash for morphed meshes:
```
wgpu error: Validation Error
Caused by:
In a RenderPass
note: encoder = `<CommandBuffer-(0, 14, Metal)>`
In a draw command, indexed:true indirect:false
note: render pipeline = `opaque_mesh_pipeline`
The pipeline layout, associated with the current render pipeline, contains a bind group layout at index 1 which is incompatible with the bind group layout associated with the bind group at 1
```
## Solution
- Fix the locations for skinned meshes in the wireframe shader
- Add the morph key to the wireframe specialisation key
- Morph the vertex in the wireframe shader
https://github.com/bevyengine/bevy/assets/8672791/ce0a9584-bd28-4d74-9c3f-256602e6fac5
# Objective
In `extract_text2d_sprite` the scaling by the scale factor should be
only be applied to the x and y axes but it's also applied to the z axis.
# Solution
Remove the scaling in the z axis
# Objective
- Fixes#9683
## Solution
- Moved `get_component` from `Query` to `QueryState`.
- Moved `get_component_unchecked_mut` from `Query` to `QueryState`.
- Moved `QueryComponentError` from `bevy_ecs::system` to
`bevy_ecs::query`. Minor Breaking Change.
- Narrowed scope of `unsafe` blocks in `Query` methods.
---
## Migration Guide
- `use bevy_ecs::system::QueryComponentError;` -> `use
bevy_ecs::query::QueryComponentError;`
## Notes
I am not very familiar with unsafe Rust nor its use within Bevy, so I
may have committed a Rust faux pas during the migration.
---------
Co-authored-by: Zac Harrold <zharrold@c5prosolutions.com>
Co-authored-by: Tristan Guichaoua <33934311+tguichaoua@users.noreply.github.com>
# Objective
Implement `From<String>` and `From<&str>` for `TextSection`
Example from something I was working on earlier:
```rust
parent.spawn(TextBundle::from_sections([
TextSection::new("press ".to_string(), TextStyle::default()),
TextSection::new("space".to_string(), TextStyle { color: Color::YELLOW, ..default() }),
TextSection::new(" to advance frames".to_string(), TextStyle::default()),
]));
```
After an `impl From<&str> for TextSection` :
```rust
parent.spawn(TextBundle::from_sections([
"press ".into(),
TextSection::new("space".to_string(), TextStyle { color: Color::YELLOW, ..default() }),
" to advance frames".into(),
]));
```
* Potentially unhelpful without a default font, so behind the
`default_font` feature.
Co-authored-by: [hate](https://github.com/hate)
---------
Co-authored-by: hate <15314665+hate@users.noreply.github.com>
# Objective
`TextLayoutInfo::size` isn't the drawn size of the text, but a scaled
value. This is fragile, counter-intuitive and makes it awkward to
retrieve the correct value.
## Solution
Multiply `TextLayoutInfo::size` by the reciprocal of the window's scale
factor after generating the text layout in `update_text2d_layout` and
`bevy_ui::widget::text_system`.
---
fixes: #7787
## Changelog
* Multiply `TextLayoutInfo::size` by the reciprocal of the scale factor
after text computation to reflect the actual size of the text as drawn.
* Reorder the operations in `extract_text2d_sprite` to apply the
alignment offset before the scale factor scaling.
## Migration Guide
The `size` value of `TextLayoutInfo` is stored in logical pixels and has
been renamed to `logical_size`. There is no longer any need to divide by
the window's scale factor to get the logical size.
This needs to be much higher to avoid failures in CI. I don't love the
"loop until" test methodology generally, but this is testing internal
state and making this event driven would change the nature of the test.
# Objective
The `AssetServer` and `AssetProcessor` do a lot of `AssetPath` cloning
(across many threads). To store the path on the handle, to store paths
in dependency lists, to pass an owned path to the offloaded thread, to
pass a path to the LoadContext, etc , etc. Cloning multiple string
allocations multiple times like this will add up. It is worth optimizing
this.
Referenced in #9714
## Solution
Added a new `CowArc<T>` type to `bevy_util`, which behaves a lot like
`Cow<T>`, but the Owned variant is an `Arc<T>`. Use this in place of
`Cow<str>` and `Cow<Path>` on `AssetPath`.
---
## Changelog
- `AssetPath` now internally uses `CowArc`, making clone operations much
cheaper
- `AssetPath` now serializes as `AssetPath("some_path.extension#Label")`
instead of as `AssetPath { path: "some_path.extension", label:
Some("Label) }`
## Migration Guide
```rust
// Old
AssetPath::new("logo.png", None);
// New
AssetPath::new("logo.png");
// Old
AssetPath::new("scene.gltf", Some("Mesh0");
// New
AssetPath::new("scene.gltf").with_label("Mesh0");
```
`AssetPath` now serializes as `AssetPath("some_path.extension#Label")`
instead of as `AssetPath { path: "some_path.extension", label:
Some("Label) }`
---------
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
# Objective
- Fix these warnings
```rust
warning: unused doc comment
--> /bevy/crates/bevy_pbr/src/light.rs:62:13
|
62 | /// Luminous power in lumens
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
63 | intensity: 800.0, // Roughly a 60W non-halogen incandescent bulb
| ---------------- rustdoc does not generate documentation for expression fields
|
= help: use `//` for a plain comment
= note: `#[warn(unused_doc_comments)]` on by default
```
```rust
warning: `&` without an explicit lifetime name cannot be used here
--> /bevy/crates/bevy_asset/src/lib.rs:89:32
|
89 | const DEFAULT_FILE_SOURCE: &str = "assets";
| ^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
= note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default
help: use the `'static` lifetime
|
89 | const DEFAULT_FILE_SOURCE: &'static str = "assets";
|
```
# Objective
`TextureAtlas` supports pregenerated texture atlases with padding, but
`TextureAtlasBuilder` can't add padding when it creates a new atlas.
fixes#8150
## Solution
Add a method `padding` to `TextureAtlasBuilder` that sets the amount of
padding to add around each texture.
When queueing the textures to be copied, add the padding value to the
size of each source texture. Then when copying the source textures to
the output atlas texture subtract the same padding value from the sizes
of the target rects.
unpadded:
<img width="961" alt="texture_atlas_example"
src="https://github.com/bevyengine/bevy/assets/27962798/8cf02442-dc3e-4429-90f1-543bc9270d8b">
padded:
<img width="961" alt="texture_atlas_example_with_padding"
src="https://github.com/bevyengine/bevy/assets/27962798/da347bcc-b083-4650-ba0c-86883853764f">
---
## Changelog
`TextureAtlasBuilder`
* Added support for building texture atlases with padding.
* Adds a `padding` method to `TextureAtlasBuilder` that can be used to
set an amount of padding to add between the sprites of the generated
texture atlas.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Related to #9715
- Example `asset_processing` logs the following error:
```
thread 'IO Task Pool (1)' panicked at 'Failed to initialize asset processor log. This cannot be recovered. Try restarting. If that doesn't work, try deleting processed asset folder. No such file or directory (os error 2)', crates/bevy_asset/src/processor/mod.rs:867:25
```
## Solution
- Create the log directory if needed
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Bevy Asset V2 Proposal
## Why Does Bevy Need A New Asset System?
Asset pipelines are a central part of the gamedev process. Bevy's
current asset system is missing a number of features that make it
non-viable for many classes of gamedev. After plenty of discussions and
[a long community feedback
period](https://github.com/bevyengine/bevy/discussions/3972), we've
identified a number missing features:
* **Asset Preprocessing**: it should be possible to "preprocess" /
"compile" / "crunch" assets at "development time" rather than when the
game starts up. This enables offloading expensive work from deployed
apps, faster asset loading, less runtime memory usage, etc.
* **Per-Asset Loader Settings**: Individual assets cannot define their
own loaders that override the defaults. Additionally, they cannot
provide per-asset settings to their loaders. This is a huge limitation,
as many asset types don't provide all information necessary for Bevy
_inside_ the asset. For example, a raw PNG image says nothing about how
it should be sampled (ex: linear vs nearest).
* **Asset `.meta` files**: assets should have configuration files stored
adjacent to the asset in question, which allows the user to configure
asset-type-specific settings. These settings should be accessible during
the pre-processing phase. Modifying a `.meta` file should trigger a
re-processing / re-load of the asset. It should be possible to configure
asset loaders from the meta file.
* **Processed Asset Hot Reloading**: Changes to processed assets (or
their dependencies) should result in re-processing them and re-loading
the results in live Bevy Apps.
* **Asset Dependency Tracking**: The current bevy_asset has no good way
to wait for asset dependencies to load. It punts this as an exercise for
consumers of the loader apis, which is unreasonable and error prone.
There should be easy, ergonomic ways to wait for assets to load and
block some logic on an asset's entire dependency tree loading.
* **Runtime Asset Loading**: it should be (optionally) possible to load
arbitrary assets dynamically at runtime. This necessitates being able to
deploy and run the asset server alongside Bevy Apps on _all platforms_.
For example, we should be able to invoke the shader compiler at runtime,
stream scenes from sources like the internet, etc. To keep deployed
binaries (and startup times) small, the runtime asset server
configuration should be configurable with different settings compared to
the "pre processor asset server".
* **Multiple Backends**: It should be possible to load assets from
arbitrary sources (filesystems, the internet, remote asset serves, etc).
* **Asset Packing**: It should be possible to deploy assets in
compressed "packs", which makes it easier and more efficient to
distribute assets with Bevy Apps.
* **Asset Handoff**: It should be possible to hold a "live" asset
handle, which correlates to runtime data, without actually holding the
asset in memory. Ex: it must be possible to hold a reference to a GPU
mesh generated from a "mesh asset" without keeping the mesh data in CPU
memory
* **Per-Platform Processed Assets**: Different platforms and app
distributions have different capabilities and requirements. Some
platforms need lower asset resolutions or different asset formats to
operate within the hardware constraints of the platform. It should be
possible to define per-platform asset processing profiles. And it should
be possible to deploy only the assets required for a given platform.
These features have architectural implications that are significant
enough to require a full rewrite. The current Bevy Asset implementation
got us this far, but it can take us no farther. This PR defines a brand
new asset system that implements most of these features, while laying
the foundations for the remaining features to be built.
## Bevy Asset V2
Here is a quick overview of the features introduced in this PR.
* **Asset Preprocessing**: Preprocess assets at development time into
more efficient (and configurable) representations
* **Dependency Aware**: Dependencies required to process an asset are
tracked. If an asset's processed dependency changes, it will be
reprocessed
* **Hot Reprocessing/Reloading**: detect changes to asset source files,
reprocess them if they have changed, and then hot-reload them in Bevy
Apps.
* **Only Process Changes**: Assets are only re-processed when their
source file (or meta file) has changed. This uses hashing and timestamps
to avoid processing assets that haven't changed.
* **Transactional and Reliable**: Uses write-ahead logging (a technique
commonly used by databases) to recover from crashes / forced-exits.
Whenever possible it avoids full-reprocessing / only uncompleted
transactions will be reprocessed. When the processor is running in
parallel with a Bevy App, processor asset writes block Bevy App asset
reads. Reading metadata + asset bytes is guaranteed to be transactional
/ correctly paired.
* **Portable / Run anywhere / Database-free**: The processor does not
rely on an in-memory database (although it uses some database techniques
for reliability). This is important because pretty much all in-memory
databases have unsupported platforms or build complications.
* **Configure Processor Defaults Per File Type**: You can say "use this
processor for all files of this type".
* **Custom Processors**: The `Processor` trait is flexible and
unopinionated. It can be implemented by downstream plugins.
* **LoadAndSave Processors**: Most asset processing scenarios can be
expressed as "run AssetLoader A, save the results using AssetSaver X,
and then load the result using AssetLoader B". For example, load this
png image using `PngImageLoader`, which produces an `Image` asset and
then save it using `CompressedImageSaver` (which also produces an
`Image` asset, but in a compressed format), which takes an `Image` asset
as input. This means if you have an `AssetLoader` for an asset, you are
already half way there! It also means that you can share AssetSavers
across multiple loaders. Because `CompressedImageSaver` accepts Bevy's
generic Image asset as input, it means you can also use it with some
future `JpegImageLoader`.
* **Loader and Saver Settings**: Asset Loaders and Savers can now define
their own settings types, which are passed in as input when an asset is
loaded / saved. Each asset can define its own settings.
* **Asset `.meta` files**: configure asset loaders, their settings,
enable/disable processing, and configure processor settings
* **Runtime Asset Dependency Tracking** Runtime asset dependencies (ex:
if an asset contains a `Handle<Image>`) are tracked by the asset server.
An event is emitted when an asset and all of its dependencies have been
loaded
* **Unprocessed Asset Loading**: Assets do not require preprocessing.
They can be loaded directly. A processed asset is just a "normal" asset
with some extra metadata. Asset Loaders don't need to know or care about
whether or not an asset was processed.
* **Async Asset IO**: Asset readers/writers use async non-blocking
interfaces. Note that because Rust doesn't yet support async traits,
there is a bit of manual Boxing / Future boilerplate. This will
hopefully be removed in the near future when Rust gets async traits.
* **Pluggable Asset Readers and Writers**: Arbitrary asset source
readers/writers are supported, both by the processor and the asset
server.
* **Better Asset Handles**
* **Single Arc Tree**: Asset Handles now use a single arc tree that
represents the lifetime of the asset. This makes their implementation
simpler, more efficient, and allows us to cheaply attach metadata to
handles. Ex: the AssetPath of a handle is now directly accessible on the
handle itself!
* **Const Typed Handles**: typed handles can be constructed in a const
context. No more weird "const untyped converted to typed at runtime"
patterns!
* **Handles and Ids are Smaller / Faster To Hash / Compare**: Typed
`Handle<T>` is now much smaller in memory and `AssetId<T>` is even
smaller.
* **Weak Handle Usage Reduction**: In general Handles are now considered
to be "strong". Bevy features that previously used "weak `Handle<T>`"
have been ported to `AssetId<T>`, which makes it statically clear that
the features do not hold strong handles (while retaining strong type
information). Currently Handle::Weak still exists, but it is very
possible that we can remove that entirely.
* **Efficient / Dense Asset Ids**: Assets now have efficient dense
runtime asset ids, which means we can avoid expensive hash lookups.
Assets are stored in Vecs instead of HashMaps. There are now typed and
untyped ids, which means we no longer need to store dynamic type
information in the ID for typed handles. "AssetPathId" (which was a
nightmare from a performance and correctness standpoint) has been
entirely removed in favor of dense ids (which are retrieved for a path
on load)
* **Direct Asset Loading, with Dependency Tracking**: Assets that are
defined at runtime can still have their dependencies tracked by the
Asset Server (ex: if you create a material at runtime, you can still
wait for its textures to load). This is accomplished via the (currently
optional) "asset dependency visitor" trait. This system can also be used
to define a set of assets to load, then wait for those assets to load.
* **Async folder loading**: Folder loading also uses this system and
immediately returns a handle to the LoadedFolder asset, which means
folder loading no longer blocks on directory traversals.
* **Improved Loader Interface**: Loaders now have a specific "top level
asset type", which makes returning the top-level asset simpler and
statically typed.
* **Basic Image Settings and Processing**: Image assets can now be
processed into the gpu-friendly Basic Universal format. The ImageLoader
now has a setting to define what format the image should be loaded as.
Note that this is just a minimal MVP ... plenty of additional work to do
here. To demo this, enable the `basis-universal` feature and turn on
asset processing.
* **Simpler Audio Play / AudioSink API**: Asset handle providers are
cloneable, which means the Audio resource can mint its own handles. This
means you can now do `let sink_handle = audio.play(music)` instead of
`let sink_handle = audio_sinks.get_handle(audio.play(music))`. Note that
this might still be replaced by
https://github.com/bevyengine/bevy/pull/8424.
**Removed Handle Casting From Engine Features**: Ex: FontAtlases no
longer use casting between handle types
## Using The New Asset System
### Normal Unprocessed Asset Loading
By default the `AssetPlugin` does not use processing. It behaves pretty
much the same way as the old system.
If you are defining a custom asset, first derive `Asset`:
```rust
#[derive(Asset)]
struct Thing {
value: String,
}
```
Initialize the asset:
```rust
app.init_asset:<Thing>()
```
Implement a new `AssetLoader` for it:
```rust
#[derive(Default)]
struct ThingLoader;
#[derive(Serialize, Deserialize, Default)]
pub struct ThingSettings {
some_setting: bool,
}
impl AssetLoader for ThingLoader {
type Asset = Thing;
type Settings = ThingSettings;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
settings: &'a ThingSettings,
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Thing, anyhow::Error>> {
Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
// convert bytes to value somehow
Ok(Thing {
value
})
})
}
fn extensions(&self) -> &[&str] {
&["thing"]
}
}
```
Note that this interface will get much cleaner once Rust gets support
for async traits. `Reader` is an async futures_io::AsyncRead. You can
stream bytes as they come in or read them all into a `Vec<u8>`,
depending on the context. You can use `let handle =
load_context.load(path)` to kick off a dependency load, retrieve a
handle, and register the dependency for the asset.
Then just register the loader in your Bevy app:
```rust
app.init_asset_loader::<ThingLoader>()
```
Now just add your `Thing` asset files into the `assets` folder and load
them like this:
```rust
fn system(asset_server: Res<AssetServer>) {
let handle = Handle<Thing> = asset_server.load("cool.thing");
}
```
You can check load states directly via the asset server:
```rust
if asset_server.load_state(&handle) == LoadState::Loaded { }
```
You can also listen for events:
```rust
fn system(mut events: EventReader<AssetEvent<Thing>>, handle: Res<SomeThingHandle>) {
for event in events.iter() {
if event.is_loaded_with_dependencies(&handle) {
}
}
}
```
Note the new `AssetEvent::LoadedWithDependencies`, which only fires when
the asset is loaded _and_ all dependencies (and their dependencies) have
loaded.
Unlike the old asset system, for a given asset path all `Handle<T>`
values point to the same underlying Arc. This means Handles can cheaply
hold more asset information, such as the AssetPath:
```rust
// prints the AssetPath of the handle
info!("{:?}", handle.path())
```
### Processed Assets
Asset processing can be enabled via the `AssetPlugin`. When developing
Bevy Apps with processed assets, do this:
```rust
app.add_plugins(DefaultPlugins.set(AssetPlugin::processed_dev()))
```
This runs the `AssetProcessor` in the background with hot-reloading. It
reads assets from the `assets` folder, processes them, and writes them
to the `.imported_assets` folder. Asset loads in the Bevy App will wait
for a processed version of the asset to become available. If an asset in
the `assets` folder changes, it will be reprocessed and hot-reloaded in
the Bevy App.
When deploying processed Bevy apps, do this:
```rust
app.add_plugins(DefaultPlugins.set(AssetPlugin::processed()))
```
This does not run the `AssetProcessor` in the background. It behaves
like `AssetPlugin::unprocessed()`, but reads assets from
`.imported_assets`.
When the `AssetProcessor` is running, it will populate sibling `.meta`
files for assets in the `assets` folder. Meta files for assets that do
not have a processor configured look like this:
```rust
(
meta_format_version: "1.0",
asset: Load(
loader: "bevy_render::texture::image_loader::ImageLoader",
settings: (
format: FromExtension,
),
),
)
```
This is metadata for an image asset. For example, if you have
`assets/my_sprite.png`, this could be the metadata stored at
`assets/my_sprite.png.meta`. Meta files are totally optional. If no
metadata exists, the default settings will be used.
In short, this file says "load this asset with the ImageLoader and use
the file extension to determine the image type". This type of meta file
is supported in all AssetPlugin modes. If in `Unprocessed` mode, the
asset (with the meta settings) will be loaded directly. If in
`ProcessedDev` mode, the asset file will be copied directly to the
`.imported_assets` folder. The meta will also be copied directly to the
`.imported_assets` folder, but with one addition:
```rust
(
meta_format_version: "1.0",
processed_info: Some((
hash: 12415480888597742505,
full_hash: 14344495437905856884,
process_dependencies: [],
)),
asset: Load(
loader: "bevy_render::texture::image_loader::ImageLoader",
settings: (
format: FromExtension,
),
),
)
```
`processed_info` contains `hash` (a direct hash of the asset and meta
bytes), `full_hash` (a hash of `hash` and the hashes of all
`process_dependencies`), and `process_dependencies` (the `path` and
`full_hash` of every process_dependency). A "process dependency" is an
asset dependency that is _directly_ used when processing the asset.
Images do not have process dependencies, so this is empty.
When the processor is enabled, you can use the `Process` metadata
config:
```rust
(
meta_format_version: "1.0",
asset: Process(
processor: "bevy_asset::processor::process::LoadAndSave<bevy_render::texture::image_loader::ImageLoader, bevy_render::texture::compressed_image_saver::CompressedImageSaver>",
settings: (
loader_settings: (
format: FromExtension,
),
saver_settings: (
generate_mipmaps: true,
),
),
),
)
```
This configures the asset to use the `LoadAndSave` processor, which runs
an AssetLoader and feeds the result into an AssetSaver (which saves the
given Asset and defines a loader to load it with). (for terseness
LoadAndSave will likely get a shorter/friendlier type name when [Stable
Type Paths](#7184) lands). `LoadAndSave` is likely to be the most common
processor type, but arbitrary processors are supported.
`CompressedImageSaver` saves an `Image` in the Basis Universal format
and configures the ImageLoader to load it as basis universal. The
`AssetProcessor` will read this meta, run it through the LoadAndSave
processor, and write the basis-universal version of the image to
`.imported_assets`. The final metadata will look like this:
```rust
(
meta_format_version: "1.0",
processed_info: Some((
hash: 905599590923828066,
full_hash: 9948823010183819117,
process_dependencies: [],
)),
asset: Load(
loader: "bevy_render::texture::image_loader::ImageLoader",
settings: (
format: Format(Basis),
),
),
)
```
To try basis-universal processing out in Bevy examples, (for example
`sprite.rs`), change `add_plugins(DefaultPlugins)` to
`add_plugins(DefaultPlugins.set(AssetPlugin::processed_dev()))` and run
with the `basis-universal` feature enabled: `cargo run
--features=basis-universal --example sprite`.
To create a custom processor, there are two main paths:
1. Use the `LoadAndSave` processor with an existing `AssetLoader`.
Implement the `AssetSaver` trait, register the processor using
`asset_processor.register_processor::<LoadAndSave<ImageLoader,
CompressedImageSaver>>(image_saver.into())`.
2. Implement the `Process` trait directly and register it using:
`asset_processor.register_processor(thing_processor)`.
You can configure default processors for file extensions like this:
```rust
asset_processor.set_default_processor::<ThingProcessor>("thing")
```
There is one more metadata type to be aware of:
```rust
(
meta_format_version: "1.0",
asset: Ignore,
)
```
This will ignore the asset during processing / prevent it from being
written to `.imported_assets`.
The AssetProcessor stores a transaction log at `.imported_assets/log`
and uses it to gracefully recover from unexpected stops. This means you
can force-quit the processor (and Bevy Apps running the processor in
parallel) at arbitrary times!
`.imported_assets` is "local state". It should _not_ be checked into
source control. It should also be considered "read only". In practice,
you _can_ modify processed assets and processed metadata if you really
need to test something. But those modifications will not be represented
in the hashes of the assets, so the processed state will be "out of
sync" with the source assets. The processor _will not_ fix this for you.
Either revert the change after you have tested it, or delete the
processed files so they can be re-populated.
## Open Questions
There are a number of open questions to be discussed. We should decide
if they need to be addressed in this PR and if so, how we will address
them:
### Implied Dependencies vs Dependency Enumeration
There are currently two ways to populate asset dependencies:
* **Implied via AssetLoaders**: if an AssetLoader loads an asset (and
retrieves a handle), a dependency is added to the list.
* **Explicit via the optional Asset::visit_dependencies**: if
`server.load_asset(my_asset)` is called, it will call
`my_asset.visit_dependencies`, which will grab dependencies that have
been manually defined for the asset via the Asset trait impl (which can
be derived).
This means that defining explicit dependencies is optional for "loaded
assets". And the list of dependencies is always accurate because loaders
can only produce Handles if they register dependencies. If an asset was
loaded with an AssetLoader, it only uses the implied dependencies. If an
asset was created at runtime and added with
`asset_server.load_asset(MyAsset)`, it will use
`Asset::visit_dependencies`.
However this can create a behavior mismatch between loaded assets and
equivalent "created at runtime" assets if `Assets::visit_dependencies`
doesn't exactly match the dependencies produced by the AssetLoader. This
behavior mismatch can be resolved by completely removing "implied loader
dependencies" and requiring `Asset::visit_dependencies` to supply
dependency data. But this creates two problems:
* It makes defining loaded assets harder and more error prone: Devs must
remember to manually annotate asset dependencies with `#[dependency]`
when deriving `Asset`. For more complicated assets (such as scenes), the
derive likely wouldn't be sufficient and a manual `visit_dependencies`
impl would be required.
* Removes the ability to immediately kick off dependency loads: When
AssetLoaders retrieve a Handle, they also immediately kick off an asset
load for the handle, which means it can start loading in parallel
_before_ the asset finishes loading. For large assets, this could be
significant. (although this could be mitigated for processed assets if
we store dependencies in the processed meta file and load them ahead of
time)
### Eager ProcessorDev Asset Loading
I made a controversial call in the interest of fast startup times ("time
to first pixel") for the "processor dev mode configuration". When
initializing the AssetProcessor, current processed versions of unchanged
assets are yielded immediately, even if their dependencies haven't been
checked yet for reprocessing. This means that
non-current-state-of-filesystem-but-previously-valid assets might be
returned to the App first, then hot-reloaded if/when their dependencies
change and the asset is reprocessed.
Is this behavior desirable? There is largely one alternative: do not
yield an asset from the processor to the app until all of its
dependencies have been checked for changes. In some common cases (load
dependency has not changed since last run) this will increase startup
time. The main question is "by how much" and is that slower startup time
worth it in the interest of only yielding assets that are true to the
current state of the filesystem. Should this be configurable? I'm
starting to think we should only yield an asset after its (historical)
dependencies have been checked for changes + processed as necessary, but
I'm curious what you all think.
### Paths Are Currently The Only Canonical ID / Do We Want Asset UUIDs?
In this implementation AssetPaths are the only canonical asset
identifier (just like the previous Bevy Asset system and Godot). Moving
assets will result in re-scans (and currently reprocessing, although
reprocessing can easily be avoided with some changes). Asset
renames/moves will break code and assets that rely on specific paths,
unless those paths are fixed up.
Do we want / need "stable asset uuids"? Introducing them is very
possible:
1. Generate a UUID and include it in .meta files
2. Support UUID in AssetPath
3. Generate "asset indices" which are loaded on startup and map UUIDs to
paths.
4 (maybe). Consider only supporting UUIDs for processed assets so we can
generate quick-to-load indices instead of scanning meta files.
The main "pro" is that assets referencing UUIDs don't need to be
migrated when a path changes. The main "con" is that UUIDs cannot be
"lazily resolved" like paths. They need a full view of all assets to
answer the question "does this UUID exist". Which means UUIDs require
the AssetProcessor to fully finish startup scans before saying an asset
doesnt exist. And they essentially require asset pre-processing to use
in apps, because scanning all asset metadata files at runtime to resolve
a UUID is not viable for medium-to-large apps. It really requires a
pre-generated UUID index, which must be loaded before querying for
assets.
I personally think this should be investigated in a separate PR. Paths
aren't going anywhere ... _everyone_ uses filesystems (and
filesystem-like apis) to manage their asset source files. I consider
them permanent canonical asset information. Additionally, they behave
well for both processed and unprocessed asset modes. Given that Bevy is
supporting both, this feels like the right canonical ID to start with.
UUIDS (and maybe even other indexed-identifier types) can be added later
as necessary.
### Folder / File Naming Conventions
All asset processing config currently lives in the `.imported_assets`
folder. The processor transaction log is in `.imported_assets/log`.
Processed assets are added to `.imported_assets/Default`, which will
make migrating to processed asset profiles (ex: a
`.imported_assets/Mobile` profile) a non-breaking change. It also allows
us to create top-level files like `.imported_assets/log` without it
being interpreted as an asset. Meta files currently have a `.meta`
suffix. Do we like these names and conventions?
### Should the `AssetPlugin::processed_dev` configuration enable
`watch_for_changes` automatically?
Currently it does (which I think makes sense), but it does make it the
only configuration that enables watch_for_changes by default.
### Discuss on_loaded High Level Interface:
This PR includes a very rough "proof of concept" `on_loaded` system
adapter that uses the `LoadedWithDependencies` event in combination with
`asset_server.load_asset` dependency tracking to support this pattern
```rust
fn main() {
App::new()
.init_asset::<MyAssets>()
.add_systems(Update, on_loaded(create_array_texture))
.run();
}
#[derive(Asset, Clone)]
struct MyAssets {
#[dependency]
picture_of_my_cat: Handle<Image>,
#[dependency]
picture_of_my_other_cat: Handle<Image>,
}
impl FromWorld for ArrayTexture {
fn from_world(world: &mut World) -> Self {
picture_of_my_cat: server.load("meow.png"),
picture_of_my_other_cat: server.load("meeeeeeeow.png"),
}
}
fn spawn_cat(In(my_assets): In<MyAssets>, mut commands: Commands) {
commands.spawn(SpriteBundle {
texture: my_assets.picture_of_my_cat.clone(),
..default()
});
commands.spawn(SpriteBundle {
texture: my_assets.picture_of_my_other_cat.clone(),
..default()
});
}
```
The implementation is _very_ rough. And it is currently unsafe because
`bevy_ecs` doesn't expose some internals to do this safely from inside
`bevy_asset`. There are plenty of unanswered questions like:
* "do we add a Loadable" derive? (effectively automate the FromWorld
implementation above)
* Should `MyAssets` even be an Asset? (largely implemented this way
because it elegantly builds on `server.load_asset(MyAsset { .. })`
dependency tracking).
We should think hard about what our ideal API looks like (and if this is
a pattern we want to support). Not necessarily something we need to
solve in this PR. The current `on_loaded` impl should probably be
removed from this PR before merging.
## Clarifying Questions
### What about Assets as Entities?
This Bevy Asset V2 proposal implementation initially stored Assets as
ECS Entities. Instead of `AssetId<T>` + the `Assets<T>` resource it used
`Entity` as the asset id and Asset values were just ECS components.
There are plenty of compelling reasons to do this:
1. Easier to inline assets in Bevy Scenes (as they are "just" normal
entities + components)
2. More flexible queries: use the power of the ECS to filter assets (ex:
`Query<Mesh, With<Tree>>`).
3. Extensible. Users can add arbitrary component data to assets.
4. Things like "component visualization tools" work out of the box to
visualize asset data.
However Assets as Entities has a ton of caveats right now:
* We need to be able to allocate entity ids without a direct World
reference (aka rework id allocator in Entities ... i worked around this
in my prototypes by just pre allocating big chunks of entities)
* We want asset change events in addition to ECS change tracking ... how
do we populate them when mutations can come from anywhere? Do we use
Changed queries? This would require iterating over the change data for
all assets every frame. Is this acceptable or should we implement a new
"event based" component change detection option?
* Reconciling manually created assets with asset-system managed assets
has some nuance (ex: are they "loaded" / do they also have that
component metadata?)
* "how do we handle "static" / default entity handles" (ties in to the
Entity Indices discussion:
https://github.com/bevyengine/bevy/discussions/8319). This is necessary
for things like "built in" assets and default handles in things like
SpriteBundle.
* Storing asset information as a component makes it easy to "invalidate"
asset state by removing the component (or forcing modifications).
Ideally we have ways to lock this down (some combination of Rust type
privacy and ECS validation)
In practice, how we store and identify assets is a reasonably
superficial change (porting off of Assets as Entities and implementing
dedicated storage + ids took less than a day). So once we sort out the
remaining challenges the flip should be straightforward. Additionally, I
do still have "Assets as Entities" in my commit history, so we can reuse
that work. I personally think "assets as entities" is a good endgame,
but it also doesn't provide _significant_ value at the moment and it
certainly isn't ready yet with the current state of things.
### Why not Distill?
[Distill](https://github.com/amethyst/distill) is a high quality fully
featured asset system built in Rust. It is very natural to ask "why not
just use Distill?".
It is also worth calling out that for awhile, [we planned on adopting
Distill / I signed off on
it](https://github.com/bevyengine/bevy/issues/708).
However I think Bevy has a number of constraints that make Distill
adoption suboptimal:
* **Architectural Simplicity:**
* Distill's processor requires an in-memory database (lmdb) and RPC
networked API (using Cap'n Proto). Each of these introduces API
complexity that increases maintenance burden and "code grokability".
Ignoring tests, documentation, and examples, Distill has 24,237 lines of
Rust code (including generated code for RPC + database interactions). If
you ignore generated code, it has 11,499 lines.
* Bevy builds the AssetProcessor and AssetServer using pluggable
AssetReader/AssetWriter Rust traits with simple io interfaces. They do
not necessitate databases or RPC interfaces (although Readers/Writers
could use them if that is desired). Bevy Asset V2 (at the time of
writing this PR) is 5,384 lines of Rust code (ignoring tests,
documentation, and examples). Grain of salt: Distill does have more
features currently (ex: Asset Packing, GUIDS, remote-out-of-process
asset processor). I do plan to implement these features in Bevy Asset V2
and I personally highly doubt they will meaningfully close the 6115
lines-of-code gap.
* This complexity gap (which while illustrated by lines of code, is much
bigger than just that) is noteworthy to me. Bevy should be hackable and
there are pillars of Distill that are very hard to understand and
extend. This is a matter of opinion (and Bevy Asset V2 also has
complicated areas), but I think Bevy Asset V2 is much more approachable
for the average developer.
* Necessary disclaimer: counting lines of code is an extremely rough
complexity metric. Read the code and form your own opinions.
* **Optional Asset Processing:** Not all Bevy Apps (or Bevy App
developers) need / want asset preprocessing. Processing increases the
complexity of the development environment by introducing things like
meta files, imported asset storage, running processors in the
background, waiting for processing to finish, etc. Distill _requires_
preprocessing to work. With Bevy Asset V2 processing is fully opt-in.
The AssetServer isn't directly aware of asset processors at all.
AssetLoaders only care about converting bytes to runtime Assets ... they
don't know or care if the bytes were pre-processed or not. Processing is
"elegantly" (forgive my self-congratulatory phrasing) layered on top and
builds on the existing Asset system primitives.
* **Direct Filesystem Access to Processed Asset State:** Distill stores
processed assets in a database. This makes debugging / inspecting the
processed outputs harder (either requires special tooling to query the
database or they need to be "deployed" to be inspected). Bevy Asset V2,
on the other hand, stores processed assets in the filesystem (by default
... this is configurable). This makes interacting with the processed
state more natural. Note that both Godot and Unity's new asset system
store processed assets in the filesystem.
* **Portability**: Because Distill's processor uses lmdb and RPC
networking, it cannot be run on certain platforms (ex: lmdb is a
non-rust dependency that cannot run on the web, some platforms don't
support running network servers). Bevy should be able to process assets
everywhere (ex: run the Bevy Editor on the web, compile + process
shaders on mobile, etc). Distill does partially mitigate this problem by
supporting "streaming" assets via the RPC protocol, but this is not a
full solve from my perspective. And Bevy Asset V2 can (in theory) also
stream assets (without requiring RPC, although this isn't implemented
yet)
Note that I _do_ still think Distill would be a solid asset system for
Bevy. But I think the approach in this PR is a better solve for Bevy's
specific "asset system requirements".
### Doesn't async-fs just shim requests to "sync" `std::fs`? What is the
point?
"True async file io" has limited / spotty platform support. async-fs
(and the rust async ecosystem generally ... ex Tokio) currently use
async wrappers over std::fs that offload blocking requests to separate
threads. This may feel unsatisfying, but it _does_ still provide value
because it prevents our task pools from blocking on file system
operations (which would prevent progress when there are many tasks to
do, but all threads in a pool are currently blocking on file system
ops).
Additionally, using async APIs for our AssetReaders and AssetWriters
also provides value because we can later add support for "true async
file io" for platforms that support it. _And_ we can implement other
"true async io" asset backends (such as networked asset io).
## Draft TODO
- [x] Fill in missing filesystem event APIs: file removed event (which
is expressed as dangling RenameFrom events in some cases), file/folder
renamed event
- [x] Assets without loaders are not moved to the processed folder. This
breaks things like referenced `.bin` files for GLTFs. This should be
configurable per-non-asset-type.
- [x] Initial implementation of Reflect and FromReflect for Handle. The
"deserialization" parity bar is low here as this only worked with static
UUIDs in the old impl ... this is a non-trivial problem. Either we add a
Handle::AssetPath variant that gets "upgraded" to a strong handle on
scene load or we use a separate AssetRef type for Bevy scenes (which is
converted to a runtime Handle on load). This deserves its own discussion
in a different pr.
- [x] Populate read_asset_bytes hash when run by the processor (a bit of
a special case .. when run by the processor the processed meta will
contain the hash so we don't need to compute it on the spot, but we
don't want/need to read the meta when run by the main AssetServer)
- [x] Delay hot reloading: currently filesystem events are handled
immediately, which creates timing issues in some cases. For example hot
reloading images can sometimes break because the image isn't finished
writing. We should add a delay, likely similar to the [implementation in
this PR](https://github.com/bevyengine/bevy/pull/8503).
- [x] Port old platform-specific AssetIo implementations to the new
AssetReader interface (currently missing Android and web)
- [x] Resolve on_loaded unsafety (either by removing the API entirely or
removing the unsafe)
- [x] Runtime loader setting overrides
- [x] Remove remaining unwraps that should be error-handled. There are
number of TODOs here
- [x] Pretty AssetPath Display impl
- [x] Document more APIs
- [x] Resolve spurious "reloading because it has changed" events (to
repro run load_gltf with `processed_dev()`)
- [x] load_dependency hot reloading currently only works for processed
assets. If processing is disabled, load_dependency changes are not hot
reloaded.
- [x] Replace AssetInfo dependency load/fail counters with
`loading_dependencies: HashSet<UntypedAssetId>` to prevent reloads from
(potentially) breaking counters. Storing this will also enable
"dependency reloaded" events (see [Next Steps](#next-steps))
- [x] Re-add filesystem watcher cargo feature gate (currently it is not
optional)
- [ ] Migration Guide
- [ ] Changelog
## Followup TODO
- [ ] Replace "eager unchanged processed asset loading" behavior with
"don't returned unchanged processed asset until dependencies have been
checked".
- [ ] Add true `Ignore` AssetAction that does not copy the asset to the
imported_assets folder.
- [ ] Finish "live asset unloading" (ex: free up CPU asset memory after
uploading an image to the GPU), rethink RenderAssets, and port renderer
features. The `Assets` collection uses `Option<T>` for asset storage to
support its removal. (1) the Option might not actually be necessary ...
might be able to just remove from the collection entirely (2) need to
finalize removal apis
- [ ] Try replacing the "channel based" asset id recycling with
something a bit more efficient (ex: we might be able to use raw atomic
ints with some cleverness)
- [ ] Consider adding UUIDs to processed assets (scoped just to helping
identify moved assets ... not exposed to load queries ... see [Next
Steps](#next-steps))
- [ ] Store "last modified" source asset and meta timestamps in
processed meta files to enable skipping expensive hashing when the file
wasn't changed
- [ ] Fix "slow loop" handle drop fix
- [ ] Migrate to TypeName
- [x] Handle "loader preregistration". See #9429
## Next Steps
* **Configurable per-type defaults for AssetMeta**: It should be
possible to add configuration like "all png image meta should default to
using nearest sampling" (currently this hard-coded per-loader/processor
Settings::default() impls). Also see the "Folder Meta" bullet point.
* **Avoid Reprocessing on Asset Renames / Moves**: See the "canonical
asset ids" discussion in [Open Questions](#open-questions) and the
relevant bullet point in [Draft TODO](#draft-todo). Even without
canonical ids, folder renames could avoid reprocessing in some cases.
* **Multiple Asset Sources**: Expand AssetPath to support "asset source
names" and support multiple AssetReaders in the asset server (ex:
`webserver://some_path/image.png` backed by an Http webserver
AssetReader). The "default" asset reader would use normal
`some_path/image.png` paths. Ideally this works in combination with
multiple AssetWatchers for hot-reloading
* **Stable Type Names**: this pr removes the TypeUuid requirement from
assets in favor of `std::any::type_name`. This makes defining assets
easier (no need to generate a new uuid / use weird proc macro syntax).
It also makes reading meta files easier (because things have "friendly
names"). We also use type names for components in scene files. If they
are good enough for components, they are good enough for assets. And
consistency across Bevy pillars is desirable. However,
`std::any::type_name` is not guaranteed to be stable (although in
practice it is). We've developed a [stable type
path](https://github.com/bevyengine/bevy/pull/7184) to resolve this,
which should be adopted when it is ready.
* **Command Line Interface**: It should be possible to run the asset
processor in a separate process from the command line. This will also
require building a network-server-backed AssetReader to communicate
between the app and the processor. We've been planning to build a "bevy
cli" for awhile. This seems like a good excuse to build it.
* **Asset Packing**: This is largely an additive feature, so it made
sense to me to punt this until we've laid the foundations in this PR.
* **Per-Platform Processed Assets**: It should be possible to generate
assets for multiple platforms by supporting multiple "processor
profiles" per asset (ex: compress with format X on PC and Y on iOS). I
think there should probably be arbitrary "profiles" (which can be
separate from actual platforms), which are then assigned to a given
platform when generating the final asset distribution for that platform.
Ex: maybe devs want a "Mobile" profile that is shared between iOS and
Android. Or a "LowEnd" profile shared between web and mobile.
* **Versioning and Migrations**: Assets, Loaders, Savers, and Processors
need to have versions to determine if their schema is valid. If an asset
/ loader version is incompatible with the current version expected at
runtime, the processor should be able to migrate them. I think we should
try using Bevy Reflect for this, as it would allow us to load the old
version as a dynamic Reflect type without actually having the old Rust
type. It would also allow us to define "patches" to migrate between
versions (Bevy Reflect devs are currently working on patching). The
`.meta` file already has its own format version. Migrating that to new
versions should also be possible.
* **Real Copy-on-write AssetPaths**: Rust's actual Cow (clone-on-write
type) currently used by AssetPath can still result in String clones that
aren't actually necessary (cloning an Owned Cow clones the contents).
Bevy's asset system requires cloning AssetPaths in a number of places,
which result in actual clones of the internal Strings. This is not
efficient. AssetPath internals should be reworked to exhibit truer
cow-like-behavior that reduces String clones to the absolute minimum.
* **Consider processor-less processing**: In theory the AssetServer
could run processors "inline" even if the background AssetProcessor is
disabled. If we decide this is actually desirable, we could add this.
But I don't think its a priority in the short or medium term.
* **Pre-emptive dependency loading**: We could encode dependencies in
processed meta files, which could then be used by the Asset Server to
kick of dependency loads as early as possible (prior to starting the
actual asset load). Is this desirable? How much time would this save in
practice?
* **Optimize Processor With UntypedAssetIds**: The processor exclusively
uses AssetPath to identify assets currently. It might be possible to
swap these out for UntypedAssetIds in some places, which are smaller /
cheaper to hash and compare.
* **One to Many Asset Processing**: An asset source file that produces
many assets currently must be processed into a single "processed" asset
source. If labeled assets can be written separately they can each have
their own configured savers _and_ they could be loaded more granularly.
Definitely worth exploring!
* **Automatically Track "Runtime-only" Asset Dependencies**: Right now,
tracking "created at runtime" asset dependencies requires adding them
via `asset_server.load_asset(StandardMaterial::default())`. I think with
some cleverness we could also do this for
`materials.add(StandardMaterial::default())`, making tracking work
"everywhere". There are challenges here relating to change detection /
ensuring the server is made aware of dependency changes. This could be
expensive in some cases.
* **"Dependency Changed" events**: Some assets have runtime artifacts
that need to be re-generated when one of their dependencies change (ex:
regenerate a material's bind group when a Texture needs to change). We
are generating the dependency graph so we can definitely produce these
events. Buuuuut generating these events will have a cost / they could be
high frequency for some assets, so we might want this to be opt-in for
specific cases.
* **Investigate Storing More Information In Handles**: Handles can now
store arbitrary information, which makes it cheaper and easier to
access. How much should we move into them? Canonical asset load states
(via atomics)? (`handle.is_loaded()` would be very cool). Should we
store the entire asset and remove the `Assets<T>` collection?
(`Arc<RwLock<Option<Image>>>`?)
* **Support processing and loading files without extensions**: This is a
pretty arbitrary restriction and could be supported with very minimal
changes.
* **Folder Meta**: It would be nice if we could define per folder
processor configuration defaults (likely in a `.meta` or `.folder_meta`
file). Things like "default to linear filtering for all Images in this
folder".
* **Replace async_broadcast with event-listener?** This might be
approximately drop-in for some uses and it feels more light weight
* **Support Running the AssetProcessor on the Web**: Most of the hard
work is done here, but there are some easy straggling TODOs (make the
transaction log an interface instead of a direct file writer so we can
write a web storage backend, implement an AssetReader/AssetWriter that
reads/writes to something like LocalStorage).
* **Consider identifying and preventing circular dependencies**: This is
especially important for "processor dependencies", as processing will
silently never finish in these cases.
* **Built-in/Inlined Asset Hot Reloading**: This PR regresses
"built-in/inlined" asset hot reloading (previously provided by the
DebugAssetServer). I'm intentionally punting this because I think it can
be cleanly implemented with "multiple asset sources" by registering a
"debug asset source" (ex: `debug://bevy_pbr/src/render/pbr.wgsl` asset
paths) in combination with an AssetWatcher for that asset source and
support for "manually loading pats with asset bytes instead of
AssetReaders". The old DebugAssetServer was quite nasty and I'd love to
avoid that hackery going forward.
* **Investigate ways to remove double-parsing meta files**: Parsing meta
files currently involves parsing once with "minimal" versions of the
meta file to extract the type name of the loader/processor config, then
parsing again to parse the "full" meta. This is suboptimal. We should be
able to define custom deserializers that (1) assume the loader/processor
type name comes first (2) dynamically looks up the loader/processor
registrations to deserialize settings in-line (similar to components in
the bevy scene format). Another alternative: deserialize as dynamic
Reflect objects and then convert.
* **More runtime loading configuration**: Support using the Handle type
as a hint to select an asset loader (instead of relying on AssetPath
extensions)
* **More high level Processor trait implementations**: For example, it
might be worth adding support for arbitrary chains of "asset transforms"
that modify an in-memory asset representation between loading and
saving. (ex: load a Mesh, run a `subdivide_mesh` transform, followed by
a `flip_normals` transform, then save the mesh to an efficient
compressed format).
* **Bevy Scene Handle Deserialization**: (see the relevant [Draft TODO
item](#draft-todo) for context)
* **Explore High Level Load Interfaces**: See [this
discussion](#discuss-on_loaded-high-level-interface) for one prototype.
* **Asset Streaming**: It would be great if we could stream Assets (ex:
stream a long video file piece by piece)
* **ID Exchanging**: In this PR Asset Handles/AssetIds are bigger than
they need to be because they have a Uuid enum variant. If we implement
an "id exchanging" system that trades Uuids for "efficient runtime ids",
we can cut down on the size of AssetIds, making them more efficient.
This has some open design questions, such as how to spawn entities with
"default" handle values (as these wouldn't have access to the exchange
api in the current system).
* **Asset Path Fixup Tooling**: Assets that inline asset paths inside
them will break when an asset moves. The asset system provides the
functionality to detect when paths break. We should build a framework
that enables formats to define "path migrations". This is especially
important for scene files. For editor-generated files, we should also
consider using UUIDs (see other bullet point) to avoid the need to
migrate in these cases.
---------
Co-authored-by: BeastLe9enD <beastle9end@outlook.de>
Co-authored-by: Mike <mike.hsu@gmail.com>
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
fix #8185, #6710
replace #7005 (closed)
rgb and rgba 16 bit textures currently default to `Rgba16Uint`, the more
common use is `Rgba16Unorm`, which also matches the default type of rgb8
and rgba8 textures.
## Solution
Change default to `Rgba16Unorm`
# Objective
Bevy currently crashes when meshes with different vertex counts for
attributes are provided.
## Solution
Instead of crashing we can warn and take the min length of all the given
attributes.
# Objective
- Fixes#9244.
## Solution
- Changed the `(Into)SystemSetConfigs` traits and structs be more like
the `(Into)SystemConfigs` traits and structs.
- Replaced uses of `IntoSystemSetConfig` with `IntoSystemSetConfigs`
- Added generic `ItemConfig` and `ItemConfigs` types.
- Changed `SystemConfig(s)` and `SystemSetConfig(s)` to be type aliases
to `ItemConfig(s)`.
- Added generic `process_configs` to `ScheduleGraph`.
- Changed `configure_sets_inner` and `add_systems_inner` to reuse
`process_configs`.
---
## Changelog
- Added `run_if` to `IntoSystemSetConfigs`
- Deprecated `Schedule::configure_set` and `App::configure_set`
- Removed `IntoSystemSetConfig`
## Migration Guide
- Use `App::configure_sets` instead of `App::configure_set`
- Use `Schedule::configure_sets` instead of `Schedule::configure_set`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Currently, the depth textures are cached based on the target. If
multiple camera have the same target but a different
`depth_texture_usage` bevy will just use the same texture and ignore
that setting.
## Solution
- Add the usage as a cache key
# Objective
- Currently we don't have panicking alternative for getting components
from `Query` like for resources. Partially addresses #9443.
## Solution
- Add these functions.
---
## Changelog
### Added
- `Query::component` and `Query::component_mut` to get specific
component from query and panic on error.
# Objective
The recently introduced check that the cursor position returned by
`Window::cursor_position()` is within the bounds of the window
(3cf94e7c9d)
has the following issue:
If *w* is the window width, points within the window satisfy the
condition 0 ≤ *x* < *w*, but the code assumes the condition 0 ≤ *x* ≤
*w*. In other words, if *x* = *w*, the point is not within the window
bounds. Likewise for the height. This program demonstrates the issue:
```rust
use bevy::{prelude::*, window::WindowResolution};
fn main() {
let mut window = Window {
resolution: WindowResolution::new(100.0, 100.0),
..default()
};
window.set_cursor_position(Some(Vec2::new(100.0, 0.0)));
println!("{:?}", window.cursor_position());
}
```
It prints `Some(Vec2(100.0, 0.0))` instead of the expected `None`.
## Solution
- Exclude the upper bound, i.e., the window width for the *x* position
and the window height for the *y* position.
# Objective
Allow mutably iterating over all registered diagnostics. This is a
useful utility method when exposing bevy's diagnostics in an editor that
allows toggling whether the diagnostic is enabled.
## Solution
- Add `iter_mut`, mirroring what `iter` does, just mutably.
---
## Changelog
### Added
- Added `DiagnosticsStore::iter_mut` for mutably iterating over all
registered diagnostics.
# Objective
This PR aims to fix a handful of problems with the `SpatialBundle` docs:
The docs describe the role of the single components of the bundle,
overshadowing the purpose of `SpatialBundle` itself. Also, those items
may be added, removed or changed over time, as it happened with #9497,
requiring a higher maintenance effort, which will often result in
errors, as it happened.
## Solution
Just describe the role of `SpatialBundle` and of the transform and
visibility concepts, without mentioning the specific component types.
Since the bundle has public fields, the reader can easily click them and
read the documentation if they need to know more. I removed the mention
of numbers of components since they were four, now they are five, and
who knows how many they will be in the future. In this process, I
removed the bullet points, which are no longer needed, and were
contextually wrong in the first place, since they were meant to list the
components, but ended up describing use-cases and requirements for
hierarchies.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
`QueryState::is_empty` is unsound, as it does not validate the world. If
a mismatched world is passed in, then the query filter may cast a
component to an incorrect type, causing undefined behavior.
## Solution
Add world validation. To prevent a performance regression in `Query`
(whose world does not need to be validated), the unchecked function
`is_empty_unsafe_world_cell` has been added. This also allows us to
remove one of the last usages of the private function
`UnsafeWorldCell::unsafe_world`, which takes us a step towards being
able to remove that method entirely.
The WGSL spec says that all scalar or vector integer vertex stage
outputs and fragment stage inputs must be marked as @interpolate(flat).
I think wgpu fixed this up for us, but being explicit is more correct.
# Objective
- Supercedes #8872
- Improve sprite rendering performance after the regression in #9236
## Solution
- Use an instance-rate vertex buffer to store per-instance data.
- Store color, UV offset and scale, and a transform per instance.
- Convert Sprite rect, custom_size, anchor, and flip_x/_y to an affine
3x4 matrix and store the transpose of that in the per-instance data.
This is similar to how MeshUniform uses transpose affine matrices.
- Use a special index buffer that has batches of 6 indices referencing 4
vertices. The lower 2 bits indicate the x and y of a quad such that the
corners are:
```
10 11
00 01
```
UVs are implicit but get modified by UV offset and scale The remaining
upper bits contain the instance index.
## Benchmarks
I will compare versus `main` before #9236 because the results should be
as good as or faster than that. Running `bevymark -- 10000 16` on an M1
Max with `main` at `e8b38925` in yellow, this PR in red:
![Screenshot 2023-08-27 at 18 44
10](https://github.com/bevyengine/bevy/assets/302146/bdc5c929-d547-44bb-b519-20dce676a316)
Looking at the median frame times, that's a 37% reduction from before.
---
## Changelog
- Changed: Improved sprite rendering performance by leveraging an
instance-rate vertex buffer.
---------
Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
# Objective
Fix#8267.
Fixes half of #7840.
The `ComputedVisibility` component contains two flags: hierarchy
visibility, and view visibility (whether its visible to any cameras).
Due to the modular and open-ended way that view visibility is computed,
it triggers change detection every single frame, even when the value
does not change. Since hierarchy visibility is stored in the same
component as view visibility, this means that change detection for
inherited visibility is completely broken.
At the company I work for, this has become a real issue. We are using
change detection to only re-render scenes when necessary. The broken
state of change detection for computed visibility means that we have to
to rely on the non-inherited `Visibility` component for now. This is
workable in the early stages of our project, but since we will
inevitably want to use the hierarchy, we will have to either:
1. Roll our own solution for computed visibility.
2. Fix the issue for everyone.
## Solution
Split the `ComputedVisibility` component into two: `InheritedVisibilty`
and `ViewVisibility`.
This allows change detection to behave properly for
`InheritedVisibility`.
View visiblity is still erratic, although it is less useful to be able
to detect changes
for this flavor of visibility.
Overall, this actually simplifies the API. Since the visibility system
consists of
self-explaining components, it is much easier to document the behavior
and usage.
This approach is more modular and "ECS-like" -- one could
strip out the `ViewVisibility` component entirely if it's not needed,
and rely only on inherited visibility.
---
## Changelog
- `ComputedVisibility` has been removed in favor of:
`InheritedVisibility` and `ViewVisiblity`.
## Migration Guide
The `ComputedVisibilty` component has been split into
`InheritedVisiblity` and
`ViewVisibility`. Replace any usages of
`ComputedVisibility::is_visible_in_hierarchy`
with `InheritedVisibility::get`, and replace
`ComputedVisibility::is_visible_in_view`
with `ViewVisibility::get`.
```rust
// Before:
commands.spawn(VisibilityBundle {
visibility: Visibility::Inherited,
computed_visibility: ComputedVisibility::default(),
});
// After:
commands.spawn(VisibilityBundle {
visibility: Visibility::Inherited,
inherited_visibility: InheritedVisibility::default(),
view_visibility: ViewVisibility::default(),
});
```
```rust
// Before:
fn my_system(q: Query<&ComputedVisibilty>) {
for vis in &q {
if vis.is_visible_in_hierarchy() {
// After:
fn my_system(q: Query<&InheritedVisibility>) {
for inherited_visibility in &q {
if inherited_visibility.get() {
```
```rust
// Before:
fn my_system(q: Query<&ComputedVisibilty>) {
for vis in &q {
if vis.is_visible_in_view() {
// After:
fn my_system(q: Query<&ViewVisibility>) {
for view_visibility in &q {
if view_visibility.get() {
```
```rust
// Before:
fn my_system(mut q: Query<&mut ComputedVisibilty>) {
for vis in &mut q {
vis.set_visible_in_view();
// After:
fn my_system(mut q: Query<&mut ViewVisibility>) {
for view_visibility in &mut q {
view_visibility.set();
```
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
# Objective
- Fixes#9641
- Anonymous sets are named by their system members. When
`ScheduleBuildSettings::report_sets` is on, systems are named by their
sets. So when getting the anonymous set name this would cause an
infinite recursion.
## Solution
- When getting the anonymous system set name, don't get their system's
names with the sets the systems belong to.
## Other Possible solutions
- An alternate solution might be to skip anonymous sets when getting the
system's name for an anonymous set's name.
# Objective
- I broke ambiguity reporting in one of my refactors.
`conflicts_to_string` should have been using the passed in parameter
rather than the one stored on self.
# Objective
I've been collecting some mistakes in the documentation and fixed them
---------
Co-authored-by: Emi <emanuel.boehm@gmail.com>
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
`Window::physical_cursor_position` checks to see if the cursor's
position is inside the window but it constructs the bounding rect for
the window using its logical size and then checks to see if it contains
the cursor's physical position. When the physical size is smaller than
the logical size, this leaves a dead zone where the cursor is over the
window but its position is unreported.
fixes: #9656
## Solution
Use the physical size of the window.
# Objective
Make it easier to create bounding boxes in user code by providing a
constructor that computes a box surrounding an arbitrary number of
points.
## Solution
Add `Aabb::enclosing`, which accepts iterators, slices, or arrays.
---------
Co-authored-by: Tristan Guichaoua <33934311+tguichaoua@users.noreply.github.com>
# Objective
- The current `EventReader::iter` has been determined to cause confusion
among new Bevy users. It was suggested by @JoJoJet to rename the method
to better clarify its usage.
- Solves #9624
## Solution
- Rename `EventReader::iter` to `EventReader::read`.
- Rename `EventReader::iter_with_id` to `EventReader::read_with_id`.
- Rename `ManualEventReader::iter` to `ManualEventReader::read`.
- Rename `ManualEventReader::iter_with_id` to
`ManualEventReader::read_with_id`.
---
## Changelog
- `EventReader::iter` has been renamed to `EventReader::read`.
- `EventReader::iter_with_id` has been renamed to
`EventReader::read_with_id`.
- `ManualEventReader::iter` has been renamed to
`ManualEventReader::read`.
- `ManualEventReader::iter_with_id` has been renamed to
`ManualEventReader::read_with_id`.
- Deprecated `EventReader::iter`
- Deprecated `EventReader::iter_with_id`
- Deprecated `ManualEventReader::iter`
- Deprecated `ManualEventReader::iter_with_id`
## Migration Guide
- Existing usages of `EventReader::iter` and `EventReader::iter_with_id`
will have to be changed to `EventReader::read` and
`EventReader::read_with_id` respectively.
- Existing usages of `ManualEventReader::iter` and
`ManualEventReader::iter_with_id` will have to be changed to
`ManualEventReader::read` and `ManualEventReader::read_with_id`
respectively.
# Objective
The latest `clippy` release has a much more aggressive application of
the
[`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#/explicit_into_iter_loop?groups=pedantic)
pedantic lint.
As a result, clippy now suggests the following:
```diff
-for event in events.iter() {
+for event in &mut events {
```
I'm generally in favor of this lint. Using `for mut item in &mut query`
is also recommended over `for mut item in query.iter_mut()` for good
reasons IMO.
But, it is my personal belief that `&mut events` is much less clear than
`events.iter()`.
Why? The reason is that the events from `EventReader` **are not
mutable**, they are immutable references to each event in the event
reader. `&mut events` suggests we are getting mutable access to events —
similarly to `&mut query` — which is not the case. Using `&mut events`
is therefore misleading.
`IntoIterator` requires a mutable `EventReader` because it updates the
internal `last_event_count`, not because it let you mutate it.
So clippy's suggested improvement is a downgrade.
## Solution
Do not implement `IntoIterator` for `&mut events`.
Without the impl, clippy won't suggest its "fix". This also prevents
generally people from using `&mut events` for iterating `EventReader`s,
which makes the ecosystem every-so-slightly better.
---
## Changelog
- Removed `IntoIterator` impl for `&mut EventReader`
## Migration Guide
- `&mut EventReader` does not implement `IntoIterator` anymore. replace
`for foo in &mut events` by `for foo in events.iter()`
# Objective
- Some of the old ambiguity tests didn't get ported over during schedule
v3.
## Solution
- Port over tests from
15ee98db8d/crates/bevy_ecs/src/schedule/ambiguity_detection.rs (L279-L612)
with minimal changes
- Make a method to convert the ambiguity conflicts to a string for
easier verification of correct results.
# Objective
As far as I can tell, this is no longer needed since the switch to
fancier shader imports via `naga_oil`.
This shouldn't have any affect on compile times because it's in our tree
from `naga_oil`, `tracing-subscriber`, and `rodio`.
# Objective
Rename `Val`'s `evaluate` method to `resolve`.
Implement `resolve` support for `Val`'s viewport variants.
fixes#9535
---
## Changelog
`bevy_ui::ui_node::Val`:
* Renamed the following methods and added a `viewport_size` parameter:
- `evaluate` to `resolve`
- `try_add_with_size` to `try_add_with_context`
- `try_add_assign_with_size` to `try_add_assign_with_context`
- `try_sub_with_size` to `try_sub_with_context`
- `try_sub_assign_with_size` to `try_sub_assign_with_context`
* Implemented `resolve` support for `Val`'s viewport coordinate types
## Migration Guide
* Renamed the following `Val` methods and added a `viewport_size`
parameter:
- `evaluate` to `resolve`
- `try_add_with_size` to `try_add_with_context`
- `try_add_assign_with_size` to `try_add_assign_with_context`
- `try_sub_with_size` to `try_sub_with_context`
- `try_sub_assign_with_size` to `try_sub_assign_with_context`
Legitimately, bevy emits a WARN when encountering entities in UI trees
without NodeBunlde components.
Bevy pretty much always panics when such a thing happens, due to the
update_clipping system.
However, sometimes, it's perfectly legitimate to have a child without UI
nodes in a UI tree. For example, as a "seed" entity that is consumed by
a 3rd party plugin, which will later spawn a valid UI tree. In loading
scenarios, you are pretty much guaranteed to have incomplete children.
The presence of the WARN hints that bevy does not intend to panic on
such occasion (otherwise the warn! would be a panic!) so I assume panic
is an unintended behavior, aka a bug.
## Solution
Early-return instead of panicking.
I did only test that it indeed fixed the panic, not checked for UI
inconsistencies. Though on a logical level, it can only have changed
code that would otherwise panic.
## Alternatives
Instead of early-returning on invalid entity in `update_clipping`, do
not call it with invalid entity in its recursive call.
---
## Changelog
- Do not panic on non-UI child of UI entity
# Objective
Fix#4278Fix#5504Fix#9422
Provide safe ways to borrow an entire entity, while allowing disjoint
mutable access. `EntityRef` and `EntityMut` are not suitable for this,
since they provide access to the entire world -- they are just helper
types for working with `&World`/`&mut World`.
This has potential uses for reflection and serialization
## Solution
Remove `EntityRef::world`, which allows it to soundly be used within
queries.
`EntityMut` no longer supports structural world mutations, which allows
multiple instances of it to exist for different entities at once.
Structural world mutations are performed using the new type
`EntityWorldMut`.
```rust
fn disjoint_system(
q2: Query<&mut A>,
q1: Query<EntityMut, Without<A>>,
) { ... }
let [entity1, entity2] = world.many_entities_mut([id1, id2]);
*entity1.get_mut::<T>().unwrap() = *entity2.get().unwrap();
for entity in world.iter_entities_mut() {
...
}
```
---
## Changelog
- Removed `EntityRef::world`, to fix a soundness issue with queries.
+ Removed the ability to structurally mutate the world using
`EntityMut`, which allows it to be used in queries.
+ Added `EntityWorldMut`, which is used to perform structural mutations
that are no longer allowed using `EntityMut`.
## Migration Guide
**Note for maintainers: ensure that the guide for #9604 is updated
accordingly.**
Removed the method `EntityRef::world`, to fix a soundness issue with
queries. If you need access to `&World` while using an `EntityRef`,
consider passing the world as a separate parameter.
`EntityMut` can no longer perform 'structural' world mutations, such as
adding or removing components, or despawning the entity. Additionally,
`EntityMut::world`, `EntityMut::world_mut` , and
`EntityMut::world_scope` have been removed.
Instead, use the newly-added type `EntityWorldMut`, which is a helper
type for working with `&mut World`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Move schedule name into `Schedule` to allow the schedule name to be
used for errors and tracing in Schedule methods
- Fixes#9510
## Solution
- Move label onto `Schedule` and adjust api's on `World` and `Schedule`
to not pass explicit label where it makes sense to.
- add name to errors and tracing.
- `Schedule::new` now takes a label so either add the label or use
`Schedule::default` which uses a default label. `default` is mostly used
in doc examples and tests.
---
## Changelog
- move label onto `Schedule` to improve error message and logging for
schedules.
## Migration Guide
`Schedule::new` and `App::add_schedule`
```rust
// old
let schedule = Schedule::new();
app.add_schedule(MyLabel, schedule);
// new
let schedule = Schedule::new(MyLabel);
app.add_schedule(schedule);
```
if you aren't using a label and are using the schedule struct directly
you can use the default constructor.
```rust
// old
let schedule = Schedule::new();
schedule.run(world);
// new
let schedule = Schedule::default();
schedule.run(world);
```
`Schedules:insert`
```rust
// old
let schedule = Schedule::new();
schedules.insert(MyLabel, schedule);
// new
let schedule = Schedule::new(MyLabel);
schedules.insert(schedule);
```
`World::add_schedule`
```rust
// old
let schedule = Schedule::new();
world.add_schedule(MyLabel, schedule);
// new
let schedule = Schedule::new(MyLabel);
world.add_schedule(schedule);
```
# Objective
Every frame, `Events::update` gets called, which clears out any old
events from the buffer. There should be a way of taking ownership of
these old events instead of throwing them away. My use-case is dumping
old events into a debug menu so they can be inspected later.
One potential workaround is to just have a system that clones any
incoming events and stores them in a list -- however, this requires the
events to implement `Clone`.
## Solution
Add `Events::update_drain`, which returns an iterator of the events that
were removed from the buffer.
# Objective
Doc comment for the `global_transform` field in `NodeBundle` says:
```
/// This field is automatically managed by the UI layout system.
```
The `GlobalTransform` component is the thing being managed, not the
`global_transform` field, and the `TransformPropagate` systems do the
managing, not the UI layout system.
# Objective
- Fixes: #9508
- Fixes: #9526
## Solution
- Adds
```rust
fn configure_schedules(&mut self, schedule_build_settings: ScheduleBuildSettings)
```
to `Schedules`, and `App` to simplify applying `ScheduleBuildSettings`
to all schedules.
---
## Migration Guide
- No breaking changes.
- Adds `Schedule::get_build_settings()` getter for the schedule's
`ScheduleBuildSettings`.
- Can replaced manual configuration of all schedules:
```rust
// Old
for (_, schedule) in app.world.resource_mut::<Schedules>().iter_mut() {
schedule.set_build_settings(build_settings);
}
// New
app.configure_schedules(build_settings);
```
# Objective
To enable non exclusive system usage of reflected components and make
reflection more ergonomic to use by making it more in line with standard
entity commands.
## Solution
- Implements a new `EntityCommands` extension trait for reflection
related functions in the reflect module of bevy_ecs.
- Implements 4 new commands, `insert_reflect`,
`insert_reflect_with_registry`, `remove_reflect`, and
`remove_reflect_with_registry`. Both insert commands take a `Box<dyn
Reflect>` component while the remove commands take the component type
name.
- Made `EntityCommands` fields pub(crate) to allow access in the reflect
module. (Might be worth making these just public to enable user end
custom entity commands in a different pr)
- Added basic tests to ensure the commands are actually working.
- Documentation of functions.
---
## Changelog
Added:
- Implements 4 new commands on the new entity commands extension.
- `insert_reflect`
- `remove_reflect`
- `insert_reflect_with_registry`
- `remove_reflect_with_registry`
The commands operate the same except the with_registry commands take a
generic parameter for a resource that implements `AsRef<TypeRegistry>`.
Otherwise the default commands use the `AppTypeRegistry` for reflection
data.
Changed:
- Made `EntityCommands` fields pub(crate) to allow access in the reflect
module.
> Hopefully this time it works. Please don't make me rebase again ☹
# Objective
- Fixes [#8835](https://github.com/bevyengine/bevy/issues/8835)
## Solution
- Added a note to the `set_volume` docstring which explains how volume
is interpreted.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: GitGhillie <jillisnoordhoek@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
# Objective
- Fixes#4917
- Replaces #9602
## Solution
- Replaced `EntityCommand` implementation for `FnOnce` to apply to
`FnOnce(EntityMut)` instead of `FnOnce(Entity, &mut World)`
---
## Changelog
- `FnOnce(Entity, &mut World)` no longer implements `EntityCommand`.
This is a breaking change.
## Migration Guide
### 1. New-Type `FnOnce`
Create an `EntityCommand` type which implements the method you
previously wrote:
```rust
pub struct ClassicEntityCommand<F>(pub F);
impl<F> EntityCommand for ClassicEntityCommand<F>
where
F: FnOnce(Entity, &mut World) + Send + 'static,
{
fn apply(self, id: Entity, world: &mut World) {
(self.0)(id, world);
}
}
commands.add(ClassicEntityCommand(|id: Entity, world: &mut World| {
/* ... */
}));
```
### 2. Extract `(Entity, &mut World)` from `EntityMut`
The method `into_world_mut` can be used to gain access to the `World`
from an `EntityMut`.
```rust
let old = |id: Entity, world: &mut World| {
/* ... */
};
let new = |mut entity: EntityMut| {
let id = entity.id();
let world = entity.into_world_mut();
/* ... */
};
```
# Objective
The name `ManualEventIterator` is long and unnecessary, as this is the
iterator type used for both `EventReader` and `ManualEventReader`.
## Solution
Rename `ManualEventIterator` to `EventIterator`. To ease migration, add
a deprecated type alias with the old name.
---
## Changelog
- The types `ManualEventIterator{WithId}` have been renamed to
`EventIterator{WithId}`.
## Migration Guide
The type `ManualEventIterator` has been renamed to `EventIterator`.
Additonally, `ManualEventIteratorWithId` has been renamed to
`EventIteratorWithId`.
# Objective
#5483 allows for the creation of non-`Sync` locals. However, it's not
actually possible to use these types as there is a `Sync` bound on the
`Deref` impls.
## Solution
Remove the unnecessary bounds.
# Objective
- have errors in configure_set and configure_sets show the line number
of the user calling location rather than pointing to schedule.rs
- use display formatting for the errors
## Example Error Text
```text
// dependency loop
// before
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39
// after
thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9
// hierarchy loop
// before
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3
// after
thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9
// configuring a system type set
// before
thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9
//after
thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9
```
Code to produce errors:
```rust
use bevy::prelude::*;
#[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)]
enum TestSet {
A,
}
fn main() {
fn foo() {}
let mut app = App::empty();
// Hierarchy Loop
app.configure_set(Main, TestSet::A.in_set(TestSet::A));
// Dependency Loop
app.configure_set(Main, TestSet::A.after(TestSet::A));
// Configure System Type Set
app.configure_set(Main, foo.into_system_set());
}
```
# Objective
A Bezier curve is a curve defined by two or more control points. In the
simplest form, it's just a line. The (arguably) most common type of
Bezier curve is a cubic Bezier, defined by four control points. These
are often used in animation, etc. Bevy has a Bezier curve struct called
`Bezier`. However, this is technically a misnomer as it only represents
cubic Bezier curves.
## Solution
This PR changes the struct name to `CubicBezier` to more accurately
reflect the struct's usage. Since it's exposed in Bevy's prelude, it can
potentially collide with other `Bezier` implementations. While that
might instead be an argument for removing it from the prelude, there's
also something to be said for adding a more general `Bezier` into Bevy,
in which case we'd likely want to use the name `Bezier`. As a final
motivator, not only is the struct located in `cubic_spines.rs`, there
are also several other spline-related structs which follow the
`CubicXxx` naming convention where applicable. For example,
`CubicSegment` represents a cubic Bezier curve (with coefficients
pre-baked).
---
## Migration Guide
- Change all `Bezier` references to `CubicBezier`
# Objective
Fixes#9550
## Solution
Removes a check that asserts that _all_ attribute metas are path-only,
rather than just the `#[deref]` attribute itself.
---
## Changelog
- Fixes an issue where deriving `Deref` with `#[deref]` on a field
causes other attributes to sometimes result in a compile error
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
These new defaults match what is used by `Camera2dBundle::default()`,
removing a potential footgun from overriding a field in the projection
component of the bundle.
## Solution
Adjusted the near clipping plane of `OrthographicProjection::default()`
to `-1000.`.
---
## Changelog
Changed: `OrthographicProjection::default()` now matches the value used
in `Camera2dBundle::default()`
## Migration Guide
Workarounds used to keep the projection consistent with the bundle
defaults are no longer required. Meanwhile, uses of
`OrthographicProjection` in 2D scenes may need to be adjusted; the
`near` clipping plane default was changed from `0.0` to `-1000.0`.
# Objective
`sync_simple_transforms` only checks for removed parents and doesn't
filter for `Without<Parent>`, so it overwrites the `GlobalTransform` of
non-orphan entities that were orphaned and then reparented since the
last update.
Introduced by #7264
## Solution
Filter for `Without<Parent>`.
Fixes#9517, #9492
## Changelog
`sync_simple_transforms`:
* Added a `Without<Parent>` filter to the orphaned entities query.
Fixes https://github.com/bevyengine/bevy/issues/9458.
On case-insensitive filesystems (Windows, Mac, NTFS mounted in Linux,
etc.), a path can be represented in a multiple ways:
- `c:\users\user\rust\assets\hello\world`
- `c:/users/user/rust/assets/hello/world`
- `C:\USERS\USER\rust\assets\hello\world`
If user specifies a path variant that doesn't match asset folder path
bevy calculates, `path.strip_prefix()` will fail, as demonstrated below:
```rs
dbg!(Path::new("c:/foo/bar/baz").strip_prefix("c:/foo"));
// Ok("bar/baz")
dbg!(Path::new("c:/FOO/bar/baz").strip_prefix("c:/foo"));
// StripPrefixError(())
```
This commit rewrites the code in question in a way that prefix stripping
is no longer necessary.
I've tested with the following paths on my computer:
```rs
let res = asset_server.load_folder("C:\\Users\\user\\rust\\assets\\foo\\bar");
dbg!(res);
let res = asset_server.load_folder("c:\\users\\user\\rust\\assets\\foo\\bar");
dbg!(res);
let res = asset_server.load_folder("C:/Users/user/rust/assets/foo/bar");
dbg!(res);
```
# Objective
* There is no way to read the fields of `GridPlacement` once set.
* Values of `0` for `GridPlacement`'s fields are invalid but can be set.
* A non-zero representation would be half the size.
fixes#9474
## Solution
* Add `get_start`, `get_end` and `get_span` accessor methods.
* Change`GridPlacement`'s constructor functions to panic on arguments of
zero.
* Use non-zero types instead of primitives for `GridPlacement`'s fields.
---
## Changelog
`bevy_ui::ui_node::GridPlacement`:
* Field types have been changed to `Option<NonZeroI16>` and
`Option<NonZeroU16>`. This is because zero values are not valid for
`GridPlacement`. Previously, Taffy interpreted these as auto variants.
* Constructor functions for `GridPlacement` panic on arguments of `0`.
* Added accessor functions: `get_start`, `get_end`, and `get_span`.
These return the inner primitive value (if present) of the respective
fields.
## Migration Guide
`GridPlacement`'s constructor functions no longer accept values of `0`.
Given any argument of `0` they will panic with a `GridPlacementError`.
# Objective
- Fixes#9321
## Solution
- `EntityMap` has been replaced by a simple `HashMap<Entity, Entity>`.
---
## Changelog
- `EntityMap::world_scope` has been replaced with `World::world_scope`
to avoid creating a new trait. This is a public facing change to the
call semantics, but has no effect on results or behaviour.
- `EntityMap`, as a `HashMap`, now operates on `&Entity` rather than
`Entity`. This changes many standard access functions (e.g, `.get`) in a
public-facing way.
## Migration Guide
- Calls to `EntityMap::world_scope` can be directly replaced with the
following:
`map.world_scope(&mut world)` -> `world.world_scope(&mut map)`
- Calls to legacy `EntityMap` methods such as `EntityMap::get` must
explicitly include de/reference symbols:
`let entity = map.get(parent);` -> `let &entity = map.get(&parent);`
# Objective
Fixes#9420
## Solution
Remove one of the two `AppExit` event checks in the
`ScheduleRunnerPlugin`'s main loop. Specificially, the check that
happens immediately before calling `App.update()`, to be consistent with
the `WinitPlugin`.
# Objective
fixes#8357
gltf animations can affect multiple "root" nodes (i.e. top level nodes
within a gltf scene).
the current loader adds an AnimationPlayer to each root node which is
affected by any animation. when a clip which affects multiple root nodes
is played on a root node player, the root node name is not checked,
leading to potentially incorrect weights being applied.
also, the `AnimationClip::compatible_with` method will never return true
for those clips, as it checks that all paths start with the root node
name - not all paths start with the same name so it can't return true.
## Solution
- check the first path node name matches the given root
- change compatible_with to return true if `any` match is found
a better alternative would probably be to attach the player to the scene
root instead of the first child, and then walk the full path from there.
this would be breaking (and would stop multiple animations that *don't*
overlap from being played concurrently), but i'm happy to modify to that
if it's preferred.
---------
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
# Objective
- Meshes with a higher number of joints than `MAX_JOINTS` are crashing
- Fixes partly #9021 (doesn't crash anymore, but the mesh is not
correctly displayed)
## Solution
- Only take up to `MAX_JOINTS` joints when extending the buffer
# Objective
Make code relating to event more readable.
Currently the `impl` block of `Events` is split in two, and the big part
of its implementations are put at the end of the file, far from the
definition of the `struct`.
## Solution
- Move and merge the `impl` blocks of `Events` next to its definition.
- Move the `EventSequence` definition and implementations before the
`Events`, because they're pretty trivial and help understand how
`Events` work, rather than being buried bellow `Events`.
I separated those two steps in two commits to not be too confusing. I
didn't modify any code of documentation. I want to do a second PR with
such modifications after this one is merged.
# Objective
Similar to #6344, but contains only `ReflectBundle` changes. Useful for
scripting. The implementation has also been updated to look exactly like
`ReflectComponent`.
---
## Changelog
### Added
- Reflection for bundles.
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
This PR's first aim is to fix a mistake in `HalfSpace`'s documentation.
When defining a `Frustum` myself in bevy_basic_portals, I realised that
the "distance" of the `HalfSpace` is not, as the current doc defines,
the "distance from the origin along the normal", but actually the
opposite of that.
See the example I gave in this PR.
This means one of two things:
1. The documentation about `HalfSpace` is wrong (it is either way
because of the `n.p + d > 0` formula given later anyway, which is how it
behaves, but in that formula `d` is indeed the opposite of the "distance
from the origin along the normal", otherwise it should be `n.p > d`)
2. The distance is supposed to be the "distance from the origin along
the normal" but when used in a Frustum it's used as the opposite, and it
is a mistake
3. Same as 2, but it is somehow intended
Since I think `HalfSpace` is only used for `Frustum`, and it's easier to
fix documentation than code, I assumed for this PR we're in case number
1. If we're in case number 3, the documentation of `Frustum` needs to
change, and in case number 2, the code needs to be fixed.
While I was at it, I also :
- Tried to improve the documentation for `Frustum`, `Aabb`, and
`VisibilitySystems`, among others, since they're all related to
`Frustum`.
- Fixed documentation about frustum culling not applying to 2d objects,
which is not true since https://github.com/bevyengine/bevy/pull/7885
## Remarks and questions
- What about a `HalfSpace` with an infinite distance, is it allowed and
does it represents the whole space? If so it should probably be
mentioned.
- I referenced the `update_frusta` system in
`bevy_render::view::visibility` directly instead of referencing its
system set, should I reference the system set instead? It's a bit
annoying since it's in 3 sets.
- `visibility_propagate` is not public for some reason, I think it
probably should be, but for now I only documented its system set, should
I make it public? I don't think that would count as a breaking change?
- Why is `Aabb` inserted by a system, with `NoFrustumCulling` as an
opt-out, instead of having it inserted by default in `PbrBundle` for
example and then the system calculating it when it's added? Is it
because there is still no way to have an optional component inside a
bundle?
---------
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
## Objective
- `bevy_text/src/pipeline.rs` had some crufty code.
## Solution
Remove the cruft.
- `&mut self` argument was unused by
`TextPipeline::create_text_measure`, so we replace it with a constructor
`TextMeasureInfo::from_text`.
- We also pass a `&Text` to `from_text` since there is no reason to
split the struct before passing it as argument.
- from_text also checks beforehand that every Font exist in the
Assets<Font>. This allows rust to skip the drop code on the Vecs we
create in the method, since there is no early exit.
- We also remove the scaled_fonts field on `TextMeasureInfo`. This
avoids an additional allocation. We can re-use the font on `fonts`
instead in `compute_size`. Building a `ScaledFont` seems fairly cheap,
when looking at the ab_glyph internals.
- We also implement ToSectionText on TextMeasureSection, this let us
skip creating a whole new Vec each time we call compute_size.
- This let us remove compute_size_from_section_text, since its only
purpose was to not have to allocate the Vec we just made redundant.
- Make some immutabe `Vec<T>` into `Box<[T]>` and `String` into
`Box<str>`
- `{min,max}_width_content_size` fields of `TextMeasureInfo` have name
`width` in them, yet the contain information on both width and height.
- `TextMeasureInfo::linebreak_behaviour` -> `linebreak_behavior`
## Migration Guide
- The `ResMut<TextPipeline>` argument to `measure_text_system` doesn't
exist anymore. If you were calling this system manually, you should
remove the argument.
- The `{min,max}_width_content_size` fields of `TextMeasureInfo` are
renamed to `min` and `max` respectively
- Other changes to `TextMeasureInfo` may also break your code if you
were manually building it. Please consider using the new
`TextMeasureInfo::from_text` to build one instead.
- `TextPipeline::create_text_measure` has been removed in favor of
`TextMeasureInfo::from_text`
# Objective
Added `AnimationPlayer` API UX improvements.
- Succestor to https://github.com/bevyengine/bevy/pull/5912
- Fixes https://github.com/bevyengine/bevy/issues/5848
_(Credits to @asafigan for filing #5848, creating the initial pull
request, and the discussion in #5912)_
## Solution
- Created `RepeatAnimation` enum to describe an animation repetition
behavior.
- Added `is_finished()`, `set_repeat()`, and `is_playback_reversed()`
methods to the animation player.
- ~~Made the animation clip optional as per the comment from #5912~~
> ~~My problem is that the default handle [used the initialize a
`PlayingAnimation`] could actually refer to an actual animation if an
AnimationClip is set for the default handle, which leads me to ask,
"Should animation_clip should be an Option?"~~
- Added an accessor for the animation clip `animation_clip()` to the
animation player.
To determine if an animation is finished, we use the number of times the
animation has completed and the repetition behavior. If the animation is
playing in reverse then `elapsed < 0.0` counts as a completion.
Otherwise, `elapsed > animation.duration` counts as a completion. This
is what I would expect, personally. If there's any ambiguity, perhaps we
could add some `AnimationCompletionBehavior`, to specify that kind of
completion behavior to use.
Update: Previously `PlayingAnimation::elapsed` was being used as the
seek time into the animation clip. This was misleading because if you
increased the speed of the animation it would also increase (or
decrease) the elapsed time. In other words, the elapsed time was not
actually the elapsed time. To solve this, we introduce
`PlayingAnimation::seek_time` to serve as the value we manipulate the
move between keyframes. Consequently, `elapsed()` now returns the actual
elapsed time, and is not effected by the animation speed. Because
`set_elapsed` was being used to manipulate the displayed keyframe, we
introduce `AnimationPlayer::seek_to` and `AnimationPlayer::replay` to
provide this functionality.
## Migration Guide
- Removed `set_elapsed`.
- Removed `stop_repeating` in favour of
`AnimationPlayer::set_repeat(RepeatAnimation::Never)`.
- Introduced `seek_to` to seek to a given timestamp inside of the
animation.
- Introduced `seek_time` accessor for the `PlayingAnimation::seek_to`.
- Introduced `AnimationPlayer::replay` to reset the `PlayingAnimation`
to a state where no time has elapsed.
---------
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
# Objective
Fixes#8840
Make the cursor position more consistent, right now the cursor position
is *sometimes* outside of the window and returns the position and
*sometimes* `None`.
Even in the cases where someone might be using that position that is
outside of the window, it'll probably require some manual
transformations for it to actually be useful.
## Solution
Check the windows width and height for out of bounds positions.
---
## Changelog
- Cursor position is now always `None` when outside of the window.
---------
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
# Objective
Any time we wish to transform the output of a system, we currently use
system piping to do so:
```rust
my_system.pipe(|In(x)| do_something(x))
```
Unfortunately, system piping is not a zero cost abstraction. Each call
to `.pipe` requires allocating two extra access sets: one for the second
system and one for the combined accesses of both systems. This also adds
extra work to each call to `update_archetype_component_access`, which
stacks as one adds multiple layers of system piping.
## Solution
Add the `AdapterSystem` abstraction: similar to `CombinatorSystem`, this
allows you to implement a trait to generically control how a system is
run and how its inputs and outputs are processed. Unlike
`CombinatorSystem`, this does not have any overhead when computing world
accesses which makes it ideal for simple operations such as inverting or
ignoring the output of a system.
Add the extension method `.map(...)`: this is similar to `.pipe(...)`,
only it accepts a closure as an argument instead of an `In<T>` system.
```rust
my_system.map(do_something)
```
This has the added benefit of making system names less messy: a system
that ignores its output will just be called `my_system`, instead of
`Pipe(my_system, ignore)`
---
## Changelog
TODO
## Migration Guide
The `system_adapter` functions have been deprecated: use `.map` instead,
which is a lightweight alternative to `.pipe`.
```rust
// Before:
my_system.pipe(system_adapter::ignore)
my_system.pipe(system_adapter::unwrap)
my_system.pipe(system_adapter::new(T::from))
// After:
my_system.map(std::mem::drop)
my_system.map(Result::unwrap)
my_system.map(T::from)
// Before:
my_system.pipe(system_adapter::info)
my_system.pipe(system_adapter::dbg)
my_system.pipe(system_adapter::warn)
my_system.pipe(system_adapter::error)
// After:
my_system.map(bevy_utils::info)
my_system.map(bevy_utils::dbg)
my_system.map(bevy_utils::warn)
my_system.map(bevy_utils::error)
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fix the `borders`, `ui` and `text_wrap_debug` examples.
## Solution
- Swap `TransparentUi` to use a stable sort
---
This is the smallest change to fix the examples but ideally this is
fixed by setting better sort keys for the UI elements such that we can
swap back to an unstable sort.
# Objective
- break up large build_schedule system to make it easier to read
- Clean up related error messages.
- I have a follow up PR that adds the schedule name to the error
messages, but wanted to break this up from that.
## Changelog
- refactor `build_schedule` to be easier to read
## Sample Error Messages
Dependency Cycle
```text
thread 'main' panicked at 'System dependencies contain cycle(s).
schedule has 1 before/after cycle(s):
cycle 1: system set 'A' must run before itself
system set 'A'
... which must run before system set 'B'
... which must run before system set 'A'
', crates\bevy_ecs\src\schedule\schedule.rs:228:13
```
```text
thread 'main' panicked at 'System dependencies contain cycle(s).
schedule has 1 before/after cycle(s):
cycle 1: system 'foo' must run before itself
system 'foo'
... which must run before system 'bar'
... which must run before system 'foo'
', crates\bevy_ecs\src\schedule\schedule.rs:228:13
```
Hierarchy Cycle
```text
thread 'main' panicked at 'System set hierarchy contains cycle(s).
schedule has 1 in_set cycle(s):
cycle 1: set 'A' contains itself
set 'A'
... which contains set 'B'
... which contains set 'A'
', crates\bevy_ecs\src\schedule\schedule.rs:230:13
```
System Type Set
```text
thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13
```
Hierarchy Redundancy
```text
thread 'main' panicked at 'System set hierarchy contains redundant edges.
hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists
', crates\bevy_ecs\src\schedule\schedule.rs:230:13
```
Systems have ordering but interset
```text
thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51
```
Cross Dependency
```text
thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13
```
Ambiguity
```text
thread 'main' panicked at 'Systems with conflicting access have indeterminate run order.
1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
-- res_mut and res_ref
conflict on: ["bevymark::ambiguity::X"]
', crates\bevy_ecs\src\schedule\schedule.rs:230:13
```
# Objective
Sometimes you want to create a plugin with a custom run condition. In a
function, you take the `Condition` trait and then make a
`BoxedCondition` from it to store it. And then you want to add that
condition to a system, but you can't, because there is only the `run_if`
function available which takes `impl Condition<M>` instead of
`BoxedCondition`. So you have to create a wrapper type for the
`BoxedCondition` and implement the `System` and `ReadOnlySystem` traits
for the wrapper (Like it's done in the picture below). It's very
inconvenient and boilerplate. But there is an easy solution for that:
make the `run_if_inner` system that takes a `BoxedCondition` public.
Also, it makes sense to make `in_set_inner` function public as well with
the same motivation.
![image](https://github.com/bevyengine/bevy/assets/61053971/a4455180-7e0c-4c2b-9372-cd8b4a9e682e)
A chunk of the source code of the `bevy-inspector-egui` crate.
## Solution
Make `run_if_inner` function public.
Rename `run_if_inner` to `run_if_dyn`.
Make `in_set_inner` function public.
Rename `in_set_inner` to `in_set_dyn`.
## Changelog
Changed visibility of `run_if_inner` from `pub(crate)` to `pub`.
Renamed `run_if_inner` to `run_if_dyn`.
Changed visibility of `in_set_inner` from `pub(crate)` to `pub`.
Renamed `in_set_inner` to `in_set_dyn`.
## Migration Guide
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
This is a continuation of this PR: #8062
# Objective
- Reorder render schedule sets to allow data preparation when phase item
order is known to support improved batching
- Part of the batching/instancing etc plan from here:
https://github.com/bevyengine/bevy/issues/89#issuecomment-1379249074
- The original idea came from @inodentry and proved to be a good one.
Thanks!
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the new
ordering
## Solution
- Move `Prepare` and `PrepareFlush` after `PhaseSortFlush`
- Add a `PrepareAssets` set that runs in parallel with other systems and
sets in the render schedule.
- Put prepare_assets systems in the `PrepareAssets` set
- If explicit dependencies are needed on Mesh or Material RenderAssets
then depend on the appropriate system.
- Add `ManageViews` and `ManageViewsFlush` sets between
`ExtractCommands` and Queue
- Move `queue_mesh*_bind_group` to the Prepare stage
- Rename them to `prepare_`
- Put systems that prepare resources (buffers, textures, etc.) into a
`PrepareResources` set inside `Prepare`
- Put the `prepare_..._bind_group` systems into a `PrepareBindGroup` set
after `PrepareResources`
- Move `prepare_lights` to the `ManageViews` set
- `prepare_lights` creates views and this must happen before `Queue`
- This system needs refactoring to stop handling all responsibilities
- Gather lights, sort, and create shadow map views. Store sorted light
entities in a resource
- Remove `BatchedPhaseItem`
- Replace `batch_range` with `batch_size` representing how many items to
skip after rendering the item or to skip the item entirely if
`batch_size` is 0.
- `queue_sprites` has been split into `queue_sprites` for queueing phase
items and `prepare_sprites` for batching after the `PhaseSort`
- `PhaseItem`s are still inserted in `queue_sprites`
- After sorting adjacent compatible sprite phase items are accumulated
into `SpriteBatch` components on the first entity of each batch,
containing a range of vertex indices. The associated `PhaseItem`'s
`batch_size` is updated appropriately.
- `SpriteBatch` items are then drawn skipping over the other items in
the batch based on the value in `batch_size`
- A very similar refactor was performed on `bevy_ui`
---
## Changelog
Changed:
- Reordered and reworked render app schedule sets. The main change is
that data is extracted, queued, sorted, and then prepared when the order
of data is known.
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the
reordering.
## Migration Guide
- Assets such as materials and meshes should now be created in
`PrepareAssets` e.g. `prepare_assets<Mesh>`
- Queueing entities to `RenderPhase`s continues to be done in `Queue`
e.g. `queue_sprites`
- Preparing resources (textures, buffers, etc.) should now be done in
`PrepareResources`, e.g. `prepare_prepass_textures`,
`prepare_mesh_uniforms`
- Prepare bind groups should now be done in `PrepareBindGroups` e.g.
`prepare_mesh_bind_group`
- Any batching or instancing can now be done in `Prepare` where the
order of the phase items is known e.g. `prepare_sprites`
## Next Steps
- Introduce some generic mechanism to ensure items that can be batched
are grouped in the phase item order, currently you could easily have
`[sprite at z 0, mesh at z 0, sprite at z 0]` preventing batching.
- Investigate improved orderings for building the MeshUniform buffer
- Implementing batching across the rest of bevy
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
# Objective
* `Local` and `SystemName` implement `Debug` manually, but they could
derive it.
* `QueryState` and `dyn System` have unconventional debug formatting.
# 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>
# Objective
Fixes#9200
Switches ()'s to []'s when talking about the optional `_mut` suffix in
the ECS Query Struct page to have more idiomatic docs.
## Solution
Replace `()` with `[]` in appropriate doc pages.
When building Bevy using Bazel, you don't need a 'Cargo.toml'... except
Bevy requires it currently. Hopefully this can help illuminate the
requirement.
# Objective
I recently started exploring Bazel and Buck2. Currently Bazel has some
great advantages over Cargo for me and I was pretty happy to find that
things generally work quite well!
Once I added a target to my test project that depended on bevy but
didn't use Cargo, I didn't create a Cargo.toml file for it and things
appeared to work, but as soon as I went to derive from Component the
build failed with the cryptic error:
```
ERROR: /Users/photex/workspaces/personal/mb-rogue/scratch/BUILD:24:12: Compiling Rust bin hello_bevy (0 files) failed: (Exit 1): process_wrapper failed: error executing command (from target //scratch:hello_bevy) bazel-out/darwin_arm64-opt-exec-2B5CBBC6/bin/external/rules_rust/util/process_wrapper/process_wrapper --arg-file ... (remaining 312 arguments skipped)
error: proc-macro derive panicked
--> scratch/hello_bevy.rs:5:10
|
5 | #[derive(Component)]
| ^^^^^^^^^
|
= help: message: called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }
error: proc-macro derive panicked
--> scratch/hello_bevy.rs:8:10
|
8 | #[derive(Component)]
| ^^^^^^^^^
|
= help: message: called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }
```
## Solution
After poking around I realized that the proc macros in Bevy all use
bevy_macro_utils::BevyManifest, which was attempting to load a Cargo
manifest that doesn't exist.
This PR doesn't address the Cargo requirement (I'd love to see if there
was a way to support more than Cargo transparently), but it *does*
replace some calls to unwrap with expect and hopefully the error
messages will be more helpful for other folks like me hoping to pat down
a new trail:
```
ERROR: /Users/photex/workspaces/personal/mb-rogue/scratch/BUILD:23:12: Compiling Rust bin hello_bevy (0 files) failed: (Exit 1): process_wrapper failed: error executing command (from target //scratch:hello_bevy) bazel-out/darwin_arm64-opt-exec-2B5CBBC6/bin/external/rules_rust/util/process_wrapper/process_wrapper --arg-file ... (remaining 312 arguments skipped)
error: proc-macro derive panicked
--> scratch/hello_bevy.rs:5:10
|
5 | #[derive(Component)]
| ^^^^^^^^^
|
= help: message: Unable to read cargo manifest: /private/var/tmp/_bazel_photex/135f23dc56826c24d6c3c9f6b688b2fe/execroot/__main__/scratch/Cargo.toml: Os { code: 2, kind: NotFound, message: "No such file or directory" }
error: proc-macro derive panicked
--> scratch/hello_bevy.rs:8:10
|
8 | #[derive(Component)]
| ^^^^^^^^^
|
= help: message: Unable to read cargo manifest: /private/var/tmp/_bazel_photex/135f23dc56826c24d6c3c9f6b688b2fe/execroot/__main__/scratch/Cargo.toml: Os { code: 2, kind: NotFound, message: "No such file or directory" }
```
Co-authored-by: Chip Collier <chip.collier@avid.com>
# Objective
Fixes#8894Fixes#7944
## Solution
The UI pipeline's `MultisampleState::count` is set to 1 whereas the
`MultisampleState::count` for the camera's ViewTarget is taken from the
`Msaa` resource, and corruption occurs when these two values are
different.
This PR solves the problem by setting `MultisampleState::count` for the
UI pipeline to the value from the Msaa resource too.
I don't know much about Bevy's rendering internals or graphics hardware,
so maybe there is a better solution than this. UI MSAA was probably
disabled for a good reason (performance?).
## Changelog
* Enabled multisampling for the UI pipeline.
# Objective
AssetPath shader imports check if the shader is added using the path
without quotes. this causes them to be re-added even if already present,
which can cause previous dependents to get unloaded leading to a
"missing import" error.
## Solution
fix the module name of AssetPath shaders used for checking if it's
already added to correctly use the quoted name.
# Objective
In
[`AssetLoader::load()`](https://docs.rs/bevy/0.11.0/bevy/asset/trait.AssetLoader.html#tymethod.load),
I have an
[`AssetPath`](https://docs.rs/bevy/0.11.0/bevy/asset/struct.AssetPath.html)
to a dependency asset.
I get a handle to this dependency asset using
[`LoadContext::get_handle()`](https://docs.rs/bevy/0.11.0/bevy/asset/struct.LoadContext.html#method.get_handle)
passing the `AssetPath`. But I also need to pass this `AssetPath` to
[`LoadedAsset::with_dependency()`](https://docs.rs/bevy/0.11.0/bevy/asset/struct.LoadedAsset.html#method.with_dependency)
later.
The current solution for this problem is either use `clone()`, but
`AssetPath` may contains owned data.
```rust
let dependency_path: AssetPath = _;
let dependency = load_context.get_handle(dependency_path.clone());
// ...
load_context.set_default_asset(LoadedAsset::new(my_asset).with_dependency(dependency_path));
```
Or to use `AssetPathId::from(&path)` which is a bit verbose.
```rust
let dependency_path: AssetPath = _;
let dependency = load_context.get_handle(AssetPathId::from(&dependency_path));
// ...
load_context.set_default_asset(LoadedAsset::new(my_asset).with_dependency(dependency_path));
```
Ideal solution (introduced by this PR) is to pass a reference to
`get_handle()`.
```rust
let dependency_path: AssetPath = _;
let dependency = load_context.get_handle(&dependency_path);
// ...
load_context.set_default_asset(LoadedAsset::new(my_asset).with_dependency(dependency_path));
```
## Solution
Implement `From<&AssetPath>` for `HandleId`
---
## Changelog
- Added: `HandleId` can be build from a reference to `AssetPath`.
# Objective
Continue #7867 now that we have URect #7984
- Return `URect` instead of `(UVec2, UVec2)` in
`Camera::physical_viewport_rect`
- Add `URect` and `IRect` to prelude
## Changelog
- Changed `Camera::physical_viewport_rect` return type from `(UVec2,
UVec2)` to `URect`
- `URect` and `IRect` were added to prelude
## Migration Guide
Before:
```rust
fn view_physical_camera_rect(camera_query: Query<&Camera>) {
let camera = camera_query.single();
let Some((min, max)) = camera.physical_viewport_rect() else { return };
dbg!(min, max);
}
```
After:
```rust
fn view_physical_camera_rect(camera_query: Query<&Camera>) {
let camera = camera_query.single();
let Some(URect { min, max }) = camera.physical_viewport_rect() else { return };
dbg!(min, max);
}
```
# Objective
Gizmos are intended to draw over everything but for some reason I set
the sort key to `0` during #8427 :v
I didn't catch this mistake because it still draws over sprites with a Z
translation of `0`.
## Solution
Set the sort key to `f32::INFINITY`.
# Objective
Some of the conversion methods on the new rect types introduced in #7984
have misleading names.
## Solution
Rename all methods returning an `IRect` to `as_irect` and all methods
returning a `URect` to `as_urect`.
## Migration Guide
Replace uses of the old method names with the new method names.
# Objective
In my application, I'm manually wrapping the built-in Bevy loaders with
a wrapper loader that stores some metadata before calling into the inner
Bevy loader. This worked for the glTF loader in Bevy 0.10, but in Bevy
0.11 it became impossible to do this because the glTF loader became
unconstructible outside Bevy due to the new private fields within it.
It's now in fact impossible to get a reference to a GltfLoader at all
from outside Bevy, because the only way to construct a GltfLoader is to
add the GltfPlugin to an App, and the GltfPlugin only hands out
references to its GltfLoader to the asset server, which provides no
public access to the loaders it manages.
## Solution
This commit fixes the problem by adding a public `new` method to allow
manual construction of a glTF loader.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
In both Text2d and Bevy UI text because of incorrect text size and
alignment calculations if a block of text has empty leading lines then
those lines are ignored. Also, depending on the font size when leading
empty lines are ignored the same number of lines of text can go missing
from the bottom of the text block.
## Example (from murtaugh on discord)
```rust
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
let text = "\nfirst line\nsecond line\nthird line\n";
commands.spawn(TextBundle {
text: Text::from_section(
text.to_string(),
TextStyle {
font_size: 60.0,
color: Color::YELLOW,
..Default::default()
},
),
style: Style {
position_type: PositionType::Absolute,
..Default::default()
},
background_color: BackgroundColor(Color::RED),
..Default::default()
});
}
```
![](https://cdn.discordapp.com/attachments/1128294384954257499/1128295142072254525/image.png)
## Solution
`TextPipeline::queue_text`,
`TextMeasureInfo::compute_size_from_section_texts` and
`GlyphBrush::process_glyphs` each have a nearly duplicate section of
code that calculates the minimum bounds around a list of text sections.
The first two functions don't apply any rounding, but `process_glyphs`
also floors all the values. It seems like this difference can cause
conflicts where the text gets incorrectly shaped.
Also when Bevy computes the text bounds it chooses the smallest possible
rect that fits all the glyphs, ignoring white space. The glyphs are then
realigned vertically so the first glyph is on the top line. Any empty
leading lines are missed.
This PR adds a function `compute_text_bounds` that replaces the
duplicate code, so the text bounds are rounded the same way by each
function. Also, since Bevy doesn't use `ab_glyph` to control vertical
alignment, the minimum y bound is just always set to 0 which ensures no
leading empty lines will be missed.
There is another problem in that trailing empty lines are also ignored,
but that's more difficult to deal with and much less important than the
other issues, so I'll leave it for another PR.
<img width="462" alt="fixed_text_align_bounds"
src="https://github.com/bevyengine/bevy/assets/27962798/85e32e2c-d68f-4677-8e87-38e27ade4487">
---
## Changelog
Added a new function `compute_text_bounds` to the `glyph_brush` module
that replaces the text size and bounds calculations in
`TextPipeline::queue_text`,
`TextMeasureInfo::compute_size_from_section_texts` and
`GlyphBrush::process_glyphs`. The text bounds are calculated identically
in each function and the minimum y bound is not derived from the glyphs
but is always set to 0.
# Objective
`ExtractedUiNodes` is cleared by the `extract_uinodes` function during
the extraction schedule. Because the Bevy UI renderer uses a painters
algorithm, this makes it impossible for users to create a custom
extraction function that adds items for a node to be drawn behind the
rectangle added by `extract_uniodes`.
## Solution
Drain `ExtractedUiNodes` in `prepare_ui_nodes` instead, after the
extraction schedule has finished.
CI-capable version of #9086
---------
Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: François <mockersf@gmail.com>
# Objective
`GlobalTransform` after insertion will be updated only on `Transform` or
hierarchy change.
Fixes#9075
## Solution
Update `GlobalTransform` after insertion too.
---
## Changelog
- `GlobalTransform` is now updated not only on `Transform` or hierarchy
change, but also on insertion.
# Objective
Fix typos throughout the project.
## Solution
[`typos`](https://github.com/crate-ci/typos) project was used for
scanning, but no automatic corrections were applied. I checked
everything by hand before fixing.
Most of the changes are documentation/comments corrections. Also, there
are few trivial changes to code (variable name, pub(crate) function name
and a few error/panic messages).
## Unsolved
`bevy_reflect_derive` has
[typo](1b51053f19/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs (L76))
in enum variant name that I didn't fix. Enum is `pub(crate)`, so there
shouldn't be any trouble if fixed. However, code is tightly coupled with
macro usage, so I decided to leave it for more experienced contributor
just in case.
I created this manually as Github didn't want to run CI for the
workflow-generated PR. I'm guessing we didn't hit this in previous
releases because we used bors.
Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
# Objective
fixes#8911, #7712
## Solution
Rounding was added to Taffy which fixed issue #7712.
The implementation uses the f32 `round` method which rounds ties
(fractional part is a half) away from zero. Issue #8911 occurs when a
node's min and max bounds on either axis are "ties" and zero is between
them. Then the bounds are rounded away from each other, and the node
grows by a pixel. This alone shouldn't cause the node to expand
continuously, but I think there is some interaction with the way Taffy
recomputes a layout from its cached data that I didn't identify.
This PR fixes#8911 by first disabling Taffy's internal rounding and
using an alternative rounding function that rounds ties up.
Then, instead of rounding the values of the internal layout tree as
Taffy's built-in rounding does, we leave those values unmodified and
only the values stored in the components are rounded. This requires
walking the tree for the UI node geometry update rather than iterating
through a query.
Because the component values are regenerated each update, that should
mean that UI updates are idempotent (ish) now and make the growing node
behaviour seen in issue #8911 impossible.
I expected a performance regression, but it's an improvement on main:
```
cargo run --profile stress-test --features trace_tracy --example many_buttons
```
<img width="461" alt="ui-rounding-fix-compare"
src="https://github.com/bevyengine/bevy/assets/27962798/914bfd50-e18a-4642-b262-fafa69005432">
I guess it makes sense to do the rounding together with the node size
and position updates.
---
## Changelog
`bevy_ui::layout`:
* Taffy's built-in rounding is disabled and rounding is now performed by
`ui_layout_system`.
* Instead of rounding the values of the internal layout tree as Taffy's
built-in rounding does, we leave those values unmodified and only the
values stored in the components are rounded. This requires walking the
tree for the UI node geometry update rather than iterating through a
query. Because the component values are regenerated each update, that
should mean that UI updates are idempotent now and make the growing node
behaviour seen in issue #8911 impossible.
* Added two helper functions `round_ties_up` and
`round_layout_coordinates`.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This pull request is mutually exclusive with #9066.
# Objective
Complete the initialization of the plugin in `ScheduleRunnerPlugin`.
## Solution
Wait for asynchronous tasks to complete, then `App::finish` and
`App::cleanup` in the runner function.
# Objective
Fixes#6689.
## Solution
Add `single-threaded` as an optional non-default feature to `bevy_ecs`
and `bevy_tasks` that:
- disable the `ParallelExecutor` as a default runner
- disables the multi-threaded `TaskPool`
- internally replace `QueryParIter::for_each` calls with
`Query::for_each`.
Removed the `Mutex` and `Arc` usage in the single-threaded task pool.
![image](https://user-images.githubusercontent.com/3137680/202833253-dd2d520f-75e6-4c7b-be2d-5ce1523cbd38.png)
## Future Work/TODO
Create type aliases for `Mutex`, `Arc` that change to single-threaaded
equivalents where possible.
---
## Changelog
Added: Optional default feature `multi-theaded` to that enables
multithreaded parallelism in the engine. Disabling it disables all
multithreading in exchange for higher single threaded performance. Does
nothing on WASM targets.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- accesskit_unix is not optional anymore
## Solution
- Enable `async-io` feature of `accesskit_winit` only when
`accesskit_unix` is enabled
# Objective
Improve the `bevy_audio` API to make it more user-friendly and
ECS-idiomatic. This PR is a first-pass at addressing some of the most
obvious (to me) problems. In the interest of keeping the scope small,
further improvements can be done in future PRs.
The current `bevy_audio` API is very clunky to work with, due to how it
(ab)uses bevy assets to represent audio sinks.
The user needs to write a lot of boilerplate (accessing
`Res<Assets<AudioSink>>`) and deal with a lot of cognitive overhead
(worry about strong vs. weak handles, etc.) in order to control audio
playback.
Audio playback is initiated via a centralized `Audio` resource, which
makes it difficult to keep track of many different sounds playing in a
typical game.
Further, everything carries a generic type parameter for the sound
source type, making it difficult to mix custom sound sources (such as
procedurally generated audio or unofficial formats) with regular audio
assets.
Let's fix these issues.
## Solution
Refactor `bevy_audio` to a more idiomatic ECS API. Remove the `Audio`
resource. Do everything via entities and components instead.
Audio playback data is now stored in components:
- `PlaybackSettings`, `SpatialSettings`, `Handle<AudioSource>` are now
components. The user inserts them to tell Bevy to play a sound and
configure the initial playback parameters.
- `AudioSink`, `SpatialAudioSink` are now components instead of special
magical "asset" types. They are inserted by Bevy when it actually begins
playing the sound, and can be queried for by the user in order to
control the sound during playback.
Bundles: `AudioBundle` and `SpatialAudioBundle` are available to make it
easy for users to play sounds. Spawn an entity with one of these bundles
(or insert them to a complex entity alongside other stuff) to play a
sound.
Each entity represents a sound to be played.
There is also a new "auto-despawn" feature (activated using
`PlaybackSettings`), which, if enabled, tells Bevy to despawn entities
when the sink playback finishes. This allows for "fire-and-forget" sound
playback. Users can simply
spawn entities whenever they want to play sounds and not have to worry
about leaking memory.
## Unsolved Questions
I think the current design is *fine*. I'd be happy for it to be merged.
It has some possibly-surprising usability pitfalls, but I think it is
still much better than the old `bevy_audio`. Here are some discussion
questions for things that we could further improve. I'm undecided on
these questions, which is why I didn't implement them. We should decide
which of these should be addressed in this PR, and what should be left
for future PRs. Or if they should be addressed at all.
### What happens when sounds start playing?
Currently, the audio sink components are inserted and the bundle
components are kept. Should Bevy remove the bundle components? Something
else?
The current design allows an entity to be reused for playing the same
sound with the same parameters repeatedly. This is a niche use case I'd
like to be supported, but if we have to give it up for a simpler design,
I'd be fine with that.
### What happens if users remove any of the components themselves?
As described above, currently, entities can be reused. Removing the
audio sink causes it to be "detached" (I kept the old `Drop` impl), so
the sound keeps playing. However, if the audio bundle components are not
removed, Bevy will detect this entity as a "queued" sound entity again
(has the bundle compoenents, without a sink component), just like before
playing the sound the first time, and start playing the sound again.
This behavior might be surprising? Should we do something different?
### Should mutations to `PlaybackSettings` be applied to the audio sink?
We currently do not do that. `PlaybackSettings` is just for the initial
settings when the sound starts playing. This is clearly documented.
Do we want to keep this behavior, or do we want to allow users to use
`PlaybackSettings` instead of `AudioSink`/`SpatialAudioSink` to control
sounds during playback too?
I think I prefer for them to be kept separate. It is not a bad mental
model once you understand it, and it is documented.
### Should `AudioSink` and `SpatialAudioSink` be unified into a single
component type?
They provide a similar API (via the `AudioSinkPlayback` trait) and it
might be annoying for users to have to deal with both of them. The
unification could be done using an enum that is matched on internally by
the methods. Spatial audio has extra features, so this might make it
harder to access. I think we shouldn't.
### Automatic synchronization of spatial sound properties from
Transforms?
Should Bevy automatically apply changes to Transforms to spatial audio
entities? How do we distinguish between listener and emitter? Which one
does the transform represent? Where should the other one come from?
Alternatively, leave this problem for now, and address it in a future
PR. Or do nothing, and let users deal with it, as shown in the
`spatial_audio_2d` and `spatial_audio_3d` examples.
---
## Changelog
Added:
- `AudioBundle`/`SpatialAudioBundle`, add them to entities to play
sounds.
Removed:
- The `Audio` resource.
- `AudioOutput` is no longer `pub`.
Changed:
- `AudioSink`, `SpatialAudioSink` are now components instead of assets.
## Migration Guide
// TODO: write a more detailed migration guide, after the "unsolved
questions" are answered and this PR is finalized.
Before:
```rust
/// Need to store handles somewhere
#[derive(Resource)]
struct MyMusic {
sink: Handle<AudioSink>,
}
fn play_music(
asset_server: Res<AssetServer>,
audio: Res<Audio>,
audio_sinks: Res<Assets<AudioSink>>,
mut commands: Commands,
) {
let weak_handle = audio.play_with_settings(
asset_server.load("music.ogg"),
PlaybackSettings::LOOP.with_volume(0.5),
);
// upgrade to strong handle and store it
commands.insert_resource(MyMusic {
sink: audio_sinks.get_handle(weak_handle),
});
}
fn toggle_pause_music(
audio_sinks: Res<Assets<AudioSink>>,
mymusic: Option<Res<MyMusic>>,
) {
if let Some(mymusic) = &mymusic {
if let Some(sink) = audio_sinks.get(&mymusic.sink) {
sink.toggle();
}
}
}
```
Now:
```rust
/// Marker component for our music entity
#[derive(Component)]
struct MyMusic;
fn play_music(
mut commands: Commands,
asset_server: Res<AssetServer>,
) {
commands.spawn((
AudioBundle::from_audio_source(asset_server.load("music.ogg"))
.with_settings(PlaybackSettings::LOOP.with_volume(0.5)),
MyMusic,
));
}
fn toggle_pause_music(
// `AudioSink` will be inserted by Bevy when the audio starts playing
query_music: Query<&AudioSink, With<MyMusic>>,
) {
if let Ok(sink) = query.get_single() {
sink.toggle();
}
}
```
# Objective
`accesskit` and `accesskit_winit` need to be upgraded.
## Solution
Upgrade `accesskit` and `accesskit_winit`.
---
## Changelog
### Changed
* Upgrade accesskit to v0.11.
* Upgrade accesskit_winit to v0.14.
# Objective
Currently, `DynamicScene`s extract all components listed in the given
(or the world's) type registry. This acts as a quasi-filter of sorts.
However, it can be troublesome to use effectively and lacks decent
control.
For example, say you need to serialize only the following component over
the network:
```rust
#[derive(Reflect, Component, Default)]
#[reflect(Component)]
struct NPC {
name: Option<String>
}
```
To do this, you'd need to:
1. Create a new `AppTypeRegistry`
2. Register `NPC`
3. Register `Option<String>`
If we skip Step 3, then the entire scene might fail to serialize as
`Option<String>` requires registration.
Not only is this annoying and easy to forget, but it can leave users
with an impossible task: serializing a third-party type that contains
private types.
Generally, the third-party crate will register their private types
within a plugin so the user doesn't need to do it themselves. However,
this means we are now unable to serialize _just_ that type— we're forced
to allow everything!
## Solution
Add the `SceneFilter` enum for filtering components to extract.
This filter can be used to optionally allow or deny entire sets of
components/resources. With the `DynamicSceneBuilder`, users have more
control over how their `DynamicScene`s are built.
To only serialize a subset of components, use the `allow` method:
```rust
let scene = builder
.allow::<ComponentA>()
.allow::<ComponentB>()
.extract_entity(entity)
.build();
```
To serialize everything _but_ a subset of components, use the `deny`
method:
```rust
let scene = builder
.deny::<ComponentA>()
.deny::<ComponentB>()
.extract_entity(entity)
.build();
```
Or create a custom filter:
```rust
let components = HashSet::from([type_id]);
let filter = SceneFilter::Allowlist(components);
// let filter = SceneFilter::Denylist(components);
let scene = builder
.with_filter(Some(filter))
.extract_entity(entity)
.build();
```
Similar operations exist for resources:
<details>
<summary>View Resource Methods</summary>
To only serialize a subset of resources, use the `allow_resource`
method:
```rust
let scene = builder
.allow_resource::<ResourceA>()
.extract_resources()
.build();
```
To serialize everything _but_ a subset of resources, use the
`deny_resource` method:
```rust
let scene = builder
.deny_resource::<ResourceA>()
.extract_resources()
.build();
```
Or create a custom filter:
```rust
let resources = HashSet::from([type_id]);
let filter = SceneFilter::Allowlist(resources);
// let filter = SceneFilter::Denylist(resources);
let scene = builder
.with_resource_filter(Some(filter))
.extract_resources()
.build();
```
</details>
### Open Questions
- [x] ~~`allow` and `deny` are mutually exclusive. Currently, they
overwrite each other. Should this instead be a panic?~~ Took @soqb's
suggestion and made it so that the opposing method simply removes that
type from the list.
- [x] ~~`DynamicSceneBuilder` extracts entity data as soon as
`extract_entity`/`extract_entities` is called. Should this behavior
instead be moved to the `build` method to prevent ordering mixups (e.g.
`.allow::<Foo>().extract_entity(entity)` vs
`.extract_entity(entity).allow::<Foo>()`)? The tradeoff would be
iterating over the given entities twice: once at extraction and again at
build.~~ Based on the feedback from @Testare it sounds like it might be
better to just keep the current functionality (if anything we can open a
separate PR that adds deferred methods for extraction, so the
choice/performance hit is up to the user).
- [ ] An alternative might be to remove the filter from
`DynamicSceneBuilder` and have it as a separate parameter to the
extraction methods (either in the existing ones or as added
`extract_entity_with_filter`-type methods). Is this preferable?
- [x] ~~Should we include constructors that include common types to
allow/deny? For example, a `SceneFilter::standard_allowlist` that
includes things like `Parent` and `Children`?~~ Consensus suggests we
should. I may split this out into a followup PR, though.
- [x] ~~Should we add the ability to remove types from the filter
regardless of whether an allowlist or denylist (e.g.
`filter.remove::<Foo>()`)?~~ See the first list item
- [x] ~~Should `SceneFilter` be an enum? Would it make more sense as a
struct that contains an `is_denylist` boolean?~~ With the added
`SceneFilter::None` state (replacing the need to wrap in an `Option` or
rely on an empty `Denylist`), it seems an enum is better suited now
- [x] ~~Bikeshed: Do we like the naming convention? Should we instead
use `include`/`exclude` terminology?~~ Sounds like we're sticking with
`allow`/`deny`!
- [x] ~~Does this feature need a new example? Do we simply include it in
the existing one (maybe even as a comment?)? Should this be done in a
followup PR instead?~~ Example will be added in a followup PR
### Followup Tasks
- [ ] Add a dedicated `SceneFilter` example
- [ ] Possibly add default types to the filter (e.g. deny things like
`ComputedVisibility`, allow `Parent`, etc)
---
## Changelog
- Added the `SceneFilter` enum for filtering components and resources
when building a `DynamicScene`
- Added methods:
- `DynamicSceneBuilder::with_filter`
- `DynamicSceneBuilder::allow`
- `DynamicSceneBuilder::deny`
- `DynamicSceneBuilder::allow_all`
- `DynamicSceneBuilder::deny_all`
- `DynamicSceneBuilder::with_resource_filter`
- `DynamicSceneBuilder::allow_resource`
- `DynamicSceneBuilder::deny_resource`
- `DynamicSceneBuilder::allow_all_resources`
- `DynamicSceneBuilder::deny_all_resources`
- Removed methods:
- `DynamicSceneBuilder::from_world_with_type_registry`
- `DynamicScene::from_scene` and `DynamicScene::from_world` no longer
require an `AppTypeRegistry` reference
## Migration Guide
- `DynamicScene::from_scene` and `DynamicScene::from_world` no longer
require an `AppTypeRegistry` reference:
```rust
// OLD
let registry = world.resource::<AppTypeRegistry>();
let dynamic_scene = DynamicScene::from_world(&world, registry);
// let dynamic_scene = DynamicScene::from_scene(&scene, registry);
// NEW
let dynamic_scene = DynamicScene::from_world(&world);
// let dynamic_scene = DynamicScene::from_scene(&scene);
```
- Removed `DynamicSceneBuilder::from_world_with_type_registry`. Now the
registry is automatically taken from the given world:
```rust
// OLD
let registry = world.resource::<AppTypeRegistry>();
let builder = DynamicSceneBuilder::from_world_with_type_registry(&world,
registry);
// NEW
let builder = DynamicSceneBuilder::from_world(&world);
```
# Objective
After the UI layout is computed when the coordinates are converted back
from physical coordinates to logical coordinates the `UiScale` is
ignored. This results in a confusing situation where we have two
different systems of logical coordinates.
Example:
```rust
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, update)
.run();
}
fn setup(mut commands: Commands, mut ui_scale: ResMut<UiScale>) {
ui_scale.scale = 4.;
commands.spawn(Camera2dBundle::default());
commands.spawn(NodeBundle {
style: Style {
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
width: Val::Percent(100.),
..Default::default()
},
..Default::default()
})
.with_children(|builder| {
builder.spawn(NodeBundle {
style: Style {
width: Val::Px(100.),
height: Val::Px(100.),
..Default::default()
},
background_color: Color::MAROON.into(),
..Default::default()
}).with_children(|builder| {
builder.spawn(TextBundle::from_section("", TextStyle::default());
});
});
}
fn update(
mut text_query: Query<(&mut Text, &Parent)>,
node_query: Query<Ref<Node>>,
) {
for (mut text, parent) in text_query.iter_mut() {
let node = node_query.get(parent.get()).unwrap();
if node.is_changed() {
text.sections[0].value = format!("size: {}", node.size());
}
}
}
```
result:
![Bevy App 30_05_2023
16_54_32](https://github.com/bevyengine/bevy/assets/27962798/a5ecbf31-0a12-4669-87df-b0c32f058732)
We asked for a 100x100 UI node but the Node's size is multiplied by the
value of `UiScale` to give a logical size of 400x400.
## Solution
Divide the output physical coordinates by `UiScale` in
`ui_layout_system` and multiply the logical viewport size by `UiScale`
when creating the projection matrix for the UI's `ExtractedView` in
`extract_default_ui_camera_view`.
---
## Changelog
* The UI layout's physical coordinates are divided by both the window
scale factor and `UiScale` when converting them back to logical
coordinates. The logical size of Ui nodes now matches the values given
to their size constraints.
* Multiply the logical viewport size by `UiScale` before creating the
projection matrix for the UI's `ExtractedView` in
`extract_default_ui_camera_view`.
* In `ui_focus_system` the cursor position returned from `Window` is
divided by `UiScale`.
* Added a scale factor parameter to `Node::physical_size` and
`Node::physical_rect`.
* The example `viewport_debug` now uses a `UiScale` of 2. to ensure that
viewport coordinates are working correctly with a non-unit `UiScale`.
## Migration Guide
Physical UI coordinates are now divided by both the `UiScale` and the
window's scale factor to compute the logical sizes and positions of UI
nodes.
This ensures that UI Node size and position values, held by the `Node`
and `GlobalTransform` components, conform to the same logical coordinate
system as the style constraints from which they are derived,
irrespective of the current `scale_factor` and `UiScale`.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Fixes#8630.
## Solution
Since a camera's view and projection matrices are modified during
`PostUpdate` in `camera_system` and `propagate_transforms`, it is fine
to move `update_previous_view_projections` from `Update` to `PreUpdate`.
Doing so adds consistence with `update_mesh_previous_global_transforms`
and allows systems in `Update` to use `PreviousViewProjection` correctly
without explicit ordering.
# Objective
I'm creating an iOS game and had to find a way to persist game state
when the application is terminated. This required listening to the
[`applicationWillTerminate()`
method](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623111-applicationwillterminate),
but I cannot do so myself anymore since `winit` already set up a
delegate to listen for it, and there can be only one delegate.
So I had to move up the stack and try to respond to one of the events
from `winit` instead. It appears `winit` fires two events that could
serve my purpose: `WindowEvent::Destroyed` and `Event::LoopDestroyed`.
It seemed to me the former might be slightly more generally useful, and
I also found a past discussion that suggested it would be appropriate
for Bevy to have a `WindowDestroyed` event:
https://github.com/bevyengine/bevy/pull/5589#discussion_r942811021
## Solution
- I've added the `WindowDestroyed` event, which fires when `winit` fires
`WindowEvent::Destroyed`.
---
## Changelog
### Added
- Introduced a new `WindowDestroyed` event type. It is used to indicate
a window has been destroyed by the windowing system.
# Objective
bevy_render currently has a dependency on a random older version of
once_cell which is not used anywhere.
## Solution
Remove the dependency
## Changelog
N/A
## Migration Guide
N/A
# Objective
- Remove need to call `.get()` on two ticks to compare them for
equality.
## Solution
- Derive `Eq` and `PartialEq`.
---
## Changelog
> `Tick` now implements `Eq` and `PartialEq`
# Objective
- Fix#8984
### Solution
- Address compilation errors
I admit: I did sneak it an unrelated mini-refactor. of the
`measurment.rs` module. it seemed to me that directly importing `taffy`
types helped reduce a lot of boilerplate, so I did it.
# Objective
The bounding box colors are from bevy_gizmo are randomized between app
runs. This can get confusing for users.
## Solution
Use a fixed seed with `RandomState::with_seeds` rather than initializing
a `AHash`.
The random number was chose so that the first few colors are clearly
distinct.
According to the `RandomState::hash_one` documentation, it's also
faster.
![bevy_bounding_box_colors_2023-07-03](https://github.com/bevyengine/bevy/assets/26321040/676f0389-d00e-4edd-bd77-1fbf73a3d9fa)
---
## Changelog
* bevy_gizmo: Keep a consistent color for AABBs of identical entities
between runs
# Objective
Since 10f5c92, shadows were broken for models with morph target.
When #5703 was merged, the morph target code in `render/mesh.wgsl` was
correctly updated to use the new import syntax. However, similar code
exists in `prepass/prepass.wgsl`, but it was never update. (the reason
code is duplicated is that the `Vertex` struct is different for both
files).
## Solution
Update the code, so that shadows render correctly with morph targets.
# Objective
Fixes https://github.com/bevyengine/bevy/issues/8925
## Solution
~~Clamp the bad values.~~
Normalize the prepass normals when we get them in the `prepass_normal()`
function.
## More Info
The issue is that NdotV is sometimes very slightly greater than 1 (maybe
FP rounding issues?), which caused `F_Schlick()` to return NANs in
`pow(1.0 - NdotV, 5.0)` (call stack looked like`pbr()` ->
`directional_light()` -> `Fd_Burley()` -> `F_Schlick()`)
# Objective
Since 10f5c92, parallax mapping was broken.
When #5703 was merged, the change from `in.uv` to `uv` in the pbr shader
was reverted. So the shader would use the wrong coordinate to sample the
various textures.
## Solution
We revert to using the correct uv.
# Objective
Followup bugfix for #5703. Without this we get the following error when
CAS (Contrast Adaptive Sharpening) is enabled:
```
2023-06-29T01:31:23.829331Z ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
error: unknown type: 'FullscreenVertexOutput'
┌─ crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/robust_contrast_adaptive_sharpening.wgsl:63:17
│
63 │ fn fragment(in: FullscreenVertexOutput) -> @location(0) vec4<f32> {
│ ^^^^^^^^^^^^^^^^^^^^^^ unknown type
│
= unknown type: 'FullscreenVertexOutput'
```
@robtfm I wouldn't expect this to fail. I was under the impression the
`#import bevy_core_pipeline::fullscreen_vertex_shader` would pull
"everything" from that file into this one?
# Objective
- This fixes a crash when loading shaders, when running an Adreno GPU
and using WebGL mode.
- Fixes#8506
- Fixes#8047
## Solution
- The shader pbr_functions.wgsl, will fail in apply_fog function, trying
to access values that are null on Adreno chipsets using WebGL, these
devices are commonly found in android handheld devices.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
# Objective
**This implementation is based on
https://github.com/bevyengine/rfcs/pull/59.**
---
Resolves#4597
Full details and motivation can be found in the RFC, but here's a brief
summary.
`FromReflect` is a very powerful and important trait within the
reflection API. It allows Dynamic types (e.g., `DynamicList`, etc.) to
be formed into Real ones (e.g., `Vec<i32>`, etc.).
This mainly comes into play concerning deserialization, where the
reflection deserializers both return a `Box<dyn Reflect>` that almost
always contain one of these Dynamic representations of a Real type. To
convert this to our Real type, we need to use `FromReflect`.
It also sneaks up in other ways. For example, it's a required bound for
`T` in `Vec<T>` so that `Vec<T>` as a whole can be made `FromReflect`.
It's also required by all fields of an enum as it's used as part of the
`Reflect::apply` implementation.
So in other words, much like `GetTypeRegistration` and `Typed`, it is
very much a core reflection trait.
The problem is that it is not currently treated like a core trait and is
not automatically derived alongside `Reflect`. This makes using it a bit
cumbersome and easy to forget.
## Solution
Automatically derive `FromReflect` when deriving `Reflect`.
Users can then choose to opt-out if needed using the
`#[reflect(from_reflect = false)]` attribute.
```rust
#[derive(Reflect)]
struct Foo;
#[derive(Reflect)]
#[reflect(from_reflect = false)]
struct Bar;
fn test<T: FromReflect>(value: T) {}
test(Foo); // <-- OK
test(Bar); // <-- Panic! Bar does not implement trait `FromReflect`
```
#### `ReflectFromReflect`
This PR also automatically adds the `ReflectFromReflect` (introduced in
#6245) registration to the derived `GetTypeRegistration` impl— if the
type hasn't opted out of `FromReflect` of course.
<details>
<summary><h4>Improved Deserialization</h4></summary>
> **Warning**
> This section includes changes that have since been descoped from this
PR. They will likely be implemented again in a followup PR. I am mainly
leaving these details in for archival purposes, as well as for reference
when implementing this logic again.
And since we can do all the above, we might as well improve
deserialization. We can now choose to deserialize into a Dynamic type or
automatically convert it using `FromReflect` under the hood.
`[Un]TypedReflectDeserializer::new` will now perform the conversion and
return the `Box`'d Real type.
`[Un]TypedReflectDeserializer::new_dynamic` will work like what we have
now and simply return the `Box`'d Dynamic type.
```rust
// Returns the Real type
let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
let mut deserializer = ron:🇩🇪:Deserializer::from_str(input)?;
let output: SomeStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?;
// Returns the Dynamic type
let reflect_deserializer = UntypedReflectDeserializer::new_dynamic(®istry);
let mut deserializer = ron:🇩🇪:Deserializer::from_str(input)?;
let output: DynamicStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?;
```
</details>
---
## Changelog
* `FromReflect` is now automatically derived within the `Reflect` derive
macro
* This includes auto-registering `ReflectFromReflect` in the derived
`GetTypeRegistration` impl
* ~~Renamed `TypedReflectDeserializer::new` and
`UntypedReflectDeserializer::new` to
`TypedReflectDeserializer::new_dynamic` and
`UntypedReflectDeserializer::new_dynamic`, respectively~~ **Descoped**
* ~~Changed `TypedReflectDeserializer::new` and
`UntypedReflectDeserializer::new` to automatically convert the
deserialized output using `FromReflect`~~ **Descoped**
## Migration Guide
* `FromReflect` is now automatically derived within the `Reflect` derive
macro. Items with both derives will need to remove the `FromReflect`
one.
```rust
// OLD
#[derive(Reflect, FromReflect)]
struct Foo;
// NEW
#[derive(Reflect)]
struct Foo;
```
If using a manual implementation of `FromReflect` and the `Reflect`
derive, users will need to opt-out of the automatic implementation.
```rust
// OLD
#[derive(Reflect)]
struct Foo;
impl FromReflect for Foo {/* ... */}
// NEW
#[derive(Reflect)]
#[reflect(from_reflect = false)]
struct Foo;
impl FromReflect for Foo {/* ... */}
```
<details>
<summary><h4>Removed Migrations</h4></summary>
> **Warning**
> This section includes changes that have since been descoped from this
PR. They will likely be implemented again in a followup PR. I am mainly
leaving these details in for archival purposes, as well as for reference
when implementing this logic again.
* The reflect deserializers now perform a `FromReflect` conversion
internally. The expected output of `TypedReflectDeserializer::new` and
`UntypedReflectDeserializer::new` is no longer a Dynamic (e.g.,
`DynamicList`), but its Real counterpart (e.g., `Vec<i32>`).
```rust
let reflect_deserializer =
UntypedReflectDeserializer::new_dynamic(®istry);
let mut deserializer = ron:🇩🇪:Deserializer::from_str(input)?;
// OLD
let output: DynamicStruct = reflect_deserializer.deserialize(&mut
deserializer)?.take()?;
// NEW
let output: SomeStruct = reflect_deserializer.deserialize(&mut
deserializer)?.take()?;
```
Alternatively, if this behavior isn't desired, use the
`TypedReflectDeserializer::new_dynamic` and
`UntypedReflectDeserializer::new_dynamic` methods instead:
```rust
// OLD
let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
// NEW
let reflect_deserializer =
UntypedReflectDeserializer::new_dynamic(®istry);
```
</details>
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Title. This is necessary in order to update
[`bevy-trait-query`](https://crates.io/crates/bevy-trait-query) to Bevy
0.11.
---
## Changelog
Added the unsafe function `UnsafeWorldCell::storages`, which provides
unchecked access to the internal data stores of a `World`.
Added `GizmoConfig::render_layers`, which will ensure Gizmos are only
rendered on cameras that can see those `RenderLayers`.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Relax unnecessary type restrictions on `App.runner` function.
## Solution
Changed the type of `App.runner` from `Fn(App)` to `FnOnce(App)`.
# Objective
#5703 caused the normal prepass to fail as the prepass uses
`pbr_functions::apply_normal_mapping`, which uses
`mesh_view_bindings::view` to determine mip bias, which conflicts with
`prepass_bindings::view`.
## Solution
pass the mip bias to the `apply_normal_mapping` function explicitly.
# Objective
Currently `App::edit_schedule` takes in `impl FnMut(&mut Schedule)`, but
it calls the function only once. It is probably the intention has been
to have it take `FnOnce` instead.
## Solution
- Relax the parameter to take `FnOnce` instead of `FnMut`
# Objective
- There was a deadlock discovered in the implementation of
`bevy_reflect::utility::GenericTypeCell`, when called on a recursive
type, e.g. `Vec<Vec<VariableCurve>>`
## Solution
- Drop the lock before calling the initialisation function, and then
pick it up again afterwards.
## Additional Context
- [Discussed on
Discord](https://discord.com/channels/691052431525675048/1002362493634629796/1122706835284185108)
# Objective
operate on naga IR directly to improve handling of shader modules.
- give codespan reporting into imported modules
- allow glsl to be used from wgsl and vice-versa
the ultimate objective is to make it possible to
- provide user hooks for core shader functions (to modify light
behaviour within the standard pbr pipeline, for example)
- make automatic binding slot allocation possible
but ... since this is already big, adds some value and (i think) is at
feature parity with the existing code, i wanted to push this now.
## Solution
i made a crate called naga_oil (https://github.com/robtfm/naga_oil -
unpublished for now, could be part of bevy) which manages modules by
- building each module independantly to naga IR
- creating "header" files for each supported language, which are used to
build dependent modules/shaders
- make final shaders by combining the shader IR with the IR for imported
modules
then integrated this into bevy, replacing some of the existing shader
processing stuff. also reworked examples to reflect this.
## Migration Guide
shaders that don't use `#import` directives should work without changes.
the most notable user-facing difference is that imported
functions/variables/etc need to be qualified at point of use, and
there's no "leakage" of visible stuff into your shader scope from the
imports of your imports, so if you used things imported by your imports,
you now need to import them directly and qualify them.
the current strategy of including/'spreading' `mesh_vertex_output`
directly into a struct doesn't work any more, so these need to be
modified as per the examples (e.g. color_material.wgsl, or many others).
mesh data is assumed to be in bindgroup 2 by default, if mesh data is
bound into bindgroup 1 instead then the shader def `MESH_BINDGROUP_1`
needs to be added to the pipeline shader_defs.
# Objective
Currently when `UntypedReflectDeserializerVisitor` deserializes a
`Box<dyn Reflect>` it only considers the first entry of the map,
silently ignoring any additional entries. For example the following RON
data:
```json
{
"f32": 1.23,
"u32": 1,
}
```
is successfully deserialized as a `f32`, completly ignoring the `"u32":
1` part.
## Solution
`UntypedReflectDeserializerVisitor` was changed to check if any other
key could be deserialized, and in that case returns an error.
---
## Changelog
`UntypedReflectDeserializer` now errors on malformed inputs instead of
silently disgarding additional data.
## Migration Guide
If you were deserializing `Box<dyn Reflect>` values with multiple
entries (i.e. entries other than `"type": { /* fields */ }`) you should
remove them or deserialization will fail.
# Objective
`World::entity`, `World::entity_mut` and `Commands::entity` should be
marked with `track_caller` to display where (in user code) the call with
the invalid `Entity` was made. `Commands::entity` already has the
attibute, but it does nothing due to the call to `unwrap_or_else`.
## Solution
- Apply the `track_caller` attribute to the `World::entity_mut` and
`World::entity`.
- Remove the call to `unwrap_or_else` which makes the `track_caller`
attribute useless (because `unwrap_or_else` is not `track_caller`
itself). The avoid eager evaluation of the panicking branch it is never
inlined.
---------
Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
# Objective
`color_from_entity` uses the poor man's hash to get a fixed random color
for an entity.
While the poor man's hash is succinct, it has a tendency to clump. As a
result, bevy_gizmos has a tendency to re-use very similar colors for
different entities.
This is bad, we would want non-similar colors that take the whole range
of possible hues. This way, each bevy_gizmos aabb gizmo is easy to
identify.
## Solution
AHash is a nice and fast hash that just so happen to be available to
use, so we use it.
# Objective
In Bevy 10.1 and before, the only way to enable text wrapping was to set
a local `Val::Px` width constraint on the text node itself.
`Val::Percent` constraints and constraints on the text node's ancestors
did nothing.
#7779 fixed those problems. But perversely displaying unwrapped text is
really difficult now, and requires users to nest each `TextBundle` in a
`NodeBundle` and apply `min_width` and `max_width` constraints. Some
constructions may even need more than one layer of nesting. I've seen
several people already who have really struggled with this when porting
their projects to main in advance of 0.11.
## Solution
Add a `NoWrap` variant to the `BreakLineOn` enum.
If `NoWrap` is set, ignore any constraints on the width for the text and
call `TextPipeline::queue_text` with a width bound of `f32::INFINITY`.
---
## Changelog
* Added a `NoWrap` variant to the `BreakLineOn` enum.
* If `NoWrap` is set, any constraints on the width for the text are
ignored and `TextPipeline::queue_text` is called with a width bound of
`f32::INFINITY`.
* Changed the `size` field of `FixedMeasure` to `pub`. This shouldn't
have been private, it was always intended to have `pub` visibility.
* Added a `with_no_wrap` method to `TextBundle`.
## Migration Guide
`bevy_text::text::BreakLineOn` has a new variant `NoWrap` that disables
text wrapping for the `Text`.
Text wrapping can also be disabled using the `with_no_wrap` method of
`TextBundle`.
# Objective
- Fix this error to be able to run UI examples in WebGPU
```
1 error(s) generated while compiling the shader:
:31:18 error: integral user-defined vertex outputs must have a flat interpolation attribute
@location(3) mode: u32,
^^^^
:36:1 note: while analyzing entry point 'vertex'
fn vertex(
^^
```
It was introduce in #8793
## Solution
- Add `@interpolate(flat)` to the `mode` field
# Objective
In Bevy main, the unconstrained size of an `ImageBundle` or
`AtlasImageBundle` UI node is based solely on the size of its texture
and doesn't change with window scale factor or `UiScale`.
## Solution
* The size field of each `ImageMeasure` should be multiplied by the
current combined scale factor.
* Each `ImageMeasure` should be updated when the combined scale factor
is changed.
## Example:
```rust
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.insert_resource(UiScale { scale: 1.5 })
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
commands.spawn(NodeBundle {
style: Style {
// The size of the "bevy_logo_dark.png" texture is 520x130 pixels
width: Val::Px(520.),
height: Val::Px(130.),
..Default::default()
},
background_color: Color::RED.into(),
..Default::default()
});
commands
.spawn(ImageBundle {
style: Style {
position_type: PositionType::Absolute,
..Default::default()
},
image: UiImage::new(asset_server.load("bevy_logo_dark.png")),
..Default::default()
});
}
```
The red node is given a size with the same dimensions as the texture. So
we would expect the texture to fill the node exactly.
* Result with Bevy main branch bb59509d44:
<img width="400" alt="image-size-broke"
src="https://github.com/bevyengine/bevy/assets/27962798/19fd927d-ecc5-49a7-be05-c121a8df163f">
* Result with this PR (and Bevy 0.10.1):
<img width="400" alt="image-size-fixed"
src="https://github.com/bevyengine/bevy/assets/27962798/40b47820-5f2d-408f-88ef-9e2beb9c92a0">
---
## Changelog
`bevy_ui::widget::image`
* Update all `ImageMeasure`s on changes to the window scale factor or
`UiScale`.
* Multiply `ImageMeasure::size` by the window scale factor and
`UiScale`.
## Migration Guide
# Objective
- Change despawn descendants to return self (#8883).
## Solution
- Change function signature `despawn_descendants` under trait
`DespawnRecursiveExt`.
- Add single extra test `spawn_children_after_despawn_descendants` (May
be unnecessary)
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Partially address #5504. Fix#4278. Provide "whole entity" access in
queries. This can be useful when you don't know at compile time what
you're accessing (i.e. reflection via `ReflectComponent`).
## Solution
Implement `WorldQuery` for `EntityRef`.
- This provides read-only access to the entire entity, and supports
anything that `EntityRef` can normally do.
- It matches all archetypes and tables and will densely iterate when
possible.
- It marks all of the ArchetypeComponentIds of a matched archetype as
read.
- Adding it to a query will cause it to panic if used in conjunction
with any other mutable access.
- Expanded the docs on Query to advertise this feature.
- Added tests to ensure the panics were working as intended.
- Added `EntityRef` to the ECS prelude.
To make this safe, `EntityRef::world` was removed as it gave potential
`UnsafeCell`-like access to other parts of the `World` including aliased
mutable access to the components it would otherwise read safely.
## Performance
Not great beyond the additional parallelization opportunity over
exclusive systems. The `EntityRef` is fetched from `Entities` like any
other call to `World::entity`, which can be very random access heavy.
This could be simplified if `ArchetypeRow` is available in
`WorldQuery::fetch`'s arguments, but that's likely not something we
should optimize for.
## Future work
An equivalent API where it gives mutable access to all components on a
entity can be done with a scoped version of `EntityMut` where it does
not provide `&mut World` access nor allow for structural changes to the
entity is feasible as well. This could be done as a safe alternative to
exclusive system when structural mutation isn't required or the target
set of entities is scoped.
---
## Changelog
Added: `Access::has_any_write`
Added: `EntityRef` now implements `WorldQuery`. Allows read-only access
to the entire entity, incompatible with any other mutable access, can be
mixed with `With`/`Without` filters for more targeted use.
Added: `EntityRef` to `bevy::ecs::prelude`.
Removed: `EntityRef::world`
## Migration Guide
TODO
---------
Co-authored-by: Carter Weinberg <weinbergcarter@gmail.com>
Co-authored-by: Jakob Hellermann <jakob.hellermann@protonmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Closes#7323
- Reduce texture blurriness for TAA
## Solution
- Add a `MipBias` component and view uniform.
- Switch material `textureSample()` calls to `textureSampleBias()`.
- Add a `-1.0` bias to TAA.
---
## Changelog
- Added `MipBias` camera component, mostly for internal use.
---------
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Add morph targets to `bevy_pbr` (closes#5756) & load them from glTF
- Supersedes #3722
- Fixes#6814
[Morph targets][1] (also known as shape interpolation, shape keys, or
blend shapes) allow animating individual vertices with fine grained
controls. This is typically used for facial expressions. By specifying
multiple poses as vertex offset, and providing a set of weight of each
pose, it is possible to define surprisingly realistic transitions
between poses. Blending between multiple poses also allow composition.
Morph targets are part of the [gltf standard][2] and are a feature of
Unity and Unreal, and babylone.js, it is only natural to implement them
in bevy.
## Solution
This implementation of morph targets uses a 3d texture where each pixel
is a component of an animated attribute. Each layer is a different
target. We use a 2d texture for each target, because the number of
attribute×components×animated vertices is expected to always exceed the
maximum pixel row size limit of webGL2. It copies fairly closely the way
skinning is implemented on the CPU side, while on the GPU side, the
shader morph target implementation is a relatively trivial detail.
We add an optional `morph_texture` to the `Mesh` struct. The
`morph_texture` is built through a method that accepts an iterator over
attribute buffers.
The `MorphWeights` component, user-accessible, controls the blend of
poses used by mesh instances (so that multiple copy of the same mesh may
have different weights), all the weights are uploaded to a uniform
buffer of 256 `f32`. We limit to 16 poses per mesh, and a total of 256
poses.
More literature:
* Old babylone.js implementation (vertex attribute-based):
https://www.eternalcoding.com/dev-log-1-morph-targets/
* Babylone.js implementation (similar to ours):
https://www.youtube.com/watch?v=LBPRmGgU0PE
* GPU gems 3:
https://developer.nvidia.com/gpugems/gpugems3/part-i-geometry/chapter-3-directx-10-blend-shapes-breaking-limits
* Development discord thread
https://discord.com/channels/691052431525675048/1083325980615114772https://user-images.githubusercontent.com/26321040/231181046-3bca2ab2-d4d9-472e-8098-639f1871ce2e.mp4https://github.com/bevyengine/bevy/assets/26321040/d2a0c544-0ef8-45cf-9f99-8c3792f5a258
## Acknowledgements
* Thanks to `storytold` for sponsoring the feature
* Thanks to `superdump` and `james7132` for guidance and help figuring
out stuff
## Future work
- Handling of less and more attributes (eg: animated uv, animated
arbitrary attributes)
- Dynamic pose allocation (so that zero-weighted poses aren't uploaded
to GPU for example, enables much more total poses)
- Better animation API, see #8357
----
## Changelog
- Add morph targets to bevy meshes
- Support up to 64 poses per mesh of individually up to 116508 vertices,
animation currently strictly limited to the position, normal and tangent
attributes.
- Load a morph target using `Mesh::set_morph_targets`
- Add `VisitMorphTargets` and `VisitMorphAttributes` traits to
`bevy_render`, this allows defining morph targets (a fairly complex and
nested data structure) through iterators (ie: single copy instead of
passing around buffers), see documentation of those traits for details
- Add `MorphWeights` component exported by `bevy_render`
- `MorphWeights` control mesh's morph target weights, blending between
various poses defined as morph targets.
- `MorphWeights` are directly inherited by direct children (single level
of hierarchy) of an entity. This allows controlling several mesh
primitives through a unique entity _as per GLTF spec_.
- Add `MorphTargetNames` component, naming each indices of loaded morph
targets.
- Load morph targets weights and buffers in `bevy_gltf`
- handle morph targets animations in `bevy_animation` (previously, it
was a `warn!` log)
- Add the `MorphStressTest.gltf` asset for morph targets testing, taken
from the glTF samples repo, CC0.
- Add morph target manipulation to `scene_viewer`
- Separate the animation code in `scene_viewer` from the rest of the
code, reducing `#[cfg(feature)]` noise
- Add the `morph_targets.rs` example to show off how to manipulate morph
targets, loading `MorpStressTest.gltf`
## Migration Guide
- (very specialized, unlikely to be touched by 3rd parties)
- `MeshPipeline` now has a single `mesh_layouts` field rather than
separate `mesh_layout` and `skinned_mesh_layout` fields. You should
handle all possible mesh bind group layouts in your implementation
- You should also handle properly the new `MORPH_TARGETS` shader def and
mesh pipeline key. A new function is exposed to make this easier:
`setup_moprh_and_skinning_defs`
- The `MeshBindGroup` is now `MeshBindGroups`, cached bind groups are
now accessed through the `get` method.
[1]: https://en.wikipedia.org/wiki/Morph_target_animation
[2]:
https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#morph-targets
---------
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Fix#8908.
## Solution
Assign the vertex buffers twice with a single item offset instead of
setting the array_stride lower than the vertex layout's size for
linestrips.
# Objective
Improve the documentation relating to windows, and update the parts that
have not been updated since version 0.8.
Version 0.9 introduced `Window` as a component, before that
`WindowDescriptor` (which would become `Window` later) was used to store
information about how a window will be created. Since version 0.9, from
my understanding, this information will also be synchronised with the
current state of the window, and can be used to modify this state.
However, some of the documentation has not been updated to reflect that,
here is an example:
https://docs.rs/bevy/0.8.0/bevy/window/enum.WindowMode.html /
https://docs.rs/bevy/latest/bevy/window/enum.WindowMode.html (notice
that the verb "Creates" is still there).
This PR aims at improving the documentation relating to windows.
## Solution
- Change "will" for "should" when relevant, "should" implies that the
information should in both direction (from the window state to the
`Window` component and vice-versa) and can be used to get and set, will
implies it is only used to set a state.
- Remove references to "creation" or be more clear about it.
- Reference back the `Window` component for most of its sub-structs.
- Clarify what needs to be clarified
- A lot of other minor changes, including fixing the link to W3schools
in `bevy_winit`
## Warning
Please note that my knowledge about how winit and bevy_winit work is
limited and some of the informations I added in the doc may be
inaccurate. A person who knows better how it works should review some of
my claims, in particular:
- How fullscreen works:
https://github.com/bevyengine/bevy/pull/8858#discussion_r1232413155
- How WindowResolution / sizes work:
https://github.com/bevyengine/bevy/pull/8858#discussion_r1233010719
- What happens when `WindowPosition` is set to `Centered` or
`Automatic`. From my understanding of the code, it should always be set
back to `At`, but is it really the case? For example [when creating the
window](https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/winit_windows.rs#L74),
or when [a `WindowEvent::Moved` is
triggered](https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/lib.rs#L602)
or when [Centered/Automatic by the code after the window is
created](https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/system.rs#L243),
am I missing some cases and do the codes I linked do that in all of
them?
- Are there any field in the `Window` component that can't be used to
modify the state of the window, only at creation?
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jerome Humbert <djeedai@gmail.com>
# Objective
- Fix the AsBindGroup texture attribute visibility flag parsing
- This appears to have been caused by a syn crate update which then the
visibility code got updated
- Also I noticed that by default the vertex and fragment flags were on,
so visibility(compute) would actually make the texture visible to
vertex, fragment and compute shaders, I fixed this too
## Solution
- Update flag parsing to use MetaList.parse_nested_meta function, which
loads the flags into a Vec then loop through those flags
- Change initial visibility flags to use VisibilityFlags::default()
rather than VisibilityFlags::vertex_fragment()
# Objective
`prepare_uinodes` creates a new `UiBatch` whenever the texture changes,
when most often it's just queuing untextured quads. Instead of switching
textures, we can reduce the number of batches generated significantly by
adding a condition to the fragment shader so that it only multiplies by
the `textureSample` value when drawing a textured quad.
# Solution
Add a `mode` field to `UiVertex`.
In `prepare_uinodes` set `mode` to 0 if the quad is textured or 1 if
untextured.
Add a condition to the fragment shader that only multiplies by the
`color` value from `textureSample` if `mode` is set to 1.
---
## Changelog
* Added a `mode` field to `UiVertex`, and added an extra `u32` vertex
attribute to the shader and vertex buffer layout.
* In `prepare_uinodes` mode is set to 0 for the vertices of textured
quads, and 1 if untextured.
* Added a condition to the fragment shader in `ui.wgsl` that only
multiplies by the `color` value from `textureSample` if the mode is
equal to 0.
# Objective
- Fixes#8645
## Solution
Cascaded shadow maps use a technique commonly called shadow pancaking to
enhance shadow map resolution by restricting the orthographic projection
used in creating the shadow maps to the frustum slice for the cascade.
The implication of this restriction is that shadow casters can be closer
than the near plane of the projection volume.
Prior to this PR, we address clamp the depth of the prepass vertex
output to ensure that these shadow casters do not get clipped, resulting
in shadow loss. However, a flaw / bug of the prior approach is that the
depth that gets written to the shadow map isn't quite correct - the
depth was previously derived by interpolated the clamped clip position,
resulting in depths that are further than they should be. This creates
artifacts that are particularly noticeable when a very 'long' object
intersects the near plane close to perpendicularly.
The fix in this PR is to propagate the unclamped depth to the prepass
fragment shader and use that depth value directly.
A complementary solution would be to use
[DEPTH_CLIP_CONTROL](https://docs.rs/wgpu/latest/wgpu/struct.Features.html#associatedconstant.DEPTH_CLIP_CONTROL)
to request `unclipped_depth`. However due to the relatively low support
of the feature on Vulkan (I believe it's ~38%), I went with this
solution for now to get the broadest fix out first.
---
## Changelog
- Fixed: Shadows from directional lights were sometimes incorrectly
omitted when the shadow caster was partially out of view.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Better consistency with `add_systems`.
- Deprecating `add_plugin` in favor of a more powerful `add_plugins`.
- Allow passing `Plugin` to `add_plugins`.
- Allow passing tuples to `add_plugins`.
## Solution
- `App::add_plugins` now takes an `impl Plugins` parameter.
- `App::add_plugin` is deprecated.
- `Plugins` is a new sealed trait that is only implemented for `Plugin`,
`PluginGroup` and tuples over `Plugins`.
- All examples, benchmarks and tests are changed to use `add_plugins`,
using tuples where appropriate.
---
## Changelog
### Changed
- `App::add_plugins` now accepts all types that implement `Plugins`,
which is implemented for:
- Types that implement `Plugin`.
- Types that implement `PluginGroup`.
- Tuples (up to 16 elements) over types that implement `Plugins`.
- Deprecated `App::add_plugin` in favor of `App::add_plugins`.
## Migration Guide
- Replace `app.add_plugin(plugin)` calls with `app.add_plugins(plugin)`.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Fix broken normals when the NormalPrepass is enabled
## Solution
- Don't use the normal prepass for the world_normal
- Only loadthe normal prepass
- when msaa is disabled
- for opaque or alpha mask meshes and only for use it for N not
world_normal
# Objective
- Use `AppTypeRegistry` on API defined in `bevy_ecs`
(https://github.com/bevyengine/bevy/pull/8895#discussion_r1234748418)
A lot of the API on `Reflect` depends on a registry. When it comes to
the ECS. We should use `AppTypeRegistry` in the general case.
This is however impossible in `bevy_ecs`, since `AppTypeRegistry` is
defined in `bevy_app`.
## Solution
- Move `AppTypeRegistry` resource definition from `bevy_app` to
`bevy_ecs`
- Still add the resource in the `App` plugin, since bevy_ecs itself
doesn't know of plugins
Note that `bevy_ecs` is a dependency of `bevy_app`, so nothing
revolutionary happens.
## Alternative
- Define the API as a trait in `bevy_app` over `bevy_ecs`. (though this
prevents us from using bevy_ecs internals)
- Do not rely on `AppTypeRegistry` for the API in question, requring
users to extract themselves the resource and pass it to the API methods.
---
## Changelog
- Moved `AppTypeRegistry` resource definition from `bevy_app` to
`bevy_ecs`
## Migration Guide
- If you were **not** using a `prelude::*` to import `AppTypeRegistry`,
you should update your imports:
```diff
- use bevy::app::AppTypeRegistry;
+ use bevy::ecs::reflect::AppTypeRegistry
```
# Objective
The "bevy_text" feature attributes for the `PrimaryWindow`, `Window` and
`TextureAtlas` imports in `bevy_ui::render` are used by non-text systems
(`extract_uinode_borders` and `extract_atlas_uinodes`) and need to be
removed.
For those who wish to be able to `#[reflect]` stuff using the `Uuid`
type
I'm very unfamiliar with the codebase, so please tell me if I'm missing
something
# Objective
- Providing a "noob-friendly" example since not many people are
proficient in 3D modeling / rendering concepts.
## Solution
- Adding more information to the example, with an explanation.
~~~~
_Thanks to Nocta on discord for helping out when I didn't understand the
subject well._
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- `bevy_log` writes logs to `stdout` (with ANSI formatting), which gets
in the way with program output and complicates parsing.
- Closes#8869
## Solution
- Change `bevy_log` to write to `stderr` instead of `stdout`
---
## Changelog
Changed:
- Logs write to `stderr` rather than `stdout` on desktop targets
## Migration Guide
- Capture logs from `stderr` instead of from `stdout`
- Use `2> output.log` on the command line to save `stderr` to a file
# Objective
Add a get_unclamped method to
[Axis](https://docs.rs/bevy/0.10.1/bevy/input/struct.Axis.html) to allow
it to be used in cases where being able to get a precise relative
movement is important. For example, camera zoom with the mouse wheel.
This would make it possible for libraries like leafwing input manager to
leverage `Axis` for mouse motion and mouse wheel axis mapping. I tried
to use it my PR here
https://github.com/Leafwing-Studios/leafwing-input-manager/pull/346 but
will likely have to revert that and read the mouse wheel events for now
which is what prompted this PR.
## Solution
Instead of clamping the axis value when it is set, it now stores the raw
value and clamps it in the `get` method. This allows a simple
get_unclamped method that just returns the raw value.
## Changelog
- Added a get_unclamped method to Axis that can return values outside of
-1.0 to 1.0
# Objective
Fixes#6920
## Solution
From the issue discussion:
> From looking at the `AsBindGroup` derive macro implementation, the
fallback image's `TextureView` is used when the binding's
`Option<Handle<Image>>` is `None`. Because this relies on already having
a view that matches the desired binding dimensions, I think the solution
will require creating a separate `GpuImage` for each possible
`TextureViewDimension`.
---
## Changelog
Users can now rely on `FallbackImage` to work with a texture binding of
any dimension.
# Objective
- Document android code that is currently causing clippy warnings due to
not being documented
## Solution
- Document the two previously undocumented items
# Objective
`WorldQuery::Fetch` is a type used to optimize the implementation of
queries. These types are hidden and not intended to be outside of the
engine, so there is no need to provide type aliases to make it easier to
refer to them. If a user absolutely needs to refer to one of these
types, they can always just refer to the associated type directly.
## Solution
Deprecate these type aliases.
---
## Changelog
- Deprecated the type aliases `QueryFetch` and `ROQueryFetch`.
## Migration Guide
The type aliases `bevy_ecs::query::QueryFetch` and `ROQueryFetch` have
been deprecated. If you need to refer to a `WorldQuery` struct's fetch
type, refer to the associated type defined on `WorldQuery` directly:
```rust
// Before:
type MyFetch<'w> = QueryFetch<'w, MyQuery>;
type MyFetchReadOnly<'w> = ROQueryFetch<'w, MyQuery>;
// After:
type MyFetch<'w> = <MyQuery as WorldQuery>::Fetch;
type MyFetchReadOnly<'w> = <<MyQuery as WorldQuery>::ReadOnly as WorldQuery>::Fetch;
```
# Objective
This adds support for using texture atlas sprites in UI. From
discussions today in the ui-dev discord it seems this is a much wanted
feature.
This was previously attempted in #5070 by @ManevilleF however that was
blocked #5103. This work can be easily modified to support #5103 changes
after that merges.
## Solution
I created a new UI bundle that reuses the existing texture atlas
infrastructure. I create a new atlas image component to prevent it from
being drawn by the existing non-UI systems and to remove unused
parameters.
In extract I added new system to calculate the required values for the
texture atlas image, this extracts into the same resource as the
existing UI Image and Text components.
This should have minimal performance impact because if texture atlas is
not present then the exact same code path is followed. Also there should
be no unintended behavior changes because without the new components the
existing systems write the extract same resulting data.
I also added an example showing the sprite working and a system to
advance the animation on space bar presses.
Naming is hard and I would accept any feedback on the bundle name!
---
## Changelog
> Added TextureAtlasImageBundle
---------
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
# Objective
Discovered that PointLight did not implement FromReflect. Adding
FromReflect where Reflect is used. I overreached and applied this rule
everywhere there was a Reflect without a FromReflect, except from where
the compiler wouldn't allow me.
Based from question: https://github.com/bevyengine/bevy/discussions/8774
## Solution
- Adding FromReflect where Reflect was already derived
## Notes
First PR I do in this ecosystem, so not sure if this is the usual
approach, that is, to touch many files at once.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
`ParsedPath` does not need to be mut to access a field of a `Reflect`.
Be that access mutable or not. Yet `element_mut` requires a mutable
borrow on `self`.
## Solution
- Make `element_mut` take a `&self` over a `&mut self`.
#8887 fixes this, but this is a major limitation in the API and I'd
rather see it merged before 0.11.
---
## Changelog
- `ParsedPath::element_mut` and `ParsedPath::reflect_element_mut` now
accept a non-mutable `ParsedPath` (only the accessed `Reflect` needs to
be mutable)
# Objective
- Implementing reflection for Cow<'static, [T]>
- Hopefully fixes#7429
## Solution
- Implementing Reflect, Typed, GetTypeRegistration, and FromReflect for
Cow<'static, [T]>
---
## Notes
I have not used bevy_reflection much yet, so I may not fully understand
all the use cases. This is also my first attempt at contributing, so I
would appreciate any feedback or recommendations for changes. I tried to
add cases for using Cow<'static, str> and Cow<'static, [u8]> to some of
the bevy_reflect tests, but I can't guarantee those tests are
comprehensive enough.
---------
Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Repetitively fetching ReflectResource and ReflectComponent from the
TypeRegistry is costly.
We want to access the underlying `fn`s. to do so, we expose the
`ReflectResourceFns` and `ReflectComponentFns` stored in ReflectResource
and ReflectComponent.
---
## Changelog
- Add the `fn_pointers` methods to `ReflectResource` and
`ReflectComponent` returning the underlying `ReflectResourceFns` and
`ReflectComponentFns`
# Objective
Make the UI code more concise.
## Solution
Add two utility methods to make manipulating `UiRect` from code more
concise:
- `UiRect::px()` create a new `UiRect` like the `new()` function, but
with values in logical pixels directly.
- `UiRect::percent()` is similar, with values as percentages.
This saves a lot of typing and makes UI code more compact while
retaining readability.
---
## Changelog
### Added
Added two new constructors `UiRect::px()` and `UiRect::percent()` to
create a new `UiRect` from values directly specified in logical pixels
and percentages, respectively. The argument order is the same as
`UiRect::new()`, but avoids having to repeat `Val::Px` and
`Val::Percent`, respectively.
# Objective
- Fixes#7811
## Solution
- I added `Has<T>` (and `HasFetch<T>` ) and implemented `WorldQuery`,
`ReadonlyWorldQuery`, and `ArchetypeFilter` it
- I also added documentation with an example and a unit test
I believe I've done everything right but this is my first contribution
and I'm not an ECS expert so someone who is should probably check my
implementation. I based it on what `Or<With<T>,>`, would do. The only
difference is that `Has` does not update component access - adding `Has`
to a query should never affect whether or not it is disjoint with
another query *I think*.
---
## Changelog
## Added
- Added `Has<T>` WorldQuery to find out whether or not an entity has a
particular component.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
# Objective
We can currently set `camera.target` to either an `Image` or `Window`.
For OpenXR & WebXR we need to be able to render to a `TextureView`.
This partially addresses #115 as with the addition we can create
internal and external xr crates.
## Solution
A `TextureView` item is added to the `RenderTarget` enum. It holds an id
which is looked up by a `ManualTextureViews` resource, much like how
`Assets<Image>` works.
I believe this approach was first used by @kcking in their [xr
fork](eb39afd51b/crates/bevy_render/src/camera/camera.rs (L322)).
The only change is that a `u32` is used to index the textures as
`FromReflect` does not support `uuid` and I don't know how to implement
that.
---
## Changelog
### Added
Render: Added `RenderTarget::TextureView` as a `camera.target` option,
enabling rendering directly to a `TextureView`.
## Migration Guide
References to the `RenderTarget` enum will need to handle the additional
field, ie in `match` statements.
---
## Comments
- The [wgpu
work](c039a74884)
done by @expenses allows us to create framebuffer texture views from
`wgpu v0.15, bevy 0.10`.
- I got the WebXR techniques from the [xr
fork](https://github.com/dekuraan/xr-bevy) by @dekuraan.
- I have tested this with a wip [external webxr
crate](018e22bb06/crates/bevy_webxr/src/bevy_utils/xr_render.rs (L50))
on an Oculus Quest 2.
![Screenshot 2023-03-11
230651](https://user-images.githubusercontent.com/25616826/224483696-c176c06f-a806-4abe-a494-b2e096ac96b7.png)
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: Paul Hansen <mail@paul.rs>
# Objective
- Cleanup the `reflect.rs` file in `bevy_ecs`, it's very large and can
get difficult to navigate
## Solution
- Split the file into 3 modules, re-export the types in the
`reflect/mod.rs` to keep a perfectly identical API.
- Add **internal** architecture doc explaining how `ReflectComponent`
works. Note that this doc is internal only, since `component.rs` is not
exposed publicly.
### Tips to reviewers
To review this change properly, you need to compare it to the previous
version of `reflect.rs`. The diff from this PR does not help at all!
What you will need to do is compare `reflect.rs` individually with each
newly created file.
Here is how I did it:
- Adding my fork as remote `git remote add nicopap
https://github.com/nicopap/bevy.git`
- Checkout out the branch `git checkout nicopap/split_ecs_reflect`
- Checkout the old `reflect.rs` by running `git checkout HEAD~1 --
crates/bevy_ecs/src/reflect.rs`
- Compare the old with the new with `git diff --no-index
crates/bevy_ecs/src/reflect.rs crates/bevy_ecs/src/reflect/component.rs`
You could also concatenate everything into a single file and compare
against it:
- `cat
crates/bevy_ecs/src/reflect/{component,resource,map_entities,mod}.rs >
new_reflect.rs`
- `git diff --no-index crates/bevy_ecs/src/reflect.rs new_reflect.rs`
# Objective
Fix https://github.com/bevyengine/bevy/issues/1018 (Textures on the
`Plane` shape appear flipped).
This bug have been around for a very long time apparently, I tested it
was still there (see test code bellow) and sure enough, this image:
![test](https://github.com/bevyengine/bevy/assets/134181069/4cda7cf8-57d9-4677-91f5-02240d1e79b1)
... is flipped vertically when used as a texture on a plane (in main,
0.10.1 and 0.9):
![image](https://github.com/bevyengine/bevy/assets/134181069/0db4f52a-51af-4041-9c45-7bfe1f08b0cc)
I'm pretty confused because this bug is so easy to fix, it has been
around for so long, it is easy to encounter, and PRs touching this code
still didn't fix it: https://github.com/bevyengine/bevy/pull/7546 To the
point where I'm wondering if it's actually intended. If it is, please
explain why and this PR can be changed to "mention that in the doc".
## Solution
Fix the UV mapping on the Plane shape
Here is how it looks after the PR
![image](https://github.com/bevyengine/bevy/assets/134181069/e07ce641-3de8-4da3-a4f3-95a6054c86d7)
## Test code
```rust
use bevy::{
prelude::*,
};
fn main () {
App::new()
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.run();
}
fn setup(
mut commands: Commands,
assets: ResMut<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0., 3., 0.).looking_at(Vec3::ZERO, Vec3::NEG_Z),
..default()
});
let mesh = meshes.add(Mesh::from(shape::Plane::default()));
let texture_image = assets.load("test.png");
let material = materials.add(StandardMaterial {
base_color_texture: Some(texture_image),
..default()
});
commands.spawn(PbrBundle {
mesh,
material,
..default()
});
}
```
## Changelog
Fix textures on `Plane` shapes being flipped vertically.
## Migration Guide
Flip the textures you use on `Plane` shapes.
# Objective
Resolves#7558.
Systems that are known to never modify the world implement the trait
`ReadOnlySystem`. This is a perfect place to add a safe API for running
a system with a shared reference to a World.
---
## Changelog
- Added the trait method `ReadOnlySystem::run_readonly`, which allows a
system to be run using `&World`.
# Objective
- The function `QueryParIter::for_each_unchecked` is a footgun: the only
ways to use it soundly can be done in safe code using `for_each` or
`for_each_mut`. See [this discussion on
discord](https://discord.com/channels/691052431525675048/749335865876021248/1118642977275924583).
## Solution
- Make `for_each_unchecked` private.
---
## Changelog
- Removed `QueryParIter::for_each_unchecked`. All use-cases of this
method were either unsound or doable in safe code using `for_each` or
`for_each_mut`.
## Migration Guide
The method `QueryParIter::for_each_unchecked` has been removed -- use
`for_each` or `for_each_mut` instead. If your use case can not be
achieved using either of these, then your code was likely unsound.
If you have a use-case for `for_each_unchecked` that you believe is
sound, please [open an
issue](https://github.com/bevyengine/bevy/issues/new/choose).
# Objective
`ComponentIdFor` is a type that gives you access to a component's
`ComponentId` in a system. It is currently awkward to use, since it must
be wrapped in a `Local<>` to be used.
## Solution
Make `ComponentIdFor` a proper SystemParam.
---
## Changelog
- Refactored the type `ComponentIdFor` in order to simplify how it is
used.
## Migration Guide
The type `ComponentIdFor<T>` now implements `SystemParam` instead of
`FromWorld` -- this means it should be used as the parameter for a
system directly instead of being used in a `Local`.
```rust
// Before:
fn my_system(
component_id: Local<ComponentIdFor<MyComponent>>,
) {
let component_id = **component_id;
}
// After:
fn my_system(
component_id: ComponentIdFor<MyComponent>,
) {
let component_id = component_id.get();
}
```