| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /// Credit Febo Zodiaco
- /// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/349/magnticinfinitescroll
- ///
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine.EventSystems;
- namespace UnityEngine.UI.Extensions
- {
- [AddComponentMenu("UI/Extensions/UI Magnetic Infinite Scroll")]
- [RequireComponent(typeof(ScrollRect))]
- public class UI_MagneticInfiniteScroll : UI_InfiniteScroll, IDragHandler, IEndDragHandler, IScrollHandler
- {
- public event Action<GameObject> OnNewSelect;
- [Tooltip("The pointer to the pivot, the visual element for centering objects.")]
- [SerializeField]
- private RectTransform pivot = null;
- [Tooltip("The maximum speed that allows you to activate the magnet to center on the pivot")]
- [SerializeField]
- private float maxSpeedForMagnetic = 10f;
- [SerializeField]
- [Tooltip("The index of the object which must be initially centered")]
- private int indexStart = 0;
- [SerializeField]
- [Tooltip("The time to decelerate and aim to the pivot")]
- private float timeForDeceleration = 0.05f;
- private float _pastPositionMouseSpeed;
- private float _initMovementDirection = 0;
- private float _pastPosition = 0;
- private float _currentSpeed = 0.0f;
- private float _stopValue = 0.0f;
- private readonly float _waitForContentSet = 0.1f;
- private float _currentTime = 0;
- private int _nearestIndex = 0;
- private bool _useMagnetic = true;
- private bool _isStopping = false;
- private bool _isMovement = false;
- public List<RectTransform> Items { get; }
- protected override void Awake()
- {
- base.Awake();
- StartCoroutine(SetInitContent());
- }
- private void Update()
- {
- if (_scrollRect == null || !_scrollRect.content || !pivot || !_useMagnetic || !_isMovement || items == null)
- {
- return;
- }
- float currentPosition = GetRightAxis(_scrollRect.content.anchoredPosition);
- _currentSpeed = Mathf.Abs(currentPosition - _pastPosition);
- _pastPosition = currentPosition;
- if (Mathf.Abs(_currentSpeed) > maxSpeedForMagnetic)
- {
- return;
- }
- if (_isStopping)
- {
- Vector2 anchoredPosition = _scrollRect.content.anchoredPosition;
- _currentTime += Time.deltaTime;
- float valueLerp = _currentTime / timeForDeceleration;
- float newPosition = Mathf.Lerp(GetRightAxis(anchoredPosition), _stopValue, valueLerp);
- _scrollRect.content.anchoredPosition = _isVertical ? new Vector2(anchoredPosition.x, newPosition) :
- new Vector2(newPosition, anchoredPosition.y);
- if (newPosition == GetRightAxis(anchoredPosition) && _nearestIndex > 0 && _nearestIndex < items.Count)
- {
- _isStopping = false;
- _isMovement = false;
- var item = items[_nearestIndex];
- if (item != null && OnNewSelect != null)
- {
- OnNewSelect.Invoke(item.gameObject);
- }
- }
- }
- else
- {
- float distance = Mathf.Infinity * (-_initMovementDirection);
- for (int i = 0; i < items.Count; i++)
- {
- var item = items[i];
- if (item == null)
- {
- continue;
- }
- var aux = GetRightAxis(item.position) - GetRightAxis(pivot.position);
- if ((_initMovementDirection <= 0 && aux < distance && aux > 0) ||
- (_initMovementDirection > 0 && aux > distance && aux < 0))
- {
- distance = aux;
- _nearestIndex = i;
- }
- }
- _isStopping = true;
- _stopValue = GetAnchoredPositionForPivot(_nearestIndex);
- _scrollRect.StopMovement();
- }
- }
- public override void SetNewItems(ref List<Transform> newItems)
- {
- foreach (var element in newItems)
- {
- RectTransform rectTransform = element.GetComponent<RectTransform>();
- if (rectTransform && pivot)
- {
- rectTransform.sizeDelta = pivot.sizeDelta;
- }
- }
- base.SetNewItems(ref newItems);
- }
- public void SetContentInPivot(int index)
- {
- float newPos = GetAnchoredPositionForPivot(index);
- Vector2 anchoredPosition = _scrollRect.content.anchoredPosition;
- if (_scrollRect.content)
- {
- _scrollRect.content.anchoredPosition = _isVertical ? new Vector2(anchoredPosition.x, newPos) :
- new Vector2(newPos, anchoredPosition.y);
- _pastPosition = GetRightAxis(_scrollRect.content.anchoredPosition);
- }
- }
- private IEnumerator SetInitContent()
- {
- yield return new WaitForSeconds(_waitForContentSet);
- SetContentInPivot(indexStart);
- }
- private float GetAnchoredPositionForPivot(int index)
- {
- if (!pivot || items == null || items.Count < 0)
- {
- return 0f;
- }
- index = Mathf.Clamp(index, 0, items.Count - 1);
- float posItem = GetRightAxis(items[index].anchoredPosition);
- float posPivot = GetRightAxis(pivot.anchoredPosition);
- return posPivot - posItem;
- }
- private void FinishPrepareMovement()
- {
- _isMovement = true;
- _useMagnetic = true;
- _isStopping = false;
- _currentTime = 0;
- }
- private float GetRightAxis(Vector2 vector)
- {
- return _isVertical ? vector.y : vector.x;
- }
- public void OnDrag(PointerEventData eventData)
- {
- float currentPosition = GetRightAxis(UIExtensionsInputManager.MousePosition);
- _initMovementDirection = Mathf.Sign(currentPosition - _pastPositionMouseSpeed);
- _pastPositionMouseSpeed = currentPosition;
- _useMagnetic = false;
- _isStopping = false;
- }
- public void OnEndDrag(PointerEventData eventData)
- {
- FinishPrepareMovement();
- }
- public void OnScroll(PointerEventData eventData)
- {
- _initMovementDirection = -UIExtensionsInputManager.MouseScrollDelta.y;
- FinishPrepareMovement();
- }
- }
- }
|