# Objective
This PR aims to improve the soundness of `CommandQueue`. In particular it aims to:
- make it sound to store commands that contain padding or uninitialized bytes;
- avoid uses of commands after moving them in the queue's buffer (`std::mem::forget` is technically a use of its argument);
- remove useless checks: `self.bytes.as_mut_ptr().is_null()` is always `false` because even `Vec`s that haven't allocated use a dangling pointer. Moreover the same pointer was used to write the command, so it ought to be valid for reads if it was for writes.
## Solution
- To soundly store padding or uninitialized bytes `CommandQueue` was changed to contain a `Vec<MaybeUninit<u8>>` instead of `Vec<u8>`;
- To avoid uses of the command through `std::mem::forget`, `ManuallyDrop` was used.
## Other observations
While writing this PR I noticed that `CommandQueue` doesn't seem to drop the commands that weren't applied. While this is a pretty niche case (you would have to be manually using `CommandQueue`/`std::mem::swap`ping one), I wonder if it should be documented anyway.
# Objective
Don't allocate memory for Component types known at compile-time. Save a bit of memory.
## Solution
Change `ComponentDescriptor::name` from `String` to `Cow<'static, str>` to use the `&'static str` returned by `std::any::type_name`.
# Objective
`debug_assert!` macros must still compile properly in release mode due to how they're implemented. This is causing release builds to fail.
## Solution
Change them to `assert!` macros inside `#[cfg(debug_assertions)]` blocks.
# Objective
`bevy_reflect` as different kinds of reflected types (each with their own trait), `trait Struct: Reflect`, `trait List: Reflect`, `trait Map: Reflect`, ...
Types that don't fit either of those are called reflect value types, they are opaque and can't be deconstructed further.
`bevy_reflect` can serialize `dyn Reflect` values. Any container types (struct, list, map) get deconstructed and their elements serialized separately, which can all happen without serde being involved ever (happens [here](https://github.com/bevyengine/bevy/blob/main/crates/bevy_reflect/src/serde/ser.rs#L50-L85=)).
The only point at which we require types to be serde-serializable is for *value types* (happens [here](https://github.com/bevyengine/bevy/blob/main/crates/bevy_reflect/src/serde/ser.rs#L104=)).
So reflect array serializing is solved, since arrays are container types which don't require serde.
#1213 also introduced added the `serialize` method and `Serialize` impls for `dyn Array` and `DynamicArray` which use their element's `Reflect::serializable` function. This is 1. unnecessary, because it is not used for array serialization, and 2. annoying for removing the `Serialize` bound on container types, because these impls don't have access to the `TypeRegistry`, so we can't move the serialization code there.
# Solution
Remove these impls and `fn serialize`. It's not used and annoying for other changes.
# Objective
Increase compatibility with a fairly common format of padded spritesheets, in which half the padding value occurs before the first sprite box begins. The original behaviour falls out when `Vec2::ZERO` is used for `offset`.
See below unity screenshot for an example of a spritesheet with padding
![Screen Shot 2022-05-24 at 4 11 49 PM](https://user-images.githubusercontent.com/30442265/170123682-287e5733-b69d-452b-b2e6-46d8d29293fb.png)
## Solution
Tiny change to `crates/bevy_sprite/src/texture_atlas.rs`
## Migration Guide
Calls to `TextureAtlas::from_grid_with_padding` should be modified to include a new parameter, which can be set to `Vec2::ZERO` to retain old behaviour.
```rust
from_grid_with_padding(texture, tile_size, columns, rows, padding)
|
V
from_grid_with_padding(texture, tile_size, columns, rows, padding, Vec2::ZERO)
```
Co-authored-by: FraserLee <30442265+FraserLee@users.noreply.github.com>
# Objective
Currently, `FromReflect` makes a couple assumptions:
* Ignored fields must implement `Default`
* Active fields must implement `FromReflect`
* The reflected must be fully populated for active fields (can't use an empty `DynamicStruct`)
However, one or both of these requirements might be unachievable, such as for external types. In these cases, it might be nice to tell `FromReflect` to use a custom default.
## Solution
Added the `#[reflect(default)]` derive helper attribute. This attribute can be applied to any field (ignored or not) and will allow a default value to be specified in place of the regular `from_reflect()` call.
It takes two forms: `#[reflect(default)]` and `#[reflect(default = "some_func")]`. The former specifies that `Default::default()` should be used while the latter specifies that `some_func()` should be used. This is pretty much [how serde does it](https://serde.rs/field-attrs.html#default).
### Example
```rust
#[derive(Reflect, FromReflect)]
struct MyStruct {
// Use `Default::default()`
#[reflect(default)]
foo: String,
// Use `get_bar_default()`
#[reflect(default = "get_bar_default")]
#[reflect(ignore)]
bar: usize,
}
fn get_bar_default() -> usize {
123
}
```
### Active Fields
As an added benefit, this also allows active fields to be completely missing from their dynamic object. This is because the attribute tells `FromReflect` how to handle missing active fields (it still tries to use `from_reflect` first so the `FromReflect` trait is still required).
```rust
let dyn_struct = DynamicStruct::default();
// We can do this without actually including the active fields since they have `#[reflect(default)]`
let my_struct = <MyStruct as FromReflect>::from_reflect(&dyn_struct);
```
### Container Defaults
Also, with the addition of #3733, people will likely start adding `#[reflect(Default)]` to their types now. Just like with the fields, we can use this to mark the entire container as "defaultable". This grants us the ability to completely remove the field markers altogether if our type implements `Default` (and we're okay with fields using that instead of their own `Default` impls):
```rust
#[derive(Reflect, FromReflect)]
#[reflect(Default)]
struct MyStruct {
foo: String,
#[reflect(ignore)]
bar: usize,
}
impl Default for MyStruct {
fn default() -> Self {
Self {
foo: String::from("Hello"),
bar: 123,
}
}
}
// Again, we can now construct this from nothing pretty much
let dyn_struct = DynamicStruct::default();
let my_struct = <MyStruct as FromReflect>::from_reflect(&dyn_struct);
```
Now if _any_ field is missing when using `FromReflect`, we simply fallback onto the container's `Default` implementation.
This behavior can be completely overridden on a per-field basis, of course, by simply defining those same field attributes like before.
### Related
* #3733
* #1395
* #2377
---
## Changelog
* Added `#[reflect(default)]` field attribute for `FromReflect`
* Allows missing fields to be given a default value when using `FromReflect`
* `#[reflect(default)]` - Use the field's `Default` implementation
* `#[reflect(default = "some_fn")]` - Use a custom function to get the default value
* Allow `#[reflect(Default)]` to have a secondary usage as a container attribute
* Allows missing fields to be given a default value based on the container's `Default` impl when using `FromReflect`
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
- Add an `ExtractResourcePlugin` for convenience and consistency
## Solution
- Add an `ExtractResourcePlugin` similar to `ExtractComponentPlugin` but for ECS `Resource`s. The system that is executed simply clones the main world resource into a render world resource, if and only if the main world resource was either added or changed since the last execution of the system.
- Add an `ExtractResource` trait with a `fn extract_resource(res: &Self) -> Self` function. This is used by the `ExtractResourcePlugin` to extract the resource
- Add a derive macro for `ExtractResource` on a `Resource` with the `Clone` trait, that simply returns `res.clone()`
- Use `ExtractResourcePlugin` wherever both possible and appropriate
This was first done in 7b4e3a5, but was then reverted when the new
renderer for 0.6 was merged (ffecb05).
I'm assuming it was simply a mistake when merging.
# Objective
- Same as #2740, I think it was reverted by mistake when merging.
> # Objective
>
> - Make it easy to use HexColorError with `thiserror`, i.e. converting it into other error types.
>
> Makes this possible:
>
> ```rust
> #[derive(Debug, thiserror::Error)]
> pub enum LdtkError {
> #[error("An error occured while deserializing")]
> Json(#[from] serde_json::Error),
> #[error("An error occured while parsing a color")]
> HexColor(#[from] bevy::render::color::HexColorError),
> }
> ```
>
> ## Solution
>
> - Derive thiserror::Error the same way we do elsewhere (see query.rs for instance)
# Objective
- Higher order system could not be created by users.
- However, a simple change to `SystemParamFunction` allows this.
- Higher order systems in this case mean functions which return systems created using other systems, such as `chain` (which is basically equivalent to map)
## Solution
- Change `SystemParamFunction` to be a safe abstraction over `FnMut([In<In>,] ...params)->Out`.
- Note that I believe `SystemParamFunction` should not have been counted as part of our public api before this PR.
- This is because its only use was an unsafe function without an actionable safety comment.
- The safety comment was basically 'call this within bevy code'.
- I also believe that there are no external users in its current form.
- A quick search on Google and in the discord confirmed this.
## See also
- https://github.com/bevyengine/bevy/pull/4666, which uses this and subsumes the example here
---
## Changelog
### Added
- `SystemParamFunction`, which can be used to create higher order systems.
# Objective
Fixes#4353. Fixes#4431. Picks up fixes for a panic for `gilrs` when `getGamepads()` is not available.
## Solution
Update the `gilrs` to `v0.9.0`. Changelog can be seen here: dba36f9186
EDIT: Updated `uuid` to 1.1 to avoid duplicate dependencies. Added `nix`'s two dependencies as exceptions until `rodio` updates their deps.
# Objective
- Add Vertex Color support to 2D meshes and ColorMaterial. This extends the work from #4528 (which in turn builds on the excellent tangent handling).
## Solution
- Added `#ifdef` wrapped support for vertex colors in the 2D mesh shader and `ColorMaterial` shader.
- Added an example, `mesh2d_vertex_color_texture` to demonstrate it in action.
![image](https://user-images.githubusercontent.com/14896751/169530930-6ae0c6be-2f69-40e3-a600-ba91d7178bc3.png)
---
## Changelog
- Added optional (ifdef wrapped) vertex color support to the 2dmesh and color material systems.
# Objective
- Sometimes, people might load an asset as one type, then use it with an `Asset`s for a different type.
- See e.g. #4784.
- This is especially likely with the Gltf types, since users may not have a clear conceptual model of what types the assets will be.
- We had an instance of this ourselves, in the `scene_viewer` example
## Solution
- Make `Assets::get` require a type safe handle.
---
## Changelog
### Changed
- `Assets::<T>::get` and `Assets::<T>::get_mut` now require that the passed handles are `Handle<T>`, improving the type safety of handles.
### Added
- `HandleUntyped::typed_weak`, a helper function for creating a weak typed version of an exisitng `HandleUntyped`.
## Migration Guide
`Assets::<T>::get` and `Assets::<T>::get_mut` now require that the passed handles are `Handle<T>`, improving the type safety of handles. If you were previously passing in:
- a `HandleId`, use `&Handle::weak(id)` instead, to create a weak handle. You may have been able to store a type safe `Handle` instead.
- a `HandleUntyped`, use `&handle_untyped.typed_weak()` to create a weak handle of the specified type. This is most likely to be the useful when using [load_folder](https://docs.rs/bevy_asset/latest/bevy_asset/struct.AssetServer.html#method.load_folder)
- a `Handle<U>` of of a different type, consider whether this is the correct handle type to store. If it is (i.e. the same handle id is used for multiple different Asset types) use `Handle::weak(handle.id)` to cast to a different type.
# Objective
Fixes#4791. `ParallelExecutor` inserts a default `CompteTaskPool` if there isn't one stored as a resource, including when it runs on a different world. When spawning the render sub-app, the main world's `ComputeTaskPool` is not cloned and inserted into the render app's, which causes a second `ComputeTaskPool` with the default configuration to be spawned. This results in an excess number of threads being spawned.
## Solution
Copy the task pools from the main world to the subapps upon creating them.
## Alternative
An alternative to this would be to make the task pools global, as seen in #2250 or bevyengine/rfcs#54.
# Objective
Resolves#4753
## Solution
Using rust doc I added documentation to the struct. Decided to not provide an example in the doc comment but instead refer to the example file that shows the usage.
# Objective
Use less memory to store SparseSet components.
## Solution
Change `ComponentSparseSet` to only use `Entity::id` in it's key internally, and change the usize value in it's SparseArray to use u32 instead, as it cannot have more than u32::MAX live entities stored at once.
This should reduce the overhead of storing components in sparse set storage by 50%.
# Objective
Fixes#3183. Requiring a `&TaskPool` parameter is sort of meaningless if the only correct one is to use the one provided by `Res<ComputeTaskPool>` all the time.
## Solution
Have `QueryState` save a clone of the `ComputeTaskPool` which is used for all `par_for_each` functions.
~~Adds a small overhead of the internal `Arc` clone as a part of the startup, but the ergonomics win should be well worth this hardly-noticable overhead.~~
Updated the docs to note that it will panic the task pool is not present as a resource.
# Future Work
If https://github.com/bevyengine/rfcs/pull/54 is approved, we can replace these resource lookups with a static function call instead to get the `ComputeTaskPool`.
---
## Changelog
Removed: The `task_pool` parameter of `Query(State)::par_for_each(_mut)`. These calls will use the `World`'s `ComputeTaskPool` resource instead.
## Migration Guide
The `task_pool` parameter for `Query(State)::par_for_each(_mut)` has been removed. Remove these parameters from all calls to these functions.
Before:
```rust
fn parallel_system(
task_pool: Res<ComputeTaskPool>,
query: Query<&MyComponent>,
) {
query.par_for_each(&task_pool, 32, |comp| {
...
});
}
```
After:
```rust
fn parallel_system(query: Query<&MyComponent>) {
query.par_for_each(32, |comp| {
...
});
}
```
If using `Query(State)` outside of a system run by the scheduler, you may need to manually configure and initialize a `ComputeTaskPool` as a resource in the `World`.
# Objective
The `ComponentId` in `Column` is redundant as it's stored in parallel in the surrounding `SparseSet` all the time.
## Solution
Remove it. Add `SparseSet::iter(_mut)` to parallel `HashMap::iter(_mut)` to allow iterating pairs of columns and their IDs.
---
## Changelog
Added: `SparseSet::iter` and `SparseSet::iter_mut`.
# Objective
- Rebase of #3159.
- Fixes https://github.com/bevyengine/bevy/issues/3156
- add #[inline] to single related functions so that they matches with other function defs
## Solution
* added functions to QueryState
* get_single_unchecked_manual
* get_single_unchecked
* get_single
* get_single_mut
* single
* single_mut
* make Query::get_single use QueryState::get_single_unchecked_manual
* added #[inline]
---
## Changelog
### Added
Functions `QueryState::single`, `QueryState::get_single`, `QueryState::single_mut`, `QueryState::get_single_mut`, `QueryState::get_single_unchecked`, `QueryState::get_single_unchecked_manual`.
### Changed
`QuerySingleError` is now in the `state` module.
## Migration Guide
Change `query::QuerySingleError` to `state::QuerySingleError`
Co-authored-by: 2ne1ugly <chattermin@gmail.com>
Co-authored-by: 2ne1ugly <47616772+2ne1ugly@users.noreply.github.com>
# Objective
the code in these fns are always identical so stop having two functions
## Solution
make them the same function
---
## Changelog
change `matches_archetype` and `matches_table` to `fn matches_component_set(&self, &SparseArray<ComponentId, usize>) -> bool` then do extremely boring updating of all `FetchState` impls
## Migration Guide
- move logic of `matches_archetype` and `matches_table` into `matches_component_set` in any manual `FetchState` impls
# Objective
Debugging reflected types can be somewhat frustrating since all `dyn Reflect` trait objects return something like `Reflect(core::option::Option<alloc::string::String>)`.
It would be much nicer to be able to see the actual value— or even use a custom `Debug` implementation.
## Solution
Added `Reflect::debug` which allows users to customize the debug output. It sets defaults for all `ReflectRef` subtraits and falls back to `Reflect(type_name)` if no `Debug` implementation was registered.
To register a custom `Debug` impl, users can add `#[reflect(Debug)]` like they can with other traits.
### Example
Using the following structs:
```rust
#[derive(Reflect)]
pub struct Foo {
a: usize,
nested: Bar,
#[reflect(ignore)]
_ignored: NonReflectedValue,
}
#[derive(Reflect)]
pub struct Bar {
value: Vec2,
tuple_value: (i32, String),
list_value: Vec<usize>,
// We can't determine debug formatting for Option<T> yet
unknown_value: Option<String>,
custom_debug: CustomDebug
}
#[derive(Reflect)]
#[reflect(Debug)]
struct CustomDebug;
impl Debug for CustomDebug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "This is a custom debug!")
}
}
pub struct NonReflectedValue {
_a: usize,
}
```
We can do:
```rust
let value = Foo {
a: 1,
_ignored: NonReflectedValue { _a: 10 },
nested: Bar {
value: Vec2::new(1.23, 3.21),
tuple_value: (123, String::from("Hello")),
list_value: vec![1, 2, 3],
unknown_value: Some(String::from("World")),
custom_debug: CustomDebug
},
};
let reflected_value: &dyn Reflect = &value;
println!("{:#?}", reflected_value)
```
Which results in:
```rust
Foo {
a: 2,
nested: Bar {
value: Vec2(
1.23,
3.21,
),
tuple_value: (
123,
"Hello",
),
list_value: [
1,
2,
3,
],
unknown_value: Reflect(core::option::Option<alloc::string::String>),
custom_debug: This is a custom debug!,
},
}
```
Notice that neither `Foo` nor `Bar` implement `Debug`, yet we can still deduce it. This might be a concern if we're worried about leaking internal values. If it is, we might want to consider a way to exclude fields (possibly with a `#[reflect(hide)]` macro) or make it purely opt in (as opposed to the default implementation automatically handled by ReflectRef subtraits).
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
Even if bevy itself does not provide any builtin scripting or modding APIs, it should have the foundations for building them yourself.
For that it should be enough to have APIs that are not tied to the actual rust types with generics, but rather accept `ComponentId`s and `bevy_ptr` ptrs.
## Solution
Add the following APIs to bevy
```rust
fn EntityRef::get_by_id(ComponentId) -> Option<Ptr<'w>>;
fn EntityMut::get_by_id(ComponentId) -> Option<Ptr<'_>>;
fn EntityMut::get_mut_by_id(ComponentId) -> Option<MutUntyped<'_>>;
fn World::get_resource_by_id(ComponentId) -> Option<Ptr<'_>>;
fn World::get_resource_mut_by_id(ComponentId) -> Option<MutUntyped<'_>>;
// Safety: `value` must point to a valid value of the component
unsafe fn World::insert_resource_by_id(ComponentId, value: OwningPtr);
fn ComponentDescriptor::new_with_layout(..) -> Self;
fn World::init_component_with_descriptor(ComponentDescriptor) -> ComponentId;
```
~~This PR would definitely benefit from #3001 (lifetime'd pointers) to make sure that the lifetimes of the pointers are valid and the my-move pointer in `insert_resource_by_id` could be an `OwningPtr`, but that can be adapter later if/when #3001 is merged.~~
### Not in this PR
- inserting components on entities (this is very tied to types with bundles and the `BundleInserter`)
- an untyped version of a query (needs good API design, has a large implementation complexity, can be done in a third-party crate)
Co-authored-by: Jakob Hellermann <hellermann@sipgate.de>
# Objective
One way to avoid texture atlas bleeding is to ensure that every vertex is
placed at an integer pixel coordinate. This is a particularly appealing
solution for regular structures like tile maps.
Doing so is currently harder than necessary when the WindowSize scaling
mode and Center origin are used: For odd window width or height, the
origin of the coordinate system is placed in the middle of a pixel at
some .5 offset.
## Solution
Avoid this issue by rounding the half width and height values.
Updates the requirements on [tracing-tracy](https://github.com/nagisa/rust_tracy_client) to permit the latest version.
<details>
<summary>Commits</summary>
<ul>
<li><a href="13b335a710"><code>13b335a</code></a> Remove ability to disable the client at runtime</li>
<li><a href="69e44977ee"><code>69e4497</code></a> The upgrades to 0.8.1</li>
<li><a href="c204b60c7a"><code>c204b60</code></a> Cancel the old test runs</li>
<li><a href="939bd04c1c"><code>939bd04</code></a> Remove the thread initialization calls</li>
<li><a href="7024e776bb"><code>7024e77</code></a> Update Tracy client bindings to v0.8.1</li>
<li><a href="5c54baa244"><code>5c54baa</code></a> tracy-client 0.12.7</li>
<li><a href="f183050b20"><code>f183050</code></a> Non-allocating <code>span!</code> macro</li>
<li><a href="15936ea751"><code>15936ea</code></a> tracy-client 0.12.6</li>
<li><a href="26d0c50542"><code>26d0c50</code></a> Relax literal the requirement of the create_plot macro so that it can be used...</li>
<li>See full diff in <a href="https://github.com/nagisa/rust_tracy_client/compare/tracing-tracy-v0.8.0...tracing-tracy-v0.9.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 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>
# Objective
- Make bevy_app's optional bevy_reflect dependency actually optional
- Because bevy_ecs has a default dependency on bevy_reflect, bevy_app includes bevy_reflect transitively even with default-features=false, despite the optional dependency indicating that it was intended to be able to leave out bevy_reflect.
## Solution
- Make bevy_app not enable bevy_ecs's default features, and then use [the `dep:` syntax](https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies) introduced in 1.60 to make the default bevy_reflect feature enable bevy_ecs's bevy_reflect feature/dependency.
---
## Changelog
- bevy_app no longer enables bevy_ecs's `bevy_reflect` feature when included without its own `bevy_reflect` feature (which is on by default).
# Objective
Reduce the catch-all grab-bag of functionality in bevy_core by minimally splitting off time functionality into bevy_time. Functionality like that provided by #3002 would increase the complexity of bevy_time, so this is a good candidate for pulling into its own unit.
A step in addressing #2931 and splitting bevy_core into more specific locations.
## Solution
Pull the time module of bevy_core into a new crate, bevy_time.
# Migration guide
- Time related types (e.g. `Time`, `Timer`, `Stopwatch`, `FixedTimestep`, etc.) should be imported from `bevy::time::*` rather than `bevy::core::*`.
- If you were adding `CorePlugin` manually, you'll also want to add `TimePlugin` from `bevy::time`.
- The `bevy::core::CorePlugin::Time` system label is replaced with `bevy::time::TimeSystem`.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- As noticed in #4333 by @x-52, the exact purpose and logic of `HasRawWIndowHandleWrapper` is unclear
- Unfortunately, there are rather good reasons why this design is needed (and why we can't just `impl HasRawWindowHandle for RawWindowHandleWrapper`
## Solution
- Rename `HasRawWindowHandleWrapper` to `ThreadLockedRawWindowHandleWrapper`, reflecting the primary distinction
- Document how this design is intended to be used
- Leave comments explaining why this design must exist
## Migration Guide
- renamed `HasRawWindowHandleWrapper` to `ThreadLockedRawWindowHandleWrapper`
# Objective
Make the function consistent with returned values and `as_hsla` method
Fixes#4826
## Solution
- Rename the method
## Migration Guide
- Rename the method
Currently Bevy's web canvases are "fixed size". They are manually set to specific dimensions. This might be fine for some games and website layouts, but for sites with flexible layouts, or games that want to "fill" the browser window, Bevy doesn't provide the tools needed to make this easy out of the box.
There are third party plugins like [bevy-web-resizer](https://github.com/frewsxcv/bevy-web-resizer/) that listen for window resizes, take the new dimensions, and resize the winit window accordingly. However this only covers a subset of cases and this is common enough functionality that it should be baked into Bevy.
A significant motivating use case here is the [Bevy WASM Examples page](https://bevyengine.org/examples/). This scales the canvas to fit smaller windows (such as mobile). But this approach both breaks winit's mouse events and removes pixel-perfect rendering (which means we might be rendering too many or too few pixels). https://github.com/bevyengine/bevy-website/issues/371
In an ideal world, winit would support this behavior out of the box. But unfortunately that seems blocked for now: https://github.com/rust-windowing/winit/pull/2074. And it builds on the ResizeObserver api, which isn't supported in all browsers yet (and is only supported in very new versions of the popular browsers).
While we wait for a complete winit solution, I've added a `fit_canvas_to_parent` option to WindowDescriptor / Window, which when enabled will listen for window resizes and resize the Bevy canvas/window to fit its parent element. This enables users to scale bevy canvases using arbitrary CSS, by "inheriting" their parents' size. Note that the wrapper element _is_ required because winit overrides the canvas sizing with absolute values on each resize.
There is one limitation worth calling out here: while the majority of canvas resizes will be triggered by window resizes, modifying element layout at runtime (css animations, javascript-driven element changes, dev-tool-injected changes, etc) will not be detected here. I'm not aware of a good / efficient event-driven way to do this outside of the ResizeObserver api. In practice, window-resize-driven canvas resizing should cover the majority of use cases. Users that want to actively poll for element resizes can just do that (or we can build another feature and let people choose based on their specific needs).
I also took the chance to make a couple of minor tweaks:
* Made the `canvas` window setting available on all platforms. Users shouldn't need to deal with cargo feature selection to support web scenarios. We can just ignore the value on non-web platforms. I added documentation that explains this.
* Removed the redundant "initial create windows" handler. With the addition of the code in this pr, the code duplication was untenable.
This enables a number of patterns:
## Easy "fullscreen window" mode for the default canvas
The "parent element" defaults to the `<body>` element.
```rust
app
.insert_resource(WindowDescriptor {
fit_canvas_to_parent: true,
..default()
})
```
And CSS:
```css
html, body {
margin: 0;
height: 100%;
}
```
## Fit custom canvas to "wrapper" parent element
```rust
app
.insert_resource(WindowDescriptor {
fit_canvas_to_parent: true,
canvas: Some("#bevy".to_string()),
..default()
})
```
And the HTML:
```html
<div style="width: 50%; height: 100%">
<canvas id="bevy"></canvas>
</div>
```
# Objective
Allow `Box<dyn Reflect>` to be converted into a `Box<dyn MyTrait>` using the `#[reflect_trait]` macro. The other methods `get` and `get_mut` only provide a reference to the reflected object.
## Solution
Add a `get_boxed` method to the `Reflect***` struct generated by the `#[reflect_trait]` macro. This method takes in a `Box<dyn Reflect>` and returns a `Box<dyn MyTrait>`.
Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
# Objective
Fixes#4657
Example code that wasnt panic'ing before this PR (and so was unsound):
```rust
#[test]
#[should_panic = "error[B0001]"]
fn option_has_no_filter_with() {
fn sys(_1: Query<(Option<&A>, &mut B)>, _2: Query<&mut B, Without<A>>) {}
let mut world = World::default();
run_system(&mut world, sys);
}
#[test]
#[should_panic = "error[B0001]"]
fn any_of_has_no_filter_with() {
fn sys(_1: Query<(AnyOf<(&A, ())>, &mut B)>, _2: Query<&mut B, Without<A>>) {}
let mut world = World::default();
run_system(&mut world, sys);
}
#[test]
#[should_panic = "error[B0001]"]
fn or_has_no_filter_with() {
fn sys(_1: Query<&mut B, Or<(With<A>, With<B>)>>, _2: Query<&mut B, Without<A>>) {}
let mut world = World::default();
run_system(&mut world, sys);
}
```
## Solution
- Only add the intersection of `with`/`without` accesses of all the elements in `Or/AnyOf` to the world query's `FilteredAccess<ComponentId>` instead of the union.
- `Option`'s fix can be thought of the same way since its basically `AnyOf<T, ()>` but its impl is just simpler as `()` has no `with`/`without` accesses
---
## Changelog
- `Or`/`AnyOf`/`Option` will now report more query conflicts in order to fix unsoundness
## Migration Guide
- If you are now getting query conflicts from `Or`/`AnyOf`/`Option` rip to you and ur welcome for it now being caught
# Objective
We have duplicated code between `QueryIter` and `QueryIterationCursor`. Reuse that code.
## Solution
- Reuse `QueryIterationCursor` inside `QueryIter`.
- Slim down `QueryIter` by removing the `&'w World`. It was only being used by the `size_hint` and `ExactSizeIterator` impls, which can use the QueryState and &Archetypes in the type already.
- Benchmark to make sure there is no significant regression.
Relevant benchmark results seem to show that there is no tangible difference between the two. Everything seems to be either identical or within a workable margin of error here.
```
group embed-cursor main
----- ------------ ----
fragmented_iter/base 1.00 387.4±19.70ns ? ?/sec 1.07 413.1±27.95ns ? ?/sec
many_maps_iter 1.00 27.3±0.22ms ? ?/sec 1.00 27.4±0.10ms ? ?/sec
simple_iter/base 1.00 13.8±0.07µs ? ?/sec 1.00 13.7±0.17µs ? ?/sec
simple_iter/sparse 1.00 61.9±0.37µs ? ?/sec 1.00 62.2±0.64µs ? ?/sec
simple_iter/system 1.00 13.7±0.34µs ? ?/sec 1.00 13.7±0.10µs ? ?/sec
sparse_fragmented_iter/base 1.00 11.0±0.54ns ? ?/sec 1.03 11.3±0.48ns ? ?/sec
world_query_iter/50000_entities_sparse 1.08 105.0±2.68µs ? ?/sec 1.00 97.5±2.18µs ? ?/sec
world_query_iter/50000_entities_table 1.00 27.3±0.13µs ? ?/sec 1.00 27.3±0.37µs ? ?/sec
```
# Objective
Quick followup to #4712.
While updating some [other PRs](https://github.com/bevyengine/bevy/pull/4218), I realized the `ReflectTraits` struct could be improved. The issue with the current implementation is that `ReflectTraits::get_xxx_impl(...)` returns just the _logic_ to the corresponding `Reflect` trait method, rather than the entire function.
This makes it slightly more annoying to manage since the variable names need to be consistent across files. For example, `get_partial_eq_impl` uses a `value` variable. But the name "value" isn't defined in the `get_partial_eq_impl` method, it's defined in three other methods in a completely separate file.
It's not likely to cause any bugs if we keep it as it is since differing variable names will probably just result in a compile error (except in very particular cases). But it would be useful to someone who wanted to edit/add/remove a method.
## Solution
Made `get_hash_impl`, `get_partial_eq_impl` and `get_serialize_impl` return the entire method implementation for `reflect_hash`, `reflect_partial_eq`, and `serializable`, respectively.
As a result of this, those three `Reflect` methods were also given default implementations. This was fairly simple to do since all three could just be made to return `None`.
---
## Changelog
* Small cleanup/refactor to `ReflectTraits` in `bevy_reflect_derive`
* Gave `Reflect::reflect_hash`, `Reflect::reflect_partial_eq`, and `Reflect::serializable` default implementations
# Objective
Support returning data out of with_children to enable the use case of changing the parent commands with data created inside the child builder.
## Solution
Change the with_children closure to return T.
Closes https://github.com/bevyengine/bevy/pull/2817.
---
## Changelog
`BuildChildren::add_children` was added with the ability to return data to use outside the closure (for spawning a new child builder on a returned entity for example).
# Objective
- We do a lot of function pointer calls in a hot loop (clearing entities in render). This is slow, since calling function pointers cannot be optimised out. We can avoid that in the cases where the function call is a no-op.
- Alternative to https://github.com/bevyengine/bevy/pull/2897
- On my machine, in `many_cubes`, this reduces dropping time from ~150μs to ~80μs.
## Solution
- Make `drop` in `BlobVec` an `Option`, recording whether the given drop impl is required or not.
- Note that this does add branching in some cases - we could consider splitting this into two fields, i.e. unconditionally call the `drop` fn pointer.
- My intuition of how often types stored in `World` should have non-trivial drops makes me think that would be slower, however.
N.B. Even once this lands, we should still test having a 'drop_multiple' variant - for types with a real `Drop` impl, the current implementation is definitely optimal.
# Objective
- Part of the splitting process of #3692.
## Solution
- Document `keyboard.rs` inside of `bevy_input`.
Co-authored-by: KDecay <KDecayMusic@protonmail.com>
# Objective
- Transform propogation could stack overflow when there was a cycle.
- I think https://github.com/bevyengine/bevy/pull/4203 would use all available memory.
## Solution
- Make sure that the child entity's `Parent`s are their parents.
This is also required for when parallelising, although as noted in the comment, the naïve solution would be UB.
(The best way to fix this would probably be an `&mut UnsafeCell<T>` `WorldQuery`, or wrapper type with the same effect)
# Objective
`bevy_ptr` works just fine without `std`. Mark it as `no_std`. This should generally be useful for non-bevy use cases, but it also marginally speeds up compilation by allowing the crate to compile without loading the std-lib.
## Solution
Replace `std` with `core`. Added `#![no_std]` to the crate and to the crate's tags.
Also added a missing `#![warn(missing_docs)]` that the other crates have.
# Objective
- Fixes#4456
## Solution
- Removed the `near` and `far` fields from the camera and the views.
---
## Changelog
- Removed the `near` and `far` fields from the camera and the views.
- Removed the `ClusterFarZMode::CameraFarPlane` far z mode.
## Migration Guide
- Cameras no longer accept near and far values during initialization
- `ClusterFarZMode::Constant` should be used with the far value instead of `ClusterFarZMode::CameraFarPlane`
# Objective
`bevy_ecs` assumes that `u32 as usize` is a lossless operation and in a few cases relies on this for soundness and correctness. The only platforms that Rust compiles to where this invariant is broken are 16-bit systems.
A very clear example of this behavior is in the SparseSetIndex impl for Entity, where it converts a u32 into a usize to act as an index. If usize is 16-bit, the conversion will overflow and provide the caller with the wrong index. This can easily result in previously unforseen aliased mutable borrows (i.e. Query::get_many_mut).
## Solution
Explicitly fail compilation on 16-bit platforms instead of introducing UB.
Properly supporting 16-bit systems will likely need a workable use case first.
---
## Changelog
Removed: Ability to compile `bevy_ecs` on 16-bit platforms.
## Migration Guide
`bevy_ecs` will now explicitly fail to compile on 16-bit platforms. If this is required, there is currently no alternative. Please file an issue (https://github.com/bevyengine/bevy/issues) to help detail your use case.
# Objective
> ℹ️ **Note**: This is a rebased version of #2383. A large portion of it has not been touched (only a few minor changes) so that any additional discussion may happen here. All credit should go to @NathanSWard for their work on the original PR.
- Currently reflection is not supported for arrays.
- Fixes#1213
## Solution
* Implement reflection for arrays via the `Array` trait.
* Note, `Array` is different from `List` in the way that you cannot push elements onto an array as they are statically sized.
* Now `List` is defined as a sub-trait of `Array`.
---
## Changelog
* Added the `Array` reflection trait
* Allows arrays up to length 32 to be reflected via the `Array` trait
## Migration Guide
* The `List` trait now has the `Array` supertrait. This means that `clone_dynamic` will need to specify which version to use:
```rust
// Before
let cloned = my_list.clone_dynamic();
// After
let cloned = List::clone_dynamic(&my_list);
```
* All implementers of `List` will now need to implement `Array` (this mostly involves moving the existing methods to the `Array` impl)
Co-authored-by: NathanW <nathansward@comcast.net>
Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
# Objective
- It's pretty common to want to check if an EventReader has received one or multiple events while also needing to consume the iterator to "clear" the EventReader.
- The current approach is to do something like `events.iter().count() > 0` or `events.iter().last().is_some()`. It's not immediately obvious that the purpose of that is to consume the events and check if there were any events. My solution doesn't really solve that part, but it encapsulates the pattern.
## Solution
- Add a `.clear()` method that consumes the iterator.
- It takes the EventReader by value to make sure it isn't used again after it has been called.
---
## Migration Guide
Not a breaking change, but if you ever found yourself in a situation where you needed to consume the EventReader and check if there was any events you can now use
```rust
fn system(events: EventReader<MyEvent>) {
if !events.is_empty {
events.clear();
// Process the fact that one or more event was received
}
}
```
Co-authored-by: Charles <IceSentry@users.noreply.github.com>
# Objective
`Query::par_for_each` and it's variants do not show up when profiling using `tracy` or other profilers. Failing to show the impact of changing batch size, the overhead of scheduling tasks, overall thread utilization, etc. other than the effect on the surrounding system.
## Solution
Add a child span that is entered on every spawned task.
Example view of the results in `tracy` using a modified `parallel_query`:
![image](https://user-images.githubusercontent.com/3137680/167560036-626bd091-344b-4664-b323-b692f4f16084.png)
---
## Changelog
Added: `tracing` spans for `Query::par_for_each` and its variants. Spans should now be visible for all
# Objective
The `bevy_reflect_derive` crate is not the cleanest or easiest to follow/maintain. The `lib.rs` file is especially difficult with over 1000 lines of code written in a confusing order. This is just a result of growth within the crate and it would be nice to clean it up for future work.
## Solution
Split `bevy_reflect_derive` into many more submodules. The submodules include:
* `container_attributes` - Code relating to container attributes
* `derive_data` - Code relating to reflection-based derive metadata
* `field_attributes` - Code relating to field attributes
* `impls` - Code containing actual reflection implementations
* `reflect_value` - Code relating to reflection-based value metadata
* `registration` - Code relating to type registration
* `utility` - General-purpose utility functions
This leaves the `lib.rs` file to contain only the public macros, making it much easier to digest (and fewer than 200 lines).
By breaking up the code into smaller modules, we make it easier for future contributors to find the code they're looking for or identify which module best fits their own additions.
### Metadata Structs
This cleanup also adds two big metadata structs: `ReflectFieldAttr` and `ReflectDeriveData`. The former is used to store all attributes for a struct field (if any). The latter is used to store all metadata for struct-based derive inputs.
Both significantly reduce code duplication and make editing these macros much simpler. The tradeoff is that we may collect more metadata than needed. However, this is usually a small thing (such as checking for attributes when they're not really needed or creating a `ReflectFieldAttr` for every field regardless of whether they actually have an attribute).
We could try to remove these tradeoffs and squeeze some more performance out, but doing so might come at the cost of developer experience. Personally, I think it's much nicer to create a `ReflectFieldAttr` for every field since it means I don't have to do two `Option` checks. Others may disagree, though, and so we can discuss changing this either in this PR or in a future one.
### Out of Scope
_Some_ documentation has been added or improved, but ultimately good docs are probably best saved for a dedicated PR.
## 🔍 Focus Points (for reviewers)
I know it's a lot to sift through, so here is a list of **key points for reviewers**:
- The following files contain code that was mostly just relocated:
- `reflect_value.rs`
- `registration.rs`
- `container_attributes.rs` was also mostly moved but features some general cleanup (reducing nesting, removing hardcoded strings, etc.) and lots of doc comments
- Most impl logic was moved from `lib.rs` to `impls.rs`, but they have been significantly modified to use the new `ReflectDeriveData` metadata struct in order to reduce duplication.
- `derive_data.rs` and `field_attributes.rs` contain almost entirely new code and should probably be given the most attention.
- Likewise, `from_reflect.rs` saw major changes using `ReflectDeriveData` so it should also be given focus.
- There was no change to the `lib.rs` exports so the end-user API should be the same.
## Prior Work
This task was initially tackled by @NathanSWard in #2377 (which was closed in favor of this PR), so hats off to them for beating me to the punch by nearly a year!
---
## Changelog
* **[INTERNAL]** Split `bevy_reflect_derive` into smaller submodules
* **[INTERNAL]** Add `ReflectFieldAttr`
* **[INTERNAL]** Add `ReflectDeriveData`
* Add `BevyManifest::get_path_direct()` method (`bevy_macro_utils`)
Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
# Objective
The frame marker event was emitted in the loop of presenting all the windows. This would mark the frame as finished multiple times if more than one window is used.
## Solution
Move the frame marker to after the `for`-loop, so that it gets executed only once.
# Objective
- The code in `events.rs` was a bit messy. There was lots of duplication between `EventReader` and `ManualEventReader`, and the state management code is not needed.
## Solution
- Clean it up.
## Future work
Should we remove the type parameter from `ManualEventReader`?
It doesn't have any meaning outside of its source `Events`. But there's no real reason why it needs to have a type parameter - it's just plain data. I didn't remove it yet to keep the type safety in some of the users of it (primarily related to `&mut World` usage)
# Objective
Relevant issue: #4474
Currently glam types implement Reflect as a value, which is problematic for reflection, making scripting/editor work much more difficult. This PR re-implements them as structs.
## Solution
Added a new proc macro, `impl_reflect_struct`, which replaces `impl_reflect_value` and `impl_from_reflect_value` for glam types. This macro could also be used for other types, but I don't know of any that would require it. It's specifically useful for foreign types that cannot derive Reflect normally.
---
## Changelog
### Added
- `impl_reflect_struct` proc macro
### Changed
- Glam reflect impls have been replaced with `impl_reflect_struct`
- from_reflect's `impl_struct` altered to take an optional custom constructor, allowing non-default non-constructible foreign types to use it
- Calls to `impl_struct` altered to conform to new signature
- Altered glam types (All vec/mat combinations) have a different serialization structure, as they are reflected differently now.
## Migration Guide
This will break altered glam types serialized to RON scenes, as they will expect to be serialized/deserialized as structs rather than values now. A future PR to add custom serialization for non-value types is likely on the way to restore previous behavior. Additionally, calls to `impl_struct` must add a `None` parameter to the end of the call to restore previous behavior.
Co-authored-by: PROMETHIA-27 <42193387+PROMETHIA-27@users.noreply.github.com>
Required for https://github.com/bevyengine/bevy/pull/4402.
# Objective
- derived `SystemParam` implementations were never `ReadOnlySystemParamFetch`
- We want them to be, e.g. for `EventReader`
## Solution
- If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
# Objective
- (Eventually) reduce noise in reporting access conflicts between unordered systems.
- `SystemStage` only looks at unfiltered `ComponentId` access, any conflicts reported are potentially `false`.
- the systems could still be accessing disjoint archetypes
- Comparing systems' filtered access sets can maybe avoid that (for statically known component types).
- #4204
## Solution
- Modify `SparseSetIndex` trait to require `PartialEq`, `Eq`, and `Hash` (all internal types except `BundleId` already did).
- Add `is_compatible` and `get_conflicts` methods to `FilteredAccessSet<T>`
- (existing method renamed to `get_conflicts_single`)
- Add docs for those and all the other methods while I'm at it.
## Objective
- ~~Make absurdly long-lived changes stay detectable for even longer (without leveling up to `u64`).~~
- Give all changes a consistent maximum lifespan.
- Improve code clarity.
## Solution
- ~~Increase the frequency of `check_tick` scans to increase the oldest reliably-detectable change.~~
(Deferred until we can benchmark the cost of a scan.)
- Ignore changes older than the maximum reliably-detectable age.
- General refactoring—name the constants, use them everywhere, and update the docs.
- Update test cases to check for the specified behavior.
## Related
This PR addresses (at least partially) the concerns raised in:
- #3071
- #3082 (and associated PR #3084)
## Background
- #1471
Given the minimum interval between `check_ticks` scans, `N`, the oldest reliably-detectable change is `u32::MAX - (2 * N - 1)` (or `MAX_CHANGE_AGE`). Reducing `N` from ~530 million (current value) to something like ~2 million would extend the lifetime of changes by a billion.
| minimum `check_ticks` interval | oldest reliably-detectable change | usable % of `u32::MAX` |
| --- | --- | --- |
| `u32::MAX / 8` (536,870,911) | `(u32::MAX / 4) * 3` | 75.0% |
| `2_000_000` | `u32::MAX - 3_999_999` | 99.9% |
Similarly, changes are still allowed to be between `MAX_CHANGE_AGE`-old and `u32::MAX`-old in the interim between `check_tick` scans. While we prevent their age from overflowing, the test to detect changes still compares raw values. This makes failure ultimately unreliable, since when ancient changes stop being detected varies depending on when the next scan occurs.
## Open Question
Currently, systems and system states are incorrectly initialized with their `last_change_tick` set to `0`, which doesn't handle wraparound correctly.
For consistent behavior, they should either be initialized to the world's `last_change_tick` (and detect no changes) or to `MAX_CHANGE_AGE` behind the world's current `change_tick` (and detect everything as a change). I've currently gone with the latter since that was closer to the existing behavior.
## Follow-up Work
(Edited: entire section)
We haven't actually profiled how long a `check_ticks` scan takes on a "large" `World` , so we don't know if it's safe to increase their frequency. However, we are currently relying on play sessions not lasting long enough to trigger a scan and apps not having enough entities/archetypes for it to be "expensive" (our assumption). That isn't a real solution. (Either scanning never costs enough to impact frame times or we provide an option to use `u64` change ticks. Nobody will accept random hiccups.)
To further extend the lifetime of changes, we actually only need to increment the world tick if a system has `Fetch: !ReadOnlySystemParamFetch`. The behavior will be identical because all writes are sequenced, but I'm not sure how to implement that in a way that the compiler can optimize the branch out.
Also, since having no false positives depends on a `check_ticks` scan running at least every `2 * N - 1` ticks, a `last_check_tick` should also be stored in the `World` so that any lull in system execution (like a command flush) could trigger a scan if needed. To be completely robust, all the systems initialized on the world should be scanned, not just those in the current stage.
# Objective
- Add two missing ogg vorbis audio extensions.
## Solution
- Add the two missing extensions to the list
- The file format is the same, there are simply two other possible extensions files can use.
- This can be easily (manually) tested by renaming the extension of `assets/sounds/Windless Slopes.ogg` to end in either `.oga` or `.spx` (in both the filesystem and in `examples/audio/audio.rs`) and then running `cargo run --example audio` and observing that the music still plays.
## More info
From the [wikipedia article for Ogg](https://en.wikipedia.org/wiki/Ogg):
> Ogg audio media is registered as [IANA](https://en.wikipedia.org/wiki/Internet_Assigned_Numbers_Authority) [media type](https://en.wikipedia.org/wiki/Media_type) audio/ogg with file extensions .oga, .ogg, and [.spx](https://en.wikipedia.org/wiki/Speex).
The current workaround is to rename any files ending in `.oga` or `.spx` to end in `.ogg` instead, which complicates tracking assets procured from other organizations.
See also [a corresponding change to bevy_kira_audio](https://github.com/NiklasEi/bevy_kira_audio/pull/8)
---
## Changelog
### Added
- Vorbis audio files may now use the `.oga` and `.spx` filename extensions in addition to the more common `.ogg` filename extension.
# Objective
It is possible to get a mutable reference to a `TypeRegistration` using
`TypeRegistry::get_mut`. However, none of its other methods
(`get_mut_with_name`, `get_type_data`, `iter`, etc.) have mutable
versions.
Besides improving consistency, this change would facilitate use cases
which involve storing mutable state data in the `TypeRegistry`.
## Solution
Provides a trivial wrapper around the mutable accessors that the
`TypeRegistration` already provides. Exactly mirrors the existing
immutable versions.
# Objective
Make it easy to get position and index data from Meshes.
## Solution
It was previously possible to get the mesh data by manually matching on `Mesh::VertexAttributeValues` and `Mesh::Indices`as in the bodies of these two methods (`VertexAttributeValues::as_float3(&self)` and `Indices::iter(&self)`), but that's needless duplication that making these methods `pub` fixes.
# Objective
- Remove `Resource` binding on events, introduce a new `Event` trait
- Ensure event iterators are `ExactSizeIterator`
## Solution
- Builds on #2382 and #2969
## Changelog
- Events<T>, EventWriter<T>, EventReader<T> and so on now require that the underlying type is Event, rather than Resource. Both of these are trivial supertraits of Send + Sync + 'static with universal blanket implementations: this change is currently purely cosmetic.
- Event reader iterators now implement ExactSizeIterator
In a `PluginGroupBuilder`, when adding a plugin that was already in the group (potentially disabled), it was then added twice to the app builder when calling `finish`. As the plugin is kept in an `HashMap`, it is not possible to have the same plugins twice with different configuration.
This PR updates the order of the plugin group so that each plugin is present only once.
Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
# Objective
- noticed a few Vec3 and Vec2 that could be const
## Solution
- Declared them as const
- It seems to make a tiny improvement in example `many_light`, but given that the change is not complex at all it could still be worth it
# Objective
We have some macros that are public but only used internally for now. They fail on user's code due to the use of crate names like `bevy_utils`, while the user only has `bevy::utils`. There are two affected macros.
- `bevy_utils::define_label`: it may be useful in user's code for defining custom kinds of label traits (this is why I made this PR).
- `bevy_asset::load_internal_asset`: not useful currently due to limitations of the debug asset server, but this may change in the future.
## Solution
We can make them work by using `$crate` instead of names of their own crates, which can refer to the macro's defining crate regardless of the user's setup. Even though our objective is rather low-priority here, the solution adds no maintenance cost so it is still worthwhile.
1. change `PtrMut::as_ptr(self)` and `OwnedPtr::as_ptr(self)` to take `&self`, otherwise printing the pointer will prevent doing anything else afterwards
2. make all `as_ptr` methods safe. There's nothing unsafe about obtaining a pointer, these kinds of methods are safe in std as well [str::as_ptr](https://doc.rust-lang.org/stable/std/primitive.str.html#method.as_ptr), [Rc::as_ptr](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.as_ptr)
3. rename `offset`/`add` to `byte_offset`/`byte_add`. The unprefixed methods in std add in increments of `std::mem::size_of::<T>`, not in bytes. There's a PR for rust to add these byte_ methods https://github.com/rust-lang/rust/pull/95643 and at the call site it makes it much more clear that you need to do `.byte_add(i * layout_size)` instead of `.add(i)`
# Objective
Fixes#3180, builds from https://github.com/bevyengine/bevy/pull/2898
## Solution
Support requesting a window to be closed and closing a window in `bevy_window`, and handle this in `bevy_winit`.
This is a stopgap until we move to windows as entites, which I'm sure I'll get around to eventually.
## Changelog
### Added
- `Window::close` to allow closing windows.
- `WindowClosed` to allow reacting to windows being closed.
### Changed
Replaced `bevy::system::exit_on_esc_system` with `bevy:🪟:close_on_esc`.
## Fixed
The app no longer exits when any window is closed. This difference is only observable when there are multiple windows.
## Migration Guide
`bevy::input::system::exit_on_esc_system` has been removed. Use `bevy:🪟:close_on_esc` instead.
`CloseWindow` has been removed. Use `Window::close` instead.
The `Close` variant has been added to `WindowCommand`. Handle this by closing the relevant window.
# Objective
Fixes#4556
## Solution
StorageBuffer must use the Size of the std430 representation to calculate the buffer size, as the std430 representation is the data that will be written to it.
# Objective
Add support for vertex colors
## Solution
This change is modeled after how vertex tangents are handled, so the shader is conditionally compiled with vertex color support if the mesh has the corresponding attribute set.
Vertex colors are multiplied by the base color. I'm not sure if this is the best for all cases, but may be useful for modifying vertex colors without creating a new mesh.
I chose `VertexFormat::Float32x4`, but I'd prefer 16-bit floats if/when support is added.
## Changelog
### Added
- Vertex colors can be specified using the `Mesh::ATTRIBUTE_COLOR` mesh attribute.
# Objective
Bevy users often want to create circles and other simple shapes.
All the machinery is in place to accomplish this, and there are external crates that help. But when writing code for e.g. a new bevy example, it's not really possible to draw a circle without bringing in a new asset, writing a bunch of scary looking mesh code, or adding a dependency.
In particular, this PR was inspired by this interaction in another PR: https://github.com/bevyengine/bevy/pull/3721#issuecomment-1016774535
## Solution
This PR adds `shape::RegularPolygon` and `shape::Circle` (which is just a `RegularPolygon` that defaults to a large number of sides)
## Discussion
There's a lot of ongoing discussion about shapes in <https://github.com/bevyengine/rfcs/pull/12> and at least one other lingering shape PR (although it seems incomplete).
That RFC currently includes `RegularPolygon` and `Circle` shapes, so I don't think that having working mesh generation code in the engine for those shapes would add much burden to an author of an implementation.
But if we'd prefer not to add additional shapes until after that's sorted out, I'm happy to close this for now.
## Alternatives for users
For any users stumbling on this issue, here are some plugins that will help if you need more shapes.
https://github.com/Nilirad/bevy_prototype_lyonhttps://github.com/johanhelsing/bevy_smudhttps://github.com/Weasy666/bevy_svghttps://github.com/redpandamonium/bevy_more_shapeshttps://github.com/ForesightMiningSoftwareCorporation/bevy_polyline
# Objective
- When spawning a sprite the alpha is used for transparency, but when using the `Color::into()` implementation to spawn a `StandardMaterial`, the alpha is ignored.
- Pretty much everytime I want to make something transparent I started with a `Color::rgb().into()` and I'm always surprised that it doesn't work when changing it to `Color::rgba().into()`
- It's possible there's an issue with this approach I am not thinking of, but I'm not sure what's the point of setting an alpha value without the goal of making a color transparent.
## Solution
- Set the alpha_mode to AlphaMode::Blend when the alpha is not the default value.
---
## Migration Guide
This is not a breaking change, but it can easily be migrated to reduce boilerplate
```rust
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(shape::Cube::default().into()),
material: materials.add(StandardMaterial {
base_color: Color::rgba(1.0, 0.0, 0.0, 0.75),
alpha_mode: AlphaMode::Blend,
..default()
}),
..default()
});
// becomes
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(shape::Cube::default().into()),
material: materials.add(Color::rgba(1.0, 0.0, 0.0, 0.75).into()),
..default()
});
```
Co-authored-by: Charles <IceSentry@users.noreply.github.com>
# Objective
The pointer types introduced in #3001 are useful not just in `bevy_ecs`, but also in crates like `bevy_reflect` (#4475) or even outside of bevy.
## Solution
Extract `Ptr<'a>`, `PtrMut<'a>`, `OwnedPtr<'a>`, `ThinSlicePtr<'a, T>` and `UnsafeCellDeref` from `bevy_ecs::ptr` into `bevy_ptr`.
**Note:** `bevy_ecs` still reexports the `bevy_ptr` as `bevy_ecs::ptr` so that crates like `bevy_transform` can use the `Bundle` derive without needing to depend on `bevy_ptr` themselves.
# Objective
- `RunOnce` was a manual `System` implementation.
- Adding run criteria to stages was yet to be systemyoten
## Solution
- Make it a normal function
- yeet
## Changelog
- Replaced `RunOnce` with `ShouldRun::once`
## Migration guide
The run criterion `RunOnce`, which would make the controlled systems run only once, has been replaced with a new run criterion function `ShouldRun::once`. Replace all instances of `RunOnce` with `ShouldRun::once`.
# Objective
The `Ptr` types gives free access to the underlying `NonNull<u8>`, which adds more publicly visible pointer wrangling than there needs to be. There are also a few edge cases where Ptr types could be more readily utilized for properly validating the soundness of ECS operations.
## Solution
- Replace `*Ptr(Mut)::inner` with `cast` which requires a concrete type to give the pointer. This function could also have a `debug_assert` with an alignment check to ensure that the pointer is aligned properly, but is currently not included.
- Use `OwningPtr::read` in ECS macros over casting the inner pointer around.
# Objective
- After #3412, `Camera::world_to_screen` got a little bit uglier to use by needing to provide both `Windows` and `Assets<Image>`, even though only one would be needed b697e73c3d/crates/bevy_render/src/camera/camera.rs (L117-L123)
- Some time, exact coordinates are not needed but normalized device coordinates is enough
## Solution
- Add a function to just get NDC
### Problem
It currently isn't possible to construct the default value of a reflected type. Because of that, it isn't possible to use `add_component` of `ReflectComponent` to add a new component to an entity because you can't know what the initial value should be.
### Solution
1. add `ReflectDefault` type
```rust
#[derive(Clone)]
pub struct ReflectDefault {
default: fn() -> Box<dyn Reflect>,
}
impl ReflectDefault {
pub fn default(&self) -> Box<dyn Reflect> {
(self.default)()
}
}
impl<T: Reflect + Default> FromType<T> for ReflectDefault {
fn from_type() -> Self {
ReflectDefault {
default: || Box::new(T::default()),
}
}
}
```
2. add `#[reflect(Default)]` to all component types that implement `Default` and are user facing (so not `ComputedSize`, `CubemapVisibleEntities` etc.)
This makes it possible to add the default value of a component to an entity without any compile-time information:
```rust
fn main() {
let mut app = App::new();
app.register_type::<Camera>();
let type_registry = app.world.get_resource::<TypeRegistry>().unwrap();
let type_registry = type_registry.read();
let camera_registration = type_registry.get(std::any::TypeId::of::<Camera>()).unwrap();
let reflect_default = camera_registration.data::<ReflectDefault>().unwrap();
let reflect_component = camera_registration
.data::<ReflectComponent>()
.unwrap()
.clone();
let default = reflect_default.default();
drop(type_registry);
let entity = app.world.spawn().id();
reflect_component.add_component(&mut app.world, entity, &*default);
let camera = app.world.entity(entity).get::<Camera>().unwrap();
dbg!(&camera);
}
```
### Open questions
- should we have `ReflectDefault` or `ReflectFromWorld` or both?
# Objective
- While optimising many_cubes, I noticed that all material handles are extracted regardless of whether the entity to which the handle belongs is visible or not. As such >100k handles are extracted when only <20k are visible.
## Solution
- Only extract material handles of visible entities.
- This improves `many_cubes -- sphere` from ~42fps to ~48fps. It reduces not only the extraction time but also system commands time. `Handle<StandardMaterial>` extraction and its system commands went from 0.522ms + 3.710ms respectively, to 0.267ms + 0.227ms an 88% reduction for this system for this case. It's very view dependent but...
# Objective
- Creating and executing render passes has GPU overhead. If there are no phase items in the render phase to draw, then this overhead should not be incurred as it has no benefit.
## Solution
- Check if there are no phase items to draw, and if not, do not construct not execute the render pass
---
## Changelog
- Changed: Do not create nor execute empty render passes
# Objective
1. Previously, the `change_tick` and `last_change_tick` fields on `SystemChangeTick` [were `pub`](https://docs.rs/bevy/0.6.1/bevy/ecs/system/struct.SystemChangeTick.html).
1. This was actively misleading, as while this can be fetched as a `SystemParam`, a copy is returned instead
2. This information could be useful for debugging, but there was no way to investigate when data was changed.
3. There were no docs!
## Solution
1. Move these to a getter method.
2. Add `last_changed` method to the `DetectChanges` trait to enable inspection of when data was last changed.
3. Add docs.
# Changelog
`SystemChangeTick` now provides getter methods for the current and previous change tick, rather than public fields.
This can be combined with `DetectChanges::last_changed()` to debug the timing of changes.
# Migration guide
The `change_tick` and `last_change_tick` fields on `SystemChangeTick` are now private, use the corresponding getter method instead.
# Objective
avoid naming collisions with user structs when deriving ``system_param``.
## Solution
~rename the fetch struct created by ``#[derive(system_param)]`` from ``{}State`` to ``{}SysParamState``.~
place the fetch struct into an anonymous scope.
## Migration Guide
For code that was using a system param's fetch struct, such as ``EventReader``'s ``EventReaderState``, the fetch struct can now be identified via the SystemParam trait associated type ``Fetch``, e.g. for ``EventReader<T>`` it can be identified as ``<EventReader<'static, 'static, T> as SystemParam>::Fetch``
Supercedes https://github.com/bevyengine/bevy/pull/3340, and absorbs the test from there.
# Objective
- Fixes#3329
## Solution
- If the `Children` component has changed, we currently do not have a way to know how it has changed.
- Therefore, we must update the hierarchy downwards from that point to be correct.
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
# Objective
Reflected tuples do not implement `GetTypeRegistration`, preventing us from registering our tuples, like:
```rust
app.register_type::<(i32, i32)>();
```
This is especially important for things like using #4042 to improve the scene format or implementing #4154 to recursively register fields.
## Solution
Added an implementation to the tuple macro:
```rust
impl<$($name: Reflect + for<'de> Deserialize<'de>),*> GetTypeRegistration for ($($name,)*) {
fn get_type_registration() -> TypeRegistration {
let mut registration = TypeRegistration::of::<($($name,)*)>();
registration.insert::<ReflectDeserialize>(FromType::<($($name,)*)>::from_type());
registration
}
}
```
This requires that the tuple's types implement `Deserialize`. This is exactly how `Vec` and `HashMap` handle it:
```rust
impl<T: FromReflect + for<'de> Deserialize<'de>> GetTypeRegistration for Vec<T> {
fn get_type_registration() -> TypeRegistration {
let mut registration = TypeRegistration::of::<Vec<T>>();
registration.insert::<ReflectDeserialize>(FromType::<Vec<T>>::from_type());
registration
}
}
```
This is a replacement for #2106
This adds a `Metadata` struct which contains metadata information about a file, at the moment only the file type.
It also adds a `get_metadata` to `AssetIo` trait and an `asset_io` accessor method to `AssetServer` and `LoadContext`
I am not sure about the changes in `AndroidAssetIo ` and `WasmAssetIo`.
# Objective
- Manually running systems is a somewhat obscure process: systems must be initialized before they are run
- The unwrap is rather hard to debug.
## Solution
- Replace unwraps in `FunctionSystem` methods with expects (progress towards #3892).
- Briefly document this requirement.
# Objective
- Part of the splitting process of #3692.
## Solution
- Remove / change the tuple structs inside of `gamepad.rs` of `bevy_input` to normal structs.
## Reasons
- It made the `gamepad_connection_system` cleaner.
- It made the `gamepad_input_events.rs` example cleaner (which is probably the most notable change for the user facing API).
- Tuple structs are not descriptive (`.0`, `.1`).
- Using tuple structs for more than 1 field is a bad idea (This means that the `Gamepad` type might be fine as a tuple struct, but I still prefer normal structs over tuple structs).
Feel free to discuss this change as this is more or less just a matter of taste.
## Changelog
### Changed
- The `Gamepad`, `GamepadButton`, `GamepadAxis`, `GamepadEvent` and `GamepadEventRaw` types are now normal structs instead of tuple structs and have a `new()` function.
## Migration Guide
- The `Gamepad`, `GamepadButton`, `GamepadAxis`, `GamepadEvent` and `GamepadEventRaw` types are now normal structs instead of tuple structs and have a `new()` function. To migrate change every instantiation to use the `new()` function instead and use the appropriate field names instead of `.0` and `.1`.
# Objective
- Clean up duplicate code in the add_before/add_after functions in PluginGroupBuilder.
## Solution
- moved index retrieval code to a private function index_of() for the PluginGroupBuilder.
- change is just tidying up. No real change to functionality.
# Objective
This code currently fails to compile with error ``the name `T` is already used for a generic parameter in this item's generic parameters``, because `T` is also used in code generated by `derive(Bundle)`.
```rust
#[derive(Bundle)]
struct MyBundle<T: Component> {
component: T,
}
```
## Solution
Add double underscores to type parameter names in `derive(Bundle)`.
# Objective
- Meshes are queued in opaque phase instead of transparent phase when drawing wireframes.
- There is a name mismatch.
## Solution
- Rename `transparent_phase` to `opaque_phase` in `wireframe.rs`.
The only tests we had for `derive(WorldQuery)` checked that the derive doesnt panic/emit a `compiler_error!`. This PR adds tests that actually assert the returned values of a query using the derived `WorldQuery` impl. Also adds a compile fail test to check that we correctly error on read only world queries containing mutable world queries.
# Objective
`bevy_ecs` has large amounts of unsafe code which is hard to get right and makes it difficult to audit for soundness.
## Solution
Introduce lifetimed, type-erased pointers: `Ptr<'a>` `PtrMut<'a>` `OwningPtr<'a>'` and `ThinSlicePtr<'a, T>` which are newtypes around a raw pointer with a lifetime and conceptually representing strong invariants about the pointee and validity of the pointer.
The process of converting bevy_ecs to use these has already caught multiple cases of unsound behavior.
## Changelog
TL;DR for release notes: `bevy_ecs` now uses lifetimed, type-erased pointers internally, significantly improving safety and legibility without sacrificing performance. This should have approximately no end user impact, unless you were meddling with the (unfortunately public) internals of `bevy_ecs`.
- `Fetch`, `FilterFetch` and `ReadOnlyFetch` trait no longer have a `'state` lifetime
- this was unneeded
- `ReadOnly/Fetch` associated types on `WorldQuery` are now on a new `WorldQueryGats<'world>` trait
- was required to work around lack of Generic Associated Types (we wish to express `type Fetch<'a>: Fetch<'a>`)
- `derive(WorldQuery)` no longer requires `'w` lifetime on struct
- this was unneeded, and improves the end user experience
- `EntityMut::get_unchecked_mut` returns `&'_ mut T` not `&'w mut T`
- allows easier use of unsafe API with less footguns, and can be worked around via lifetime transmutery as a user
- `Bundle::from_components` now takes a `ctx` parameter to pass to the `FnMut` closure
- required because closure return types can't borrow from captures
- `Fetch::init` takes `&'world World`, `Fetch::set_archetype` takes `&'world Archetype` and `&'world Tables`, `Fetch::set_table` takes `&'world Table`
- allows types implementing `Fetch` to store borrows into world
- `WorldQuery` trait now has a `shrink` fn to shorten the lifetime in `Fetch::<'a>::Item`
- this works around lack of subtyping of assoc types, rust doesnt allow you to turn `<T as Fetch<'static>>::Item'` into `<T as Fetch<'a>>::Item'`
- `QueryCombinationsIter` requires this
- Most types implementing `Fetch` now have a lifetime `'w`
- allows the fetches to store borrows of world data instead of using raw pointers
## Migration guide
- `EntityMut::get_unchecked_mut` returns a more restricted lifetime, there is no general way to migrate this as it depends on your code
- `Bundle::from_components` implementations must pass the `ctx` arg to `func`
- `Bundle::from_components` callers have to use a fn arg instead of closure captures for borrowing from world
- Remove lifetime args on `derive(WorldQuery)` structs as it is nonsensical
- `<Q as WorldQuery>::ReadOnly/Fetch` should be changed to either `RO/QueryFetch<'world>` or `<Q as WorldQueryGats<'world>>::ReadOnly/Fetch`
- `<F as Fetch<'w, 's>>` should be changed to `<F as Fetch<'w>>`
- Change the fn sigs of `Fetch::init/set_archetype/set_table` to match respective trait fn sigs
- Implement the required `fn shrink` on any `WorldQuery` implementations
- Move assoc types `Fetch` and `ReadOnlyFetch` on `WorldQuery` impls to `WorldQueryGats` impls
- Pass an appropriate `'world` lifetime to whatever fetch struct you are for some reason using
### Type inference regression
in some cases rustc may give spurrious errors when attempting to infer the `F` parameter on a query/querystate this can be fixed by manually specifying the type, i.e. `QueryState:🆕:<_, ()>(world)`. The error is rather confusing:
```rust=
error[E0271]: type mismatch resolving `<() as Fetch<'_>>::Item == bool`
--> crates/bevy_pbr/src/render/light.rs:1413:30
|
1413 | main_view_query: QueryState::new(world),
| ^^^^^^^^^^^^^^^ expected `bool`, found `()`
|
= note: required because of the requirements on the impl of `for<'x> FilterFetch<'x>` for `<() as WorldQueryGats<'x>>::Fetch`
note: required by a bound in `bevy_ecs::query::QueryState::<Q, F>::new`
--> crates/bevy_ecs/src/query/state.rs:49:32
|
49 | for<'x> QueryFetch<'x, F>: FilterFetch<'x>,
| ^^^^^^^^^^^^^^^ required by this bound in `bevy_ecs::query::QueryState::<Q, F>::new`
```
---
Made with help from @BoxyUwU and @alice-i-cecile
Co-authored-by: Boxy <supbscripter@gmail.com>
# Objective
Reduce from scratch build time.
## Solution
Reduce the size of the critical path by removing dependencies between crates where not necessary. For `cargo check --no-default-features` this reduced build time from ~51s to ~45s. For some commits I am not completely sure if the tradeoff between build time reduction and convenience caused by the commit is acceptable. If not, I can drop them.
## Objective
This fixes#1686.
`size_hint` can be useful even if a little niche. For example,
`collect::<Vec<_>>()` uses the `size_hint` of Iterator it collects from
to pre-allocate a memory slice large enough to not require re-allocating
when pushing all the elements of the iterator.
## Solution
To this effect I made the following changes:
* Add a `IS_ARCHETYPAL` associated constant to the `Fetch` trait,
this constant tells us when it is safe to assume that the `Fetch`
relies exclusively on archetypes to filter queried entities
* Add `IS_ARCHETYPAL` to all the implementations of `Fetch`
* Use that constant in `QueryIter::size_hint` to provide a more useful
## Migration guide
The new associated constant is an API breaking change. For the user,
if they implemented a custom `Fetch`, it means they have to add this
associated constant to their implementation. Either `true` if it doesn't limit
the number of entities returned in a query beyond that of archetypes, or
`false` for when it does.
# Objective
Reduce the catch-all grab-bag of functionality in bevy_core by moving FloatOrd to bevy_utils.
A step in addressing #2931 and splitting bevy_core into more specific locations.
## Solution
Move FloatOrd into bevy_utils. Fix the compile errors.
As a result, bevy_core_pipeline, bevy_pbr, bevy_sprite, bevy_text, and bevy_ui no longer depend on bevy_core (they were only using it for `FloatOrd` previously).
# Objective
- Small change that better facilitates custom animation systems
## Solution
- Added a public access function to `bevy::animation::AnimationClip`, making duration publicly readable
---
# Objective
- Code quality bad
## Solution
- Code quality better
- Using rust-analyzer's inline function and inline variable quick assists, I validated that the call to `AssetServer::new` is exactly the same code as the previous version.
# Objective
Comparing two reflected floating points would always fail:
```rust
let a: &dyn Reflect = &1.23_f32;
let b: &dyn Reflect = &1.23_f32;
// Panics:
assert!(a.reflect_partial_eq(b).unwrap_or_default());
```
The comparison returns `None` since `f32` (and `f64`) does not have a reflected `PartialEq` implementation.
## Solution
Include `PartialEq` in the `impl_reflect_value!` macro call for both `f32` and `f64`.
`Hash` is still excluded since neither implement `Hash`.
Also added equality tests for some of the common types from `std` (including `f32`).
Support for deriving `TypeUuid` for types with generics was initially added in https://github.com/bevyengine/bevy/pull/2044 but later reverted https://github.com/bevyengine/bevy/pull/2204 because it lead to `MyStruct<A>` and `MyStruct<B>` having the same type uuid.
This PR fixes this by generating code like
```rust
#[derive(TypeUuid)]
#[uuid = "69b09733-a21a-4dab-a444-d472986bd672"]
struct Type<T>(T);
impl<T: TypeUuid> TypeUuid for Type<T> {
const TYPE_UUID: TypeUuid = generate_compound_uuid(Uuid::from_bytes([/* 69b0 uuid */]), T::TYPE_UUID);
}
```
where `generate_compound_uuid` will XOR the non-metadata bits of the two UUIDs.
Co-authored-by: XBagon <xbagon@outlook.de>
Co-authored-by: Jakob Hellermann <hellermann@sipgate.de>
# Objective
Fix wonky torus normals.
## Solution
I attempted this previously in #3549, but it looks like I botched it. It seems like I mixed up the y/z axes. Somehow, the result looked okay from that particular camera angle.
This video shows toruses generated with
- [left, orange] original torus mesh code
- [middle, pink] PR 3549
- [right, purple] This PR
https://user-images.githubusercontent.com/200550/164093183-58a7647c-b436-4512-99cd-cf3b705cefb0.mov
# Objective
Make timers update `just_finished` on tick, even if paused.
Fixes#4436
## Solution
`just_finished()` returns `times_finished > 0`. So I:
* Renamed `times_finished` to `times_finished_this_tick` to reduce confusion.
* Set `times_finished_this_tick` to `0` on tick when paused.
* Additionally set `finished` to `false` if the timer is repeating.
Notably this change broke none of the existing tests, so I added a couple for this.
Files changed shows a lot of noise because of the rename. Check the first commit for the relevant changes.
Co-authored-by: devil-ira <justthecooldude@gmail.com>
# Objective
- Part of the splitting process of #3692.
## Solution
- Document `mouse.rs` inside of `bevy_input`.
Co-authored-by: KDecay <KDecayMusic@protonmail.com>
# Objective
In some cases, you may want to take ownership of the values in `DynamicList` or `DynamicMap`.
I came across this need while trying to implement a custom deserializer, but couldn't get ownership of the values in the list.
## Solution
Implemented `IntoIter` for both `DynamicList` and `DynamicMap`.
# Objective
- Closes#335.
- Related #4285.
- Part of the splitting process of #3503.
## Solution
- Move `Rect` to `bevy_ui` and rename it to `UiRect`.
## Reasons
- `Rect` is only used in `bevy_ui` and therefore calling it `UiRect` makes the intent clearer.
- We have two types that are called `Rect` currently and it's missleading (see `bevy_sprite::Rect` and #335).
- Discussion in #3503.
## Changelog
### Changed
- The `Rect` type got moved from `bevy_math` to `bevy_ui` and renamed to `UiRect`.
## Migration Guide
- The `Rect` type got renamed to `UiRect`. To migrate you just have to change every occurrence of `Rect` to `UiRect`.
Co-authored-by: KDecay <KDecayMusic@protonmail.com>
# Objective
- `EntityRef` and `EntityMut` are surpisingly important public types when working directly with the `World`.
- They're undocumented.
## Solution
- Just add docs!
# Objective
Trait objects that have `Reflect` as a supertrait cannot be upcast to a `dyn Reflect`.
Attempting something like:
```rust
trait MyTrait: Reflect {
// ...
}
fn foo(value: &dyn MyTrait) {
let reflected = value as &dyn Reflect; // Error!
// ...
}
```
Results in `error[E0658]: trait upcasting coercion is experimental`.
The reason this is important is that a lot of `bevy_reflect` methods require a `&dyn Reflect`. This is trivial with concrete types, but if we don't know the concrete type (we only have the trait object), we can't use these methods. For example, we couldn't create a `ReflectSerializer` for the type since it expects a `&dyn Reflect` value— even though we should be able to.
## Solution
Add `as_reflect` and `as_reflect_mut` to `Reflect` to allow upcasting to a `dyn Reflect`:
```rust
trait MyTrait: Reflect {
// ...
}
fn foo(value: &dyn MyTrait) {
let reflected = value.as_reflect();
// ...
}
```
## Alternatives
We could defer this type of logic to the crate/user. They can add these methods to their trait in the same exact way we do here. The main benefit of doing it ourselves is it makes things convenient for them (especially when using the derive macro).
We could also create an `AsReflect` trait with a blanket impl over all reflected types, however, I could not get that to work for trait objects since they aren't sized.
---
## Changelog
- Added trait method `Reflect::as_reflect(&self)`
- Added trait method `Reflect::as_reflect_mut(&mut self)`
## Migration Guide
- Manual implementors of `Reflect` will need to add implementations for the methods above (this should be pretty easy as most cases just need to return `self`)
# Objective
- Related #4276.
- Part of the splitting process of #3503.
## Solution
- Move `Size` to `bevy_ui`.
## Reasons
- `Size` is only needed in `bevy_ui` (because it needs to use `Val` instead of `f32`), but it's also used as a worse `Vec2` replacement in other areas.
- `Vec2` is more powerful than `Size` so it should be used whenever possible.
- Discussion in #3503.
## Changelog
### Changed
- The `Size` type got moved from `bevy_math` to `bevy_ui`.
## Migration Guide
- The `Size` type got moved from `bevy::math` to `bevy::ui`. To migrate you just have to import `bevy::ui::Size` instead of `bevy::math::Math` or use the `bevy::prelude` instead.
Co-authored-by: KDecay <KDecayMusic@protonmail.com>
# Objective
- The `OrthographicCameraBundle` constructor for 2d cameras uses a hardcoded value for Z position and scale of the camera. It could be useful to be able to customize these values.
## Solution
- Add a new constructor `custom_2d` that takes `far` (Z position) and `scale` as parameters. The default constructor `new_2d` uses this constructor with `far = 1000.0` and `scale = 1.0`.
A couple more uncontroversial changes extracted from #3886.
* Enable full feature of syn
It is necessary for the ItemFn and ItemTrait type. Currently it is indirectly
enabled through the tracing dependency of bevy_utils, but this may no
longer be the case in the future.
* Remove unused function from bevy_macro_utils
# Objective
- Part of the splitting process of #3692.
## Solution
- Add more tests to `input.rs` inside of `bevy_input`.
## Note
- The tests would now catch a change like #4410 and fail accordingly.
# Objective
- Debug logs are useful in release builds, but `tracing` logs are hard-capped (`release_max_level_info`) at the `info` level by `bevy_utils`.
## Solution
- This PR simply removes the limit in `bevy_utils` with no further actions.
- If any out-of-the box performance regressions arise, the steps to enable this `tracing` feature should be documented in a user guide in the future.
This PR closes#4069 and closes#1206.
## Alternatives considered
- Instruct the user to build with `debug-assertions` enabled: this is just a workaround, as it obviously enables all `debug-assertions` that affect more than logging itself.
- Re-exporting the feature from `tracing` and enabling it by default: I believe it just adds complexity and confusion, the `tracing` feature can also be re-enabled with one line in userland.
---
## Changelog
### Fixed
- Log level is not hard capped at `info` for release builds anymore.
## Migration Guide
- Maximum log levels for release builds is not enforced by Bevy anymore, to omit "debug" and "trace" level logs entirely from release builds, `tracing` must be added as a dependency with its `release_max_level_info` feature enabled in `Cargo.toml`. (`tracing = { version = "0.1", features = ["release_max_level_info"] }`)
# Objective
To test systems that implement frame rate-independent update logic, one needs to be able to mock `Time`. By mocking time, it's possible to write tests that confirm systems are frame rate-independent.
This is a follow-up PR to #2549 by @ostwilkens and based on his work.
## Solution
To mock `Time`, one needs to be able to manually update the Time resource with an `Instant` defined by the developer. This can be achieved by making the existing `Time::update_with_instant` method public for use in tests.
## Changelog
- Make `Time::update_with_instant` public
- Add doc to `Time::update_with_instant` clarifying that the method should not be called outside of tests.
- Add doc test to `Time` demonstrating how to use `update_with_instant` in tests.
Co-authored-by: Martin Dickopp <martin@zero-based.org>
# Objective
- The single threaded task pool is not documented
- This doesn't warn in CI as it's feature gated for wasm, but I'm tired of seeing the warnings when building in wasm
## Solution
- Document it
# Objective
- Part of the splitting process of #3692.
## Solution
- Rename `ElementState` to `ButtonState`
## Reasons
- The old name was too generic.
- If something can be pressed it is automatically button-like (thanks to @alice-i-cecile for bringing it up in #3692).
- The reason it is called `ElementState` is because that's how `winit` calls it.
- It is used to define if a keyboard or mouse **button** is pressed or not.
- Discussion in #3692.
## Changelog
### Changed
- The `ElementState` type received a rename and is now called `ButtonState`.
## Migration Guide
- The `ElementState` type received a rename and is now called `ButtonState`. To migrate you just have to change every occurrence of `ElementState` to `ButtonState`.
Co-authored-by: KDecay <KDecayMusic@protonmail.com>
# Objective
`AsSystemLabel` has been introduced on system descriptors to make ordering systems more convenient, but `SystemSet::before` and `SystemSet::after` still take `SystemLabels` directly:
use bevy::ecs::system::AsSystemLabel;
/*…*/ SystemSet::new().before(foo.as_system_label()) /*…*/
is currently necessary instead of
/*…*/ SystemSet::new().before(foo) /*…*/
## Solution
Use `AsSystemLabel` for `SystemSet`
The only way to soundly use this API is already encapsulated within `EntityMut::get`, so this api is removed.
# Migration guide
Replace calls to `EntityMut::get_unchecked` with calls to `EntityMut::get`.
# Objective
When using `derive(WorldQuery)`, then clippy complains with the following:
```rust
warning: missing documentation for a struct
--> src\wild_boar_type\marker_vital_status.rs:35:17
|
35 | #[derive(Debug, WorldQuery)]
| ^^^^^^^^^^
|
= note: this warning originates in the derive macro `WorldQuery` (in Nightly builds, run with -Z macro-backtrace for more info)
```
## Solution
* Either `#[doc(hidden)]` or
* Add a generic documentation line to it.
I don't know what is preferred, but I'd gladly add it in here.
# Objective
- The current API docs of `Commands` is very short and is very opaque to newcomers.
## Solution
- Try to explain what it is without requiring knowledge of other parts of `bevy_ecs` like `World` or `SystemParam`.
Co-authored-by: Charles <IceSentry@users.noreply.github.com>
Free at last!
# Objective
- Using `.system()` is no longer needed anywhere, and anyone using it will have already gotten a deprecation warning.
- https://github.com/bevyengine/bevy/pull/3302 was a super special case for `.system()`, since it was so prevelant. However, that's no reason.
- Despite it being deprecated, another couple of uses of it have already landed, including in the deprecating PR.
- These have all been because of doc examples having warnings not breaking CI - 🎟️?
## Solution
- Remove it.
- It's gone
---
## Changelog
- You can no longer use `.system()`
## Migration Guide
- You can no longer use `.system()`. It was deprecated in 0.7.0, and you should have followed the deprecation warning then. You can just remove the method call.
![image](https://user-images.githubusercontent.com/36049421/163688197-3e774a04-6f8f-40a6-b7a4-1330e0b7acf0.png)
- Thanks to the @TheRawMeatball for producing
# Objective
- Fix `ClusterConfig::None`
- This fix is from @robtfm but they didn't have time to submit it, so I am.
## Solution
- Always clear clusters and skip processing when `ClusterConfig::None`
- Conditionally remove `VisiblePointLights` from the view if it is present
# Objective
- https://github.com/bevyengine/bevy/pull/4098 still hasn't fixed minimisation on Windows.
- `Clusters.lights` is assumed to have the number of items given by the product of `Clusters.dimensions`'s axes.
## Solution
- Make that true in `clear`.
# Objective
- Fixes#4234
- Fixes#4473
- Built on top of #3989
- Improve performance of `assign_lights_to_clusters`
## Solution
- Remove the OBB-based cluster light assignment algorithm and calculation of view space AABBs
- Implement the 'iterative sphere refinement' algorithm used in Just Cause 3 by Emil Persson as documented in the Siggraph 2015 Practical Clustered Shading talk by Persson, on pages 42-44 http://newq.net/dl/pub/s2015_practical.pdf
- Adapt to also support orthographic projections
- Add `many_lights -- orthographic` for testing many lights using an orthographic projection
## Results
- `assign_lights_to_clusters` in `many_lights` before this PR on an M1 Max over 1500 frames had a median execution time of 1.71ms. With this PR it is 1.51ms, a reduction of 0.2ms or 11.7% for this system.
---
## Changelog
- Changed: Improved cluster light assignment performance
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- in #3851, a feature for tracing was added to bevy_transform
- usage of that feature was moved to bevy_hierarchy, but the feature was not updated
## Solution
- add the feature to bevy_hierarchy, remove it from bevy_transform
# Objective
- Provide more information when despawning an entity
## Solution
- Add a debug log when despawning an entity
- Add spans to the recursive ways of despawning an entity
```sh
RUST_LOG=debug cargo run --example panic --features trace
# RUST_LOG=debug needed to show debug logs from bevy_ecs
# --features trace needed to have the extra spans
...
DEBUG bevy_app:frame:stage{name=Update}:system_commands{name="panic::despawn_parent"}:command{name="DespawnRecursive" entity=0v0}: bevy_ecs::world: Despawning entity 1v0
DEBUG bevy_app:frame:stage{name=Update}:system_commands{name="panic::despawn_parent"}:command{name="DespawnRecursive" entity=0v0}: bevy_ecs::world: Despawning entity 0v0
```
## Objective
Fixes#4122.
## Solution
Inherit the visibility of the struct being derived for the `xxItem`, `xxFetch`, `xxState` structs.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
The documentation of the `Time::last_update` and `Time::time_since_startup` methods contains typos. It uses apostrophe instead of backtick characters around `Instant` and `Duration`, so that these words are not recognized as identifiers in the generated API documentation. This should be fixed.
## Solution
Fix the typos.
# Objective
Fixes https://github.com/bevyengine/bevy/issues/3499
## Solution
Uses a `HashMap` from `RenderTarget` to sampled textures when preparing `ViewTarget`s to ensure that two passes with the same render target get sampled to the same texture.
This builds on and depends on https://github.com/bevyengine/bevy/pull/3412, so this will be a draft PR until #3412 is merged. All changes for this PR are in the last commit.
# Objective
glTF files can contain cameras. Currently the scene viewer example uses _a_ camera defined in the file if possible, otherwise it spawns a new one. It would be nice if instead it could load all the cameras and cycle through them, while also having a separate user-controller camera.
## Solution
- instead of just a camera that is already defined, always spawn a new separate user-controller camera
- maintain a list of loaded cameras and cycle through them (wrapping to the user-controller camera) when pressing `C`
This matches the behavious that https://github.khronos.org/glTF-Sample-Viewer-Release/ has.
## Implementation notes
- The gltf scene asset loader just spawns the cameras into the world, but does not return a mapping of camera index to bevy entity. So instead the scene_viewer example just collects all spawned cameras with a good old `query.iter().collect()`, so the order is unspecified and may change between runs.
## Demo
https://user-images.githubusercontent.com/22177966/161826637-40161482-5b3b-4df5-aae8-1d5e9b918393.mp4
using the virtual city glTF sample file: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/VC
Co-authored-by: Jakob Hellermann <hellermann@sipgate.de>
# Objective
- While playing with volume, I noticed that when setting the volume just after playback start, I still get a few milliseconds at normal volume
## Solution
- Replace `play_in_loop` with `play_with_settings` that allows from more controls
- Adds a `PlaybackSettings` to specify the settings from start. Can be used: `PlaybackSettings::LOOP.with_volume(0.75)`
Currently `tracy` interprets the entire trace as one frame because the marker for frames isn't being recorded.
~~When an event with `tracy.trace_marker=true` is recorded, `tracing-tracy` will mark the frame as finished:
<aa0b96b2ae/tracing-tracy/src/lib.rs (L240)>~~
~~Unfortunately this leads to~~
```rs
INFO bevy_app:frame: bevy_app::app: finished frame tracy.frame_mark=true
```
~~being printed every frame (we can't use DEBUG because bevy_log sets `max_release_level_info`.~~
Instead of emitting an event that gets logged every frame, we can depend on tracy-client itself and call `finish_continuous_frame!();`
# Objective
- Fixes the issue with orthographic camera imported from glTF not displaying anything (mentioned in #4005).
## Solution
- This was due to wrong scaling mode being used. This PR simply changes WindowSize scaling mode to FixedHorizontal.
## Important Note
Currently, othographic scale in Blender, three.js, and possibly other software does not translate to Bevy (via glTF) because their developers have [misinterpreted the spec](https://github.com/KhronosGroup/glTF/issues/1663#issuecomment-618194015). The camera parameters have been clarified in glTF 2.0, which was released on October of 2021. In Blender 3.0.1 this issue has **not** been fixed yet. If you are importing orthographic cameras from Blender, you have to divide the scale by 2.
# Objective
- Previously, `iter_combinations()` does not work on queries that have filters.
- Fixes#3651
## Solution
- Derived Copy on all `*Fetch<T>` structs, and manually implemented `Clone` to allow the test to pass (`.count()` does not work on `QueryCombinationIter` when `Clone` is derived)
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Make `set_active_camera` system correctly respond to camera deletion, while preserving its correct behavior on first ever frame and any consequent frame, and with multiple cameras of the same type available in the world.
- Fixes#4227
## Solution
- Add a check that the entity referred to by `ActiveCamera` still exists in the world.
# Objective
- In glTF, mesh can be named. This named is used to be able to reference the mesh, but not as a component on the entity
- Bevy only added the node name to the parent node.
## Solution
- Also adds the name on the mesh entity if there is one.
Limitation: In glTF, it's possible to have one mesh (which can be named) corresponding to several primitives (which can't, but are the actual mesh). I added the mesh name to the entity with the `PbrBundle` matching the primitives, which means that a mesh with several primitives would all have the same name. I think this is acceptable...
# Objective
- Make it possible to use `System`s outside of the scheduler/executor without having to define logic to track new archetypes and call `System::add_archetype()` for each.
## Solution
- Replace `System::add_archetype(&Archetype)` with `System::update_archetypes(&World)`, making systems responsible for tracking their own most recent archetype generation the way that `SystemState` already does.
This has minimal (or simplifying) effect on most of the code with the exception of `FunctionSystem`, which must now track the latest `ArchetypeGeneration` it saw instead of relying on the executor to do it.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Fixes#4193
## Solution
When resetting a node's `Interaction` to `None`, ignore any `Clicked` node because that should be handled by the mouse release check exclusively.
Remove the 'chaining' api, as it's peculiar
~~Implement the label traits for `Box<dyn ThatTrait>` (n.b. I'm not confident about this change, but it was the quickest path to not regressing)~~
Remove the need for '`.system`' when using run criteria piping
# Objective
- While animating 501 https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/BrainStem, I noticed things were getting a little slow
- Looking in tracy, the system `extract_skinned_meshes` is taking a lot of time, with a mean duration of 15.17ms
## Solution
- ~~Use `Vec` instead of a `SmallVec`~~
- ~~Don't use an temporary variable~~
- Compute the affine matrix as an `Affine3A` instead
- Remove the `temp` vec
| |mean|
|---|---|
|base|15.17ms|
|~~vec~~|~~9.31ms~~|
|~~no temp variable~~|~~11.31ms~~|
|removing the temp vector|8.43ms|
|affine|13.21ms|
|all together|7.23ms|
# Objective
- Make use of storage buffers, where they are available, for clustered forward bindings to support far more point lights in a scene
- Fixes#3605
- Based on top of #4079
This branch on an M1 Max can keep 60fps with about 2150 point lights of radius 1m in the Sponza scene where I've been testing. The bottleneck is mostly assigning lights to clusters which grows faster than linearly (I think 1000 lights was about 1.5ms and 5000 was 7.5ms). I have seen papers and presentations leveraging compute shaders that can get this up to over 1 million. That said, I think any further optimisations should probably be done in a separate PR.
## Solution
- Add `RenderDevice` to the `Material` and `SpecializedMaterial` trait `::key()` functions to allow setting flags on the keys depending on feature/limit availability
- Make `GpuPointLights` and `ViewClusterBuffers` into enums containing `UniformVec` and `StorageBuffer` variants. Implement the necessary API on them to make usage the same for both cases, and the only difference is at initialisation time.
- Appropriate shader defs in the shader code to handle the two cases
## Context on some decisions / open questions
- I'm using `max_storage_buffers_per_shader_stage >= 3` as a check to see if storage buffers are supported. I was thinking about diving into 'binding resource management' but it feels like we don't have enough use cases to understand the problem yet, and it is mostly a separate concern to this PR, so I think it should be handled separately.
- Should `ViewClusterBuffers` and `ViewClusterBindings` be merged, duplicating the count variables into the enum variants?
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
The `bevy_app` crate has a lot of inconsistencies in the documentation (formatting, spelling, phrasing, consistency).
## Solution
Make it more consistent.
# Objective
- Fix#4416
- The scene has two root nodes, with the second one being the animation root
## Solution
- Check all scene root nodes, and add the `AnimationPlayer` component to nodes that are also animation roots
# Objective
Make `FromWorld` more useful for abstractions with a form similar to
```rs
trait FancyAbstraction {
type PreInitializedData: FromWorld;
}
```
## Solution
Add a `FromWorld` implementation for `SystemState` as well as a way to group together multiple `FromWorld` implementing types as one.
Note: I plan to follow up this PR with another to add `Local` support to exclusive systems, which should get a fair amount of use from the `FromWorld` implementation on `SystemState`.
# Objective
Avoid crashing if `RenderDevice` doesn't exist (required for headless mode).
Fixes#4392.
## Solution
Use `CompressedImageFormats::all()` if there is no `RenderDevice`.
# Objective
- Revert #4410
- `Input<T>.clear()` is the method call at the end of each frame for inputs. Clearing `pressed` in it mean that checking if a key is pressed will always return false
# Objective
- Fixes#1616, fixes#2225
- Let user specify an anchor for a sprite
## Solution
- Add an enum for an anchor point for most common values, with a variant for a custom point
- Defaults to Center to not change current behaviour
Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
Fixes#3408#3001 also solves this but I dont see it getting merged any time soon so...
# Objective
make bevy ecs a lil bit less unsound
## Solution
make `EntityMut::get_component_mut` return borrows from self instead of `'w`
# Objective
- Animation is using `Name` to be able to address nodes in an entity free way
- When loading random animated gltf files, I noticed some had animations without names sometimes
## Solution
- Add default names to all nodes
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/2096
## Solution
- This PR enables the drag-and-drop feature for winit on windows again, as the collision issue between cpal and winit has been fixed in https://github.com/RustAudio/cpal/pull/597. I confirmed the drag and drop example working on windows 10 with this change.
- ~~It also bumps the rodio version, though this is not strictly necessary.~~
# Objective
- While playing with animated models, I noticed some were a little off
## Solution
- Some animations curves only have one keyframe, they are used to set a transform to a given value
- Those were ignored as we're never exactly at the ts 0.0 of an animation. going there explicitly (`.set_elapsed(0.0).pause()`) would crash
- Special case this as there isn't much to animate in this case
https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
# Objective
Fixes#4382
## Solution
- Describe the solution used to achieve the objective above.
Fixed conversion formula to account for red and green component being max and equal
---
## Changelog
Fixed RGB -> HSL colorspace conversion
## Migration Guide
Co-authored-by: Francesco Giordana <fgiordana@netflix.com>
# Objective
- Part of the splitting process of #3503.
## Solution
- Remove the `face_toward.rs` file containing the `FaceToward` trait.
## Reasons
- It is unused inside of `bevy`.
- The method `Mat4::face_toward` of the trait is identical to `Mat4::look_at_rh` (see https://docs.rs/glam/latest/glam/f32/struct.Mat4.html#method.look_at_rh).
- Discussion in #3503.
## Changelog
### Removed
- The `FaceToward` trait got removed.
## Migration Guide
- The `FaceToward` trait got removed. To migrate you just have to change every occurrence of `Mat4::face_toward` to `Mat4::look_at_rh`.
# Objective
- Since #4224, using labels which only refer to one system doesn't make sense.
## Solution
- Remove some of those.
## Future work
- We should remove the ability to use strings as system labels entirely. I haven't in this PR because there are tests which use this, and that's a lot of code to change.
- The only use cases for labels are either intra-crate, which use #4224, or inter-crate, which should either use #4224 or explicit types. Neither of those should use strings.
# Objective
- std's new APIs do the same thing as `Query::get_multiple_mut`, but are called `get_many`: https://github.com/rust-lang/rust/pull/83608
## Solution
- Find and replace `get_multiple` with `get_many`
# Objective
Make it so that loading in a mesh without normals that is not a `TriangleList` succeeds.
## Solution
Flat normals can only be calculated on a mesh made of triangles.
Check whether the mesh is a `TriangleList` before trying to compute missing normals.
## Additional changes
The panic condition in `duplicate_vertices` did not make sense to me. I moved it to `compute_flat_normals` where the algorithm would produce incorrect results if the mesh is not a `TriangleList`.
Co-authored-by: devil-ira <justthecooldude@gmail.com>
# Objective
- Clarify `RemovedComponents` are flushed in `CoreStage::Last` and systems relying on that should run before that stage
## Solution
- Update `RemovedComponents` doc comment
# Objective
make bevy ecs a lil bit less unsound
## Solution
make unsound API unsafe so that there is an unsafe block to blame:
```rust
use bevy_ecs::prelude::*;
#[derive(Debug, Component)]
struct Foo(u8);
fn main() {
let mut world = World::new();
let e1 = world.spawn().id();
let e2 = world.spawn().insert(Foo(2)).id();
world.entities_mut().meta[0] = world.entities_mut().meta[1].clone();
let foo = world.entity(e1).get::<Foo>().unwrap();
// whoo i love having components i dont have
dbg!(foo);
}
```
This is not _strictly_ speaking UB, however:
- `Query::get_multiple` cannot work if this is allowed
- bevy_ecs is a pile of unsafe code whose soundness generally depends on the world being in a "correct" state with "no funny business" so it seems best to disallow this
- it is trivial to get bevy to panic inside of functions with safety invariants that have been violated (the entity location is not valid)
- it seems to violate what the safety invariant on `Entities::flush` is trying to ensure
# Objective
An entity spawned with `MaterialMesh2dBundle<M>` cannot be saved and spawned using `DynamicScene` because the `Mesh2dHandle` component does not `impl Reflect`.
## Solution
Add `#[derive(Reflect)]` and `#[reflect(Component)]` to `Mesh2dHandle`, and call `register_type` in `SpritePlugin`. Also add `#[derive(Debug)]` since I'm touching the `derive`s anyway.
# Objective
Animation with shadows crashes with:
```
thread 'main' panicked at 'wgpu error: Validation Error
Caused by:
In Device::create_render_pipeline
note: label = `shadow_pipeline`
error matching VERTEX shader requirements against the pipeline
shader global ResourceBinding { group: 1, binding: 1 } is not available in the layout pipeline layout
visibility flags don't include the shader stage
```
Animation with wireframe crashes with:
```
thread 'main' panicked at 'wgpu error: Validation Error
Caused by:
In Device::create_render_pipeline
note: label = `opaque_mesh_pipeline`
error matching VERTEX shader requirements against the pipeline
shader global ResourceBinding { group: 2, binding: 0 } is not available in the layout pipeline layout
binding is missing from the pipeline layout
```
## Solution
- Fix the bindings
# Objective
- The inability to have multiple active mutable borrows into a query is a common source of borrow-checker pain for users.
- This is a pointless restriction if and only if we can guarantee that the entities they are accessing are unique.
- This could already by bypassed with get_unchecked, but that is an extremely unsafe API.
- Closes https://github.com/bevyengine/bevy/issues/2042.
## Solution
- Add `get_multiple`, `get_multiple_mut` and their unchecked equivalents (`multiple` and `multiple_mut`) to `Query` and `QueryState`.
- Improve the `QueryEntityError` type to provide more useful error information.
## Changelog
- Added `get_multiple`, `get_multiple_mut` and their unchecked equivalents (`multiple` and `multiple_mut`) to Query and QueryState.
## Migration Guide
- The `QueryEntityError` enum now has a `AliasedMutability variant, and returns the offending entity.
## Context
This is a fresh attempt at #3333; rebasing was behaving very badly and it was important to rebase on top of the recent query soundness fixes. Many thanks to all the reviewers in that thread, especially @BoxyUwU for the help with lifetimes.
## To-do
- [x] Add compile fail tests
- [x] Successfully deduplicate code
- [x] Decide what to do about failing doc tests
- [x] Get some reviews for lifetime soundness
# Objective
Add a system parameter `ParamSet` to be used as container for conflicting parameters.
## Solution
Added two methods to the SystemParamState trait, which gives the access used by the parameter. Did the implementation. Added some convenience methods to FilteredAccessSet. Changed `get_conflicts` to return every conflicting component instead of breaking on the first conflicting `FilteredAccess`.
Co-authored-by: bilsen <40690317+bilsen@users.noreply.github.com>
# Objective
Cleans up some duplicated color -> u32 conversion code in `bevy_sprite` and `bevy_ui`
## Solution
Use `as_linear_rgba_u32` which was added recently by #4088
# Objective
Fixes#4344.
## Solution
Add a new component `Text2dBounds` to `Text2dBundle` that specifies the maximum width and height of text. Text will wrap according to this size.
# Objective
- Part of the splitting process of #3692.
## Solution
- Change the `gamepad_connection_system` to run after the `InputSystem` label.
## Reasons
I changed the `gamepad_connection_system` to run after the `InputSystem` instead of in parallel, because this system checks the `GamepadEvent`s which get send inside of the `gamepad_event_system`. This means that the `gamepad_connection_system` could respond to the events one frame later, instead of instantly resulting in one frame lag.
Old possible case:
1. `gamepad_connection_system` (reacts to the `GamepadEvent`s too early)
2. `gamepad_event_system` (sends the `GamepadEvent`s)
New fixed ordering:
1. `gamepad_event_system` (sends the `GamepadEvent`s)
2. `gamepad_connection_system` (reacts to the `GamepadEvent`s)
# Objective
- Closes#335.
- Part of the splitting process of #3503.
## Solution
- Remove the `margins.rs` file containing the `Margins` type.
## Reasons
- It is unused inside of `bevy`.
- The `Rect`/`UiRect` is identical to the `Margins` type and is also used for margins inside of `bevy` (rename of `Rect` happens in #4276)
- Discussion in #3503.
## Changelog
### Removed
- The `Margins` type got removed.
## Migration Guide
- The `Margins` type got removed. To migrate you just have to change every occurrence of `Margins` to `UiRect`.
# Objective
We are currently inserting an `input` into `pressed` even if it is already pressed. This also applies to releasing an input. This is not a big deal, but since we are already checking if the `input` is pressed or not we might as well remove the cost of the value update caused by the `pressed.insert` method.
Related to #4209
## Solution
Only insert or remove input if needed.
related: https://github.com/bevyengine/bevy/pull/3289
In addition to validating shaders early when debug assertions are enabled, use the new [error scopes](https://gpuweb.github.io/gpuweb/#error-scopes) API when creating a shader module.
I chose to keep the early validation (and thereby parsing twice) when debug assertions are enabled in, because it lets as handle errors ourselves and display them with pretty colors, while the error scopes API just gives us a string we can display.
This change pulls in `futures-util` as a new dependency for `future.now_or_never()`. I can inline that part of futures-lite into `bevy_render` to keep the compilation time lower if that's preferred.
# Objective
Fixes `StandardMaterial` texture update (see sample code below).
Most probably fixes#3674 (did not test)
## Solution
Material updates, such as PBR update, reference the underlying `GpuImage`. Like here: 9a7852db0f/crates/bevy_pbr/src/pbr_material.rs (L177)
However, currently the `GpuImage` update may actually happen *after* the material update fetches the gpu image. Resulting in the material actually not being updated for the correct gpu image.
In this pull req, I introduce new systemlabels for the renderassetplugin. Also assigned the RenderAssetPlugin::<Image> to the `PreAssetExtract` stage, so that it is executed before any material updates.
Code to test.
Expected behavior:
* should update to red texture
Unexpected behavior (before this merge):
* texture stays randomly as green one (depending on the execution order of systems)
```rust
use bevy::{
prelude::*,
render::render_resource::{Extent3d, TextureDimension, TextureFormat},
};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.add_system(changes)
.run();
}
struct Iteration(usize);
#[derive(Component)]
struct MyComponent;
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut images: ResMut<Assets<Image>>,
) {
commands.spawn_bundle(PointLightBundle {
point_light: PointLight {
..Default::default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..Default::default()
});
commands.spawn_bundle(PerspectiveCameraBundle {
transform: Transform::from_xyz(-2.0, 0.0, 5.0)
.looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
..Default::default()
});
commands.insert_resource(Iteration(0));
commands
.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Quad::new(Vec2::new(3., 2.)))),
material: materials.add(StandardMaterial {
base_color_texture: Some(images.add(Image::new(
Extent3d {
width: 600,
height: 400,
depth_or_array_layers: 1,
},
TextureDimension::D2,
[0, 255, 0, 128].repeat(600 * 400), // GREEN
TextureFormat::Rgba8Unorm,
))),
..Default::default()
}),
..Default::default()
})
.insert(MyComponent);
}
fn changes(
mut materials: ResMut<Assets<StandardMaterial>>,
mut images: ResMut<Assets<Image>>,
mut iteration: ResMut<Iteration>,
webview_query: Query<&Handle<StandardMaterial>, With<MyComponent>>,
) {
if iteration.0 == 2 {
let material = materials.get_mut(webview_query.single()).unwrap();
let image = images
.get_mut(material.base_color_texture.as_ref().unwrap())
.unwrap();
image
.data
.copy_from_slice(&[255, 0, 0, 255].repeat(600 * 400));
}
iteration.0 += 1;
}
```
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Load skeletal weights and indices from GLTF files. Animate meshes.
## Solution
- Load skeletal weights and indices from GLTF files.
- Added `SkinnedMesh` component and ` SkinnedMeshInverseBindPose` asset
- Added `extract_skinned_meshes` to extract joint matrices.
- Added queue phase systems for enqueuing the buffer writes.
Some notes:
- This ports part of # #2359 to the current main.
- This generates new `BufferVec`s and bind groups every frame. The expectation here is that the number of `Query::get` calls during extract is probably going to be the stronger bottleneck, with up to 256 calls per skinned mesh. Until that is optimized, caching buffers and bind groups is probably a non-concern.
- Unfortunately, due to the uniform size requirements, this means a 16KB buffer is allocated for every skinned mesh every frame. There's probably a few ways to get around this, but most of them require either compute shaders or storage buffers, which are both incompatible with WebGL2.
Co-authored-by: james7132 <contact@jamessliu.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
- Improve transform propagation performance
## Solution
- Use `Changed<Transform>` as part of the `root_query` and `transform_query` to avoid the indirection of having to look up the `Entity` in the `changed_transform_query`
- Get rid of the `changed_transform_query` entirely
- `transform_propagate_system` execution time for `many_cubes -- sphere` dropped from 1.07ms to 0.159ms, an 85% reduction for this system. Frame rate increased from ~42fps to ~44fps
# Objective
A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like:
```rust
#[derive(Component)]
struct Items(Vec<String>);
fn give_sword(query: Query<&mut Items>) {
query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```
> We could then define another struct that wraps `Vec<String>` without anything clashing in the query.
However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this.
Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations.
## Solution
Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field:
```rust
#[derive(Deref)]
struct Foo(String);
#[derive(Deref, DerefMut)]
struct Bar {
name: String,
}
```
This allows us to then remove that pesky `.0`:
```rust
#[derive(Component, Deref, DerefMut)]
struct Items(Vec<String>);
fn give_sword(query: Query<&mut Items>) {
query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```
### Alternatives
There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now).
### Considerations
One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree.
### Additional Context
Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630))
---
## Changelog
- Add `Deref` derive macro (exported to prelude)
- Add `DerefMut` derive macro (exported to prelude)
- Updated most newtypes in examples to use one or both derives
Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
# Objective
Fixes#1529
Run bevy_ecs in miri
## Solution
- Don't set thread names when running in miri rust-lang/miri/issues/1717
- Update `event-listener` to `2.5.2` as previous versions have UB that is detected by miri: [event-listener commit](1fa31c553e)
- Ignore memory leaks when running in miri as they are impossible to track down rust-lang/miri/issues/1481
- Make `table_add_remove_many` test less "many" because miri is really quite slow :)
- Make CI run `RUSTFLAGS="-Zrandomize-layout" MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-tag-raw-pointers -Zmiri-disable-isolation" cargo +nightly miri test -p bevy_ecs`
* Refactor assign_lights_to_clusters to always clear + update clusters, even if the screen size isn't available yet / is zero. This fixes#4167. We still avoid the "expensive" per-light work when the screen size isn't available yet. I also consolidated some logic to eliminate some redundancies.
* Removed _a ton_ of (potentially very large) per-frame reallocations
* Removed `Res<VisiblePointLights>` (a vec) in favor of `Res<GlobalVisiblePointLights>` (a hashmap). We were allocating a new hashmap every frame, the collecting it into a vec every frame, then in another system _re-generating the hashmap_. It is always used like a hashmap, might as well embrace that. We now reuse the same hashmap every frame and dont use any intermediate collections.
* We were re-allocating Clusters aabb and light vectors every frame by re-constructing Clusters every frame. We now re-use the existing collections.
* Reuse per-camera VisiblePointLight vecs when possible instead of allocating them every frame. We now only insert VisiblePointLights if the component doesn't exist yet.
This adds the concept of "default labels" for systems (currently scoped to "parallel systems", but this could just as easily be implemented for "exclusive systems"). Function systems now include their function's `SystemTypeIdLabel` by default.
This enables the following patterns:
```rust
// ordering two systems without manually defining labels
app
.add_system(update_velocity)
.add_system(movement.after(update_velocity))
// ordering sets of systems without manually defining labels
app
.add_system(foo)
.add_system_set(
SystemSet::new()
.after(foo)
.with_system(bar)
.with_system(baz)
)
```
Fixes: #4219
Related to: #4220
Credit to @aevyrie @alice-i-cecile @DJMcNab (and probably others) for proposing (and supporting) this idea about a year ago. I was a big dummy that both shut down this (very good) idea and then forgot I did that. Sorry. You all were right!
# Objective
- Fixes#3970
- To support Bevy's shader abstraction(shader defs, shader imports and hot shader reloading) for compute shaders, I have followed carts advice and change the `PipelinenCache` to accommodate both compute and render pipelines.
## Solution
- renamed `RenderPipelineCache` to `PipelineCache`
- Cached Pipelines are now represented by an enum (render, compute)
- split the `SpecializedPipelines` into `SpecializedRenderPipelines` and `SpecializedComputePipelines`
- updated the game of life example
## Open Questions
- should `SpecializedRenderPipelines` and `SpecializedComputePipelines` be merged and how would we do that?
- should the `get_render_pipeline` and `get_compute_pipeline` methods be merged?
- is pipeline specialization for different entry points a good pattern
Co-authored-by: Kurt Kühnert <51823519+Ku95@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Add a helper for storage buffers similar to `UniformVec`
## Solution
- Add a `StorageBuffer<T, U>` where `T` is the main body of the shader struct without any final variable-sized array member, and `U` is the type of the items in a variable-sized array.
- Use `()` as the type for unwanted parts, e.g. `StorageBuffer<(), Vec4>::default()` would construct a binding that would work with `struct MyType { data: array<vec4<f32>>; }` in WGSL and `StorageBuffer<MyType, ()>::default()` would work with `struct MyType { ... }` in WGSL as long as there are no variable-sized arrays.
- Std430 requires that there is at most one variable-sized array in a storage buffer, that if there is one it is the last member of the binding, and that it has at least one item. `StorageBuffer` handles all of these constraints.
Add support for removing nodes, edges, and subgraphs. This enables live re-wiring of the render graph.
This was something I did to support the MSAA implementation, but it turned out to be unnecessary there. However, it is still useful so here it is in its own PR.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
make bevy ecs a lil bit less unsound
## Solution
yeet unsound API `World::components_mut`:
```rust
use bevy_ecs::prelude::*;
#[derive(Component)]
struct Foo(u8);
#[derive(Debug, Component)]
struct Bar([u8; 100]);
fn main() {
let mut world = World::new();
let e = world.spawn().insert(Foo(0)).id();
*world.components_mut() = Default::default();
let bar = world.entity_mut(e).remove::<Bar>().unwrap();
// oopsies reading memory copied from outside allocation
dbg!(bar);
}
```
# Objective
When loading a gltf scene with a camera, bevy will panic at ``thread 'main' panicked at 'scene contains the unregistered type `bevy_render:📷:bundle::Camera3d`. consider registering the type using `app.register_type::<T>()`', /home/jakob/dev/rust/contrib/bevy/bevy/crates/bevy_scene/src/scene_spawner.rs:332:35``.
## Solution
Register the camera types to fix the panic.
# Objective
As described in #4257, registering an Event twice would cause some systems to miss events on some starts, since the event buffer is cleared + swapped multiple times.
Fixes#4257
## Solution
A simple check whether the event is already registered is added, making adding an Event a second time a no-op.
# Objective
- Fixes#4208
## Solution
- Adds a check before inserting into an `Input`'s `just_released` set, in the same way that one exists for adding into the `just_pressed` set.
# Objective
The [glTF spec](8e798b02d2/specification/2.0/Specification.adoc (395-double-sided)) the `doubleSided` has the following to say about the `doubleSided` boolean:
> When this value is false, back-face culling is enabled, i.e., only front-facing triangles are rendered.
> When this value is true, back-face culling is disabled and double sided lighting is enabled. The back-face MUST have its normals reversed before the lighting equation is evaluated.
## Solution
Disable backface culling when `doubleSided: true`.
# Objective
- Make visible how much time is spent building the Opaque3d, AlphaMask3d, and Transparent3d passes
## Solution
- Add a `trace` feature to `bevy_core_pipeline`
- Add tracy spans around the three passes
- I didn't do this for shadows, sprites, etc as they are only one pass in the node. Perhaps it should be split into 3 nodes to allow insertion of other nodes between...?
# Objective
- Reduce time spent in the `check_visibility` system
## Solution
- Use `Vec3A` for all bounding volume types to leverage SIMD optimisations and to avoid repeated runtime conversions from `Vec3` to `Vec3A`
- Inline all bounding volume intersection methods
- Add on-the-fly calculated `Aabb` -> `Sphere` and do `Sphere`-`Frustum` intersection tests before `Aabb`-`Frustum` tests. This is faster for `many_cubes` but could be slower in other cases where the sphere test gives a false-positive that the `Aabb` test discards. Also, I tested precalculating the `Sphere`s and inserting them alongside the `Aabb` but this was slower.
- Do not test meshes against the far plane. Apparently games don't do this anymore with infinite projections, and it's one fewer plane to test against. I made it optional and still do the test for culling lights but that is up for discussion.
- These collectively reduce `check_visibility` execution time in `many_cubes -- sphere` from 2.76ms to 1.48ms and increase frame rate from ~42fps to ~44fps
Tracing added support for "inline span entering", which cuts down on a lot of complexity:
```rust
let span = info_span!("my_span").entered();
```
This adapts our code to use this pattern where possible, and updates our docs to recommend it.
This produces equivalent tracing behavior. Here is a side by side profile of "before" and "after" these changes.
![image](https://user-images.githubusercontent.com/2694663/158912137-b0aa6dc8-c603-425f-880f-6ccf5ad1b7ef.png)
# Objective
- Support compressed textures including 'universal' formats (ETC1S, UASTC) and transcoding of them to
- Support `.dds`, `.ktx2`, and `.basis` files
## Solution
- Fixes https://github.com/bevyengine/bevy/issues/3608 Look there for more details.
- Note that the functionality is all enabled through non-default features. If it is desirable to enable some by default, I can do that.
- The `basis-universal` crate, used for `.basis` file support and for transcoding, is built on bindings against a C++ library. It's not feasible to rewrite in Rust in a short amount of time. There are no Rust alternatives of which I am aware and it's specialised code. In its current state it doesn't support the wasm target, but I don't know for sure. However, it is possible to build the upstream C++ library with emscripten, so there is perhaps a way to add support for web too with some shenanigans.
- There's no support for transcoding from BasisLZ/ETC1S in KTX2 files as it was quite non-trivial to implement and didn't feel important given people could use `.basis` files for ETC1S.
# Objective
- Fixes#3300
- `RunSystem` is messy
## Solution
- Adds the trick theorised in https://github.com/bevyengine/bevy/issues/3300#issuecomment-991791234
P.S. I also want this for an experimental refactoring of `Assets`, to remove the duplication of `Events<AssetEvent<T>>`
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Hierarchy tools are not just used for `Transform`: they are also used for scenes.
- In the future there's interest in using them for other features, such as visiibility inheritance.
- The fact that these tools are found in `bevy_transform` causes a great deal of user and developer confusion
- Fixes#2758.
## Solution
- Split `bevy_transform` into two!
- Make everything work again.
Note that this is a very tightly scoped PR: I *know* there are code quality and docs issues that existed in bevy_transform that I've just moved around. We should fix those in a seperate PR and try to merge this ASAP to reduce the bitrot involved in splitting an entire crate.
## Frustrations
The API around `GlobalTransform` is a mess: we have massive code and docs duplication, no link between the two types and no clear way to extend this to other forms of inheritance.
In the medium-term, I feel pretty strongly that `GlobalTransform` should be replaced by something like `Inherited<Transform>`, which lives in `bevy_hierarchy`:
- avoids code duplication
- makes the inheritance pattern extensible
- links the types at the type-level
- allows us to remove all references to inheritance from `bevy_transform`, making it more useful as a standalone crate and cleaning up its docs
## Additional context
- double-blessed by @cart in https://github.com/bevyengine/bevy/issues/4141#issuecomment-1063592414 and https://github.com/bevyengine/bevy/issues/2758#issuecomment-913810963
- preparation for more advanced / cleaner hierarchy tools: go read https://github.com/bevyengine/rfcs/pull/53 !
- originally attempted by @finegeometer in #2789. It was a great idea, just needed more discussion!
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
**Problem**
- whenever you want more than one of the builtin cameras (for example multiple windows, split screen, portals), you need to add a render graph node that executes the correct sub graph, extract the camera into the render world and add the correct `RenderPhase<T>` components
- querying for the 3d camera is annoying because you need to compare the camera's name to e.g. `CameraPlugin::CAMERA_3d`
**Solution**
- Introduce the marker types `Camera3d`, `Camera2d` and `CameraUi`
-> `Query<&mut Transform, With<Camera3d>>` works
- `PerspectiveCameraBundle::new_3d()` and `PerspectiveCameraBundle::<Camera3d>::default()` contain the `Camera3d` marker
- `OrthographicCameraBundle::new_3d()` has `Camera3d`, `OrthographicCameraBundle::new_2d()` has `Camera2d`
- remove `ActiveCameras`, `ExtractedCameraNames`
- run 2d, 3d and ui passes for every camera of their respective marker
-> no custom setup for multiple windows example needed
**Open questions**
- do we need a replacement for `ActiveCameras`? What about a component `ActiveCamera { is_active: bool }` similar to `Visibility`?
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Make insertion of uniform components faster
## Solution
- Use batch insertion in the prepare_uniform_components system
- Improves `many_cubes -- sphere` from ~42fps to ~43fps
Co-authored-by: François <mockersf@gmail.com>
# Objective
fix cluster tilesize and tilecount calculations.
Fixes https://github.com/bevyengine/bevy/issues/4127 & https://github.com/bevyengine/bevy/issues/3596
## Solution
- calculate tilesize as smallest integers such that dimensions.xy() tiles will cover the screen
- calculate final dimensions as smallest integers such that final dimensions * tilesize will cover the screen
there is more cleanup that could be done in these functions. a future PR will likely remove the tilesize completely, so this is just a minimal change set to fix the current bug at small screen sizes
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Lets say we need to rotate stretched object for this purpose we can created stretched `Child` and add as child to `Parent`, later we can rotate `Parent`, `Child` in this situation should rotate keeping it form, it is not the case with `SpriteBundle` currently. If you try to do it with `SpriteBundle` it will deform.
## Solution
My pull request fixes order of transformations to scale -> rotate -> translate, with this fix `SpriteBundle` behaves as expected in described rotation, without deformation. Here is quote from "Essential Mathematics for Games":
> Generally, the desired order we wish to use for these transforms is to scale first, then rotate, then translate. Scaling first gives us the scaling along the axes we expect. We can then rotate around the origin of the frame, and then translate it into place.
I'm must say when I was using `MaterialMesh2dBundle` it behaves correctly in both cases with `bevy main` and with my fix, don't know why, was not able to figure it out why there is difference.
here is code I was using for testing:
```rust
use bevy::{
prelude::*,
render::render_resource::{Extent3d, TextureDimension, TextureFormat},
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};
fn main() {
let mut app = App::new();
app.insert_resource(ClearColor(Color::rgb(0.1, 0.2, 0.3)))
.add_plugins(DefaultPlugins)
.add_startup_system(setup);
app.run();
}
fn setup(
mut commands: Commands,
mut images: ResMut<Assets<Image>>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let mut c = OrthographicCameraBundle::new_2d();
c.orthographic_projection.scale = 1.0 / 10.0;
commands.spawn_bundle(c);
// note: mesh somehow works for both variants
// let quad: Mesh2dHandle = meshes.add(Mesh::from(shape::Quad::default())).into();
// let child = commands
// .spawn_bundle(MaterialMesh2dBundle {
// mesh: quad.clone(),
// transform: Transform::from_translation(Vec3::new(0.0, 0.0, -1.0))
// .with_scale(Vec3::new(10.0, 1.0, 1.0)),
// material: materials.add(ColorMaterial::from(Color::BLACK)),
// ..Default::default()
// })
// .id();
// commands
// .spawn_bundle(MaterialMesh2dBundle {
// mesh: quad,
// transform: Transform::from_rotation(Quat::from_rotation_z(0.78))
// .with_translation(Vec3::new(0.0, 0.0, 10.0)),
// material: materials.add(ColorMaterial::from(Color::WHITE)),
// ..Default::default()
// })
// .push_children(&[child]);
let white = images.add(get_image(Color::rgb(1.0, 1.0, 1.0)));
let black = images.add(get_image(Color::rgb(0.0, 0.0, 0.0)));
let child = commands
.spawn_bundle(SpriteBundle {
texture: black,
transform: Transform::from_translation(Vec3::new(0.0, 0.0, -1.0))
.with_scale(Vec3::new(10.0, 1.0, 1.0)),
..Default::default()
})
.id();
commands
.spawn_bundle(SpriteBundle {
texture: white,
transform: Transform::from_rotation(Quat::from_rotation_z(0.78))
.with_translation(Vec3::new(0.0, 0.0, 10.0)),
..Default::default()
})
.push_children(&[child]);
}
fn get_image(color: Color) -> Image {
let mut bytes = Vec::with_capacity((1 * 1 * 4 * 4) as usize);
let color = color.as_rgba_f32();
bytes.extend(color[0].to_le_bytes());
bytes.extend(color[1].to_le_bytes());
bytes.extend(color[2].to_le_bytes());
bytes.extend(1.0_f32.to_le_bytes());
Image::new(
Extent3d {
width: 1,
height: 1,
depth_or_array_layers: 1,
},
TextureDimension::D2,
bytes,
TextureFormat::Rgba32Float,
)
}
```
here is screenshot with `bevy main` and my fix:
![examples](https://user-images.githubusercontent.com/816292/151708304-c07c891e-da70-43f4-9c41-f85fa166a96d.png)
# Objective
provide some customisation for default cluster setup
avoid "cluster index lists is full" in all cases (using a strategy outlined by @superdump)
## Solution
Add ClusterConfig enum (which can be inserted into a view at any time) to allow specifying cluster setup with variants:
- None (do not do any light assignment - for views which do not require light info, e.g. minimaps etc)
- Single (one cluster)
- XYZ (explicit cluster counts in each dimension)
- FixedZ (most similar to current - specify Z-slices and total, then x and y counts are dynamically determined to give approximately square clusters based on current aspect ratio)
Defaults to FixedZ { total: 4096, z: 24 } which is similar to the current setup.
Per frame, estimate the number of indices that would be required for the current config and decrease the cluster counts / increase the cluster sizes in the x and y dimensions if the index list would be too small.
notes:
- I didn't put ClusterConfig in the camera bundles to avoid introducing a dependency from bevy_render to bevy_pbr. the ClusterConfig enum comes with a pbr-centric impl block so i didn't want to move that into bevy_render either.
- ~Might want to add None variant to cluster config for views that don't care about lights?~
- Not well tested for orthographic
- ~there's a cluster_muck branch on my repo which includes some diagnostics / a modified lighting example which may be useful for tyre-kicking~ (outdated, i will bring it up to date if required)
anecdotal timings:
FPS on the lighting demo is negligibly better (~5%), maybe due to a small optimisation constraining the light aabb to be in front of the camera
FPS on the lighting demo with 100 extra lights added is ~33% faster, and also renders correctly as the cluster index count is no longer exceeded
# Objective
- Fix#2163
- Allow configuration of thread pools through `DefaultTaskPoolOptions`
## Solution
- `TaskPoolThreadAssignmentPolicy` was already public but not exported. Export it.
# Objective
Fixes#4133
## Solution
Add comparisons to make sure we don't dereference `Mut<>` in the two places where `Transform` is being mutated. `GlobalTransform` implementation already works properly so fixing Transform automatically fixed that as well.
## Objective
Currently, all directional and point lights have their viewing frusta recalculated every frame, even if they have not moved or been disabled/enabled.
## Solution
The relevant systems now make use of change detection to only update those lights whose viewing frusta may have changed.
# Objective
- Improve documentation.
- Provide helper functions for common uses of `Windows` relating to getting the primary `Window`.
- Reduce repeated `Window` code.
# Solution
- Adds infallible `primary()` and `primary_mut()` functions with standard error text. This replaces the commonly used `get_primary().unwrap()` seen throughout bevy which has inconsistent or nonexistent error messages.
- Adds `scale_factor(WindowId)` to replace repeated code blocks throughout.
# Considerations
- The added functions can panic if the primary window does not exist.
- It is very uncommon for the primary window to not exist, as seen by the regular use of `get_primary().unwrap()`. Most users will have a single window and will need to reference the primary window in their code multiple times.
- The panic provides a consistent error message to make this class of error easy to spot from the panic text.
- This follows the established standard of short names for infallible-but-unlikely-to-panic functions in bevy.
- Removes line noise for common usage of `Windows`.
# Objective
Fixes#3744
## Solution
The old code used the formula `normal . center + d + radius <= 0` to determine if the sphere with center `center` and radius `radius` is outside the plane with normal `normal` and distance from origin `d`. This only works if `normal` is normalized, which is not necessarily the case. Instead, `normal` and `d` are both multiplied by some factor that `radius` isn't multiplied by. So the additional code multiplied `radius` by that factor.
## Objective
A step towards `f64` `Transform`s (#1680). For now, I am rolling my own `Transform`. But in order to derive Reflect, I specifically need `DQuat` to be reflectable.
```rust
#[derive(Component, Reflect, Copy, Clone, PartialEq, Debug)]
#[reflect(Component, PartialEq)]
pub struct Transform {
pub translation: DVec3,
pub rotation: DQuat, // error: the trait `bevy::prelude::Reflect` is not implemented for `DQuat`
pub scale: DVec3,
}
```
## Solution
I have added a `DQuat` impl for `Reflect` alongside the other glam impls. I've also added impls for `DMat3` and `DMat4` to match.
# Objective
- Reduce power usage for games when not focused.
- Reduce power usage to ~0 when a desktop application is minimized (opt-in).
- Reduce power usage when focused, only updating on a `winit` event, or the user sends a redraw request. (opt-in)
https://user-images.githubusercontent.com/2632925/156904387-ec47d7de-7f06-4c6f-8aaf-1e952c1153a2.mp4
Note resource usage in the Task Manager in the above video.
## Solution
- Added a type `UpdateMode` that allows users to specify how the winit event loop is updated, without exposing winit types.
- Added two fields to `WinitConfig`, both with the `UpdateMode` type. One configures how the application updates when focused, and the other configures how the application behaves when it is not focused. Users can modify this resource manually to set the type of event loop control flow they want.
- For convenience, two functions were added to `WinitConfig`, that provide reasonable presets: `game()` (default) and `desktop_app()`.
- The `game()` preset, which is used by default, is unchanged from current behavior with one exception: when the app is out of focus the app updates at a minimum of 10fps, or every time a winit event is received. This has a huge positive impact on power use and responsiveness on my machine, which will otherwise continue running the app at many hundreds of fps when out of focus or minimized.
- The `desktop_app()` preset is fully reactive, only updating when user input (winit event) is supplied or a `RedrawRequest` event is sent. When the app is out of focus, it only updates on `Window` events - i.e. any winit event that directly interacts with the window. What this means in practice is that the app uses *zero* resources when minimized or not interacted with, but still updates fluidly when the app is out of focus and the user mouses over the application.
- Added a `RedrawRequest` event so users can force an update even if there are no events. This is useful in an application when you want to, say, run an animation even when the user isn't providing input.
- Added an example `low_power` to demonstrate these changes
## Usage
Configuring the event loop:
```rs
use bevy::winit::{WinitConfig};
// ...
.insert_resource(WinitConfig::desktop_app()) // preset
// or
.insert_resource(WinitConfig::game()) // preset
// or
.insert_resource(WinitConfig{ .. }) // manual
```
Requesting a redraw:
```rs
use bevy:🪟:RequestRedraw;
// ...
fn request_redraw(mut event: EventWriter<RequestRedraw>) {
event.send(RequestRedraw);
}
```
## Other details
- Because we have a single event loop for multiple windows, every time I've mentioned "focused" above, I more precisely mean, "if at least one bevy window is focused".
- Due to a platform bug in winit (https://github.com/rust-windowing/winit/issues/1619), we can't simply use `Window::request_redraw()`. As a workaround, this PR will temporarily set the window mode to `Poll` when a redraw is requested. This is then reset to the user's `WinitConfig` setting on the next frame.
# Objective
Currently, errors in the render graph runner are exposed via a `Result::unwrap()` panic message, which dumps the debug representation of the error.
## Solution
This PR updates `render_system` to log the chain of errors, followed by an explicit panic:
```
ERROR bevy_render::renderer: Error running render graph:
ERROR bevy_render::renderer: > encountered an error when running a sub-graph
ERROR bevy_render::renderer: > tried to pass inputs to sub-graph "outline_graph", which has no input slots
thread 'main' panicked at 'Error running render graph: encountered an error when running a sub-graph', /[redacted]/bevy/crates/bevy_render/src/renderer/mod.rs:44:9
```
Some errors' `Display` impls (via `thiserror`) have also been updated to provide more detail about the cause of the error.
# Objective
- `Assets<T>::iter_mut` sends `Modified` event for all assets first, then returns the iterator
- This means that events could be sent for assets that would not have been mutated if iteration was stopped before
## Solution
- Send `Modified` event when assets are iterated over.
Co-authored-by: François <8672791+mockersf@users.noreply.github.com>