diff --git a/.vs/Switch_Toolbox/v15/.suo b/.vs/Switch_Toolbox/v15/.suo index c650c3aa..3a8aa653 100644 Binary files a/.vs/Switch_Toolbox/v15/.suo and b/.vs/Switch_Toolbox/v15/.suo differ diff --git a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide index 1f20f823..4c6828e9 100644 Binary files a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide and b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide differ diff --git a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal index 3be07996..18d7c577 100644 Binary files a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal and b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal differ diff --git a/BrawlboxHelper/BrawlHelper.cs b/BrawlboxHelper/BrawlHelper.cs index a23d14f7..e7176856 100644 --- a/BrawlboxHelper/BrawlHelper.cs +++ b/BrawlboxHelper/BrawlHelper.cs @@ -226,6 +226,12 @@ namespace BrawlboxHelper static float Deg2Rad = (float)(Math.PI / 180f); static float Rad2Deg = (float)(180f / Math.PI); + public static SkeletalAnim Anim2Fska(string FileName) + { + CHR0Node chr0 = AnimFormat.Read(FileName); + return Chr02Fska(chr0); + } + public static void Fska2Chr0(SkeletalAnim fska, string FileName) { @@ -477,7 +483,11 @@ namespace BrawlboxHelper public static SkeletalAnim Chr02Fska(string FileName) { CHR0Node chr0 = CHR0Node.FromFile(FileName); + return Chr02Fska(chr0); + } + private static SkeletalAnim Chr02Fska(CHR0Node chr0) + { SkeletalAnim fska = new SkeletalAnim(); fska.FrameCount = chr0.FrameCount; fska.Name = chr0.Name; diff --git a/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/SubFiles/FSKA.cs b/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/SubFiles/FSKA.cs index 9a27ecef..ee2cc71d 100644 --- a/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/SubFiles/FSKA.cs +++ b/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/SubFiles/FSKA.cs @@ -149,7 +149,6 @@ namespace Bfres.Structs ANIM.CreateANIM(FileName, this, skeleton); else throw new Exception("No skeleton found to assign!"); - } else if (ext == ".seanim") { @@ -246,6 +245,26 @@ namespace Bfres.Structs } } } + else if (ext == ".anim") + { + FromAnim(FileName); + + /* STSkeleton skeleton = GetActiveSkeleton(); + + var anim = ANIM.read(FileName, skeleton); + var ska = FromGeneric(anim); + + if (GetResFileU() != null) + { + SkeletalAnimU = ConvertSwitchToWiiU(ska); + LoadAnim(SkeletalAnimU); + } + else + { + SkeletalAnim = ska; + LoadAnim(SkeletalAnim); + }*/ + } else if (ext == ".seanim") { FromSeanim(FileName); @@ -256,6 +275,218 @@ namespace Bfres.Structs } } + public SkeletalAnim FromGeneric(Animation anim) + { + SkeletalAnim ska = new SkeletalAnim(); + ska.FrameCount = anim.FrameCount; + ska.Name = anim.Text; + ska.Path = ""; + ska.FlagsScale = SkeletalAnimFlagsScale.Maya; + ska.FlagsRotate = SkeletalAnimFlagsRotate.EulerXYZ; + ska.Loop = anim.CanLoop; + ska.Baked = false; + + for (int b = 0; b < anim.Bones.Count; b++) + ska.BoneAnims.Add(GenericBoneAnimToBfresBoneAnim(anim.Bones[b])); + + ska.BakedSize = CalculateBakeSize(ska); + ska.BindIndices = GenerateIndices(ska.BoneAnims.Count); + return ska; + } + + private BoneAnim GenericBoneAnimToBfresBoneAnim(Animation.KeyNode boneNode) + { + BoneAnim boneAnim = new BoneAnim(); + boneAnim.Name = boneNode.Text; + var posx = boneNode.XPOS.GetValue(0); + var posy = boneNode.YPOS.GetValue(0); + var posz = boneNode.ZPOS.GetValue(0); + var scax = boneNode.XSCA.GetValue(0); + var scay = boneNode.YSCA.GetValue(0); + var scaz = boneNode.ZSCA.GetValue(0); + var rotx = boneNode.XROT.GetValue(0); + var roty = boneNode.YROT.GetValue(0); + var rotz = boneNode.ZROT.GetValue(0); + var rotw = boneNode.WROT.GetValue(0); + + BoneAnimData boneBaseData = new BoneAnimData(); + boneBaseData.Translate = new Syroot.Maths.Vector3F(posx, posy, posz); + boneBaseData.Scale = new Syroot.Maths.Vector3F(scax, scay, scaz); + boneBaseData.Rotate = new Syroot.Maths.Vector4F(rotx, roty, rotz, rotw); + boneAnim.BaseData = boneBaseData; + boneAnim.BeginBaseTranslate = 0; + boneAnim.BeginRotate = 0; + boneAnim.BeginTranslate = 0; + boneAnim.Curves = new List(); + boneAnim.FlagsBase = BoneAnimFlagsBase.Translate | BoneAnimFlagsBase.Scale | BoneAnimFlagsBase.Rotate; + boneAnim.FlagsTransform = BoneAnimFlagsTransform.Identity; + + if (boneNode.XPOS.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateX; + var curve = SetAnimationCurve(boneNode.XPOS, (uint)FSKA.TrackType.XPOS); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.YPOS.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateY; + var curve = SetAnimationCurve(boneNode.YPOS, (uint)FSKA.TrackType.YPOS); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.ZPOS.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateZ; + var curve = SetAnimationCurve(boneNode.ZPOS, (uint)FSKA.TrackType.ZPOS); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.XSCA.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleX; + var curve = SetAnimationCurve(boneNode.XSCA, (uint)FSKA.TrackType.XSCA); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.YSCA.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleY; + var curve = SetAnimationCurve(boneNode.YSCA, (uint)FSKA.TrackType.YSCA); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.ZSCA.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleZ; + var curve = SetAnimationCurve(boneNode.ZSCA, (uint)FSKA.TrackType.ZSCA); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.XROT.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateX; + var curve = SetAnimationCurve(boneNode.XROT, (uint)FSKA.TrackType.XROT); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.YROT.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateY; + var curve = SetAnimationCurve(boneNode.YROT, (uint)FSKA.TrackType.YROT); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.ZROT.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateZ; + var curve = SetAnimationCurve(boneNode.ZROT, (uint)FSKA.TrackType.ZROT); + if (curve != null) + boneAnim.Curves.Add(curve); + } + if (boneNode.WROT.HasAnimation()) + { + boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateW; + var curve = SetAnimationCurve(boneNode.WROT, (uint)FSKA.TrackType.WROT); + if (curve != null) + boneAnim.Curves.Add(curve); + } + + return boneAnim; + } + + 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.EndFrame = keyGroup.FrameCount; + 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] = keyGroup.Keys[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]; + } + + //Difference of last and first key value + if (curve.Keys.Length > 0) + curve.Delta = curve.Keys[curve.Keys.Length - 1, 0] - curve.Keys[0, 0]; + + return curve; + } + + private ushort[] GenerateIndices(int count) + { + var indices = new ushort[count]; + for (int i = 0; i < count; i++) + indices[i] = ushort.MaxValue; + + return indices; + } + + //This hasn't been necessary so far but i do need todo this + public uint CalculateBakeSize(SkeletalAnim ska) + { + return 0; + } + public static SkeletalAnim ConvertWiiUToSwitch(ResU.SkeletalAnim skeletalAnimU) { SkeletalAnim ska = new SkeletalAnim(); @@ -537,6 +768,23 @@ namespace Bfres.Structs Initialize(); } + public void FromAnim(string FileName) + { + if (SkeletalAnimU != null) + { + var SkeletalAnimNX = BrawlboxHelper.FSKAConverter.Anim2Fska(FileName); + SkeletalAnimU = ConvertSwitchToWiiU(SkeletalAnimNX); + SkeletalAnimU.Name = Text; + LoadAnim(SkeletalAnimU); + } + else + { + SkeletalAnim = BrawlboxHelper.FSKAConverter.Anim2Fska(FileName); + SkeletalAnim.Name = Text; + LoadAnim(SkeletalAnim); + } + } + public void FromChr0(string FileName) { if (SkeletalAnimU != null) diff --git a/Switch_FileFormatsMain/FileFormats/BFRES/BfresWiiU.cs b/Switch_FileFormatsMain/FileFormats/BFRES/BfresWiiU.cs index 03757fc3..8d7ac1f4 100644 --- a/Switch_FileFormatsMain/FileFormats/BFRES/BfresWiiU.cs +++ b/Switch_FileFormatsMain/FileFormats/BFRES/BfresWiiU.cs @@ -270,7 +270,11 @@ namespace FirstPlugin if (fshp.VertexSkinCount == 1) { - Matrix4 sb = model.Skeleton.bones[model.Skeleton.Node_Array[v.boneIds[0]]].Transform; + int boneIndex = fshp.BoneIndex; + if (v.boneIds.Count > 0) + boneIndex = model.Skeleton.Node_Array[v.boneIds[0]]; + + Matrix4 sb = model.Skeleton.bones[boneIndex].Transform; v.pos = Vector3.TransformPosition(v.pos, sb); v.nrm = Vector3.TransformNormal(v.nrm, sb); } diff --git a/Switch_FileFormatsMain/Main.cs b/Switch_FileFormatsMain/Main.cs index 438d8b37..75a80bef 100644 --- a/Switch_FileFormatsMain/Main.cs +++ b/Switch_FileFormatsMain/Main.cs @@ -290,7 +290,7 @@ namespace FirstPlugin Formats.Add(typeof(SHARC)); Formats.Add(typeof(SHARCFB)); Formats.Add(typeof(NARC)); - // Formats.Add(typeof(SDF)); + Formats.Add(typeof(SDF)); Formats.Add(typeof(TMPK)); Formats.Add(typeof(TEX3DS)); Formats.Add(typeof(NXARC)); diff --git a/Switch_FileFormatsMain/NodeWrappers/BfresFilters.cs b/Switch_FileFormatsMain/NodeWrappers/BfresFilters.cs index f7738f02..d9290a0b 100644 --- a/Switch_FileFormatsMain/NodeWrappers/BfresFilters.cs +++ b/Switch_FileFormatsMain/NodeWrappers/BfresFilters.cs @@ -22,7 +22,7 @@ namespace FirstPlugin public static string FMAT = GetFilter(".bfmat"); public static string FSKA_EXPORT = GetFilter(".bfska", ".anim", ".seanim", ".smd", ".chr0"); - public static string FSKA_REPLACE = GetFilter(".bfska", ".chr0"); + public static string FSKA_REPLACE = GetFilter(".bfska",".anim", ".chr0"); public static string FMAA = GetFilter(".bfmaa", ".gif"); diff --git a/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache b/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache index 284ffa3e..318ca32e 100644 Binary files a/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache and b/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache differ diff --git a/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache b/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache index bff93e64..deceff2e 100644 Binary files a/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache and b/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache differ