using System; using UnityEngine; namespace XCharts.Runtime { /// /// the animation info. /// ||动画配置参数。 /// [Since("v3.8.0")] [System.Serializable] public class AnimationInfo { [SerializeField][Since("v3.8.0")] private bool m_Enable = true; [SerializeField][Since("v3.8.0")] private bool m_Reverse = false; [SerializeField][Since("v3.8.0")] private float m_Delay = 0; [SerializeField][Since("v3.8.0")] private float m_Duration = 1000; public AnimationInfoContext context = new AnimationInfoContext(); /// /// whether enable animation. /// ||是否开启动画效果。 /// public bool enable { get { return m_Enable; } set { m_Enable = value; } } /// /// whether enable reverse animation. /// ||是否开启反向动画效果。 /// public bool reverse { get { return m_Reverse; } set { m_Reverse = value; } } /// /// the delay time before animation start. /// ||动画开始前的延迟时间。 /// public float delay { get { return m_Delay; } set { m_Delay = value; } } /// /// the duration of animation. /// ||动画的时长。 /// public float duration { get { return m_Duration; } set { m_Duration = value; } } /// /// the callback function of animation start. /// ||动画开始的回调。 /// public Action OnAnimationStart { get; set; } /// /// the callback function of animation end. /// ||动画结束的回调。 /// public Action OnAnimationEnd { get; set; } /// /// the delegate function of animation delay. /// ||动画延迟的委托函数。 /// public AnimationDelayFunction delayFunction { get; set; } /// /// the delegate function of animation duration. /// ||动画时长的委托函数。 /// public AnimationDurationFunction durationFunction { get; set; } /// /// Reset animation. /// ||重置动画。 /// public void Reset() { if (!enable) return; context.init = false; context.start = false; context.pause = false; context.end = false; context.startTime = 0; context.currProgress = 0; context.destProgress = 0; context.totalProgress = 0; context.sizeProgress = 0; context.currPointIndex = 0; context.currPoint = Vector3.zero; context.destPoint = Vector3.zero; context.dataCurrProgress.Clear(); context.dataDestProgress.Clear(); } /// /// Start animation. /// ||开始动画。 /// /// 是否重置上一次的参数 public void Start(bool reset = true) { if (!enable) return; if (context.start) { context.pause = false; return; } context.init = false; context.start = true; context.end = false; context.pause = false; context.startTime = Time.time; if (reset) { context.currProgress = 0; context.destProgress = 1; context.totalProgress = 0; context.sizeProgress = 0; context.dataCurrProgress.Clear(); context.dataDestProgress.Clear(); } if (OnAnimationStart != null) { OnAnimationStart(); } } /// /// Pause animation. /// ||暂停动画。 /// public void Pause() { if (!enable) return; if (!context.start || context.end) return; context.pause = true; } /// /// Resume animation. /// ||恢复动画。 /// public void Resume() { if (!enable) return; if (!context.pause) return; context.pause = false; } /// /// End animation. /// ||结束动画。 /// public void End() { if (!enable) return; if (!context.start || context.end) return; context.start = false; context.end = true; context.currPointIndex = context.destPointIndex; context.startTime = Time.time; if (OnAnimationEnd != null) { OnAnimationEnd(); } } /// /// Initialize animation. /// ||初始化动画。 /// /// 当前进度 /// 目标进度 /// 目标索引 /// public bool Init(float curr, float dest, int totalPointIndex) { if (!enable || !context.start) return false; if (context.init || context.end) return false; context.init = true; context.totalProgress = dest - curr; context.destPointIndex = totalPointIndex; if (reverse) { context.currProgress = dest; context.destProgress = curr; } else { context.currProgress = curr; context.destProgress = dest; } return true; } /// /// Whether animation is finish. /// ||动画是否结束。 /// public bool IsFinish() { if (!context.start) return true; if (context.end) return true; if (context.pause) return false; if (!context.init) return false; return m_Reverse ? context.currProgress <= context.destProgress : context.currProgress >= context.destProgress; } /// /// Whether animation is in delay. /// ||动画是否在延迟中。 /// public bool IsInDelay() { if (!context.start) return false; else return (m_Delay > 0 && Time.time - context.startTime < m_Delay / 1000); } /// /// Whether animation is in index delay. /// ||动画是否在索引延迟中。 /// /// /// public bool IsInIndexDelay(int dataIndex) { if (context.start) return Time.time - context.startTime < GetIndexDelay(dataIndex) / 1000f; else return false; } /// /// Get animation delay. /// ||获取动画延迟。 /// /// /// public float GetIndexDelay(int dataIndex) { if (!context.start) return 0; if (delayFunction != null) return delayFunction(dataIndex); return delay; } internal float GetCurrAnimationDuration(int dataIndex = -1) { if (dataIndex >= 0) { if (context.start && durationFunction != null) return durationFunction(dataIndex) / 1000f; } return m_Duration > 0 ? m_Duration / 1000 : 1f; } internal void SetDataCurrProgress(int index, float state) { context.dataCurrProgress[index] = state; } internal float GetDataCurrProgress(int index, float initValue, float destValue, ref bool isBarEnd) { if (IsInDelay()) { isBarEnd = false; return initValue; } var c1 = !context.dataCurrProgress.ContainsKey(index); var c2 = !context.dataDestProgress.ContainsKey(index); if (c1 || c2) { if (c1) context.dataCurrProgress.Add(index, initValue); if (c2) context.dataDestProgress.Add(index, destValue); isBarEnd = false; } else { isBarEnd = context.dataCurrProgress[index] == context.dataDestProgress[index]; } return context.dataCurrProgress[index]; } internal void CheckProgress(double total, bool m_UnscaledTime) { if (!context.start || !context.init || context.pause) return; if (IsInDelay()) return; var duration = GetCurrAnimationDuration(); var delta = (float)(total / duration * (m_UnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime)); if (reverse) { context.currProgress -= delta; if (context.currProgress <= context.destProgress) { context.currProgress = context.destProgress; End(); } } else { context.currProgress += delta; if (context.currProgress >= context.destProgress) { context.currProgress = context.destProgress; End(); } } } internal float CheckItemProgress(int dataIndex, float destProgress, ref bool isEnd, float startProgress, bool m_UnscaledTime) { if (m_Reverse) { var temp = startProgress; startProgress = destProgress; destProgress = temp; } var currHig = GetDataCurrProgress(dataIndex, startProgress, destProgress, ref isEnd); if (IsFinish()) { return destProgress; } else if (IsInDelay() || IsInIndexDelay(dataIndex)) { return startProgress; } else if (context.pause) { return currHig; } else { var duration = GetCurrAnimationDuration(dataIndex); var delta = (destProgress - startProgress) / duration * (m_UnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime); currHig += delta; if (reverse) { if ((destProgress > 0 && currHig <= 0) || (destProgress < 0 && currHig >= 0)) { currHig = 0; isEnd = true; } } else { if ((destProgress - startProgress > 0 && currHig > destProgress) || (destProgress - startProgress < 0 && currHig < destProgress)) { currHig = destProgress; isEnd = true; } } SetDataCurrProgress(dataIndex, currHig); return currHig; } } internal void CheckSymbol(float dest, bool m_UnscaledTime) { if (!context.start || !context.init || context.pause) return; if (IsInDelay()) return; var duration = GetCurrAnimationDuration(); var delta = dest / duration * (m_UnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime); if (reverse) { context.sizeProgress -= delta; if (context.sizeProgress < 0) context.sizeProgress = 0; } else { context.sizeProgress += delta; if (context.sizeProgress > dest) context.sizeProgress = dest; } } } /// /// Fade in animation. /// ||淡入动画。 /// [Since("v3.8.0")] [System.Serializable] public class AnimationFadeIn : AnimationInfo { } /// /// Fade out animation. /// ||淡出动画。 /// [Since("v3.8.0")] [System.Serializable] public class AnimationFadeOut : AnimationInfo { } /// /// Data change animation. /// ||数据变更动画。 /// [Since("v3.8.0")] [System.Serializable] public class AnimationChange : AnimationInfo { } /// /// Data addition animation. /// ||数据新增动画。 /// [Since("v3.8.0")] [System.Serializable] public class AnimationAddition : AnimationInfo { } /// /// Data hiding animation. /// ||数据隐藏动画。 /// [Since("v3.8.0")] [System.Serializable] public class AnimationHiding : AnimationInfo { } /// /// Interactive animation of charts. /// ||交互动画。 /// [Since("v3.8.0")] [System.Serializable] public class AnimationInteraction : AnimationInfo { [SerializeField][Since("v3.8.0")] private MLValue m_Width = new MLValue(1.1f); [SerializeField][Since("v3.8.0")] private MLValue m_Radius = new MLValue(1.1f); [SerializeField][Since("v3.8.0")] private MLValue m_Offset = new MLValue(MLValue.Type.Absolute, 5f); /// /// the mlvalue of width. /// ||宽度的多样式数值。 /// public MLValue width { get { return m_Width; } set { m_Width = value; } } /// /// the mlvalue of radius. /// ||半径的多样式数值。 /// public MLValue radius { get { return m_Radius; } set { m_Radius = value; } } /// /// the mlvalue of offset. Such as the offset of the pie chart when the sector is selected. /// ||交互的多样式数值。如饼图的扇形选中时的偏移。 /// public MLValue offset { get { return m_Offset; } set { m_Offset = value; } } public float GetRadius(float radius) { return m_Radius.GetValue(radius); } public float GetWidth(float width) { return m_Width.GetValue(width); } public float GetOffset(float total) { return m_Offset.GetValue(total); } public float GetOffset() { return m_Offset.value; } } }