using System; using UnityEngine; using UnityEngine.UI; namespace XericUI.ReflectionUIGenerator { /// /// Slider 值组件 — 处理 float / int / double 类型的滑块交互 /// 适用 Shader Range 属性或标记了 [XuiavrgFieldTag(Slider)] 的字段 /// [AddComponentMenu("Xeric Library/UI Action Vessel/Values/XUIAvrgMDSliderValue")] public class XUIAvrgMDSliderValue : XUIAvrgMDValue { [SerializeField, Tooltip("关联的 Slider 组件(未设置则自动查找)")] private Slider _slider; [Header("Slider 专属插槽")] [SerializeField, Tooltip("值显示文本 — 显示当前 Slider 数值")] #if dUI_TextMeshPro private TMPro.TMP_Text _valueDisplayText; #else private UnityEngine.UI.Text _valueDisplayText; #endif [SerializeField, Tooltip("最小值文本 — 显示 Slider 下限")] #if dUI_TextMeshPro private TMPro.TMP_Text _minValueText; #else private UnityEngine.UI.Text _minValueText; #endif [SerializeField, Tooltip("最大值文本 — 显示 Slider 上限")] #if dUI_TextMeshPro private TMPro.TMP_Text _maxValueText; #else private UnityEngine.UI.Text _maxValueText; #endif [SerializeField, Tooltip("增加按钮(点击按步进值 +)")] private Button _incrementButton; [SerializeField, Tooltip("减少按钮(点击按步进值 -)")] private Button _decrementButton; private const float DefaultStep = 0.1f; private void Awake() { if (_slider == null) _slider = GetComponent(); } // ============ 对象池生命周期 ============ public override void OnPoolGet(AvrgMemberMetaData metaData) { base.OnPoolGet(metaData); if (_slider == null) return; // 从元数据初始化 Slider 参数 if (metaData?.RangeMin.HasValue == true) _slider.minValue = metaData.RangeMin.Value; if (metaData?.RangeMax.HasValue == true) _slider.maxValue = metaData.RangeMax.Value; _slider.wholeNumbers = metaData?.ValueType == typeof(int); } public override void OnPoolRelease() { if (_incrementButton != null) _incrementButton.onClick.RemoveAllListeners(); if (_decrementButton != null) _decrementButton.onClick.RemoveAllListeners(); if (_slider != null) _slider.onValueChanged.RemoveAllListeners(); // 重置子类文本 if (_valueDisplayText != null) _valueDisplayText.text = ""; if (_minValueText != null) _minValueText.text = ""; if (_maxValueText != null) _maxValueText.text = ""; base.OnPoolRelease(); } // ============ 核心绑定 ============ public override void BindToAccessor( IAvrgValueAccessor accessor, AvrgMvvmBinding binding, AvrgMvvmScheduler scheduler) { CurrentAccessor = accessor; CurrentBinding = binding; if (binding == null || accessor == null || _slider == null) return; // 初始化上下限文本 ApplyRangeTexts(); // 增减按钮 if (_incrementButton != null) _incrementButton.onClick.AddListener(OnIncrementClicked); if (_decrementButton != null) _decrementButton.onClick.AddListener(OnDecrementClicked); // UI → 数据 _slider.onValueChanged.AddListener(val => { object convertedVal = ConvertValueForAccessor(val, accessor.ValueType); binding.WriteFromUI(convertedVal); scheduler?.MarkUIDirty(binding); RefreshValueText(convertedVal); }); // 数据 → UI(带验证状态) binding.OnUIDataChanged += (value, state) => { float sliderVal = Convert.ToSingle(value); _slider.SetValueWithoutNotify(sliderVal); RefreshValueText(value); ApplyValueTextColor(state); base.UpdateValueDisplay(value, state); }; // 验证状态变更 binding.OnValidationStateChanged += OnValidationStateChanged; // 首次同步 var initialValue = accessor.GetValue(); if (initialValue != null) _slider.SetValueWithoutNotify(Convert.ToSingle(initialValue)); RefreshValueText(initialValue); UpdateValueDisplay(initialValue ?? 0f, ValidationState.Normal); } // ============ 值显示 ============ protected override void UpdateValueDisplay(object value, ValidationState state) { ApplyValueTextColor(state); base.UpdateValueDisplay(value, state); } private void RefreshValueText(object value) { if (_valueDisplayText == null || CurrentAccessor == null) return; _valueDisplayText.text = CurrentAccessor.FormatDisplay(value); } private void ApplyValueTextColor(ValidationState state) { if (_valueDisplayText == null) return; _valueDisplayText.color = state == ValidationState.Invalid ? Color.red : state == ValidationState.Warning ? new Color(1f, 0.92f, 0.016f) : Color.white; } private void ApplyRangeTexts() { if (_minValueText != null) _minValueText.text = CurrentAccessor?.FormatDisplay(_slider.minValue) ?? _slider.minValue.ToString(); if (_maxValueText != null) _maxValueText.text = CurrentAccessor?.FormatDisplay(_slider.maxValue) ?? _slider.maxValue.ToString(); } // ============ 步进值 ============ private float GetStepValue() { return _slider.wholeNumbers ? 1f : DefaultStep; } private void OnIncrementClicked() { if (CurrentAccessor?.IsReadOnly == true || _slider == null) return; float step = GetStepValue(); float current = Convert.ToSingle(CurrentAccessor.GetValue()); float newVal = Mathf.Clamp(current + step, _slider.minValue, _slider.maxValue); _slider.value = newVal; } private void OnDecrementClicked() { if (CurrentAccessor?.IsReadOnly == true || _slider == null) return; float step = GetStepValue(); float current = Convert.ToSingle(CurrentAccessor.GetValue()); float newVal = Mathf.Clamp(current - step, _slider.minValue, _slider.maxValue); _slider.value = newVal; } // ============ 验证状态回调 ============ protected override void OnValidationStateChanged(ValidationState state) { base.OnValidationStateChanged(state); // Slider 填充色随验证状态变化 if (_slider != null) { var fillArea = _slider.fillRect; if (fillArea != null && fillArea.TryGetComponent(out var fill)) { fill.color = state switch { ValidationState.Invalid => Color.red, ValidationState.Warning => new Color(1f, 0.92f, 0.016f), _ => Color.white }; } } ApplyValueTextColor(state); } private static object ConvertValueForAccessor(float val, Type targetType) { if (targetType == typeof(int)) return (int)val; if (targetType == typeof(double)) return (double)val; return val; } } }