Files
XRLib/Assets/Scripts/UVC/UIToolkit/Property/Items/UTKVector2PropertyItem.cs
2026-01-08 20:15:57 +09:00

157 lines
4.6 KiB
C#

#nullable enable
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit.Property
{
/// <summary>
/// 2D 벡터 속성 아이템
/// X, Y 두 개의 FloatField 사용
/// </summary>
public class UTKVector2PropertyItem : UTKPropertyItemBase<Vector2>
{
#region Fields
private FloatField? _xField;
private FloatField? _yField;
#endregion
#region Properties
public override UTKPropertyType PropertyType => UTKPropertyType.Vector2;
#endregion
#region Constructor
public UTKVector2PropertyItem(string id, string name, Vector2 initialValue = default)
: base(id, name, initialValue)
{
}
#endregion
#region Override Methods
public override VisualElement CreateUI()
{
var container = CreateContainer();
var label = CreateNameLabel();
container.Add(label);
var valueContainer = new VisualElement();
valueContainer.AddToClassList("utk-property-item__value");
// X 필드
var xContainer = new VisualElement();
xContainer.AddToClassList("utk-property-item__vector-field");
xContainer.style.flexDirection = FlexDirection.Row;
var xLabel = new Label("X");
xLabel.AddToClassList("utk-property-item__vector-label");
xLabel.AddToClassList("utk-vector-label--x");
_xField = new FloatField();
_xField.name = "x-field";
_xField.value = Value.x;
_xField.style.flexGrow = 1;
xContainer.Add(xLabel);
xContainer.Add(_xField);
valueContainer.Add(xContainer);
// Y 필드
var yContainer = new VisualElement();
yContainer.AddToClassList("utk-property-item__vector-field");
yContainer.style.flexDirection = FlexDirection.Row;
var yLabel = new Label("Y");
yLabel.AddToClassList("utk-property-item__vector-label");
yLabel.AddToClassList("utk-vector-label--y");
_yField = new FloatField();
_yField.name = "y-field";
_yField.value = Value.y;
_yField.style.flexGrow = 1;
yContainer.Add(yLabel);
yContainer.Add(_yField);
valueContainer.Add(yContainer);
container.Add(valueContainer);
return container;
}
public override void BindUI(VisualElement element)
{
base.BindUI(element);
_xField = element.Q<FloatField>("x-field");
_yField = element.Q<FloatField>("y-field");
if (_xField != null)
{
_xField.value = Value.x;
_xField.SetEnabled(!IsReadOnly);
_xField.RegisterValueChangedCallback(OnXChanged);
}
if (_yField != null)
{
_yField.value = Value.y;
_yField.SetEnabled(!IsReadOnly);
_yField.RegisterValueChangedCallback(OnYChanged);
}
}
public override void UnbindUI(VisualElement element)
{
if (_xField != null)
{
_xField.UnregisterValueChangedCallback(OnXChanged);
_xField = null;
}
if (_yField != null)
{
_yField.UnregisterValueChangedCallback(OnYChanged);
_yField = null;
}
base.UnbindUI(element);
}
public override void RefreshUI()
{
if (_xField != null && !Mathf.Approximately(_xField.value, Value.x))
{
_xField.SetValueWithoutNotify(Value.x);
}
if (_yField != null && !Mathf.Approximately(_yField.value, Value.y))
{
_yField.SetValueWithoutNotify(Value.y);
}
}
protected override void UpdateReadOnlyState()
{
base.UpdateReadOnlyState();
_xField?.SetEnabled(!IsReadOnly);
_yField?.SetEnabled(!IsReadOnly);
}
#endregion
#region Private Methods
private void OnXChanged(ChangeEvent<float> evt)
{
var newValue = new Vector2(evt.newValue, Value.y);
DebounceValueChange(newValue, 100).Forget();
}
private void OnYChanged(ChangeEvent<float> evt)
{
var newValue = new Vector2(Value.x, evt.newValue);
DebounceValueChange(newValue, 100).Forget();
}
#endregion
}
}