UTKPropertyItem 개선
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UVC.UIToolkit
|
||||
{
|
||||
/// <summary>
|
||||
/// Vector2 속성 View 클래스입니다.
|
||||
/// UTKVector2Field를 사용하여 Vector2 값을 표시/편집합니다.
|
||||
/// </summary>
|
||||
[UxmlElement]
|
||||
public partial class UTKVector2PropertyItemView : UTKPropertyItemViewBase, IUTKPropertyItemView<Vector2>
|
||||
{
|
||||
#region Fields
|
||||
private UTKVector2Field? _vectorField;
|
||||
|
||||
private Vector2 _value;
|
||||
private IUTKPropertyItem<Vector2>? _boundData;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
protected override string ViewTypeName => "UTKVector2PropertyItemView";
|
||||
|
||||
/// <summary>현재 값</summary>
|
||||
public Vector2 Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (_value != value)
|
||||
{
|
||||
_value = value;
|
||||
UpdateValueUI();
|
||||
OnValueChanged?.Invoke(value);
|
||||
|
||||
if (_boundData != null && _boundData.Value != value)
|
||||
{
|
||||
_boundData.Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
public event Action<Vector2>? OnValueChanged;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public UTKVector2PropertyItemView() : base()
|
||||
{
|
||||
InitializeUI();
|
||||
}
|
||||
|
||||
public UTKVector2PropertyItemView(string label, Vector2 value = default) : base()
|
||||
{
|
||||
_value = value;
|
||||
Label = label;
|
||||
InitializeUI();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
private void InitializeUI()
|
||||
{
|
||||
AddToClassList("utk-property-item-view");
|
||||
AddToClassList("utk-property-item-view--vector2");
|
||||
|
||||
if (!CreateUIFromUxml())
|
||||
{
|
||||
CreateUIFallback();
|
||||
}
|
||||
|
||||
// UXML에서 요소 가져오기
|
||||
QueryUIElements();
|
||||
|
||||
// 이벤트 등록
|
||||
RegisterEvents();
|
||||
|
||||
UpdateValueUI();
|
||||
UpdateReadOnlyState();
|
||||
}
|
||||
|
||||
private void QueryUIElements()
|
||||
{
|
||||
_vectorField = this.Q<UTKVector2Field>("value-field");
|
||||
|
||||
// Fallback: UXML에서 못 찾으면 생성
|
||||
if (_valueContainer != null && _vectorField == null)
|
||||
{
|
||||
_vectorField = new UTKVector2Field
|
||||
{
|
||||
name = "value-field",
|
||||
label = ""
|
||||
};
|
||||
_vectorField.AddToClassList("utk-property-item-view__vector-field");
|
||||
_valueContainer.Add(_vectorField);
|
||||
}
|
||||
|
||||
// 초기 값 설정
|
||||
if (_vectorField != null)
|
||||
{
|
||||
_vectorField.label = "";
|
||||
_vectorField.SetValueWithoutNotify(_value);
|
||||
_vectorField.IsReadOnly = IsReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterEvents()
|
||||
{
|
||||
if (_vectorField != null)
|
||||
{
|
||||
_vectorField.OnValueChanged += OnVectorChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void UnregisterEvents()
|
||||
{
|
||||
if (_vectorField != null)
|
||||
{
|
||||
_vectorField.OnValueChanged -= OnVectorChanged;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
protected override void CreateValueUI(VisualElement container)
|
||||
{
|
||||
// UXML/QueryUIElements 기반으로 생성하므로 여기서는 생성하지 않음
|
||||
}
|
||||
|
||||
public override void RefreshUI()
|
||||
{
|
||||
UpdateValueUI();
|
||||
}
|
||||
|
||||
protected override void OnReadOnlyStateChanged(bool isReadOnly)
|
||||
{
|
||||
if (_vectorField != null)
|
||||
{
|
||||
_vectorField.IsReadOnly = isReadOnly;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Event Handling
|
||||
private void OnVectorChanged(Vector2 newValue)
|
||||
{
|
||||
if (_value != newValue)
|
||||
{
|
||||
_value = newValue;
|
||||
OnValueChanged?.Invoke(newValue);
|
||||
|
||||
if (_boundData != null && _boundData.Value != newValue)
|
||||
{
|
||||
_boundData.Value = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Value Update
|
||||
private void UpdateValueUI()
|
||||
{
|
||||
if (_vectorField != null && _vectorField.Value != _value)
|
||||
{
|
||||
_vectorField.SetValueWithoutNotify(_value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Data Binding
|
||||
public void Bind(IUTKPropertyItem data)
|
||||
{
|
||||
if (data is IUTKPropertyItem<Vector2> vectorData)
|
||||
{
|
||||
Bind(vectorData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[UTKVector2PropertyItemView] Cannot bind to non-Vector2 data: {data.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Bind(IUTKPropertyItem<Vector2> data)
|
||||
{
|
||||
Unbind();
|
||||
|
||||
_boundData = data;
|
||||
|
||||
Label = data.Name;
|
||||
_value = data.Value;
|
||||
IsReadOnly = data.IsReadOnly;
|
||||
IsVisible = data.IsVisible;
|
||||
TooltipText = data.Tooltip;
|
||||
|
||||
data.OnTypedValueChanged += OnDataValueChanged;
|
||||
|
||||
UpdateValueUI();
|
||||
UpdateReadOnlyState();
|
||||
}
|
||||
|
||||
public void Unbind()
|
||||
{
|
||||
if (_boundData != null)
|
||||
{
|
||||
_boundData.OnTypedValueChanged -= OnDataValueChanged;
|
||||
_boundData = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDataValueChanged(IUTKPropertyItem<Vector2> item, Vector2 oldValue, Vector2 newValue)
|
||||
{
|
||||
if (_value != newValue)
|
||||
{
|
||||
_value = newValue;
|
||||
UpdateValueUI();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Dispose
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
UnregisterEvents();
|
||||
Unbind();
|
||||
|
||||
OnValueChanged = null;
|
||||
_vectorField = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user