using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UIElements; namespace MuHua { /// /// 滚动视图 - 水平 /// public class UIScrollViewH : ModuleUIPanel, UIControl { /// 绑定的画布 public readonly VisualElement canvas; /// 元素方向 public readonly UIDirection direction; /// 水平滑块 public readonly UIScrollerH horizontal; /// 值改变时 public event Action ValueChanged; /// /// 方向 /// public enum UIDirection { FromLeftToRight = 0, FromRightToLeft = 1, } public float value; public bool isDrag; public Vector3 originalPosition; public Vector3 pointerPosition; public readonly VisualElement Viewport; public readonly VisualElement Container; public readonly VisualElement ScrollerHorizontal; public UIScrollViewH(VisualElement element, VisualElement canvas, UIDirection direction = UIDirection.FromLeftToRight) : base(element) { this.canvas = canvas; this.direction = direction; Viewport = element.Children().FirstOrDefault(e => e.name == "Viewport"); Container = Viewport.Children().FirstOrDefault(e => e.name == "Container"); ScrollerHorizontal = element.Children().FirstOrDefault(e => e.name == "ScrollerHorizontal"); if (direction == UIDirection.FromLeftToRight) { horizontal = new UIScrollerH(ScrollerHorizontal, canvas, UIScrollerH.UIDirection.FromLeftToRight); } if (direction == UIDirection.FromRightToLeft) { horizontal = new UIScrollerH(ScrollerHorizontal, canvas, UIScrollerH.UIDirection.FromRightToLeft); } // 设置事件 horizontal.ValueChanged += (y) => { UpdateValue(y); }; Viewport.RegisterCallback(ViewportWheel); Viewport.RegisterCallback(DraggerDown); Viewport.RegisterCallback(DraggerUpOrLeave); Viewport.style.flexDirection = direction == UIDirection.FromLeftToRight ? FlexDirection.Row : FlexDirection.RowReverse; // 释放 canvas.RegisterCallback(DraggerUpOrLeave); canvas.RegisterCallback(DraggerUpOrLeave); // 视图原始更新 element.generateVisualContent += ElementGenerateVisualContent; } /// 解绑事件,防止内存泄漏 public virtual void Dispose() { Viewport.UnregisterCallback(ViewportWheel); Viewport.UnregisterCallback(DraggerDown); Viewport.UnregisterCallback(DraggerUpOrLeave); canvas.UnregisterCallback(DraggerUpOrLeave); canvas.UnregisterCallback(DraggerUpOrLeave); element.generateVisualContent -= ElementGenerateVisualContent; } /// 原始更新 private void ElementGenerateVisualContent(MeshGenerationContext context) { float width = Mathf.Clamp01(Viewport.resolvedStyle.width / Container.resolvedStyle.width); horizontal.Dragger.style.width = Length.Percent(width * 100); } /// 滚轮滑动 private void ViewportWheel(WheelEvent evt) { float wheel = Mathf.Clamp(evt.delta.y, -1, 1); UpdateValue(value - wheel); } /// 拖拽按下 private void DraggerDown(PointerDownEvent evt) { isDrag = true; originalPosition = Container.transform.position; Vector3 mousePosition = UITool.GetMousePosition(); pointerPosition = new Vector3(mousePosition.x, Screen.height - mousePosition.y); } /// 拖拽滑动 private void Dragger() { Vector3 mousePosition = UITool.GetMousePosition(); Vector3 differ = new Vector3(mousePosition.x, Screen.height - mousePosition.y) - pointerPosition; Vector3 offset = differ + originalPosition; float maxWidth = Viewport.resolvedStyle.width - Container.resolvedStyle.width; float x = offset.x / maxWidth; x *= direction == UIDirection.FromLeftToRight ? 1 : -1; UpdateValue(x); } /// 滑动弹性 private void SlidingElasticity() { float original = value; float max = Viewport.resolvedStyle.width < Container.resolvedStyle.width ? 1 : 0; if (value < 0) { value = Mathf.Lerp(value, 0, Time.deltaTime * 10); } if (value > max) { value = Mathf.Lerp(value, max, Time.deltaTime * 10); } if (original != value) { UpdateValue(value); } } /// 鼠标松开或离开 private void DraggerUpOrLeave(EventBase evt) { isDrag = false; } /// 更新状态 public void Update() { horizontal.Update(); SlidingElasticity(); if (isDrag) { Dragger(); } } /// 更新值(0-1) public void UpdateValue(float value, bool send = true) { this.value = value; if (send) { ValueChanged?.Invoke(value); } float maxWidth = Viewport.resolvedStyle.width - Container.resolvedStyle.width; float position = maxWidth * value; position *= direction == UIDirection.FromLeftToRight ? 1 : -1; Container.transform.position = new Vector3(position, 0); if (horizontal.value != value) { horizontal.UpdateValue(value, false); } } } }