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;
}
}
}