Commit graph

2133 commits

Author SHA1 Message Date
Predko Silvestr
deb135c25c
Proportional scaling for the sprite's texture. (#17258)
# Objective

Bevy sprite image mode lacks proportional scaling for the underlying
texture. In many cases, it's required. For example, if it is desired to
support a wide variety of screens with a single texture, it's okay to
cut off some portion of the original texture.

## Solution

I added scaling of the texture during the preparation step. To fill the
sprite with the original texture, I scaled UV coordinates accordingly to
the sprite size aspect ratio and texture size aspect ratio. To fit
texture in a sprite the original `quad` is scaled and then the
additional translation is applied to place the scaled quad properly.


## Testing

For testing purposes could be used `2d/sprite_scale.rs`. Also, I am
thinking that it would be nice to have some tests for a
`crates/bevy_sprite/src/render/mod.rs:sprite_scale`.

---

## Showcase

<img width="1392" alt="image"
src="https://github.com/user-attachments/assets/c2c37b96-2493-4717-825f-7810d921b4bc"
/>
2025-01-24 18:24:02 +00:00
spvky
40007cdb2e
Adds update interval config for FpsOverlayPlugin (#17489)
# Objective
Fixes #17487 

- Adds a new field `refresh_interval` to `FpsOverlayConfig` to allow the
user setting a minimum time before each refresh of the FPS display

## Solution

- Add `refresh_interval` to `FpsOverlayConfig`
- When updating the on screen text, check a duration of
`refresh_interval` has passed, if not, don't update the FPS counter

## Testing

- Created a new bevy project
- Included the `FpsOverlayPlugin` with the default `refresh_interval`
(100 ms)
- Included the `FpsOverlayPlugin` with an obnoxious `refresh_interval`
(2 seconds)
---

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-24 05:57:36 +00:00
Rostyslav Toch
af3a84fc0b
Add many_materials stress test (#17346)
# Objective

- This PR adds a new stress test called `many_materials` to benchmark
the rendering performance of many animated materials.
- Fixes #11588 
- This PR continues the work started in the previous PR #11592, which
was closed due to inactivity.

## Solution

- Created a new example (`examples/stress_tests/many_materials.rs`) that
renders a grid of cubes with animated materials.
- The size of the grid can be configured using the `-n` command-line
argument (or `--grid-size`). The default grid size is 10x10.
- The materials animate by cycling through colors in the HSL color
space.

## Testing

- I have tested these changes locally on my Linux machine.
- Reviewers can test the changes by running the example with different
grid sizes and observing the performance (FPS, frame time).
- I have not tested on other platforms (macOS, Windows, wasm), but I
expect it to work as the code uses standard Bevy features.

---

## Showcase

<details>
  <summary>Click to view showcase</summary>


![image](https://github.com/user-attachments/assets/b15209d4-f832-402b-a527-58e5048971d1)

</details>
2025-01-24 05:46:23 +00:00
mgi388
14ad25227b
Make CustomCursor variants CustomCursorImage/CustomCursorUrl structs (#17518)
# Objective

- Make `CustomCursor::Image` easier to work with by splitting the enum
variants off into `CustomCursorImage` and `CustomCursorUrl` structs and
deriving `Default` on those structs.
- Refs #17276.

## Testing

- Ran two examples: `cargo run --example custom_cursor_image
--features=custom_cursor` and `cargo run --example window_settings
--features=custom_cursor`
- CI.

---

## Migration Guide

The `CustomCursor` enum's variants now hold instances of
`CustomCursorImage` or `CustomCursorUrl`. Update your uses of
`CustomCursor` accordingly.
2025-01-24 05:39:04 +00:00
Emerson Coskey
81a25bb0c7
Procedural atmospheric scattering (#16314)
Implement procedural atmospheric scattering from [Sebastien Hillaire's
2020 paper](https://sebh.github.io/publications/egsr2020.pdf). This
approach should scale well even down to mobile hardware, and is
physically accurate.

## Co-author: @mate-h 

He helped massively with getting this over the finish line, ensuring
everything was physically correct, correcting several places where I had
misunderstood or misapplied the paper, and improving the performance in
several places as well. Thanks!

## Credits

@aevyrie: helped find numerous bugs and improve the example to best show
off this feature :)

Built off of @mtsr's original branch, which handled the transmittance
lut (arguably the most important part)

## Showcase: 


![sunset](https://github.com/user-attachments/assets/2eee1f38-f66d-4772-bb72-163e13c719d8)

![twilight](https://github.com/user-attachments/assets/f7d358b6-898d-4df7-becc-188cd753102d)


## For followup

- Integrate with pcwalton's volumetrics code
- refactor/reorganize for better integration with other effects
- have atmosphere transmittance affect directional lights
- add support for generating skybox/environment map

---------

Co-authored-by: Emerson Coskey <56370779+EmersonCoskey@users.noreply.github.com>
Co-authored-by: atlv <email@atlasdostal.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: Emerson Coskey <coskey@emerlabs.net>
Co-authored-by: Máté Homolya <mate.homolya@gmail.com>
2025-01-23 22:52:46 +00:00
Radislav Myasnikov
94e0e1f031
Updated the 2D examples to make them uniform (#17237)
# Objective

Make the examples look more uniform and more polished.
following the issue #17167

## Solution

- [x] Added a minimal UI explaining how to interact with the examples
only when needed.
- [x] Used the same notation for interactions ex : "Up Arrow: Move
Forward \nLeft / Right Arrow: Turn"
- [x] Set the color to
[GRAY](https://github.com/bevyengine/bevy/pull/17237#discussion_r1907560092)
when it's not visible enough
- [x] Changed some colors to be easy on the eyes
- [x] removed the //camera comment
- [x] Unified the use of capital letters in the examples.
- [x] Simplified the mesh2d_arc offset calculations.

...

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-01-23 16:46:58 +00:00
Zachary Harrold
9bc0ae33c3
Move hashbrown and foldhash out of bevy_utils (#17460)
# Objective

- Contributes to #16877

## Solution

- Moved `hashbrown`, `foldhash`, and related types out of `bevy_utils`
and into `bevy_platform_support`
- Refactored the above to match the layout of these types in `std`.
- Updated crates as required.

## Testing

- CI

---

## Migration Guide

- The following items were moved out of `bevy_utils` and into
`bevy_platform_support::hash`:
  - `FixedState`
  - `DefaultHasher`
  - `RandomState`
  - `FixedHasher`
  - `Hashed`
  - `PassHash`
  - `PassHasher`
  - `NoOpHash`
- The following items were moved out of `bevy_utils` and into
`bevy_platform_support::collections`:
  - `HashMap`
  - `HashSet`
- `bevy_utils::hashbrown` has been removed. Instead, import from
`bevy_platform_support::collections` _or_ take a dependency on
`hashbrown` directly.
- `bevy_utils::Entry` has been removed. Instead, import from
`bevy_platform_support::collections::hash_map` or
`bevy_platform_support::collections::hash_set` as appropriate.
- All of the above equally apply to `bevy::utils` and
`bevy::platform_support`.

## Notes

- I left `PreHashMap`, `PreHashMapExt`, and `TypeIdMap` in `bevy_utils`
as they might be candidates for micro-crating. They can always be moved
into `bevy_platform_support` at a later date if desired.
2025-01-23 16:46:08 +00:00
Zachary Harrold
41e79ae826
Refactored ComponentHook Parameters into HookContext (#17503)
# Objective

- Make the function signature for `ComponentHook` less verbose

## Solution

- Refactored `Entity`, `ComponentId`, and `Option<&Location>` into a new
`HookContext` struct.

## Testing

- CI

---

## Migration Guide

Update the function signatures for your component hooks to only take 2
arguments, `world` and `context`. Note that because `HookContext` is
plain data with all members public, you can use de-structuring to
simplify migration.

```rust
// Before
fn my_hook(
    mut world: DeferredWorld,
    entity: Entity,
    component_id: ComponentId,
) { ... }

// After
fn my_hook(
    mut world: DeferredWorld,
    HookContext { entity, component_id, caller }: HookContext,
) { ... }
``` 

Likewise, if you were discarding certain parameters, you can use `..` in
the de-structuring:

```rust
// Before
fn my_hook(
    mut world: DeferredWorld,
    entity: Entity,
    _: ComponentId,
) { ... }

// After
fn my_hook(
    mut world: DeferredWorld,
    HookContext { entity, .. }: HookContext,
) { ... }
```
2025-01-23 02:45:24 +00:00
SpecificProtagonist
f32a6fb205
Track callsite for observers & hooks (#15607)
# Objective

Fixes #14708

Also fixes some commands not updating tracked location.


## Solution

`ObserverTrigger` has a new `caller` field with the
`track_change_detection` feature;
hooks take an additional caller parameter (which is `Some(…)` or `None`
depending on the feature).

## Testing

See the new tests in `src/observer/mod.rs`

---

## Showcase

Observers now know from where they were triggered (if
`track_change_detection` is enabled):
```rust
world.observe(move |trigger: Trigger<OnAdd, Foo>| {
    println!("Added Foo from {}", trigger.caller());
});
```

## Migration

- hooks now take an additional `Option<&'static Location>` argument

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-22 20:02:39 +00:00
Alice Cecile
b34833f00c
Add an example teaching users about custom relationships (#17443)
# Objective

After #17398, Bevy now has relations! We don't teach users how to make /
work with these in the examples yet though, but we definitely should.

## Solution

- Add a simple abstract example that goes over defining, spawning,
traversing and removing a custom relations.
- ~~Add `Relationship` and `RelationshipTarget` to the prelude: the
trait methods are really helpful here.~~
- this causes subtle ambiguities with method names and weird compiler
errors. Not doing it here!
- Clean up related documentation that I referenced when writing this
example.

## Testing

`cargo run --example relationships`

## Notes to reviewers

1. Yes, I know that the cycle detection code could be more efficient. I
decided to reduce the caching to avoid distracting from the broader
point of "here's how you traverse relationships".
2. Instead of using an `App`, I've decide to use
`World::run_system_once` + system functions defined inside of `main` to
do something closer to literate programming.

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2025-01-20 23:17:38 +00:00
Carter Anderson
ba5e71f53d
Parent -> ChildOf (#17427)
Fixes #17412

## Objective

`Parent` uses the "has a X" naming convention. There is increasing
sentiment that we should use the "is a X" naming convention for
relationships (following #17398). This leaves `Children` as-is because
there is prevailing sentiment that `Children` is clearer than `ParentOf`
in many cases (especially when treating it like a collection).

This renames `Parent` to `ChildOf`.

This is just the implementation PR. To discuss the path forward, do so
in #17412.

## Migration Guide

- The `Parent` component has been renamed to `ChildOf`.
2025-01-20 22:13:29 +00:00
Alice Cecile
5a9bc28502
Support non-Vec data structures in relations (#17447)
# Objective

The existing `RelationshipSourceCollection` uses `Vec` as the only
possible backing for our relationships. While a reasonable choice,
benchmarking use cases might reveal that a different data type is better
or faster.

For example:

- Not all relationships require a stable ordering between the
relationship sources (i.e. children). In cases where we a) have many
such relations and b) don't care about the ordering between them, a hash
set is likely a better datastructure than a `Vec`.
- The number of children-like entities may be small on average, and a
`smallvec` may be faster

## Solution

- Implement `RelationshipSourceCollection` for `EntityHashSet`, our
custom entity-optimized `HashSet`.
-~~Implement `DoubleEndedIterator` for `EntityHashSet` to make things
compile.~~
   -  This implementation was cursed and very surprising.
- Instead, by moving the iterator type on `RelationshipSourceCollection`
from an erased RPTIT to an explicit associated type we can add a trait
bound on the offending methods!
- Implement `RelationshipSourceCollection` for `SmallVec`

## Testing

I've added a pair of new tests to make sure this pattern compiles
successfully in practice!

## Migration Guide

`EntityHashSet` and `EntityHashMap` are no longer re-exported in
`bevy_ecs::entity` directly. If you were not using `bevy_ecs` / `bevy`'s
`prelude`, you can access them through their now-public modules,
`hash_set` and `hash_map` instead.

## Notes to reviewers

The `EntityHashSet::Iter` type needs to be public for this impl to be
allowed. I initially renamed it to something that wasn't ambiguous and
re-exported it, but as @Victoronz pointed out, that was somewhat
unidiomatic.

In
1a8564898f,
I instead made the `entity_hash_set` public (and its `entity_hash_set`)
sister public, and removed the re-export. I prefer this design (give me
module docs please), but it leads to a lot of churn in this PR.

Let me know which you'd prefer, and if you'd like me to split that
change out into its own micro PR.
2025-01-20 21:26:08 +00:00
Chris Biscardi
1dd30a620a
Add docs to custom vertex attribute example (#17422)
# Objective

The gltf-json crate seems like it strips/adds an `_` when doing the name
comparison for custom vertex attributes.

* gltf-json
[add](88e719d5de/gltf-json/src/mesh.rs (L341))
* gltf-json
[strip](88e719d5de/gltf-json/src/mesh.rs (L298C12-L298C42))
* [bevy's
handling](b66c3ceb0e/crates/bevy_gltf/src/vertex_attributes.rs (L273-L276))
seems like it uses the non-underscore'd version.

The bevy example gltf:
[barycentric.gltf](b66c3ceb0e/assets/models/barycentric/barycentric.gltf),
includes two underscores: `__BARYCENTRIC` in the gltf file, resulting in
needing `_BARYCENTRIC` (one underscore) as the attribute name in Bevy.
This extra underscore is redundant and does not appear if exporting from
blender, which only requires a single underscore to trigger the
attribute export.

I'm not sure if we want to change the example itself (maybe there's a
reason it has two underscores, I couldn't find a reason), but a docs
comment would help.

## Solution

add docs detailing the behavior
2025-01-20 21:16:11 +00:00
Greeble
b2f3248432
Make the animated_mesh example more intuitive (#17421)
# Objective

Make the `animated_mesh` example more intuitive and easier for the user
to extend.

# Solution

The `animated_mesh` example shows how to spawn a single mesh and play a
single animation. The original code is roughly:

1. In `setup_mesh_and_animation`, spawn an entity with a SceneRoot that
will load and spawn the mesh. Also record the animation to play as a
resource.
2. Use `play_animation_once_loaded` to detect when any animation players
are spawned, then play the animation from the resource.

When I used this example as a starting point for my own app, I hit a
wall when trying to spawn multiple meshes with different animations.
`play_animation_once_loaded` tells me an animation player spawned
somewhere, but how do I get from there to the right animation? The
entity it runs on is spawned by the scene so I can't attach any data to
it?

The new code takes a different approach. Instead of a global resource,
the animation is recorded as a component on the entity with the
SceneRoot. Instead of detecting animation players spawning wherever, an
observer is attached to that specific entity.

This feels more intuitive and localised, and I think most users will
work out how to get from there to different animations and meshes. The
downside is more lines of code, and the "find the animation players"
part still feels a bit magical and inefficient.

# Side Notes

- The solution was mostly stolen from
https://github.com/bevyengine/bevy/issues/14852#issuecomment-2481401769.
- The example still feels too complicated.
    - "Why do I have to make this graph to play one animation?"
- "Why can't I choose and play the animation in one step and avoid this
temporary component?"
    - I think this requires engine changes.
- I originally started on a separate example of multiple meshes
([branch](https://github.com/bevyengine/bevy/compare/main...greeble-dev:bevy:animated-mesh-multiple)).
- I decided that the user could probably work this out themselves from
the single animation example.
    - But maybe still worth following through.

# Testing

`cargo run --example animated_mesh`

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-01-20 21:12:06 +00:00
ickshonpe
3f99a3e8cd
Text 2d alignment fix (#17365)
# Objective

`Text2d` ignores `TextBounds` when calculating the offset for text
aligment.
On main a text entity positioned in the center of the window with center
justification and 600px horizontal text bounds isn't centered like it
should be but shifted off to the right:
<img width="305" alt="hellox"
src="https://github.com/user-attachments/assets/8896c6f0-1b9f-4633-9c12-1de6eff5f3e1"
/>
(second example in the testing section below)

Fixes #14266

I already had a PR in review for this (#14270) but it used post layout
adjustment (which we want to avoid) and ignored `TextBounds`.

## Solution

* If `TextBounds` are present for an axis, use them instead of the size
of the computed text layout size to calculate the offset.
* Adjust the vertical offset of text so it's top is aligned with the top
of the texts bounding rect (when present).

## Testing

```
use bevy::prelude::*;
use bevy::color::palettes;
use bevy::sprite::Anchor;
use bevy::text::TextBounds;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn example(commands: &mut Commands, dest: Vec3, justify: JustifyText) {
    commands.spawn((
        Sprite {
            color: palettes::css::YELLOW.into(),
            custom_size: Some(10. * Vec2::ONE),
            anchor: Anchor::Center,
            ..Default::default()
        },
        Transform::from_translation(dest),
    ));

    for a in [
        Anchor::TopLeft,
        Anchor::TopRight,
        Anchor::BottomRight,
        Anchor::BottomLeft,
    ] {
        commands.spawn((
            Text2d(format!("L R\n{:?}\n{:?}", a, justify)),
            TextFont {
                font_size: 14.0,
                ..default()
            },
            TextLayout {
                justify,
                ..Default::default()
            },
            TextBounds::new(300., 75.),
            Transform::from_translation(dest + Vec3::Z),
            a,
        ));
    }
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d::default());

    for (i, j) in [
        JustifyText::Left,
        JustifyText::Right,
        JustifyText::Center,
        JustifyText::Justified,
    ]
    .into_iter()
    .enumerate()
    {
        example(&mut commands, (300. - 150. * i as f32) * Vec3::Y, j);
    }

    commands.spawn(Sprite {
        color: palettes::css::YELLOW.into(),
        custom_size: Some(10. * Vec2::ONE),
        anchor: Anchor::Center,
        ..Default::default()
    });
}
```

<img width="566" alt="cap"
src="https://github.com/user-attachments/assets/e6a98fa5-80b2-4380-a9b7-155bb49635b8"
/>

This probably looks really confusing but it should make sense if you
imagine each block of text surrounded by a 300x75 rectangle that is
anchored to the center of the yellow square.

# 

```
use bevy::prelude::*;
use bevy::sprite::Anchor;
use bevy::text::TextBounds;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d::default());

    commands.spawn((
        Text2d::new("hello"),
        TextFont {
            font_size: 60.0,
            ..default()
        },
        TextLayout::new_with_justify(JustifyText::Center),
        TextBounds::new(600., 200.),
        Anchor::Center,
    ));
}
```

<img width="338" alt="hello"
src="https://github.com/user-attachments/assets/e5e89364-afda-4baa-aca8-df4cdacbb4ed"
/>

The text being above the center is intended. When `TextBounds` are
present, the text block's offset is calculated using its `TextBounds`
not the layout size returned by cosmic-text.

# 

Probably we should add a vertical alignment setting for Text2d. Didn't
do it here as this is intended for a 0.15.2 release.
2025-01-20 20:54:32 +00:00
theotherphil
e66aef2d7a
Correct 'Text2dBundle' to 'Text2d' in example comment (#17425)
# Objective

Update out of date comment.

## Solution

## Testing

N/A
2025-01-19 22:22:28 +00:00
Arend-Jan
9c5f5b8455
docs: rewrite scene loading example documentation for clarity and depth (#17434)
This commit overhauls the documentation in the Bevy scene loading
example. It adds thorough explanatory comments to guide new Rust and
Bevy developers. The rewritten docs clarify how to:

- Register types for reflection, enabling serialization and dynamic
property access
- Skip serializing certain fields with `#[reflect(skip_serializing)]`
- Use `FromWorld` for components that require runtime initialization
- Store and serialize `Resources` in scene files
- Load scenes using a `DynamicSceneRoot` and handle updates in a system
- Serialize a brand-new scene to a separate file asynchronously using
`IoTaskPool`

These additions aim to provide a clear, step-by-step reference that
demonstrates how to implement a scene-based workflow, making it easier
for beginners and experienced developers alike to use Bevy’s scene
system effectively.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-19 20:15:09 +00:00
ickshonpe
adc33b5108
Rename TargetCamera to UiTargetCamera (#17403)
# 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`.
2025-01-19 19:56:57 +00:00
Sigma-dev
7c8da1c05d
Reworked Segment types into their cartesian forms (#17404)
# 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>
2025-01-19 03:54:45 +00:00
Carter Anderson
21f1e3045c
Relationships (non-fragmenting, one-to-many) (#17398)
This adds support for one-to-many non-fragmenting relationships (with
planned paths for fragmenting and non-fragmenting many-to-many
relationships). "Non-fragmenting" means that entities with the same
relationship type, but different relationship targets, are not forced
into separate tables (which would cause "table fragmentation").

Functionally, this fills a similar niche as the current Parent/Children
system. The biggest differences are:

1. Relationships have simpler internals and significantly improved
performance and UX. Commands and specialized APIs are no longer
necessary to keep everything in sync. Just spawn entities with the
relationship components you want and everything "just works".
2. Relationships are generalized. Bevy can provide additional built in
relationships, and users can define their own.

**REQUEST TO REVIEWERS**: _please don't leave top level comments and
instead comment on specific lines of code. That way we can take
advantage of threaded discussions. Also dont leave comments simply
pointing out CI failures as I can read those just fine._

## Built on top of what we have

Relationships are implemented on top of the Bevy ECS features we already
have: components, immutability, and hooks. This makes them immediately
compatible with all of our existing (and future) APIs for querying,
spawning, removing, scenes, reflection, etc. The fewer specialized APIs
we need to build, maintain, and teach, the better.

## Why focus on one-to-many non-fragmenting first?

1. This allows us to improve Parent/Children relationships immediately,
in a way that is reasonably uncontroversial. Switching our hierarchy to
fragmenting relationships would have significant performance
implications. ~~Flecs is heavily considering a switch to non-fragmenting
relations after careful considerations of the performance tradeoffs.~~
_(Correction from @SanderMertens: Flecs is implementing non-fragmenting
storage specialized for asset hierarchies, where asset hierarchies are
many instances of small trees that have a well defined structure)_
2. Adding generalized one-to-many relationships is currently a priority
for the [Next Generation Scene / UI
effort](https://github.com/bevyengine/bevy/discussions/14437).
Specifically, we're interested in building reactions and observers on
top.

## The changes

This PR does the following:

1. Adds a generic one-to-many Relationship system
3. Ports the existing Parent/Children system to Relationships, which now
lives in `bevy_ecs::hierarchy`. The old `bevy_hierarchy` crate has been
removed.
4. Adds on_despawn component hooks
5. Relationships can opt-in to "despawn descendants" behavior, meaning
that the entire relationship hierarchy is despawned when
`entity.despawn()` is called. The built in Parent/Children hierarchies
enable this behavior, and `entity.despawn_recursive()` has been removed.
6. `world.spawn` now applies commands after spawning. This ensures that
relationship bookkeeping happens immediately and removes the need to
manually flush. This is in line with the equivalent behaviors recently
added to the other APIs (ex: insert).
7. Removes the ValidParentCheckPlugin (system-driven / poll based) in
favor of a `validate_parent_has_component` hook.

## Using Relationships

The `Relationship` trait looks like this:

```rust
pub trait Relationship: Component + Sized {
    type RelationshipSources: RelationshipSources<Relationship = Self>;
    fn get(&self) -> Entity;
    fn from(entity: Entity) -> Self;
}
```

A relationship is a component that:

1. Is a simple wrapper over a "target" Entity.
2. Has a corresponding `RelationshipSources` component, which is a
simple wrapper over a collection of entities. Every "target entity"
targeted by a "source entity" with a `Relationship` has a
`RelationshipSources` component, which contains every "source entity"
that targets it.

For example, the `Parent` component (as it currently exists in Bevy) is
the `Relationship` component and the entity containing the Parent is the
"source entity". The entity _inside_ the `Parent(Entity)` component is
the "target entity". And that target entity has a `Children` component
(which implements `RelationshipSources`).

In practice, the Parent/Children relationship looks like this:

```rust
#[derive(Relationship)]
#[relationship(relationship_sources = Children)]
pub struct Parent(pub Entity);

#[derive(RelationshipSources)]
#[relationship_sources(relationship = Parent)]
pub struct Children(Vec<Entity>);
```

The Relationship and RelationshipSources derives automatically implement
Component with the relevant configuration (namely, the hooks necessary
to keep everything in sync).

The most direct way to add relationships is to spawn entities with
relationship components:

```rust
let a = world.spawn_empty().id();
let b = world.spawn(Parent(a)).id();

assert_eq!(world.entity(a).get::<Children>().unwrap(), &[b]);
```

There are also convenience APIs for spawning more than one entity with
the same relationship:

```rust
world.spawn_empty().with_related::<Children>(|s| {
    s.spawn_empty();
    s.spawn_empty();
})
```

The existing `with_children` API is now a simpler wrapper over
`with_related`. This makes this change largely non-breaking for existing
spawn patterns.

```rust
world.spawn_empty().with_children(|s| {
    s.spawn_empty();
    s.spawn_empty();
})
```

There are also other relationship APIs, such as `add_related` and
`despawn_related`.

## Automatic recursive despawn via the new on_despawn hook

`RelationshipSources` can opt-in to "despawn descendants" behavior,
which will despawn all related entities in the relationship hierarchy:

```rust
#[derive(RelationshipSources)]
#[relationship_sources(relationship = Parent, despawn_descendants)]
pub struct Children(Vec<Entity>);
```

This means that `entity.despawn_recursive()` is no longer required.
Instead, just use `entity.despawn()` and the relevant related entities
will also be despawned.

To despawn an entity _without_ despawning its parent/child descendants,
you should remove the `Children` component first, which will also remove
the related `Parent` components:

```rust
entity
    .remove::<Children>()
    .despawn()
```

This builds on the on_despawn hook introduced in this PR, which is fired
when an entity is despawned (before other hooks).

## Relationships are the source of truth

`Relationship` is the _single_ source of truth component.
`RelationshipSources` is merely a reflection of what all the
`Relationship` components say. By embracing this, we are able to
significantly improve the performance of the system as a whole. We can
rely on component lifecycles to protect us against duplicates, rather
than needing to scan at runtime to ensure entities don't already exist
(which results in quadratic runtime). A single source of truth gives us
constant-time inserts. This does mean that we cannot directly spawn
populated `Children` components (or directly add or remove entities from
those components). I personally think this is a worthwhile tradeoff,
both because it makes the performance much better _and_ because it means
theres exactly one way to do things (which is a philosophy we try to
employ for Bevy APIs).

As an aside: treating both sides of the relationship as "equivalent
source of truth relations" does enable building simple and flexible
many-to-many relationships. But this introduces an _inherent_ need to
scan (or hash) to protect against duplicates.
[`evergreen_relations`](https://github.com/EvergreenNest/evergreen_relations)
has a very nice implementation of the "symmetrical many-to-many"
approach. Unfortunately I think the performance issues inherent to that
approach make it a poor choice for Bevy's default relationship system.

## Followup Work

* Discuss renaming `Parent` to `ChildOf`. I refrained from doing that in
this PR to keep the diff reasonable, but I'm personally biased toward
this change (and using that naming pattern generally for relationships).
* [Improved spawning
ergonomics](https://github.com/bevyengine/bevy/discussions/16920)
* Consider adding relationship observers/triggers for "relationship
targets" whenever a source is added or removed. This would replace the
current "hierarchy events" system, which is unused upstream but may have
existing users downstream. I think triggers are the better fit for this
than a buffered event queue, and would prefer not to add that back.
* Fragmenting relations: My current idea hinges on the introduction of
"value components" (aka: components whose type _and_ value determines
their ComponentId, via something like Hashing / PartialEq). By labeling
a Relationship component such as `ChildOf(Entity)` as a "value
component", `ChildOf(e1)` and `ChildOf(e2)` would be considered
"different components". This makes the transition between fragmenting
and non-fragmenting a single flag, and everything else continues to work
as expected.
* Many-to-many support
* Non-fragmenting: We can expand Relationship to be a list of entities
instead of a single entity. I have largely already written the code for
this.
* Fragmenting: With the "value component" impl mentioned above, we get
many-to-many support "for free", as it would allow inserting multiple
copies of a Relationship component with different target entities.

Fixes #3742 (If this PR is merged, I think we should open more targeted
followup issues for the work above, with a fresh tracking issue free of
the large amount of less-directed historical context)
Fixes #17301
Fixes #12235 
Fixes #15299
Fixes #15308 

## Migration Guide

* Replace `ChildBuilder` with `ChildSpawnerCommands`.
* Replace calls to `.set_parent(parent_id)` with
`.insert(Parent(parent_id))`.
* Replace calls to `.replace_children()` with `.remove::<Children>()`
followed by `.add_children()`. Note that you'll need to manually despawn
any children that are not carried over.
* Replace calls to `.despawn_recursive()` with `.despawn()`.
* Replace calls to `.despawn_descendants()` with
`.despawn_related::<Children>()`.
* If you have any calls to `.despawn()` which depend on the children
being preserved, you'll need to remove the `Children` component first.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-18 22:20:30 +00:00
Alex Habich
b66c3ceb0e
Add external assets to .gitignore (#17388)
Added an external assets section to .gitignore. This prevents
contributors from accidentally adding or committing them.

I believe currently the only externel asset is the meshlet bunny.
2025-01-17 01:20:14 +00:00
Alice Cecile
3737f86d84
Small improvements for directional navigation (#17395)
# Objective

While working on more complex directional navigation work, I noticed a
few small things.

## Solution

Rather than stick them in a bigger PR, split them out now.

- Include more useful information when responding to
`DirectionalNavigationError`.
- Use the less controversial `Click` events (rather than `Pressed`) in
the example
- Implement add_looping_edges in terms of `add_edges`. Thanks @rparrett
for the idea.

## Testing

Ran the `directional_navigation` example and things still work.
2025-01-17 01:15:39 +00:00
Alice Cecile
72f70745c5
add_edges helper for directional navigation (#17389)
# Objective

While `add_looping_edges` is a helpful method for manually defining
directional navigation maps, we don't always want to loop around!

## Solution

Add a non-looping variant.

These commits are cherrypicked from the more complex #17247.

## Testing

I've updated the `directional_navigation` example to use these changes,
and verified that it works.

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-15 23:43:03 +00:00
JMS55
e8e2426058
Forward decals (port of bevy_contact_projective_decals) (#16600)
# Objective

- Implement ForwardDecal as outlined in
https://github.com/bevyengine/bevy/issues/2401

## Solution

- Port https://github.com/naasblod/bevy_contact_projective_decals, and
cleanup the API a little.

## Testing

- Ran the new decal example.

---

## Showcase


![image](https://github.com/user-attachments/assets/72134af0-724f-4df9-a11f-b0888819a791)

## Changelog
* Added ForwardDecal and associated types
* Added MaterialExtension::alpha_mode()

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2025-01-15 02:31:30 +00:00
MichiRecRoom
26bb0b40d2
Move #![warn(clippy::allow_attributes, clippy::allow_attributes_without_reason)] to the workspace Cargo.toml (#17374)
# 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>
2025-01-15 01:14:58 +00:00
mgi388
0756a19f28
Support texture atlases in CustomCursor::Image (#17121)
# Objective

- Bevy 0.15 added support for custom cursor images in
https://github.com/bevyengine/bevy/pull/14284.
- However, to do animated cursors using the initial support shipped in
0.15 means you'd have to animate the `Handle<Image>`: You can't use a
`TextureAtlas` like you can with sprites and UI images.
- For my use case, my cursors are spritesheets. To animate them, I'd
have to break them down into multiple `Image` assets, but that seems
less than ideal.


## Solution

- Allow users to specify a `TextureAtlas` field when creating a custom
cursor image.
- To create parity with Bevy's `TextureAtlas` support on `Sprite`s and
`ImageNode`s, this also allows users to specify `rect`, `flip_x` and
`flip_y`. In fact, for my own use case, I need to `flip_y`.

## Testing

- I added unit tests for `calculate_effective_rect` and
`extract_and_transform_rgba_pixels`.
- I added a brand new example for custom cursor images. It has controls
to toggle fields on and off. I opted to add a new example because the
existing cursor example (`window_settings`) would be far too messy for
showcasing these custom cursor features (I did start down that path but
decided to stop and make a brand new example).
- The new example uses a [Kenny cursor icon] sprite sheet. I included
the licence even though it's not required (and it's CC0).
- I decided to make the example just loop through all cursor icons for
its animation even though it's not a _realistic_ in-game animation
sequence.
- I ran the PNG through https://tinypng.com. Looks like it's about 35KB.
- I'm open to adjusting the example spritesheet if required, but if it's
fine as is, great.

[Kenny cursor icon]: https://kenney-assets.itch.io/crosshair-pack

---

## Showcase


https://github.com/user-attachments/assets/8f6be8d7-d1d4-42f9-b769-ef8532367749

## Migration Guide

The `CustomCursor::Image` enum variant has some new fields. Update your
code to set them.

Before:

```rust
CustomCursor::Image {
    handle: asset_server.load("branding/icon.png"),
    hotspot: (128, 128),
}
```

After:

```rust
CustomCursor::Image {
    handle: asset_server.load("branding/icon.png"),
    texture_atlas: None,
    flip_x: false,
    flip_y: false,
    rect: None,
    hotspot: (128, 128),
}
```

## References

- Feature request [originally raised in Discord].

[originally raised in Discord]:
https://discord.com/channels/691052431525675048/692572690833473578/1319836362219847681
2025-01-14 22:27:24 +00:00
Matty Weatherley
ec611976ef
Fix a missing .entity() -> .target() conversion in observers example (#17363)
See title :)
2025-01-14 21:52:24 +00:00
Patrick Walton
35101f3ed5
Use multi_draw_indirect_count where available, in preparation for two-phase occlusion culling. (#17211)
This commit allows Bevy to use `multi_draw_indirect_count` for drawing
meshes. The `multi_draw_indirect_count` feature works just like
`multi_draw_indirect`, but it takes the number of indirect parameters
from a GPU buffer rather than specifying it on the CPU.

Currently, the CPU constructs the list of indirect draw parameters with
the instance count for each batch set to zero, uploads the resulting
buffer to the GPU, and dispatches a compute shader that bumps the
instance count for each mesh that survives culling. Unfortunately, this
is inefficient when we support `multi_draw_indirect_count`. Draw
commands corresponding to meshes for which all instances were culled
will remain present in the list when calling
`multi_draw_indirect_count`, causing overhead. Proper use of
`multi_draw_indirect_count` requires eliminating these empty draw
commands.

To address this inefficiency, this PR makes Bevy fully construct the
indirect draw commands on the GPU instead of on the CPU. Instead of
writing instance counts to the draw command buffer, the mesh
preprocessing shader now writes them to a separate *indirect metadata
buffer*. A second compute dispatch known as the *build indirect
parameters* shader runs after mesh preprocessing and converts the
indirect draw metadata into actual indirect draw commands for the GPU.
The build indirect parameters shader operates on a batch at a time,
rather than an instance at a time, and as such each thread writes only 0
or 1 indirect draw parameters, simplifying the current logic in
`mesh_preprocessing`, which currently has to have special cases for the
first mesh in each batch. The build indirect parameters shader emits
draw commands in a tightly packed manner, enabling maximally efficient
use of `multi_draw_indirect_count`.

Along the way, this patch switches mesh preprocessing to dispatch one
compute invocation per render phase per view, instead of dispatching one
compute invocation per view. This is preparation for two-phase occlusion
culling, in which we will have two mesh preprocessing stages. In that
scenario, the first mesh preprocessing stage must only process opaque
and alpha tested objects, so the work items must be separated into those
that are opaque or alpha tested and those that aren't. Thus this PR
splits out the work items into a separate buffer for each phase. As this
patch rewrites so much of the mesh preprocessing infrastructure, it was
simpler to just fold the change into this patch instead of deferring it
to the forthcoming occlusion culling PR.

Finally, this patch changes mesh preprocessing so that it runs
separately for indexed and non-indexed meshes. This is because draw
commands for indexed and non-indexed meshes have different sizes and
layouts. *The existing code is actually broken for non-indexed meshes*,
as it attempts to overlay the indirect parameters for non-indexed meshes
on top of those for indexed meshes. Consequently, right now the
parameters will be read incorrectly when multiple non-indexed meshes are
multi-drawn together. *This is a bug fix* and, as with the change to
dispatch phases separately noted above, was easiest to include in this
patch as opposed to separately.

## Migration Guide

* Systems that add custom phase items now need to populate the indirect
drawing-related buffers. See the `specialized_mesh_pipeline` example for
an example of how this is done.
2025-01-14 21:19:20 +00:00
ickshonpe
d34803f5f4
Add some multi-span text to the text2d example (#17308)
# Objective

The `Text2d` example should have have some multi-span text.

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 07:58:21 +00:00
Greeble
c96949dabe
Improve the animated_mesh example (#17328)
# Objective

Building upon https://github.com/bevyengine/bevy/pull/17191, improve the
`animated_mesh` example by removing code, adding comments, and making
the example more c&p'able.

## Solution

- Split the setup function in two to clarify what the example is
demonstrating.
    - `setup_mesh_and_animation` is the demonstration.
    - `setup_camera_and_environment` just sets up the example app.
- Changed the animation playing to use `AnimationPlayer` directly
instead of creating `AnimationTransitions`.
    - This appears sufficient when only playing a single animation.
- Added a comment pointing users to an example of multiple animations.
- Changed the animation to be the run cycle.
- I think it got accidentally changed to the idle in
[#17191](https://github.com/bevyengine/bevy/pull/17191), so this is
reverting back to the original.
- Note that we can improve it to select the animation by name if
[#16529](https://github.com/bevyengine/bevy/pull/16529) lands.
- Renamed `FOX_PATH` to a more neutral `GLTF_PATH`.
- Updated the example descriptions to mention the fox.
- This adds a little character and hints that the example involves
character animation.
- Removed a seemingly redundant `AnimationGraphHandle` component.
- Removed an unnecessary `clone()`.
- Added various comments.

## Notes

- A draft of this PR was discussed on Discord:
https://discord.com/channels/691052431525675048/1326910663972618302/1326920498663133348
- There was discord discussion on whether a component is "inserted
onto", "inserted into" or "added to" an entity.
- "Added to" is most common in code and docs, and seems best to me. But
it awkwardly differs from the name of `EntityCommands::insert`.
    - This PR prefers "added to".
- I plan to follow up this PR with similar changes to the
`animated_mesh_control` and `animated_mesh_events` examples.
    - But I could roll them into this PR if requested.

## Testing

`cargo run --example animated_mesh`

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 01:10:50 +00:00
Patrick Walton
141b7673ab
Key render phases off the main world view entity, not the render world view entity. (#16942)
We won't be able to retain render phases from frame to frame if the keys
are unstable. It's not as simple as simply keying off the main world
entity, however, because some main world entities extract to multiple
render world entities. For example, directional lights extract to
multiple shadow cascades, and point lights extract to one view per
cubemap face. Therefore, we key off a new type, `RetainedViewEntity`,
which contains the main entity plus a *subview ID*.

This is part of the preparation for retained bins.

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
2025-01-12 20:24:17 +00:00
Rob Parrett
f0047899d7
Allow users to customize history length in FrameTimeDiagnosticsPlugin (#17259)
# Objective

I have an application where I'd like to measure average frame rate over
the entire life of the application, and it would be handy if I could
just configure this on the existing `FrameTimeDiagnosticsPlugin`.

Probably fixes #10948?

## Solution

Add `max_history_length` to `FrameTimeDiagnosticsPlugin`, and because
`smoothing_factor` seems to be based on history length, add that too.

## Discussion

I'm not totally sure that `DEFAULT_MAX_HISTORY_LENGTH` is a great
default for `FrameTimeDiagnosticsPlugin` (or any diagnostic?). That's
1/3 of a second at typical game frame rates. Moreover, the default print
interval for `LogDiagnosticsPlugin` is 1 second. So when the two are
combined, you are printing the average over the last third of the
duration between now and the previous print, which seems a bit wonky.
(related: #11429)

I'm pretty sure this default value discussed and the current value
wasn't totally arbitrary though.

Maybe it would be nice for `Diagnostic` to have a
`with_max_history_length_and_also_calculate_a_good_default_smoothing_factor`
method? And then make an explicit smoothing factor in
`FrameTimeDiagnosticsPlugin` optional?

Or add a `new(max_history_length: usize)` method to
`FrameTimeDiagnosticsPlugin` that sets a reasonable default
`smoothing_factor`? edit: This one seems like a no-brainer, doing it.

## Alternatives

It's really easy to roll your own `FrameTimeDiagnosticsPlugin`, but that
might not be super interoperable with, for example, third party FPS
overlays. Still, might be the right call.

## Testing

`cargo run --example many_sprites` (modified to use a custom
`max_history_length`)

## Migration Guide

`FrameTimeDiagnosticsPlugin` now contains two fields. Use
`FrameTimeDiagnosticsPlugin::default()` to match Bevy's previous
behavior or, for example, `FrameTimeDiagnosticsPlugin::new(60)` to
configure it.
2025-01-12 18:18:14 +00:00
JMS55
bb0a82b9a7
Higher quality bicubic lightmap sampling (#16740)
# Objective
- Closes https://github.com/bevyengine/bevy/issues/14322.

## Solution
- Implement fast 4-sample bicubic filtering based on this shader toy
https://www.shadertoy.com/view/4df3Dn, with a small speedup from a ghost
of tushima presentation.

## Testing

- Did you test these changes? If so, how?
  - Ran on lightmapped example. Practically no difference in that scene.
- Are there any parts that need more testing?
  - Lightmapping a better scene.

## Changelog
- Lightmaps now have a higher quality bicubic sampling method (off by
default).

---------

Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
2025-01-12 05:40:30 +00:00
AlephCubed
e808fbe987
Renamed members of ParamWarnPolicy to reflect new behaviour. (#17311)
- `Once` renamed to `Warn`.
- `param_warn_once()` renamed to `warn_param_missing()`.
- `never_param_warn()` renamed to `ignore_param_missing()`.

Also includes changes to the documentation of the above methods.

Fixes #17262.

## Migration Guide
- `ParamWarnPolicy::Once` has been renamed to `ParamWarnPolicy::Warn`.
- `ParamWarnPolicy::param_warn_once` has been renamed to
`ParamWarnPolicy::warn_param_missing`.
- `ParamWarnPolicy::never_param_warn` has been renamed to
`ParamWarnPolicy::ignore_param_missing`.
2025-01-12 05:40:04 +00:00
Antony
02bb151889
Rename PickingBehavior to Pickable (#17266)
# Objective

PR #17225 allowed for sprite picking to be opt-in. After some
discussion, it was agreed that `PickingBehavior` should be used to
opt-in to sprite picking behavior for entities. This leads to
`PickingBehavior` having two purposes: mark an entity for use in a
backend, and describe how it should be picked. Discussion led to the
name `Pickable`making more sense (also: this is what the component was
named before upstreaming).

A follow-up pass will be made after this PR to unify backends.

## Solution

Replace all instances of `PickingBehavior` and `picking_behavior` with
`Pickable` and `pickable`, respectively.

## Testing

CI

## Migration Guide

Change all instances of `PickingBehavior` to `Pickable`.
2025-01-12 05:36:52 +00:00
Rob Parrett
5c0e13f29b
Fix text alignment for unbounded text (#17270)
# Objective

Fixes #16783

## Solution

Works around a `cosmic-text` bug or limitation by triggering a re-layout
with the calculated width from the first layout run. See linked issue.

Credit to @ickshonpe for the clever solution.

## Performance

This has a significant performance impact only on unbounded text that
are not `JustifyText::Left`, which is still a bit of a bummer because
text2d performance in 0.15.1 is already not great. But this seems better
than alignment not working.

||many_text2d nfc re|many_text2d nfc re center|
|-|-|-|
|unbounded-layout-no-fix|3.06|3.10|
|unbounded-layout-fix|3.05  -0.2%|2.71 🟥 -12.5%|

## Testing

I added a centered text to the `text2d` example.

`cargo run --example text2d`

We should look at other text examples and stress tests. I haven't tested
as thoroughly as I would like, so help testing that this doesn't break
something in UI would be appreciated.
2025-01-11 05:45:32 +00:00
Rob Parrett
b77e3ef33a
Fix a few typos (#17292)
# Objective

Stumbled upon a `from <-> form` transposition while reviewing a PR,
thought it was interesting, and went down a bit of a rabbit hole.

## Solution

Fix em
2025-01-10 22:48:30 +00:00
Alice Cecile
145f5f4394
Add a simple directional UI navigation example (#17224)
# Objective

Gamepad / directional navigation needs an example, for both teaching and
testing purposes.

## Solution

- Add a simple grid-based example.
- Fix an intermittent panic caused by a race condition with bevy_a11y
- Clean up small issues noticed in bevy_input_focus


![image](https://github.com/user-attachments/assets/3a924255-0cd6-44a5-9bb7-b2c400a22d7e)

## To do: this PR

- [x] figure out why "enter" isn't doing anything
- [x] change button color on interaction rather than printing
- [x] add on-screen directions
- [x] move to an asymmetric grid to catch bugs
- [x] ~~fix colors not resetting on button press~~ lol this is mostly
just a problem with hacking `Interaction` for this
- [x] swap to using observers + bubbling, rather than `Interaction`

## To do: future work

- when I increase the button size, such that there is no line break, the
text on the buttons is no longer centered :( EDIT: this is
https://github.com/bevyengine/bevy/issues/16783
- add gamepad stick navigation
- add tools to find the nearest populated quadrant to make diagonal
inputs work
- add a `add_edges` method to `DirectionalNavigationMap`
- add a `add_grid` method to `DirectionalNavigationMap`
- make the example's layout more complex and realistic
- add tools to automatically generate this list
- add button shake on failed navigation rather than printing an error
- make Pressed events easier to mock: default fields, PointerId::Focus

## Testing

`cargo run --example directional_navigation`

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-01-09 21:15:28 +00:00
Antony
0a9740c18f
Make sprite picking opt-in (#17225)
# Objective

Fixes #16903.

## Solution

- Make sprite picking opt-in by requiring a new `SpritePickingCamera`
component for cameras and usage of a new `Pickable` component for
entities.
- Update the `sprite_picking` example to reflect these changes.
- Some reflection cleanup (I hope that's ok).

## Testing

Ran the `sprite_picking` example

## Open Questions

<del>
   <ul>
    <li>Is the name `SpritePickable` appropriate?</li>
    <li>Should `SpritePickable` be in `bevy_sprite::prelude?</li>
  </ul> 
</del>

## Migration Guide

The sprite picking backend is now strictly opt-in using the
`SpritePickingCamera` and `Pickable` components. You should add the
`Pickable` component any entities that you want sprite picking to be
enabled for, and mark their respective cameras with
`SpritePickingCamera`.
2025-01-09 18:11:44 +00:00
MichiRecRoom
3742e621ef
Allow clippy::too_many_arguments to lint without warnings (#17249)
# 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.
2025-01-09 07:26:15 +00:00
MichiRecRoom
8e51b326b5
Cleanup instances of #[allow(clippy::type_complexity)] (#17248)
# Objective
I never realized `clippy::type_complexity` was an allowed lint - I've
been assuming it'd generate a warning when performing my linting PRs.

## Solution
Removes any instances of `#[allow(clippy::type_complexity)]` and
`#[expect(clippy::type_complexity)]`

## Testing
`cargo clippy` ran without errors or warnings.
2025-01-09 06:25:20 +00:00
Greeble
6462935b32
Rename animated fox examples to better communicate their purpose (#17239)
Fixes #17192.

Replaces "animated_fox" with "animated_mesh".

I considered a few different names - should it say "skinned_mesh" to be
precise? Should it mention gltf? But "animated_mesh" seems intuitive and
keeps it short.

## Testing

- Ran all three examples (Windows 10).
2025-01-08 18:59:17 +00:00
Sean Kim
5faff84c10
Upstream DebugPickingPlugin from bevy_mod_picking (#17177)
# Objective

The debug features (`DebugPickingPlugin`) from `bevy_mod_picking` were
not upstreamed with the rest of the core changes, this PR reintroduces
it for usage inside `bevy_dev_tools`

## Solution

Vast majority of this code is taken as-is from `bevy_mod_picking` aside
from changes to ensure compilation and code style, as such @aevyrie was
added as the co-author for this change.

### Main changes
* `multiselection` support - the relevant code was explicitly not
included in the process of upstreaming the rest of the package, so it
also has been omitted here.
* `bevy_egui` support - the old package had a preference for using
`bevy_egui` instead of `bevy_ui` if possible, I couldn't see a way to
support this in a core crate, so this has been removed.

Relevant code has been added to the `bevy_dev_tools` crate instead of
`bevy_picking` as it is a better fit and requires a dependency on
`bevy_ui` for drawing debug elements.

### Minor changes
* Changed the debug text size from `60` to `12` as the former was so
large as to be unreadable in the new example.

## Testing
* `cargo run -p ci`
* Added a new example in `dev_tools/picking_debug` and visually verified
the in-window results and the console messages

---------

Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-07 05:19:50 +00:00
Cyborus04
4ba09f3dd9
add line height to TextFont (#16614)
# Objective

- Allow users to customize the line height of text.
- Implements #16085

## Solution

- Add a `line_height` field to `TextFont` to feed into `cosmic_text`'s
`Metrics`.

## Testing

- Tested on my own game, and worked exactly as I wanted.
- My game is only 2D, so I only tested `Text2d`. `Text` still needs
tested, but I imagine it'll work fine.
- An example is available
[here](https://code.cartoon-aa.xyz/Cyborus/custom-line-height-example)

---

## Showcase

<details>
  <summary>Click to view showcase</summary>

With font:
```rust
TextFont {
    font: /* unimportant */,
    font_size: 16.0,
    line_height: None,
    ..default()
}
```


![image](https://github.com/user-attachments/assets/d12d8334-72ae-44b4-9b2e-993bbfd19da6)

With font:
```rust
TextFont {
    font: /* unimportant */,
    font_size: 16.0,
    line_height: Some(16.0),
    ..default()
}
```


![image](https://github.com/user-attachments/assets/6bc843b0-b633-4c30-bf77-6bbad774c1e5)

</details>

## Migration Guide

`TextFont` now has a `line_height` field. Any instantiation of
`TextFont` that doesn't have `..default()` will need to add this field.
2025-01-06 23:11:38 +00:00
Rob Parrett
6f68776eac
Split up animated_fox example (#17191)
# Objective

Our `animated_fox` example used to be a bare-bones example of how to
spawn an animated gltf and play a single animation.

I think that's a valuable example, and the current `animated_fox`
example is doing way too much. Users who are trying to understand how
our animation system are presented with an enormous amount of
information that may not be immediately relevant.

Over the past few releases, I've been migrating a simple app of mine
where the only animation I need is a single gltf that starts playing a
single animation when it is loaded. It has been a slight struggle to
wade through changes to the animation system to figure out the minimal
amount of things required to accomplish this.

Somewhat motivated by this [recent reddit
thread](https://www.reddit.com/r/rust/comments/1ht93vl/comment/m5c0nc9/?utm_source=share&utm_medium=mweb3x&utm_name=mweb3xcss&utm_term=1)
where Bevy and animation got a mention.

## Solution

- Split `animated_fox` into three separate examples
  - `animated_fox` - Loads and immediately plays a single animation
  - `animated_fox_control` - Shows how to control animations
- `animated_fox_events` - Shows fancy particles when the fox's feet hit
the ground
- Some minor drive-by tidying of these examples

I have created this PR after playing around with the idea and liking how
it turned out, but the duplication isn't totally ideal and there's some
slight overlap with other examples and inconsistencies:

- `animation_events` is simplified and not specific to "loaded animated
scenes" and seems valuable on its own
- `animation_graph` also uses a fox

I am happy to close this if there's no consensus that it's a good idea /
step forward for these examples.

## Testing

`cargo run --example animated_fox`
`cargo run --example animated_fox_control`
`cargo run --example animated_fox_events`
2025-01-06 19:32:32 +00:00
François Mockers
94b9fe384f
can hide status bar on iOS (#17179)
# Objective

- I want to hide the clock and the battery indicator on iOS

## Solution

- Add the platform specific property `prefers_status_bar_hidden` on
Window creation, and map it to `with_prefers_status_bar_hidden` in
winit.

## Testing

- Tested on iOS
2025-01-06 19:19:56 +00:00
Aevyrie
13deb3ed76
Anamorphic Bloom (#17096)
https://github.com/user-attachments/assets/e2de3d20-4246-4eba-a0a7-8469a468dddb

The _JJ Abrahams_


https://github.com/user-attachments/assets/2dce3df9-665b-46ff-b687-e7cb54364f30

The _Cyberfunk 2025_

<img width="1392" alt="image"
src="https://github.com/user-attachments/assets/0179df38-ea2e-4f34-bbd3-d3240f0d0a4f"
/>

# Objective

- Add the ability to scale bloom for artistic control, and to mimic
anamorphic blurs.

## Solution

- Add a scale factor in bloom settings, and plumb this to the shader.

## Testing

- Added runtime-tweak-able setting to the `bloom_3d`/`bloom_2d ` example

---

## Showcase


![image](https://github.com/user-attachments/assets/bb44dae4-52bb-4981-a77f-aaa1ec83f5d6)

- Added `scale` parameter to `Bloom` to improve artistic control and
enable anamorphic bloom.
2025-01-06 18:43:21 +00:00
Patrick Walton
a8f15bd95e
Introduce two-level bins for multidrawable meshes. (#16898)
Currently, our batchable binned items are stored in a hash table that
maps bin key, which includes the batch set key, to a list of entities.
Multidraw is handled by sorting the bin keys and accumulating adjacent
bins that can be multidrawn together (i.e. have the same batch set key)
into multidraw commands during `batch_and_prepare_binned_render_phase`.

This is reasonably efficient right now, but it will complicate future
work to retain indirect draw parameters from frame to frame. Consider
what must happen when we have retained indirect draw parameters and the
application adds a bin (i.e. a new mesh) that shares a batch set key
with some pre-existing meshes. (That is, the new mesh can be multidrawn
with the pre-existing meshes.) To be maximally efficient, our goal in
that scenario will be to update *only* the indirect draw parameters for
the batch set (i.e. multidraw command) containing the mesh that was
added, while leaving the others alone. That means that we have to
quickly locate all the bins that belong to the batch set being modified.

In the existing code, we would have to sort the list of bin keys so that
bins that can be multidrawn together become adjacent to one another in
the list. Then we would have to do a binary search through the sorted
list to find the location of the bin that was just added. Next, we would
have to widen our search to adjacent indexes that contain the same batch
set, doing expensive comparisons against the batch set key every time.
Finally, we would reallocate the indirect draw parameters and update the
stored pointers to the indirect draw parameters that the bins store.

By contrast, it'd be dramatically simpler if we simply changed the way
bins are stored to first map from batch set key (i.e. multidraw command)
to the bins (i.e. meshes) within that batch set key, and then from each
individual bin to the mesh instances. That way, the scenario above in
which we add a new mesh will be simpler to handle. First, we will look
up the batch set key corresponding to that mesh in the outer map to find
an inner map corresponding to the single multidraw command that will
draw that batch set. We will know how many meshes the multidraw command
is going to draw by the size of that inner map. Then we simply need to
reallocate the indirect draw parameters and update the pointers to those
parameters within the bins as necessary. There will be no need to do any
binary search or expensive batch set key comparison: only a single hash
lookup and an iteration over the inner map to update the pointers.

This patch implements the above technique. Because we don't have
retained bins yet, this PR provides no performance benefits. However, it
opens the door to maximally efficient updates when only a small number
of meshes change from frame to frame.

The main churn that this patch causes is that the *batch set key* (which
uniquely specifies a multidraw command) and *bin key* (which uniquely
specifies a mesh *within* that multidraw command) are now separate,
instead of the batch set key being embedded *within* the bin key.

In order to isolate potential regressions, I think that at least #16890,
#16836, and #16825 should land before this PR does.

## Migration Guide

* The *batch set key* is now separate from the *bin key* in
`BinnedPhaseItem`. The batch set key is used to collect multidrawable
meshes together. If you aren't using the multidraw feature, you can
safely set the batch set key to `()`.
2025-01-06 18:34:40 +00:00
Rob Parrett
22ab715a77
Add diagnostic logging to many_gizmos (#17182)
# Objective

Make this `stress_test` more consistent with others.

## Solution

Add `LogDiagnosticsPlugin`

## Testing

`cargo run --example many_gizmos`, observe frame rate now being logged.
2025-01-06 05:38:28 +00:00
Zachary Harrold
a371ee3019
Remove tracing re-export from bevy_utils (#17161)
# Objective

- Contributes to #11478

## Solution

- Made `bevy_utils::tracing` `doc(hidden)`
- Re-exported `tracing` from `bevy_log` for end-users
- Added `tracing` directly to crates that need it.

## Testing

- CI

---

## Migration Guide

If you were importing `tracing` via `bevy::utils::tracing`, instead use
`bevy::log::tracing`. Note that many items within `tracing` are also
directly re-exported from `bevy::log` as well, so you may only need
`bevy::log` for the most common items (e.g., `warn!`, `trace!`, etc.).
This also applies to the `log_once!` family of macros.

## Notes

- While this doesn't reduce the line-count in `bevy_utils`, it further
decouples the internal crates from `bevy_utils`, making its eventual
removal more feasible in the future.
- I have just imported `tracing` as we do for all dependencies. However,
a workspace dependency may be more appropriate for version management.
2025-01-05 23:06:34 +00:00