# Objective
- The doc example for `World::run_system_with_input` mistakenly
indicates that systems share state
- Some of the doc example code is unnecessary and/or could be cleaned up
## Solution
Replace the incorrect result value for the correct one in the doc
example. I also went with an explicit `assert_eq` check as it presents
the same information but can be validated by CI via doc tests.
Also removed some unnecessary code, such as the `Resource` derives on
`Counter`. In fact, I just replaced `Counter` with a `u8` in the
`Local`. I think it makes the example a little cleaner.
---
## Changelog
- Update docs for `World::run_system` and `World::run_system_with_input`
# Objective
- Fixes#12255
Still needs confirming what the consequences are from having camera
viewport nodes live on the root of the taffy tree.
## Solution
To fix calculating the layouts for UI nodes we need to cleanup the
children previously set whenever `TargetCamera` is updated. This also
maintains a list of taffy camera nodes and cleans them up when removed.
---
## Changelog
Fixed#12255
## Migration Guide
changes affect private structs/members so shouldn't need actions by
engine users.
# Objective
Fixes#12126
Notably this does not appear to fix the console error spam that appears
to be coming from winit, only the performance bug that occurs when
tabbing out and back into the game.
## Solution
The winit event loop starts out as `ControlFlow::Wait` by default. When
switching to `UpdateMode::Reactive` or `UpdateMode::ReactiveLowPower`,
we repeatedly update this to `ControlFlow::WaitUntil(next)`. When
switching back to `UpdateMode::Continuous`, the event loop is
erroneously stuck at the latest `ControlFlow::WaitUntil(next)` that was
issued.
I also changed how we handle `Event::NewEvents` since the `StartCause`
already tells us enough information to make that decision. This came
about my debugging and I left it in as an improvement.
# Objective
Resolves#4154
Currently, registration must all be done manually:
```rust
#[derive(Reflect)]
struct Foo(Bar);
#[derive(Reflect)]
struct Bar(Baz);
#[derive(Reflect)]
struct Baz(usize);
fn main() {
// ...
app
.register_type::<Foo>()
.register_type::<Bar>()
.register_type::<Baz>()
// .register_type::<usize>() <- This one is handled by Bevy, thankfully
// ...
}
```
This can grow really quickly and become very annoying to add, remove,
and update as types change. It would be great if we could help reduce
the number of types that a user must manually implement themselves.
## Solution
As suggested in #4154, this PR adds automatic recursive registration.
Essentially, when a type is registered, it may now also choose to
register additional types along with it using the new
`GetTypeRegistration::register_type_dependencies` trait method.
The `Reflect` derive macro now automatically does this for all fields in
structs, tuple structs, struct variants, and tuple variants. This is
also done for tuples, arrays, `Vec<T>`, `HashMap<K, V>`, and
`Option<T>`.
This allows us to simplify the code above like:
```rust
#[derive(Reflect)]
struct Foo(Bar);
#[derive(Reflect)]
struct Bar(Baz);
#[derive(Reflect)]
struct Baz(usize);
fn main() {
// ...
app.register_type::<Foo>()
// ...
}
```
This automatic registration only occurs if the type has not yet been
registered. If it has been registered, we simply skip it and move to the
next one. This reduces the cost of registration and prevents overwriting
customized registrations.
## Considerations
While this does improve ergonomics on one front, it's important to look
at some of the arguments against adopting a PR like this.
#### Generic Bounds
~~Since we need to be able to register the fields individually, we need
those fields to implement `GetTypeRegistration`. This forces users to
then add this trait as a bound on their generic arguments. This
annoyance could be relieved with something like #5772.~~
This is no longer a major issue as the `Reflect` derive now adds the
`GetTypeRegistration` bound by default. This should technically be okay,
since we already add the `Reflect` bound.
However, this can also be considered a breaking change for manual
implementations that left out a `GetTypeRegistration` impl ~~or for
items that contain dynamic types (e.g. `DynamicStruct`) since those also
do not implement `GetTypeRegistration`~~.
#### Registration Assumptions
By automatically registering fields, users might inadvertently be
relying on certain types to be automatically registered. If `Foo`
auto-registers `Bar`, but `Foo` is later removed from the code, then
anywhere that previously used or relied on `Bar`'s registration would
now fail.
---
## Changelog
- Added recursive type registration to structs, tuple structs, struct
variants, tuple variants, tuples, arrays, `Vec<T>`, `HashMap<K, V>`, and
`Option<T>`
- Added a new trait in the hidden `bevy_reflect::__macro_exports` module
called `RegisterForReflection`
- Added `GetTypeRegistration` impl for
`bevy_render::render_asset::RenderAssetUsages`
## Migration Guide
All types that derive `Reflect` will now automatically add
`GetTypeRegistration` as a bound on all (unignored) fields. This means
that all reflected fields will need to also implement
`GetTypeRegistration`.
If all fields **derive** `Reflect` or are implemented in `bevy_reflect`,
this should not cause any issues. However, manual implementations of
`Reflect` that excluded a `GetTypeRegistration` impl for their type will
need to add one.
```rust
#[derive(Reflect)]
struct Foo<T: FromReflect> {
data: MyCustomType<T>
}
// OLD
impl<T: FromReflect> Reflect for MyCustomType<T> {/* ... */}
// NEW
impl<T: FromReflect + GetTypeRegistration> Reflect for MyCustomType<T> {/* ... */}
impl<T: FromReflect + GetTypeRegistration> GetTypeRegistration for MyCustomType<T> {/* ... */}
```
---------
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: radiish <cb.setho@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Hi, this is a minimal implementation of #12159. I wasn't sure if the
`EventLoopProxy` should be wrapped somewhat to make it more explicit.
# Objective
Minimal implementation of #12159
When using `UpdateMode::Reactive` it is currently not possible to
request a redraw when a long running task is finished or an external
source has new data.
This makes the following possible which will then run an app update once
``` rust
// EventLoopProxy is Send on most architectures
// The EventLoopProxy can also be saved in a thread local for WASM or a static in other architecturecs
pub fn example(proxy: NonSend<EventLoopProxy<()>>) {
let clone: EventLoopProxy<()> = proxy.clone();
thread::spawn(move || {
// do long work
clone.send_event(());
});
}
```
## Solution
By using the EventLoopProxy one can manually send events from external
threads to the event loop as `UserEvent`s.
This simply sets redraw_requested when a `UserEvent` is received.
## Changelog
- Added the ability to request a redraw from an external source
---------
Co-authored-by: Kellner, Robin <Robin.Kellner@vector.com>
# Objective
Correct references to `Input` into `ButtonInput` in the keyboard input
docs since it was renamed in 0.13.
## Solution
Change the type used in the keyboard input docs from `Input` to
`ButtonInput`.
# Objective
`Dir3` and `Dir3A` can be rotated using `Quat`s. However, if enough
floating point error accumulates or (more commonly) the rotation itself
is degenerate (like not normalized), the resulting direction can also
become denormalized.
Currently, with debug assertions enabled, it panics in these cases with
the message `rotated.is_normalized()`. This error message is unclear,
doesn't give information about *how* it is denormalized (like is the
length too large, NaN, or something else), and is overall not very
helpful. Panicking for small-ish error might also be a bit too strict,
and has lead to unwanted crashes in crates like `bevy_xpbd` (although it
has also helped in finding actual bugs).
The error message should be clearer and give more context, and it
shouldn't cause unwanted crashes.
## Solution
Change the `debug_assert!` to a warning for small error with a (squared
length) threshold of 2e-4 and a panic for clear error with a threshold
of 2e-2. The warnings mention the direction type and the length of the
denormalized vector.
Here's what the error and warning look like:
```
Error: `Dir3` is denormalized after rotation. The length is 1.014242.
```
```
Warning: `Dir3A` is denormalized after rotation. The length is 1.0001414.
```
I gave the same treatment to `new_unchecked`:
```
Error: The vector given to `Dir3::new_unchecked` is not normalized. The length is 1.014242.
```
```
Warning: The vector given to `Dir3A::new_unchecked` is not normalized. The length is 1.0001414.
```
---
## Discussion
### Threshold values
The thresholds are somewhat arbitrary. 2e-4 is what Glam uses for the
squared length in `is_normalized` (after I corrected it in
bitshifter/glam-rs#480), and 2e-2 is just what I thought could be a
clear sign of something being critically wrong. I can definitely tune
them if there are better thresholds though.
### Logging
`bevy_math` doesn't have `bevy_log`, so we can't use `warn!` or
`error!`. This is why I made it use just `eprintln!` and `panic!` for
now. Let me know if there's a better way of logging errors in
`bevy_math`.
# Objective
In my library,
[`bevy_dev_console`](https://github.com/doonv/bevy_dev_console) I need
access to `App` within `LogPlugin::update_subscriber` in order to
communicate with the `App` from my custom `Layer`.
## Solution
Give access to `App`.
---
## Changelog
- Added access to `App` within `LogPlugin::update_subscriber`
## Migration Guide
`LogPlugin::update_subscriber` now has a `&mut App` parameter. If you
don't need access to `App`, you can ignore the parameter with an
underscore (`_`).
```diff,rust
- fn update_subscriber(subscriber: BoxedSubscriber) -> BoxedSubscriber {
+ fn update_subscriber(_: &mut App, subscriber: BoxedSubscriber) -> BoxedSubscriber {
Box::new(subscriber.with(CustomLayer))
}
```
# Objective
- Allow users to read window events in the sequence they appeared. This
is important for precise input handling when there are multiple input
events in a single frame (e.g. click and release vs release and click).
## Solution
- Add a mega-enum `WinitEvent` that collects window events, and send
those alongside the existing more granular window events.
---
## Changelog
- Added `WinitEvent` event that aggregates all window events into a
synchronized event stream.
# Objective
Fixes https://github.com/bevyengine/bevy/issues/11157.
## Solution
Stop using `BackgroundColor` as a color tint for `UiImage`. Add a
`UiImage::color` field for color tint instead. Allow a UI node to
simultaneously include a solid-color background and an image, with the
image rendered on top of the background (this is already how it works
for e.g. text).
![2024-02-29_1709239666_563x520](https://github.com/bevyengine/bevy/assets/12173779/ec50c9ef-4c7f-4ab8-a457-d086ce5b3425)
---
## Changelog
- The `BackgroundColor` component now renders a solid-color background
behind `UiImage` instead of tinting its color.
- Removed `BackgroundColor` from `ImageBundle`, `AtlasImageBundle`, and
`ButtonBundle`.
- Added `UiImage::color`.
- Expanded `RenderUiSystem` variants.
- Renamed `bevy_ui::extract_text_uinodes` to `extract_uinodes_text` for
consistency.
## Migration Guide
- `BackgroundColor` no longer tints the color of UI images. Use
`UiImage::color` for that instead.
- For solid color buttons, replace `ButtonBundle { background_color:
my_color.into(), ... }` with `ButtonBundle { image:
UiImage::default().with_color(my_color), ... }`, and update button
interaction systems to use `UiImage::color` instead of `BackgroundColor`
as well.
- `bevy_ui::RenderUiSystem::ExtractNode` has been split into
`ExtractBackgrounds`, `ExtractImages`, `ExtractBorders`, and
`ExtractText`.
- `bevy_ui::extract_uinodes` has been split into
`bevy_ui::extract_uinode_background_colors` and
`bevy_ui::extract_uinode_images`.
- `bevy_ui::extract_text_uinodes` has been renamed to
`extract_uinode_text`.
# Objective
After the `TextureAtlas` changes that landed in 0.13,
`SpriteSheetBundle` is equivalent to `TextureAtlas` + `SpriteBundle` and
`AtlasImageBundle` is equivalent to `TextureAtlas` + `ImageBundle`. As
such, the atlas bundles aren't particularly useful / necessary additions
to the API anymore.
In addition, atlas bundles are inconsistent with `ImageScaleMode` (also
introduced in 0.13) which doesn't have its own version of each image
bundle.
## Solution
Deprecate `SpriteSheetBundle` and `AtlasImageBundle` in favor of
including `TextureAtlas` as a separate component alongside
`SpriteBundle` and `ImageBundle`, respectively.
---
## Changelog
- Deprecated `SpriteSheetBundle` and `AtlasImageBundle`.
## Migration Guide
- `SpriteSheetBundle` has been deprecated. Use `TextureAtlas` alongside
a `SpriteBundle` instead.
- `AtlasImageBundle` has been deprecated. Use `TextureAtlas` alongside
an `ImageBundle` instead.
# Objective
- Part of #9400.
- Add light gizmos for `SpotLight`, `PointLight` and `DirectionalLight`.
## Solution
- Add a `ShowLightGizmo` and its related gizmo group and plugin, that
shows a gizmo for all lights of an entities when inserted on it. Light
display can also be toggled globally through the gizmo config in the
same way it can already be done for `Aabb`s.
- Add distinct segment setters for height and base one `Cone3dBuilder`.
This allow having a properly rounded base without too much edges along
the height. The doc comments explain how to ensure height and base
connect when setting different values.
Gizmo for the three light types without radius with the depth bias set
to -1:
![without-radius](https://github.com/bevyengine/bevy/assets/18357657/699d0154-f367-4727-9b09-8b458d96a0e2)
With Radius:
![with-radius](https://github.com/bevyengine/bevy/assets/18357657/f3af003e-dbba-427a-a305-c5cc1676e340)
Possible future improvements:
- Add a billboarded sprite with a distinct sprite for each light type.
- Display the intensity of the light somehow (no idea how to represent
that apart from some text).
---
## Changelog
### Added
- The new `ShowLightGizmo`, part of the `LightGizmoPlugin` and
configurable globally with `LightGizmoConfigGroup`, allows drawing gizmo
for `PointLight`, `SpotLight` and `DirectionalLight`. The gizmos color
behavior can be controlled with the `LightGizmoColor` member of
`ShowLightGizmo` and `LightGizmoConfigGroup`.
- The cone gizmo builder (`Cone3dBuilder`) now allows setting a
differing number of segments for the base and height.
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
Bevy's `Dir3` and `Dir3A` only implement `Mul<f32>` and not vice versa,
and `Dir2` can not be multiplied by `f32` at all. They all should
implement multiplication both ways, just like Glam's vector types.
## Solution
Implement `Mul<Dir2>`, `Mul<Dir3>`, and `Mul<Dir3A>` for `f32`, and
`Mul<f32>` for `Dir2`.
# Objective
Adoption of #2104 and #11843. The `Option<usize>` wastes 3-7 bytes of
memory per potential entry, and represents a scaling memory overhead as
the ID space grows.
The goal of this PR is to reduce memory usage without significantly
impacting common use cases.
Co-Authored By: @NathanSWard
Co-Authored By: @tygyh
## Solution
Replace `usize` in `SparseSet`'s sparse array with
`nonmax::NonMaxUsize`. NonMaxUsize wraps a NonZeroUsize, and applies a
bitwise NOT to the value when accessing it. This allows the compiler to
niche the value and eliminate the extra padding used for the `Option`
inside the sparse array, while moving the niche value from 0 to
usize::MAX instead.
Checking the [diff in x86 generated
assembly](6e4da653cc),
this change actually results in fewer instructions generated. One
potential downside is that it seems to have moved a load before a
branch, which means we may be incurring a cache miss even if the element
is not there.
Note: unlike #2104 and #11843, this PR only targets the metadata stores
for the ECS and not the component storage itself. Due to #9907 targeting
`Entity::generation` instead of `Entity::index`, `ComponentSparseSet`
storing only up to `u32::MAX` elements would become a correctness issue.
This will come with a cost when inserting items into the SparseSet, as
now there is a potential for a panic. These cost are really only
incurred when constructing a new Table, Archetype, or Resource that has
never been seen before by the World. All operations that are fairly cold
and not on any particular hotpath, even for command application.
---
## Changelog
Changed: `SparseSet` now can only store up to `usize::MAX - 1` elements
instead of `usize::MAX`.
Changed: `SparseSet` now uses 33-50% less memory overhead per stored
item.
Follow up to #11057
Implemented suggestions from reviewers from: a simpler
fit_canvas_to_parent leads to an explicit CSS setting to the canvas.
From my understanding, it has do be set after wgpu creation due to wgpu
overriding the canvas width/height:
4400a58470/examples/src/utils.rs (L68-L74)
# Changelog
- Re-enable a `fit_canvas_to_parent`, it's removal from
https://github.com/bevyengine/bevy/pull/11057 was problematic. Still,
its inner working is more simple than before: bevy doesn't handle its
resizing, winit does.
## Migration Guide
- Cancels the migration from
https://github.com/bevyengine/bevy/pull/11057
# Objective
Fixes https://github.com/bevyengine/bevy/issues/11628
## Migration Guide
`Command` and `CommandQueue` have migrated from `bevy_ecs::system` to
`bevy_ecs::world`, so `use bevy_ecs::world::{Command, CommandQueue};`
when necessary.
# Objective
Fixes#11298. Make the use of bevy_log vs bevy_utils::tracing more
consistent.
## Solution
Replace all uses of bevy_log's logging macros with the reexport from
bevy_utils. Remove bevy_log as a dependency where it's no longer needed
anymore.
Ideally we should just be using tracing directly, but given that all of
these crates are already using bevy_utils, this likely isn't that great
of a loss right now.
# Objective
bevy_ecs has been developed with a de facto assumption that `Entity` is
to be treated as an opaque identifier by external users, and that its
internal representation is readable but in no way guaranteed to be
stable between versions of bevy_ecs.
This hasn't been clear to users, and the functions on the type that
expose its guts speak a different story.
## Solution
Explicitly document the lack of stability here and define internal
representation changes as a non-breaking change under SemVer. Give it
the same treatment that the standard lib gives `TypeId`.
# Objective
While mucking around with batch_and_prepare systems, it became apparent
that `GpuArrayBufferIndex::index` doesn't need to be a NonMaxU32.
## Solution
Replace it with a normal u32.
This likely has some potential perf benefit by avoiding panics and the
NOT operations, but I haven't been able to find any substantial gains,
so this is primarily for code quality.
---
## Changelog
Changed: `GpuArrayBufferIndex::index` is now a u32.
## Migration Guide
`GpuArrayBuferIndex::index` is now a u32 instead of a `NonMaxU32`.
Remove any calls to `NonMaxU32::get` on the member.
# Objective
- Fix mismatch between the `Component` trait method and the `World`
method.
## Solution
- Replace init_component_info with register_component_hooks.
# Objective
This PR unpins `web-sys` so that unrelated projects that have
`bevy_render` in their workspace can finally update their `web-sys`.
More details in and fixes#12246.
## Solution
* Update `wgpu` from 0.19.1 to 0.19.3.
* Remove the `web-sys` pin.
* Update docs and wasm helper to remove the now-stale
`--cfg=web_sys_unstable_apis` Rust flag.
---
## Changelog
Updated `wgpu` to v0.19.3 and removed `web-sys` pin.
This is an implementation within `bevy_window::window` that fixes
#12229.
# Objective
Fixes#12229, allow users to retrieve the window's size and physical
size as Vectors without having to manually construct them using
`height()` and `width()` or `physical_height()` and `physical_width()`
## Solution
As suggested in #12229, created two public functions within `window`:
`size() -> Vec` and `physical_size() -> UVec` that return the needed
Vectors ready-to-go.
### Discussion
My first FOSS PRQ ever, so bear with me a bit. I'm new to this.
- I replaced instances of ```Vec2::new(window.width(),
window.height());``` or `UVec2::new(window.physical_width(),
window.physical_height());` within bevy examples be replaced with their
`size()`/`physical_size()` counterparts?
- Discussion within #12229 still holds: should these also be added to
WindowResolution?
Although we cached hashes of `MeshVertexBufferLayout`, we were paying
the cost of `PartialEq` on `InnerMeshVertexBufferLayout` for every
entity, every frame. This patch changes that logic to place
`MeshVertexBufferLayout`s in `Arc`s so that they can be compared and
hashed by pointer. This results in a 28% speedup in the
`queue_material_meshes` phase of `many_cubes`, with frustum culling
disabled.
Additionally, this patch contains two minor changes:
1. This commit flattens the specialized mesh pipeline cache to one level
of hash tables instead of two. This saves a hash lookup.
2. The example `many_cubes` has been given a `--no-frustum-culling`
flag, to aid in benchmarking.
See the Tracy profile:
<img width="1064" alt="Screenshot 2024-02-29 144406"
src="https://github.com/bevyengine/bevy/assets/157897/18632f1d-1fdd-4ac7-90ed-2d10306b2a1e">
## Migration guide
* Duplicate `MeshVertexBufferLayout`s are now combined into a single
object, `MeshVertexBufferLayoutRef`, which contains an
atomically-reference-counted pointer to the layout. Code that was using
`MeshVertexBufferLayout` may need to be updated to use
`MeshVertexBufferLayoutRef` instead.
# Objective
- Provide a reliable and performant mechanism to allows users to keep
components synchronized with external sources: closing/opening sockets,
updating indexes, debugging etc.
- Implement a generic mechanism to provide mutable access to the world
without allowing structural changes; this will not only be used here but
is a foundational piece for observers, which are key for a performant
implementation of relations.
## Solution
- Implement a new type `DeferredWorld` (naming is not important,
`StaticWorld` is also suitable) that wraps a world pointer and prevents
user code from making any structural changes to the ECS; spawning
entities, creating components, initializing resources etc.
- Add component lifecycle hooks `on_add`, `on_insert` and `on_remove`
that can be assigned callbacks in user code.
---
## Changelog
- Add new `DeferredWorld` type.
- Add new world methods: `register_component::<T>` and
`register_component_with_descriptor`. These differ from `init_component`
in that they provide mutable access to the created `ComponentInfo` but
will panic if the component is already in any archetypes. These
restrictions serve two purposes:
1. Prevent users from defining hooks for components that may already
have associated hooks provided in another plugin. (a use case better
served by observers)
2. Ensure that when an `Archetype` is created it gets the appropriate
flags to early-out when triggering hooks.
- Add methods to `ComponentInfo`: `on_add`, `on_insert` and `on_remove`
to be used to register hooks of the form `fn(DeferredWorld, Entity,
ComponentId)`
- Modify `BundleInserter`, `BundleSpawner` and `EntityWorldMut` to
trigger component hooks when appropriate.
- Add bit flags to `Archetype` indicating whether or not any contained
components have each type of hook, this can be expanded for other flags
as needed.
- Add `component_hooks` example to illustrate usage. Try it out! It's
fun to mash keys.
## Safety
The changes to component insertion, removal and deletion involve a large
amount of unsafe code and it's fair for that to raise some concern. I
have attempted to document it as clearly as possible and have confirmed
that all the hooks examples are accepted by `cargo miri` as not causing
any undefined behavior. The largest issue is in ensuring there are no
outstanding references when passing a `DeferredWorld` to the hooks which
requires some use of raw pointers (as was already happening to some
degree in those places) and I have taken some time to ensure that is the
case but feel free to let me know if I've missed anything.
## Performance
These changes come with a small but measurable performance cost of
between 1-5% on `add_remove` benchmarks and between 1-3% on `insert`
benchmarks. One consideration to be made is the existence of the current
`RemovedComponents` which is on average more costly than the addition of
`on_remove` hooks due to the early-out, however hooks doesn't completely
remove the need for `RemovedComponents` as there is a chance you want to
respond to the removal of a component that already has an `on_remove`
hook defined in another plugin, so I have not removed it here. I do
intend to deprecate it with the introduction of observers in a follow up
PR.
## Discussion Questions
- Currently `DeferredWorld` implements `Deref` to `&World` which makes
sense conceptually, however it does cause some issues with rust-analyzer
providing autocomplete for `&mut World` references which is annoying.
There are alternative implementations that may address this but involve
more code churn so I have attempted them here. The other alternative is
to not implement `Deref` at all but that leads to a large amount of API
duplication.
- `DeferredWorld`, `StaticWorld`, something else?
- In adding support for hooks to `EntityWorldMut` I encountered some
unfortunate difficulties with my desired API. If commands are flushed
after each call i.e. `world.spawn() // flush commands .insert(A) //
flush commands` the entity may be despawned while `EntityWorldMut` still
exists which is invalid. An alternative was then to add
`self.world.flush_commands()` to the drop implementation for
`EntityWorldMut` but that runs into other problems for implementing
functions like `into_unsafe_entity_cell`. For now I have implemented a
`.flush()` which will flush the commands and consume `EntityWorldMut` or
users can manually run `world.flush_commands()` after using
`EntityWorldMut`.
- In order to allowing querying on a deferred world we need
implementations of `WorldQuery` to not break our guarantees of no
structural changes through their `UnsafeWorldCell`. All our
implementations do this, but there isn't currently any safety
documentation specifying what is or isn't allowed for an implementation,
just for the caller, (they also shouldn't be aliasing components they
didn't specify access for etc.) is that something we should start doing?
(see 10752)
Please check out the example `component_hooks` or the tests in
`bundle.rs` for usage examples. I will continue to expand this
description as I go.
See #10839 for a more ergonomic API built on top of this one that isn't
subject to the same restrictions and supports `SystemParam` dependency
injection.
# Objective
- We introduce a gizmo that displays coordinate axes relative to a
Transform*, primarily for debugging purposes.
- See #9400
## Solution
A new method, `Gizmos::axes`, takes a `Transform`* as input and displays
the standard coordinate axes, transformed according to it; its signature
looks like this:
````rust
pub fn axes(&mut self, transform: into TransformPoint, base_length: f32) { //... }
````
If my carefully placed asterisks hadn't already tipped you off, the
argument here is not actually a `Transform` but instead anything which
implements `TransformPoint`, which allows it to work also with
`GlobalTransform` (and also `Mat4` and `Affine3A`, if the user happens
to be hand-rolling transformations in some way).
The `base_length` parameter is a scaling factor applied to the
coordinate vectors before the transformation takes place; in other
words, the caller can use this to help size the coordinate axes
appropriately for the entity that they are attached to.
An example invocation of this method looks something like this:
````rust
fn draw_axes_system(
mut gizmos: Gizmos,
query: Query<&Transform, With<MyMarkerComponent>>,
) {
for &transform in &query {
gizmos.axes(transform, 2.);
}
}
````
The result is the three coordinate axes, X, Y, Z (colored red, green,
and blue, respectively), drawn onto the entity:
<img width="206" alt="Screenshot 2024-02-29 at 2 41 45 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/789d1703-29ae-4295-80ab-b87459cf8037">
Note that, if scaling was applied as part of the given transformation,
it shows up in scaling on the axes as well:
<img width="377" alt="Screenshot 2024-02-29 at 2 43 53 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/6dc1caf4-8b3e-47f7-a86a-8906d870fa72">
---
## Changelog
- Added `Gizmos::axes` in bevy_gizmos/src/arrows.rs
- Fixed a minor issue with `ArrowBuilder::with_tip_length` not correctly
implementing builder style (no external impact)
---
## Discussion
### Design considerations
I feel pretty strongly that having no default length scale is for the
best, at least for the time being, since it's very easy for the length
scale to be too small, leading to the axes being hidden inside the body
of the object they are associated with. That is, if the API instead
looked like this:
````rust
gizmos.axes(transform); // or
gizmos.axes(transform).with_length_scale(3.0);
````
then I think it's a reasonable expectation that the first thing would
"just work" for most applications, and it wouldn't, which would be kind
of a footgun.
### Future steps
There are a few directions that this might expand in the future:
1. Introduce additional options via the standard builder pattern; i.e.
introducing `AxesBuilder<T: TransformPoint>` so that people can
configure the axis colors, normalize all axes to a fixed length
independent of scale deformations, etc.
2. Fold this functionality into a plugin (like AabbGizmoPlugin) so that
the functionality becomes more-or-less automatic based on certain fixed
marker components. This wouldn't be very hard to implement, and it has
the benefit of making the axes more frictionless to use. Furthermore, if
we coupled this to the AABB functionality we already have, we could also
ensure that the plugin automatically sizes the axes (by coupling their
size to the dimensions of the AABB, for example).
3. Implement something similar for 2d. Honestly, I have no idea if this
is desired/useful, but I could probably just implement it in this PR if
that's the case.
# Objective
- As part of the migration process we need to a) see the end effect of
the migration on user ergonomics b) check for serious perf regressions
c) actually migrate the code
- To accomplish this, I'm going to attempt to migrate all of the
remaining user-facing usages of `LegacyColor` in one PR, being careful
to keep a clean commit history.
- Fixes#12056.
## Solution
I've chosen to use the polymorphic `Color` type as our standard
user-facing API.
- [x] Migrate `bevy_gizmos`.
- [x] Take `impl Into<Color>` in all `bevy_gizmos` APIs
- [x] Migrate sprites
- [x] Migrate UI
- [x] Migrate `ColorMaterial`
- [x] Migrate `MaterialMesh2D`
- [x] Migrate fog
- [x] Migrate lights
- [x] Migrate StandardMaterial
- [x] Migrate wireframes
- [x] Migrate clear color
- [x] Migrate text
- [x] Migrate gltf loader
- [x] Register color types for reflection
- [x] Remove `LegacyColor`
- [x] Make sure CI passes
Incidental improvements to ease migration:
- added `Color::srgba_u8`, `Color::srgba_from_array` and friends
- added `set_alpha`, `is_fully_transparent` and `is_fully_opaque` to the
`Alpha` trait
- add and immediately deprecate (lol) `Color::rgb` and friends in favor
of more explicit and consistent `Color::srgb`
- standardized on white and black for most example text colors
- added vector field traits to `LinearRgba`: ~~`Add`, `Sub`,
`AddAssign`, `SubAssign`,~~ `Mul<f32>` and `Div<f32>`. Multiplications
and divisions do not scale alpha. `Add` and `Sub` have been cut from
this PR.
- added `LinearRgba` and `Srgba` `RED/GREEN/BLUE`
- added `LinearRgba_to_f32_array` and `LinearRgba::to_u32`
## Migration Guide
Bevy's color types have changed! Wherever you used a
`bevy::render::Color`, a `bevy::color::Color` is used instead.
These are quite similar! Both are enums storing a color in a specific
color space (or to be more precise, using a specific color model).
However, each of the different color models now has its own type.
TODO...
- `Color::rgba`, `Color::rgb`, `Color::rbga_u8`, `Color::rgb_u8`,
`Color::rgb_from_array` are now `Color::srgba`, `Color::srgb`,
`Color::srgba_u8`, `Color::srgb_u8` and `Color::srgb_from_array`.
- `Color::set_a` and `Color::a` is now `Color::set_alpha` and
`Color::alpha`. These are part of the `Alpha` trait in `bevy_color`.
- `Color::is_fully_transparent` is now part of the `Alpha` trait in
`bevy_color`
- `Color::r`, `Color::set_r`, `Color::with_r` and the equivalents for
`g`, `b` `h`, `s` and `l` have been removed due to causing silent
relatively expensive conversions. Convert your `Color` into the desired
color space, perform your operations there, and then convert it back
into a polymorphic `Color` enum.
- `Color::hex` is now `Srgba::hex`. Call `.into` or construct a
`Color::Srgba` variant manually to convert it.
- `WireframeMaterial`, `ExtractedUiNode`, `ExtractedDirectionalLight`,
`ExtractedPointLight`, `ExtractedSpotLight` and `ExtractedSprite` now
store a `LinearRgba`, rather than a polymorphic `Color`
- `Color::rgb_linear` and `Color::rgba_linear` are now
`Color::linear_rgb` and `Color::linear_rgba`
- The various CSS color constants are no longer stored directly on
`Color`. Instead, they're defined in the `Srgba` color space, and
accessed via `bevy::color::palettes::css`. Call `.into()` on them to
convert them into a `Color` for quick debugging use, and consider using
the much prettier `tailwind` palette for prototyping.
- The `LIME_GREEN` color has been renamed to `LIMEGREEN` to comply with
the standard naming.
- Vector field arithmetic operations on `Color` (add, subtract, multiply
and divide by a f32) have been removed. Instead, convert your colors
into `LinearRgba` space, and perform your operations explicitly there.
This is particularly relevant when working with emissive or HDR colors,
whose color channel values are routinely outside of the ordinary 0 to 1
range.
- `Color::as_linear_rgba_f32` has been removed. Call
`LinearRgba::to_f32_array` instead, converting if needed.
- `Color::as_linear_rgba_u32` has been removed. Call
`LinearRgba::to_u32` instead, converting if needed.
- Several other color conversion methods to transform LCH or HSL colors
into float arrays or `Vec` types have been removed. Please reimplement
these externally or open a PR to re-add them if you found them
particularly useful.
- Various methods on `Color` such as `rgb` or `hsl` to convert the color
into a specific color space have been removed. Convert into
`LinearRgba`, then to the color space of your choice.
- Various implicitly-converting color value methods on `Color` such as
`r`, `g`, `b` or `h` have been removed. Please convert it into the color
space of your choice, then check these properties.
- `Color` no longer implements `AsBindGroup`. Store a `LinearRgba`
internally instead to avoid conversion costs.
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
Co-authored-by: Afonso Lage <lage.afonso@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
# Objective
Just some mild annoyances:
- The `Color::Oklaba`, `Color::Oklcha` and `oklaba::Oklaba` doc comments
were inconsistent with the others
- The crate-level docs didn't include `Oklch` in the list of
representations and misspelt it in a later paragraph
## Solution
- Fix 'em
# Objective
- Cull 2D text outside the view frustum.
- Part of #11081.
## Solution
- Compute AABBs for entities with a `Text2DBundle` to enable culling
them.
`text2d` example with AABB gizmos on the text entities:
https://github.com/bevyengine/bevy/assets/18357657/52ed3ddc-2274-4480-835b-a7cf23338931
---
## Changelog
### Added
- 2D text outside the view are now culled with the
`calculate_bounds_text2d` system adding the necessary AABBs.
# Objective
`bevy_tasks` provides utilities for parallel mapping over slices. It can
be useful to have a chunk index available in the iteration function to
know which part of the original slice is being processed.
## Solution
Adds an index argument to the parallel map functions in `bevy_tasks`.
---
## Changelog
### Changed
- `par_chunk_map`, `par_splat_map`, `par_chunk_map_mut`, and
`par_splat_map_mut` now provide a chunk index during iteration.
## Migration Guide
Functions passed as arguments to `par_chunk_map`, `par_splat_map`,
`par_chunk_map_mut`, and `par_splat_map_mut` must now take an additional
index argument.
# Objective
Split up from #12017, rename Bevy's direction types.
Currently, Bevy has the `Direction2d`, `Direction3d`, and `Direction3dA`
types, which provide a type-level guarantee that their contained vectors
remain normalized. They can be very useful for a lot of APIs for safety,
explicitness, and in some cases performance, as they can sometimes avoid
unnecessary normalizations.
However, many consider them to be inconvenient to use, and opt for
standard vector types like `Vec3` because of this. One reason is that
the direction type names are a bit long and can be annoying to write (of
course you can use autocomplete, but just typing `Vec3` is still nicer),
and in some intances, the extra characters can make formatting worse.
The naming is also inconsistent with Glam's shorter type names, and
results in names like `Direction3dA`, which (in my opinion) are
difficult to read and even a bit ugly.
This PR proposes renaming the types to `Dir2`, `Dir3`, and `Dir3A`.
These names are nice and easy to write, consistent with Glam, and work
well for variants like the SIMD aligned `Dir3A`. As a bonus, it can also
result in nicer formatting in a lot of cases, which can be seen from the
diff of this PR.
Some examples of what it looks like: (copied from #12017)
```rust
// Before
let ray_cast = RayCast2d::new(Vec2::ZERO, Direction2d::X, 5.0);
// After
let ray_cast = RayCast2d::new(Vec2::ZERO, Dir2::X, 5.0);
```
```rust
// Before (an example using Bevy XPBD)
let hit = spatial_query.cast_ray(
Vec3::ZERO,
Direction3d::X,
f32::MAX,
true,
SpatialQueryFilter::default(),
);
// After
let hit = spatial_query.cast_ray(
Vec3::ZERO,
Dir3::X,
f32::MAX,
true,
SpatialQueryFilter::default(),
);
```
```rust
// Before
self.circle(
Vec3::new(0.0, -2.0, 0.0),
Direction3d::Y,
5.0,
Color::TURQUOISE,
);
// After (formatting is collapsed in this case)
self.circle(Vec3::new(0.0, -2.0, 0.0), Dir3::Y, 5.0, Color::TURQUOISE);
```
## Solution
Rename `Direction2d`, `Direction3d`, and `Direction3dA` to `Dir2`,
`Dir3`, and `Dir3A`.
---
## Migration Guide
The `Direction2d` and `Direction3d` types have been renamed to `Dir2`
and `Dir3`.
## Additional Context
This has been brought up on the Discord a few times, and we had a small
[poll](https://discord.com/channels/691052431525675048/1203087353850364004/1212465038711984158)
on this. `Dir2`/`Dir3`/`Dir3A` was quite unanimously chosen as the best
option, but of course it was a very small poll and inconclusive, so
other opinions are certainly welcome too.
---------
Co-authored-by: IceSentry <c.giguere42@gmail.com>
# Objective
- Fixes#12170
## Solution
- Moved the existing `color_from_entity` internals into
`Hsla::sequence_dispersed` which generates a randomly distributed but
deterministic color sequence based.
- Replicated the method for `Lcha` and `Oklcha` as well.
## Examples
### Getting a few colours for a quick palette
```rust
let palette = Hsla::sequence_dispersed().take(5).collect::<Vec<_>>();
/*[
Hsla::hsl(0.0, 1., 0.5),
Hsla::hsl(222.49225, 1., 0.5),
Hsla::hsl(84.984474, 1., 0.5),
Hsla::hsl(307.4767, 1., 0.5),
Hsla::hsl(169.96895, 1., 0.5),
]*/
```
### Getting a colour from an `Entity`
```rust
let color = Oklcha::sequence_dispersed().nth(entity.index() as u32).unwrap();
```
## Notes
This was previously a private function exclusively for `Entity` types.
I've decided it should instead be public and operate on a `u32`
directly, since this function may have broader uses for debugging
purposes.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/11929
- make sysinfo plugin optional
## Solution
- added features to allow for conditional compilation
---
## Migration Guide
- For users who disable default features of bevy and wish to enable the
diagnostic plugin, add `sysinfo_plugin` to your bevy features list.
---------
Co-authored-by: ebola <dev@axiomatic>
Co-authored-by: François <mockersf@gmail.com>
# Objective
fix#12182
- extract (or default) target camera for ui material nodes in the same
way as for other material nodes
- render ui material nodes only to their specified target
# Objective
Improve the `bevy::math::cubic_splines` module by making it more
flexible and adding new curve types.
Closes#10220
## Solution
Added new spline types and improved existing
---
## Changelog
### Added
- `CubicNurbs` rational cubic curve generator, allows setting the knot
vector and weights associated with every point
- `LinearSpline` curve generator, allows generating a linearly
interpolated curve segment
- Ability to push additional cubic segments to `CubicCurve`
- `IntoIterator` and `Extend` implementations for `CubicCurve`
### Changed
- `Point` trait has been implemented for more types: `Quat` and `Vec4`.
- `CubicCurve::coefficients` was moved to `CubicSegment::coefficients`
because the function returns `CubicSegment`, so it seems logical to be
associated with `CubicSegment` instead. The method is still not public.
### Fixed
- `CubicBSpline::new` was referencing Cardinal spline instead of
B-Spline
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
Co-authored-by: Miles Silberling-Cook <nth.tensor@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
- #12165 recently added links to Bevy errors in error messages.
- The links were in the form of `See:
https://bevyengine.org/learn/errors/#b000N`
- B0004 does not have the colon separating `See` and the link, unlike
the rest of the error messages
## Solution
- Add a colon, for consistency :)
# Objective
- More reflection
## Solution
- More. Reflection.
(not sure what bevy's policy on `derive(Debug)` is given that reflection
already lets you accomplish something largely equivalent; maybe
`derive(Reflect)` should generate a `Debug` impl that goes through
`Reflect::debug` unless you opt out?)
# Objective
The `css` contains all of the `basic` colors. Rather than defining them
twice, we can re-export them.
Suggested by @viridia <3
## Solution
- Re-export basic color palette within the css color palette.
- Remove the duplicate colors
- Fix alphabetization of the basic color palette file while I'm here
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
- Complete compatibility with CSS Module 4
## Solution
- Added `Oklcha` which implements the Oklch color model.
- Updated `Color` and `LegacyColor` accordingly.
## Migration Guide
- Convert `Oklcha` to `Oklaba` using the provided `From` implementations
and then handle accordingly.
## Notes
This is the _last_ color space missing from the CSS Module 4 standard,
and is also the one I believe we should recommend users actually work
with for hand-crafting colours. It has all the uniformity benefits of
Oklab combined with the intuition chroma and hue provide (when compared
to a-axis and b-axis parameters).
# Objective
- Implement grid gizmos, suggestion of #9400
## Solution
- Added `gizmos.grid(...) ` and `gizmos.grid_2d(...)`
- The grids may be configured using `.outer_edges(...)` to specify
whether to draw the outer border/edges of the grid and `.skew(...)`to
specify the skew of the grid along the x or y directions.
---
## Changelog
- Added a `grid` module to `bevy_gizmos` containing `gizmos.grid(...) `
and `gizmos.grid_2d(...)` as well as assorted items.
- Updated the `2d_gizmos` and `3d_gizmos` examples to use grids.
## Additional
The 2D and 3D examples now look like this:
<img width="1440" alt="Screenshot 2024-02-20 at 15 09 40"
src="https://github.com/bevyengine/bevy/assets/62256001/ce04191e-d839-4faf-a6e3-49b6bb4b922b">
<img width="1440" alt="Screenshot 2024-02-20 at 15 10 07"
src="https://github.com/bevyengine/bevy/assets/62256001/317459ba-d452-42eb-ae95-7c84cdbd569b">
# Objective
As suggested in #12163 by @cart, we should add convenience constructors
to `bevy_color::Color` to match the existing API (easing migration pain)
and generally improve ergonomics.
## Solution
- Add `const fn Color::rgba(red, green, blue, alpha)` and friends, which
directly construct the appropriate variant.
- Add `const fn Color::rgb(red, green, blue)` and friends, which impute
and alpha value of 1.0.
- Add `const BLACK, WHITE, NONE` to `Color`. These are stored in
`LinearRgba` to reduce pointless conversion costs and inaccuracy.
- Changed the default `Color` from `Srgba::WHITE` to the new linear
equivalent for the same reason.
---------
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>