Updated FancyScrollView to latest
parent
88b4a54603
commit
41e082802a
|
@ -13,7 +13,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
public class ScrollerEditor : Editor
|
public class ScrollerEditor : Editor
|
||||||
{
|
{
|
||||||
SerializedProperty viewport;
|
SerializedProperty viewport;
|
||||||
SerializedProperty directionOfRecognize;
|
SerializedProperty scrollDirection;
|
||||||
SerializedProperty movementType;
|
SerializedProperty movementType;
|
||||||
SerializedProperty elasticity;
|
SerializedProperty elasticity;
|
||||||
SerializedProperty scrollSensitivity;
|
SerializedProperty scrollSensitivity;
|
||||||
|
@ -24,6 +24,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
SerializedProperty snapVelocityThreshold;
|
SerializedProperty snapVelocityThreshold;
|
||||||
SerializedProperty snapDuration;
|
SerializedProperty snapDuration;
|
||||||
SerializedProperty snapEasing;
|
SerializedProperty snapEasing;
|
||||||
|
SerializedProperty draggable;
|
||||||
|
SerializedProperty scrollbar;
|
||||||
|
|
||||||
AnimBool showElasticity;
|
AnimBool showElasticity;
|
||||||
AnimBool showInertiaRelatedValues;
|
AnimBool showInertiaRelatedValues;
|
||||||
|
@ -32,7 +34,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
void OnEnable()
|
void OnEnable()
|
||||||
{
|
{
|
||||||
viewport = serializedObject.FindProperty("viewport");
|
viewport = serializedObject.FindProperty("viewport");
|
||||||
directionOfRecognize = serializedObject.FindProperty("directionOfRecognize");
|
scrollDirection = serializedObject.FindProperty("scrollDirection");
|
||||||
movementType = serializedObject.FindProperty("movementType");
|
movementType = serializedObject.FindProperty("movementType");
|
||||||
elasticity = serializedObject.FindProperty("elasticity");
|
elasticity = serializedObject.FindProperty("elasticity");
|
||||||
scrollSensitivity = serializedObject.FindProperty("scrollSensitivity");
|
scrollSensitivity = serializedObject.FindProperty("scrollSensitivity");
|
||||||
|
@ -43,6 +45,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
snapVelocityThreshold = serializedObject.FindProperty("snap.VelocityThreshold");
|
snapVelocityThreshold = serializedObject.FindProperty("snap.VelocityThreshold");
|
||||||
snapDuration = serializedObject.FindProperty("snap.Duration");
|
snapDuration = serializedObject.FindProperty("snap.Duration");
|
||||||
snapEasing = serializedObject.FindProperty("snap.Easing");
|
snapEasing = serializedObject.FindProperty("snap.Easing");
|
||||||
|
draggable = serializedObject.FindProperty("draggable");
|
||||||
|
scrollbar = serializedObject.FindProperty("scrollbar");
|
||||||
|
|
||||||
showElasticity = new AnimBool(Repaint);
|
showElasticity = new AnimBool(Repaint);
|
||||||
showInertiaRelatedValues = new AnimBool(Repaint);
|
showInertiaRelatedValues = new AnimBool(Repaint);
|
||||||
|
@ -59,7 +63,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
void SetAnimBools(bool instant)
|
void SetAnimBools(bool instant)
|
||||||
{
|
{
|
||||||
SetAnimBool(showElasticity, !movementType.hasMultipleDifferentValues && movementType.enumValueIndex == (int)Scroller.MovementType.Elastic, instant);
|
SetAnimBool(showElasticity, !movementType.hasMultipleDifferentValues && movementType.enumValueIndex == (int)MovementType.Elastic, instant);
|
||||||
SetAnimBool(showInertiaRelatedValues, !inertia.hasMultipleDifferentValues && inertia.boolValue, instant);
|
SetAnimBool(showInertiaRelatedValues, !inertia.hasMultipleDifferentValues && inertia.boolValue, instant);
|
||||||
SetAnimBool(showSnapEnableRelatedValues, !snapEnable.hasMultipleDifferentValues && snapEnable.boolValue, instant);
|
SetAnimBool(showSnapEnableRelatedValues, !snapEnable.hasMultipleDifferentValues && snapEnable.boolValue, instant);
|
||||||
}
|
}
|
||||||
|
@ -82,12 +86,14 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
EditorGUILayout.PropertyField(viewport);
|
EditorGUILayout.PropertyField(viewport);
|
||||||
EditorGUILayout.PropertyField(directionOfRecognize);
|
EditorGUILayout.PropertyField(scrollDirection);
|
||||||
EditorGUILayout.PropertyField(movementType);
|
EditorGUILayout.PropertyField(movementType);
|
||||||
DrawMovementTypeRelatedValue();
|
DrawMovementTypeRelatedValue();
|
||||||
EditorGUILayout.PropertyField(scrollSensitivity);
|
EditorGUILayout.PropertyField(scrollSensitivity);
|
||||||
EditorGUILayout.PropertyField(inertia);
|
EditorGUILayout.PropertyField(inertia);
|
||||||
DrawInertiaRelatedValues();
|
DrawInertiaRelatedValues();
|
||||||
|
EditorGUILayout.PropertyField(draggable);
|
||||||
|
EditorGUILayout.PropertyField(scrollbar);
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6096cd9225d267f4da3b54947c75809c
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -1,15 +1,13 @@
|
||||||
/// Credit setchi (https://github.com/setchi)
|
/// Credit setchi (https://github.com/setchi)
|
||||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
public abstract class FancyScrollView<TItemData, TContext> : MonoBehaviour where TContext : class, new()
|
public abstract class FancyScrollView<TItemData, TContext> : MonoBehaviour where TContext : class, new()
|
||||||
{
|
{
|
||||||
[SerializeField, Range(float.Epsilon, 1f)] protected float cellInterval = 0.2f;
|
[SerializeField, Range(1e-2f, 1f)] protected float cellInterval = 0.2f;
|
||||||
[SerializeField, Range(0f, 1f)] protected float scrollOffset = 0.5f;
|
[SerializeField, Range(0f, 1f)] protected float scrollOffset = 0.5f;
|
||||||
[SerializeField] protected bool loop = false;
|
[SerializeField] protected bool loop = false;
|
||||||
[SerializeField] protected Transform cellContainer = default;
|
[SerializeField] protected Transform cellContainer = default;
|
||||||
|
@ -17,7 +15,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
readonly IList<FancyScrollViewCell<TItemData, TContext>> pool =
|
readonly IList<FancyScrollViewCell<TItemData, TContext>> pool =
|
||||||
new List<FancyScrollViewCell<TItemData, TContext>>();
|
new List<FancyScrollViewCell<TItemData, TContext>>();
|
||||||
|
|
||||||
float currentPosition;
|
protected float currentPosition;
|
||||||
|
|
||||||
protected abstract GameObject CellPrefab { get; }
|
protected abstract GameObject CellPrefab { get; }
|
||||||
protected IList<TItemData> ItemsSource { get; set; } = new List<TItemData>();
|
protected IList<TItemData> ItemsSource { get; set; } = new List<TItemData>();
|
||||||
|
@ -27,7 +25,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// Updates the contents.
|
/// Updates the contents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="itemsSource">Items source.</param>
|
/// <param name="itemsSource">Items source.</param>
|
||||||
protected void UpdateContents(IList<TItemData> itemsSource)
|
protected virtual void UpdateContents(IList<TItemData> itemsSource)
|
||||||
{
|
{
|
||||||
ItemsSource = itemsSource;
|
ItemsSource = itemsSource;
|
||||||
Refresh();
|
Refresh();
|
||||||
|
@ -36,15 +34,15 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refreshes the cells.
|
/// Refreshes the cells.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected void Refresh() => UpdatePosition(currentPosition, true);
|
protected virtual void Refresh() => UpdatePosition(currentPosition, true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the scroll position.
|
/// Updates the scroll position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="position">Position.</param>
|
/// <param name="position">Position.</param>
|
||||||
protected void UpdatePosition(float position) => UpdatePosition(position, false);
|
protected virtual void UpdatePosition(float position) => UpdatePosition(position, false);
|
||||||
|
|
||||||
void UpdatePosition(float position, bool forceRefresh)
|
protected void UpdatePosition(float position, bool forceRefresh)
|
||||||
{
|
{
|
||||||
currentPosition = position;
|
currentPosition = position;
|
||||||
|
|
||||||
|
@ -62,15 +60,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
void ResizePool(float firstPosition)
|
void ResizePool(float firstPosition)
|
||||||
{
|
{
|
||||||
if (CellPrefab == null)
|
Debug.Assert(CellPrefab != null);
|
||||||
{
|
Debug.Assert(cellContainer != null);
|
||||||
throw new NullReferenceException(nameof(CellPrefab));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cellContainer == null)
|
|
||||||
{
|
|
||||||
throw new MissingComponentException(nameof(cellContainer));
|
|
||||||
}
|
|
||||||
|
|
||||||
var addCount = Mathf.CeilToInt((1f - firstPosition) / cellInterval) - pool.Count;
|
var addCount = Mathf.CeilToInt((1f - firstPosition) / cellInterval) - pool.Count;
|
||||||
for (var i = 0; i < addCount; i++)
|
for (var i = 0; i < addCount; i++)
|
||||||
|
@ -139,11 +130,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class FancyScrollViewNullContext
|
public sealed class FancyScrollViewNullContext { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class FancyScrollView<TItemData> : FancyScrollView<TItemData, FancyScrollViewNullContext>
|
public abstract class FancyScrollView<TItemData> : FancyScrollView<TItemData, FancyScrollViewNullContext> { }
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
/// Credit setchi (https://github.com/setchi)
|
/// Credit setchi (https://github.com/setchi)
|
||||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
public abstract class FancyScrollViewCell<TItemData, TContext> : MonoBehaviour where TContext : class, new()
|
public abstract class FancyScrollViewCell<TItemData, TContext> : MonoBehaviour where TContext : class, new()
|
|
@ -1,214 +0,0 @@
|
||||||
//
|
|
||||||
// EasingCore - https://github.com/setchi/EasingCore
|
|
||||||
//
|
|
||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2019 setchi
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions.EasingCore
|
|
||||||
{
|
|
||||||
public enum Ease
|
|
||||||
{
|
|
||||||
Linear,
|
|
||||||
InBack,
|
|
||||||
InBounce,
|
|
||||||
InCirc,
|
|
||||||
InCubic,
|
|
||||||
InElastic,
|
|
||||||
InExpo,
|
|
||||||
InQuad,
|
|
||||||
InQuart,
|
|
||||||
InQuint,
|
|
||||||
InSine,
|
|
||||||
OutBack,
|
|
||||||
OutBounce,
|
|
||||||
OutCirc,
|
|
||||||
OutCubic,
|
|
||||||
OutElastic,
|
|
||||||
OutExpo,
|
|
||||||
OutQuad,
|
|
||||||
OutQuart,
|
|
||||||
OutQuint,
|
|
||||||
OutSine,
|
|
||||||
InOutBack,
|
|
||||||
InOutBounce,
|
|
||||||
InOutCirc,
|
|
||||||
InOutCubic,
|
|
||||||
InOutElastic,
|
|
||||||
InOutExpo,
|
|
||||||
InOutQuad,
|
|
||||||
InOutQuart,
|
|
||||||
InOutQuint,
|
|
||||||
InOutSine,
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class EasingFunction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the easing function
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">ease type</param>
|
|
||||||
/// <returns>easing function</returns>
|
|
||||||
public static Func<float, float> Get(Ease type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case Ease.Linear: return Linear;
|
|
||||||
case Ease.InBack: return InBack;
|
|
||||||
case Ease.InBounce: return InBounce;
|
|
||||||
case Ease.InCirc: return InCirc;
|
|
||||||
case Ease.InCubic: return InCubic;
|
|
||||||
case Ease.InElastic: return InElastic;
|
|
||||||
case Ease.InExpo: return InExpo;
|
|
||||||
case Ease.InQuad: return InQuad;
|
|
||||||
case Ease.InQuart: return InQuart;
|
|
||||||
case Ease.InQuint: return InQuint;
|
|
||||||
case Ease.InSine: return InSine;
|
|
||||||
case Ease.OutBack: return OutBack;
|
|
||||||
case Ease.OutBounce: return OutBounce;
|
|
||||||
case Ease.OutCirc: return OutCirc;
|
|
||||||
case Ease.OutCubic: return OutCubic;
|
|
||||||
case Ease.OutElastic: return OutElastic;
|
|
||||||
case Ease.OutExpo: return OutExpo;
|
|
||||||
case Ease.OutQuad: return OutQuad;
|
|
||||||
case Ease.OutQuart: return OutQuart;
|
|
||||||
case Ease.OutQuint: return OutQuint;
|
|
||||||
case Ease.OutSine: return OutSine;
|
|
||||||
case Ease.InOutBack: return InOutBack;
|
|
||||||
case Ease.InOutBounce: return InOutBounce;
|
|
||||||
case Ease.InOutCirc: return InOutCirc;
|
|
||||||
case Ease.InOutCubic: return InOutCubic;
|
|
||||||
case Ease.InOutElastic: return InOutElastic;
|
|
||||||
case Ease.InOutExpo: return InOutExpo;
|
|
||||||
case Ease.InOutQuad: return InOutQuad;
|
|
||||||
case Ease.InOutQuart: return InOutQuart;
|
|
||||||
case Ease.InOutQuint: return InOutQuint;
|
|
||||||
case Ease.InOutSine: return InOutSine;
|
|
||||||
default: return Linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static float Linear(float t) => t;
|
|
||||||
|
|
||||||
static float InBack(float t) => t * t * t - t * Mathf.Sin(t * Mathf.PI);
|
|
||||||
|
|
||||||
static float OutBack(float t) => 1f - InBack(1f - t);
|
|
||||||
|
|
||||||
static float InOutBack(float t) =>
|
|
||||||
t < 0.5f
|
|
||||||
? 0.5f * InBack(2f * t)
|
|
||||||
: 0.5f * OutBack(2f * t - 1f) + 0.5f;
|
|
||||||
|
|
||||||
static float InBounce(float t) => 1f - OutBounce(1f - t);
|
|
||||||
|
|
||||||
static float OutBounce(float t) =>
|
|
||||||
t < 4f / 11.0f ?
|
|
||||||
(121f * t * t) / 16.0f :
|
|
||||||
t < 8f / 11.0f ?
|
|
||||||
(363f / 40.0f * t * t) - (99f / 10.0f * t) + 17f / 5.0f :
|
|
||||||
t < 9f / 10.0f ?
|
|
||||||
(4356f / 361.0f * t * t) - (35442f / 1805.0f * t) + 16061f / 1805.0f :
|
|
||||||
(54f / 5.0f * t * t) - (513f / 25.0f * t) + 268f / 25.0f;
|
|
||||||
|
|
||||||
static float InOutBounce(float t) =>
|
|
||||||
t < 0.5f
|
|
||||||
? 0.5f * InBounce(2f * t)
|
|
||||||
: 0.5f * OutBounce(2f * t - 1f) + 0.5f;
|
|
||||||
|
|
||||||
static float InCirc(float t) => 1f - Mathf.Sqrt(1f - (t * t));
|
|
||||||
|
|
||||||
static float OutCirc(float t) => Mathf.Sqrt((2f - t) * t);
|
|
||||||
|
|
||||||
static float InOutCirc(float t) =>
|
|
||||||
t < 0.5f
|
|
||||||
? 0.5f * (1 - Mathf.Sqrt(1f - 4f * (t * t)))
|
|
||||||
: 0.5f * (Mathf.Sqrt(-((2f * t) - 3f) * ((2f * t) - 1f)) + 1f);
|
|
||||||
|
|
||||||
static float InCubic(float t) => t * t * t;
|
|
||||||
|
|
||||||
static float OutCubic(float t) => InCubic(t - 1f) + 1f;
|
|
||||||
|
|
||||||
static float InOutCubic(float t) =>
|
|
||||||
t < 0.5f
|
|
||||||
? 4f * t * t * t
|
|
||||||
: 0.5f * InCubic(2f * t - 2f) + 1f;
|
|
||||||
|
|
||||||
static float InElastic(float t) => Mathf.Sin(13f * (Mathf.PI * 0.5f) * t) * Mathf.Pow(2f, 10f * (t - 1f));
|
|
||||||
|
|
||||||
static float OutElastic(float t) => Mathf.Sin(-13f * (Mathf.PI * 0.5f) * (t + 1)) * Mathf.Pow(2f, -10f * t) + 1f;
|
|
||||||
|
|
||||||
static float InOutElastic(float t) =>
|
|
||||||
t < 0.5f
|
|
||||||
? 0.5f * Mathf.Sin(13f * (Mathf.PI * 0.5f) * (2f * t)) * Mathf.Pow(2f, 10f * ((2f * t) - 1f))
|
|
||||||
: 0.5f * (Mathf.Sin(-13f * (Mathf.PI * 0.5f) * ((2f * t - 1f) + 1f)) * Mathf.Pow(2f, -10f * (2f * t - 1f)) + 2f);
|
|
||||||
|
|
||||||
static float InExpo(float t) => Mathf.Approximately(0.0f, t) ? t : Mathf.Pow(2f, 10f * (t - 1f));
|
|
||||||
|
|
||||||
static float OutExpo(float t) => Mathf.Approximately(1.0f, t) ? t : 1f - Mathf.Pow(2f, -10f * t);
|
|
||||||
|
|
||||||
static float InOutExpo(float v) =>
|
|
||||||
Mathf.Approximately(0.0f, v) || Mathf.Approximately(1.0f, v)
|
|
||||||
? v
|
|
||||||
: v < 0.5f
|
|
||||||
? 0.5f * Mathf.Pow(2f, (20f * v) - 10f)
|
|
||||||
: -0.5f * Mathf.Pow(2f, (-20f * v) + 10f) + 1f;
|
|
||||||
|
|
||||||
static float InQuad(float t) => t * t;
|
|
||||||
|
|
||||||
static float OutQuad(float t) => -t * (t - 2f);
|
|
||||||
|
|
||||||
static float InOutQuad(float t) =>
|
|
||||||
t < 0.5f
|
|
||||||
? 2f * t * t
|
|
||||||
: -2f * t * t + 4f * t - 1f;
|
|
||||||
|
|
||||||
static float InQuart(float t) => t * t * t * t;
|
|
||||||
|
|
||||||
static float OutQuart(float t)
|
|
||||||
{
|
|
||||||
var u = t - 1f;
|
|
||||||
return u * u * u * (1f - t) + 1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float InOutQuart(float t) =>
|
|
||||||
t < 0.5f
|
|
||||||
? 8f * InQuart(t)
|
|
||||||
: -8f * InQuart(t - 1f) + 1f;
|
|
||||||
|
|
||||||
static float InQuint(float t) => t * t * t * t * t;
|
|
||||||
|
|
||||||
static float OutQuint(float t) => InQuint(t - 1f) + 1f;
|
|
||||||
|
|
||||||
static float InOutQuint(float t) =>
|
|
||||||
t < 0.5f
|
|
||||||
? 16f * InQuint(t)
|
|
||||||
: 0.5f * InQuint(2f * t - 2f) + 1f;
|
|
||||||
|
|
||||||
static float InSine(float t) => Mathf.Sin((t - 1f) * (Mathf.PI * 0.5f)) + 1f;
|
|
||||||
|
|
||||||
static float OutSine(float t) => Mathf.Sin(t * (Mathf.PI * 0.5f));
|
|
||||||
|
|
||||||
static float InOutSine(float t) => 0.5f * (1f - Mathf.Cos(t * Mathf.PI));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e2c5beedd885c4490a86bb4973f965bf
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
||||||
|
/// Credit setchi (https://github.com/setchi)
|
||||||
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
public enum Alignment
|
||||||
|
{
|
||||||
|
Head,
|
||||||
|
Center,
|
||||||
|
Tail,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 006f67d6afad7c2479f7188b033aea31
|
guid: 3e786463ba934403cacf7e8c0d5822d7
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -0,0 +1,191 @@
|
||||||
|
/// Credit setchi (https://github.com/setchi)
|
||||||
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine.UI.Extensions.EasingCore;
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
[RequireComponent(typeof(Scroller))]
|
||||||
|
public abstract class FancyScrollRect<TItemData, TContext> : FancyScrollView<TItemData, TContext>
|
||||||
|
where TContext : class, IFancyScrollRectContext, new()
|
||||||
|
{
|
||||||
|
[SerializeField] protected float reuseCellMarginCount = 0f;
|
||||||
|
[SerializeField] protected float paddingHead = 0f;
|
||||||
|
[SerializeField] protected float paddingTail = 0f;
|
||||||
|
[SerializeField] protected float spacing = 0f;
|
||||||
|
|
||||||
|
protected virtual float ScrollLength => 1f / Mathf.Max(cellInterval, 1e-2f) - 1f;
|
||||||
|
|
||||||
|
protected virtual float ViewportLength => ScrollLength - reuseCellMarginCount * 2f;
|
||||||
|
|
||||||
|
protected virtual float MaxScrollPosition => ItemsSource.Count
|
||||||
|
- ScrollLength
|
||||||
|
+ reuseCellMarginCount * 2f
|
||||||
|
+ (paddingHead + (paddingTail - spacing)) / (CellSize + spacing);
|
||||||
|
|
||||||
|
protected virtual bool ScrollEnabled => MaxScrollPosition > 0f;
|
||||||
|
|
||||||
|
protected virtual float CellSize => Scroller.ScrollDirection == ScrollDirection.Horizontal
|
||||||
|
? CellRectTransform.rect.width
|
||||||
|
: CellRectTransform.rect.height;
|
||||||
|
|
||||||
|
Scroller cachedScroller;
|
||||||
|
protected Scroller Scroller => cachedScroller ?? (cachedScroller = GetComponent<Scroller>());
|
||||||
|
|
||||||
|
RectTransform cachedCellRect;
|
||||||
|
RectTransform CellRectTransform => cachedCellRect ?? (cachedCellRect = CellPrefab.transform as RectTransform);
|
||||||
|
|
||||||
|
protected virtual void Awake()
|
||||||
|
{
|
||||||
|
Context.CalculateScrollSize = () =>
|
||||||
|
{
|
||||||
|
var interval = CellSize + spacing;
|
||||||
|
var reuseMargin = interval * reuseCellMarginCount;
|
||||||
|
var scrollSize = Scroller.ViewportSize + interval + reuseMargin * 2f;
|
||||||
|
return (scrollSize, reuseMargin);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Start()
|
||||||
|
{
|
||||||
|
AdjustCellIntervalAndScrollOffset();
|
||||||
|
Scroller.OnValueChanged(OnScrollerValueChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnScrollerValueChanged(float p)
|
||||||
|
{
|
||||||
|
base.UpdatePosition(ScrollEnabled ? ToFancyScrollViewPosition(p) : 0f);
|
||||||
|
|
||||||
|
if (Scroller.Scrollbar)
|
||||||
|
{
|
||||||
|
if (p > ItemsSource.Count - 1)
|
||||||
|
{
|
||||||
|
ShrinkScrollbar(p - (ItemsSource.Count - 1));
|
||||||
|
}
|
||||||
|
else if (p < 0f)
|
||||||
|
{
|
||||||
|
ShrinkScrollbar(-p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShrinkScrollbar(float offset)
|
||||||
|
{
|
||||||
|
var scale = 1f - ToFancyScrollViewPosition(offset) / ViewportLength;
|
||||||
|
UpdateScrollbarSize(ViewportLength * scale / Mathf.Max(ItemsSource.Count, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateContents(IList<TItemData> items)
|
||||||
|
{
|
||||||
|
Debug.Assert(Context.CalculateScrollSize != null);
|
||||||
|
|
||||||
|
AdjustCellIntervalAndScrollOffset();
|
||||||
|
base.UpdateContents(items);
|
||||||
|
|
||||||
|
Scroller.SetTotalCount(items.Count);
|
||||||
|
Scroller.Draggable = ScrollEnabled;
|
||||||
|
Scroller.ScrollSensitivity = ToScrollerPosition(ViewportLength);
|
||||||
|
Scroller.Position = ToScrollerPosition(currentPosition);
|
||||||
|
|
||||||
|
if (Scroller.Scrollbar)
|
||||||
|
{
|
||||||
|
Scroller.Scrollbar.gameObject.SetActive(ScrollEnabled);
|
||||||
|
UpdateScrollbarSize(ViewportLength / Mathf.Max(ItemsSource.Count, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected new void UpdatePosition(float position)
|
||||||
|
{
|
||||||
|
UpdatePosition(position, Alignment.Center);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdatePosition(float position, Alignment alignment)
|
||||||
|
{
|
||||||
|
Scroller.Position = ToScrollerPosition(position, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ScrollTo(int index, float duration, Alignment alignment = Alignment.Center, Action onComplete = null)
|
||||||
|
{
|
||||||
|
Scroller.ScrollTo(ToScrollerPosition(index, alignment), duration, onComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ScrollTo(int index, float duration, Ease easing, Alignment alignment = Alignment.Center, Action onComplete = null)
|
||||||
|
{
|
||||||
|
Scroller.ScrollTo(ToScrollerPosition(index, alignment), duration, easing, onComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateScrollbarSize(float size)
|
||||||
|
{
|
||||||
|
Scroller.Scrollbar.size = ScrollEnabled ? Mathf.Clamp01(size) : 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual float ToFancyScrollViewPosition(float position)
|
||||||
|
{
|
||||||
|
return position
|
||||||
|
/ Mathf.Max(ItemsSource.Count - 1, 1)
|
||||||
|
* MaxScrollPosition
|
||||||
|
- (paddingHead - spacing * 0.5f) / (CellSize + spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual float ToScrollerPosition(float position)
|
||||||
|
{
|
||||||
|
return (position + (paddingHead - spacing * 0.5f) / (CellSize + spacing))
|
||||||
|
/ MaxScrollPosition
|
||||||
|
* Mathf.Max(ItemsSource.Count - 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual float ToScrollerPosition(float position, Alignment alignment = Alignment.Center)
|
||||||
|
{
|
||||||
|
var offset = (ScrollLength - (1f + reuseCellMarginCount * 2f)) * GetAnchore(alignment);
|
||||||
|
return ToScrollerPosition(Mathf.Clamp(position - offset, 0f, MaxScrollPosition));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual float GetAnchore(Alignment alignment)
|
||||||
|
{
|
||||||
|
switch (alignment)
|
||||||
|
{
|
||||||
|
case Alignment.Head: return 0.0f;
|
||||||
|
case Alignment.Center: return 0.5f;
|
||||||
|
case Alignment.Tail: return 1.0f;
|
||||||
|
default: return GetAnchore(Alignment.Center);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdjustCellIntervalAndScrollOffset()
|
||||||
|
{
|
||||||
|
var totalSize = Scroller.ViewportSize + (CellSize + spacing) * (1f + reuseCellMarginCount * 2f);
|
||||||
|
cellInterval = (CellSize + spacing) / totalSize;
|
||||||
|
scrollOffset = cellInterval * (1f + reuseCellMarginCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnValidate()
|
||||||
|
{
|
||||||
|
if (CellPrefab)
|
||||||
|
{
|
||||||
|
AdjustCellIntervalAndScrollOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loop)
|
||||||
|
{
|
||||||
|
loop = false;
|
||||||
|
Debug.LogError("Loop is currently not supported in FancyScrollRect.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Scroller.SnapEnabled)
|
||||||
|
{
|
||||||
|
Scroller.SnapEnabled = false;
|
||||||
|
Debug.LogError("Snap is currently not supported in FancyScrollRect.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Scroller.MovementType == MovementType.Unrestricted)
|
||||||
|
{
|
||||||
|
Scroller.MovementType = MovementType.Elastic;
|
||||||
|
Debug.LogError("MovementType.Unrestricted is currently not supported in FancyScrollRect.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class FancyScrollRect<TItemData> : FancyScrollRect<TItemData, FancyScrollRectContext> { }
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 66c8eb84fdbde4a4a8273b98227a282d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,28 @@
|
||||||
|
/// Credit setchi (https://github.com/setchi)
|
||||||
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
public abstract class FancyScrollRectCell<TItemData, TContext> : FancyScrollViewCell<TItemData, TContext>
|
||||||
|
where TContext : class, IFancyScrollRectContext, new()
|
||||||
|
{
|
||||||
|
public override void UpdatePosition(float position)
|
||||||
|
{
|
||||||
|
var (scrollSize, reuseMargin) = Context.CalculateScrollSize();
|
||||||
|
|
||||||
|
var unclampedPosition = (Mathf.Lerp(0f, scrollSize, position) - reuseMargin) / (scrollSize - reuseMargin * 2f);
|
||||||
|
|
||||||
|
var start = 0.5f * scrollSize;
|
||||||
|
var end = -start;
|
||||||
|
|
||||||
|
UpdatePosition(unclampedPosition, Mathf.Lerp(start, end, position));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdatePosition(float position, float viewportPosition) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class FancyScrollRectCell<TItemData> : FancyScrollRectCell<TItemData, FancyScrollRectContext>
|
||||||
|
{
|
||||||
|
public sealed override void SetupContext(FancyScrollRectContext context) => base.SetupContext(context);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 09f137a55810740eab42e24ef242dcfa
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
||||||
|
/// Credit setchi (https://github.com/setchi)
|
||||||
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
public class FancyScrollRectContext : IFancyScrollRectContext
|
||||||
|
{
|
||||||
|
Func<(float ScrollSize, float ReuseMargin)> IFancyScrollRectContext.CalculateScrollSize { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 91383bd46cee541a7a03e08cfaa47c16
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
||||||
|
/// Credit setchi (https://github.com/setchi)
|
||||||
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
|
||||||
|
public interface IFancyScrollRectContext
|
||||||
|
{
|
||||||
|
Func<(float ScrollSize, float ReuseMargin)> CalculateScrollSize { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e425de6354b6946c7a3b9f2c807b60fe
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 691a9f5ee4aec4112a01b9a4332cac51
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,214 @@
|
||||||
|
//
|
||||||
|
// EasingCore - https://github.com/setchi/EasingCore
|
||||||
|
//
|
||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 setchi
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions.EasingCore
|
||||||
|
{
|
||||||
|
public enum Ease
|
||||||
|
{
|
||||||
|
Linear,
|
||||||
|
InBack,
|
||||||
|
InBounce,
|
||||||
|
InCirc,
|
||||||
|
InCubic,
|
||||||
|
InElastic,
|
||||||
|
InExpo,
|
||||||
|
InQuad,
|
||||||
|
InQuart,
|
||||||
|
InQuint,
|
||||||
|
InSine,
|
||||||
|
OutBack,
|
||||||
|
OutBounce,
|
||||||
|
OutCirc,
|
||||||
|
OutCubic,
|
||||||
|
OutElastic,
|
||||||
|
OutExpo,
|
||||||
|
OutQuad,
|
||||||
|
OutQuart,
|
||||||
|
OutQuint,
|
||||||
|
OutSine,
|
||||||
|
InOutBack,
|
||||||
|
InOutBounce,
|
||||||
|
InOutCirc,
|
||||||
|
InOutCubic,
|
||||||
|
InOutElastic,
|
||||||
|
InOutExpo,
|
||||||
|
InOutQuad,
|
||||||
|
InOutQuart,
|
||||||
|
InOutQuint,
|
||||||
|
InOutSine,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EasingFunction
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the easing function
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Ease type</param>
|
||||||
|
/// <returns>Easing function</returns>
|
||||||
|
public static Func<float, float> Get(Ease type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Ease.Linear: return linear;
|
||||||
|
case Ease.InBack: return inBack;
|
||||||
|
case Ease.InBounce: return inBounce;
|
||||||
|
case Ease.InCirc: return inCirc;
|
||||||
|
case Ease.InCubic: return inCubic;
|
||||||
|
case Ease.InElastic: return inElastic;
|
||||||
|
case Ease.InExpo: return inExpo;
|
||||||
|
case Ease.InQuad: return inQuad;
|
||||||
|
case Ease.InQuart: return inQuart;
|
||||||
|
case Ease.InQuint: return inQuint;
|
||||||
|
case Ease.InSine: return inSine;
|
||||||
|
case Ease.OutBack: return outBack;
|
||||||
|
case Ease.OutBounce: return outBounce;
|
||||||
|
case Ease.OutCirc: return outCirc;
|
||||||
|
case Ease.OutCubic: return outCubic;
|
||||||
|
case Ease.OutElastic: return outElastic;
|
||||||
|
case Ease.OutExpo: return outExpo;
|
||||||
|
case Ease.OutQuad: return outQuad;
|
||||||
|
case Ease.OutQuart: return outQuart;
|
||||||
|
case Ease.OutQuint: return outQuint;
|
||||||
|
case Ease.OutSine: return outSine;
|
||||||
|
case Ease.InOutBack: return inOutBack;
|
||||||
|
case Ease.InOutBounce: return inOutBounce;
|
||||||
|
case Ease.InOutCirc: return inOutCirc;
|
||||||
|
case Ease.InOutCubic: return inOutCubic;
|
||||||
|
case Ease.InOutElastic: return inOutElastic;
|
||||||
|
case Ease.InOutExpo: return inOutExpo;
|
||||||
|
case Ease.InOutQuad: return inOutQuad;
|
||||||
|
case Ease.InOutQuart: return inOutQuart;
|
||||||
|
case Ease.InOutQuint: return inOutQuint;
|
||||||
|
case Ease.InOutSine: return inOutSine;
|
||||||
|
default: return linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
float linear(float t) => t;
|
||||||
|
|
||||||
|
float inBack(float t) => t * t * t - t * Mathf.Sin(t * Mathf.PI);
|
||||||
|
|
||||||
|
float outBack(float t) => 1f - inBack(1f - t);
|
||||||
|
|
||||||
|
float inOutBack(float t) =>
|
||||||
|
t < 0.5f
|
||||||
|
? 0.5f * inBack(2f * t)
|
||||||
|
: 0.5f * outBack(2f * t - 1f) + 0.5f;
|
||||||
|
|
||||||
|
float inBounce(float t) => 1f - outBounce(1f - t);
|
||||||
|
|
||||||
|
float outBounce(float t) =>
|
||||||
|
t < 4f / 11.0f ?
|
||||||
|
(121f * t * t) / 16.0f :
|
||||||
|
t < 8f / 11.0f ?
|
||||||
|
(363f / 40.0f * t * t) - (99f / 10.0f * t) + 17f / 5.0f :
|
||||||
|
t < 9f / 10.0f ?
|
||||||
|
(4356f / 361.0f * t * t) - (35442f / 1805.0f * t) + 16061f / 1805.0f :
|
||||||
|
(54f / 5.0f * t * t) - (513f / 25.0f * t) + 268f / 25.0f;
|
||||||
|
|
||||||
|
float inOutBounce(float t) =>
|
||||||
|
t < 0.5f
|
||||||
|
? 0.5f * inBounce(2f * t)
|
||||||
|
: 0.5f * outBounce(2f * t - 1f) + 0.5f;
|
||||||
|
|
||||||
|
float inCirc(float t) => 1f - Mathf.Sqrt(1f - (t * t));
|
||||||
|
|
||||||
|
float outCirc(float t) => Mathf.Sqrt((2f - t) * t);
|
||||||
|
|
||||||
|
float inOutCirc(float t) =>
|
||||||
|
t < 0.5f
|
||||||
|
? 0.5f * (1 - Mathf.Sqrt(1f - 4f * (t * t)))
|
||||||
|
: 0.5f * (Mathf.Sqrt(-((2f * t) - 3f) * ((2f * t) - 1f)) + 1f);
|
||||||
|
|
||||||
|
float inCubic(float t) => t * t * t;
|
||||||
|
|
||||||
|
float outCubic(float t) => inCubic(t - 1f) + 1f;
|
||||||
|
|
||||||
|
float inOutCubic(float t) =>
|
||||||
|
t < 0.5f
|
||||||
|
? 4f * t * t * t
|
||||||
|
: 0.5f * inCubic(2f * t - 2f) + 1f;
|
||||||
|
|
||||||
|
float inElastic(float t) => Mathf.Sin(13f * (Mathf.PI * 0.5f) * t) * Mathf.Pow(2f, 10f * (t - 1f));
|
||||||
|
|
||||||
|
float outElastic(float t) => Mathf.Sin(-13f * (Mathf.PI * 0.5f) * (t + 1)) * Mathf.Pow(2f, -10f * t) + 1f;
|
||||||
|
|
||||||
|
float inOutElastic(float t) =>
|
||||||
|
t < 0.5f
|
||||||
|
? 0.5f * Mathf.Sin(13f * (Mathf.PI * 0.5f) * (2f * t)) * Mathf.Pow(2f, 10f * ((2f * t) - 1f))
|
||||||
|
: 0.5f * (Mathf.Sin(-13f * (Mathf.PI * 0.5f) * ((2f * t - 1f) + 1f)) * Mathf.Pow(2f, -10f * (2f * t - 1f)) + 2f);
|
||||||
|
|
||||||
|
float inExpo(float t) => Mathf.Approximately(0.0f, t) ? t : Mathf.Pow(2f, 10f * (t - 1f));
|
||||||
|
|
||||||
|
float outExpo(float t) => Mathf.Approximately(1.0f, t) ? t : 1f - Mathf.Pow(2f, -10f * t);
|
||||||
|
|
||||||
|
float inOutExpo(float v) =>
|
||||||
|
Mathf.Approximately(0.0f, v) || Mathf.Approximately(1.0f, v)
|
||||||
|
? v
|
||||||
|
: v < 0.5f
|
||||||
|
? 0.5f * Mathf.Pow(2f, (20f * v) - 10f)
|
||||||
|
: -0.5f * Mathf.Pow(2f, (-20f * v) + 10f) + 1f;
|
||||||
|
|
||||||
|
float inQuad(float t) => t * t;
|
||||||
|
|
||||||
|
float outQuad(float t) => -t * (t - 2f);
|
||||||
|
|
||||||
|
float inOutQuad(float t) =>
|
||||||
|
t < 0.5f
|
||||||
|
? 2f * t * t
|
||||||
|
: -2f * t * t + 4f * t - 1f;
|
||||||
|
|
||||||
|
float inQuart(float t) => t * t * t * t;
|
||||||
|
|
||||||
|
float outQuart(float t)
|
||||||
|
{
|
||||||
|
var u = t - 1f;
|
||||||
|
return u * u * u * (1f - t) + 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float inOutQuart(float t) =>
|
||||||
|
t < 0.5f
|
||||||
|
? 8f * inQuart(t)
|
||||||
|
: -8f * inQuart(t - 1f) + 1f;
|
||||||
|
|
||||||
|
float inQuint(float t) => t * t * t * t * t;
|
||||||
|
|
||||||
|
float outQuint(float t) => inQuint(t - 1f) + 1f;
|
||||||
|
|
||||||
|
float inOutQuint(float t) =>
|
||||||
|
t < 0.5f
|
||||||
|
? 16f * inQuint(t)
|
||||||
|
: 0.5f * inQuint(2f * t - 2f) + 1f;
|
||||||
|
|
||||||
|
float inSine(float t) => Mathf.Sin((t - 1f) * (Mathf.PI * 0.5f)) + 1f;
|
||||||
|
|
||||||
|
float outSine(float t) => Mathf.Sin(t * (Mathf.PI * 0.5f));
|
||||||
|
|
||||||
|
float inOutSine(float t) => 0.5f * (1f - Mathf.Cos(t * Mathf.PI));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: b5e2a916ad19c74468262e656243bc6f
|
guid: 3b2a35f9ff1c8487582b74620e380486
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -0,0 +1,13 @@
|
||||||
|
/// Credit setchi (https://github.com/setchi)
|
||||||
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
public enum MovementDirection
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 11769de5e972543c7a4132ceff94a5c4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
||||||
|
/// Credit setchi (https://github.com/setchi)
|
||||||
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
public enum MovementType
|
||||||
|
{
|
||||||
|
Unrestricted = ScrollRect.MovementType.Unrestricted,
|
||||||
|
Elastic = ScrollRect.MovementType.Elastic,
|
||||||
|
Clamped = ScrollRect.MovementType.Clamped
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 585de8f4f272547c89041f94f2ad92b8
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,11 @@
|
||||||
|
/// Credit setchi (https://github.com/setchi)
|
||||||
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
namespace UnityEngine.UI.Extensions
|
||||||
|
{
|
||||||
|
public enum ScrollDirection
|
||||||
|
{
|
||||||
|
Vertical,
|
||||||
|
Horizontal,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3392a30c085c642139c92e94ec0d6309
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -10,47 +10,83 @@ namespace UnityEngine.UI.Extensions
|
||||||
public class Scroller : UIBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
|
public class Scroller : UIBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
|
||||||
{
|
{
|
||||||
[SerializeField] RectTransform viewport = default;
|
[SerializeField] RectTransform viewport = default;
|
||||||
[SerializeField] ScrollDirection directionOfRecognize = ScrollDirection.Vertical;
|
[SerializeField] ScrollDirection scrollDirection = ScrollDirection.Vertical;
|
||||||
[SerializeField] MovementType movementType = MovementType.Elastic;
|
[SerializeField] MovementType movementType = MovementType.Elastic;
|
||||||
[SerializeField] float elasticity = 0.1f;
|
[SerializeField] float elasticity = 0.1f;
|
||||||
[SerializeField] float scrollSensitivity = 1f;
|
[SerializeField] float scrollSensitivity = 1f;
|
||||||
[SerializeField] bool inertia = true;
|
[SerializeField] bool inertia = true;
|
||||||
[SerializeField] float decelerationRate = 0.03f;
|
[SerializeField] float decelerationRate = 0.03f;
|
||||||
[SerializeField] Snap snap = new Snap {
|
[SerializeField]
|
||||||
|
Snap snap = new Snap
|
||||||
|
{
|
||||||
Enable = true,
|
Enable = true,
|
||||||
VelocityThreshold = 0.5f,
|
VelocityThreshold = 0.5f,
|
||||||
Duration = 0.3f,
|
Duration = 0.3f,
|
||||||
Easing = Ease.InOutCubic
|
Easing = Ease.InOutCubic
|
||||||
};
|
};
|
||||||
|
[SerializeField] bool draggable = true;
|
||||||
|
[SerializeField] Scrollbar scrollbar = default;
|
||||||
|
|
||||||
|
public ScrollDirection ScrollDirection => scrollDirection;
|
||||||
|
|
||||||
|
public MovementType MovementType
|
||||||
|
{
|
||||||
|
get => movementType;
|
||||||
|
set => movementType = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float ViewportSize => scrollDirection == ScrollDirection.Horizontal
|
||||||
|
? viewport.rect.size.x
|
||||||
|
: viewport.rect.size.y;
|
||||||
|
|
||||||
|
public bool SnapEnabled
|
||||||
|
{
|
||||||
|
get => snap.Enable;
|
||||||
|
set => snap.Enable = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float ScrollSensitivity
|
||||||
|
{
|
||||||
|
get => scrollSensitivity;
|
||||||
|
set => scrollSensitivity = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Draggable
|
||||||
|
{
|
||||||
|
get => draggable;
|
||||||
|
set => draggable = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scrollbar Scrollbar => scrollbar;
|
||||||
|
|
||||||
|
public float Position
|
||||||
|
{
|
||||||
|
get => currentPosition;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
autoScrollState.Reset();
|
||||||
|
velocity = 0f;
|
||||||
|
dragging = false;
|
||||||
|
|
||||||
|
UpdatePosition(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
readonly AutoScrollState autoScrollState = new AutoScrollState();
|
readonly AutoScrollState autoScrollState = new AutoScrollState();
|
||||||
|
|
||||||
Action<float> onValueChanged;
|
Action<float> onValueChanged;
|
||||||
Action<int> onSelectionChanged;
|
Action<int> onSelectionChanged;
|
||||||
|
|
||||||
Vector2 pointerStartLocalPosition;
|
Vector2 beginDragPointerPosition;
|
||||||
float dragStartScrollPosition;
|
float scrollStartPosition;
|
||||||
float prevScrollPosition;
|
float prevPosition;
|
||||||
float currentScrollPosition;
|
float currentPosition;
|
||||||
|
|
||||||
int totalCount;
|
int totalCount;
|
||||||
|
|
||||||
bool dragging;
|
bool dragging;
|
||||||
float velocity;
|
float velocity;
|
||||||
|
|
||||||
enum ScrollDirection
|
|
||||||
{
|
|
||||||
Vertical,
|
|
||||||
Horizontal,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum MovementType
|
|
||||||
{
|
|
||||||
Unrestricted = ScrollRect.MovementType.Unrestricted,
|
|
||||||
Elastic = ScrollRect.MovementType.Elastic,
|
|
||||||
Clamped = ScrollRect.MovementType.Clamped
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
class Snap
|
class Snap
|
||||||
{
|
{
|
||||||
|
@ -69,7 +105,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
public float Duration;
|
public float Duration;
|
||||||
public Func<float, float> EasingFunction;
|
public Func<float, float> EasingFunction;
|
||||||
public float StartTime;
|
public float StartTime;
|
||||||
public float EndScrollPosition;
|
public float EndPosition;
|
||||||
|
|
||||||
public Action OnComplete;
|
public Action OnComplete;
|
||||||
|
|
||||||
|
@ -80,7 +116,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
Duration = 0f;
|
Duration = 0f;
|
||||||
StartTime = 0f;
|
StartTime = 0f;
|
||||||
EasingFunction = DefaultEasingFunction;
|
EasingFunction = DefaultEasingFunction;
|
||||||
EndScrollPosition = 0f;
|
EndPosition = 0f;
|
||||||
OnComplete = null;
|
OnComplete = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,21 +127,32 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Start()
|
||||||
|
{
|
||||||
|
base.Start();
|
||||||
|
|
||||||
|
if (scrollbar)
|
||||||
|
{
|
||||||
|
scrollbar.onValueChanged.AddListener(x => UpdatePosition(x * (totalCount - 1f), false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void OnValueChanged(Action<float> callback) => onValueChanged = callback;
|
public void OnValueChanged(Action<float> callback) => onValueChanged = callback;
|
||||||
|
|
||||||
public void OnSelectionChanged(Action<int> callback) => onSelectionChanged = callback;
|
public void OnSelectionChanged(Action<int> callback) => onSelectionChanged = callback;
|
||||||
|
|
||||||
public void SetTotalCount(int totalCount) => this.totalCount = totalCount;
|
public void SetTotalCount(int totalCount) => this.totalCount = totalCount;
|
||||||
|
|
||||||
public void ScrollTo(int index, float duration, Action onComplete = null) => ScrollTo(index, duration, Ease.OutCubic, onComplete);
|
public void ScrollTo(float position, float duration, Action onComplete = null) => ScrollTo(position, duration, Ease.OutCubic, onComplete);
|
||||||
|
|
||||||
public void ScrollTo(int index, float duration, Ease easing, Action onComplete = null) => ScrollTo(index, duration, EasingFunction.Get(easing), onComplete);
|
public void ScrollTo(float position, float duration, Ease easing, Action onComplete = null) => ScrollTo(position, duration, EasingFunction.Get(easing), onComplete);
|
||||||
|
|
||||||
public void ScrollTo(int index, float duration, Func<float, float> easingFunction, Action onComplete = null)
|
public void ScrollTo(float position, float duration, Func<float, float> easingFunction, Action onComplete = null)
|
||||||
{
|
{
|
||||||
if (duration <= 0f)
|
if (duration <= 0f)
|
||||||
{
|
{
|
||||||
JumpTo(index);
|
Position = CircularPosition(position, totalCount);
|
||||||
|
onComplete?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,55 +161,64 @@ namespace UnityEngine.UI.Extensions
|
||||||
autoScrollState.Duration = duration;
|
autoScrollState.Duration = duration;
|
||||||
autoScrollState.EasingFunction = easingFunction ?? DefaultEasingFunction;
|
autoScrollState.EasingFunction = easingFunction ?? DefaultEasingFunction;
|
||||||
autoScrollState.StartTime = Time.unscaledTime;
|
autoScrollState.StartTime = Time.unscaledTime;
|
||||||
autoScrollState.EndScrollPosition = CalculateDestinationIndex(index);
|
autoScrollState.EndPosition = currentPosition + CalculateMovementAmount(currentPosition, position);
|
||||||
autoScrollState.OnComplete = onComplete;
|
autoScrollState.OnComplete = onComplete;
|
||||||
|
|
||||||
velocity = 0f;
|
velocity = 0f;
|
||||||
dragStartScrollPosition = currentScrollPosition;
|
scrollStartPosition = currentPosition;
|
||||||
|
|
||||||
UpdateSelection(Mathf.RoundToInt(CircularPosition(autoScrollState.EndScrollPosition, totalCount)));
|
UpdateSelection(Mathf.RoundToInt(CircularPosition(autoScrollState.EndPosition, totalCount)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void JumpTo(int index)
|
public void JumpTo(int index)
|
||||||
{
|
{
|
||||||
|
if (index < 0 || index > totalCount - 1)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
|
}
|
||||||
|
|
||||||
autoScrollState.Reset();
|
autoScrollState.Reset();
|
||||||
|
|
||||||
velocity = 0f;
|
velocity = 0f;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
|
|
||||||
index = CalculateDestinationIndex(index);
|
|
||||||
|
|
||||||
UpdateSelection(index);
|
UpdateSelection(index);
|
||||||
UpdatePosition(index);
|
UpdatePosition(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MovementDirection GetMovementDirection(int sourceIndex, int destIndex)
|
||||||
|
{
|
||||||
|
var movementAmount = CalculateMovementAmount(sourceIndex, destIndex);
|
||||||
|
return scrollDirection == ScrollDirection.Horizontal
|
||||||
|
? movementAmount > 0
|
||||||
|
? MovementDirection.Left
|
||||||
|
: MovementDirection.Right
|
||||||
|
: movementAmount > 0
|
||||||
|
? MovementDirection.Up
|
||||||
|
: MovementDirection.Down;
|
||||||
|
}
|
||||||
|
|
||||||
void IBeginDragHandler.OnBeginDrag(PointerEventData eventData)
|
void IBeginDragHandler.OnBeginDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (eventData.button != PointerEventData.InputButton.Left)
|
if (!draggable || eventData.button != PointerEventData.InputButton.Left)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointerStartLocalPosition = Vector2.zero;
|
|
||||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||||
viewport,
|
viewport,
|
||||||
eventData.position,
|
eventData.position,
|
||||||
eventData.pressEventCamera,
|
eventData.pressEventCamera,
|
||||||
out pointerStartLocalPosition);
|
out beginDragPointerPosition);
|
||||||
|
|
||||||
dragStartScrollPosition = currentScrollPosition;
|
scrollStartPosition = currentPosition;
|
||||||
dragging = true;
|
dragging = true;
|
||||||
autoScrollState.Reset();
|
autoScrollState.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDragHandler.OnDrag(PointerEventData eventData)
|
void IDragHandler.OnDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (eventData.button != PointerEventData.InputButton.Left)
|
if (!draggable || eventData.button != PointerEventData.InputButton.Left || !dragging)
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dragging)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -171,16 +227,16 @@ namespace UnityEngine.UI.Extensions
|
||||||
viewport,
|
viewport,
|
||||||
eventData.position,
|
eventData.position,
|
||||||
eventData.pressEventCamera,
|
eventData.pressEventCamera,
|
||||||
out var localCursor))
|
out var dragPointerPosition))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pointerDelta = localCursor - pointerStartLocalPosition;
|
var pointerDelta = dragPointerPosition - beginDragPointerPosition;
|
||||||
var position = (directionOfRecognize == ScrollDirection.Horizontal ? -pointerDelta.x : pointerDelta.y)
|
var position = (scrollDirection == ScrollDirection.Horizontal ? -pointerDelta.x : pointerDelta.y)
|
||||||
/ ViewportSize
|
/ ViewportSize
|
||||||
* scrollSensitivity
|
* scrollSensitivity
|
||||||
+ dragStartScrollPosition;
|
+ scrollStartPosition;
|
||||||
|
|
||||||
var offset = CalculateOffset(position);
|
var offset = CalculateOffset(position);
|
||||||
position += offset;
|
position += offset;
|
||||||
|
@ -198,7 +254,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
void IEndDragHandler.OnEndDrag(PointerEventData eventData)
|
void IEndDragHandler.OnEndDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (eventData.button != PointerEventData.InputButton.Left)
|
if (!draggable || eventData.button != PointerEventData.InputButton.Left)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -206,10 +262,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
dragging = false;
|
dragging = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float ViewportSize => directionOfRecognize == ScrollDirection.Horizontal
|
|
||||||
? viewport.rect.size.x
|
|
||||||
: viewport.rect.size.y;
|
|
||||||
|
|
||||||
float CalculateOffset(float position)
|
float CalculateOffset(float position)
|
||||||
{
|
{
|
||||||
if (movementType == MovementType.Unrestricted)
|
if (movementType == MovementType.Unrestricted)
|
||||||
|
@ -230,10 +282,14 @@ namespace UnityEngine.UI.Extensions
|
||||||
return 0f;
|
return 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdatePosition(float position)
|
void UpdatePosition(float position, bool updateScrollbar = true)
|
||||||
{
|
{
|
||||||
currentScrollPosition = position;
|
onValueChanged?.Invoke(currentPosition = position);
|
||||||
onValueChanged?.Invoke(currentScrollPosition);
|
|
||||||
|
if (scrollbar && updateScrollbar)
|
||||||
|
{
|
||||||
|
scrollbar.value = Mathf.Clamp01(position / Mathf.Max(totalCount - 1f, 1e-4f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateSelection(int index) => onSelectionChanged?.Invoke(index);
|
void UpdateSelection(int index) => onSelectionChanged?.Invoke(index);
|
||||||
|
@ -244,7 +300,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
var deltaTime = Time.unscaledDeltaTime;
|
var deltaTime = Time.unscaledDeltaTime;
|
||||||
var offset = CalculateOffset(currentScrollPosition);
|
var offset = CalculateOffset(currentPosition);
|
||||||
|
|
||||||
if (autoScrollState.Enable)
|
if (autoScrollState.Enable)
|
||||||
{
|
{
|
||||||
|
@ -252,7 +308,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
if (autoScrollState.Elastic)
|
if (autoScrollState.Elastic)
|
||||||
{
|
{
|
||||||
position = Mathf.SmoothDamp(currentScrollPosition, currentScrollPosition + offset, ref velocity,
|
position = Mathf.SmoothDamp(currentPosition, currentPosition + offset, ref velocity,
|
||||||
elasticity, Mathf.Infinity, deltaTime);
|
elasticity, Mathf.Infinity, deltaTime);
|
||||||
|
|
||||||
if (Mathf.Abs(velocity) < 0.01f)
|
if (Mathf.Abs(velocity) < 0.01f)
|
||||||
|
@ -265,8 +321,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var alpha = Mathf.Clamp01((Time.unscaledTime - autoScrollState.StartTime) /
|
var alpha = Mathf.Clamp01((Time.unscaledTime - autoScrollState.StartTime) /
|
||||||
Mathf.Max(autoScrollState.Duration, float.Epsilon));
|
Mathf.Max(autoScrollState.Duration, float.Epsilon));
|
||||||
position = Mathf.LerpUnclamped(dragStartScrollPosition, autoScrollState.EndScrollPosition,
|
position = Mathf.LerpUnclamped(scrollStartPosition, autoScrollState.EndPosition,
|
||||||
autoScrollState.EasingFunction(alpha));
|
autoScrollState.EasingFunction(alpha));
|
||||||
|
|
||||||
if (Mathf.Approximately(alpha, 1f))
|
if (Mathf.Approximately(alpha, 1f))
|
||||||
|
@ -279,7 +335,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
else if (!dragging && (!Mathf.Approximately(offset, 0f) || !Mathf.Approximately(velocity, 0f)))
|
else if (!dragging && (!Mathf.Approximately(offset, 0f) || !Mathf.Approximately(velocity, 0f)))
|
||||||
{
|
{
|
||||||
var position = currentScrollPosition;
|
var position = currentPosition;
|
||||||
|
|
||||||
if (movementType == MovementType.Elastic && !Mathf.Approximately(offset, 0f))
|
if (movementType == MovementType.Elastic && !Mathf.Approximately(offset, 0f))
|
||||||
{
|
{
|
||||||
|
@ -302,7 +358,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
if (snap.Enable && Mathf.Abs(velocity) < snap.VelocityThreshold)
|
if (snap.Enable && Mathf.Abs(velocity) < snap.VelocityThreshold)
|
||||||
{
|
{
|
||||||
ScrollTo(Mathf.RoundToInt(currentScrollPosition), snap.Duration, snap.Easing);
|
ScrollTo(Mathf.RoundToInt(currentPosition), snap.Duration, snap.Easing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -330,28 +386,28 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
if (!autoScrollState.Enable && dragging && inertia)
|
if (!autoScrollState.Enable && dragging && inertia)
|
||||||
{
|
{
|
||||||
var newVelocity = (currentScrollPosition - prevScrollPosition) / deltaTime;
|
var newVelocity = (currentPosition - prevPosition) / deltaTime;
|
||||||
velocity = Mathf.Lerp(velocity, newVelocity, deltaTime * 10f);
|
velocity = Mathf.Lerp(velocity, newVelocity, deltaTime * 10f);
|
||||||
}
|
}
|
||||||
|
|
||||||
prevScrollPosition = currentScrollPosition;
|
prevPosition = currentPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CalculateDestinationIndex(int index) => movementType == MovementType.Unrestricted
|
float CalculateMovementAmount(float sourcePosition, float destPosition)
|
||||||
? CalculateClosestIndex(index)
|
|
||||||
: Mathf.Clamp(index, 0, totalCount - 1);
|
|
||||||
|
|
||||||
int CalculateClosestIndex(int index)
|
|
||||||
{
|
{
|
||||||
var diff = CircularPosition(index, totalCount)
|
if (movementType != MovementType.Unrestricted)
|
||||||
- CircularPosition(currentScrollPosition, totalCount);
|
|
||||||
|
|
||||||
if (Mathf.Abs(diff) > totalCount * 0.5f)
|
|
||||||
{
|
{
|
||||||
diff = Mathf.Sign(-diff) * (totalCount - Mathf.Abs(diff));
|
return Mathf.Clamp(destPosition, 0, totalCount - 1) - sourcePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Mathf.RoundToInt(diff + currentScrollPosition);
|
var movementAmount = CircularPosition(destPosition, totalCount) - CircularPosition(sourcePosition, totalCount);
|
||||||
|
|
||||||
|
if (Mathf.Abs(movementAmount) > totalCount * 0.5f)
|
||||||
|
{
|
||||||
|
movementAmount = Mathf.Sign(-movementAmount) * (totalCount - Mathf.Abs(movementAmount));
|
||||||
|
}
|
||||||
|
|
||||||
|
return movementAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CircularPosition(float p, int size) => size < 1 ? 0 : p < 0 ? size - 1 + (p + 1) % size : p % size;
|
float CircularPosition(float p, int size) => size < 1 ? 0 : p < 0 ? size - 1 + (p + 1) % size : p % size;
|
|
@ -0,0 +1,12 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9f0e995f494626a4f878eedbded37c8d
|
||||||
|
timeCreated: 1487408581
|
||||||
|
licenseType: Free
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue