前回はコールバックを作成しましたが、今回は独自のコントロールを作ってみましょう!
ということで、早速 UXML と C# スクリプトを書きます。
たとえば、こんな感じのメッセージボックスを作りたい場合は、
以下のような UXML になると思います。
<?xml version="1.0" encoding="utf-8"?> <engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" xsi:noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" > <engine:VisualElement class="flex flex-row border-2 border-slate-400 rounded-md p-2 my-2 items-center"> <engine:VisualElement class="flex justify-center items-center"> <engine:Image name="icon" class="w-10 h-10 min-h-full" /> </engine:VisualElement> <engine:VisualElement class="flex-grow ml-2"> <engine:TextElement name="text" class="text-lg" /> </engine:VisualElement> </engine:VisualElement> </engine:UXML>
そして、これの icon
と text
部分を、親コンポーネントから受け取る値だったとします。
その場合、次のような C# スクリプトを記述します。
// ------------------------------------------------------------------------------------------ // Copyright (c) Natsuneko. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. // ------------------------------------------------------------------------------------------ using System.Collections.Generic; using NatsunekoLaboratory.VRAvatarToolkit.Enums; using NatsunekoLaboratory.VRAvatarToolkit.Extensions; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; namespace NatsunekoLaboratory.VRAvatarToolkit.Controls { public class MessageBox : VisualElement { private readonly Image _icon; private readonly TextElement _text; public MessageBoxIcon Icon { set => _icon.style.backgroundImage = new StyleBackground(Background.FromTexture2D(EditorGUIUtility.Load(value.ToResourceString()) as Texture2D)); } public string Text { get => _text.text; set => _text.text = value; } public MessageBox() { // UXML / USS 読み込み部分は省略 _icon = this.Q<Image>("icon"); _text = this.Q<TextElement>("text"); } public new class UxmlFactory : UxmlFactory<MessageBox, UxmlTraits> { } public new class UxmlTraits : VisualElement.UxmlTraits { private readonly UxmlEnumAttributeDescription<MessageBoxIcon> _icon = new UxmlEnumAttributeDescription<MessageBoxIcon> { name = "icon", defaultValue = MessageBoxIcon.Info }; private readonly UxmlStringAttributeDescription _text = new UxmlStringAttributeDescription { name = "text", defaultValue = "" }; public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription { get { yield break; } } public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) { base.Init(ve, bag, cc); ((MessageBox)ve).Text = _text.GetValueFromBag(bag, cc); ((MessageBox)ve).Icon = _icon.GetValueFromBag(bag, cc); } } } }
該当コントロールのクラス実装のインナークラスとして、 UxmlTraits
みたいな感じで作ってあげると、バインディングされた値を受け取ることが出来ます。
最後に、 Init
メソッド経由で受け取れば、初期値がバインドされます。
2回目以降は普通に C# スクリプトからプロパティ経由でアクセス可能なので、特に実装は必要ありません。
ということで、今日のメモでした!