using DG.Tweening; using System; using UnityEngine; using XGame.Framework.FGUI; using XGame.Framework.Interfaces; using XGame.Framework.Time; namespace FL.FGUI.Actions { /// /// MoveLineAction的参数 /// public struct UIMoveActionArgs { public Vector3 from; public Vector3 to; /// /// 单位:毫秒 /// public int duration; /// /// 延迟,单位: 毫秒 /// public int delay; public float offset; public Ease ease; public Action onUpdate; public Action onComplete; } public class UIMoveBezierAction : IAction, IPauseable, ITimeScalable { public UIMoveActionArgs args; private Tween _tween; private bool _paused; float ITimeScalable.TimeScale { get => _tween?.timeScale ?? 1; set { if (_tween == null) { return; } _tween.timeScale = value; } } void IReference.Clear() { _tween?.Kill(); _tween = null; args = default; _paused = false; } public void Start(FguiViewModel viewModel) { // 贝塞尔曲线运动 viewModel.Pos = args.from; var timeScale = UnityEngine.Random.Range(0.2f, 0.8f); var linePoint = Vector3.Lerp(args.from, args.to, timeScale); var dir = Vector3.Cross(args.to - args.from, Vector3.forward).normalized; //运动方向的法线 var offset = args.offset > 0 ? args.offset : 300; var disOffset = UnityEngine.Random.Range(-offset, offset); var center = linePoint + dir * disOffset; var totalTime = args.duration * 0.001f; var timeTween = DOTween.To(() => 0, (t) => { var tNormal = t / totalTime; var pos = args.from.BezierPoint(center, args.to, tNormal); viewModel.Pos = pos; args.onUpdate.SafeInvoke(pos); }, totalTime, totalTime); if (args.delay > 0) timeTween.SetDelay(args.delay * 0.001f); timeTween.SetEase(args.ease == Ease.Unset ? Ease.OutQuad : args.ease); _tween = timeTween; timeTween.onComplete = () => { var callback = args.onComplete; _tween = null; args = default; callback?.Invoke(); }; } void IAction.Start(FguiViewModel viewModel) { Start(viewModel); } void IPauseable.Pause() { if (_tween == null || _paused) { return; } _paused = true; _tween.Pause(); } void IPauseable.Resume() { if (_paused) { _paused = false; _tween?.Play(); } } } }