Files
MinFt/Client/Assets/Scripts/UIExtend/PanelScroll.cs
Liubing\LB 3d8d4d18f3 first commit
先修复一下,错误的场景

删除不必要的钓场资产

修复into场景

update:更新meta文件,修复报错

update:修复资源

修复第一章节建造

修复建造第三章

update:删除多余内容

update:更新README.md

update:还原图标

update:更新README

update:更新配置
2026-04-28 02:17:22 +08:00

687 lines
26 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
using System.Collections.Generic;
using DG.Tweening;
public class PanelScroll : ScrollRect
{
// [SerializeField] public float inertiaMaxTime = 0.5f; //限制惯性持续时间
// private float _scrolledTime = 0f;
private Action _stopScrollCallback = null;
private Vector2 _lastPosition = Vector2.zero;
private float offsetX;
private RectTransform _content;
private Action StopScrollCallback;
private Action RefreshItem;
public bool loop = false;
public int currentIndex;
public int FirstIndex;
public int CurDownIndex;
private int minShowItemNum;
List<GameObject> itemGoList = new List<GameObject>();
Vector2 startDeltaPos;
Vector2 endDeltaDirection;
bool isDrag = false;
public bool isReversal = false;
int minShowAdd = 2;
Vector2 InverseTransformPointOffset;
float startAdd = 0;
protected override void Start()
{
base.Start();
RectTransform rectTransform = GetComponent<RectTransform>();
var pivot = rectTransform.pivot - new Vector2(0.5f, 0.5f);
var rect = rectTransform.rect.size;
InverseTransformPointOffset = new Vector2(pivot.x * rect.x, pivot.y * rect.y);
}
public List<T> Init<T, T1>(float _offsetX, GameObject _item, Action<T> _OnBtnItem,
List<T1> _ItemData, bool click = false, int _currentIndex = 0, int _minShowAdd = 2)
where T : PanelItemBase<T1>
{
float spacing = 0;
float addSizeDelta = 0; startAdd = 0;
if (horizontal)
{
HorizontalLayoutGroup layoutGroup = content.GetComponent<HorizontalLayoutGroup>();
if (layoutGroup != null)
{
spacing = layoutGroup.spacing;
addSizeDelta = layoutGroup.padding.horizontal;
startAdd = layoutGroup.padding.left;
layoutGroup.enabled = false;
}
}
else
{
VerticalLayoutGroup layoutGroup = content.GetComponent<VerticalLayoutGroup>();
if (layoutGroup != null)
{
spacing = layoutGroup.spacing;
addSizeDelta = layoutGroup.padding.vertical;
startAdd = layoutGroup.padding.top;
layoutGroup.enabled = false;
}
}
_offsetX += spacing;
minShowAdd = _minShowAdd;
if (_currentIndex >= _ItemData.Count)
{
_currentIndex = _ItemData.Count - 1;
}
int _showItemNum;
int showDelta = _ItemData.Count;
if (horizontal)
minShowItemNum = Mathf.CeilToInt(GetComponent<RectTransform>().rect.width / _offsetX) + minShowAdd;
else
minShowItemNum = Mathf.CeilToInt(GetComponent<RectTransform>().rect.height / _offsetX) + minShowAdd;
_showItemNum = minShowItemNum;
if (loop)
{
showDelta = minShowItemNum;
}
else if (minShowItemNum > _ItemData.Count)
{
_showItemNum = showDelta;
}
movementType = loop ? MovementType.Unrestricted : MovementType.Elastic;
offsetX = _offsetX;
_item.gameObject.SetActive(false);
_content = transform.Find("Viewport/Content").GetComponent<RectTransform>();
_content.sizeDelta = horizontal ? new Vector2(showDelta * _offsetX + addSizeDelta, _content.sizeDelta.y) : new Vector2(_content.sizeDelta.x, showDelta * _offsetX + addSizeDelta);
if (isReversal)
{
_content.anchoredPosition = horizontal ?
new Vector2(loop ? -((_showItemNum - 1) / 2f - _currentIndex) * _offsetX : _currentIndex * _offsetX, _content.anchoredPosition.y) :
new Vector2(_content.anchoredPosition.x, loop ? -(_currentIndex - (_showItemNum - 1) / 2f) * _offsetX : -_currentIndex * _offsetX);
}
else
{
_content.anchoredPosition = horizontal ?
new Vector2(loop ? ((_showItemNum - 1) / 2f - _currentIndex) * _offsetX : -_currentIndex * _offsetX, _content.anchoredPosition.y) :
new Vector2(_content.anchoredPosition.x, loop ? (_currentIndex - (_showItemNum - 1) / 2f) * _offsetX : _currentIndex * _offsetX);
}
List<T> items = new List<T>();
int count = itemGoList.Count;
for (int i = 0; i < count; i++)
{
itemGoList[i].SetActive(false);
}
for (int i = 0; i < _showItemNum; i++)
{
GameObject go;
if (count > i)
{
go = itemGoList[i].gameObject;
}
else
{
go = Instantiate(_item, _content);
itemGoList.Add(go);
}
go.SetActive(true);
if (isReversal)
{
go.transform.GetComponent<RectTransform>().anchoredPosition = horizontal ?
new Vector3(-(i + 0.5f) * _offsetX - startAdd, go.transform.GetComponent<RectTransform>().anchoredPosition.y, 0) :
new Vector3(go.transform.GetComponent<RectTransform>().anchoredPosition.x, (i + 0.5f) * _offsetX + startAdd, 0);
}
else
{
go.transform.GetComponent<RectTransform>().anchoredPosition = horizontal ?
new Vector3((i + 0.5f) * _offsetX + startAdd, go.transform.GetComponent<RectTransform>().anchoredPosition.y, 0) :
new Vector3(go.transform.GetComponent<RectTransform>().anchoredPosition.x, -(i + 0.5f) * _offsetX - startAdd, 0);
}
T t = go.GetComponent<T>() ?? go.AddComponent<T>();
items.Add(t);
items[i].index = i;
var i1 = i;
items[i].OnBtnItemAction = () => { _OnBtnItem?.Invoke(items[i1]); };
items[i].SetDataAction = () =>
{
int count = _ItemData.Count;
items[i1].index %= count;
if (items[i1].index < 0)
{
items[i1].index += count;
}
return _ItemData[items[i1].index];
};
}
if (isReversal)
{
ReversalSetOnValueChanged(items, _ItemData);
}
else
{
SetOnValueChanged(items, _ItemData);
}
SetStopScrollCallback(click, items, _ItemData);
RefreshItem = () =>
{
foreach (var t in items)
{
t.SetData();
}
};
currentIndex = _currentIndex;
if (currentIndex > 1)
{
if (!loop)
{
if (currentIndex + _showItemNum > showDelta)
{
currentIndex = showDelta - _showItemNum;
}
currentIndex--;
}
//currentIndex -= minShowItemNum;
for (int i = items.Count - 1; i >= 0; i--)
{
T t = items[i];
if (isReversal)
{
t.rectTransform.anchoredPosition = horizontal ?
new Vector3(t.rectTransform.anchoredPosition.x - currentIndex * offsetX, t.rectTransform.anchoredPosition.y, 0) :
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y + currentIndex * offsetX, 0);
}
else
{
t.rectTransform.anchoredPosition = horizontal ?
new Vector3(t.rectTransform.anchoredPosition.x + currentIndex * offsetX, t.rectTransform.anchoredPosition.y, 0) :
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y - currentIndex * offsetX, 0);
}
t.index += currentIndex;
}
}
RefreshItem();
currentIndex = _currentIndex;
if (click)
{
if (currentIndex > 0)
{
for (int i = 0; i < items.Count; i++)
{
if (items[i].index == _currentIndex)
{
_OnBtnItem?.Invoke(items[i]);
return items;
}
}
}
if (items.Count > 0)
{
_OnBtnItem?.Invoke(items[0]);
}
}
return items;
}
void ReversalSetOnValueChanged<T, T1>(List<T> items, List<T1> _ItemData) where T : PanelItemBase<T1>
{
onValueChanged.RemoveAllListeners();
if (horizontal)
{
onValueChanged.AddListener(arg0 =>
{
foreach (var t in items)
{
//transform相对于scrollRect的位置
var arg1 = InverseTransformPoint(t.transform.position);
if (arg1.x < -(minShowItemNum + 1) / 2 * offsetX/* - offsetX*/)
{
if (loop || t.index - minShowItemNum >= 0)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x + minShowItemNum * offsetX, t.rectTransform.anchoredPosition.y, 0);
t.OnChangIndex(-minShowItemNum);
}
}
else if (arg1.x > (minShowItemNum + 1) / 2 * offsetX /*+ offsetX*/)
{
if (loop || t.index + minShowItemNum < _ItemData.Count)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x - minShowItemNum * offsetX, t.rectTransform.anchoredPosition.y, 0);
t.OnChangIndex(minShowItemNum);
}
}
arg1 = InverseTransformPoint(t.transform.position);
t.OffsetX(arg1.x, offsetX);
}
});
}
else
{
onValueChanged.AddListener(arg0 =>
{
foreach (var t in items)
{
//transform相对于scrollRect的位置
var arg1 = InverseTransformPoint(t.transform.position);
if (arg1.y < -(minShowItemNum + 1) / 2 * offsetX/* - offsetX*/)
{
if (loop || t.index + minShowItemNum < _ItemData.Count)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y + minShowItemNum * offsetX, 0);
t.OnChangIndex(minShowItemNum);
}
}
else if (arg1.y > (minShowItemNum + 1) / 2 * offsetX /*+ offsetX*/)
{
if (loop || t.index - minShowItemNum >= 0)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y - minShowItemNum * offsetX, 0);
t.OnChangIndex(-minShowItemNum);
}
}
arg1 = InverseTransformPoint(t.transform.position);
t.OffsetX(arg1.y, offsetX);
}
});
}
}
void SetOnValueChanged<T, T1>(List<T> items, List<T1> _ItemData) where T : PanelItemBase<T1>
{
onValueChanged.RemoveAllListeners();
if (horizontal)
{
onValueChanged.AddListener(arg0 =>
{
var panelHeight = GetComponent<RectTransform>().rect.width;
var panelUpPos = panelHeight / 2f;
var PanelDownPos = -panelHeight / 2f;
foreach (var t in items)
{
//transform相对于scrollRect的位置
var arg1 = InverseTransformPoint(t.transform.position);
//进入退出窗口判断
var itemUpPos = arg1.x + offsetX / 2f;
var itemDownPos = arg1.x - offsetX / 2f;
if (itemUpPos > PanelDownPos && CurDownIndex < t.index)
CurDownIndex = t.index;
if (itemUpPos < PanelDownPos && CurDownIndex >= t.index)
CurDownIndex = Mathf.Clamp(t.index - 1, 0, _ItemData.Count - 1);
if (itemDownPos < panelUpPos && FirstIndex > t.index)
{
FirstIndex = t.index;
}
if (itemDownPos > panelUpPos && FirstIndex <= t.index)
FirstIndex = Mathf.Clamp(t.index + 1, 0, _ItemData.Count - 1);
if (arg1.x < -(minShowItemNum + 1) / 2 * offsetX/* - offsetX*/)
{
if (loop || t.index + minShowItemNum < _ItemData.Count)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x + minShowItemNum * offsetX, t.rectTransform.anchoredPosition.y, 0);
t.OnChangIndex(minShowItemNum);
}
}
else if (arg1.x > (minShowItemNum + 1) / 2 * offsetX /*+ offsetX*/)
{
if (loop || t.index - minShowItemNum >= 0)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x - minShowItemNum * offsetX, t.rectTransform.anchoredPosition.y, 0);
t.OnChangIndex(-minShowItemNum);
}
}
arg1 = InverseTransformPoint(t.transform.position);
t.OffsetX(arg1.x, offsetX);
}
});
}
else
{
onValueChanged.AddListener(arg0 =>
{
var panelHeight = GetComponent<RectTransform>().rect.height;
var panelUpPos = panelHeight / 2f;
var PanelDownPos = -panelHeight / 2f;
foreach (var t in items)
{
//transform相对于scrollRect的位置
var arg1 = InverseTransformPoint(t.transform.position);
//进入退出窗口判断
var itemUpPos = arg1.y + offsetX / 2f;
var itemDownPos = arg1.y - offsetX / 2f;
if (itemUpPos > PanelDownPos && CurDownIndex < t.index)
CurDownIndex = t.index;
if (itemUpPos < PanelDownPos && CurDownIndex >= t.index)
CurDownIndex = Mathf.Clamp(t.index - 1, 0, _ItemData.Count - 1);
if (itemDownPos < panelUpPos && FirstIndex > t.index)
{
FirstIndex = t.index;
}
if (itemDownPos > panelUpPos && FirstIndex <= t.index)
FirstIndex = Mathf.Clamp(t.index + 1, 0, _ItemData.Count - 1);
//循环判断
if (arg1.y < -(minShowItemNum + 1) / 2 * offsetX /*- offsetX*/)
{
if (loop || t.index - minShowItemNum >= 0)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y + minShowItemNum * offsetX, 0);
t.OnChangIndex(-minShowItemNum);
}
}
else if (arg1.y > (minShowItemNum + 1) / 2 * offsetX /*+ offsetX*/)
{
if (loop || t.index + minShowItemNum < _ItemData.Count)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y - minShowItemNum * offsetX, 0);
t.OnChangIndex(minShowItemNum);
}
}
arg1 = InverseTransformPoint(t.transform.position);
t.OffsetX(arg1.y, offsetX);
}
});
}
}
void SetStopScrollCallback<T, T1>(bool click, List<T> items, List<T1> _ItemData) where T : PanelItemBase<T1>
{
if (click)
{
if (horizontal)
{
StopScrollCallback = () =>
{
int count = items.Count;
for (int i = 0; i < count; i++)
{
T t = items[i];
Vector3 pos = InverseTransformPoint(t.transform.position);
if (pos.x > -offsetX / 2 - 0.01f && pos.x < offsetX / 2 + 0.01f)
{
if (isDrag)
{
if (endDeltaDirection.x > 1)
{
if (pos.x > 5)
{
if (i != 0)
{
if (loop || currentIndex > 0)
{
t = items[i - 1];
}
}
else if (loop || t.index - minShowItemNum / 2 >= 0)
{
t = items[^1];
}
}
}
else if (endDeltaDirection.x < -1)
{
if (pos.x < -5)
{
if (i < count - 1)
{
if (loop || currentIndex < _ItemData.Count - 1)
{
t = items[i + 1];
}
}
else if (loop || t.index + minShowItemNum / 2 < _ItemData.Count)
{
t = items[0];
}
}
}
}
if (!loop)
{
content.DOLocalMoveX(-t.transform.localPosition.x + 0.5f * offsetX, 0.2f);
}
currentIndex = t.index;
t.OnBtnItem();
break;
}
}
isDrag = false;
};
}
else
{
StopScrollCallback = () =>
{
int count = items.Count;
for (int i = 0; i < count; i++)
{
T t = items[i];
Vector3 pos = InverseTransformPoint(t.transform.position);
if (pos.y > -offsetX / 2 - 0.01f && pos.y < offsetX / 2 + 0.01f)
{
if (isDrag)
{
if (endDeltaDirection.y > 1)
{
if (pos.y > 10)
{
if (i < count - 1)
{
t = items[i + 1];
}
else if (loop || t.index + minShowItemNum / 2 < _ItemData.Count)
{
t = items[0];
}
}
}
else if (endDeltaDirection.y < -1)
{
if (pos.y < -10)
{
if (i != 0)
{
t = items[i - 1];
}
else if (loop || t.index - minShowItemNum / 2 >= 0)
{
t = items[^1];
}
}
}
}
if (!loop)
{
content.DOLocalMoveY(-t.transform.localPosition.y - 0.5f * offsetX, 0.2f);
}
currentIndex = t.index;
t.OnBtnItem();
break;
}
}
isDrag = false;
};
}
}
else
{
StopScrollCallback = null;
}
}
//跳到目标位置
public void JumpToTarget(int index, float posOffset = 0f)
{
float offset = offsetX;
if (isReversal)
{
offset = -offsetX;
}
if (loop)
{
if (index > currentIndex)
{
if (horizontal)
{
_content.DOLocalMoveX(_content.localPosition.x - (index - currentIndex) * offset + posOffset, 0.3f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
else
{
_content.DOLocalMoveY(_content.localPosition.y + (index - currentIndex) * offset + posOffset, 0.3f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
}
else
{
if (horizontal)
{
_content.DOLocalMoveX(_content.localPosition.x + (currentIndex - index) * offset + posOffset, 0.3f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
else
{
_content.DOLocalMoveY(_content.localPosition.y - (currentIndex - index) * offset + posOffset, 0.3f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
}
}
else
{
index -= (int)((minShowItemNum - minShowAdd) / 2f);
if (horizontal)
{
_content.DOLocalMoveX(-index * offset + posOffset, 0.5f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
else
{
_content.DOLocalMoveY(index * offset + posOffset, 0.5f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
}
}
public void Refresh()
{
RefreshItem?.Invoke();
}
public override void OnBeginDrag(PointerEventData eventData)
{
base.OnBeginDrag(eventData);
startDeltaPos = eventData.position;
}
public override void OnEndDrag(PointerEventData eventData)
{
base.OnEndDrag(eventData);
endDeltaDirection = eventData.position - startDeltaPos;
isDrag = true;
_stopScrollCallback = StopScrollCallback;
// _scrolledTime = 0f;
//如果没有在移动
if (this.velocity.magnitude < 3)
{
if (_stopScrollCallback != null)
{
_stopScrollCallback();
_stopScrollCallback = null;
}
}
}
public override void OnDrag(PointerEventData eventData)
{
base.OnDrag(eventData);
// _scrolledTime = 0f;
}
protected override void SetContentAnchoredPosition(Vector2 position)
{
if (Vector3.Distance(_lastPosition, position) < 3)
{
if (_stopScrollCallback != null)
{
_stopScrollCallback();
_stopScrollCallback = null;
}
return;
}
_lastPosition = position;
base.SetContentAnchoredPosition(position);
// _scrolledTime += Time.unscaledDeltaTime;
}
public Vector3 InverseTransformPoint(Vector3 position)
{
var point = transform.InverseTransformPoint(position);
point.x += InverseTransformPointOffset.x;
point.y += InverseTransformPointOffset.y;
return point;
}
}
public abstract class PanelItemBase<T> : MonoBehaviour
{
private RectTransform _rectTransform;
public Action OnBtnItemAction;
public Func<T> SetDataAction;
public T data;
public RectTransform rectTransform
{
get
{
if (_rectTransform == null)
{
_rectTransform = GetComponent<RectTransform>();
}
return _rectTransform;
}
}
public int index = 0;
public abstract void OnInit();
public virtual void OffsetX(float _offsetX, float width)
{
}
public virtual void SetData()
{
data = SetDataAction();
OnInit();
}
public virtual void OnBtnItem()
{
OnBtnItemAction?.Invoke();
}
public void OnChangIndex(int _index)
{
index += _index;
SetData();
}
}