Commit graph

773 commits

Author SHA1 Message Date
Rich Churcher
fd329c0426
Allow to expect (adopted) (#15301)
# Objective

> Rust 1.81 released the #[expect(...)] attribute, which works like
#[allow(...)] but throws a warning if the lint isn't raised. This is
preferred to #[allow(...)] because it tells us when it can be removed.

- Adopts the parts of #15118 that are complete, and updates the branch
so it can be merged.
- There were a few conflicts, let me know if I misjudged any of 'em.

Alice's
[recommendation](https://github.com/bevyengine/bevy/issues/15059#issuecomment-2349263900)
seems well-taken, let's do this crate by crate now that @BD103 has done
the lion's share of this!

(Relates to, but doesn't yet completely finish #15059.)

Crates this _doesn't_ cover:

- bevy_input
- bevy_gilrs
- bevy_window
- bevy_winit
- bevy_state
- bevy_render
- bevy_picking
- bevy_core_pipeline
- bevy_sprite
- bevy_text
- bevy_pbr
- bevy_ui
- bevy_gltf
- bevy_gizmos
- bevy_dev_tools
- bevy_internal
- bevy_dylib

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Ben Frankel <ben.frankel7@gmail.com>
Co-authored-by: Antony <antony.m.3012@gmail.com>
2024-09-20 19:16:42 +00:00
patrickariel
3efef59d83
Enable/disable UI anti-aliasing (#15170)
# Objective

Currently, UI is always rendered with anti-aliasing. This makes bevy's
UI completely unsuitable for art-styles that demands hard pixelated
edges, such as retro-style games.

## Solution

Add a component for disabling anti-aliasing in UI.

## Testing

In
[`examples/ui/button.rs`](15e246eff8/examples/ui/button.rs),
add the component to the camera like this:

```rust
use bevy::{prelude::*, ui::prelude::*};

commands.spawn((Camera2dBundle::default(), UiAntiAlias::Off));
```

The rounded button will now render without anti-aliasing.

## Showcase

An example of a rounded UI node rendered without anti-aliasing, with and
without borders:


![image](https://github.com/user-attachments/assets/ea797e40-bdaa-4ede-a0d3-c9a7eab95b6e)
2024-09-16 23:06:23 +00:00
Blazepaws
cb6ab16c97
Reflect derived traits on all components and resources: bevy_ui (#15231)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_ui
2024-09-15 17:52:38 +00:00
ickshonpe
1b1105e327
Remove border radius scaling (#15173)
# Objective

Fixes #15142

Split this off from #15163 as it's a very simple fix.

## Solution

UiScale was applied twice to border radius, remove the second
application.

## Testing

You can use this modified button example from the issue for testing:

```
use bevy::{color::palettes::basic::*, prelude::*, winit::WinitSettings};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        // Only run the app when there is user input. This will significantly reduce CPU/GPU use.
        .insert_resource(UiScale(2.))
        .insert_resource(WinitSettings::desktop_app())
        .add_systems(Startup, setup)
        .add_systems(Update, button_system)
        .run();
}

const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);

fn button_system(
    mut interaction_query: Query<
        (
            &Interaction,
            &mut BackgroundColor,
            &mut BorderColor,
            &Children,
        ),
        (Changed<Interaction>, With<Button>),
    >,
    mut text_query: Query<&mut Text>,
) {
    for (interaction, mut color, mut border_color, children) in &mut interaction_query {
        let mut text = text_query.get_mut(children[0]).unwrap();
        match *interaction {
            Interaction::Pressed => {
                text.sections[0].value = "Press".to_string();
                *color = PRESSED_BUTTON.into();
                border_color.0 = RED.into();
            }
            Interaction::Hovered => {
                text.sections[0].value = "Hover".to_string();
                *color = HOVERED_BUTTON.into();
                border_color.0 = Color::WHITE;
            }
            Interaction::None => {
                text.sections[0].value = "Button".to_string();
                *color = NORMAL_BUTTON.into();
                border_color.0 = Color::BLACK;
            }
        }
    }
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // ui camera
    commands.spawn(Camera2dBundle::default());
    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Percent(100.0),
                height: Val::Percent(100.0),
                align_items: AlignItems::Center,
                justify_content: JustifyContent::Center,
                ..default()
            },
            ..default()
        })
        .with_children(|parent| {
            parent
                .spawn(ButtonBundle {
                    style: Style {
                        width: Val::Px(250.0),
                        height: Val::Px(100.0),
                        border: UiRect::all(Val::Px(25.0)),
                        // horizontally center child text
                        justify_content: JustifyContent::Center,
                        // vertically center child text
                        align_items: AlignItems::Center,
                        ..default()
                    },
                    border_color: BorderColor(Color::BLACK),
                    border_radius: BorderRadius::all(Val::Px(25.)),
                    background_color: NORMAL_BUTTON.into(),
                    ..default()
                })
                .with_child(TextBundle::from_section(
                    "Button",
                    TextStyle {
                        font: asset_server.load("fonts/FiraSans-Bold.ttf"),
                        font_size: 40.0,
                        color: Color::srgb(0.9, 0.9, 0.9),
                    },
                ));
            parent
                .spawn(NodeBundle {
                    style: Style {
                        width: Val::Px(150.0),
                        padding: UiRect::vertical(Val::Px(25.)),
                        height: Val::Px(100.0),
                        align_items: AlignItems::Stretch,
                        justify_content: JustifyContent::Stretch,
                        ..Default::default()
                    },
                    ..default()
                })
                .with_child(NodeBundle {
                    style: Style {
                        flex_basis: Val::Percent(100.),
                        ..Default::default()
                    },
                    background_color: RED.into(),
                    ..Default::default()
                });
        });
}
```

## Showcase

Using the modified button example

### main

<img alt="366023197-e6124f07-e522-4514-bd8e-7986ac32890c"
src="https://github.com/user-attachments/assets/b7b909ed-1184-4d9d-b50b-e30f4c1f76b2">


### this PR

![image](https://github.com/user-attachments/assets/89b89a2f-533f-41bd-b2cb-4743aec6519e)
2024-09-13 15:52:42 +00:00
ickshonpe
cacf3929db
fix spelling mistake (#15146)
# Objective

Fix spelling mistake: `interned_root_notes` -> `interned_root_nodes`
2024-09-10 20:21:40 +00:00
ickshonpe
8d143e3ed8
ui material node border calculations fix (#15119)
# Objective

Fixes  #15115

## Solution

Retrieve the size of the node's parent in a separate query and base
percentage border values on the parent node's width (or the width of the
viewport in the case of root nodes).
2024-09-09 22:35:29 +00:00
ickshonpe
4de9edeaa6
Retrieve the stack_index from Node in extract_ui_material_nodes instead of walking UiStack (#15104)
# Objective

 `ExtractedUiMaterialNode` is still walking the whole `UiStack`. 

more info: https://github.com/bevyengine/bevy/pull/9853

## Solution

Retrieve the `stack_index` from the `Node` component instead.
Also changed the `stack_index` field of `ExtractedUiMaterialNode` to
`u32`.
2024-09-09 16:18:37 +00:00
Marco Meijer
66b5128b6f
Add rect field to UI image (#15095)
# Objective

Fixes #14424 

## Solution

Add a rect field to UiImage, and update the extraction of ui images and
slices.

## Testing

I tested all possible combinations of having a rect, using a texture
atlas, setting image scale mode to sliced and image scale mode to tiled.
See the showcase section.

---

## Showcase

<img width="1279" alt="Screenshot 2024-09-08 at 16 23 05"
src="https://github.com/user-attachments/assets/183e53eb-f27c-4c8e-9fd5-4678825db3b6">

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

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

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
        .add_systems(Startup, create_ui)
        .run();
}

fn create_ui(
    mut commands: Commands,
    assets: Res<AssetServer>,
    mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
) {
    let texture = assets.load("textures/fantasy_ui_borders/numbered_slices.png");
    let layout = TextureAtlasLayout::from_grid(UVec2::splat(16), 3, 3, None, None);
    let texture_atlas_layout = texture_atlas_layouts.add(layout);

    commands.spawn(Camera2dBundle::default());

    let style = Style {
        width: Val::Px(96.),
        height: Val::Px(96.),
        ..default()
    };

    commands
        .spawn(NodeBundle { ..default() })
        .with_children(|parent| {
            // nothing
            parent.spawn(ImageBundle {
                image: UiImage::new(texture.clone()),
                style: style.clone(),
                ..default()
            });

            // with rect
            parent.spawn(ImageBundle {
                image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 16., 16.)),
                style: style.clone(),
                ..default()
            });

            // with rect and texture atlas
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 8., 8.)),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 1,
                },
            ));

            // with texture atlas
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 2,
                },
            ));

            // with texture slicer
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                ImageScaleMode::Sliced(TextureSlicer {
                    border: BorderRect::square(16.),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.,
                }),
            ));

            // with rect and texture slicer
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 16., 16.)),
                    style: style.clone(),
                    ..default()
                },
                ImageScaleMode::Sliced(TextureSlicer {
                    border: BorderRect::square(2.),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.,
                }),
            ));

            // with rect, texture atlas and texture slicer
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 8., 8.)),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 1,
                },
                ImageScaleMode::Sliced(TextureSlicer {
                    border: BorderRect::square(1.),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.,
                }),
            ));

            // with texture atlas and texture slicer
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 2,
                },
                ImageScaleMode::Sliced(TextureSlicer {
                    border: BorderRect::square(2.),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.,
                }),
            ));

            // with tiled
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                ImageScaleMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: 1.,
                },
            ));

            // with rect and tiled
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 16., 16.)),
                    style: style.clone(),
                    ..default()
                },
                ImageScaleMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: 1.,
                },
            ));

            // with rect, texture atlas and tiled
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 8., 8.)),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 1,
                },
                ImageScaleMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: 1.,
                },
            ));

            // with texture atlas and tiled
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 2,
                },
                ImageScaleMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: 1.,
                },
            ));
        });
}
```

</details>
2024-09-09 16:16:33 +00:00
CrazyboyQCD
bca228fdaa
Simplify pick_rounded_rect (#15065)
# Objective

Simplify `pick_rounded_rect` with multiple `if` statements to make it
more readable and efficient([Godbolt
link](https://godbolt.org/z/W5vPEvT5c)).

Co-authored-by: WX\shixi <shixi1@cnwxsoft.com>
2024-09-09 15:40:00 +00:00
Ben Frankel
7b217a976c
Remove deprecated SpriteSheetBundle and AtlasImageBundle (#15062)
# Objective

Remove bundles that were deprecated in 0.14.

## Testing

`rg SpriteSheetBundle` and `rg AtlasImageBundle` show no results.
2024-09-09 15:36:09 +00:00
BD103
6ec6a55645
Unify crate-level preludes (#15080)
# Objective

- Crate-level prelude modules, such as `bevy_ecs::prelude`, are plagued
with inconsistency! Let's fix it!

## Solution

Format all preludes based on the following rules:

1. All preludes should have brief documentation in the format of:
   > The _name_ prelude.
   >
> This includes the most common types in this crate, re-exported for
your convenience.
2. All documentation should be outer, not inner. (`///` instead of
`//!`.)
3. No prelude modules should be annotated with `#[doc(hidden)]`. (Items
within them may, though I'm not sure why this was done.)

## Testing

- I manually searched for the term `mod prelude` and updated all
occurrences by hand. 🫠

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-09-08 17:10:57 +00:00
BigWingBeat
54aa45e62f
Fix bevy_ui compile error when bevy_picking feature is disabled (#15053)
# Objective

#14957 added the `pick_rounded_rect` function to `bevy_ui` in the
`picking_backend` module, which is gated behind the `bevy_picking`
feature. This function is used in that module, as well as in the `focus`
module. The latter usage is not gated behind the `bevy_picking` feature,
causing a compile error when the feature is disabled.

## Solution

Move the `pick_rounded_rect` function out of the `picking_backend`
module, as it does not depend on anything defined in that module. I put
it in `lib.rs` but it could reasonably be moved somewhere else instead.

## Testing

Encountered this compile error in a project and confirmed that this
patch fixes it.
2024-09-05 19:16:57 +00:00
ickshonpe
cb221d8852
Node::is_empty (#15050)
# Objective

Add a `Node::is_empty` method to replace the `uinode.size().x() <= 0. ||
uinode.size.y() <= 0.` checks.
2024-09-05 16:26:45 +00:00
ickshonpe
a0f5ea0d36
UI outlines radius (#15018)
# Objective

Fixes #13479

This also fixes the gaps you can sometimes observe in outlines
(screenshot from main, not this PR):

<img width="636" alt="outline-gaps"
src="https://github.com/user-attachments/assets/c11dae24-20f5-4aea-8ffc-1894ad2a2b79">

The outline around the last item in each section has vertical gaps. 

## Solution

Draw the outlines with corner radius using the existing border rendering
for uinodes. The outline radius is very simple to calculate. We just
take the computed border radius of the node, and if it's greater than
zero, add it to the distance from the edge of the node to the outer edge
of the node's outline.

---

## Showcase

<img width="634" alt="outlines-radius"
src="https://github.com/user-attachments/assets/1ecda26c-65c5-41ef-87e4-5d9171ddc3ae">

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-09-04 22:30:16 +00:00
ickshonpe
8ac745ab10
UI texture slice texture flipping reimplementation (#15034)
# Objective

Fixes #15032

## Solution

Reimplement support for the `flip_x` and `flip_y` fields.
This doesn't flip the border geometry, I'm not really sure whether that
is desirable or not.
Also fixes a bug that was causing the side and center slices to tile
incorrectly.

### Testing

```
cargo run --example ui_texture_slice_flip_and_tile
```

## Showcase
<img width="787" alt="nearest"
src="https://github.com/user-attachments/assets/bc044bae-1748-42ba-92b5-0500c87264f6">
With tiling need to use nearest filtering to avoid bleeding between the
slices.

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-04 19:31:41 +00:00
Alice Cecile
4ac2a63556
Remove all existing system order ambiguities in DefaultPlugins (#15031)
# Objective

As discussed in https://github.com/bevyengine/bevy/issues/7386, system
order ambiguities within `DefaultPlugins` are a source of bugs in the
engine and badly pollute diagnostic output for users.

We should eliminate them!

This PR is an alternative to #15027: with all external ambiguities
silenced, this should be much less prone to merge conflicts and the test
output should be much easier for authors to understand.

Note that system order ambiguities are still permitted in the
`RenderApp`: these need a bit of thought in terms of how to test them,
and will be fairly involved to fix. While these aren't *good*, they'll
generally only cause graphical bugs, not logic ones.

## Solution

All remaining system order ambiguities have been resolved.
Review this PR commit-by-commit to see how each of these problems were
fixed.

## Testing

`cargo run --example ambiguity_detection` passes with no panics or
logging!
2024-09-03 20:24:34 +00:00
Chris Juchem
c620eb7833
Return Results from Camera's world/viewport conversion methods (#14989)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/14593.

## Solution

- Add `ViewportConversionError` and return it from viewport conversion
methods on Camera.

## Testing

- I successfully compiled and ran all changed examples.

## Migration Guide

The following methods on `Camera` now return a `Result` instead of an
`Option` so that they can provide more information about failures:
 - `world_to_viewport`
 - `world_to_viewport_with_depth`
 - `viewport_to_world`
 - `viewport_to_world_2d`

Call `.ok()` on the `Result` to turn it back into an `Option`, or handle
the `Result` directly.

---------

Co-authored-by: Lixou <82600264+DasLixou@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-09-03 19:45:15 +00:00
ickshonpe
4e9a62f094
Ignore clicks on uinodes outside of rounded corners (#14957)
# Objective

Fixes #14941

## Solution
1. Add a `resolved_border_radius` field to `Node` to hold the resolved
border radius values.
2. Remove the border radius calculations from the UI's extraction
functions.
4. Compute the border radius during UI relayouts in `ui_layout_system`
and store them in `Node`.
5. New `pick_rounded_rect` function based on the border radius SDF from
`ui.wgsl`.
6. Use `pick_rounded_rect` in `focus` and `picking_backend` to check if
the pointer is hovering UI nodes with rounded corners.
---

## Showcase

```
cargo run --example button
```


https://github.com/user-attachments/assets/ea951a64-17ef-455e-b5c9-a2e6f6360648

## Testing

Modified button example with buttons with different corner radius:

```
use bevy::{color::palettes::basic::*, prelude::*, winit::WinitSettings};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        // Only run the app when there is user input. This will significantly reduce CPU/GPU use.
        .insert_resource(WinitSettings::desktop_app())
        .add_systems(Startup, setup)
        .add_systems(Update, button_system)
        .run();
}

const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);

fn button_system(
    mut interaction_query: Query<
        (
            &Interaction,
            &mut BackgroundColor,
            &mut BorderColor,
            &Children,
        ),
        (Changed<Interaction>, With<Button>),
    >,
    mut text_query: Query<&mut Text>,
) {
    for (interaction, mut color, mut border_color, children) in &mut interaction_query {
        let mut text = text_query.get_mut(children[0]).unwrap();
        match *interaction {
            Interaction::Pressed => {
                text.sections[0].value = "Press".to_string();
                *color = PRESSED_BUTTON.into();
                border_color.0 = RED.into();
            }
            Interaction::Hovered => {
                text.sections[0].value = "Hover".to_string();
                *color = HOVERED_BUTTON.into();
                border_color.0 = Color::WHITE;
            }
            Interaction::None => {
                text.sections[0].value = "Button".to_string();
                *color = NORMAL_BUTTON.into();
                border_color.0 = Color::BLACK;
            }
        }
    }
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // ui camera
    commands.spawn(Camera2dBundle::default());
    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Percent(100.0),
                height: Val::Percent(100.0),
                align_items: AlignItems::Center,
                justify_content: JustifyContent::Center,
                row_gap: Val::Px(10.),
                ..default()
            },
            ..default()
        })
        .with_children(|parent| {
            for border_radius in [
                BorderRadius {
                    top_left: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    top_right: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    bottom_right: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    bottom_left: Val::ZERO,
                    ..BorderRadius::MAX
                },
            ] {
                parent
                    .spawn(ButtonBundle {
                        style: Style {
                            width: Val::Px(150.0),
                            height: Val::Px(65.0),
                            border: UiRect::all(Val::Px(5.0)),
                            // horizontally center child text
                            justify_content: JustifyContent::Center,
                            // vertically center child text
                            align_items: AlignItems::Center,
                            ..default()
                        },
                        border_color: BorderColor(Color::BLACK),
                        border_radius,
                        background_color: NORMAL_BUTTON.into(),
                        ..default()
                    })
                    .with_child(TextBundle::from_section(
                        "Button",
                        TextStyle {
                            font: asset_server.load("fonts/FiraSans-Bold.ttf"),
                            font_size: 40.0,
                            color: Color::srgb(0.9, 0.9, 0.9),
                        },
                    ));
            }
        });
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
2024-09-03 12:38:59 +00:00
ickshonpe
01a3b0e830
UI texture atlas slice shader (#14990)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/14183

## Solution

Reimplement the UI texture atlas slicer using a shader. 

The problems with #14183 could be fixed more simply by hacking around
with the coordinates and scaling but that way is very fragile and might
get broken again the next time we make changes to the layout
calculations. A shader based solution is more robust, it's impossible
for gaps to appear between the image slices with these changes as we're
only drawing a single quad.

I've not tried any benchmarks yet but it should much more efficient as
well, in the worst cases even hundreds or thousands of times faster.

Maybe could have used the UiMaterialPipeline. I wrote the shader first
and used fat vertices and then realised it wouldn't work that way with a
UiMaterial. If it's rewritten it so it puts all the slice geometry in
uniform buffer, then it might work? Adding the uniform buffer would
probably make the shader more complicated though, so don't know if it's
even worth it. Instancing is another alternative.

## Testing
The examples are working and it seems to match the old API correctly but
I've not used the texture atlas slicing API for anything before, I
reviewed the PR but that was back in January.

Needs a review by someone who knows the rendering pipeline and wgsl
really well because I don't really have any idea what I'm doing.
2024-09-02 23:03:58 +00:00
ickshonpe
96942058f7
Extract borders without border radius (#15020)
# Objective

The `BorderRadius` component shouldn't be required to draw borders for
nodes with sharp corners.

## Solution

Make `BorderRadius` optional in `extract_uinode_borders`'s UI node
query.
2024-09-02 22:47:43 +00:00
UkoeHB
3fc02cb925
Reduce allocations in ui_layout_system (#15001)
# Objective

- Shave off some allocations from `ui_layout_system`.

## Solution

- Add a `Local` for allocation buffers.
2024-09-02 22:37:27 +00:00
UkoeHB
3227c3de36
Don't reallocate scale factors in measure_text_system (#14999)
# Objective

- Reuse allocation of `scale_factors` in `measure_text_system`.

## Solution

- Move it to a `Local`.
2024-09-02 17:01:59 +00:00
UkoeHB
2b94a108ae
Reuse TextLayoutInfo in queue_text (#14997)
# Objective

Don't reallocate `TextLayoutInfo` every time it needs to be updated.

## Solution

Reuse existing allocation.
2024-09-02 17:01:56 +00:00
ickshonpe
be100b8760
Resolve UI outlines using the correct target's viewport size (#14947)
# Objective
`resolve_outlines_system` wasn't updated when multi-window support was
added and it always uses the size of the primary window when resolving
viewport coords, regardless of the layout's camera target.

Fixes #14945

## Solution

It's awkward to get the viewport size of the target for an individual
node without walking the tree or adding extra fields to `Node`, so I
removed `resolve_outlines_system` and instead the outline values are
updated in `ui_layout_system`.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-02 16:56:58 +00:00
UkoeHB
41474226c3
Optimize UI text measurement (#15003)
# Objective

- Avoid cloning the `CosmicBuffer` every time you create a new text
measurement.

## Solution

- Inject a buffer query when calculating layout so existing buffers can
be reused.

## Testing

- I tested the `text`, `text_debug`, and `text_wrap_debug` examples.
- I did not do a performance test.
2024-09-01 11:50:54 +00:00
Zachary Harrold
bc13161416
Migrated NonZero* to NonZero<*> (#14978)
# Objective

- Fixes #14974

## Solution

- Replace all* instances of `NonZero*` with `NonZero<*>`

## Testing

- CI passed locally.

---

## Notes

Within the `bevy_reflect` implementations for `std` types,
`impl_reflect_value!()` will continue to use the type aliases instead,
as it inappropriately parses the concrete type parameter as a generic
argument. If the `ZeroablePrimitive` trait was stable, or the macro
could be modified to accept a finite list of types, then we could fully
migrate.
2024-08-30 02:37:47 +00:00
François Mockers
e63d7c340f
don't use padding for layout (#14944)
# Objective

- Fixes #14792 
- Padding is already handled by taffy, don't handle it also on Bevy side

## Solution

- Remove extra computation added in
https://github.com/bevyengine/bevy/pull/14777
2024-08-27 22:41:23 +00:00
charlotte
1caa64d948
Refactor AsBindGroup to use a associated SystemParam. (#14909)
# Objective

Adding more features to `AsBindGroup` proc macro means making the trait
arguments uglier. Downstream implementors of the trait without the proc
macro might want to do different things than our default arguments.

## Solution

Make `AsBindGroup` take an associated `Param` type.

## Migration Guide

`AsBindGroup` now allows the user to specify a `SystemParam` to be used
for creating bind groups.
2024-08-25 20:16:34 +00:00
robtfm
6e2f96f222
check sampler type in as_bind_group derives (#12637)
# Objective

currently if we use an image with the wrong sampler type in a material,
wgpu panics with an invalid texture format. turn this into a warning and
fail more gracefully.

## Solution

the expected sampler type is specified in the AsBindGroup derive, so we
can just check the image sampler is what it should be.

i am not totally sure about the mapping of image sampler type to
#[sampler(type)], i assumed:

```
    "filtering" => [ TextureSampleType::Float { filterable: true } ],
    "non_filtering" => [
        TextureSampleType::Float { filterable: false },
        TextureSampleType::Sint,
        TextureSampleType::Uint,
    ],
    "comparison" => [ TextureSampleType::Depth ],
```
2024-08-21 01:41:31 +00:00
Rob Parrett
618cf7f51d
Remove useless Direction field (#14793)
# Objective

Delete some code that isn't actually doing anything. This was actually
discovered way back in this obsolete PR: #5513.

Also Fixes #6286

## Solution

Delete it

## Alternatives

Make `Direction` do things. But it's not totally clear to me if it's
possible to override cosmic-text's unicode bidi stuff.

## Migration Guide

`Style` no longer has a `direction` field, and `Direction` has been
deleted. They didn't do anything, so you can delete any references to
them as well.
2024-08-19 21:45:28 +00:00
Nihilistas
ae74df3464
#14143 - fix bevy_ui padding (#14777)
# Objective

fixes #14143

## Solution

- removed the temporary blocker if statement when setting padding in
`Style`
- adjusted the `layout_location` and `layout_size` so they use
`layout.padding` which we already get from Taffy

## Testing

- this is the test code I used:
```rust
use bevy::prelude::*;

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

fn setup(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
){
    let font = asset_server.load("fonts/FiraSans-Bold.ttf");
    commands.spawn(Camera2dBundle::default());

    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Px(200.),
                height: Val::Px(100.),
                align_items: AlignItems::Center,
                justify_content: JustifyContent::Center,
                align_self: AlignSelf::Center,
                justify_self: JustifySelf::Center,
                ..Default::default()
            },
            background_color: BackgroundColor(Color::srgb(0.,1., 1.)),
            ..Default::default()
        })
        .with_children(|builder| {
            builder.spawn((TextBundle::from_section(
                    "Hello World",
                    TextStyle {
                        font,
                        font_size: 32.0,
                        color: Color::WHITE,
                        },
                ).with_style(Style {
                    padding: UiRect::all(Val::Px(10.)),
                    width: Val::Px(100.),
                    height: Val::Px(100.),
                    ..Default::default()
                }).with_background_color(Color::srgb(1.,0., 0.)),
            ));
            // spawn an image bundle
            builder.spawn(ImageBundle {
                style: Style {
                    padding: UiRect::all(Val::Px(10.)),
                    width: Val::Px(100.),
                    height: Val::Px(100.),
                    ..Default::default()
                },
                image: asset_server.load("square.png").into(),
                ..Default::default()
            });
        });
}
```

- I tested 5 cases: 10px padding from all sides, and 10px padding from
left, right, bottom, and top separately

- **For reviewers**: please check more cases or try to run it on some
more complicated real-world UI

## Showcase

<img width="374" alt="Screenshot 2024-08-16 at 09 28 04"
src="https://github.com/user-attachments/assets/59b85b00-e255-4669-be13-a287ef35d4d9">
<img width="288" alt="Screenshot 2024-08-16 at 09 28 47"
src="https://github.com/user-attachments/assets/170a79b1-ec9c-45f9-82f5-ba7fa4029334">
<img width="274" alt="Screenshot 2024-08-16 at 09 45 16"
src="https://github.com/user-attachments/assets/e3fd9b59-b41f-427d-8c07-5acdf1dc5ecf">
<img width="292" alt="Screenshot 2024-08-16 at 09 45 36"
src="https://github.com/user-attachments/assets/c4f708aa-3f0d-4ff3-b779-0d4ed5f6ba73">
<img width="261" alt="Screenshot 2024-08-16 at 09 45 58"
src="https://github.com/user-attachments/assets/eba1e26f-04ca-4178-87c8-3a79daff3a9a">

---------

Co-authored-by: dpeke <dpekelis@funstage.com>
2024-08-16 21:22:44 +00:00
Alice Cecile
5243fe6956
Remove manual apply_deferred in bevy_ui (#14768)
# Objective

This `apply_deferred` doesn't seem to have any effect, pointlessly
restricts parallelism and is responsible for a large number of system
order ambiguities. Spotted as part of #7386.

## Solution

Remove it.

This is the *only* manual apply_deferred in the code base currently.

## Testing

I've checked various UI examples and `split_screen`, and couldn't
discern any difference.

This looks like a remnant of a `(a, apply_deferred, b).chain()` pattern
where `b` got removed, leaving us with a weird vestige.
2024-08-15 20:51:25 +00:00
TotalKrill
6adf31babf
hooking up observers and clicking for ui node (#14695)
Makes the newly merged picking usable for UI elements. 

currently it both triggers the events, as well as sends them as throught
commands.trigger_targets. We should probably figure out if this is
needed for them all.

# Objective

Hooks up obserers and picking for a very simple example

## Solution

upstreamed the UI picking backend from bevy_mod_picking

## Testing

tested with the new example picking/simple_picking.rs


---

---------

Co-authored-by: Lixou <82600264+DasLixou@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-08-15 14:43:55 +00:00
Ben Frankel
9b254aab1e
Explicitly order CameraUpdateSystem before UiSystem::Prepare (#14609)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/14277.

May also fix https://github.com/bevyengine/bevy/issues/14255, needs
verification.

## Solution

Explicitly order `CameraUpdateSystem` before `UiSystem::Prepare`, so
that when the window resizes, `camera_system` will update the `Camera`'s
viewport size before `ui_layout_system` also reacts to the window resize
and tries to read the new `Camera` viewport size to set UI node sizes
accordingly.

## Testing

I tested that explicitly ordering `CameraUpdateSystem` _after_ triggers
the buggy behavior, and explicitly ordering it _before_ does not trigger
the buggy behavior or crash the app (which also demonstrates that the
system sets are ambiguous).

---

## Migration Guide

`CameraUpdateSystem` is now explicitly ordered before
`UiSystem::Prepare` instead of being ambiguous with it.
2024-08-04 13:34:51 +00:00
s-puig
ba09f35474
Fix UI texture atlas with offset (#13620)
# Objective

- Fixes #11219 

## Solution

- Scaling calculations use texture dimensions instead of layout
dimensions.

## Testing

- Did you test these changes? If so, how?

All UI examples look fine.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

Example in #11219

## Migration Guide

```diff
let ui_node = ExtractedUiNode {
                    stack_index,
                    transform,
                    color,
                    rect,
                    image,
-                   atlas_size: Some(atlas_size * scale_factor),      
+                   atlas_scaling: Some(Vec2::splat(scale_factor)),
                    clip,
                    flip_x,
                    flip_y,
                    camera_entity,
                    border,
                    border_radius,
                    node_type,
                },
```

```diff
let computed_slices = ComputedTextureSlices {
    slices,
-    image_size,
}
```
2024-07-30 15:31:58 +00:00
Tamás Kiss
396153ae59
fix issue with phantom ui node children (#14490)
# Objective

The `ui_layout_system` relies on change detection to sync parent-child
relation to taffy. The children need to by synced before node removal to
avoid trying to set deleted nodes as children (due to how the different
queries collect entities). This however may leave nodes that were
removed set as children to other nodes in special cases.

Fixes #11385

## Solution

The solution is simply to re-sync the changed children after the nodes
are removed.

## Testing

Tested with `sickle_ui` where docking zone highlights would end up
glitched when docking was done in a certain manner:
- run the `docking_zone_splits` example
- pop out a tab from the top
- dock the floating panel in the center right
- grab another tab and try to hover the original static docking zone:
the highlight is semi-stuck
- (NOTE: sometimes it worked even without the fix due to scheduling
order not producing the bugged query results)

After the fix, the issue is no longer present.

NOTE: The performance impact should be minimal, as the child sync relies
on change detection. The change detection was also the reason the parent
nodes remained "stuck" with the phantom children if no other update were
done to them.
2024-07-29 23:42:56 +00:00
Blake Bedford
eabb58aa04
Add BorderRadius field to ImageBundle (#14457)
# Objective

- Fixes #14453

## Solution

- Added BorderRadius to ImageBundle

## Testing

- Did you test these changes? If so, how?

- Tested on a random picture I found in the examples and it added a
border radius.

- Are there any parts that need more testing?

- I don't fink so.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

- Apply a border radius to a random picture.
2024-07-24 18:41:26 +00:00
Sludge
f0ff7fb544
Add and reflect Default impls for CSS grid types (#14443)
# Objective

- Some types here were not constructible via reflection, and some were
missing fairly obvious `Default` values.
- Some types used `#[reflect_value]` for some unstated reason, making
them opaque to reflection-based code.

## Solution

- Add and reflect some `Default` impls, and stop using
`#[reflect_value]`.
2024-07-22 21:39:59 +00:00
IceSentry
3faca1e549
Don't ignore draw errors (#13240)
# Objective

- It's possible to have errors in a draw command, but these errors are
ignored

## Solution

- Return a result with the error

## Changelog

Renamed `RenderCommandResult::Failure` to `RenderCommandResult::Skip`
Added a `reason` string parameter to `RenderCommandResult::Failure`

## Migration Guide
If you were using `RenderCommandResult::Failure` to just ignore an error
and retry later, use `RenderCommandResult::Skip` instead.

This wasn't intentional, but this PR should also help with
https://github.com/bevyengine/bevy/issues/12660 since we can turn a few
unwraps into error messages now.

---------

Co-authored-by: Charlotte McElwain <charlotte.c.mcelwain@gmail.com>
2024-07-22 19:22:30 +00:00
BD103
cd497152bb
Fix error in bevy_ui when building without bevy_text (#14430)
# Objective

- `bevy_ui` does not build without the `bevy_text` feature due to
improper feature gating.
- Specifically, `MeasureArgs<'a>` had an unused lifetime `'a` without
`bevy_text` enabled. This is because it stores a reference to a
`cosmic_text::FontSystem`.
- This was caught by `flag-frenzy` in [this
run](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/10024258523/job/27706132250).

## Solution

- Add a `PhantomData` to `MeasureArgs<'a>` in order to maintain its
lifetime argument.
- I also named it `font_system`, after the feature-gated argument that
actually needs a lifetime, for usability. Please comment if you have a
better solution!
- Move some unused imports to be behind the `bevy_text` feature gate.

## Testing

```bash
# Fails on main.
cargo check -p bevy_ui --no-default-features
# Succeeds on main.
cargo check -p bevy_ui --no-default-features -F bevy_text
```

---

## Migration Guide

**This is not a breaking change for users migrating from 0.14, since
`MeasureArgs` did not exist then.**

When the `bevy_text` feature is disabled for `bevy_ui`, the type of the
`MeasureArgs::font_system` field is now a `PhantomData` instead of being
removed entirely. This is in order to keep the lifetime parameter, even
though it is unused without text being enabled.
2024-07-22 19:19:10 +00:00
Peter Hayman
b8416b3043
Add some missing reflect attributes (#14259)
# Objective

- Some types are missing reflection attributes, which means we can't use
them in scene serialization etc.
- Effected types
   - `BorderRadius`
   - `AnimationTransitions`
   - `OnAdd`
   - `OnInsert`
   - `OnRemove`
- My use-case for `OnAdd` etc to derive reflect is 'Serializable
Observer Components'. Add the component, save the scene, then the
observer is re-added on scene load.

```rust
#[derive(Reflect)]
struct MySerializeableObserver<T: Event>(#[reflect(ignore)]PhantomData<T>);

impl<T: Event> Component for MySerializeableObserver<T> {
  const STORAGE_TYPE: StorageType  = StorageType::Table;
    fn register_component_hooks(hooks: &mut ComponentHooks) {
      hooks.on_add(|mut world, entity, _| {
        world
          .commands()
          .entity(entity)
          .observe(|_trigger: Trigger<T>| {
            println!("it triggered etc.");
          });
    });
  }
}
```

## Solution

- Add the missing traits

---
2024-07-22 18:24:10 +00:00
UkoeHB
c3320627ac
Clean up UiSystem system sets (#14228)
# Objective

- All UI systems should be in system sets that are easy to order around
in user code.

## Solution

- Add `UiSystem::Prepare` and `UiSystem::PostLayout` system sets to
capture floater systems.
- Adjust how UI systems are scheduled to align with the new sets.

This is *mostly* a pure refactor without any behavior/scheduling
changes. See migration guide.

## Testing

- Not tested, correctness by inspection.

---

## Migration Guide

`UiSystem` system set adjustments.
- The `UiSystem::Outline` system set is now strictly ordered after
`UiSystem::Layout`, rather than overlapping it.
2024-07-15 15:27:38 +00:00
Mike
91dd7e6f0f
add entity to error message (#14163)
# Objective

- There was a new warning added about having an unstyled child in the ui
hierarchy. Debugging the new error is pretty hard without any info about
which entity is.

## Solution

- Add the entity id to the warning.

```text
// Before
2024-07-05T19:40:59.904014Z  WARN bevy_ui::layout::ui_surface: Unstyled child in a UI entity hierarchy. You are using an entity without UI components as a child of an entity with UI components, results may be unexpected.

//After
2024-07-05T19:40:59.904014Z  WARN bevy_ui::layout::ui_surface: Unstyled child `3v1` in a UI entity hierarchy. You are using an entity without UI components as a child of an entity with UI components, results may be unexpected.
```

## Changelog

- add entity id to ui surface warning
2024-07-08 01:01:47 +00:00
re0312
db19d2ee47
Optimize ui_layout_system (#14064)
# Objective

- Currently bevy's ui layout system could takes a long time.

## Solution

- cache `default_ui_camera `entity to avoid repetitive lookup


## Performance
cargo run --release --example many_buttons --features bevy/trace_tracy  


![image](https://github.com/bevyengine/bevy/assets/45868716/f8eda0b0-343d-4379-847f-f1636c38e5ec)
2024-07-08 00:48:35 +00:00
TotalKrill
5986d5d309
Cosmic text (#10193)
# Replace ab_glyph with the more capable cosmic-text

Fixes #7616.

Cosmic-text is a more mature text-rendering library that handles scripts
and ligatures better than ab_glyph, it can also handle system fonts
which can be implemented in bevy in the future

Rebase of https://github.com/bevyengine/bevy/pull/8808

## Changelog

Replaces text renderer ab_glyph with cosmic-text

The definition of the font size has changed with the migration to cosmic
text. The behavior is now consistent with other platforms (e.g. the
web), where the font size in pixels measures the height of the font (the
distance between the top of the highest ascender and the bottom of the
lowest descender). Font sizes in your app need to be rescaled to
approximately 1.2x smaller; for example, if you were using a font size
of 60.0, you should now use a font size of 50.0.

## Migration guide

- `Text2dBounds` has been replaced with `TextBounds`, and it now accepts
`Option`s to the bounds, instead of using `f32::INFINITY` to inidicate
lack of bounds
- Textsizes should be changed, dividing the current size with 1.2 will
result in the same size as before.
- `TextSettings` struct is removed
- Feature `subpixel_alignment` has been removed since cosmic-text
already does this automatically
- TextBundles and things rendering texts requires the `CosmicBuffer`
Component on them as well

## Suggested followups:

- TextPipeline: reconstruct byte indices for keeping track of eventual
cursors in text input
- TextPipeline: (future work) split text entities into section entities
- TextPipeline: (future work) text editing
- Support line height as an option. Unitless `1.2` is the default used
in browsers (1.2x font size).
- Support System Fonts and font families
- Example showing of animated text styles. Eg. throbbing hyperlinks

---------

Co-authored-by: tigregalis <anak.harimau@gmail.com>
Co-authored-by: Nico Burns <nico@nicoburns.com>
Co-authored-by: sam edelsten <samedelsten1@gmail.com>
Co-authored-by: Dimchikkk <velo.app1@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
2024-07-04 20:41:08 +00:00
re0312
1c2f687202
Skip extract UiImage When its texture is default (#14122)
# Objective

- After #14017 , I noticed that the drawcall increased 10x in the
`many_buttons`, causing the `UIPassNode `to increase from 1.5ms to 6ms.
This is because our UI batching is very fragile.

## Solution

- skip extract UiImage when its texture is default


## Performance 
many_buttons UiPassNode

![image](https://github.com/bevyengine/bevy/assets/45868716/9295d958-8c3f-469c-a7e0-d1e90db4dfb7)
2024-07-03 20:54:11 +00:00
re0312
2893fc3e8b
Using simple approx round up in ui_layout_system (#14079)
# Objective

- built-in `f32::round `is slow 
- splits from #14064 
## Solution

- using a simple floor instead of round

## Testing

- I am not an expert on floating-point values, but I enumerated all f32
values to test for potential errors compared to the previous function.
[rust
playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=0d8ed5604499e7bd9c61ce57d47e8c06)

three cases where the behavior differs between the new and previous
functions:
| value  |  previous | new  |  
|---|---|---|
|  [-0.5,0) |  -0 | +0  |   
|  0.49999997  | 0  |  1 |   
| +-8388609 |  8388609   | 8388610  |   

## Performance


![image](https://github.com/bevyengine/bevy/assets/45868716/1910f342-e55b-4f5c-851c-24a142d5c72e)
2024-07-03 12:48:34 +00:00
Lura
856b39d821
Apply Clippy lints regarding lazy evaluation and closures (#14015)
# Objective

- Lazily evaluate
[default](https://rust-lang.github.io/rust-clippy/master/index.html#/unwrap_or_default)~~/[or](https://rust-lang.github.io/rust-clippy/master/index.html#/or_fun_call)~~
values where it makes sense
  - ~~`unwrap_or(foo())` -> `unwrap_or_else(|| foo())`~~
  - `unwrap_or(Default::default())` -> `unwrap_or_default()`
  - etc.
- Avoid creating [redundant
closures](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure),
even for [method
calls](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure_for_method_calls)
  - `map(|something| something.into())` -> `map(Into:into)`

## Solution

- Apply Clippy lints:
-
~~[or_fun_call](https://rust-lang.github.io/rust-clippy/master/index.html#/or_fun_call)~~
-
[unwrap_or_default](https://rust-lang.github.io/rust-clippy/master/index.html#/unwrap_or_default)
-
[redundant_closure_for_method_calls](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure_for_method_calls)
([redundant
closures](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure)
is already enabled)

## Testing

- Tested on Windows 11 (`stable-x86_64-pc-windows-gnu`, 1.79.0)
- Bevy compiles without errors or warnings and examples seem to work as
intended
  - `cargo clippy` 
  - `cargo run -p ci -- compile` 

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-01 15:54:40 +00:00
BD103
f7bc0a01dd
Bump accesskit to 0.16 (#14091)
Also bumps `accesskit_winit` to 0.22 and fixes one breaking change.

# Objective

- `accesskit` has been updated recently to 0.16!

## Solution

- Update `accesskit`, as well as `accesskit_winit`.
- [`accesskit`
changelog](552032c839/common/CHANGELOG.md (0160-2024-06-29))
- [`accesskit_winit`
changelog](552032c839/platforms/winit/CHANGELOG.md (0220-2024-06-29))
- Fix one breaking change where `Role::StaticText` has been renamed to
`Role::Label`.

## Testing

- The test suite should cover most things.
- It would be good to test this with an example, but I don't know how.

---

## Changelog

- Update `accesskit` to 0.16 and `accesskit_winit` to 0.22.

## Migration Guide

`accesskit`'s `Role::StaticText` variant has been renamed to
`Role::Label`.
2024-07-01 14:42:40 +00:00
Al M
ace4eaaf0e
Merge BuildWorldChildren and BuildChildren traits. (#14052)
# Objective

The `BuildChildren` and `BuildWorldChildren` traits are mostly
identical, so I decided to try and merge them. I'm not sure of the
history, maybe they were added before GATs existed.

## Solution

- Add an associated type to `BuildChildren` which reflects the prior
differences between the `BuildChildren` and `BuildWorldChildren` traits.
- Add `ChildBuild` trait that is the bounds for
`BuildChildren::Builder`, with impls for `ChildBuilder` and
`WorldChildBuilder`.
- Remove `BuildWorldChildren` trait and replace it with an impl of
`BuildChildren` for `EntityWorldMut`.

## Testing

I ran several of the examples that use entity hierarchies, mainly UI.

---

## Changelog

n/a

## Migration Guide

n/a
2024-07-01 14:29:39 +00:00
Tamás Kiss
edca8707c8
add PartialEq to Outline (#14055)
# Objective

`sickle_ui` needs `PartialEq` on components to turn them into animatable
style attributes.

## Solution

All properties of Outline is already `PartialEq`, add derive on
`Outline` as well.

## Testing

- used `sickle_ui` to test if it can be made animatable
2024-06-27 20:03:07 +00:00
Alice Cecile
336fddb101
Make default behavior for BackgroundColor and BorderColor more intuitive (#14017)
# Objective

In Bevy 0.13, `BackgroundColor` simply tinted the image of any
`UiImage`. This was confusing: in every other case (e.g. Text), this
added a solid square behind the element. #11165 changed this, but
removed `BackgroundColor` from `ImageBundle` to avoid confusion, since
the semantic meaning had changed.

However, this resulted in a serious UX downgrade / inconsistency, as
this behavior was no longer part of the bundle (unlike for `TextBundle`
or `NodeBundle`), leaving users with a relatively frustrating upgrade
path.

Additionally, adding both `BackgroundColor` and `UiImage` resulted in a
bizarre effect, where the background color was seemingly ignored as it
was covered by a solid white placeholder image.

Fixes #13969.

## Solution

Per @viridia's design:

> - if you don't specify a background color, it's transparent.
> - if you don't specify an image color, it's white (because it's a
multiplier).
> - if you don't specify an image, no image is drawn.
> - if you specify both a background color and an image color, they are
independent.
> - the background color is drawn behind the image (in whatever pixels
are transparent)

As laid out by @benfrankel, this involves:

1. Changing the default `UiImage` to use a transparent texture but a
pure white tint.
2. Adding `UiImage::solid_color` to quickly set placeholder images.
3. Changing the default `BorderColor` and `BackgroundColor` to
transparent.
4. Removing the default overrides for these values in the other assorted
UI bundles.
5. Adding `BackgroundColor` back to `ImageBundle` and `ButtonBundle`.
6. Adding a 1x1 `Image::transparent`, which can be accessed from
`Assets<Image>` via the `TRANSPARENT_IMAGE_HANDLE` constant.

Huge thanks to everyone who helped out with the design in the linked
issue and [the Discord
thread](https://discord.com/channels/691052431525675048/1255209923890118697/1255209999278280844):
this was very much a joint design.

@cart helped me figure out how to set the UiImage's default texture to a
transparent 1x1 image, which is a much nicer fix.

## Testing

I've checked the examples modified by this PR, and the `ui` example as
well just to be sure.

## Migration Guide

- `BackgroundColor` no longer tints the color of images in `ImageBundle`
or `ButtonBundle`. Set `UiImage::color` to tint images instead.
- The default texture for `UiImage` is now a transparent white square.
Use `UiImage::solid_color` to quickly draw debug images.
- The default value for `BackgroundColor` and `BorderColor` is now
transparent. Set the color to white manually to return to previous
behavior.
2024-06-25 21:50:41 +00:00
Tamás Kiss
87fa69bd7e
fix panic: invalid SlotMap key used (#13990)
# Objective

Tight, in-frame generation, re-parenting, despawning, etc., UI
operations could sometime lead taffy to panic (invalid SlotMap key used)
when an entity with an invalid state later despawned.

Fixes #12403 

## Solution

Move the `remove_entities` call after children updates.

## Testing

`sickle_ui` had a case that always caused the panic. Tested before this
change, after this change, and before the change again to make sure the
error is there without the fix. The fix worked. Test steps and used
commit described in issue #12403.

I have also ran every bevy UI example, though none of them deal with
entity re-parenting or removal. No regression detected on them.

Tested on Windows only.
2024-06-24 20:47:44 +00:00
Rob Parrett
e46e246581
Fix a few "repeated word" typos (#13955)
# Objective

Stumbled on one of these and went digging for more

## Solution

```diff
- word word
+ word
```
2024-06-20 21:35:20 +00:00
Jan Hohenheim
6273227e09
Fix lints introduced in Rust beta 1.80 (#13899)
Resolves #13895

Mostly just involves being more explicit about which parts of the docs
belong to a list and which begin a new paragraph.
- found a few docs that were malformed because of exactly this, so I
fixed that by introducing a paragraph
- added indentation to nearly all multiline lists
- fixed a few minor typos
- added `#[allow(dead_code)]` to types that are needed to test
annotations but are never constructed
([here](https://github.com/bevyengine/bevy/pull/13899/files#diff-b02b63604e569c8577c491e7a2030d456886d8f6716eeccd46b11df8aac75dafR1514)
and
[here](https://github.com/bevyengine/bevy/pull/13899/files#diff-b02b63604e569c8577c491e7a2030d456886d8f6716eeccd46b11df8aac75dafR1523))
- verified that  `cargo +beta run -p ci -- lints` passes
- verified that `cargo +beta run -p ci -- test` passes
2024-06-17 17:22:01 +00:00
Mike
004ba585b2
reduce the antialias strength (#13814)
# Objective

- Fixes #13807

## Solution

- Before this pr we antialiased between 0.5 and -0.5. This pr changes
things to antialias between 0.25 and -0.25. I tried slightly larger
ranges, but the edge between the boxes still showed. I'm not 100% sure
this is the correct solution, but from what I could find the range you
use is more art than science.

## Testing

- Ran rounded_borders example, the code in the linked issue, and the
testing example from #12702.

---

## Changelog

- reduce antialiasing in ui shader.
2024-06-14 18:36:15 +00:00
Gagnus
298b01f10d
Adds back in way to convert color to u8 array, implemented for the two RGB color types, also renames Color::linear to Color::to_linear. (#13759)
# Objective

One thing missing from the new Color implementation in 0.14 is the
ability to easily convert to a u8 representation of the rgb color.

(note this is a redo of PR https://github.com/bevyengine/bevy/pull/13739
as I needed to move the source branch

## Solution

I have added to_u8_array and to_u8_array_no_alpha to a new trait called
ColorToPacked to mirror the f32 conversions in ColorToComponents and
implemented the new trait for Srgba and LinearRgba.
To go with those I also added matching from_u8... functions and
converted a couple of cases that used ad-hoc implementations of that
conversion to use these.
After discussion on Discord of the experience of using the API I renamed
Color::linear to Color::to_linear, as without that it looks like a
constructor (like Color::rgb).
I also added to_srgba which is the other commonly converted to type of
color (for UI and 2D) to match to_linear.
Removed a redundant extra implementation of to_f32_array for LinearColor
as it is also supplied in ColorToComponents (I'm surprised that's
allowed?)

## Testing

Ran all tests and manually tested.
Added to_and_from_u8 to linear_rgba::tests

## Changelog

visible change is Color::linear becomes Color::to_linear.

---------

Co-authored-by: John Payne <20407779+johngpayne@users.noreply.github.com>
2024-06-10 13:03:46 +00:00
François Mockers
3d9b1e4025
make UI text rendering camera driven (#13697)
# Objective

- Fixes #13687 

## Solution

- Text rendering in UI is still dependent on the `PrimaryWIndow`
- implements #10559 for text rendering

There are other parts of UI that are still `PrimaryWindow` dependent, if
the changes here are OK I'll apply them everywhere.
I'm not a fan of the `EntityHashMap` here to hold the scale factors, but
it seems the quick and easy fix

## Testing

- Run example `multiple_windows` on a screen with a scale factor
different than 1, close the primary window
2024-06-06 00:20:50 +00:00
Ricky Taylor
9b9d3d81cb
Normalise matrix naming (#13489)
# Objective
- Fixes #10909
- Fixes #8492

## Solution
- Name all matrices `x_from_y`, for example `world_from_view`.

## Testing
- I've tested most of the 3D examples. The `lighting` example
particularly should hit a lot of the changes and appears to run fine.

---

## Changelog
- Renamed matrices across the engine to follow a `y_from_x` naming,
making the space conversion more obvious.

## Migration Guide
- `Frustum`'s `from_view_projection`, `from_view_projection_custom_far`
and `from_view_projection_no_far` were renamed to
`from_clip_from_world`, `from_clip_from_world_custom_far` and
`from_clip_from_world_no_far`.
- `ComputedCameraValues::projection_matrix` was renamed to
`clip_from_view`.
- `CameraProjection::get_projection_matrix` was renamed to
`get_clip_from_view` (this affects implementations on `Projection`,
`PerspectiveProjection` and `OrthographicProjection`).
- `ViewRangefinder3d::from_view_matrix` was renamed to
`from_world_from_view`.
- `PreviousViewData`'s members were renamed to `view_from_world` and
`clip_from_world`.
- `ExtractedView`'s `projection`, `transform` and `view_projection` were
renamed to `clip_from_view`, `world_from_view` and `clip_from_world`.
- `ViewUniform`'s `view_proj`, `unjittered_view_proj`,
`inverse_view_proj`, `view`, `inverse_view`, `projection` and
`inverse_projection` were renamed to `clip_from_world`,
`unjittered_clip_from_world`, `world_from_clip`, `world_from_view`,
`view_from_world`, `clip_from_view` and `view_from_clip`.
- `GpuDirectionalCascade::view_projection` was renamed to
`clip_from_world`.
- `MeshTransforms`' `transform` and `previous_transform` were renamed to
`world_from_local` and `previous_world_from_local`.
- `MeshUniform`'s `transform`, `previous_transform`,
`inverse_transpose_model_a` and `inverse_transpose_model_b` were renamed
to `world_from_local`, `previous_world_from_local`,
`local_from_world_transpose_a` and `local_from_world_transpose_b` (the
`Mesh` type in WGSL mirrors this, however `transform` and
`previous_transform` were named `model` and `previous_model`).
- `Mesh2dTransforms::transform` was renamed to `world_from_local`.
- `Mesh2dUniform`'s `transform`, `inverse_transpose_model_a` and
`inverse_transpose_model_b` were renamed to `world_from_local`,
`local_from_world_transpose_a` and `local_from_world_transpose_b` (the
`Mesh2d` type in WGSL mirrors this).
- In WGSL, in `bevy_pbr::mesh_functions`, `get_model_matrix` and
`get_previous_model_matrix` were renamed to `get_world_from_local` and
`get_previous_world_from_local`.
- In WGSL, `bevy_sprite::mesh2d_functions::get_model_matrix` was renamed
to `get_world_from_local`.
2024-06-03 16:56:53 +00:00
Nico Burns
a3e60d39b7
Fix image measure function to apply inherent aspect ratio to style sizes (#13555)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/13155
- fixes https://github.com/bevyengine/bevy/issues/13517
- Supercedes https://github.com/bevyengine/bevy/pull/13381
- Requires https://github.com/DioxusLabs/taffy/pull/661

## Solution

- Taffy has been updated to:
    - Apply size styles to absolutely positioned children
    - Pass the node's `Style` through to the measure function
- Bevy's image measure function has been updated to make use of this
style information

## Notes

- This is currently using a git version of Taffy. If this is tested as
fixing the issue then we can turn that into a Taffy 0.5 release (this
would be the only change between Taffy 0.4 and Taffy 0.5 so upgrading is
not expected to be an issue)
- This implementation may not be completely correct. I would have
preferred to extend Taffy's gentest infrastructure to handle images and
used that to nail down the correct behaviour. But I don't have time for
that atm so we'll have to iterate on this in future. This PR at least
puts that under Bevy's control.

## Testing

- I manually tested the game_menu_example (from
https://github.com/bevyengine/bevy/issues/13155)
- More testing is probably merited

---

## Changelog

No changelog should be required as it fixes a regression on `main` that
was not present in bevy 0.13. The changelog for "Taffy upgrade" may want
to be changed from 0.4 to 0.5 if this change gets merged.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-05-30 18:37:39 +00:00
François Mockers
4065098586
Fix UI in WebGPU: call textureSample from outside the if (#13546)
# Objective

- since #13523, UI is broken in WebGPU

```
Compilation log for [Invalid ShaderModule (unlabeled)]:
1 error(s) generated while compiling the shader:
:108:27 error: 'textureSample' must only be called from uniform control flow
    let texture_color_1 = textureSample(sprite_texture, sprite_sampler, in_2.uv);
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

:151:19 note: called by 'draw_background' from 'fragment'
        let _e5 = draw_background(in);
                  ^^^^^^^^^^^^^^^^^^^

:147:5 note: control flow depends on possibly non-uniform value
    if _e3 {
    ^^

:146:23 note: parameter 'in' of 'fragment' may be non-uniform
    let _e3 = enabled(in.flags, BORDER);
```


## Solution

- call `textureSample` from outside the if. both branches are using the
same parameters
2024-05-29 23:03:57 +00:00
François Mockers
901d71b81c
fix rounded borders on buttons (#13541)
# Objective

- #13523 introduced a new bug on rounded corners in UI on buttons
- there are artefacts outside of the border, and the text in buttons is
more gray than it should be
- example `color_grading`:

<img width="1280" alt="Screenshot 2024-05-27 at 22 19 13"
src="https://github.com/bevyengine/bevy/assets/8672791/fbb6a8ba-2096-4fcc-9c94-3764e9d16d2f">

## Solution

- Clamp alpha to be between 0.0 and 1.0

<img width="1280" alt="Screenshot 2024-05-27 at 22 18 19"
src="https://github.com/bevyengine/bevy/assets/8672791/295d8e16-30eb-40cc-8d61-4995fca6dded">
2024-05-27 21:46:56 +00:00
Mike
cef31ffdd9
Fix various bugs with UI rounded borders (#13523)
# Objective

- Fixes #13503 
- Fix other various bugs I noticed while debugging above issue.

## Solution

- Change the antialiasing(AA) method. It was using fwidth which is the
derivative between pixels, but there were a lot of artifacts being added
from this. So just use the sdf value. This aa method probably isn't as
smooth looking, but better than having artifacts. Below is a
visualization of the fwidth.

![image](https://github.com/bevyengine/bevy/assets/2180432/4e475ad0-c9d0-4a40-af39-5f4422a78392)
- Use the internal sdf for drawing the background instead of the
external sdf and extract the border for these type of nodes. This fixed
2 bugs, one with the background coloring the AA pixels on the edge of
rounded borders. And also allows for the border to use a transparent
color.
- Don't extract borders if all the widths are zero.

## Testing

- played a bunch with the example in the linked issue.
This PR:

![image](https://github.com/bevyengine/bevy/assets/2180432/d7797e0e-e348-4daa-8646-554dc2032523)
Main:

![image](https://github.com/bevyengine/bevy/assets/2180432/4d46c17e-a12d-4e20-aaef-0ffc950cefe2)

- ran the `borders` and `rounded_borders` examples

---

## Changelog

- Fixed various antialiasing issues to do with rounded ui borders.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Andreas Weibye <13300393+Weibye@users.noreply.github.com>
2024-05-27 17:42:13 +00:00
Patrick Walton
a785e3c20d
Fix UI elements randomly not appearing after #13277. (#13462)
We invoked the `extract_default_ui_camera_view` system twice: once for
2D cameras and once for 3D cameras. This was fine before moving to
resources for render phases, but, after the move to resources, the first
thing such systems do is to clear out all the entities-to-be-rendered
from the previous frame. So, if the scheduler happened to run
`extract_default_ui_camera_view::<Camera2d>` first, then all the UI
elements that it queued would be overwritten by the
`extract_default_ui_camera_view::<Camera3d>` system, or vice versa. The
ordering dependence is the reason why this problem was intermittent.

This commit fixes the problem by merging the two systems into one
systems, using an `Or` query filter.

## Migration Guide

* The `bevy_ui::render::extract_default_ui_camera_view` system is no
longer parameterized over the specific type of camera and is hard-wired
to either `Camera2d` or `Camera3d` components.
2024-05-21 22:06:25 +00:00
Martín Maita
f9da5eecf2
Rename Rect inset() method to inflate() (#13452)
# Objective

- Fixes #13092.

## Solution

- Renamed the `inset()` method in `Rect`, `IRect` and `URect` to
`inflate()`.
- Added `EMPTY` constants to all `Rect` variants, represented by corners
with the maximum numerical values for each kind.

---

## Migration Guide

- Replace `Rect::inset()`, `IRect::inset()` and `URect::inset()` calls
with `inflate()`.
2024-05-21 20:53:55 +00:00
Patrick Walton
9da0b2a0ec
Make render phases render world resources instead of components. (#13277)
This commit makes us stop using the render world ECS for
`BinnedRenderPhase` and `SortedRenderPhase` and instead use resources
with `EntityHashMap`s inside. There are three reasons to do this:

1. We can use `clear()` to clear out the render phase collections
instead of recreating the components from scratch, allowing us to reuse
allocations.

2. This is a prerequisite for retained bins, because components can't be
retained from frame to frame in the render world, but resources can.

3. We want to move away from storing anything in components in the
render world ECS, and this is a step in that direction.

This patch results in a small performance benefit, due to point (1)
above.

## Changelog

### Changed

* The `BinnedRenderPhase` and `SortedRenderPhase` render world
components have been replaced with `ViewBinnedRenderPhases` and
`ViewSortedRenderPhases` resources.

## Migration Guide

* The `BinnedRenderPhase` and `SortedRenderPhase` render world
components have been replaced with `ViewBinnedRenderPhases` and
`ViewSortedRenderPhases` resources. Instead of querying for the
components, look the camera entity up in the
`ViewBinnedRenderPhases`/`ViewSortedRenderPhases` tables.
2024-05-21 18:23:04 +00:00
floppyhammer
8da4fcb616
Fix UI border artifacts caused by incorrect blending (#12725)
Fixes https://github.com/bevyengine/bevy/issues/12702.

Co-authored-by: François Mockers <mockersf@gmail.com>
2024-05-15 18:50:30 +00:00
IceSentry
64e1a7835a
Clean up 2d render phases (#12982)
# Objective

Currently, the 2d pipeline only has a transparent pass that is used for
everything. I want to have separate passes for opaque/alpha
mask/transparent meshes just like in 3d.

This PR does the basic work to start adding new phases to the 2d
pipeline and get the current setup a bit closer to 3d.

## Solution

- Use `ViewNode` for `MainTransparentPass2dNode`
- Added `Node2d::StartMainPass`, `Node2d::EndMainPass`
- Rename everything to clarify that the main pass is currently the
transparent pass

---

## Changelog

- Added `Node2d::StartMainPass`, `Node2d::EndMainPass`

## Migration Guide

If you were using `Node2d::MainPass` to order your own custom render
node. You now need to order it relative to `Node2d::StartMainPass` or
`Node2d::EndMainPass`.
2024-05-08 08:13:39 +00:00
Kristoffer Søholm
2089a28717
Add BufferVec, an higher-performance alternative to StorageBuffer, and make GpuArrayBuffer use it. (#13199)
This is an adoption of #12670 plus some documentation fixes. See that PR
for more details.

---

## Changelog

* Renamed `BufferVec` to `RawBufferVec` and added a new `BufferVec`
type.

## Migration Guide
`BufferVec` has been renamed to `RawBufferVec` and a new similar type
has taken the `BufferVec` name.

---------

Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2024-05-03 11:39:21 +00:00
Nico Burns
96b9d0a7e2
Upgrade to Taffy 0.4 (#10690)
# Objective

- Enables support for `Display::Block`
- Enables support for `Overflow::Hidden`
- Allows for cleaner integration with text, image and other content
layout.
- Unblocks https://github.com/bevyengine/bevy/pull/8104
- Unlocks the possibility of Bevy creating a custom layout tree over
which Taffy operates.
- Enables #8808 / #10193 to remove a Mutex around the font system.

## Todo

- [x] ~Fix rendering of text/images to account for padding/border on
nodes (should size/position to content box rather than border box)~ In
order get this into a mergeable state this PR instead zeroes out
padding/border when syncing leaf node styles into Taffy to preserve the
existing behaviour. https://github.com/bevyengine/bevy/issues/6879 can
be fixed in a followup PR.

## Solution

- Update the version of Taffy
- Update code to work with the new version

Note: Taffy 0.4 has not yet been released. This PR is being created in
advance of the release to ensure that there are no blockers to upgrading
once the release occurs.

---

## Changelog

- Bevy now supports the `Display::Block` and `Overflow::Hidden` styles.
2024-04-30 14:13:17 +00:00
Patrick Walton
16531fb3e3
Implement GPU frustum culling. (#12889)
This commit implements opt-in GPU frustum culling, built on top of the
infrastructure in https://github.com/bevyengine/bevy/pull/12773. To
enable it on a camera, add the `GpuCulling` component to it. To
additionally disable CPU frustum culling, add the `NoCpuCulling`
component. Note that adding `GpuCulling` without `NoCpuCulling`
*currently* does nothing useful. The reason why `GpuCulling` doesn't
automatically imply `NoCpuCulling` is that I intend to follow this patch
up with GPU two-phase occlusion culling, and CPU frustum culling plus
GPU occlusion culling seems like a very commonly-desired mode.

Adding the `GpuCulling` component to a view puts that view into
*indirect mode*. This mode makes all drawcalls indirect, relying on the
mesh preprocessing shader to allocate instances dynamically. In indirect
mode, the `PreprocessWorkItem` `output_index` points not to a
`MeshUniform` instance slot but instead to a set of `wgpu`
`IndirectParameters`, from which it allocates an instance slot
dynamically if frustum culling succeeds. Batch building has been updated
to allocate and track indirect parameter slots, and the AABBs are now
supplied to the GPU as `MeshCullingData`.

A small amount of code relating to the frustum culling has been borrowed
from meshlets and moved into `maths.wgsl`. Note that standard Bevy
frustum culling uses AABBs, while meshlets use bounding spheres; this
means that not as much code can be shared as one might think.

This patch doesn't provide any way to perform GPU culling on shadow
maps, to avoid making this patch bigger than it already is. That can be
a followup.

## Changelog

### Added

* Frustum culling can now optionally be done on the GPU. To enable it,
add the `GpuCulling` component to a camera.
* To disable CPU frustum culling, add `NoCpuCulling` to a camera. Note
that `GpuCulling` doesn't automatically imply `NoCpuCulling`.
2024-04-28 12:50:00 +00:00
François Mockers
75f1c5df7d
UI: pass the untransformed node size to the shader (#12839)
# Objective

- #12500 broke rotating ui nodes, see examples `pbr` (missing "metallic"
label) or `overflow_debug` (bottom right box is empty)

## Solution

- Pass the untransformed node size to the shader
2024-04-26 23:50:04 +00:00
Franklin Blanco
9c38844fc8
Added vmin and vmax to the gridtrack impls, repeatedgridtrack impls (#13096)
# Objective

- Fixes #13094 

## Solution

- Added vmin() and vmax() to the `GridTrack` & `RepeatedGridTrack`
impls, repeatedgridtrack impls, and both to the variants of Min & Max
TrackSizingFunction

## Sidenote
This would be my first PR to bevy. Feel free to say anything.

Thanks to the Bevy Team for everything you've done!

---------

Co-authored-by: Franklin <franklinblanco@tutanota.com>
2024-04-26 18:30:15 +00:00
findmyhappy
36a3e53e10
chore: fix some comments (#13083)
# Objective

remove repetitive words

Signed-off-by: findmyhappy <findhappy@sohu.com>
2024-04-25 19:09:16 +00:00
Salvador Carvalhinho
16ff354f1c
Correctly handle UI hierarchy without a camera (#12816)
# Objective
Add support so bevy_ui can correctly handle an UI hierarchy without a
camera present.

- Fixes #12184

## Solution

As there was no default behavior for what should happen when a camera is
not present in a UI hierarchy, the solution
was based in defining that default behavior and improving the overall
handling of this "exception".


## Changelog

- Create default values to be used in upsert_node
- Add flag to control warnings about no camera present
- Create unit test no_camera_ui (to test if ui handles no camera
present)
2024-04-22 16:42:13 +00:00
targrub
8316166622
Fix uses of "it's" vs "its". (#13033)
Grammar changes only.
2024-04-19 18:17:31 +00:00
Marco Meijer
2ad27ee4ee
fix: use try_insert instead of insert in bevy_ui to prevent panics when despawning ui nodes (#13000)
# Objective

Sometimes when despawning a ui node in the PostUpdate schedule it
panics. This is because both a despawn command and insert command are
being run on the same entity.

See this example code:

```rs
use bevy::{prelude::*, ui::UiSystem};

#[derive(Resource)]
struct SliceSquare(Handle<Image>);

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, create_ui)
        .add_systems(PostUpdate, despawn_nine_slice.after(UiSystem::Layout))
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle::default());
    commands.insert_resource(SliceSquare(asset_server.load("textures/slice_square.png")));
}

fn create_ui(mut commands: Commands, slice_square: Res<SliceSquare>) {
    commands.spawn((
        NodeBundle {
            style: Style {
                width: Val::Px(200.),
                height: Val::Px(200.),
                ..default()
            },
            background_color: Color::WHITE.into(),
            ..default()
        },
        UiImage::new(slice_square.0.clone()),
        ImageScaleMode::Sliced(TextureSlicer {
            border: BorderRect::square(220.),
            center_scale_mode: SliceScaleMode::Stretch,
            sides_scale_mode: SliceScaleMode::Stretch,
            max_corner_scale: 1.,
        }),
    ));
}

fn despawn_nine_slice(mut commands: Commands, mut slices: Query<Entity, With<ImageScaleMode>>) {
    for entity in slices.iter_mut() {
        commands.entity(entity).despawn_recursive();
    }
}
```

This code spawns a UiNode with a sliced image scale mode, and despawns
it in the same frame. The
bevy_ui::texture_slice::compute_slices_on_image_change system tries to
insert the ComputedTextureSlices component on that node, but that entity
is already despawned causing this error:

```md
error[B0003]: Could not insert a bundle (of type `bevy_ui::texture_slice::ComputedTextureSlices`) for entity Entity { index: 2, generation: 3 } because it doesn't 
exist in this World. See: https://bevyengine.org/learn/errors/#b0003
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic when applying buffers for system `bevy_ui::texture_slice::compute_slices_on_image_change`!
Encountered a panic in system `bevy_ecs::schedule::executor::apply_deferred`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
```

Note that you might have to run the code a few times before this error
appears.

## Solution

Use try_insert instead of insert for non critical inserts in the bevy_ui
crate.

## Some notes

In a lot of cases it does not makes much sense to despawn ui nodes after
the layout system has finished. Except maybe if you delete the root ui
node of a tree. I personally encountered this issue in bevy `0.13.2`
with a system that was running before the layout system. And in `0.13.2`
the `compute_slices_on_image_change` system was also running before the
layout system. But now it runs after the layout system. So the only way
that this bug appears now is if you despawn ui nodes after the layout
system. So I am not 100% sure if using try_insert in this system is the
best option. But personally I still think it is better then the program
panicking.

However the `update_children_target_camera` system does still run before
the layout system. So I do think it might still be able to panic when ui
nodes are despawned before the layout system. Though I haven't been able
to verify that.
2024-04-19 18:12:08 +00:00
Brezak
f68bc01544
Run CheckVisibility after all the other visibility system sets have… (#12962)
# Objective

Make visibility system ordering explicit. Fixes #12953.

## Solution

Specify `CheckVisibility` happens after all other `VisibilitySystems`
sets have happened.

---------

Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
2024-04-18 20:33:29 +00:00
Patrick Walton
5caf085dac
Divide the single VisibleEntities list into separate lists for 2D meshes, 3D meshes, lights, and UI elements, for performance. (#12582)
This commit splits `VisibleEntities::entities` into four separate lists:
one for lights, one for 2D meshes, one for 3D meshes, and one for UI
elements. This allows `queue_material_meshes` and similar methods to
avoid examining entities that are obviously irrelevant. In particular,
this separation helps scenes with many skinned meshes, as the individual
bones are considered visible entities but have no rendered appearance.

Internally, `VisibleEntities::entities` is a `HashMap` from the `TypeId`
representing a `QueryFilter` to the appropriate `Entity` list. I had to
do this because `VisibleEntities` is located within an upstream crate
from the crates that provide lights (`bevy_pbr`) and 2D meshes
(`bevy_sprite`). As an added benefit, this setup allows apps to provide
their own types of renderable components, by simply adding a specialized
`check_visibility` to the schedule.

This provides a 16.23% end-to-end speedup on `many_foxes` with 10,000
foxes (24.06 ms/frame to 20.70 ms/frame).

## Migration guide

* `check_visibility` and `VisibleEntities` now store the four types of
renderable entities--2D meshes, 3D meshes, lights, and UI
elements--separately. If your custom rendering code examines
`VisibleEntities`, it will now need to specify which type of entity it's
interested in using the `WithMesh2d`, `WithMesh`, `WithLight`, and
`WithNode` types respectively. If your app introduces a new type of
renderable entity, you'll need to add an explicit call to
`check_visibility` to the schedule to accommodate your new component or
components.

## Analysis

`many_foxes`, 10,000 foxes: `main`:
![Screenshot 2024-03-31
114444](https://github.com/bevyengine/bevy/assets/157897/16ecb2ff-6e04-46c0-a4b0-b2fde2084bad)

`many_foxes`, 10,000 foxes, this branch:
![Screenshot 2024-03-31
114256](https://github.com/bevyengine/bevy/assets/157897/94dedae4-bd00-45b2-9aaf-dfc237004ddb)

`queue_material_meshes` (yellow = this branch, red = `main`):
![Screenshot 2024-03-31
114637](https://github.com/bevyengine/bevy/assets/157897/f90912bd-45bd-42c4-bd74-57d98a0f036e)

`queue_shadows` (yellow = this branch, red = `main`):
![Screenshot 2024-03-31
114607](https://github.com/bevyengine/bevy/assets/157897/6ce693e3-20c0-4234-8ec9-a6f191299e2d)
2024-04-11 20:33:20 +00:00
Robert Swain
ab7cbfa8fc
Consolidate Render(Ui)Materials(2d) into RenderAssets (#12827)
# Objective

- Replace `RenderMaterials` / `RenderMaterials2d` / `RenderUiMaterials`
with `RenderAssets` to enable implementing changes to one thing,
`RenderAssets`, that applies to all use cases rather than duplicating
changes everywhere for multiple things that should be one thing.
- Adopts #8149 

## Solution

- Make RenderAsset generic over the destination type rather than the
source type as in #8149
- Use `RenderAssets<PreparedMaterial<M>>` etc for render materials

---

## Changelog

- Changed:
- The `RenderAsset` trait is now implemented on the destination type.
Its `SourceAsset` associated type refers to the type of the source
asset.
- `RenderMaterials`, `RenderMaterials2d`, and `RenderUiMaterials` have
been replaced by `RenderAssets<PreparedMaterial<M>>` and similar.

## Migration Guide

- `RenderAsset` is now implemented for the destination type rather that
the source asset type. The source asset type is now the `RenderAsset`
trait's `SourceAsset` associated type.
2024-04-09 13:26:34 +00:00
Brett Striker
ba8d70288d
[bevy_ui/layout] Update tests to get GlobalTransform properly (#12802)
This is 2 of 5 iterative PR's that affect bevy_ui/layout

- [x] Blocked by https://github.com/bevyengine/bevy/pull/12801

[Diff to parent
PR](https://github.com/StrikeForceZero/bevy/compare/dev/bevy_ui/breakup_layout_mod..dev/bevy_ui/update_layout_tests)

---

# Objective

- Update a test in bevy_ui/layout to use the proper way to get an up to
date `GlobalTransform`

## Solution

- Adds `sync_simple_transforms`, and `propagate_transforms` to the test
schedule in bevy_ui/layout

---
2024-04-03 02:48:06 +00:00
Brett Striker
cf092d45f9
[bevy_ui/layout] Extract UiSurface to its own file (#12801)
This is 1 of 5 iterative PR's that affect bevy_ui/layout

---

# Objective

- Extract `UiSurface` into its own file to make diffs in future PR's
easier to digest

## Solution

- Moved `UiSurface` to its own file
2024-04-01 22:47:34 +00:00
Cameron
01649f13e2
Refactor App and SubApp internals for better separation (#9202)
# Objective

This is a necessary precursor to #9122 (this was split from that PR to
reduce the amount of code to review all at once).

Moving `!Send` resource ownership to `App` will make it unambiguously
`!Send`. `SubApp` must be `Send`, so it can't wrap `App`.

## Solution

Refactor `App` and `SubApp` to not have a recursive relationship. Since
`SubApp` no longer wraps `App`, once `!Send` resources are moved out of
`World` and into `App`, `SubApp` will become unambiguously `Send`.

There could be less code duplication between `App` and `SubApp`, but
that would break `App` method chaining.

## Changelog

- `SubApp` no longer wraps `App`.
- `App` fields are no longer publicly accessible.
- `App` can no longer be converted into a `SubApp`.
- Various methods now return references to a `SubApp` instead of an
`App`.
## Migration Guide

- To construct a sub-app, use `SubApp::new()`. `App` can no longer
convert into `SubApp`.
- If you implemented a trait for `App`, you may want to implement it for
`SubApp` as well.
- If you're accessing `app.world` directly, you now have to use
`app.world()` and `app.world_mut()`.
- `App::sub_app` now returns `&SubApp`.
- `App::sub_app_mut`  now returns `&mut SubApp`.
- `App::get_sub_app` now returns `Option<&SubApp>.`
- `App::get_sub_app_mut` now returns `Option<&mut SubApp>.`
2024-03-31 03:16:10 +00:00
Patrick Walton
4dadebd9c4
Improve performance by binning together opaque items instead of sorting them. (#12453)
Today, we sort all entities added to all phases, even the phases that
don't strictly need sorting, such as the opaque and shadow phases. This
results in a performance loss because our `PhaseItem`s are rather large
in memory, so sorting is slow. Additionally, determining the boundaries
of batches is an O(n) process.

This commit makes Bevy instead applicable place phase items into *bins*
keyed by *bin keys*, which have the invariant that everything in the
same bin is potentially batchable. This makes determining batch
boundaries O(1), because everything in the same bin can be batched.
Instead of sorting each entity, we now sort only the bin keys. This
drops the sorting time to near-zero on workloads with few bins like
`many_cubes --no-frustum-culling`. Memory usage is improved too, with
batch boundaries and dynamic indices now implicit instead of explicit.
The improved memory usage results in a significant win even on
unbatchable workloads like `many_cubes --no-frustum-culling
--vary-material-data-per-instance`, presumably due to cache effects.

Not all phases can be binned; some, such as transparent and transmissive
phases, must still be sorted. To handle this, this commit splits
`PhaseItem` into `BinnedPhaseItem` and `SortedPhaseItem`. Most of the
logic that today deals with `PhaseItem`s has been moved to
`SortedPhaseItem`. `BinnedPhaseItem` has the new logic.

Frame time results (in ms/frame) are as follows:

| Benchmark                | `binning` | `main`  | Speedup |
| ------------------------ | --------- | ------- | ------- |
| `many_cubes -nfc -vpi` | 232.179     | 312.123   | 34.43%  |
| `many_cubes -nfc`        | 25.874 | 30.117 | 16.40%  |
| `many_foxes`             | 3.276 | 3.515 | 7.30%   |

(`-nfc` is short for `--no-frustum-culling`; `-vpi` is short for
`--vary-per-instance`.)

---

## Changelog

### Changed

* Render phases have been split into binned and sorted phases. Binned
phases, such as the common opaque phase, achieve improved CPU
performance by avoiding the sorting step.

## Migration Guide

- `PhaseItem` has been split into `BinnedPhaseItem` and
`SortedPhaseItem`. If your code has custom `PhaseItem`s, you will need
to migrate them to one of these two types. `SortedPhaseItem` requires
the fewest code changes, but you may want to pick `BinnedPhaseItem` if
your phase doesn't require sorting, as that enables higher performance.

## Tracy graphs

`many-cubes --no-frustum-culling`, `main` branch:
<img width="1064" alt="Screenshot 2024-03-12 180037"
src="https://github.com/bevyengine/bevy/assets/157897/e1180ce8-8e89-46d2-85e3-f59f72109a55">

`many-cubes --no-frustum-culling`, this branch:
<img width="1064" alt="Screenshot 2024-03-12 180011"
src="https://github.com/bevyengine/bevy/assets/157897/0899f036-6075-44c5-a972-44d95895f46c">

You can see that `batch_and_prepare_binned_render_phase` is a much
smaller fraction of the time. Zooming in on that function, with yellow
being this branch and red being `main`, we see:

<img width="1064" alt="Screenshot 2024-03-12 175832"
src="https://github.com/bevyengine/bevy/assets/157897/0dfc8d3f-49f4-496e-8825-a66e64d356d0">

The binning happens in `queue_material_meshes`. Again with yellow being
this branch and red being `main`:
<img width="1064" alt="Screenshot 2024-03-12 175755"
src="https://github.com/bevyengine/bevy/assets/157897/b9b20dc1-11c8-400c-a6cc-1c2e09c1bb96">

We can see that there is a small regression in `queue_material_meshes`
performance, but it's not nearly enough to outweigh the large gains in
`batch_and_prepare_binned_render_phase`.

---------

Co-authored-by: James Liu <contact@jamessliu.com>
2024-03-30 02:55:02 +00:00
Jacques Schutte
4508077297
Move FloatOrd into bevy_math (#12732)
# Objective

- Fixes #12712

## Solution

- Move the `float_ord.rs` file to `bevy_math`
- Change any `bevy_utils::FloatOrd` statements to `bevy_math::FloatOrd`

---

## Changelog

- Moved `FloatOrd` from `bevy_utils` to `bevy_math`

## Migration Guide

- References to `bevy_utils::FloatOrd` should be changed to
`bevy_math::FloatOrd`
2024-03-27 18:30:11 +00:00
James Liu
56bcbb0975
Forbid unsafe in most crates in the engine (#12684)
# Objective
Resolves #3824. `unsafe` code should be the exception, not the norm in
Rust. It's obviously needed for various use cases as it's interfacing
with platforms and essentially running the borrow checker at runtime in
the ECS, but the touted benefits of Bevy is that we are able to heavily
leverage Rust's safety, and we should be holding ourselves accountable
to that by minimizing our unsafe footprint.

## Solution
Deny `unsafe_code` workspace wide. Add explicit exceptions for the
following crates, and forbid it in almost all of the others.

* bevy_ecs - Obvious given how much unsafe is needed to achieve
performant results
* bevy_ptr - Works with raw pointers, even more low level than bevy_ecs.
 * bevy_render - due to needing to integrate with wgpu
 * bevy_window - due to needing to integrate with raw_window_handle
* bevy_utils - Several unsafe utilities used by bevy_ecs. Ideally moved
into bevy_ecs instead of made publicly usable.
 * bevy_reflect - Required for the unsafe type casting it's doing.
 * bevy_transform - for the parallel transform propagation
 * bevy_gizmos  - For the SystemParam impls it has.
* bevy_assets - To support reflection. Might not be required, not 100%
sure yet.
* bevy_mikktspace - due to being a conversion from a C library. Pending
safe rewrite.
* bevy_dynamic_plugin - Inherently unsafe due to the dynamic loading
nature.

Several uses of unsafe were rewritten, as they did not need to be using
them:

* bevy_text - a case of `Option::unchecked` could be rewritten as a
normal for loop and match instead of an iterator.
* bevy_color - the Pod/Zeroable implementations were replaceable with
bytemuck's derive macros.
2024-03-27 03:30:08 +00:00
Brett Striker
b2b302bdfd
Restore pre 0.13.1 Root Node Layout behavior (#12698)
# Objective

Fix the regression for Root Node's Layout behavior introduced in
https://github.com/bevyengine/bevy/pull/12268

- Add regression test for Root Node Layout's behaving as they did before
0.13.1
- Restore pre 0.13.1 Root Node Layout behavior (fixes
https://github.com/bevyengine/bevy/issues/12624)

## Solution

This implements [@nicoburns suggestion
](https://discord.com/channels/691052431525675048/743663673393938453/1221593626476548146),
where instead of adding the camera to the taffy node tree, we revert
back to adding a new "parent" node for each root node while maintaining
their relationship with the camera.

> If you can do the ecs change detection to move the node to the correct
Taffy instance for the camera then you should also be able to move it to
a `Vec` of root nodes for that camera.

---

## Changelog

Fixed https://github.com/bevyengine/bevy/issues/12624 - Restores pre
0.13.1 Root Node Layout behavior

## Migration Guide

If you were affected by the 0.13.1 regression and added `position_type:
Absolute` to all your root nodes you might be able to reclaim some LOC
by removing them now that the 0.13 behavior is restored.
2024-03-25 19:11:50 +00:00
James Liu
f096ad4155
Set the logo and favicon for all of Bevy's published crates (#12696)
# Objective
Currently the built docs only shows the logo and favicon for the top
level `bevy` crate. This makes views like
https://docs.rs/bevy_ecs/latest/bevy_ecs/ look potentially unrelated to
the project at first glance.

## Solution
Reproduce the docs attributes for every crate that Bevy publishes.

Ideally this would be done with some workspace level Cargo.toml control,
but AFAICT, such support does not exist.
2024-03-25 18:52:50 +00:00
Pietro
99d9cc1e49
fix: make WebGPU shader work again (#12683)
# Objective

- Fixes WebGPU UI shader.

<img width="505" alt="image"
src="https://github.com/bevyengine/bevy/assets/106191044/0ae30234-0aae-4f02-95f2-dfb3657d8e67">


## Solution

- Renames a variable to avoid naming conflict.
2024-03-24 10:29:39 +00:00
Ame
72c51cdab9
Make feature(doc_auto_cfg) work (#12642)
# Objective

- In #12366 `![cfg_attr(docsrs, feature(doc_auto_cfg))] `was added. But
to apply it it needs `--cfg=docsrs` in rustdoc-args.


## Solution

- Apply `--cfg=docsrs` to all crates and CI.

I also added `[package.metadata.docs.rs]` to all crates to avoid adding
code behind a feature and forget adding the metadata.

Before:

![Screenshot 2024-03-22 at 00 51
57](https://github.com/bevyengine/bevy/assets/104745335/6a9dfdaa-8710-4784-852b-5f9b74e3522c)

After:
![Screenshot 2024-03-22 at 00 51
32](https://github.com/bevyengine/bevy/assets/104745335/c5bd6d8e-8ddb-45b3-b844-5ecf9f88961c)
2024-03-23 02:22:52 +00:00
François Mockers
2f6d8663d0
rounded border: remove dead code in shader (#12602)
# Objective

- #12500 added dead code to the ui shader

## Solution

- Remove it
2024-03-21 19:17:13 +00:00
François Mockers
7b842e373e
UI: rounded border should use camera instead of windows (#12601)
# Objective

- #12500 use the primary window resolution to do all its calculation.
This means bad support for multiple windows or multiple ui camera

## Solution

- Use camera driven UI (https://github.com/bevyengine/bevy/pull/10559)
2024-03-20 23:50:08 +00:00
François Mockers
bd90a64ae0
UI: don't multiply color channels by alpha (#12599)
# Objective

- since #12500, text is a little bit more gray in UI

## Solution

- don't multiply color by alpha. I think this was done in the original
PR (#8973) for shadows which were not added in #12500
2024-03-20 23:15:40 +00:00
François Mockers
779e4c4901
UI: allow border radius to be optional for images and background (#12592)
# Objective

- #12500 broke images and background colors in UI. Try examples
`overflow`, `ui_scaling` or `ui_texture_atlas`

## Solution

- Makes the component `BorderRadius` optional in the query, as it's not
always present. Use `[0.; 4]` as border radius in the extracted node
when none was found
2024-03-20 13:11:24 +00:00
Antony
e7a31d000e
Add border radius to UI nodes (adopted) (#12500)
# Objective

Implements border radius for UI nodes. Adopted from #8973, but excludes
shadows.

## Solution

- Add a component `BorderRadius` which contains a radius value for each
corner of the UI node.
- Use a fragment shader to generate the rounded corners using a signed
distance function.

<img width="50%"
src="https://github.com/bevyengine/bevy/assets/26204416/16b2ba95-e274-4ce7-adb2-34cc41a776a5"></img>

## Changelog

- `BorderRadius`: New component that holds the border radius values.
- `NodeBundle` & `ButtonBundle`: Added a `border_radius: BorderRadius`
field.
- `extract_uinode_borders`: Stripped down, most of the work is done in
the shader now. Borders are no longer assembled from multiple rects,
instead the shader uses a signed distance function to draw the border.
- `UiVertex`: Added size, border and radius fields.
- `UiPipeline`: Added three vertex attributes to the vertex buffer
layout, to accept the UI node's size, border thickness and border
radius.
- Examples: Added rounded corners to the UI element in the `button`
example, and a `rounded_borders` example.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
2024-03-19 22:44:00 +00:00
Andrew
fc4716f56c
feat: derive some common traits on some UI types (#12532)
# Objective

- working with UI components in Bevy, I found myself wanting some of
these common traits, like `PartialEq` for comparing simple types

## Solution

- I added only (hopefully) uncontroversial `derive`s for some common UI
types

Note that many types, unfortunately, can't have `PartialEq` `derive`d
for them, because they contain `f32`s and / or `Vec`s.
2024-03-18 03:41:50 +00:00
Marco Meijer
fe7069e4cc
Compute texture slices after layout (#12533)
# Objective

Whenever a nodes size gets changed, its texture slices get updated a
frame later. This results in visual glitches when animating the size of
a node with a texture slice. See this video:

[Screencast from 17-03-24
14:53:13.webm](https://github.com/bevyengine/bevy/assets/46689298/64e711f7-a1ec-41e3-b119-dc8d7e1a7669)


## Solution

Compute texture slices after the layout system has finished.
2024-03-17 21:10:28 +00:00
robtfm
1323de7cd7
stop retrying removed assets (#12505)
# Objective

assets that don't load before they get removed are retried forever,
causing buffer churn and slowdown.

## Solution

stop trying to prepare dead assets.
2024-03-16 04:49:16 +00:00
Antony
fec00040ef
Add with_left, with_right, with_top, with_bottom to UiRect (#12487)
# Objective

Originally proposed as part of #8973. Adds `with_` methods for each side
of `UiRect`

## Solution

Add `with_left`, `with_right`, `with_top`, `with_bottom` to `UiRect`.
2024-03-15 17:43:39 +00:00
Rob Parrett
55b786c2b7
Fix blurry text (#12429)
# Objective

Fixes #12064

## Solution

Prior to #11326, the "global physical" translation of text was rounded.

After #11326, only the "offset" is being rounded.

This moves things around so that the "global translation" is converted
to physical pixels, rounded, and then converted back to logical pixels,
which is what I believe was happening before / what the comments above
describe.

## Discussion

This seems to work and fix an obvious mistake in some code, but I don't
fully grok the ui / text pipelines / math here.

## Before / After and test example

<details>
<summary>Expand Code</summary>

```rust
use std::f32::consts::FRAC_PI_2;

use bevy::prelude::*;
use bevy_internal:🪟:WindowResolution;

const FONT_SIZE: f32 = 25.0;
const PADDING: f32 = 5.0;

fn main() {
    App::new()
        .add_plugins(
            DefaultPlugins.set(WindowPlugin {
                primary_window: Some(Window {
                    resolution: WindowResolution::default().with_scale_factor_override(1.0),
                    ..default()
                }),
                ..default()
            }),
            //.set(ImagePlugin::default_nearest()),
        )
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle::default());

    let font = asset_server.load("fonts/FiraSans-Bold.ttf");

    for x in [20.5, 140.0] {
        for i in 1..10 {
            text(
                &mut commands,
                font.clone(),
                x,
                (FONT_SIZE + PADDING) * i as f32,
                i,
                Quat::default(),
                1.0,
            );
        }
    }

    for x in [450.5, 700.0] {
        for i in 1..10 {
            text(
                &mut commands,
                font.clone(),
                x,
                ((FONT_SIZE * 2.0) + PADDING) * i as f32,
                i,
                Quat::default(),
                2.0,
            );
        }
    }

    for y in [400.0, 600.0] {
        for i in 1..10 {
            text(
                &mut commands,
                font.clone(),
                (FONT_SIZE + PADDING) * i as f32,
                y,
                i,
                Quat::from_rotation_z(FRAC_PI_2),
                1.0,
            );
        }
    }
}

fn text(
    commands: &mut Commands,
    font: Handle<Font>,
    x: f32,
    y: f32,
    i: usize,
    rot: Quat,
    scale: f32,
) {
    let text = (65..(65 + i)).map(|a| a as u8 as char).collect::<String>();

    commands.spawn(TextBundle {
        style: Style {
            position_type: PositionType::Absolute,
            left: Val::Px(x),
            top: Val::Px(y),
            ..default()
        },
        text: Text::from_section(
            text,
            TextStyle {
                font,
                font_size: FONT_SIZE,
                ..default()
            },
        ),
        transform: Transform::from_rotation(rot).with_scale(Vec2::splat(scale).extend(1.)),
        ..default()
    });
}
```

</details>

Open both images in new tabs and swap back and forth. Pay attention to
the "A" and "ABCD" lines.

<details>
<summary>Before</summary>

<img width="640" alt="main3"
src="https://github.com/bevyengine/bevy/assets/200550/248d7a55-d06d-433f-80da-1914803c3551">

</details>

<details>
<summary>After</summary>

<img width="640" alt="pr3"
src="https://github.com/bevyengine/bevy/assets/200550/26a9d292-07ae-4af3-b035-e187b2529ace">

</details>

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2024-03-13 01:21:10 +00:00
UkoeHB
535250c088
Reduce steady-state allocations in ui_stack_system (#12413)
# Objective

- Reduce allocations on the UI hot path.

## Solution

- Cache buffers used by the `ui_stack_system`.

## Follow-Up

- `sort_by_key` is potentially-allocating. It might be worthwhile to
include the child index as part of the sort-key and use unstable sort.
2024-03-12 13:57:57 +00:00
robtfm
bc4d8bbb93
don't attempt to set cursor relative position for zero sized nodes (#12395)
# Objective

fix #12007

## Solution

when node size is zero on either axis, set
`RelativeCursorPosition::normalized` to None.
2024-03-10 02:18:40 +00:00
Al M
52e3f2007b
Add "all-features = true" to docs.rs metadata for most crates (#12366)
# Objective

Fix missing `TextBundle` (and many others) which are present in the main
crate as default features but optional in the sub-crate. See:

- https://docs.rs/bevy/0.13.0/bevy/ui/node_bundles/index.html
- https://docs.rs/bevy_ui/0.13.0/bevy_ui/node_bundles/index.html

~~There are probably other instances in other crates that I could track
down, but maybe "all-features = true" should be used by default in all
sub-crates? Not sure.~~ (There were many.) I only noticed this because
rust-analyzer's "open docs" features takes me to the sub-crate, not the
main one.

## Solution

Add "all-features = true" to docs.rs metadata for crates that use
features.

## Changelog

### Changed

- Unified features documented on docs.rs between main crate and
sub-crates
2024-03-08 20:03:09 +00:00
Frank Hampus Weslien
118424d64a
Fix incorrect link in UiMaterial documentation (#12361)
# Objective

- Fix incorrect link in UIMaterial docs

## Solution

- Updated the link

Co-authored-by: Frank Hampus Weslien <frankhampusweslien@google.com>
2024-03-07 22:09:57 +00:00
James Liu
512b7463a3
Disentangle bevy_utils/bevy_core's reexported dependencies (#12313)
# Objective
Make bevy_utils less of a compilation bottleneck. Tackle #11478.

## Solution
* Move all of the directly reexported dependencies and move them to
where they're actually used.
* Remove the UUID utilities that have gone unused since `TypePath` took
over for `TypeUuid`.
* There was also a extraneous bytemuck dependency on `bevy_core` that
has not been used for a long time (since `encase` became the primary way
to prepare GPU buffers).
* Remove the `all_tuples` macro reexport from bevy_ecs since it's
accessible from `bevy_utils`.

---

## Changelog
Removed: Many of the reexports from bevy_utils (petgraph, uuid, nonmax,
smallvec, and thiserror).
Removed: bevy_core's reexports of bytemuck.

## Migration Guide
bevy_utils' reexports of petgraph, uuid, nonmax, smallvec, and thiserror
have been removed.

bevy_core' reexports of bytemuck's types has been removed. 

Add them as dependencies in your own crate instead.
2024-03-07 02:30:15 +00:00
James Liu
9e5db9abc7
Clean up type registrations (#12314)
# Objective
Fix #12304. Remove unnecessary type registrations thanks to #4154.

## Solution
Conservatively remove type registrations. Keeping the top level
components, resources, and events, but dropping everything else that is
a type of a member of those types.
2024-03-06 16:05:53 +00:00
Ben Frankel
e9671f3e96
Fix docs for atlas + slicing support (#12325)
# Objective

The docs say that atlas and slicing are incompatible, but they are now
compatible after https://github.com/bevyengine/bevy/pull/12059.

## Solution

Update the docs.
2024-03-05 18:04:22 +00:00
Félix Lescaudey de Maneville
fc202f2e3d
Slicing support for texture atlas (#12059)
# Objective

Follow up to #11600 and #10588 
https://github.com/bevyengine/bevy/issues/11944 made clear that some
people want to use slicing with texture atlases

## Changelog

* Added support for `TextureAtlas` slicing and tiling.
`SpriteSheetBundle` and `AtlasImageBundle` can now use `ImageScaleMode`
* Added new `ui_texture_atlas_slice` example using a texture sheet

<img width="798" alt="Screenshot 2024-02-23 at 11 58 35"
src="https://github.com/bevyengine/bevy/assets/26703856/47a8b764-127c-4a06-893f-181703777501">

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
2024-03-05 16:05:39 +00:00
Brett Striker
b02a2eff17
Fix #12255 Updating TargetCamera on multi camera scenes not allowing layout to be calculated (#12268)
# Objective

- Fixes #12255

Still needs confirming what the consequences are from having camera
viewport nodes live on the root of the taffy tree.

## Solution

To fix calculating the layouts for UI nodes we need to cleanup the
children previously set whenever `TargetCamera` is updated. This also
maintains a list of taffy camera nodes and cleans them up when removed.

---

## Changelog

Fixed #12255

## Migration Guide

changes affect private structs/members so shouldn't need actions by
engine users.
2024-03-04 19:19:25 +00:00
Ben Frankel
e8ae0d6c49
Decouple BackgroundColor from UiImage (#11165)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/11157.

## Solution

Stop using `BackgroundColor` as a color tint for `UiImage`. Add a
`UiImage::color` field for color tint instead. Allow a UI node to
simultaneously include a solid-color background and an image, with the
image rendered on top of the background (this is already how it works
for e.g. text).


![2024-02-29_1709239666_563x520](https://github.com/bevyengine/bevy/assets/12173779/ec50c9ef-4c7f-4ab8-a457-d086ce5b3425)

---

## Changelog

- The `BackgroundColor` component now renders a solid-color background
behind `UiImage` instead of tinting its color.
- Removed `BackgroundColor` from `ImageBundle`, `AtlasImageBundle`, and
`ButtonBundle`.
- Added `UiImage::color`.
- Expanded `RenderUiSystem` variants.
- Renamed `bevy_ui::extract_text_uinodes` to `extract_uinodes_text` for
consistency.

## Migration Guide

- `BackgroundColor` no longer tints the color of UI images. Use
`UiImage::color` for that instead.
- For solid color buttons, replace `ButtonBundle { background_color:
my_color.into(), ... }` with `ButtonBundle { image:
UiImage::default().with_color(my_color), ... }`, and update button
interaction systems to use `UiImage::color` instead of `BackgroundColor`
as well.
- `bevy_ui::RenderUiSystem::ExtractNode` has been split into
`ExtractBackgrounds`, `ExtractImages`, `ExtractBorders`, and
`ExtractText`.
- `bevy_ui::extract_uinodes` has been split into
`bevy_ui::extract_uinode_background_colors` and
`bevy_ui::extract_uinode_images`.
- `bevy_ui::extract_text_uinodes` has been renamed to
`extract_uinode_text`.
2024-03-03 21:35:50 +00:00
Ben Frankel
6e83439a06
Deprecate SpriteSheetBundle and AtlasImageBundle (#12218)
# Objective

After the `TextureAtlas` changes that landed in 0.13,
`SpriteSheetBundle` is equivalent to `TextureAtlas` + `SpriteBundle` and
`AtlasImageBundle` is equivalent to `TextureAtlas` + `ImageBundle`. As
such, the atlas bundles aren't particularly useful / necessary additions
to the API anymore.

In addition, atlas bundles are inconsistent with `ImageScaleMode` (also
introduced in 0.13) which doesn't have its own version of each image
bundle.

## Solution

Deprecate `SpriteSheetBundle` and `AtlasImageBundle` in favor of
including `TextureAtlas` as a separate component alongside
`SpriteBundle` and `ImageBundle`, respectively.

---

## Changelog

- Deprecated `SpriteSheetBundle` and `AtlasImageBundle`.

## Migration Guide

- `SpriteSheetBundle` has been deprecated. Use `TextureAtlas` alongside
a `SpriteBundle` instead.
- `AtlasImageBundle` has been deprecated. Use `TextureAtlas` alongside
an `ImageBundle` instead.
2024-03-03 20:11:15 +00:00
targrub
13cbb9cf10
Move commands module into bevy::ecs::world (#12234)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/11628

## Migration Guide

`Command` and `CommandQueue` have migrated from `bevy_ecs::system` to
`bevy_ecs::world`, so `use bevy_ecs::world::{Command, CommandQueue};`
when necessary.
2024-03-02 23:13:45 +00:00
James Liu
5619bd09d1
Replace bevy_log's tracing reexport with bevy_utils' (#12254)
# Objective
Fixes #11298. Make the use of bevy_log vs bevy_utils::tracing more
consistent.

## Solution
Replace all uses of bevy_log's logging macros with the reexport from
bevy_utils. Remove bevy_log as a dependency where it's no longer needed
anymore.

Ideally we should just be using tracing directly, but given that all of
these crates are already using bevy_utils, this likely isn't that great
of a loss right now.
2024-03-02 18:38:04 +00:00
Natalie Soltis
cc32610543
Add size and physical_size to window (#12238)
This is an implementation within `bevy_window::window` that fixes
#12229.

# Objective

Fixes #12229, allow users to retrieve the window's size and physical
size as Vectors without having to manually construct them using
`height()` and `width()` or `physical_height()` and `physical_width()`

## Solution

As suggested in #12229, created two public functions within `window`:
`size() -> Vec` and `physical_size() -> UVec` that return the needed
Vectors ready-to-go.

### Discussion

My first FOSS PRQ ever, so bear with me a bit. I'm new to this.

- I replaced instances of ```Vec2::new(window.width(),
window.height());``` or `UVec2::new(window.physical_width(),
window.physical_height());` within bevy examples be replaced with their
`size()`/`physical_size()` counterparts?
- Discussion within #12229 still holds: should these also be added to
WindowResolution?
2024-03-01 22:28:37 +00:00
Sludge
080f280b59
Avoid panicking with non-UI nodes (#12213)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/10826
- Fixes https://github.com/bevyengine/bevy/issues/9615

## Solution

- Early-out when components are missing.
2024-02-29 21:36:45 +00:00
Alice Cecile
599e5e4e76
Migrate from LegacyColor to bevy_color::Color (#12163)
# Objective

- As part of the migration process we need to a) see the end effect of
the migration on user ergonomics b) check for serious perf regressions
c) actually migrate the code
- To accomplish this, I'm going to attempt to migrate all of the
remaining user-facing usages of `LegacyColor` in one PR, being careful
to keep a clean commit history.
- Fixes #12056.

## Solution

I've chosen to use the polymorphic `Color` type as our standard
user-facing API.

- [x] Migrate `bevy_gizmos`.
- [x] Take `impl Into<Color>` in all `bevy_gizmos` APIs
- [x] Migrate sprites
- [x] Migrate UI
- [x] Migrate `ColorMaterial`
- [x] Migrate `MaterialMesh2D`
- [x] Migrate fog
- [x] Migrate lights
- [x] Migrate StandardMaterial
- [x] Migrate wireframes
- [x] Migrate clear color
- [x] Migrate text
- [x] Migrate gltf loader
- [x] Register color types for reflection
- [x] Remove `LegacyColor`
- [x] Make sure CI passes

Incidental improvements to ease migration:

- added `Color::srgba_u8`, `Color::srgba_from_array` and friends
- added `set_alpha`, `is_fully_transparent` and `is_fully_opaque` to the
`Alpha` trait
- add and immediately deprecate (lol) `Color::rgb` and friends in favor
of more explicit and consistent `Color::srgb`
- standardized on white and black for most example text colors
- added vector field traits to `LinearRgba`: ~~`Add`, `Sub`,
`AddAssign`, `SubAssign`,~~ `Mul<f32>` and `Div<f32>`. Multiplications
and divisions do not scale alpha. `Add` and `Sub` have been cut from
this PR.
- added `LinearRgba` and `Srgba` `RED/GREEN/BLUE`
- added `LinearRgba_to_f32_array` and `LinearRgba::to_u32`

## Migration Guide

Bevy's color types have changed! Wherever you used a
`bevy::render::Color`, a `bevy::color::Color` is used instead.

These are quite similar! Both are enums storing a color in a specific
color space (or to be more precise, using a specific color model).
However, each of the different color models now has its own type.

TODO...

- `Color::rgba`, `Color::rgb`, `Color::rbga_u8`, `Color::rgb_u8`,
`Color::rgb_from_array` are now `Color::srgba`, `Color::srgb`,
`Color::srgba_u8`, `Color::srgb_u8` and `Color::srgb_from_array`.
- `Color::set_a` and `Color::a` is now `Color::set_alpha` and
`Color::alpha`. These are part of the `Alpha` trait in `bevy_color`.
- `Color::is_fully_transparent` is now part of the `Alpha` trait in
`bevy_color`
- `Color::r`, `Color::set_r`, `Color::with_r` and the equivalents for
`g`, `b` `h`, `s` and `l` have been removed due to causing silent
relatively expensive conversions. Convert your `Color` into the desired
color space, perform your operations there, and then convert it back
into a polymorphic `Color` enum.
- `Color::hex` is now `Srgba::hex`. Call `.into` or construct a
`Color::Srgba` variant manually to convert it.
- `WireframeMaterial`, `ExtractedUiNode`, `ExtractedDirectionalLight`,
`ExtractedPointLight`, `ExtractedSpotLight` and `ExtractedSprite` now
store a `LinearRgba`, rather than a polymorphic `Color`
- `Color::rgb_linear` and `Color::rgba_linear` are now
`Color::linear_rgb` and `Color::linear_rgba`
- The various CSS color constants are no longer stored directly on
`Color`. Instead, they're defined in the `Srgba` color space, and
accessed via `bevy::color::palettes::css`. Call `.into()` on them to
convert them into a `Color` for quick debugging use, and consider using
the much prettier `tailwind` palette for prototyping.
- The `LIME_GREEN` color has been renamed to `LIMEGREEN` to comply with
the standard naming.
- Vector field arithmetic operations on `Color` (add, subtract, multiply
and divide by a f32) have been removed. Instead, convert your colors
into `LinearRgba` space, and perform your operations explicitly there.
This is particularly relevant when working with emissive or HDR colors,
whose color channel values are routinely outside of the ordinary 0 to 1
range.
- `Color::as_linear_rgba_f32` has been removed. Call
`LinearRgba::to_f32_array` instead, converting if needed.
- `Color::as_linear_rgba_u32` has been removed. Call
`LinearRgba::to_u32` instead, converting if needed.
- Several other color conversion methods to transform LCH or HSL colors
into float arrays or `Vec` types have been removed. Please reimplement
these externally or open a PR to re-add them if you found them
particularly useful.
- Various methods on `Color` such as `rgb` or `hsl` to convert the color
into a specific color space have been removed. Convert into
`LinearRgba`, then to the color space of your choice.
- Various implicitly-converting color value methods on `Color` such as
`r`, `g`, `b` or `h` have been removed. Please convert it into the color
space of your choice, then check these properties.
- `Color` no longer implements `AsBindGroup`. Store a `LinearRgba`
internally instead to avoid conversion costs.

---------

Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
Co-authored-by: Afonso Lage <lage.afonso@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-02-29 19:35:12 +00:00
robtfm
c13de09feb
ui materials respect target camera (#12183)
# Objective

fix #12182 

- extract (or default) target camera for ui material nodes in the same
way as for other material nodes
- render ui material nodes only to their specified target
2024-02-28 17:43:24 +00:00
Alex
a7be8a2655
Prefer UVec2 when working with texture dimensions (#11698)
# Objective

The physical width and height (pixels) of an image is always integers,
but for `GpuImage` bevy currently stores them as `Vec2` (`f32`).
Switching to `UVec2` makes this more consistent with the [underlying
texture data](https://docs.rs/wgpu/latest/wgpu/struct.Extent3d.html).

I'm not sure if this is worth the change in the surface level API. If
not, feel free to close this PR.

## Solution

- Replace uses of `Vec2` with `UVec2` when referring to texture
dimensions.
- Use integer types for the texture atlas dimensions and sections.


[`Sprite::rect`](a81a2d1da3/crates/bevy_sprite/src/sprite.rs (L29))
remains unchanged, so manually specifying a sub-pixel region of an image
is still possible.

---

## Changelog

- `GpuImage` now stores its size as `UVec2` instead of `Vec2`.
- Texture atlases store their size and sections as `UVec2` and `URect`
respectively.
- `UiImageSize` stores its size as `UVec2`.

## Migration Guide

- Change floating point types (`Vec2`, `Rect`) to their respective
unsigned integer versions (`UVec2`, `URect`) when using `GpuImage`,
`TextureAtlasLayout`, `TextureAtlasBuilder`,
`DynamicAtlasTextureBuilder` or `FontAtlas`.
2024-02-25 15:23:04 +00:00
eri
5f8f3b532c
Check cfg during CI and fix feature typos (#12103)
# Objective

- Add the new `-Zcheck-cfg` checks to catch more warnings
- Fixes #12091

## Solution

- Create a new `cfg-check` to the CI that runs `cargo check -Zcheck-cfg
--workspace` using cargo nightly (and fails if there are warnings)
- Fix all warnings generated by the new check

---

## Changelog

- Remove all redundant imports
- Fix cfg wasm32 targets
- Add 3 dead code exceptions (should StandardColor be unused?)
- Convert ios_simulator to a feature (I'm not sure if this is the right
way to do it, but the check complained before)

## Migration Guide

No breaking changes

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-02-25 15:19:27 +00:00
Alice Cecile
de004da8d5
Rename bevy_render::Color to LegacyColor (#12069)
# Objective

The migration process for `bevy_color` (#12013) will be fairly involved:
there will be hundreds of affected files, and a large number of APIs.

## Solution

To allow us to proceed granularly, we're going to keep both
`bevy_color::Color` (new) and `bevy_render::Color` (old) around until
the migration is complete.

However, simply doing this directly is confusing! They're both called
`Color`, making it very hard to tell when a portion of the code has been
ported.

As discussed in #12056, by renaming the old `Color` type, we can make it
easier to gradually migrate over, one API at a time.

## Migration Guide

THIS MIGRATION GUIDE INTENTIONALLY LEFT BLANK.

This change should not be shipped to end users: delete this section in
the final migration guide!

---------

Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
2024-02-24 21:35:32 +00:00
Félix Lescaudey de Maneville
fa1740630c
Fixed Ui Image slicing (#12047)
# Objective

Fixes #11944

## Solution

#11600 made an incorrect assumption on what `UiImageSize` does, removing
its usage in slicing fixes the problem
2024-02-23 01:08:32 +00:00
Ame
9d67edc3a6
fix some typos (#12038)
# Objective

Split - containing only the fixed typos

-
https://github.com/bevyengine/bevy/pull/12036#pullrequestreview-1894738751


# Migration Guide
In `crates/bevy_mikktspace/src/generated.rs` 

```rs
// before
pub struct SGroup {
    pub iVertexRepresentitive: i32,
    ..
}

// after
pub struct SGroup {
    pub iVertexRepresentative: i32,
    ..
}
```

In `crates/bevy_core_pipeline/src/core_2d/mod.rs`

```rs
// before
Node2D::ConstrastAdaptiveSharpening

// after
Node2D::ContrastAdaptiveSharpening
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: François <mockersf@gmail.com>
2024-02-22 18:55:22 +00:00
Carter Anderson
f83de49b7a
Rename Core Render Graph Labels (#11882)
# Objective

#10644 introduced nice "statically typed" labels that replace the old
strings. I would like to propose some changes to the names introduced:

* `SubGraph2d` -> `Core2d` and `SubGraph3d` -> `Core3d`. The names of
these graphs have been / should continue to be the "core 2d" graph not
the "sub graph 2d" graph. The crate is called `bevy_core_pipeline`, the
modules are still `core_2d` and `core_3d`, etc.
* `Labels2d` and `Labels3d`, at the very least, should not be plural to
follow naming conventions. A Label enum is not a "collection of labels",
it is a _specific_ Label. However I think `Label2d` and `Label3d` is
significantly less clear than `Node2d` and `Node3d`, so I propose those
changes here. I've done the same for `LabelsPbr` -> `NodePbr` and
`LabelsUi` -> `NodeUi`

Additionally, #10644 accidentally made one of the Camera2dBundle
constructors use the 3D graph instead of the 2D graph. I've fixed that
here.
 
---

## Changelog

* Renamed `SubGraph2d` -> `Core2d`, `SubGraph3d` -> `Core3d`, `Labels2d`
-> `Node2d`, `Labels3d` -> `Node3d`, `LabelsUi` -> `NodeUi`, `LabelsPbr`
-> `NodePbr`
2024-02-15 23:15:16 +00:00
BD103
8018d62e41
Use question mark operator when possible (#11865)
# Objective

- There are multiple instances of `let Some(x) = ... else { None };`
throughout the project.
- Because `Option<T>` implements
[`Try`](https://doc.rust-lang.org/stable/std/ops/trait.Try.html), it can
use the question mark `?` operator.

## Solution

- Use question mark operator instead of `let Some(x) = ... else { None
}`.

---

There was another PR that did a similar thing a few weeks ago, but I
couldn't find it.
2024-02-14 18:44:33 +00:00
Doonv
1c67e020f7
Move EntityHash related types into bevy_ecs (#11498)
# Objective

Reduce the size of `bevy_utils`
(https://github.com/bevyengine/bevy/issues/11478)

## Solution

Move `EntityHash` related types into `bevy_ecs`. This also allows us
access to `Entity`, which means we no longer need `EntityHashMap`'s
first generic argument.

---

## Changelog

- Moved `bevy::utils::{EntityHash, EntityHasher, EntityHashMap,
EntityHashSet}` into `bevy::ecs::entity::hash` .
- Removed `EntityHashMap`'s first generic argument. It is now hardcoded
to always be `Entity`.

## Migration Guide

- Uses of `bevy::utils::{EntityHash, EntityHasher, EntityHashMap,
EntityHashSet}` now have to be imported from `bevy::ecs::entity::hash`.
- Uses of `EntityHashMap` no longer have to specify the first generic
parameter. It is now hardcoded to always be `Entity`.
2024-02-12 15:02:24 +00:00
Patrick Walton
3af8526786
Stop extracting mesh entities to the render world. (#11803)
This fixes a `FIXME` in `extract_meshes` and results in a performance
improvement.

As a result of this change, meshes in the render world might not be
attached to entities anymore. Therefore, the `entity` parameter to
`RenderCommand::render()` is now wrapped in an `Option`. Most
applications that use the render app's ECS can simply unwrap the
`Option`.

Note that for now sprites, gizmos, and UI elements still use the render
world as usual.

## Migration guide

* For efficiency reasons, some meshes in the render world may not have
corresponding `Entity` IDs anymore. As a result, the `entity` parameter
to `RenderCommand::render()` is now wrapped in an `Option`. Custom
rendering code may need to be updated to handle the case in which no
`Entity` exists for an object that is to be rendered.
2024-02-10 10:46:10 +00:00
Félix Lescaudey de Maneville
e0c296ee14
Optional ImageScaleMode (#11780)
> Follow up to #11600 and #10588 

@mockersf expressed some [valid
concerns](https://github.com/bevyengine/bevy/pull/11600#issuecomment-1932796498)
about the current system this PR attempts to fix:

The `ComputedTextureSlices` reacts to asset change in both `bevy_sprite`
and `bevy_ui`, meaning that if the `ImageScaleMode` is inserted by
default in the bundles, we will iterate through most 2d items every time
an asset is updated.

# Solution

- `ImageScaleMode` only has two variants: `Sliced` and `Tiled`. I
removed the `Stretched` default
- `ImageScaleMode` is no longer part of any bundle, but the relevant
bundles explain that this additional component can be inserted

This way, the *absence* of `ImageScaleMode` means the image will be
stretched, and its *presence* will include the entity to the various
slicing systems

Optional components in bundles would make this more straigthfoward

# Additional work

Should I add new bundles with the `ImageScaleMode` component ?
2024-02-09 20:36:32 +00:00
Félix Lescaudey de Maneville
ab16f5ed6a
UI Texture 9 slice (#11600)
> Follow up to #10588 
> Closes #11749 (Supersedes #11756)

Enable Texture slicing for the following UI nodes:
- `ImageBundle`
- `ButtonBundle`

<img width="739" alt="Screenshot 2024-01-29 at 13 57 43"
src="https://github.com/bevyengine/bevy/assets/26703856/37675681-74eb-4689-ab42-024310cf3134">

I also added a collection of `fantazy-ui-borders` from
[Kenney's](www.kenney.nl) assets, with the appropriate license (CC).
If it's a problem I can use the same textures as the `sprite_slice`
example

# Work done

Added the `ImageScaleMode` component to the targetted bundles, most of
the logic is directly reused from `bevy_sprite`.
The only additional internal component is the UI specific
`ComputedSlices`, which does the same thing as its spritee equivalent
but adapted to UI code.

Again the slicing is not compatible with `TextureAtlas`, it's something
I need to tackle more deeply in the future

# Fixes

* [x] I noticed that `TextureSlicer::compute_slices` could infinitely
loop if the border was larger that the image half extents, now an error
is triggered and the texture will fallback to being stretched
* [x] I noticed that when using small textures with very small *tiling*
options we could generate hundred of thousands of slices. Now I set a
minimum size of 1 pixel per slice, which is already ridiculously small,
and a warning will be sent at runtime when slice count goes above 1000
* [x] Sprite slicing with `flip_x` or `flip_y` would give incorrect
results, correct flipping is now supported to both sprites and ui image
nodes thanks to @odecay observation

# GPU Alternative

I create a separate branch attempting to implementing 9 slicing and
tiling directly through the `ui.wgsl` fragment shader. It works but
requires sending more data to the GPU:
- slice border
- tiling factors

And more importantly, the actual quad *scale* which is hard to put in
the shader with the current code, so that would be for a later iteration
2024-02-07 20:07:53 +00:00
Marco Buono
e169b2b217
Missing registrations (#11736)
# Objective

During my exploratory work on the remote editor, I found a couple of
types that were either not registered, or that were missing
`ReflectDefault`.

## Solution

- Added registration and `ReflectDefault` where applicable
- (Drive by fix) Moved `Option<f32>` registration to `bevy_core` instead
of `bevy_ui`, along with similar types.

---

## Changelog

- Fixed: Registered `FogSettings`, `FogFalloff`,
`ParallaxMappingMethod`, `OpaqueRendererMethod` structs for reflection
- Fixed: Registered `ReflectDefault` trait for `ColorGrading` and
`CascadeShadowConfig` structs
2024-02-06 16:33:17 +00:00
Talin
a57832bc9a
Include UI node size in the vertex inputs for UiMaterial. (#11722)
# Objective

Includes the UI node size as a parameter to the UiMaterial shader,
useful for SDF-based rendering, aspect ratio correction and other use
cases.

Fixes #11392

## Solution

Added the node size to the UiMaterial vertex shader params and also to
the data that is passed to the fragment shader.

## Migration Guide

This change should be backwards compatible, using the new field is
optional.

Note to reviewers: render pipelines are a bit outside my comfort zone,
so please make sure I haven't made any mistakes.

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2024-02-06 16:15:09 +00:00
Kanabenki
312df3cec7
Use warn_once where relevant instead of manually implementing a single warn check (#11693)
# Objective

- Some places manually use a `bool` /`AtomicBool` to warn once.

## Solution

- Use the `warn_once` macro which internally creates an `AtomicBool`.

Downside: in some case the warning state would have been reset after
recreating the struct carrying the warn state, whereas now it will
always warn only once per program run (For example, if all
`MeshPipeline`s are dropped or the `World` is recreated for
`Local<bool>`/ a `bool` resource, which shouldn't happen over the course
of a standard `App` run).


---

## Changelog

### Removed

- `FontAtlasWarning` has been removed, but the corresponding warning is
still emitted.
2024-02-05 21:05:43 +00:00
Zachary Harrold
1974723a63
Deprecated Various Component Methods from Query and QueryState (#9920)
# Objective

- (Partially) Fixes #9904
- Acts on #9910

## Solution

- Deprecated the relevant methods from `Query`, cascading changes as
required across Bevy.

---

## Changelog

- Deprecated `QueryState::get_component_unchecked_mut` method
- Deprecated `Query::get_component` method
- Deprecated `Query::get_component_mut` method
- Deprecated `Query::component` method
- Deprecated `Query::component_mut` method
- Deprecated `Query::get_component_unchecked_mut` method

## Migration Guide

### `QueryState::get_component_unchecked_mut`

Use `QueryState::get_unchecked_manual` and select for the exact
component based on the structure of the exact query as required.

### `Query::(get_)component(_unchecked)(_mut)`

Use `Query::get` and select for the exact component based on the
structure of the exact query as required.

- For mutable access (`_mut`), use `Query::get_mut`
- For unchecked access (`_unchecked`), use `Query::get_unchecked`
- For panic variants (non-`get_`), add `.unwrap()`

## Notes

- `QueryComponentError` can be removed once these deprecated methods are
also removed. Due to an interaction with `thiserror`'s derive macro, it
is not marked as deprecated.
2024-02-04 01:01:59 +00:00
Tristan Guichaoua
694c06f3d0
Inverse missing_docs logic (#11676)
# Objective

Currently the `missing_docs` lint is allowed-by-default and enabled at
crate level when their documentations is complete (see #3492).
This PR proposes to inverse this logic by making `missing_docs`
warn-by-default and mark crates with imcomplete docs allowed.

## Solution

Makes `missing_docs` warn at workspace level and allowed at crate level
when the docs is imcomplete.
2024-02-03 21:40:55 +00:00
Lixou
16d28ccb91
RenderGraph Labelization (#10644)
# Objective

The whole `Cow<'static, str>` naming for nodes and subgraphs in
`RenderGraph` is a mess.

## Solution

Replaces hardcoded and potentially overlapping strings for nodes and
subgraphs inside `RenderGraph` with bevy's labelsystem.

---

## Changelog

* Two new labels: `RenderLabel` and `RenderSubGraph`.
* Replaced all uses for hardcoded strings with those labels
* Moved `Taa` label from its own mod to all the other `Labels3d`
* `add_render_graph_edges` now needs a tuple of labels
* Moved `ScreenSpaceAmbientOcclusion` label from its own mod with the
`ShadowPass` label to `LabelsPbr`
* Removed  `NodeId`
* Renamed `Edges.id()` to `Edges.label()`
* Removed `NodeLabel`
* Changed examples according to the new label system
* Introduced new `RenderLabel`s: `Labels2d`, `Labels3d`, `LabelsPbr`,
`LabelsUi`
* Introduced new `RenderSubGraph`s: `SubGraph2d`, `SubGraph3d`,
`SubGraphUi`
* Removed `Reflect` and `Default` derive from `CameraRenderGraph`
component struct
* Improved some error messages

## Migration Guide

For Nodes and SubGraphs, instead of using hardcoded strings, you now
pass labels, which can be derived with structs and enums.

```rs
// old
#[derive(Default)]
struct MyRenderNode;
impl MyRenderNode {
    pub const NAME: &'static str = "my_render_node"
}

render_app
    .add_render_graph_node::<ViewNodeRunner<MyRenderNode>>(
        core_3d::graph::NAME,
        MyRenderNode::NAME,
    )
    .add_render_graph_edges(
        core_3d::graph::NAME,
        &[
            core_3d::graph::node::TONEMAPPING,
            MyRenderNode::NAME,
            core_3d::graph::node::END_MAIN_PASS_POST_PROCESSING,
        ],
    );

// new
use bevy::core_pipeline::core_3d::graph::{Labels3d, SubGraph3d};

#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)]
pub struct MyRenderLabel;

#[derive(Default)]
struct MyRenderNode;

render_app
    .add_render_graph_node::<ViewNodeRunner<MyRenderNode>>(
        SubGraph3d,
        MyRenderLabel,
    )
    .add_render_graph_edges(
        SubGraph3d,
        (
            Labels3d::Tonemapping,
            MyRenderLabel,
            Labels3d::EndMainPassPostProcessing,
        ),
    );
```

### SubGraphs

#### in `bevy_core_pipeline::core_2d::graph`
| old string-based path | new label |
|-----------------------|-----------|
| `NAME` | `SubGraph2d` |

#### in `bevy_core_pipeline::core_3d::graph`
| old string-based path | new label |
|-----------------------|-----------|
| `NAME` | `SubGraph3d` |

#### in `bevy_ui::render`
| old string-based path | new label |
|-----------------------|-----------|
| `draw_ui_graph::NAME` | `graph::SubGraphUi` |

### Nodes

#### in `bevy_core_pipeline::core_2d::graph`
| old string-based path | new label |
|-----------------------|-----------|
| `node::MSAA_WRITEBACK` | `Labels2d::MsaaWriteback` | 
| `node::MAIN_PASS` | `Labels2d::MainPass` | 
| `node::BLOOM` | `Labels2d::Bloom` | 
| `node::TONEMAPPING` | `Labels2d::Tonemapping` | 
| `node::FXAA` | `Labels2d::Fxaa` | 
| `node::UPSCALING` | `Labels2d::Upscaling` | 
| `node::CONTRAST_ADAPTIVE_SHARPENING` |
`Labels2d::ConstrastAdaptiveSharpening` |
| `node::END_MAIN_PASS_POST_PROCESSING` |
`Labels2d::EndMainPassPostProcessing` |

#### in `bevy_core_pipeline::core_3d::graph`
| old string-based path | new label |
|-----------------------|-----------|
| `node::MSAA_WRITEBACK` | `Labels3d::MsaaWriteback` | 
| `node::PREPASS` | `Labels3d::Prepass` | 
| `node::DEFERRED_PREPASS` | `Labels3d::DeferredPrepass` | 
| `node::COPY_DEFERRED_LIGHTING_ID` | `Labels3d::CopyDeferredLightingId`
|
| `node::END_PREPASSES` | `Labels3d::EndPrepasses` | 
| `node::START_MAIN_PASS` | `Labels3d::StartMainPass` | 
| `node::MAIN_OPAQUE_PASS` | `Labels3d::MainOpaquePass` | 
| `node::MAIN_TRANSMISSIVE_PASS` | `Labels3d::MainTransmissivePass` | 
| `node::MAIN_TRANSPARENT_PASS` | `Labels3d::MainTransparentPass` | 
| `node::END_MAIN_PASS` | `Labels3d::EndMainPass` | 
| `node::BLOOM` | `Labels3d::Bloom` | 
| `node::TONEMAPPING` | `Labels3d::Tonemapping` | 
| `node::FXAA` | `Labels3d::Fxaa` | 
| `node::UPSCALING` | `Labels3d::Upscaling` | 
| `node::CONTRAST_ADAPTIVE_SHARPENING` |
`Labels3d::ContrastAdaptiveSharpening` |
| `node::END_MAIN_PASS_POST_PROCESSING` |
`Labels3d::EndMainPassPostProcessing` |

#### in `bevy_core_pipeline`
| old string-based path | new label |
|-----------------------|-----------|
| `taa::draw_3d_graph::node::TAA` | `Labels3d::Taa` |

#### in `bevy_pbr`
| old string-based path | new label |
|-----------------------|-----------|
| `draw_3d_graph::node::SHADOW_PASS` | `LabelsPbr::ShadowPass` |
| `ssao::draw_3d_graph::node::SCREEN_SPACE_AMBIENT_OCCLUSION` |
`LabelsPbr::ScreenSpaceAmbientOcclusion` |
| `deferred::DEFFERED_LIGHTING_PASS` | `LabelsPbr::DeferredLightingPass`
|

#### in `bevy_render`
| old string-based path | new label |
|-----------------------|-----------|
| `main_graph::node::CAMERA_DRIVER` | `graph::CameraDriverLabel` |

#### in `bevy_ui::render`
| old string-based path | new label |
|-----------------------|-----------|
| `draw_ui_graph::node::UI_PASS` | `graph::LabelsUi::UiPass` |

---

## Future work

* Make `NodeSlot`s also use types. Ideally, we have an enum with unit
variants where every variant resembles one slot. Then to make sure you
are using the right slot enum and make rust-analyzer play nicely with
it, we should make an associated type in the `Node` trait. With today's
system, we can introduce 3rd party slots to a node, and i wasnt sure if
this was used, so I didn't do this in this PR.

## Unresolved Questions

When looking at the `post_processing` example, we have a struct for the
label and a struct for the node, this seems like boilerplate and on
discord, @IceSentry (sowy for the ping)
[asked](https://discord.com/channels/691052431525675048/743663924229963868/1175197016947699742)
if a node could automatically introduce a label (or i completely
misunderstood that). The problem with that is, that nodes like
`EmptyNode` exist multiple times *inside the same* (sub)graph, so there
we need extern labels to distinguish between those. Hopefully we can
find a way to reduce boilerplate and still have everything unique. For
EmptyNode, we could maybe make a macro which implements an "empty node"
for a type, but for nodes which contain code and need to be present
multiple times, this could get nasty...
2024-01-31 14:51:19 +00:00
Chia-Hsiang Cheng
fb124c35be
Avoid unconditionally unwrapping the Result - UI Stack System (#11575)
# Objective

- Fixes #11572

## Solution

- Avoid unconditionally unwrapping the `Result` in the `ui_stack_system`
function.
2024-01-29 02:38:41 +00:00
BD103
069a8776f5
Feature-gate all references to bevy_text in bevy_ui (#11391)
# Objective

- `bevy_ui` fails to compile without `bevy_text` being enabled.
- Fixes #11363.

## Solution

- Add `#[cfg(feature = "bevy_text")]` to all items that require it.

I think this change is honestly a bit ugly, but I can't see any other
way around it. I considered making `bevy_text` required, but we agreed
[on
Discord](https://discord.com/channels/691052431525675048/743663673393938453/1196868117486379148)
that there were some use cases for `bevy_ui` without `bevy_text`. If you
have any ideas that decreases the amount of `#[cfg(...)]`s and
`#[allow(...)]`s, that would be greatly appreciated.

This was tested by running the following commands:

```shell
$ cargo clippy -p bevy_ui
$ cargo clippy -p bevy_ui -F bevy_text
$ cargo run -p ci
```

---

## Changelog

- Fixed `bevy_ui` not compiling without `bevy_text`.
2024-01-28 16:24:54 +00:00
Stepan Koltsov
335c3ff17d
Rustdoc links in bevy_ui (#11555)
# Objective

No links between types make create rustdoc harder to understand.

## Solution

Add links. Also tweak some sentences.
2024-01-28 02:21:39 +00:00
pablo-lua
1e241fb6b4
Allow user to choose default ui camera (#11436)
# Objective

- Resolves #11377 

## Solution

- Add marker component `IsDefaultUiCamera` that will be choosen first as
the default camera.

If you want the IsDefaultUiCamera default camera to be in another
window, thats now possible.
- `IsDefaultUiCamera` is expected to be within a single Camera, if that
assertion fails, one PrimaryWindow Camera will be choosen.

---

## Changelog

### Added
- Added `IsDefaultUiCamera` marker component.

---------

Co-authored-by: Mateusz Wachowiak <mateusz_wachowiak@outlook.com>
2024-01-27 17:27:24 +00:00
François
95b92307b4
UI and unloaded assets: don't filter out nodes with an unloaded image (#11205)
# Objective

- after #10520, UI can't display images or text with a background color

## Solution

- don't filter out UI nodes with an unloaded image
2024-01-24 22:15:43 +00:00
Alice Cecile
eb07d16871
Revert rendering-related associated type name changes (#11027)
# Objective

> Can anyone explain to me the reasoning of renaming all the types named
Query to Data. I'm talking about this PR
https://github.com/bevyengine/bevy/pull/10779 It doesn't make sense to
me that a bunch of types that are used to run queries aren't named Query
anymore. Like ViewQuery on the ViewNode is the type of the Query. I
don't really understand the point of the rename, it just seems like it
hides the fact that a query will run based on those types.


[@IceSentry](https://discord.com/channels/691052431525675048/692572690833473578/1184946251431694387)

## Solution

Revert several renames in #10779.

## Changelog

- `ViewNode::ViewData` is now `ViewNode::ViewQuery` again.

## Migration Guide

- This PR amends the migration guide in
https://github.com/bevyengine/bevy/pull/10779

---------

Co-authored-by: atlas dostal <rodol@rivalrebels.com>
2024-01-22 15:01:55 +00:00
Doonv
03ee959809
Fix panic on Text UI without Cameras (#11405)
# Objective

Fix https://github.com/bevyengine/bevy/issues/11396.

## Solution

Don't panic on taffy node not existing.

Plus minor warning text improvement.
2024-01-18 20:33:22 +00:00
robtfm
30940e5cb4
fix occasional crash moving ui root nodes (#11371)
# Objective

fix an occasional crash when moving ui root nodes between cameras.

occasionally, updating the TargetCamera of a ui element and then
removing the element causes a crash.

i believe that is because when we assign a child in taffy, the old
parent doesn't remove that child from it's children, so we have:

```
user: create root node N1, camera A
-> layout::set_camera_children(A) : 
	- create implicit node A1
	- assign 1 as child -> taffy.children[A1] = [N1], taffy.parents[1] = A1

user: move root node N1 to camera B
-> layout::set_camera_children(B) :
	- create implicit node B1
	- assign 1 as child -> taffy.children[A1] = [N1], taffy.children[B1] = [N1], taffy.parents[1] = B1
-> layout::set_camera_children(A) :
	- remove implicit node A1 (which still has N1 as a child) -> 
		-> taffy sets parent[N1] = None ***
		-> taffy.children[B1] = [N1], taffy.parents[1] = None

user: remove N1
-> layout::remove_entities(N1)
	- since parent[N1] is None, it's not removed from B1 -> taffy.children[B1] = [N1], taffy.parents[1] is removed
-> layout::set_camera_children(B)
	- remove implicit node B1
	- taffy crash accessing taffy.parents[N1]
```

## Solution

we can work around this by making sure to remove the child from the old
parent if one exists (this pr).

i think a better fix may be for taffy to check in `Taffy::remove` and
only set the child's parent to None if it is currently equal to the node
being removed but i'm not sure if there's an explicit assumption we're
violating here (@nicoburns).
2024-01-17 16:53:27 +00:00
Félix Lescaudey de Maneville
135c7240f1
Texture Atlas rework (#5103)
# Objective

> Old MR: #5072 
> ~~Associated UI MR: #5070~~
> Adresses #1618

Unify sprite management

## Solution

- Remove the `Handle<Image>` field in `TextureAtlas` which is the main
cause for all the boilerplate
- Remove the redundant `TextureAtlasSprite` component
- Renamed `TextureAtlas` asset to `TextureAtlasLayout`
([suggestion](https://github.com/bevyengine/bevy/pull/5103#discussion_r917281844))
- Add a `TextureAtlas` component, containing the atlas layout handle and
the section index

The difference between this solution and #5072 is that instead of the
`enum` approach is that we can more easily manipulate texture sheets
without any breaking changes for classic `SpriteBundle`s (@mockersf
[comment](https://github.com/bevyengine/bevy/pull/5072#issuecomment-1165836139))

Also, this approach is more *data oriented* extracting the
`Handle<Image>` and avoiding complex texture atlas manipulations to
retrieve the texture in both applicative and engine code.
With this method, the only difference between a `SpriteBundle` and a
`SpriteSheetBundle` is an **additional** component storing the atlas
handle and the index.

~~This solution can be applied to `bevy_ui` as well (see #5070).~~

EDIT: I also applied this solution to Bevy UI

## Changelog

- (**BREAKING**) Removed `TextureAtlasSprite`
- (**BREAKING**) Renamed `TextureAtlas` to `TextureAtlasLayout`
- (**BREAKING**) `SpriteSheetBundle`:
  - Uses a  `Sprite` instead of a `TextureAtlasSprite` component
- Has a `texture` field containing a `Handle<Image>` like the
`SpriteBundle`
- Has a new `TextureAtlas` component instead of a
`Handle<TextureAtlasLayout>`
- (**BREAKING**) `DynamicTextureAtlasBuilder::add_texture` takes an
additional `&Handle<Image>` parameter
- (**BREAKING**) `TextureAtlasLayout::from_grid` no longer takes a
`Handle<Image>` parameter
- (**BREAKING**) `TextureAtlasBuilder::finish` now returns a
`Result<(TextureAtlasLayout, Handle<Image>), _>`
- `bevy_text`:
  - `GlyphAtlasInfo` stores the texture `Handle<Image>`
  - `FontAtlas` stores the texture `Handle<Image>`
- `bevy_ui`:
- (**BREAKING**) Removed `UiAtlasImage` , the atlas bundle is now
identical to the `ImageBundle` with an additional `TextureAtlas`

## Migration Guide

* Sprites

```diff
fn my_system(
  mut images: ResMut<Assets<Image>>, 
-  mut atlases: ResMut<Assets<TextureAtlas>>, 
+  mut atlases: ResMut<Assets<TextureAtlasLayout>>, 
  asset_server: Res<AssetServer>
) {
    let texture_handle: asset_server.load("my_texture.png");
-   let layout = TextureAtlas::from_grid(texture_handle, Vec2::new(25.0, 25.0), 5, 5, None, None);
+   let layout = TextureAtlasLayout::from_grid(Vec2::new(25.0, 25.0), 5, 5, None, None);
    let layout_handle = atlases.add(layout);
    commands.spawn(SpriteSheetBundle {
-      sprite: TextureAtlasSprite::new(0),
-      texture_atlas: atlas_handle,
+      atlas: TextureAtlas {
+         layout: layout_handle,
+         index: 0
+      },
+      texture: texture_handle,
       ..Default::default()
     });
}
```
* UI


```diff
fn my_system(
  mut images: ResMut<Assets<Image>>, 
-  mut atlases: ResMut<Assets<TextureAtlas>>, 
+  mut atlases: ResMut<Assets<TextureAtlasLayout>>, 
  asset_server: Res<AssetServer>
) {
    let texture_handle: asset_server.load("my_texture.png");
-   let layout = TextureAtlas::from_grid(texture_handle, Vec2::new(25.0, 25.0), 5, 5, None, None);
+   let layout = TextureAtlasLayout::from_grid(Vec2::new(25.0, 25.0), 5, 5, None, None);
    let layout_handle = atlases.add(layout);
    commands.spawn(AtlasImageBundle {
-      texture_atlas_image: UiTextureAtlasImage {
-           index: 0,
-           flip_x: false,
-           flip_y: false,
-       },
-      texture_atlas: atlas_handle,
+      atlas: TextureAtlas {
+         layout: layout_handle,
+         index: 0
+      },
+      image: UiImage {
+           texture: texture_handle,
+           flip_x: false,
+           flip_y: false,
+       },
       ..Default::default()
     });
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2024-01-16 13:59:08 +00:00
Roman Salnikov
eb9db21113
Camera-driven UI (#10559)
# Objective

Add support for presenting each UI tree on a specific window and
viewport, while making as few breaking changes as possible.

This PR is meant to resolve the following issues at once, since they're
all related.

- Fixes #5622 
- Fixes #5570 
- Fixes #5621 

Adopted #5892 , but started over since the current codebase diverged
significantly from the original PR branch. Also, I made a decision to
propagate component to children instead of recursively iterating over
nodes in search for the root.


## Solution

Add a new optional component that can be inserted to UI root nodes and
propagate to children to specify which camera it should render onto.
This is then used to get the render target and the viewport for that UI
tree. Since this component is optional, the default behavior should be
to render onto the single camera (if only one exist) and warn of
ambiguity if multiple cameras exist. This reduces the complexity for
users with just one camera, while giving control in contexts where it
matters.

## Changelog

- Adds `TargetCamera(Entity)` component to specify which camera should a
node tree be rendered into. If only one camera exists, this component is
optional.
- Adds an example of rendering UI to a texture and using it as a
material in a 3D world.
- Fixes recalculation of physical viewport size when target scale factor
changes. This can happen when the window is moved between displays with
different DPI.
- Changes examples to demonstrate assigning UI to different viewports
and windows and make interactions in an offset viewport testable.
- Removes `UiCameraConfig`. UI visibility now can be controlled via
combination of explicit `TargetCamera` and `Visibility` on the root
nodes.

---------

Co-authored-by: davier <bricedavier@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
2024-01-16 00:39:10 +00:00
vero
4695b82f6b
Use EntityHashMap whenever possible (#11353)
# Objective

Fixes #11352

## Solution

- Use `EntityHashMap<Entity, T>` instead of `HashMap<Entity, T>`

---

## Changelog

Changed
- Use `EntityHashMap<Entity, T>` instead of `HashMap<Entity, T>`
whenever possible

## Migration Guide

TODO
2024-01-15 15:51:17 +00:00
ickshonpe
03404c48ca
UI text rotation and scaling fix (#11326)
# Objective

UI node text is drawn in the wrong position after rotation or scaling.


![294723406-d031a3e6-a4f9-48b4-a66a-ee963100a8b9](https://github.com/bevyengine/bevy/assets/27962798/2755e2e3-6a03-4ee8-8676-bdcaa72ec678)

## Solution
In `extract_text_uinodes` to set the text's offset create a translation
matrix and multiply it by the UI node's transform.

Previously the offset was just added directly to the translation of the
Node's `GlobalTransform`, which meant no scaling or rotation would be
applied to the offset.

<img width="961" alt="296440025-537ec11c-1ea1-469c-8eec-2ad4ae012095"
src="https://github.com/bevyengine/bevy/assets/27962798/eae1a1d2-1369-47ad-8963-3862d03ec0bf">

<img width="961" alt="296440156-dd04029d-8112-4fa5-89a2-56d7acab66df"
src="https://github.com/bevyengine/bevy/assets/27962798/90b1b6db-13f4-4745-9f14-7c1661baad50">

Fixes #11241
2024-01-13 22:21:40 +00:00
Jakob Hellermann
a657478675
resolve all internal ambiguities (#10411)
- ignore all ambiguities that are not a problem
- remove `.before(Assets::<Image>::track_assets),` that points into a
different schedule (-> should this be caught?)
- add some explicit orderings:
- run `poll_receivers` and `update_accessibility_nodes` after
`window_closed` in `bevy_winit::accessibility`
  - run `bevy_ui::accessibility::calc_bounds` after `CameraUpdateSystem`
- run ` bevy_text::update_text2d_layout` and `bevy_ui::text_system`
after `font_atlas_set::remove_dropped_font_atlas_sets`
- add `app.ignore_ambiguity(a, b)` function for cases where you want to
ignore an ambiguity between two independent plugins `A` and `B`
- add `IgnoreAmbiguitiesPlugin` in `DefaultPlugins` that allows
cross-crate ambiguities like `bevy_animation`/`bevy_ui`
- Fixes https://github.com/bevyengine/bevy/issues/9511

## Before
**Render**
![render_schedule_Render
dot](https://github.com/bevyengine/bevy/assets/22177966/1c677968-7873-40cc-848c-91fca4c8e383)

**PostUpdate**
![schedule_PostUpdate
dot](https://github.com/bevyengine/bevy/assets/22177966/8fc61304-08d4-4533-8110-c04113a7367a)

## After
**Render**
![render_schedule_Render
dot](https://github.com/bevyengine/bevy/assets/22177966/462f3b28-cef7-4833-8619-1f5175983485)
**PostUpdate**
![schedule_PostUpdate
dot](https://github.com/bevyengine/bevy/assets/22177966/8cfb3d83-7842-4a84-9082-46177e1a6c70)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
2024-01-09 19:08:15 +00:00
Atomei Alexandru
3f535d54eb
Made the remaining types from bevy_ui to reflect the Default trait if… (#11199)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/11197

## Solution

- Made the remaining types from bevy_ui that do not reflect the Default
trait to do it if possible.
2024-01-03 18:57:05 +00:00
pablo-lua
41c362051c
Create serialize feature for bevy_ui (#11188)
# Objective

- Fixes #11119  

## Solution

- Creation of the serialize feature to ui

---

## Changelog

### Changed
- Changed all the structs that implement Serialize and Deserialize to
only implement when feature is on

## Migration Guide

- If you want to use serialize and deserialize with types from bevy_ui,
you need to use the feature serialize in your TOML
```toml
[dependencies.bevy]
features = ["serialize"]
```
2024-01-03 17:52:16 +00:00
JMS55
44424391fe
Unload render assets from RAM (#10520)
# Objective
- No point in keeping Meshes/Images in RAM once they're going to be sent
to the GPU, and kept in VRAM. This saves a _significant_ amount of
memory (several GBs) on scenes like bistro.
- References
  - https://github.com/bevyengine/bevy/pull/1782
  - https://github.com/bevyengine/bevy/pull/8624 

## Solution
- Augment RenderAsset with the capability to unload the underlying asset
after extracting to the render world.
- Mesh/Image now have a cpu_persistent_access field. If this field is
RenderAssetPersistencePolicy::Unload, the asset will be unloaded from
Assets<T>.
- A new AssetEvent is sent upon dropping the last strong handle for the
asset, which signals to the RenderAsset to remove the GPU version of the
asset.

---

## Changelog
- Added `AssetEvent::NoLongerUsed` and
`AssetEvent::is_no_longer_used()`. This event is sent when the last
strong handle of an asset is dropped.
- Rewrote the API for `RenderAsset` to allow for unloading the asset
data from the CPU.
- Added `RenderAssetPersistencePolicy`.
- Added `Mesh::cpu_persistent_access` for memory savings when the asset
is not needed except for on the GPU.
- Added `Image::cpu_persistent_access` for memory savings when the asset
is not needed except for on the GPU.
- Added `ImageLoaderSettings::cpu_persistent_access`.
- Added `ExrTextureLoaderSettings`.
- Added `HdrTextureLoaderSettings`.

## Migration Guide
- Asset loaders (GLTF, etc) now load meshes and textures without
`cpu_persistent_access`. These assets will be removed from
`Assets<Mesh>` and `Assets<Image>` once `RenderAssets<Mesh>` and
`RenderAssets<Image>` contain the GPU versions of these assets, in order
to reduce memory usage. If you require access to the asset data from the
CPU in future frames after the GLTF asset has been loaded, modify all
dependent `Mesh` and `Image` assets and set `cpu_persistent_access` to
`RenderAssetPersistencePolicy::Keep`.
- `Mesh` now requires a new `cpu_persistent_access` field. Set it to
`RenderAssetPersistencePolicy::Keep` to mimic the previous behavior.
- `Image` now requires a new `cpu_persistent_access` field. Set it to
`RenderAssetPersistencePolicy::Keep` to mimic the previous behavior.
- `MorphTargetImage::new()` now requires a new `cpu_persistent_access`
parameter. Set it to `RenderAssetPersistencePolicy::Keep` to mimic the
previous behavior.
- `DynamicTextureAtlasBuilder::add_texture()` now requires that the
`TextureAtlas` you pass has an `Image` with `cpu_persistent_access:
RenderAssetPersistencePolicy::Keep`. Ensure you construct the image
properly for the texture atlas.
- The `RenderAsset` trait has significantly changed, and requires
adapting your existing implementations.
  - The trait now requires `Clone`.
- The `ExtractedAsset` associated type has been removed (the type itself
is now extracted).
  - The signature of `prepare_asset()` is slightly different
- A new `persistence_policy()` method is now required (return
RenderAssetPersistencePolicy::Unload to match the previous behavior).
- Match on the new `NoLongerUsed` variant for exhaustive matches of
`AssetEvent`.
2024-01-03 03:31:04 +00:00