#nullable enable using System; using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// Vector2 속성 View 클래스입니다. /// UTKVector2Field를 사용하여 Vector2 값을 표시/편집합니다. /// [UxmlElement] public partial class UTKVector2PropertyItemView : UTKPropertyItemViewBase, IUTKPropertyItemView { #region Fields private UTKVector2Field? _vectorField; private Vector2 _value; private IUTKPropertyItem? _boundData; #endregion #region Properties protected override string ViewTypeName => "UTKVector2PropertyItemView"; /// 현재 값 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? 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("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 vectorData) { Bind(vectorData); } else { Debug.LogWarning($"[UTKVector2PropertyItemView] Cannot bind to non-Vector2 data: {data.GetType().Name}"); } } public void Bind(IUTKPropertyItem data) { Unbind(); _boundData = data; BindBase(data); Label = data.Name; _value = data.Value; IsVisible = data.IsVisible; TooltipText = data.Tooltip; ShowLabel = data.ShowLabel; data.OnTypedValueChanged += OnDataValueChanged; UpdateValueUI(); IsReadOnly = data.IsReadOnly; } public void Unbind() { if (_boundData != null) { _boundData.OnTypedValueChanged -= OnDataValueChanged; UnbindBase(); _boundData = null; } } private void OnDataValueChanged(IUTKPropertyItem 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 } }