diff --git a/Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollViewCell.cs b/Runtime/Scripts/Layout/FancyScrollView/Core/FancyCell.cs
similarity index 75%
rename from Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollViewCell.cs
rename to Runtime/Scripts/Layout/FancyScrollView/Core/FancyCell.cs
index 676a9a7..17928d1 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollViewCell.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/Core/FancyCell.cs
@@ -1,16 +1,17 @@
/// Credit setchi (https://github.com/setchi)
/// Sourced from - https://github.com/setchi/FancyScrollView
+
namespace UnityEngine.UI.Extensions
{
///
/// のセルを実装するための抽象基底クラス.
- /// が不要な場合は
- /// 代わりに を使用します.
+ /// が不要な場合は
+ /// 代わりに を使用します.
///
/// アイテムのデータ型.
/// の型.
- public abstract class FancyScrollViewCell : MonoBehaviour where TContext : class, new()
+ public abstract class FancyCell : MonoBehaviour where TContext : class, new()
{
///
/// このセルで表示しているデータのインデックス.
@@ -29,10 +30,15 @@ namespace UnityEngine.UI.Extensions
protected TContext Context { get; private set; }
///
- /// のセットアップを行います.
+ /// をセットします.
///
/// コンテキスト.
- public virtual void SetupContext(TContext context) => Context = context;
+ public virtual void SetContext(TContext context) => Context = context;
+
+ ///
+ /// 初期化を行います.
+ ///
+ public virtual void Initialize() { }
///
/// このセルの可視状態を設定します.
@@ -57,10 +63,10 @@ namespace UnityEngine.UI.Extensions
/// のセルを実装するための抽象基底クラス.
///
/// アイテムのデータ型.
- ///
- public abstract class FancyScrollViewCell : FancyScrollViewCell
+ ///
+ public abstract class FancyCell : FancyCell
{
///
- public sealed override void SetupContext(FancyScrollViewNullContext context) => base.SetupContext(context);
+ public sealed override void SetContext(NullContext context) => base.SetContext(context);
}
}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollViewCell.cs.meta b/Runtime/Scripts/Layout/FancyScrollView/Core/FancyCell.cs.meta
similarity index 100%
rename from Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollViewCell.cs.meta
rename to Runtime/Scripts/Layout/FancyScrollView/Core/FancyCell.cs.meta
diff --git a/Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollView.cs b/Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollView.cs
index a225142..df3f942 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollView.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/Core/FancyScrollView.cs
@@ -42,8 +42,7 @@ namespace UnityEngine.UI.Extensions
///
[SerializeField] protected Transform cellContainer = default;
- readonly IList> pool =
- new List>();
+ readonly IList> pool = new List>();
///
/// 初期化済みかどうか.
@@ -90,7 +89,12 @@ namespace UnityEngine.UI.Extensions
}
///
- /// セルの表示内容を更新します.
+ /// セルのレイアウトを強制的に更新します.
+ ///
+ protected virtual void Relayout() => UpdatePosition(currentPosition, false);
+
+ ///
+ /// セルのレイアウトと表示内容を強制的に更新します.
///
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>();
+ var cell = Instantiate(CellPrefab, cellContainer).GetComponent>();
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
///
/// のコンテキストクラス.
///
- public sealed class FancyScrollViewNullContext { }
+ public sealed class NullContext { }
///
/// スクロールビューを実装するための抽象基底クラス.
@@ -208,5 +212,5 @@ namespace UnityEngine.UI.Extensions
///
///
///
- public abstract class FancyScrollView : FancyScrollView { }
+ public abstract class FancyScrollView : FancyScrollView { }
}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyCellGroup.cs b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyCellGroup.cs
new file mode 100644
index 0000000..5aa3698
--- /dev/null
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyCellGroup.cs
@@ -0,0 +1,72 @@
+/// Credit setchi (https://github.com/setchi)
+/// Sourced from - https://github.com/setchi/FancyScrollView
+
+using System.Linq;
+
+namespace UnityEngine.UI.Extensions
+{
+ ///
+ /// 複数の を持つセルグループ実装するための抽象基底クラス.
+ ///
+ /// アイテムのデータ型.
+ /// の型.
+ public abstract class FancyCellGroup : FancyCell
+ where TContext : class, IFancyCellGroupContext, new()
+ {
+ ///
+ /// このグループで表示するセルの配列.
+ ///
+ protected virtual FancyCell[] Cells { get; private set; }
+
+ ///
+ /// このグループで表示するセルの配列をインスタンス化します.
+ ///
+ /// このグループで表示するセルの配列.
+ protected virtual FancyCell[] InstantiateCells()
+ {
+ return Enumerable.Range(0, Context.GetGroupCount())
+ .Select(_ => Instantiate(Context.CellTemplate, transform))
+ .Select(x => x.GetComponent>())
+ .ToArray();
+ }
+
+ ///
+ 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();
+ }
+ }
+
+ ///
+ 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]);
+ }
+ }
+ }
+
+ ///
+ public override void UpdatePosition(float position)
+ {
+ for (var i = 0; i < Cells.Length; i++)
+ {
+ Cells[i].UpdatePosition(position);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/Alignment.cs.meta b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyCellGroup.cs.meta
similarity index 83%
rename from Runtime/Scripts/Layout/FancyScrollView/ScrollRect/Alignment.cs.meta
rename to Runtime/Scripts/Layout/FancyScrollView/GridView/FancyCellGroup.cs.meta
index 9c0ac48..65a825d 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/Alignment.cs.meta
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyCellGroup.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 3e786463ba934403cacf7e8c0d5822d7
+guid: 5d97e25c7748b8d44acd2298e509c8f1
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridView.cs b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridView.cs
index e74f517..4e1417b 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridView.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridView.cs
@@ -11,77 +11,106 @@ namespace UnityEngine.UI.Extensions
///
/// グリッドレイアウトのスクロールビューを実装するための抽象基底クラス.
/// 無限スクロールおよびスナップには対応していません.
+ /// が不要な場合は
+ /// 代わりに を使用します.
///
/// アイテムのデータ型.
/// の型.
public abstract class FancyGridView : FancyScrollRect
- where TContext : class, IFancyScrollRectContext, IFancyGridViewContext, new()
+ where TContext : class, IFancyGridViewContext, new()
{
///
- /// カラム同士の余白.
+ /// デフォルトのセルグループクラス.
///
- [SerializeField] protected float columnSpacing = 0f;
-
- GameObject cachedRowPrefab;
+ protected abstract class DefaultCellGroup : FancyCellGroup { }
///
- /// 行の Prefab.
+ /// 最初にセルを配置する軸方向のセル同士の余白.
+ ///
+ [SerializeField] protected float startAxisSpacing = 0f;
+
+ ///
+ /// 最初にセルを配置する軸方向のセル数.
+ ///
+ [SerializeField] protected int startAxisCellCount = 4;
+
+ ///
+ /// セルのサイズ.
+ ///
+ [SerializeField] protected Vector2 cellSize = new Vector2(100f, 100f);
+
+ ///
+ /// セルのグループ Prefab.
///
///
/// では,
- /// を行オブジェクトとして使用します.
+ /// を最初にセルを配置する軸方向のセルコンテナとして使用します.
///
- protected sealed override GameObject CellPrefab => cachedRowPrefab ?? (cachedRowPrefab = SetupRowTemplate());
+ protected sealed override GameObject CellPrefab => cellGroupTemplate;
- ///
- /// 一行あたりの要素数.
- ///
- protected abstract int ColumnCount { get; }
-
- ///
- /// セルのテンプレート.
- ///
- protected abstract FancyScrollViewCell CellTemplate { get; }
-
- ///
- /// 行オブジェクトのテンプレート.
- ///
- protected abstract FancyGridViewRow RowTemplate { get; }
+ ///
+ protected override float CellSize => Scroller.ScrollDirection == ScrollDirection.Horizontal
+ ? cellSize.x
+ : cellSize.y;
///
/// アイテムの総数.
///
public int DataCount { get; private set; }
+ GameObject cellGroupTemplate;
+
///
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();
}
///
- /// 行オブジェクトのセットアップを行います.
+ /// 最初にセルが生成される直前に呼び出されます.
+ /// メソッドを使用してセルテンプレートのセットアップを行ってください.
///
- /// 行を構成する GameObject.
- protected virtual GameObject SetupRowTemplate()
+ ///
+ ///
+ /// {
+ /// class CellGroup : DefaultCellGroup { }
+ ///
+ /// [SerializeField] Cell cellPrefab = default;
+ ///
+ /// protected override void SetupCellTemplate() => Setup(cellPrefab);
+ /// }
+ /// ]]>
+ ///
+ protected abstract void SetupCellTemplate();
+
+ ///
+ /// セルテンプレートのセットアップを行います.
+ ///
+ /// セルのテンプレート.
+ /// セルグループの型.
+ protected virtual void Setup(FancyCell cellTemplate)
+ where TGroup : FancyCell
{
- var cell = CellTemplate.GetComponent();
- var row = RowTemplate.GetComponent();
+ 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().gameObject;
+ cellGroupTemplate.transform.SetParent(cellContainer, false);
+ cellGroupTemplate.SetActive(false);
}
///
@@ -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);
+ }
+
+ ///
+ /// 指定したアイテムの位置までジャンプします.
+ ///
+ /// アイテムのインデックス.
+ /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).
+ protected override void JumpTo(int itemIndex, float alignment = 0.5f)
+ {
+ var groupIndex = itemIndex / startAxisCellCount;
+ base.JumpTo(groupIndex, alignment);
}
///
@@ -108,12 +148,12 @@ namespace UnityEngine.UI.Extensions
///
/// アイテムのインデックス.
/// 移動にかける秒数.
- /// .
+ /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).
/// 移動が完了した際に呼び出されるコールバック.
- 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);
}
///
@@ -122,23 +162,20 @@ namespace UnityEngine.UI.Extensions
/// アイテムのインデックス.
/// 移動にかける秒数.
/// 移動に使用するイージング.
- /// .
+ /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).
/// 移動が完了した際に呼び出されるコールバック.
- 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);
- }
-
- ///
- /// 指定したアイテムの位置までジャンプします.
- ///
- /// アイテムのインデックス.
- /// .
- 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);
}
}
+
+ ///
+ /// グリッドレイアウトのスクロールビューを実装するための抽象基底クラス.
+ /// 無限スクロールおよびスナップには対応していません.
+ ///
+ /// アイテムのデータ型.
+ ///
+ public abstract class FancyGridView : FancyGridView { }
}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewCell.cs b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewCell.cs
new file mode 100644
index 0000000..0e78f0f
--- /dev/null
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewCell.cs
@@ -0,0 +1,42 @@
+/// Credit setchi (https://github.com/setchi)
+/// Sourced from - https://github.com/setchi/FancyScrollView
+
+namespace UnityEngine.UI.Extensions
+{
+ ///
+ /// のセルを実装するための抽象基底クラス.
+ /// が不要な場合は
+ /// 代わりに を使用します.
+ ///
+ /// アイテムのデータ型.
+ /// の型.
+ public abstract class FancyGridViewCell : FancyScrollRectCell
+ where TContext : class, IFancyGridViewContext, new()
+ {
+ ///
+ 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);
+ }
+ }
+
+ ///
+ /// のセルを実装するための抽象基底クラス.
+ ///
+ /// アイテムのデータ型.
+ ///
+ public abstract class FancyGridViewCell : FancyGridViewCell
+ {
+ ///
+ public sealed override void SetContext(FancyGridViewContext context) => base.SetContext(context);
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewRow.cs.meta b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewCell.cs.meta
similarity index 83%
rename from Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewRow.cs.meta
rename to Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewCell.cs.meta
index dbcb384..8320c0a 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewRow.cs.meta
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewCell.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 84300901ad8704c11b39587ed6d87468
+guid: ab8a59bbf5118824ab084e32342ad86b
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewContext.cs b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewContext.cs
index 05090c8..eb5de46 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewContext.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewContext.cs
@@ -8,16 +8,13 @@ namespace UnityEngine.UI.Extensions
///
/// のコンテキスト基底クラス.
///
- 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 GetColumnCount { get; set; }
-
- public Func GetColumnSpacing { get; set; }
+ GameObject IFancyCellGroupContext.CellTemplate { get; set; }
+ Func IFancyCellGroupContext.GetGroupCount { get; set; }
+ Func IFancyGridViewContext.GetStartAxisSpacing { get; set; }
+ Func IFancyGridViewContext.GetCellSize { get; set; }
}
}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewRow.cs b/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewRow.cs
deleted file mode 100644
index 3613bce..0000000
--- a/Runtime/Scripts/Layout/FancyScrollView/GridView/FancyGridViewRow.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-/// Credit setchi (https://github.com/setchi)
-/// Sourced from - https://github.com/setchi/FancyScrollView
-
-using System.Linq;
-
-namespace UnityEngine.UI.Extensions
-{
- ///
- /// の行を実装するための抽象基底クラス.
- ///
- /// アイテムのデータ型.
- /// の型.
- public abstract class FancyGridViewRow : FancyScrollRectCell
- where TContext : class, IFancyScrollRectContext, IFancyGridViewContext, new()
- {
- ///
- /// この行で表示するセルの配列.
- ///
- protected virtual FancyScrollViewCell[] Cells { get; private set; }
-
- ///
- /// この行で表示するセルの配列をインスタンス化します.
- ///
- /// この行で表示するセルの配列.
- protected virtual FancyScrollViewCell[] InstantiateCells()
- {
- return Enumerable.Range(0, Context.GetColumnCount())
- .Select(_ => Instantiate(Context.CellTemplate, transform))
- .Select(x => x.GetComponent>())
- .ToArray();
- }
-
- ///
- 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);
- }
- }
-
- ///
- 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]);
- }
- }
- }
-
- ///
- public override void UpdatePosition(float position)
- {
- base.UpdatePosition(position);
-
- for (var i = 0; i < Cells.Length; i++)
- {
- Cells[i].UpdatePosition(position);
- }
- }
-
- ///
- 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);
- }
- }
-}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyCellGroupContext.cs b/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyCellGroupContext.cs
new file mode 100644
index 0000000..07854ce
--- /dev/null
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyCellGroupContext.cs
@@ -0,0 +1,16 @@
+/// Credit setchi (https://github.com/setchi)
+/// Sourced from - https://github.com/setchi/FancyScrollView
+
+using System;
+
+namespace UnityEngine.UI.Extensions
+{
+ ///
+ /// のコンテキストインターフェース.
+ ///
+ public interface IFancyCellGroupContext
+ {
+ GameObject CellTemplate { get; set; }
+ Func GetGroupCount { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyCellGroupContext.cs.meta b/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyCellGroupContext.cs.meta
new file mode 100644
index 0000000..1733d84
--- /dev/null
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyCellGroupContext.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1dc086f250206754aa8449e252d50388
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyGridViewContext.cs b/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyGridViewContext.cs
index 70221da..33adb1b 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyGridViewContext.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/GridView/IFancyGridViewContext.cs
@@ -8,11 +8,9 @@ namespace UnityEngine.UI.Extensions
///
/// のコンテキストインターフェース.
///
- public interface IFancyGridViewContext
+ public interface IFancyGridViewContext : IFancyScrollRectContext, IFancyCellGroupContext
{
- GameObject CellTemplate { get; set; }
- ScrollDirection ScrollDirection { get; set; }
- Func GetColumnCount { get; set; }
- Func GetColumnSpacing { get; set; }
+ Func GetStartAxisSpacing { get; set; }
+ Func GetCellSize { get; set ; }
}
}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/Alignment.cs b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/Alignment.cs
deleted file mode 100644
index d3c1566..0000000
--- a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/Alignment.cs
+++ /dev/null
@@ -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,
- }
-}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRect.cs b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRect.cs
index 54b5a66..57ba6bb 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRect.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRect.cs
@@ -39,10 +39,15 @@ namespace UnityEngine.UI.Extensions
[SerializeField] protected float paddingTail = 0f;
///
- /// セル同士の余白.
+ /// スクロール軸方向のセル同士の余白.
///
[SerializeField] protected float spacing = 0f;
+ ///
+ /// セルのサイズ.
+ ///
+ protected abstract float CellSize { get; }
+
///
/// スクロール可能かどうか.
///
@@ -51,13 +56,6 @@ namespace UnityEngine.UI.Extensions
///
protected virtual bool Scrollable => MaxScrollPosition > 0f;
- ///
- /// セルのサイズ.
- ///
- protected virtual float CellSize => Scroller.ScrollDirection == ScrollDirection.Horizontal
- ? CellRectTransform.rect.width
- : CellRectTransform.rect.height;
-
Scroller cachedScroller;
///
@@ -68,9 +66,6 @@ namespace UnityEngine.UI.Extensions
///
protected Scroller Scroller => cachedScroller ?? (cachedScroller = GetComponent());
- 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();
}
+ ///
+ protected override void Relayout()
+ {
+ AdjustCellIntervalAndScrollOffset();
+ RefreshScroller();
+ base.Relayout();
+ }
+
///
/// の各種状態を更新します.
///
@@ -172,17 +176,17 @@ namespace UnityEngine.UI.Extensions
/// スクロール位置.
protected new void UpdatePosition(float position)
{
- UpdatePosition(position, Alignment.Center);
+ Scroller.Position = ToScrollerPosition(position, 0.5f);
}
///
- /// スクロール位置を更新します.
+ /// 指定したアイテムの位置までジャンプします.
///
- /// スクロール位置.
- /// .
- protected virtual void UpdatePosition(float position, Alignment alignment)
+ /// アイテムのインデックス.
+ /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).
+ protected virtual void JumpTo(int itemIndex, float alignment = 0.5f)
{
- Scroller.Position = ToScrollerPosition(position, alignment);
+ Scroller.Position = ToScrollerPosition(itemIndex, alignment);
}
///
@@ -190,9 +194,9 @@ namespace UnityEngine.UI.Extensions
///
/// アイテムのインデックス.
/// 移動にかける秒数.
- /// .
+ /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).
/// 移動が完了した際に呼び出されるコールバック.
- 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
/// アイテムのインデックス.
/// 移動にかける秒数.
/// 移動に使用するイージング.
- /// .
+ /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).
/// 移動が完了した際に呼び出されるコールバック.
- 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
/// が扱うスクロール位置を が扱うスクロール位置に変換します.
///
/// が扱うスクロール位置.
- /// .
+ /// ビューポート内におけるセル位置の基準. 0f(先頭) ~ 1f(末尾).
/// が扱うスクロール位置.
- 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);
- }
- }
-
///
/// 指定された設定を実現するための
/// と
@@ -277,10 +271,7 @@ namespace UnityEngine.UI.Extensions
protected virtual void OnValidate()
{
- if (CellPrefab)
- {
- AdjustCellIntervalAndScrollOffset();
- }
+ AdjustCellIntervalAndScrollOffset();
if (loop)
{
diff --git a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRectCell.cs b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRectCell.cs
index 4e368c9..4b25d5b 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRectCell.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRectCell.cs
@@ -5,12 +5,12 @@ namespace UnityEngine.UI.Extensions
{
///
/// のセルを実装するための抽象基底クラス.
- /// が不要な場合は
+ /// が不要な場合は
/// 代わりに を使用します.
///
/// アイテムのデータ型.
- /// の型.
- public abstract class FancyScrollRectCell : FancyScrollViewCell
+ /// の型.
+ public abstract class FancyScrollRectCell : FancyCell
where TContext : class, IFancyScrollRectContext, new()
{
///
@@ -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));
}
///
/// このセルの位置を更新します.
///
- ///
+ ///
/// ビューポートの範囲で正規化されたスクロール位置.
/// の値に基づいて
/// 0.0 ~ 1.0 の範囲を超えた値が渡されることがあります.
///
- /// ローカル位置.
- protected virtual void UpdatePosition(float position, float viewportPosition) { }
+ /// ローカル位置.
+ protected virtual void UpdatePosition(float normalizedPosition, float localPosition)
+ {
+ transform.localPosition = Context.ScrollDirection == ScrollDirection.Horizontal
+ ? new Vector2(-localPosition, 0)
+ : new Vector2(0, localPosition);
+ }
}
///
@@ -46,6 +51,6 @@ namespace UnityEngine.UI.Extensions
public abstract class FancyScrollRectCell : FancyScrollRectCell
{
///
- public sealed override void SetupContext(FancyScrollRectContext context) => base.SetupContext(context);
+ public sealed override void SetContext(FancyScrollRectContext context) => base.SetContext(context);
}
-}
\ No newline at end of file
+}
diff --git a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRectContext.cs b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRectContext.cs
index 17c113f..8b1b0c3 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRectContext.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/FancyScrollRectContext.cs
@@ -10,6 +10,7 @@ namespace UnityEngine.UI.Extensions
///
public class FancyScrollRectContext : IFancyScrollRectContext
{
+ ScrollDirection IFancyScrollRectContext.ScrollDirection { get; set; }
Func<(float ScrollSize, float ReuseMargin)> IFancyScrollRectContext.CalculateScrollSize { get; set; }
}
}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/IFancyScrollRectContext.cs b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/IFancyScrollRectContext.cs
index 0a83479..e40396e 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/IFancyScrollRectContext.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/ScrollRect/IFancyScrollRectContext.cs
@@ -10,6 +10,7 @@ namespace UnityEngine.UI.Extensions
///
public interface IFancyScrollRectContext
{
+ ScrollDirection ScrollDirection { get; set; }
Func<(float ScrollSize, float ReuseMargin)> CalculateScrollSize { get; set; }
}
}
\ No newline at end of file
diff --git a/Runtime/Scripts/Layout/FancyScrollView/Scroller/EasingCore.cs b/Runtime/Scripts/Layout/FancyScrollView/Scroller/EasingCore.cs
index e6b1626..9828a81 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/Scroller/EasingCore.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/Scroller/EasingCore.cs
@@ -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
{
///
/// Gets the easing function
///
/// Ease type
/// Easing function
- public static Func 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;
diff --git a/Runtime/Scripts/Layout/FancyScrollView/Scroller/Scroller.cs b/Runtime/Scripts/Layout/FancyScrollView/Scroller/Scroller.cs
index 262cabc..ea0c276 100644
--- a/Runtime/Scripts/Layout/FancyScrollView/Scroller/Scroller.cs
+++ b/Runtime/Scripts/Layout/FancyScrollView/Scroller/Scroller.cs
@@ -10,7 +10,7 @@ namespace UnityEngine.UI.Extensions
///
/// スクロール位置の制御を行うコンポーネント.
///
- 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 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 EasingFunction;
+ public EasingFunction EasingFunction;
public float StartTime;
public float EndPosition;
@@ -240,7 +240,7 @@ namespace UnityEngine.UI.Extensions
/// 移動にかける秒数.
/// 移動に使用するイージング.
/// 移動が完了した際に呼び出されるコールバック.
- 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);
///
/// 指定した位置まで移動します.
@@ -249,7 +249,7 @@ namespace UnityEngine.UI.Extensions
/// 移動にかける秒数.
/// 移動に使用するイージング関数.
/// 移動が完了した際に呼び出されるコールバック.
- public void ScrollTo(float position, float duration, Func 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;
}
///
@@ -311,6 +306,75 @@ namespace UnityEngine.UI.Extensions
: MovementDirection.Down;
}
+ ///
+ void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
+ {
+ if (!draggable || eventData.button != PointerEventData.InputButton.Left)
+ {
+ return;
+ }
+
+ hold = true;
+ velocity = 0f;
+ autoScrollState.Reset();
+ }
+
+ ///
+ 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;
+ }
+
+ ///
+ 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);
+ }
+
///
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)