Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make default behavior for BackgroundColor and BorderColor more intuitive #14017

Merged
merged 13 commits into from
Jun 25, 2024

Conversation

alice-i-cecile
Copy link
Member

@alice-i-cecile alice-i-cecile commented Jun 25, 2024

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: 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.

@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-UI Graphical user interfaces, styles, layouts, and widgets C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Needs-Review Needs reviewer attention (from anyone!) to move forward S-Needs-Testing Testing must be done before this is safe to merge labels Jun 25, 2024
Copy link

@eidloi eidloi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

works for me!

Copy link
Contributor

@benfrankel benfrankel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The examples that were updated to use UiImage::color as a solid background for buttons should be reverted back to BackgroundColor to be more idiomatic. This isn't blocking 0.14 release though, so it can be a separate PR.

@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward S-Needs-Testing Testing must be done before this is safe to merge labels Jun 25, 2024
@alice-i-cecile alice-i-cecile added the X-Contentious There are nontrivial implications that should be thought through label Jun 25, 2024
@alice-i-cecile alice-i-cecile added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Jun 25, 2024
Copy link
Contributor

@pablo-lua pablo-lua left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can follow up with that to the next release, LGTM

@alice-i-cecile alice-i-cecile added the A-Rendering Drawing game state to the screen label Jun 25, 2024
Copy link
Contributor

@benfrankel benfrankel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nits. Approved other than that.

///
/// Like [`Handle<Image>::default`], this is a handle to a fallaback image asset.
/// While that handle points to an opaque white 1 x 1 image, this handle points to a 1 x 1 transparent white image.
// Number randomly selected by fair WolframAlpha query. Totally arbitrary.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better than a fair dice roll (xkcd)!

Copy link

@eidloi eidloi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is a lot more elegant! Thanks!

pub fn transparent() -> Image {
// We rely on the default texture format being RGBA8UnormSrgb
// when constructing a transparent color from bytes.
// If this changes, this function will need to be updated.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will we find out? Will it fail to compile?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will panic when the examples are run :)

@alice-i-cecile alice-i-cecile enabled auto-merge June 25, 2024 21:42
@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jun 25, 2024
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Jun 25, 2024
Merged via the queue into bevyengine:main with commit 336fddb Jun 25, 2024
28 checks passed
@alice-i-cecile alice-i-cecile added this to the 0.14 milestone Jun 25, 2024
mockersf pushed a commit that referenced this pull request Jun 25, 2024
…tuitive (#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.
github-merge-queue bot pushed a commit that referenced this pull request Jun 26, 2024
…14033)

# Objective

- #14017 changed how `UiImage` and `BackgroundColor` work
- one change was missed in example `color_grading`, another in the
mobile example

## Solution

- Change it in the examples
mockersf added a commit that referenced this pull request Jun 26, 2024
…14033)

# Objective

- #14017 changed how `UiImage` and `BackgroundColor` work
- one change was missed in example `color_grading`, another in the
mobile example

## Solution

- Change it in the examples
Copy link
Contributor

@lufog lufog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it was missed

image.color = PRESSED_BUTTON;

image.color = HOVERED_BUTTON;

image.color = NORMAL_BUTTON;

github-merge-queue bot pushed a commit that referenced this pull request Jul 3, 2024
# 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)
zmbush pushed a commit to zmbush/bevy that referenced this pull request Jul 3, 2024
# Objective

- After bevyengine#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)
MrGVSV pushed a commit to MrGVSV/bevy that referenced this pull request Jul 5, 2024
# Objective

- After bevyengine#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)
AmonDeShir added a commit to AmonDeShir/tomt_bevycss that referenced this pull request Sep 18, 2024
- Fixed an error where the application failed to load a CSS asset, resulting in the error:
`tomt_bevycss::system: Failed to load stylesheet from handle StrongHandle<StyleSheetAsset>{ id: Index(AssetIndex { generation: 0, index: 0 }), path: Some(sheets/index.css) }`.
The issue was related to the loading order of systems. Moving the entire schedule right after the update phase resolved the problem.

- Make hot reload enabled when Bevy has the file_watcher feature enabled.
- Updated the alpha demo: due to commit bevyengine/bevy#14017, an image can now have a BackgroundColor. The fix ensures alpha is adjusted based on the component combination: if an entity has a UIImage component, the alpha is set on it; if not, the BackgroundColor component is updated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it X-Contentious There are nontrivial implications that should be thought through
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Styling regression: ButtonBundle background color
5 participants