Commit graph

5849 commits

Author SHA1 Message Date
ickshonpe
aab36f3951
UI anti-aliasing fix (#16181)
# Objective

UI Anti-aliasing is incorrectly implemented. It always uses an edge
radius of 0.25 logical pixels, and ignores the physical resolution. For
low dpi screens 0.25 is is too low and on higher dpi screens the
physical edge radius is much too large, resulting in visual artifacts.

## Solution

Multiply the distance by the scale factor in the `antialias` function so
that the edge radius stays constant in physical pixels.

## Testing

To see the problem really clearly run the button example with `UiScale`
set really high. With `UiScale(25.)` on main if you examine the button's
border you can see a thick gradient fading away from the edges:

<img width="127" alt="edgg"
src="https://github.com/user-attachments/assets/7c852030-c0e8-4aef-8d3e-768cb2464cab">

With this PR the edges are sharp and smooth at all scale factors: 

<img width="127" alt="edge"
src="https://github.com/user-attachments/assets/b3231140-1bbc-4a4f-a1d3-dde21f287988">
2024-11-13 21:41:02 +00:00
ickshonpe
c0fbadbc4c
Text2d scalefactor change detection fix (#16264)
# Objective 

Text2d doesn't respond to changes to the window scalefactor.

Fixes #16223

## Solution 

In `update_text2d_layout` store the previous scale factor in a `Local`
instead and check against the current scale factor to detect changes.

It seems like previously the text wasn't updated because of a bug with
the `WindowScaleFactorChanged` event and it isn't emitted after changes
to the scale factor. That needs to be looked into, but this will work
for now.

## Testing

Really simple app that draws a big message in the middle of the window:

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

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

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d);
    commands.spawn((
        Text2d::new("Hello"),
        TextFont {
            font_size: 400.,
            ..Default::default()
        },
    ));
}
```

Looks fine:
<img width="500" alt="hello1"
src="https://github.com/user-attachments/assets/5320746b-687e-4682-9e4c-bc43ab7ff9d3">

On main, after changing the monitor's scale factor:
<img width="500" alt="hello2"
src="https://github.com/user-attachments/assets/486cea16-fc44-4d66-9468-6f68905d4196">


With this PR the text maintains the same size and position after the
scale factor is changed.
2024-11-13 21:22:20 +00:00
Rich Churcher
bf9971f239
Minor docs fixes (#16347)
Happened upon a few stray characters while reading about picking.
2024-11-13 20:42:53 +00:00
Volodymyr Enhelhardt
db1915a1f0
Use the fully qualified name for Component in the require attribute (#16378)
# Objective

- Describe the objective or issue this PR addresses.
Use the fully qualified name for `Component` in the `require` attribute

- If you're fixing a specific issue, say "Fixes #X".
Fixes #16377

## Solution

- Describe the solution used to achieve the objective above.
Use the fully qualified name for `Component` in the `require` attribute,
i.e.,`<#ident as #bevy_ecs_path::component::Component>`

## Testing

- Did you test these changes? If so, how?
`cargo run -p ci -- lints`
`cargo run -p ci -- compile`
`cargo run -p ci -- test`
- 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?
try to compile
```rust
#[derive(::bevy::ecs::component::Component, Default)]
pub struct A;

#[derive(::bevy::ecs::component::Component)]
#[require(A)]
pub struct B;
```
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Mac only
---


</details>

## Migration Guide

> This section is optional. If there are no breaking changes, you can
delete this section.

- If this PR is a breaking change (relative to the last release of
Bevy), describe how a user might need to migrate their code to support
these changes
- Simply adding new functionality is not a breaking change.
- Fixing behavior that was definitely a bug, rather than a questionable
design choice is not a breaking change.

