Accessing dimension based custom properties

I’m currently trying to use a CustomStyleProperty to retrieve a my own custom “–custom-line-width” property from USS. I’ve set this up as follows (simplified example):

[UxmlElement]
public partial class UITest : VisualElement {
    private static readonly CustomStyleProperty<float> CustomLineWidthStyleProperty = new("--custom-line-width");
    private float _customLineWidth;

    UITest() {
        RegisterCallback<CustomStyleResolvedEvent>(OnCustomStyleResolved);
    }

    private void OnCustomStyleResolved(CustomStyleResolvedEvent evt) {
        evt.customStyle.TryGetValue(CustomLineWidthStyleProperty, out _customLineWidth);
    }
}

This all works as expected for Color and the like, but reading pixel values for a line width gives the error:
Trying to read custom property --custom-line-width value as Float while parsed type is Dimension

I can’t however see a Dimension type that TryGetValue supports, what type should I be using here?

The associated USS is:

UITest {
    --custom-line-width: 5px;
}

Hi,
Dimension is an internal class, so this looks like it either needs exposing or we need to provide a conversion to float.
Could you please file a bug report so we can look into it? Unity QA: Building quality with passion

For now, you may be able to work around it by removing the “px” on the value, it should then be treated as a number instead of a Dimension,

Thanks, I have submitted as: IN-76502 (Now tracked publicly as: UUM-72374)

Removing the “px” does work, but gives differing results to a value of 1px (retrieve from another property). If I use my custom property to draw a line with that width, and then use resolvedStyle.borderBottomWidth with a USS value of 1px, they give differing widths. I suspect this is due to my Windows UI scale being set to 150% and px properties are handling this, where as float properties are not?

1 Like

resolvedStyle.border + padding are rounded to fit a whole pixel on screen.

2 Likes

I think exposing is a good idea. And it would be nice to have access to all parsed values/tokens of custom properties (not just the first item). I had to write some asmref/internal code to do just that and it was kind of a pain, but I saw some interesting uses for it

Unfortunately that bug report was closed as wont fix :(.

For future readers of this thread, You can use something similar to the class below in-place to achieve the same effect until this is properly supported (Use CustomLengthProperty instead of CustomStyleProperty<float>):

using UnityEditor;

namespace UnityEngine.UIElements {
    public readonly struct CustomLengthProperty {

        private readonly CustomStyleProperty<string> _internalProperty;

        public CustomLengthProperty(string propertyName) {
            _internalProperty = new CustomStyleProperty<string>(propertyName);
        }

        internal bool TryGetValue(ICustomStyle customStyle, out float value) {
            if (!customStyle.TryGetValue(_internalProperty, out var dimension)) {
                value = float.NaN;
                return false;
            }
      
            // Dimensional values are not currently supported.
            if (dimension.EndsWith("%")) {
                value = float.NaN;
                return false;
            }
      
            // All other values should be interpreted as pixel values, remove the suffix if present.
            if (dimension.EndsWith("px")) {
                dimension = dimension[..^2];
            }
      
            return float.TryParse(dimension, out value)) {
        }
    }

    public static class CustomStyleExtensions {
        public static bool TryGetValue(this ICustomStyle customStyle, CustomLengthProperty property, out float value) {
            return property.TryGetValue(customStyle, out value);
        }
    }
}

You could extend this to deal with DPI scaling by multiplying by a value like EditorGUIUtility.pixelsPerPoint or similar mechanism.

3 Likes