Search Unity

  1. We would like to hear your feedback about Unity and our products. Click here for more information.
    Dismiss Notice

How to modify the internal style on UIElements?

Discussion in 'UIElements' started by 5argon, May 5, 2019.

  1. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,193
    Previously I could do something like draw a label, but use EditorStyles from HelpBox, for example.

    Now supposed I am drawing `new ObjectField`, how could I go in and modify the style it use to draw the built-in component? In `.style`, there are mostly layout related properties except for something like backgroundColor.
     
  2. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    162
    I could try to explain in boring text but if you have some time (and are coming from IMGUI), it's worth watching the Unite LA 2018 intro session for UIElements. It details the main equivalences between IMGUI and UIElements, including styles.


    But as a quick answer, use the UIElements Debugger (Window > Analysis > UIElements Debugger) to understand the hierarchy under ObjectField, and then use either
    myObjectField.Q<Label>(className: "some-class-name")
    query system in C# to change styles directly on the child elements, or better, use a StyleSheet (.uss) asset.
     
    Mauri and 5argon like this.
  3. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,193
    Thank you, will try that.

    One more related question to manipulate the internal style, I have to measure the "calculated width" of some internal elements, but all elements came with a flex box settings without a definite width/height. I need to specify the width explicitly, because I want to layout horizontally, one after another without distributing equal width to all members, within a new VisualElement with flex direction as Row. If left as is, the 0 width will not be arranged from left to right correctly.

    Screenshot 2019-05-06 23.07.08.png

    For example the ObjectField. It apparently contains Image and Label for the icon and the text, and ObjectFieldSelector as that dot on the back. I want to put one ObjectField after another, so each one need the width of the icon and the label added up.

    I want to estimate the width if they are, for example, like display:inline-block in the front end dev. (I notice Unity provided just Flex and None)

    For the icon, I could go with asking its maxWidth that is preventing the icon from getting too large as its width. But for the Label, currently I turned to IMGUI's `EditorStyles.objectField.CalcSize(new GUIContent(labelText)).x` to estimate the width required, which works, but I found it weird that I need help from equivalent style (EditorStyles.objectField) in IMGUI to properly use UIElements (ObjectField). Is there any methods that help me "simulate the layout engine" and get a minimum required width?

    On the Label element, I found MeasureTextSize but I had trouble understanding it to make it return something. So it returns Vector2, but also require me to input both width and height? Is this how it should be used?

    Code (CSharp):
    1. label.MeasureTextSize(labelText, 0, MeasureMode.Undefined, EditorGUIUtility.singleLineHeight, MeasureMode.Exactly).x;
    (This returns NaN for labelText that is not empty)
     
    Last edited: May 6, 2019
  4. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    162
    One of the main reasons to use UIElements in the first place is to *not* have to calculate any sizes or layouts manually and let the "system" do it for you. If you just want 2 ObjectFields on the same row, I'm not sure why
    Code (csharp):
    1. flex-direction: row
    is not working for you. It should put them both beside each other.

    You can additionally give them min-widths to make sure they are a certain size, or just give them widths to hard-code specific sizes. But these properties would still be on the ObjectFields themselves, not their child elements.

    Can you clarify exactly what you're trying to achieve? Maybe create something simple in IMGUI and screenshot?
     
  5. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,193
    Sure. I have 2 ObjectField layout with simple .Add to the root VisualElement like this. It take the entire row. So I thought, I want to bring them to the same line and I want to know the width of red rectangles. If I don't specify this width, when I add both of them to a VisualElement with Row flex direction they all disappeared, I thought explicit width is required.

    Screenshot 2019-05-06 17.57.21 copy.png

    So, I finished trying to use the debugger and strip off some classes so that the back dot disappear along with the dropwell box. When I was putting width = 100 manually, it works but less than ideal.

    Screenshot 2019-05-06 19.12.24.png

    After using text measuring from IMGUI, I could achieve what I want. Also I have one more element in the middle, which thanks to explicit width it is able to move the 3rd element (which also has an explicit width) back accordingly.

    Screenshot 2019-05-06 19.55.38 copy.png

    So I just wish there is more official UIElements way to get the text width measurement to do something like this.
     
  6. MattM_Unity

    MattM_Unity

    Unity Technologies

    Joined:
    Aug 18, 2017
    Posts:
    35
    Hey 5argon!

    I'm going to investigate your problem, I'll get back to you asap!