using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; namespace UIWidgets { public abstract class RangeSliderBase : MonoBehaviour, IPointerClickHandler, IEventSystemHandler where T : struct { [Serializable] public class OnChangeEvent : UnityEvent { } [SerializeField] protected T valueMin; [SerializeField] protected T valueMax; [SerializeField] protected T step; [SerializeField] protected T limitMin; [SerializeField] protected T limitMax; [SerializeField] protected RangeSliderHandle handleMin; protected RectTransform handleMinRect; [SerializeField] protected RangeSliderHandle handleMax; protected RectTransform handleMaxRect; [SerializeField] protected RectTransform UsableRangeRect; [SerializeField] protected RectTransform FillRect; protected RectTransform rangeSliderRect; public OnChangeEvent OnValuesChange = new OnChangeEvent(); public UnityEvent OnChange = new UnityEvent(); public bool WholeNumberOfSteps; private bool initCalled; public T ValueMin { get { return valueMin; } set { if (!EqualityComparer.Default.Equals(valueMin, InBoundsMin(value))) { valueMin = InBoundsMin(value); UpdateMinHandle(); UpdateFill(); OnValuesChange.Invoke(valueMin, valueMax); OnChange.Invoke(); } } } public T ValueMax { get { return valueMax; } set { if (!EqualityComparer.Default.Equals(valueMax, InBoundsMax(value))) { valueMax = InBoundsMax(value); UpdateMaxHandle(); UpdateFill(); OnValuesChange.Invoke(valueMin, valueMax); OnChange.Invoke(); } } } public T Step { get { return step; } set { step = value; } } public T LimitMin { get { return limitMin; } set { limitMin = value; ValueMin = valueMin; ValueMax = valueMax; } } public T LimitMax { get { return limitMax; } set { limitMax = value; ValueMin = valueMin; ValueMax = valueMax; } } public RectTransform HandleMinRect { get { if (handleMin != null && handleMinRect == null) { handleMinRect = handleMin.transform as RectTransform; } return handleMinRect; } } public RangeSliderHandle HandleMin { get { return handleMin; } set { handleMin = value; handleMinRect = null; handleMin.IsHorizontal = IsHorizontal; handleMin.PositionLimits = MinPositionLimits; handleMin.PositionChanged = UpdateMinValue; handleMin.OnSubmit = SelectMaxHandle; handleMin.Increase = IncreaseMin; handleMin.Decrease = DecreaseMin; HandleMinRect.anchorMin = new Vector2(0f, 0f); HandleMinRect.anchorMax = ((!IsHorizontal()) ? new Vector2(1f, 0f) : new Vector2(0f, 1f)); } } public RectTransform HandleMaxRect { get { if (handleMax != null && handleMaxRect == null) { handleMaxRect = handleMax.transform as RectTransform; } return handleMaxRect; } } public RangeSliderHandle HandleMax { get { return handleMax; } set { handleMax = value; handleMaxRect = null; handleMax.IsHorizontal = IsHorizontal; handleMax.PositionLimits = MaxPositionLimits; handleMax.PositionChanged = UpdateMaxValue; handleMax.OnSubmit = SelectMinHandle; handleMax.Increase = IncreaseMax; handleMax.Decrease = DecreaseMax; HandleMaxRect.anchorMin = new Vector2(0f, 0f); HandleMaxRect.anchorMax = ((!IsHorizontal()) ? new Vector2(1f, 0f) : new Vector2(0f, 1f)); } } public RectTransform RangeSliderRect { get { if (rangeSliderRect == null) { rangeSliderRect = base.transform as RectTransform; } return rangeSliderRect; } } private void Awake() { } private void Init() { if (!initCalled) { initCalled = true; HandleMin = handleMin; HandleMax = handleMax; UpdateMinHandle(); UpdateMaxHandle(); UpdateFill(); } } private void Start() { Init(); } public void SetValue(T min, T max) { T x = valueMin; T x2 = valueMax; valueMin = min; valueMax = max; valueMin = InBoundsMin(valueMin); valueMax = InBoundsMax(valueMax); bool flag = EqualityComparer.Default.Equals(x, valueMin); bool flag2 = EqualityComparer.Default.Equals(x2, valueMax); if (!flag || !flag2) { UpdateMinHandle(); UpdateMaxHandle(); UpdateFill(); OnValuesChange.Invoke(valueMin, valueMax); OnChange.Invoke(); } } public void SetLimit(T min, T max) { T x = valueMin; T x2 = valueMax; limitMin = min; limitMax = max; valueMin = InBoundsMin(valueMin); valueMax = InBoundsMax(valueMax); bool flag = EqualityComparer.Default.Equals(x, valueMin); bool flag2 = EqualityComparer.Default.Equals(x2, valueMax); if (!flag || !flag2) { UpdateMinHandle(); UpdateMaxHandle(); UpdateFill(); OnValuesChange.Invoke(valueMin, valueMax); OnChange.Invoke(); } } protected virtual bool IsHorizontal() { return true; } protected float FillSize() { return (!IsHorizontal()) ? UsableRangeRect.rect.height : UsableRangeRect.rect.width; } protected float MinHandleSize() { if (IsHorizontal()) { return HandleMinRect.rect.width; } return HandleMinRect.rect.height; } protected float MaxHandleSize() { if (IsHorizontal()) { return HandleMaxRect.rect.width; } return HandleMaxRect.rect.height; } protected void UpdateMinValue(float position) { valueMin = PositionToValue(position - GetStartPoint()); UpdateMinHandle(); UpdateFill(); OnValuesChange.Invoke(valueMin, valueMax); OnChange.Invoke(); } protected void UpdateMaxValue(float position) { valueMax = PositionToValue(position - GetStartPoint()); UpdateMaxHandle(); UpdateFill(); OnValuesChange.Invoke(valueMin, valueMax); OnChange.Invoke(); } protected abstract float ValueToPosition(T value); protected abstract T PositionToValue(float position); protected float GetStartPoint() { return (!IsHorizontal()) ? ((0f - UsableRangeRect.sizeDelta.y) / 2f) : ((0f - UsableRangeRect.sizeDelta.x) / 2f); } protected abstract Vector2 MinPositionLimits(); protected abstract Vector2 MaxPositionLimits(); protected abstract T InBounds(T value); protected abstract T InBoundsMin(T value); protected abstract T InBoundsMax(T value); protected abstract void IncreaseMin(); protected abstract void DecreaseMin(); protected abstract void IncreaseMax(); protected abstract void DecreaseMax(); protected void UpdateMinHandle() { UpdateHandle(HandleMinRect, valueMin); } protected void UpdateMaxHandle() { UpdateHandle(HandleMaxRect, valueMax); } private void UpdateFill() { if (IsHorizontal()) { FillRect.anchoredPosition = new Vector2(HandleMinRect.anchoredPosition.x, FillRect.anchoredPosition.y); Vector2 sizeDelta = new Vector2(HandleMaxRect.anchoredPosition.x - HandleMinRect.anchoredPosition.x, FillRect.sizeDelta.y); FillRect.sizeDelta = sizeDelta; } else { FillRect.anchoredPosition = new Vector2(FillRect.anchoredPosition.x, HandleMinRect.anchoredPosition.y); Vector2 sizeDelta2 = new Vector2(FillRect.sizeDelta.x, HandleMaxRect.anchoredPosition.y - HandleMinRect.anchoredPosition.y); FillRect.sizeDelta = sizeDelta2; } } protected void UpdateHandle(RectTransform handleTransform, T value) { Vector2 anchoredPosition = handleTransform.anchoredPosition; if (IsHorizontal()) { anchoredPosition.x = ValueToPosition(value) + handleTransform.rect.width * (handleTransform.pivot.x - 0.5f); } else { anchoredPosition.y = ValueToPosition(value) + handleTransform.rect.height * (handleTransform.pivot.y - 0.5f); } handleTransform.anchoredPosition = anchoredPosition; } private void SelectMinHandle() { if (EventSystem.current != null && !EventSystem.current.alreadySelecting) { EventSystem.current.SetSelectedGameObject(handleMin.gameObject); } } private void SelectMaxHandle() { if (EventSystem.current != null && !EventSystem.current.alreadySelecting) { EventSystem.current.SetSelectedGameObject(handleMax.gameObject); } } public void OnPointerClick(PointerEventData eventData) { Vector2 localPoint; if (RectTransformUtility.ScreenPointToLocalPointInRectangle(UsableRangeRect, eventData.position, eventData.pressEventCamera, out localPoint)) { localPoint -= UsableRangeRect.rect.position; float num = ((!IsHorizontal()) ? localPoint.y : localPoint.x) + GetStartPoint(); float num2 = num - MaxHandleSize(); float num3 = ((!IsHorizontal()) ? HandleMinRect.anchoredPosition.y : HandleMinRect.anchoredPosition.x); float num4 = ((!IsHorizontal()) ? HandleMaxRect.anchoredPosition.y : HandleMaxRect.anchoredPosition.x); float num5 = num - num3; float num6 = num4 - num2; if (num5 < num6) { UpdateMinValue(num); } else { UpdateMaxValue(num2); } } } } }