public static BooleanKeyGroup CreateBooleanTrackWiiU(ResU.AnimCurve animCurve) { BooleanKeyGroup track = new BooleanKeyGroup(); track.AnimDataOffset = animCurve.AnimDataOffset; track.Scale = animCurve.Scale; track.Offset = animCurve.Offset; track.StartFrame = animCurve.StartFrame; track.EndFrame = animCurve.EndFrame; track.Delta = animCurve.Delta; for (int i = 0; i < (ushort)animCurve.Frames.Length; i++) { switch (animCurve.CurveType) { case ResU.AnimCurveType.StepBool: //1 element are stored for step track.Keys.Add(new BooleanKeyFrame() { IsKeyed = true, InterType = InterpolationType.STEPBOOL, Frame = (int)animCurve.Frames[i], Visible = animCurve.KeyStepBoolData[i], }); break; default: throw new Exception("Unsupported anim type!"); } } return(track); }
private static IList <ResU.AnimCurve> ConvertAnimCurveSwitchToWiiU(IList <ResNX.AnimCurve> curvesNX) { var curvesU = new List <ResU.AnimCurve>(); foreach (var curveNX in curvesNX) { ResU.AnimCurve curve = new ResU.AnimCurve(); curve.AnimDataOffset = curveNX.AnimDataOffset; curve.CurveType = (ResU.AnimCurveType)curveNX.CurveType; curve.Delta = curveNX.Delta; curve.EndFrame = curveNX.EndFrame; curve.Frames = curveNX.Frames; curve.Keys = curveNX.Keys; curve.KeyStepBoolData = curveNX.KeyStepBoolData; curve.KeyType = (ResU.AnimCurveKeyType)curveNX.KeyType; curve.FrameType = (ResU.AnimCurveFrameType)curveNX.FrameType; curve.StartFrame = curveNX.StartFrame; curve.Scale = curveNX.Scale; curve.Offset = (float)curveNX.Offset; curvesU.Add(curve); } return(curvesU); }
public static float[] GetSlopes(ResU.AnimCurve curve, float index) { float[] slopes = new float[2]; if (curve.CurveType == ResU.AnimCurveType.Cubic) { float InSlope = 0; float OutSlope = 0; for (int i = 0; i < curve.Frames.Length; i++) { var coef0 = curve.Keys[i, 0] * curve.Scale + curve.Offset; var coef1 = curve.Keys[i, 1] * curve.Scale; var coef2 = curve.Keys[i, 2] * curve.Scale; var coef3 = curve.Keys[i, 3] * curve.Scale; float time = 0; float delta = 0; float invTime = 1; if (i < curve.Frames.Length - 1) { var nextValue = curve.Keys[i + 1, 0] * curve.Scale + curve.Offset; delta = nextValue - coef0; time = curve.Frames[i + 1] - curve.Frames[i]; invTime = 1f / time; } float p0 = coef0; float p1 = coef0 + (coef1 + coef3) / 3f; float p2 = coef0 + (coef1 + coef1 + coef2) / 3f; float p3 = coef0 + delta; if (index == i) { OutSlope = (p1 - p0) * 3f * invTime; return(new float[2] { InSlope, OutSlope }); } InSlope = (p3 - p2) * 3f * invTime; } } return(slopes); }
public static float[] GetSlopes(ResU.AnimCurve curve, float index) { float[] slopes = new float[2]; if (curve.CurveType == ResU.AnimCurveType.Cubic) { float InSlope = 0; float OutSlope = 0; for (int i = 0; i < curve.Frames.Length; i++) { var coef0 = curve.Keys[i, 0] * curve.Scale + curve.Offset; var coef1 = curve.Keys[i, 1] * curve.Scale + curve.Offset; var coef2 = curve.Keys[i, 2] * curve.Scale + curve.Offset; var coef3 = curve.Keys[i, 3] * curve.Scale + curve.Offset; float time = 0; float delta = 0; if (i < curve.Frames.Length - 1) { var nextValue = curve.Keys[i + 1, 0] * curve.Scale + curve.Offset; delta = nextValue - coef0; time = curve.Frames[i + 1] - curve.Frames[i]; } var slopeData = CurveInterpolationHelper.GetCubicSlopes(time, delta, new float[4] { coef0, coef1, coef2, coef3, }); if (index == i) { OutSlope = slopeData[1]; return(new float[2] { InSlope, OutSlope }); } //The previous inslope is used InSlope = slopeData[0]; } } return(slopes); }
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); }
public GifToTexturePatternAnimation(string FileName, BFRESGroupNode TargetFTEXFolder, FTXP ftxp) { string TextureName = System.IO.Path.GetFileNameWithoutExtension(FileName); string ext = Utils.GetExtension(FileName); ImageKeyFrame[] Images = new ImageKeyFrame[0]; if (ext == ".gif") { Image gifImg = Image.FromFile(FileName); //Add all the images Images = GetImages(gifImg); } if (ext == ".png" || ext == ".apng") { APNG png = new APNG(); png.Load(FileName); for (int i = 0; i < png.NumEmbeddedPNG; i++) { Images[i] = new ImageKeyFrame() { Frame = i, Image = png.ToBitmap(i) }; } } TargetFTEXFolder.ImportTexture(Images, TextureName); //Now load the key data to the animation ftxp.TexPatternAnim = new ResU.TexPatternAnim(); ftxp.TexPatternAnim.Name = ftxp.Text; ftxp.TexPatternAnim.Path = ""; ftxp.TexPatternAnim.FrameCount = Images.Length; ftxp.TexPatternAnim.TextureRefs = new ResU.ResDict <ResU.TextureRef>(); foreach (ImageKeyFrame key in Images) { string name = $"{TextureName}{key.Frame}"; ftxp.TexPatternAnim.TextureRefs.Add($"{TextureName}{key.Frame}", new ResU.TextureRef() { Name = $"{name}", Texture = ((FTEX)TargetFTEXFolder.ResourceNodes[name]).texture, }); } var material = new ResU.TexPatternMatAnim(); material.Name = "NewMaterial"; material.PatternAnimInfos = new List <ResU.PatternAnimInfo>(); material.BaseDataList.Add(0); ResU.PatternAnimInfo info = new ResU.PatternAnimInfo(); info.CurveIndex = 0; info.SubBindIndex = -1; info.Name = "_a0"; material.PatternAnimInfos.Add(info); ftxp.TexPatternAnim.TexPatternMatAnims.Add(material); ResU.AnimCurve curve = new ResU.AnimCurve(); curve.AnimDataOffset = 0; curve.CurveType = ResU.AnimCurveType.StepInt; curve.Delta = 0; curve.EndFrame = Images.Length; curve.StartFrame = 0; curve.FrameType = ResU.AnimCurveFrameType.Byte; curve.Scale = 1; curve.Offset = 0; curve.Frames = new float[(int)curve.EndFrame]; for (int i = 0; i < curve.EndFrame; i++) { curve.Frames[i] = Images[i].Frame; } curve.Keys = new float[(int)curve.Frames.Length, 1]; for (int i = 0; i < (ushort)curve.Keys.Length; i++) { int index = ftxp.TexPatternAnim.TextureRefs.IndexOf($"{TextureName}{Images[i].Frame}"); curve.Keys[i, 0] = index; } material.Curves.Add(curve); ftxp.UpdateMaterialBinds(); }
private static ResU.AnimCurve GenerateCurve(uint AnimOffset, CLR0Node anim, CLR0MaterialEntryNode entry) { ResU.AnimCurve curve = new ResU.AnimCurve(); curve.AnimDataOffset = AnimOffset; curve.StartFrame = 0; curve.Offset = 0; curve.Scale = 1; curve.FrameType = ResU.AnimCurveFrameType.Single; curve.KeyType = ResU.AnimCurveKeyType.Single; curve.CurveType = ResU.AnimCurveType.Linear; List <float> Frames = new List <float>(); List <float> Keys = new List <float>(); for (int c = 0; c < entry.Colors.Count; c++) { Frames.Add(c); //Max of 4 values. Cubic using 4, linear using 2, and step using 1 float[] KeyValues = new float[4]; switch (AnimOffset) { case 0: //Red Keys.Add((float)entry.Colors[c].R / 255f); break; case 4: //Green Keys.Add((float)entry.Colors[c].G / 255f); break; case 8: //Blue Keys.Add((float)entry.Colors[c].B / 255f); break; case 12: //Alpha Keys.Add((float)entry.Colors[c].A / 255f); break; default: throw new Exception("Invalid animation offset set!"); } } //Max value in frames is our end frame curve.EndFrame = Frames.Max(); curve.Frames = Frames.ToArray(); //If a curve only has one frame we don't need to interpolate or add keys to a curve as it's constant if (curve.Frames.Length <= 1) { return(null); } switch (curve.CurveType) { case ResU.AnimCurveType.Cubic: curve.Keys = new float[Keys.Count, 4]; for (int frame = 0; frame < Keys.Count; frame++) { float Delta = 0; if (frame < Keys.Count - 1) { Delta = Keys[frame + 1] - Keys[frame]; } float value = Keys[frame]; float Slope = 0; float Slope2 = 0; curve.Keys[frame, 0] = value; curve.Keys[frame, 1] = Slope; curve.Keys[frame, 2] = Slope2; curve.Keys[frame, 3] = Delta; } break; case ResU.AnimCurveType.StepInt: //Step requires no interpolation curve.Keys = new float[Keys.Count, 1]; for (int frame = 0; frame < Keys.Count; frame++) { curve.Keys[frame, 0] = 0; } break; case ResU.AnimCurveType.Linear: curve.Keys = new float[Keys.Count, 2]; for (int frame = 0; frame < Keys.Count; frame++) { //Delta for second value used in linear curves float time = curve.Frames[frame]; float Delta = 0; if (frame < Keys.Count - 1) { Delta = Keys[frame + 1] - Keys[frame]; } curve.Keys[frame, 0] = Keys[frame]; curve.Keys[frame, 1] = Delta; } break; } return(curve); }