Created
November 18, 2021 14:44
-
-
Save green224/d6334bf17e4a66015098f3ad503eed7c to your computer and use it in GitHub Desktop.
UnityのAnimationCurveを自前でシリアライズするためのクラス
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEngine; | |
using System.Linq; | |
[Serializable] | |
public struct AnimCurveKey | |
{ | |
#pragma warning disable 0414 | |
[SerializeField] byte serializedVersion; // これは3固定 | |
public float time, value; | |
public float inSlope, outSlope; | |
[SerializeField] int tangentMode; | |
public WeightedMode weightedMode; | |
public float inWeight, outWeight; | |
#pragma warning restore 0414 | |
public enum TangentMode | |
{ | |
Free = 0, | |
Auto = 1, | |
Linear = 2, | |
Constant = 3, | |
ClampedAuto = 4 | |
} | |
public TangentMode LeftTangentMode { | |
get => new TangentModeDetail(tangentMode).LeftTangentMode; | |
set { | |
var tmd = new TangentModeDetail(tangentMode); | |
tmd.LeftTangentMode = value; | |
tangentMode = tmd.value; | |
} | |
} | |
public TangentMode RightTangentMode { | |
get => new TangentModeDetail(tangentMode).RightTangentMode; | |
set { | |
var tmd = new TangentModeDetail(tangentMode); | |
tmd.RightTangentMode = value; | |
tangentMode = tmd.value; | |
} | |
} | |
public bool TangentIsBroken { | |
get => new TangentModeDetail(tangentMode).IsBroken; | |
set { | |
var tmd = new TangentModeDetail(tangentMode); | |
tmd.IsBroken = value; | |
tangentMode = tmd.value; | |
} | |
} | |
// UnityのKeyframeにコンバートする | |
public Keyframe Convert() | |
{ | |
return new Keyframe( | |
time, value, | |
inSlope, outSlope, | |
inWeight, outWeight | |
) { | |
#pragma warning disable 0618 | |
tangentMode = tangentMode, | |
#pragma warning restore 0618 | |
weightedMode = weightedMode, | |
}; | |
} | |
// シリアライズバージョンを決める必要があるので、必ずこれ経由で作成すること | |
public AnimCurveKey( | |
float time, float value, | |
float slope, TangentMode tangentMode | |
) { | |
serializedVersion = 3; | |
this.time = time; | |
this.value = value; | |
inSlope = outSlope = slope; | |
this.tangentMode = new TangentModeDetail{ | |
LeftTangentMode = tangentMode, | |
RightTangentMode = tangentMode, | |
IsBroken = false, | |
}.value; | |
weightedMode = WeightedMode.None; | |
inWeight = outWeight = 0; | |
} | |
public AnimCurveKey( | |
float time, float value, | |
float inSlope, float outSlope, | |
TangentMode leftTangentMode, TangentMode rightTangentMode | |
) { | |
serializedVersion = 3; | |
this.time = time; | |
this.value = value; | |
this.inSlope = inSlope; | |
this.outSlope = outSlope; | |
tangentMode = new TangentModeDetail{ | |
LeftTangentMode = leftTangentMode, | |
RightTangentMode = rightTangentMode, | |
IsBroken = true, | |
}.value; | |
weightedMode = WeightedMode.None; | |
inWeight = outWeight = 0; | |
} | |
/** TangentModeのint型から、中身の細かいデータを得るためのもの */ | |
struct TangentModeDetail | |
{ | |
public int value; | |
public TangentMode LeftTangentMode { | |
get => (TangentMode)( (value>>1) & 0b111 ); | |
set => this.value = | |
(this.value & 0b1111_0001) | | |
((int)value << 1); | |
} | |
public TangentMode RightTangentMode { | |
get => (TangentMode)( (value>>5) & 0b111 ); | |
set => this.value = | |
(this.value & 0b0001_1111) | | |
((int)value << 5); | |
} | |
public bool IsBroken { | |
get => (value & 1) != 0; | |
set => this.value = | |
(this.value & 0b1111_1110) | | |
(value ? 1 : 0); | |
} | |
public TangentModeDetail(int value) => this.value = value; | |
} | |
} | |
[Serializable] | |
public struct AnimationCurveWrapper | |
{ | |
#pragma warning disable 0414 | |
[SerializeField] byte serializedVersion; // これは2固定 | |
[SerializeField] AnimCurveKey[] m_Curve; | |
// TODO : これらの使い道を調査する | |
[SerializeField] byte m_PreInfinity; | |
[SerializeField] byte m_PostInfinity; | |
[SerializeField] byte m_RotationOrder; | |
#pragma warning restore 0414 | |
static public AnimationCurveWrapper InitValue => | |
new AnimationCurveWrapper( | |
new[] { | |
new AnimCurveKey(0, 0, 1, AnimCurveKey.TangentMode.Auto), | |
new AnimCurveKey(1, 1, 1, AnimCurveKey.TangentMode.Auto), | |
} | |
); | |
public AnimCurveKey[] Keys { | |
get => m_Curve; | |
set { | |
m_Curve = value; | |
_nativeAC = null; | |
} | |
} | |
public float Evaluate(float time) => _nativeAC.Evaluate(time); | |
// デフォルト値。シリアライズバージョンを決める必要があるので、必ずこれ経由で作成すること | |
public AnimationCurveWrapper( AnimCurveKey[] keys ) { | |
serializedVersion = 2; | |
m_Curve = keys; | |
m_PreInfinity = 2; | |
m_PostInfinity = 2; | |
m_RotationOrder = 4; | |
_nativeAC = null; | |
} | |
AnimationCurve _nativeAC; | |
AnimationCurve NativeAC { get { | |
if (_nativeAC == null) | |
_nativeAC = new AnimationCurve( | |
m_Curve.Select(i => i.Convert()).ToArray() | |
) { | |
}; | |
return _nativeAC; | |
} } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment