public AnimationHelperTrack EncodeTrack(Animation.KeyGroup Group, AnimTrackType Type) { AnimationHelperTrack t = new AnimationHelperTrack(); t.TrackType = Type; foreach (Animation.KeyFrame kf in Group.Keys) { AnimationHelperKeyFrame f = new AnimationHelperKeyFrame(); f.Frame = (int)kf.Frame; f.Value = kf.Value; f.Tan = kf.In; t.KeyFrames.Add(f); switch (kf.InterType) { case Animation.InterpolationType.CONSTANT: f.InterpolationType = InterpolationType.Constant; break; case Animation.InterpolationType.HERMITE: f.InterpolationType = InterpolationType.Hermite; break; case Animation.InterpolationType.LINEAR: if (Group.Keys.Count == 1) { f.InterpolationType = InterpolationType.Constant; } else { f.InterpolationType = InterpolationType.Linear; } break; case Animation.InterpolationType.STEP: f.InterpolationType = InterpolationType.Step; break; } } return(t); }
public void LoadAnim(ShaderParamAnim anim, AnimationType type) { Initialize(); Text = anim.Name; AnimType = type; FrameCount = anim.FrameCount; ShaderParamAnim = anim; foreach (ShaderParamMatAnim matAnim in anim.ShaderParamMatAnims) { MaterialAnimEntry matNode = new MaterialAnimEntry(matAnim.Name); matNode.materialAnimData = matAnim; Materials.Add(matNode); //Param info determines which curves to use for each param //Add the curves and keys for left/right for interpolating after foreach (var param in matAnim.ParamAnimInfos) { BfresParamAnim paramInfo = new BfresParamAnim(param.Name); paramInfo.Type = type; matNode.Params.Add(paramInfo); //Get constant anims for (int constant = 0; constant < param.ConstantCount; constant++) { Animation.KeyGroup keyGroup = new Animation.KeyGroup(); keyGroup.Keys.Add(new Animation.KeyFrame() { InterType = InterpolationType.CONSTANT, Frame = 0, Value = matAnim.Constants[constant].Value, }); paramInfo.Values.Add(new Animation.KeyGroup() { AnimDataOffset = matAnim.Constants[constant].AnimDataOffset, Keys = keyGroup.Keys, }); } for (int curve = 0; curve < param.FloatCurveCount + param.IntCurveCount; curve++) { int index = curve + param.BeginCurve; Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(matAnim.Curves[index]); keyGroup.AnimDataOffset = matAnim.Curves[index].AnimDataOffset; paramInfo.Values.Add(new Animation.KeyGroup() { AnimDataOffset = keyGroup.AnimDataOffset, Keys = keyGroup.Keys, }); } } } }
public void LoadKeyData(Animation.KeyGroup keyGroup) { acitveGroup = keyGroup; stListView1.View = View.Details; stListView1.HeaderStyle = ColumnHeaderStyle.None; foreach (var key in keyGroup.Keys) { stListView1.Items.Add($"Frame: [{key.Frame}] Value: {key.Value}"); } }
private static AnimCurve SetAnimationCurve(Animation.KeyGroup keyGroup) { AnimCurve curve = new AnimCurve(); curve.Frames = new float[(int)keyGroup.Keys.Count]; curve.FrameType = AnimCurveFrameType.Single; curve.KeyType = AnimCurveKeyType.Single; curve.EndFrame = keyGroup.FrameCount; curve.AnimDataOffset = 0; curve.Delta = 0; curve.Scale = 1; curve.StartFrame = 0; curve.Offset = 0; var frame = keyGroup.GetKeyFrame(0); int valuesLength = 1; if (frame.InterType == Animation.InterpolationType.HERMITE) { curve.CurveType = AnimCurveType.Cubic; curve.Keys = new float[keyGroup.Keys.Count, 4]; for (int k = 0; k < keyGroup.Keys.Count; k++) { float value = keyGroup.GetValue(keyGroup.Keys[k].Frame); curve.Keys[k, 0] = value; curve.Keys[k, 1] = 0; curve.Keys[k, 2] = 0; curve.Keys[k, 3] = 0; curve.Frames[k] = keyGroup.Keys[k].Frame; } } if (frame.InterType == Animation.InterpolationType.LINEAR) { curve.CurveType = AnimCurveType.Linear; curve.Keys = new float[keyGroup.Keys.Count, 2]; } if (frame.InterType == Animation.InterpolationType.STEP) { curve.CurveType = AnimCurveType.StepInt; curve.Keys = new float[keyGroup.Keys.Count, 1]; } if (frame.InterType == Animation.InterpolationType.STEPBOOL) { curve.CurveType = AnimCurveType.StepBool; curve.Keys = new float[keyGroup.Keys.Count, 1]; } return(curve); }
public void LoadAnim(ResU.CameraAnim anim) { Initialize(); CameraAnimU = anim; Text = anim.Name; FrameCount = anim.FrameCount; AspectRatio = anim.BaseData.AspectRatio; ClipFar = anim.BaseData.ClipFar; ClipNear = anim.BaseData.ClipNear; FieldOfView = anim.BaseData.FieldOfView; Position = Utils.ToVec3(anim.BaseData.Position); Rotation = Utils.ToVec3(anim.BaseData.Rotation); Twist = anim.BaseData.Twist; if (anim.Flags.HasFlag(CameraAnimFlags.EulerZXY)) { settings |= Settings.EulerZXY; } if (anim.Flags.HasFlag(CameraAnimFlags.Perspective)) { settings |= Settings.Perspective; } for (int curve = 0; curve < anim.Curves.Count; curve++) { Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(anim.Curves[curve]); keyGroup.AnimDataOffset = anim.Curves[curve].AnimDataOffset; Values.Add(new Animation.KeyGroup() { AnimDataOffset = keyGroup.AnimDataOffset, Keys = keyGroup.Keys, }); } }
private void LoadAnim(MaterialAnim anim) { Initialize(); MaterialAnim = anim; FrameCount = MaterialAnim.FrameCount; Text = anim.Name; Textures.Clear(); if (anim.TextureNames != null) { foreach (var name in anim.TextureNames) { Textures.Add(name); } } Materials.Clear(); foreach (var matanim in anim.MaterialAnimDataList) { var mat = new MaterialAnimEntry(matanim.Name); mat.MaterialAnimData = matanim; Materials.Add(mat); foreach (var param in matanim.ParamAnimInfos) { FSHU.BfresParamAnim paramInfo = new FSHU.BfresParamAnim(param.Name); mat.Params.Add(paramInfo); paramInfo.Type = AnimationType.ShaderParam; //There is no better way to determine if the param is a color type afaik if (param.Name.Contains("Color") || param.Name.Contains("color") || param.Name == "multi_tex_reg2") { paramInfo.Type = AnimationType.Color; } else if (AnimType == AnimationType.TexturePattern) { paramInfo.Type = AnimationType.TexturePattern; } else if (AnimType == AnimationType.TextureSrt) { paramInfo.Type = AnimationType.TextureSrt; } else { paramInfo.Type = AnimationType.ShaderParam; } //Get constant anims for (int constant = 0; constant < param.ConstantCount; constant++) { int index = constant + param.BeginConstant; Animation.KeyGroup keyGroup = new Animation.KeyGroup(); keyGroup.Keys.Add(new Animation.KeyFrame() { InterType = InterpolationType.CONSTANT, Frame = 0, Value = matanim.Constants[index].Value, }); paramInfo.Values.Add(new Animation.KeyGroup() { AnimDataOffset = matanim.Constants[index].AnimDataOffset, Keys = keyGroup.Keys, }); } for (int curve = 0; curve < param.FloatCurveCount + param.IntCurveCount; curve++) { int index = curve + param.BeginCurve; Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(matanim.Curves[index]); keyGroup.AnimDataOffset = matanim.Curves[index].AnimDataOffset; paramInfo.Values.Add(new Animation.KeyGroup() { AnimDataOffset = keyGroup.AnimDataOffset, Keys = keyGroup.Keys, }); } } foreach (TexturePatternAnimInfo SamplerInfo in matanim.TexturePatternAnimInfos) { BfresSamplerAnim sampler = new BfresSamplerAnim(SamplerInfo.Name, this, mat); mat.Samplers.Add(sampler); int textureIndex = 0; if (SamplerInfo.BeginConstant != 65535) { textureIndex = matanim.Constants[SamplerInfo.BeginConstant].Value; sampler.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = textureIndex }); sampler.Constant = true; sampler.AnimDataOffset = matanim.Constants[SamplerInfo.BeginConstant].AnimDataOffset; } if (SamplerInfo.CurveIndex != 65535) { int index = (int)SamplerInfo.CurveIndex; Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(matanim.Curves[index]); sampler.AnimDataOffset = matanim.Curves[index].AnimDataOffset; sampler.Keys = keyGroup.Keys; } } } }
public static Animation.KeyGroup CreateTrackWiiU(ResU.AnimCurve animCurve) { Animation.KeyGroup track = new Animation.KeyGroup(); track.AnimDataOffset = animCurve.AnimDataOffset; track.Scale = animCurve.Scale; track.Offset = animCurve.Offset; track.StartFrame = animCurve.StartFrame; track.EndFrame = animCurve.EndFrame; track.Delta = animCurve.Delta; float tanscale = animCurve.Delta; if (tanscale == 0) { tanscale = 1; } if (animCurve.Scale == 0) { animCurve.Scale = 1; } for (int i = 0; i < (ushort)animCurve.Frames.Length; i++) { switch (animCurve.CurveType) { case ResU.AnimCurveType.Cubic: //4 elements are stored for cubic track.InterpolationType = InterpolationType.HERMITE; track.Keys.Add(new Animation.KeyFrame() { IsKeyed = true, InterType = InterpolationType.HERMITE, Frame = (int)animCurve.Frames[i], Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale), Slope1 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale), Slope2 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale), Delta = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale), }); break; case ResU.AnimCurveType.Linear: //2 elements are stored for linear track.InterpolationType = InterpolationType.LINEAR; track.Keys.Add(new Animation.KeyFrame() { IsKeyed = true, InterType = InterpolationType.LINEAR, Frame = (int)animCurve.Frames[i], Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale), Delta = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale), }); break; case ResU.AnimCurveType.StepInt: //1 element are stored for step track.InterpolationType = InterpolationType.STEP; track.Keys.Add(new Animation.KeyFrame() { IsKeyed = true, InterType = InterpolationType.STEP, Frame = (int)animCurve.Frames[i], Value = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale, Value1 = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale, }); Console.WriteLine($"Frame {animCurve.Frames[i]} Offset " + (int)animCurve.Offset + " " + ((int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale)); break; default: throw new Exception("Unsupported anim type!"); } } return(track); }
private void LoadAnimData(ResU.SkeletalAnim ska) { Nodes.Clear(); Bones.Clear(); CanLoop = ska.FlagsAnimSettings.HasFlag(ResU.SkeletalAnimFlags.Looping); foreach (ResU.BoneAnim bn in ska.BoneAnims) { BoneAnimNode bone = new BoneAnimNode(bn.Name, false); bone.BoneAnimU = bn; bone.UseSegmentScaleCompensate = bn.ApplySegmentScaleCompensate; Bones.Add(bone); // Nodes.Add(bone); if (ska.FlagsRotate == ResU.SkeletalAnimFlagsRotate.EulerXYZ) { bone.RotType = Animation.RotationType.EULER; } else { bone.RotType = Animation.RotationType.QUATERNION; } if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Scale)) { bone.XSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.X, IsKeyed = true }); bone.YSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.Y, IsKeyed = true }); bone.ZSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.Z, IsKeyed = true }); } if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Rotate)) { bone.XROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.X, IsKeyed = true }); bone.YROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.Y, IsKeyed = true }); bone.ZROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.Z, IsKeyed = true }); bone.WROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.W, IsKeyed = true }); } if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Translate)) { bone.XPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.X, IsKeyed = true }); bone.YPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.Y, IsKeyed = true }); bone.ZPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.Z, IsKeyed = true }); } for (int curve = 0; curve < bn.Curves.Count; curve++) { Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(bn.Curves[curve]); keyGroup.AnimDataOffset = bn.Curves[curve].AnimDataOffset; switch (keyGroup.AnimDataOffset) { case (int)TrackType.XPOS: bone.XPOS.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.YPOS: bone.YPOS.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.ZPOS: bone.ZPOS.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.XROT: bone.XROT.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.YROT: bone.YROT.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.ZROT: bone.ZROT.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.WROT: bone.WROT.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.XSCA: bone.XSCA.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.YSCA: bone.YSCA.Keys.AddRange(keyGroup.Keys); break; case (int)TrackType.ZSCA: bone.ZSCA.Keys.AddRange(keyGroup.Keys); break; default: throw new Exception("Unknown Anim Offset " + keyGroup.AnimDataOffset); } } } }
private static AnimCurve SetAnimationCurve(Animation.KeyGroup keyGroup, uint DataOffset) { if (keyGroup.Keys.Count <= 1) { return(null); } AnimCurve curve = new AnimCurve(); curve.Frames = new float[(int)keyGroup.Keys.Count]; curve.FrameType = AnimCurveFrameType.Single; curve.KeyType = AnimCurveKeyType.Single; curve.AnimDataOffset = DataOffset; curve.Scale = 1; curve.StartFrame = 0; curve.Offset = 0; var keyFrame = keyGroup.GetKeyFrame(0); if (keyFrame.InterType == InterpolationType.HERMITE) { curve.CurveType = AnimCurveType.Cubic; curve.Keys = new float[keyGroup.Keys.Count, 4]; curve.Frames = new float[keyGroup.Keys.Count]; for (int k = 0; k < keyGroup.Keys.Count; k++) { float Delta = 0; float frame = keyGroup.Keys[k].Frame; if (k < keyGroup.Keys.Count - 1) { Delta = keyGroup.GetValue(k + 1) - keyGroup.GetValue(k); } float value = keyGroup.GetValue(frame); curve.Keys[k, 0] = value; curve.Keys[k, 1] = 0; curve.Keys[k, 2] = 0; curve.Keys[k, 3] = Delta; curve.Frames[k] = keyGroup.Keys[k].Frame; } } else if (keyFrame.InterType == InterpolationType.LINEAR) { curve.CurveType = AnimCurveType.Linear; curve.Keys = new float[keyGroup.Keys.Count, 2]; curve.Frames = new float[keyGroup.Keys.Count]; for (int k = 0; k < keyGroup.Keys.Count; k++) { float frame = keyGroup.Keys[k].Frame; float Delta = 0; if (k < keyGroup.Keys.Count - 1) { Delta = keyGroup.GetValue(k + 1) - keyGroup.GetValue(k); } curve.Keys[k, 0] = keyGroup.GetValue(frame); curve.Keys[k, 1] = Delta; curve.Frames[k] = frame; } } else if (keyFrame.InterType == InterpolationType.STEPBOOL) { curve.CurveType = AnimCurveType.StepBool; curve.Keys = new float[keyGroup.Keys.Count, 1]; } else { curve.CurveType = AnimCurveType.StepInt; curve.Keys = new float[keyGroup.Keys.Count, 1]; curve.Frames = new float[keyGroup.Keys.Count]; for (int k = 0; k < keyGroup.Keys.Count; k++) { float frame = keyGroup.Keys[k].Frame; curve.Keys[k, 0] = keyGroup.GetValue(frame); curve.Frames[k] = frame; } } //Difference of last and first key value if (curve.Keys.Length > 0) { curve.Delta = curve.Keys[keyGroup.Keys.Count - 1, 0] - curve.Keys[0, 0]; } curve.EndFrame = curve.Frames.Max(); QuantizeCurveData(curve); return(curve); }
public virtual Animation GetAnimation() { Animation a = new Smash_Forge.Animation(Text); a.FrameCount = (int)DatAnimation.FrameCount; int bid = 0; foreach (DatAnimationNode bone in DatAnimation.Nodes) { Animation.KeyNode node = new Animation.KeyNode("Bone_" + bid++); //Console.WriteLine(node.Text + " " + bone.Tracks.Count); a.Bones.Add(node); node.RotType = Animation.RotationType.EULER; AnimationHelperTrack[] helper; try { helper = AnimationKeyFrameHelper.DecodeKeyFrames(bone); } catch (Exception) { Console.WriteLine("Error Loading animation"); helper = new AnimationHelperTrack[0]; } foreach (AnimationHelperTrack track in helper) { float prevValue = 0; float prevTan = 0; Animation.KeyFrame prevkey = null; Animation.KeyGroup Group = new Animation.KeyGroup(); foreach (AnimationHelperKeyFrame key in track.KeyFrames) { Animation.KeyFrame f = new Animation.KeyFrame(); f.Frame = key.Frame; f.Value = key.Value; f.In = key.Tan; switch (key.InterpolationType) { case InterpolationType.Constant: f.InterType = Animation.InterpolationType.CONSTANT; break; case InterpolationType.Hermite: f.InterType = Animation.InterpolationType.HERMITE; break; case InterpolationType.Linear: f.InterType = Animation.InterpolationType.LINEAR; break; case InterpolationType.Step: f.InterType = Animation.InterpolationType.STEP; break; case InterpolationType.HermiteValue: f.InterType = Animation.InterpolationType.HERMITE; f.In = prevTan; break; case InterpolationType.HermiteCurve: prevkey.Out = key.Tan; continue; } prevValue = key.Value; prevTan = key.Tan; prevkey = f; Group.Keys.Add(f); } switch (track.TrackType) { case AnimTrackType.XPOS: node.XPOS = Group; break; case AnimTrackType.YPOS: node.YPOS = Group; break; case AnimTrackType.ZPOS: node.ZPOS = Group; break; case AnimTrackType.XROT: node.XROT = Group; break; case AnimTrackType.YROT: node.YROT = Group; break; case AnimTrackType.ZROT: node.ZROT = Group; break; case AnimTrackType.XSCA: node.XSCA = Group; break; case AnimTrackType.YSCA: node.YSCA = Group; break; case AnimTrackType.ZSCA: node.ZSCA = Group; break; } } } return(a); }
private void LoadAnim(TexPatternAnim anim) { CanReplace = true; CanExport = true; CanDelete = true; CanRename = true; Text = anim.Name; TexPatternAnim = anim; FrameCount = anim.FrameCount; Materials.Clear(); Textures.Clear(); if (anim.TextureRefNames != null) { foreach (var tex in anim.TextureRefNames) { Textures.Add(tex.Name); } } if (anim.TextureRefs != null) { foreach (var tex in anim.TextureRefs) { Textures.Add(tex.Key); } } foreach (TexPatternMatAnim matanim in anim.TexPatternMatAnims) { var mat = new MaterialAnimEntry(matanim.Name); mat.TexPatternMatAnim = matanim; Materials.Add(mat); foreach (PatternAnimInfo SamplerInfo in matanim.PatternAnimInfos) { BfresSamplerAnim sampler = new BfresSamplerAnim(SamplerInfo.Name, this); mat.Samplers.Add(sampler); int textureIndex = 0; if (SamplerInfo.SubBindIndex != -1) { textureIndex = SamplerInfo.SubBindIndex; sampler.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = textureIndex }); sampler.Constant = true; } if (SamplerInfo.CurveIndex != -1) { int index = (int)SamplerInfo.CurveIndex; Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(matanim.Curves[index]); sampler.AnimDataOffset = matanim.Curves[index].AnimDataOffset; sampler.Keys = keyGroup.Keys; foreach (var ind in keyGroup.Keys) { Console.WriteLine($"{SamplerInfo.Name} {ind.Value}"); } } } } }
public static Animation.KeyGroup CreateTrack(AnimCurve animCurve) { Animation.KeyGroup track = new Animation.KeyGroup(); track.AnimDataOffset = animCurve.AnimDataOffset; track.Scale = animCurve.Scale; track.Offset = animCurve.Offset; track.StartFrame = animCurve.StartFrame; track.EndFrame = animCurve.EndFrame; track.Delta = animCurve.Delta; float tanscale = animCurve.Delta; if (tanscale == 0) { tanscale = 1; } if (animCurve.Scale == 0) { animCurve.Scale = 1; } for (int i = 0; i < (ushort)animCurve.Frames.Length; i++) { switch (animCurve.CurveType) { case AnimCurveType.Cubic: //4 elements are stored for cubic track.InterpolationType = InterpolationType.HERMITE; var coef0 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale); var coef1 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale); var coef2 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale); var coef3 = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale); var slopes = GetSlopes(animCurve, i); var inSlope = slopes[0] * animCurve.Scale + animCurve.Offset; var outSlope = slopes[1] * animCurve.Scale + animCurve.Offset; track.Keys.Add(new Animation.KeyFrame() { IsKeyed = true, InterType = InterpolationType.HERMITE, Frame = (int)animCurve.Frames[i], Value = coef0, Slope1 = inSlope, Slope2 = outSlope, }); break; case AnimCurveType.Linear: //2 elements are stored for linear track.InterpolationType = InterpolationType.LINEAR; track.Keys.Add(new Animation.KeyFrame() { IsKeyed = true, InterType = InterpolationType.LINEAR, Frame = (int)animCurve.Frames[i], Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale), Value1 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale), Delta = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale), }); break; case AnimCurveType.StepInt: //1 element are stored for step track.InterpolationType = InterpolationType.STEP; track.Keys.Add(new Animation.KeyFrame() { IsKeyed = true, InterType = InterpolationType.STEP, Frame = (int)animCurve.Frames[i], Value = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale, Value1 = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale, }); break; default: throw new Exception("Unsupported anim type!"); } } return(track); }