// using AlicizaX.UI.Extension; // using UnityEngine.EventSystems; // using Direction = UnityEngine.UI.Slider.Direction; // // namespace UnityEngine.UI // { // [ExecuteAlways] // [RequireComponent(typeof(RectTransform))] // public class UXSlider : UXSelectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement // { // [SerializeField] private RectTransform m_FillRect; // // public RectTransform fillRect // { // get { return m_FillRect; } // set // { // if (SetPropertyUtility.SetClass(ref m_FillRect, value)) // { // UpdateCachedReferences(); // UpdateVisuals(); // } // } // } // // [SerializeField] private RectTransform m_HandleRect; // // public RectTransform handleRect // { // get { return m_HandleRect; } // set // { // if (SetPropertyUtility.SetClass(ref m_HandleRect, value)) // { // UpdateCachedReferences(); // UpdateVisuals(); // } // } // } // // [Space] [SerializeField] private Slider.Direction m_Direction = Slider.Direction.LeftToRight; // // public Slider.Direction direction // { // get { return m_Direction; } // set // { // if (SetPropertyUtility.SetStruct(ref m_Direction, value)) UpdateVisuals(); // } // } // // [SerializeField] private float m_MinValue = 0; // // public float minValue // { // get { return m_MinValue; } // set // { // if (SetPropertyUtility.SetStruct(ref m_MinValue, value)) // { // Set(m_Value); // UpdateVisuals(); // } // } // } // // [SerializeField] private float m_MaxValue = 1; // // public float maxValue // { // get { return m_MaxValue; } // set // { // if (SetPropertyUtility.SetStruct(ref m_MaxValue, value)) // { // Set(m_Value); // UpdateVisuals(); // } // } // } // // [SerializeField] private bool m_WholeNumbers = false; // // public bool wholeNumbers // { // get { return m_WholeNumbers; } // set // { // if (SetPropertyUtility.SetStruct(ref m_WholeNumbers, value)) // { // Set(m_Value); // UpdateVisuals(); // } // } // } // // [Space] [SerializeField] protected float m_Value; // // public virtual float value // { // get { return wholeNumbers ? Mathf.Round(m_Value) : m_Value; } // set { Set(value); } // } // // public virtual void SetValueWithoutNotify(float input) // { // Set(input, false); // } // // public float normalizedValue // { // get // { // if (Mathf.Approximately(minValue, maxValue)) // return 0; // return Mathf.InverseLerp(minValue, maxValue, value); // } // set { this.value = Mathf.Lerp(minValue, maxValue, value); } // } // // [Space] [SerializeField] private Slider.SliderEvent m_OnValueChanged = new Slider.SliderEvent(); // // public Slider.SliderEvent onValueChanged // { // get { return m_OnValueChanged; } // set { m_OnValueChanged = value; } // } // // // --- SMOOTHING FIELDS --- // [Space] // [SerializeField] private bool m_SmoothMovement = false; // [SerializeField] private float m_SmoothSpeed = 8f; // value-per-second, larger=faster // // public bool smoothMovement // { // get { return m_SmoothMovement; } // set { m_SmoothMovement = value; } // } // // /// // /// 平滑移动目标值(只有当 smoothMovement && !wholeNumbers 时生效) // /// // protected float m_TargetValue; // protected bool m_IsSmoothMoving = false; // // ------------------------ // // private Image m_FillImage; // private Transform m_FillTransform; // private RectTransform m_FillContainerRect; // private Transform m_HandleTransform; // private RectTransform m_HandleContainerRect; // // private Vector2 m_Offset = Vector2.zero; // // #pragma warning disable 649 // private DrivenRectTransformTracker m_Tracker; // #pragma warning restore 649 // // private bool m_DelayedUpdateVisuals = false; // // float stepSize // { // get { return wholeNumbers ? 1 : (maxValue - minValue) * 0.1f; } // } // // protected UXSlider() // { // } // #if UNITY_EDITOR // protected override void OnValidate() // { // base.OnValidate(); // if (wholeNumbers) // { // m_MinValue = Mathf.Round(m_MinValue); // m_MaxValue = Mathf.Round(m_MaxValue); // } // // //Onvalidate is called before OnEnabled. We need to make sure not to touch any other objects before OnEnable is run. // if (IsActive()) // { // UpdateCachedReferences(); // // Update rects in next update since other things might affect them even if value didn't change. // m_DelayedUpdateVisuals = true; // } // // if (!UnityEditor.PrefabUtility.IsPartOfPrefabAsset(this) && !Application.isPlaying) // CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this); // } // #endif // // protected override void OnEnable() // { // base.OnEnable(); // UpdateCachedReferences(); // Set(m_Value, false); // // Update rects since they need to be initialized correctly. // UpdateVisuals(); // // 初始化 target // m_TargetValue = m_Value; // m_IsSmoothMoving = false; // } // // protected override void OnDisable() // { // m_Tracker.Clear(); // base.OnDisable(); // } // // protected virtual void Update() // { // if (m_DelayedUpdateVisuals) // { // m_DelayedUpdateVisuals = false; // Set(m_Value, false); // UpdateVisuals(); // } // // // 处理平滑移动(仅当开启时) // if (m_IsSmoothMoving) // { // // 如果 wholeNumbers 为 true,则取消平滑,直接设置最终值(避免小数) // if (wholeNumbers) // { // m_IsSmoothMoving = false; // Set(m_TargetValue); // } // else // { // float maxDelta = m_SmoothSpeed * Time.unscaledDeltaTime; // float newValue = Mathf.MoveTowards(m_Value, m_TargetValue, maxDelta); // // 使用 Set 来保持更新视觉并触发回调(会在数值改变时触发) // Set(newValue); // if (Mathf.Approximately(newValue, m_TargetValue)) // { // m_IsSmoothMoving = false; // // 确保最终值精确到目标(避免浮点残留) // Set(m_TargetValue); // } // } // } // } // // protected override void OnDidApplyAnimationProperties() // { // m_Value = ClampValue(m_Value); // float oldNormalizedValue = normalizedValue; // if (m_FillContainerRect != null) // { // if (m_FillImage != null && m_FillImage.type == Image.Type.Filled) // oldNormalizedValue = m_FillImage.fillAmount; // else // oldNormalizedValue = (reverseValue ? 1 - m_FillRect.anchorMin[(int)axis] : m_FillRect.anchorMax[(int)axis]); // } // else if (m_HandleContainerRect != null) // oldNormalizedValue = (reverseValue ? 1 - m_HandleRect.anchorMin[(int)axis] : m_HandleRect.anchorMin[(int)axis]); // // UpdateVisuals(); // // if (oldNormalizedValue != normalizedValue) // { // UISystemProfilerApi.AddMarker("Slider.value", this); // onValueChanged.Invoke(m_Value); // } // // // UUM-34170 Apparently, some properties on slider such as IsInteractable and Normalcolor Animation is broken. // // We need to call base here to render the animation on Scene // base.OnDidApplyAnimationProperties(); // } // // void UpdateCachedReferences() // { // if (m_FillRect && m_FillRect != (RectTransform)transform) // { // m_FillTransform = m_FillRect.transform; // m_FillImage = m_FillRect.GetComponent(); // if (m_FillTransform.parent != null) // m_FillContainerRect = m_FillTransform.parent.GetComponent(); // } // else // { // m_FillRect = null; // m_FillContainerRect = null; // m_FillImage = null; // } // // if (m_HandleRect && m_HandleRect != (RectTransform)transform) // { // m_HandleTransform = m_HandleRect.transform; // if (m_HandleTransform.parent != null) // m_HandleContainerRect = m_HandleTransform.parent.GetComponent(); // } // else // { // m_HandleRect = null; // m_HandleContainerRect = null; // } // } // // float ClampValue(float input) // { // float newValue = Mathf.Clamp(input, minValue, maxValue); // if (wholeNumbers) // newValue = Mathf.Round(newValue); // return newValue; // } // // protected virtual void Set(float input, bool sendCallback = true) // { // // Clamp the input // float newValue = ClampValue(input); // // // If the stepped value doesn't match the last one, it's time to update // if (m_Value == newValue) // return; // // m_Value = newValue; // UpdateVisuals(); // if (sendCallback) // { // UISystemProfilerApi.AddMarker("Slider.value", this); // m_OnValueChanged.Invoke(newValue); // } // } // // protected override void OnRectTransformDimensionsChange() // { // base.OnRectTransformDimensionsChange(); // if (!IsActive()) // return; // // UpdateVisuals(); // } // // enum Axis // { // Horizontal = 0, // Vertical = 1 // } // // Axis axis // { // get { return (m_Direction == Direction.LeftToRight || m_Direction == Direction.RightToLeft) ? Axis.Horizontal : Axis.Vertical; } // } // // bool reverseValue // { // get { return m_Direction == Direction.RightToLeft || m_Direction == Direction.TopToBottom; } // } // // // private void UpdateVisuals() // { // #if UNITY_EDITOR // if (!Application.isPlaying) // UpdateCachedReferences(); // #endif // // m_Tracker.Clear(); // // if (m_FillContainerRect != null) // { // m_Tracker.Add(this, m_FillRect, DrivenTransformProperties.Anchors); // Vector2 anchorMin = Vector2.zero; // Vector2 anchorMax = Vector2.one; // // if (m_FillImage != null && m_FillImage.type == Image.Type.Filled) // { // m_FillImage.fillAmount = normalizedValue; // } // else // { // if (reverseValue) // anchorMin[(int)axis] = 1 - normalizedValue; // else // anchorMax[(int)axis] = normalizedValue; // } // // m_FillRect.anchorMin = anchorMin; // m_FillRect.anchorMax = anchorMax; // } // // if (m_HandleContainerRect != null) // { // m_Tracker.Add(this, m_HandleRect, DrivenTransformProperties.Anchors); // Vector2 anchorMin = Vector2.zero; // Vector2 anchorMax = Vector2.one; // anchorMin[(int)axis] = anchorMax[(int)axis] = (reverseValue ? (1 - normalizedValue) : normalizedValue); // m_HandleRect.anchorMin = anchorMin; // m_HandleRect.anchorMax = anchorMax; // } // } // // void UpdateDrag(PointerEventData eventData, Camera cam) // { // RectTransform clickRect = m_HandleContainerRect ?? m_FillContainerRect; // if (clickRect != null && clickRect.rect.size[(int)axis] > 0) // { // Vector2 position = Vector2.zero; // if (!MultipleDisplayUtilities.GetRelativeMousePositionForDrag(eventData, ref position)) // return; // // Vector2 localCursor; // if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, position, cam, out localCursor)) // return; // localCursor -= clickRect.rect.position; // // float val = Mathf.Clamp01((localCursor - m_Offset)[(int)axis] / clickRect.rect.size[(int)axis]); // normalizedValue = (reverseValue ? 1f - val : val); // } // } // // private bool MayDrag(PointerEventData eventData) // { // return IsActive() && IsInteractable() && eventData.button == PointerEventData.InputButton.Left; // } // // public override void OnPointerDown(PointerEventData eventData) // { // if (!MayDrag(eventData)) // return; // // base.OnPointerDown(eventData); // // // 取消任何平滑移动(开始拖拽时) // m_IsSmoothMoving = false; // m_TargetValue = m_Value; // // m_Offset = Vector2.zero; // if (m_HandleContainerRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HandleRect, eventData.pointerPressRaycast.screenPosition, eventData.enterEventCamera)) // { // Vector2 localMousePos; // if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HandleRect, eventData.pointerPressRaycast.screenPosition, eventData.pressEventCamera, out localMousePos)) // m_Offset = localMousePos; // } // else // { // // Outside the slider handle - jump to this point instead // UpdateDrag(eventData, eventData.pressEventCamera); // } // } // // public void OnDrag(PointerEventData eventData) // { // if (!MayDrag(eventData)) // return; // // 拖拽也取消平滑 // m_IsSmoothMoving = false; // m_TargetValue = m_Value; // UpdateDrag(eventData, eventData.pressEventCamera); // } // // public override void OnMove(AxisEventData eventData) // { // if (!IsActive() || !IsInteractable()) // { // base.OnMove(eventData); // return; // } // // // 基准值:如果当前已经在平滑移动中,累加到 target 上;否则从当前 value 开始。 // float currentBase = m_IsSmoothMoving ? m_TargetValue : value; // // switch (eventData.moveDir) // { // case MoveDirection.Left: // if (axis == Axis.Horizontal && FindSelectableOnLeft() == null) // { // float dest = ClampValue(reverseValue ? currentBase + stepSize : currentBase - stepSize); // if (m_SmoothMovement && !wholeNumbers) // { // m_TargetValue = dest; // m_IsSmoothMoving = true; // } // else // { // Set(dest); // } // } // else // base.OnMove(eventData); // break; // case MoveDirection.Right: // if (axis == Axis.Horizontal && FindSelectableOnRight() == null) // { // float dest = ClampValue(reverseValue ? currentBase - stepSize : currentBase + stepSize); // if (m_SmoothMovement && !wholeNumbers) // { // m_TargetValue = dest; // m_IsSmoothMoving = true; // } // else // { // Set(dest); // } // } // else // base.OnMove(eventData); // break; // case MoveDirection.Up: // if (axis == Axis.Vertical && FindSelectableOnUp() == null) // { // float dest = ClampValue(reverseValue ? currentBase - stepSize : currentBase + stepSize); // if (m_SmoothMovement && !wholeNumbers) // { // m_TargetValue = dest; // m_IsSmoothMoving = true; // } // else // { // Set(dest); // } // } // else // base.OnMove(eventData); // break; // case MoveDirection.Down: // if (axis == Axis.Vertical && FindSelectableOnDown() == null) // { // float dest = ClampValue(reverseValue ? currentBase + stepSize : currentBase - stepSize); // if (m_SmoothMovement && !wholeNumbers) // { // m_TargetValue = dest; // m_IsSmoothMoving = true; // } // else // { // Set(dest); // } // } // else // base.OnMove(eventData); // break; // } // } // // public override UXSelectable FindSelectableOnLeft() // { // if (navigation.mode == UXNavigation.Mode.Automatic && axis == Axis.Horizontal) // return null; // return base.FindSelectableOnLeft(); // } // // public override UXSelectable FindSelectableOnRight() // { // if (navigation.mode == UXNavigation.Mode.Automatic && axis == Axis.Horizontal) // return null; // return base.FindSelectableOnRight(); // } // // public override UXSelectable FindSelectableOnUp() // { // if (navigation.mode == UXNavigation.Mode.Automatic && axis == Axis.Vertical) // return null; // return base.FindSelectableOnUp(); // } // // public override UXSelectable FindSelectableOnDown() // { // if (navigation.mode == UXNavigation.Mode.Automatic && axis == Axis.Vertical) // return null; // return base.FindSelectableOnDown(); // } // // // public void OnInitializePotentialDrag(PointerEventData eventData) // { // eventData.useDragThreshold = false; // } // // public void SetDirection(Direction direction, bool includeRectLayouts) // { // Axis oldAxis = axis; // bool oldReverse = reverseValue; // this.direction = direction; // // if (!includeRectLayouts) // return; // // if (axis != oldAxis) // RectTransformUtility.FlipLayoutAxes(transform as RectTransform, true, true); // // if (reverseValue != oldReverse) // RectTransformUtility.FlipLayoutOnAxis(transform as RectTransform, (int)axis, true, true); // } // // public void Rebuild(CanvasUpdate executing) // { // #if UNITY_EDITOR // if (executing == CanvasUpdate.Prelayout) // onValueChanged.Invoke(value); // #endif // } // // public void LayoutComplete() // { // } // // public void GraphicUpdateComplete() // { // } // } // }