using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.EventSystems; abstract public class AbstractSlider : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public RectTransform sliderBackground; // Assign in Inspector public float minValue = 0f; public float maxValue = 1f; public float slideareaOffsetMultiplier = 0.9f; public float CurrentValue { get; private set; } public float CurrentNormalizedValue { get; private set; } private RectTransform handleRect; private Vector2 backgroundStart; private float backgroundWidth; public System.Action OnValueChanged; private void OnEnable() { if (null == handleRect) { handleRect = GetComponent(); } if (sliderBackground != null) { backgroundStart = sliderBackground.position; backgroundWidth = sliderBackground.rect.width; } UpdateHandlePosition(); } virtual public void OnBeginDrag(PointerEventData eventData) { UpdateSlider(eventData); } virtual public void OnDrag(PointerEventData eventData) { UpdateSlider(eventData); } virtual public void OnEndDrag(PointerEventData eventData) { UpdateSlider(eventData, true); EventSystem.current.SetSelectedGameObject(null); } virtual public void SetHandleValue(float unnormalizedValue) { SetValuesFromValue(unnormalizedValue); UpdateHandlePosition(); } virtual public void SetHandleNormalizedValue(float normalizedValue) { SetValuesFromNormalizedValue(normalizedValue); UpdateHandlePosition(); } virtual protected void UpdateHandlePosition() { if (null == handleRect) return; // The options menu might not be opened yet float halfWidth = sliderBackground.rect.width * 0.5f; float limit = halfWidth * slideareaOffsetMultiplier; float x = Mathf.Lerp(-limit, limit, CurrentNormalizedValue); handleRect.localPosition = new Vector3(x, handleRect.localPosition.y, 0); } virtual protected void UpdateSlider(PointerEventData eventData, bool draggingEnded = false) { Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(sliderBackground, eventData.position, eventData.pressEventCamera, out localPoint); float halfWidth = sliderBackground.rect.width * 0.5f; // Only allow dragging within 90% of the slider width, centered float limit = halfWidth * slideareaOffsetMultiplier; float clampedX = Mathf.Clamp(localPoint.x, -limit, limit); Vector3 newPosition = new Vector3(clampedX, handleRect.localPosition.y, handleRect.localPosition.z); handleRect.localPosition = newPosition; // Normalize within the limited 90% range float normalized = (clampedX + limit) / (limit * 2f); SetValuesFromValue(Mathf.Lerp(minValue, maxValue, normalized)); OnValueChanged?.Invoke(CurrentValue, draggingEnded); } protected void SetValuesFromNormalizedValue(float normalizedValue) { CurrentNormalizedValue = normalizedValue; CurrentValue = CurrentNormalizedValue * (maxValue - minValue) + minValue; } protected void SetValuesFromValue(float unnormalizedValue) { CurrentValue = unnormalizedValue; CurrentNormalizedValue = (CurrentValue - minValue) / (maxValue - minValue); } }