This adds support for one-to-many non-fragmenting relationships (with
planned paths for fragmenting and non-fragmenting many-to-many
relationships). "Non-fragmenting" means that entities with the same
relationship type, but different relationship targets, are not forced
into separate tables (which would cause "table fragmentation").
Functionally, this fills a similar niche as the current Parent/Children
system. The biggest differences are:
1. Relationships have simpler internals and significantly improved
performance and UX. Commands and specialized APIs are no longer
necessary to keep everything in sync. Just spawn entities with the
relationship components you want and everything "just works".
2. Relationships are generalized. Bevy can provide additional built in
relationships, and users can define their own.
**REQUEST TO REVIEWERS**: _please don't leave top level comments and
instead comment on specific lines of code. That way we can take
advantage of threaded discussions. Also dont leave comments simply
pointing out CI failures as I can read those just fine._
## Built on top of what we have
Relationships are implemented on top of the Bevy ECS features we already
have: components, immutability, and hooks. This makes them immediately
compatible with all of our existing (and future) APIs for querying,
spawning, removing, scenes, reflection, etc. The fewer specialized APIs
we need to build, maintain, and teach, the better.
## Why focus on one-to-many non-fragmenting first?
1. This allows us to improve Parent/Children relationships immediately,
in a way that is reasonably uncontroversial. Switching our hierarchy to
fragmenting relationships would have significant performance
implications. ~~Flecs is heavily considering a switch to non-fragmenting
relations after careful considerations of the performance tradeoffs.~~
_(Correction from @SanderMertens: Flecs is implementing non-fragmenting
storage specialized for asset hierarchies, where asset hierarchies are
many instances of small trees that have a well defined structure)_
2. Adding generalized one-to-many relationships is currently a priority
for the [Next Generation Scene / UI
effort](https://github.com/bevyengine/bevy/discussions/14437).
Specifically, we're interested in building reactions and observers on
top.
## The changes
This PR does the following:
1. Adds a generic one-to-many Relationship system
3. Ports the existing Parent/Children system to Relationships, which now
lives in `bevy_ecs::hierarchy`. The old `bevy_hierarchy` crate has been
removed.
4. Adds on_despawn component hooks
5. Relationships can opt-in to "despawn descendants" behavior, meaning
that the entire relationship hierarchy is despawned when
`entity.despawn()` is called. The built in Parent/Children hierarchies
enable this behavior, and `entity.despawn_recursive()` has been removed.
6. `world.spawn` now applies commands after spawning. This ensures that
relationship bookkeeping happens immediately and removes the need to
manually flush. This is in line with the equivalent behaviors recently
added to the other APIs (ex: insert).
7. Removes the ValidParentCheckPlugin (system-driven / poll based) in
favor of a `validate_parent_has_component` hook.
## Using Relationships
The `Relationship` trait looks like this:
```rust
pub trait Relationship: Component + Sized {
type RelationshipSources: RelationshipSources<Relationship = Self>;
fn get(&self) -> Entity;
fn from(entity: Entity) -> Self;
}
```
A relationship is a component that:
1. Is a simple wrapper over a "target" Entity.
2. Has a corresponding `RelationshipSources` component, which is a
simple wrapper over a collection of entities. Every "target entity"
targeted by a "source entity" with a `Relationship` has a
`RelationshipSources` component, which contains every "source entity"
that targets it.
For example, the `Parent` component (as it currently exists in Bevy) is
the `Relationship` component and the entity containing the Parent is the
"source entity". The entity _inside_ the `Parent(Entity)` component is
the "target entity". And that target entity has a `Children` component
(which implements `RelationshipSources`).
In practice, the Parent/Children relationship looks like this:
```rust
#[derive(Relationship)]
#[relationship(relationship_sources = Children)]
pub struct Parent(pub Entity);
#[derive(RelationshipSources)]
#[relationship_sources(relationship = Parent)]
pub struct Children(Vec<Entity>);
```
The Relationship and RelationshipSources derives automatically implement
Component with the relevant configuration (namely, the hooks necessary
to keep everything in sync).
The most direct way to add relationships is to spawn entities with
relationship components:
```rust
let a = world.spawn_empty().id();
let b = world.spawn(Parent(a)).id();
assert_eq!(world.entity(a).get::<Children>().unwrap(), &[b]);
```
There are also convenience APIs for spawning more than one entity with
the same relationship:
```rust
world.spawn_empty().with_related::<Children>(|s| {
s.spawn_empty();
s.spawn_empty();
})
```
The existing `with_children` API is now a simpler wrapper over
`with_related`. This makes this change largely non-breaking for existing
spawn patterns.
```rust
world.spawn_empty().with_children(|s| {
s.spawn_empty();
s.spawn_empty();
})
```
There are also other relationship APIs, such as `add_related` and
`despawn_related`.
## Automatic recursive despawn via the new on_despawn hook
`RelationshipSources` can opt-in to "despawn descendants" behavior,
which will despawn all related entities in the relationship hierarchy:
```rust
#[derive(RelationshipSources)]
#[relationship_sources(relationship = Parent, despawn_descendants)]
pub struct Children(Vec<Entity>);
```
This means that `entity.despawn_recursive()` is no longer required.
Instead, just use `entity.despawn()` and the relevant related entities
will also be despawned.
To despawn an entity _without_ despawning its parent/child descendants,
you should remove the `Children` component first, which will also remove
the related `Parent` components:
```rust
entity
.remove::<Children>()
.despawn()
```
This builds on the on_despawn hook introduced in this PR, which is fired
when an entity is despawned (before other hooks).
## Relationships are the source of truth
`Relationship` is the _single_ source of truth component.
`RelationshipSources` is merely a reflection of what all the
`Relationship` components say. By embracing this, we are able to
significantly improve the performance of the system as a whole. We can
rely on component lifecycles to protect us against duplicates, rather
than needing to scan at runtime to ensure entities don't already exist
(which results in quadratic runtime). A single source of truth gives us
constant-time inserts. This does mean that we cannot directly spawn
populated `Children` components (or directly add or remove entities from
those components). I personally think this is a worthwhile tradeoff,
both because it makes the performance much better _and_ because it means
theres exactly one way to do things (which is a philosophy we try to
employ for Bevy APIs).
As an aside: treating both sides of the relationship as "equivalent
source of truth relations" does enable building simple and flexible
many-to-many relationships. But this introduces an _inherent_ need to
scan (or hash) to protect against duplicates.
[`evergreen_relations`](https://github.com/EvergreenNest/evergreen_relations)
has a very nice implementation of the "symmetrical many-to-many"
approach. Unfortunately I think the performance issues inherent to that
approach make it a poor choice for Bevy's default relationship system.
## Followup Work
* Discuss renaming `Parent` to `ChildOf`. I refrained from doing that in
this PR to keep the diff reasonable, but I'm personally biased toward
this change (and using that naming pattern generally for relationships).
* [Improved spawning
ergonomics](https://github.com/bevyengine/bevy/discussions/16920)
* Consider adding relationship observers/triggers for "relationship
targets" whenever a source is added or removed. This would replace the
current "hierarchy events" system, which is unused upstream but may have
existing users downstream. I think triggers are the better fit for this
than a buffered event queue, and would prefer not to add that back.
* Fragmenting relations: My current idea hinges on the introduction of
"value components" (aka: components whose type _and_ value determines
their ComponentId, via something like Hashing / PartialEq). By labeling
a Relationship component such as `ChildOf(Entity)` as a "value
component", `ChildOf(e1)` and `ChildOf(e2)` would be considered
"different components". This makes the transition between fragmenting
and non-fragmenting a single flag, and everything else continues to work
as expected.
* Many-to-many support
* Non-fragmenting: We can expand Relationship to be a list of entities
instead of a single entity. I have largely already written the code for
this.
* Fragmenting: With the "value component" impl mentioned above, we get
many-to-many support "for free", as it would allow inserting multiple
copies of a Relationship component with different target entities.
Fixes#3742 (If this PR is merged, I think we should open more targeted
followup issues for the work above, with a fresh tracking issue free of
the large amount of less-directed historical context)
Fixes#17301Fixes#12235Fixes#15299Fixes#15308
## Migration Guide
* Replace `ChildBuilder` with `ChildSpawnerCommands`.
* Replace calls to `.set_parent(parent_id)` with
`.insert(Parent(parent_id))`.
* Replace calls to `.replace_children()` with `.remove::<Children>()`
followed by `.add_children()`. Note that you'll need to manually despawn
any children that are not carried over.
* Replace calls to `.despawn_recursive()` with `.despawn()`.
* Replace calls to `.despawn_descendants()` with
`.despawn_related::<Children>()`.
* If you have any calls to `.despawn()` which depend on the children
being preserved, you'll need to remove the `Children` component first.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes https://github.com/bevyengine/bevy/issues/17111
## Solution
Move `#![warn(clippy::allow_attributes,
clippy::allow_attributes_without_reason)]` to the workspace `Cargo.toml`
## Testing
Lots of CI testing, and local testing too.
---------
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
I realized that setting these to `deny` may have been a little
aggressive - especially since we upgrade warnings to denies in CI.
## Solution
Downgrades these lints to `warn`, so that compiles can work locally. CI
will still treat these as denies.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_audio` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
`cargo clippy` and `cargo test --package bevy_audio` were run, and no
errors were encountered.
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 Mockers <mockersf@gmail.com>
# Objective
- Contributes to #11478
## Solution
- Made `bevy_utils::tracing` `doc(hidden)`
- Re-exported `tracing` from `bevy_log` for end-users
- Added `tracing` directly to crates that need it.
## Testing
- CI
---
## Migration Guide
If you were importing `tracing` via `bevy::utils::tracing`, instead use
`bevy::log::tracing`. Note that many items within `tracing` are also
directly re-exported from `bevy::log` as well, so you may only need
`bevy::log` for the most common items (e.g., `warn!`, `trace!`, etc.).
This also applies to the `log_once!` family of macros.
## Notes
- While this doesn't reduce the line-count in `bevy_utils`, it further
decouples the internal crates from `bevy_utils`, making its eventual
removal more feasible in the future.
- I have just imported `tracing` as we do for all dependencies. However,
a workspace dependency may be more appropriate for version management.
Derived `Default` for all public unit structs that already derive from
`Component`. This allows them to be used more easily as required
components.
To avoid clutter in tests/examples, only public components were
affected, but this could easily be expanded to affect all unit
components.
Fixes#17052.
# Objective
Fixes#16104
## Solution
I removed all instances of `:?` and put them back one by one where it
caused an error.
I removed some bevy_utils helper functions that were only used in 2
places and don't add value. See: #11478
## Testing
CI should catch the mistakes
## Migration Guide
`bevy::utils::{dbg,info,warn,error}` were removed. Use
`bevy::utils::tracing::{debug,info,warn,error}` instead.
---------
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
# Objective
- Prework for reviving #9582.
## Solution
- Move the two types to volume.rs and made it compile.
- Also `#[reflect(Debug)]` on `Volume` while I'm here.
## Testing
- Ran example locally.
- Rely on CI.
# Objective
- #16813 added the ability to mute sinks and added a new method
`toggle_mute()`.
- Leaving `toggle()` as is creates inconsistency and a bit of confusion
about what is being toggled.
## Solution
- Rename `toggle()` to `toggle_playback()`.
- The choice to use the `_playback` suffix was easy because the method
comment was already telling us what is being toggled: `Toggles playback
of the sink.`
- [Raised in Discord] and got the OK from Alice.
[Raised in Discord]:
https://discord.com/channels/691052431525675048/749430447326625812/1318000355824504905
## Testing
- I ran the example and also updated the instruction text to make it
clear `Space` is toggling the playback not just pausing.
- I added a unit test for `toggle_playback()` because why not.
---
## Showcase
Example instructions:
<img width="292" alt="image"
src="https://github.com/user-attachments/assets/585c36c6-c4d7-428b-acbe-a92f3a37b460"
/>
## Migration Guide
- `AudioSinkPlayback`'s `toggle` method has been renamed to
`toggle_playback`. This was done to create consistency with the
`toggle_mute` method added in
https://github.com/bevyengine/bevy/pull/16813. Change instances of
`toggle` to `toggle_playback`. E.g.:
Before:
```rust
fn pause(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink>) {
if keyboard_input.just_pressed(KeyCode::Space) {
sink.toggle();
}
}
```
After:
```rust
fn pause(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink>) {
if keyboard_input.just_pressed(KeyCode::Space) {
sink.toggle_playback();
}
}
```
# Objective
- Allow users to mute audio.
```rust
fn mute(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut sink: Single<&mut AudioSink, With<MyMusic>>,
) {
if keyboard_input.just_pressed(KeyCode::KeyM) {
sink.toggle_mute();
}
}
```
- I want to be able to press, say, `M` and mute all my audio. I want
this for dev, but I'm sure it's a useful player setting as well.
- Muting is different to pausing—I don't want to pause my sounds, I want
them to keep playing but with no volume. For example if I have
background music playing which is made up of 5 tracks, I want to be able
to temporarily mute my background music, and if I unmute at, say, track
4, I want to play track 4 rather than have had everything paused and
still be on the first track.
- I want to be able to continue to control the volume of my audio even
when muted. Like in the example, if I have muted my audio but I use the
volume up/down controls, I want Bevy to remember those volume changes so
that when I unmute, the volume corresponds to that.
## Solution
- Add methods to audio to allow muting, unmuting and toggling muting.
- To preserve the user's intended volume, each sink needs to keep track
of a "managed volume".
- I checked `rodio` and I don't see any built in support for doing this,
so I added it to `bevy_audio`.
- I'm interested to hear if this is a good idea or a bad idea. To me,
this API looks nice and looks usable, but I'm aware it involves some
changes to the existing API and now also requires mutable access in some
places compared to before.
- I'm also aware of work on *Better Audio*, but I'm hoping that if this
change isn't too wild it might be a useful addition considering we don't
really know when we'll eventually get better audio.
## Testing
- Update and run the example: `cargo run --example audio_control`
- Run the example: `cargo run --example soundtrack`
- Update and run the example: `cargo run --example spatial_audio_3d`
- Add unit tests.
---
## Showcase
See 2 changed examples that show how you can mute an audio sink and a
spatial audio sink.
## Migration Guide
- The `AudioSinkPlayback` trait now has 4 new methods to allow you to
mute audio sinks: `is_muted`, `mute`, `unmute` and `toggle_mute`. You
can use these methods on `bevy_audio`'s `AudioSink` and
`SpatialAudioSink` components to manage the sink's mute state.
- `AudioSinkPlayback`'s `set_volume` method now takes a mutable
reference instead of an immutable one. Update your code which calls
`set_volume` on `AudioSink` and `SpatialAudioSink` components to take a
mutable reference. E.g.:
Before:
```rust
fn increase_volume(sink: Single<&AudioSink>) {
sink.set_volume(sink.volume() + 0.1);
}
```
After:
```rust
fn increase_volume(mut sink: Single<&mut AudioSink>) {
let current_volume = sink.volume();
sink.set_volume(current_volume + 0.1);
}
```
- The `PlaybackSettings` component now has a `muted` field which you can
use to spawn your audio in a muted state. `PlaybackSettings` also now
has a helper method `muted` which you can use when building the
component. E.g.:
```rust
commands.spawn((
// ...
AudioPlayer::new(asset_server.load("sounds/Windless Slopes.ogg")),
PlaybackSettings::LOOP.with_spatial(true).muted(),
));
```
---------
Co-authored-by: Nathan Graule <solarliner@gmail.com>
# Objective
Fixes#12359
## Solution
Implement alternative number 4.
https://github.com/bevyengine/bevy/issues/12359#issuecomment-2536422301
> I don't think that I agree with the premise of this issue anymore. I
am not sure that entities "magically" despawning themselves or
components removing themselves make for great defaults in an "ECS-based
API". This behavior is likely to be just as surprising to people.
>
> I think that the lack of sink re-usability should be treated as a bug
and possibly the documentation improved to reflect the current
limitations if it doesn't seem like a fix is forthcoming.
> -- me
# Objective
`AudioPlayer::<AudioSource>(assets.load("audio.mp3"))` is awkward and
complicated to type because the `AudioSource` generic type cannot be
elided. This is especially annoying because `AudioSource` is used in the
majority of cases. Most users don't need to think about it.
## Solution
Add an `AudioPlayer::new()` function that is hard-coded to
`AudioSource`, allowing `AudioPlayer::new(assets.load("audio.mp3"))`.
Prefer using that in the relevant places.
# Objective
Someone (let's not name names here) might've been a bit of a goofball,
and happened to forget that "playing audio" should cause this thing
called "sound" to be emitted! That someone might not have realized that
queries should be updated to account for audio using wrapper components
instead of raw asset handles after #15573.
## Solution
Update systems, and listen to the relaxing soundscapes of `Windless
Slopes.ogg` 🎵
# Objective
What's that? Another PR for the grand migration to required components?
This time, audio!
## Solution
Deprecate `AudioSourceBundle`, `AudioBundle`, and `PitchBundle`, as per
the [chosen
proposal](https://hackmd.io/@bevy/required_components/%2Fzxgp-zMMRUCdT7LY1ZDQwQ).
However, we cannot call the component `AudioSource`, because that's what
the stored asset is called. I deliberated on a few names, like
`AudioHandle`, or even just `Audio`, but landed on `AudioPlayer`, since
it's probably the most accurate and "nice" name for this. Open to
alternatives though.
---
## Migration Guide
Replace all insertions of `AudioSoucreBundle`, `AudioBundle`, and
`PitchBundle` with the `AudioPlayer` component. The other components
required by it will now be inserted automatically.
In cases where the generics cannot be inferred, you may need to specify
them explicitly. For example:
```rust
commands.spawn(AudioPlayer::<AudioSource>(asset_server.load("sounds/sick_beats.ogg")));
```
# Objective
Fixes#15541
A bunch of lifetimes were added during the Assets V2 rework, but after
moving to async traits in #12550 they can be elided. That PR mentions
that this might be the case, but apparently it wasn't followed up on at
the time.
~~I ended up grepping for `<'a` and finding a similar case in
`bevy_reflect` which I also fixed.~~ (edit: that one was needed
apparently)
Note that elided lifetimes are unstable in `impl Trait`. If that gets
stabilized then we can elide even more.
## Solution
Remove the extra lifetimes.
## Testing
Everything still compiles. If I have messed something up there is a
small risk that some user code stops compiling, but all the examples
still work at least.
---
## Migration Guide
The traits `AssetLoader`, `AssetSaver` and `Process` traits from
`bevy_asset` now use elided lifetimes. If you implement these then
remove the named lifetime.
# Objective
- Fixes#6370
- Closes#6581
## Solution
- Added the following lints to the workspace:
- `std_instead_of_core`
- `std_instead_of_alloc`
- `alloc_instead_of_core`
- Used `cargo +nightly fmt` with [item level use
formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Item%5C%3A)
to split all `use` statements into single items.
- Used `cargo clippy --workspace --all-targets --all-features --fix
--allow-dirty` to _attempt_ to resolve the new linting issues, and
intervened where the lint was unable to resolve the issue automatically
(usually due to needing an `extern crate alloc;` statement in a crate
root).
- Manually removed certain uses of `std` where negative feature gating
prevented `--all-features` from finding the offending uses.
- Used `cargo +nightly fmt` with [crate level use
formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Crate%5C%3A)
to re-merge all `use` statements matching Bevy's previous styling.
- Manually fixed cases where the `fmt` tool could not re-merge `use`
statements due to conditional compilation attributes.
## Testing
- Ran CI locally
## Migration Guide
The MSRV is now 1.81. Please update to this version or higher.
## Notes
- This is a _massive_ change to try and push through, which is why I've
outlined the semi-automatic steps I used to create this PR, in case this
fails and someone else tries again in the future.
- Making this change has no impact on user code, but does mean Bevy
contributors will be warned to use `core` and `alloc` instead of `std`
where possible.
- This lint is a critical first step towards investigating `no_std`
options for Bevy.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
- Crate-level prelude modules, such as `bevy_ecs::prelude`, are plagued
with inconsistency! Let's fix it!
## Solution
Format all preludes based on the following rules:
1. All preludes should have brief documentation in the format of:
> The _name_ prelude.
>
> This includes the most common types in this crate, re-exported for
your convenience.
2. All documentation should be outer, not inner. (`///` instead of
`//!`.)
3. No prelude modules should be annotated with `#[doc(hidden)]`. (Items
within them may, though I'm not sure why this was done.)
## Testing
- I manually searched for the term `mod prelude` and updated all
occurrences by hand. 🫠
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
- Fix issue #2611
## Solution
- Add `--generate-link-to-definition` to all the `rustdoc-args` arrays
in the `Cargo.toml`s (for docs.rs)
- Add `--generate-link-to-definition` to the `RUSTDOCFLAGS` environment
variable in the docs workflow (for dev-docs.bevyengine.org)
- Document all the workspace crates in the docs workflow (needed because
otherwise only the source code of the `bevy` package will be included,
making the argument useless)
- I think this also fixes#3662, since it fixes the bug on
dev-docs.bevyengine.org, while on docs.rs it has been fixed for a while
on their side.
---
## Changelog
- The source code viewer on docs.rs now includes links to the
definitions.
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 Mockers <mockersf@gmail.com>
# Objective
The `AssetReader` trait allows customizing the behavior of fetching
bytes for an `AssetPath`, and expects implementors to return `dyn
AsyncRead + AsyncSeek`. This gives implementors of `AssetLoader` great
flexibility to tightly integrate their asset loading behavior with the
asynchronous task system.
However, almost all implementors of `AssetLoader` don't use the async
functionality at all, and just call `AsyncReadExt::read_to_end(&mut
Vec<u8>)`. This is incredibly inefficient, as this method repeatedly
calls `poll_read` on the trait object, filling the vector 32 bytes at a
time. At my work we have assets that are hundreds of megabytes which
makes this a meaningful overhead.
## Solution
Turn the `Reader` type alias into an actual trait, with a provided
method `read_to_end`. This provided method should be more efficient than
the existing extension method, as the compiler will know the underlying
type of `Reader` when generating this function, which removes the
repeated dynamic dispatches and allows the compiler to make further
optimizations after inlining. Individual implementors are able to
override the provided implementation -- for simple asset readers that
just copy bytes from one buffer to another, this allows removing a large
amount of overhead from the provided implementation.
Now that `Reader` is an actual trait, I also improved the ergonomics for
implementing `AssetReader`. Currently, implementors are expected to box
their reader and return it as a trait object, which adds unnecessary
boilerplate to implementations. This PR changes that trait method to
return a pseudo trait alias, which allows implementors to return `impl
Reader` instead of `Box<dyn Reader>`. Now, the boilerplate for boxing
occurs in `ErasedAssetReader`.
## Testing
I made identical changes to my company's fork of bevy. Our app, which
makes heavy use of `read_to_end` for asset loading, still worked
properly after this. I am not aware if we have a more systematic way of
testing asset loading for correctness.
---
## Migration Guide
The trait method `bevy_asset::io::AssetReader::read` (and `read_meta`)
now return an opaque type instead of a boxed trait object. Implementors
of these methods should change the type signatures appropriately
```rust
impl AssetReader for MyReader {
// Before
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
let reader = // construct a reader
Box::new(reader) as Box<Reader<'a>>
}
// After
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
// create a reader
}
}
```
`bevy::asset::io::Reader` is now a trait, rather than a type alias for a
trait object. Implementors of `AssetLoader::load` will need to adjust
the method signature accordingly
```rust
impl AssetLoader for MyLoader {
async fn load<'a>(
&'a self,
// Before:
reader: &'a mut bevy::asset::io::Reader,
// After:
reader: &'a mut dyn bevy::asset::io::Reader,
_: &'a Self::Settings,
load_context: &'a mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> {
}
```
Additionally, implementors of `AssetReader` that return a type
implementing `futures_io::AsyncRead` and `AsyncSeek` might need to
explicitly implement `bevy::asset::io::Reader` for that type.
```rust
impl bevy::asset::io::Reader for MyAsyncReadAndSeek {}
```
# Objective
- Though Rodio will eventually be replaced with Kira for `bevy_audio`,
we should not let it languish.
## Solution
- Bump Rodio to 0.19.
- This is [the
changelog](27f2b42406/CHANGELOG.md (version-0190-2024-06-29)).
No apparent breaking changes, only 1 feature and 1 fix.
## Testing
- Run an example that uses audio, on both native and WASM.
---
## Changelog
- Bumped Rodio to 0.19.
# Objective
- Adopted from #13528.
- `rodio` released 0.18! While we are working on migrating away from it
and towards `kira`, it is still good to keep our dependencies
up-to-date.
## Solution
- Update `Cargo.toml` to depend on `rodio` 0.18.
- #13528 was failing because it didn't update `rodio` for
`wasm32-unknown-unknown` too.
## Testing
- The CI should catch any errors here, but you can also run an audio
example if you want like `spatial_audio_2d`.
---
## Changelog
- Updated `rodio` to 0.18.
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# Objective
- `README.md` is a common file that usually gives an overview of the
folder it is in.
- When on <https://crates.io>, `README.md` is rendered as the main
description.
- Many crates in this repository are lacking `README.md` files, which
makes it more difficult to understand their purpose.
<img width="1552" alt="image"
src="https://github.com/bevyengine/bevy/assets/59022059/78ebf91d-b0c4-4b18-9874-365d6310640f">
- There are also a few inconsistencies with `README.md` files that this
PR and its follow-ups intend to fix.
## Solution
- Create a `README.md` file for all crates that do not have one.
- This file only contains the title of the crate (underscores removed,
proper capitalization, acronyms expanded) and the <https://shields.io>
badges.
- Remove the `readme` field in `Cargo.toml` for `bevy` and
`bevy_reflect`.
- This field is redundant because [Cargo automatically detects
`README.md`
files](https://doc.rust-lang.org/cargo/reference/manifest.html#the-readme-field).
The field is only there if you name it something else, like `INFO.md`.
- Fix capitalization of `bevy_utils`'s `README.md`.
- It was originally `Readme.md`, which is inconsistent with the rest of
the project.
- I created two commits renaming it to `README.md`, because Git appears
to be case-insensitive.
- Expand acronyms in title of `bevy_ptr` and `bevy_utils`.
- In the commit where I created all the new `README.md` files, I
preferred using expanded acronyms in the titles. (E.g. "Bevy Developer
Tools" instead of "Bevy Dev Tools".)
- This commit changes the title of existing `README.md` files to follow
the same scheme.
- I do not feel strongly about this change, please comment if you
disagree and I can revert it.
- Add <https://shields.io> badges to `bevy_time` and `bevy_transform`,
which are the only crates currently lacking them.
---
## Changelog
- Added `README.md` files to all crates missing it.
# 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>
# 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
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
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
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
- 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
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
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
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
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
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
- Make the implementation order consistent between all sources to fit
the order in the trait.
## Solution
- Change the implementation order.
# 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: