Adding new magnetic scroll control
Includes some fix updates to the Infinite scroll for content of various sizespull/413/head
parent
dbd3bcbaa7
commit
37fa5da1c8
|
@ -1 +1 @@
|
||||||
Subproject commit a8ce2ee705be43c98db82e8307b5b4bf4801387e
|
Subproject commit 9d756f7bd9c2195d34e482c9402b715cf760fc96
|
|
@ -273,6 +273,18 @@ namespace UnityEngine.UI.Extensions
|
||||||
return Input.mousePosition;
|
return Input.mousePosition;
|
||||||
#else
|
#else
|
||||||
return Mouse.current.position.ReadValue();
|
return Mouse.current.position.ReadValue();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 MouseScrollDelta
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||||
|
return Input.mouseScrollDelta;
|
||||||
|
#else
|
||||||
|
return Mouse.current.position.ReadValue();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/// Credit Tomasz Schelenz
|
/// Credit Tomasz Schelenz
|
||||||
/// Sourced from - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/issues/81/infinite-scrollrect
|
/// Sourced from - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/issues/81/infinite-scrollrect
|
||||||
/// Demo - https://www.youtube.com/watch?v=uVTV7Udx78k - configures automatically. - works in both vertical and horizontal (but not both at the same time) - drag and drop - can be initialized by code (in case you populate your scrollview content from code)
|
/// Demo - https://www.youtube.com/watch?v=uVTV7Udx78k - configures automatically. - works in both vertical and horizontal (but not both at the same time) - drag and drop - can be initialized by code (in case you populate your scrollview content from code)
|
||||||
|
/// Updated by Febo Zodiaco - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/349/magnticinfinitescroll
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -11,10 +12,10 @@ namespace UnityEngine.UI.Extensions
|
||||||
///
|
///
|
||||||
/// Fields
|
/// Fields
|
||||||
/// - InitByUSer - in case your scrollrect is populated from code, you can explicitly Initialize the infinite scroll after your scroll is ready
|
/// - InitByUSer - in case your scrollrect is populated from code, you can explicitly Initialize the infinite scroll after your scroll is ready
|
||||||
/// by callin Init() method
|
/// by calling Init() method
|
||||||
///
|
///
|
||||||
/// Notes
|
/// Notes
|
||||||
/// - doesn't work in both vertical and horizontal orientation at the same time.
|
/// - does not work in both vertical and horizontal orientation at the same time.
|
||||||
/// - in order to work it disables layout components and size fitter if present(automatically)
|
/// - in order to work it disables layout components and size fitter if present(automatically)
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -29,12 +30,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
private VerticalLayoutGroup _verticalLayoutGroup;
|
private VerticalLayoutGroup _verticalLayoutGroup;
|
||||||
private HorizontalLayoutGroup _horizontalLayoutGroup;
|
private HorizontalLayoutGroup _horizontalLayoutGroup;
|
||||||
private GridLayoutGroup _gridLayoutGroup;
|
private GridLayoutGroup _gridLayoutGroup;
|
||||||
private bool _isVertical = false;
|
protected bool _isVertical = false;
|
||||||
private bool _isHorizontal = false;
|
protected bool _isHorizontal = false;
|
||||||
private float _disableMarginX = 0;
|
private float _disableMarginX = 0;
|
||||||
private float _disableMarginY = 0;
|
private float _disableMarginY = 0;
|
||||||
private bool _hasDisabledGridComponents = false;
|
private bool _hasDisabledGridComponents = false;
|
||||||
private List<RectTransform> items = new List<RectTransform>();
|
protected List<RectTransform> items = new List<RectTransform>();
|
||||||
private Vector2 _newAnchoredPosition = Vector2.zero;
|
private Vector2 _newAnchoredPosition = Vector2.zero;
|
||||||
//TO DISABLE FLICKERING OBJECT WHEN SCROLL VIEW IS IDLE IN BETWEEN OBJECTS
|
//TO DISABLE FLICKERING OBJECT WHEN SCROLL VIEW IS IDLE IN BETWEEN OBJECTS
|
||||||
private float _treshold = 100f;
|
private float _treshold = 100f;
|
||||||
|
@ -42,12 +43,52 @@ namespace UnityEngine.UI.Extensions
|
||||||
private float _recordOffsetX = 0;
|
private float _recordOffsetX = 0;
|
||||||
private float _recordOffsetY = 0;
|
private float _recordOffsetY = 0;
|
||||||
|
|
||||||
void Awake()
|
protected virtual void Awake()
|
||||||
{
|
{
|
||||||
if (!InitByUser)
|
if (!InitByUser)
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void SetNewItems(ref List<Transform> newItems)
|
||||||
|
{
|
||||||
|
if (_scrollRect != null)
|
||||||
|
{
|
||||||
|
if (_scrollRect.content == null && newItems == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items != null)
|
||||||
|
{
|
||||||
|
items.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = _scrollRect.content.childCount - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Transform child = _scrollRect.content.GetChild(i);
|
||||||
|
child.SetParent(null);
|
||||||
|
GameObject.DestroyImmediate(child.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Transform newItem in newItems)
|
||||||
|
{
|
||||||
|
newItem.SetParent(_scrollRect.content);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetItems()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _scrollRect.content.childCount; i++)
|
||||||
|
{
|
||||||
|
items.Add(_scrollRect.content.GetChild(i).GetComponent<RectTransform>());
|
||||||
|
}
|
||||||
|
|
||||||
|
_itemCount = _scrollRect.content.childCount;
|
||||||
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
if (GetComponent<ScrollRect>() != null)
|
if (GetComponent<ScrollRect>() != null)
|
||||||
|
@ -56,10 +97,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
_scrollRect.onValueChanged.AddListener(OnScroll);
|
_scrollRect.onValueChanged.AddListener(OnScroll);
|
||||||
_scrollRect.movementType = ScrollRect.MovementType.Unrestricted;
|
_scrollRect.movementType = ScrollRect.MovementType.Unrestricted;
|
||||||
|
|
||||||
for (int i = 0; i < _scrollRect.content.childCount; i++)
|
|
||||||
{
|
|
||||||
items.Add(_scrollRect.content.GetChild(i).GetComponent<RectTransform>());
|
|
||||||
}
|
|
||||||
if (_scrollRect.content.GetComponent<VerticalLayoutGroup>() != null)
|
if (_scrollRect.content.GetComponent<VerticalLayoutGroup>() != null)
|
||||||
{
|
{
|
||||||
_verticalLayoutGroup = _scrollRect.content.GetComponent<VerticalLayoutGroup>();
|
_verticalLayoutGroup = _scrollRect.content.GetComponent<VerticalLayoutGroup>();
|
||||||
|
@ -85,7 +122,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
Debug.LogError("UI_InfiniteScroll doesn't support scrolling in both directions, please choose one direction (horizontal or vertical)");
|
Debug.LogError("UI_InfiniteScroll doesn't support scrolling in both directions, please choose one direction (horizontal or vertical)");
|
||||||
}
|
}
|
||||||
|
|
||||||
_itemCount = _scrollRect.content.childCount;
|
SetItems();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -102,7 +139,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
_recordOffsetY *= -1;
|
_recordOffsetY *= -1;
|
||||||
}
|
}
|
||||||
_disableMarginY = _recordOffsetY * _itemCount / 2;// _scrollRect.GetComponent<RectTransform>().rect.height/2 + items[0].sizeDelta.y;
|
_disableMarginY = _recordOffsetY * _itemCount / 2;
|
||||||
}
|
}
|
||||||
if (_isHorizontal)
|
if (_isHorizontal)
|
||||||
{
|
{
|
||||||
|
@ -111,7 +148,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
_recordOffsetX *= -1;
|
_recordOffsetX *= -1;
|
||||||
}
|
}
|
||||||
_disableMarginX = _recordOffsetX * _itemCount / 2;//_scrollRect.GetComponent<RectTransform>().rect.width/2 + items[0].sizeDelta.x;
|
_disableMarginX = _recordOffsetX * _itemCount / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_verticalLayoutGroup)
|
if (_verticalLayoutGroup)
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
/// Credit Febo Zodiaco
|
||||||
|
/// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/349/magnticinfinitescroll
|
||||||
|
///
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
[AddComponentMenu("UI/Extensions/UI Magnetic Infinite Scroll")]
|
||||||
|
public class UI_MagneticInfiniteScroll : UI_InfiniteScroll
|
||||||
|
{
|
||||||
|
public event Action<GameObject> OnNewSelect;
|
||||||
|
|
||||||
|
[Tooltip("The pointer to the pivot, the visual element for centering objects.")]
|
||||||
|
[SerializeField]
|
||||||
|
private RectTransform pivot = null;
|
||||||
|
[Tooltip("The pointer to the object container")]
|
||||||
|
[SerializeField]
|
||||||
|
private RectTransform content = 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 initial index of the object which must be initially centered")]
|
||||||
|
private int indexStart = 0;
|
||||||
|
[SerializeField]
|
||||||
|
[Tooltip("The time to decelerate and aim for the pivot")]
|
||||||
|
private float timeForDeceleration = 0.05f;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private ScrollRect scrollRect = null;
|
||||||
|
|
||||||
|
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 (!content || !pivot || !_useMagnetic || !_isMovement || items == null || scrollRect == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float currentPosition = GetRightAxis(content.anchoredPosition);
|
||||||
|
_currentSpeed = Mathf.Abs(currentPosition - _pastPosition);
|
||||||
|
_pastPosition = currentPosition;
|
||||||
|
if (Mathf.Abs(_currentSpeed) > maxSpeedForMagnetic)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isStopping)
|
||||||
|
{
|
||||||
|
Vector2 anchoredPosition = content.anchoredPosition;
|
||||||
|
_currentTime += Time.deltaTime;
|
||||||
|
float valueLerp = _currentTime / timeForDeceleration;
|
||||||
|
|
||||||
|
float newPosition = Mathf.Lerp(GetRightAxis(anchoredPosition), _stopValue, valueLerp);
|
||||||
|
|
||||||
|
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 void Drag()
|
||||||
|
{
|
||||||
|
float currentPosition = GetRightAxis(UIExtensionsInputManager.MousePosition);
|
||||||
|
|
||||||
|
initMovementDirection = Mathf.Sign(currentPosition - _pastPositionMouseSpeed);
|
||||||
|
_pastPositionMouseSpeed = currentPosition;
|
||||||
|
_useMagnetic = false;
|
||||||
|
_isStopping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndDrag()
|
||||||
|
{
|
||||||
|
FinishPrepareMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 Scroll()
|
||||||
|
{
|
||||||
|
initMovementDirection = -UIExtensionsInputManager.MouseScrollDelta.y;
|
||||||
|
FinishPrepareMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetContentInPivot(int index)
|
||||||
|
{
|
||||||
|
float newPos = GetAnchoredPositionForPivot(index);
|
||||||
|
Vector2 anchoredPosition = content.anchoredPosition;
|
||||||
|
|
||||||
|
if (content)
|
||||||
|
{
|
||||||
|
content.anchoredPosition = _isVertical ? new Vector2(anchoredPosition.x, newPos) :
|
||||||
|
new Vector2(newPos, anchoredPosition.y);
|
||||||
|
_pastPosition = GetRightAxis(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8a2ddc0989b894a499a02fb975aa0322
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue