Search Unity

Official Introducing transform styles

Discussion in 'UI Toolkit' started by SimonDufour, Nov 10, 2021.

  1. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    Starting with Unity 2021.2, Transform values can now be set through styles.

    Transform values allow you to move a visual element without affecting the overall layout of your panel. This addition is a crucial step toward doing some motion design and unlocks new use cases that were previously hard to achieve.

    The transform separates into 4 properties: translate, rotate, scale and transform-origin. These all affect the final position and size of an element and all its children.
    all demo.gif


    We’ve also introduced support for the `transform-origin` property, which allows you to specify the pivot point around which transformation operations will be applied.

    To match user expectations, the default value for the `transform-origin` property is now the center of the VisualElement. This changes the previous behavior, where the rotation and scaling were always applied from the top left corner of the element.

    The rotate and scale properties are applied relative to the transform-origin property.

    We aligned the properties closely as possible to the CSS Standard:

    https://developer.mozilla.org/en-US/docs/Web/CSS/translate
    https://developer.mozilla.org/en-US/docs/Web/CSS/rotate
    https://developer.mozilla.org/en-US/docs/Web/CSS/scale
    https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin


    Transform behavior
    Some other notes on the new transform behavior:

    • UI Toolkit currently does not support the z-axis. This applies to the z value in translate, scale and transform-origin. Consequently, only 2d rotation is supported (with a single angle unit).

    • Length percentage values are relative to the size of the visual element (width or height). This allows a quick positioning of the element without having to know their final size in pixels.

    • All four transform properties can be inspected and set directly with the UI Builder. See the new Transform category in the Style Inspector panel.

    • Standard unit types can be used to define transform property values.

    • The rotate property also supports all 4 angle unit types: degrees (deg), gradians (grad), radians (rad) and turns (turn):
     
    Last edited: Nov 10, 2021
  2. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    Frequently asked questions

    Q: What will happen with the old visualElement.transform interface?
    Accessing transform values through styles is now the preferred way. The style will eventually replace the interface, as they’re both equivalent in their usage and that the new style values respect the pattern exposed by the other style properties. Reading from the transform interface now returns the computed style, and setting the interface sets the inline style of the element.

    Q: Why not use the "CSS transform" property and have three separate properties for translate rotate and scale?
    Supporting the three separate values can make the result more predictable, as any combination would be possible. It is also easier to manage for both the users and the developers.


    Q: When should I use the transform instead of other existing properties to set the position and scale of the elements?
    The regular layout (height, width, top, bottom, etc...) is preferred for determining the size and position of the elements, as it’s a much more powerful and precise tool. The new properties are lighter to calculate and are calculated after the layout, which is ideal for animation and other effects because less work is required to update the visuals.

    Overall, the transform modifies the geometry generated by the layout. For example, doubling the width of an element preserves the specified border size, compared to applying a horizontal scale of 2 that would stretch the whole geometry, including the border.
     
  3. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    The transform style is conveniently set in the ui builder Gui.

    If you are setting inline style in the code, the syntax is similar to the other properties:
    Code (CSharp):
    1. VisualElement.style.translate = new Translate(1,1,0));
    2. VisualElement.style.scale = new Scale(new Vector3 (2, 2, 01));
    3. VisualElement.style.transformOrigin = new TransformOrigin(Length.Percent(100), 0, 0));
    Finally, if you are writing USS directly, it is the same syntax as CSS.
     
    Last edited: Nov 12, 2021
    KamilCSPS, Catsoft-Studios and Nexer8 like this.
  4. Catsoft-Studios

    Catsoft-Studios

    Joined:
    Jan 15, 2011
    Posts:
    703
    Excellent news! I've been trying to come up with a way to make a control that slides the content up/down with a simple animation, and was hoping this could help me. Like an expand box that reveals more content.

    However, scaling an object seems to ignore the new bounds of the element, like if it was positioned in "absolute". This leaves an empty gap when scaling a visual element down.

    On another note, the experimental "animate" also comes with a Scale option, but this one can only use a single value for all 3 axis (which is not percentage based, but unit-based). Do you have plans on splitting it into X, Y and Z axis and changing into a scale ratio?

    Thanks!
     
  5. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    The using element.style.scale, the effect will be relative to the point specified in the transform-origin, and by default this is the center of the element. You can change the transform-origin to be the point that does not move during your animation.

    Right now, no changes are intended to the experimental animate framework, but we will have something interesting announced soon that will handle transitions with different values in x, y and z scale. :)
     
    mariandev and Catsoft-Studios like this.
  6. Midiphony-panda

    Midiphony-panda

    Joined:
    Feb 10, 2020
    Posts:
    243
    Hello ! I'm looking for some help in resetting the transform styles that have been set inline.

    I tried the following but it doesn't work :
    Code (CSharp):
    1. targetElement.style.translate = StyleKeyword.Null;
    2. targetElement.style.rotate = StyleKeyword.Null;
    3. targetElement.style.scale = StyleKeyword.Null;
    https://forum.unity.com/threads/resetting-c-styles-to-defaults.969942/#post-7758462

    I tried setting the styles with both the transform interface and the newer styles :
    • TargetElement.style.scale = new Scale(someVector3);
    • TargetElement.transform.scale = someVector3
    In both cases, the null styles are kept but the VisualElement on screen doesn't fallback to its default styles.

    My current guess is that something internally isn't refreshed/dirtied/incremented when setting null styles on those transform properties

    My code :
    upload_2022-1-5_15-44-42.png

    The IL code, where the IncrementVersion line will never be reached if we set a Null style :
    upload_2022-1-5_15-45-59.png

    The SetInlineTranslate implementation (which returns false when setting a Null style) :
    upload_2022-1-5_15-48-55.png


    I have no issues with other styles : I can reset the opacity to its default value for example.
    So I'm thinking it might be a bug related to the implementations of SetInlineTranslate, SetInlineRotate and SetInlineScale ^^"
     
    Last edited: Jan 5, 2022
  7. Midiphony-panda

    Midiphony-panda

    Joined:
    Feb 10, 2020
    Posts:
    243
    Bug report sent : case 1392844

    Repro :
    ResetDoesntWorkForTransformProperties.gif


    Also, resizing the game view seems to eventually repaint the UI properly :
    ResizingWindowRepaintsUICorrectly.gif
     
  8. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    Thanks for the repro, it seems like there is a corner case where one cache is not "dirtied".
     
    Midiphony-panda likes this.
  9. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    The fix is already landed in the 2022.1 alpha and shoud be backported soon to the older version of the editor
     
    Midiphony-panda likes this.
  10. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
  11. KamilCSPS

    KamilCSPS

    Joined:
    May 21, 2020
    Posts:
    448
    Not sure if it's directly related to the transform styles or a UITK general issue but;
    • Have a VisualElement with a Label as a child. Label is position absolute and placed so its contents are outside the size of the parent VisualElement. Overflow is set to hidden as to hide the Label's text.
    • Have a mouseHover that increases/decreases the width of VisualElement thus showing the Label.
    • So far so good.
    • Add & trigger a transition to scale to 0 the VisualElement. (hide it).
    • At transitionEnd, Debug.Log the Label's resolved height = 0; (ok, I guess?)
    • Add & trigger a transition to scale return to 1. (show it).
    • At transitionEnd, Debug.Log the Label's resolved height = 0; <=== Issue.
    Label will still be visible but during mouseHover it will jerk all-around trying to return to it's proper height.
    • If you completely remove the mouseHover it will never have a height of 0 when transitioning from/to scale 0.
    • And if you don't do any scale to 0 transition it will also never have a height of 0 while doing the mouseHover (width) transitions.

    Any thoughts?
     
    Last edited: Feb 17, 2022
  12. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    The whole sequence is hard to follow, having 2 transitions on different set of properties. maybe a video would help?

    The transform.scale property should not touch this because it is the result of the layout. Possibly another style is involved?
     
  13. KamilCSPS

    KamilCSPS

    Joined:
    May 21, 2020
    Posts:
    448
    Here's a gif of the issue;

    https://i.imgur.com/Wgx1pRE.gif

    Clicking on the bottom-right button triggers the Scale to 0 transition.
    Clicking top-left button trigger the Scale back to to 1 transition.

    Log is captured at TransitionEndEvent on the bottom-right button, showing the resolved height of the ToolButtonBG/ControlLabel
     
    Last edited: Feb 17, 2022
  14. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    Thanks for the gif, It helps, but there are some things I am missing to understand what is going on. Why is the height set to 0? Can you share your code/uxml/uss in case I could see something relevant?
     
  15. KamilCSPS

    KamilCSPS

    Joined:
    May 21, 2020
    Posts:
    448
    That's what I don't understand. I don't set it. It just sets itself... And Hover only transitions the width of the parent VE, there's nothing changing the height.

    Sent a bug report with the project... will just be easier; Case 1404078
     
  16. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    Thanks for filling the bug!
     
    KamilCSPS likes this.
  17. fg_davevanegdom

    fg_davevanegdom

    Joined:
    Sep 9, 2021
    Posts:
    9
    How would one center a visual element in another visual element? Im trying to center this panel like visual element in the middle of my editor window but can't for the life of me figure out how to do it. Closest I got is this.


    upload_2022-4-25_20-57-25.png
     
  18. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    There is multiples way to achieve this, the easiest way would be to add
    align-items: center;
    and
    justify-content: center;
    to the parent if flex is used to position the child.

    Another way would be to use absolute positioning:

    Setting the chils as a percentage of the parent size
    Code (CSharp):
    1. position: absolute;
    2. top: 25%;
    3. left: 25%;
    4. botom: 25%;
    5. right: 25%;
    Or keeping the auto size of the children:
    Code (CSharp):
    1. position: absolute;
    2. top: 50%;
    3. left: 50%;
    4. transform: translate(-50%, -50%);
    But there are other ways to achieve this, and you may well end up in a case where none of the following will work for you. I would suggest starting another thread if you need more help with this.
     
  19. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    Howdy! The use of "currently" makes me think you guys may be considering supporting 3D rotation. So how likely is it for us to see perspective support in the future?

    This will allow us to come up with UIs that are sort of in between pure 2D and world space. UIs like Overwatch and a lot of space exploration games come to mind.
     
  20. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    572
    I don't think we have a public announcement of any date related to this yet, so I won't be giving one, but you can see on the roadmap that the feature is planned. One of the challenge we have with both perspective and 3D UI is that it renders our rendering strategy of "one batch" impossible to achieve with masking or by mixing with objects using the regular shaders. Landing this feature without causing any regression in the editor/2d rendering performance is our goal, and we are not willing to compromise on that aspect.
     
  21. fg_davevanegdom

    fg_davevanegdom

    Joined:
    Sep 9, 2021
    Posts:
    9
    Amazing, thank you! Solved :p
     
  22. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    @SimonDufour Is
    skew
    support also on the same boat? Will it be easier to implement? I'm thinking the shear mapping is easier to streamline than true perspective and 3D when it comes to masking.
     
    Last edited: May 21, 2022
    mitaywalle likes this.
  23. hyouuu

    hyouuu

    Joined:
    Nov 26, 2020
    Posts:
    42
    Is there a way to only adjust e.g. y axis of a translate? e.g. ideally I'd like to do:
    label.style.translate.y += 5;

    Or at least:
    label.style.translate += new StyleTranslate(new Translate(0, 5, 0));

    But it seems currently I have to do:
    label.style.translate = new StyleTranslate(new Translate(label.style.translate.value.x, label.style.translate.value.y.value + 5, 0));

    Did I miss something? cc @SimonDufour
     
  24. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    780
    Translate is a struct and needs to be fully re-assigned for modifications to take effect.

    This should work:
    Code (csharp):
    1. labe.style.translate = new Translate(label.style.translate.value.x, label.style.translate.value.y + 5, 0);
     
  25. hyouuu

    hyouuu

    Joined:
    Nov 26, 2020
    Posts:
    42
    Thanks for the explanation. WIth your line the compiler complains that "error CS0019: Operator '+' cannot be applied to operands of type 'Length' and 'int'"; if I do `label.style.translate.value.y + new UnityEngine.UIElements.Length(5)`, then it complains "Cannot apply operator '+' to operands of type 'UnityEngine.UIElements.Length' and 'UnityEngine.UIElements.Length'" - thoughts?
     
  26. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    780
    I must admit I didn't try it, sorry. The style structures are indeed difficult to manipulate through code.

    This should work:

    Code (csharp):
    1.  
    2. Translate translate = label.style.translate.value;
    3. translate.x = new Length(translate.x.value, LengthUnit.Pixel);
    4. label.style.translate = translate;
    5.  
    There are two concepts at play here:
    - The C# API for style mimics the expressiveness of USS. Numeric values are often of type Length (which can have a unit), they can exist in a structure with multiple components (ex: Translate) and are stored inside a Style structure to represent generic USS keywords (ex: StyleTranslate).
    - Most if not all Unity public APIs use properties, not fields. When a property is a of type struct, it's not possible to assign to one of its properties without actually re-assigning the structure to the property. This problem is further described here: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs1612
     
    hyouuu likes this.
  27. hyouuu

    hyouuu

    Joined:
    Nov 26, 2020
    Posts:
    42
    Thanks for the detailed explanation Antoine!