Unity UI Toolkit カスタムコントロールサンプル
始めに
UI Toolkit でのカスタムコントロール その2 です。
主にデフォルト動作を変えるためのものです。
- Unity 6000.4.4f1
- R3 1.3.0
参考
【UI Toolkit】Unity6 で UiBuilder 上で Image タグを Library から使用できるように拡張する https://qiita.com/john95206/items/8e7498f1dfb894396383
サンプルコード
using UnityEngine;
using UnityEngine.UIElements;
namespace Assets.MyUI
{
[UxmlElement]
public partial class MyButton : Button
{
public MyButton()
{
selection.doubleClickSelectsWord = false;
selection.tripleClickSelectsLine = false;
enableRichText = false;
displayTooltipWhenElided = false;
blocker = new VisualElement();
blocker.style.position = Position.Absolute;
blocker.style.top = 0;
blocker.style.left = 0;
blocker.style.right = 0;
blocker.style.bottom = 0;
blocker.pickingMode = PickingMode.Position;
Add(blocker);
}
VisualElement blocker;
public void SetIconImage(Sprite sprite)
{
iconImage = Background.FromSprite(sprite);
}
public void SetEnabledAndClickable(bool enabled)
{
//SetEnabled(enabled);//子であるblokerも無効化される。自前で見た目とクリックの有効/無効を切り替える
style.opacity = enabled ? 1f : 0.5f;
blocker.style.display = enabled ? DisplayStyle.None : DisplayStyle.Flex;
}
}
}
SetEnabledをした時にクリックが背面に貫通してしまう対策をしています。
using Unity.Properties;
using UnityEngine;
using UnityEngine.UIElements;
namespace Assets.MyUI
{
[UxmlElement]
public partial class MyImage : VisualElement
{
[CreateProperty]
[UxmlAttribute]
public Sprite ImageSprite
{
get => _image.sprite;
set
{
_image.sprite = value;
}
}
private readonly Image _image;
public MyImage()
{
_image = new Image();
Add(_image);
style.flexGrow = 1;
style.justifyContent = Justify.Center;
}
}
}
using UnityEngine.UIElements;
namespace Assets.MyUI
{
[UxmlElement]
public partial class MyLabel : Label
{
public MyLabel()
{
selection.doubleClickSelectsWord = false;
selection.tripleClickSelectsLine = false;
enableRichText = false;
displayTooltipWhenElided = false;
}
}
}
using R3;
using System;
using System.Collections.Generic;
using UnityEngine.UIElements;
namespace Assets.MyUI
{
[UxmlElement]
public partial class MyListView : ListView
{
public MyListView()
{
// 項目がない時の"List is Empty"を消す
makeNoneElement = () => null;
}
public Observable<IEnumerable<int>> ObservableSelectedIndicesChanged()
{
return Observable.FromEvent<IEnumerable<int>>(
h => selectedIndicesChanged += h,
h => selectedIndicesChanged -= h);
}
public Observable<IEnumerable<int>> ObservableItemAdded()
{
return Observable.FromEvent<IEnumerable<int>>(
h => itemsAdded += h,
h => itemsAdded -= h);
}
public Observable<IEnumerable<int>> ObservableItemRemoved()
{
return Observable.FromEvent<IEnumerable<int>>(
h => itemsRemoved += h,
h => itemsRemoved -= h);
}
public Observable<Unit> ObservableItemsSourceChanged()
{
return Observable.FromEvent(
h => itemsSourceChanged += h,
h => itemsSourceChanged -= h);
}
public Observable<(int oldIndex, int newIndex)> ObservableItemIndexChanged()
{
return Observable.FromEvent<Action<int, int>, (int oldIndex, int newIndex)>(
h => new Action<int, int>((oldIndex, newIndex) => h((oldIndex, newIndex))),
h => itemIndexChanged += h,
h => itemIndexChanged -= h);
}
public Observable<Unit> ObservableCountModified()
{
return Observable.Merge(
ObservableItemAdded().AsUnitObservable(),
ObservableItemRemoved().AsUnitObservable()
);
}
public Observable<Unit> ObservableModified()
{
return Observable.Merge(
ObservableItemAdded().AsUnitObservable(),
ObservableItemRemoved().AsUnitObservable(),
ObservableItemsSourceChanged(),
ObservableItemIndexChanged().AsUnitObservable()
);
}
}
}