Property fields don't seem to render correctly

These two property fields are created with following code…

// First property field
root.Add(new PropertyField(property.FindPropertyRelative("testField")));

// Second property field
float value = (fieldInfo.GetValue(property.serializedObject.targetObject) as SceneContext).testField;
PropertyField propField = new(); // just to match visual tree hierarchy 
propField.Add(new FloatField() {
    label = "Test Field",
    value = value
});
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.

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.

Those are both UIToolkit methods. Confusing part is why PropertyField applies dynamic inline styling while FloatField does not.

I have looked at the PropertyField source code (L:461)

 // These default values are based off IMGUI
m_LabelWidthRatio = 0.45f;
m_LabelExtraPadding = 2.0f;

field.RegisterCallback<CustomStyleResolvedEvent>(OnCustomStyleResolved);

and function in question

private void OnCustomStyleResolved(CustomStyleResolvedEvent evt)
{
    if (evt.customStyle.TryGetValue(s_LabelWidthRatioProperty, out var labelWidthRatio))
    {
        m_LabelWidthRatio = labelWidthRatio;
     }

     if (evt.customStyle.TryGetValue(s_LabelExtraPaddingProperty, out var labelExtraPadding))
     {
          m_LabelExtraPadding = labelExtraPadding;
     }
}

@Doomchecker was on the right track.

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

1 Like

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.

// stores reference to all labels created by non PropertyField
private List<Label> customFieldLabels = new List<Label>();

// Wraps visual element in a property field and registers custom field label
private PropertyField AsPropertyField(VisualElement element)
{
    PropertyField propField = new();
    propField.Add(element);
    customFieldLabels.Add(element.Q<Label>());
    return propField;
}


public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
// ....

    // force label adjustment on root resize
    root.RegisterCallback<GeometryChangedEvent>(evt => {
       // first label is a PropertyField label so we will use it to get base width
       // IMPORTANT: adjust below selector if 1st label is a custom one
        VisualElement el = root.Q<Label>(); 
        StyleLength width = el.style.width;
        StyleLength minWidth = el.style.minWidth;
        foreach (Label label in customFieldLabels) {
            label.style.width = width;
            label.style.minWidth = minWidth;
        }
    });

    // finally I can functionally call it while adding to parent container
    root.Add(AsPropertyField(new FloatField() {
        label = "Test Field",
        value = 123
    }));

// ...

}
1 Like