Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Discussion Property fields don't seem to render correctly

Discussion in 'UI Toolkit' started by IndieForger, Dec 1, 2022.

  1. IndieForger

    IndieForger

    Joined:
    Dec 31, 2012
    Posts:
    92
    upload_2022-12-1_4-55-32.png

    These two property fields are created with following code...

    Code (CSharp):
    1. // First property field
    2. root.Add(new PropertyField(property.FindPropertyRelative("testField")));
    3.  
    4. // Second property field
    5. float value = (fieldInfo.GetValue(property.serializedObject.targetObject) as SceneContext).testField;
    6. PropertyField propField = new(); // just to match visual tree hierarchy
    7. propField.Add(new FloatField() {
    8.     label = "Test Field",
    9.     value = value
    10. });
    11. root.Add(propField);
    I have been scratching my head for hours now trying to figure out how to make width of the label created by FloatField match label width created by PropertyField class.

    Using UIToolkit debugger I can see that PropertyField attaches "dynamic" inline width, which updates when inspector width changes.

    How can I make sure manually created field label matches other labels generated by PropertyField?


    Not sure if it's a bug or not so I am marking this thread as discussion for now.
     
  2. Doomchecker

    Doomchecker

    Joined:
    Apr 5, 2021
    Posts:
    101
    I wonder why the distance from Label to Input is shorter than in classic MGUI and if this is about to change or the new standard.
     
  3. IndieForger

    IndieForger

    Joined:
    Dec 31, 2012
    Posts:
    92
    Those are both UIToolkit methods. Confusing part is why PropertyField applies dynamic inline styling while FloatField does not.
     
  4. IndieForger

    IndieForger

    Joined:
    Dec 31, 2012
    Posts:
    92
    I have looked at the PropertyField source code (L:461)

    Code (CSharp):
    1.  // These default values are based off IMGUI
    2. m_LabelWidthRatio = 0.45f;
    3. m_LabelExtraPadding = 2.0f;
    4.  
    5. field.RegisterCallback<CustomStyleResolvedEvent>(OnCustomStyleResolved);
    and function in question


    Code (CSharp):
    1. private void OnCustomStyleResolved(CustomStyleResolvedEvent evt)
    2. {
    3.     if (evt.customStyle.TryGetValue(s_LabelWidthRatioProperty, out var labelWidthRatio))
    4.     {
    5.         m_LabelWidthRatio = labelWidthRatio;
    6.      }
    7.  
    8.      if (evt.customStyle.TryGetValue(s_LabelExtraPaddingProperty, out var labelExtraPadding))
    9.      {
    10.           m_LabelExtraPadding = labelExtraPadding;
    11.      }
    12. }


    @Doomchecker was on the right track.

    PropertyField auto adjusts width to match IMGUI styling, while Editor.UIElements (eg.: FloatField) do not.
     
    Doomchecker likes this.
  5. IndieForger

    IndieForger

    Joined:
    Dec 31, 2012
    Posts:
    92
    All right... final update.

    Didn't want to spend too much time on the problem so decided to go with the simplest solution I could come up with.
    posting it here in case someone stumbles upon similar issues.

    Ok, so... I am fixing the issue using AsPropertyField wrapper method that will "convert" any custom non property field to property field-like field. It registers custom labels that then are forced to be adjusted using GeometryChangeEvent handler registered on the top level (root) element.

    And here is relevant code.

    Code (CSharp):
    1. // stores reference to all labels created by non PropertyField
    2. private List<Label> customFieldLabels = new List<Label>();
    3.  
    4. // Wraps visual element in a property field and registers custom field label
    5. private PropertyField AsPropertyField(VisualElement element)
    6. {
    7.     PropertyField propField = new();
    8.     propField.Add(element);
    9.     customFieldLabels.Add(element.Q<Label>());
    10.     return propField;
    11. }
    12.  
    13.  
    14. public override VisualElement CreatePropertyGUI(SerializedProperty property)
    15. {
    16. // ....
    17.  
    18.     // force label adjustment on root resize
    19.     root.RegisterCallback<GeometryChangedEvent>(evt => {
    20.        // first label is a PropertyField label so we will use it to get base width
    21.        // IMPORTANT: adjust below selector if 1st label is a custom one
    22.         VisualElement el = root.Q<Label>();
    23.         StyleLength width = el.style.width;
    24.         StyleLength minWidth = el.style.minWidth;
    25.         foreach (Label label in customFieldLabels) {
    26.             label.style.width = width;
    27.             label.style.minWidth = minWidth;
    28.         }
    29.     });
    30.  
    31.     // finally I can functionally call it while adding to parent container
    32.     root.Add(AsPropertyField(new FloatField() {
    33.         label = "Test Field",
    34.         value = 123
    35.     }));
    36.  
    37. // ...
    38.  
    39. }
     
    Last edited: Dec 1, 2022