using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace RosettaUI.UIToolkit.AnimationCurveEditor
{
internal static class AnimationCurveEditorUtility
{
public static bool GetKeyBroken(this AnimationCurve curve, int index)
{
#if UNITY_EDITOR
return AnimationUtility.GetKeyBroken(curve, index);
#else
return PredictGetBroken(curve, index);
#endif
}
public static TangentMode GetInTangentMode(this AnimationCurve curve, int index)
{
#if UNITY_EDITOR
return ToTangentMode(AnimationUtility.GetKeyLeftTangentMode(curve, index));
#else
return PredictLeftTangentMode(curve, index);
#endif
}
public static TangentMode GetOutTangentMode(this AnimationCurve curve, int index)
{
#if UNITY_EDITOR
return ToTangentMode(AnimationUtility.GetKeyRightTangentMode(curve, index));
#else
return PredictRightTangentMode(curve, index);
#endif
}
#if UNITY_EDITOR
///
/// KeyBrokenを設定する
/// Editor中のみ有効。インスペクターと同期をとるために使用する。
///
public static void SetKeyBroken(this AnimationCurve curve, int index, bool broken)
{
AnimationUtility.SetKeyBroken(curve, index, broken);
}
///
/// TangentModeを設定する
/// Editor中のみ有効。インスペクターと同期をとるために使用する。
///
public static void SetTangentMode(this AnimationCurve curve, int index, TangentMode leftMode, TangentMode rightMode)
{
AnimationUtility.SetKeyLeftTangentMode(curve, index, ToAnimationUtilityTangentMode(leftMode));
AnimationUtility.SetKeyRightTangentMode(curve, index, ToAnimationUtilityTangentMode(rightMode));
}
#endif
#if UNITY_EDITOR
private static TangentMode ToTangentMode(AnimationUtility.TangentMode mode)
{
return mode switch
{
AnimationUtility.TangentMode.Free => TangentMode.Free,
AnimationUtility.TangentMode.Linear => TangentMode.Linear,
AnimationUtility.TangentMode.Constant => TangentMode.Constant,
AnimationUtility.TangentMode.Auto => TangentMode.Free,
AnimationUtility.TangentMode.ClampedAuto => TangentMode.Free,
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null)
};
}
private static AnimationUtility.TangentMode ToAnimationUtilityTangentMode(TangentMode mode)
{
return mode switch
{
TangentMode.Free => AnimationUtility.TangentMode.Free,
TangentMode.Linear => AnimationUtility.TangentMode.Linear,
TangentMode.Constant => AnimationUtility.TangentMode.Constant,
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null)
};
}
#endif
public static bool PredictGetBroken(this AnimationCurve curve, int index)
{
var keyframe = curve[index];
return !Mathf.Approximately(keyframe.inTangent, keyframe.outTangent);
}
public static TangentMode PredictLeftTangentMode(this AnimationCurve curve, int index)
{
var key = curve[index];
if (float.IsPositiveInfinity(curve[index].inTangent)) return TangentMode.Constant;
if (index > 0)
{
var prevKey = curve[index - 1];
float tangentToPrevKey = (key.value - prevKey.value) / (key.time - prevKey.time);
if (Mathf.Approximately(tangentToPrevKey, key.inTangent)) return TangentMode.Linear;
}
return TangentMode.Free;
}
public static TangentMode PredictRightTangentMode(this AnimationCurve curve, int index)
{
var key = curve[index];
if (float.IsPositiveInfinity(curve[index].outTangent)) return TangentMode.Constant;
if (index < curve.length - 1)
{
var nextKey = curve[index + 1];
float tangentToNextKey = (nextKey.value - key.value) / (nextKey.time - key.time);
if (Mathf.Approximately(tangentToNextKey, key.outTangent)) return TangentMode.Linear;
}
return TangentMode.Free;
}
}
}