Commit Graph

757 Commits

Author SHA1 Message Date
Zachary Harrold
6299e3de3b
Add examples/helpers/* as library examples (#18288)
# Objective

Some of Bevy's examples contain boilerplate which is split out into the
`helpers` folder. This allows examples to have access to common
functionality without building into Bevy directly. However, these
helpers are themselves quite high-quality code, and we do intend for
users to read them and even use them. But, we don't list them in the
examples document, and they aren't explicitly checked in CI, only
transitively through examples which import them.

## Solution

- Added `camera_controller` and `widgets` as library examples.

## Testing

- CI

---

## Notes

- Library examples are identical to any other example, just with
`crate-type = ["lib"]` in the `Cargo.toml`. Since they are marked as
libraries, they don't require a `main` function but do require public
items to be documented.
- Library examples opens the possibility of creating examples which
don't need to be actual runnable applications. This may be more
appropriate for certain ECS examples, and allows for adding helpers
which (currently) don't have an example that needs them without them
going stale.
- I learned about this as a concept during research for `no_std`
examples, but believe it has value for Bevy outside that specific niche.

---------

Co-authored-by: mgi388 <135186256+mgi388@users.noreply.github.com>
Co-authored-by: Carter Weinberg <weinbergcarter@gmail.com>
2025-03-13 16:34:16 +00:00
Cyrill Schenkel
8570af1d96
Add print_stdout and print_stderr lints (#17446) (#18233)
# Objective

- Prevent usage of `println!`, `eprintln!` and the like because they
require `std`
- Fixes #17446

## Solution

- Enable the `print_stdout` and `print_stderr` clippy lints
- Replace all `println!` and `eprintln!` occurrences with `log::*` where
applicable or alternatively ignore the warnings

## Testing

- Run `cargo clippy --workspace` to ensure that there are no warnings
relating to printing to `stdout` or `stderr`
2025-03-11 19:35:48 +00:00
Benjamin Brienen
c3ff6d4136
Fix non-crate typos (#18219)
# Objective

Correct spelling

## Solution

Fix typos, specifically ones that I found in folders other than /crates

## Testing

CI

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-11 06:17:48 +00:00
Johannes Ringler
683b08fec9
Respect viewport position in coordinate conversion functions (#17633)
# Objective

- In `Camera::viewport_to_world_2d`, `Camera::viewport_to_world`,
`Camera::world_to_viewport` and `Camera::world_to_viewport_with_depth`,
the results were incorrect when the `Camera::viewport` field was
configured with a viewport position that was non-zero. This PR attempts
to correct that.
- Fixes #16200 

## Solution

- This PR now takes the viewport position into account in the functions
mentioned above.
- Extended `2d_viewport_to_world` example to test the functions with a
dynamic viewport position and size, camera positions and zoom levels. It
is probably worth discussing whether to change the example, add a new
one or just completely skip touching the examples.

## Testing

Used the modified example to test the functions with dynamic camera
transform as well as dynamic viewport size and position.
2025-03-10 21:19:26 +00:00
charlotte
181445c56b
Add support for experimental WESL shader source (#17953)
# Objective

WESL's pre-MVP `0.1.0` has been
[released](https://docs.rs/wesl/latest/wesl/)!

Add support for WESL shader source so that we can begin playing and
testing WESL, as well as aiding in their development.

## Solution

Adds a `ShaderSource::WESL` that can be used to load `.wesl` shaders.

Right now, we don't support mixing `naga-oil`. Additionally, WESL
shaders currently need to pass through the naga frontend, which the WESL
team is aware isn't great for performance (they're working on compiling
into naga modules). Also, since our shaders are managed using the asset
system, we don't currently support using file based imports like `super`
or package scoped imports. Further work will be needed to asses how we
want to support this.

---

## Showcase

See the `shader_material_wesl` example. Be sure to press space to
activate party mode (trigger conditional compilation)!


https://github.com/user-attachments/assets/ec6ad19f-b6e4-4e9d-a00f-6f09336b08a4
2025-03-09 19:26:55 +00:00
Zachary Harrold
c6204279eb
Support for non-browser wasm (#17499)
# Objective

- Contributes to #15460
- Supersedes #8520
- Fixes #4906

## Solution

- Added a new `web` feature to `bevy`, and several of its crates.
- Enabled new `web` feature automatically within crates without `no_std`
support.

## Testing

- `cargo build --no-default-features --target wasm32v1-none`

---

## Migration Guide

When using Bevy crates which _don't_ automatically enable the `web`
feature, please enable it when building for the browser.

## Notes

- I added [`cfg_if`](https://crates.io/crates/cfg-if) to help manage
some of the feature gate gore that this extra feature introduces. It's
still pretty ugly, but I think much easier to read.
- Certain `wasm` targets (e.g.,
[wasm32-wasip1](https://doc.rust-lang.org/nightly/rustc/platform-support/wasm32-wasip1.html#wasm32-wasip1))
provide an incomplete implementation for `std`. I have not tested these
platforms, but I suspect Bevy's liberal use of usually unsupported
features (e.g., threading) will cause these targets to fail. As such,
consider `wasm32-unknown-unknown` as the only `wasm` platform with
support from Bevy for `std`. All others likely will need to be treated
as `no_std` platforms.
2025-03-07 21:22:28 +00:00
Zachary Harrold
cc69fdd0c6
Add no_std support to bevy (#17955)
# Objective

- Fixes #15460 (will open new issues for further `no_std` efforts)
- Supersedes #17715

## Solution

- Threaded in new features as required
- Made certain crates optional but default enabled
- Removed `compile-check-no-std` from internal `ci` tool since GitHub CI
can now simply check `bevy` itself now
- Added CI task to check `bevy` on `thumbv6m-none-eabi` to ensure
`portable-atomic` support is still valid [^1]

[^1]: This may be controversial, since it could be interpreted as
implying Bevy will maintain support for `thumbv6m-none-eabi` going
forward. In reality, just like `x86_64-unknown-none`, this is a
[canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine) target to
make it clear when `portable-atomic` no longer works as intended (fixing
atomic support on atomically challenged platforms). If a PR comes
through and makes supporting this class of platforms impossible, then
this CI task can be removed. I however wager this won't be a problem.

## Testing

- CI

---

## Release Notes

Bevy now has support for `no_std` directly from the `bevy` crate.

Users can disable default features and enable a new `default_no_std`
feature instead, allowing `bevy` to be used in `no_std` applications and
libraries.

```toml
# Bevy for `no_std` platforms
bevy = { version = "0.16", default-features = false, features = ["default_no_std"] }
```

`default_no_std` enables certain required features, such as `libm` and
`critical-section`, and as many optional crates as possible (currently
just `bevy_state`). For atomically-challenged platforms such as the
Raspberry Pi Pico, `portable-atomic` will be used automatically.

For library authors, we recommend depending on `bevy` with
`default-features = false` to allow `std` and `no_std` users to both
depend on your crate. Here are some recommended features a library crate
may want to expose:

```toml
[features]
# Most users will be on a platform which has `std` and can use the more-powerful `async_executor`.
default = ["std", "async_executor"]

# Features for typical platforms.
std = ["bevy/std"]
async_executor = ["bevy/async_executor"]

# Features for `no_std` platforms.
libm = ["bevy/libm"]
critical-section = ["bevy/critical-section"]

[dependencies]
# We disable default features to ensure we don't accidentally enable `std` on `no_std` targets, for example. 
bevy = { version = "0.16", default-features = false }
```

While this is verbose, it gives the maximum control to end-users to
decide how they wish to use Bevy on their platform.

We encourage library authors to experiment with `no_std` support. For
libraries relying exclusively on `bevy` and no other dependencies, it
may be as simple as adding `#![no_std]` to your `lib.rs` and exposing
features as above! Bevy can also provide many `std` types, such as
`HashMap`, `Mutex`, and `Instant` on all platforms. See
`bevy::platform_support` for details on what's available out of the box!

## Migration Guide

- If you were previously relying on `bevy` with default features
disabled, you may need to enable the `std` and `async_executor`
features.
- `bevy_reflect` has had its `bevy` feature removed. If you were relying
on this feature, simply enable `smallvec` and `smol_str` instead.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-07 03:39:46 +00:00
François Mockers
019a6fde25
testbed for UI (#18091)
# Objective

- have a testbed for UI

## Solution

- move previous `ui` example to `full_ui`
- add a testbed ui with several scenes
- `ui_layout_rounding` is one of those scenes, so remove it as a
standalone example

the previous `ui` / new `full_ui` is I think still useful as it has some
things like scroll, debug ui that are not shown anywhere else
2025-03-04 11:02:55 +00:00
Martín Maita
f3db44b635
Update ureq requirement from 2.10.1 to 3.0.8 (#18146)
# Objective

- Closes #18131

## Solution

- Update ureq requirement from 2.10.1 to 3.0.8 and migrate breaking
code.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-04 01:11:28 +00:00
Martín Maita
05bad0673f
Removes compile_fail glob pattern (#18040)
# Objective

- Attempts to fix #17876.

## Solution

- Reverted some changes that added a glob pattern to match all
`compile_fail` crates. This should enable Dependabot to create PRs
again.
- Added a TODO comment to not forget that this glob matching failure
should also be fixed in the Dependabot repo.
2025-02-25 23:53:17 +00:00
Lucas Franca
7d7c43dd62
Add uv_transform to ColorMaterial (#17879)
# Objective

Implements and closes #17515

## Solution

Add `uv_transform` to `ColorMaterial`

## Testing

Create a example similar to `repeated_texture` but for `Mesh2d` and
`MeshMaterial2d<ColorMaterial>`

## Showcase


![image](https://github.com/user-attachments/assets/72943b9b-59a6-489a-96a2-f9c245f0dd53)

## Migration Guide

Add `uv_transform` field to constructors of `ColorMaterial`
2025-02-24 21:17:26 +00:00
Zachary Harrold
5241e09671
Upgrade to Rust Edition 2024 (#17967)
# Objective

- Fixes #17960

## Solution

- Followed the [edition upgrade
guide](https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html)

## Testing

- CI

---

## Summary of Changes

### Documentation Indentation

When using lists in documentation, proper indentation is now linted for.
This means subsequent lines within the same list item must start at the
same indentation level as the item.

```rust
/* Valid */
/// - Item 1
///   Run-on sentence.
/// - Item 2
struct Foo;

/* Invalid */
/// - Item 1
///     Run-on sentence.
/// - Item 2
struct Foo;
```

### Implicit `!` to `()` Conversion

`!` (the never return type, returned by `panic!`, etc.) no longer
implicitly converts to `()`. This is particularly painful for systems
with `todo!` or `panic!` statements, as they will no longer be functions
returning `()` (or `Result<()>`), making them invalid systems for
functions like `add_systems`. The ideal fix would be to accept functions
returning `!` (or rather, _not_ returning), but this is blocked on the
[stabilisation of the `!` type
itself](https://doc.rust-lang.org/std/primitive.never.html), which is
not done.

The "simple" fix would be to add an explicit `-> ()` to system
signatures (e.g., `|| { todo!() }` becomes `|| -> () { todo!() }`).
However, this is _also_ banned, as there is an existing lint which (IMO,
incorrectly) marks this as an unnecessary annotation.

So, the "fix" (read: workaround) is to put these kinds of `|| -> ! { ...
}` closuers into variables and give the variable an explicit type (e.g.,
`fn()`).

```rust
// Valid
let system: fn() = || todo!("Not implemented yet!");
app.add_systems(..., system);

// Invalid
app.add_systems(..., || todo!("Not implemented yet!"));
```

### Temporary Variable Lifetimes

The order in which temporary variables are dropped has changed. The
simple fix here is _usually_ to just assign temporaries to a named
variable before use.

### `gen` is a keyword

We can no longer use the name `gen` as it is reserved for a future
generator syntax. This involved replacing uses of the name `gen` with
`r#gen` (the raw-identifier syntax).

### Formatting has changed

Use statements have had the order of imports changed, causing a
substantial +/-3,000 diff when applied. For now, I have opted-out of
this change by amending `rustfmt.toml`

```toml
style_edition = "2021"
```

This preserves the original formatting for now, reducing the size of
this PR. It would be a simple followup to update this to 2024 and run
`cargo fmt`.

### New `use<>` Opt-Out Syntax

Lifetimes are now implicitly included in RPIT types. There was a handful
of instances where it needed to be added to satisfy the borrow checker,
but there may be more cases where it _should_ be added to avoid
breakages in user code.

### `MyUnitStruct { .. }` is an invalid pattern

Previously, you could match against unit structs (and unit enum
variants) with a `{ .. }` destructuring. This is no longer valid.

### Pretty much every use of `ref` and `mut` are gone

Pattern binding has changed to the point where these terms are largely
unused now. They still serve a purpose, but it is far more niche now.

### `iter::repeat(...).take(...)` is bad

New lint recommends using the more explicit `iter::repeat_n(..., ...)`
instead.

## Migration Guide

The lifetimes of functions using return-position impl-trait (RPIT) are
likely _more_ conservative than they had been previously. If you
encounter lifetime issues with such a function, please create an issue
to investigate the addition of `+ use<...>`.

## Notes

