支持自定义初始化回调、自定义元素循环显示触发的范围、是否进行上次位置记录、元素初始化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;
}
}