#nullable enable using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// 정수 속성 아이템 /// IntegerField 또는 SliderInt 사용 /// public class UTKIntPropertyItem : UTKPropertyItemBase { #region Fields private UTKIntegerField? _intField; private UTKSliderInt? _slider; private bool _useSlider; private int _minValue; private int _maxValue = 100; #endregion #region Properties public override UTKPropertyType PropertyType => UTKPropertyType.Int; /// 슬라이더 사용 여부 public bool UseSlider { get => _useSlider; set => _useSlider = value; } /// 최소값 (슬라이더 모드) public int MinValue { get => _minValue; set { _minValue = value; if (_slider != null) { _slider.lowValue = value; } } } /// 최대값 (슬라이더 모드) public int MaxValue { get => _maxValue; set { _maxValue = value; if (_slider != null) { _slider.highValue = value; } } } #endregion #region Constructor public UTKIntPropertyItem(string id, string name, int initialValue = 0) : base(id, name, initialValue) { } public UTKIntPropertyItem(string id, string name, int initialValue, int minValue, int maxValue, bool useSlider = true, bool isReadOnly = false) : base(id, name, initialValue) { _minValue = minValue; _maxValue = maxValue; _useSlider = useSlider; _isReadOnly = isReadOnly; } #endregion #region Override Methods public override VisualElement CreateUI() { string uxmlName = _useSlider ? "UTKIntPropertyItemSlider" : "UTKIntPropertyItem"; var container = CreateUIFromUxml(uxmlName); if (container == null) { return CreateUIFallback(); } _intField = container.Q("value-field"); _slider = container.Q("slider-field"); if (_intField != null) { _intField.Value = Value; _intField.isReadOnly = IsReadOnly; } if (_slider != null) { _slider.lowValue = _minValue; _slider.highValue = _maxValue; _slider.Value = Value; _slider.IsEnabled = !IsReadOnly; } return container; } private VisualElement CreateUIFallback() { var container = CreateContainer(); if (_useSlider) { container.AddToClassList("utk-property-item--slider"); } var label = CreateNameLabel(); container.Add(label); var valueContainer = new VisualElement(); valueContainer.AddToClassList("utk-property-item__value"); if (_useSlider) { _slider = new UTKSliderInt("", _minValue, _maxValue, Value); _slider.name = "slider-field"; _slider.AddToClassList("utk-property-item__slider"); _slider.IsEnabled = !IsReadOnly; valueContainer.Add(_slider); _intField = new UTKIntegerField(); _intField.name = "value-field"; _intField.Value = Value; _intField.isReadOnly = IsReadOnly; _intField.AddToClassList("utk-property-item__number-field"); valueContainer.Add(_intField); } else { _intField = new UTKIntegerField(); _intField.name = "value-field"; _intField.Value = Value; _intField.isReadOnly = IsReadOnly; valueContainer.Add(_intField); } container.Add(valueContainer); return container; } public override void BindUI(VisualElement element) { base.BindUI(element); _intField = element.Q("value-field"); _slider = element.Q("slider-field"); if (_intField != null) { _intField.Value = Value; _intField.isReadOnly = IsReadOnly; _intField.OnValueChanged += OnIntFieldChanged; } if (_slider != null) { _slider.lowValue = _minValue; _slider.highValue = _maxValue; _slider.Value = Value; _slider.IsEnabled = !IsReadOnly; _slider.OnValueChanged += OnSliderChanged; } } public override void UnbindUI(VisualElement element) { if (_intField != null) { _intField.OnValueChanged -= OnIntFieldChanged; _intField = null; } if (_slider != null) { _slider.OnValueChanged -= OnSliderChanged; _slider = null; } base.UnbindUI(element); } public override void RefreshUI() { if (_intField != null && _intField.Value != Value) { _intField.SetValueWithoutNotify(Value); } if (_slider != null && _slider.Value != Value) { _slider.SetValueWithoutNotify(Value); } } protected override void UpdateReadOnlyState() { base.UpdateReadOnlyState(); if (_intField != null) { _intField.isReadOnly = IsReadOnly; } if (_slider != null) _slider.IsEnabled = !IsReadOnly; } #endregion #region Private Methods private void OnIntFieldChanged(int newValue) { int clampedValue = _useSlider ? Mathf.Clamp(newValue, _minValue, _maxValue) : newValue; if (_slider != null && _slider.Value != clampedValue) { _slider.SetValueWithoutNotify(clampedValue); } DebounceValueChange(clampedValue, 100).Forget(); } private void OnSliderChanged(int newValue) { if (_intField != null && _intField.Value != newValue) { _intField.SetValueWithoutNotify(newValue); } // 슬라이더는 빠른 반응이 필요하므로 짧은 디바운스 DebounceValueChange(newValue, 50).Forget(); } #endregion } }