# Objective
Avoid needing to compile `taplo-cli` every time we use it in CI.
## Solution
Use [cargo-binstall](https://github.com/cargo-bins/cargo-binstall) to
install `taplo-cli`.
cargo-binstall is different from `cargo install`, in that it will first
attempt download a precompiled `taplo-cli` binary, in an attempt to
avoid compilation. However, failing that (for any reason), it will fall
back to installing the binary through `cargo install`.
While installing `taplo-cli` from source is relatively fast (around
50-60s), this still provides a small speed boost to the job, by not
needing to spend time compiling `taplo-cli` from source at all.
## Note on how this affects workflows
This PR does have one side-effect: Should `taplo-cli` need to be
compiled from source at all, it is no longer guaranteed to use the
latest `stable` version of `rustc`. This may be considered problematic,
as `taplo-cli` doesn't appear to have a MSRV policy.
However, its MSRV (as of writing this PR) is `1.74` - a nearly 1.5 year
old version. This seems to imply that, if `taplo-cli`'s MSRV is ever
updated, it won't be to the absolute latest stable version of Rust until
said version is a few months old.
Combine that with [the Github Actions runner images being frequently
(and automatically) updated to use the latest Rust
tooling](https://github.com/actions/runner-images/pull/11957), and I
don't foresee `taplo-cli`'s MSRV being an issue in 99% of circumstances.
Still, there is the possibility of it being a problem in those 1% of
circumstances - if this is a concern, please let me know and I'll try to
fix it.
## Testing
This change was tested on my local fork. The specific job run can be
found
[here](https://github.com/LikeLakers2/bevy/actions/runs/14350945588/job/40229485624).
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
Contributes to #18741 and #18453.
## Solution
Deprecate `SimpleExecutor`. If users run into migration issues, we can
backtrack. Otherwise, we follow this up with #18741
We can't easily deprecate the module too because of
[this](https://github.com/rust-lang/rust/issues/47238).
## Testing
CI
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Cyrill Schenkel <cyrill.schenkel@gmail.com>
# Objective
- bevy removed `Observe` type parameters in #15151 ,it enables merging
`Observer` and `ObserverState ` into a single component. with this
consolidation ,we can improve efficiency while reducing boilerplate.
## Solution
- remove `ObserverState `and merge it into `Observer`
## Testing
40%~60% performance win due to removal of redundant look up.

This also improves ergonomics when using dynamic observer
```rust
// previously
world.spawn(ObserverState {
// SAFETY: we registered `event_a` above and it matches the type of EventA
descriptor: unsafe { ObserverDescriptor::default().with_events(vec![event_a]) },
runner: |mut world, _trigger, _ptr, _propagate| {
world.resource_mut::<Order>().observed("event_a");
},
..Default::default()
});
// now
let observe = unsafe {
Observer::with_dynamic_runner(|mut world, _trigger, _ptr, _propagate| {
world.resource_mut::<Order>().observed("event_a");
})
.with_event(event_a)
};
world.spawn(observe);
```
# Objective
Simplify code in the `SingleThreadedExecutor` by removing a special case
for exclusive systems.
The `SingleThreadedExecutor` runs systems without immediately applying
deferred buffers. That required calling `run_unsafe()` instead of
`run()`, but that would `panic` for exclusive systems, so the code also
needed a special case for those. Following #18076 and #18406, we have a
`run_without_applying_deferred` method that has the exact behavior we
want and works on exclusive systems.
## Solution
Replace the code in `SingleThreadedExecutor` that runs systems with a
single call to `run_without_applying_deferred()`. Also add this as a
wrapper in the `__rust_begin_short_backtrace` module to preserve the
special behavior for backtraces.
## Objective
Reduce the time spent on ECS benchmarks without significantly
compromising coverage.
## Background
A `cargo bench -p benches --bench ecs` takes about 45 minutes. I'm
guessing this bench is mainly used to check for regressions after ECS
changes, and requiring 2x45 minute tests means that most people will
skip benchmarking entirely.
I noticed that some benches are repeated with sizes from long linear
progressions (10, 20, ..., 100). This might be nice for detailed
profiling, but seems too much for a overall regression check.
## Solution
The PR follows the principles of "three or four different sizes is fine"
and "powers of ten where it fits". The number of benches is reduced from
394 to 238 (-40%), and time from 46.2 minutes to 32.8 (-30%).
While some coverage is lost, I think it's reasonable for anyone doing
detailed profiling of a particular feature to temporarily add more
benches.
There's a couple of changes to avoid leading zeroes. I felt that `0010,
0100, 1000` is harder to read than `10, 100, 1000`.
## Is That Enough?
32 minutes is still too much. Possible future options:
- Reduce measurement and warmup times. I suspect the current times
(mostly 4-5 seconds total) are too conservative, and 1 second would be
fine for spotting significant regressions.
- Split the bench into quick and detailed variants.
## Testing
```
cargo bench -p benches --bench ecs
```
# Objective
Colors currently do not implement `StableInterpolate`, which makes them
ineligible for functions like `smooth_nudge` and make some generic APIs
awkward.
## Solution
Implemented `StableInterpolate` for linear color types that should be
uncontroversial. Non-linear types like `Hsl` are not implemented in this
PR.
## Testing
Added a test that checks implementations are correct.
# Objective
- Minor cleanup.
- This seems to have been introduced in #8336. There is no discussion
about it I can see, there's no comment explaining why this is here and
not in `ScreenshotPlugin`. This seems to have just been misplaced.
## Solution
- Move this to the ScreenshotPlugin!
## Testing
- The screenshot example still works at least on desktop.
# Objective
It has long been a todo item in the ecs to create a `BundleRemover`
alongside the inserter, spawner, etc.
This is an uncontroversial first step of #18514.
## Solution
Move existing code from complex helper functions to one generalized
`BundleRemover`.
## Testing
Existing tests.
# Objective
Let `FilteredEntityRef` and `FilteredEntityMut` receive access when
nested inside tuples or `#[derive(QueryData)]` types. Make sure to
exclude any access that would conflict with other subqueries!
Fixes#14349
## Solution
Replace `WorldQuery::set_access(state, access)` with a new method,
`QueryData::provide_extra_access(state, access, available_access)`, that
passes both the total available access and the currently used access.
This is called after `WorldQuery::update_component_access()`, so any
access used by ordinary subqueries will be known. `FilteredEntityRef`
and `FilteredEntityMut` can use the combination to determine how much
access they can safely take, while tuples can safely pass those
parameters directly to their subqueries.
This requires a new `Access::remove_conflicting_access()` method that
can be used to remove any access that would conflict with existing
access. Implementing this method was easier by first factoring some
common set manipulation code out of `Access::extend`. I can extract that
refactoring to a separate PR if desired.
Have `FilteredEntity(Ref|Mut)` store `Access` instead of
`FilteredAccess` because they do not need to keep track of the filter.
This was necessary in an early draft but no longer is. I left it in
because it's small and I'm touching that code anyway, but I can extract
it to a separate PR if desired.
# Objective
Fixes#17803
## Solution
- Add an `Allows<T>` `QueryFilter` that adds archetypal access for `T`
- Fix access merging to include archetypal from both sides
## Testing
- Added a case to the unit test for the application of
`DefaultQueryFilters`
# Objective
Based on and closes#18054, this PR builds on #18035 and #18147 to
remove:
- `Commands::insert_or_spawn_batch`
- `Entities::alloc_at_without_replacement`
- `Entities::alloc_at`
- `entity::AllocAtWithoutReplacement`
- `World::insert_or_spawn_batch`
- `World::insert_or_spawn_batch_with_caller`
## Testing
Just removing unused, deprecated code, so no new tests. Note that as of
writing, #18035 is still under testing and review.
## Future Work
Per
[this](https://github.com/bevyengine/bevy/issues/18054#issuecomment-2689088899)
comment on #18054, there may be additional performance improvements
possible to the entity allocator now that `alloc_at` no longer is
supported. At a glance, I don't see anything obvious to improve, but it
may be worth further investigation in the future.
---------
Co-authored-by: JaySpruce <jsprucebruce@gmail.com>
The LogPlugin now allows overriding the default
`tracing_subscriber::fmt::Layer` through a new `fmt_layer` option. This
enables customization of the default log output format without having to
replace the entire logging system.
For example, to disable timestamps in the log output:
```rust
fn fmt_layer(_app: &mut App) -> Option<bevy::log::BoxedFmtLayer> {
Some(Box::new(
bevy::log::tracing_subscriber::fmt::Layer::default()
.without_time()
.with_writer(std::io::stderr),
))
}
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(bevy::log::LogPlugin {
fmt_layer,
..default()
}))
.run();
}
```
This is different from the existing `custom_layer` option, because that
option _adds_ additional layers to the subscriber, but can't modify the
default formatter layer (at least, not to my knowledge).
I almost always disable timestamps in my Bevy logs, and usually also
tweak other default log formatting (such as `with_span_events`), which
made it so that I always had to disable the default logger. This allows
me to use everything the Bevy logger supports (including tracy support),
while still formatting the default logs the way I like them.
---------
Signed-off-by: Jean Mertz <git@jeanmertz.com>
# Objective
Add a viewport widget.
## Solution
- Add a new `ViewportNode` component to turn a UI node into a viewport.
- Add `viewport_picking` to pass pointer inputs from other pointers to
the viewport's pointer.
- Notably, this is somewhat functionally different from the viewport
widget in [the editor
prototype](https://github.com/bevyengine/bevy_editor_prototypes/pull/110/files#L124),
which just moves the pointer's location onto the render target. Viewport
widgets have their own pointers.
- Care is taken to handle dragging in and out of viewports.
- Add `update_viewport_render_target_size` to update the viewport node's
render target's size if the node size changes.
- Feature gate picking-related viewport items behind
`bevy_ui_picking_backend`.
## Testing
I've been using an example I made to test the widget (and added it as
`viewport_node`):
<details><summary>Code</summary>
```rust
//! A simple scene to demonstrate spawning a viewport widget. The example will demonstrate how to
//! pick entities visible in the widget's view.
use bevy::picking::pointer::PointerInteraction;
use bevy::prelude::*;
use bevy::ui::widget::ViewportNode;
use bevy::{
image::{TextureFormatPixelInfo, Volume},
window::PrimaryWindow,
};
use bevy_render::{
camera::RenderTarget,
render_resource::{
Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
},
};
fn main() {
App::new()
.add_plugins((DefaultPlugins, MeshPickingPlugin))
.add_systems(Startup, test)
.add_systems(Update, draw_mesh_intersections)
.run();
}
#[derive(Component, Reflect, Debug)]
#[reflect(Component)]
struct Shape;
fn test(
mut commands: Commands,
window: Query<&Window, With<PrimaryWindow>>,
mut images: ResMut<Assets<Image>>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Spawn a UI camera
commands.spawn(Camera3d::default());
// Set up an texture for the 3D camera to render to
let window = window.get_single().unwrap();
let window_size = window.physical_size();
let size = Extent3d {
width: window_size.x,
height: window_size.y,
..default()
};
let format = TextureFormat::Bgra8UnormSrgb;
let image = Image {
data: Some(vec![0; size.volume() * format.pixel_size()]),
texture_descriptor: TextureDescriptor {
label: None,
size,
dimension: TextureDimension::D2,
format,
mip_level_count: 1,
sample_count: 1,
usage: TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
},
..default()
};
let image_handle = images.add(image);
// Spawn the 3D camera
let camera = commands
.spawn((
Camera3d::default(),
Camera {
// Render this camera before our UI camera
order: -1,
target: RenderTarget::Image(image_handle.clone().into()),
..default()
},
))
.id();
// Spawn something for the 3D camera to look at
commands
.spawn((
Mesh3d(meshes.add(Cuboid::new(5.0, 5.0, 5.0))),
MeshMaterial3d(materials.add(Color::WHITE)),
Transform::from_xyz(0.0, 0.0, -10.0),
Shape,
))
// We can observe pointer events on our objects as normal, the
// `bevy::ui::widgets::viewport_picking` system will take care of ensuring our viewport
// clicks pass through
.observe(on_drag_cuboid);
// Spawn our viewport widget
commands
.spawn((
Node {
position_type: PositionType::Absolute,
top: Val::Px(50.0),
left: Val::Px(50.0),
width: Val::Px(200.0),
height: Val::Px(200.0),
border: UiRect::all(Val::Px(5.0)),
..default()
},
BorderColor(Color::WHITE),
ViewportNode::new(camera),
))
.observe(on_drag_viewport);
}
fn on_drag_viewport(drag: Trigger<Pointer<Drag>>, mut node_query: Query<&mut Node>) {
if matches!(drag.button, PointerButton::Secondary) {
let mut node = node_query.get_mut(drag.target()).unwrap();
if let (Val::Px(top), Val::Px(left)) = (node.top, node.left) {
node.left = Val::Px(left + drag.delta.x);
node.top = Val::Px(top + drag.delta.y);
};
}
}
fn on_drag_cuboid(drag: Trigger<Pointer<Drag>>, mut transform_query: Query<&mut Transform>) {
if matches!(drag.button, PointerButton::Primary) {
let mut transform = transform_query.get_mut(drag.target()).unwrap();
transform.rotate_y(drag.delta.x * 0.02);
transform.rotate_x(drag.delta.y * 0.02);
}
}
fn draw_mesh_intersections(
pointers: Query<&PointerInteraction>,
untargetable: Query<Entity, Without<Shape>>,
mut gizmos: Gizmos,
) {
for (point, normal) in pointers
.iter()
.flat_map(|interaction| interaction.iter())
.filter_map(|(entity, hit)| {
if !untargetable.contains(*entity) {
hit.position.zip(hit.normal)
} else {
None
}
})
{
gizmos.arrow(point, point + normal.normalize() * 0.5, Color::WHITE);
}
}
```
</details>
## Showcase
https://github.com/user-attachments/assets/39f44eac-2c2a-4fd9-a606-04171f806dc1
## Open Questions
- <del>Not sure whether the entire widget should be feature gated behind
`bevy_ui_picking_backend` or not? I chose a partial approach since maybe
someone will want to use the widget without any picking being
involved.</del>
- <del>Is `PickSet::Last` the expected set for `viewport_picking`?
Perhaps `PickSet::Input` is more suited.</del>
- <del>Can `dragged_last_frame` be removed in favor of a better dragging
check? Another option that comes to mind is reading `Drag` and `DragEnd`
events, but this seems messier.</del>
---------
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
Stop using `ArchetypeComponentId` in the executor. These IDs will grow
even more quickly with relations, and the size may start to degrade
performance.
## Solution
Have systems expose their `FilteredAccessSet<ComponentId>`, and have the
executor use that to determine which systems conflict. This can be
determined statically, so determine all conflicts during initialization
and only perform bit tests when running.
## Testing
I ran many_foxes and didn't see any performance changes. It's probably
worth testing this with a wider range of realistic schedules to see
whether the reduced concurrency has a cost in practice, but I don't know
what sort of test cases to use.
## Migration Guide
The schedule will now prevent systems from running in parallel if there
*could* be an archetype that they conflict on, even if there aren't
actually any. For example, these systems will now conflict even if no
entity has both `Player` and `Enemy` components:
```rust
fn player_system(query: Query<(&mut Transform, &Player)>) {}
fn enemy_system(query: Query<(&mut Transform, &Enemy)>) {}
```
To allow them to run in parallel, use `Without` filters, just as you
would to allow both queries in a single system:
```rust
// Either one of these changes alone would be enough
fn player_system(query: Query<(&mut Transform, &Player), Without<Enemy>>) {}
fn enemy_system(query: Query<(&mut Transform, &Enemy), Without<Player>>) {}
```
# Objective
- When loading a folder with dot files inside, Bevy crashes:
```
thread 'IO Task Pool (1)' panicked at crates/bevy_asset/src/io/mod.rs:260:10:
asset paths must have extensions
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
- those files are common for other tools to store their
settings/metadata
## Solution
- Ignore files starting with a dot when loading folders
The occlusion culling plugin checks for a GPU feature by looking at
`RenderAdapter`. This is wrong - it should be checking `RenderDevice`.
See these notes for background:
https://github.com/bevyengine/bevy/discussions/18973
I don't have any evidence that this was causing any bugs, so right now
it's just a precaution.
## Testing
```
cargo run --example occlusion_culling
```
Tested on Win10/Nvidia across Vulkan, WebGL/Chrome, WebGPU/Chrome.
# Objective
Prevent using exclusive systems as observers. Allowing them is unsound,
because observers are only expected to have `DeferredWorld` access, and
the observer infrastructure will keep pointers that are invalidated by
the creation of `&mut World`.
See
https://github.com/bevyengine/bevy/actions/runs/14778342801/job/41491517847?pr=19011
for a MIRI failure in a recent PR caused by an exclusive system being
used as an observer in a test.
## Solution
Have `Observer::new` panic if `System::is_exclusive()` is true. Document
that method, and methods that call it, as panicking.
(It should be possible to express this in the type system so that the
calls won't even compile, but I did not want to attempt that.)
## Testing
Added a unit test that calls `World::add_observer` with an exclusive
system.
# Objective
I've been tinkering with ECS insertion/removal lately, and noticed that
sparse sets just... don't interact with `InsertMode` at all. Sure
enough, using `insert_if_new` with a sparse component does the same
thing as `insert`.
# Solution
- Add a check in `BundleInfo::write_components` to drop the new value if
the entity already has the component and `InsertMode` is `Keep`.
- Add necessary methods to sparse set internals to fetch the drop
function.
# Testing
Minimal reproduction:
<details>
<summary>Code</summary>
```
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(PostStartup, component_print)
.run();
}
#[derive(Component)]
#[component(storage = "SparseSet")]
struct SparseComponent(u32);
fn setup(mut commands: Commands) {
let mut entity = commands.spawn_empty();
entity.insert(SparseComponent(1));
entity.insert(SparseComponent(2));
let mut entity = commands.spawn_empty();
entity.insert(SparseComponent(3));
entity.insert_if_new(SparseComponent(4));
}
fn component_print(query: Query<&SparseComponent>) {
for component in &query {
info!("{}", component.0);
}
}
```
</details>
Here it is on Bevy Playground (0.15.3):
https://learnbevy.com/playground?share=2a96a68a81e804d3fdd644a833c1d51f7fa8dd33fc6192fbfd077b082a6b1a41
Output on `main`:
```
2025-05-04T17:50:50.401328Z INFO system{name="fork::component_print"}: fork: 2
2025-05-04T17:50:50.401583Z INFO system{name="fork::component_print"}: fork: 4
```
Output with this PR :
```
2025-05-04T17:51:33.461835Z INFO system{name="fork::component_print"}: fork: 2
2025-05-04T17:51:33.462091Z INFO system{name="fork::component_print"}: fork: 3
```
# Objective
- The tonemapping example allows using a local image to try out
different color grading. However, using a local file stopped working
when we added the `UnapprovedPathMode` setting to the assets plugin.
## Solution
- Set `unapproved_path_mode: UnapprovedPathMode::Allow` in the example
## Testing
- I tried out the example with local images, previously it would fail
saying it's an untrusted path.
# Objective
- Contributes to #18978
## Solution
- Disable default features on all dependencies in `bevy_asset` and
explicitly enable ones that are required.
- Remove `compile_error` caused by enabling `file_watcher` without
`multi_threaded` by including `multi_threaded` in `file_watcher`.
## Testing
- CI
---
## Notes
No breaking changes here, just a little cleaning before the more
controversial changes for `no_std` support.
---------
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
- CI fails due to `atomic-polyfill` being unmaintained
## Solution
- Dependency chain of `postcard -> heapless -> atomic-polyfill` .
`heapless` is updated. `postcard` has not yet.
- See https://github.com/jamesmunns/postcard/issues/223
- Ignore the advisory for now
## Testing
- CI with this PR
---------
Co-authored-by: MichiRecRoom <1008889+LikeLakers2@users.noreply.github.com>
# Objective
Fixes#18969
## Solution
Also updated `Aabb3d` implementation for consistency.
## Testing
Added tests for `Aabb2d` and `Aabb3d` to verify correct rotation
behavior for angles greater than 90 degrees.
# Objective
`BTreeSet` doesn't implement `RelationshipSourceCollection`.
## Solution
Implement it.
## Testing
`cargo clippy`
---
## Showcase
You can now use `BTreeSet` in a `RelationshipTarget`
---------
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
Create a `When` system param wrapper for skipping systems that fail
validation.
Currently, the `Single` and `Populated` parameters cause systems to skip
when they fail validation, while the `Res` family causes systems to
error. Generalize this so that any fallible parameter can be used either
to skip a system or to raise an error. A parameter used directly will
always raise an error, and a parameter wrapped in `When<P>` will always
cause the system to be silently skipped.
~~Note that this changes the behavior for `Single` and `Populated`. The
current behavior will be available using `When<Single>` and
`When<Populated>`.~~
Fixes#18516
## Solution
Create a `When` system param wrapper that wraps an inner parameter and
converts all validation errors to `skipped`.
~~Change the behavior of `Single` and `Populated` to fail by default.~~
~~Replace in-engine use of `Single` with `When<Single>`. I updated the
`fallible_systems` example, but not all of the others. The other
examples I looked at appeared to always have one matching entity, and it
seemed more clear to use the simpler type in those cases.~~
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
Refactor
[`examples/ui/borders.rs`](7f0490655c/examples/ui/borders.rs)
to use the new spawning/hierarchy APIs in 0.16.
## Solution
This refactor reduces the number of `.spawn` calls from about 16 to 2,
using one spawn for each major feature:
* camera2d
* ui layout
The `Children::spawn` relationship API is used to take advantage of
`SpawnIter` for the borders examples in each block.
Each block of examples now returns a Bundle into its respective
variable, which is then used in combination with the new `label` widget
which makes use of the new `impl Bundle` return capability. This allows
the ui layout to use a single `.spawn` with the `children!` macro.
The blocks of examples are still in separate variables because it felt
like a useful way to organize it still, even without needing to spawn at
those locations.
Functionality of the demo hasn't changed, this is just an API/code
update.
## Showcase

<details>
<summary>Before screenshot</summary>

</details>
---------
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
- If using a `NonNilUuid` in Bevy, it's difficult to reflect it.
## Solution
- Adds `NonNilUuid` using `impl_reflect_opaque!`.
## Testing
- Built with no issues found locally.
- Essentially the same as the `Uuid` support except without `Default`.
Co-authored-by: TM Storey <mail@tmstorey.id.au>
# Objective
Add background colors for text.
Fixes#18889
## Solution
New component `TextBackgroundColor`, add it to any UI `Text` or
`TextSpan` entity to add a background color to its text.
New field on `TextLayoutInfo` `section_rects` holds the list of bounding
rects for each text section.
The bounding rects are generated in `TextPipeline::queue_text` during
text layout, `extract_text_background_colors` extracts the colored
background rects for rendering.
Didn't include `Text2d` support because of z-order issues.
The section rects can also be used to implement interactions targeting
individual text sections.
## Testing
Includes a basic example that can be used for testing:
```
cargo run --example text_background_colors
```
---
## Showcase

Using a proportional font with kerning the results aren't so tidy (since
the bounds of adjacent glyphs can overlap) but it still works fine:

---------
Co-authored-by: Olle Lukowski <lukowskiolle@gmail.com>
Co-authored-by: Gilles Henaux <ghx_github_priv@fastmail.com>
Adopted #13869
# Objective
Fixes#9076
## Solution
Using `rodio`'s `try_seek`
## Testing
@ivanstepanovftw added a `seek` system using `AudioSink` to the
`audio_control.rs` example. I got it working with .mp3 files, but rodio
doesn't support seeking for .ogg and .flac files, so I removed it from
the commit (since the assets folder only has .ogg files). Another thing
to note is that `try_seek` fails when using `PlaybackMode::Loop`, as
`rodio::source::buffered::Buffered` doesn't support `try_seek`. I
haven't tested `SpatialAudioSink`.
## Notes
I copied the docs for `try_seek` verbatim from `rodio`, and re-exported
`rodio::source::SeekError`. I'm not completely confident in those
decisions, please let me know if I'm doing anything wrong.
</details>
---------
Co-authored-by: Ivan Stepanov <ivanstepanovftw@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
The default should be `OverflowClipBox::PaddingBox` not
`OverflowClipBox::ContentBox`
`padding-box` is the default in CSS.
## Solution
Set the default to `PaddingBox`.
## Testing
Compare the `overflow` UI example on main vs with this PR. You should
see that on main the outline around the inner node gets clipped. With
this PR by default clipping starts at the inner edge of the border (the
`padding-box`) and the outlines are visible.
Fixes#18934
# Objective
We have methods to:
- Add related entities
- Replace related entities
- Remove specific related entities
We don't have a method the remove all related entities so.
## Solution
Add a method to remove all related entities.
## Testing
A new test case.
# Objective
Tripped over the `directional_navigation` one recently while playing
around with that example.
Examples should import items from `bevy` rather than the sub-crates
directly.
## Solution
Use paths re-exported by `bevy`.
## Testing
```
cargo run --example log_diagnostics
cargo run --example directional_navigation
cargo run --example custom_projection
```
# Objective
When implementing `SystemParam` for an object which contains a mutable
reference to World, which cannot be derived due to a required lifetime
parameter, it's necessary to check that there aren't any conflicts.
As far as I know, the is_empty method is the only way provided to check
for no conflicts at all
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/15389.
- Add documentation for RawHandleWrapper::_window field since It's
needed to drop the window at the correct time.
## Solution
- Added documentation to RawHandleWrapper::_window field as same as
WindowWrapper documentation.
## Testing
- No testing needed since it is documentation.
---
# Objective
Subtle, very minor issue. The following code fails to compile on main:
```rs
struct bevy;
#[derive(::bevy::ecs::component::Component)]
struct MyComponent;
```
The derive proc macro is pasting in essentially:
```rs
impl bevy::ecs::component::Component for MyComponent
```
...which normally works, but I've added `struct bevy`, which makes the
proc macro spit out incorrect code.
Very cursed, but to my knowledge has never been encountered in practice.
All the same, it's technically incorrect and should be fixed.
## Solution
The solution is simply to prepend `::` to crate names. Specifically, all
(all?) Bevy's derive macros determine the root crate name using
`BevyManifest`, which does some toml-parsing witchcraft to figure out
whether to qualify names using the umbrella `bevy` crate or individual
`bevy_xxx` crates. I just added a `::` to the spot where we parse the
`syn::Path`. The above example compiles properly after that.
## Testing
- CI should catch any errors since this change should cause compile
errors if for some reason they're being used in a cursed way somewhere
that would make this break something.
## Note
If this does break something for someone, this *really* needs a comment
in `BevyManifest::maybe_get_path` explaining why we can't make this
change.
# Objective
Fixes#18943
## Solution
Reintroduces support for `hashbrown`'s `HashMap` and `HashSet` types.
These were inadvertently removed when `bevy_platform` newtyped the
`hashbrown` types.
Since we removed our `hashbrown` dependency, I gated these impls behind
a `hashbrown` feature. Not entirely sure if this is necessary since we
enabled it for `bevy_reflect` through `bevy_platform` anyways. (Complex
features still confuse me a bit so let me know if I can just remove it!)
I also went ahead and preemptively implemented `TypePath` for `PassHash`
while I was here.
## Testing
You can test that it works by adding the following to a Bevy example
based on this PR (you'll also need to include `hashbrown` of course):
```rust
#[derive(Reflect)]
struct Foo(hashbrown::HashMap<String, String>);
```
Then check it compiles with:
```
cargo check --example hello_world --no-default-features --features=bevy_reflect/hashbrown
```
# Objective
- Fixes#18856.
## Solution
After PR #17633, `Camera::viewport_to_world` method corrects
`viewport_position` passed in that input so that it's offset by camera's
viewport. `Camera::viewport_to_world` is used by `make_ray` function
which in turn also offsets pointer position by viewport position, which
causes picking objects to be shifted by viewport position, and it wasn't
removed in the aforementioned PR. This second offsetting in `make_ray`
was removed.
## Testing
- I tested simple_picking example by applying some horizontal offset to
camera's viewport.
- I tested my application that displayed a single rectangle with picking
on two cameras arranged in a row. When using local bevy with this fix,
both cameras can be used for picking correctly.
- I modified split_screen example: I added observer to ground plane that
changes color on hover, and removed UI as it interfered with picking
both on master and my branch. On master, only top left camera was
triggering the observer, and on my branch all cameras could change
plane's color on hover.
- I added viewport offset to mesh_picking, with my changes it works
correctly, while on master picking ray is shifted.
- Sprite picking with viewport offset doesn't work both on master and on
this branch.
These are the only scenarios I tested. I think other picking functions
that use this function should be tested but I couldn't track more uses
of it.
Co-authored-by: Krzysztof Zywiecki <krzysiu@pop-os.Dlink>