123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956 |
- using CommonLang;
- using CommonLang.Property;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using UnityEngine;
- using UnityEngine.EventSystems;
- using UnityEngine.UI;
- namespace CommonUnity3D.UGUI
- { //----------------------------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 普通滑动控件
- /// </summary>
- public class ScrollablePanel : DisplayNode
- {
- protected readonly DisplayNode mContent;
- protected readonly RectMask2D mRectMask;
- protected readonly Image mMaskGraphics;
- protected readonly ScrollRectInteractive mMaskScrollRect;
- //protected readonly Mask mMask;
- public ScrollRectInteractive Scroll
- {
- get { return mMaskScrollRect; }
- }
- public Rect ScrollRect2D
- {
- get { return mMaskScrollRect.ScrollRect2D; }
- }
- public DisplayNode Container
- {
- get { return mContent; }
- }
- public bool ShowSlider
- {
- get { return mMaskScrollRect.ShowSlider; }
- set { mMaskScrollRect.ShowSlider = value; }
- }
- public float ScrollFadeTimeMaxMS
- {
- get { return mMaskScrollRect.ScrollFadeTimeMaxMS; }
- set { mMaskScrollRect.ScrollFadeTimeMaxMS = value; }
- }
- public ScrollablePanel(string name = null) : base(name)
- {
- this.EnableChildren = true;
- this.mContent = new DisplayNode("container");
- this.mContent.EnableChildren = true;
- this.AddChild(mContent);
- this.mMaskGraphics = mGameObject.AddComponent<InteractiveDummyGraphics>();
- this.mMaskGraphics.color = Color.white;
- this.mMaskGraphics.type = Image.Type.Filled;
- this.mMaskScrollRect = mGameObject.AddComponent<ScrollRectInteractive>();
- this.mMaskScrollRect.movementType = ScrollRectInteractive.MovementType.Elastic;
- this.mMaskScrollRect.content = mContent.Transform;
- this.mMaskScrollRect.viewport = this.Transform;
- this.mMaskScrollRect.event_Scrolled += DoScrolled;
- this.mMaskScrollRect.event_OnEndDrag += DoEndDrag;
- this.mRectMask = mGameObject.AddComponent<RectMask2D>();
- // this.mMask = mGameObject.AddComponent<Mask>();
- // this.mMask.showMaskGraphic = false;
- this.IsInteractive = true;
- this.Enable = true;
- }
- public bool IsInViewRect(ref Rect src, ref Rect dst)
- {
- return mMaskScrollRect.IsInViewRect(ref src, ref dst);
- }
- public void LookAt(Vector2 pos)
- {
- mMaskScrollRect.LookAt(pos, false);
- }
- public void LookAt(Vector2 pos, bool scroll)
- {
- mMaskScrollRect.LookAt(pos, scroll);
- }
- public void SetScrollBarPair(DisplayNode scrollh, DisplayNode scrollv)
- {
- mMaskScrollRect.SetScrollBarPair(scrollh, scrollv);
- }
- //-----------------------------------------------------------------------------------------------------------------------
- protected override void OnUpdate()
- {
- base.OnUpdate();
- if (!Scroll.AutoUpdateContentSize)
- {
- this.OnUpdateContentSize();
- }
- }
- protected virtual void OnUpdateContentSize()
- {
- }
- #region _Events_
- protected override void OnDisposeEvents()
- {
- this.event_Scrolled = null;
- this.event_OnEndDrag = null;
- base.OnDisposeEvents();
- }
- private void DoEndDrag(DisplayNode sender, PointerEventData e)
- {
- if (event_OnEndDrag != null)
- {
- event_OnEndDrag(sender, e);
- }
- }
- private void DoScrolled(Vector2 value)
- {
- OnScrolled(value);
- if (event_Scrolled != null)
- {
- event_Scrolled.Invoke(this, value);
- }
- }
- protected virtual void OnScrolled(Vector2 value) { }
- public delegate void ScrollEventHandler(DisplayNode sender, Vector2 e);
- public ScrollEventHandler event_Scrolled;
- public DisplayNode.PointerEventHandler event_OnEndDrag;
- public event ScrollEventHandler Scrolled { add { event_Scrolled += value; } remove { event_Scrolled -= value; } }
- public event DisplayNode.PointerEventHandler OnEndDragEvent { add { event_OnEndDrag += value; } remove { event_OnEndDrag -= value; } }
- #endregion
- }
- //----------------------------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 静态网格滚动控件
- /// </summary>
- public class GridScrollablePanel : ScrollablePanel
- {
- private int mRowCount = 0, mColumnCount = 0;
- private Vector2 mCellSize;
- private Vector2 mContentSize;
- private DisplayNode[,] mGridMatrix;
- public GridScrollablePanel(string name = null) : base(name)
- {
- Scroll.AutoUpdateContentSize = false;
- }
- public Vector2 CellSize { get { return mCellSize; } }
- public int RowCount { get { return mRowCount; } }
- public int ColumnCount { get { return mColumnCount; } }
- private void CleanMatrix()
- {
- if (mGridMatrix != null)
- {
- for (int r = 0; r < mRowCount; r++)
- {
- for (int c = 0; c < mColumnCount; c++)
- {
- DisplayNode cell = mGridMatrix[c, r];
- this.mContent.RemoveChild(cell, true);
- }
- }
- mGridMatrix = null;
- }
- }
- public void Initialize(DisplayNode[,] cells, Vector2 cellSize)
- {
- CleanMatrix();
- if (mGridMatrix == null)
- {
- mGridMatrix = cells;
- mColumnCount = cells.GetLength(0);
- mRowCount = cells.GetLength(1);
- mCellSize = cellSize;
- mContentSize = new Vector2(cellSize.x * mColumnCount, cellSize.y * mRowCount);
- for (int r = 0; r < mRowCount; r++)
- {
- for (int c = 0; c < mColumnCount; c++)
- {
- DisplayNode cell = mGridMatrix[c, r];
- cell.Bounds2D = new Rect(c * cellSize.x, r * cellSize.y, cellSize.x, cellSize.y);
- mGridMatrix[c, r] = cell;
- this.mContent.AddChild(cell);
- }
- }
- }
- }
- public void Initialize(int columns, int rows, Vector2 cellSize, CreateCellItemHandler createCell)
- {
- CleanMatrix();
- if (mGridMatrix == null)
- {
- if (rows < 1 || columns < 1) throw new Exception("rows columns must be lager than 1.");
- if (cellSize.x < 0 || cellSize.y < 0) throw new Exception("unitWidth unitHeight must be lager than 0.");
- mGridMatrix = new DisplayNode[columns, rows];
- mColumnCount = columns;
- mRowCount = rows;
- mCellSize = cellSize;
- mContentSize = new Vector2(cellSize.x * mColumnCount, cellSize.y * mRowCount);
- for (int r = 0; r < mRowCount; r++)
- {
- for (int c = 0; c < mColumnCount; c++)
- {
- DisplayNode cell = createCell(this, c, r);
- cell.Bounds2D = new Rect(c * cellSize.x, r * cellSize.y, cellSize.x, cellSize.y);
- mGridMatrix[c, r] = cell;
- this.mContent.AddChild(cell);
- }
- }
- }
- }
- public DisplayNode GetCell(int column, int row)
- {
- if (mGridMatrix != null && CMath.isInRange(row, mRowCount) && CMath.isInRange(column, mColumnCount))
- {
- return mGridMatrix[column, row];
- }
- return null;
- }
- protected override void OnUpdateContentSize()
- {
- base.OnUpdateContentSize();
- this.mContent.Size2D = mContentSize;
- }
- public delegate DisplayNode CreateCellItemHandler(GridScrollablePanel panel, int column, int row);
- }
- //----------------------------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 网格滚动控件(缓冲模式)
- /// 适合大量固定数量数据的列表
- /// </summary>
- public class CachedGridScrollablePanel : ScrollablePanel
- {
- private Vector2 mCellSize = Vector2.zero;
- private Vector2 mContentSize = Vector2.one;
- private int mCacheSize = 2;
- private int mRowCount = 0, mColumnCount = 0;
- private int mViewRowCount = 0, mViewColumnCount = 0;
- private Cell[,] mGridMatrix;
- private LinkedList<Cell> mViewList = new LinkedList<Cell>();
- private LinkedList<Cell> mHideList = new LinkedList<Cell>();
- private List<Cell> mHidingList = new List<Cell>();
-
- public CachedGridScrollablePanel(string name = null)
- : base(name)
- {
- base.Scroll.AutoUpdateContentSize = false;
- Gap = new Vector2();
- Border = new Vector2();
- }
- public Vector2 CellSize { get { return mCellSize; } }
- public int RowCount { get { return mRowCount; } }
- public int ColumnCount { get { return mColumnCount; } }
- public int ViewRowCount { get { return mViewRowCount; } }
- public int ViewColumnCount { get { return mViewColumnCount; } }
- public bool IsUseCache { get { return mCacheSize > -1; } }
- public Vector2 Gap { get; set; }
- public Vector2 Border { get; set; }
- /// <summary>
- /// 初始化滚动控件.CacheSize = -1时候为非托管模式,需要自己维护销毁节点.
- /// </summary>
- /// <param name="columns"></param>
- /// <param name="rows"></param>
- /// <param name="cellSize"></param>
- /// <param name="cacheSize"></param>
- public void Initialize(int columns, int rows, Vector2 cellSize, int cacheSize = 1)
- {
- ClearGrid();
- if (mGridMatrix == null)
- {
- if (cellSize.x < 0 || cellSize.y < 0) throw new Exception("unitWidth unitHeight must be lager than 0.");
- this.mCacheSize = cacheSize;
- this.mCellSize = cellSize;
- CalViewContent(columns, rows, true);
- }
- }
- public void Reset(int columns, int rows)
- {
- if (mGridMatrix != null)
- {
- for (int r = 0; r < mRowCount; r++)
- {
- for (int c = 0; c < mColumnCount; c++)
- {
- Cell cell = mGridMatrix[c, r];
- if (cell != null)
- {
- OnHideCell(cell);
- }
- }
- }
- mGridMatrix = null;
- }
- if (mGridMatrix == null)
- {
- CalViewContent(columns, rows, false);
- }
- }
- public DisplayNode GetCell(int column, int row)
- {
- if (mGridMatrix != null && CMath.isInRange(row, mRowCount) && CMath.isInRange(column, mColumnCount))
- {
- Cell cell = mGridMatrix[column, row];
- if (cell != null)
- {
- return cell.Node;
- }
- }
- return null;
- }
- protected override void OnUpdateContentSize()
- {
- this.mContent.Size2D = this.mContentSize;
- this.UpdateGrid();
- }
- /// <summary>
- /// 清理所有滚动并销毁节点.
- /// </summary>
- public void ClearGrid()
- {
- bool isCache = IsUseCache;
- if (mGridMatrix != null)
- {
- for (int r = 0; r < mRowCount; r++)
- {
- for (int c = 0; c < mColumnCount; c++)
- {
- Cell cell = mGridMatrix[c, r];
- if (cell != null && cell.Node != null)
- {
- if (isCache)
- {
- //缓存托管模式主动释放销毁节点.
- cell.Node.Dispose();
- }
- else
- {
- //非托管模式需要自己释放销毁节点.
- cell.Node.RemoveFromParent(false);
- }
- mGridMatrix[c, r] = null;
- }
- }
- }
- mGridMatrix = null;
- }
- if (mHideList != null)
- {
- if (isCache)
- {
- for (LinkedListNode<Cell> it = mHideList.First; it != null; it = it.Next)
- {
- Cell cell = it.Value;
- if (cell != null && cell.Node != null)
- {
- cell.Node.Dispose();
- }
- }
- }
- mHideList.Clear();
- }
- if (mViewList != null)
- {
- mViewList.Clear();
- }
- mColumnCount = 0;
- mRowCount = 0;
- mGridMatrix = null;
- }
- /// <summary>
- /// 计算需要创建的节点个数.
- /// </summary>
- private void CalViewContent(int columns, int rows, bool isCreate)
- {
- if (columns < 1 || rows < 1) { return; }
- Vector2 viewSize = this.Size2D;
- this.mGridMatrix = new Cell[columns, rows];
- this.mRowCount = rows;
- this.mColumnCount = columns;
- this.mContentSize = new Vector2(Border.x + columns * (mCellSize.x + Gap.x), Border.y + rows * (mCellSize.y + Gap.y));
- this.mContent.Position2D = Vector2.zero;
- this.mContent.Size2D = this.mContentSize;
-
- if (IsUseCache == true)
- {
- this.mViewRowCount = (rows == 1) ? 1 : (int)(viewSize.y / mCellSize.y) + mCacheSize;
- this.mViewRowCount = Math.Min(mRowCount, mViewRowCount);
- this.mViewColumnCount = (columns == 1) ? 1 : (int)(viewSize.x / mCellSize.x) + mCacheSize;
- this.mViewColumnCount = Math.Min(mColumnCount, mViewColumnCount);
- }
- else
- {
- this.mViewRowCount = rows;
- this.mViewColumnCount = columns;
- }
- for (int r = 0; r < mViewRowCount; r++)
- {
- for (int c = 0; c < mViewColumnCount; c++)
- {
- //这里的Create应该注释掉,否则会在下一个update才会正真初始化完成。如果一定要区分create和show,建议重构一下.
- //if (isCreate)
- //{
- // OnCreateCell();
- //}
- //else
- {
- OnShowCell(c, r);
- }
- }
- }
- }
- //-----------------------------------------------------------------------------------------------------------------------
- #region _Events_
- protected override void OnDisposeEvents()
- {
- this.event_CreateCell = null;
- this.event_HideCell = null;
- this.event_ShowCell = null;
- base.OnDisposeEvents();
- }
- public delegate DisplayNode CreateCellItemHandler(CachedGridScrollablePanel panel);
- public delegate void HideCellItemHandler(CachedGridScrollablePanel panel, int column, int row, DisplayNode cell);
- public delegate void ShowCellItemHandler(CachedGridScrollablePanel panel, int column, int row, DisplayNode cell);
- [Desc("请求创建节点")]
- public CreateCellItemHandler event_CreateCell;
- [Desc("节点被隐藏")]
- public HideCellItemHandler event_HideCell;
- [Desc("节点将显示")]
- public ShowCellItemHandler event_ShowCell;
- #endregion
- //-----------------------------------------------------------------------------------------------------------------------
- #region _Cells_
- private Cell OnCreateCell()
- {
- DisplayNode node = null;
- if (event_CreateCell != null)
- {
- node = event_CreateCell.Invoke(this);
- }
- else
- {
- node = new DisplayNode("default cell");
- }
- //实际上代价很大,setactive会产生大量的gc,这里由rect2d来保证clip
- //node.VisibleInParent = false;
- Cell cell = new Cell(node);
- mContent.AddChild(node);
- mHideList.AddLast(cell);
- return cell;
- }
- private Cell OnShowCell(int column, int row)
- {
- Cell cell = mGridMatrix[column, row];
- if (cell == null)
- {
- if (mHideList.Count == 0)
- {
- cell = OnCreateCell();
- }
- cell = mHideList.First.Value;
- mHideList.RemoveFirst();
- mViewList.AddFirst(cell);
- mGridMatrix[column, row] = cell;
- cell.column = column;
- cell.row = row;
- cell.Node.Position2D = new Vector2(Border.x + (column * (mCellSize.x + Gap.x)), Border.y + row * (mCellSize.y+Gap.y));
- //cell.Node.VisibleInParent = true;
- if (event_ShowCell != null)
- {
- event_ShowCell.Invoke(this, column, row, cell.Node);
- }
- }
- return cell;
- }
- private void OnHideCell(Cell cell)
- {
- mGridMatrix[cell.column, cell.row] = null;
- mHideList.AddFirst(cell);
- mViewList.Remove(cell);
- cell.Node.Position2D = new Vector2(10000, 10000);
- //cell.Node.VisibleInParent = false;
- if (event_HideCell != null)
- {
- event_HideCell.Invoke(this, cell.column, cell.row, cell.Node);
- }
- }
- private void UpdateGrid()
- {
- if (mGridMatrix != null)
- {
- Rect scroll_rect = this.ScrollRect2D;
- Vector2 vsize = this.Size2D;
- int sx1 = (int)((scroll_rect.x - Border.x) / (mCellSize.x + Gap.x));
- int sx2 = (int)((scroll_rect.x - Border.x + scroll_rect.width) / (mCellSize.x + Gap.x));
- int sy1 = (int)((scroll_rect.y - Border.y) / (mCellSize.y + Gap.y));
- int sy2 = (int)((scroll_rect.y - Border.y + scroll_rect.height) / (mCellSize.y + Gap.y));
- sx1 = Math.Max(sx1, 0);
- sy1 = Math.Max(sy1, 0);
- sx2 = Math.Min(sx2, this.mColumnCount - 1);
- sy2 = Math.Min(sy2, this.mRowCount - 1);
- //隐藏超出视野的//
- mHidingList.Clear();
- for (LinkedListNode<Cell> it = mViewList.First; it != null; it = it.Next)
- {
- Cell cell = it.Value;
- if (!CMath.isIncludeEqual(cell.column, sx1, sx2) || !CMath.isIncludeEqual(cell.row, sy1, sy2))
- {
- mHidingList.Add(cell);
- }
- }
- if (mHidingList.Count > 0)
- {
- for (int i = mHidingList.Count - 1; i >= 0; --i)
- {
- OnHideCell(mHidingList[i]);
- }
- mHidingList.Clear();
- }
- //显示进入视野//
- for (int x = sx1; x <= sx2; x++)
- {
- for (int y = sy1; y <= sy2; y++)
- {
- OnShowCell(x, y);
- }
- }
- }
- }
- public void RefreshShowCell()
- {
- if (mGridMatrix != null && mMaskScrollRect.Binding != null)
- {
- Rect scroll_rect = this.ScrollRect2D;
- int sx1 = (int)((scroll_rect.x) / mCellSize.x);
- int sx2 = (int)((scroll_rect.x + scroll_rect.width) / mCellSize.x);
- int sy1 = (int)((scroll_rect.y) / mCellSize.y);
- int sy2 = (int)((scroll_rect.y + scroll_rect.height) / mCellSize.y);
- sx1 = Math.Max(sx1, 0);
- sy1 = Math.Max(sy1, 0);
- sx2 = Math.Min(sx2, this.mColumnCount - 1);
- sy2 = Math.Min(sy2, this.mRowCount - 1);
- //显示进入视野//
- for (int x = sx1; x <= sx2; x++)
- {
- for (int y = sy1; y <= sy2; y++)
- {
- Cell cell = mGridMatrix[x, y];
- if (event_ShowCell != null)
- {
- event_ShowCell.Invoke(this, x, y, cell.Node);
- }
- }
- }
- }
- }
- class Cell
- {
- public DisplayNode Node;
- public int column, row;
- public Cell(DisplayNode node)
- {
- this.Node = node;
- }
- }
- #endregion
- }
- //-----------------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 分页式滚动控件
- /// </summary>
- public class PagedScrollablePanel : ScrollablePanel
- {
- private readonly PagedScrollableSnap mScrollSnap;
- private int mPageCount;
- private Vector2 mPageSize;
- private Vector2 mContentSize;
- private DisplayNode[] mPageList;
- public PagedScrollablePanel(string name = null)
- : base(name)
- {
- this.mScrollSnap = mGameObject.AddComponent<PagedScrollableSnap>();
- this.Scroll.inertia = false;
- this.Scroll.movementType = ScrollRectInteractive.MovementType.Clamped;
- this.Scroll.horizontal = true;
- this.Scroll.vertical = false;
- this.Scroll.AutoUpdateContentSize = true;
- }
- public Vector2 ContentSize { get { return mContentSize; } }
- public Vector2 PageSize { get { return mPageSize; } }
- public int PageCount { get { return mPageCount; } }
- public PagedScrollableSnap ScrollSnap { get { return mScrollSnap; } }
- private void CleanPages()
- {
- if (mPageList != null)
- {
- for (int i = 0; i < mPageCount; i++)
- {
- DisplayNode cell = mPageList[i];
- this.mContent.RemoveChild(cell, true);
- }
- mPageList = null;
- }
- }
- public void Initialize(DisplayNode[] pages, Vector2 pageSize)
- {
- CleanPages();
- if (mPageList == null)
- {
- mPageList = pages;
- mPageCount = pages.Length;
- mPageSize = pageSize;
- mContentSize = new Vector2(pageSize.x * mPageCount, pageSize.y);
- for (int i = 0; i < mPageCount; i++)
- {
- DisplayNode cell = mPageList[i];
- cell.Bounds2D = new Rect(i * pageSize.x, 0, pageSize.x, pageSize.y);
- mPageList[i] = cell;
- this.mContent.AddChild(cell);
- }
- this.mContent.Size2D = mContentSize;
- this.mScrollSnap.Reset();
- }
- }
- public void Initialize(int pages, Vector2 pageSize, CreatePageItemHandler createPage)
- {
- CleanPages();
- if (mPageList == null)
- {
- if (pages < 1) throw new Exception("rows columns must be lager than 1.");
- if (pageSize.x < 0 || pageSize.y < 0) throw new Exception("unitWidth unitHeight must be lager than 0.");
- mPageList = new DisplayNode[pages];
- mPageCount = pages;
- mPageSize = pageSize;
- mContentSize = new Vector2(pageSize.x * mPageCount, pageSize.y);
- for (int i = 0; i < mPageCount; i++)
- {
- DisplayNode page = createPage(this, i);
- page.Bounds2D = new Rect(i * pageSize.x, 0, pageSize.x, pageSize.y);
- mPageList[i] = page;
- this.mContent.AddChild(page);
- }
- this.mContent.Size2D = mContentSize;
- this.mScrollSnap.Reset();
- }
- }
- public DisplayNode GetPage(int index)
- {
- if (mPageList != null && CMath.isInRange(index, mPageCount))
- {
- return mPageList[index];
- }
- return null;
- }
- protected override void OnUpdateContentSize()
- {
- base.OnUpdateContentSize();
- this.mContent.Size2D = mContentSize;
- }
- public delegate DisplayNode CreatePageItemHandler(PagedScrollablePanel panel, int index);
- }
- [RequireComponent(typeof(ScrollRect))]
- public class PagedScrollableSnap : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
- {
- private PagedScrollablePanel _owner;
- private Transform _screensContainer;
- private int _screens = 1;
- private int _startingScreen = 1;
- private System.Collections.Generic.List<Vector3> _positions;
- private ScrollRect _scroll_rect;
- private Vector3 _lerp_target;
- private bool _lerp;
- private float _containerSize;
- private bool _startDrag = true;
- private Vector3 _startPosition = new Vector3();
- private int _currentScreen;
- public float LerpSpeed = 10;
- public float DockDistance = 1;
- /// <summary>
- /// If set to something above zero, it will be possible to move to the next page after dragging past the specified threshold.
- /// </summary>
- public float nextPageThreshold = 0f;
- // Use this for initialization
- public void Reset()
- {
- _owner = DisplayNode.AsDisplayNode(gameObject) as PagedScrollablePanel;
- _scroll_rect = _owner.Scroll;
- _screensContainer = _owner.Container.Transform;
- _screens = _owner.PageCount;
- _lerp = false;
- _positions = new System.Collections.Generic.List<Vector3>();
- if (_screens > 0)
- {
- float step = _owner.PageSize.x;
- for (int i = 0; i < _screens; ++i)
- {
- _scroll_rect.horizontalNormalizedPosition = (float)i / (float)(_screens - 1);
- Vector3 pos = _screensContainer.localPosition;
- pos.x = (int)(pos.x);
- _positions.Add(pos);
- }
- }
- _scroll_rect.horizontalNormalizedPosition = (float)(_startingScreen - 1) / (float)(_screens - 1);
- _containerSize = _owner.ContentSize.x;
- }
- void Update()
- {
- if (_lerp)
- {
- float lpspeed = Mathf.Max(0.1f, LerpSpeed);
- float dock = Mathf.Max(0.005f, DockDistance);
- _screensContainer.localPosition = Vector3.Lerp(_screensContainer.localPosition, _lerp_target, lpspeed * Time.deltaTime);
- if (Vector3.Distance(_screensContainer.localPosition, _lerp_target) < dock)
- {
- _screensContainer.localPosition = _lerp_target;
- _lerp = false;
- }
- }
- }
- //Function for switching screens with buttons
- public void NextScreen()
- {
- if (CurrentScreen() < _screens - 1)
- {
- _lerp = true;
- _lerp_target = _positions[CurrentScreen() + 1];
- }
- }
- //Function for switching screens with buttons
- public void PreviousScreen()
- {
- if (CurrentScreen() > 0)
- {
- _lerp = true;
- _lerp_target = _positions[CurrentScreen() - 1];
- }
- }
- //Because the CurrentScreen function is not so reliable, these are the functions used for swipes
- private void NextScreenCommand()
- {
- if (_currentScreen < _screens - 1)
- {
- _lerp = true;
- _lerp_target = _positions[_currentScreen + 1];
- }
- }
- //Because the CurrentScreen function is not so reliable, these are the functions used for swipes
- private void PrevScreenCommand()
- {
- if (_currentScreen > 0)
- {
- _lerp = true;
- _lerp_target = _positions[_currentScreen - 1];
- }
- }
- //find the closest registered point to the releasing point
- private Vector3 FindClosestFrom(Vector3 start, System.Collections.Generic.List<Vector3> positions)
- {
- Vector3 closest = Vector3.zero;
- float distance = Mathf.Infinity;
- foreach (Vector3 position in _positions)
- {
- if (Vector3.Distance(start, position) < distance)
- {
- distance = Vector3.Distance(start, position);
- closest = position;
- }
- }
- return closest;
- }
- private Vector3 FindMatchCondition(Vector3 start)
- {
- float delta = 0f;
- if (_scroll_rect.horizontal)
- {
- delta = start.x - _positions[_currentScreen].x;
- }
- else if(_scroll_rect.vertical)
- {
- delta = start.y - _positions[_currentScreen].y;
- }
- if (Mathf.Abs(delta) > nextPageThreshold)
- {
- if (delta < -nextPageThreshold)
- {
- // Next page
- if (_currentScreen < _positions.Count - 1)
- {
- _currentScreen = _currentScreen + 1;
- }
- }
- else if (delta > nextPageThreshold)
- {
- // Previous page
- if (_currentScreen > 0)
- {
- _currentScreen = _currentScreen - 1;
- }
- }
- }
- return _positions[_currentScreen];
- }
- //returns the current screen that the is seeing
- public int CurrentScreen()
- {
- float absPoz = Math.Abs((_screensContainer as RectTransform).offsetMin.x);
- absPoz = Mathf.Clamp(absPoz, 1, _containerSize - 1);
- //0.5f为4舍5入的附加值,防止6.9被转成6的情况
- float calc = (absPoz / _containerSize) * _screens + 0.5f;
- return (int)calc;
- }
- #region Interfaces
- public void OnBeginDrag(PointerEventData eventData)
- {
- if (_owner.EnableTouchInParents)
- {
- _startPosition = _screensContainer.localPosition;
- _currentScreen = CurrentScreen();
- }
- }
- public void OnEndDrag(PointerEventData eventData)
- {
- if (_owner.EnableTouchInParents)
- {
- _startDrag = true;
- if (_scroll_rect.horizontal)
- {
- _lerp = true;
- // If we have a touch in progress and the next page threshold set
- if (nextPageThreshold > 0f)
- {
- _lerp_target = FindMatchCondition(_screensContainer.localPosition);
- }
- else
- {
- _lerp_target = FindClosestFrom(_screensContainer.localPosition, _positions);
- }
- }
- }
- }
- public void OnDrag(PointerEventData eventData)
- {
- _lerp = false;
- if (_startDrag)
- {
- OnBeginDrag(eventData);
- _startDrag = false;
- }
- }
- #endregion
- }
- //----------------------------------------------------------------------------------------------------------------------------------
- }
|