/// <summary> /// Reads the data out of the given track. /// </summary> /// <param name="track"></param> /// <returns></returns> public object[] ReadTrack(AnimTrack track) { //Console.WriteLine(Track.Name + " " + Track.Flags.ToString("X") + " " + Track.FrameCount + " " + Track.DataOffset.ToString("X")); List <object> output = new List <object>(); using (SsbhParser parser = new SsbhParser(new MemoryStream(animFile.Buffer))) { parser.Seek(track.DataOffset); if (CheckFlag(track.Flags, 0xFF00, AnimTrackFlags.Constant)) { output.Add(ReadDirect(parser, track.Flags)); } if (CheckFlag(track.Flags, 0xFF00, AnimTrackFlags.ConstTransform)) { // TODO: investigate more output.Add(ReadDirect(parser, track.Flags)); } if (CheckFlag(track.Flags, 0xFF00, AnimTrackFlags.Direct)) { for (int i = 0; i < track.FrameCount; i++) { output.Add(ReadDirect(parser, track.Flags)); } } if (CheckFlag(track.Flags, 0xFF00, AnimTrackFlags.Compressed)) { output.AddRange(ReadCompressed(parser, track.Flags)); } } return(output.ToArray()); }
public static Formats.Meshes.MeshAttributeString ParseMeshAttributeString(this SsbhParser parser) { var result = new Formats.Meshes.MeshAttributeString(); result.Name = parser.ReadOffsetReadString(); return(result); }
public static Formats.ModlMaterialName ParseModlMaterialName(this SsbhParser parser) { var result = new Formats.ModlMaterialName(); result.MaterialFileName = parser.ReadOffsetReadString(); return(result); }
public static Formats.Materials.MatlAttribute.MatlString ParseMatlString(this SsbhParser parser) { var result = new Formats.Materials.MatlAttribute.MatlString(); result.Text = parser.ReadOffsetReadString(); return(result); }
public static Formats.Materials.Matl ParseMatl(this SsbhParser parser) { var result = new Formats.Materials.Matl(); result.Magic = parser.ReadUInt32(); result.MajorVersion = parser.ReadInt16(); result.MinorVersion = parser.ReadInt16(); { // TODO: Extract this code to a method? long absoluteOffset = parser.ReadRelativeGetAbsoluteOffset(); long elementCount = parser.ReadInt64(); long previousPosition = parser.Position; parser.Seek(absoluteOffset); result.Entries = new Formats.Materials.MatlEntry[elementCount]; for (int i = 0; i < elementCount; i++) { result.Entries[i] = parser.ParseMatlEntry(); } parser.Seek(previousPosition); } return(result); }
public static Formats.SsbhString ParseSsbhString(this SsbhParser parser) { var result = new Formats.SsbhString(); result.Text = parser.ReadOffsetReadString(); return(result); }
/// <summary> /// Reads the data from a compressed track /// </summary> /// <param name="reader"></param> /// <param name="flags"></param> /// <returns></returns> private object[] ReadCompressed(SsbhParser reader, uint flags) { List <object> output = new List <object>(); uint dataOffset = (uint)reader.BaseStream.Position; SsbhAnimCompressedHeader header = reader.ByteToType <SsbhAnimCompressedHeader>(); if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Boolean)) { ReadBooleans(reader, output, dataOffset, header); } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Texture)) { // TODO: What type is this } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Float)) { //TODO: What type is this } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.PatternIndex)) { //TODO: What type is this } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Vector4)) { ReadVector4(reader, output, dataOffset, header); } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Transform)) { ReadTransform(reader, output, dataOffset, header); } return(output.ToArray()); }
public static Formats.HlpbRotateAim ParseHlpbRotateAim(this SsbhParser parser) { var result = new Formats.HlpbRotateAim(); result.Name = parser.ReadOffsetReadString(); result.AimBoneName1 = parser.ReadOffsetReadString(); result.AimBoneName2 = parser.ReadOffsetReadString(); result.AimType1 = parser.ReadOffsetReadString(); result.AimType2 = parser.ReadOffsetReadString(); result.TargetBoneName1 = parser.ReadOffsetReadString(); result.TargetBoneName2 = parser.ReadOffsetReadString(); result.Unknown1 = parser.ReadInt32(); result.Unknown2 = parser.ReadInt32(); result.Unknown3 = parser.ReadSingle(); result.Unknown4 = parser.ReadSingle(); result.Unknown5 = parser.ReadSingle(); result.Unknown6 = parser.ReadSingle(); result.Unknown7 = parser.ReadSingle(); result.Unknown8 = parser.ReadSingle(); result.Unknown9 = parser.ReadSingle(); result.Unknown10 = parser.ReadSingle(); result.Unknown11 = parser.ReadSingle(); result.Unknown12 = parser.ReadSingle(); result.Unknown13 = parser.ReadSingle(); result.Unknown14 = parser.ReadSingle(); result.Unknown15 = parser.ReadSingle(); result.Unknown16 = parser.ReadSingle(); result.Unknown17 = parser.ReadSingle(); result.Unknown18 = parser.ReadSingle(); result.Unknown19 = parser.ReadSingle(); result.Unknown20 = parser.ReadSingle(); result.Unknown21 = parser.ReadSingle(); result.Unknown22 = parser.ReadSingle(); return(result); }
public static Formats.HlpbRotateInterpolation ParseHlpbRotateInterpolation(this SsbhParser parser) { var result = new Formats.HlpbRotateInterpolation(); result.Name = parser.ReadOffsetReadString(); result.BoneName = parser.ReadOffsetReadString(); result.RootBoneName = parser.ReadOffsetReadString(); result.ParentBoneName = parser.ReadOffsetReadString(); result.DriverBoneName = parser.ReadOffsetReadString(); result.Type = parser.ReadUInt32(); result.AoIx = parser.ReadSingle(); result.AoIy = parser.ReadSingle(); result.AoIz = parser.ReadSingle(); result.Quat1X = parser.ReadSingle(); result.Quat1Y = parser.ReadSingle(); result.Quat1Z = parser.ReadSingle(); result.Quat1W = parser.ReadSingle(); result.Quat2X = parser.ReadSingle(); result.Quat2Y = parser.ReadSingle(); result.Quat2Z = parser.ReadSingle(); result.Quat2W = parser.ReadSingle(); result.MinRangeX = parser.ReadSingle(); result.MinRangeY = parser.ReadSingle(); result.MinRangeZ = parser.ReadSingle(); result.MaxRangeX = parser.ReadSingle(); result.MaxRangeY = parser.ReadSingle(); result.MaxRangeZ = parser.ReadSingle(); return(result); }
public static Formats.Meshes.MeshAttribute ParseMeshAttribute(this SsbhParser parser) { var result = new Formats.Meshes.MeshAttribute(); result.Index = parser.ReadInt32(); result.DataType = (Formats.Meshes.MeshAttribute.AttributeDataType)parser.ReadUInt32(); result.BufferIndex = parser.ReadInt32(); result.BufferOffset = parser.ReadInt32(); result.Unk4 = parser.ReadInt32(); result.Unk5 = parser.ReadInt32(); result.Name = parser.ReadOffsetReadString(); { // TODO: Extract this code to a method? long absoluteOffset = parser.ReadRelativeGetAbsoluteOffset(); long elementCount = parser.ReadInt64(); long previousPosition = parser.Position; parser.Seek(absoluteOffset); result.AttributeStrings = new Formats.SsbhString[elementCount]; for (int i = 0; i < elementCount; i++) { result.AttributeStrings[i] = parser.ParseSsbhString(); } parser.Seek(previousPosition); } return(result); }
public static Formats.Meshes.MeshRiggingGroup ParseMeshRiggingGroup(this SsbhParser parser) { var result = new Formats.Meshes.MeshRiggingGroup(); result.MeshName = parser.ReadOffsetReadString(); result.MeshSubIndex = parser.ReadInt64(); result.Flags = parser.ReadInt64(); { // TODO: Extract this code to a method? long absoluteOffset = parser.ReadRelativeGetAbsoluteOffset(); long elementCount = parser.ReadInt64(); long previousPosition = parser.Position; parser.Seek(absoluteOffset); result.Buffers = new Formats.Meshes.MeshBoneBuffer[elementCount]; for (int i = 0; i < elementCount; i++) { result.Buffers[i] = parser.ParseMeshBoneBuffer(); } parser.Seek(previousPosition); } return(result); }
public static Formats.Meshes.MeshBoneInfluence ParseMeshBoneInfluence(this SsbhParser parser) { var result = new Formats.Meshes.MeshBoneInfluence(); result.VertexIndex = parser.ReadUInt16(); result.Weight = parser.ReadSingle(); return(result); }
/// <summary> /// Tries to parse an SSBH file from a byte array /// </summary> /// <param name="fileData">The file to parse</param> /// <param name="hbssFile">The parsed file result or <c>null</c> if parsing failed</param> /// <returns>true if parsing was successful</returns> public static bool TryParseSsbhFile <T>(byte[] fileData, out T hbssFile) where T : SsbhFile { hbssFile = null; using (var parser = new SsbhParser(new MemoryStream(fileData))) { return(parser.TryParse(out hbssFile)); } }
public static Formats.Rendering.NrpdStateContainer ParseNrpdStateContainer(this SsbhParser parser) { var result = new Formats.Rendering.NrpdStateContainer(); result.StateObject = parser.ParseNrpdSampler(); result.Type = parser.ReadUInt64(); return(result); }
private void ReadTransform(SsbhParser reader, List <object> output, uint dataOffset, SsbhAnimCompressedHeader header) { var decompressed = DecompressTransform(reader, dataOffset, header); foreach (var v in decompressed) { output.Add(v); } }
private void ReadVector4(SsbhParser reader, List <object> output, uint dataOffset, SsbhAnimCompressedHeader header) { var decompressed = DecompressValues(reader, dataOffset, header, 4); foreach (var decom in decompressed) { output.Add(new AnimTrackCustomVector4(decom[0], decom[1], decom[2], decom[3])); } }
public static Formats.Rendering.Nrpd ParseNrpd(this SsbhParser parser) { var result = new Formats.Rendering.Nrpd(); result.Magic = parser.ReadUInt32(); result.MajorVersion = parser.ReadUInt16(); result.MinorVersion = parser.ReadUInt16(); { // TODO: Extract this code to a method? long absoluteOffset = parser.ReadRelativeGetAbsoluteOffset(); long elementCount = parser.ReadInt64(); long previousPosition = parser.Position; parser.Seek(absoluteOffset); result.FrameBufferContainers = new Formats.Rendering.NrpdFrameBufferContainer[elementCount]; for (int i = 0; i < elementCount; i++) { result.FrameBufferContainers[i] = parser.ParseNrpdFrameBufferContainer(); } parser.Seek(previousPosition); } { // TODO: Extract this code to a method? long absoluteOffset = parser.ReadRelativeGetAbsoluteOffset(); long elementCount = parser.ReadInt64(); long previousPosition = parser.Position; parser.Seek(absoluteOffset); result.StateContainers = new Formats.Rendering.NrpdStateContainer[elementCount]; for (int i = 0; i < elementCount; i++) { result.StateContainers[i] = parser.ParseNrpdStateContainer(); } parser.Seek(previousPosition); } { // TODO: Extract this code to a method? long absoluteOffset = parser.ReadRelativeGetAbsoluteOffset(); long elementCount = parser.ReadInt64(); long previousPosition = parser.Position; parser.Seek(absoluteOffset); result.RenderPasses = new Formats.Rendering.NrpdRenderPass[elementCount]; for (int i = 0; i < elementCount; i++) { result.RenderPasses[i] = parser.ParseNrpdRenderPass(); } parser.Seek(previousPosition); } return(result); }
public static Formats.ModlEntry ParseModlEntry(this SsbhParser parser) { var result = new Formats.ModlEntry(); result.MeshName = parser.ReadOffsetReadString(); result.SubIndex = parser.ReadInt64(); result.MaterialLabel = parser.ReadOffsetReadString(); return(result); }
/// <summary> /// Reads direct information from track /// </summary> /// <param name="reader"></param> /// <param name="flags"></param> /// <returns></returns> private object ReadDirect(SsbhParser reader, uint flags) { if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Transform)) { var transform = new AnimTrackTransform() { Sx = reader.ReadSingle(), Sy = reader.ReadSingle(), Sz = reader.ReadSingle(), Rx = reader.ReadSingle(), Ry = reader.ReadSingle(), Rz = reader.ReadSingle(), Rw = reader.ReadSingle(), X = reader.ReadSingle(), Y = reader.ReadSingle(), Z = reader.ReadSingle(), CompensateScale = reader.ReadInt32() }; return(transform); } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Texture)) { return(new AnimTrackTexture() { UnkFloat1 = reader.ReadSingle(), UnkFloat2 = reader.ReadSingle(), UnkFloat3 = reader.ReadSingle(), UnkFloat4 = reader.ReadSingle(), Unknown = reader.ReadInt32() }); } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Float)) { return(reader.ReadSingle()); } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.PatternIndex)) { return(reader.ReadInt32()); } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Boolean)) { return(reader.ReadByte() == 1); } if (CheckFlag(flags, 0x00FF, AnimTrackFlags.Vector4)) { return(new AnimTrackCustomVector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle())); } return(null); }
public static Formats.Materials.MatlAttribute.MatlVector4 ParseMatlVector4(this SsbhParser parser) { var result = new Formats.Materials.MatlAttribute.MatlVector4(); result.X = parser.ReadSingle(); result.Y = parser.ReadSingle(); result.Z = parser.ReadSingle(); result.W = parser.ReadSingle(); return(result); }
public static Formats.SkelBoneEntry ParseSkelBoneEntry(this SsbhParser parser) { var result = new Formats.SkelBoneEntry(); result.Name = parser.ReadOffsetReadString(); result.Id = parser.ReadInt16(); result.ParentId = parser.ReadInt16(); result.Type = parser.ReadInt32(); return(result); }
private static void ReadBooleans(SsbhParser reader, List <object> output, uint dataOffset, SsbhAnimCompressedHeader header) { reader.Seek((int)dataOffset + header.CompressedDataOffset); // note: there is a section for "default" and "compressed items" but they seem to always be 0-ed out for (int i = 0; i < header.FrameCount; i++) { output.Add(reader.ReadBits(header.BitsPerEntry) == 1); } }
private static float[] GetDefaultValues(SsbhParser parser, int valueCount) { float[] defaultValues = new float[valueCount]; for (int i = 0; i < valueCount; i++) { defaultValues[i] = parser.ReadSingle(); } return(defaultValues); }
public static Formats.Rendering.NrpdFrameBuffer ParseNrpdFrameBuffer(this SsbhParser parser) { var result = new Formats.Rendering.NrpdFrameBuffer(); result.Name = parser.ReadOffsetReadString(); result.Width = parser.ReadUInt32(); result.Height = parser.ReadUInt32(); result.Unk1 = parser.ReadUInt64(); result.Unk2 = parser.ReadUInt32(); result.Unk3 = parser.ReadUInt32(); return(result); }
/// <summary> /// Decompresses values in a track /// </summary> /// <param name="parser"></param> /// <param name="dataOffset"></param> /// <param name="header"></param> /// <param name="valueCount"></param> /// <returns></returns> private List <float[]> DecompressValues(SsbhParser parser, uint dataOffset, SsbhAnimCompressedHeader header, int valueCount) { List <float[]> transforms = new List <float[]>(header.FrameCount); // PreProcess SsbhAnimCompressedItem[] items = parser.ByteToType <SsbhAnimCompressedItem>(valueCount); parser.Seek(dataOffset + header.DefaultDataOffset); float[] defaultValues = GetDefaultValues(parser, valueCount); parser.Seek(dataOffset + header.CompressedDataOffset); for (int frameIndex = 0; frameIndex < header.FrameCount; frameIndex++) { // Copy default values. float[] values = new float[valueCount]; for (int i = 0; i < valueCount; i++) { values[i] = defaultValues[i]; } for (int itemIndex = 0; itemIndex < items.Length; itemIndex++) { var item = items[itemIndex]; // Decompress int valueBitCount = (int)item.Count; if (valueBitCount == 0) { continue; } int value = parser.ReadBits(valueBitCount); int scale = 0; for (int k = 0; k < valueBitCount; k++) { scale |= 0x1 << k; } float frameValue = Lerp(item.Start, item.End, 0, 1, value / (float)scale); if (float.IsNaN(frameValue)) { frameValue = 0; } values[itemIndex] = frameValue; } transforms.Add(values); } return(transforms); }
public static Formats.Animation.AnimTrack ParseAnimTrack(this SsbhParser parser) { var result = new Formats.Animation.AnimTrack(); result.Name = parser.ReadOffsetReadString(); result.Flags = parser.ReadUInt32(); result.FrameCount = parser.ReadUInt32(); result.Unk3 = parser.ReadUInt32(); result.DataOffset = parser.ReadUInt32(); result.DataSize = parser.ReadInt64(); return(result); }
public static Formats.Rendering.NrpdRenderPass ParseNrpdRenderPass(this SsbhParser parser) { var result = new Formats.Rendering.NrpdRenderPass(); result.Name = parser.ReadOffsetReadString(); result.Offset2 = parser.ReadUInt64(); result.Type2 = parser.ReadUInt64(); result.Offset3 = parser.ReadUInt64(); result.Type3 = parser.ReadUInt64(); result.UnkString = parser.ReadOffsetReadString(); result.Type4 = parser.ReadUInt64(); result.Padding = parser.ReadUInt64(); return(result); }
public static Formats.Meshes.MeshObject ParseMeshObject(this SsbhParser parser) { var result = new Formats.Meshes.MeshObject(); result.Name = parser.ReadOffsetReadString(); result.SubIndex = parser.ReadInt64(); result.ParentBoneName = parser.ReadOffsetReadString(); result.VertexCount = parser.ReadInt32(); result.IndexCount = parser.ReadInt32(); result.Unk2 = parser.ReadUInt32(); result.VertexOffset = parser.ReadInt32(); result.VertexOffset2 = parser.ReadInt32(); result.FinalBufferOffset = parser.ReadInt32(); result.BufferIndex = parser.ReadInt32(); result.Stride = parser.ReadInt32(); result.Stride2 = parser.ReadInt32(); result.Unk6 = parser.ReadInt32(); result.Unk7 = parser.ReadInt32(); result.ElementOffset = parser.ReadUInt32(); result.Unk8 = parser.ReadInt32(); result.DrawElementType = (Formats.Meshes.DrawElementType)parser.ReadInt32(); result.RiggingType = (Formats.Meshes.RiggingType)parser.ReadInt32(); result.Unk11 = parser.ReadInt32(); result.Unk12 = parser.ReadInt32(); result.BoundingSphereCenter = parser.ReadVector3(); result.BoundingSphereRadius = parser.ReadSingle(); result.BoundingBoxMin = parser.ReadVector3(); result.BoundingBoxMax = parser.ReadVector3(); result.OrientedBoundingBoxCenter = parser.ReadVector3(); result.OrientedBoundingBoxTransform = parser.ReadMatrix3x3(); result.OrientedBoundingBoxSize = parser.ReadVector3(); { // TODO: Extract this code to a method? long absoluteOffset = parser.ReadRelativeGetAbsoluteOffset(); long elementCount = parser.ReadInt64(); long previousPosition = parser.Position; parser.Seek(absoluteOffset); result.Attributes = new Formats.Meshes.MeshAttribute[elementCount]; for (int i = 0; i < elementCount; i++) { result.Attributes[i] = parser.ParseMeshAttribute(); } parser.Seek(previousPosition); } return(result); }
public static Formats.Materials.MatlAttribute ParseMatlAttribute(this SsbhParser parser) { var result = new Formats.Materials.MatlAttribute(); result.ParamId = (Formats.Materials.MatlEnums.ParamId)parser.ReadUInt64(); result.OffsetToData = parser.Position + parser.ReadInt64(); result.DataType = (Formats.Materials.MatlEnums.ParamDataType)parser.ReadUInt64(); // This only needs to be generated for MATL attributes. long temp = parser.Position; result.PostProcess(parser); parser.Seek(temp); return(result); }
public static Formats.Materials.MatlAttribute.MatlSampler ParseMatlSampler(this SsbhParser parser) { var result = new Formats.Materials.MatlAttribute.MatlSampler(); result.WrapS = (Formats.Materials.MatlWrapMode)parser.ReadInt32(); result.WrapT = (Formats.Materials.MatlWrapMode)parser.ReadInt32(); result.WrapR = (Formats.Materials.MatlWrapMode)parser.ReadInt32(); result.MinFilter = (Formats.Materials.MatlMinFilter)parser.ReadInt32(); result.MagFilter = (Formats.Materials.MatlMagFilter)parser.ReadInt32(); result.TextureFilteringType = (Formats.Materials.FilteringType)parser.ReadInt32(); result.BorderColor = parser.ParseMatlVector4(); result.Unk11 = parser.ReadInt32(); result.Unk12 = parser.ReadInt32(); result.LodBias = parser.ReadSingle(); result.MaxAnisotropy = parser.ReadInt32(); return(result); }