public static CurveAnimStruct FromCurve(AnimCurve curve, string target, bool useDegrees) { var convCurve = new CurveAnimStruct(); convCurve.KeyFrames = new Dictionary<float, object>(); convCurve.Target = target; convCurve.Scale = curve.Scale; convCurve.Offset = curve.Offset; convCurve.WrapMode = $"{curve.PreWrap}, {curve.PostWrap}"; convCurve.Interpolation = curve.CurveType; convCurve.FrameType = curve.FrameType; convCurve.KeyType = curve.KeyType; float valueScale = curve.Scale > 0 ? curve.Scale : 1; for (int i = 0; i < curve.Frames.Length; i++) { var frame = curve.Frames[i]; switch (curve.CurveType) { case AnimCurveType.Cubic: { var coef0 = curve.Keys[i, 0] * valueScale + curve.Offset; var slopes = CurveConvert.GetSlopes(curve, i); if (useDegrees) { coef0 *= CurveConvert.Rad2Deg; slopes[0] *= CurveConvert.Rad2Deg; slopes[1] *= CurveConvert.Rad2Deg; } convCurve.KeyFrames.Add(frame, new HermiteKey() { Value = coef0, In = slopes[0], Out = slopes[1], }); } break; case AnimCurveType.StepBool: convCurve.KeyFrames.Add(frame, new BooleanKey() { Value = curve.KeyStepBoolData[i], }); break; case AnimCurveType.StepInt: convCurve.KeyFrames.Add(frame, new KeyFrame() { Value = (int)curve.Keys[i, 0] + (int)curve.Offset }); break; default: var value = curve.Keys[i, 0] * valueScale + curve.Offset; convCurve.KeyFrames.Add(frame, new KeyFrame() { Value = value }); break; } } return convCurve; }
public static AnimCurve GenerateCurve(CurveAnimStruct curveJson, uint target, bool isDegrees) { AnimCurve curve = new AnimCurve(); curve.Offset = curveJson.Offset; curve.Scale = curveJson.Scale; curve.CurveType = curveJson.Interpolation; curve.FrameType = curveJson.FrameType; curve.KeyType = curveJson.KeyType; curve.AnimDataOffset = target; var first = curveJson.KeyFrames.First(); var last = curveJson.KeyFrames.Last(); curve.EndFrame = last.Key; curve.StartFrame = first.Key; var keys = curveJson.KeyFrames.Values.ToList(); var frames = curveJson.KeyFrames.Keys.ToList(); curve.Frames = frames.ToArray(); curve.Keys = new float[keys.Count, 4]; for (int i = 0; i < keys.Count; i++) { switch (curve.CurveType) { case AnimCurveType.Cubic: var hermiteKey = ((JObject)keys[i]).ToObject<HermiteKey>(); float time = 0; float value = hermiteKey.Value; float outSlope = hermiteKey.Out; float nextValue = 0; float nextInSlope = 0; if (i < keys.Count - 1) { var nextKey = ((JObject)keys[i + 1]).ToObject<HermiteKey>(); var nextFrame = frames[i + 1]; nextValue = nextKey.Value; nextInSlope = nextKey.In; time = nextFrame - frames[i]; } if (isDegrees) { value *= Deg2Rad; nextValue *= Deg2Rad; nextInSlope *= Deg2Rad; outSlope *= Deg2Rad; } float[] coefs = HermiteToCubicKey( value, nextValue, outSlope * time, nextInSlope * time); curve.Keys[i, 0] = coefs[0]; if (time != 0) { curve.Keys[i, 1] = coefs[1]; curve.Keys[i, 2] = coefs[2]; curve.Keys[i, 3] = coefs[3]; } break; case AnimCurveType.StepBool: var booleanKey = ((JObject)keys[i]).ToObject<BooleanKey>(); curve.KeyStepBoolData[i] = booleanKey.Value; break; case AnimCurveType.Linear: var linearKey = ((JObject)keys[i]).ToObject<KeyFrame>(); curve.Keys[i, 0] = linearKey.Value; if (i < keys.Count - 1) { //Get next value. Calculate delta var nextLinearKey = ((JObject)keys[i+1]).ToObject<KeyFrame>(); var delta = nextLinearKey.Value - linearKey.Value; curve.Keys[i, 1] = delta; } break; case AnimCurveType.StepInt: var stepKey = ((JObject)keys[i]).ToObject<KeyFrame>(); curve.Keys[i, 0] = stepKey.Value; break; } } if (curve.Keys.Length >= 2) { var lastKey = curve.Keys[keys.Count - 1, 0]; var firstKey = curve.Keys[0, 0]; curve.Delta = lastKey - firstKey; } for (int i = 0; i < keys.Count; i++) { curve.Keys[i, 0] -= curve.Offset; //Apply scale for cubic and linear curves only if (curve.CurveType == AnimCurveType.Cubic) { if (curve.Scale != 0) { curve.Keys[i, 0] /= curve.Scale; curve.Keys[i, 1] /= curve.Scale; curve.Keys[i, 2] /= curve.Scale; curve.Keys[i, 3] /= curve.Scale; } } else if (curve.CurveType == AnimCurveType.Linear) { if (curve.Scale != 0) { curve.Keys[i, 0] /= curve.Scale; curve.Keys[i, 1] /= curve.Scale; } } } return curve; }