diff --git a/File_Format_Library/FileFormats/Archives/NARC.cs b/File_Format_Library/FileFormats/Archives/NARC.cs index 3251c497..bfc51baf 100644 --- a/File_Format_Library/FileFormats/Archives/NARC.cs +++ b/File_Format_Library/FileFormats/Archives/NARC.cs @@ -2,6 +2,7 @@ using Syroot.BinaryData; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using Toolbox.Library; using Toolbox.Library.IO; @@ -28,9 +29,7 @@ namespace FirstPlugin { // private private Header header; - private BTAF btaf; - private BTNF btnf; - private GMIF gmif; + private byte[] bfntUnk = new byte[] { 0x00, 0x00, 0x01, 0x00 }; private List files = new List(); @@ -56,33 +55,86 @@ namespace FirstPlugin { public void Load(Stream stream) { using(FileReader reader = new FileReader(stream)) { + //DirectoryEntry currentDirEntry = rootDir; + string currentDir = string.Empty; + header = new Header(reader); - for(uint i = 0; i < header.DataBlocks; i++) { - long PositionBuf = reader.Position; - string cSectionMagic = Encoding.ASCII.GetString(reader.ReadBytes(4)).ToUpperInvariant(); - uint cSectionSize = reader.ReadUInt32(); + reader.ReadSignature(4, "BTAF"); - switch(cSectionMagic) { - case "BTAF": - btaf = new BTAF(reader); - break; - case "BTNF": - btnf = new BTNF(reader, (uint) btaf.FileDataArray.Length); - break; - case "GMIF": - gmif = new GMIF(reader, btaf); - break; + // The positions where the sections' reading was left last time. + long bfatIndex = reader.Position + 8; + long bfntIndex = reader.Position + reader.ReadUInt32(); // From the BFAT length. + long fimgIndex; + + uint fileCount = reader.ReadUInt32(); + + uint currentFileOffset; + uint currentFileEnd; + + reader.Position = bfntIndex; + + fimgIndex = reader.Position + reader.ReadUInt32() + 4; // Sets FIMG section begining. + bfntUnk = reader.ReadBytes(reader.ReadInt32() - 4); + + for(int i = 0; i < fileCount; i++) { + byte nameLength = reader.ReadByte(); + + if(nameLength == 0x00) { // End of the "folder". + List slashIndices = new List(); + for(int j = 0; j < currentDir.Length; j++) + if(currentDir[j] == '/') + slashIndices.Add(j); + + int lastSlash = slashIndices.Last(); + slashIndices.Remove(lastSlash); + int slashBeforeLast = slashIndices.Count > 0 ? slashIndices.Last() : 0; + + currentDir = currentDir.Remove(slashBeforeLast + 1); + + if(currentDir.Length == 1) + currentDir = string.Empty; + + i--; + continue; } - reader.Position = PositionBuf + cSectionSize; - } + if(nameLength >= 0x80) { // If it is a "folder". + // Disable file modifications: + CanSave = false; + CanAddFiles = false; + CanRenameFiles = false; + CanReplaceFiles = false; + CanDeleteFiles = false; - for(int i = 0; i < btnf.FileNames.Length; i++) - files.Add(new FileEntry(this) { - FileName = btnf.FileNames[i], - BlockData = gmif.FilesData[i] + string dirName = reader.ReadString(nameLength & 0x7F); + currentDir += dirName + "/"; + + reader.Position += 2; + i--; + continue; + } + + // Read BFAT section: + using(reader.TemporarySeek()) { + reader.Position = bfatIndex; + + currentFileOffset = reader.ReadUInt32(); + currentFileEnd = reader.ReadUInt32(); + + bfatIndex = reader.Position; + } + + string name = reader.ReadString(nameLength); + + using(reader.TemporarySeek()) { + reader.Position = fimgIndex + currentFileOffset; + files.Add(new FileEntry(this) { + FileName = currentDir + name, + BlockData = reader.ReadBytes((int) (currentFileEnd - currentFileOffset)) }); + } + } } } @@ -219,7 +271,7 @@ namespace FirstPlugin { writer.Write(header.Version); // Version. long headerLengthPorsition = writer.Position; - writer.Write(0x00000000); // Skips length writing. + writer.Position += 4; // Skips length writing. writer.Write(header.HeaderSize); // Header length. writer.Write(header.DataBlocks); // Section count. @@ -230,21 +282,21 @@ namespace FirstPlugin { writer.Write((uint) files.Count); // File count. for(uint i = 0; i < files.Count; i++) // Reads unset bytes per file. (Reserved space for later) - writer.Write((long) 0x0000000000000000); + writer.Position += 8; WriteSectionLength(btafPosition); #endregion #region BTNF long btnfPosition = WriteSectionHeader("BTNF"); // Header. - writer.Write(btnf.Unknown); + writer.Write(bfntUnk.Length + 4); + writer.Write(bfntUnk); foreach(ArchiveFileInfo file in files) writer.Write(file.FileName, BinaryStringFormat.ByteLengthPrefix); writer.Write((byte) 0x00); - writer.Align(32); - writer.Position += 8; + writer.Align(128); WriteSectionLength(btnfPosition); #endregion @@ -257,7 +309,7 @@ namespace FirstPlugin { WriteBTAFEntry(); // BTAF offset writer.Write(file.FileData); WriteBTAFEntry(); // BTAF size. - writer.Align(16); + writer.Align(128); } WriteSectionLength(gmifPosition); @@ -270,7 +322,7 @@ namespace FirstPlugin { long startPosition = writer.Position; writer.Write(magic, BinaryStringFormat.NoPrefixOrTermination, Encoding.ASCII); // Magic. - writer.Write(0x00000000); // Skips length position. + writer.Position += 4; // Skips length position. return startPosition; } @@ -296,60 +348,5 @@ namespace FirstPlugin { } } } - - #region Sections - internal class BTAF { - public FD[] FileDataArray; - - public BTAF() { } - public BTAF(BinaryDataReader reader) { - uint numberOfFiles = reader.ReadUInt32(); - FileDataArray = new FD[numberOfFiles]; - - for(ulong i = 0; i < numberOfFiles; i++) { - FileDataArray[i].offset = reader.ReadUInt32(); - FileDataArray[i].size = reader.ReadUInt32(); - } - } - - public class FD - { - public uint offset; - public uint size; - } - } - - internal class BTNF { - public string[] FileNames; - public ulong Unknown; - - public BTNF() { } - public BTNF(BinaryDataReader reader, uint numberOfFiles) { - Unknown = reader.ReadUInt64(); - FileNames = new string[numberOfFiles]; - - for(int i = 0; i < numberOfFiles; i++) { - FileNames[i] = reader.ReadString(BinaryStringFormat.ByteLengthPrefix, Encoding.ASCII); - } - } - } - - internal class GMIF { - public byte[][] FilesData; - - public GMIF() { } - public GMIF(BinaryDataReader reader, BTAF btaf) { - FilesData = new byte[btaf.FileDataArray.Length][]; - long PositionBuf = reader.Position; - - for(int i = 0; i < btaf.FileDataArray.Length; i++) { - reader.Position = PositionBuf + btaf.FileDataArray[i].offset; - - FilesData[i] = reader.ReadBytes( - (int) (btaf.FileDataArray[i].size - btaf.FileDataArray[i].offset)); - } - } - } - #endregion } } diff --git a/File_Format_Library/FileFormats/Pokemon/GFLX/GFBANIM/GFBANM.cs b/File_Format_Library/FileFormats/Pokemon/GFLX/GFBANIM/GFBANM.cs index 8ba0e2da..f6b84ad9 100644 --- a/File_Format_Library/FileFormats/Pokemon/GFLX/GFBANIM/GFBANM.cs +++ b/File_Format_Library/FileFormats/Pokemon/GFLX/GFBANIM/GFBANM.cs @@ -1,664 +1,665 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Toolbox; -using System.Windows.Forms; -using Toolbox.Library; -using Toolbox.Library.IO; -using OpenTK; -using System.Reflection; -using Toolbox.Library.IO.FlatBuffer; -using Toolbox.Library.Animations; -using FirstPlugin.Forms; -using Toolbox.Library.Forms; - -namespace FirstPlugin -{ - public class GFBANM : TreeNodeFile, IFileFormat, IAnimationContainer, IConvertableTextFormat - { - public STAnimation AnimationController => AnimationData; - - public FileType FileType { get; set; } = FileType.Model; - - public bool CanSave { get; set; } - public string[] Description { get; set; } = new string[] { "GFBANM" }; - public string[] Extension { get; set; } = new string[] { "*.gfbanm" }; - public string FileName { get; set; } - public string FilePath { get; set; } - public IFileInfo IFileInfo { get; set; } - - public bool Identify(System.IO.Stream stream) - { - return Utils.GetExtension(FileName) == ".gfbanm"; - } - - public override void OnClick(TreeView treeView) - { - ViewportEditor editor = (ViewportEditor)LibraryGUI.GetActiveContent(typeof(ViewportEditor)); - if (editor == null) - { - editor = new ViewportEditor(true); - editor.Dock = DockStyle.Fill; - LibraryGUI.LoadEditor(editor); - } - } - - #region Text Converter Interface - public TextFileType TextFileType => TextFileType.Json; - public bool CanConvertBack => false; - - public string ConvertToString() - { - if (IFileInfo.ArchiveParent != null) - { - foreach (var file in IFileInfo.ArchiveParent.Files) - if (file.FileName == FileName) - return FlatBufferConverter.DeserializeToJson(new System.IO.MemoryStream(file.FileData), "gfbanm"); - } - else - return FlatBufferConverter.DeserializeToJson(FilePath, "gfbanm"); - - return ""; - } - - public void ConvertFromString(string text) - { - } - - #endregion - - public Type[] Types - { - get - { - List types = new List(); - return types.ToArray(); - } - } - - Animation AnimationData; - public void Load(System.IO.Stream stream) - { - Text = FileName; - Gfbanim.Animation anim = Gfbanim.Animation.GetRootAsAnimation( - new FlatBuffers.ByteBuffer(stream.ToBytes())); - - AnimationData = new Animation(); - AnimationData.FrameCount = anim.AnimConfig.Value.KeyFrames; - - if (anim.Bones.HasValue) { - for (int i = 0; i < anim.Bones.Value.BonesLength; i++) - AnimationData.LoadBoneGroup(anim.Bones.Value.Bones(i).Value); - } - if (anim.Materials.HasValue) { - for (int i = 0; i < anim.Materials.Value.MaterialsLength; i++) - AnimationData.LoadMaterialGroup(anim.Materials.Value.Materials(i).Value); - } - if (anim.Groups.HasValue) { - for (int i = 0; i < anim.Groups.Value.GroupsLength; i++) - AnimationData.LoadVisibilyGroup(anim.Groups.Value.Groups(i).Value); - } - if (anim.Triggers.HasValue) { - for (int i = 0; i < anim.Triggers.Value.TriggersLength; i++) - AnimationData.LoadTriggerGroup(anim.Triggers.Value.Triggers(i).Value); - } - } - - public void Unload() - { - - } - - public void Save(System.IO.Stream stream) - { - } - - public class MeshAnimationController - { - public bool IsVisible = true; - } - - public class Animation : STSkeletonAnimation - { - private GFBMDL ActiveModel - { - get - { - GFBMDL model = null; - foreach (var container in ObjectEditor.GetDrawableContainers()) { - foreach (var drawable in container.Drawables) - { - if (!drawable.Visible) - continue; - - if (drawable is GFBMDL_Render) - model = ((GFBMDL_Render)drawable).GfbmdlFile; - } - } - return model; - } - } - - public override STSkeleton GetActiveSkeleton() - { - if (ActiveModel == null) return null; - - return ActiveModel.Model.Skeleton; - } - - public override void NextFrame() - { - if (Frame > FrameCount || ActiveModel == null) return; - - var skeleton = ActiveModel.Model.Skeleton; - if (skeleton == null) - return; - - if (Frame == 0) - skeleton.reset(); - - bool Updated = false; // no need to update skeleton of animations that didn't change - foreach (var animGroup in AnimGroups) - { - if (animGroup is VisibiltyGroup && ActiveModel != null) - { - var node = animGroup as VisibiltyGroup; - foreach (var mesh in ActiveModel.Model.GenericMeshes) { - if (animGroup.Name == mesh.Text) - { - var value = node.BooleanTrack.GetFrameValue(Frame); - mesh.AnimationController.IsVisible = value == 1; - } - } - } - if (animGroup is MaterialGroup && ActiveModel != null) - { - foreach (var mat in ActiveModel.Model.GenericMaterials) { - if (animGroup.Name == mat.Text) - { - - } - } - } - if (animGroup is BoneGroup) - { - var node = animGroup as BoneGroup; - - STBone b = null; - - b = skeleton.GetBone(node.Name); - if (b == null) continue; - - Updated = true; - - if (node.TranslateX.HasKeys) - b.pos.X = node.TranslateX.GetFrameValue(Frame); - if (node.TranslateY.HasKeys) - b.pos.Y = node.TranslateY.GetFrameValue(Frame); - if (node.TranslateZ.HasKeys) - b.pos.Z = node.TranslateZ.GetFrameValue(Frame); - - if (node.ScaleX.HasKeys) - b.sca.X = node.ScaleX.GetFrameValue(Frame); - else b.sca.X = 1; - if (node.ScaleY.HasKeys) - b.sca.Y = node.ScaleY.GetFrameValue(Frame); - else b.sca.Y = 1; - if (node.ScaleZ.HasKeys) - b.sca.Z = node.ScaleZ.GetFrameValue(Frame); - else b.sca.Z = 1; - - if (node.RotationX.HasKeys || node.RotationY.HasKeys || node.RotationZ.HasKeys) - { - STKeyFrame xL = GetFVGFL(node.RotationX, Frame); - STKeyFrame yL = GetFVGFL(node.RotationY, Frame); - STKeyFrame zL = GetFVGFL(node.RotationZ, Frame); - STKeyFrame xR = GetFVGFR(node.RotationX, Frame); - STKeyFrame yR = GetFVGFR(node.RotationY, Frame); - STKeyFrame zR = GetFVGFR(node.RotationZ, Frame); - - short value1 = (short)xL.Value; - short value2 = (short)yL.Value; - short value3 = (short)zL.Value; - - Quaternion rotL = PackedToQuat(value1, value2, value3); - - short value1r = (short)xR.Value; - short value2r = (short)yR.Value; - short value3r = (short)zR.Value; - - Quaternion rotR = PackedToQuat(value1r, value2r, value3r); - - float weight = (Frame - xL.Frame) / (xR.Frame - xL.Frame); - if (xR.Frame - xL.Frame == 0) //NaN if divided by zero - { - weight = 0; - } - - b.rot = Quaternion.Slerp(rotL, rotR, weight); - } - else - { - b.rot = EulerToQuat(b.EulerRotation.Z, b.EulerRotation.Y, b.EulerRotation.X); - } - } - } - - if (Updated) - { - skeleton.update(); - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox; +using System.Windows.Forms; +using Toolbox.Library; +using Toolbox.Library.IO; +using OpenTK; +using System.Reflection; +using Toolbox.Library.IO.FlatBuffer; +using Toolbox.Library.Animations; +using FirstPlugin.Forms; +using Toolbox.Library.Forms; + +namespace FirstPlugin +{ + public class GFBANM : TreeNodeFile, IFileFormat, IAnimationContainer, IConvertableTextFormat + { + public STAnimation AnimationController => AnimationData; + + public FileType FileType { get; set; } = FileType.Model; + + public bool CanSave { get; set; } + public string[] Description { get; set; } = new string[] { "GFBANM" }; + public string[] Extension { get; set; } = new string[] { "*.gfbanm" }; + public string FileName { get; set; } + public string FilePath { get; set; } + public IFileInfo IFileInfo { get; set; } + + public bool Identify(System.IO.Stream stream) + { + return Utils.GetExtension(FileName) == ".gfbanm"; + } + + public override void OnClick(TreeView treeView) + { + ViewportEditor editor = (ViewportEditor)LibraryGUI.GetActiveContent(typeof(ViewportEditor)); + if (editor == null) + { + editor = new ViewportEditor(true); + editor.Dock = DockStyle.Fill; + LibraryGUI.LoadEditor(editor); + } + } + + #region Text Converter Interface + public TextFileType TextFileType => TextFileType.Json; + public bool CanConvertBack => false; + + public string ConvertToString() + { + if (IFileInfo.ArchiveParent != null) + { + foreach (var file in IFileInfo.ArchiveParent.Files) + if (file.FileName == FileName) + return FlatBufferConverter.DeserializeToJson(new System.IO.MemoryStream(file.FileData), "gfbanm"); + } + else + return FlatBufferConverter.DeserializeToJson(FilePath, "gfbanm"); + + return ""; + } + + public void ConvertFromString(string text) + { + } + + #endregion + + public Type[] Types + { + get + { + List types = new List(); + return types.ToArray(); + } + } + + Animation AnimationData; + public void Load(System.IO.Stream stream) + { + Text = FileName; + Gfbanim.Animation anim = Gfbanim.Animation.GetRootAsAnimation( + new FlatBuffers.ByteBuffer(stream.ToBytes())); + + AnimationData = new Animation(); + AnimationData.Name = FileName; + AnimationData.FrameCount = anim.AnimConfig.Value.KeyFrames; + + if (anim.Bones.HasValue) { + for (int i = 0; i < anim.Bones.Value.BonesLength; i++) + AnimationData.LoadBoneGroup(anim.Bones.Value.Bones(i).Value); + } + if (anim.Materials.HasValue) { + for (int i = 0; i < anim.Materials.Value.MaterialsLength; i++) + AnimationData.LoadMaterialGroup(anim.Materials.Value.Materials(i).Value); + } + if (anim.Groups.HasValue) { + for (int i = 0; i < anim.Groups.Value.GroupsLength; i++) + AnimationData.LoadVisibilyGroup(anim.Groups.Value.Groups(i).Value); + } + if (anim.Triggers.HasValue) { + for (int i = 0; i < anim.Triggers.Value.TriggersLength; i++) + AnimationData.LoadTriggerGroup(anim.Triggers.Value.Triggers(i).Value); + } + } + + public void Unload() + { + + } + + public void Save(System.IO.Stream stream) + { + } + + public class MeshAnimationController + { + public bool IsVisible = true; + } + + public class Animation : STSkeletonAnimation + { + private GFBMDL ActiveModel + { + get + { + GFBMDL model = null; + foreach (var container in ObjectEditor.GetDrawableContainers()) { + foreach (var drawable in container.Drawables) + { + if (!drawable.Visible) + continue; + + if (drawable is GFBMDL_Render) + model = ((GFBMDL_Render)drawable).GfbmdlFile; + } + } + return model; + } } - public STKeyFrame GetFVGFL(STAnimationTrack t, float frame, float startFrame = 0) - { - if (t.KeyFrames.Count == 0) return new STKeyFrame(frame, 0); - if (t.KeyFrames.Count == 1) return t.KeyFrames[0]; - - STKeyFrame LK = t.KeyFrames.First(); - - float Frame = frame - startFrame; - - foreach (STKeyFrame keyFrame in t.KeyFrames) - { - if (keyFrame.Frame <= Frame) LK = keyFrame; - } - - return LK; - } - - public STKeyFrame GetFVGFR(STAnimationTrack t, float frame, float startFrame = 0) - { - if (t.KeyFrames.Count == 0) return new STKeyFrame(frame, 0); - if (t.KeyFrames.Count == 1) return t.KeyFrames[0]; - - STKeyFrame RK = t.KeyFrames.Last(); - - float Frame = frame - startFrame; - - foreach (STKeyFrame keyFrame in t.KeyFrames) - { - if (keyFrame.Frame >= Frame && keyFrame.Frame < RK.Frame) RK = keyFrame; - } - - return RK; + public override STSkeleton GetActiveSkeleton() + { + if (ActiveModel == null) return null; + + return ActiveModel.Model.Skeleton; + } + + public override void NextFrame() + { + if (Frame > FrameCount || ActiveModel == null) return; + + var skeleton = ActiveModel.Model.Skeleton; + if (skeleton == null) + return; + + if (Frame == 0) + skeleton.reset(); + + bool Updated = false; // no need to update skeleton of animations that didn't change + foreach (var animGroup in AnimGroups) + { + if (animGroup is VisibiltyGroup && ActiveModel != null) + { + var node = animGroup as VisibiltyGroup; + foreach (var mesh in ActiveModel.Model.GenericMeshes) { + if (animGroup.Name == mesh.Text) + { + var value = node.BooleanTrack.GetFrameValue(Frame); + mesh.AnimationController.IsVisible = value == 1; + } + } + } + if (animGroup is MaterialGroup && ActiveModel != null) + { + foreach (var mat in ActiveModel.Model.GenericMaterials) { + if (animGroup.Name == mat.Text) + { + + } + } + } + if (animGroup is BoneGroup) + { + var node = animGroup as BoneGroup; + + STBone b = null; + + b = skeleton.GetBone(node.Name); + if (b == null) continue; + + Updated = true; + + if (node.TranslateX.HasKeys) + b.pos.X = node.TranslateX.GetFrameValue(Frame); + if (node.TranslateY.HasKeys) + b.pos.Y = node.TranslateY.GetFrameValue(Frame); + if (node.TranslateZ.HasKeys) + b.pos.Z = node.TranslateZ.GetFrameValue(Frame); + + if (node.ScaleX.HasKeys) + b.sca.X = node.ScaleX.GetFrameValue(Frame); + else b.sca.X = 1; + if (node.ScaleY.HasKeys) + b.sca.Y = node.ScaleY.GetFrameValue(Frame); + else b.sca.Y = 1; + if (node.ScaleZ.HasKeys) + b.sca.Z = node.ScaleZ.GetFrameValue(Frame); + else b.sca.Z = 1; + + if (node.RotationX.HasKeys || node.RotationY.HasKeys || node.RotationZ.HasKeys) + { + STKeyFrame xL = GetFVGFL(node.RotationX, Frame); + STKeyFrame yL = GetFVGFL(node.RotationY, Frame); + STKeyFrame zL = GetFVGFL(node.RotationZ, Frame); + STKeyFrame xR = GetFVGFR(node.RotationX, Frame); + STKeyFrame yR = GetFVGFR(node.RotationY, Frame); + STKeyFrame zR = GetFVGFR(node.RotationZ, Frame); + + short value1 = (short)xL.Value; + short value2 = (short)yL.Value; + short value3 = (short)zL.Value; + + Quaternion rotL = PackedToQuat(value1, value2, value3); + + short value1r = (short)xR.Value; + short value2r = (short)yR.Value; + short value3r = (short)zR.Value; + + Quaternion rotR = PackedToQuat(value1r, value2r, value3r); + + float weight = (Frame - xL.Frame) / (xR.Frame - xL.Frame); + if (xR.Frame - xL.Frame == 0) //NaN if divided by zero + { + weight = 0; + } + + b.rot = Quaternion.Slerp(rotL, rotR, weight); + } + else + { + b.rot = EulerToQuat(b.EulerRotation.Z, b.EulerRotation.Y, b.EulerRotation.X); + } + } + } + + if (Updated) + { + skeleton.update(); + } + } + + public STKeyFrame GetFVGFL(STAnimationTrack t, float frame, float startFrame = 0) + { + if (t.KeyFrames.Count == 0) return new STKeyFrame(frame, 0); + if (t.KeyFrames.Count == 1) return t.KeyFrames[0]; + + STKeyFrame LK = t.KeyFrames.First(); + + float Frame = frame - startFrame; + + foreach (STKeyFrame keyFrame in t.KeyFrames) + { + if (keyFrame.Frame <= Frame) LK = keyFrame; + } + + return LK; + } + + public STKeyFrame GetFVGFR(STAnimationTrack t, float frame, float startFrame = 0) + { + if (t.KeyFrames.Count == 0) return new STKeyFrame(frame, 0); + if (t.KeyFrames.Count == 1) return t.KeyFrames[0]; + + STKeyFrame RK = t.KeyFrames.Last(); + + float Frame = frame - startFrame; + + foreach (STKeyFrame keyFrame in t.KeyFrames) + { + if (keyFrame.Frame >= Frame && keyFrame.Frame < RK.Frame) RK = keyFrame; + } + + return RK; } // private static readonly ushort _flagsMask = 0b11000011_11111111; - private static short UnpackS15(short u15) - { - int sign = (u15 >> 14) & 1; - u15 &= 0x3FFF; - if (sign == 0) u15 -= 0x4000; - return u15; - } - - static int[][] QUATERNION_SWIZZLES = { - new int[] { 0, 3, 2, 1 }, new int[] { 3, 0, 2, 1 }, - new int[] { 3, 2, 0, 1 }, new int[] { 3, 2, 1, 0 } - }; - - private static Quaternion PackedToQuat(short z, short y, short x) - { - - const int count = 15; - const int BASE = (1 << count) - 1; - float maxval = 1 / (0x399E * (float)Math.Sqrt(2.0)); // such obvious, so constant, wow - - long cq = x & 0xFFFF; - cq <<= 16; - cq |= ((uint)y) & 0xFFFF; - cq <<= 16; - cq |= ((uint)z) & 0xFFFF; - - - short extra = (short)(cq & 0x7); - - long num = cq >> 3; - - x = UnpackS15((short)((num >> (count * 2)) & BASE)); - y = UnpackS15((short)((num >> (count * 1)) & BASE)); - z = UnpackS15((short)((num >> (count * 0)) & BASE)); - - float fx = x * maxval; - float fy = y * maxval; - float fz = z * maxval; - - float[] quat = { - (float)Math.Sqrt(1 - fx * fx - fy * fy - fz * fz), - fx, - fy, - fz }; - - int[] qmap = QUATERNION_SWIZZLES[(extra & 3)]; - Quaternion q = new Quaternion(quat[qmap[0]], quat[qmap[1]], quat[qmap[2]], quat[qmap[3]]); - if ((extra >> 2) != 0) q *= -1; - - return q; - - } - - public static Quaternion EulerToQuat(float z, float y, float x) - { - Quaternion xRotation = Quaternion.FromAxisAngle(Vector3.UnitX, x); - Quaternion yRotation = Quaternion.FromAxisAngle(Vector3.UnitY, y); - Quaternion zRotation = Quaternion.FromAxisAngle(Vector3.UnitZ, z); - return (zRotation * yRotation * xRotation); - } - - public void LoadBoneGroup(Gfbanim.Bone boneAnim) - { - BoneGroup groupAnim = new BoneGroup(); - groupAnim.Name = boneAnim.Name; - AnimGroups.Add(groupAnim); - - //Tracks use 3 types - // Fixed/constant - // Dynamic (baked and multiple keys, no frames) - // Framed (multiple keys and frames) - - List Frames = new List(); - - switch (boneAnim.RotateType) - { - case Gfbanim.QuatTrack.DynamicQuatTrack: - { - var rotate = boneAnim.Rotate(); - if (rotate.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadRotationTrack(rotate.Value); - groupAnim.RotationX = values[0]; - groupAnim.RotationY = values[1]; - groupAnim.RotationZ = values[2]; - } - } - break; - case Gfbanim.QuatTrack.FixedQuatTrack: - { - var rotate = boneAnim.Rotate(); - if (rotate.HasValue) - { - var vec = rotate.Value.Value.Value; - groupAnim.RotationX.KeyFrames.Add(new STKeyFrame(0, GfbanimKeyFrameLoader.ConvertRotation(vec.X))); - groupAnim.RotationY.KeyFrames.Add(new STKeyFrame(0, GfbanimKeyFrameLoader.ConvertRotation(vec.Y))); - groupAnim.RotationZ.KeyFrames.Add(new STKeyFrame(0, GfbanimKeyFrameLoader.ConvertRotation(vec.Z))); - } - } + private static short UnpackS15(short u15) + { + int sign = (u15 >> 14) & 1; + u15 &= 0x3FFF; + if (sign == 0) u15 -= 0x4000; + return u15; + } + + static int[][] QUATERNION_SWIZZLES = { + new int[] { 0, 3, 2, 1 }, new int[] { 3, 0, 2, 1 }, + new int[] { 3, 2, 0, 1 }, new int[] { 3, 2, 1, 0 } + }; + + private static Quaternion PackedToQuat(short z, short y, short x) + { + + const int count = 15; + const int BASE = (1 << count) - 1; + float maxval = 1 / (0x399E * (float)Math.Sqrt(2.0)); // such obvious, so constant, wow + + long cq = x & 0xFFFF; + cq <<= 16; + cq |= ((uint)y) & 0xFFFF; + cq <<= 16; + cq |= ((uint)z) & 0xFFFF; + + + short extra = (short)(cq & 0x7); + + long num = cq >> 3; + + x = UnpackS15((short)((num >> (count * 2)) & BASE)); + y = UnpackS15((short)((num >> (count * 1)) & BASE)); + z = UnpackS15((short)((num >> (count * 0)) & BASE)); + + float fx = x * maxval; + float fy = y * maxval; + float fz = z * maxval; + + float[] quat = { + (float)Math.Sqrt(1 - fx * fx - fy * fy - fz * fz), + fx, + fy, + fz }; + + int[] qmap = QUATERNION_SWIZZLES[(extra & 3)]; + Quaternion q = new Quaternion(quat[qmap[0]], quat[qmap[1]], quat[qmap[2]], quat[qmap[3]]); + if ((extra >> 2) != 0) q *= -1; + + return q; + + } + + public static Quaternion EulerToQuat(float z, float y, float x) + { + Quaternion xRotation = Quaternion.FromAxisAngle(Vector3.UnitX, x); + Quaternion yRotation = Quaternion.FromAxisAngle(Vector3.UnitY, y); + Quaternion zRotation = Quaternion.FromAxisAngle(Vector3.UnitZ, z); + return (zRotation * yRotation * xRotation); + } + + public void LoadBoneGroup(Gfbanim.Bone boneAnim) + { + BoneGroup groupAnim = new BoneGroup(); + groupAnim.Name = boneAnim.Name; + AnimGroups.Add(groupAnim); + + //Tracks use 3 types + // Fixed/constant + // Dynamic (baked and multiple keys, no frames) + // Framed (multiple keys and frames) + + List Frames = new List(); + + switch (boneAnim.RotateType) + { + case Gfbanim.QuatTrack.DynamicQuatTrack: + { + var rotate = boneAnim.Rotate(); + if (rotate.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadRotationTrack(rotate.Value); + groupAnim.RotationX = values[0]; + groupAnim.RotationY = values[1]; + groupAnim.RotationZ = values[2]; + } + } break; - case Gfbanim.QuatTrack.FramedQuatTrack16: - { - var rotate = boneAnim.Rotate(); - if (rotate.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadRotationTrack(rotate.Value); - groupAnim.RotationX = values[0]; - groupAnim.RotationY = values[1]; - groupAnim.RotationZ = values[2]; - } - } + case Gfbanim.QuatTrack.FixedQuatTrack: + { + var rotate = boneAnim.Rotate(); + if (rotate.HasValue) + { + var vec = rotate.Value.Value.Value; + groupAnim.RotationX.KeyFrames.Add(new STKeyFrame(0, GfbanimKeyFrameLoader.ConvertRotation(vec.X))); + groupAnim.RotationY.KeyFrames.Add(new STKeyFrame(0, GfbanimKeyFrameLoader.ConvertRotation(vec.Y))); + groupAnim.RotationZ.KeyFrames.Add(new STKeyFrame(0, GfbanimKeyFrameLoader.ConvertRotation(vec.Z))); + } + } break; - case Gfbanim.QuatTrack.FramedQuatTrack8: - { - var rotate = boneAnim.Rotate(); - if (rotate.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadRotationTrack(rotate.Value); - groupAnim.RotationX = values[0]; - groupAnim.RotationY = values[1]; - groupAnim.RotationZ = values[2]; - } - } - break; - } - switch (boneAnim.ScaleType) - { - case Gfbanim.VectorTrack.DynamicVectorTrack: - { - var scale = boneAnim.Scale(); - if (scale.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadVectorTrack(scale.Value); - groupAnim.ScaleX = values[0]; - groupAnim.ScaleY = values[1]; - groupAnim.ScaleZ = values[2]; - } - } + case Gfbanim.QuatTrack.FramedQuatTrack16: + { + var rotate = boneAnim.Rotate(); + if (rotate.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadRotationTrack(rotate.Value); + groupAnim.RotationX = values[0]; + groupAnim.RotationY = values[1]; + groupAnim.RotationZ = values[2]; + } + } break; - case Gfbanim.VectorTrack.FramedVectorTrack16: - { - var scale = boneAnim.Scale(); - if (scale.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadVectorTrack(scale.Value); - groupAnim.ScaleX = values[0]; - groupAnim.ScaleY = values[1]; - groupAnim.ScaleZ = values[2]; - } - } - break; - case Gfbanim.VectorTrack.FramedVectorTrack8: - { - var scale = boneAnim.Scale(); - if (scale.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadVectorTrack(scale.Value); - groupAnim.ScaleX = values[0]; - groupAnim.ScaleY = values[1]; - groupAnim.ScaleZ = values[2]; - } - } - break; - case Gfbanim.VectorTrack.FixedVectorTrack: - { - var scale = boneAnim.Scale(); - if (scale.HasValue) - { - var vec = scale.Value.Value.Value; - groupAnim.ScaleX.KeyFrames.Add(new STKeyFrame(0, vec.X)); - groupAnim.ScaleY.KeyFrames.Add(new STKeyFrame(0, vec.Y)); - groupAnim.ScaleZ.KeyFrames.Add(new STKeyFrame(0, vec.Z)); - } - } - break; - } - switch (boneAnim.TranslateType) - { - case Gfbanim.VectorTrack.DynamicVectorTrack: - { - var trans = boneAnim.Translate(); - if (trans.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadVectorTrack(trans.Value); - groupAnim.TranslateX = values[0]; - groupAnim.TranslateY = values[1]; - groupAnim.TranslateZ = values[2]; - } - } - break; - case Gfbanim.VectorTrack.FramedVectorTrack16: - { - var trans = boneAnim.Translate(); - if (trans.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadVectorTrack(trans.Value); - groupAnim.TranslateX = values[0]; - groupAnim.TranslateY = values[1]; - groupAnim.TranslateZ = values[2]; - } - } + case Gfbanim.QuatTrack.FramedQuatTrack8: + { + var rotate = boneAnim.Rotate(); + if (rotate.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadRotationTrack(rotate.Value); + groupAnim.RotationX = values[0]; + groupAnim.RotationY = values[1]; + groupAnim.RotationZ = values[2]; + } + } break; - case Gfbanim.VectorTrack.FramedVectorTrack8: - { - var trans = boneAnim.Translate(); - if (trans.HasValue) - { - var values = GfbanimKeyFrameLoader.LoadVectorTrack(trans.Value); - groupAnim.TranslateX = values[0]; - groupAnim.TranslateY = values[1]; - groupAnim.TranslateZ = values[2]; - } - } - break; - case Gfbanim.VectorTrack.FixedVectorTrack: - { - var trans = boneAnim.Translate(); - if (trans.HasValue) - { - var vec = trans.Value.Value.Value; - groupAnim.TranslateX.KeyFrames.Add(new STKeyFrame(0, vec.X)); - groupAnim.TranslateY.KeyFrames.Add(new STKeyFrame(0, vec.Y)); - groupAnim.TranslateZ.KeyFrames.Add(new STKeyFrame(0, vec.Z)); - } - } - break; - } - } - - public void LoadMaterialGroup(Gfbanim.Material matAnim) - { - for (int i = 0; i < matAnim.SwitchesLength; i++) - { - var switchTrack = matAnim.Switches(i).Value; - - } - for (int i = 0; i < matAnim.ValuesLength; i++) - { - var valueTrack = matAnim.Values(i).Value; - - } - for (int i = 0; i < matAnim.VectorsLength; i++) - { - var vectorTrack = matAnim.Vectors(i).Value; - - } - } - - public void LoadVisibilyGroup(Gfbanim.Group visAnim) - { - VisibiltyGroup groupAnim = new VisibiltyGroup(); - groupAnim.Name = visAnim.Name; - AnimGroups.Add(groupAnim); - - if (visAnim.ValueType == Gfbanim.BooleanTrack.FixedBooleanTrack) { - var track = visAnim.Value(); - if (track.HasValue) - { - var animTrack = new STAnimationTrack(); - animTrack.KeyFrames.Add(new STKeyFrame(0, track.Value.Value)); - groupAnim.BooleanTrack = animTrack; - } - } - else if (visAnim.ValueType == Gfbanim.BooleanTrack.DynamicBooleanTrack) { - var track = visAnim.Value(); - if (track.HasValue) { - groupAnim.BooleanTrack = GfbanimKeyFrameLoader.LoadBooleanTrack(track.Value); - } - } - else if(visAnim.ValueType == Gfbanim.BooleanTrack.FramedBooleanTrack) { - var track = visAnim.Value(); - if (track.HasValue) - { - groupAnim.BooleanTrack = GfbanimKeyFrameLoader.LoadBooleanTrack(track.Value); - } - } - } - - public void LoadTriggerGroup(Gfbanim.Trigger triggerAnim) - { - - } - - private STAnimationTrack LoadTrack(float[] Frames, float[] Values) - { - STAnimationTrack track = new STAnimationTrack(); - track.InterpolationType = STInterpoaltionType.Linear; - for (int i = 0; i < Values?.Length; i++) - { - STKeyFrame keyFrame = new STKeyFrame(); - keyFrame.Value = Values[i]; - keyFrame.Value = Frames[i]; - track.KeyFrames.Add(keyFrame); - } - return track; - } - } - - public class BoneGroup : STAnimGroup - { - public STAnimationTrack TranslateX = new STAnimationTrack(); - public STAnimationTrack TranslateY = new STAnimationTrack(); - public STAnimationTrack TranslateZ = new STAnimationTrack(); - - public STAnimationTrack RotationX = new STAnimationTrack(); - public STAnimationTrack RotationY = new STAnimationTrack(); - public STAnimationTrack RotationZ = new STAnimationTrack(); - public STAnimationTrack RotationW = new STAnimationTrack(); - - public STAnimationTrack ScaleX = new STAnimationTrack(); - public STAnimationTrack ScaleY = new STAnimationTrack(); - public STAnimationTrack ScaleZ = new STAnimationTrack(); - - public override List GetTracks() - { - List anims = new List(); - anims.Add(TranslateX); anims.Add(TranslateY); anims.Add(TranslateZ); - anims.Add(RotationX); anims.Add(RotationY); anims.Add(RotationZ); - anims.Add(ScaleX); anims.Add(ScaleY); anims.Add(ScaleZ); - return anims; - } - } - - public class MaterialGroup : STAnimGroup - { - - } - - public class MaterialSwitchGroup : STAnimGroup - { - public STAnimationTrack SwitchTrack = new STAnimationTrack(); - - public override List GetTracks() { - return new List() { SwitchTrack }; - } - } - - public class MaterialValueGroup : STAnimGroup - { - public STAnimationTrack ValueTrack = new STAnimationTrack(); - - public override List GetTracks() { - return new List() { ValueTrack }; - } - } - - public class MaterialVectorGroup : STAnimGroup - { - public STAnimationTrack VectorX = new STAnimationTrack(); - public STAnimationTrack VectorY = new STAnimationTrack(); - public STAnimationTrack VectorZ = new STAnimationTrack(); - - public override List GetTracks() - { - return new List() - { VectorX, VectorY, VectorZ }; - } - } - - public class VisibiltyGroup : STAnimGroup - { - public STAnimationTrack BooleanTrack = new STAnimationTrack(); - - public override List GetTracks() { - return new List() { BooleanTrack }; - } - } - - public class TriggerGroup : STAnimGroup - { - - } - } -} + } + switch (boneAnim.ScaleType) + { + case Gfbanim.VectorTrack.DynamicVectorTrack: + { + var scale = boneAnim.Scale(); + if (scale.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadVectorTrack(scale.Value); + groupAnim.ScaleX = values[0]; + groupAnim.ScaleY = values[1]; + groupAnim.ScaleZ = values[2]; + } + } + break; + case Gfbanim.VectorTrack.FramedVectorTrack16: + { + var scale = boneAnim.Scale(); + if (scale.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadVectorTrack(scale.Value); + groupAnim.ScaleX = values[0]; + groupAnim.ScaleY = values[1]; + groupAnim.ScaleZ = values[2]; + } + } + break; + case Gfbanim.VectorTrack.FramedVectorTrack8: + { + var scale = boneAnim.Scale(); + if (scale.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadVectorTrack(scale.Value); + groupAnim.ScaleX = values[0]; + groupAnim.ScaleY = values[1]; + groupAnim.ScaleZ = values[2]; + } + } + break; + case Gfbanim.VectorTrack.FixedVectorTrack: + { + var scale = boneAnim.Scale(); + if (scale.HasValue) + { + var vec = scale.Value.Value.Value; + groupAnim.ScaleX.KeyFrames.Add(new STKeyFrame(0, vec.X)); + groupAnim.ScaleY.KeyFrames.Add(new STKeyFrame(0, vec.Y)); + groupAnim.ScaleZ.KeyFrames.Add(new STKeyFrame(0, vec.Z)); + } + } + break; + } + switch (boneAnim.TranslateType) + { + case Gfbanim.VectorTrack.DynamicVectorTrack: + { + var trans = boneAnim.Translate(); + if (trans.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadVectorTrack(trans.Value); + groupAnim.TranslateX = values[0]; + groupAnim.TranslateY = values[1]; + groupAnim.TranslateZ = values[2]; + } + } + break; + case Gfbanim.VectorTrack.FramedVectorTrack16: + { + var trans = boneAnim.Translate(); + if (trans.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadVectorTrack(trans.Value); + groupAnim.TranslateX = values[0]; + groupAnim.TranslateY = values[1]; + groupAnim.TranslateZ = values[2]; + } + } + break; + case Gfbanim.VectorTrack.FramedVectorTrack8: + { + var trans = boneAnim.Translate(); + if (trans.HasValue) + { + var values = GfbanimKeyFrameLoader.LoadVectorTrack(trans.Value); + groupAnim.TranslateX = values[0]; + groupAnim.TranslateY = values[1]; + groupAnim.TranslateZ = values[2]; + } + } + break; + case Gfbanim.VectorTrack.FixedVectorTrack: + { + var trans = boneAnim.Translate(); + if (trans.HasValue) + { + var vec = trans.Value.Value.Value; + groupAnim.TranslateX.KeyFrames.Add(new STKeyFrame(0, vec.X)); + groupAnim.TranslateY.KeyFrames.Add(new STKeyFrame(0, vec.Y)); + groupAnim.TranslateZ.KeyFrames.Add(new STKeyFrame(0, vec.Z)); + } + } + break; + } + } + + public void LoadMaterialGroup(Gfbanim.Material matAnim) + { + for (int i = 0; i < matAnim.SwitchesLength; i++) + { + var switchTrack = matAnim.Switches(i).Value; + + } + for (int i = 0; i < matAnim.ValuesLength; i++) + { + var valueTrack = matAnim.Values(i).Value; + + } + for (int i = 0; i < matAnim.VectorsLength; i++) + { + var vectorTrack = matAnim.Vectors(i).Value; + + } + } + + public void LoadVisibilyGroup(Gfbanim.Group visAnim) + { + VisibiltyGroup groupAnim = new VisibiltyGroup(); + groupAnim.Name = visAnim.Name; + AnimGroups.Add(groupAnim); + + if (visAnim.ValueType == Gfbanim.BooleanTrack.FixedBooleanTrack) { + var track = visAnim.Value(); + if (track.HasValue) + { + var animTrack = new STAnimationTrack(); + animTrack.KeyFrames.Add(new STKeyFrame(0, track.Value.Value)); + groupAnim.BooleanTrack = animTrack; + } + } + else if (visAnim.ValueType == Gfbanim.BooleanTrack.DynamicBooleanTrack) { + var track = visAnim.Value(); + if (track.HasValue) { + groupAnim.BooleanTrack = GfbanimKeyFrameLoader.LoadBooleanTrack(track.Value); + } + } + else if(visAnim.ValueType == Gfbanim.BooleanTrack.FramedBooleanTrack) { + var track = visAnim.Value(); + if (track.HasValue) + { + groupAnim.BooleanTrack = GfbanimKeyFrameLoader.LoadBooleanTrack(track.Value); + } + } + } + + public void LoadTriggerGroup(Gfbanim.Trigger triggerAnim) + { + + } + + private STAnimationTrack LoadTrack(float[] Frames, float[] Values) + { + STAnimationTrack track = new STAnimationTrack(); + track.InterpolationType = STInterpoaltionType.Linear; + for (int i = 0; i < Values?.Length; i++) + { + STKeyFrame keyFrame = new STKeyFrame(); + keyFrame.Value = Values[i]; + keyFrame.Value = Frames[i]; + track.KeyFrames.Add(keyFrame); + } + return track; + } + } + + public class BoneGroup : STAnimGroup + { + public STAnimationTrack TranslateX = new STAnimationTrack(); + public STAnimationTrack TranslateY = new STAnimationTrack(); + public STAnimationTrack TranslateZ = new STAnimationTrack(); + + public STAnimationTrack RotationX = new STAnimationTrack(); + public STAnimationTrack RotationY = new STAnimationTrack(); + public STAnimationTrack RotationZ = new STAnimationTrack(); + public STAnimationTrack RotationW = new STAnimationTrack(); + + public STAnimationTrack ScaleX = new STAnimationTrack(); + public STAnimationTrack ScaleY = new STAnimationTrack(); + public STAnimationTrack ScaleZ = new STAnimationTrack(); + + public override List GetTracks() + { + List anims = new List(); + anims.Add(TranslateX); anims.Add(TranslateY); anims.Add(TranslateZ); + anims.Add(RotationX); anims.Add(RotationY); anims.Add(RotationZ); + anims.Add(ScaleX); anims.Add(ScaleY); anims.Add(ScaleZ); + return anims; + } + } + + public class MaterialGroup : STAnimGroup + { + + } + + public class MaterialSwitchGroup : STAnimGroup + { + public STAnimationTrack SwitchTrack = new STAnimationTrack(); + + public override List GetTracks() { + return new List() { SwitchTrack }; + } + } + + public class MaterialValueGroup : STAnimGroup + { + public STAnimationTrack ValueTrack = new STAnimationTrack(); + + public override List GetTracks() { + return new List() { ValueTrack }; + } + } + + public class MaterialVectorGroup : STAnimGroup + { + public STAnimationTrack VectorX = new STAnimationTrack(); + public STAnimationTrack VectorY = new STAnimationTrack(); + public STAnimationTrack VectorZ = new STAnimationTrack(); + + public override List GetTracks() + { + return new List() + { VectorX, VectorY, VectorZ }; + } + } + + public class VisibiltyGroup : STAnimGroup + { + public STAnimationTrack BooleanTrack = new STAnimationTrack(); + + public override List GetTracks() { + return new List() { BooleanTrack }; + } + } + + public class TriggerGroup : STAnimGroup + { + + } + } +} diff --git a/Switch_Toolbox_Library/Compression/Formats/LZSS.cs b/Switch_Toolbox_Library/Compression/Formats/LZSS.cs index d2d274e2..4722b2dd 100644 --- a/Switch_Toolbox_Library/Compression/Formats/LZSS.cs +++ b/Switch_Toolbox_Library/Compression/Formats/LZSS.cs @@ -22,8 +22,7 @@ namespace Toolbox.Library { using (var reader = new FileReader(stream, true)) { - hasMagic = reader.CheckSignature(4, "LzS\x01"); - return hasMagic || Utils.GetExtension(fileName) == ".lzs"; + return reader.CheckSignature(4, "LzS\x01"); } }