Conversation
|
You added a new example but didn't add metadata for it. Please update the root Cargo.toml file. |
2 similar comments
|
You added a new example but didn't add metadata for it. Please update the root Cargo.toml file. |
|
You added a new example but didn't add metadata for it. Please update the root Cargo.toml file. |
|
The generated |
pablo-lua
left a comment
There was a problem hiding this comment.
Liked those changes but I think there is some places that can get better
One more thing
Does this work with borders and outlines? Looks like the background color isn't picked for this types in extract_uinode_borders and extract_uinode_outlines
| stack_index: uinode.stack_index, | ||
| transform: transform.compute_matrix(), | ||
| color: color.0, | ||
| color: opacity * color.0, |
There was a problem hiding this comment.
This can get very strange if opacity is > 1 or < 0, which can happen very easily, we might want to clamp somewhere on the CalculatedOpacity and warn the user to use only opacity between 0 and 1 maybe ?
There was a problem hiding this comment.
Is this fix sufficient? We could also clamp the Opacity during propagation.
bevy/crates/bevy_ui/src/ui_node.rs
Lines 1666 to 1674 in 55368a1
There was a problem hiding this comment.
I think this is good for now, another possibility would be clamp in the propagate_opacity function, for example
Given the parent Opacity is 0.5, and the children opacity is 2, all the children of the given children would have a bigger opacity than the root parent, if we only clamp there.
I think this should go before the Layout, because this is a "style" change after all, but if we want to go without ordering, looks like this will not affect too much in this case.
I think its okay to have this 2 opacity components, as this is used for calculating purposes
Maybe in
My first suggestion is using And second is the fact that generally, when building ui in the examples, we don't really use helper functions, just build the ui raw, so I think we should do the same in this example? Have a look at the ui example |
|
Thank you Pablo. I pushed most of those changes. I'll make those better examples a bit later tonight. |
|
UI opacity is actually a lot trickier than it might seem. Glancing at this PR, each UI node is still rendered independently right? If so, this is actually not how most UI libraries handle opacity. On the web for example if you make a parent element transparent the parent and all its children are flattened into a single texture, then the resulting texture is rendered transparently. What I think is necessary to do this properly is a compositor api that does the flattening. |
Perhaps. How would it figure out multiple levels of opacity? As in a parent has 50% and child has 50%. Would it just set the texture it to the parent's opacity and only do this once and not go deeper? As it is right now there isn't really a structure to opacity at all. Setting a parent node to have a |
|
I see what you mean, it makes sense that is the norm. Thank you for the example with text. Also, I was saying 'perhaps' in the context of me making that a part of this PR. |
No problem. I don't really have an opinion on whether bevy should use this as a placeholder or not. Probably best to discuss in discord to see what people think. |
|
@CooCooCaCha I'm in agreement with you here - the UI should be rendered into an offscreen buffer, and then the buffer should be composited onto the main view with it's own separate alpha multiplier. I've thought a lot about this, and here's the API I would like to see:
In other words, we shouldn't just focus on opacity here, we want a more general solution. Imagine a dialog box that opens by starting out blurry and then "comes into focus" as it opens. |
So you want every node to have this compositing component on it, and have a system that not just propagates opacity but other things as well, sort of like filters/effects in something like photoshop, correct? |
Not every node. Only the root node of the dialog box (or inventory panel or whatever modal ui we are talking about here). To be clear, the dialog box and all of its children get rendered into a single off-screen buffer, and then we apply various effects to that buffer as we draw it on the screen. What I'm proposing is using a special ECS component to opt-in to this behavior, so that you only pay the cost if you actually need the effect. This is similar to how it works in browsers as well: when you apply a transform or a visual effect (such as opacity) to an element, it composites that element and all of its children to a buffer. This happens automatically, and is triggered by the presence of specific CSS properties such as |
|
Thats a pretty difficult decision we have to take with this feature in regards of design and so, but the example was very good @CooCooCaCha, thank you for clarifying this aspect! |
This is pretty much what I was thinking. Awhile back in discord I mentioned a general-purpose compositing API and it sounds like we're on the same page in that regard. I could see this being used for all sorts of stuff including video, overlay effects, etc. For the rendering algorithm I wonder if we could re-use composite buffers? If we pre-allocated a handful of full-screen buffers that would potentially lower memory usage and we wouldn't have to worry about synchronizing the size of the composite buffer with the size of the elements since they're all full-screen anyways. I haven't thought about this in-depth but I think you could get away with N buffers where N is the length of the longest opacity chain in the hierarchy. For example, image a scene where elements are nested to a depth of 8, but for any given chain from root -> leaf the maximum number of transparent nodes you encounter is 4. You could potentially get away with allocating 4 full-screen buffers re-using them by rendering clusters of children to a single buffer, then going up a level and rendering another cluster of children, etc. |
This is exactly how I was thinking of it as well. I'm unsure if I will be able to make this a part of this PR. |
|
Just to be clear, I am not in favor of the approach of modifying child opacities. While it might look OK in some cases, it will look bad in others. For example, a dialog with a textured background with buttons on top: you don't want the textured background to show through the buttons while it's fading in. Using a compositing buffer may require more work up front, but it's more robust and general in the long run. @CooCooCaCha If you are really clever you can get away with just two buffers: one to read, and one to write. |
We can take an approch like a component similar to |
|
See #15256 for a proposed solution. |
|
@Sjael are you still interested in working on this? |




Objective
Solution
OpacityandCalculatedOpacitytuple struct components to allow child UI nodes to inherit opacity.Things I want feedback on:
Precise ordering for the system, what set it should go inShould this could be made into a single component with 2 fields to avoid bundle bloat? (rather not since I'd have to rewrite away from clean change detection)Where to store the system declarations (right now it's inbevy_ui/lib.rs, wanted to consult before naming a new mod)Changelog
OpacityandCalculatedOpacityOpacityBundleNodeBundle/TextBundle/ImageBundle/AtlasImageBundleto have opacity componentsMigration Guide
NodeBundle/TextBundle/ImageBundle/AtlasImageBundleneed opacity components