using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using System.Collections; /// /// /// public class UI_ScrollFlow : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { /// /// 元素初始化 /// /// 游戏对象 /// 数据索引 public delegate void OnInitializeItem(GameObject go, int dataIndex); /// /// 元素初始化 /// public OnInitializeItem onInitializeItem; /// /// 卡牌的像素宽度 /// public float itemWidth = 700; /// /// 最大缩放 /// public float MaxScale = 1.0f; /// /// 开始坐标值 /// public float startValue = 0.5f; /// /// /// private int defaultItemIndex = 0; /// /// 卡牌之间的间隔坐标 /// private float spaceValue = 0.2f; /// /// 移动速度曲线 /// public AnimationCurve SpeedCurve; /// /// 坐标曲线 /// public AnimationCurve PositionCurve; /// /// 缩放幅度大小曲线 /// public AnimationCurve ScaleCurve; /// /// 拖拽时候的,托主幅度量 /// private float dragV = 0; /// /// 拖拽时候的,计算值 /// private Vector2 start_point, add_vect; /// /// 移动结束事件 /// public event CallBack MoveEnd; /// /// 更改当前卡牌的状态 /// public event CallBack EventRefreshCardState; /// /// 是否开启动画 /// public bool _anim = false; /// /// 移动的量 /// private float AddV = 0; /// /// 移动方向 /// private float Vk = 0; /// /// /// private float Vtotal = 0; /// /// 动画速度 * 单位时间* 移动方向,计算出来的移动值 /// private float CurrentV = 0; /// /// /// private float VT = 0; /// /// /// private float _v1 = 0, _v2 = 0; /// /// 动画速度 /// public float _anim_speed = 1f; /// /// /// public UI_ScrollFlow_Item Current; /// /// 初始化 /// /// 数据的数量 public void Init(int dataCount) { // 不显示元素预制物体 goItemPrefab.SetActive(false); // 如果数据数量为 0 ,没有初始化的必要 if (dataCount <= 0) { return; } mDataCount = dataCount; unUseItem.Clear(); useItemList.Clear(); Debug.LogError("Init!!!!!" + useItemList.Count); setUpdateRectItem(0, true); } /// /// 初始化 英雄滑动列表的组件设置 /// public void InitHeroComponmentsSetting() { MaxScale = 1.0f; itemWidth = 500; float[] tixxx = new float[] { -0.95f, -0.59f, -0.23f, 0.13f, 0.5f, 0.87f, 1.23f, 1.59f, 1.95f }; Keyframe[] ks = new Keyframe[3]; ks[0] = new Keyframe(0, 0.9f); ks[1] = new Keyframe(0.5f, 1.0f); ks[2] = new Keyframe(1.0f, 0.9f); ScaleCurve = new AnimationCurve(ks); Keyframe[] spks = new Keyframe[5]; spks[0] = new Keyframe(-1.0f, 2.0f); spks[1] = new Keyframe(-0.5f, 1.5f); spks[2] = new Keyframe(0, 0.5f); spks[3] = new Keyframe(0.5f, 1.5f); spks[4] = new Keyframe(1.0f, 2.0f); SpeedCurve = new AnimationCurve(spks); Keyframe[] posArr = new Keyframe[tixxx.Length]; int index = 0; for (int i = -4; i <= 4; i++) { posArr[index] = new Keyframe(startValue + i * spaceValue, tixxx[index]); index++; } PositionCurve = new AnimationCurve(posArr); } /// /// 初始化 图鉴滑动列表的组件设置 /// public void InitBook_ComponmentsSetting() { MaxScale = 1.0f; itemWidth = 200; Keyframe[] spks = new Keyframe[5]; spks[0] = new Keyframe(-1.0f, 1.5f); spks[1] = new Keyframe(-0.5f, 1); spks[2] = new Keyframe(0, 0.5f); spks[3] = new Keyframe(0.5f, 1); spks[4] = new Keyframe(1.0f, 1.5f); SpeedCurve = new AnimationCurve(spks); Keyframe[] ks = new Keyframe[2]; ks[0] = new Keyframe(-1.0f, 1.0f); ks[1] = new Keyframe(1.0f, 1.0f); ScaleCurve = new AnimationCurve(ks); float[] tixxx = new float[] { -3.0f, -2.0f, -1.0f, 0, 1.0f, 2.0f, 3.0f }; Keyframe[] posArr = new Keyframe[tixxx.Length]; int index = 0; for (int i = -3; i <= 3; i++) { posArr[index] = new Keyframe(startValue + i * spaceValue, tixxx[index]); index++; } PositionCurve = new AnimationCurve(posArr); } /// /// /// public void InitPvp_ComponmentsSetting() { MaxScale = 1.0f; itemWidth = 800; Keyframe[] spks = new Keyframe[5]; spks[0] = new Keyframe(-1.0f, 1.5f); spks[1] = new Keyframe(-0.5f, 1); spks[2] = new Keyframe(0, 0.5f); spks[3] = new Keyframe(0.5f, 1); spks[4] = new Keyframe(1.0f, 1.5f); SpeedCurve = new AnimationCurve(spks); Keyframe[] ks = new Keyframe[3]; ks[0] = new Keyframe(0, 0.9f); ks[1] = new Keyframe(0.5f, 1.0f); ks[2] = new Keyframe(1.0f, 0.9f); ScaleCurve = new AnimationCurve(ks); float[] tixxx = new float[] { -3.0f, -2.0f, -1.0f, 0, 1.0f, 2.0f, 3.0f }; Keyframe[] posArr = new Keyframe[tixxx.Length]; int index = 0; for (int i = -3; i <= 3; i++) { posArr[index] = new Keyframe(startValue + i * spaceValue, tixxx[index]); index++; } PositionCurve = new AnimationCurve(posArr); } /// /// 当前处于选中的对象数据索引 /// public int CurSelectElementIndex = -1; /// /// 接手到通知,某个子对象的选中状态发生改变了 /// public void OnReceiveUpdateState(bool isSelected, UI_ScrollFlow_Item item) { if (isSelected) { if (CurSelectElementIndex != item.Index) { CurSelectElementIndex = item.Index; RefreshDraw(); } } if (EventRefreshCardState != null) { EventRefreshCardState(isSelected, item); } } /// /// 当前元素总值 /// public int mDataCount; /// /// 上次定位的位置 /// private int _lastCurIndex; /// /// /// private int lastCurIndex { get { return _lastCurIndex; } set { if (_lastCurIndex != value) { _lastCurIndex = value; } } } /// /// /// private int curIndex = 0; /// /// 英雄列表滑动的数据发生变化 /// public void Hero_DataChanged(int dataCount, bool bResetPos) { CurSelectElementIndex = -1; Current = null; mDataCount = dataCount; if (bResetPos) { //if (mDataCount > 5) //{ // defaultItemIndex = 5; //} //else //{ // defaultItemIndex = mDataCount - 1; //} //lastCurIndex = defaultItemIndex; } //// Debug.LogError("bResetPos:::" + bResetPos + " lastCurIndex:: " + lastCurIndex); /* * 如果需要重新定位的话 * 重新计算每个数据在时间轴的位置 */ // 因为数据改变了,元素要重新获取数据 for (int i = useItemList.Count - 1; i >= 0; i--) { UI_ScrollFlow_Item item = useItemList[i]; item.Index = -1; useItemList.Remove(item); unUseItem.Enqueue(item); } //// Debug.LogError("DataChanged!!!!!" + useItemList.Count); setUpdateRectItem(lastCurIndex, true); //////if (bResetPos) //////{ ////// if (useItemList.Count > 0) ////// { ////// UI_ScrollFlow_Item script = useItemList[0]; ////// if (script == null) ////// { ////// return; ////// } ////// if (Current != script) ////// { ////// //// Debug.LogError("Current 0.5fIndex:::" + Current.Index + " script:: " + script.Index); ////// ToAppointedItem(script); ////// } ////// } //////} //////else //////{ ////// UI_ScrollFlow_Item script = null; ////// //// Debug.LogError(" lastCurIndex:: " + lastCurIndex + " useItemList count::: " + useItemList.Count); ////// if (useItemList.Count > 0) ////// { ////// if (lastCurIndex >= useItemList.Count) ////// { ////// script = useItemList[useItemList.Count - 1]; ////// } ////// else ////// { ////// script = useItemList[lastCurIndex]; ////// } ////// } ////// if (script != null) ////// { ////// //// Debug.LogError("0.5fIndex:::script:: " + script.Index); ////// ToAppointedItem(script); ////// } //////} if (Current != null) { ToAppointedItem(Current); } RefreshDraw(); } /// /// 图鉴的数据发生变化 /// public void Book_DataChanged(int dataCount) { Current = null; mDataCount = dataCount; lastCurIndex = 2; /* * 如果需要重新定位的话 * 重新计算每个数据在时间轴的位置 */ // 因为数据改变了,元素要重新获取数据 for (int i = useItemList.Count - 1; i >= 0; i--) { UI_ScrollFlow_Item item = useItemList[i]; item.Index = -1; useItemList.Remove(item); unUseItem.Enqueue(item); } setUpdateRectItem(lastCurIndex, true); UI_ScrollFlow_Item script = null; if (useItemList.Count > 0) { if (lastCurIndex >= useItemList.Count) { script = useItemList[useItemList.Count - 1]; } else { script = useItemList[lastCurIndex]; } } if (script != null) { ToAppointedItem(script); } } #region /// /// 刷新元素 /// /// 当前所处的行数 private void setUpdateRectItem(int scrollPerLineIndex, bool isNeedFindCurrent = false) { if (scrollPerLineIndex < 0) { return; } int startDataIndex = 0; int endDataIndex = mDataCount; // 移除 for (int i = useItemList.Count - 1; i >= 0; i--) { UI_ScrollFlow_Item item = useItemList[i]; int index = item.Index; if (index < startDataIndex || index >= endDataIndex) { item.Index = -1; useItemList.Remove(item); unUseItem.Enqueue(item); } } // 显示 for (int dataIndex = startDataIndex; dataIndex < endDataIndex; dataIndex++) { if (dataIndex < 0) { continue; } if (dataIndex >= mDataCount) { continue; } if (isExistDataByDataIndex(dataIndex)) { //需要重置下坐标位置 continue; } ////StartCoroutine(createItem(dataIndex, isNeedFindCurrent)); createItem(dataIndex, isNeedFindCurrent); } } private int tempStartIndex = 0; private int tempEndIndex = 0; /// /// content 对象 /// public RectTransform nodeContent = null; /// /// 元素预制物体 /// public GameObject goItemPrefab = null; /// /// 创建元素 /// /// 数据索引 private void createItem(int dataIndex, bool isNeedFindCurrent) { UI_ScrollFlow_Item item = null; if (unUseItem.Count > 0) { item = unUseItem.Dequeue(); } else { GameObject temp = addChild(goItemPrefab, nodeContent); item = temp.GetComponent(); if (item == null) { AssemblyHelper.Instance.BindScript("UI_ScrollFlow_Item", temp); item = temp.GetComponent(); } } item.gameObject.name = dataIndex.ToString(); item.gameObject.SetActive(true); item.ScrollFlowParent = this; item.Index = dataIndex; useItemList.Add(item); float dv = startValue + (dataIndex - lastCurIndex) * spaceValue; //// Debug.LogError("dv !!!!!" + dv); item.Drag(dv); if (isNeedFindCurrent) { if (Mathf.Abs(dv - startValue) < 0.05f) { Current = item; } } ////yield return null; } /// /// 当前数据是否存在 List 中 /// /// 数据索引 /// 是否已存在 private bool isExistDataByDataIndex(int dataIndex, bool isNeedFindCurrent = false) { if (useItemList == null || useItemList.Count <= 0) { return false; } for (int i = 0; i < useItemList.Count; i++) { if (useItemList[i].Index == dataIndex) { return true; } } return false; } /// /// 实例化预设对象 、添加实例化对象到指定的子对象下 /// /// 元素预制物体 /// 父节点 /// 新创建的元素对象 private GameObject addChild(GameObject goPrefab, Transform parent) { if (goPrefab == null || parent == null) { Debug.LogError("异常。UIWarpContent.cs addChild(goPrefab = null || parent = null)"); return null; } GameObject goChild = GameObject.Instantiate(goPrefab) as GameObject; goChild.transform.SetParent(parent, false); goChild.SetActive(true); return goChild; } /// /// 正在使用中的元素 /// private List useItemList = new List(); /// /// 未在使用中的元素 /// private Queue unUseItem = new Queue(); /// /// 销毁 /// private void OnDestroy() { nodeContent = null; goItemPrefab = null; onInitializeItem = null; useItemList.Clear(); unUseItem.Clear(); useItemList = null; unUseItem = null; } #endregion /// /// /// /// public void OnBeginDrag(PointerEventData eventData) { start_point = eventData.position; add_vect = Vector3.zero; _anim = false; } /// /// /// /// public void OnDrag(PointerEventData eventData) { //判断此时 是不是已经到列表尽头,然后做一个极限设定 if (useItemList[0].v > startValue) { float abs = Mathf.Abs(startValue - useItemList[0].v); if (abs > spaceValue) { return; } } if (useItemList[useItemList.Count - 1].v < startValue) { float abs = Mathf.Abs(startValue - useItemList[useItemList.Count - 1].v); if (abs > spaceValue) { return; } } add_vect = eventData.position - start_point; dragV = eventData.delta.x * 1.00f / itemWidth; //计算移动量,对应卡牌的比例 for (int i = 0; i < useItemList.Count; i++) { useItemList[i].Drag(dragV); } } /// /// 这块需要调整 /// 要不然不知道拖拽到哪个了...................... /// /// public void OnEndDrag(PointerEventData eventData) { float k = 0, v1; for (int i = 0; i < useItemList.Count; i++) { if (useItemList[i].v >= startValue) { v1 = (useItemList[i].v - startValue) % spaceValue; if (add_vect.x >= 0) { k = spaceValue - v1; //确定向右移动 () } else { k = v1 * -1; } break; } } add_vect = Vector3.zero; // 判断是否拖拽到极限 if (useItemList[0].v > startValue) { //说明向右滑道头了 k = useItemList[0].v; k = startValue - k; AnimToEnd(k); return; } if (useItemList[useItemList.Count - 1].v < startValue) { k = useItemList[useItemList.Count - 1].v; k = startValue - k; AnimToEnd(k); return; } AnimToEnd(k); } /// /// /// /// /// public float GetPositionX(float v, int _index) { //return v * itemWidth; return PositionCurve.Evaluate(v) * itemWidth; } /// /// 获取卡牌移动速度 /// /// /// public float GetMoveSpeed(float v) { //return v * itemWidth; return SpeedCurve.Evaluate(v) * 1.0f; } /// /// /// /// /// public float GetScale(float v) { return ScaleCurve.Evaluate(v) * MaxScale; } /// /// 主要进行排序 /// 除了中间之外的, 左侧的,从左到右绘制. /// 中间右侧,从右到左绘制 /// public void LateUpdate() { if (!IsOPenReDraw) { return; } List left = new List(); List right = new List(); List middle = new List(); int index = 0; // Debug.LogError("LateUpdate:::" + useItemList.Count); for (int i = 0; i < useItemList.Count; i++) { float abs = Mathf.Abs(startValue - useItemList[i].v); if (abs < 0.05f) { middle.Add(useItemList[i]); } else { if (useItemList[i].v > startValue) { right.Add(useItemList[i]); } else { left.Add(useItemList[i]); } } } ////按照 顺序重新绘制 左侧 索引 右侧绘制从大到小 left.Sort(sortByIndex); right.Sort(sortByIndex); for (int i = 0; i < left.Count; i++) { left[i].rect.SetSiblingIndex(index); index++; } for (int i = right.Count - 1; i >= 0; i--) { right[i].rect.SetSiblingIndex(index); index++; } for (int i = 0; i < middle.Count; i++) { middle[i].rect.SetSiblingIndex(index); index++; } IsOPenReDraw = false; } private bool IsOPenReDraw = false; /// /// /// public void RefreshDraw() { // 停止创建元素 ////StopCoroutine("ReDraw"); ////StartCoroutine("ReDraw"); IsOPenReDraw = true; } ////private IEnumerator ReDraw() ////{ //// Dictionary xx = new Dictionary(); //// foreach (UI_ScrollFlow_Item ele in useItemList) //// { //// xx.Add(ele.ResetSiblingIndex(), ele); //// } //// List temp = new List(); //// temp.AddRange(xx.Keys); //// temp.Sort(); //// temp.Reverse(); //// foreach (int key in temp) //// { //// xx[key].rect.SetAsLastSibling(); //// } //// yield return null; ////} private int sortByIndex(UI_ScrollFlow_Item item1, UI_ScrollFlow_Item item2) { int result = 0; if (item1.Index > item2.Index) { result = 1; } else if (item1.Index < item2.Index) { result = -1; } return result; } /// /// 移动结束 /// /// 移动距离 public void AnimToEnd(float k) { AddV = k; if (AddV > 0) { Vk = 1; } else if (AddV < 0) { Vk = -1; } else { return; } Vtotal = 0; _anim_speed = GetMoveSpeed(k); _anim = true; } /// /// /// private void Update() { if (_anim) { CurrentV = Time.deltaTime * _anim_speed * Vk; ////通过update 来累加 CurrentV; ////直到移动量,达到要求的结束动画. ////主要对点击某个卡牌,移动直到显示某个具体位置卡牌有效. VT = Vtotal + CurrentV; if (Vk > 0 && VT >= AddV) { _anim = false; CurrentV = AddV - Vtotal; } if (Vk < 0 && VT <= AddV) { _anim = false; CurrentV = AddV - Vtotal; } ////============================================= for (int i = 0; i < useItemList.Count; i++) { useItemList[i].Drag(CurrentV); if (useItemList[i].v - startValue < 0.05f) { Current = useItemList[i]; } } Vtotal = VT; if (!_anim) { lastCurIndex = Current.Index; //setUpdateRectItem(lastCurIndex); if (MoveEnd != null) { MoveEnd(Current); } } } } /// /// 转到指定子对象显示 /// /// public void ToAppointedItem(UI_ScrollFlow_Item script) { if (script == null) return; float k = script.v; k = startValue - k; AnimToEnd(k); } }