- Check the individual commits for a clearer breakdown for what
_actually_ changed.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-02-24 03:54:47 +00:00
AlephCubed
726d8ac4b0
Added top level reflect_documentation feature flag. (#17892)
Fixes #17811.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2025-02-23 21:21:50 +00:00
BD103
63e0f794d1
Enable nonstandard_macro_braces and enforce [] for children! (#17974)
# Objective

-
[`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces)
is a Clippy lint that enforces what braces certain known macros are
allowed to use.
  - For instance, requiring `println!()` instead of `println!{}`.
- I started working on this after seeing
https://github.com/TheBevyFlock/bevy_cli/issues/277.

## Solution

- Enable `nonstandard_macro_braces` in the workspace.
- Configure Clippy so it enforces `[]` braces for `children!`.

## Testing

1. Create `examples/clippy_test.rs`.
2. Paste the following code:

```rust
//! Some docs woooooooo

use bevy::prelude::*;

fn main() {
    let _ = children!(Name::new("Foo"));
}
```

3. Run `cargo clippy --example clippy_test`.
4. Ensure the following warning is emitted:

```sh
warning: use of irregular braces for `children!` macro
 --> examples/clippy_test.rs:6:13
  |
6 |     let _ = children!(Name::new("Foo"));
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `children![Name::new("Foo")]`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
  = note: requested on the command line with `-W clippy::nonstandard-macro-braces`

warning: `bevy` (example "clippy_test") generated 1 warning (run `cargo clippy --fix --example "clippy_test"` to apply 1 suggestion)
```
2025-02-22 01:54:49 +00:00
François Mockers
cff17364b1
Deterministic fallible_systems example (#17813)
# Objective

- `fallible_systems` example is not deterministic

## Solution

- Make it deterministic
- Also fix required feature declaration
2025-02-11 23:54:20 +00:00
Mads Marquart
94deca81bf
Use target_abi = "sim" instead of ios_simulator feature (#17702)
## Objective

Get rid of a redundant Cargo feature flag.

## Solution

Use the built-in `target_abi = "sim"` instead of a custom Cargo feature
flag, which is set for the iOS (and visionOS and tvOS) simulator. This
has been stable since Rust 1.78.

In the future, some of this may become redundant if Wgpu implements
proper supper for the iOS Simulator:
https://github.com/gfx-rs/wgpu/issues/7057

CC @mockersf who implemented [the original
fix](https://github.com/bevyengine/bevy/pull/10178).

## Testing

- Open mobile example in Xcode.
- Launch the simulator.
- See that no errors are emitted.
- Remove the code cfg-guarded behind `target_abi = "sim"`.
- See that an error now happens.

(I haven't actually performed these steps on the latest `main`, because
I'm hitting an unrelated error (EDIT: It was
https://github.com/bevyengine/bevy/pull/17637). But tested it on
0.15.0).

---

## Migration Guide

> If you're using a project that builds upon the mobile example, remove
the `ios_simulator` feature from your `Cargo.toml` (Bevy now handles
this internally).
2025-02-11 23:01:26 +00:00
Jean Mertz
7d8504f30e
feat(ecs): implement fallible observer systems (#17731)
This commit builds on top of the work done in #16589 and #17051, by
adding support for fallible observer systems.

As with the previous work, the actual results of the observer system are
suppressed for now, but the intention is to provide a way to handle
errors in a global way.

Until then, you can use a `PipeSystem` to manually handle results.

---------

Signed-off-by: Jean Mertz <git@jeanmertz.com>
2025-02-11 22:15:43 +00:00
SpecificProtagonist
5b0d898866
Trait tags on docs.rs (#17758)
# Objective

Bevy's ECS provides several core traits such as `Component`,
`SystemParam`, etc that determine where a type can be used. When reading
the docs, this currently requires scrolling down to and scanning the
"Trait Implementations" section. Make these core traits more visible.

## Solution

Add a color-coded labels below the type heading denoting the following
types:
- `Component`
  - immutable components are labeled as such
- `Resource`
- `Asset`
- `Event`
- `Plugin` & `PluginGroup`
- `ScheduleLabel` & `SystemSet`
- `SystemParam`

As docs.rs does not provide an option for post-processing the html,
these are added via JS with traits implementations being detected by
scanning the DOM. Rustdoc's html output is unstable, which could
potentially lead to this detection (or the adding of the labels) to
break, however it only needs to work when a new release is deployed and
falls back to the status quo of not displaying these labels.

Idea by JMS55, implementation by Jondolf (see
https://github.com/Jondolf/bevy_docs_extension_demo/).

## Testing

Run this in Bevy's root folder:
```bash
 RUSTDOCFLAGS="--html-after-content docs-rs/trait-tags.html --cfg docsrs_dep" RUSTFLAGS="--cfg docsrs_dep" cargo doc --no-deps -p <some_bevy_package>
```

---

## Showcase
Check it out on
[docs.rs](https://docs.rs/bevy_docs_extension_demo/0.1.1/bevy_docs_extension_demo/struct.TestAllTraits.html)

![trait
tags](https://github.com/user-attachments/assets/a30d8324-41fd-432a-8e49-6d475f143725)

## Release Notes

On docs.rs, Bevy now displays labels indicating which core traits a type
implements:
![trait tags
small](https://github.com/user-attachments/assets/c69b565f-e4bc-4277-9f6b-40830031077d)

If you want to add these to your own crate, check out [these
instructions](https://github.com/bevyengine/bevy/blob/main/docs-rs#3rd-party-crates).

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: Carter Weinberg <weinbergcarter@gmail.com>
2025-02-11 22:13:38 +00:00
IceSentry
4ecbe001d5
Add a custom render phase example (#16916)
# Objective

- It's currently very hard for beginners and advanced users to get a
full understanding of a complete render phase.

## Solution

- Implement a full custom render phase
- The render phase in the example is intended to show a custom stencil
phase that renders the stencil in red directly on the screen

---

## Showcase

<img width="1277" alt="image"
src="https://github.com/user-attachments/assets/e9dc0105-4fb6-463f-ad53-0529b575fd28"
/>

## Notes

More docs to explain what is going on is still needed but the example
works and can already help some people.

We might want to consider using a batched phase and cold specialization
in the future, but the example is already complex enough as it is.

---------

Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
2025-02-10 21:17:37 +00:00
Mike
8e84b461a0
many_components stress test improvements (#16913)
# Objective

- I was getting familiar with the many_components example to test some
recent pr's for executor changes and saw some things to improve.

## Solution

- Use `insert_by_ids` instead of `insert_by_id`. This reduces the number
of archetype moves and improves startup times substantially.
- Add a tracing span to `base_system`. I'm not sure why, but tracing
spans weren't showing for this system. I think it's something to do with
how pipe system works, but need to investigate more. The approach in
this pr is a little better than the default span too, since it allows
adding the number of entities queried to the span which is not possible
with the default system span.
- println the number of archetype component id's that are created. This
is useful since part of the purpose of this stress test is to test how
well the use of FixedBitSet scales in the executor.

## Testing

- Ran the example with `cargo run --example many_components -F
trace_tracy 1000000` and connected with tracy
- Timed the time it took to spawn 1 million entities on main (240 s) vs
this pr (15 s)

---

## Showcase


![image](https://github.com/user-attachments/assets/69da4db0-4ecc-4acb-aebb-2e47d1a35f3b)

## Future Work

- Currently systems are created with a random set of components and
entities are created with a random set of components without any
correlation between the randomness. This means that some systems won't
match any entities and some entities could not match any systems. It
might be better to spawn the entities from the pool of components that
match the queries that the systems are using.
2025-02-10 21:13:57 +00:00
raldone01
1b7db895b7
Harden proc macro path resolution and add integration tests. (#17330)
This pr uses the `extern crate self as` trick to make proc macros behave
the same way inside and outside bevy.

# Objective

- Removes noise introduced by `crate as` in the whole bevy repo.
- Fixes #17004.
- Hardens proc macro path resolution.

## TODO

- [x] `BevyManifest` needs cleanup.
- [x] Cleanup remaining `crate as`.
- [x] Add proper integration tests to the ci.

## Notes

- `cargo-manifest-proc-macros` is written by me and based/inspired by
the old `BevyManifest` implementation and
[`bkchr/proc-macro-crate`](https://github.com/bkchr/proc-macro-crate).
- What do you think about the new integration test machinery I added to
the `ci`?
  More and better integration tests can be added at a later stage.
The goal of these integration tests is to simulate an actual separate
crate that uses bevy. Ideally they would lightly touch all bevy crates.

## Testing

- Needs RA test
- Needs testing from other users
- Others need to run at least `cargo run -p ci integration-test` and
verify that they work.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-09 19:45:45 +00:00
JMS55
669d139c13
Upgrade to wgpu v24 (#17542)
Didn't remove WgpuWrapper. Not sure if it's needed or not still.

## Testing

- Did you test these changes? If so, how? Example runner
- Are there any parts that need more testing? Web (portable atomics
thingy?), DXC.

## Migration Guide
- Bevy has upgraded to [wgpu
v24](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v2400-2025-01-15).
- When using the DirectX 12 rendering backend, the new priority system
for choosing a shader compiler is as follows:
- If the `WGPU_DX12_COMPILER` environment variable is set at runtime, it
is used
- Else if the new `statically-linked-dxc` feature is enabled, a custom
version of DXC will be statically linked into your app at compile time.
- Else Bevy will look in the app's working directory for
`dxcompiler.dll` and `dxil.dll` at runtime.
- Else if they are missing, Bevy will fall back to FXC (not recommended)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IceSentry <c.giguere42@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-02-09 19:40:53 +00:00
Alice Cecile
33e83330eb
Add entity disabling example (#17710)
# Objective

The entity disabling / default query filter work added in #17514 and
#13120 is neat, but we don't teach users how it works!

We should fix that before 0.16.

## Solution

Write a simple example to teach the basics of entity disabling!

## Testing

`cargo run --example entity_disabling`

## Showcase


![image](https://github.com/user-attachments/assets/9edcc5e1-2bdf-40c5-89b7-5b61c817977a)

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2025-02-09 19:16:48 +00:00
Lucas Franca
9ea9c5df00
Add edit_material_on_gltf example (#17677)
# Objective

Create a minimal example of how to modify the material from a `Gltf`.
This is frequently asked about on the help channel of the discord.

## Solution

Create the example.

## Showcase


![image](https://github.com/user-attachments/assets/efeab96d-056d-4597-953b-80ee5162749c)
2025-02-05 22:45:20 +00:00
NiseVoid
203d0b4aae
Move bounding_2d example to math folder (#17523)
# Objective

The bounding_2d example was originally placed in 2d_rendering because
there was no folder for bounding or math, but now that this folder exist
it makes no sense for it to be here.

## Solution

Move the example

## Testing

I ran the example
2025-01-28 05:29:05 +00:00
Patrick Walton
dda97880c4
Implement experimental GPU two-phase occlusion culling for the standard 3D mesh pipeline. (#17413)
*Occlusion culling* allows the GPU to skip the vertex and fragment
shading overhead for objects that can be quickly proved to be invisible
because they're behind other geometry. A depth prepass already
eliminates most fragment shading overhead for occluded objects, but the
vertex shading overhead, as well as the cost of testing and rejecting
fragments against the Z-buffer, is presently unavoidable for standard
meshes. We currently perform occlusion culling only for meshlets. But
other meshes, such as skinned meshes, can benefit from occlusion culling
too in order to avoid the transform and skinning overhead for unseen
meshes.

This commit adapts the same [*two-phase occlusion culling*] technique
that meshlets use to Bevy's standard 3D mesh pipeline when the new
`OcclusionCulling` component, as well as the `DepthPrepass` component,
are present on the camera. It has these steps:

1. *Early depth prepass*: We use the hierarchical Z-buffer from the
previous frame to cull meshes for the initial depth prepass, effectively
rendering only the meshes that were visible in the last frame.

2. *Early depth downsample*: We downsample the depth buffer to create
another hierarchical Z-buffer, this time with the current view
transform.

3. *Late depth prepass*: We use the new hierarchical Z-buffer to test
all meshes that weren't rendered in the early depth prepass. Any meshes
that pass this check are rendered.

4. *Late depth downsample*: Again, we downsample the depth buffer to
create a hierarchical Z-buffer in preparation for the early depth
prepass of the next frame. This step is done after all the rendering, in
order to account for custom phase items that might write to the depth
buffer.

Note that this patch has no effect on the per-mesh CPU overhead for
occluded objects, which remains high for a GPU-driven renderer due to
the lack of `cold-specialization` and retained bins. If
`cold-specialization` and retained bins weren't on the horizon, then a
more traditional approach like potentially visible sets (PVS) or low-res
CPU rendering would probably be more efficient than the GPU-driven
approach that this patch implements for most scenes. However, at this
point the amount of effort required to implement a PVS baking tool or a
low-res CPU renderer would probably be greater than landing
`cold-specialization` and retained bins, and the GPU driven approach is
the more modern one anyway. It does mean that the performance
improvements from occlusion culling as implemented in this patch *today*
are likely to be limited, because of the high CPU overhead for occluded
meshes.

Note also that this patch currently doesn't implement occlusion culling
for 2D objects or shadow maps. Those can be addressed in a follow-up.
Additionally, note that the techniques in this patch require compute
shaders, which excludes support for WebGL 2.

This PR is marked experimental because of known precision issues with
the downsampling approach when applied to non-power-of-two framebuffer
sizes (i.e. most of them). These precision issues can, in rare cases,
cause objects to be judged occluded that in fact are not. (I've never
seen this in practice, but I know it's possible; it tends to be likelier
to happen with small meshes.) As a follow-up to this patch, we desire to
switch to the [SPD-based hi-Z buffer shader from the Granite engine],
which doesn't suffer from these problems, at which point we should be
able to graduate this feature from experimental status. I opted not to
include that rewrite in this patch for two reasons: (1) @JMS55 is
planning on doing the rewrite to coincide with the new availability of
image atomic operations in Naga; (2) to reduce the scope of this patch.

A new example, `occlusion_culling`, has been added. It demonstrates
objects becoming quickly occluded and disoccluded by dynamic geometry
and shows the number of objects that are actually being rendered. Also,
a new `--occlusion-culling` switch has been added to `scene_viewer`, in
order to make it easy to test this patch with large scenes like Bistro.

[*two-phase occlusion culling*]:
https://medium.com/@mil_kru/two-pass-occlusion-culling-4100edcad501

[Aaltonen SIGGRAPH 2015]:

https://www.advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf

[Some literature]:

https://gist.github.com/reduz/c5769d0e705d8ab7ac187d63be0099b5?permalink_comment_id=5040452#gistcomment-5040452

[SPD-based hi-Z buffer shader from the Granite engine]:
https://github.com/Themaister/Granite/blob/master/assets/shaders/post/hiz.comp

## Migration guide

* When enqueuing a custom mesh pipeline, work item buffers are now
created with
`bevy::render::batching::gpu_preprocessing::get_or_create_work_item_buffer`,
not `PreprocessWorkItemBuffers::new`. See the
`specialized_mesh_pipeline` example.

## Showcase

Occlusion culling example:
![Screenshot 2025-01-15
175051](https://github.com/user-attachments/assets/1544f301-68a3-45f8-84a6-7af3ad431258)

Bistro zoomed out, before occlusion culling:
![Screenshot 2025-01-16
185425](https://github.com/user-attachments/assets/5114bbdf-5dec-4de9-b17e-7aa77e7b61ed)

Bistro zoomed out, after occlusion culling:
![Screenshot 2025-01-16
184949](https://github.com/user-attachments/assets/9dd67713-656c-4276-9768-6d261ca94300)

In this scene, occlusion culling reduces the number of meshes Bevy has
to render from 1591 to 585.
2025-01-27 05:02:46 +00:00
Patrick Walton
1c765c9ae7
Add support for specular tints and maps per the KHR_materials_specular glTF extension. (#14069)
This commit allows specular highlights to be tinted with a color and for
the reflectance and color tint values to vary across a model via a pair
of maps. The implementation follows the [`KHR_materials_specular`] glTF
extension. In order to reduce the number of samplers and textures in the
default `StandardMaterial` configuration, the maps are gated behind the
`pbr_specular_textures` Cargo feature.

Specular tinting is currently unsupported in the deferred renderer,
because I didn't want to bloat the deferred G-buffers. A possible fix
for this in the future would be to make the G-buffer layout more
configurable, so that specular tints could be supported on an opt-in
basis. As an alternative, Bevy could force meshes with specular tints to
render in forward mode. Both of these solutions require some more
design, so I consider them out of scope for now.

Note that the map is a *specular* map, not a *reflectance* map. In Bevy
and Filament terms, the reflectance values in the specular map range
from [0.0, 0.5], rather than [0.0, 1.0]. This is an unfortunate
[`KHR_materials_specular`] specification requirement that stems from the
fact that glTF is specified in terms of a specular strength model, not
the reflectance model that Filament and Bevy use. A workaround, which is
noted in the `StandardMaterial` documentation, is to set the
`reflectance` value to 2.0, which spreads the specular map range from
[0.0, 1.0] as normal.

The glTF loader has been updated to parse the [`KHR_materials_specular`]
extension. Note that, unless the non-default `pbr_specular_textures` is
supplied, the maps are ignored. The `specularFactor` value is applied as
usual. Note that, as with the specular map, the glTF `specularFactor` is
twice Bevy's `reflectance` value.

This PR adds a new example, `specular_tint`, which demonstrates the
specular tint and map features. Note that this example requires the
[`KHR_materials_specular`] Cargo feature.

[`KHR_materials_specular`]:
https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_specular

## Changelog

### Added

* Specular highlights can now be tinted with the `specular_tint` field
in `StandardMaterial`.
* Specular maps are now available in `StandardMaterial`, gated behind
the `pbr_specular_textures` Cargo feature.
* The `KHR_materials_specular` glTF extension is now supported, allowing
for customization of specular reflectance and specular maps. Note that
the latter are gated behind the `pbr_specular_textures` Cargo feature.
2025-01-26 20:38:46 +00:00
Patrick Walton
fc831c390d
Implement basic clustered decal projectors. (#17315)
This commit adds support for *decal projectors* to Bevy, allowing for
textures to be projected on top of geometry. Decal projectors are
clusterable objects, just as punctual lights and light probes are. This
means that decals are only evaluated for objects within the conservative
bounds of the projector, and they don't require a second pass.

These clustered decals require support for bindless textures and as such
currently don't work on WebGL 2, WebGPU, macOS, or iOS. For an
alternative that doesn't require bindless, see PR #16600. I believe that
both contact projective decals in #16600 and clustered decals are
desirable to have in Bevy. Contact projective decals offer broader
hardware and driver support, while clustered decals don't require the
creation of bounding geometry.

A new example, `decal_projectors`, has been added, which demonstrates
multiple decals on a rotating object. The decal projectors can be scaled
and rotated with the mouse.

There are several limitations of this initial patch that can be
addressed in follow-ups:

1. There's no way to specify the Z-index of decals. That is, the order
in which multiple decals are blended on top of one another is arbitrary.
A follow-up could introduce some sort of Z-index field so that artists
can specify that some decals should be blended on top of others.

2. Decals don't take the normal of the surface they're projected onto
into account. Most decal implementations in other engines have a feature
whereby the angle between the decal projector and the normal of the
surface must be within some threshold for the decal to appear. Often,
artists can specify a fade-off range for a smooth transition between
oblique surfaces and aligned surfaces.

3. There's no distance-based fadeoff toward the end of the projector
range. Many decal implementations have this.

This addresses #2401.
 
## Showcase

![Screenshot 2025-01-11
052913](https://github.com/user-attachments/assets/8fabbafc-60fb-461d-b715-d7977e10fe1f)
2025-01-26 20:13:39 +00:00
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
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
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
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
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
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
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
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
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
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
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
github-actions[bot]
573b980685
Bump Version after Release (#17176)
Bump version after release
This PR has been auto-generated

---------

Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-06 00:04:44 +00:00
Rob Parrett
818c57821d
Allow users to easily use bevy_sprite and bevy_ui without picking (#17175)
# Objective

RIght now it's not possible to opt out of sprite or ui picking at the
feature level without jumping through some hoops.

If you add the `bevy_sprite` feature, you get
`bevy_sprite_picking_backend`.

If you add the `bevy_ui` feature, you get `bevy_ui_picking_backend`

To get `bevy_sprite` without picking, I think you would have to do
something like this, which seems **very** annoying.

```toml
[dependencies]
bevy = { version = "0.15", default-features = false, features = [
    # ... omitted
    # "bevy_sprite",
    # "bevy_ui", # this also brings in bevy_sprite
    # "bevy_text", # this also brings in bevy_sprite
    "bevy_render",
    "bevy_core_pipeline",
    "bevy_color",
] }
bevy_internal = { version = "0.15", default-features = false, features = [
    "bevy_sprite",
    "bevy_ui",
    "bevy_text"
] }
```

## Solution

- Remove `bevy_sprite_picking_backend` from the `bevy_sprite` feature.
- Remove `bevy_ui_picking_backend` from the `bevy_ui` feature.

These are still in Bevy's `default-plugins`.

## Testing

I did some basic testing in a minimal project based on the
`sprite_picking` example to verify that "picking stuff" didn't get
included with `bevy_sprite`.

I would appreciate help testing. I am just unraveling these features and
think that this is correct, but I am not 100% sure.

## Migration Guide

`bevy_sprite_picking_backend` is no longer included by default when
using the `bevy_sprite` feature. If you are using Bevy without default
features and relied on sprite picking, add this feature to your
`Cargo.toml`.

`bevy_ui_picking_backend` is no longer included by default when using
the `bevy_ui` feature. If you are using Bevy without default features
and relied on sprite picking, add this feature to your `Cargo.toml`.

## Additional info

It looks like we attempted to fix this earlier in #16469, but the fix
was incomplete?
2025-01-05 19:40:07 +00:00
JMS55
fe58993577
METIS-based meshlet generation (#16947)
# Objective
Improve DAG building for virtual geometry

## Solution

- Use METIS to group triangles into meshlets which lets us minimize
locked vertices which improves simplification, instead of using meshopt
which prioritizes culling efficiency. Also some other minor tweaks.
- Currently most meshlets have 126 triangles, and not 128. Fixing this
might involve calling METIS recursively ourselves to manually bisect the
graph, not sure. Not going to attempt to fix this in this PR.

## Testing

- Did you test these changes? If so, how?
  - Tested on bunny.glb and cliff.glb
- Are there any parts that need more testing?
  - No
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Download the new bunny asset, run the meshlet example.

---

## Showcase

New 

![image](https://github.com/user-attachments/assets/68f5d2f0-a4ca-41e1-90d5-35a2c6969c21)

Old

![image](https://github.com/user-attachments/assets/a3d97a09-773d-44b2-9990-25e1f6b51ec9)

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2025-01-05 02:03:26 +00:00
Aevyrie
bed9ddf3ce
Refactor and simplify custom projections (#17063)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/16556
- Closes https://github.com/bevyengine/bevy/issues/11807

## Solution

- Simplify custom projections by using a single source of truth -
`Projection`, removing all existing generic systems and types.
- Existing perspective and orthographic structs are no longer components
- I could dissolve these to simplify further, but keeping them around
was the fast way to implement this.
- Instead of generics, introduce a third variant, with a trait object.
- Do an object safety dance with an intermediate trait to allow cloning
boxed camera projections. This is a normal rust polymorphism papercut.
You can do this with a crate but a manual impl is short and sweet.

## Testing

- Added a custom projection example

---

## Showcase

- Custom projections and projection handling has been simplified.
- Projection systems are no longer generic, with the potential for many
different projection components on the same camera.
- Instead `Projection` is now the single source of truth for camera
projections, and is the only projection component.
- Custom projections are still supported, and can be constructed with
`Projection::custom()`.

## Migration Guide

- `PerspectiveProjection` and `OrthographicProjection` are no longer
components. Use `Projection` instead.
- Custom projections should no longer be inserted as a component.
Instead, simply set the custom projection as a value of `Projection`
with `Projection::custom()`.
2025-01-01 20:44:24 +00:00
Sean Kim
294e0db719
Rename track_change_detection flag to track_location (#17075)
# Objective

- As stated in the related issue, this PR is to better align the feature
flag name with what it actually does and the plans for the future.
- Fixes #16852 

## Solution

- Simple find / replace

## Testing

- Local run of `cargo run -p ci`

## Migration Guide

The `track_change_detection` feature flag has been renamed to
`track_location` to better reflect its extended capabilities.
2025-01-01 18:43:47 +00:00
Rob Parrett
ad9f946201
Add many_text2d stress test (#16997)
# Objective

Make it easier to test for `Text2d` performance regressions.

Related to #16972

## Solution

Add a new `stress_test`, based on `many_sprites` and other existing
stress tests.

The `many-glyphs` option is inspired by
https://github.com/bevyengine/bevy/issues/16901#issuecomment-2558572382.

## Testing

```bash
cargo run --release --example many_text2d -- --help
cargo run --release --example many_text2d
cargo run --release --example many_text2d -- --many_glyphs
```

etc
2024-12-29 22:47:01 +00:00
François Mockers
99c869d58d
bevy_winit feature should enable bevy_window (#16949)
# Objective

- Fixes #16568 

## Solution

- `bevy_winit` feature also enables `bevy_window`
2024-12-24 03:12:05 +00:00
François Mockers
6577f5d26a
Expose bevy_image as a feature (#16948)
# Objective

- Fixes #16563 
- Make sure bevy_image is available when needed

## Solution

- Add a new feature for `bevy_image`
- Also enable the `bevy_image` feature in `bevy_internal` for all
features that use `bevy_image` themselves
2024-12-24 03:11:01 +00:00
BD103
20277006ce
Add benchmarks and compile_fail tests back to workspace (#16858)
# Objective

- Our benchmarks and `compile_fail` tests lag behind the rest of the
engine because they are not in the Cargo workspace, so not checked by
CI.
- Fixes #16801, please see it for further context!

## Solution

- Add benchmarks and `compile_fail` tests to the Cargo workspace.
- Fix any leftover formatting issues and documentation.

## Testing

- I think CI should catch most things!

## Questions

<details>
<summary>Outdated issue I was having with function reflection being
optional</summary>

The `reflection_types` example is failing in Rust-Analyzer for me, but
not a normal check.

```rust
error[E0004]: non-exhaustive patterns: `ReflectRef::Function(_)` not covered
   --> examples/reflection/reflection_types.rs:81:11
    |
81  |     match value.reflect_ref() {
    |           ^^^^^^^^^^^^^^^^^^^ pattern `ReflectRef::Function(_)` not covered
    |
note: `ReflectRef<'_>` defined here
   --> /Users/bdeep/dev/bevy/bevy/crates/bevy_reflect/src/kind.rs:178:1
    |
178 | pub enum ReflectRef<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^
...
188 |     Function(&'a dyn Function),
    |     -------- not covered
    = note: the matched value is of type `ReflectRef<'_>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
126 ~         ReflectRef::Opaque(_) => {},
127 +         ReflectRef::Function(_) => todo!()
    |
```

I think it is because the following line is feature-gated:


cc0f6a8db4/examples/reflection/reflection_types.rs (L117-L122)

My theory for why this is happening is because the benchmarks enabled
`bevy_reflect`'s `function` feature, which gets merged with the rest of
the features when RA checks the workspace, but the `#[cfg(...)]` gate in
the example isn't detecting it:


cc0f6a8db4/benches/Cargo.toml (L19)

Any thoughts on how to fix this? It's not blocking, since the example
still compiles as normal, but it's just RA and the command `cargo check
--workspace --all-targets` appears to fail.

</summary>
2024-12-21 22:30:29 +00:00
Aevyrie
753d46fd95
Enable motion blur on WASM (#16893)
This feature was tested with WASM, WebGL, and WebGPU. It should work on
these targets. I think this was an oversight in the original PR.
2024-12-19 00:25:11 +00:00
SpecificProtagonist
21195a75e6
track_change_detection: Also track spawns/despawns (#16047)
# Objective

Expand `track_change_detection` feature to also track entity spawns and
despawns. Use this to create better error messages.

# Solution

Adds `Entities::entity_get_spawned_or_despawned_by` as well as `{all
entity reference types}::spawned_by`.

This also removes the deprecated `get_many_entities_mut` & co (and
therefore can't land in 0.15) because we don't yet have no Polonius.

## Testing

Added a test that checks that the locations get updated and these
updates are ordered correctly vs hooks & observers.

---

## Showcase

Access location:
```rust
let mut world = World::new();
let entity = world.spawn_empty().id();
println!("spawned by: {}", world.entity(entity).spawned_by());
```
```
spawned by: src/main.rs:5:24
```
Error message (with `track_change_detection`):
```rust
world.despawn(entity);
world.entity(entity);
```
```
thread 'main' panicked at src/main.rs:11:11:
Entity 0v1#4294967296 was despawned by src/main.rs:10:11
```
and without:
```
thread 'main' panicked at src/main.rs:11:11:
Entity 0v1#4294967296 does not exist (enable `track_change_detection` feature for more details)
```
Similar error messages now also exists for `Query::get`,
`World::entity_mut`, `EntityCommands` creation and everything that
causes `B0003`, e.g.
```
error[B0003]: Could not insert a bundle (of type `MaterialMeshBundle<StandardMaterial>`) for entity Entity { index: 7, generation: 1 }, which was despawned by src/main.rs:10:11. See: https://bevyengine.org/learn/errors/#b0003
```

---------

Co-authored-by: kurk070ff <108901106+kurk070ff@users.noreply.github.com>
Co-authored-by: Freya Pines <freya@MacBookAir.lan>
Co-authored-by: Freya Pines <freya@Freyas-MacBook-Air.local>
Co-authored-by: Matty Weatherley <weatherleymatthew@gmail.com>
2024-12-17 04:46:31 +00:00
Talin
5c67cfc8b7
Tab navigation framework for bevy_input_focus. (#16795)
# Objective

This PR continues the work of `bevy_input_focus` by adding a pluggable
tab navigation framework.

As part of this work, `FocusKeyboardEvent` now propagates to the window
after exhausting all ancestors.

## Testing

Unit tests and manual tests.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-12-16 23:54:53 +00:00
Patrick Walton
bf3692a011
Introduce support for mixed lighting by allowing lights to opt out of contributing diffuse light to lightmapped objects. (#16761)
This PR adds support for *mixed lighting* to Bevy, whereby some parts of
the scene are lightmapped, while others take part in real-time lighting.
(Here *real-time lighting* means lighting at runtime via the PBR shader,
as opposed to precomputed light using lightmaps.) It does so by adding a
new field, `affects_lightmapped_meshes` to `IrradianceVolume` and
`AmbientLight`, and a corresponding field
`affects_lightmapped_mesh_diffuse` to `DirectionalLight`, `PointLight`,
`SpotLight`, and `EnvironmentMapLight`. By default, this value is set to
true; when set to false, the light contributes nothing to the diffuse
irradiance component to meshes with lightmaps.

Note that specular light is unaffected. This is because the correct way
to bake specular lighting is *directional lightmaps*, which we have no
support for yet.

There are two general ways I expect this field to be used:

1. When diffuse indirect light is baked into lightmaps, irradiance
volumes and reflection probes shouldn't contribute any diffuse light to
the static geometry that has a lightmap. That's because the baking tool
should have already accounted for it, and in a higher-quality fashion,
as lightmaps typically offer a higher effective texture resolution than
the light probe does.

2. When direct diffuse light is baked into a lightmap, punctual lights
shouldn't contribute any diffuse light to static geometry with a
lightmap, to avoid double-counting. It may seem odd to bake *direct*
light into a lightmap, as opposed to indirect light. But there is a use
case: in a scene with many lights, avoiding light leaks requires shadow
mapping, which quickly becomes prohibitive when many lights are
involved. Baking lightmaps allows light leaks to be eliminated on static
geometry.

A new example, `mixed_lighting`, has been added. It demonstrates a sofa
(model from the [glTF Sample Assets]) that has been lightmapped offline
using [Bakery]. It has four modes:

1. In *baked* mode, all objects are locked in place, and all the diffuse
direct and indirect light has been calculated ahead of time. Note that
the bottom of the sphere has a red tint from the sofa, illustrating that
the baking tool captured indirect light for it.

2. In *mixed direct* mode, lightmaps capturing diffuse direct and
indirect light have been pre-calculated for the static objects, but the
dynamic sphere has real-time lighting. Note that, because the diffuse
lighting has been entirely pre-calculated for the scenery, the dynamic
sphere casts no shadow. In a real app, you would typically use real-time
lighting for the most important light so that dynamic objects can shadow
the scenery and relegate baked lighting to the less important lights for
which shadows aren't as important. Also note that there is no red tint
on the sphere, because there is no global illumination applied to it. In
an actual game, you could fix this problem by supplementing the
lightmapped objects with an irradiance volume.

3. In *mixed indirect* mode, all direct light is calculated in
real-time, and the static objects have pre-calculated indirect lighting.
This corresponds to the mode that most applications are expected to use.
Because direct light on the scenery is computed dynamically, shadows are
fully supported. As in mixed direct mode, there is no global
illumination on the sphere; in a real application, irradiance volumes
could be used to supplement the lightmaps.

4. In *real-time* mode, no lightmaps are used at all, and all punctual
lights are rendered in real-time. No global illumination exists.

In the example, you can click around to move the sphere, unless you're
in baked mode, in which case the sphere must be locked in place to be
lit correctly.

## Showcase

Baked mode:
![Screenshot 2024-12-13
112926](https://github.com/user-attachments/assets/cc00d84e-abd7-4117-97e9-17267d815c6a)

Mixed direct mode:
![Screenshot 2024-12-13
112933](https://github.com/user-attachments/assets/49997305-349a-4f6a-b451-8cccbb469889)

Mixed indirect mode (default):
![Screenshot 2024-12-13
112939](https://github.com/user-attachments/assets/0f4f6d8a-998f-474b-9fa5-fe4c212c921c)

Real-time mode:
![Screenshot 2024-12-13
112944](https://github.com/user-attachments/assets/fdbc4535-d902-4ba0-bfbc-f5c7b723fac8)

## Migration guide

* The `AmbientLight` resource, the `IrradianceVolume` component, and the
`EnvironmentMapLight` component now have `affects_lightmapped_meshes`
fields. If you don't need to use that field (for example, if you aren't
using lightmaps), you can safely set the field to true.
* `DirectionalLight`, `PointLight`, and `SpotLight` now have
`affects_lightmapped_mesh_diffuse` fields. If you don't need to use that
field (for example, if you aren't using lightmaps), you can safely set
the field to true.

[glTF Sample Assets]:
https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main

[Bakery]:
https://geom.io/bakery/wiki/index.php?title=Bakery_-_GPU_Lightmapper
2024-12-16 23:48:33 +00:00
Rich Churcher
f2719f5470
Rust 1.83, allow -> expect (missing_docs) (#16561)
# Objective

We were waiting for 1.83 to address most of these, due to a bug with
`missing_docs` and `expect`. Relates to, but does not entirely complete,
#15059.

## Solution

- Upgrade to 1.83
- Switch `allow(missing_docs)` to `expect(missing_docs)`
- Remove a few now-unused `allow`s along the way, or convert to `expect`
2024-12-16 23:27:57 +00:00
ickshonpe
9098973fb9
Draw the UI debug overlay using the UI renderer (#16693)
# Objective

Draw the UI debug overlay using the UI renderer.

Significantly simpler and easier to use than
`bevy_dev_tools::ui_debug_overlay` which uses `bevy_gizmos`.
* Supports multiple windows and UI rendered to texture.
* Draws rounded debug rects for rounded UI nodes. 

Fixes #16666

## Solution

Removed the `ui_debug_overlay` module from `bevy_dev_tools`.

Added a `bevy_ui_debug` feature gate.

Draw the UI debug overlay using the UI renderer.
Adds a new module `bevy_ui::render::debug_overlay`. 

The debug overlay extraction function queries for the existing UI layout
and then adds a border around each UI node with `u32::MAX / 2` added to
each stack index so it's drawn on top.

There is a `UiDebugOptions` resource that can be used to enable or
disable the debug overlay and set the line width.

## Testing

The `testbed_ui` example has been changed to use the new debug overlay:

```
cargo run --example testbed_ui --features bevy_ui_debug
```

Press Space to toggle the debug overlay on and off.

---

## Showcase

<img width="961" alt="testbed-ui-new-debug"
src="https://github.com/user-attachments/assets/e9523d18-39ae-46a8-adbe-7d3f3ab8e951">

## Migration Guide

The `ui_debug_overlay` module has been removed from `bevy_dev_tools`.
There is a new debug overlay implemented using the `bevy_ui` renderer.
To use it, enable the `bevy_ui_debug` feature and set the `enable` field
of the `UiDebugOptions` resource to `true`.
2024-12-11 00:49:47 +00:00
Trashtalk217
1f884de53c
Added stress test for large ecs worlds (#16591)
# Objective

We currently have no benchmarks for large worlds with many entities,
components and systems.
Having a benchmark for a world with many components is especially useful
for the performance improvements needed for relations. This is also a
response to this [comment from
cart](https://github.com/bevyengine/bevy/pull/14385#issuecomment-2311292546).

> I'd like both a small bevy_ecs-scoped executor benchmark that
generates thousands of components used by hundreds of systems.

## Solution

I use dynamic components and components to construct a benchmark with
2000 components, 4000 systems, and 10000 entities.

## Some notes

- ~I use a lot of random entities, which creates unpredictable
performance, I should use a seeded PRNG.~
- Not entirely sure if everything is ran concurrently currently. And
there are many conflicts, meaning there's probably a lot of
first-come-first-serve going on. Not entirely sure if these benchmarks
are very reproducible.
- Maybe add some more safety comments
- Also component_reads_and_writes() is about to be deprecated #16339,
but there's no other way to currently do what I'm trying to do.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
2024-12-10 02:26:42 +00:00
dependabot[bot]
61391c5e93
Update thiserror requirement from 1.0 to 2.0 (#16346)
Updates the requirements on
[thiserror](https://github.com/dtolnay/thiserror) to permit the latest
version.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dtolnay/thiserror/releases">thiserror's
releases</a>.</em></p>
<blockquote>
<h2>2.0.3</h2>
<ul>
<li>Support the same Path field being repeated in both Debug and Display
representation in error message (<a
href="https://redirect.github.com/dtolnay/thiserror/issues/383">#383</a>)</li>
<li>Improve error message when a format trait used in error message is
not implemented by some field (<a
href="https://redirect.github.com/dtolnay/thiserror/issues/384">#384</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="15fd26e476"><code>15fd26e</code></a>
Release 2.0.3</li>
<li><a
href="7046023130"><code>7046023</code></a>
Simplify how has_bonus_display is accumulated</li>
<li><a
href="9cc1d0b251"><code>9cc1d0b</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/thiserror/issues/384">#384</a>
from dtolnay/nowrap</li>
<li><a
href="1d040f358a"><code>1d040f3</code></a>
Use Var wrapper only for Pointer formatting</li>
<li><a
href="6a6132d79b"><code>6a6132d</code></a>
Extend no-display ui test to cover another fmt trait</li>
<li><a
href="a061beb9dc"><code>a061beb</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/thiserror/issues/383">#383</a>
from dtolnay/both</li>
<li><a
href="63882935be"><code>6388293</code></a>
Support Display and Debug of same path in error message</li>
<li><a
href="dc0359eeec"><code>dc0359e</code></a>
Defer binding_value construction</li>
<li><a
href="520343e37d"><code>520343e</code></a>
Add test of Debug and Display of paths</li>
<li><a
href="49be39dee1"><code>49be39d</code></a>
Release 2.0.2</li>
<li>Additional commits viewable in <a
href="https://github.com/dtolnay/thiserror/compare/1.0.0...2.0.3">compare
view</a></li>
</ul>
</details>
<br />


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>
2024-12-10 02:12:02 +00:00
Miles Silberling-Cook
0070514f54
Fallible systems (#16589)
# Objective

Error handling in bevy is hard. See for reference
https://github.com/bevyengine/bevy/issues/11562,
https://github.com/bevyengine/bevy/issues/10874 and
https://github.com/bevyengine/bevy/issues/12660. The goal of this PR is
to make it better, by allowing users to optionally return `Result` from
systems as outlined by Cart in
<https://github.com/bevyengine/bevy/issues/14275#issuecomment-2223708314>.

## Solution

This PR introduces a new `ScheuleSystem` type to represent systems that
can be added to schedules. Instances of this type contain either an
infallible `BoxedSystem<(), ()>` or a fallible `BoxedSystem<(),
Result>`. `ScheuleSystem` implements `System<In = (), Out = Result>` and
replaces all uses of `BoxedSystem` in schedules. The async executor now
receives a result after executing a system, which for infallible systems
is always `Ok(())`. Currently it ignores this result, but more useful
error handling could also be implemented.

Aliases for `Error` and `Result` have been added to the `bevy_ecs`
prelude, as well as const `OK` which new users may find more friendly
than `Ok(())`.

## Testing

- Currently there are not actual semantics changes that really require
new tests, but I added a basic one just to make sure we don't break
stuff in the future.
- The behavior of existing systems is totally unchanged, including
logging.
- All of the existing systems tests pass, and I have not noticed
anything strange while playing with the examples

## Showcase

The following minimal example prints "hello world" once, then completes.

```rust
use bevy::prelude::*;

fn main() {
    App::new().add_systems(Update, hello_world_system).run();
}

fn hello_world_system() -> Result {
    println!("hello world");
    Err("string")?;
    println!("goodbye world");
    OK
}
```

## Migration Guide

This change should be pretty much non-breaking, except for users who
have implemented their own custom executors. Those users should use
`ScheduleSystem` in place of `BoxedSystem<(), ()>` and import the
`System` trait where needed. They can choose to do whatever they wish
with the result.

## Current Work

+ [x] Fix tests & doc comments
+ [x] Write more tests
+ [x] Add examples
+ [X] Draft release notes

## Draft Release Notes

As of this release, systems can now return results.

First a bit of background: Bevy has hisotrically expected systems to
return the empty type `()`. While this makes sense in the context of the
ecs, it's at odds with how error handling is typically done in rust:
returning `Result::Error` to indicate failure, and using the
short-circuiting `?` operator to propagate that error up the call stack
to where it can be properly handled. Users of functional languages will
tell you this is called "monadic error handling".

Not being able to return `Results` from systems left bevy users with a
quandry. They could add custom error handling logic to every system, or
manually pipe every system into an error handler, or perhaps sidestep
the issue with some combination of fallible assignents, logging, macros,
and early returns. Often, users would just litter their systems with
unwraps and possible panics.

While any one of these approaches might be fine for a particular user,
each of them has their own drawbacks, and none makes good use of the
language. Serious issues could also arrise when two different crates
used by the same project made different choices about error handling.

Now, by returning results, systems can defer error handling to the
application itself. It looks like this:

```rust
// Previous, handling internally
app.add_systems(my_system)
fn my_system(window: Query<&Window>) {
   let Ok(window) = query.get_single() else {
       return;
   };
   // ... do something to the window here
}

// Previous, handling externally
app.add_systems(my_system.pipe(my_error_handler))
fn my_system(window: Query<&Window>) -> Result<(), impl Error> {
   let window = query.get_single()?;
   // ... do something to the window here
   Ok(())
}

// Previous, panicking
app.add_systems(my_system)
fn my_system(window: Query<&Window>) {
   let window = query.single();
   // ... do something to the window here
}

// Now 
app.add_systems(my_system)
fn my_system(window: Query<&Window>) -> Result {
    let window = query.get_single()?;
    // ... do something to the window here
    Ok(())
}
```

There are currently some limitations. Systems must either return `()` or
`Result<(), Box<dyn Error + Send + Sync + 'static>>`, with no
in-between. Results are also ignored by default, and though implementing
a custom handler is possible, it involves writing your own custom ecs
executor (which is *not* recomended).

Systems should return errors when they cannot perform their normal
behavior. In turn, errors returned to the executor while running the
schedule will (eventually) be treated as unexpected. Users and library
authors should prefer to return errors for anything that disrupts the
normal expected behavior of a system, and should only handle expected
cases internally.

We have big plans for improving error handling further:
+ Allowing users to change the error handling logic of the default
executors.
+ Adding source tracking and optional backtraces to errors.
+ Possibly adding tracing-levels (Error/Warn/Info/Debug/Trace) to
errors.
+ Generally making the default error logging more helpful and
inteligent.
+ Adding monadic system combininators for fallible systems.
+ Possibly removing all panicking variants from our api.

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-12-05 22:29:06 +00:00
Christian Hughes
f87b9fe20c
Turn apply_deferred into a ZST System (#16642)
# Objective

- Required by #16622 due to differing implementations of `System` by
`FunctionSystem` and `ExclusiveFunctionSystem`.
- Optimize the memory usage of instances of `apply_deferred` in system
schedules.

## Solution

By changing `apply_deferred` from being an ordinary system that ends up
as an `ExclusiveFunctionSystem`, and instead into a ZST struct that
implements `System` manually, we save ~320 bytes per instance of
`apply_deferred` in any schedule.

## Testing

- All current tests pass.

---

## Migration Guide

- If you were previously calling the special `apply_deferred` system via
`apply_deferred(world)`, don't.
2024-12-05 18:14:05 +00:00
Zachary Harrold
a35811d088
Add Immutable Component Support (#16372)
# Objective

- Fixes #16208

## Solution

- Added an associated type to `Component`, `Mutability`, which flags
whether a component is mutable, or immutable. If `Mutability= Mutable`,
the component is mutable. If `Mutability= Immutable`, the component is
immutable.
- Updated `derive_component` to default to mutable unless an
`#[component(immutable)]` attribute is added.
- Updated `ReflectComponent` to check if a component is mutable and, if
not, panic when attempting to mutate.

## Testing

- CI
- `immutable_components` example.

---

## Showcase

Users can now mark a component as `#[component(immutable)]` to prevent
safe mutation of a component while it is attached to an entity:

```rust
#[derive(Component)]
#[component(immutable)]
struct Foo {
    // ...
}
```

This prevents creating an exclusive reference to the component while it
is attached to an entity. This is particularly powerful when combined
with component hooks, as you can now fully track a component's value,
ensuring whatever invariants you desire are upheld. Before this would be
done my making a component private, and manually creating a `QueryData`
implementation which only permitted read access.

<details>
  <summary>Using immutable components as an index</summary>
  
```rust
/// This is an example of a component like [`Name`](bevy::prelude::Name), but immutable.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Component)]
#[component(
    immutable,
    on_insert = on_insert_name,
    on_replace = on_replace_name,
)]
pub struct Name(pub &'static str);

/// This index allows for O(1) lookups of an [`Entity`] by its [`Name`].
#[derive(Resource, Default)]
struct NameIndex {
    name_to_entity: HashMap<Name, Entity>,
}

impl NameIndex {
    fn get_entity(&self, name: &'static str) -> Option<Entity> {
        self.name_to_entity.get(&Name(name)).copied()
    }
}

fn on_insert_name(mut world: DeferredWorld<'_>, entity: Entity, _component: ComponentId) {
    let Some(&name) = world.entity(entity).get::<Name>() else {
        unreachable!()
    };
    let Some(mut index) = world.get_resource_mut::<NameIndex>() else {
        return;
    };

    index.name_to_entity.insert(name, entity);
}

fn on_replace_name(mut world: DeferredWorld<'_>, entity: Entity, _component: ComponentId) {
    let Some(&name) = world.entity(entity).get::<Name>() else {
        unreachable!()
    };
    let Some(mut index) = world.get_resource_mut::<NameIndex>() else {
        return;
    };

    index.name_to_entity.remove(&name);
}

// Setup our name index
world.init_resource::<NameIndex>();

// Spawn some entities!
let alyssa = world.spawn(Name("Alyssa")).id();
let javier = world.spawn(Name("Javier")).id();

// Check our index
let index = world.resource::<NameIndex>();

assert_eq!(index.get_entity("Alyssa"), Some(alyssa));
assert_eq!(index.get_entity("Javier"), Some(javier));

// Changing the name of an entity is also fully capture by our index
world.entity_mut(javier).insert(Name("Steven"));

// Javier changed their name to Steven
let steven = javier;

// Check our index
let index = world.resource::<NameIndex>();

assert_eq!(index.get_entity("Javier"), None);
assert_eq!(index.get_entity("Steven"), Some(steven));
```
  
</details>

Additionally, users can use `Component<Mutability = ...>` in trait
bounds to enforce that a component _is_ mutable or _is_ immutable. When
using `Component` as a trait bound without specifying `Mutability`, any
component is applicable. However, methods which only work on mutable or
immutable components are unavailable, since the compiler must be
pessimistic about the type.

## Migration Guide

- When implementing `Component` manually, you must now provide a type
for `Mutability`. The type `Mutable` provides equivalent behaviour to
earlier versions of `Component`:
```rust
impl Component for Foo {
    type Mutability = Mutable;
    // ...
}
```
- When working with generic components, you may need to specify that
your generic parameter implements `Component<Mutability = Mutable>`
rather than `Component` if you require mutable access to said component.
- The entity entry API has had to have some changes made to minimise
friction when working with immutable components. Methods which
previously returned a `Mut<T>` will now typically return an
`OccupiedEntry<T>` instead, requiring you to add an `into_mut()` to get
the `Mut<T>` item again.

## Draft Release Notes

Components can now be made immutable while stored within the ECS.

Components are the fundamental unit of data within an ECS, and Bevy
provides a number of ways to work with them that align with Rust's rules
around ownership and borrowing. One part of this is hooks, which allow
for defining custom behavior at key points in a component's lifecycle,
such as addition and removal. However, there is currently no way to
respond to _mutation_ of a component using hooks. The reasons for this
are quite technical, but to summarize, their addition poses a
significant challenge to Bevy's core promises around performance.
Without mutation hooks, it's relatively trivial to modify a component in
such a way that breaks invariants it intends to uphold. For example, you
can use `core::mem::swap` to swap the components of two entities,
bypassing the insertion and removal hooks.

This means the only way to react to this modification is via change
detection in a system, which then begs the question of what happens
_between_ that alteration and the next run of that system?
Alternatively, you could make your component private to prevent
mutation, but now you need to provide commands and a custom `QueryData`
implementation to allow users to interact with your component at all.

Immutable components solve this problem by preventing the creation of an
exclusive reference to the component entirely. Without an exclusive
reference, the only way to modify an immutable component is via removal
or replacement, which is fully captured by component hooks. To make a
component immutable, simply add `#[component(immutable)]`:

```rust
#[derive(Component)]
#[component(immutable)]
struct Foo {
    // ...
}
```

When implementing `Component` manually, there is an associated type
`Mutability` which controls this behavior:

```rust
impl Component for Foo {
    type Mutability = Mutable;
    // ...
}
```

Note that this means when working with generic components, you may need
to specify that a component is mutable to gain access to certain
methods:

```rust
// Before
fn bar<C: Component>() {
    // ...
}

// After
fn bar<C: Component<Mutability = Mutable>>() {
    // ...
}
```

With this new tool, creating index components, or caching data on an
entity should be more user friendly, allowing libraries to provide APIs
relying on components and hooks to uphold their invariants.

## Notes

- ~~I've done my best to implement this feature, but I'm not happy with
how reflection has turned out. If any reflection SMEs know a way to
improve this situation I'd greatly appreciate it.~~ There is an
outstanding issue around the fallibility of mutable methods on
`ReflectComponent`, but the DX is largely unchanged from `main` now.
- I've attempted to prevent all safe mutable access to a component that
does not implement `Component<Mutability = Mutable>`, but there may
still be some methods I have missed. Please indicate so and I will
address them, as they are bugs.
- Unsafe is an escape hatch I am _not_ attempting to prevent. Whatever
you do with unsafe is between you and your compiler.
- I am marking this PR as ready, but I suspect it will undergo fairly
major revisions based on SME feedback.
- I've marked this PR as _Uncontroversial_ based on the feature, not the
implementation.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Co-authored-by: Nuutti Kotivuori <naked@iki.fi>
2024-12-05 14:27:48 +00:00
Patrick Walton
5adf831b42
Add a bindless mode to AsBindGroup. (#16368)
This patch adds the infrastructure necessary for Bevy to support
*bindless resources*, by adding a new `#[bindless]` attribute to
`AsBindGroup`.

Classically, only a single texture (or sampler, or buffer) can be
attached to each shader binding. This means that switching materials
requires breaking a batch and issuing a new drawcall, even if the mesh
is otherwise identical. This adds significant overhead not only in the
driver but also in `wgpu`, as switching bind groups increases the amount
of validation work that `wgpu` must do.

*Bindless resources* are the typical solution to this problem. Instead
of switching bindings between each texture, the renderer instead
supplies a large *array* of all textures in the scene up front, and the
material contains an index into that array. This pattern is repeated for
buffers and samplers as well. The renderer now no longer needs to switch
binding descriptor sets while drawing the scene.

Unfortunately, as things currently stand, this approach won't quite work
for Bevy. Two aspects of `wgpu` conspire to make this ideal approach
unacceptably slow:

1. In the DX12 backend, all binding arrays (bindless resources) must
have a constant size declared in the shader, and all textures in an
array must be bound to actual textures. Changing the size requires a
recompile.

2. Changing even one texture incurs revalidation of all textures, a
process that takes time that's linear in the total size of the binding
array.

This means that declaring a large array of textures big enough to
encompass the entire scene is presently unacceptably slow. For example,
if you declare 4096 textures, then `wgpu` will have to revalidate all
4096 textures if even a single one changes. This process can take
multiple frames.

To work around this problem, this PR groups bindless resources into
small *slabs* and maintains a free list for each. The size of each slab
for the bindless arrays associated with a material is specified via the
`#[bindless(N)]` attribute. For instance, consider the following
declaration:

```rust
#[derive(AsBindGroup)]
#[bindless(16)]
struct MyMaterial {
    #[buffer(0)]
    color: Vec4,
    #[texture(1)]
    #[sampler(2)]
    diffuse: Handle<Image>,
}
```

The `#[bindless(N)]` attribute specifies that, if bindless arrays are
supported on the current platform, each resource becomes a binding array
of N instances of that resource. So, for `MyMaterial` above, the `color`
attribute is exposed to the shader as `binding_array<vec4<f32>, 16>`,
the `diffuse` texture is exposed to the shader as
`binding_array<texture_2d<f32>, 16>`, and the `diffuse` sampler is
exposed to the shader as `binding_array<sampler, 16>`. Inside the
material's vertex and fragment shaders, the applicable index is
available via the `material_bind_group_slot` field of the `Mesh`
structure. So, for instance, you can access the current color like so:

```wgsl
// `uniform` binding arrays are a non-sequitur, so `uniform` is automatically promoted
// to `storage` in bindless mode.
@group(2) @binding(0) var<storage> material_color: binding_array<Color, 4>;
...
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
    let color = material_color[mesh[in.instance_index].material_bind_group_slot];
    ...
}
```

Note that portable shader code can't guarantee that the current platform
supports bindless textures. Indeed, bindless mode is only available in
Vulkan and DX12. The `BINDLESS` shader definition is available for your
use to determine whether you're on a bindless platform or not. Thus a
portable version of the shader above would look like:

```wgsl
#ifdef BINDLESS
@group(2) @binding(0) var<storage> material_color: binding_array<Color, 4>;
#else // BINDLESS
@group(2) @binding(0) var<uniform> material_color: Color;
#endif // BINDLESS
...
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
#ifdef BINDLESS
    let color = material_color[mesh[in.instance_index].material_bind_group_slot];
#else // BINDLESS
    let color = material_color;
#endif // BINDLESS
    ...
}
```

Importantly, this PR *doesn't* update `StandardMaterial` to be bindless.
So, for example, `scene_viewer` will currently not run any faster. I
intend to update `StandardMaterial` to use bindless mode in a follow-up
patch.

A new example, `shaders/shader_material_bindless`, has been added to
demonstrate how to use this new feature.

Here's a Tracy profile of `submit_graph_commands` of this patch and an
additional patch (not submitted yet) that makes `StandardMaterial` use
bindless. Red is those patches; yellow is `main`. The scene was Bistro
Exterior with a hack that forces all textures to opaque. You can see a
1.47x mean speedup.
![Screenshot 2024-11-12
161713](https://github.com/user-attachments/assets/4334b362-42c8-4d64-9cfb-6835f019b95c)

## Migration Guide

* `RenderAssets::prepare_asset` now takes an `AssetId` parameter.
* Bin keys now have Bevy-specific material bind group indices instead of
`wgpu` material bind group IDs, as part of the bindless change. Use the
new `MaterialBindGroupAllocator` to map from bind group index to bind
group ID.
2024-12-03 18:00:34 +00:00
Niklas Eicker
89d094e50f
Remove duplicated default feature (#16552)
# Objective

- The feature `android-game-activity` was in the default feature list
twice

## Solution

- Remove one of the features
2024-11-30 02:02:25 +00:00
notmd
d9282486e3
Dont enable bevy_remote by default (#16464)
# Objective

- I dont think we want bevy_remote enable by default until our editor is
out.

## Solution

- Disable it
2024-11-22 19:22:12 +00:00
andriyDev
b1e4512648
Fix the picking backend features not actually disabling the features (#16470)
# Objective

- Fixes #16469.

## Solution

- Make the picking backend features not enabled by default in each
sub-crate.
- Make features in `bevy_internal` to set the backend features
- Make the root `bevy` crate set the features by default.

## Testing

- The mesh and sprite picking examples still work correctly.
2024-11-22 18:14:16 +00:00
François Mockers
6e81a05c93
Headless by features (#16401)
# Objective

- Fixes #16152 

## Solution

- Put `bevy_window` and `bevy_a11y` behind the `bevy_window` feature.
they were the only difference
- Add `ScheduleRunnerPlugin` to the `DefaultPlugins` when `bevy_window`
is disabled
- Remove `HeadlessPlugins`
- Update the `headless` example
2024-11-16 21:33:37 +00:00
Carter Anderson
6beeaa89d3
Make PCSS experimental (#16382)
# Objective

PCSS still has some fundamental issues (#16155). We should resolve them
before "releasing" the feature.

## Solution

1. Rename the already-optional `pbr_pcss` cargo feature to
`experimental_pbr_pcss` to better communicate its state to developers.
2. Adjust the description of the `experimental_pbr_pcss` cargo feature
to better communicate its state to developers.
3. Gate PCSS-related light component fields behind that cargo feature,
to prevent surfacing them to developers by default.
2024-11-14 07:39:26 +00:00
Marco Buono
ef23f465ce
Do not re-check visibility or re-render shadow maps for point and spot lights for each view (#15156)
# Objective

_If I understand it correctly_, we were checking mesh visibility, as
well as re-rendering point and spot light shadow maps for each view.
This makes it so that M views and N lights produce M x N complexity.
This PR aims to fix that, as well as introduce a stress test for this
specific scenario.

## Solution

- Keep track of what lights have already had mesh visibility calculated
and do not calculate it again;
- Reuse shadow depth textures and attachments across all views, and only
render shadow maps for the _first_ time a light is encountered on a
view;
- Directional lights remain unaltered, since their shadow map cascades
are view-dependent;
- Add a new `many_cameras_lights` stress test example to verify the
solution

## Showcase

110% speed up on the stress test
83% reduction of memory usage in stress test

### Before (5.35 FPS on stress test)
<img width="1392" alt="Screenshot 2024-09-11 at 12 25 57"
src="https://github.com/user-attachments/assets/136b0785-e9a4-44df-9a22-f99cc465e126">

### After (11.34 FPS on stress test)
<img width="1392" alt="Screenshot 2024-09-11 at 12 24 35"
src="https://github.com/user-attachments/assets/b8dd858f-5e19-467f-8344-2b46ca039630">


## Testing

- Did you test these changes? If so, how? 
- On my game project where I have two cameras, and many shadow casting
lights I managed to get pretty much double the FPS.
  - Also included a stress test, see the comparison above
- Are there any parts that need more testing?
- Yes, I would like help verifying that this fix is indeed correct, and
that we were really re-rendering the shadow maps by mistake and it's
indeed okay to not do that
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Run the `many_cameras_lights` example
- On the `main` branch, cherry pick the commit with the example (`git
cherry-pick --no-commit 1ed4ace01`) and run it
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - macOS

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-11-11 18:49:09 +00:00
Benjamin Brienen
e155fe1d86
Disable lint that interferes with rust beta CI compatibility (#16199)
# Objective

Fix our CI with rust beta

## Solution

Disable new lint

## Testing

Ran `cargo +nightly clippy`.
2024-11-10 14:42:29 +00:00
Derick M
0ac495f7f4
Remove accesskit re-export from bevy_a11y (#16257)
# Objective

- Fixes #16235 

## Solution

- Both Bevy and AccessKit export a `Node` struct, to reduce confusion
Bevy will no longer re-export `AccessKit` from `bevy_a11y`

## Testing

- Tested locally

## Migration Guide

```diff
# main.rs
--    use bevy_a11y::{
--        accesskit::{Node, Rect, Role},
--        AccessibilityNode,
--    };
++    use bevy_a11y::AccessibilityNode;
++    use accesskit::{Node, Rect, Role};

# Cargo.toml
++    accesskit = "0.17"
```

- Users will need to add `accesskit = "0.17"` to the dependencies
section of their `Cargo.toml` file and update their `accesskit` use
statements to come directly from the external crate instead of
`bevy_a11y`.
- Make sure to keep the versions of `accesskit` aligned with the
versions Bevy uses.
2024-11-08 21:01:16 +00:00
Rich Churcher
cdc18ee886
Move UI example to testbed (#16241)
# Objective

UI example is quite extensive, probably not the best teaching example
anymore.

Closes #16230.
2024-11-07 20:57:45 +00:00
JMS55
267b57e565
Meshlet normal-aware LOD and meshoptimizer upgrade (#16111)
# Objective

- Choose LOD based on normal simplification error in addition to
position error
- Update meshoptimizer to 0.22, which has a bunch of simplifier
improvements

## Testing

- Did you test these changes? If so, how?
- Visualize normals, and compare LOD changes before and after. Normals
no longer visibly change as the LOD cut changes.
- Are there any parts that need more testing?
  - No
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Run the meshlet example in this PR and on main and move around to
change the LOD cut. Before running each example, in
meshlet_mesh_material.wgsl, replace `let color = vec3(rand_f(&rng),
rand_f(&rng), rand_f(&rng));` with `let color =
(vertex_output.world_normal + 1.0) / 2.0;`. Make sure to download the
appropriate bunny asset for each branch!
2024-11-04 15:20:22 +00:00
mamekoro
4b0efda354
Make some associated functions of Color const (#16091)
# Objective
Make the following functions `const` that will be useful to define
colors as constants.

- `Color::srgb_from_array`
- `Color::srgba_u8`
- `Color::srgb_u8`

The last two require Rust 1.82.0.

## Solution
- Make them `const`
- Change MSRV to 1.82.0

## Testing
I tested bevy_color only. My machine does not have enough RAM capacity
to test the whole bevy.

`cargo test -p bevy_color`
2024-10-28 03:26:35 +00:00
ickshonpe
3d72f494a2
Layout rounding debug example (#16096)
# Objective

Simple example for debugging layout rounding errors.

<img width="1039" height="752" alt="layout_rounding_debug"
src="https://github.com/user-attachments/assets/12673000-e267-467e-b25b-3f8001c1347c">

Any white lines are gaps in the layout caused by coordinate rounding
errors.
2024-10-27 20:08:51 +00:00
Patrick Walton
c6a66a7e96
Place percentage-closer soft shadows behind a feature gate to save on samplers. (#16068)
The two additional linear texture samplers that PCSS added caused us to
blow past the limit on Apple Silicon macOS and WebGL. To fix the issue,
this commit adds a `--feature pbr_pcss` feature gate that disables PCSS
if not present.

Closes #15345.
Closes #15525.
Closes #15821.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2024-10-24 21:16:00 +00:00
JMS55
6d42830c7f
Meshlet builder improvements redux (#15886)
Take a bunch more improvements from @zeux's nanite.cpp code.

* Use position-only vertices (discard other attributes) to determine
meshlet connectivity for grouping
* Rather than using the lock borders flag when simplifying meshlet
groups, provide the locked vertices ourselves. The lock borders flag
locks the entire border of the meshlet group, but really we only want to
lock the edges between meshlet groups - outwards facing edges are fine
to unlock. This gives a really significant increase to the DAG quality.
* Add back stuck meshlets (group has only a single meshlet,
simplification failed) to the simplification queue to allow them to get
used later on and have another attempt at simplifying
* Target 8 meshlets per group instead of 4 (second biggest improvement
after manual locks)
* Provide a seed to metis for deterministic meshlet building
* Misc other improvements

We can remove the usage of unsafe after the next upstream meshopt
release, but for now we need to use the ffi function directly. I'll do
another round of improvements later, mainly attribute-aware
simplification and using spatial weights for meshlet grouping.

Need to merge https://github.com/bevyengine/bevy/pull/15846 first.
2024-10-23 16:56:50 +00:00
JMS55
9d54fe0370
Meshlet new error projection (#15846)
* New error projection code taken from @zeux's meshoptimizer nanite.cpp
demo for determining LOD (thanks zeux!)
* Builder: `compute_lod_group_data()`
* Runtime: `lod_error_is_imperceptible()`
2024-10-22 20:14:30 +00:00
Rob Parrett
30d84519a2
Use en-us locale for typos (#16037)
# Objective

Bevy seems to want to standardize on "American English" spellings. Not
sure if this is laid out anywhere in writing, but see also #15947.

While perusing the docs for `typos`, I noticed that it has a `locale`
config option and tried it out.

## Solution

Switch to `en-us` locale in the `typos` config and run `typos -w`

## Migration Guide

The following methods or fields have been renamed from `*dependants*` to
`*dependents*`.

- `ProcessorAssetInfo::dependants`
- `ProcessorAssetInfos::add_dependant`
- `ProcessorAssetInfos::non_existent_dependants`
- `AssetInfo::dependants_waiting_on_load`
- `AssetInfo::dependants_waiting_on_recursive_dep_load`
- `AssetInfos::loader_dependants`
- `AssetInfos::remove_dependants_and_labels`
2024-10-20 18:55:17 +00:00
François Mockers
74dedb2841
Testbed for 3d (#15993)
# Objective

- Progress towards #15918 
- Add tests for 3d

## Solution

- Add tests that cover lights, bloom, gltf and animation
- Removed examples `contributors` and `load_gltf` as they don't
contribute additional checks to CI

## Testing

- `CI_TESTING_CONFIG=.github/example-run/testbed_3d.ron cargo run
--example testbed_3d --features "bevy_ci_testing"`
2024-10-19 19:32:03 +00:00
Clar Fon
683d6c90a9
Remove AVIF feature (#15973)
Resolves #15968. Since this feature never worked, and enabling it in the
`image` crate requires system dependencies, we've decided that it's best
to just remove it and let other plugin crates offer support for it as
needed.

## Migration Guide

AVIF images are no longer supported. They never really worked, and
require system dependencies (libdav1d) to work correctly, so, it's
better to simply offer this support via an unofficial plugin instead as
needed. The corresponding types have been removed from Bevy to account
for this.
2024-10-17 19:47:28 +00:00
Alice Cecile
76744bf58c
Mark ghost nodes as experimental and partially feature flag them (#15961)
# Objective

As discussed in #15341, ghost nodes are a contentious and experimental
feature. In the interest of enabling ecosystem experimentation, we've
decided to keep them in Bevy 0.15.

That said, we don't use them internally, and don't expect third-party
crates to support them. If the experimentation returns a negative result
(they aren't very useful, an alternative design is preferred etc) they
will be removed.

We should clearly communicate this status to users, and make sure that
users don't use ghost nodes in their projects without a very clear
understanding of what they're getting themselves into.

## Solution

To make life easy for users (and Bevy), `GhostNode` and all associated
helpers remain public and are always available.

However, actually constructing these requires enabling a feature flag
that's clearly marked as experimental. To do so, I've added a
meaningless private field.

When the feature flag is enabled, our constructs (`new` and `default`)
can be used. I've added a `new` constructor, which should be preferred
over `Default::default` as that can be readily deprecated, allowing us
to prompt users to swap over to the much nicer `GhostNode` syntax once
this is a unit struct again.

Full credit: this was mostly @cart's design: I'm just implementing it!

## Testing

I've run the ghost_nodes example and it fails to compile without the
feature flag. With the feature flag, it works fine :)

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-10-16 22:20:48 +00:00
François Mockers
e1b9f545fb
Introduce testbed examples starting with 2d (#15954)
# Objective

- Make progress for #15918 
- Start with 2d

## Solution

- Remove screenshots for existing examples as they're not deterministic
- Create new "testbed" example category, with a 2d one to start

## Testing

- Run `CI_TESTING_CONFIG=.github/example-run/testbed_2d.ron cargo run
--example testbed_2d --features "bevy_ci_testing"`
- ???
- Check the screenshots
2024-10-16 17:37:47 +00:00
ickshonpe
6d3965f520
Overflow clip margin (#15561)
# Objective

Limited implementation of the CSS property `overflow-clip-margin`
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-clip-margin

Allows you to control the visible area for clipped content when using
overfllow-clip, -hidden, or -scroll and expand it with a margin.

Based on #15442

Fixes #15468

## Solution

Adds a new field to Style: `overflow_clip_margin: OverflowClipMargin`.
The field is ignored unless overflow-clip, -hidden or -scroll is set on
at least one axis.

`OverflowClipMargin` has these associated constructor functions:
```
pub const fn content_box() -> Self;
pub const fn padding_box() -> Self;
pub const fn border_box() -> Self;
```
You can also use the method `with_margin` to increases the size of the
visible area:
```
commands
  .spawn(NodeBundle {
      style: Style {
          width: Val::Px(100.),
          height: Val::Px(100.),
          padding: UiRect::all(Val::Px(20.)),
          border: UiRect::all(Val::Px(5.)),
          overflow: Overflow::clip(),
          overflow_clip_margin: OverflowClipMargin::border_box().with_margin(25.),
          ..Default::default()
      },
      border_color: Color::BLACK.into(),
      background_color: GRAY.into(),
      ..Default::default()
  })
```
`with_margin` expects a length in logical pixels, negative values are
clamped to zero.

## Notes
* To keep this PR as simple as possible I omitted responsive margin
values support. This could be added in a follow up if we want it.
* CSS also supports a `margin-box` option but we don't have access to
the margin values in `Node` so it's probably not feasible to implement
atm.

## Testing

```cargo run --example overflow_clip_margin```

<img width="396" alt="overflow-clip-margin" src="https://github.com/user-attachments/assets/07b51cd6-a565-4451-87a0-fa079429b04b">

## Migration Guide

Style has a new field `OverflowClipMargin`.  It allows users to set the visible area for clipped content when using overflow-clip, -hidden, or -scroll and expand it with a margin.

There are three associated constructor functions `content_box`, `padding_box` and `border_box`:
* `content_box`: elements painted outside of the content box area (the innermost part of the node excluding the padding and border) of the node are clipped. This is the new default behaviour.
* `padding_box`: elements painted outside outside of the padding area of the node are clipped. 
* `border_box`:  elements painted outside of the bounds of the node are clipped. This matches the behaviour from Bevy 0.14.

There is also a `with_margin` method that increases the size of the visible area by the given number in logical pixels, negative margin values are clamped to zero.

`OverflowClipMargin` is ignored unless overflow-clip, -hidden or -scroll is also set on at least one axis of the UI node.

---------

Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
2024-10-16 13:17:49 +00:00
Shane Celis
5157fef84b
Add window drag move and drag resize without decoration example. (#15814)
# Objective

Add an example for the new drag move and drag resize introduced by PR
#15674 and fix #15734.

## Solution

I created an example that allows the user to exercise drag move and drag
resize separately. The user can also choose what direction the resize
works in.

![Screenshot 2024-10-10 at 4 06
43 AM](https://github.com/user-attachments/assets/1da558ab-a80f-49af-8b7d-bb635b0f038f)

### Name

The example is called `window_drag_move`. Happy to have that
bikeshedded.

### Contentious Refactor?

This PR removed the `ResizeDirection` enumeration in favor of using
`CompassOctant` which had the same variants. Perhaps this is
contentious.

### Unsafe?

In PR #15674 I mentioned that `start_drag_move()` and
`start_drag_resize()`'s requirement to only be called in the presence of
a left-click looks like a compiler-unenforceable contract that can cause
intermittent panics when not observed, so perhaps the functions should
be marked them unsafe. **I have not made that change** here since I
didn't see a clear consensus on that.

## Testing

I exercised this on x86 macOS. However, winit for macOS does not support
drag resize. It reports a good error when `start_drag_resize()` is
called. I'd like to see it tested on Windows and Linux.

---

## Showcase

Example window_drag_move shows how to drag or resize a window without
decoration.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-15 23:38:35 +00:00
Joona Aalto
0e30b68b20
Add mesh picking backend and MeshRayCast system parameter (#15800)
# Objective

Closes #15545.

`bevy_picking` supports UI and sprite picking, but not mesh picking.
Being able to pick meshes would be extremely useful for various games,
tools, and our own examples, as well as scene editors and inspectors.
So, we need a mesh picking backend!

Luckily,
[`bevy_mod_picking`](https://github.com/aevyrie/bevy_mod_picking) (which
`bevy_picking` is based on) by @aevyrie already has a [backend for
it](74f0c3c0fb/backends/bevy_picking_raycast/src/lib.rs)
using [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast).
As a side product of adding mesh picking, we also get support for
performing ray casts on meshes!

## Solution

Upstream a large chunk of the immediate-mode ray casting functionality
from `bevy_mod_raycast`, and add a mesh picking backend based on
`bevy_mod_picking`. Huge thanks to @aevyrie who did all the hard work on
these incredible crates!

All meshes are pickable by default. Picking can be disabled for
individual entities by adding `PickingBehavior::IGNORE`, like normal.
Or, if you want mesh picking to be entirely opt-in, you can set
`MeshPickingBackendSettings::require_markers` to `true` and add a
`RayCastPickable` component to the desired camera and target entities.

You can also use the new `MeshRayCast` system parameter to cast rays
into the world manually:

```rust
fn ray_cast_system(mut ray_cast: MeshRayCast, foo_query: Query<(), With<Foo>>) {
    let ray = Ray3d::new(Vec3::ZERO, Dir3::X);

    // Only ray cast against entities with the `Foo` component.
    let filter = |entity| foo_query.contains(entity);

    // Never early-exit. Note that you can change behavior per-entity.
    let early_exit_test = |_entity| false;

    // Ignore the visibility of entities. This allows ray casting hidden entities.
    let visibility = RayCastVisibility::Any;

    let settings = RayCastSettings::default()
        .with_filter(&filter)
        .with_early_exit_test(&early_exit_test)
        .with_visibility(visibility);

    // Cast the ray with the settings, returning a list of intersections.
    let hits = ray_cast.cast_ray(ray, &settings);
}
```

This is largely a direct port, but I did make several changes to match
our APIs better, remove things we don't need or that I think are
unnecessary, and do some general improvements to code quality and
documentation.

### Changes Relative to `bevy_mod_raycast` and `bevy_mod_picking`

- Every `Raycast` and "raycast" has been renamed to `RayCast` and "ray
cast" (similar reasoning as the "Naming" section in #15724)
- `Raycast` system param has been renamed to `MeshRayCast` to avoid
naming conflicts and to be explicit that it is not for colliders
- `RaycastBackend` has been renamed to `MeshPickingBackend`
- `RayCastVisibility` variants are now `Any`, `Visible`, and
`VisibleInView` instead of `Ignore`, `MustBeVisible`, and
`MustBeVisibleAndInView`
- `NoBackfaceCulling` has been renamed to `RayCastBackfaces`, to avoid
implying that it affects the rendering of backfaces for meshes (it
doesn't)
- `SimplifiedMesh` and `RayCastBackfaces` live near other ray casting
API types, not in their own 10 LoC module
- All intersection logic and types are in the same `intersections`
module, not split across several modules
- Some intersection types have been renamed to be clearer and more
consistent
	- `IntersectionData` -> `RayMeshHit` 
	- `RayHit` -> `RayTriangleHit`
- General documentation and code quality improvements

### Removed / Not Ported

- Removed unused ray helpers and types, like `PrimitiveIntersection`
- Removed getters on intersection types, and made their properties
public
- There is no `2d` feature, and `Raycast::mesh_query` and
`Raycast::mesh2d_query` have been merged into `MeshRayCast::mesh_query`,
which handles both 2D and 3D
- I assume this existed previously because `Mesh2dHandle` used to be in
`bevy_sprite`. Now both the 2D and 3D mesh are in `bevy_render`.
- There is no `debug` feature or ray debug rendering
- There is no deferred API (`RaycastSource`)
- There is no `CursorRayPlugin` (the picking backend handles this)

### Note for Reviewers

In case it's helpful, the [first
commit](281638ef10)
here is essentially a one-to-one port. The rest of the commits are
primarily refactoring and cleaning things up in the ways listed earlier,
as well as changes to the module structure.

It may also be useful to compare the original [picking
backend](74f0c3c0fb/backends/bevy_picking_raycast/src/lib.rs)
and [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast) to
this PR. Feel free to mention if there are any changes that I should
revert or something I should not include in this PR.

## Testing

I tested mesh picking and relevant components in some examples, for both
2D and 3D meshes, and added a new `mesh_picking` example. I also
~~stole~~ ported over the [ray-mesh intersection
benchmark](dbc5ef32fe/benches/ray_mesh_intersection.rs)
from `bevy_mod_raycast`.

---

## Showcase

Below is a version of the `2d_shapes` example modified to demonstrate 2D
mesh picking. This is not included in this PR.


https://github.com/user-attachments/assets/7742528c-8630-4c00-bacd-81576ac432bf

And below is the new `mesh_picking` example:


https://github.com/user-attachments/assets/b65c7a5a-fa3a-4c2d-8bbd-e7a2c772986e

There is also a really cool new `mesh_ray_cast` example ported over from
`bevy_mod_raycast`:


https://github.com/user-attachments/assets/3c5eb6c0-bd94-4fb0-bec6-8a85668a06c9

---------

Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Trent <2771466+tbillington@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2024-10-13 17:24:19 +00:00
Andrew
6a39c33d49
Use oslog for ios (#13364)
# Objective

On mobile devices, it's best to use the OS's native logging due to the
difficulty of accessing the console. This is already done for Android.

This is an updated version of
https://github.com/bevyengine/bevy/pull/4462.

## Solution

This PR uses Absolucy's
[tracing-oslog](https://github.com/Absolucy/tracing-oslog) ([ZLib
license](https://github.com/Absolucy/tracing-oslog/blob/main/LICENSE.md))
for iOS in order to use Apple's `os_log`.

## Testing

I ran `examples/mobile` with the logging from `examples/app/logs.rs` on
an iOS device, I then checked the logs could be filtered in the MacOS
Console.app.

## Changelog

 - Change bevy_log to use Apple's os_log on iOS.

## Questions for Reviewers
It's worth noting that the dependency this adds hasn't had bug fixes
released in a few years, so we may want to consider one or more of:
 1. a feature flag to opt-in, and it would also allow `os_log` on MacOS
 2. merge as-is and have some (minor?) upstream bugs
 3. hold off on this PR until a suitable alternative dependency arises
 4. maintain our own implementation

## Future work

In a follow-up PR it might be good to make the `subsystem` field have a
better default value, like [this
one](https://github.com/bevyengine/bevy/blob/main/examples/mobile/bevy_mobile_example.xcodeproj/project.pbxproj#L363).
That value can be retrieved programmatically if we bind another system
API (For posterity in Swift this is `Bundle.main.bundleIdentifier`, but
the C/ObjC equivalent is likely easier to bind). This would almost
always be the correct value, while the current default is unlikely to
ever be correct.

---------

Co-authored-by: Dusty DeWeese <dustin.deweese@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-10-11 08:58:14 +00:00
Matty
e563f86a1d
Simplified easing curves (#15711)
# Objective

Simplify the API surrounding easing curves. Broaden the base of types
that support easing.

## Solution

There is now a single library function, `easing_curve`, which constructs
a unit-parametrized easing curve between two values based on an
`EaseFunction`:
```rust
/// Given a `start` and `end` value, create a curve parametrized over [the unit interval]
/// that connects them, using the given [ease function] to determine the form of the
/// curve in between.
///
/// [the unit interval]: Interval::UNIT
/// [ease function]: EaseFunction
pub fn easing_curve<T: Ease>(start: T, end: T, ease_fn: EaseFunction) -> EasingCurve<T> { //... }
```

As this shows, the type of the output curve is generic only in `T`. In
particular, as long as `T` is `Reflect` (and `FromReflect` etc. — i.e.,
a standard "well-behaved" reflectable type), `EasingCurve<T>` is also
`Reflect`, and there is no special field handling nonsense. Therefore,
`EasingCurve` is the kind of thing that would be able to be easily
changed in an editor. This is made possible by storing the actual
`EaseFunction` on `EasingCurve<T>` instead of indirecting through some
kind of function type (which generally leads to issues with reflection).

The types that can be eased are those that implement a trait `Ease`:
```rust
/// A type whose values can be eased between.
///
/// This requires the construction of an interpolation curve that actually extends
/// beyond the curve segment that connects two values, because an easing curve may
/// extrapolate before the starting value and after the ending value. This is
/// especially common in easing functions that mimic elastic or springlike behavior.
pub trait Ease: Sized {
    /// Given `start` and `end` values, produce a curve with [unlimited domain]
    /// that:
    /// - takes a value equivalent to `start` at `t = 0`
    /// - takes a value equivalent to `end` at `t = 1`
    /// - has constant speed everywhere, including outside of `[0, 1]`
    ///
    /// [unlimited domain]: Interval::EVERYWHERE
    fn interpolating_curve_unbounded(start: &Self, end: &Self) -> impl Curve<Self>;
}
```

(I know, I know, yet *another* interpolation trait. See 'Future
direction'.)

The other existing easing functions from the previous version of this
module have also become new members of `EaseFunction`: `Linear`,
`Steps`, and `Elastic` (which maybe needs a different name). The latter
two are parametrized.

## Testing

Tested using the `easing_functions` example. I also axed the
`cubic_curve` example which was of questionable value and replaced it
with `eased_motion`, which uses this API in the context of animation:


https://github.com/user-attachments/assets/3c802992-6b9b-4b56-aeb1-a47501c29ce2


---

## Future direction

Morally speaking, `Ease` is incredibly similar to `StableInterpolate`.
Probably, we should just merge `StableInterpolate` into `Ease`, and then
make `SmoothNudge` an automatic extension trait of `Ease`. The reason I
didn't do that is that `StableInterpolate` is not implemented for
`VectorSpace` because of concerns about the `Color` types, and I wanted
to avoid controversy. I think that may be a good idea though.

As Alice mentioned before, we should also probably get rid of the
`interpolation` dependency.

The parametrized `Elastic` variant probably also needs some additional
work (e.g. renaming, in/out/in-out variants, etc.) if we want to keep
it.
2024-10-08 19:45:13 +00:00
JMS55
aa626e4f0b
Per-meshlet compressed vertex data (#15643)
# Objective
- Prepare for streaming by storing vertex data per-meshlet, rather than
per-mesh (this means duplicating vertices per-meshlet)
- Compress vertex data to reduce the cost of this

## Solution
The important parts are in from_mesh.rs, the changes to the Meshlet type
in asset.rs, and the changes in meshlet_bindings.wgsl. Everything else
is pretty secondary/boilerplate/straightforward changes.

- Positions are quantized in centimeters with a user-provided power of 2
factor (ideally auto-determined, but that's a TODO for the future),
encoded as an offset relative to the minimum value within the meshlet,
and then stored as a packed list of bits using the minimum number of
bits needed for each vertex position channel for that meshlet
- E.g. quantize positions (lossly, throws away precision that's not
needed leading to using less bits in the bitstream encoding)
- Get the min/max quantized value of each X/Y/Z channel of the quantized
positions within a meshlet
- Encode values relative to the min value of the meshlet. E.g. convert
from [min, max] to [0, max - min]
- The new max value in the meshlet is (max - min), which only takes N
bits, so we only need N bits to store each channel within the meshlet
(lossless)
- We can store the min value and that it takes N bits per channel in the
meshlet metadata, and reconstruct the position from the bitstream
- Normals are octahedral encoded and than snorm2x16 packed and stored as
a single u32.
- Would be better to implement the precise variant of octhedral encoding
for extra precision (no extra decode cost), but decided to keep it
simple for now and leave that as a followup
- Tried doing a quantizing and bitstream encoding scheme like I did for
positions, but struggled to get it smaller. Decided to go with this for
simplicity for now
- UVs are uncompressed and take a full 64bits per vertex which is
expensive
  - In the future this should be improved
- Tangents, as of the previous PR, are not explicitly stored and are
instead derived from screen space gradients
- While I'm here, split up MeshletMeshSaverLoader into two separate
types

Other future changes include implementing a smaller encoding of triangle
data (3 u8 indices = 24 bits per triangle currently), and more
disk-oriented compression schemes.

References:
* "A Deep Dive into UE5's Nanite Virtualized Geometry"
https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf#page=128
(also available on youtube)
* "Towards Practical Meshlet Compression"
https://arxiv.org/pdf/2404.06359
* "Vertex quantization in Omniforce Game Engine"
https://daniilvinn.github.io/2024/05/04/omniforce-vertex-quantization.html

## Testing

- Did you test these changes? If so, how?
- Converted the stanford bunny, and rendered it with a debug material
showing normals, and confirmed that it's identical to what's on main.
EDIT: See additional testing in the comments below.
- Are there any parts that need more testing?
- Could use some more size comparisons on various meshes, and testing
different quantization factors. Not sure if 4 is a good default. EDIT:
See additional testing in the comments below.
- Also did not test runtime performance of the shaders. EDIT: See
additional testing in the comments below.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Use my unholy script, replacing the meshlet example
https://paste.rs/7xQHk.rs (must make MeshletMesh fields pub instead of
pub crate, must add lz4_flex as a dev-dependency) (must compile with
meshlet and meshlet_processor features, mesh must have only positions,
normals, and UVs, no vertex colors or tangents)

---

## Migration Guide
- TBD by JMS55 at the end of the release
2024-10-08 18:42:55 +00:00
ickshonpe
99b9a2fcd7
box shadow (#15204)
# Objective

UI box shadow support

Adds a new component `BoxShadow`:

```rust
pub struct BoxShadow {
    /// The shadow's color
    pub color: Color,
    /// Horizontal offset
    pub x_offset: Val,
    /// Vertical offset
    pub y_offset: Val,
    /// Horizontal difference in size from the occluding uninode
    pub spread_radius: Val,
    /// Blurriness of the shadow
    pub blur_radius: Val,
}
```

To use `BoxShadow`, add the component to any Bevy UI node and a shadow
will be drawn beneath that node.
Also adds a resource `BoxShadowSamples` that can be used to adjust the
shadow quality.

#### Notes
* I'm not super happy with the field names. Maybe we need a `struct Size
{ width: Val, height: Val }` type or something.
* The shader isn't very optimised but I don't see that it's too
important for now as the number of shadows being rendered is not going
to be massive most of the time. I think it's more important to get the
API and geometry correct with this PR.
* I didn't implement an inset property, it's not essential and can
easily be added in a follow up.
* Shadows are only rendered for uinodes, not for images or text.
* Batching isn't supported, it would need out-of-the-scope-of-this-pr
changes to the way the UI handles z-ordering for it to be effective.

# Showcase

```cargo run --example box_shadow -- --samples 4```

<img width="391" alt="br" src="https://github.com/user-attachments/assets/4e8add96-dc93-46e0-9e35-d995eb0943ad">

```cargo run --example box_shadow -- --samples 10```

<img width="391" alt="s10"
src="https://github.com/user-attachments/assets/ecb384c9-4012-4cd6-9dea-5180904bf28e">
2024-10-08 16:26:17 +00:00
IceSentry
4bf647ff3b
Add Order Independent Transparency (#14876)
# Objective

- Alpha blending can easily fail in many situations and requires sorting
on the cpu

## Solution

- Implement order independent transparency (OIT) as an alternative to
alpha blending
- The implementation uses 2 passes
- The first pass records all the fragments colors and position to a
buffer that is the size of N layers * the render target resolution.
- The second pass sorts the fragments, blends them and draws them to the
screen. It also currently does manual depth testing because early-z
fails in too many cases in the first pass.

## Testing

- We've been using this implementation at foresight in production for
many months now and we haven't had any issues related to OIT.

---

## Showcase


![image](https://github.com/user-attachments/assets/157f3e32-adaf-4782-b25b-c10313b9bc43)

![image](https://github.com/user-attachments/assets/bef23258-0c22-4b67-a0b8-48a9f571c44f)

## Future work

- Add an example showing how to use OIT for a custom material
- Next step would be to implement a per-pixel linked list to reduce
memory use
- I'd also like to investigate using a BinnedRenderPhase instead of a
SortedRenderPhase. If it works, it would make the transparent pass
significantly faster.

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: Charlotte McElwain <charlotte.c.mcelwain@gmail.com>
2024-10-07 23:50:28 +00:00
Mohamed Osama
91bed8ce51
Screen shake example (#15567)
# Objective

Closes https://github.com/bevyengine/bevy/issues/15564

## Solution

Adds a screen shake example.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-07 21:14:07 +00:00
François Mockers
01387101df
add example for ease functions (#15703)
# Objective

- Followup to #15675 
- Add an example showcasing the functions

## Solution

- Add an example showcasing the functions
- Some of the functions from the interpolation crate are messed up,
fixed in #15706


![ease](https://github.com/user-attachments/assets/1f3b2b80-23d2-45c7-8b08-95b2e870aa02)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2024-10-07 18:31:43 +00:00
Clar Fon
8adc9e9d6e
Feature-gate all image formats (#15586)
# Objective

Bevy supports feature gates for each format it supports, but several
formats that it loads via the `image` crate do not have feature gates.
Additionally, the QOI format is supported by the `image` crate and
wasn't available at all. This fixes that.

## Solution

The following feature gates are added:

* `avif`
* `ff` (Farbfeld)
* `gif`
* `ico`
* `qoi`
* `tiff`

None of these formats are enabled by default, despite the fact that all
these formats appeared to be enabled by default before. Since
`default-features` was disabled for the `image` crate, it's likely that
using any of these formats would have errored by default before this
change, although this probably needs additional testing.

## Testing

The changes seemed minimal enough that a compile test would be
sufficient.

## Migration guide

Image formats that previously weren't feature-gated are now
feature-gated, meaning they will have to be enabled if you use them:

* `avif`
* `ff` (Farbfeld)
* `gif`
* `ico`
* `tiff`

Additionally, the `qoi` feature has been added to support loading QOI
format images.

Previously, these formats appeared in the enum by default, but weren't
actually enabled via the `image` crate, potentially resulting in weird
bugs. Now, you should be able to add these features to your projects to
support them properly.
2024-10-07 16:37:45 +00:00
Ida "Iyes
31409ebc61
Add Image methods for easy access to a pixel's color (#10392)
# Objective

If you want to draw / generate images from the CPU, such as:
 - to create procedurally-generated assets
- for games whose artstyle is best implemented by poking pixels directly
from the CPU, instead of using shaders

It is currently very unergonomic to do in Bevy, because you have to deal
with the raw bytes inside `image.data`, take care of the pixel format,
etc.

## Solution

This PR adds some helper methods to `Image` for pixel manipulation.
These methods allow you to use Bevy's user-friendly `Color` struct to
read and write the colors of pixels, at arbitrary coordinates (specified
as `UVec3` to support any texture dimension). They handle
encoding/decoding to the `Image`s `TextureFormat`, incl. any sRGB
conversion.

While we are at it, also add methods to help with direct access to the
raw bytes. It is now easy to compute the offset where the bytes of a
specific pixel coordinate are found, or to just get a Rust slice to
access them.

Caveat: `Color` roundtrips are obviously going to be lossy for non-float
`TextureFormat`s. Using `set_color_at` followed by `get_color_at` will
return a different value, due to the data conversions involved (such as
`f32` -> `u8` -> `f32` for the common `Rgba8UnormSrgb` texture format).
Be careful when comparing colors (such as checking for a color you wrote
before)!

Also adding a new example: `cpu_draw` (under `2d`), to showcase these
new APIs.

---

## Changelog

### Added

 - `Image` APIs for easy access to the colors of specific pixels.

---------

Co-authored-by: Pascal Hertleif <killercup@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: ltdk <usr@ltdk.xyz>
2024-10-07 14:38:41 +00:00
Bude
6edb78a8c3
Inverse bevy_render bevy_winit dependency and move cursor to bevy_winit (#15649)
# Objective

- `bevy_render` should not depend on `bevy_winit`
- Fixes #15565

## Solution

- `bevy_render` no longer depends on `bevy_winit`
- The following is behind the `custom_cursor` feature
- Move custom cursor code from `bevy_render` to `bevy_winit` behind the
`custom_cursor` feature
- `bevy_winit` now depends on `bevy_render` (for `Image` and
`TextureFormat`)
- `bevy_winit` now depends on `bevy_asset` (for `Assets`, `Handle` and
`AssetId`)
  - `bevy_winit` now depends on `bytemuck` (already in tree)
- Custom cursor code in `bevy_winit` reworked to use `AssetId` (other
than that it is taken over 1:1)
- Rework `bevy_winit` custom cursor interface visibility now that the
logic is all contained in `bevy_winit`

## Testing

- I ran the screenshot and window_settings examples
- Tested on linux wayland so far

---

## Migration Guide

`CursorIcon` and `CustomCursor` previously provided by
`bevy::render::view::cursor` is now available from `bevy::winit`.
A new feature `custom_cursor` enables this functionality (default
feature).
2024-10-06 18:25:50 +00:00
poopy
d9190e4ff6
Add Support for Triggering Events via AnimationEvents (#15538)
# Objective

Add support for events that can be triggered from animation clips. This
is useful when you need something to happen at a specific time in an
animation. For example, playing a sound every time a characters feet
hits the ground when walking.

Closes #15494 

## Solution

Added a new field to `AnimationClip`: `events`, which contains a list of
`AnimationEvent`s. These are automatically triggered in
`animate_targets` and `trigger_untargeted_animation_events`.

## Testing

Added a couple of tests and example (`animation_events.rs`) to make sure
events are triggered when expected.

---

## Showcase

`Events` need to also implement `AnimationEvent` and `Reflect` to be
used with animations.

```rust
#[derive(Event, AnimationEvent, Reflect)]
struct SomeEvent;
```

Events can be added to an `AnimationClip` by specifying a time and
event.

```rust
// trigger an event after 1.0 second
animation_clip.add_event(1.0, SomeEvent);
```

And optionally, providing a target id.

```rust
let id = AnimationTargetId::from_iter(["shoulder", "arm", "hand"]);
animation_clip.add_event_to_target(id, 1.0, HandEvent);
```

I modified the `animated_fox` example to show off the feature.

![CleanShot 2024-10-05 at 02 41
57](https://github.com/user-attachments/assets/0bb47db7-24f9-4504-88f1-40e375b89b1b)

---------

Co-authored-by: Matty <weatherleymatthew@gmail.com>
Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-10-06 10:03:05 +00:00
Joona Aalto
25bfa80e60
Migrate cameras to required components (#15641)
# Objective

Yet another PR for migrating stuff to required components. This time,
cameras!

## Solution

As per the [selected
proposal](https://hackmd.io/tsYID4CGRiWxzsgawzxG_g#Combined-Proposal-1-Selected),
deprecate `Camera2dBundle` and `Camera3dBundle` in favor of `Camera2d`
and `Camera3d`.

Adding a `Camera` without `Camera2d` or `Camera3d` now logs a warning,
as suggested by Cart [on
Discord](https://discord.com/channels/691052431525675048/1264881140007702558/1291506402832945273).
I would personally like cameras to work a bit differently and be split
into a few more components, to avoid some footguns and confusing
semantics, but that is more controversial, and shouldn't block this core
migration.

## Testing

I ran a few 2D and 3D examples, and tried cameras with and without
render graphs.

---

## Migration Guide

`Camera2dBundle` and `Camera3dBundle` have been deprecated in favor of
`Camera2d` and `Camera3d`. Inserting them will now also insert the other
components required by them automatically.
2024-10-05 01:59:52 +00:00
Viktor Gustavsson
f86ee32576
Add UI GhostNode (#15341)
# Objective

- Fixes #14826 
- For context, see #15238

## Solution
Add a `GhostNode` component to `bevy_ui` and update all the relevant
systems to use it to traverse for UI children.

- [x] `ghost_hierarchy` module
  - [x] Add `GhostNode`
- [x] Add `UiRootNodes` system param for iterating (ghost-aware) UI root
nodes
- [x] Add `UiChildren` system param for iterating (ghost-aware) UI
children
- [x] Update `layout::ui_layout_system`
  - [x] Use ghost-aware root nodes for camera updates
  - [x] Update and remove children in taffy
    - [x] Initial spawn
    - [x] Detect changes on nested UI children
- [x] Use ghost-aware children traversal in
`update_uinode_geometry_recursive`
- [x] Update the rest of the UI systems to use the ghost hierarchy
  - [x] `stack::ui_stack_system`
  - [x] `update::`
    - [x] `update_clipping_system`
    - [x] `update_target_camera_system`
  - [x] `accessibility::calc_name`

## Testing
- [x] Added a new example `ghost_nodes` that can be used as a testbed.
- [x] Added unit tests for _some_ of the traversal utilities in
`ghost_hierarchy`
- [x] Ensure this fulfills the needs for currently known use cases
  - [x] Reactivity libraries (test with `bevy_reactor`)
- [ ] Text spans (mentioned by koe [on
discord](https://discord.com/channels/691052431525675048/1285371432460881991/1285377442998915246))
  
---
## Performance
[See comment
below](https://github.com/bevyengine/bevy/pull/15341#issuecomment-2385456820)

## Migration guide
Any code that previously relied on `Parent`/`Children` to iterate UI
children may now want to use `bevy_ui::UiChildren` to ensure ghost nodes
are skipped, and their first descendant Nodes included.

UI root nodes may now be children of ghost nodes, which means
`Without<Parent>` might not query all root nodes. Use
`bevy_ui::UiRootNodes` where needed to iterate root nodes instead.

## Potential future work
- Benchmarking/optimizations of hierarchies containing lots of ghost
nodes
- Further exploration of UI hierarchies and markers for root nodes/leaf
nodes to create better ergonomics for things like `UiLayer` (world-space
ui)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
2024-10-02 00:24:28 +00:00
Litttle_fish
e924df0e1a
Add features to switch NativeActivity and GameActivity usage (#12095)
# Objective

Add two features to switch bevy to use `NativeActivity` or
`GameActivity` on Android, use `GameActivity` by default.

Also close  #12058 and probably #12026 .

## Solution

Add two features to the corresponding crates so you can toggle it, like
what `winit` and `android-activity` crate did.

---

## Changelog

Removed default `NativeActivity` feature implementation for Android,
added two new features to enable `NativeActivity` and `GameActivity`,
and use `GameActivity` by default.

## Migration Guide

Because `cargo-apk` is not compatible with `GameActivity`,
building/running using `cargo apk build/run -p bevy_mobile_example` is
no longer possible.
Users should follow the new workflow described in document.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Rich Churcher <rich.churcher@gmail.com>
2024-10-01 22:23:48 +00:00