Merged in dev/fancyscrollviewupdate (pull request #77)
Updated Fancy Scroll View code to the latest from repopull/413/head
commit
9a66b92de2
|
@ -1,16 +1,17 @@
|
|||
/// Credit setchi (https://github.com/setchi)
|
||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="FancyScrollView{TItemData, TContext}"/> のセルを実装するための抽象基底クラス.
|
||||
/// <see cref="FancyScrollViewCell{TItemData, TContext}.Context"/> が不要な場合は
|
||||
/// 代わりに <see cref="FancyScrollViewCell{TItemData}"/> を使用します.
|
||||
/// <see cref="FancyCell{TItemData, TContext}.Context"/> が不要な場合は
|
||||
/// 代わりに <see cref="FancyCell{TItemData}"/> を使用します.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <typeparam name="TContext"><see cref="Context"/> の型.</typeparam>
|
||||
public abstract class FancyScrollViewCell<TItemData, TContext> : MonoBehaviour where TContext : class, new()
|
||||
public abstract class FancyCell<TItemData, TContext> : MonoBehaviour where TContext : class, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// このセルで表示しているデータのインデックス.
|
||||
|
@ -29,10 +30,15 @@ namespace UnityEngine.UI.Extensions
|
|||
protected TContext Context { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Context"/> のセットアップを行います.
|
||||
/// <see cref="Context"/> をセットします.
|
||||
/// </summary>
|
||||
/// <param name="context">コンテキスト.</param>
|
||||
public virtual void SetupContext(TContext context) => Context = context;
|
||||
public virtual void SetContext(TContext context) => Context = context;
|
||||
|
||||
/// <summary>
|
||||
/// 初期化を行います.
|
||||
/// </summary>
|
||||
public virtual void Initialize() { }
|
||||
|
||||
/// <summary>
|
||||
/// このセルの可視状態を設定します.
|
||||
|
@ -57,10 +63,10 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <see cref="FancyScrollView{TItemData}"/> のセルを実装するための抽象基底クラス.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <seealso cref="FancyScrollViewCell{TItemData, TContext}"/>
|
||||
public abstract class FancyScrollViewCell<TItemData> : FancyScrollViewCell<TItemData, FancyScrollViewNullContext>
|
||||
/// <seealso cref="FancyCell{TItemData, TContext}"/>
|
||||
public abstract class FancyCell<TItemData> : FancyCell<TItemData, NullContext>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public sealed override void SetupContext(FancyScrollViewNullContext context) => base.SetupContext(context);
|
||||
public sealed override void SetContext(NullContext context) => base.SetContext(context);
|
||||
}
|
||||
}
|
|
@ -42,8 +42,7 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
[SerializeField] protected Transform cellContainer = default;
|
||||
|
||||
readonly IList<FancyScrollViewCell<TItemData, TContext>> pool =
|
||||
new List<FancyScrollViewCell<TItemData, TContext>>();
|
||||
readonly IList<FancyCell<TItemData, TContext>> pool = new List<FancyCell<TItemData, TContext>>();
|
||||
|
||||
/// <summary>
|
||||
/// 初期化済みかどうか.
|
||||
|
@ -90,7 +89,12 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// セルの表示内容を更新します.
|
||||
/// セルのレイアウトを強制的に更新します.
|
||||
/// </summary>
|
||||
protected virtual void Relayout() => UpdatePosition(currentPosition, false);
|
||||
|
||||
/// <summary>
|
||||
/// セルのレイアウトと表示内容を強制的に更新します.
|
||||
/// </summary>
|
||||
protected virtual void Refresh() => UpdatePosition(currentPosition, true);
|
||||
|
||||
|
@ -130,16 +134,16 @@ namespace UnityEngine.UI.Extensions
|
|||
var addCount = Mathf.CeilToInt((1f - firstPosition) / cellInterval) - pool.Count;
|
||||
for (var i = 0; i < addCount; i++)
|
||||
{
|
||||
var cell = Instantiate(CellPrefab, cellContainer)
|
||||
.GetComponent<FancyScrollViewCell<TItemData, TContext>>();
|
||||
var cell = Instantiate(CellPrefab, cellContainer).GetComponent<FancyCell<TItemData, TContext>>();
|
||||
if (cell == null)
|
||||
{
|
||||
throw new MissingComponentException(
|
||||
$"FancyScrollViewCell<{typeof(TItemData).FullName}, {typeof(TContext).FullName}> " +
|
||||
$"component not found in {CellPrefab.name}.");
|
||||
throw new MissingComponentException(string.Format(
|
||||
"FancyCell<{0}, {1}> component not found in {2}.",
|
||||
typeof(TItemData).FullName, typeof(TContext).FullName, CellPrefab.name));
|
||||
}
|
||||
|
||||
cell.SetupContext(Context);
|
||||
cell.SetContext(Context);
|
||||
cell.Initialize();
|
||||
cell.SetVisible(false);
|
||||
pool.Add(cell);
|
||||
}
|
||||
|
@ -200,7 +204,7 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <summary>
|
||||
/// <see cref="FancyScrollView{TItemData}"/> のコンテキストクラス.
|
||||
/// </summary>
|
||||
public sealed class FancyScrollViewNullContext { }
|
||||
public sealed class NullContext { }
|
||||
|
||||
/// <summary>
|
||||
/// スクロールビューを実装するための抽象基底クラス.
|
||||
|
@ -208,5 +212,5 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
/// <typeparam name="TItemData"></typeparam>
|
||||
/// <seealso cref="FancyScrollView{TItemData, TContext}"/>
|
||||
public abstract class FancyScrollView<TItemData> : FancyScrollView<TItemData, FancyScrollViewNullContext> { }
|
||||
public abstract class FancyScrollView<TItemData> : FancyScrollView<TItemData, NullContext> { }
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/// Credit setchi (https://github.com/setchi)
|
||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 複数の <see cref="FancyCell{TItemData, TContext}"/> を持つセルグループ実装するための抽象基底クラス.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <typeparam name="TContext"><see cref="FancyCell{TItemData, TContext}.Context"/> の型.</typeparam>
|
||||
public abstract class FancyCellGroup<TItemData, TContext> : FancyCell<TItemData[], TContext>
|
||||
where TContext : class, IFancyCellGroupContext, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// このグループで表示するセルの配列.
|
||||
/// </summary>
|
||||
protected virtual FancyCell<TItemData, TContext>[] Cells { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// このグループで表示するセルの配列をインスタンス化します.
|
||||
/// </summary>
|
||||
/// <returns>このグループで表示するセルの配列.</returns>
|
||||
protected virtual FancyCell<TItemData, TContext>[] InstantiateCells()
|
||||
{
|
||||
return Enumerable.Range(0, Context.GetGroupCount())
|
||||
.Select(_ => Instantiate(Context.CellTemplate, transform))
|
||||
.Select(x => x.GetComponent<FancyCell<TItemData, TContext>>())
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
Cells = InstantiateCells();
|
||||
Debug.Assert(Cells.Length == Context.GetGroupCount());
|
||||
|
||||
for (var i = 0; i < Cells.Length; i++)
|
||||
{
|
||||
Cells[i].SetContext(Context);
|
||||
Cells[i].Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void UpdateContent(TItemData[] contents)
|
||||
{
|
||||
var firstCellIndex = Index * Context.GetGroupCount();
|
||||
|
||||
for (var i = 0; i < Cells.Length; i++)
|
||||
{
|
||||
Cells[i].Index = i + firstCellIndex;
|
||||
Cells[i].SetVisible(i < contents.Length);
|
||||
|
||||
if (Cells[i].IsVisible)
|
||||
{
|
||||
Cells[i].UpdateContent(contents[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void UpdatePosition(float position)
|
||||
{
|
||||
for (var i = 0; i < Cells.Length; i++)
|
||||
{
|
||||
Cells[i].UpdatePosition(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3e786463ba934403cacf7e8c0d5822d7
|
||||
guid: 5d97e25c7748b8d44acd2298e509c8f1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -11,77 +11,106 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <summary>
|
||||
/// グリッドレイアウトのスクロールビューを実装するための抽象基底クラス.
|
||||
/// 無限スクロールおよびスナップには対応していません.
|
||||
/// <see cref="FancyScrollView{TItemData, TContext}.Context"/> が不要な場合は
|
||||
/// 代わりに <see cref="FancyGridView{TItemData}"/> を使用します.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <typeparam name="TContext"><see cref="FancyScrollView{TItemData, TContext}.Context"/> の型.</typeparam>
|
||||
public abstract class FancyGridView<TItemData, TContext> : FancyScrollRect<TItemData[], TContext>
|
||||
where TContext : class, IFancyScrollRectContext, IFancyGridViewContext, new()
|
||||
where TContext : class, IFancyGridViewContext, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// カラム同士の余白.
|
||||
/// デフォルトのセルグループクラス.
|
||||
/// </summary>
|
||||
[SerializeField] protected float columnSpacing = 0f;
|
||||
|
||||
GameObject cachedRowPrefab;
|
||||
protected abstract class DefaultCellGroup : FancyCellGroup<TItemData, TContext> { }
|
||||
|
||||
/// <summary>
|
||||
/// 行の Prefab.
|
||||
/// 最初にセルを配置する軸方向のセル同士の余白.
|
||||
/// </summary>
|
||||
[SerializeField] protected float startAxisSpacing = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// 最初にセルを配置する軸方向のセル数.
|
||||
/// </summary>
|
||||
[SerializeField] protected int startAxisCellCount = 4;
|
||||
|
||||
/// <summary>
|
||||
/// セルのサイズ.
|
||||
/// </summary>
|
||||
[SerializeField] protected Vector2 cellSize = new Vector2(100f, 100f);
|
||||
|
||||
/// <summary>
|
||||
/// セルのグループ Prefab.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="FancyGridView{TItemData, TContext}"/> では,
|
||||
/// <see cref="FancyScrollView{TItemData, TContext}.CellPrefab"/> を行オブジェクトとして使用します.
|
||||
/// <see cref="FancyScrollView{TItemData, TContext}.CellPrefab"/> を最初にセルを配置する軸方向のセルコンテナとして使用します.
|
||||
/// </remarks>
|
||||
protected sealed override GameObject CellPrefab => cachedRowPrefab ?? (cachedRowPrefab = SetupRowTemplate());
|
||||
protected sealed override GameObject CellPrefab => cellGroupTemplate;
|
||||
|
||||
/// <summary>
|
||||
/// 一行あたりの要素数.
|
||||
/// </summary>
|
||||
protected abstract int ColumnCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// セルのテンプレート.
|
||||
/// </summary>
|
||||
protected abstract FancyScrollViewCell<TItemData, TContext> CellTemplate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 行オブジェクトのテンプレート.
|
||||
/// </summary>
|
||||
protected abstract FancyGridViewRow<TItemData, TContext> RowTemplate { get; }
|
||||
/// <inheritdoc/>
|
||||
protected override float CellSize => Scroller.ScrollDirection == ScrollDirection.Horizontal
|
||||
? cellSize.x
|
||||
: cellSize.y;
|
||||
|
||||
/// <summary>
|
||||
/// アイテムの総数.
|
||||
/// </summary>
|
||||
public int DataCount { get; private set; }
|
||||
|
||||
GameObject cellGroupTemplate;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
Debug.Assert(RowTemplate != null);
|
||||
Debug.Assert(CellTemplate != null);
|
||||
Debug.Assert(ColumnCount > 0);
|
||||
Debug.Assert(startAxisCellCount > 0);
|
||||
|
||||
Context.CellTemplate = CellTemplate.gameObject;
|
||||
Context.ScrollDirection = Scroller.ScrollDirection;
|
||||
Context.GetColumnCount = () => ColumnCount;
|
||||
Context.GetColumnSpacing = () => columnSpacing;
|
||||
Context.GetGroupCount = () => startAxisCellCount;
|
||||
Context.GetStartAxisSpacing = () => startAxisSpacing;
|
||||
Context.GetCellSize = () => Scroller.ScrollDirection == ScrollDirection.Horizontal
|
||||
? cellSize.y
|
||||
: cellSize.x;
|
||||
|
||||
SetupCellTemplate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 行オブジェクトのセットアップを行います.
|
||||
/// 最初にセルが生成される直前に呼び出されます.
|
||||
/// <see cref="Setup{TGroup}(FancyCell{TItemData, TContext})"/> メソッドを使用してセルテンプレートのセットアップを行ってください.
|
||||
/// </summary>
|
||||
/// <returns>行を構成する <c>GameObject</c>.</returns>
|
||||
protected virtual GameObject SetupRowTemplate()
|
||||
/// <example>
|
||||
/// <code><![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using FancyScrollView;
|
||||
///
|
||||
/// public class MyGridView : FancyGridView<ItemData, Context>
|
||||
/// {
|
||||
/// class CellGroup : DefaultCellGroup { }
|
||||
///
|
||||
/// [SerializeField] Cell cellPrefab = default;
|
||||
///
|
||||
/// protected override void SetupCellTemplate() => Setup<CellGroup>(cellPrefab);
|
||||
/// }
|
||||
/// ]]></code>
|
||||
/// </example>
|
||||
protected abstract void SetupCellTemplate();
|
||||
|
||||
/// <summary>
|
||||
/// セルテンプレートのセットアップを行います.
|
||||
/// </summary>
|
||||
/// <param name="cellTemplate">セルのテンプレート.</param>
|
||||
/// <typeparam name="TGroup">セルグループの型.</typeparam>
|
||||
protected virtual void Setup<TGroup>(FancyCell<TItemData, TContext> cellTemplate)
|
||||
where TGroup : FancyCell<TItemData[], TContext>
|
||||
{
|
||||
var cell = CellTemplate.GetComponent<RectTransform>();
|
||||
var row = RowTemplate.GetComponent<RectTransform>();
|
||||
Context.CellTemplate = cellTemplate.gameObject;
|
||||
|
||||
row.sizeDelta = Scroller.ScrollDirection == ScrollDirection.Horizontal
|
||||
? new Vector2(cell.rect.width, row.sizeDelta.y)
|
||||
: new Vector2(row.sizeDelta.x, cell.rect.height);
|
||||
|
||||
return row.gameObject;
|
||||
cellGroupTemplate = new GameObject("Group").AddComponent<TGroup>().gameObject;
|
||||
cellGroupTemplate.transform.SetParent(cellContainer, false);
|
||||
cellGroupTemplate.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -92,15 +121,26 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
DataCount = items.Count;
|
||||
|
||||
var rows = items
|
||||
var itemGroups = items
|
||||
.Select((item, index) => (item, index))
|
||||
.GroupBy(
|
||||
x => x.index / ColumnCount,
|
||||
x => x.index / startAxisCellCount,
|
||||
x => x.item)
|
||||
.Select(group => group.ToArray())
|
||||
.ToArray();
|
||||
|
||||
UpdateContents(rows);
|
||||
UpdateContents(itemGroups);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定したアイテムの位置までジャンプします.
|
||||
/// </summary>
|
||||
/// <param name="itemIndex">アイテムのインデックス.</param>
|
||||
/// <param name="alignment">ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).</param>
|
||||
protected override void JumpTo(int itemIndex, float alignment = 0.5f)
|
||||
{
|
||||
var groupIndex = itemIndex / startAxisCellCount;
|
||||
base.JumpTo(groupIndex, alignment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -108,12 +148,12 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
/// <param name="itemIndex">アイテムのインデックス.</param>
|
||||
/// <param name="duration">移動にかける秒数.</param>
|
||||
/// <param name="alignment"><see cref="Alignment"/>.</param>
|
||||
/// <param name="alignment">ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).</param>
|
||||
/// <param name="onComplete">移動が完了した際に呼び出されるコールバック.</param>
|
||||
public override void ScrollTo(int itemIndex, float duration, Alignment alignment = Alignment.Center, Action onComplete = null)
|
||||
protected override void ScrollTo(int itemIndex, float duration, float alignment = 0.5f, Action onComplete = null)
|
||||
{
|
||||
var rowIndex = itemIndex / Context.GetColumnCount();
|
||||
base.ScrollTo(rowIndex, duration, alignment, onComplete);
|
||||
var groupIndex = itemIndex / startAxisCellCount;
|
||||
base.ScrollTo(groupIndex, duration, alignment, onComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -122,23 +162,20 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="itemIndex">アイテムのインデックス.</param>
|
||||
/// <param name="duration">移動にかける秒数.</param>
|
||||
/// <param name="easing">移動に使用するイージング.</param>
|
||||
/// <param name="alignment"><see cref="Alignment"/>.</param>
|
||||
/// <param name="alignment">ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).</param>
|
||||
/// <param name="onComplete">移動が完了した際に呼び出されるコールバック.</param>
|
||||
public override void ScrollTo(int itemIndex, float duration, Ease easing, Alignment alignment = Alignment.Center, Action onComplete = null)
|
||||
protected override void ScrollTo(int itemIndex, float duration, Ease easing, float alignment = 0.5f, Action onComplete = null)
|
||||
{
|
||||
var rowIndex = itemIndex / Context.GetColumnCount();
|
||||
base.ScrollTo(rowIndex, duration, easing, alignment, onComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定したアイテムの位置までジャンプします.
|
||||
/// </summary>
|
||||
/// <param name="itemIndex">アイテムのインデックス.</param>
|
||||
/// <param name="alignment"><see cref="Alignment"/>.</param>
|
||||
public virtual void JumpTo(int itemIndex, Alignment alignment = Alignment.Center)
|
||||
{
|
||||
var rowIndex = itemIndex / Context.GetColumnCount();
|
||||
UpdatePosition(rowIndex, alignment);
|
||||
var groupIndex = itemIndex / startAxisCellCount;
|
||||
base.ScrollTo(groupIndex, duration, easing, alignment, onComplete);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// グリッドレイアウトのスクロールビューを実装するための抽象基底クラス.
|
||||
/// 無限スクロールおよびスナップには対応していません.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <seealso cref="FancyGridView{TItemData, TContext}"/>
|
||||
public abstract class FancyGridView<TItemData> : FancyGridView<TItemData, FancyGridViewContext> { }
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/// Credit setchi (https://github.com/setchi)
|
||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="FancyGridView{TItemData, TContext}"/> のセルを実装するための抽象基底クラス.
|
||||
/// <see cref="FancyCell{TItemData, TContext}.Context"/> が不要な場合は
|
||||
/// 代わりに <see cref="FancyGridViewCell{TItemData}"/> を使用します.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <typeparam name="TContext"><see cref="FancyCell{TItemData, TContext}.Context"/> の型.</typeparam>
|
||||
public abstract class FancyGridViewCell<TItemData, TContext> : FancyScrollRectCell<TItemData, TContext>
|
||||
where TContext : class, IFancyGridViewContext, new()
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override void UpdatePosition(float normalizedPosition, float localPosition)
|
||||
{
|
||||
var cellSize = Context.GetCellSize();
|
||||
var spacing = Context.GetStartAxisSpacing();
|
||||
var groupCount = Context.GetGroupCount();
|
||||
|
||||
var indexInGroup = Index % groupCount;
|
||||
var positionInGroup = (cellSize + spacing) * (indexInGroup - (groupCount - 1) * 0.5f);
|
||||
|
||||
transform.localPosition = Context.ScrollDirection == ScrollDirection.Horizontal
|
||||
? new Vector2(-localPosition, -positionInGroup)
|
||||
: new Vector2(positionInGroup, localPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="FancyGridView{TItemData}"/> のセルを実装するための抽象基底クラス.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <seealso cref="FancyGridViewCell{TItemData, TContext}"/>
|
||||
public abstract class FancyGridViewCell<TItemData> : FancyGridViewCell<TItemData, FancyGridViewContext>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public sealed override void SetContext(FancyGridViewContext context) => base.SetContext(context);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 84300901ad8704c11b39587ed6d87468
|
||||
guid: ab8a59bbf5118824ab084e32342ad86b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -8,16 +8,13 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <summary>
|
||||
/// <see cref="FancyGridView{TItemData, TContext}"/> のコンテキスト基底クラス.
|
||||
/// </summary>
|
||||
public class FancyGridViewContext : IFancyGridViewContext, IFancyScrollRectContext
|
||||
public class FancyGridViewContext : IFancyGridViewContext
|
||||
{
|
||||
ScrollDirection IFancyScrollRectContext.ScrollDirection { get; set; }
|
||||
Func<(float ScrollSize, float ReuseMargin)> IFancyScrollRectContext.CalculateScrollSize { get; set; }
|
||||
|
||||
GameObject IFancyGridViewContext.CellTemplate { get; set; }
|
||||
|
||||
ScrollDirection IFancyGridViewContext.ScrollDirection { get; set; }
|
||||
|
||||
public Func<int> GetColumnCount { get; set; }
|
||||
|
||||
public Func<float> GetColumnSpacing { get; set; }
|
||||
GameObject IFancyCellGroupContext.CellTemplate { get; set; }
|
||||
Func<int> IFancyCellGroupContext.GetGroupCount { get; set; }
|
||||
Func<float> IFancyGridViewContext.GetStartAxisSpacing { get; set; }
|
||||
Func<float> IFancyGridViewContext.GetCellSize { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/// Credit setchi (https://github.com/setchi)
|
||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="FancyGridView{TItemData, TContext}"/> の行を実装するための抽象基底クラス.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <typeparam name="TContext"><see cref="FancyScrollViewCell{TItemData, TContext}.Context"/> の型.</typeparam>
|
||||
public abstract class FancyGridViewRow<TItemData, TContext> : FancyScrollRectCell<TItemData[], TContext>
|
||||
where TContext : class, IFancyScrollRectContext, IFancyGridViewContext, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// この行で表示するセルの配列.
|
||||
/// </summary>
|
||||
protected virtual FancyScrollViewCell<TItemData, TContext>[] Cells { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// この行で表示するセルの配列をインスタンス化します.
|
||||
/// </summary>
|
||||
/// <returns>この行で表示するセルの配列.</returns>
|
||||
protected virtual FancyScrollViewCell<TItemData, TContext>[] InstantiateCells()
|
||||
{
|
||||
return Enumerable.Range(0, Context.GetColumnCount())
|
||||
.Select(_ => Instantiate(Context.CellTemplate, transform))
|
||||
.Select(x => x.GetComponent<FancyScrollViewCell<TItemData, TContext>>())
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetupContext(TContext context)
|
||||
{
|
||||
base.SetupContext(context);
|
||||
|
||||
Cells = InstantiateCells();
|
||||
Debug.Assert(Cells.Length == Context.GetColumnCount());
|
||||
|
||||
for (var i = 0; i < Cells.Length; i++)
|
||||
{
|
||||
Cells[i].SetupContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void UpdateContent(TItemData[] rowContents)
|
||||
{
|
||||
for (var i = 0; i < Cells.Length; i++)
|
||||
{
|
||||
Cells[i].Index = i + Index * Context.GetColumnCount();
|
||||
Cells[i].SetVisible(i < rowContents.Length);
|
||||
|
||||
if (Cells[i].IsVisible)
|
||||
{
|
||||
Cells[i].UpdateContent(rowContents[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void UpdatePosition(float position)
|
||||
{
|
||||
base.UpdatePosition(position);
|
||||
|
||||
for (var i = 0; i < Cells.Length; i++)
|
||||
{
|
||||
Cells[i].UpdatePosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void UpdatePosition(float position, float viewportPosition)
|
||||
{
|
||||
transform.localPosition = Context.ScrollDirection == ScrollDirection.Horizontal
|
||||
? new Vector2(viewportPosition, transform.localPosition.y)
|
||||
: new Vector2(transform.localPosition.x, viewportPosition);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/// Credit setchi (https://github.com/setchi)
|
||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="FancyCellGroup{TItemData, TContext}"/> のコンテキストインターフェース.
|
||||
/// </summary>
|
||||
public interface IFancyCellGroupContext
|
||||
{
|
||||
GameObject CellTemplate { get; set; }
|
||||
Func<int> GetGroupCount { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1dc086f250206754aa8449e252d50388
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -8,11 +8,9 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <summary>
|
||||
/// <see cref="FancyGridView{TItemData, TContext}"/> のコンテキストインターフェース.
|
||||
/// </summary>
|
||||
public interface IFancyGridViewContext
|
||||
public interface IFancyGridViewContext : IFancyScrollRectContext, IFancyCellGroupContext
|
||||
{
|
||||
GameObject CellTemplate { get; set; }
|
||||
ScrollDirection ScrollDirection { get; set; }
|
||||
Func<int> GetColumnCount { get; set; }
|
||||
Func<float> GetColumnSpacing { get; set; }
|
||||
Func<float> GetStartAxisSpacing { get; set; }
|
||||
Func<float> GetCellSize { get; set ; }
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
/// Credit setchi (https://github.com/setchi)
|
||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
public enum Alignment
|
||||
{
|
||||
Head,
|
||||
Center,
|
||||
Tail,
|
||||
}
|
||||
}
|
|
@ -39,10 +39,15 @@ namespace UnityEngine.UI.Extensions
|
|||
[SerializeField] protected float paddingTail = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// セル同士の余白.
|
||||
/// スクロール軸方向のセル同士の余白.
|
||||
/// </summary>
|
||||
[SerializeField] protected float spacing = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// セルのサイズ.
|
||||
/// </summary>
|
||||
protected abstract float CellSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// スクロール可能かどうか.
|
||||
/// </summary>
|
||||
|
@ -51,13 +56,6 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </remarks>
|
||||
protected virtual bool Scrollable => MaxScrollPosition > 0f;
|
||||
|
||||
/// <summary>
|
||||
/// セルのサイズ.
|
||||
/// </summary>
|
||||
protected virtual float CellSize => Scroller.ScrollDirection == ScrollDirection.Horizontal
|
||||
? CellRectTransform.rect.width
|
||||
: CellRectTransform.rect.height;
|
||||
|
||||
Scroller cachedScroller;
|
||||
|
||||
/// <summary>
|
||||
|
@ -68,9 +66,6 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </remarks>
|
||||
protected Scroller Scroller => cachedScroller ?? (cachedScroller = GetComponent<Scroller>());
|
||||
|
||||
RectTransform cachedCellRect;
|
||||
RectTransform CellRectTransform => cachedCellRect ?? (cachedCellRect = CellPrefab.transform as RectTransform);
|
||||
|
||||
float ScrollLength => 1f / Mathf.Max(cellInterval, 1e-2f) - 1f;
|
||||
|
||||
float ViewportLength => ScrollLength - reuseCellMarginCount * 2f;
|
||||
|
@ -87,6 +82,7 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
base.Initialize();
|
||||
|
||||
Context.ScrollDirection = Scroller.ScrollDirection;
|
||||
Context.CalculateScrollSize = () =>
|
||||
{
|
||||
var interval = CellSize + spacing;
|
||||
|
@ -138,6 +134,14 @@ namespace UnityEngine.UI.Extensions
|
|||
base.Refresh();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Relayout()
|
||||
{
|
||||
AdjustCellIntervalAndScrollOffset();
|
||||
RefreshScroller();
|
||||
base.Relayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Scroller"/> の各種状態を更新します.
|
||||
/// </summary>
|
||||
|
@ -172,17 +176,17 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="position">スクロール位置.</param>
|
||||
protected new void UpdatePosition(float position)
|
||||
{
|
||||
UpdatePosition(position, Alignment.Center);
|
||||
Scroller.Position = ToScrollerPosition(position, 0.5f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// スクロール位置を更新します.
|
||||
/// 指定したアイテムの位置までジャンプします.
|
||||
/// </summary>
|
||||
/// <param name="position">スクロール位置.</param>
|
||||
/// <param name="alignment"><see cref="Alignment"/>.</param>
|
||||
protected virtual void UpdatePosition(float position, Alignment alignment)
|
||||
/// <param name="itemIndex">アイテムのインデックス.</param>
|
||||
/// <param name="alignment">ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).</param>
|
||||
protected virtual void JumpTo(int itemIndex, float alignment = 0.5f)
|
||||
{
|
||||
Scroller.Position = ToScrollerPosition(position, alignment);
|
||||
Scroller.Position = ToScrollerPosition(itemIndex, alignment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -190,9 +194,9 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
/// <param name="index">アイテムのインデックス.</param>
|
||||
/// <param name="duration">移動にかける秒数.</param>
|
||||
/// <param name="alignment"><see cref="Alignment"/>.</param>
|
||||
/// <param name="alignment">ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).</param>
|
||||
/// <param name="onComplete">移動が完了した際に呼び出されるコールバック.</param>
|
||||
public virtual void ScrollTo(int index, float duration, Alignment alignment = Alignment.Center, Action onComplete = null)
|
||||
protected virtual void ScrollTo(int index, float duration, float alignment = 0.5f, Action onComplete = null)
|
||||
{
|
||||
Scroller.ScrollTo(ToScrollerPosition(index, alignment), duration, onComplete);
|
||||
}
|
||||
|
@ -203,9 +207,9 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="index">アイテムのインデックス.</param>
|
||||
/// <param name="duration">移動にかける秒数.</param>
|
||||
/// <param name="easing">移動に使用するイージング.</param>
|
||||
/// <param name="alignment"><see cref="Alignment"/>.</param>
|
||||
/// <param name="alignment">ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).</param>
|
||||
/// <param name="onComplete">移動が完了した際に呼び出されるコールバック.</param>
|
||||
public virtual void ScrollTo(int index, float duration, Ease easing, Alignment alignment = Alignment.Center, Action onComplete = null)
|
||||
protected virtual void ScrollTo(int index, float duration, Ease easing, float alignment = 0.5f, Action onComplete = null)
|
||||
{
|
||||
Scroller.ScrollTo(ToScrollerPosition(index, alignment), duration, easing, onComplete);
|
||||
}
|
||||
|
@ -244,25 +248,15 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <see cref="FancyScrollRect{TItemData, TContext}"/> が扱うスクロール位置を <see cref="Scroller"/> が扱うスクロール位置に変換します.
|
||||
/// </summary>
|
||||
/// <param name="position"><see cref="FancyScrollRect{TItemData, TContext}"/> が扱うスクロール位置.</param>
|
||||
/// <param name="alignment"><see cref="Alignment"/>.</param>
|
||||
/// <param name="alignment">ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).</param>
|
||||
/// <returns><see cref="Scroller"/> が扱うスクロール位置.</returns>
|
||||
protected float ToScrollerPosition(float position, Alignment alignment = Alignment.Center)
|
||||
protected float ToScrollerPosition(float position, float alignment = 0.5f)
|
||||
{
|
||||
var offset = (ScrollLength - (1f + reuseCellMarginCount * 2f)) * GetAnchore(alignment);
|
||||
var offset = alignment * (ScrollLength - (1f + reuseCellMarginCount * 2f))
|
||||
+ (1f - alignment - 0.5f) * spacing / (CellSize + spacing);
|
||||
return ToScrollerPosition(Mathf.Clamp(position - offset, 0f, MaxScrollPosition));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定された設定を実現するための
|
||||
/// <see cref="FancyScrollView{TItemData,TContext}.cellInterval"/> と
|
||||
|
@ -277,10 +271,7 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
if (CellPrefab)
|
||||
{
|
||||
AdjustCellIntervalAndScrollOffset();
|
||||
}
|
||||
AdjustCellIntervalAndScrollOffset();
|
||||
|
||||
if (loop)
|
||||
{
|
||||
|
|
|
@ -5,12 +5,12 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
/// <summary>
|
||||
/// <see cref="FancyScrollRect{TItemData, TContext}"/> のセルを実装するための抽象基底クラス.
|
||||
/// <see cref="FancyScrollViewCell{TItemData, TContext}.Context"/> が不要な場合は
|
||||
/// <see cref="FancyCell{TItemData, TContext}.Context"/> が不要な場合は
|
||||
/// 代わりに <see cref="FancyScrollRectCell{TItemData}"/> を使用します.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItemData">アイテムのデータ型.</typeparam>
|
||||
/// <typeparam name="TContext"><see cref="FancyScrollViewCell{TItemData, TContext}.Context"/> の型.</typeparam>
|
||||
public abstract class FancyScrollRectCell<TItemData, TContext> : FancyScrollViewCell<TItemData, TContext>
|
||||
/// <typeparam name="TContext"><see cref="FancyCell{TItemData, TContext}.Context"/> の型.</typeparam>
|
||||
public abstract class FancyScrollRectCell<TItemData, TContext> : FancyCell<TItemData, TContext>
|
||||
where TContext : class, IFancyScrollRectContext, new()
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
|
@ -18,24 +18,29 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
var (scrollSize, reuseMargin) = Context.CalculateScrollSize();
|
||||
|
||||
var unclampedPosition = (Mathf.Lerp(0f, scrollSize, position) - reuseMargin) / (scrollSize - reuseMargin * 2f);
|
||||
var normalizedPosition = (Mathf.Lerp(0f, scrollSize, position) - reuseMargin) / (scrollSize - reuseMargin * 2f);
|
||||
|
||||
var start = 0.5f * scrollSize;
|
||||
var end = -start;
|
||||
|
||||
UpdatePosition(unclampedPosition, Mathf.Lerp(start, end, position));
|
||||
UpdatePosition(normalizedPosition, Mathf.Lerp(start, end, position));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// このセルの位置を更新します.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// <param name="normalizedPosition">
|
||||
/// ビューポートの範囲で正規化されたスクロール位置.
|
||||
/// <see cref="FancyScrollRect{TItemData, TContext}.reuseCellMarginCount"/> の値に基づいて
|
||||
/// <c>0.0</c> ~ <c>1.0</c> の範囲を超えた値が渡されることがあります.
|
||||
/// </param>
|
||||
/// <param name="viewportPosition">ローカル位置.</param>
|
||||
protected virtual void UpdatePosition(float position, float viewportPosition) { }
|
||||
/// <param name="localPosition">ローカル位置.</param>
|
||||
protected virtual void UpdatePosition(float normalizedPosition, float localPosition)
|
||||
{
|
||||
transform.localPosition = Context.ScrollDirection == ScrollDirection.Horizontal
|
||||
? new Vector2(-localPosition, 0)
|
||||
: new Vector2(0, localPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -46,6 +51,6 @@ namespace UnityEngine.UI.Extensions
|
|||
public abstract class FancyScrollRectCell<TItemData> : FancyScrollRectCell<TItemData, FancyScrollRectContext>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public sealed override void SetupContext(FancyScrollRectContext context) => base.SetupContext(context);
|
||||
public sealed override void SetContext(FancyScrollRectContext context) => base.SetContext(context);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
public class FancyScrollRectContext : IFancyScrollRectContext
|
||||
{
|
||||
ScrollDirection IFancyScrollRectContext.ScrollDirection { get; set; }
|
||||
Func<(float ScrollSize, float ReuseMargin)> IFancyScrollRectContext.CalculateScrollSize { get; set; }
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
public interface IFancyScrollRectContext
|
||||
{
|
||||
ScrollDirection ScrollDirection { get; set; }
|
||||
Func<(float ScrollSize, float ReuseMargin)> CalculateScrollSize { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,30 +1,8 @@
|
|||
//
|
||||
// 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;
|
||||
/*
|
||||
* EasingCore (https://github.com/setchi/EasingCore)
|
||||
* Copyright (c) 2020 setchi
|
||||
* Licensed under MIT (https://github.com/setchi/EasingCore/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
namespace UnityEngine.UI.Extensions.EasingCore
|
||||
{
|
||||
|
@ -63,14 +41,16 @@ namespace UnityEngine.UI.Extensions.EasingCore
|
|||
InOutSine,
|
||||
}
|
||||
|
||||
public static class EasingFunction
|
||||
public delegate float EasingFunction(float t);
|
||||
|
||||
public static class Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the easing function
|
||||
/// </summary>
|
||||
/// <param name="type">Ease type</param>
|
||||
/// <returns>Easing function</returns>
|
||||
public static Func<float, float> Get(Ease type)
|
||||
public static EasingFunction Get(Ease type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
@ -170,7 +150,7 @@ namespace UnityEngine.UI.Extensions.EasingCore
|
|||
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)
|
||||
: -0.5f * Mathf.Pow(2f, (-20f * v) + 10f) + 1f;
|
||||
|
||||
float inQuad(float t) => t * t;
|
||||
|
@ -179,7 +159,7 @@ namespace UnityEngine.UI.Extensions.EasingCore
|
|||
|
||||
float inOutQuad(float t) =>
|
||||
t < 0.5f
|
||||
? 2f * t * t
|
||||
? 2f * t * t
|
||||
: -2f * t * t + 4f * t - 1f;
|
||||
|
||||
float inQuart(float t) => t * t * t * t;
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <summary>
|
||||
/// スクロール位置の制御を行うコンポーネント.
|
||||
/// </summary>
|
||||
public class Scroller : UIBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
|
||||
public class Scroller : UIBehaviour, IPointerUpHandler, IPointerDownHandler, IBeginDragHandler, IEndDragHandler, IDragHandler, IScrollHandler
|
||||
{
|
||||
[SerializeField] RectTransform viewport = default;
|
||||
|
||||
|
@ -83,9 +83,7 @@ namespace UnityEngine.UI.Extensions
|
|||
set => decelerationRate = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
Snap snap = new Snap
|
||||
{
|
||||
[SerializeField] Snap snap = new Snap {
|
||||
Enable = true,
|
||||
VelocityThreshold = 0.5f,
|
||||
Duration = 0.3f,
|
||||
|
@ -151,6 +149,8 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
int totalCount;
|
||||
|
||||
bool hold;
|
||||
bool scrolling;
|
||||
bool dragging;
|
||||
float velocity;
|
||||
|
||||
|
@ -163,14 +163,14 @@ namespace UnityEngine.UI.Extensions
|
|||
public Ease Easing;
|
||||
}
|
||||
|
||||
static readonly Func<float, float> DefaultEasingFunction = EasingFunction.Get(Ease.OutCubic);
|
||||
static readonly EasingFunction DefaultEasingFunction = Easing.Get(Ease.OutCubic);
|
||||
|
||||
class AutoScrollState
|
||||
{
|
||||
public bool Enable;
|
||||
public bool Elastic;
|
||||
public float Duration;
|
||||
public Func<float, float> EasingFunction;
|
||||
public EasingFunction EasingFunction;
|
||||
public float StartTime;
|
||||
public float EndPosition;
|
||||
|
||||
|
@ -240,7 +240,7 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="duration">移動にかける秒数.</param>
|
||||
/// <param name="easing">移動に使用するイージング.</param>
|
||||
/// <param name="onComplete">移動が完了した際に呼び出されるコールバック.</param>
|
||||
public void ScrollTo(float position, float duration, Ease easing, Action onComplete = null) => ScrollTo(position, duration, EasingFunction.Get(easing), onComplete);
|
||||
public void ScrollTo(float position, float duration, Ease easing, Action onComplete = null) => ScrollTo(position, duration, Easing.Get(easing), onComplete);
|
||||
|
||||
/// <summary>
|
||||
/// 指定した位置まで移動します.
|
||||
|
@ -249,7 +249,7 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="duration">移動にかける秒数.</param>
|
||||
/// <param name="easingFunction">移動に使用するイージング関数.</param>
|
||||
/// <param name="onComplete">移動が完了した際に呼び出されるコールバック.</param>
|
||||
public void ScrollTo(float position, float duration, Func<float, float> easingFunction, Action onComplete = null)
|
||||
public void ScrollTo(float position, float duration, EasingFunction easingFunction, Action onComplete = null)
|
||||
{
|
||||
if (duration <= 0f)
|
||||
{
|
||||
|
@ -283,13 +283,8 @@ namespace UnityEngine.UI.Extensions
|
|||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
autoScrollState.Reset();
|
||||
|
||||
velocity = 0f;
|
||||
dragging = false;
|
||||
|
||||
UpdateSelection(index);
|
||||
UpdatePosition(index);
|
||||
Position = index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -311,6 +306,75 @@ namespace UnityEngine.UI.Extensions
|
|||
: MovementDirection.Down;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (!draggable || eventData.button != PointerEventData.InputButton.Left)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hold = true;
|
||||
velocity = 0f;
|
||||
autoScrollState.Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
if (!draggable || eventData.button != PointerEventData.InputButton.Left)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (hold && snap.Enable)
|
||||
{
|
||||
UpdateSelection(Mathf.Clamp(Mathf.RoundToInt(currentPosition), 0, totalCount - 1));
|
||||
ScrollTo(Mathf.RoundToInt(currentPosition), snap.Duration, snap.Easing);
|
||||
}
|
||||
|
||||
hold = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IScrollHandler.OnScroll(PointerEventData eventData)
|
||||
{
|
||||
if (!draggable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var delta = eventData.scrollDelta;
|
||||
|
||||
// Down is positive for scroll events, while in UI system up is positive.
|
||||
delta.y *= -1;
|
||||
var scrollDelta = scrollDirection == ScrollDirection.Horizontal
|
||||
? Mathf.Abs(delta.y) > Mathf.Abs(delta.x)
|
||||
? delta.y
|
||||
: delta.x
|
||||
: Mathf.Abs(delta.x) > Mathf.Abs(delta.y)
|
||||
? delta.x
|
||||
: delta.y;
|
||||
|
||||
if (eventData.IsScrolling())
|
||||
{
|
||||
scrolling = true;
|
||||
}
|
||||
|
||||
var position = currentPosition + scrollDelta / ViewportSize * scrollSensitivity;
|
||||
if (movementType == MovementType.Clamped)
|
||||
{
|
||||
position += CalculateOffset(position);
|
||||
}
|
||||
|
||||
if (autoScrollState.Enable)
|
||||
{
|
||||
autoScrollState.Reset();
|
||||
}
|
||||
|
||||
UpdatePosition(position);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IBeginDragHandler.OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
|
@ -319,6 +383,7 @@ namespace UnityEngine.UI.Extensions
|
|||
return;
|
||||
}
|
||||
|
||||
hold = false;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
viewport,
|
||||
eventData.position,
|
||||
|
@ -449,7 +514,7 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
UpdatePosition(position);
|
||||
}
|
||||
else if (!dragging && (!Mathf.Approximately(offset, 0f) || !Mathf.Approximately(velocity, 0f)))
|
||||
else if (!(dragging || scrolling) && (!Mathf.Approximately(offset, 0f) || !Mathf.Approximately(velocity, 0f)))
|
||||
{
|
||||
var position = currentPosition;
|
||||
|
||||
|
@ -500,13 +565,14 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
if (!autoScrollState.Enable && dragging && inertia)
|
||||
if (!autoScrollState.Enable && (dragging || scrolling) && inertia)
|
||||
{
|
||||
var newVelocity = (currentPosition - prevPosition) / deltaTime;
|
||||
velocity = Mathf.Lerp(velocity, newVelocity, deltaTime * 10f);
|
||||
}
|
||||
|
||||
prevPosition = currentPosition;
|
||||
scrolling = false;
|
||||
}
|
||||
|
||||
float CalculateMovementAmount(float sourcePosition, float destPosition)
|
||||
|
|
Loading…
Reference in New Issue