Unity 6.3
0 онлайн 67 гостей 3 в системе
Вход

UxmlObjectReferenceAttribute

класс в UnityEngine.UIElements

Выполнено в:UnityEngine.UIElementsModule

Описание

Заявляет, что поле или свойство связано с вложенными объектами UXML.

Вы можете использовать UxmlObjectReferenceAttribute, чтобы указать, что свойство или поле связано с одним или несколькими объектами UXML. UxmlObjectAttribute атрибут к классу, вы можете объявить объект UXML. С помощью таких объектов с полем связывают сложные данные, выходящие за пределы возможностей одного UxmlAttributeAttribute. Тип поля должен быть UXML-объектом или интерфейсом. При использовании интерфейса для сериализации UXML допустимы только типы UXML Object.

В следующем примере показан общий случай использования UxmlObjectReferenceAttribute. В нем используется атрибут для ассоциации списка объектов UXML с полем или свойством:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

[UxmlObject] public partial class Option { [UxmlAttribute] public string name { get; set; }

[UxmlAttribute] public bool bold { get; set; }

[UxmlAttribute] public Color color; }

[UxmlElement] public partial class MyColoredListField : VisualElement { private List<Option> m_Options; private PopupField<Option> m_PopupField;

[UxmlObjectReference("options")] public List<Option> options { get => m_Options; set { m_Options = value; m_PopupField.choices = m_Options; } }

public MyColoredListField() { m_PopupField = new PopupField<Option>(); Add(m_PopupField);

if (options != null) m_PopupField.choices = options;

m_PopupField.formatSelectedValueCallback = FormatItem; m_PopupField.formatListItemCallback = FormatItem; }

static string FormatItem(Option option) { if (option == null) return "";

var coloredString = $"<color=#{ColorUtility.ToHtmlStringRGB(option.color)}>{option.name}</color>";

if (option.bold) return $"<b>{coloredString}</b>"; return coloredString; } }

Пример UXML:

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <MyColoredListField>
        <options>
            <Option name="Red" color="#FF0000FF" bold="true" />
            <Option name="Green" color="#00FF00FF" />
            <Option name="Blue" color="#0000FFFF" />
        </options>
    </MyColoredListField>
</ui:UXML>

Вы можете использовать базовый тип и включить производные типы в качестве объектов UXML. В следующем примере кнопка настраивается таким образом, чтобы при нажатии на неё происходило различное поведение, например, отображалась метка или воспроизводился звук.

using UnityEngine;
using UnityEngine.UIElements;

[UxmlObject] public abstract partial class ButtonBehaviour { [UxmlAttribute] public string name { get; set; }

public abstract void OnClicked(Button button); }

[UxmlObject] public partial class CreateLabel : ButtonBehaviour { [UxmlAttribute] public string text { get; set; } = "I was clicked!";

public override void OnClicked(Button button) { var label = new Label(text); button.parent.Add(label); } }

[UxmlObject] public partial class PlaySound : ButtonBehaviour { [UxmlAttribute] public AudioClip sound { get; set; }

public override void OnClicked(Button button) { AudioSource.PlayClipAtPoint(sound, Vector3.zero); } }

[UxmlElement] public partial class ButtonWithClickBehaviourExample : Button { [UxmlObjectReference("clicked")] public ButtonBehaviour clickedBehaviour { get; set; }

public ButtonWithClickBehaviourExample() { clicked += OnClick; }

void OnClick() { clickedBehaviour?.OnClicked(this); } }

Пример UXML:

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
    <ButtonWithClickBehaviourExample text="Play Sound">
        <clicked>
            <PlaySound sound="project://database/Assets/ClickedSound.wav" />
        </clicked>
    </ButtonWithClickBehaviourExample>
    <ButtonWithClickBehaviourExample text="Show Label">
        <clicked>
            <CreateLabel text="I was clicked!" />
        </clicked>
    </ButtonWithClickBehaviourExample>
</ui:UXML>

Можно также использовать интерфейс с реализующими его объектами UXML.

using System.Collections.Generic;
using UnityEngine.UIElements;

public interface IMyUxmlObjectInterface { string name { get; set; } }

[UxmlObject] public partial class MyUxmlObject : IMyUxmlObjectInterface { [UxmlAttribute] public string name { get; set; } }

