From 8b4d4e6cf3a42d5d56297c78b11edc9d344afdf6 Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Fri, 29 Mar 2024 16:35:34 +0100 Subject: [PATCH] Move FileFormats folder into Internal folder --- PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs | 157 ++++++++++++++---- PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs | 116 ++++++++++--- .../Classes/IO/PckAudio/PckAudioFileReader.cs | 2 +- .../Classes/IO/PckAudio/PckAudioFileWriter.cs | 2 +- PCK-Studio/FileFormats/CSMBFile.cs | 92 ---------- PCK-Studio/Forms/Editor/AudioEditor.cs | 2 +- PCK-Studio/Forms/Editor/CustomSkinEditor.cs | 2 +- PCK-Studio/Internal/FileFormats/CSMBFile.cs | 97 +++++++++++ .../FileFormats/PckAudioFile.cs | 4 +- PCK-Studio/MainForm.cs | 5 +- PCK-Studio/PckStudio.csproj | 4 +- 11 files changed, 322 insertions(+), 161 deletions(-) delete mode 100644 PCK-Studio/FileFormats/CSMBFile.cs create mode 100644 PCK-Studio/Internal/FileFormats/CSMBFile.cs rename PCK-Studio/{ => Internal}/FileFormats/PckAudioFile.cs (98%) diff --git a/PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs b/PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs index 9314e618..9ab6a9d1 100644 --- a/PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs +++ b/PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs @@ -1,8 +1,10 @@ -using System.IO; +using System.Diagnostics; +using System.IO; using System.Text; using OMI; using OMI.Workers; -using PckStudio.FileFormats; +using PckStudio.Internal.FileFormats; +using PckStudio.Internal; namespace PckStudio.IO.CSMB { @@ -15,52 +17,135 @@ namespace PckStudio.IO.CSMB using (var fs = File.OpenRead(filename)) { return FromStream(fs); - } + } } throw new FileNotFoundException(filename); } public CSMBFile FromStream(Stream stream) { - CSMBFile csmbFile = new CSMBFile(); - using (var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian)) + using var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian); + + var magic = reader.ReadString(3); + if (magic != CSMBFile.HEADER_MAGIC) { - reader.ReadInt32(); - int numOfParts = reader.ReadInt32(); - for (int i = 0; i < numOfParts; i++) - { - CSMBPart part = new CSMBPart(); - part.Name = ReadString(reader); - part.Parent = (CSMBParentPart)reader.ReadInt32(); - part.posX = reader.ReadSingle(); - part.posY = reader.ReadSingle(); - part.posZ = reader.ReadSingle(); - part.sizeX = reader.ReadSingle(); - part.sizeY = reader.ReadSingle(); - part.sizeZ = reader.ReadSingle(); - part.uvX = reader.ReadInt32(); - part.uvY = reader.ReadInt32(); - part.MirrorTexture = reader.ReadBoolean(); - part.HideWArmour = reader.ReadBoolean(); - part.Inflation = reader.ReadSingle(); - csmbFile.Parts.Add(part); - } - int numOfOffsets = reader.ReadInt32(); - for (int i = 0; i < numOfOffsets; i++) - { - CSMBOffset offset = new CSMBOffset(); - offset.offsetPart = (CSMBOffsetPart)reader.ReadInt32(); - offset.VerticalOffset = reader.ReadSingle(); - csmbFile.Offsets.Add(offset); - } + Trace.TraceError("CSMBFileReader.FromStream - Failed to load csmb.\n\tReason: Header magic mismatch."); + return new CSMBFile(byte.MaxValue); } + + byte version = reader.ReadByte(); + if (version < 1 || version > 1) + { + Trace.TraceError("CSMBFileReader.FromStream - Failed to load csmb.\n\tReason: Unsupported version."); + return new CSMBFile(byte.MaxValue); + } + + var skinANIM = SkinANIM.FromValue(reader.ReadInt32()); + CSMBFile csmbFile = new CSMBFile(version, skinANIM); + int numOfParts = reader.ReadInt32(); + for (int i = 0; i < numOfParts; i++) + { + SkinBOX part = ReadPart(reader); + csmbFile.Parts.Add(part); + } + int numOfOffsets = reader.ReadInt32(); + for (int i = 0; i < numOfOffsets; i++) + { + SkinPartOffset offset = ReadOffset(reader); + csmbFile.Offsets.Add(offset); + } + return csmbFile; } - private string ReadString(EndiannessAwareBinaryReader reader) + private SkinBOX ReadPart(EndiannessAwareBinaryReader reader) { - ushort strlen = reader.ReadUInt16(); - return reader.ReadString(strlen); + string type = GetParentType((CSMBParentType)reader.ReadByte()); + float posX = reader.ReadSingle(); + float posY = reader.ReadSingle(); + float posZ = reader.ReadSingle(); + float sizeX = reader.ReadSingle(); + float sizeY = reader.ReadSingle(); + float sizeZ = reader.ReadSingle(); + byte mirrorAndUvX = reader.ReadByte(); + byte hideWithArmorAndUvY = reader.ReadByte(); + int uvX = mirrorAndUvX & 0x7f; + int uvY = hideWithArmorAndUvY & 0x7f; + bool mirror = (mirrorAndUvX & 0x80) != 0; + bool hideWithArmor = (hideWithArmorAndUvY & 0x80) != 0; + float scale = reader.ReadSingle(); + return new SkinBOX(type, new System.Numerics.Vector3(posX, posY, posZ), new System.Numerics.Vector3(sizeX, sizeY, sizeZ), new System.Numerics.Vector2(uvX, uvY), hideWithArmor, mirror, scale); + } + + private SkinPartOffset ReadOffset(EndiannessAwareBinaryReader reader) + { + CSMBOffsetType type = (CSMBOffsetType)reader.ReadByte(); + float value = reader.ReadSingle(); + return new SkinPartOffset(GetOffsetType(type), value); + } + + private static string GetParentType(CSMBParentType type) + { + switch (type) + { + case CSMBParentType.HEAD: + return "HEAD"; + case CSMBParentType.BODY: + return "BODY"; + case CSMBParentType.ARM0: + return "ARM0"; + case CSMBParentType.ARM1: + return "ARM1"; + case CSMBParentType.LEG0: + return "LEG0"; + case CSMBParentType.LEG1: + return "LEG1"; + default: + throw new InvalidDataException(type.ToString()); + } + } + + private static string GetOffsetType(CSMBOffsetType type) + { + switch (type) + { + case CSMBOffsetType.HEAD: + return "HEAD"; + case CSMBOffsetType.BODY: + return "BODY"; + case CSMBOffsetType.ARM0: + return "ARM0"; + case CSMBOffsetType.ARM1: + return "ARM1"; + case CSMBOffsetType.LEG0: + return "LEG0"; + case CSMBOffsetType.LEG1: + return "LEG1"; + case CSMBOffsetType.TOOL0: + return "TOOL0"; + case CSMBOffsetType.TOOL1: + return "TOOL1"; + case CSMBOffsetType.HELMET: + return "HELMET"; + case CSMBOffsetType.SHOULDER0: + return "SHOULDER0"; + case CSMBOffsetType.SHOULDER1: + return "SHOULDER1"; + case CSMBOffsetType.CHEST: + return "CHEST"; + case CSMBOffsetType.WAIST: + return "WAIST"; + case CSMBOffsetType.PANTS0: + return "PANTS0"; + case CSMBOffsetType.PANTS1: + return "PANTS1"; + case CSMBOffsetType.BOOT0: + return "BOOT0"; + case CSMBOffsetType.BOOT1: + return "BOOT1"; + default: + throw new InvalidDataException(type.ToString()); + } } object IDataFormatReader.FromStream(Stream stream) => FromStream(stream); diff --git a/PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs b/PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs index f7847c7d..2e715cd0 100644 --- a/PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs +++ b/PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs @@ -1,8 +1,11 @@ using System.IO; using System.Text; -using PckStudio.FileFormats; +using PckStudio.Internal.FileFormats; using OMI.Workers; using OMI; +using PckStudio.Internal; +using System; +using OpenTK; namespace PckStudio.IO.CSMB { @@ -27,32 +30,105 @@ namespace PckStudio.IO.CSMB { using (var writer = new EndiannessAwareBinaryWriter(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian)) { - writer.Write(0); + writer.Write(CSMBFile.HEADER_MAGIC); + writer.Write(_CSMB.Version); + writer.Write(_CSMB.SkinANIM.ToValue()); writer.Write(_CSMB.Parts.Count); - foreach (CSMBPart part in _CSMB.Parts) + foreach (SkinBOX part in _CSMB.Parts) { - writer.Write((short)part.Name.Length); - writer.WriteString(part.Name); - writer.Write((int)part.Parent); - writer.Write(part.posX); - writer.Write(part.posY); - writer.Write(part.posZ); - writer.Write(part.sizeX); - writer.Write(part.sizeY); - writer.Write(part.sizeZ); - writer.Write(part.uvX); - writer.Write(part.uvY); - writer.Write(part.MirrorTexture); - writer.Write(part.HideWArmour); - writer.Write(part.Inflation); + WritePart(writer, part); } writer.Write(_CSMB.Offsets.Count); - foreach (CSMBOffset offset in _CSMB.Offsets) + foreach (SkinPartOffset offset in _CSMB.Offsets) { - writer.Write((int)offset.offsetPart); - writer.Write(offset.VerticalOffset); + writer.Write((byte)GetOffsetPart(offset.Type)); + writer.Write(offset.Value); } } } + + private void WritePart(EndiannessAwareBinaryWriter writer, SkinBOX part) + { + writer.Write((byte)GetParentPart(part.Type)); + writer.Write(part.Pos.X); + writer.Write(part.Pos.Y); + writer.Write(part.Pos.Z); + writer.Write(part.Size.X); + writer.Write(part.Size.Y); + writer.Write(part.Size.Z); + + byte uvX = (byte)MathHelper.Clamp((int)part.UV.X, 0, 64); + byte uvY = (byte)MathHelper.Clamp((int)part.UV.Y, 0, 64); + byte mirrorAndUvX = (byte)(Convert.ToByte(part.Mirror) << 7 | uvX); + byte hideWithArmorAndUvY = (byte)(Convert.ToByte(part.HideWithArmor) << 7 | uvY); + + writer.Write(mirrorAndUvX); + writer.Write(hideWithArmorAndUvY); + writer.Write(part.Scale); + } + + private static CSMBParentType GetParentPart(string type) + { + switch (type) + { + case "HEAD": + return CSMBParentType.HEAD; + case "BODY": + return CSMBParentType.BODY; + case "ARM0": + return CSMBParentType.ARM0; + case "ARM1": + return CSMBParentType.ARM1; + case "LEG0": + return CSMBParentType.LEG0; + case "LEG1": + return CSMBParentType.LEG1; + default: + throw new InvalidDataException(type); + } + } + + private static CSMBOffsetType GetOffsetPart(string type) + { + switch (type) + { + case "HEAD": + return CSMBOffsetType.HEAD; + case "BODY": + return CSMBOffsetType.BODY; + case "ARM0": + return CSMBOffsetType.ARM0; + case "ARM1": + return CSMBOffsetType.ARM1; + case "LEG0": + return CSMBOffsetType.LEG0; + case "LEG1": + return CSMBOffsetType.LEG1; + case "TOOL0": + return CSMBOffsetType.TOOL0; + case "TOOL1": + return CSMBOffsetType.TOOL1; + case "HELMET": + return CSMBOffsetType.HELMET; + case "SHOULDER0": + return CSMBOffsetType.SHOULDER0; + case "SHOULDER1": + return CSMBOffsetType.SHOULDER1; + case "CHEST": + return CSMBOffsetType.CHEST; + case "WAIST": + return CSMBOffsetType.WAIST; + case "PANTS0": + return CSMBOffsetType.PANTS0; + case "PANTS1": + return CSMBOffsetType.PANTS1; + case "BOOT0": + return CSMBOffsetType.BOOT0; + case "BOOT1": + return CSMBOffsetType.BOOT1; + default: + throw new InvalidDataException(type); + } + } } } diff --git a/PCK-Studio/Classes/IO/PckAudio/PckAudioFileReader.cs b/PCK-Studio/Classes/IO/PckAudio/PckAudioFileReader.cs index 2e29b2bc..5aa841f4 100644 --- a/PCK-Studio/Classes/IO/PckAudio/PckAudioFileReader.cs +++ b/PCK-Studio/Classes/IO/PckAudio/PckAudioFileReader.cs @@ -1,6 +1,6 @@ using OMI; using OMI.Workers; -using PckStudio.FileFormats; +using PckStudio.Internal.FileFormats; using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/PCK-Studio/Classes/IO/PckAudio/PckAudioFileWriter.cs b/PCK-Studio/Classes/IO/PckAudio/PckAudioFileWriter.cs index 5c62e632..5be2c4b4 100644 --- a/PCK-Studio/Classes/IO/PckAudio/PckAudioFileWriter.cs +++ b/PCK-Studio/Classes/IO/PckAudio/PckAudioFileWriter.cs @@ -1,6 +1,6 @@ using OMI; using OMI.Workers; -using PckStudio.FileFormats; +using PckStudio.Internal.FileFormats; using System.Collections.Generic; using System.IO; using System.Text; diff --git a/PCK-Studio/FileFormats/CSMBFile.cs b/PCK-Studio/FileFormats/CSMBFile.cs deleted file mode 100644 index abd85514..00000000 --- a/PCK-Studio/FileFormats/CSMBFile.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Drawing; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace PckStudio.FileFormats -{ - #region File Structure - /* - Version - 4 bytes[int32] - NumberOfParts - 4 bytes[int32] - { - Part name length - 2 bytes[int16] - part name - x bytes - part parent - 4 bytes[int32] (HEAD=1, BODY=2, LEG0=3, LEG1=4, ARM0=5, ARM1=6) - Position-X - 4 bytes[float] - Position-Y - 4 bytes[float] - Position-Z - 4 bytes[float] - Size-X - 4 bytes[float] - Size-Y - 4 bytes[float] - Size-Z - 4 bytes[float] - UV-Y - 4 bytes[int32] - UV-X - 4 bytes[int32] - mirror texture - 1 byte[bool] - Hide with armour - 1 byte[bool] - inflation/scale value - 4 bytes[float] - } - NumberOfOffsets - 4 bytes[int32] - { - offset part - 4 bytes[int32] - vertical offset - 4 bytes[float] - } - */ - #endregion - class CSMBFile - { - public List Parts = new List(); - public List Offsets = new List(); - } - - public class CSMBPart - { - public string Name = "Partname"; - public CSMBParentPart Parent = 0; - public float posX, posY, posZ = 0.0f; - public float sizeX, sizeY, sizeZ = 0.0f; - public int uvX, uvY = 0; - public bool HideWArmour, MirrorTexture = false; - public float Inflation = 0.0f; - } - public class CSMBOffset - { - public CSMBOffsetPart offsetPart = 0; - public float VerticalOffset = 0.0f; - } - - public enum CSMBOffsetType : byte - { - HEAD = 0, - BODY = 1, - ARM0 = 2, - ARM1 = 3, - LEG0 = 4, - LEG1 = 5, - - TOOL0 = 6, - TOOL1 = 7, - - HELMET = 8, - SHOULDER0 = 9, - SHOULDER1 = 10, - CHEST = 11, - WAIST = 12, - PANTS0 = 13, - PANTS1 = 14, - BOOT0 = 15, - BOOT1 = 16, - } - - public enum CSMBParentPart - { - HEAD = 0, - BODY = 1, - ARM0 = 2, - ARM1 = 3, - LEG0 = 4, - LEG1 = 5, - } -} diff --git a/PCK-Studio/Forms/Editor/AudioEditor.cs b/PCK-Studio/Forms/Editor/AudioEditor.cs index 3ac86ddc..802f6ce3 100644 --- a/PCK-Studio/Forms/Editor/AudioEditor.cs +++ b/PCK-Studio/Forms/Editor/AudioEditor.cs @@ -13,12 +13,12 @@ using NAudio.Wave; using OMI.Formats.Pck; -using PckStudio.FileFormats; using PckStudio.IO.PckAudio; using PckStudio.Forms.Additional_Popups; using PckStudio.Properties; using PckStudio.API.Miles; using PckStudio.Internal; +using PckStudio.Internal.FileFormats; using PckStudio.Extensions; // Audio Editor by MattNL and Miku-666 diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs index cbd165ca..b34b2e84 100644 --- a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs +++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs @@ -10,7 +10,7 @@ using MetroFramework.Forms; using PckStudio.Internal; using PckStudio.Extensions; using PckStudio.IO.CSMB; -using PckStudio.FileFormats; +using PckStudio.Internal.FileFormats; using System.Linq; using PckStudio.Forms.Additional_Popups; diff --git a/PCK-Studio/Internal/FileFormats/CSMBFile.cs b/PCK-Studio/Internal/FileFormats/CSMBFile.cs new file mode 100644 index 00000000..3e08a440 --- /dev/null +++ b/PCK-Studio/Internal/FileFormats/CSMBFile.cs @@ -0,0 +1,97 @@ +using System; +using System.Drawing; +using System.IO; +using System.Collections.Generic; +using System.Linq; + +namespace PckStudio.Internal.FileFormats +{ + #region File Structure +/* + Magic - 8 bytes[uint64] + Version - 1 byte [u8] + Anim - 4 bytes[int32] + NumberOfParts - 4 bytes[int32] + { + part parent - 1 byte (HEAD=0, BODY=1, LEG0=2, LEG1=3, ARM0=4, ARM1=5) + Position-X - 4 bytes (float32) + Position-Y - 4 bytes (float32) + Position-Z - 4 bytes (float32) + Size-X - 4 bytes (float32) + Size-Y - 4 bytes (float32) + Size-Z - 4 bytes (float32) + MirrorAndUvX - 1 bit flag 7 bits uv.x value(0-64) (s8) + HideWithArmorAndUvY - 1 bit flag 7 bits uv.y value(0-64) (s8) + inflation/scale value - 4 bytes (float32) + } + NumberOfOffsets - 4 bytes[int32] + { + offset part - 1 byte + vertical offset - 4 bytes[float] + } +*/ + #endregion + class CSMBFile + { + internal static readonly string HEADER_MAGIC = "psm"; + + public readonly byte Version; + + internal CSMBFile(byte version) + { + Version = version; + } + + internal CSMBFile(byte version, SkinANIM skinANIM) + : this(version) + { + SkinANIM = skinANIM; + } + + public SkinANIM SkinANIM { get; private set; } + public readonly List Parts = new List(); + public readonly List Offsets = new List(); + + public static CSMBFile FromSkin(Skin skin) + { + var csmb = new CSMBFile(1); + csmb.SkinANIM = skin.ANIM; + csmb.Parts.AddRange(skin.AdditionalBoxes); + csmb.Offsets.AddRange(skin.PartOffsets); + return csmb; + } + } + + public enum CSMBOffsetType : byte + { + HEAD = 0, + BODY = 1, + ARM0 = 2, + ARM1 = 3, + LEG0 = 4, + LEG1 = 5, + + TOOL0 = 6, + TOOL1 = 7, + + HELMET = 8, + SHOULDER0 = 9, + SHOULDER1 = 10, + CHEST = 11, + WAIST = 12, + PANTS0 = 13, + PANTS1 = 14, + BOOT0 = 15, + BOOT1 = 16, + } + + public enum CSMBParentType : byte + { + HEAD = 0, + BODY = 1, + ARM0 = 2, + ARM1 = 3, + LEG0 = 4, + LEG1 = 5, + } +} diff --git a/PCK-Studio/FileFormats/PckAudioFile.cs b/PCK-Studio/Internal/FileFormats/PckAudioFile.cs similarity index 98% rename from PCK-Studio/FileFormats/PckAudioFile.cs rename to PCK-Studio/Internal/FileFormats/PckAudioFile.cs index 0ceb6608..8aa0312c 100644 --- a/PCK-Studio/FileFormats/PckAudioFile.cs +++ b/PCK-Studio/Internal/FileFormats/PckAudioFile.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using OMI.Formats.Languages; -namespace PckStudio.FileFormats +namespace PckStudio.Internal.FileFormats { public class PckAudioFile { diff --git a/PCK-Studio/MainForm.cs b/PCK-Studio/MainForm.cs index 3dd1cbcd..211011dd 100644 --- a/PCK-Studio/MainForm.cs +++ b/PCK-Studio/MainForm.cs @@ -7,16 +7,14 @@ using System.Windows.Forms; using System.Drawing.Drawing2D; using System.Diagnostics; using System.Drawing.Imaging; -using OMI.Formats.Archive; using OMI.Formats.Pck; using OMI.Formats.GameRule; using OMI.Formats.Languages; -using OMI.Workers.Archive; using OMI.Workers.Pck; using OMI.Workers.GameRule; using OMI.Workers.Language; using PckStudio.Properties; -using PckStudio.FileFormats; +using PckStudio.Internal.FileFormats; using PckStudio.Forms; using PckStudio.Forms.Editor; using PckStudio.Forms.Additional_Popups.Animation; @@ -30,7 +28,6 @@ using PckStudio.Extensions; using PckStudio.Popups; using PckStudio.Classes.Utils; using PckStudio.Helper; -using PCKStudio_Updater; namespace PckStudio { diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 79ba0344..4c693dd1 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -233,8 +233,8 @@ - - + +