基于NGUI的循环滑动组件

支持自定义初始化回调、自定义元素循环显示触发的范围、是否进行上次位置记录、元素初始化Tween特效、

using UnityEngine;
using System.Collections.Generic;
using System.Collections;
[AddComponentMenu("Yinwu/SUIWrapContent")]
public enum WrapType
{
    RightSide = 1,
    LeftSide,
    UpSide,
}
public class SUIWrapContent : MonoBehaviour
{
    public static SUIWrapContent Get(GameObject go)
    {
        SUIWrapContent wrap = go.GetComponent();
        if (wrap == null) wrap = go.AddComponent();
        return wrap;
    }
    #region 数据定义 (    )
    /// 列表成员尺寸
    public Vector2 itemSize = new Vector2(100.0f, 100.0f);
    /// 元素显示触发的值
    public float showMargin = 250;
    /// 是否记录上一次滑动的位置 
    public bool isRecordPos = false;
    /// 超出UIPanel是否激死 
    public bool cullContent = false;
    /// 列表第一个成员的定位点 
    public float first = 0.0f;
    /// 列表首序号 
    public int from = 0;
    /// 列表尾序号   
    public int to = 9;
    /// 列表总成员个数  
    public int maxNum = 100;
    /// 列表首标志 
    public UISprite spriteStart;
    /// 列表尾标志 
    public UISprite spriteEnd;
    /// 列表首之前组 
    public Transform groupBeforeStart;
    /// 列表尾之后组 
    public Transform groupAfterEnd;
    /// 自动居中 
    public bool autoCenter = false;
    /// 启动复位列表 
    public bool resetOnStart = false;
    /// 灵敏度
    private float momentumAmount = 60.0f;
    /// 是否循环列表 
    public bool wrapContent = true;
    public bool disableDragIfFits = false;
    public delegate void Callback(GameObject item, int index);
    /// 更新列表成员数据回调接口 
    public Callback updateItemCallback = null;
    /// 列表成员飞入完成回调接口
    public Callback moveEffectFinishCallback = null;
    /// 列表成员点击事件回调接口  
    public UIEventListener.VoidDelegate clickCallback = null;
    /// 列表成员自动居中回调接口 
    public UIEventListener.VoidDelegate centerCallback = null;
    /// Item父元素 
    private Transform mTrans;
    private UIScrollView mScroll;
    private bool mHorizontal = false;
    private List mChildren = new List();
    private bool mStopYieldFlag = false;
    private bool mResetOverFlag = true;
    #endregion
    public WrapType WrapContentType = WrapType.RightSide;//;
    void Start()
    {
        if (resetOnStart == true)
        {
            Reset(true);
        }
    }
    #region 复位处理
    /// 
    /// 复位
    /// 
    /// 是否添加移动特效
    public void Reset(bool moveEffect)
    {
        if (this.gameObject.activeInHierarchy)
            StartCoroutine(DelayReset(moveEffect));
    }
    //对元素位置从新设置
    IEnumerator DelayReset(bool moveEffect)
    {
        mResetOverFlag = false;
        yield return 1;
        if (mStopYieldFlag == true) { yield break; }
        SortBasedOnScrollMovement(moveEffect);
        if (mScroll != null && mScroll.panel != null)
        {
            SpringPanel spring = mScroll.panel.GetComponent();
            if (spring != null)
            {
                Destroy(spring);
            }
            if (mInitPanelOffset == false)
            {
                mPanelClipOffset = mScroll.panel.clipOffset;
                mPanleLocalPosition = mScroll.panel.transform.localPosition; //每次初始化要重新设置的 位置上一次的位置
                mInitPanelOffset = true;
            }
            ResetPanelClipOffset();
            mScroll.UpdateScrollbars(true);
            //mScroll.onPressUp = OnPressUp;
            mScroll.panel.onClipMove = OnMove;  //移动触发托管到 UIScrollView
            mScroll.disableDragIfFits = disableDragIfFits;
            if (autoCenter)
            {
                mScroll.momentumAmount = momentumAmount * 0.7f;
            }
            else
            {
                mScroll.momentumAmount = momentumAmount;
            }
        }
        WrapContent();
        mResetOverFlag = true;
    }
    private Vector2 mPanelClipOffset = Vector2.zero;
    private Vector3 mPanleLocalPosition = Vector3.zero;
    private bool mInitPanelOffset = false;
    public bool mIsRememberLastPos = false;
    private int LastPos = 0;
    //重设Panel的偏移
    private void ResetPanelClipOffset()
    {
        if (isRecordPos) return;
        if (mScroll != null && mScroll.panel != null)
        {
            float baseFirst = first;
            if (groupBeforeStart != null && baseFirst <= 0.0f)
            {
                baseFirst -= 1.0f;
            }
            if (autoCenter == true)
            {
                if (baseFirst >= 0.0f)
                {
                    baseFirst = (int)baseFirst;
                }
                else
                {
                    baseFirst = -1.0f;
                }
            }
            if(mIsRememberLastPos==true)
            {
                baseFirst = LastPos;
            }
            float modifyOffset = 0.0f;
            if (mHorizontal)
            {
                if (autoCenter == true)
                {
                    modifyOffset = itemSize.x / 2.0f - mScroll.panel.finalClipRegion.z / 2.0f;
                }
                //这两个量的 反向 偏移形成移动 
                mScroll.panel.clipOffset = mPanelClipOffset + new Vector2(itemSize.x, 0.0f) * baseFirst + new Vector2(modifyOffset, 0.0f);
                //Item父Panel所在Obj ,如果要进行位置记录 ,也在这里计算
                mScroll.panel.transform.localPosition = mPanleLocalPosition - new Vector3(itemSize.x, 0.0f, 0.0f) * (baseFirst)- new Vector3(modifyOffset, 0.0f, 0.0f);
                //mScroll.panel.transform.localPosition = mPanleLocalPosition - new Vector3(0, 0.0f, 0.0f) * baseFirst - new Vector3(modifyOffset, 0.0f, 0.0f);
            }
            else
            {
                if (autoCenter == true)
                {
                    modifyOffset = itemSize.y / 2.0f - mScroll.panel.finalClipRegion.w / 2.0f;
                }
                mScroll.panel.clipOffset = mPanelClipOffset - new Vector2(0.0f, itemSize.y) * baseFirst - new Vector2(0.0f, modifyOffset);
                mScroll.panel.transform.localPosition = mPanleLocalPosition + new Vector3(0.0f, itemSize.y, 0.0f) * baseFirst + new Vector3(0.0f, modifyOffset, 0.0f);
            }
            //mScroll.panel.Refresh();
        }
    }
    #endregion
    #region 自动居中处理
    void OnPressUp()  //松开是否自动居中处理
    {
        if (autoCenter)
        {
            ReCenter();
        }
    }
    private float nextPageThreshold = 0f;
    private GameObject mCenteredObject;
    [ContextMenu("ReCenter")]
    public void ReCenter()
    {
        if (mScroll != null && mScroll.panel != null)
        {
            if (maxNum == 0)
            {
                return;
            }
            // Calculate the panel's center in world coordinates
            Vector3[] corners = mScroll.panel.worldCorners;
            Vector3 panelCenter = (corners[2] + corners[0]) * 0.5f;
            // Offset this value by the momentum
            Vector3 momentum = mScroll.currentMomentum * mScroll.momentumAmount;
            Vector3 moveDelta = NGUIMath.SpringDampen(ref momentum, 9f, 2f);
            Vector3 pickingPoint = panelCenter - moveDelta * 0.05f; // Magic number based on what "feels right"
            mScroll.currentMomentum = Vector3.zero;
            float min = float.MaxValue;
            Transform closest = null;
            int index = 0;
            // Determine the closest child
            for (int i = 0; i < mChildren.Count; ++i)
            {
                Transform t = mChildren[i];
                if (!t.gameObject.activeInHierarchy) continue;
                float sqrDist = Vector3.SqrMagnitude(t.position - pickingPoint);
                if (sqrDist < min)
                {
                    min = sqrDist;
                    closest = t;
                    index = i;
                }
            }
            // If we have a touch in progress and the next page threshold set
            if (nextPageThreshold > 0f && UICamera.currentTouch != null)
            {
                // If we're still on the same object
                if (mCenteredObject != null && mCenteredObject.transform == mChildren[index])
                {
                    Vector2 totalDelta = UICamera.currentTouch.totalDelta;
                    float delta = 0f;
                    switch (mScroll.movement)
                    {
                        case UIScrollView.Movement.Horizontal:
                            {
                                delta = totalDelta.x;
                                break;
                            }
                        case UIScrollView.Movement.Vertical:
                            {
                                delta = totalDelta.y;
                                break;
                            }
                        default:
                            {
                                delta = totalDelta.magnitude;
                                break;
                            }
                    }
                    if (delta > nextPageThreshold)
                    {
                        // Next page
                        if (index > 0)
                            closest = mChildren[index - 1];
                    }
                    else if (delta < -nextPageThreshold)
                    {
                        // Previous page
                        if (index < mChildren.Count - 1)
                            closest = mChildren[index + 1];
                    }
                }
            }
            CenterOn(closest, panelCenter);
        }
    }
    /// 
    /// Center the panel on the specified target.
    /// 
    void CenterOn(Transform target, Vector3 panelCenter)
    {
        if (target != null && mScroll != null && mScroll.panel != null)
        {
            Transform panelTrans = mScroll.panel.cachedTransform;
            mCenteredObject = target.gameObject;
            // Figure out the difference between the chosen child and the panel's center in local coordinates
            Vector3 cp = panelTrans.InverseTransformPoint(target.position);
            Vector3 cc = panelTrans.InverseTransformPoint(panelCenter);
            Vector3 localOffset = cp - cc;
            // Offset shouldn't occur if blocked
            if (!mScroll.canMoveHorizontally) localOffset.x = 0f;
            if (!mScroll.canMoveVertically) localOffset.y = 0f;
            localOffset.z = 0f;
            // Spring the panel to this calculated position
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                panelTrans.localPosition = panelTrans.localPosition - localOffset;
                Vector4 co = mScroll.panel.clipOffset;
                co.x += localOffset.x;
                co.y += localOffset.y;
                mScroll.panel.clipOffset = co;
            }
            else
#endif
            {
                SpringPanel.Begin(mScroll.panel.cachedGameObject, panelTrans.localPosition - localOffset, 10);//.onFinished = onFinished
            }
            // Notify the listener
            if (centerCallback != null)
            {
                centerCallback(mCenteredObject);
            }
        }
        else
        {
            mCenteredObject = null;
        }
    }
    #endregion
    /// 
    /// Callback triggered by the UIPanel when its clipping region moves (for example when it's being scrolled).
    /// 
    protected virtual void OnMove(UIPanel panel)
    {
        if (mResetOverFlag == true)
        {
            if (wrapContent)
            {
                WrapContent(); //进行循环计算处理 是否需要 更新位置
            }
        }
    }
    /// 
    /// Immediately reposition all children.
    /// 
    [ContextMenu("Sort Based on Scroll Movement")]
    public void SortBasedOnScrollMovement(bool moveEffect)
    {
        if (!CacheScrollView()) return;
        float maxFirst = from;
        int needNum = maxNum;
        if (wrapContent) //进行循环利用 只使用需要显示的最大 固定个数
        {
            if (mHorizontal)
            {
                maxFirst = maxNum - mScroll.panel.finalClipRegion.z / itemSize.x;
                needNum = (int)(mScroll.panel.finalClipRegion.z / itemSize.x) + 2; //计算需要的Item元素个数
            }
            else
            {
                maxFirst = maxNum - mScroll.panel.finalClipRegion.z / itemSize.x;
                needNum = (int)(mScroll.panel.finalClipRegion.w / itemSize.y) + 2;
            }
            if (first < 0.0f)
            {
                first = 0.0f;
            }
            else if (first > maxFirst && maxFirst > 0.0f)
            {
                first = maxFirst;
            }
            from = (int)first;
            if (from > 0)
            {
                from -= 1;
            }
            to = from + needNum - 1;
            if (to > maxNum - 1)
            {
                to = maxNum - 1;
                from = to - needNum + 1;
                if (from < 0)
                {
                    from = 0;
                }
            }
        }
        else //不进行循环 直接实例化所有的部件
        {
            to = maxNum - 1;
        }
        if (to < 0)
        {
            to = 0;
        }
        if (mTrans.childCount < needNum) //添加所有元素
        {
            if (mTrans.childCount > 0)
            {
                mTrans.GetChild(0).gameObject.SetActive(true);
                Transform item = mTrans.GetChild(0);
                int max = needNum - mTrans.childCount;
                for (int i = 0; i < max; ++i)
                {
                    NGUITools.AddChild(this.gameObject, item.gameObject);
                }
            }
        }
        // Cache all children and place them in order ,用来排序
        mChildren.Clear();
        if (mTrans.childCount > 0)
        {
            for (int i = 0; i < mTrans.childCount; ++i) //给所有元素添加点击和滑动
            {
                Transform tran = mTrans.GetChild(i);
                List boxs = GetComponentsAll(tran.gameObject, true);
                if (boxs != null && boxs.Count > 0)
                {
                    for (int j = 0; j < boxs.Count; j++)
                    {
                        BoxCollider box = boxs[j];
                        if (clickCallback != null)
                        {
                            UIEventListener.Get(box.gameObject).onClick = clickCallback;
                        }
                        UIDragScrollView drag = box.GetComponent();
                        if (drag == null)
                        {
                            drag = box.gameObject.AddComponent();
                        }
                        if (drag.scrollView == null)
                        {
                            drag.scrollView = mScroll;
                        }
                    }
                }
                mChildren.Add(tran);
            }
        }
        if (mChildren.Count > 0) //对所有缓存元素排序
        {
            // Sort the list of children so that they are in order
            if (mHorizontal) mChildren.Sort(UIGrid.SortHorizontal);
            else mChildren.Sort(UIGrid.SortVertical);
        }
        ResetChildPositions(moveEffect);
    }
    /// 获取对象上及子对象上所有的组件
    private List GetComponentsAll(GameObject go, bool includeInactive) where T : Component
    {
        List listT = new List();
        if (go != null)
        {
            T t = go.GetComponent();
            if (t != null)
            {
                listT.Add(t);
            }
            T[] ts = go.GetComponentsInChildren(includeInactive);
            if (ts != null)
            {
                for (int i = 0, max = ts.Length; i < max; i++)
                {
                    T tt = ts[i];
                    listT.Add(tt);
                }
            }
        }
        return listT;
    }
    /// 
    /// Immediately reposition all children, sorting them alphabetically.
    /// 
    [ContextMenu("Sort Alphabetically")]
    public void SortAlphabetically()
    {
        if (!CacheScrollView()) return;
        // Cache all children and place them in order
        mChildren.Clear();
        for (int i = 0; i < mTrans.childCount; ++i)
            mChildren.Add(mTrans.GetChild(i));
        // Sort the list of children so that they are in order
        mChildren.Sort(UIGrid.SortByName);
        ResetChildPositions(false);
    }
    /// 
    /// Cache the scroll view and return 'false' if the scroll view is not found.
    /// 
    protected bool CacheScrollView()
    {
        mTrans = transform;
        mTrans.GetChild(0).gameObject.SetActive(false);
        mScroll = NGUITools.FindInParents(gameObject);
        if (mScroll == null) return false;
        if (mScroll.movement == UIScrollView.Movement.Horizontal) mHorizontal = true;
        else if (mScroll.movement == UIScrollView.Movement.Vertical) mHorizontal = false;
        else return false;
        return true;
    }
    private Vector3 mClipTopLeftPos = Vector3.zero;
    /// 
    /// Helper function that resets the position of all the children.设置位置
    /// 
    void ResetChildPositions(bool moveEffect)
    {
        mClipTopLeftPos = new Vector3(-mScroll.panel.finalClipRegion.z / 2.0f + mScroll.panel.clipSoftness.x, mScroll.panel.finalClipRegion.w / 2.0f - mScroll.panel.clipSoftness.y, 0.0f);
        mListSpringPosition.Clear();
        //---开始元素的位置计算
        if (spriteStart != null)
        {
            spriteStart.width = (int)itemSize.x;
            spriteStart.height = (int)itemSize.y;
            //spriteStart.color = new Color(0.0f, 0.0f, 0.0f, 1.0f / 255.0f);
            spriteStart.transform.localPosition = mHorizontal ? new Vector3(mClipTopLeftPos.x + itemSize.x / 2.0f, 0f, 0f) : new Vector3(0f, mClipTopLeftPos.y - itemSize.y / 2.0f, 0f);
            if (spriteStart.gameObject.activeSelf == false)
            {
                spriteStart.gameObject.SetActive(true);
            }
        }
        if (spriteEnd != null)
        {
            int index = maxNum - 1;
            if (index < 0)
            {
                index = 0;
            }
            spriteEnd.width = (int)itemSize.x;
            spriteEnd.height = (int)itemSize.y;
            //spriteEnd.color = new Color(0.0f, 0.0f, 0.0f, 1.0f / 255.0f);
            spriteEnd.transform.localPosition = mHorizontal ? new Vector3(mClipTopLeftPos.x + itemSize.x / 2.0f + (float)(index) * itemSize.x, 0f, 0f) : new Vector3(0f, mClipTopLeftPos.y - itemSize.y / 2.0f - (float)(index) * itemSize.y, 0f);
            if (spriteEnd.gameObject.activeSelf == false)
            {
                spriteEnd.gameObject.SetActive(true);
            }
        }
        int moveIndex = 1;
        if (groupBeforeStart != null)
        {
            groupBeforeStart.localPosition = mHorizontal ? new Vector3(mClipTopLeftPos.x - itemSize.x / 2.0f, 0f, 0f) : new Vector3(0f, mClipTopLeftPos.y + itemSize.y / 2.0f, 0f);
            if (groupBeforeStart.gameObject.activeSelf == false)
            {
                groupBeforeStart.gameObject.SetActive(true);
            }
            if (moveEffect == true)
            {
                AddMoveEffect(groupBeforeStart.gameObject, moveIndex, false);
                moveIndex++;
            }
        }
        //---给每个元素的位置赋值
        for (int i = 0; i < mChildren.Count; ++i)
        {
            Transform t = mChildren[i];
            int index = (from + i);//循环状况下每次 开始的标记量
            t.gameObject.name = index.ToString();
            t.localPosition = mHorizontal ? new Vector3(mClipTopLeftPos.x + itemSize.x / 2.0f + index * itemSize.x, 0f, 0f) : new Vector3(0f, mClipTopLeftPos.y - itemSize.y / 2.0f - index * itemSize.y, 0f);
            if (index >= 0 && index < maxNum)
            {
                t.gameObject.SetActive(true);
                if (moveEffect == true)
                {
                    AddMoveEffect(t.gameObject, moveIndex, true);
                    moveIndex++;
                    if (mScroll.enabled == true)
                    {
                        mScroll.enabled = false;
                    }
                }
                UpdateItem(t, index);
            }
            else
            {
                t.gameObject.SetActive(false);
            }
        }
        if (groupAfterEnd != null)
        {
            groupAfterEnd.localPosition = mHorizontal ? new Vector3(mClipTopLeftPos.x + itemSize.x / 2.0f + (float)(maxNum) * itemSize.x, 0f, 0f) : new Vector3(0f, mClipTopLeftPos.y - itemSize.y / 2.0f - (float)(maxNum) * itemSize.y, 0f);
            if (groupAfterEnd.gameObject.activeSelf == false)
            {
                groupAfterEnd.gameObject.SetActive(true);
            }
            if (moveEffect == true)
            {
                AddMoveEffect(groupAfterEnd.gameObject, moveIndex, false);
                moveIndex++;
            }
        }
    }
    /// 
    /// 添加移动特效
    /// 
    /// 
    /// 位置
    /// 
    void AddMoveEffect(GameObject item, int index, bool addList)
    {
        Vector3 pos = item.transform.localPosition;
        switch (WrapContentType)
        {
            case WrapType.RightSide:
                item.transform.localPosition += new Vector3(mScroll.panel.finalClipRegion.z * (float)(index), 0.0f, 0.0f);
                break;
            case WrapType.UpSide:
                item.transform.localPosition += new Vector3(0.0f, mScroll.bounds.size.y + mScroll.panel.finalClipRegion.w * (float)(index), 0.0f);
                break;
            case WrapType.LeftSide:
                item.transform.localPosition += new Vector3(-1 * mScroll.panel.finalClipRegion.z * (float)(index), 0.0f, 0.0f);
                break;
        }
        SSpringPosition sp = SSpringPosition.Begin(item, pos, 10.0f);
        sp.onFinished = MoveEffectFinishOver;
        if (addList == true)
        {
            mListSpringPosition.Add(sp);
        }
        //Vector3 pos = item.transform.localPosition;
        //
        //PSpringPosition sp = PSpringPosition.Begin(item, pos, 10.0f);
        //sp.onFinished = MoveEffectFinishOver;
        //if (addList == true)
        //{
        //    mListSpringPosition.Add(sp);
        //}
    }
    private List mListSpringPosition = new List();
    void MoveEffectFinishOver(SSpringPosition sp)
    {
        GameObject item = sp.gameObject;
        if (item != null)
        {
            int index = -1;
            int.TryParse(item.name, out index);
            if (index >= 0 && index < maxNum)
            {
                if (moveEffectFinishCallback != null)
                {
                    moveEffectFinishCallback(item, index);
                }
            }
        }
        mListSpringPosition.Remove(sp);
        if (mListSpringPosition.Count <= 0)
        {
            if (mScroll.enabled == false)
            {
                mScroll.enabled = true;
            }
        }
    }
    /// 
    /// Wrap all content, repositioning all children as needed. 循环列表 裁剪模式
    /// 
    public void WrapContent()
    {
        Vector3[] corners = mScroll.panel.worldCorners;//元素的对齐方式
        for (int i = 0; i < 4; ++i)
        {
            Vector3 v = corners[i];
            v = mTrans.InverseTransformPoint(v);
            corners[i] = v;
        }
        Vector3 center = Vector3.Lerp(corners[0], corners[2], 0.5f); //基于UIPanel 的判定点 这里取的是Panel的中心
        if (mHorizontal)
        {
            float extents = itemSize.x * mChildren.Count * 0.5f;//成员范围
            float ext2 = extents * 2f;
            float min = corners[0].x - itemSize.x; //最小位置x
            float max = corners[2].x + itemSize.x; //最大位置x
            for (int i = 0; i < mChildren.Count; ++i)//所有子物件
            {
                Transform t = mChildren[i];
                float distance = t.localPosition.x - center.x - showMargin;  //距中心点的距离
                Vector3 pos = t.localPosition;  //元素位置
                bool modify = false;
                if (distance < -extents) //左边超出  计算新的位置 标记修改
                {
                    pos.x += ext2;
                    distance = pos.x - center.x;
                    modify = true;
                }
                else if (distance > extents) //右边超出  计算新的位置 标记修改
                {
                    pos.x -= ext2;
                    distance = pos.x - center.x;
                    modify = true;
                }
                if (modify == true) //进行位置修改
                {
                    int index = GetIndex(pos); //要更改的ITem
                    if (index >= 0 && index < maxNum)
                    {
                        if (index < from)
                        {
                            to -= from - index;
                            from = index;
                        }
                        else if (index > to)
                        {
                            from += index - to;
                            to = index;
                        }
                        t.localPosition = pos; //重新计算位置 按列表 index 进行新的重设
                        UpdateItem(t, index);
                    }
                }
                if (cullContent)// 超出部分进行裁剪
                {
                    distance += mScroll.panel.clipOffset.x - mTrans.localPosition.x;
                    if (!UICamera.IsPressed(t.gameObject))
                        NGUITools.SetActive(t.gameObject, (distance > min && distance < max), false);
                }
            }
        }
        else
        {
            float extents = itemSize.y * mChildren.Count * 0.5f;
            float ext2 = extents * 2f;
            float min = corners[0].y - itemSize.y;
            float max = corners[2].y + itemSize.y;
            for (int i = 0; i < mChildren.Count; ++i)
            {
                Transform t = mChildren[i];
                float distance = t.localPosition.y - center.y - showMargin;
                Vector3 pos = t.localPosition;
                bool modify = false;
                if (distance < -extents)
                {
                    pos.y += ext2;
                    distance = pos.y - center.y;
                    modify = true;
                }
                else if (distance > extents)
                {
                    pos.y -= ext2;
                    distance = pos.y - center.y;
                    modify = true;
                }
                if (modify == true)//需要重新更新位置
                {
                    int index = GetIndex(pos);
                    if (index >= 0 && index < maxNum)
                    {
                        if (index < from)
                        {
                            to -= from - index;
                            from = index;
                        }
                        else if (index > to)
                        {
                            from += index - to;
                            to = index;
                        }
                        t.localPosition = pos;
                        UpdateItem(t, index);
                    }
                }
                if (cullContent)//超出Panel 激死
                {
                    distance += mScroll.panel.clipOffset.y - mTrans.localPosition.y;
                    if (!UICamera.IsPressed(t.gameObject))
                        NGUITools.SetActive(t.gameObject, (distance > min && distance < max), false);
                }
            }
        }
    }
    /// 
    /// Want to update the content of items as they are scrolled? Override this function. 元素更新
    /// 
    protected virtual void UpdateItem(Transform item, int index)
    {
        if (item != null)
        {
            item.gameObject.name = index.ToString();
            if (index >= 0 && index < maxNum)
            {
                if (item.gameObject.activeSelf == false)
                {
                    item.gameObject.SetActive(true);
                }
                if (updateItemCallback != null)
                {
                    updateItemCallback(item.gameObject, index);
                }
            }
            else
            {
                if (item.gameObject.activeSelf == true)
                {
                    item.gameObject.SetActive(false);
                }
            }
            //Debugger.Log(string.Format("UpdateItem={0}",index.ToString()));
        }
    }
    /// 
    /// 更新滑动控件
    /// 
    private void UpdateScrowView()
    {
        if (spriteEnd != null)
        {
            int index = maxNum - 1;
            if (index < 0)
            {
                index = 0;
            }
            spriteEnd.transform.localPosition = mHorizontal ? new Vector3(mClipTopLeftPos.x + itemSize.x / 2.0f + (float)(index) * itemSize.x, 0f, 0f) : new Vector3(0f, mClipTopLeftPos.y - itemSize.y / 2.0f - (float)(index) * itemSize.y, 0f);
        }
        if (groupAfterEnd != null)
        {
            groupAfterEnd.localPosition = mHorizontal ? new Vector3(mClipTopLeftPos.x + itemSize.x / 2.0f + (float)(maxNum) * itemSize.x, 0f, 0f) : new Vector3(0f, mClipTopLeftPos.y - itemSize.y / 2.0f - (float)(maxNum) * itemSize.y, 0f);
        }
        if (mScroll != null)
        {
            mScroll.UpdateScrollbars(true);
        }
    }
    #region 外部接口
    /// 
    /// 获取成员序号  , , ,  youke.pro
    /// 
    /// 成员对象
    /// 序号
    public int GetIndex(GameObject item)
    {
        int index = -1;
        if (item != null)
        {
            index = GetIndex(item.transform.localPosition);
        }
        return index;
    }
    public int GetIndex(Vector3 pos)
    {
        int index = -1;
        if (mHorizontal)
        {
            if (pos.x > mClipTopLeftPos.x)
            {
                index = (int)((pos.x - mClipTopLeftPos.x) / itemSize.x);
            }
        }
        else
        {
            if (pos.y < mClipTopLeftPos.y)
            {
                index = (int)((-pos.y + mClipTopLeftPos.y) / itemSize.y);
            }
        }
        return index;
    }
    /// 
    /// 获取指定列表成员坐标
    /// 
    /// 指定序号
    /// 列表成员坐标
    public Vector3 GetItemPosByIndex(int index)
    {
        Vector3 pos = Vector3.zero;
        if (mHorizontal)
        {
            pos = new Vector3(mClipTopLeftPos.x + itemSize.x / 2.0f + (float)index * itemSize.x, 0.0f, 0.0f);
        }
        else
        {
            pos = new Vector3(0.0f, mClipTopLeftPos.y - itemSize.y / 2.0f - (float)index * itemSize.y, 0.0f);
        }
        return pos;
    }

    /// 
    /// 刷新列表数据
    /// 
    public void RefreshList()
    {
        for (int i = 0; i < mChildren.Count; ++i)
        {
            Transform t = mChildren[i];
            int index = GetIndex(t.gameObject);
            if (index >= from && index <= to)
            {
                UpdateItem(t, index);
            }
        }
        if (wrapContent)
        {
            WrapContent();
        }
    }
    /// 
    /// 摧毁所有成员
    /// 
    /// 是否包含模板Item
    public void DestoryAllItem(bool includeModel)
    {
        maxNum = 0;
        for (int i = 0; i < mChildren.Count; ++i)
        {
            Transform t = mChildren[i];
            if (includeModel == false && i == 0)
            {
                t.gameObject.SetActive(false);
            }
            else
            {
                GameObject.Destroy(t.gameObject);
            }
        }
        UpdateScrowView();
        if (wrapContent)
        {
            WrapContent();
        }
    }
    /// 
    /// 移除列表所有成员  \ ! !  youke.pro
    /// 
    public void RemoveAllItem()
    {
        maxNum = 0;
        for (int i = 0; i < mChildren.Count; ++i)
        {
            Transform t = mChildren[i];
            t.gameObject.SetActive(false);
        }
        UpdateScrowView();
        if (wrapContent)
        {
            WrapContent();
        }
    }
    /// 
    /// 移除列表指定成员  ! \ !  youke.pro
    /// 
    /// 成员对象
    public void RemoveItem(GameObject item)
    {
        if (item != null)
        {
            int ind = GetIndex(item);
            if (ind >= 0 && ind < maxNum)
            {
                RemoveItem(ind);
            }
        }
    }
    /// 
    /// 移除列表指定成员  ! \ !  youke.pro
    /// 
    /// 序号
    public void RemoveItem(int index)
    {
        if (index < 0 && index >= maxNum)
        {
            return;
        }
        maxNum--;
        for (int i = 0; i < mChildren.Count; ++i)
        {
            Transform t = mChildren[i];
            int ind = GetIndex(t.gameObject);
            if (ind >= index && ind <= to)
            {
                UpdateItem(t, ind);
            }
        }
        UpdateScrowView();
        if (wrapContent)
        {
            WrapContent();
        }
    }
    /// 
    /// 插入列表成员  ! ! \  youke.pro
    /// 
    /// 指定序号
    public void InsertItem(int index)
    {
        if (index < 0 && index >= maxNum)
        {
            return;
        }
        maxNum++;
        for (int i = 0; i < mChildren.Count; ++i)
        {
            Transform t = mChildren[i];
            int ind = GetIndex(t.gameObject);
            if (ind >= index && ind <= to)
            {
                UpdateItem(t, ind);
            }
        }
        UpdateScrowView();
        if (wrapContent)
        {
            WrapContent();
        }
    }
    /// 
    /// 追加列表成员
    /// 
    public void AppentItem()
    {
        maxNum++;
        UpdateScrowView();
        if (wrapContent)
        {
            WrapContent();
        }
    }
    /// 
    /// 移动列表  ! ! /  youke.pro
    /// 
    /// 指定序号
    public void SpringList(int index)
    {
        if (index < 0 && index >= maxNum)
        {
            return;
        }
        Vector3 panelOffset = GetPanelOffsetByIndex(index);
        Vector3 pos = mPanleLocalPosition;
        if (mHorizontal)
        {
            pos -= new Vector3(panelOffset.x, 0.0f, 0.0f);
            if (autoCenter)
            {
                pos += new Vector3(-itemSize.x / 2.0f + mScroll.panel.finalClipRegion.z / 2.0f, 0.0f, 0.0f);
            }
        }
        else
        {
            pos -= new Vector3(0.0f, panelOffset.y, 0.0f);
            if (autoCenter)
            {
                pos += new Vector3(0.0f, itemSize.y / 2.0f - mScroll.panel.finalClipRegion.w / 2.0f, 0.0f);
            }
        }
        SpringPanel spring = SpringPanel.Begin(mScroll.panel.gameObject, pos, 10);
        spring.onFinished = SpringListFinishCallback;
    }
    void SpringListFinishCallback()
    {
        SpringPanel spring = mScroll.gameObject.GetComponent();
        if (spring != null)
        {
            Destroy(spring);
        }
        ReCenter();
    }
    /// 
    /// 获取指定序号裁剪偏移量  ! ! *  youke.pro
    /// 
    /// 指定序号
    /// 裁剪偏移量
    private Vector3 GetPanelOffsetByIndex(int index)
    {
        Vector3 pos = Vector3.zero;
        if (mHorizontal)
        {
            pos = new Vector3(mPanelClipOffset.x + (float)index * itemSize.x, mScroll.panel.clipOffset.y, 0.0f);
        }
        else
        {
            pos = new Vector3(mScroll.panel.clipOffset.x, mPanelClipOffset.y - (float)index * itemSize.y, 0.0f);
        }
        return pos;
    }
    #endregion
}