[UxmlElement] public partial class MyUxmlObjectElement : VisualElement { [UxmlObjectReference("item")] public IMyUxmlObjectInterface item { get; set; }

[UxmlObjectReference("item-list")] public List<IMyUxmlObjectInterface> itemList { get; set; } }

Следующий пример создает несколько типов UxmlObjects с пользовательскими выдвижными ящиками свойств. Он использует UxmlObjects для описания школ, учителей и студентов:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

/// <summary> /// The classes that a student can take. /// </summary> public enum Class { Maths, MathsAdvanced, Science, ScienceAdvanced, Psychology, Sociology, Economics, English, French, History, }

/// <summary> /// The base class contains the common properties for both students and teachers. /// </summary> [UxmlObject] public abstract partial class Person { [UxmlAttribute] public int Id { get; set; }

[UxmlAttribute] public string Name { get; set; } }

/// <summary> /// A student has a list of classes and a photo. /// </summary> [UxmlObject] public partial class Student : Person { [UxmlAttribute] public List<Class> Classes { get; set; }

[UxmlAttribute] public Texture2D Photo { get; set; } }

/// <summary> /// A teacher has a list of classes taught. /// </summary> [UxmlObject] public partial class Teacher : Person { [UxmlAttribute] public List<Class> ClassesTaught { get; set; } }

/// <summary> /// A school has a list of people which includes both students and teachers. /// </summary> [UxmlObject] public partial class School { [UxmlAttribute] public string Name { get; set; }

[UxmlAttribute] public int NextAvailableId;

[UxmlObjectReference("people")] public List<Person> People { get; set; } }

/// <summary> /// A school district has a list of schools. /// </summary> [UxmlElement] public partial class SchoolDistrict : VisualElement { [UxmlObjectReference("schools")] public List<School> Schools { get; set; } }

Вы можете использовать пользовательский ящик свойств для отображения UXML объектов в космосе Inspector. Выдвижной ящик должен быть для UxmlObject's UxmlSerializedData Например, чтобы создать ящик свойств для объекта UxmlObject Студент, ящик должен быть для типа Studen.UxmlSerializedData.

using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

// Note: The custom property drawer must be for the serialized data type. [CustomPropertyDrawer(typeof(School.UxmlSerializedData))] public class SchoolPropertyDrawer : PropertyDrawer { SerializedProperty m_People; SerializedProperty m_NextAvailableId; ListView m_ListView;

int GetNextId() { var id = m_NextAvailableId.intValue; if (id == 0) id++;

m_NextAvailableId.intValue = id + 1; return id; }

public override VisualElement CreatePropertyGUI(SerializedProperty property) { var root = new VisualElement();

m_People = property.FindPropertyRelative("People"); m_NextAvailableId = property.FindPropertyRelative("NextAvailableId");

var name = new PropertyField(); name.BindProperty(property.FindPropertyRelative("Name")); root.Add(name);

m_ListView = new ListView { showAddRemoveFooter = true, showBorder = true, showBoundCollectionSize = false, showAlternatingRowBackgrounds = AlternatingRowBackground.All, overridingAddButtonBehavior = OnAddItem, reorderable = true, reorderMode = ListViewReorderMode.Animated, virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight, bindingPath = m_People.propertyPath, };

root.Add(m_ListView);

return root; }

void OnAddItem(BaseListView baseListView, Button button) { var menu = new GenericMenu(); menu.AddItem(new GUIContent("Student"), false, () => AddItem<Student>()); menu.AddItem(new GUIContent("Teacher"), false, () => AddItem<Teacher>()); menu.DropDown(button.worldBound); }

void AddItem<T>() where T : new() { m_People.InsertArrayElementAtIndex(m_People.arraySize); var person = m_People.GetArrayElementAtIndex(m_People.arraySize - 1); person.managedReferenceValue = UxmlSerializedDataCreator.CreateUxmlSerializedData(typeof(T)); person.FindPropertyRelative("Id").intValue = GetNextId(); m_People.serializedObject.ApplyModifiedProperties(); m_ListView.RefreshItem(m_People.arraySize - 1); } }