Co-authored-by: Volodymyr Enhelhardt <volodymyr.enhelhardt@ambr.net>
2024-11-13 20:37:50 +00:00
Carter Anderson
7477928f13
Use normal constructors for EasingCurve, FunctionCurve, ConstantCurve (#16367)
# Objective

We currently use special "floating" constructors for `EasingCurve`,
`FunctionCurve`, and `ConstantCurve` (ex: `easing_curve`). This erases
the type being created (and in general "what is happening"
structurally), for very minimal ergonomics improvements. With rare
exceptions, we prefer normal `X::new()` constructors over floating `x()`
constructors in Bevy. I don't think this use case merits special casing
here.

## Solution

Add `EasingCurve::new()`, use normal constructors everywhere, and remove
the floating constructors.

I think this should land in 0.15 in the interest of not breaking people
later.
2024-11-13 15:30:05 +00:00
ickshonpe
7b935c424b
Trivial bevy_picking refactor (#16374)
# Objective

Remove the rebinding and use `Rect::contains` in
`bevy_picking::pointer::Location::is_in_viewport`.
2024-11-13 14:09:17 +00:00
Rob Grindeland
a8c610a52d
Add unregister_system command (#16340)
# Objective

Fixes #16266 

## Solution

Added an `UnregisterSystem` command struct and
`Commands::unregister_system`. Also renamed `World::remove_system` and
`World::remove_system_cached` to `World::unregister_*`

## Testing

It's a fairly simple change, but I tested locally to ensure it actually
works.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2024-11-12 22:49:29 +00:00
François Mockers
4225848b0a
undeprecate component_reads_and_writes (#16357)
# Objective

- Does not correct #16339 but takes it out of the 0.15 milestone

## Solution

- Make it future us problem instead of solving it now
2024-11-11 23:28:16 +00:00
Brett Striker
0dea47e90f
Fix not being able to run bevy_ui tests (#16358)
# Objective

Fixes #16316

## Solution

Tweaked a few crates cargo files until I was able to build and test
`bevy_ui` via `cargo test --package bevy_ui`

## Testing

- ran `cargo test --package bevy_ui` successfully
- CI should catch anything amiss (Hopefully?)
2024-11-11 22:50:56 +00:00
ickshonpe
820a64fc7e
Remove the measure func for image nodes with the default UI texture (#16351)
# Objective

`ButtonBundle` has an `ImageNode` component (renamed from `UiImage`)
which wasn't a problem in 0.14 but in 0.15 `requires` pulls in the
`ContentSize` and `NodeImageSize` which means that by default
`ButtonBundle` nodes are given a measure func based on the size of the
image belonging to `TRANSPARENT_IMAGE_HANDLE`, which is 1x1.

This doesn't make sense and the behaviour for default image nodes should
either be to go to zero size or not add a measure func.

## Solution

Check if an image has a `TRANSPARENT_IMAGE_HANDLE` and if it does remove
its measure func.

Possibly a zero-sized measure would make more sense, but that would
break existing code.

## Testing

Used `ButtonBundle` in the 0.15 `button` example and the border doesn't
render, after this change it does.
2024-11-11 22:07:49 +00:00
UkoeHB
33abd3e7f4
Fix panic in UiSurface if Node is removed and re-added (#16288)
# Objective

- Fix bug where `UiSurface::set_camera_children` (and
`UiSurface::update_children` sometimes) will panic if you remove and add
a `Node` component in a single tick. This is more likely to happen now
because of `remove_with_requires`.

## Solution

- Filter out entities with `Node` when cleaning up entities from
`RemovedComponents<Node>`.

## Testing

- Not tested (rust compiler refused to cooperate when I tried to patch
this into my project), correct by inspection.
2024-11-11 21:59:56 +00:00
Logic
bafb9a25fb
Support on_thread_spawn and on_thread_destroy for TaskPoolPlugin (#13045)
# Objective

- Allow to configure `on_thread_spawn` and `on_thread_destroy` when
using `TaskPoolPlugin` of bevy.

## Solution

- In `TaskPoolThreadAssignmentPolicy`, two options `on_thread_spawn` and
`on_thread_destroy` are added, which will be passed to two new methods
motioned above when creating corresponding task pool using builder.
- Due to lack of debug derive for these two options, manually implement
the debug for `TaskPoolThreadAssignmentPolicy`.

---

## Changelog

### Added
- `on_thread_spawn` option and `on_thread_destroy` option to the
`TaskPoolPlugin`, allow user to customize them as needed.

## Migration Guide

- `TaskPooolThreadAssignmentPolicy` now has two additional fields:
`on_thread_spawn` and `on_thread_destroy`. Please consider defaulting
them to `None`.

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-11-11 20:00:01 +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
aad1fc6eba
Fix missing import (#16337)
# Objective

Should compile successfully with any combination of features

## Solution

Add the missing import on the right cfg.

## Testing

Tested building locally.

Fixes https://github.com/bevyengine/bevy/issues/16352
2024-11-11 18:48:41 +00:00
Joona Aalto
3ada15ee1c
Add more Glam types and constructors to prelude (#16261)
# Objective

Glam has some common and useful types and helpers that are not in the
prelude of `bevy_math`. This includes shorthand constructors like
`vec3`, or even `Vec3A`, the aligned version of `Vec3`.

```rust
// The "normal" way to create a 3D vector
let vec = Vec3::new(2.0, 1.0, -3.0);

// Shorthand version
let vec = vec3(2.0, 1.0, -3.0);
```

## Solution

Add the following types and methods to the prelude:

- `vec2`, `vec3`, `vec3a`, `vec4`
- `uvec2`, `uvec3`, `uvec4`
- `ivec2`, `ivec3`, `ivec4`
- `bvec2`, `bvec3`, `bvec3a`, `bvec4`, `bvec4a`
- `mat2`, `mat3`, `mat3a`, `mat4`
- `quat` (not sure if anyone uses this, but for consistency)
- `Vec3A`
- `BVec3A`, `BVec4A`
- `Mat3A`

I did not add the u16, i16, or f64 variants like `dvec2`, since there
are currently no existing types like those in the prelude.

The shorthand constructors are currently used a lot in some places in
Bevy, and not at all in others. In a follow-up, we might want to
consider if we have a preference for the shorthand, and make a PR to
change the codebase to use it more consistently.
2024-11-11 18:47:16 +00:00
Sou1gh0st
b83c0e106e
Add EntityMut::get_mut_by_id_unchecked (#16210)
# Objective

- Fixes: #15603 

## Solution

- Add an unsafe `get_mut_by_id_unchecked` to `EntityMut` that borrows
&self instead of &mut self, thereby allowing access to multiple
components simultaneously.

## Testing

- a unit test function `get_mut_by_id_unchecked` was added.

---------

Co-authored-by: Mike <mike.hsu@gmail.com>
2024-11-11 18:46:47 +00:00
aecsocket
57931ce42f
bevy_reflect: Add ReflectDeserializerProcessor (#15482)
**NOTE: Also see https://github.com/bevyengine/bevy/pull/15548 for the
serializer equivalent**

# Objective

The current `ReflectDeserializer` and `TypedReflectDeserializer` use the
`TypeRegistration` and/or `ReflectDeserialize` of a given type in order
to determine how to deserialize a value of that type. However, there is
currently no way to statefully override deserialization of a given type
when using these two deserializers - that is, to have some local data in
the same scope as the `ReflectDeserializer`, and make use of that data
when deserializing.

The motivating use case for this came up when working on
[`bevy_animation_graph`](https://github.com/aecsocket/bevy_animation_graph/tree/feat/dynamic-nodes),
when loading an animation graph asset. The `AnimationGraph` stores
`Vec<Box<dyn NodeLike>>`s which we have to load in. Those `Box<dyn
NodeLike>`s may store `Handle`s to e.g. `Handle<AnimationClip>`. I want
to trigger a `load_context.load()` for that handle when it's loaded.
```rs
#[derive(Reflect)]
struct Animation {
    clips: Vec<Handle<AnimationClip>>,
}
```
```rs
(
    clips: [
        "animation_clips/walk.animclip.ron",
        "animation_clips/run.animclip.ron",
        "animation_clips/jump.animclip.ron",
    ],
)
````
Currently, if this were deserialized from an asset loader, this would be
deserialized as a vec of `Handle::default()`s, which isn't useful since
we also need to `load_context.load()` those handles for them to be used.
With this processor field, a processor can detect when `Handle<T>`s are
being loaded, then actually load them in.

## Solution

```rs
trait ReflectDeserializerProcessor {
    fn try_deserialize<'de, D>(
        &mut self,
        registration: &TypeRegistration,
        deserializer: D,
    ) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
    where
        D: serde::Deserializer<'de>;
}
```
```diff
- pub struct ReflectDeserializer<'a> {
+ pub struct ReflectDeserializer<'a, P = ()> { // also for ReflectTypedDeserializer
      registry: &'a TypeRegistry,
+     processor: Option<&'a mut P>,
  }
```
```rs
impl<'a, P: ReflectDeserializerProcessor> ReflectDeserializer<'a, P> { // also for ReflectTypedDeserializer
    pub fn with_processor(registry: &'a TypeRegistry, processor: &'a mut P) -> Self {
        Self {
            registry,
            processor: Some(processor),
        }
    }
}
```
This does not touch the existing `fn new`s.
This `processor` field is also added to all internal visitor structs.

When `TypedReflectDeserializer` runs, it will first try to deserialize a
value of this type by passing the `TypeRegistration` and deserializer to
the processor, and fallback to the default logic. This processor runs
the earliest, and takes priority over all other deserialization logic.

## Testing

Added unit tests to `bevy_reflect::serde::de`. Also using almost exactly
the same implementation in [my fork of
`bevy_animation_graph`](https://github.com/aecsocket/bevy_animation_graph/tree/feat/dynamic-nodes).

## Migration Guide

(Since I added `P = ()`, I don't think this is actually a breaking
change anymore, but I'll leave this in)

`bevy_reflect`'s `ReflectDeserializer` and `TypedReflectDeserializer`
now take a `ReflectDeserializerProcessor` as the type parameter `P`,
which allows you to customize deserialization for specific types when
they are found. However, the rest of the API surface (`new`) remains the
same.

<details>
<summary>Original implementation</summary>

Add `ReflectDeserializerProcessor`:
```rs
struct ReflectDeserializerProcessor {
    pub can_deserialize: Box<dyn FnMut(&TypeRegistration) -> bool + 'p>,
    pub deserialize: Box<
        dyn FnMut(
                &TypeRegistration,
                &mut dyn erased_serde::Deserializer,
            ) -> Result<Box<dyn PartialReflect>, erased_serde::Error>
            + 'p,
}
``` 

Along with `ReflectDeserializer::new_with_processor` and
`TypedReflectDeserializer::new_with_processor`. This does not touch the
public API of the existing `new` fns.

This is stored as an `Option<&mut ReflectDeserializerProcessor>` on the
deserializer and any of the private `-Visitor` structs, and when we
attempt to deserialize a value, we first pass it through this processor.

Also added a very comprehensive doc test to
`ReflectDeserializerProcessor`, which is actually a scaled down version
of the code for the `bevy_animation_graph` loader. This should give
users a good motivating example for when and why to use this feature.

### Why `Box<dyn ..>`?

When I originally implemented this, I added a type parameter to
`ReflectDeserializer` to determine the processor used, with `()` being
"no processor". However when using this, I kept running into rustc
errors where it failed to validate certain type bounds and led to
overflows. I then switched to a dynamic dispatch approach.

The dynamic dispatch should not be that expensive, nor should it be a
performance regression, since it's only used if there is `Some`
processor. (Note: I have not benchmarked this, I am just speculating.)
Also, it means that we don't infect the rest of the code with an extra
type parameter, which is nicer to maintain.

### Why the `'p` on `ReflectDeserializerProcessor<'p>`?

Without a lifetime here, the `Box`es would automatically become `Box<dyn
FnMut(..) + 'static>`. This makes them practically useless, since any
local data you would want to pass in must then be `'static`. In the
motivating example, you couldn't pass in that `&mut LoadContext` to the
function.

This means that the `'p` infects the rest of the Visitor types, but this
is acceptable IMO. This PR also elides the lifetimes in the `impl<'de>
Visitor<'de> for -Visitor` blocks where possible.

### Future possibilities

I think it's technically possible to turn the processor into a trait,
and make the deserializers generic over that trait. This would also open
the door to an API like:
```rs
type Seed;

fn seed_deserialize(&mut self, r: &TypeRegistration) -> Option<Self::Seed>;

fn deserialize(&mut self, r: &TypeRegistration, d: &mut dyn erased_serde::Deserializer, s: Self::Seed) -> ...;
```

A similar processor system should also be added to the serialization
side, but that's for another PR. Ideally, both PRs will be in the same
release, since one isn't very useful without the other.

## Testing

Added unit tests to `bevy_reflect::serde::de`. Also using almost exactly
the same implementation in [my fork of
`bevy_animation_graph`](https://github.com/aecsocket/bevy_animation_graph/tree/feat/dynamic-nodes).

## Migration Guide

`bevy_reflect`'s `ReflectDeserializer` and `TypedReflectDeserializer`
now take a second lifetime parameter `'p` for storing the
`ReflectDeserializerProcessor` field lifetimes. However, the rest of the
API surface (`new`) remains the same, so if you are not storing these
deserializers or referring to them with lifetimes, you should not have
to make any changes.

</details>
2024-11-11 18:46:23 +00:00
Tim
03991cd595
Rename Rot2::angle_between to Rot2::angle_to (#16327)
# Objective

`glam` has opted to rename `Vec2::angle_between` to `Vec2::angle_to`
because of the difference in semantics compared to `Vec3::angle_between`
and others which return an unsigned angle `[0, PI]` where
`Vec2::angle_between` returns a signed angle `[-PI, PI]`.
We should follow suit for `Rot2` in 0.15 to avoid further confusion.

Links:
-
https://github.com/bitshifter/glam-rs/issues/514#issuecomment-2143202294
- https://github.com/bitshifter/glam-rs/pull/524

## Migration Guide

`Rot2::angle_between` has been deprecated, use `Rot2::angle_to` instead,
the semantics of `Rot2::angle_between` will change in the future.

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2024-11-10 14:36:48 +00:00
Benjamin Brienen
40640fdf42
Don't reëxport bevy_image from bevy_render (#16163)
# Objective

Fixes #15940

## Solution

Remove the `pub use` and fix the compile errors.
Make `bevy_image` available as `bevy::image`.

## Testing

Feature Frenzy would be good here! Maybe I'll learn how to use it if I
have some time this weekend, or maybe a reviewer can use it.

## Migration Guide

Use `bevy_image` instead of `bevy_render::texture` items.

---------

Co-authored-by: chompaa <antony.m.3012@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-11-10 06:54:38 +00:00
Knar
1e3ecbefdb
Handle failed cursor grab mode changes so that the cursor grab mode change can be attempted again (#16293)
# Objective

- Currently when you attempt to change the cursor_grab_mode it caches
the new value whether the cursor grab succeeded or failed. This change
handles the Result being returned by set_cursor_grab and changes the
cursor_grab_mode back to the cached version in case of an Error.
- Creates a way to handle #16237 and #16238

## Solution

- I changed the signature of winit_windows attempt_grab to return the
Result<(), ExternalError> that winit set_cursor_grab returns. The system
that calls attempt_grab now checks if there's an error returned, and if
there is it sets the grab_mode back to the cached version (similar to
what hit_test does a few lines down).

## Testing

- I tested using this system that previously would not correctly lock
the mouse on Ubuntu/x11
```
pub fn lock_mouse(mut primary_window: Query<&mut Window, With<PrimaryWindow>>) {
    let window = &mut primary_window.single_mut();
    if window.focused {
        window.cursor_options.grab_mode = CursorGrabMode::Confined;
    } else {
        window.cursor_options.grab_mode = CursorGrabMode::None;
    }
}
```
- I only tested on Ubuntu with x11
2024-11-09 23:30:57 +00:00
AxiomaticSemantics
ef9427727f
Fix permissions of rust source files (#16310)
# Objective

- Permissions of some rust source files are incorrect.

## Solution
- chmod 644 instead of 755

Co-authored-by: _ <>
2024-11-09 16:34:38 +00:00
s-puig
5cbc2a9018
Reflect TextLayout and ComputedTextBlock (#16296)
# Objective

- Fix panic when saving/loading scenes with text nodes due to missing
Reflect implementations.
2024-11-08 22:36:31 +00:00
Benjamin Brienen
56a002b693
Return Error instead of panicking when reading invalid dds file (#16283)
# Objective

Fixes #15928

## Solution

return Error instead of panic

## Testing

I don't know if we need to add a test for this. It is pretty
straightforward.
2024-11-08 21:55:34 +00:00
atlv
c29e67153b
Expose Pipeline Compilation Zero Initialize Workgroup Memory Option (#16301)
# Objective

- wgpu 0.20 made workgroup vars stop being zero-init by default. this
broke some applications (cough foresight cough) and now we workaround
it. wgpu exposes a compilation option that zero initializes workgroup
memory by default, but bevy does not expose it.

## Solution

- expose the compilation option wgpu gives us

## Testing

- ran examples: 3d_scene, compute_shader_game_of_life, gpu_readback,
lines, specialized_mesh_pipeline. they all work
- confirmed fix for our own problems

---

</details>

## Migration Guide

- add `zero_initialize_workgroup_memory: false,` to
`ComputePipelineDescriptor` or `RenderPipelineDescriptor` structs to
preserve 0.14 functionality, add `zero_initialize_workgroup_memory:
true,` to restore bevy 0.13 functionality.
2024-11-08 21:42:37 +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
Zachary Harrold
d143da338a
Fixed issue with derive_more Display Implementations (#16298)
# Objective

- Fixed issue where `thiserror` `#[error(...)]` attributes were
improperly converted to `derive_more` `#[display(...)]` equivalents in
certain cases with a tuple struct/enum variant.

## Solution

- Used `re/#\[display\(.*\{[0-9]+\}.*\)\]/` to find occurences of using
`{0}` where `{_0}` was intended (checked for other field indexes too)and
updated accordingly.

## Testing

- `cargo check`
- CI

## Notes

This was discovered by @dtolnay in [this
comment](https://github.com/bevyengine/bevy/pull/15772#discussion_r1833730555).
2024-11-08 20:29:52 +00:00
Carter Anderson
013e11a14f
AudioPlayer::new() (#16287)
# Objective

`AudioPlayer::<AudioSource>(assets.load("audio.mp3"))` is awkward and
complicated to type because the `AudioSource` generic type cannot be
elided. This is especially annoying because `AudioSource` is used in the
majority of cases. Most users don't need to think about it.

## Solution

Add an `AudioPlayer::new()` function that is hard-coded to
`AudioSource`, allowing `AudioPlayer::new(assets.load("audio.mp3"))`.
Prefer using that in the relevant places.
2024-11-08 01:51:50 +00:00
Asier Illarramendi
2b434035b7
Fix typos in bevy_picking module docs (#16265)
# Objective

- Fix typo: `ovserver` => `observer`

---------

Co-authored-by: Thierry Berger <contact@thierryberger.com>
2024-11-08 01:15:44 +00:00
Carter Anderson
f754cecb49
UiImage -> ImageNode, UiImageSize -> ImageNodeSize (#16271)
# Objective

Align `UiImage` with the new `XNode` naming convention.

## Solution

- Rename `UiImage` to `ImageNode`
- Rename `UiImageSize` to `ImageNodeSize`

---

## Migration Guide

Before:
```rust
commands.spawn(UiImage::new(image));
````

After:
```rust
commands.spawn(ImageNode::new(image));
```
2024-11-07 21:52:58 +00:00
Matty
9beb1d96e7
Incorporate all node weights in additive blending (#16279)
# Objective

In the existing implementation, additive blending effectively treats the
node with least index specially by basically forcing its weight to be
`1.0` regardless of what its computed weight would be (based on the
weights in the `AnimationGraph` and `AnimationPlayer`).

Arguably this makes some amount of sense, because the "base" animation
is often one which was not authored to be used additively, meaning that
its sampled values are interpreted absolutely rather than as deltas.
However, this also leads to strange behavior with respect to animation
masks: if the "base" animation is masked out on some target, then the
next node is treated as the "base" animation, despite the fact that it
would normally be interpreted additively, and the weight of that
animation is thrown away as a result.

This is all kind of weird and revolves around special treatment (if the
behavior is even really intentional in the first place). From a
mathematical standpoint, there is nothing special about how the "base"
animation must be treated other than having a weight of 1.0 under an
`Add` node, which is something that the user can do without relying on
some bizarre corner-case behavior of the animation system — this is the
only present situation under which weights are discarded.

This PR changes this behavior so that the weight of every node is
incorporated. In other words, for an animation graph that looks like
this:
```text
┌───────────────┐                                 
│Base clip      ┼──┐                              
│      0.5      │  │                              
└───────────────┘  │                              
┌───────────────┐  │  ┌───────────────┐     ┌────┐
│Additive clip 1┼──┼─►┤Additive blend ┼────►│Root│
│      0.1      │  │  │      1.0      │     └────┘
└───────────────┘  │  └───────────────┘           
┌───────────────┐  │                              
│Additive clip 2┼──┘                              
│      0.2      │                                 
└───────────────┘                                 
```

Previously, the result would have been
```text
base_clip + 0.1 * additive_clip_1 + 0.2 * additive_clip_2
```

whereas now it would be
```text
0.5 * base_clip + 0.1 * additive_clip_1 + 0.2 * additive_clip_2
```

and in the scenario where `base_clip` is masked out:
```text
additive_clip_1 + 0.2 * additive_clip_2
```
vs.
```text
0.1 * additive_clip_1 + 0.2 * additive_clip_2
```

## Solution

For background, the way that the additive blending procedure works is
something like this:
- During graph traversal, the node values and weights of the children
are pushed onto the evaluator `stack`. The traversal order guarantees
that the item with least node index will be on top.
- Once we reach the `Add` node itself, we start popping off the `stack`
and into the evaluator's `blend_register`, which is an accumulator
holding up to one weight-value pair:
- If the `blend_register` is empty, it is filled using data from the top
of the `stack`.
- Otherwise, the `blend_register` is combined with data popped from the
`stack` and updated.

In the example above, the additive blending steps would look like this
(with the pre-existing implementation):
1. The `blend_register` is empty, so we pop `(base_clip, 0.5)` from the
top of the `stack` and put it in. Now the value of the `blend_register`
is `(base_clip, 0.5)`.
2. The `blend_register` is non-empty: we pop `(additive_clip_1, 0.1)`
from the top of the `stack` and combine it additively with the value in
the `blend_register`, forming `(base_clip + 0.1 * additive_clip_1, 0.6)`
in the `blend_register` (the carried weight value goes unused).
3. The `blend_register` is non-empty: we pop `(additive_clip_2, 0.2)`
from the top of the `stack` and combine it additively with the value in
the `blend_register`, forming `(base_clip + 0.1 * additive_clip_1 + 0.2
* additive_clip_2, 0.8)` in the `blend_register`.

The solution in this PR changes step 1: the `base_clip` is multiplied by
its weight as it is added to the `blend_register` in the first place,
yielding `0.5 * base_clip + 0.1 * additive_clip_1 + 0.2 *
additive_clip_2` as the final result.

### Note for reviewers

It might be tempting to look at the code, which contains a segment that
looks like this:
```rust
if additive {
    current_value = A::blend(
        [
            BlendInput {
                weight: 1.0, // <--
                value: current_value,
                additive: true,
            },
            BlendInput {
                weight: weight_to_blend,
                value: value_to_blend,
                additive: true,
            },
        ]
        .into_iter(),
    );
} 
```
and conclude that the explicit value of `1.0` is responsible for
overwriting the weight of the base animation. This is incorrect.

Rather, this additive blend has to be written this way because it is
multiplying the *existing value in the blend register* by 1 (i.e. not
doing anything) before adding the next value to it. Changing this to
another quantity (e.g. the existing weight) would cause the value in the
blend register to be spuriously multiplied down.

## Testing

Tested on `animation_masks` example. Checked `morph_weights` example as
well.

## Migration Guide

I will write a migration guide later if this change is not included in
0.15.
2024-11-07 19:12:08 +00:00
Benjamin Brienen
1e1b6e5b6d
Make BinnedRenderPhase fields for accessing batchable and unbatchable entities public (#16142)
# Objective

Fixes #16080

## Solution

Make the fields and struct pub as per the suggested solution.

## Testing

None
2024-11-07 18:03:47 +00:00
Hennadii Chernyshchyk
e53aaddf96
Make ComponentTicks field public (#16269)
# Objective

After #12929 we no longer have methods to get component or ticks for
previously obtained table column.
It's possible to use a lower level API by indexing the slice, but then
it won't be possible to construct `ComponentTicks`.

## Solution

Make `ComponentTicks` fields public. They don't hold any invariants and
you can't get a mutable reference to the struct in Bevy.

I also removed the getters since they are no longer needed.

## Testing

- I tested the compilation

---

## Migration Guide

- Instead of using `ComponentTicks::last_changed_tick` and
`ComponentTicks::added_tick` methods, access fields directly.
2024-11-06 22:21:04 +00:00
Chris Russell
a967c75e92
Enable EntityRef tests that now pass. (#16263)
# Objective

Re-enable some tests in `entity_ref.rs` that are marked as `#[ignore]`,
but that pass after #14561.

## Solution

Remove `#[ignore]` from those tests.
2024-11-06 16:10:55 +00:00
ickshonpe
619c5e3bda
Require ContentSize for UiImage (#16262)
# Objective

Automatic imaging sizing for image nodes isn't working because the the
`ContentSize` requirement for `UiImage` got lost in some merge again.

Fixes #16239 
Fixes #16240 
Fixes the missing images seen in #16241

## Solution

Require `ContentSize` for `UiImage`.
2024-11-06 14:56:28 +00:00
François Mockers
eb558bbf77
properly flag using CustomCursor::Url in wasm (#16255)
# Objective

- Fixes #16254 
- fix building in wasm without custom_cursor

## Solution

- Properly flag `CustomCursor::Url` which only exist in wasm, but also
only when `custom_cursor` is enabled

## Testing

- `cargo check --target wasm32-unknown-unknown -p bevy_winit`
2024-11-06 13:14:12 +00:00
Derick M
49f63ed2cf
chore(deps): remove unused uuid dependency from bevy_core (#16253)
# Objective

- Closes #16242 

## Solution

- Remove unused `uuid` dep in `bevy_core` crate

## Testing

- ~~Awaiting CI~~ tested locally and it doesn't break anything
2024-11-05 23:31:58 +00:00
charlotte
4b05d2f4d8
Upgrade to wgpu 23 (#15988)
Fixes https://github.com/bevyengine/bevy/issues/15893

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2024-11-05 21:18:48 +00:00
Martín Maita
7fc8318b7f
BRP System Ordering (#16198)
# Objective

- Attempts to fix #16042

## Solution

- Added a new `RemoteSystem` `SystemSet` for the BRP systems.
- Changed the schedule on which these systems run from `Update` to
`Last`.

## Testing

- I did not test these changes and would appreciate a hand in doing so.
I assume it would be good to test that you can order against these
systems easily now.

---

## Migration Guide

- `process_remote_requests`, `process_ongoing_watching_requests` and
`remove_closed_watching_requests` now run in the `Last` schedule. Make
sure you use `RemoteSystem` `SystemSet` in case you need to order your
systems against them.
2024-11-05 21:05:11 +00:00
Martín Maita
a44b668b90
Bump crate-ci/typos from 1.26.8 to 1.27.0 (#16236)
# Objective

- Closes #16224

## Solution

- Bumps `crate-ci/typos@v1.26.8` to `crate-ci/typos@v1.27.0`.

## Testing

- CI checks should pass.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-05 01:33:27 +00:00
Hennadii Chernyshchyk
282ca735ba
Use Name component for gamepad (#16233)
# Objective

Addressing a suggestion I made in Discord: store gamepad name as a
`Name` component.
Advantages: 
- Will be nicely displayed in inspector / editor.
- Easier to spawn in tests, just `world.spawn(Gamepad::default())`.

## Solution

`Gamepad` component now stores only vendor and product IDs and `Name`
stores the gamepad name.
Since `GamepadInfo` is no longer necessary, I removed it and merged its
fields into the connection event.

## Testing

- Run unit tests.

---

## Migration Guide

- `GamepadInfo` no longer exists:
  -  Name now accesible via `Name` component.
  -  Other information available on `Gamepad` component directly.
  - `GamepadConnection::Connected` now stores all info fields directly.
2024-11-05 00:30:48 +00:00
Asier Illarramendi
718688e791
Use stack_z_offsets in all the cases we create a TransparentUi (#16197)
# Objective

Use same pattern when creating `TransparentUi` items where the
`sort_key` is the `UiNode` stack index + some offset.

## Solution

Refactored to follow same pattern.

## Testing

Ran few UI examples.

## Doubts

Maybe `stack_z_offsets::BACKGROUND_COLOR` should be renamed. This is
used for `ExtractedUiNode`, which is not only used for "background
color" it's also used to render borders, images and text (I think).
2024-11-04 22:18:41 +00:00
Miles Silberling-Cook
50dde9b0a7
Expose picking pointer state as a resource (#16229)
In `bevy_mod_picking` events are driven by several interlocking state
machines, which read and write events, and share state in a few common
resources. When I merged theses state machines into one to make event
ordering work properly, I combined this state and hid it in a `Local`.

This PR exposes the state in a resource again. Also adds a simple little
API for it. Useful for adding debug UI.
2024-11-04 22:06:14 +00:00
Rich Churcher
7740c0f879
Support creating asset directories (#16220)
# Objective

Exposes a means to create an asset directory (and its parent
directories). Wasn't sure whether we also wanted the variant to create
directories without the parent (i.e. `mkdir` instead of `mkdir -p`)?

Fixes https://github.com/bevyengine/bevy_editor_prototypes/issues/144
2024-11-04 22:06:00 +00:00
Nolan Darilek
817f160d35
Bump accesskit and accesskit_winit. (#16234)
# Objective

- Bumps accesskit and accesskit_winit dependencies

## Solution

- Fixes several breaking API changes introduced in accesskit 0.23.

## Testing

- Tested with the ui example and seems to work comparably
2024-11-04 20:07:38 +00:00
Hennadii Chernyshchyk
b0058dc54b
Gamepad improvements (#16222)
# Objective

Closes #16221.

## Solution

- Make `Gamepad` fields public and remove delegates / getters.
- Move `impl Into` to `Axis` methods (delegates for `Axis` used `impl
Into` to allow passing both `GamepadAxis` and `GamepadButton`).
- Improve docs.

## Testing

- I run tests.

Not sure if the migration guide is needed, since it's a feature from RC,
but I wrote it just in case.

---

## Migration Guide

- `Gamepad` fields are now public.
- Instead of using `Gamepad` delegates like `Gamepad::just_pressed`,
call these methods directly on the fields.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-11-04 17:05:24 +00:00
Derick M
8d24efe60c
Remove unused debug identifiers for ComponentHooks methods (#16228)
# Objective

- Cleans up unused debug identifiers for `ComponentHooks` methods:
`on_add`, `on_insert`, `on_replace`, and `on_remove`
 
## Solution

- Simplify the expect messages by removing the unused `{:?}`

## Testing

- Currently untested


[Context](https://discord.com/channels/691052431525675048/749335865876021248/1302988180592525362)
2024-11-04 15:41:07 +00:00
Sigma-dev
3c2830d607
Improved the global transform api to access rotation and scale (#16211)
# Objective

GlobalTransform's current methods make it unintuitive, long and clunky
to access just the rotation or just the scale.

## Solution

Dedicated just_rotation() and scale() methods to access just these
properties.

I'm not sure about the naming, I chose just_rotation() to show that try
to indicate there is a waste since it also computes the other fields.

## Testing

- Did you test these changes? If so, how?
I tried logging the methods with a rotating and scaling cube and the
values were correct.
- Are there any parts that need more testing?
My methods are based on existing bevy/glam methods so should be correct
from the getgo.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Probably the easiest is using the 3d_rotations example, adding scaling
to it and then logging the methods I added

---

## Showcase
```rust
fn log(gt_query: Query<&GlobalTransform>) {
        for global_transform in gt_query().iter() {
                   println!("{} {}", global_transform.just_rotation(), global_transform.scale());
        }
}
```

---------

Co-authored-by: Sigma-dev <antonin.programming@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-11-04 15:35:16 +00:00
Tim
b53ec4c35c
Fix WGSL formatting inconsistency on mesh_view_binding (#16202)
# Objective

- fix formatting issue in "mesh_view_binding.wgsl"

_note: As naga-oil preprocessor match the whole line when finding an
"#endif",
It's just for external formatting tool and consistency._

## Solution
Trivial change.
Add  '//' before the closing comment of the "#endif"
2024-11-04 15:32:38 +00:00
robtfm
262f471934
move mesh uniform construction out of Core3d (#16188)
# Objective

gpu based mesh uniform construction in the `GpuPreprocessNode` is
currently in `Core3d`. The node iterates all views and schedules the
uniform construction for each. so
- when there are multiple 3d cameras, it runs multiple times on each
view
- if a view wants to render meshes but doesn't use the `Core3d` graph,
the camera must run later than at least one `Core3d`-based camera (or
add the node to its own graph, duplicating the work)
- If views want to share mesh uniforms there is no way to avoid running
the preprocessing for every view

## Solution

- move the node to the top level of the rendergraph, before the camera
driver node
- make the `PreprocessBindGroup` `clone`able, and add a
`SkipGpuPreprocessing` component to allow opting out per view
2024-11-04 15:29:11 +00:00
Lennard
cd2d14c0fd
Fix blending for CameraOutputMode::Skip (#16157)
# Objective

Currently, if we have two cameras with the same output texture, one with
`CameraOutputMode::Write` and one with `CameraOutputMode::Skip`, it is
possible for the `CameraOutputMode::Write` camera to be assigned alpha
blending (which is the fallback blending when multiple cameras write to
the same output texture), although it is the only camera writing to the
output texture. This may or may not happen every restart of the app,
because the camera iteration order in prepare_view_upscaling_pipelines
isn't consistent. Since this is random behaviour I consider this a bug
and didn't add a migration guide.

## Solution

In `prepare_view_upscaling_pipelines` make sure we don't consider
cameras with CameraOutputMode::Skip to be outputting something to the
output texture.

## Testing

I ran a few examples to make sure nothing obvious is broken. There is no
example using CameraOutputMode::Skip, so I only tested the change in my
own App where this was relevant, which however isn't public.
2024-11-04 15:26:42 +00:00