using UnityEngine;
using System.Collections.Generic;
/// 
/// Spring-like motion -- the farther away the object is from the target, the stronger the pull.
/// 
[AddComponentMenu("Yinwu.pro/SSpringPosition")]
public class SSpringPosition : MonoBehaviour
{
    static public SSpringPosition current;
    /// 
    /// Target position to tween to.
    /// 
    public Vector3 target = Vector3.zero;
    /// 
    /// Strength of the spring. The higher the value, the faster the movement.
    /// 
    public float strength = 10f;
    /// 
    /// Is the calculation done in world space or local space?
    /// 
    public bool worldSpace = false;
    /// 
    /// Whether the time scale will be ignored. Generally UI components should set it to 'true'.
    /// 
    public bool ignoreTimeScale = false;
    public delegate void OnFinished(SSpringPosition go);
    /// 
    /// Delegate to trigger when the spring finishes.
    /// 
    public OnFinished onFinished;
    Transform mTrans;
    float mThreshold = 0f;
    /// 
    /// Cache the transform.
    /// 
    void Start()
    {
        mTrans = transform;
    }
    /// 
    /// Advance toward the target position.
    /// 
    void Update()
    {
        float delta = ignoreTimeScale ? RealTime.deltaTime : Time.deltaTime;
        if (worldSpace)
        {
            if (mThreshold == 0f) mThreshold = (target - mTrans.position).sqrMagnitude * 0.001f;
            mTrans.position = NGUIMath.SpringLerp(mTrans.position, target, strength, delta);
            if (mThreshold >= (target - mTrans.position).sqrMagnitude)
            {
                mTrans.position = target;
                NotifyListeners();
                enabled = false;
            }
        }
        else
        {
            if (mThreshold == 0f) mThreshold = (target - mTrans.localPosition).sqrMagnitude * 0.00001f;
            mTrans.localPosition = NGUIMath.SpringLerp(mTrans.localPosition, target, strength, delta);
            if (mThreshold >= (target - mTrans.localPosition).sqrMagnitude)
            {
                mTrans.localPosition = target;
                NotifyListeners();
                enabled = false;
            }
        }
    }
    /// 
    /// Notify all finished event listeners.
    /// 
    void NotifyListeners()
    {
        current = this;
        if (onFinished != null) onFinished(this);
        current = null;
    }
    /// 
    /// Start the tweening process.
    /// 
    static public SSpringPosition Begin(GameObject go, Vector3 pos, float strength)
    {
        SSpringPosition sp = go.GetComponent();
        if (sp == null) sp = go.AddComponent();
        sp.target = pos;
        sp.strength = strength;
        sp.onFinished = null;
        if (!sp.enabled)
        {
            sp.mThreshold = 0f;
            sp.enabled = true;
        }
        return sp;
    }
}


你可能感兴趣的:(NGUI)