4e02d3cdb9
9 Commits
Author | SHA1 | Message | Date | |
---|---|---|---|---|
![]() |
4e02d3cdb9
|
Improved UiImage and Sprite scaling and slicing APIs (#16088)
# Objective 1. UI texture slicing chops and scales an image to fit the size of a node and isn't meant to place any constraints on the size of the node itself, but because the required components changes required `ImageSize` and `ContentSize` for nodes with `UiImage`, texture sliced nodes are laid out using an `ImageMeasure`. 2. In 0.14 users could spawn a `(UiImage, NodeBundle)` which would display an image stretched to fill the UI node's bounds ignoring the image's instrinsic size. Now that `UiImage` requires `ContentSize`, there's no option to display an image without its size placing constrains on the UI layout (unless you force the `Node` to a fixed size, but that's not a solution). 3. It's desirable that the `Sprite` and `UiImage` share similar APIs. Fixes #16109 ## Solution * Remove the `Component` impl from `ImageScaleMode`. * Add a `Stretch` variant to `ImageScaleMode`. * Add a field `scale_mode: ImageScaleMode` to `Sprite`. * Add a field `mode: UiImageMode` to `UiImage`. * Add an enum `UiImageMode` similar to `ImageScaleMode` but with additional UI specific variants. * Remove the queries for `ImageScaleMode` from Sprite and UI extraction, and refer to the new fields instead. * Change `ui_layout_system` to update measure funcs on any change to `ContentSize`s to enable manual clearing without removing the component. * Don't add a measure unless `UiImageMode::Auto` is set in `update_image_content_size_system`. Mutably deref the `Mut<ContentSize>` if the `UiImage` is changed to force removal of any existing measure func. ## Testing Remove all the constraints from the ui_texture_slice example: ```rust //! This example illustrates how to create buttons with their textures sliced //! and kept in proportion instead of being stretched by the button dimensions use bevy::{ color::palettes::css::{GOLD, ORANGE}, 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(); } fn button_system( mut interaction_query: Query< (&Interaction, &Children, &mut UiImage), (Changed<Interaction>, With<Button>), >, mut text_query: Query<&mut Text>, ) { for (interaction, children, mut image) in &mut interaction_query { let mut text = text_query.get_mut(children[0]).unwrap(); match *interaction { Interaction::Pressed => { **text = "Press".to_string(); image.color = GOLD.into(); } Interaction::Hovered => { **text = "Hover".to_string(); image.color = ORANGE.into(); } Interaction::None => { **text = "Button".to_string(); image.color = Color::WHITE; } } } } fn setup(mut commands: Commands, asset_server: Res<AssetServer>) { let image = asset_server.load("textures/fantasy_ui_borders/panel-border-010.png"); let slicer = TextureSlicer { border: BorderRect::square(22.0), center_scale_mode: SliceScaleMode::Stretch, sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; // ui camera commands.spawn(Camera2d); commands .spawn(Node { width: Val::Percent(100.0), height: Val::Percent(100.0), align_items: AlignItems::Center, justify_content: JustifyContent::Center, ..default() }) .with_children(|parent| { for [w, h] in [[150.0, 150.0], [300.0, 150.0], [150.0, 300.0]] { parent .spawn(( Button, Node { // width: Val::Px(w), // height: Val::Px(h), // horizontally center child text justify_content: JustifyContent::Center, // vertically center child text align_items: AlignItems::Center, margin: UiRect::all(Val::Px(20.0)), ..default() }, UiImage::new(image.clone()), ImageScaleMode::Sliced(slicer.clone()), )) .with_children(|parent| { // parent.spawn(( // Text::new("Button"), // TextFont { // font: asset_server.load("fonts/FiraSans-Bold.ttf"), // font_size: 33.0, // ..default() // }, // TextColor(Color::srgb(0.9, 0.9, 0.9)), // )); }); } }); } ``` This should result in a blank window, since without any constraints the texture slice image nodes should be zero-sized. But in main the image nodes are given the size of the underlying unsliced source image `textures/fantasy_ui_borders/panel-border-010.png`: <img width="321" alt="slicing" src="https://github.com/user-attachments/assets/cbd74c9c-14cd-4b4d-93c6-7c0152bb05ee"> For this PR need to change the lines: ``` UiImage::new(image.clone()), ImageScaleMode::Sliced(slicer.clone()), ``` to ``` UiImage::new(image.clone()).with_mode(UiImageMode::Sliced(slicer.clone()), ``` and then nothing should be rendered, as desired. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com> |
||
![]() |
7d40e3ec87
|
Migrate bevy_sprite to required components (#15489)
# Objective Continue migration of bevy APIs to required components, following guidance of https://hackmd.io/@bevy/required_components/ ## Solution - Make `Sprite` require `Transform` and `Visibility` and `SyncToRenderWorld` - move image and texture atlas handles into `Sprite` - deprecate `SpriteBundle` - remove engine uses of `SpriteBundle` ## Testing ran cargo tests on bevy_sprite and tested several sprite examples. --- ## Migration Guide Replace all uses of `SpriteBundle` with `Sprite`. There are several new convenience constructors: `Sprite::from_image`, `Sprite::from_atlas_image`, `Sprite::from_color`. WARNING: use of `Handle<Image>` and `TextureAtlas` as components on sprite entities will NO LONGER WORK. Use the fields on `Sprite` instead. I would have removed the `Component` impls from `TextureAtlas` and `Handle<Image>` except it is still used within ui. We should fix this moving forward with the migration. |
||
![]() |
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 |
||
![]() |
a5fa32e1e7
|
Normalization anchor for sprite slice in dimensions of this slice (#12769)
# Objective Fixes #12408 . Fixes #12680. ## Solution - Recaclulated anchor from dimensions of sprite to dimension of each part of it (each part contains its own anchor) |
||
![]() |
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> |
||
![]() |
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> |
||
![]() |
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 ? |
||
![]() |
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 |
||
![]() |
01139b3472
|
Sprite slicing and tiling (#10588)
> Replaces #5213 # Objective Implement sprite tiling and [9 slice scaling](https://en.wikipedia.org/wiki/9-slice_scaling) for `bevy_sprite`. Allowing slice scaling and texture tiling. Basic scaling vs 9 slice scaling:  Slicing example: <img width="481" alt="Screenshot 2022-07-05 at 15 05 49" src="https://user-images.githubusercontent.com/26703856/177336112-9e961af0-c0af-4197-aec9-430c1170a79d.png"> Tiling example: <img width="1329" alt="Screenshot 2023-11-16 at 13 53 32" src="https://github.com/bevyengine/bevy/assets/26703856/14db39b7-d9e0-4bc3-ba0e-b1f2db39ae8f"> # Solution - `SpriteBundlue` now has a `scale_mode` component storing a `SpriteScaleMode` enum with three variants: - `Stretched` (default) - `Tiled` to have sprites tile horizontally and/or vertically - `Sliced` allowing 9 slicing the texture and optionally tile some sections with a `Textureslicer`. - `bevy_sprite` has two extra systems to compute a `ComputedTextureSlices` if necessary,: - One system react to changes on `Sprite`, `Handle<Image>` or `SpriteScaleMode` - The other listens to `AssetEvent<Image>` to compute slices on sprites when the texture is ready or changed - I updated the `bevy_sprite` extraction stage to extract potentially multiple textures instead of one, depending on the presence of `ComputedTextureSlices` - I added two examples showcasing the slicing and tiling feature. The addition of `ComputedTextureSlices` as a cache is to avoid querying the image data, to retrieve its dimensions, every frame in a extract or prepare stage. Also it reacts to changes so we can have stuff like this (tiling example): https://github.com/bevyengine/bevy/assets/26703856/a349a9f3-33c3-471f-8ef4-a0e5dfce3b01 # Related - [ ] Once #5103 or #10099 is merged I can enable tiling and slicing for texture sheets as ui # To discuss There is an other option, to consider slice/tiling as part of the asset, using the new asset preprocessing but I have no clue on how to do it. Also, instead of retrieving the Image dimensions, we could use the same system as the sprite sheet and have the user give the image dimensions directly (grid). But I think it's less user friendly --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: ickshonpe <david.curthoys@googlemail.com> Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com> |