-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Specialized UI transform #16615
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
base: main
Are you sure you want to change the base?
Specialized UI transform #16615
Conversation
* Required `GlobalTransform` instead of `Transform` on `Node`. * Update node's global transforms during layout updates.
…bevy into node-global-transform
I like this as an incremental move forward. We shouldn't be storing a full Should this be on |
It looks like your PR is a breaking change, but you didn't provide a migration guide. Could you add some context on what users should update when this change get released in a new version of Bevy? |
This does seem like the least-bad option. But I thought there was code in I believe this should fix the issues |
The new transform field on I made another branch first just before this one that removed both |
I haven't seen anything like this. Afaik the only way to opt-out of transform propagation is by removing |
…lue in physical pixels. This required adding an extra parameter for the scale factor.
Yeah my fault keep changing my mind as to how this should be implemented. I don't intend to make any more changes now though. |
Starting a review. From just the readme, this seems fantastic. Exactly what I was looking for in basically every way. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks great. This is a smaller change than I was expecting tbh. Have not run any of the examples, I'll check it out later today and approve if I don't find any bugs.
Self::ZERO | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub trait IntoVal2 { | |
fn px(self) -> Val2; | |
fn percent(self) -> Val2; | |
fn vw(self) -> Val2; | |
fn vh(self) -> Val2; | |
fn vmin(self) -> Val2; | |
fn vmax(self) -> Val2; | |
} | |
impl IntoVal2 for Vec2 { | |
fn px(self) -> Val2 { | |
Val2 { x: Val::Px(self.x), y: Val::Px(self.y) } | |
} | |
fn percent(self) -> Val2 { | |
Val2 { x: Val::Percent(self.x), y: Val::Percent(self.y) } | |
} | |
fn vw(self) -> Val2 { | |
Val2 { x: Val::Vw(self.x), y: Val::vw(self.y) } | |
} | |
fn vh(self) -> Val2 { | |
Val2 { x: Val::Vh(self.x), y: Val::Vh(self.y) } | |
} | |
fn vmin(self) -> Val2 { | |
Val2 { x: Val::Vmin(self.x), y: Val::Vmin(self.y) } | |
} | |
fn vmax(self) -> Val2 { | |
Val2 { x: Val::Vmax(self.x), y: Val::Vmax(self.y) } | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure but implementing these on Vec2 might be a bit controversial. I could just have Val2's px
and percent
methods take Vec2s instead and add more methods for the other variants instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets leave it as it is then, and I'll open up a PR adding this as follow up. I don't think it will be that controversial, and I want to add a similar pattern to some other types for conversion into Val
anyway.
/// Translate the node. | ||
pub translation: Val2, | ||
/// Scale the node. A negative value reflects the node in that axis. | ||
pub scale: Vec2, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-uniformscale my old enemy. This may create issues with shear just like we have in 3d. It's probably fine. Non-blocking, just a call-out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep only went with scaling in both axis because it was supported with Transform
/GlobalTransform
and I wanted to avoid too much controversy with this PR.
/// A component storing the position of the mouse relative to the node, (0., 0.) being the center and (0.5, 0.5) being the bottom-right | ||
/// If the mouse is not over the node, the value will go beyond the range of (-0.5, -0.5) to (0.5, 0.5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you justified this change anywhere. I'm not against it, but why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's part of the changes to replace top-left-aligned coordinates and consistantly use only object-centered coordinates.
Definitely some users find having the origin at the top-left more intuitive though, if people really hate it I'm not against changing it back in this case.
thanks that's great, I was just about to go and beg on discord for someone to review this |
Added `compute_affine` function
…bevy into node-global-transform
Objective
Add specialized UI transform
Component
s and fix some related problems:Transform
component of UI nodes doesn't work very well becauseui_layout_system
overwrites the translations each frame. Theoverflow_debug
example uses a horrible hack where it copies the transform into the position that'll likely cause a panic if any users naively copy it.CalculatedClip
is wrong for rotated and scaled elements.Transform
doesn't support responsive coordinates.Solution
Transform
fromNode
.UiTransform
,UiGlobalTransform
:Node
requiresUiTransform
,UiTransform
requiresUiGlobalTransform
UiTransform
is a 2d-only equivalent ofTransform
with a translation inVal
s.UiGlobalTransform
newtypesAffine2
and is updated inui_layout_system
.ComputedNode
for mapping between viewport and local node space.RelativeCursorPosition
's coordinates are now object-centered with (0,0) at the the center of the node and the corners at (±0.5, ±0.5).normalized_visible_node_rect: Rect
field ofRelativeCursorPosition
withcursor_over: bool
, which is set to true when the cursor is over an unclipped point on the node. The visible area of the node is not necessarily a rectangle, so the previous implementation didn't work.This should fix all the logical bugs with non-axis aligned interactions and clipping. Rendering still needs changes but they are far outside the scope of this PR.
Tried and abandoned two other approaches:
transform
field onNode
, requireGlobalTransform
onNode
, and unrequireTransform
onNode
. UnrequiringTransform
opts out of transform propagation so there is then no conflict with updating theGlobalTransform
inui_layout_system
. This was a nice change in its simplicity but potentially confusing for users I think, all theGlobalTransform
docs mentionTransform
and having special rules for how it's updated just for the UI is unpleasently surprising.transform
field onNode
. UnrequireTransform
onNode
. Newtransform: Affine2
field onComputedNode
.This was okay but I think most users want a separate specialized UI transform components. The fat
ComputedNode
doesn't work well with change detection.Fixes #18929, #18930
Testing
There is an example you can look at:
Sometimes in the example if you press the rotate button couple of times the first glyph from the top label disappears , I'm not sure what's causing it yet but I don't think it's related to this PR.
Migration Guide
New specialized 2D UI transform components
UiTransform
andUiGlobalTransform
.UiTransform
is a 2d-only equivalent ofTransform
with a translation inVal
s.UiGlobalTransform
newtypesAffine2
and is updated inui_layout_system
.Node
now requiresUiTransform
instead ofTransform
.UiTransform
requiresUiGlobalTransform
.In previous versions of Bevy
ui_layout_system
would overwrite UI node'sTransform::translation
each frame.UiTransform
s aren't overwritten and there is no longer any need for systems that cache and rewrite the transform for translated UI elements.RelativeCursorPosition
's coordinates are now object-centered with (0,0) at the the center of the node and the corners at (±0.5, ±0.5). Itsnormalized_visible_node_rect
field has been removed and replaced with a newcursor_over: bool
field which is set to true when the cursor is hovering an unclipped area of the UI node.