Search Unity

StretchToParentSize only validate at initialize stage?

Discussion in 'UI Toolkit' started by wang37921, Jan 16, 2019.

  1. wang37921

    wang37921

    Joined:
    Aug 1, 2014
    Posts:
    102
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using UnityEngine.Experimental.UIElements;
    4. using UnityEditor.Experimental.UIElements;
    5.  
    6. public class TestWindow : EditorWindow
    7. {
    8.     [MenuItem("Window/UIElements/TestWindow")]
    9.     public static void ShowExample()
    10.     {
    11.         TestWindow wnd = GetWindow<TestWindow>();
    12.         wnd.titleContent = new GUIContent("LineView");
    13.     }
    14.  
    15.     public void OnEnable()
    16.     {
    17.         VisualElement root = this.GetRootVisualContainer();
    18.         VisualElement label = new VisualElement
    19.         {
    20.             style = {
    21.                 backgroundColor=Color.red
    22.             }
    23.         };
    24.         var btn = new Button(() => {
    25.             label.StretchToParentSize();
    26.         });
    27.         root.Add(btn);
    28.         root.Add(label);
    29.     }
    30. }
    click the button, the label not stretch.
    if move it beneath at construct function, the label will be stretch. why?
     
  2. wang37921

    wang37921

    Joined:
    Aug 1, 2014
    Posts:
    102
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using UnityEngine.Experimental.UIElements;
    4. using UnityEngine.Experimental.UIElements.StyleEnums;
    5. using UnityEditor.Experimental.UIElements;
    6.  
    7.  
    8. public class TestWindow : EditorWindow
    9. {
    10.     [MenuItem("Window/UIElements/TestWindow")]
    11.     public static void ShowExample()
    12.     {
    13.         TestWindow wnd = GetWindow<TestWindow>();
    14.         wnd.titleContent = new GUIContent("TestWindow");
    15.     }
    16.  
    17.     public void OnEnable()
    18.     {
    19.         // Each editor window contains a root VisualElement object
    20.         VisualElement root = this.GetRootVisualContainer();
    21.  
    22.         var ve = new VisualElement
    23.         {
    24.             style = {
    25.                 backgroundColor = Color.red,
    26.                 width = 10,
    27.                 height = 10
    28.             }
    29.         };
    30.  
    31.         root.Add(ve);
    32.  
    33.         var btn = new Button(() => {
    34.             ve.ResetPositionProperties();
    35.             ve.style.positionType = PositionType.Absolute;
    36.             ve.style.positionLeft = 10;
    37.             ve.style.positionTop = 10;
    38.             ve.style.positionRight = 10;
    39.             ve.style.positionBottom = 10;
    40.         });
    41.         root.Add(btn);
    42.     }
    43. }
     
  3. jonathanma_unity

    jonathanma_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    229
    Hi,

    this is a bug in the experimental version of UIElements, it is fixed in the upcoming 2019.1 non experimental version.

    A work around that you can use for now is to use a USS class instead of setting the styles inline in C# with StretchToParentSize.

    Code (CSharp):
    1. public void OnEnable()
    2.     {
    3.         VisualElement root = this.GetRootVisualContainer();
    4.         root.AddStyleSheetPath("Assets/Editor/styles.uss");
    5.         VisualElement label = new VisualElement
    6.         {
    7.             style = {
    8.                 backgroundColor=Color.red
    9.             }
    10.         };
    11.         Button btn = null;
    12.         btn = new Button(() =>
    13.         {
    14.             label.AddToClassList("stretch");
    15.         });
    16.         root.Add(btn);
    17.         root.Add(label);
    18.     }
    And then in the style sheet :

    .stretch {
    position-type: absolute;
    position-left: 0;
    position-top: 0;
    position-right: 0;
    position-bottom: 0;
    }
     
  4. wang37921

    wang37921

    Joined:
    Aug 1, 2014
    Posts:
    102
    i want change it at runtime, maybe onetime use width,height,positionleft,positiontop
    another time use pos left, top, right, bottom.
    positionleft, right, top, bottom, if any one is zero. it wont effective.
     
    Last edited: Jan 17, 2019
  5. jmaurice

    jmaurice

    Joined:
    Feb 21, 2016
    Posts:
    1
    The bug you're encountering only happen when the position-left/right/top/bottom are set to 0 at initialization.
    Once they've been set to any other value you should be able to set them back to 0 without any issue.

    In this case if you add the "stretch" class like above you're still free to change the value at runtime afterward and you'll be able to reset them to 0 if needed.
     
  6. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    Using style = { } we can set things like backgroundColor , width, height, etc programmatically. How would you set a hover property for a button programmatically?
     
  7. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    I figured out a way to do it.... In my stylesheet, I had a style defined for the toolbar item as .toolbaritem {}, one for the button as Button.toolbaritem {} and another one for hover Button:hover {} . Then in the C# code, I called

    Code (CSharp):
    1. Button btn = new UnityEngine.UIElements.Button() { style = { backgroundImage = tex } };
    2. btn.AddToClassList("toolbaritem");
    It took me an hour of searching and trial and error to figure out that you need to use "toolbaritem" and NOT ".toolbaritem" (that "." makes a huge difference). Maybe this would have been obvious to a webdev expert, but it wasn't to me. I am looking forward to some UI Toolkit documentation :) . jonathanma_unity's post above where he used AddToClassList("stretch") is what tipped me off that I should try it without the period, so thanks jonathanma!
     
  8. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    Here's UI Toolkit's current documentation and where it will continue to evolve:
    https://docs.unity3d.com/Packages/com.unity.ui@1.0/manual/index.html

    Here's the bit on styles:
    https://docs.unity3d.com/2020.1/Documentation/Manual/UIE-USS.html

    You also don't need the
    Button
    in
    Button.toolbaritem {}
    , just
    .toolbaritem {}
    and
    .toolbaritem:hover {}
    are sufficient for your use case.

    And to confirm, there is no way to set the
    :hover
    effect in C#. You'll need to use MouseEnter/MouseLeave events to manage hover styles in C#. The USS
    :hover
    pseudo state is the recommended way to do it.
     
    lclemens likes this.
  9. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    Thanks 1000x uDamian! That's a good tip - I'll remove the Button specifier.

    You're right, there is documentation... I misspoke there. However, I couldn't find any documentation on the AddToClassList() function and how to use it. I kinda just guessed that it corresponded to the "Add Style Class to List" button on the "Style Class List" section in the Inspector on UIBuilder, and googling brought me to this forum page. In UIBuilder the period precedes the class string, so I thought that it would be the same for AddToClassList(). I used the search box in the documentation and also went to the definition of AddToClassList() in the code, but neither had a description of what the function does or what parameter to pass it.

    Anyway, so far the UI Toolkit seems to be working pretty well. I'm looking forward to trying it with the new input system soon.
     
  10. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    No, it's definitely something we can clarify. The UI Builder's "Add Style Class to List" box _ensures_ there's NO "." added to the class name before giving to AddToClassList() because so many users would add the ".". And it's only now that we have users (like you) going from UI Builder to the C# API. Usually it was the other way around. :)
     
    lclemens likes this.