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

UxmlAttributeConverter<T0>

класс в UnityEditor.UIElements

Описание

Преобразует тип UxmlAttribute в строку и обратно.

Поля, отмеченные * UxmlAttributeAttribute представлены в UXML атрибутом одной строки, однако для правильной сериализации этих атрибутов, вы должны объявить UxmlAttributeConverter. Этот конвертер преобразует значение атрибута строки в соответствующий тип данных для отмеченного поля. Кроме того, тип данных должен быть сериализуемым с помощью Unity сериализатор и придерживаться правила сериализации.

Примечание: Следующие типы имеют нативную поддержку, и вы можете использовать их без объявления UxmlAttributeConverter:

В следующем примере создаётся пользовательский элемент управления, атрибутами которого служат экземпляр класса и список экземпляров класса.

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

[Serializable] public class MyClassWithData { public int myInt; public float myFloat; }

[UxmlElement] public partial class MyElementWithData : VisualElement { [UxmlAttribute] public MyClassWithData someData;

[UxmlAttribute] public List<MyClassWithData> lotsOfData; }

Чтобы класс поддерживался, объявите конвертер:

using System;
using System.Globalization;
using UnityEditor.UIElements;

public class MyClassWithDataConverter : UxmlAttributeConverter<MyClassWithData> { public override MyClassWithData FromString(string value) { // Split using a | so that comma (,) can be used by the list. var split = value.Split('|');

return new MyClassWithData { myInt = int.Parse(split[0]), myFloat = float.Parse(split[1], CultureInfo.InvariantCulture) }; }

public override string ToString(MyClassWithData value) => FormattableString.Invariant($"{value.myInt}|{value.myFloat}"); }

Пример UXML:

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <MyElementWithData some-data="1|2.3" lots-of-data="1|2,3|4,5|6" />
</ui:UXML>

Также можно использовать общие конвертер атрибутов. Однако, атрибут должен быть объявлен с общим типом. Чтобы использовать тип, полученный из общего типа, объявьте новый конвертер специально для него. В следующем примере используется общий конвертер атрибутов и пользовательский выдвижной ящик свойств для создания общего сериализованного словаря:

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

[Serializable] public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver { [SerializeField] public List<TKey> keys = new List<TKey>(); [SerializeField] public List<TValue> values = new List<TValue>();

void ISerializationCallbackReceiver.OnAfterDeserialize() => TransferSerializedKeys(); void ISerializationCallbackReceiver.OnBeforeSerialize() { }

public void TransferSerializedKeys() { Clear();

for (var i = 0; i < Math.Min(keys.Count, values.Count); i++) { this[keys[i]] = values[i]; } } }

[UxmlElement] public partial class MyDictElement : VisualElement { [UxmlAttribute] public SerializableDictionary<int, string> dictionaryIntString;

[UxmlAttribute] public SerializableDictionary<int, int> dictionaryIntInt;

[UxmlAttribute] public SerializableDictionary<string, string> dictionaryStringString; }

Общий конвертер атрибутов:

using System;
using System.Globalization;
using System.Text;
using UnityEditor.UIElements;

public class SerializableDictionaryConverter<TKey, TValue> : UxmlAttributeConverter<SerializableDictionary<TKey, TValue>> { static string ValueToString(object v) => Convert.ToString(v, CultureInfo.InvariantCulture);

public override string ToString(SerializableDictionary<TKey, TValue> source) { var sb = new StringBuilder(); foreach (var pair in source) { sb.Append($"{ValueToString(pair.Key)}|{ValueToString(pair.Value)},"); } return sb.ToString(); }

public override SerializableDictionary<TKey, TValue> FromString(string source) { var result = new SerializableDictionary<TKey, TValue>(); var items = source.Split(','); foreach (var item in items) { var fields = item.Split('|'); var key = (TKey)Convert.ChangeType(fields[0], typeof(TKey)); var value = (TValue)Convert.ChangeType(fields[1], typeof(TValue));

result.keys.Add(key); result.values.Add(value); } result.TransferSerializedKeys(); return result; } }

Настраиваемый ящик свойств:

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

[CustomPropertyDrawer(typeof(SerializableDictionary<,>))] class SerializableDictionaryPropertyDrawer : PropertyDrawer { SerializedProperty m_Property; SerializedProperty m_Keys; SerializedProperty m_Values;

public override VisualElement CreatePropertyGUI(SerializedProperty property) { m_Property = property; m_Keys = property.FindPropertyRelative("keys"); m_Values = property.FindPropertyRelative("values");

var list = new ListView() { showAddRemoveFooter = true, showBorder = true, showAlternatingRowBackgrounds = AlternatingRowBackground.All, showFoldoutHeader = true, showBoundCollectionSize = false, reorderable = true, reorderMode = ListViewReorderMode.Animated, virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight, headerTitle = property.displayName, bindingPath = m_Keys.propertyPath, overridingAddButtonBehavior = OnAddButton, bindItem = BindListItem, }; return list; }

void BindListItem(VisualElement item, int index) { item.Clear();

item.Add(new PropertyField(m_Keys.GetArrayElementAtIndex(index)) { label = "Key" }); item.Add(new PropertyField(m_Values.GetArrayElementAtIndex(index)) { label = "Value" }); item.Bind(m_Property.serializedObject); }

void OnAddButton(BaseListView baseListView, Button button) { m_Keys.InsertArrayElementAtIndex(m_Keys.arraySize); m_Values.InsertArrayElementAtIndex(m_Values.arraySize); m_Property.serializedObject.ApplyModifiedProperties(); } }

Открытые методы

Метод Описание
FromStringПредоставляет тип, преобразованный из строкового представления.
ToStringПредоставляет строковое представление типа.