using BeinLab.Util; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using XRTool.UI; using XRTool.Util; namespace XRTool.WorldUI { /// /// LayoutGroup /// public enum LayoutType { None = -2, UnKnow = -1, GridLayoutGroup = 0, VerticalLayoutGroup = 1, HorizontalLayoutGroup = 2, } /// /// 目标:1实现基本列表功能,生成,销毁,刷新,点击事件的传递等,支持常规的Button,Toggle类型的组件支持 /// 2,实现滑动循环列表 /// 3,实现多项内容展示时的优化 /// 4,指定距离停顿 /// public class XRScrollRect : ScrollRect { public bool isLoop; public LayoutType layoutType = LayoutType.UnKnow; private int allCount; private int showCount; private Vector2 cellSize; private Vector2 cellSpace; //private bool isDraging = false; private ItemCell superCell; private LayoutGroup layoutGroup; private List cellList; private Bounds viewBounds; //private float dragTime = 0.2f; //private float lastDragTime; protected override void Start() { base.Start(); viewBounds = new Bounds(viewRect.rect.center, viewRect.rect.size); } public LayoutGroup LayoutGroup { get { if (!layoutGroup) { layoutGroup = content.GetComponent(); } return layoutGroup; } } public List CellList { get => cellList; set => cellList = value; } protected override void LateUpdate() { if ( velocity.magnitude > 66 || !IsMoveCalculatePosition()) { base.LateUpdate(); XRUpdateItemVisibility(); } } /// /// 更新显示Scroll /// private void XRUpdateItemVisibility() { ///存在子物体,同时显示数据小于总物体数字时 if (allCount > 0 && showCount < allCount && content.childCount > 0) { for (int i = 0; i < content.childCount; i++) { RectTransform child = content.GetChild(i) as RectTransform; if (child.anchoredPosition.x < 0) { child.GetChild(0).gameObject.SetActive(false); } } } } /// /// 计算最终落点 /// /// public bool IsMoveCalculatePosition() { return false; } /// /// 初始化数据 /// /// /// /// /// /// public void InitData(int count, int showCount, Vector2 cellSize, Vector3 cellSpace, ItemCell prefab) { this.allCount = count; this.showCount = showCount; this.cellSize = cellSize; this.cellSpace = cellSpace; this.superCell = prefab; CreateScrollList(); } public void ClearScrollList() { if (content) { for (int i = 0; i < content.childCount; i++) { Destroy(content.GetChild(i).gameObject); } } CellList.Clear(); } /// /// 创建列表 /// private void CreateScrollList(bool isClear = true) { if (CellList == null) { CellList = new List(); } if (isClear) { ClearScrollList(); } GameObject prefab = superCell.GetInstance(); ///prefab.GetInstance()获取抽象类的实例,不确定这么做可以正常运行,测试中 if (prefab) { if (!isLoop) { int instanceCount = showCount; if (showCount >= allCount) { instanceCount = allCount; } for (int i = 0; i < instanceCount; i++) { GameObject obj = Instantiate(prefab); UnityUtil.SetParent(content, obj.transform); CellList.Add(obj.GetComponent()); } RectTransform body = GetComponent(); Vector2 size = body.sizeDelta; if (horizontal && !vertical) { size.y = cellSize.y; //size.x = instanceCount*cellSize.x + } else if (vertical && !horizontal) { size.x = cellSize.x; } } } if (LayoutGroup) { if (LayoutGroup is GridLayoutGroup) { var lay = (LayoutGroup as GridLayoutGroup); lay.cellSize = this.cellSize; lay.spacing = this.cellSpace; } else if (LayoutGroup is VerticalLayoutGroup) { var lay = (LayoutGroup as VerticalLayoutGroup); lay.spacing = this.cellSpace.y; } else if (LayoutGroup is HorizontalLayoutGroup) { var lay = (LayoutGroup as HorizontalLayoutGroup); lay.spacing = this.cellSpace.x; } } } //private void XRUpdateScrollbarVisibility() //{ // if (horizontalScrollbar && !isShowHorizontal && horizontalScrollbar.isActiveAndEnabled) // { // horizontalScrollbar.gameObject.SetActive(false); // } // if (verticalScrollbar && !isShowVertical && verticalScrollbar.isActiveAndEnabled) // { // verticalScrollbar.gameObject.SetActive(false); // } //} public override void OnDrag(PointerEventData eventData) { base.OnDrag(eventData); } protected override void SetContentAnchoredPosition(Vector2 position) { base.SetContentAnchoredPosition(position); } //public override void OnBeginDrag(PointerEventData eventData) //{ // base.OnBeginDrag(eventData); // //isDraging = true; // //lastDragTime = Time.time; //} //public override void OnEndDrag(PointerEventData eventData) //{ // base.OnEndDrag(eventData); // //isDraging = false; // //if (Time.time - lastDragTime < dragTime) // //{ // // if (eventData.pointerEnter) // // { // // var tmpbutton = eventData.pointerEnter.GetComponentInParent(); // // if (tmpbutton != null) // // { // // tmpbutton.OnPointerClick(eventData); // // } // // } // //} //} protected override void OnRectTransformDimensionsChange() { base.OnRectTransformDimensionsChange(); viewBounds = new Bounds(viewRect.rect.center, viewRect.rect.size); } private static float XRRubberDelta(float overStretching, float viewSize) { return (1 - (1 / ((Mathf.Abs(overStretching) * 0.55f / viewSize) + 1))) * viewSize * Mathf.Sign(overStretching); } private Vector2 XRCalculateOffset(Vector2 delta) { return XRInternalCalculateOffset(ref viewBounds, ref m_ContentBounds, horizontal, vertical, movementType, ref delta); } internal static Vector2 XRInternalCalculateOffset(ref Bounds viewBounds, ref Bounds contentBounds, bool horizontal, bool vertical, MovementType movementType, ref Vector2 delta) { Vector2 offset = Vector2.zero; if (movementType == MovementType.Unrestricted) return offset; Vector2 min = contentBounds.min; Vector2 max = contentBounds.max; // min/max offset extracted to check if approximately 0 and avoid recalculating layout every frame (case 1010178) if (horizontal) { min.x += delta.x; max.x += delta.x; float maxOffset = viewBounds.max.x - max.x; float minOffset = viewBounds.min.x - min.x; if (minOffset < -0.001f) offset.x = minOffset; else if (maxOffset > 0.001f) offset.x = maxOffset; } if (vertical) { min.y += delta.y; max.y += delta.y; float maxOffset = viewBounds.max.y - max.y; float minOffset = viewBounds.min.y - min.y; if (maxOffset > 0.001f) offset.y = maxOffset; else if (minOffset < -0.001f) offset.y = minOffset; } return offset; } } }