#region Copyright RenGuiYou. All rights reserved. //===================================================== // NeatlyFrameWork // Author: RenGuiyou // Feedback: mailto:750539605@qq.com //===================================================== #endregion using System; using UnityEngine; using System.Collections.Generic; namespace Neatly.UI { internal class UITween : MonoBehaviour { // public int tweenCount = 0; // public int impCount = 0; // public int objCount = 0; private static UITween m_Instance; public static UITween Instance { get { if (m_Instance == null) { GameObject go = new GameObject(); m_Instance = go.AddComponent(); go.hideFlags = HideFlags.HideInHierarchy; DontDestroyOnLoad(go); } return m_Instance; } } private readonly List m_TweenImps = new List(); private readonly UITweenPool m_TweenImpPool = new UITweenPool(); private readonly UITweenPool m_TweenObjectPool = new UITweenPool(); public static UITweenImp RadarScale(NRadarChart radar, float[] radarData, float time) { TweenObject itween = TweenObject.CreateRadarScale(radar, radarData, time); return CreateTweenImp(itween); } public static UITweenImp ButtonPress(NButtonBase button, Color start, Color target, float time) { TweenObject itween = TweenObject.CreateButtonPress(button, start, target, time); return CreateTweenImp(itween); } public static UITweenImp SliderMove(NSlider slider, float target, float time) { TweenObject itween = TweenObject.CreateSliderMove(slider, slider.value, target, time); return CreateTweenImp(itween); } public static UITweenImp Scale(GameObject gameObject, Vector3 target, float time) { return Scale(gameObject, gameObject.transform.localScale, target, time); } public static UITweenImp Scale(GameObject gameObject, Vector3 start, Vector3 target, float time) { TweenObject itween = TweenObject.CreateScale(gameObject, start, target, time); return CreateTweenImp(itween); } public static UITweenImp MoveX(RectTransform transform, float targetX, float time) { var anchoredPosition = transform.anchoredPosition; var target = anchoredPosition; target.x = targetX; return Move(transform, anchoredPosition, target, time); } public static UITweenImp MoveY(RectTransform transform, float targetY, float time) { var anchoredPosition = transform.anchoredPosition; var target = anchoredPosition; target.y = targetY; return Move(transform, anchoredPosition, target, time); } public static UITweenImp Move(RectTransform transform, Vector2 target, float time) { return Move(transform, transform.anchoredPosition, target, time); } public static UITweenImp Move(RectTransform transform, Vector3 start, Vector3 target, float time) { TweenObject itween = TweenObject.CreateMove(transform, start, target, time); return CreateTweenImp(itween); } void Update() { // tweenCount = m_TweenImps.Count; // impCount = m_TweenImpPool.Count; // objCount = m_TweenObjectPool.Count; for (int i = m_TweenImps.Count - 1; i >= 0; i--) { if (m_TweenImps[i].IsDestroy) { m_TweenImps[i].Destroy(); m_TweenImps.RemoveAt(i); continue; } m_TweenImps[i].Excute(Time.unscaledDeltaTime); } } public static TweenObject CreateTweenObject() { var tweenObject = Instance.m_TweenObjectPool.Create(); tweenObject.Init(); return tweenObject; } public static void ReleaseTweenObject(TweenObject obj) { if (m_Instance) { m_Instance.m_TweenObjectPool.Release(obj); } } private static UITweenImp CreateTweenImp(UITweenBase tweenBase) { var imp = Instance.m_TweenImpPool.Create().Init(tweenBase); Instance.m_TweenImps.Add(imp); return imp; } public static void ReleaseTweenImp(UITweenImp imp) { if (m_Instance) { m_Instance.m_TweenImpPool.Release(imp); } } public static void Cancel(UITweenBase tween) { Cancel(tween.gameObject, tween.tweenType); } public static void Cancel(GameObject gameObject, TweenType tweenType = TweenType.None) { if (m_Instance == null || gameObject == null) return; for (int i = 0; i < m_Instance.m_TweenImps.Count; i++) { m_Instance.m_TweenImps[i].CancelUnique(gameObject, tweenType); } } } internal class UITweenImp { private UITweenBase m_Tween; private GameObject gameObject; public bool IsDestroy { get; private set; } private Action m_CompleteAction; public UITweenImp Init(UITweenBase tween) { m_Tween = tween; gameObject = tween.gameObject; IsDestroy = false; m_CompleteAction = null; return this; } public UITweenImp SetOnComplete(Action action) { m_CompleteAction = action; return this; } public void Excute(float dt) { if (m_Tween.IsDestroy) { IsDestroy = true; return; } if (m_Tween.Excute(dt)) { IsDestroy = true; } } public void Destroy() { if (!m_Tween.IsDestroy) { m_CompleteAction?.Invoke(); } m_Tween.OnDestroy(); UITween.ReleaseTweenImp(this); } public void CancelUnique(GameObject go, TweenType tweenType) { if (tweenType == TweenType.None) { if (gameObject == go) { IsDestroy = true; } } else { if (gameObject == go && m_Tween.tweenType == tweenType) { IsDestroy = true; } } } } internal class UITweenPool where T : new() { private readonly List m_Pool = new List(); private int m_MaxCount = 10; public T Create() { if (m_Pool.Count <= 0) { return new T(); } T obj = m_Pool[Count - 1]; m_Pool.RemoveAt(Count - 1); return obj; } public void SetMaxCount(int count) { m_MaxCount = count; } public void Release(T obj) { if (Count >= m_MaxCount) return; m_Pool.Add(obj); } public int Count { get { return m_Pool.Count; } } } internal abstract class UITweenBase { public TweenType tweenType; public RectTransform rectTransform; public GameObject gameObject; public float m_AccumTime; public float m_TotalTime; public virtual bool IsDestroy { get { return gameObject == null; } } public virtual void OnDestroy() { } public abstract bool Excute(float dt); public abstract void Init(); } enum TweenType { None, Move, Scale, ButtonPress, SliderMove, RadarScale, } internal sealed class TweenObject : UITweenBase { public override void Init() { m_Button = null; } private NRadarChart m_Radar; private float[] m_RadarData; private NButtonBase m_Button; private NSlider m_Slider; private float m_StartFloat; private float m_TargetFloat; private Color m_StartColor; private Color m_TargetColor; private Vector3 m_StartV3; private Vector3 m_TargetV3; public static TweenObject CreateRadarScale(NRadarChart radar, float[] data, float totalTime) { var tween = UITween.CreateTweenObject(); tween.gameObject = radar.gameObject; tween.m_Radar = radar; tween.m_RadarData = data; tween.m_AccumTime = 0; tween.m_TotalTime = totalTime; tween.tweenType = TweenType.RadarScale; UITween.Cancel(tween); return tween; } public static TweenObject CreateButtonPress(NButtonBase button, Color start, Color target, float totalTime) { var tween = UITween.CreateTweenObject(); tween.gameObject = button.gameObject; tween.m_Button = button; tween.m_StartColor = start; tween.m_TargetColor = target; tween.m_TotalTime = totalTime; tween.m_AccumTime = 0; tween.tweenType = TweenType.ButtonPress; UITween.Cancel(tween); return tween; } public static TweenObject CreateSliderMove(NSlider slider, float start, float target, float totalTime) { var tween = UITween.CreateTweenObject(); tween.gameObject = slider.gameObject; tween.m_Slider = slider; tween.m_StartFloat = start; tween.m_TargetFloat = target; tween.m_TotalTime = totalTime; tween.m_AccumTime = 0; tween.tweenType = TweenType.SliderMove; UITween.Cancel(tween); return tween; } public static TweenObject CreateScale(GameObject gameObject, Vector3 start, Vector3 target, float totalTime) { var tween = UITween.CreateTweenObject(); tween.gameObject = gameObject; tween.m_StartV3 = start; tween.m_TargetV3 = target; tween.m_TotalTime = totalTime; tween.m_AccumTime = 0; tween.tweenType = TweenType.Scale; UITween.Cancel(tween); return tween; } public static TweenObject CreateMove(RectTransform rectTransform, Vector3 start, Vector3 target, float totalTime) { var tween = UITween.CreateTweenObject(); tween.rectTransform = rectTransform; tween.gameObject = rectTransform.gameObject; tween.m_StartV3 = start; tween.m_TargetV3 = target; tween.m_TotalTime = totalTime; tween.m_AccumTime = 0; tween.tweenType = TweenType.Move; UITween.Cancel(tween); return tween; } public override bool Excute(float dt) { m_AccumTime += dt; switch (tweenType) { case TweenType.Move: rectTransform.anchoredPosition = Vector2.Lerp(m_StartV3, m_TargetV3, m_AccumTime / m_TotalTime); break; case TweenType.ButtonPress: m_Button.SetRenderColorGroup(Color.Lerp(m_StartColor, m_TargetColor, m_AccumTime / m_TotalTime)); break; case TweenType.Scale: gameObject.transform.localScale = Vector3.Lerp(m_StartV3, m_TargetV3, m_AccumTime / m_TotalTime); break; case TweenType.SliderMove: m_Slider.SetValue(Mathf.Lerp(m_StartFloat, m_TargetFloat, m_AccumTime / m_TotalTime)); break; case TweenType.RadarScale: var current = m_Radar.GetCurrentList(); current.Clear(); for (var i = 0; i < m_RadarData.Length; i++) { current.Add(NMathf.Lerp(0, m_RadarData[i], m_AccumTime / m_TotalTime)); } break; } return m_AccumTime >= m_TotalTime; } public override void OnDestroy() { m_Button = null; UITween.ReleaseTweenObject(this); } } }