# Objective
While trying out the lint `unsafe_op_in_unsafe_fn` I noticed that `insert_resource_by_id` didn't drop the old value if it already existed, and reimplemented `Column::replace` manually for no apparent reason.
## Solution
- use `Column::replace` and add a test expecting the correct drop count
---
## Changelog
- `World::insert_resource_by_id` will now correctly drop the old resource value, if one already existed
# Objective
- The `Display` impl for `ReflectPathError` is pretty unspecific (e.g. `the current struct doesn't have a field with the given name`
- it has info for better messages available
## Solution
- make the display impl more descriptive by including values from the type
# Objective
- `ReflectMut` served no purpose that wasn't met by `Mut<dyn Reflect>` which is easier to understand since you have to deal with fewer types
- there is another `ReflectMut` type that could be confused with this one
## Solution/Changelog
- relax `T: ?Sized` bound in `Mut<T>`
- replace all instances of `ReflectMut` with `Mut<dyn Reflect>`
# Objective
Provide a safe API to access an `EntityMut`'s `World`.
## Solution
* Add `EntityMut::into_world_mut` for safe access to the entity's world.
---
## Changelog
* Add `EntityMut::into_world_mut` for safe access to the entity's world.
# Objective
`ShaderData` is marked as public, but is an internal type only used by one other
internal type, so it should be made private.
## Solution
`ShaderData` is only used in `ShaderCache`, and the latter is private,
so there is no need to make the former public. This change removes the
`pub` keyword from `ShaderData`, hidding it as the implementation detail
it is.
Split from #5600
# Objective
- I often have UI nodes that are completely transparent and just for organisation
- Don't render them
- I doesn't bring a lot of improvements, but it doesn't add a lot of complexity either
*This PR description is an edited copy of #5007, written by @alice-i-cecile.*
# Objective
Follow-up to https://github.com/bevyengine/bevy/pull/2254. The `Resource` trait currently has a blanket implementation for all types that meet its bounds.
While ergonomic, this results in several drawbacks:
* it is possible to make confusing, silent mistakes such as inserting a function pointer (Foo) rather than a value (Foo::Bar) as a resource
* it is challenging to discover if a type is intended to be used as a resource
* we cannot later add customization options (see the [RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/27-derive-component.md) for the equivalent choice for Component).
* dependencies can use the same Rust type as a resource in invisibly conflicting ways
* raw Rust types used as resources cannot preserve privacy appropriately, as anyone able to access that type can read and write to internal values
* we cannot capture a definitive list of possible resources to display to users in an editor
## Notes to reviewers
* Review this commit-by-commit; there's effectively no back-tracking and there's a lot of churn in some of these commits.
*ira: My commits are not as well organized :')*
* I've relaxed the bound on Local to Send + Sync + 'static: I don't think these concerns apply there, so this can keep things simple. Storing e.g. a u32 in a Local is fine, because there's a variable name attached explaining what it does.
* I think this is a bad place for the Resource trait to live, but I've left it in place to make reviewing easier. IMO that's best tackled with https://github.com/bevyengine/bevy/issues/4981.
## Changelog
`Resource` is no longer automatically implemented for all matching types. Instead, use the new `#[derive(Resource)]` macro.
## Migration Guide
Add `#[derive(Resource)]` to all types you are using as a resource.
If you are using a third party type as a resource, wrap it in a tuple struct to bypass orphan rules. Consider deriving `Deref` and `DerefMut` to improve ergonomics.
`ClearColor` no longer implements `Component`. Using `ClearColor` as a component in 0.8 did nothing.
Use the `ClearColorConfig` in the `Camera3d` and `Camera2d` components instead.
Co-authored-by: Alice <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: devil-ira <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- I wanted to have controls independent from keyboard layout and found that bevy doesn't have a proper implementation for that
## Solution
- I created a `ScanCode` enum with two hundreds scan codes and updated `keyboard_input_system` to include and update `ResMut<Input<ScanCode>>`
- closes both https://github.com/bevyengine/bevy/issues/2052 and https://github.com/bevyengine/bevy/issues/862
Co-authored-by: Bleb1k <91003089+Bleb1k@users.noreply.github.com>
#4197 intended to remove all `pub` constructors of `Children` and `Parent` and it seems like this one was missed.
Co-authored-by: devil-ira <justthecooldude@gmail.com>
# Objective
- Fixes#5544
- Part of the splitting process of #3692.
## Solution
- Document everything in the `gamepad.rs` file.
- Add a doc example for mocking gamepad input.
---
## Changelog
- Added and updated the documentation inside of the `gamepad.rs` file.
# Objective
- Similar to #5512 , the `View` struct definition in the shaders in `bevy_sprite` and `bevy_ui` were out of sync with the rust-side `ViewUniform`. Only `view_proj` was being used and is the first member and as those shaders are not customisable it makes little difference in practice, unlike for `Mesh2d`.
## Solution
- Sync shader `View` struct definition in `bevy_sprite` and `bevy_ui` with the correct definition that matches `ViewUniform`
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Change frametimediagnostic from seconds to milliseconds because this will always be less than one seconds and is the common diagnostic display unit for game engines.
## Solution
- multiplied the existing value by 1000
---
## Changelog
Frametimes are now reported in milliseconds
Co-authored-by: Syama Mishra <38512086+SyamaMishra@users.noreply.github.com>
Co-authored-by: McSpidey <mcspidey@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
In Bevy 0.8, the default filter mode was changed to linear (#4465). I believe this is a sensible default, but it's also very common to want to use point filtering (e.g. for pixel art games).
## Solution
I am proposing including `bevy_render::texture::ImageSettings` in the Bevy prelude so it is more ergonomic to change the filtering in such cases.
---
## Changelog
### Added
- Added `bevy_render::texture::ImageSettings` to prelude.
# Objective
Add reflect/from reflect impls for NonZero integer types. I'm guessing these haven't been added yet because no one has needed them as of yet.
# Objective
Simplify the worldquery trait hierarchy as much as possible by putting it all in one trait. If/when gats are stabilised this can be trivially migrated over to use them, although that's not why I made this PR, those reasons are:
- Moves all of the conceptually related unsafe code for a worldquery next to eachother
- Removes now unnecessary traits simplifying the "type system magic" in bevy_ecs
---
## Changelog
All methods/functions/types/consts on `FetchState` and `Fetch` traits have been moved to the `WorldQuery` trait and the other traits removed. `WorldQueryGats` now only contains an `Item` and `Fetch` assoc type.
## Migration Guide
Implementors should move items in impls to the `WorldQuery/Gats` traits and remove any `Fetch`/`FetchState` impls
Any use sites of items in the `Fetch`/`FetchState` traits should be updated to use the `WorldQuery` trait items instead
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Fixes#5384 and maybe other issues around window closing/app not exiting
## Solution
There are three systems involved in exiting when closing a window:
- `close_when_requested` asking Winit to close the window in stage `Update`
- `exit_on_all_closed` exiting when no window remains opened in stage `Update`
- `change_window` removing windows that are closed in stage `PostUpdate`
This ordering meant that when closing a window, we had to run one more frame to actually exit. As there was no window, panics could occur in systems assuming there was a window. In case of Bevy app using a low power options, that means waiting for the timeout before actually exiting the app (60 seconds by default)
This PR changes the ordering so that `exit_on_all_closed` happens after `change_window` in the same frame, so there isn't an extra frame without window
> In draft until #4761 is merged. See the relevant commits [here](a85fe94a18).
---
# Objective
Update enums across Bevy to use the new enum reflection and get rid of `#[reflect_value(...)]` usages.
## Solution
Find and replace all[^1] instances of `#[reflect_value(...)]` on enum types.
---
## Changelog
- Updated all[^1] reflected enums to implement `Enum` (i.e. they are no longer `ReflectRef::Value`)
## Migration Guide
Bevy-defined enums have been updated to implement `Enum` and are not considered value types (`ReflectRef::Value`) anymore. This means that their serialized representations will need to be updated. For example, given the Bevy enum:
```rust
pub enum ScalingMode {
None,
WindowSize,
Auto { min_width: f32, min_height: f32 },
FixedVertical(f32),
FixedHorizontal(f32),
}
```
You will need to update the serialized versions accordingly.
```js
// OLD FORMAT
{
"type": "bevy_render:📷:projection::ScalingMode",
"value": FixedHorizontal(720),
},
// NEW FORMAT
{
"type": "bevy_render:📷:projection::ScalingMode",
"enum": {
"variant": "FixedHorizontal",
"tuple": [
{
"type": "f32",
"value": 720,
},
],
},
},
```
This may also have other smaller implications (such as `Debug` representation), but serialization is probably the most prominent.
[^1]: All enums except `HandleId` as neither `Uuid` nor `AssetPathId` implement the reflection traits
# Objective
> This is a revival of #1347. Credit for the original PR should go to @Davier.
Currently, enums are treated as `ReflectRef::Value` types by `bevy_reflect`. Obviously, there needs to be better a better representation for enums using the reflection API.
## Solution
Based on prior work from @Davier, an `Enum` trait has been added as well as the ability to automatically implement it via the `Reflect` derive macro. This allows enums to be expressed dynamically:
```rust
#[derive(Reflect)]
enum Foo {
A,
B(usize),
C { value: f32 },
}
let mut foo = Foo::B(123);
assert_eq!("B", foo.variant_name());
assert_eq!(1, foo.field_len());
let new_value = DynamicEnum::from(Foo::C { value: 1.23 });
foo.apply(&new_value);
assert_eq!(Foo::C{value: 1.23}, foo);
```
### Features
#### Derive Macro
Use the `#[derive(Reflect)]` macro to automatically implement the `Enum` trait for enum definitions. Optionally, you can use `#[reflect(ignore)]` with both variants and variant fields, just like you can with structs. These ignored items will not be considered as part of the reflection and cannot be accessed via reflection.
```rust
#[derive(Reflect)]
enum TestEnum {
A,
// Uncomment to ignore all of `B`
// #[reflect(ignore)]
B(usize),
C {
// Uncomment to ignore only field `foo` of `C`
// #[reflect(ignore)]
foo: f32,
bar: bool,
},
}
```
#### Dynamic Enums
Enums may be created/represented dynamically via the `DynamicEnum` struct. The main purpose of this struct is to allow enums to be deserialized into a partial state and to allow dynamic patching. In order to ensure conversion from a `DynamicEnum` to a concrete enum type goes smoothly, be sure to add `FromReflect` to your derive macro.
```rust
let mut value = TestEnum::A;
// Create from a concrete instance
let dyn_enum = DynamicEnum::from(TestEnum::B(123));
value.apply(&dyn_enum);
assert_eq!(TestEnum::B(123), value);
// Create a purely dynamic instance
let dyn_enum = DynamicEnum::new("TestEnum", "A", ());
value.apply(&dyn_enum);
assert_eq!(TestEnum::A, value);
```
#### Variants
An enum value is always represented as one of its variants— never the enum in its entirety.
```rust
let value = TestEnum::A;
assert_eq!("A", value.variant_name());
// Since we are using the `A` variant, we cannot also be the `B` variant
assert_ne!("B", value.variant_name());
```
All variant types are representable within the `Enum` trait: unit, struct, and tuple.
You can get the current type like:
```rust
match value.variant_type() {
VariantType::Unit => println!("A unit variant!"),
VariantType::Struct => println!("A struct variant!"),
VariantType::Tuple => println!("A tuple variant!"),
}
```
> Notice that they don't contain any values representing the fields. These are purely tags.
If a variant has them, you can access the fields as well:
```rust
let mut value = TestEnum::C {
foo: 1.23,
bar: false
};
// Read/write specific fields
*value.field_mut("bar").unwrap() = true;
// Iterate over the entire collection of fields
for field in value.iter_fields() {
println!("{} = {:?}", field.name(), field.value());
}
```
#### Variant Swapping
It might seem odd to group all variant types under a single trait (why allow `iter_fields` on a unit variant?), but the reason this was done ~~is to easily allow *variant swapping*.~~ As I was recently drafting up the **Design Decisions** section, I discovered that other solutions could have been made to work with variant swapping. So while there are reasons to keep the all-in-one approach, variant swapping is _not_ one of them.
```rust
let mut value: Box<dyn Enum> = Box::new(TestEnum::A);
value.set(Box::new(TestEnum::B(123))).unwrap();
```
#### Serialization
Enums can be serialized and deserialized via reflection without needing to implement `Serialize` or `Deserialize` themselves (which can save thousands of lines of generated code). Below are the ways an enum can be serialized.
> Note, like the rest of reflection-based serialization, the order of the keys in these representations is important!
##### Unit
```json
{
"type": "my_crate::TestEnum",
"enum": {
"variant": "A"
}
}
```
##### Tuple
```json
{
"type": "my_crate::TestEnum",
"enum": {
"variant": "B",
"tuple": [
{
"type": "usize",
"value": 123
}
]
}
}
```
<details>
<summary>Effects on Option</summary>
This ends up making `Option` look a little ugly:
```json
{
"type": "core::option::Option<usize>",
"enum": {
"variant": "Some",
"tuple": [
{
"type": "usize",
"value": 123
}
]
}
}
```
</details>
##### Struct
```json
{
"type": "my_crate::TestEnum",
"enum": {
"variant": "C",
"struct": {
"foo": {
"type": "f32",
"value": 1.23
},
"bar": {
"type": "bool",
"value": false
}
}
}
}
```
## Design Decisions
<details>
<summary><strong>View Section</strong></summary>
This section is here to provide some context for why certain decisions were made for this PR, alternatives that could have been used instead, and what could be improved upon in the future.
### Variant Representation
One of the biggest decisions was to decide on how to represent variants. The current design uses a "all-in-one" design where unit, tuple, and struct variants are all simultaneously represented by the `Enum` trait. This is not the only way it could have been done, though.
#### Alternatives
##### 1. Variant Traits
One way of representing variants would be to define traits for each variant, implementing them whenever an enum featured at least one instance of them. This would allow us to define variants like:
```rust
pub trait Enum: Reflect {
fn variant(&self) -> Variant;
}
pub enum Variant<'a> {
Unit,
Tuple(&'a dyn TupleVariant),
Struct(&'a dyn StructVariant),
}
pub trait TupleVariant {
fn field_len(&self) -> usize;
// ...
}
```
And then do things like:
```rust
fn get_tuple_len(foo: &dyn Enum) -> usize {
match foo.variant() {
Variant::Tuple(tuple) => tuple.field_len(),
_ => panic!("not a tuple variant!")
}
}
```
The reason this PR does not go with this approach is because of the fact that variants are not separate types. In other words, we cannot implement traits on specific variants— these cover the *entire* enum. This means we offer an easy footgun:
```rust
let foo: Option<i32> = None;
let my_enum = Box::new(foo) as Box<dyn TupleVariant>;
```
Here, `my_enum` contains `foo`, which is a unit variant. However, since we need to implement `TupleVariant` for `Option` as a whole, it's possible to perform such a cast. This is obviously wrong, but could easily go unnoticed. So unfortunately, this makes it not a good candidate for representing variants.
##### 2. Variant Structs
To get around the issue of traits necessarily needing to apply to both the enum and its variants, we could instead use structs that are created on a per-variant basis. This was also considered but was ultimately [[removed](71d27ab3c6) due to concerns about allocations.
Each variant struct would probably look something like:
```rust
pub trait Enum: Reflect {
fn variant_mut(&self) -> VariantMut;
}
pub enum VariantMut<'a> {
Unit,
Tuple(TupleVariantMut),
Struct(StructVariantMut),
}
struct StructVariantMut<'a> {
fields: Vec<&'a mut dyn Reflect>,
field_indices: HashMap<Cow<'static, str>, usize>
}
```
This allows us to isolate struct variants into their own defined struct and define methods specifically for their use. It also prevents users from casting to it since it's not a trait. However, this is not an optimal solution. Both `field_indices` and `fields` will require an allocation (remember, a `Box<[T]>` still requires a `Vec<T>` in order to be constructed). This *might* be a problem if called frequently enough.
##### 3. Generated Structs
The original design, implemented by @Davier, instead generates structs specific for each variant. So if we had a variant path like `Foo::Bar`, we'd generate a struct named `FooBarWrapper`. This would be newtyped around the original enum and forward tuple or struct methods to the enum with the chosen variant.
Because it involved using the `Tuple` and `Struct` traits (which are also both bound on `Reflect`), this meant a bit more code had to be generated. For a single struct variant with one field, the generated code amounted to ~110LoC. However, each new field added to that variant only added ~6 more LoC.
In order to work properly, the enum had to be transmuted to the generated struct:
```rust
fn variant(&self) -> crate::EnumVariant<'_> {
match self {
Foo::Bar {value: i32} => {
let wrapper_ref = unsafe {
std::mem::transmute::<&Self, &FooBarWrapper>(self)
};
crate::EnumVariant::Struct(wrapper_ref as &dyn crate::Struct)
}
}
}
```
This works because `FooBarWrapper` is defined as `repr(transparent)`.
Out of all the alternatives, this would probably be the one most likely to be used again in the future. The reasons for why this PR did not continue to use it was because:
* To reduce generated code (which would hopefully speed up compile times)
* To avoid cluttering the code with generated structs not visible to the user
* To keep bevy_reflect simple and extensible (these generated structs act as proxies and might not play well with current or future systems)
* To avoid additional unsafe blocks
* My own misunderstanding of @Davier's code
That last point is obviously on me. I misjudged the code to be too unsafe and unable to handle variant swapping (which it probably could) when I was rebasing it. Looking over it again when writing up this whole section, I see that it was actually a pretty clever way of handling variant representation.
#### Benefits of All-in-One
As stated before, the current implementation uses an all-in-one approach. All variants are capable of containing fields as far as `Enum` is concerned. This provides a few benefits that the alternatives do not (reduced indirection, safer code, etc.).
The biggest benefit, though, is direct field access. Rather than forcing users to have to go through pattern matching, we grant direct access to the fields contained by the current variant. The reason we can do this is because all of the pattern matching happens internally. Getting the field at index `2` will automatically return `Some(...)` for the current variant if it has a field at that index or `None` if it doesn't (or can't).
This could be useful for scenarios where the variant has already been verified or just set/swapped (or even where the type of variant doesn't matter):
```rust
let dyn_enum: &mut dyn Enum = &mut Foo::Bar {value: 123};
// We know it's the `Bar` variant
let field = dyn_enum.field("value").unwrap();
```
Reflection is not a type-safe abstraction— almost every return value is wrapped in `Option<...>`. There are plenty of places to check and recheck that a value is what Reflect says it is. Forcing users to have to go through `match` each time they want to access a field might just be an extra step among dozens of other verification processes.
Some might disagree, but ultimately, my view is that the benefit here is an improvement to the ergonomics and usability of reflected enums.
</details>
---
## Changelog
### Added
* Added `Enum` trait
* Added `Enum` impl to `Reflect` derive macro
* Added `DynamicEnum` struct
* Added `DynamicVariant`
* Added `EnumInfo`
* Added `VariantInfo`
* Added `StructVariantInfo`
* Added `TupleVariantInfo`
* Added `UnitVariantInfo`
* Added serializtion/deserialization support for enums
* Added `EnumSerializer`
* Added `VariantType`
* Added `VariantFieldIter`
* Added `VariantField`
* Added `enum_partial_eq(...)`
* Added `enum_hash(...)`
### Changed
* `Option<T>` now implements `Enum`
* `bevy_window` now depends on `bevy_reflect`
* Implemented `Reflect` and `FromReflect` for `WindowId`
* Derive `FromReflect` on `PerspectiveProjection`
* Derive `FromReflect` on `OrthographicProjection`
* Derive `FromReflect` on `WindowOrigin`
* Derive `FromReflect` on `ScalingMode`
* Derive `FromReflect` on `DepthCalculation`
## Migration Guide
* Enums no longer need to be treated as values and usages of `#[reflect_value(...)]` can be removed or replaced by `#[reflect(...)]`
* Enums (including `Option<T>`) now take a different format when serializing. The format is described above, but this may cause issues for existing scenes that make use of enums.
---
Also shout out to @nicopap for helping clean up some of the code here! It's a big feature so help like this is really appreciated!
Co-authored-by: Gino Valente <gino.valente.code@gmail.com>
# Objective
Currently, actually using a `Local` on a system requires that it be `T: FromWorld`, but that requirement is only expressed on the `SystemParam` machinery, which leads to the confusing error message for when the user attempts to add an invalid system. By adding these bounds to `Local` directly, it improves clarity on usage and semantics.
## Solution
- Add `T: FromWorld` bound to `Local`'s definition
## Migration Guide
- It might be possible for references to `Local`s without `T: FromWorld` to exist, but these should be exceedingly rare and probably dead code. In the event that one of these is encountered, the easiest solutions are to delete the code or wrap the inner `T` in an `Option` to allow it to be default constructed to `None`.
# Objective
- Migrate changes from #3503.
## Solution
- Change `Size<T>` and `UiRect<T>` to `Size` and `UiRect` using `Val`.
- Implement `Sub`, `SubAssign`, `Mul`, `MulAssign`, `Div` and `DivAssign` for `Val`.
- Update tests for `Size`.
---
## Changelog
### Changed
- The generic `T` of `Size` and `UiRect` got removed and instead they both now always use `Val`.
## Migration Guide
- The generic `T` of `Size` and `UiRect` got removed and instead they both now always use `Val`. If you used a `Size<f32>` consider replacing it with a `Vec2` which is way more powerful.
Co-authored-by: KDecay <KDecayMusic@protonmail.com>
# Objective
View mesh2d_view_types.wgsl was missing a couple of fields present in bevy::render::ViewUniform, causing rendering issues for shaders using later fields.
## Solution
Solved by adding the fields in question
# Objective
- Fix / support KTX2 array / cubemap / cubemap array textures
- Fixes#4495 . Supersedes #4514 .
## Solution
- Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture.
- This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need
- Automatically configure this when loading KTX2
- Transcode all layers and faces instead of just one
- Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data
- `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data
- Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order
- Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures.
---
## Changelog
- Fixed: KTX2 array / cubemap / cubemap array textures
- Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions.
- Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Replace `many_for_each_mut` with `iter_many_mut` using the same tricks to avoid aliased mutability that `iter_combinations_mut` uses.
<sub>I tried rebasing the draft PR I made for this before and it died. F</sub>
## Why
`many_for_each_mut` is worse for a few reasons:
1. The closure prevents the use of `continue`, `break`, and `return` behaves like a limited `continue`.
2. rustfmt will crumple it and double the indentation when the line gets too long.
```rust
query.many_for_each_mut(
&entity_list,
|(mut transform, velocity, mut component_c)| {
// Double trouble.
},
);
```
3. It is more surprising to have `many_for_each_mut` as a mutable counterpart to `iter_many` than `iter_many_mut`.
4. It required a separate unsafe fn; more unsafe code to maintain.
5. The `iter_many_mut` API matches the existing `iter_combinations_mut` API.
Co-authored-by: devil-ira <justthecooldude@gmail.com>
# Objective
Sadly, #4944 introduces a serious exponential despawn behavior, which cannot be included in 0.8. [Handling AABBs properly is a controversial topic](https://github.com/bevyengine/bevy/pull/5423#issuecomment-1199995825) and one that deserves more time than the day we have left before release.
## Solution
This reverts commit c2b332f98a.
# Objective
- Expose the wgpu debug label on storage buffer types.
## Solution
🐄
- Add an optional cow static string and pass that to the label field of create_buffer_with_data
- This pattern is already used by Bevy for debug tags on bind group and layout descriptors.
---
Example Usage:
A buffer is given a label using the label function. Alternatively a buffer may be labeled when it is created if the default() convention is not used.
![ray_buf](https://user-images.githubusercontent.com/106117615/179366494-f037bd8c-4d65-4b37-8135-01ac0c5c8ee0.png)
Here is the buffer appearing with the correct name in RenderDoc. Previously the buffer would have an anonymous name such as "Buffer223":
![buffer_named](https://user-images.githubusercontent.com/106117615/179366552-faeb6c27-5373-4e4e-a0e2-c04446f95a4b.png)
Co-authored-by: rebelroad-reinhart <reinhart@rebelroad.gg>
# Objective
- Improve performance when rendering text
## Solution
- While playing with example `many_buttons`, I noticed a lot of time was spent converting colours
- Investigating, the biggest culprit seems to be text colour. Each glyph in a text is an individual UI node for rendering, with a copy of the colour. Making the conversion to RGBA linear only once per text section reduces the number of conversion done once rendering.
- This improves FPS for example `many_buttons` from ~33 to ~42
- I did the same change for text 2d
# Objective
I found this small ux hiccup when writing the 0.8 blog post:
```rust
image.sampler = ImageSampler::Descriptor(ImageSampler::nearest_descriptor());
```
Not good!
## Solution
```rust
image.sampler = ImageSampler::nearest();
```
(there are Good Reasons to keep around the nearest_descriptor() constructor and I think it belongs on this type)
# Objective
`ReadOnlyWorldQuery` should have required `Self::ReadOnly = Self` so that calling `.iter()` on a readonly query is equivelent to calling `iter_mut()`.
## Solution
add `ReadOnly = Self` to the definition of `ReadOnlyWorldQuery`
---
## Changelog
ReadOnlyWorldQuery's `ReadOnly` assoc type is now always equal to `Self`
## Migration Guide
Make `Self::ReadOnly = Self` hold
# Objective
fix an error in shadow map indexing that occurs when point lights without shadows are used in conjunction with spotlights with shadows
## Solution
calculate point_light_count correctly
# Objective
Enable treating components and resources equally, which can
simplify the implementation of some systems where only the change
detection feature is relevant and not the kind of object (resource or
component).
## Solution
Implement `From<ResMut<T>>` and `From<NonSendMut<T>>` for
`Mut`. Since the 3 structs are similar, and only differ by their system
param role, the conversion is trivial.
---
## Changelog
Added - `From<ResMut>` and `From<NonSendMut>` for `Mut<T>`.
# Objective
- Even though it's marked as optional, it is no longer possible to not depend on `bevy_render` as it's a dependency of `bevy_scene`
## Solution
- Make `bevy_scene` optional
- For the minimalist among us, also make `bevy_asset` optional
# Objective
- Fix some typos
## Solution
For the first time in my life, I made a pull request to OSS.
Am I right?
Co-authored-by: eiei114 <60887155+eiei114@users.noreply.github.com>
# Objective
- `#![warn(missing_docs)]` was added to bevy_asset in #3536
- A method was not documented when targeting wasm
## Solution
- Add documentation for it
# Objective
Some generic types like `Option<T>`, `Vec<T>` and `HashMap<K, V>` implement `Reflect` when where their generic types `T`/`K`/`V` implement `Serialize + for<'de> Deserialize<'de>`.
This is so that in their `GetTypeRegistration` impl they can insert the `ReflectSerialize` and `ReflectDeserialize` type data structs.
This has the annoying side effect that if your struct contains a `Option<NonSerdeStruct>` you won't be able to derive reflect (https://github.com/bevyengine/bevy/issues/4054).
## Solution
- remove the `Serialize + Deserialize` bounds on wrapper types
- this means that `ReflectSerialize` and `ReflectDeserialize` will no longer be inserted even for `.register::<Option<DoesImplSerde>>()`
- add `register_type_data<T, D>` shorthand for `registry.get_mut(T).insert(D::from_type<T>())`
- require users to register their specific generic types **and the serde types** separately like
```rust
.register_type::<Option<String>>()
.register_type_data::<Option<String>, ReflectSerialize>()
.register_type_data::<Option<String>, ReflectDeserialize>()
```
I believe this is the best we can do for extensibility and convenience without specialization.
## Changelog
- `.register_type` for generic types like `Option<T>`, `Vec<T>`, `HashMap<K, V>` will no longer insert `ReflectSerialize` and `ReflectDeserialize` type data. Instead you need to register it separately for concrete generic types like so:
```rust
.register_type::<Option<String>>()
.register_type_data::<Option<String>, ReflectSerialize>()
.register_type_data::<Option<String>, ReflectDeserialize>()
```
TODO: more docs and tweaks to the scene example to demonstrate registering generic types.
# Objective
- wgpu 0.13 has validation to ensure that the width and height specified for a texture are both multiples of the respective block width and block height. This means validation fails for compressed textures with say a 4x4 block size, but non-modulo-4 image width/height.
## Solution
- Using `Extent3d`'s `physical_size()` method in the `dds` loader. It takes a `TextureFormat` argument and ensures the resolution is correct.
---
## Changelog
- Fixes: Validation failure for compressed textures stored in `dds` where the width/height are not a multiple of the block dimensions.
# Objective
the bevy pbr shader doesn't handle at all normal maps
if a mesh doesn't have backed tangents. This is a pitfall
(that I fell into) and needs to be documented.
# Solution
Document the behavior. (Also document a few other
`StandardMaterial` fields)
## Changelog
* Add documentation to `emissive`, `normal_map_texture` and `occlusion_texture` fields of `StandardMaterial`.
# Objective
I've found there is a duplicated line, probably left after some copy paste.
## Solution
- removed it
---
Co-authored-by: adsick <vadimgangsta73@gmail.com>
# Objective
UI nodes can be hidden by setting their `Visibility` property. Since #5310 was merged, this is now ergonomic to use, as visibility is now inherited.
However, UI nodes still receive (and store) interactions when hidden, resulting in surprising hidden state (and an inability to otherwise disable UI nodes.
## Solution
Fixes#5360.
I've updated the `ui_focus_system` to accomplish this in a minimally intrusive way, and updated the docs to match.
**NOTE:** I have not added automated tests to verify this behavior, as we do not currently have a good testing paradigm for `bevy_ui`. I'm not thrilled with that by any means, but I'm not sure fixing it is within scope.
## Paths not taken
### Separate `Disabled` component
This is a much larger and more controversial change, and not well-scoped to UI.
Furthermore, it is extremely rare that you want hidden UI elements to function: the most common cases are for things like changing tabs, collapsing elements or so on.
Splitting this behavior would be more complex, and substantially violate user expectations.
### A separate limbo world
Mentioned in the linked issue. Super cool, but all of the problems of the `Disabled` component solution with a whole new RFC-worth of complexity.
### Using change detection to reduce the amount of redundant work
Adds a lot of complexity for questionable performance gains. Likely involves a complete refactor of the entire system.
We simply don't have the tests or benchmarks here to justify this.
## Changelog
- UI nodes are now always in an `Interaction::None` state while they are hidden (via the `ComputedVisibility` component).
# Objective
- Fixes#5293
- UI nodes with a rotation that made the top left corner lower than the top right corner (z rotations greater than π/4) were culled
## Solution
- Do not cull nodes with a rotation, but don't do proper culling in this case
As a reminder, changing rotation and scale of UI nodes is not recommended as it won't impact layout. This is a quick fix but doesn't handle properly rotations and scale in clipping/culling. This would need a lot more work as mentioned here: c2b332f98a/crates/bevy_ui/src/render/mod.rs (L404-L405)
# Objective
I noticed while working on #5366 that the documentation for label types wasn't working correctly. Having experimented with this for a few weeks, I believe that generating docs in macros is more effort than it's worth.
## Solution
Add more boilerplate, copy-paste and edit the docs across types. This also lets us add custom doctests for specific types. Also, we don't need `concat_idents` as a dependency anymore.
# Objective
- Migrate changes from #3503.
## Solution
- Document `Size` and `UiRect`.
- I also removed the type alias from the `size_ops` test since it's unnecessary.
## Follow Up
After this change is merged I'd follow up with removing the generics from `Size` and `UiRect` since `Val` should be extensible enough. This was also discussed and decided on in #3503. let me know if this is not needed or wanted anymore!
# Objective
I want to use the `deno_runtime` crate in my game, but it has a conflict with the version of the `notify` crate that Bevy depends on.
## Solution
Updates the version of the `notify` crate the Bevy depends on.
If users try to implement a custom asset loader, they must manually import anyhow::error as it's used by the asset loader trait but not exported.
2b93ab5812/examples/asset/custom_asset.rs (L25)Fixes#3138
Co-authored-by: sark <sarkahn@hotmail.com>
# Objective
Creating UI elements is very boilerplate-y with lots of indentation.
This PR aims to reduce boilerplate around creating text elements.
## Changelog
* Renamed `Text::with_section` to `from_section`.
It no longer takes a `TextAlignment` as argument, as the vast majority of cases left it `Default::default()`.
* Added `Text::from_sections` which creates a `Text` from a list of `TextSections`.
Reduces line-count and reduces indentation by one level.
* Added `Text::with_alignment`.
A builder style method for setting the `TextAlignment` of a `Text`.
* Added `TextSection::new`.
Does not reduce line count, but reduces character count and made it easier to read. No more `.to_string()` calls!
* Added `TextSection::from_style` which creates an empty `TextSection` with a style.
No more empty strings! Reduces indentation.
* Added `TextAlignment::CENTER` and friends.
* Added methods to `TextBundle`. `from_section`, `from_sections`, `with_text_alignment` and `with_style`.
## Note for reviewers.
Because of the nature of these changes I recommend setting diff view to 'split'.
~~Look for the book icon~~ cog in the top-left of the Files changed tab.
Have fun reviewing ❤️
<sup> >:D </sup>
## Migration Guide
`Text::with_section` was renamed to `from_section` and no longer takes a `TextAlignment` as argument.
Use `with_alignment` to set the alignment instead.
Co-authored-by: devil-ira <justthecooldude@gmail.com>
# Objective
- Fix some small errors in the documentation of the `OwningPtr` struct.
## Solution
- Change comments with 4 slashes `////` to doc comments with 3 slashes `///`.
- Fix typos.
# Objective
Update the `calculate_bounds` system to update `Aabb`s
for entities who've either:
- gotten a new mesh
- had their mesh mutated
Fixes https://github.com/bevyengine/bevy/issues/4294.
## Solution
There are two commits here to address the two issues above:
### Commit 1
**This Commit**
Updates the `calculate_bounds` system to operate not only on entities
without `Aabb`s but also on entities whose `Handle<Mesh>` has changed.
**Why?**
So if an entity gets a new mesh, its associated `Aabb` is properly
recalculated.
**Questions**
- This type is getting pretty gnarly - should I extract some types?
- This system is public - should I add some quick docs while I'm here?
### Commit 2
**This Commit**
Updates `calculate_bounds` to update `Aabb`s of entities whose meshes
have been directly mutated.
**Why?**
So if an entity's mesh gets updated, its associated `Aabb` is properly
recalculated.
**Questions**
- I think we should be using `ahash`. Do we want to do that with a
direct `hashbrown` dependency or an `ahash` dependency that we
configure the `HashMap` with?
- There is an edge case of duplicates with `Vec<Entity>` in the
`HashMap`. If an entity gets its mesh handle changed and changed back
again it'll be added to the list twice. Do we want to use a `HashSet`
to avoid that? Or do a check in the list first (assuming iterating
over the `Vec` is faster and this edge case is rare)?
- There is an edge case where, if an entity gets a new mesh handle and
then its old mesh is updated, we'll update the entity's `Aabb` to the
new geometry of the _old_ mesh. Do we want to remove items from the
`Local<HashMap>` when handles change? Does the `Changed` event give us
the old mesh handle? If not we might need to have a
`HashMap<Entity, Handle<Mesh>>` or something so we can unlink entities
from mesh handles when the handle changes.
- I did the `zip()` with the two `HashMap` gets assuming those would
be faster than calculating the Aabb of the mesh (otherwise we could do
`meshes.get(mesh_handle).and_then(Mesh::compute_aabb).zip(entity_mesh_map...)`
or something). Is that assumption way off?
## Testing
I originally tried testing this with `bevy_mod_raycast` as mentioned in the
original issue but it seemed to work (maybe they are currently manually
updating the Aabbs?). I then tried doing it in 2D but it looks like
`Handle<Mesh>` is just for 3D. So I took [this example](https://github.com/bevyengine/bevy/blob/main/examples/3d/pbr.rs)
and added some systems to mutate/assign meshes:
<details>
<summary>Test Script</summary>
```rust
use bevy::prelude::*;
use bevy::render:📷:ScalingMode;
use bevy::render::primitives::Aabb;
/// Make sure we only mutate one mesh once.
#[derive(Eq, PartialEq, Clone, Debug, Default)]
struct MutateMeshState(bool);
/// Let's have a few global meshes that we can cycle between.
/// This way we can be assigned a new mesh, mutate the old one, and then get the old one assigned.
#[derive(Eq, PartialEq, Clone, Debug, Default)]
struct Meshes(Vec<Handle<Mesh>>);
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_resource::<MutateMeshState>()
.init_resource::<Meshes>()
.add_startup_system(setup)
.add_system(assign_new_mesh)
.add_system(show_aabbs.after(assign_new_mesh))
.add_system(mutate_meshes.after(show_aabbs))
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut global_meshes: ResMut<Meshes>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let m1 = meshes.add(Mesh::from(shape::Icosphere::default()));
let m2 = meshes.add(Mesh::from(shape::Icosphere {
radius: 0.90,
..Default::default()
}));
let m3 = meshes.add(Mesh::from(shape::Icosphere {
radius: 0.80,
..Default::default()
}));
global_meshes.0.push(m1.clone());
global_meshes.0.push(m2);
global_meshes.0.push(m3);
// add entities to the world
// sphere
commands.spawn_bundle(PbrBundle {
mesh: m1,
material: materials.add(StandardMaterial {
base_color: Color::hex("ffd891").unwrap(),
..default()
}),
..default()
});
// new 3d camera
commands.spawn_bundle(Camera3dBundle {
projection: OrthographicProjection {
scale: 3.0,
scaling_mode: ScalingMode::FixedVertical(1.0),
..default()
}
.into(),
..default()
});
// old 3d camera
// commands.spawn_bundle(OrthographicCameraBundle {
// transform: Transform::from_xyz(0.0, 0.0, 8.0).looking_at(Vec3::default(), Vec3::Y),
// orthographic_projection: OrthographicProjection {
// scale: 0.01,
// ..default()
// },
// ..OrthographicCameraBundle::new_3d()
// });
}
fn show_aabbs(query: Query<(Entity, &Handle<Mesh>, &Aabb)>) {
for thing in query.iter() {
println!("{thing:?}");
}
}
/// For testing the second part - mutating a mesh.
///
/// Without the fix we should see this mutate an old mesh and it affects the new mesh that the
/// entity currently has.
/// With the fix, the mutation doesn't affect anything until the entity is reassigned the old mesh.
fn mutate_meshes(
mut meshes: ResMut<Assets<Mesh>>,
time: Res<Time>,
global_meshes: Res<Meshes>,
mut mutate_mesh_state: ResMut<MutateMeshState>,
) {
let mutated = mutate_mesh_state.0;
if time.seconds_since_startup() > 4.5 && !mutated {
println!("Mutating {:?}", global_meshes.0[0]);
let m = meshes.get_mut(&global_meshes.0[0]).unwrap();
let mut p = m.attribute(Mesh::ATTRIBUTE_POSITION).unwrap().clone();
use bevy::render::mesh::VertexAttributeValues;
match &mut p {
VertexAttributeValues::Float32x3(v) => {
v[0] = [10.0, 10.0, 10.0];
}
_ => unreachable!(),
}
m.insert_attribute(Mesh::ATTRIBUTE_POSITION, p);
mutate_mesh_state.0 = true;
}
}
/// For testing the first part - assigning a new handle.
fn assign_new_mesh(
mut query: Query<&mut Handle<Mesh>, With<Aabb>>,
time: Res<Time>,
global_meshes: Res<Meshes>,
) {
let s = time.seconds_since_startup() as usize;
let idx = s % global_meshes.0.len();
for mut handle in query.iter_mut() {
*handle = global_meshes.0[idx].clone_weak();
}
}
```
</details>
## Changelog
### Fixed
Entity `Aabb`s not updating when meshes are mutated or re-assigned.
# Objective
- Allows conversion of mutable queries to immutable queries.
- Fixes#4606
## Solution
- Add `to_readonly` method on `Query`, which uses `QueryState::as_readonly`
- `AsRef` is not feasible because creation of new queries is needed.
---
## Changelog
### Added
- Allows conversion of mutable queries to immutable queries using `Query::to_readonly`.
# Objective
https://github.com/bevyengine/bevy/pull/4447 adds functions that can fetch resources/components as `*const ()` ptr by providing the `ComponentId`. This alone is not enough for them to be usable safely with reflection, because there is no general way to go from the raw pointer to a `&dyn Reflect` which is the pointer + a pointer to the VTable of the `Reflect` impl.
By adding a `ReflectFromPtr` type that is included in the type type registration when deriving `Reflect`, safe functions can be implemented in scripting languages that don't assume a type layout and can access the component data via reflection:
```rust
#[derive(Reflect)]
struct StringResource {
value: String
}
```
```lua
local res_id = world:resource_id_by_name("example::StringResource")
local res = world:resource(res_id)
print(res.value)
```
## Solution
1. add a `ReflectFromPtr` type with a `FromType<T: Reflect>` implementation and the following methods:
- ` pub unsafe fn as_reflect_ptr<'a>(&self, val: Ptr<'a>) -> &'a dyn Reflect`
- ` pub unsafe fn as_reflect_ptr_mut<'a>(&self, val: PtrMut<'a>) -> &'a mud dyn Reflect`
Safety requirements of the methods are that you need to check that the `ReflectFromPtr` was constructed for the correct type.
2. add that type to the `TypeRegistration` in the `GetTypeRegistration` impl generated by `#[derive(Reflect)]`.
This is different to other reflected traits because it doesn't need `#[reflect(ReflectReflectFromPtr)]` which IMO should be there by default.
Co-authored-by: Jakob Hellermann <hellermann@sipgate.de>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
after #5355, three methods were added on world:
* `send_event`
* `send_event_batch`
* `send_default_event`
rename `send_default_event` to `send_event_default` for better discoverability
# Objective
- Provide better compile-time errors and diagnostics.
- Add more options to allow more textures types and sampler types.
- Update array_texture example to use upgraded AsBindGroup derive macro.
## Solution
Split out the parsing of the inner struct/field attributes (the inside part of a `#[foo(...)]` attribute) for better clarity
Parse the binding index for all inner attributes, as it is part of all attributes (`#[foo(0, ...)`), then allow each attribute implementer to parse the rest of the attribute metadata as needed. This should make it very trivial to extend/change if needed in the future.
Replaced invocations of `panic!` with the `syn::Error` type, providing fine-grained errors that retains span information. This provides much nicer compile-time errors, and even better IDE errors.
![image](https://user-images.githubusercontent.com/7478134/179452241-6d85d440-4b67-44da-80a7-9d47e8c88b8a.png)
Updated the array_texture example to demonstrate the new changes.
## New AsBindGroup attribute options
### `#[texture(u32, ...)]`
Where `...` is an optional list of arguments.
| Arguments | Values | Default |
|-------------- |---------------------------------------------------------------- | ----------- |
| dimension = "..." | `"1d"`, `"2d"`, `"2d_array"`, `"3d"`, `"cube"`, `"cube_array"` | `"2d"` |
| sample_type = "..." | `"float"`, `"depth"`, `"s_int"` or `"u_int"` | `"float"` |
| filterable = ... | `true`, `false` | `true` |
| multisampled = ... | `true`, `false` | `false` |
| visibility(...) | `all`, `none`, or a list-combination of `vertex`, `fragment`, `compute` | `vertex`, `fragment` |
Example: `#[texture(0, dimension = "2d_array", visibility(vertex, fragment))]`
### `#[sampler(u32, ...)]`
Where `...` is an optional list of arguments.
| Arguments | Values | Default |
|----------- |--------------------------------------------------- | ----------- |
| sampler_type = "..." | `"filtering"`, `"non_filtering"`, `"comparison"`. | `"filtering"` |
| visibility(...) | `all`, `none`, or a list-combination of `vertex`, `fragment`, `compute` | `vertex`, `fragment` |
Example: `#[sampler(0, sampler_type = "filtering", visibility(vertex, fragment)]`
## Changelog
- Added more options to `#[texture(...)]` and `#[sampler(...)]` attributes, supporting more kinds of materials. See above for details.
- Upgraded IDE and compile-time error messages.
- Updated array_texture example using the new options.
# Objective
- With access to `World`, it's not obvious how to send an event.
- This is especially useful if you are writing a `Command` that needs to send an `Event`.
- `Events` are a first-class construct in bevy, even though they are just `Resources` under the hood. Their methods should be discoverable.
## Solution
- Provide a simple helpers to send events through `Res<Events<T>>`.
---
## Changelog
> `send_event`, `send_default_event`, and `send_event_batch` methods added to `World`.
# Objective
Fixes#5362
## Solution
Add the attribute `#[label(ignore_fields)]` for `*Label` types.
```rust
#[derive(SystemLabel)]
pub enum MyLabel {
One,
// Previously this was not allowed since labels cannot contain data.
#[system_label(ignore_fields)]
Two(PhantomData<usize>),
}
```
## Notes
This label makes it possible for equality to behave differently depending on whether or not you are treating the type as a label. For example:
```rust
#[derive(SystemLabel, PartialEq, Eq)]
#[system_label(ignore_fields)]
pub struct Foo(usize);
```
If you compare it as a label, it will ignore the wrapped fields as the user requested. But if you compare it as a `Foo`, the derive will incorrectly compare the inner fields. I see a few solutions
1. Do nothing. This is technically intended behavior, but I think we should do our best to prevent footguns.
2. Generate impls of `PartialEq` and `Eq` along with the `#[derive(Label)]` macros. This is a breaking change as it requires all users to remove these derives from their types.
3. Only allow `PhantomData` to be used with `ignore_fields` -- seems needlessly prescriptive.
---
## Changelog
* Added the `ignore_fields` attribute to the derive macros for `*Label` types.
* Added an example showing off different forms of the derive macro.
<!--
## Migration Guide
> This section is optional. If there are no breaking changes, you can delete this section.
- If this PR is a breaking change (relative to the last release of Bevy), describe how a user might need to migrate their code to support these changes
- Simply adding new functionality is not a breaking change.
- Fixing behavior that was definitely a bug, rather than a questionable design choice is not a breaking change.
-->
# Objective
remove `QF` generics from a bunch of types and methods on query related items. this has a few benefits:
- simplifies type signatures `fn iter(&self) -> QueryIter<'_, 's, Q::ReadOnly, F::ReadOnly>` is (imo) conceptually simpler than `fn iter(&self) -> QueryIter<'_, 's, Q, ROQueryFetch<'_, Q>, F>`
- `Fetch` is mostly an implementation detail but previously we had to expose it on every `iter` `get` etc method
- Allows us to potentially in the future simplify the `WorldQuery` trait hierarchy by removing the `Fetch` trait
## Solution
remove the `QF` generic and add a way to (unsafely) turn `&QueryState<Q1, F1>` into `&QueryState<Q2, F2>`
---
## Changelog/Migration Guide
The `QF` generic was removed from various `Query` iterator types and some methods, you should update your code to use the type of the corresponding worldquery of the fetch type that was being used, or call `as_readonly`/`as_nop` to convert a querystate to the appropriate type. For example:
`.get_single_unchecked_manual::<ROQueryFetch<Q>>(..)` -> `.as_readonly().get_single_unchecked_manual(..)`
`my_field: QueryIter<'w, 's, Q, ROQueryFetch<'w, Q>, F>` -> `my_field: QueryIter<'w, 's, Q::ReadOnly, F::ReadOnly>`
# Objective
- Help user when they need to add both a `TransformBundle` and a `VisibilityBundle`
## Solution
- Add a `SpatialBundle` adding all components
# Objective
[This unwrap()](de484c1e41/crates/bevy_pbr/src/pbr_material.rs (L195)) in pbr_material.rs will be hit if a StandardMaterial normal_map image has not finished loading, resulting in an error message that is hard to debug.
## Solution
~~This PR improves the error message including a potential indication of why the unwrap() could have panic'd by using expect() instead of unwrap().~~
This PR removes the panic by only proceeding if the image is found.
---
## Changelog
Don't panic when StandardMaterial normal_map images have not finished loading.
# Objective
- Fixes #5338
- Allow the usage of `use bevy::ui::Size` (see migration guide in #4285)
## Solution
- Remove the `use crate::Size` import so that the `pub use geometry::*` import also publicly uses the `Size` struct.
# Objective
- 0.8 is coming soon, and our mikktspace implementation is unsound - see https://github.com/gltf-rs/mikktspace/issues/26
- Best not to ship that
## Solution
- Fix the unsoundness in a minimal way
- Obviously there might be others, but it seems unlikely we have any way to know about those
# Objective
- Add capability to use `Affine3A`s for some `GlobalTransform`s. This allows affine transformations that are not possible using a single `Transform` such as shear and non-uniform scaling along an arbitrary axis.
- Related to #1755 and #2026
## Solution
- `GlobalTransform` becomes an enum wrapping either a `Transform` or an `Affine3A`.
- The API of `GlobalTransform` is minimized to avoid inefficiency, and to make it clear that operations should be performed using the underlying data types.
- using `GlobalTransform::Affine3A` disables transform propagation, because the main use is for cases that `Transform`s cannot support.
---
## Changelog
- `GlobalTransform`s can optionally support any affine transformation using an `Affine3A`.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Port changes made to Material in #5053 to Material2d as well.
This is more or less an exact copy of the implementation in bevy_pbr; I
simply pretended the API existed, then copied stuff over until it
started building and the shapes example was working again.
# Objective
The changes in #5053 makes it possible to add custom materials with a lot less boiler plate. However, the implementation isn't shared with Material 2d as it's a kind of fork of the bevy_pbr version. It should be possible to use AsBindGroup on the 2d version as well.
## Solution
This makes the same kind of changes in Material2d in bevy_sprite.
This makes the following work:
```rust
//! Draws a circular purple bevy in the middle of the screen using a custom shader
use bevy::{
prelude::*,
reflect::TypeUuid,
render::render_resource::{AsBindGroup, ShaderRef},
sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle},
};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(Material2dPlugin::<CustomMaterial>::default())
.add_startup_system(setup)
.run();
}
/// set up a simple 2D scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<CustomMaterial>>,
asset_server: Res<AssetServer>,
) {
commands.spawn_bundle(MaterialMesh2dBundle {
mesh: meshes.add(shape::Circle::new(50.).into()).into(),
material: materials.add(CustomMaterial {
color: Color::PURPLE,
color_texture: Some(asset_server.load("branding/icon.png")),
}),
transform: Transform::from_translation(Vec3::new(-100., 0., 0.)),
..default()
});
commands.spawn_bundle(Camera2dBundle::default());
}
/// The Material2d trait is very configurable, but comes with sensible defaults for all methods.
/// You only need to implement functions for features that need non-default behavior. See the Material api docs for details!
impl Material2d for CustomMaterial {
fn fragment_shader() -> ShaderRef {
"shaders/custom_material.wgsl".into()
}
}
// This is the struct that will be passed to your shader
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
pub struct CustomMaterial {
#[uniform(0)]
color: Color,
#[texture(1)]
#[sampler(2)]
color_texture: Option<Handle<Image>>,
}
```
# Objective
Fixes#4907. Fixes#838. Fixes#5089.
Supersedes #5146. Supersedes #2087. Supersedes #865. Supersedes #5114
Visibility is currently entirely local. Set a parent entity to be invisible, and the children are still visible. This makes it hard for users to hide entire hierarchies of entities.
Additionally, the semantics of `Visibility` vs `ComputedVisibility` are inconsistent across entity types. 3D meshes use `ComputedVisibility` as the "definitive" visibility component, with `Visibility` being just one data source. Sprites just use `Visibility`, which means they can't feed off of `ComputedVisibility` data, such as culling information, RenderLayers, and (added in this pr) visibility inheritance information.
## Solution
Splits `ComputedVisibilty::is_visible` into `ComputedVisibilty::is_visible_in_view` and `ComputedVisibilty::is_visible_in_hierarchy`. For each visible entity, `is_visible_in_hierarchy` is computed by propagating visibility down the hierarchy. The `ComputedVisibility::is_visible()` function combines these two booleans for the canonical "is this entity visible" function.
Additionally, all entities that have `Visibility` now also have `ComputedVisibility`. Sprites, Lights, and UI entities now use `ComputedVisibility` when appropriate.
This means that in addition to visibility inheritance, everything using Visibility now also supports RenderLayers. Notably, Sprites (and other 2d objects) now support `RenderLayers` and work properly across multiple views.
Also note that this does increase the amount of work done per sprite. Bevymark with 100,000 sprites on `main` runs in `0.017612` seconds and this runs in `0.01902`. That is certainly a gap, but I believe the api consistency and extra functionality this buys us is worth it. See [this thread](https://github.com/bevyengine/bevy/pull/5146#issuecomment-1182783452) for more info. Note that #5146 in combination with #5114 _are_ a viable alternative to this PR and _would_ perform better, but that comes at the cost of api inconsistencies and doing visibility calculations in the "wrong" place. The current visibility system does have potential for performance improvements. I would prefer to evolve that one system as a whole rather than doing custom hacks / different behaviors for each feature slice.
Here is a "split screen" example where the left camera uses RenderLayers to filter out the blue sprite.
![image](https://user-images.githubusercontent.com/2694663/178814868-2e9a2173-bf8c-4c79-8815-633899d492c3.png)
Note that this builds directly on #5146 and that @james7132 deserves the credit for the baseline visibility inheritance work. This pr moves the inherited visibility field into `ComputedVisibility`, then does the additional work of porting everything to `ComputedVisibility`. See my [comments here](https://github.com/bevyengine/bevy/pull/5146#issuecomment-1182783452) for rationale.
## Follow up work
* Now that lights use ComputedVisibility, VisibleEntities now includes "visible lights" in the entity list. Functionally not a problem as we use queries to filter the list down in the desired context. But we should consider splitting this out into a separate`VisibleLights` collection for both clarity and performance reasons. And _maybe_ even consider scoping `VisibleEntities` down to `VisibleMeshes`?.
* Investigate alternative sprite rendering impls (in combination with visibility system tweaks) that avoid re-generating a per-view fixedbitset of visible entities every frame, then checking each ExtractedEntity. This is where most of the performance overhead lives. Ex: we could generate ExtractedEntities per-view using the VisibleEntities list, avoiding the need for the bitset.
* Should ComputedVisibility use bitflags under the hood? This would cut down on the size of the component, potentially speed up the `is_visible()` function, and allow us to cheaply expand ComputedVisibility with more data (ex: split out local visibility and parent visibility, add more culling classes, etc).
---
## Changelog
* ComputedVisibility now takes hierarchy visibility into account.
* 2D, UI and Light entities now use the ComputedVisibility component.
## Migration Guide
If you were previously reading `Visibility::is_visible` as the "actual visibility" for sprites or lights, use `ComputedVisibilty::is_visible()` instead:
```rust
// before (0.7)
fn system(query: Query<&Visibility>) {
for visibility in query.iter() {
if visibility.is_visible {
log!("found visible entity");
}
}
}
// after (0.8)
fn system(query: Query<&ComputedVisibility>) {
for visibility in query.iter() {
if visibility.is_visible() {
log!("found visible entity");
}
}
}
```
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Export and register a missing type from `glam`.
Reflect impls were already present, but not registered.
Co-authored-by: devil-ira <justthecooldude@gmail.com>
# Objective
- There is a warning when building in release:
```
warning: unused import: `Local`
--> crates/bevy_render/src/extract_resource.rs:4:34
|
4 | use bevy_ecs::system::{Commands, Local, Res, ResMut, Resource};
| ^^^^^
|
= note: `#[warn(unused_imports)]` on by default
```
- It's used 814f8d1635/crates/bevy_render/src/extract_resource.rs (L45)
- Fix it
## Solution
- Gate the import
# Objective
- Closes#4954
- Reduce the complexity of the `{System, App, *}Label` APIs.
## Solution
For the sake of brevity I will only refer to `SystemLabel`, but everything applies to all of the other label types as well.
- Add `SystemLabelId`, a lightweight, `copy` struct.
- Convert custom types into `SystemLabelId` using the trait `SystemLabel`.
## Changelog
- String literals implement `SystemLabel` for now, but this should be changed with #4409 .
## Migration Guide
- Any previous use of `Box<dyn SystemLabel>` should be replaced with `SystemLabelId`.
- `AsSystemLabel` trait has been modified.
- No more output generics.
- Method `as_system_label` now returns `SystemLabelId`, removing an unnecessary level of indirection.
- If you *need* a label that is determined at runtime, you can use `Box::leak`. Not recommended.
## Questions for later
* Should we generate a `Debug` impl along with `#[derive(*Label)]`?
* Should we rename `as_str()`?
* Should we remove the extra derives (such as `Hash`) from builtin `*Label` types?
* Should we automatically derive types like `Clone, Copy, PartialEq, Eq`?
* More-ergonomic comparisons between `Label` and `LabelId`.
* Move `Dyn{Eq, Hash,Clone}` somewhere else.
* Some API to make interning dynamic labels easier.
* Optimize string representation
* Empty string for unit structs -- no debug info but faster comparisons
* Don't show enum types -- same tradeoffs as asbove.
This replaces `rand` with `fastrand` as the source of randomness for `HandleId::new()` in `bevy_asset`. This was the only crate with a dependency on `rand`, and now the dependency exists only as a dev-dependency.
`fastrand` was already in the dependency tree, thanks to `futures-lite`, `async-executor`, and `tempfile` to name a few.
## Changelog
Removed `rand` from dependencies in `bevy_asset` in favor of existing in-tree `fast-rand`
Add compile time check for if a system is an exclusive system. Resolves#4788
Co-authored-by: Daniel Liu <mr.picklepinosaur@gmail.com>
Co-authored-by: Daniel Liu <danieliu3120@gmail.com>
Following https://github.com/bevyengine/bevy/pull/5124 I decided to add the `ExactSizeIterator` impl for `QueryCombinationIter`.
Also:
- Clean up the tests for `size_hint` and `len` for both the normal `QueryIter` and `QueryCombinationIter`.
- Add tests to `QueryCombinationIter` when it shouldn't be `ExactSizeIterator`
---
## Changelog
- Added `ExactSizeIterator` implementation for `QueryCombinatonIter`
# Objective
- `.iter_combinations_*()` cannot be used on custom derived `WorldQuery`, so this fixes that
- Fixes#5284
## Solution
- `#[derive(Clone)]` on the `Fetch` of the proc macro derive.
- `#[derive(Clone)]` for `AnyOf` to satisfy tests.
Someone noted that the `rotate_around` method did not give the results they expected: [discord thread](https://discord.com/channels/691052431525675048/996497295325544479)
I tested `rotate_around` and their workaround and it seems like it was indeed incorrect.
Here is a scene with some cubes at different angles all being rotated around the center on the Y axis.
https://user-images.githubusercontent.com/29694403/178598432-407d7e80-1caf-4b17-b69b-66d9156c81e1.mp4
Interestingly, the middle cube rotates as you might expect. This threw me for a bit of a loop before I added the other cubes to the test haha.
Here is the same scene with the order multiplication of the quaternions flipped in `rotate_around`.
https://user-images.githubusercontent.com/29694403/178598446-a98026f3-524c-448b-8437-4d0d3175c6ca.mp4
That looks better :)
## Changelog
* Fixed `rotate_around` rotating the wrong way around
* Added `translate_around`. - Split out the translation code from `rotate_around`.
* Simplified/optimized `rotate_local_*` methods. - Yep, That works somehow.
<sup>Quaternions sure are wacky. Do not ask me how this works exactly, haha.</sup>
Co-authored-by: devil-ira <justthecooldude@gmail.com>
Generally a good idea.
I ran into this because I wanted to store `Gamepads` in a wrapper struct in https://github.com/Leafwing-Studios/leafwing-input-manager/pull/168.
This PR allows the `Debug` derive used there to continue working. I could workaround this with a custom impl, but a PR upstream seemed like the right fix.
# Objective
Improve documentation, information users of the limitations in bevy's idiomatic patterns, and suggesting alternatives for when those limitations are encountered.
## Solution
* Add documentation to `Commands` informing the user of the option of writing one-shot commands with closures.
* Add documentation to `EventWriter` regarding the limitations of event types, and suggesting alternatives using commands.
# Objective
Fixes#5304
## Solution
Instead of using a simple utility function for loading, which uses a default allocation limit of 512MB, we use a Reader object which can be configured ad hoc.
## Changelog
> This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.
- Allows loading of textures larger than 512MB
# Objective
- Wireframes are currently not rendering on main because they aren't being extracted correctly
## Solution
- Extract the wireframes correctly
# Objective
When someone searches in rustdoc for `world_to_screen`, they now will
find `world_to_viewport`. The method was renamed in 0.8, it would be
nice to allow users to find the new name more easily.
---
# Objective
This PR aims to document the `bevy_asset` crate to complete coverage, while also trying to improve some bits of UX.
### Progress
- [x] Root items
- [x] `handle` module
- [x] `info` module
- [x] `path` module
- [x] `loader` module
- [x] `io` and `filesystem_watcher` module
- [x] `assets` module
- [x] `asset_server` module
- [x] `diagnostic` module
- [x] `debug_asset_server` module
- [x] Crate level documentation
- [x] Add `#![warn(missing_docs)]` lint
Coverage: 100%
## Migration Guide
- Rename `FileAssetIo::get_root_path` uses to `FileAssetIo::get_base_path`
`FileAssetIo::root_path()` is a getter for the `root_path` field, while `FileAssetIo::get_root_path` returned the parent directory of the asset root path, which was the executable's directory unless `CARGO_MANIFEST_DIR` was set. This change solves the ambiguity between the two methods.
# Objective
- Added a bunch of backticks to things that should have them, like equations, abstract variable names,
- Changed all small x, y, and z to capitals X, Y, Z.
This might be more annoying than helpful; Feel free to refuse this PR.
# Objective
- The time update is currently done in the wrong part of the schedule. For a single frame the current order of things is update input, update time (First stage), other stages, render stage (frame presentation). So when we update the time it includes the input processing of the current frame and the frame presentation of the previous frame. This is a problem when vsync is on. When input processing takes a longer amount of time for a frame, the vsync wait time gets shorter. So when these are not paired correctly we can potentially have a long input processing time added to the normal vsync wait time in the previous frame. This leads to inaccurate frame time reporting and more variance of the time than actually exists. For more details of why this is an issue see the linked issue below.
- Helps with https://github.com/bevyengine/bevy/issues/4669
- Supercedes https://github.com/bevyengine/bevy/pull/4728 and https://github.com/bevyengine/bevy/pull/4735. This PR should be less controversial than those because it doesn't add to the API surface.
## Solution
- The most accurate frame time would come from hardware. We currently don't have access to that for multiple reasons, so the next best thing we can do is measure the frame time as close to frame presentation as possible. This PR gets the Instant::now() for the time immediately after frame presentation in the render system and then sends that time to the app world through a channel.
- implements suggestion from @aevyrie from here https://github.com/bevyengine/bevy/pull/4728#discussion_r872010606
## Statistics
![image](https://user-images.githubusercontent.com/2180432/168410265-f249f66e-ea9d-45d1-b3d8-7207a7bc536c.png)
---
## Changelog
- Make frame time reporting more accurate.
## Migration Guide
`time.delta()` now reports zero for 2 frames on startup instead of 1 frame.
Remove unnecessary calls to `iter()`/`iter_mut()`.
Mainly updates the use of queries in our code, docs, and examples.
```rust
// From
for _ in list.iter() {
for _ in list.iter_mut() {
// To
for _ in &list {
for _ in &mut list {
```
We already enable the pedantic lint [clippy::explicit_iter_loop](https://rust-lang.github.io/rust-clippy/stable/) inside of Bevy. However, this only warns for a few known types from the standard library.
## Note for reviewers
As you can see the additions and deletions are exactly equal.
Maybe give it a quick skim to check I didn't sneak in a crypto miner, but you don't have to torture yourself by reading every line.
I already experienced enough pain making this PR :)
Co-authored-by: devil-ira <justthecooldude@gmail.com>
Resolves#5004. As suggested in the original issue, change tuple types to their corresponding vector type.
## migration guide
Changed the following fields
- `WindowCommand::SetWindowMode.resolution` from `(u32, u32)` to `UVec2`
- `WindowCommand::SetResolution.logical_resolution` from `(f32, f32)` to `Vec2`
Co-authored-by: Daniel Liu <mr.picklepinosaur@gmail.com>
# Objective
- Validate the format of the values with the expected attribute format.
- Currently, if you pass the wrong format, it will crash somewhere unrelated with a very cryptic error message, so it's really hard to debug for beginners.
## Solution
- Compare the format and panic when unexpected format is passed
## Note
- I used a separate `error!()` for a human friendly message because the panic message is very noisy and hard to parse for beginners. I don't mind changing this to only a panic if people prefer that.
- This could potentially be something that runs only in debug mode, but I don't think inserting attributes is done often enough for this to be an issue.
Co-authored-by: Charles <IceSentry@users.noreply.github.com>
Small optimization. `.collect()` from arrays generates very nice code without reallocations: https://rust.godbolt.org/z/6E6c595bq
Co-authored-by: Kornel <kornel@geekhood.net>
# Objective
Currently some TextureFormats are not supported by the Image type.
The `TextureFormat::R16Unorm` format is useful for storing heightmaps.
This small change would unblock releasing my terrain plugin on bevy 0.8.
## Solution
Added `TextureFormat::R16Unorm` support to Image.
This is an alternative (short term solution) to the large texture format issue https://github.com/bevyengine/bevy/pull/4124.
# Objective
- Slight documentation tweak to make it more clear that `FloatOrd` also implements `Hash` and `Eq`, not just `Ord`.
- I know that it does show that Hash is implemented in the docs, but I had missed it after reading the description and assuming it didn't do it, so hopefully this helps other people who might miss it like I did. :)
## Solution
- Just mention in the Hash and Eq implementation in the docstring.
# Objective
- Currently bevy_ui only checks for primary window cursor position to determine `Interaction` behavior.
- Added checks for focused window where cursor position is available.
- Fixes#5224.
## Solution
- Added checks for focused windows in `Interaction` focus system.
## Follow Up
- All windows with camera will be rendering the UI elements right now.
- We will need some way to tell which camera to render which UI.
---
Co-authored-by: fadhliazhari <44402264+fadhliazhari@users.noreply.github.com>
# Objective
- Enable the `axis_dpad_to_button` gilrs filter to map hats to dpad buttons on supported remotes.
- Fixes https://github.com/Leafwing-Studios/leafwing-input-manager/issues/149
- Might have fixed the confusion related to https://github.com/bevyengine/bevy/issues/3229
## Solution
- Enables the `axis_dpad_to_button` filter in `gilrs` which will use it's remote mapping information to see if there are hats mapped to dpads for that remote model. I don't really understand the logic it uses exactly, but it is usually enabled by default in gilrs and I believe it probably leads to more intuitive mapping compared to the current situation of dpad buttons being mapped to an axis.
- Removes the `GamepadAxisType::DPadX` and `GamepadAxisType::DPadY` enum variants to avoid user confusion. Those variants should never be emitted anyway, for all supported remotes.
---
## Changelog
### Changed
- Removed `GamepadAxisType::DPadX` and `GamepadAxisType::DPadY` in favor of using `GamepadButtonType::DPad[Up/Down/Left/Right]` instead.
## Migration Guide
If your game reads gamepad events or queries the axis state of `GamePadAxisType::DPadX` or `GamePadAxisType::DPadY`, then you must migrate your code to check whether or not the `GamepadButtonType::DPadUp`, `GamepadButtonType::DPadDown`, etc. buttons were pressed instead.
# Objective
`ReflectResource` and `ReflectComponent` will panic on `apply` method if there is no such component. It's not very ergonomic. And not very good for performance since I need to check if such component exists first.
## Solution
* Add `ReflectComponent::apply_or_insert` and `ReflectResource::apply_or_insert` functions.
* Rename `ReflectComponent::add` into `ReflectComponent::insert` for consistency.
---
## Changelog
### Added
* `ReflectResource::apply_or_insert` and `ReflectComponent::apply_on_insert`.
### Changed
* Rename `ReflectComponent::add` into `ReflectComponent::insert` for consistency.
* Use `ReflectComponent::apply_on_insert` in `DynamicScene` instead of manual checking.
## Migration Guide
* Rename `ReflectComponent::add` into `ReflectComponent::insert`.