[CustomPropertyDrawer(typeof(Student.UxmlSerializedData))] public class StudentPropertyDrawer : PropertyDrawer { public override VisualElement CreatePropertyGUI(SerializedProperty property) { var id = property.FindPropertyRelative("Id").intValue; var photo = property.FindPropertyRelative("Photo").objectReferenceValue as Texture2D;

var root = new VisualElement { style = { backgroundColor = new Color(0, 0.2f, 0, 0.25f) } }; root.Add(new Label($"Student({id})") { style = { unityTextAlign = TextAnchor.MiddleCenter } }); var image = new Image { image = photo, style = { height = 100, width = 100 } }; root.Add(image);

var name = new PropertyField(); name.BindProperty(property.FindPropertyRelative("Name")); root.Add(name);

var photoField = new PropertyField(); photoField.BindProperty(property.FindPropertyRelative("Photo")); photoField.RegisterValueChangeCallback(evt => { image.image = property.FindPropertyRelative("Photo").objectReferenceValue as Texture2D; }); root.Add(photoField);

var course = new PropertyField(); course.BindProperty(property.FindPropertyRelative("Classes")); root.Add(course);

return root; } }

[CustomPropertyDrawer(typeof(Teacher.UxmlSerializedData))] public class TeacherPropertyDrawer : StudentPropertyDrawer { public override VisualElement CreatePropertyGUI(SerializedProperty property) { var id = property.FindPropertyRelative("Id").intValue; var root = new VisualElement { style = { backgroundColor = new Color(0, 0, 0.2f, 0.25f) } }; root.Add(new Label($"Teacher({id})") { style = {unityTextAlign = TextAnchor.MiddleCenter }});

var name = new PropertyField(); name.BindProperty(property.FindPropertyRelative("Name")); root.Add(name);

var classField = new PropertyField(); classField.BindProperty(property.FindPropertyRelative("ClassesTaught")); root.Add(classField);

return root; } }

Пример UXML:

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
    <SchoolDistrict>
        <schools>
            <School name="Herrington High School" next-available-id="6">
                <people>
                    <Teacher id="1" classes-taught="Science" name="Elizabeth Burke" />
                    <Teacher id="2" classes-taught="Maths" name="Coach Willis" />
                    <Student id="3" classes="Maths" name="Casey Connor" />
                    <Student id="4" classes="Maths,English,French,History,Sociology" name="Delilah Profitt" />
                    <Student id="5" classes="Maths,MathsAdvanced,Science,ScienceAdvanced" name=" Marybeth Louise Hutchinson" />
                </people>
            </School>        
            <School name="Shermer High School" next-available-id="9">
                <people>
                    <Teacher id="3" classes-taught="English" name="Ed Rooney" />
                    <Teacher id="4" name="Mr. Lorensax" classes-taught="Economics" />
                    <Teacher id="5" classes-taught="English" name="Mr. Knowlan" />
                    <Teacher id="6" classes-taught="History" name="Mr. Rickets" />
                    <Student id="1" classes="Maths,Science,English" name="Ferris Bueller" />
                    <Student id="7" classes="Maths,MathsAdvanced,Science,ScienceAdvanced,French" name="Cameron Frye" />
                    <Student id="8" classes="Sociology,Economics,Phycology" name="Sloan Peterson" />
                </people>
            </School>
            <School name="Sunnydale High School" next-available-id="6">
                <people>
                    <Teacher id="1" classes-taught="Science,ScienceAdvanced" name="Grace Newman" />
                    <Teacher id="2" classes-taught="Science" name="Dr. Gregory" />
                    <Student id="3" classes="Maths" name=" James Stanley" photo="project://database/Assets/james-class-photo.jpg" />
                    <Student id="4" classes="Maths,English,French,History,Sociology" name="Buffy Summers" photo="project://database/Assets/buffy-class-photo.jpg" />
                    <Student id="5" classes="Maths,MathsAdvanced,Science,ScienceAdvanced" name="Willow Rosenberg" photo="project://database/Assets/willow-class-photo.jpg" />
                </people>
            </School>
        </schools>
    </SchoolDistrict>
</ui:UXML>

Свойства

Свойство Описание
nameИмя вложенного элемента UXML, к которому серийизованы объекты UXML. Обратите внимание: нулевое или пустое значение приведет к серийизации объектов в корне.
typesВ UI Builder, при добавлении объекта UXML в поле, имеющее несколько производных типов, появляется раскрывающийся список с выбором доступных типов, которые могут быть добавлены в поле. По умолчанию этот список содержит все типы, наследуемые от типа объекта UXML. Вы можете использовать параметр для указания списка приемлемых типов для отображения, вместо того, чтобы показывать все доступные типы

Конструкторы

Конструктор Описание
UxmlObjectReferenceAttributeЗаявляет, что поле или свойство связано с вложенными объектами UXML.