1
\$\begingroup\$

I am trying to access the per letter vertices array in the UIElements (UI Toolkit) Label Unity class.

Background

A Label of this type can be created for example with:

using UnityEngine.UIElements;

Label label = new Label();
label.text = "This is a test";
label.style.unityFontDefinition = FontDefinition.FromFont(Resources.Load<Font>("font-path"));
label.style.fontSize = 40;
VisualElement rootVE = gameObject.GetComponent<UIDocument>().rootVisualElement;
rootVE.Add(label);

(To use this you must go Game Object > UI Document, then right click in assets, create blank UI Document, and drag it onto game object's "source asset field" with this script.)

Objective

I am trying to get the per letter vertices of a Label of this nature. I was instructed by a Unity developer:

"The vertices of letters are currently internal as this area is still subject to change and we are not ready to expose it publicly. If you need the data you could access it through reflection, and it is located here (as of 2022.2) : m_Label.uitkTextHandle.textInfo."

Problem

I can get uitkTextHandle but can't find textInfo within it. I have tried:

foreach (var propertyInfo in typeof(Label).GetProperties(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)) { //gives uitkTextHandle
            Debug.Log("PROPERTIES " + propertyInfo.Name);
        }

foreach (var propertyInfo in (typeof(Label).GetProperty("uitkTextHandle", System.Reflection.BindingFlags.NonPublic| System.Reflection.BindingFlags.Instance)).GetType().GetMembers(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)) { //NO TEXTINFO FOUND
            Debug.Log("PROPERTIES " + propertyInfo.Name);
        }

And while I can get the uitkTextHandle this way, I cannot cast it to access textInfo within it (as it is a protected class) and I otherwise can't find any textInfo inside it.

        var uitkTextHandle = typeof(Label).GetProperty("uitkTextHandle", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(testLabel, null);

Am I doing something wrong perhaps, or might the Unity Admin have given me the wrong information? This is my first time using Reflection so I am not sure.

How would I get the vertices array that they say I should be able to this way in a format I can use? What am I still missing?

Thanks.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I'm not familiar with these classes, so it's possible that something else is the probelm, but having worked with Reflection before my first instinct is that the BindingFlags are to blame. See, the thing is by default you only get public members, but if you specify BindingFlags.NonPublic, like you are doing, then you only get NonPublic ones.

So, to get all the members in that instance, you need BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance.

Pretty annoying, if you ask me.

\$\endgroup\$
2
  • \$\begingroup\$ Wow you just saved me completely! I was able to get the data I needed with your flag modification. I was missing out on the public data without that flag. Thanks so much! \$\endgroup\$
    – mike
    Commented Aug 26, 2022 at 11:36
  • 1
    \$\begingroup\$ Glad it worked! \$\endgroup\$
    – PepeOjeda
    Commented Aug 26, 2022 at 15:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .