# Objective
The documentation for observers is not very good. This poses a problem
to users, but *also* causes serious problems for engine devs, as they
attempt to improve assorted issues surrounding observers.
This PR:
- Fixes#14084.
- Fixes#14726.
- Fixes#16538.
- Closes#18914, by attempting to solve the same issue.
To keep this PR at all reviewable, I've opted to simply note the various
limitations (some may call them bugs!) in place, rather than attempting
to fix them. There is a huge amount of cleanup work to be done here: see
https://github.com/orgs/bevyengine/projects/17.
## Solution
- Write good module docs for observers, offering bread crumbs to the
most common methods and techniques and comparing-and-contrasting as
needed.
- Fix any actively misleading documentation.
- Try to explain how the various bits of the (public?!) internals are
related.
---------
Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
#19366 implemented core button widgets, which included the `Depressed`
state component.
`Depressed` was chosen instead of `Pressed` to avoid conflict with the
`Pointer<Pressed>` event, but it is problematic and awkward in many
ways:
- Using the word "depressed" for such a high-traffic type is not great
due to the obvious connection to "depressed" as in depression.
- "Depressed" is not what I would search for if I was looking for a
component like this, and I'm not aware of any other engine or UI
framework using the term.
- `Depressed` is not a very natural pair to the `Pointer<Pressed>`
event.
- It might be because I'm not a native English speaker, but I have very
rarely heard someone say "a button is depressed". Seeing it, my mind
initially goes from "depression??" to "oh, de-pressed, meaning released"
and definitely not "is pressed", even though that *is* also a valid
meaning for it.
A related problem is that the current `Pointer<Pressed>` and
`Pointer<Released>` event names use a different verb tense than all of
our other observer events such as `Pointer<Click>` or
`Pointer<DragStart>`. By fixing this and renaming `Pressed` (and
`Released`), we can then use `Pressed` instead of `Depressed` for the
state component.
Additionally, the `IsHovered` and `IsDirectlyHovered` components added
in #19366 use an inconsistent naming; the other similar components don't
use an `Is` prefix. It also makes query filters like `Has<IsHovered>`
and `With<IsHovered>` a bit more awkward.
This is partially related to Cart's [picking concept
proposal](https://gist.github.com/cart/756e48a149db2838028be600defbd24a?permalink_comment_id=5598154).
## Solution
- Rename `Pointer<Pressed>` to `Pointer<Press>`
- Rename `Pointer<Released>` to `Pointer<Release>`
- Rename `Depressed` to `Pressed`
- Rename `IsHovered` to `Hovered`
- Rename `IsDirectlyHovered` to `DirectlyHovered`
# Objective
Part of #19236
## Solution
Adds a new `bevy_core_widgets` crate containing headless widget
implementations. This PR adds a single `CoreButton` widget, more widgets
to be added later once this is approved.
## Testing
There's an example, ui/core_widgets.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fixes#17183
## Solution
- Copied the stress settings from the `many_animated_sprite` example
that were mentioned in the ticket
## Testing
- Run the example
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
As discussed in #19285, some of our names conflict. `Entry` in bevy_ecs
is one of those overly general names.
## Solution
Rename this type (and the related types) to `ComponentEntry`.
---------
Co-authored-by: urben1680 <55257931+urben1680@users.noreply.github.com>
# Objective
I set out with one simple goal: clearly document the differences between
each of the component lifecycle events via module docs.
Unfortunately, no such module existed: the various lifecycle code was
scattered to the wind.
Without a unified module, it's very hard to discover the related types,
and there's nowhere good to put my shiny new documentation.
## Solution
1. Unify the assorted types into a single
`bevy_ecs::component_lifecycle` module.
2. Write docs.
3. Write a migration guide.
## Testing
Thanks CI!
## Follow-up
1. The lifecycle event names are pretty confusing, especially
`OnReplace`. We should consider renaming those. No bikeshedding in my PR
though!
2. Observers need real module docs too :(
3. Any additional functional changes should be done elsewhere; this is a
simple docs and re-org PR.
---------
Co-authored-by: theotherphil <phil.j.ellison@gmail.com>
## Objective
Fixes#19051.
---
## Solution
Originally implemented `compiler_error!()` within bevy_tasks/src/lib.rs
file to provide descriptive message regarding missing feature. However,
a cleaner approach was to add `async_executor` to the array of features
enabled by `multi_threaded` instead. This removes the need for users to
manually add `features = ["multi_threaded", "async_executor"]`
separately as needed to be done previously.
---
## Testing
These changes were tested using a minimal, external project designed to
specifically test whether the standalone `multi_threaded` feature for
`bevy_tasks` with `default-features` disabled worked as intended without
running into any compile-time error.
### How it was tested:
1. A `bevy_tasks_test` binary project was set up in an external
directory.
2. Its `Cargo.toml` was configured to depend on the local `bevy_tasks`,
explicitly disabling default features and enabling only
`multi_threaded`.
3. A simple `bevy_tasks_test/bin/bevy_crates_test.rs` was created and
configured within `Cargo.toml` file where bevy_tasks was set to the
local version of the crate with the modified changes and `cargo add
bevy_platform` was executed through the terminal since that dependency
is also needed to execute the sample examples.
4. Then both the `examples/busy_behavior.rs` and
`examples/idle_behavior.rs` code was added and tested with just the
`multi_threaded` feature was enabled and the code executed successfully.
### Results:
The code executed successfully for both examples where a threadPool was
utilized with 4 tasks and spawning 40 tasks that spin for 100ms.
Demonstrating how the threads finished executing all the tasks
simultaneously after a brief delay of less than a second (this is
referencing `bevy_tasks/examples/busy_behavior.rs`). Alongside the
second example where one thread per logical core was was utilized for a
single spinning task and aside from utilizing the single thread, system
was intended to remain idle as part of good practice when it comes to
handling small workloads. (this is referencing
`bevy_tasks/examples/idle_behavior.rs`).
### How to test:
Reviewers can easily verify this by:
1. Checking out this PR.
2. Creating `cargo new bevy_tasks_test` and the `Cargo.toml` should look
something like this:
```toml
# bevy/tests/compile_fail_tasks/Cargo.toml
[package]
name = "bevy_tasks_test"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
# path to bevy_tasks sub-crate to test locally
bevy_tasks = { path = "../../bevy_tasks", default-features = false,
features = ["multi_threaded"] }
bevy_platform = "0.16.1"
```
3. Copying the examples within bevy_creates/examples one by one and
testing them separately within `src/main.rs` to check whether the
examples work.
4. Then simply running `cargo run` within the terminal should suffice to
test if the single `multi_threaded` feature works without the need for
separately adding `async_executor` as `multi_threaded` already uses
`async_executor` internally.
### Platforms tested:
macOS (aarch64). As a `#[cfg]` based compile-time check, behavior should
be consistent across platforms.
# Objective
Fixes#19403
As described in the issue, the objective is to support the use of
systems returning `Result<(), BevyError>` and
`Result<bool, BevyError>` as run conditions. In these cases, the run
condition would hold on `Ok(())` and `Ok(true)` respectively.
## Solution
`IntoSystem<In, bool, M>` cannot be implemented for systems returning
`Result<(), BevyError>` and `Result<bool, BevyError>` as that would
conflict with their trivial implementation of the trait. That led me to
add a method to the sealed trait `SystemCondition` that does the
conversion. In the original case of a system returning `bool`, the
system is returned as is. With the new types, the system is combined
with `map()` to obtain a `bool`.
By the way, I'm confused as to why `SystemCondition` has a generic `In`
parameter as it is only ever used with `In = ()` as far as I can tell.
## Testing
I added a simple test for both type of system. That's minimal but it
felt enough. I could not picture the more complicated tests passing for
a run condition returning `bool` and failing for the new types.
## Doc
I documenting the change on the page of the trait. I had trouble wording
it right but I'm not sure how to improve it. The phrasing "the condition
returns `true`" which reads naturally is now technically incorrect as
the new types return a `Result`. However, the underlying condition
system that the implementing system turns into does indeed return
`bool`. But talking about the implementation details felt too much.
Another possibility is to use another turn of phrase like "the condition
holds" or "the condition checks out". I've left "the condition returns
`true`" in the documentation of `run_if` and the provided methods for
now.
I'm perplexed about the examples. In the first one, why not implement
the condition directly instead of having a system returning it? Is it
from a time of Bevy where you had to implement your conditions that way?
In that case maybe that should be updated. And in the second example I'm
missing the point entirely. As I stated above, I've only seen conditions
used in contexts where they have no input parameter. Here we create a
condition with an input parameter (cannot be used by `run_if`) and we
are using it with `pipe()` which actually doesn't need our system to
implement `SystemCondition`. Both examples are also calling
`IntoSystem::into_system` which should not be encouraged. What am I
missing?
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.32.0 to
1.33.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
releases</a>.</em></p>
<blockquote>
<h2>v1.33.1</h2>
<h2>[1.33.1] - 2025-06-02</h2>
<h3>Fixes</h3>
<ul>
<li><em>(dict)</em> Don't correct <code>wasn't</code> to
<code>wasm't</code></li>
</ul>
<h2>v1.33.0</h2>
<h2>[1.33.0] - 2025-06-02</h2>
<h3>Features</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1290">May
2025</a> changes</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
changelog</a>.</em></p>
<blockquote>
<h2>[1.33.1] - 2025-06-02</h2>
<h3>Fixes</h3>
<ul>
<li><em>(dict)</em> Don't correct <code>wasn't</code> to
<code>wasm't</code></li>
</ul>
<h2>[1.33.0] - 2025-06-02</h2>
<h3>Features</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1290">May
2025</a> changes</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b1ae8d918b"><code>b1ae8d9</code></a>
chore: Release</li>
<li><a
href="6c5d17de8e"><code>6c5d17d</code></a>
docs: Update changelog</li>
<li><a
href="0a237ba81a"><code>0a237ba</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1311">#1311</a>
from epage/wasn</li>
<li><a
href="79920cf069"><code>79920cf</code></a>
fix(dict): Don't correct <code>wasn't</code></li>
<li><a
href="e99b2b47d9"><code>e99b2b4</code></a>
chore: Release</li>
<li><a
href="2afc152754"><code>2afc152</code></a>
chore: Release</li>
<li><a
href="544a19b4ae"><code>544a19b</code></a>
docs: Update changelog</li>
<li><a
href="2e0ca28a95"><code>2e0ca28</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1310">#1310</a>
from epage/may</li>
<li><a
href="94eb4e7b40"><code>94eb4e7</code></a>
feat(dict): May 2025 updates</li>
<li><a
href="a4cce4ca70"><code>a4cce4c</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1308">#1308</a>
from crate-ci/renovate/schemars-0.x</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-ci/typos/compare/v1.32.0...v1.33.1">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
- Cleanup related to #19495.
## Solution
- Delete `System::component_access()`. It is redundant with
`System::component_access_set().combined_access()`.
## Testing
- None. There are no callers of this function.
# Objective
In the past I had custom data structures containing `Tick`s. I learned
that these need to be regularly checked to clamp them. But there was no
way to hook into that logic so I abandoned storing ticks since then.
Another motivation to open this up some more is to be more able to do a
correct implementation of `System::check_ticks`.
## Solution
Add `CheckChangeTicks` and trigger it in `World::check_change_ticks`.
Make `Tick::check_tick` public.
This event makes it possible to store ticks in components or resources
and have them checked.
I also made `Schedules::check_change_ticks` public so users can store
schedules in custom resources/components for whatever reasons.
## Testing
The logic boils down to a single `World::trigger` call and I don't think
this needs more tests.
## Alternatives
Making this obsolete like with #15683.
---
## Showcase
From the added docs:
```rs
use bevy_ecs::prelude::*;
use bevy_ecs::component::CheckChangeTicks;
#[derive(Resource)]
struct CustomSchedule(Schedule);
let mut world = World::new();
world.add_observer(|tick: Trigger<CheckChangeTicks>, mut schedule: ResMut<CustomSchedule>| {
schedule.0.check_change_ticks(tick.get());
});
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#19136
## Solution
- Add a new container attribute which when set does not emit
`BundleFromComponents`
## Testing
- Did you test these changes?
Yes, a new test was added.
- Are there any parts that need more testing?
Since `BundleFromComponents` is unsafe I made extra sure that I did not
misunderstand its purpose. As far as I can tell, _not_ implementing it
is ok.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Nope
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
I don't think the platform is relevant
---
One thing I am not sure about is how to document this? I'll gladly add
it
---------
Signed-off-by: Marcel Müller <neikos@neikos.email>
# Objective
`SystemSet`s are surprisingly rich and nuanced, but are extremely poorly
documented.
Fixes#19536.
## Solution
Explain the basic concept of system sets, how to create them, and give
some opinionated advice about their more advanced functionality.
## Follow-up
I'd like proper module level docs on system ordering that I can link to
here, but they don't exist. Punting to follow-up!
---------
Co-authored-by: theotherphil <phil.j.ellison@gmail.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
- Fixes#4381
## Solution
- Replace `component_access` with `component_access_set` when
determining conflicting systems during schedule building.
- All `component_access()` impls just forward to
`&component_access_set().combined_access`, so we are essentially trading
`Access::is_compatible` for `FilteredAccessSet::is_compatible`.
- `FilteredAccessSet::get_conflicts` internally calls
`combined_access.is_compatible` as the first step, so we can remove that
redundant check.
## Testing
- Un-ignored a previously failing test now that it passes!
- Ran the `build_schedule` benchmark and got basically no change in the
results. Perhaps are benchmarks are just not targetted towards this
situation.
```
$ critcmp main fix-ambiguity -f 'build_schedule'
group fix-ambiguity main
----- ------------- ----
build_schedule/1000_schedule 1.00 2.9±0.02s ? ?/sec 1.01 2.9±0.05s ? ?/sec
build_schedule/1000_schedule_no_constraints 1.02 48.3±1.48ms ? ?/sec 1.00 47.4±1.78ms ? ?/sec
build_schedule/100_schedule 1.00 9.9±0.17ms ? ?/sec 1.06 10.5±0.32ms ? ?/sec
build_schedule/100_schedule_no_constraints 1.00 804.7±21.85µs ? ?/sec 1.03 828.7±19.36µs ? ?/sec
build_schedule/500_schedule 1.00 451.7±7.25ms ? ?/sec 1.04 468.9±11.70ms ? ?/sec
build_schedule/500_schedule_no_constraints 1.02 12.7±0.46ms ? ?/sec 1.00 12.5±0.44ms ? ?/sec
```
# Objective
`Entity::PLACEHOLDER` acts as a magic number that will *probably* never
really exist, but it certainly could. And, `Entity` has a niche, so the
only reason to use `PLACEHOLDER` is as an alternative to `MaybeUninit`
that trades safety risks for logic risks.
As a result, bevy has generally advised against using `PLACEHOLDER`, but
we still use if for a lot internally. This pr starts removing internal
uses of it, starting from observers.
## Solution
Change all trigger target related types from `Entity` to
`Option<Entity>`
Small migration guide to come.
## Testing
CI
## Future Work
This turned a lot of code from
```rust
trigger.target()
```
to
```rust
trigger.target().unwrap()
```
The extra panic is no worse than before; it's just earlier than
panicking after passing the placeholder to something else.
But this is kinda annoying.
I would like to add a `TriggerMode` or something to `Event` that would
restrict what kinds of targets can be used for that event. Many events
like `Removed` etc, are always triggered with a target. We can make
those have a way to assume Some, etc. But I wanted to save that for a
future pr.
# Objective
At the moment, if someone wants to despawn all the children of an
entity, they would need to use `despawn_related::<Children>();`.
In my opinion, this makes a very common operation less easily
discoverable and require some understanding of Entity Relationships.
## Solution
Adding a `despawn_children ` makes a very simple, discoverable and
readable way to despawn all the children while maintaining cohesion with
other similar methods.
## Testing
The implementation itself is very simple as it simply wraps around
`despawn_related` with `Children` as the generic type.
I gave it a quick try by modifying the parenting example and it worked
as expected.
---------
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
# Objective
- Fix https://github.com/bevyengine/bevy/issues/13843
- Clarify the difference between Mut and &mut when accessing query data
## Solution
- Mention `Mut` in `QueryData` docs as an example of a type that
implements this trait
- Give example of `iter_mut` vs `iter` access to `Mut` and `& mut`
parameters
## Testing
-
# Objective
Make the restrictions of `transmute_lens` and related functions clearer.
Related issue: https://github.com/bevyengine/bevy/issues/12156
Related PR: https://github.com/bevyengine/bevy/pull/12157
## Solution
* Make it clearer that the set of returned entities is a subset of those
from the original query
* Move description of read/write/required access to a table
* Reference the new table in `transmute_lens` docs from the other
`transmute_lens*` functions
## Testing
cargo doc --open locally to check this render correctly
---------
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
Add specialized UI transform `Component`s and fix some related problems:
* Animating UI elements by modifying the `Transform` component of UI
nodes doesn't work very well because `ui_layout_system` overwrites the
translations each frame. The `overflow_debug` example uses a horrible
hack where it copies the transform into the position that'll likely
cause a panic if any users naively copy it.
* Picking ignores rotation and scaling and assumes UI nodes are always
axis aligned.
* The clipping geometry stored in `CalculatedClip` is wrong for rotated
and scaled elements.
* Transform propagation is unnecessary for the UI, the transforms can be
updated during layout updates.
* The UI internals use both object-centered and top-left-corner-based
coordinates systems for UI nodes. Depending on the context you have to
add or subtract the half-size sometimes before transforming between
coordinate spaces. We should just use one system consistantly so that
the transform can always be directly applied.
* `Transform` doesn't support responsive coordinates.
## Solution
* Unrequire `Transform` from `Node`.
* New components `UiTransform`, `UiGlobalTransform`:
- `Node` requires `UiTransform`, `UiTransform` requires
`UiGlobalTransform`
- `UiTransform` is a 2d-only equivalent of `Transform` with a
translation in `Val`s.
- `UiGlobalTransform` newtypes `Affine2` and is updated in
`ui_layout_system`.
* New helper functions on `ComputedNode` for mapping between viewport
and local node space.
* The cursor position is transformed to local node space during picking
so that it respects rotations and scalings.
* To check if the cursor hovers a node recursively walk up the tree to
the root checking if any of the ancestor nodes clip the point at the
cursor. If the point is clipped the interaction is ignored.
* Use object-centered coordinates for UI nodes.
* `RelativeCursorPosition`'s coordinates are now object-centered with
(0,0) at the the center of the node and the corners at (±0.5, ±0.5).
* Replaced the `normalized_visible_node_rect: Rect` field of
`RelativeCursorPosition` with `cursor_over: bool`, which is set to true
when the cursor is over an unclipped point on the node. The visible area
of the node is not necessarily a rectangle, so the previous
implementation didn't work.
This should fix all the logical bugs with non-axis aligned interactions
and clipping. Rendering still needs changes but they are far outside the
scope of this PR.
Tried and abandoned two other approaches:
* New `transform` field on `Node`, require `GlobalTransform` on `Node`,
and unrequire `Transform` on `Node`. Unrequiring `Transform` opts out of
transform propagation so there is then no conflict with updating the
`GlobalTransform` in `ui_layout_system`. This was a nice change in its
simplicity but potentially confusing for users I think, all the
`GlobalTransform` docs mention `Transform` and having special rules for
how it's updated just for the UI is unpleasently surprising.
* New `transform` field on `Node`. Unrequire `Transform` on `Node`. New
`transform: Affine2` field on `ComputedNode`.
This was okay but I think most users want a separate specialized UI
transform components. The fat `ComputedNode` doesn't work well with
change detection.
Fixes#18929, #18930
## Testing
There is an example you can look at:
```
cargo run --example ui_transform
```
Sometimes in the example if you press the rotate button couple of times
the first glyph from the top label disappears , I'm not sure what's
causing it yet but I don't think it's related to this PR.
## Migration Guide
New specialized 2D UI transform components `UiTransform` and
`UiGlobalTransform`. `UiTransform` is a 2d-only equivalent of
`Transform` with a translation in `Val`s. `UiGlobalTransform` newtypes
`Affine2` and is updated in `ui_layout_system`.
`Node` now requires `UiTransform` instead of `Transform`. `UiTransform`
requires `UiGlobalTransform`.
In previous versions of Bevy `ui_layout_system` would overwrite UI
node's `Transform::translation` each frame. `UiTransform`s aren't
overwritten and there is no longer any need for systems that cache and
rewrite the transform for translated UI elements.
`RelativeCursorPosition`'s coordinates are now object-centered with
(0,0) at the the center of the node and the corners at (±0.5, ±0.5). Its
`normalized_visible_node_rect` field has been removed and replaced with
a new `cursor_over: bool` field which is set to true when the cursor is
hovering an unclipped area of the UI node.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- A preparation for the 'system as entities'
- The current system has a series of states such as `is_send`,
`is_exclusive`, `has_defered`, As `system as entites` landed, it may
have more states. Using Bitflags to unify all states is a more concise
and performant approach
## Solution
- Using Bitflags to unify system state.
# Objective
When running the `gradient` example, part of the content doesn't fit
within the initial window:

The UI requires 1830×930 pixels, but the initial window size is
1280×720.
## Solution
Make ui elements smaller:

Alternative: Use a larger initial window size. I decided against this
because that would make the examples less uniform, make the code less
focused on gradients and not help on web.
# Objective
Fixes#19464
## Solution
Instead of clearing previous `PickingInteractions` before updating, we
clear them last for those components that weren't updated, and use
`set_if_neq` when writing.
## Testing
I tried the sprite_picking example and it still works.
You can add the following system to picking examples to check that
change detection works as intended:
```rust
fn print_picking(query: Query<(Entity, &PickingInteraction), Changed<PickingInteraction>>) {
for (entity, interaction) in &query {
println!("{entity} {interaction:?}");
}
}
```
# Objective
Deny missing docs for bevy_ecs_macros, towards
https://github.com/bevyengine/bevy/issues/3492.
## Solution
More docs of the form
```
/// Does the thing
fn do_the_thing() {}
```
But I don't think the derive macros are where anyone is going to be
looking for details of these concepts and deny(missing_docs) inevitably
results in some items having noddy docs.
# Objective
I can't build a project using bevy under the environment of NixOS, so I
have to create flake.nix file.
## Solution
I add flake.nix example to `linux_dependencies.md`.
## Testing
I checked my NixOS environment in a project using bevy and booted the
project's game successfully.
---
## Showcase
<details>
<summary>Click to view showcase</summary>
1. Create a GitHub project using bevy.
2. Add a flake.nix file.
3. Commit to add this file to the GitHub repository.
4. Run `nix develop`
</details>
---------
Co-authored-by: nukanoto <me@nukanoto.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Ilia <43654815+istudyatuni@users.noreply.github.com>
# Objective
Certain classes of games, usually those with enormous worlds, require
some amount of support for double-precision. Libraries like `big_space`
exist to allow for large worlds while integrating cleanly with Bevy's
primarily single-precision ecosystem, but even then, games will often
still work directly in double-precision throughout the part of the
pipeline that feeds into the Bevy interface.
Currently, working with double-precision types in Bevy is a pain. `glam`
provides types like `DVec3`, but Bevy doesn't provide double-precision
analogs for `glam` wrappers like `Dir3`. This is mostly because doing so
involves one of:
- code duplication
- generics
- templates (like `glam` uses)
- macros
Each of these has issues that are enough to be deal-breakers as far as
maintainability, usability or readability. To work around this, I'm
putting together `bevy_dmath`, a crate that duplicates `bevy_math` types
and functionality to allow downstream users to enjoy the ergonomics and
power of `bevy_math` in double-precision. For the most part, it's a
smooth process, but in order to fully integrate, there are some
necessary changes that can only be made in `bevy_math`.
## Solution
This PR addresses the first and easiest issue with downstream
double-precision math support: `VectorSpace` currently can only
represent vector spaces over `f32`. This automatically closes the door
to double-precision curves, among other things. This restriction can be
easily lifted by allowing vector spaces to specify the underlying scalar
field. This PR adds a new trait `ScalarField` that satisfies the
properties of a scalar field (the ones that can be upheld statically)
and adds a new associated type `type Scalar: ScalarField` to
`VectorSpace`. It's mostly an unintrusive change. The biggest annoyances
are:
- it touches a lot of curve code
- `bevy_math::ops` doesn't support `f64`, so there are some annoying
workarounds
As far as curves code, I wanted to make this change unintrusive and
bite-sized, so I'm trying to touch as little code as possible. To prove
to myself it can be done, I went ahead and (*not* in this PR) migrated
most of the curves API to support different `ScalarField`s and it went
really smoothly! The ugliest thing was adding `P::Scalar: From<usize>`
in several places. There's an argument to be made here that we should be
using `num-traits`, but that's not immediately relevant. The point is
that for now, the smallest change I could make was to go into every
curve impl and make them generic over `VectorSpace<Scalar = f32>`.
Curves work exactly like before and don't change the user API at all.
# Follow-up
- **Extend `bevy_math::ops` to work with `f64`.** `bevy_math::ops` is
used all over, and if curves are ever going to support different
`ScalarField` types, we'll need to be able to use the correct `std` or
`libm` ops for `f64` types as well. Adding an `ops64` mod turned out to
be really ugly, but I'll point out the maintenance burden is low because
we're not going to be adding new floating-point ops anytime soon.
Another solution is to build a floating-point trait that calls the right
op variant and impl it for `f32` and `f64`. This reduces maintenance
burden because on the off chance we ever *do* want to go modify it, it's
all tied together: you can't change the interface on one without
changing the trait, which forces you to update the other. A third option
is to use `num-traits`, which is basically option 2 but someone else did
the work for us. They already support `no_std` using `libm`, so it would
be more or less a drop-in replacement. They're missing a couple
floating-point ops like `floor` and `ceil`, but we could make our own
floating-point traits for those (there's even the potential for
upstreaming them into `num-traits`).
- **Tweak curves to accept vector spaces over any `ScalarField`.**
Curves are ready to support custom scalar types as soon as the bullet
above is addressed. I will admit that the code is not as fun to look at:
`P::Scalar` instead of `f32` everywhere. We could consider an alternate
design where we use `f32` even to interpolate something like a `DVec3`,
but personally I think that's a worse solution than parameterizing
curves over the vector space's scalar type. At the end of the day, it's
not really bad to deal with in my opinion... `ScalarType` supports
enough operations that working with them is almost like working with raw
float types, and it unlocks a whole ecosystem for games that want to use
double-precision.
# Objective
#19421 implemented `Ord` for `EntityGeneration` along the lines of [the
impl from
slotmap](https://docs.rs/slotmap/latest/src/slotmap/util.rs.html#8):
```rs
/// Returns if a is an older version than b, taking into account wrapping of
/// versions.
pub fn is_older_version(a: u32, b: u32) -> bool {
let diff = a.wrapping_sub(b);
diff >= (1 << 31)
}
```
But that PR and the slotmap impl are different:
**slotmap impl**
- if `(1u32 << 31)` is greater than `a.wrapping_sub(b)`, then `a` is
older than `b`
- if `(1u32 << 31)` is equal to `a.wrapping_sub(b)`, then `a` is older
than `b`
- if `(1u32 << 31)` is less than `a.wrapping_sub(b)`, then `a` is equal
or newer than `b`
**previous PR impl**
- if `(1u32 << 31)` is greater than `a.wrapping_sub(b)`, then `a` is
older than `b`
- if `(1u32 << 31)` is equal to `a.wrapping_sub(b)`, then `a` is equal
to `b` ⚠️
- if `(1u32 << 31)` is less than `a.wrapping_sub(b)`, then `a` is newer
than `b` ⚠️
This ordering is also not transitive, therefore it should not implement
`PartialOrd`.
## Solution
Fix the impl in a standalone method, remove the `Partialord`/`Ord`
implementation.
## Testing
Given the first impl was wrong and got past reviews, I think a new unit
test is justified.
# Objective
- Fixes#18109.
## Solution
- All these docs now mention screen-space vs world-space.
- `start_pos` and `latest_pos` both link to `viewport_to_world` and
`viewport_to_world_2d`.
- The remaining cases are all deltas. Unfortunately `Camera` doesn't
have an appropriate method for these cases, and implementing one would
be non-trivial (e.g., the delta could have a different world-space size
based on the depth). For these cases, I just link to `Camera` and
suggest using some of its methods. Not a great solution, but at least it
gets users on the correct track.
# Objective
As discussed in #19285, we do a poor job at keeping the namespace tidy
and free of duplicates / user-conflicting names in places. `cosmic_text`
re-exports were the worst offender.
## Solution
Remove the re-exports completely. While the type aliases were quite
thoughtful, they weren't used in any of our code / API.
# Objective
- Partial fix#19504
- As more features were added to Bevy ECS, certain core hot-path
function calls exceeded LLVM's automatic inlining threshold, leading to
significant performance regressions in some cases.
## Solution
- inline more functions.
## Performance
This brought nearly 3x improvement in Windows bench (using Sander's
testing code)
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- #19504 showed a 11x regression in getting component values for
unregistered components. This pr should fix that and improve others a
little too.
- This is some cleanup work from #18173 .
## Solution
- Whenever we expect a component value to exist, we only care about
fully registered components, not queued to be registered components
since, for the value to exist, it must be registered.
- So we can use the faster `get_valid_*` instead of `get_*` in a lot of
places.
- Also found a bug where `valid_*` did not forward to `get_valid_*`
properly. That's fixed.
## Testing
CI
# Objective
The new nightly lint produces [unhelpful, noisy
output](http://github.com/bevyengine/bevy/actions/runs/15491867876/job/43620116435?pr=19510)
that makes lifetimes more prominent in our library code than we
generally find helpful.
This needs to be fixed or allowed, in order to unbreak CI for every PR
in this repo.
## Solution
Blanket allow the lint at the workspace level.
## Testing
Let's see if CI passes!
# Objective
add functionality to allow propagating components to children. requested
originally for `RenderLayers` but can be useful more generally.
## Solution
- add `HierarchyPropagatePlugin<C, F=()>` which schedules systems to
propagate components through entities matching `F`
- add `Propagate<C: Component + Clone + PartialEq>` which will cause `C`
to be added to all children
more niche features:
- add `PropagateStop<C>` which stops the propagation at this entity
- add `PropagateOver<C>` which allows the propagation to continue to
children, but doesn't add/remove/modify a `C` on this entity itself
## Testing
see tests inline
## Notes
- could happily be an out-of-repo plugin
- not sure where it lives: ideally it would be in `bevy_ecs` but it
requires a `Plugin` so I put it in `bevy_app`, doesn't really belong
there though.
- i'm not totally up-to-date on triggers and observers so possibly this
could be done more cleanly, would be very happy to take review comments
- perf: this is pretty cheap except for `update_reparented` which has to
check the parent of every moved entity. since the entirety is opt-in i
think it's acceptable but i could possibly use `(Changed<Children>,
With<Inherited<C>>)` instead if it's a concern
fix: [Ensure linear volume subtraction does not go below zero
](https://github.com/bevyengine/bevy/issues/19417)
## Solution
- Clamp the result of linear volume subtraction to a minimum of 0.0
- Add a new test case to verify behavior when subtracting beyond zero
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>