# Objective
Remove the `new_with_` prefixes from the `TextLayout` constuctor
functions. Generally, the "new" part is redundant and "with" is used by
fluent APIs.
## Solution
Just delete the prefixes, shorten the names (all on `TextLayout`).
* `new_with_justify` -> `justify`
* `new_with_linebreak` -> `linebreak`
* `new_with_no_wrap` -> `no_wrap`
## Objective
Fixes#15823
The `sampling_primitives` and `random_sampling` examples are redundant —
they both demonstrate sampling random points from primitive shapes and
even had identical doc descriptions. Per maintainer consensus,
`sampling_primitives` should be removed.
## Solution
- Removed `examples/math/sampling_primitives.rs`
- Removed the corresponding entry from `Cargo.toml`
- Removed the corresponding entry from `examples/README.md`
## Testing
- Verified `random_sampling` example still exists and is unmodified
- Confirmed no other files reference `sampling_primitives`
# Objective
- `glam`, `hexasphere` & `rand` have released their latest versions,
update Bevy to support them.
## Solution
- The above have been updated to their compatible versions. `rand_distr`
updated as well to match `rand` v0.10 support.
- `rand_chacha` is soft deprecated and no longer used by `rand`, so its
usage has been changed to `chacha20` to match `rand` dep tree.
- `uuid` is in the process of updating to `getrandom` v0.4, which `rand`
v0.10 supports. This PR remains in draft until a new `uuid` release hits
crates.io.
- `RngCore` is now `Rng`, and `Rng` is now `RngExt`, so this required
updating across many files.
- `choose_multiple` method is deprecated, changed to `sample`.
## Testing
- Chase all compiler errors, since this should not regress any already
existing behaviour.
- This must pass CI without regressions.
## Additional Notes
`getrandom` v0.4 doesn't add anything new for Web WASM support, so the
same `wasm_js` feature is used.
# Objective
We include several run condition combinators, such as `and`, `or`, etc.,
which short-circuit depending on the output of the first condition in
the combinator.
This is incredibly error-prone due to the subtle way that
short-circuiting interacts with change detection -- rather than reacting
to changes frame-by-frame, the second condition in short-circuiting
combinator will react to _the last time that the first condition did not
short circuit_. This can easily lead to confusing bugs if the user does
not expect this, and I suspect that most users will not expect this.
For this reason, when combining multiple run conditions added via
`.run_if()`, all run conditions are intentionally eagerly evaluated.
## Solution
Add new run condition combinators `and_then`, `and_eager`, `or_else`,
`or_eager`, etc., for clarity, and deprecate the previous methods,
pointing users to the new ones.
After the previous combinators have been removed for a few release
cycles, we should consider renaming combinators such as `and_eager` to
simply `and`.
# Migration Guide
Bevy supports run condition combinators (`and`, `or`, `nan`, `nor`),
which have historically short-circuited. While familiar,
short-circuiting interacts with Bevy’s change detection in a subtle way:
when the left-hand condition short-circuits, the right-hand condition is
not evaluated and therefore does not observe changes on that frame.
Instead, it reacts based on the last frame it ran, which can lead to
confusing and non-local bugs.
By contrast, Bevy's scheduler combines multiple .run_if(...) conditions
using eager evaluation, which avoids this known pitfall.
To make intent explicit and reduce footguns, short-circuiting
combinators have been renamed and eagerly-evaluated variants have been
added.
## Examples
Most users should use eager evaluation, which ensures all conditions
participate in change detection every frame:
```rust
// Before (deprecated)
cond_a.and(cond_b)
cond_a.or(cond_b)
cond_a.nand(cond_b)
cond_a.nor(cond_b)
// After (recommended default)
cond_a.and_eager(cond_b)
cond_a.or_eager(cond_b)
cond_a.nand_eager(cond_b)
cond_a.nor_eager(cond_b)
```
If you *intentionally rely on short-circuiting* for correctness, use the
explicit short-circuiting variants:
```rust
// Explicit short-circuiting
cond_a.and_then(cond_b)
cond_a.or_else(cond_b)
cond_a.nand_then(cond_b)
cond_a.nor_else(cond_b)
```
`xor` and `xnor` are unchanged, as they cannot short-circuit by nature.
## Future naming note
The `_eager` suffix exists to ease migration without changing the
behavior of existing code that relied on short-circuiting. After the
deprecated combinators have been removed for a few release cycles, we
expect to revisit naming and likely remove the _eager suffix, keeping
`and_then` / `or_else` as the explicit short-circuiting forms.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Mike <mike.hsu@gmail.com>
Implement the infrastructure needed to support portals and mirrors.
Bevy currently supports multiple cameras and rendering to off-screen
render targets, so one might naïvely think that the engine has support
for portals and mirrors already. However, Bevy is missing two key
features that enable portals and mirrors at present:
1. Bevy has support for neither custom clip planes nor oblique clip
planes. This prevents the construction of proper portals or mirrors, as
meshes that intersect the portal plane must be clipped to render
properly.
2. Bevy has no support for cameras that invert the culling mode, so
meshes that are reflected across a plane will render inside-out.
This PR addresses the two issues above:
1. This commit introduces a new field on `PerspectiveProjection`,
`near_plane`, which allows the application to specify a custom near
plane. That feature fully enables [Lengyel oblique clipping], which is
the most optimal way to achieve a custom near clipping plane. It allows
us to avoid having to support custom clip planes, which are often
implemented inefficiently in hardware.
2. This patch adds a new field on the `Camera` component,
`invert_culling`. This field causes the Bevy renderer to invert the
front face setting when rendering the objects visible from that camera.
When coupled with an appropriately-set [Householder matrix] on the
camera, this allows correct rendering of objects reflected across a
plane.
Additionally, this PR adds a new function to `bevy_math::mat3`,
`reflection_matrix`. This generates the matrix that reflects objects
across a plane, suitable for encoding into a `Transform`. It's fully
documented for ease of use.
Finally, a new example, `mirror`, has been added. This example is a
complete instance of a working mirror, combining a camera with a
Householder matrix, oblique projection, and inverted culling with a
custom material to render an animated mesh and its planar reflection.
The camera and mesh may be moved with the mouse, and the off-screen
render target that stores the rendered contents of the mirror world is
properly resized when the user resizes the window.
[Lengyel oblique clipping]:
https://terathon.com/lengyel/Lengyel-Oblique.pdf
[Householder matrix]:
https://en.wikipedia.org/wiki/Householder_transformation
<img width="2564" height="1500" alt="Screenshot 2025-12-05 212155"
src="https://github.com/user-attachments/assets/35652b58-a9a5-415a-bdff-367889a23b9f"
/>
# Objective
For resources-as-components (#19731), structs mustn't doubly derive both
`Component` and `Resource`.
## Solution
Split `AmbientLight` in two: `AmbientLight` (the resource) and
`AmbientLightOverride` (the component).
## Testing
I initially made two structs `AmbientLightComponent` and
`AmbientLightResource`, and replaced every mention with the relevant one
to ensure that I didn't confuse the two.
## Notes
- I don't know if the names are correct. I kept the easiest name for the
resource, as that's the one most often used.
- I haven't provided any conversion methods as there are already plans
to replace the component variant with something else.
---------
Co-authored-by: atlv <email@atlasdostal.com>
# Objective
This introduces a generalised 2d `Ring` shape for any underlying
primitive (i.e. what an `Annulus` is to a `Circle`). This allows us to
have "hollow" shapes or "outlines". `Ring` is also extrudable. It is
assumed that the inner and outer meshes have the same number of
vertices.
```rs
let capsule_ring = Ring::new(Capsule2d::new(50.0, 100.0), Capsule2d::new(45.0, 100.0));
let hexagon_ring = Ring::new(RegularPolygon::new(50.0, 6), RegularPolygon::new(45.0, 6)); // note vertex count must match
```
## Solution
There is a new generic primitive `Ring`, which takes as input any
`Primitive2d`, with two instances of that shape: the outer and the inner
(or hollow).
The mesh for a `RingMeshBuilder` is constructed by concatenating the
vertices of the outer and inner meshes, then walking the perimeter to
join corresponding vertices like so:
<img width="513" height="509" alt="image"
src="https://github.com/user-attachments/assets/2cecb458-3b59-44fb-858b-1beffecd1e57"
/>
```
# outer vertices, then inner vertices
positions = [
0 1 2 3 4
0' 1' 2' 3' 4'
]
# pairs of triangles
indices = [
0 1 0' 0' 1 1'
1 2 1' 1' 2 2'
2 3 2' 2' 3 3'
3 4 3' 3' 4 4'
4 0 4' 4' 0 0'
]
```
Examples of generated meshes:
<img width="398" height="351" alt="image"
src="https://github.com/user-attachments/assets/348bbd91-9f4e-4040-bfa5-d508a4308c10"
/>
<img width="472" height="376" alt="image"
src="https://github.com/user-attachments/assets/dbaf894e-6f7f-4b79-af3e-69516da85898"
/>
<img width="388" height="357" alt="image"
src="https://github.com/user-attachments/assets/cb9881e5-4518-4743-b8de-5816b632f36f"
/>
<img width="449" height="402" alt="image"
src="https://github.com/user-attachments/assets/7d2022c9-b8cf-4b4b-bb09-cbe4fe49fb89"
/>
## Testing
I've tested these changes by updating the `2d_shapes`, `3d_shapes` and
`custom_primitives` examples.
It could potentially benefit from unit tests.
---
## Showcase
<img width="1282" height="752" alt="image"
src="https://github.com/user-attachments/assets/edab9dbf-1093-43c7-9804-8e5c8a830573"
/>
_Rings of 2d primitives (bottom row)_
<img width="1282" height="752" alt="image"
src="https://github.com/user-attachments/assets/fbeed7f9-42bb-432c-bce9-cfeca87d70af"
/>
_Extrusions of rings of extrudable primitives (back row)_
---
## Follow-up work
I've only realised this from looking at Extrudable, but because I used
the mesh positions but it does assume the positions are well-ordered
around the perimeter. Extrudable instead uses the notion of a perimeter
(via indices so it doesn't matter what order the mesh positions are in),
a follow-up may be to do something similar for Ring. An alternative idea
may be to compute the perimeter first as directly a list of Vec2
positions (maybe a Perimeter trait), then construct any needed meshes
from that.
This potentially makes `Annulus` redundant as it is equivalent to a
`Ring<Circle>`. One thing of note is that `Extrusion<Annulus>` is
textured differently from `Extrusion<Ring<Circle>>`.
Another idea is to have a way to construct `PrimitiveTopology::LineList`
meshes from Primitive shapes (which may have a similar effect as
creating a Ring).
This renames the concept of `BufferedEvent` to `Message`, and updates
our APIs, comments, and documentation to refer to these types as
"messages" instead of "events". It also removes/updates anything that
considers messages to be "observable", "listenable", or "triggerable".
This is a followup to https://github.com/bevyengine/bevy/pull/20731,
which omitted the `BufferedEvent -> Message` rename for brevity.
See that post for rationale.
# Objective
Split out post process effects from bevy_core_pipeline because they are
not core pipelines.
## Solution
@IceSentry proposed something like this, not sure if the split is
exactly as he envisioned but this seems reasonable to me.
The goal is to move absolutely everything possible out of
bevy_core_pipelines to unblock bevy_pbr/bevy_sprite_render compilation.
Future PRs may attempt to move more little bits out.
## Testing
# Objective
- Allow the `Val`-helper functions to accept more types besides just
`f32`
Fixes#20549
## Solution
- Adds a new trait that can be implemented for numbers
- That trait has a method that converts `self` to `f32`
## Testing
- I tested it using Rust's testing framework (although I didn't leave
the tests in, as I don't deem them important enough)
<details>
<summary>Rust test</summary>
```rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_val_helpers_work() {
let p = px(10_u8);
assert_eq!(p, Val::Px(10.0));
let p = px(10_u16);
assert_eq!(p, Val::Px(10.0));
let p = px(10_u32);
assert_eq!(p, Val::Px(10.0));
let p = px(10_u64);
assert_eq!(p, Val::Px(10.0));
let p = px(10_u128);
assert_eq!(p, Val::Px(10.0));
let p = px(10_i8);
assert_eq!(p, Val::Px(10.0));
let p = px(10_i16);
assert_eq!(p, Val::Px(10.0));
let p = px(10_i32);
assert_eq!(p, Val::Px(10.0));
let p = px(10_i64);
assert_eq!(p, Val::Px(10.0));
let p = px(10_i128);
assert_eq!(p, Val::Px(10.0));
let p = px(10.3_f32);
assert_eq!(p, Val::Px(10.3));
let p = px(10.6_f64);
assert_eq!(p, Val::Px(10.6));
}
}
```
</details>
---
## Showcase
```rust
// Same as Val::Px(10.)
px(10);
px(10_u8);
px(10.0);
```
# Objective
Many math primitives require const generics and thus are not
constructable at runtime and also not meshable. While the use of const
generics is theoretically more performant, it makes them very difficult
to interact with in a generic way, particularly in relationship to mesh
construction. For example, a ui that would allow selecting a primitive
in order to create a mesh.
## Solution
Make them alloc and meshable.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- prepare to remove bevy_mesh re-export from bevy_render. This will be
done in 0.18, but we might as well prepare for it now.
## Solution
- Add a prelude and use bevy_mesh directly. After this pr and #20471, we
will be ready.
## Testing
- cargo check --examples
# Objective
New `rand` version, which means updating `glam` and `encase` to support
the newer ecosystem update. Does mean that this changes how WASM builds
need to be done in order to configure `getrandom` correctly, but this
can be remedied with updated docs.
## Solution
Updating all needed dependencies to their compatible versions. ~~This PR
is currently blocked by `encase`, which is waiting on [this
PR](https://github.com/teoxoy/encase/pull/88) to be merged and then a
new version published.~~ ~~This PR is no longer blocked~~,
~~`hexasphere` is blocking this PR now due to not yet having a new
release with the latest `glam` version support~~, The PR is all good to
go now, everything in order across glam/rand deps.
## Testing
- Must pass CI for all checks, tests, not introduce breaking changes.
---
## Migration Guide
With newer versions of `glam` & `encase`, the updated versions don't
seem to have introduced breakages, though as always, best to consult
their docs [1](https://docs.rs/glam/latest/glam/)
[2](https://docs.rs/encase/0.11.0/encase/) for any changes.
`rand` changes are more extensive, with changes such as `thread_rng()`
-> `rng()`, `from_entropy()` -> `from_os_rng()`, and so forth. `RngCore`
is now split into infallible `RngCore` and fallible `TryRngCore`, and
the `distributions` module has been renamed to `distr`. Most of this
affects only internals, and doesn't directly affect Bevy's APIs. For the
full set of changes, see `rand` [migration
notes](https://rust-random.github.io/book/update-0.9.html).
`getrandom` is also updated, and will require additional configuration
when building Bevy for WASM/Web (if also using `rand`). The full details
of how to do this is in the `getrandom` docs
[1](https://github.com/rust-random/getrandom?tab=readme-ov-file#opt-in-backends)
[2](https://github.com/rust-random/getrandom?tab=readme-ov-file#webassembly-support).
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
Rename `JustifyText`:
* The name `JustifyText` is just ugly.
* It's inconsistent since no other `bevy_text` types have a `Text-`
suffix, only prefix.
* It's inconsistent with the other text layout enum `Linebreak` which
doesn't have a prefix or suffix.
Fixes#19521.
## Solution
Rename `JustifyText` to `Justify`.
Without other context, it's natural to assume the name `Justify` refers
to text justification.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Simplify `Camera` initialization
- allow effects to require HDR
## Solution
- Split out `Camera.hdr` into a marker `Hdr` component
## Testing
- ran `bloom_3d` example
---
## Showcase
```rs
// before
commands.spawn((
Camera3d
Camera {
hdr: true
..Default::default()
}
))
// after
commands.spawn((Camera3d, Hdr));
// other rendering components can require that the camera enables hdr!
// currently implemented for Bloom, AutoExposure, and Atmosphere.
#[require(Hdr)]
pub struct Bloom;
```
# Objective
Contributes to #18238
Updates the `render_primitives` example to use the `children!` macro.
## Solution
Updates examples to use the Improved Spawning API merged in
https://github.com/bevyengine/bevy/pull/17521
## Testing
- Did you test these changes? If so, how?
- Opened the examples before and after and verified the same behavior
was observed. I did this on Ubuntu 24.04.2 LTS using `--features
wayland`.
- Are there any parts that need more testing?
- Other OS's and features can't hurt, but this is such a small change it
shouldn't be a problem.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Run the examples yourself with and without these changes.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
- see above
---
## Showcase
n/a
## Migration Guide
n/a
# Objective
Correct spelling
## Solution
Fix typos, specifically ones that I found in folders other than /crates
## Testing
CI
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This reverts commit 0b5302d96a.
# Objective
- Fixes#18158
- #17482 introduced rendering changes and was merged a bit too fast
## Solution
- Revert #17482 so that it can be redone and rendering changes discussed
before being merged. This will make it easier to compare changes with
main in the known "valid" state
This is not an issue with the work done in #17482 that is still
interesting
# Objective
Transparently uses simple `EnvironmentMapLight`s to mimic
`AmbientLight`s. Implements the first part of #17468, but I can
implement hemispherical lights in this PR too if needed.
## Solution
- A function `EnvironmentMapLight::solid_color(&mut Assets<Image>,
Color)` is provided to make an environment light with a solid color.
- A new system is added to `SimulationLightSystems` that maps
`AmbientLight`s on views or the world to a corresponding
`EnvironmentMapLight`.
I have never worked with (or on) Bevy before, so nitpicky comments on
how I did things are appreciated :).
## Testing
Testing was done on a modified version of the `3d/lighting` example,
where I removed all lights except the ambient light. I have not included
the example, but can if required.
## Migration
`bevy_pbr::AmbientLight` has been deprecated, so all usages of it should
be replaced by a `bevy_pbr::EnvironmentMapLight` created with
`EnvironmentMapLight::solid_color` placed on the camera. There is no
alternative to ambient lights as resources.
# Objective
The bounding_2d example was originally placed in 2d_rendering because
there was no folder for bounding or math, but now that this folder exist
it makes no sense for it to be here.
## Solution
Move the example
## Testing
I ran the example
# Objective
It's not immediately obvious that `TargetCamera` only works with UI node
entities. It's natural to assume from looking at something like the
`multiple_windows` example that it will work with everything.
## Solution
Rename `TargetCamera` to `UiTargetCamera`.
## Migration Guide
`TargetCamera` has been renamed to `UiTargetCamera`.
# Objective
Segment2d and Segment3d are currently hard to work with because unlike
many other primary shapes, they are bound to the origin.
The objective of this PR is to allow these segments to exist anywhere in
cartesian space, making them much more useful in a variety of contexts.
## Solution
Reworking the existing segment type's internal fields and methods to
allow them to exist anywhere in cartesian space.
I have done both reworks for 2d and 3d segments but I was unsure if I
should just have it all here or not so feel free to tell me how I should
proceed, for now I have only pushed Segment2d changes.
As I am not a very seasoned contributor, this first implementation is
very likely sloppy and will need some additional work from my end, I am
open to all criticisms and willing to work to get this to bevy's
standards.
## Testing
I am not very familiar with the standards of testing. Of course my
changes had to pass the thorough existing tests for primitive shapes.
I also checked the gizmo 2d shapes intersection example and everything
looked fine.
I did add a few utility methods to the types that have no tests yet. I
am willing to implement some if it is deemed necessary
## Migration Guide
The segment type constructors changed so if someone previously created a
Segment2d with a direction and length they would now need to use the
`from_direction` constructor
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
Fixes https://github.com/bevyengine/bevy/issues/17111
## Solution
Move `#![warn(clippy::allow_attributes,
clippy::allow_attributes_without_reason)]` to the workspace `Cargo.toml`
## Testing
Lots of CI testing, and local testing too.
---------
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
Many instances of `clippy::too_many_arguments` linting happen to be on
systems - functions which we don't call manually, and thus there's not
much reason to worry about the argument count.
## Solution
Allow `clippy::too_many_arguments` globally, and remove all lint
attributes related to it.
# Objective
clean up example get_single method, make code clean;
## Solution
- replace `Query` with `Single` Query
- remove `get_single` or `get_single_mut` condition block
# Objective
Bevy seems to want to standardize on "American English" spellings. Not
sure if this is laid out anywhere in writing, but see also #15947.
While perusing the docs for `typos`, I noticed that it has a `locale`
config option and tried it out.
## Solution
Switch to `en-us` locale in the `typos` config and run `typos -w`
## Migration Guide
The following methods or fields have been renamed from `*dependants*` to
`*dependents*`.
- `ProcessorAssetInfo::dependants`
- `ProcessorAssetInfos::add_dependant`
- `ProcessorAssetInfos::non_existent_dependants`
- `AssetInfo::dependants_waiting_on_load`
- `AssetInfo::dependants_waiting_on_recursive_dep_load`
- `AssetInfos::loader_dependants`
- `AssetInfos::remove_dependants_and_labels`
# Objective
Continue improving the user experience of our UI Node API in the
direction specified by [Bevy's Next Generation Scene / UI
System](https://github.com/bevyengine/bevy/discussions/14437)
## Solution
As specified in the document above, merge `Style` fields into `Node`,
and move "computed Node fields" into `ComputedNode` (I chose this name
over something like `ComputedNodeLayout` because it currently contains
more than just layout info. If we want to break this up / rename these
concepts, lets do that in a separate PR). `Style` has been removed.
This accomplishes a number of goals:
## Ergonomics wins
Specifying both `Node` and `Style` is now no longer required for
non-default styles
Before:
```rust
commands.spawn((
Node::default(),
Style {
width: Val::Px(100.),
..default()
},
));
```
After:
```rust
commands.spawn(Node {
width: Val::Px(100.),
..default()
});
```
## Conceptual clarity
`Style` was never a comprehensive "style sheet". It only defined "core"
style properties that all `Nodes` shared. Any "styled property" that
couldn't fit that mold had to be in a separate component. A "real" style
system would style properties _across_ components (`Node`, `Button`,
etc). We have plans to build a true style system (see the doc linked
above).
By moving the `Style` fields to `Node`, we fully embrace `Node` as the
driving concept and remove the "style system" confusion.
## Next Steps
* Consider identifying and splitting out "style properties that aren't
core to Node". This should not happen for Bevy 0.15.
---
## Migration Guide
Move any fields set on `Style` into `Node` and replace all `Style`
component usage with `Node`.
Before:
```rust
commands.spawn((
Node::default(),
Style {
width: Val::Px(100.),
..default()
},
));
```
After:
```rust
commands.spawn(Node {
width: Val::Px(100.),
..default()
});
```
For any usage of the "computed node properties" that used to live on
`Node`, use `ComputedNode` instead:
Before:
```rust
fn system(nodes: Query<&Node>) {
for node in &nodes {
let computed_size = node.size();
}
}
```
After:
```rust
fn system(computed_nodes: Query<&ComputedNode>) {
for computed_node in &computed_nodes {
let computed_size = computed_node.size();
}
}
```
# Objective
Fixes#15791.
As raised in #11022, scaling orthographic cameras is confusing! In Bevy
0.14, there were multiple completely redundant ways to do this, and no
clear guidance on which to use.
As a result, #15075 removed the `scale` field from
`OrthographicProjection` completely, solving the redundancy issue.
However, this resulted in an unintuitive API and a painful migration, as
discussed in #15791. Users simply want to change a single parameter to
zoom, rather than deal with the irrelevant details of how the camera is
being scaled.
## Solution
This PR reverts #15075, and takes an alternate, more nuanced approach to
the redundancy problem. `ScalingMode::WindowSize` was by far the biggest
offender. This was the default variant, and stored a float that was
*fully* redundant to setting `scale`.
All of the other variants contained meaningful semantic information and
had an intuitive scale. I could have made these unitless, storing an
aspect ratio, but this would have been a worse API and resulted in a
pointlessly painful migration.
In the course of this work I've also:
- improved the documentation to explain that you should just set `scale`
to zoom cameras
- swapped to named fields for all of the variants in `ScalingMode` for
more clarity about the parameter meanings
- substantially improved the `projection_zoom` example
- removed the footgunny `Mul` and `Div` impls for `ScalingMode`,
especially since these no longer have the intended effect on
`ScalingMode::WindowSize`.
- removed a rounding step because this is now redundant 🎉
## Testing
I've tested these changes as part of my work in the `projection_zoom`
example, and things seem to work fine.
## Migration Guide
`ScalingMode` has been refactored for clarity, especially on how to zoom
orthographic cameras and their projections:
- `ScalingMode::WindowSize` no longer stores a float, and acts as if its
value was 1. Divide your camera's scale by any previous value to achieve
identical results.
- `ScalingMode::FixedVertical` and `FixedHorizontal` now use named
fields.
---------
Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
Fixes#15834
## Migration Guide
The APIs of `Time`, `Timer` and `Stopwatch` have been cleaned up for
consistency with each other and the standard library's `Duration` type.
The following methods have been renamed:
- `Stowatch::paused` -> `Stopwatch::is_paused`
- `Time::elapsed_seconds` -> `Time::elasped_secs` (including `_f64` and
`_wrapped` variants)
# Objective
Cleanup naming and docs, add missing migration guide after #15591
All text root nodes now use `Text` (UI) / `Text2d`.
All text readers/writers use `Text<Type>Reader`/`Text<Type>Writer`
convention.
---
## Migration Guide
Doubles as #15591 migration guide.
Text bundles (`TextBundle` and `Text2dBundle`) were removed in favor of
`Text` and `Text2d`.
Shared configuration fields were replaced with `TextLayout`, `TextFont`
and `TextColor` components.
Just `TextBundle`'s additional field turned into `TextNodeFlags`
component,
while `Text2dBundle`'s additional fields turned into `TextBounds` and
`Anchor` components.
Text sections were removed in favor of hierarchy-based approach.
For root text entities with `Text` or `Text2d` components, child
entities with `TextSpan` will act as additional text sections.
To still access text spans by index, use the new `TextUiReader`,
`Text2dReader` and `TextUiWriter`, `Text2dWriter` system parameters.
# Objective
- closes#15866
## Solution
- Simply migrate where possible.
## Testing
- Expect that CI will do most of the work. Examples is another way of
testing this, as most of the work is in that area.
---
## Notes
For now, this PR doesn't migrate `QueryState::single` and friends as for
now, this look like another issue. So for example, QueryBuilders that
used single or `World::query` that used single wasn't migrated. If there
is a easy way to migrate those, please let me know.
Most of the uses of `Query::single` were removed, the only other uses
that I found was related to tests of said methods, so will probably be
removed when we remove `Query::single`.
# Objective
Currently text is recomputed unnecessarily on any changes to its color,
which is extremely expensive.
## Solution
Split up `TextStyle` into two separate components `TextFont` and
`TextColor`.
## Testing
I added this system to `many_buttons`:
```rust
fn set_text_colors_changed(mut colors: Query<&mut TextColor>) {
for mut text_color in colors.iter_mut() {
text_color.set_changed();
}
}
```
reports ~4fps on main, ~50fps with this PR.
## Migration Guide
`TextStyle` has been renamed to `TextFont` and its `color` field has
been moved to a separate component named `TextColor` which newtypes
`Color`.
**Ready for review. Examples migration progress: 100%.**
# Objective
- Implement https://github.com/bevyengine/bevy/discussions/15014
## Solution
This implements [cart's
proposal](https://github.com/bevyengine/bevy/discussions/15014#discussioncomment-10574459)
faithfully except for one change. I separated `TextSpan` from
`TextSpan2d` because `TextSpan` needs to require the `GhostNode`
component, which is a `bevy_ui` component only usable by UI.
Extra changes:
- Added `EntityCommands::commands_mut` that returns a mutable reference.
This is a blocker for extension methods that return something other than
`self`. Note that `sickle_ui`'s `UiBuilder::commands` returns a mutable
reference for this reason.
## Testing
- [x] Text examples all work.
---
## Showcase
TODO: showcase-worthy
## Migration Guide
TODO: very breaking
### Accessing text spans by index
Text sections are now text sections on different entities in a
hierarchy, Use the new `TextReader` and `TextWriter` system parameters
to access spans by index.
Before:
```rust
fn refresh_text(mut query: Query<&mut Text, With<TimeText>>, time: Res<Time>) {
let text = query.single_mut();
text.sections[1].value = format_time(time.elapsed());
}
```
After:
```rust
fn refresh_text(
query: Query<Entity, With<TimeText>>,
mut writer: UiTextWriter,
time: Res<Time>
) {
let entity = query.single();
*writer.text(entity, 1) = format_time(time.elapsed());
}
```
### Iterating text spans
Text spans are now entities in a hierarchy, so the new `UiTextReader`
and `UiTextWriter` system parameters provide ways to iterate that
hierarchy. The `UiTextReader::iter` method will give you a normal
iterator over spans, and `UiTextWriter::for_each` lets you visit each of
the spans.
---------
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Several of our APIs (namely gizmos and bounding) use isometries on
current Bevy main. This is nicer than separate properties in a lot of
cases, but users have still expressed usability concerns.
One problem is that in a lot of cases, you only care about e.g.
translation, so you end up with this:
```rust
gizmos.cross_2d(
Isometry2d::from_translation(Vec2::new(-160.0, 120.0)),
12.0,
FUCHSIA,
);
```
The isometry adds quite a lot of length and verbosity, and isn't really
that relevant since only the translation is important here.
It would be nice if you could use the translation directly, and only
supply an isometry if both translation and rotation are needed. This
would make the following possible:
```rust
gizmos.cross_2d(Vec2::new(-160.0, 120.0), 12.0, FUCHSIA);
```
removing a lot of verbosity.
## Solution
Implement `From<Vec2>` and `From<Rot2>` for `Isometry2d`, and
`From<Vec3>`, `From<Vec3A>`, and `From<Quat>` for `Isometry3d`. These
are lossless conversions that fit the semantics of `From`.
This makes the proposed API possible! The methods must now simply take
an `impl Into<IsometryNd>`, and this works:
```rust
gizmos.cross_2d(Vec2::new(-160.0, 120.0), 12.0, FUCHSIA);
```
# Objective
Yet another PR for migrating stuff to required components. This time,
cameras!
## Solution
As per the [selected
proposal](https://hackmd.io/tsYID4CGRiWxzsgawzxG_g#Combined-Proposal-1-Selected),
deprecate `Camera2dBundle` and `Camera3dBundle` in favor of `Camera2d`
and `Camera3d`.
Adding a `Camera` without `Camera2d` or `Camera3d` now logs a warning,
as suggested by Cart [on
Discord](https://discord.com/channels/691052431525675048/1264881140007702558/1291506402832945273).
I would personally like cameras to work a bit differently and be split
into a few more components, to avoid some footguns and confusing
semantics, but that is more controversial, and shouldn't block this core
migration.
## Testing
I ran a few 2D and 3D examples, and tried cameras with and without
render graphs.
---
## Migration Guide
`Camera2dBundle` and `Camera3dBundle` have been deprecated in favor of
`Camera2d` and `Camera3d`. Inserting them will now also insert the other
components required by them automatically.
# Objective
A big step in the migration to required components: meshes and
materials!
## Solution
As per the [selected
proposal](https://hackmd.io/@bevy/required_components/%2Fj9-PnF-2QKK0on1KQ29UWQ):
- Deprecate `MaterialMesh2dBundle`, `MaterialMeshBundle`, and
`PbrBundle`.
- Add `Mesh2d` and `Mesh3d` components, which wrap a `Handle<Mesh>`.
- Add `MeshMaterial2d<M: Material2d>` and `MeshMaterial3d<M: Material>`,
which wrap a `Handle<M>`.
- Meshes *without* a mesh material should be rendered with a default
material. The existence of a material is determined by
`HasMaterial2d`/`HasMaterial3d`, which is required by
`MeshMaterial2d`/`MeshMaterial3d`. This gets around problems with the
generics.
Previously:
```rust
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Circle::new(100.0)).into(),
material: materials.add(Color::srgb(7.5, 0.0, 7.5)),
transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
..default()
});
```
Now:
```rust
commands.spawn((
Mesh2d(meshes.add(Circle::new(100.0))),
MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
Transform::from_translation(Vec3::new(-200., 0., 0.)),
));
```
If the mesh material is missing, previously nothing was rendered. Now,
it renders a white default `ColorMaterial` in 2D and a
`StandardMaterial` in 3D (this can be overridden). Below, only every
other entity has a material:


Why white? This is still open for discussion, but I think white makes
sense for a *default* material, while *invalid* asset handles pointing
to nothing should have something like a pink material to indicate that
something is broken (I don't handle that in this PR yet). This is kind
of a mix of Godot and Unity: Godot just renders a white material for
non-existent materials, while Unity renders nothing when no materials
exist, but renders pink for invalid materials. I can also change the
default material to pink if that is preferable though.
## Testing
I ran some 2D and 3D examples to test if anything changed visually. I
have not tested all examples or features yet however. If anyone wants to
test more extensively, it would be appreciated!
## Implementation Notes
- The relationship between `bevy_render` and `bevy_pbr` is weird here.
`bevy_render` needs `Mesh3d` for its own systems, but `bevy_pbr` has all
of the material logic, and `bevy_render` doesn't depend on it. I feel
like the two crates should be refactored in some way, but I think that's
out of scope for this PR.
- I didn't migrate meshlets to required components yet. That can
probably be done in a follow-up, as this is already a huge PR.
- It is becoming increasingly clear to me that we really, *really* want
to disallow raw asset handles as components. They caused me a *ton* of
headache here already, and it took me a long time to find every place
that queried for them or inserted them directly on entities, since there
were no compiler errors for it. If we don't remove the `Component`
derive, I expect raw asset handles to be a *huge* footgun for users as
we transition to wrapper components, especially as handles as components
have been the norm so far. I personally consider this to be a blocker
for 0.15: we need to migrate to wrapper components for asset handles
everywhere, and remove the `Component` derive. Also see
https://github.com/bevyengine/bevy/issues/14124.
---
## Migration Guide
Asset handles for meshes and mesh materials must now be wrapped in the
`Mesh2d` and `MeshMaterial2d` or `Mesh3d` and `MeshMaterial3d`
components for 2D and 3D respectively. Raw handles as components no
longer render meshes.
Additionally, `MaterialMesh2dBundle`, `MaterialMeshBundle`, and
`PbrBundle` have been deprecated. Instead, use the mesh and material
components directly.
Previously:
```rust
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Circle::new(100.0)).into(),
material: materials.add(Color::srgb(7.5, 0.0, 7.5)),
transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
..default()
});
```
Now:
```rust
commands.spawn((
Mesh2d(meshes.add(Circle::new(100.0))),
MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
Transform::from_translation(Vec3::new(-200., 0., 0.)),
));
```
If the mesh material is missing, a white default material is now used.
Previously, nothing was rendered if the material was missing.
The `WithMesh2d` and `WithMesh3d` query filter type aliases have also
been removed. Simply use `With<Mesh2d>` or `With<Mesh3d>`.
---------
Co-authored-by: Tim Blackbird <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Another step in the migration to required components: lights!
Note that this does not include `EnvironmentMapLight` or reflection
probes yet, because their API hasn't been fully chosen yet.
## Solution
As per the [selected
proposals](https://hackmd.io/@bevy/required_components/%2FLLnzwz9XTxiD7i2jiUXkJg):
- Deprecate `PointLightBundle` in favor of the `PointLight` component
- Deprecate `SpotLightBundle` in favor of the `PointLight` component
- Deprecate `DirectionalLightBundle` in favor of the `DirectionalLight`
component
## Testing
I ran some examples with lights.
---
## Migration Guide
`PointLightBundle`, `SpotLightBundle`, and `DirectionalLightBundle` have
been deprecated. Use the `PointLight`, `SpotLight`, and
`DirectionalLight` components instead. Adding them will now insert the
other components required by them automatically.
# Objective
- Fixes#15236
## Solution
- Use bevy_math::ops instead of std floating point operations.
## Testing
- Did you test these changes? If so, how?
Unit tests and `cargo run -p ci -- test`
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Execute `cargo run -p ci -- test` on Windows.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Windows
## Migration Guide
- Not a breaking change
- Projects should use bevy math where applicable
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
The names of numerous rendering components in Bevy are inconsistent and
a bit confusing. Relevant names include:
- `AutoExposureSettings`
- `AutoExposureSettingsUniform`
- `BloomSettings`
- `BloomUniform` (no `Settings`)
- `BloomPrefilterSettings`
- `ChromaticAberration` (no `Settings`)
- `ContrastAdaptiveSharpeningSettings`
- `DepthOfFieldSettings`
- `DepthOfFieldUniform` (no `Settings`)
- `FogSettings`
- `SmaaSettings`, `Fxaa`, `TemporalAntiAliasSettings` (really
inconsistent??)
- `ScreenSpaceAmbientOcclusionSettings`
- `ScreenSpaceReflectionsSettings`
- `VolumetricFogSettings`
Firstly, there's a lot of inconsistency between `Foo`/`FooSettings` and
`FooUniform`/`FooSettingsUniform` and whether names are abbreviated or
not.
Secondly, the `Settings` post-fix seems unnecessary and a bit confusing
semantically, since it makes it seem like the component is mostly just
auxiliary configuration instead of the core *thing* that actually
enables the feature. This will be an even bigger problem once bundles
like `TemporalAntiAliasBundle` are deprecated in favor of required
components, as users will expect a component named `TemporalAntiAlias`
(or similar), not `TemporalAntiAliasSettings`.
## Solution
Drop the `Settings` post-fix from the component names, and change some
names to be more consistent.
- `AutoExposure`
- `AutoExposureUniform`
- `Bloom`
- `BloomUniform`
- `BloomPrefilter`
- `ChromaticAberration`
- `ContrastAdaptiveSharpening`
- `DepthOfField`
- `DepthOfFieldUniform`
- `DistanceFog`
- `Smaa`, `Fxaa`, `TemporalAntiAliasing` (note: we might want to change
to `Taa`, see "Discussion")
- `ScreenSpaceAmbientOcclusion`
- `ScreenSpaceReflections`
- `VolumetricFog`
I kept the old names as deprecated type aliases to make migration a bit
less painful for users. We should remove them after the next release.
(And let me know if I should just... not add them at all)
I also added some very basic docs for a few types where they were
missing, like on `Fxaa` and `DepthOfField`.
## Discussion
- `TemporalAntiAliasing` is still inconsistent with `Smaa` and `Fxaa`.
Consensus [on
Discord](https://discord.com/channels/691052431525675048/743663924229963868/1280601167209955431)
seemed to be that renaming to `Taa` would probably be fine, but I think
it's a bit more controversial, and it would've required renaming a lot
of related types like `TemporalAntiAliasNode`,
`TemporalAntiAliasBundle`, and `TemporalAntiAliasPlugin`, so I think
it's better to leave to a follow-up.
- I think `Fog` should probably have a more specific name like
`DistanceFog` considering it seems to be distinct from `VolumetricFog`.
~~This should probably be done in a follow-up though, so I just removed
the `Settings` post-fix for now.~~ (done)
---
## Migration Guide
Many rendering components have been renamed for improved consistency and
clarity.
- `AutoExposureSettings` → `AutoExposure`
- `BloomSettings` → `Bloom`
- `BloomPrefilterSettings` → `BloomPrefilter`
- `ContrastAdaptiveSharpeningSettings` → `ContrastAdaptiveSharpening`
- `DepthOfFieldSettings` → `DepthOfField`
- `FogSettings` → `DistanceFog`
- `SmaaSettings` → `Smaa`
- `TemporalAntiAliasSettings` → `TemporalAntiAliasing`
- `ScreenSpaceAmbientOcclusionSettings` → `ScreenSpaceAmbientOcclusion`
- `ScreenSpaceReflectionsSettings` → `ScreenSpaceReflections`
- `VolumetricFogSettings` → `VolumetricFog`
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Hello! I am adopting #11022 to resolve conflicts with `main`. tldr: this
removes `scale` in favour of `scaling_mode`. Please see the original PR
for explanation/discussion.
Also relates to #2580.
## Migration Guide
Replace all uses of `scale` with `scaling_mode`, keeping in mind that
`scale` is (was) a multiplier. For example, replace
```rust
scale: 2.0,
scaling_mode: ScalingMode::FixedHorizontal(4.0),
```
with
```rust
scaling_mode: ScalingMode::FixedHorizontal(8.0),
```
---------
Co-authored-by: Stepan Koltsov <stepan.koltsov@gmail.com>