Files
PCK-Studio/PckStudio.ModelSupport/Format/Internal/PSM/PSMFileWriter.cs
2026-02-15 08:04:50 -05:00

135 lines
4.4 KiB
C#

using System.IO;
using System.Text;
using PckStudio.Core.FileFormats;
using OMI.Workers;
using OMI;
using System;
using OpenTK;
using PckStudio.Core.Skin;
namespace PckStudio.ModelSupport.Internal.Format
{
internal class PSMFileWriter : IDataFormatWriter
{
PSMFile _PSM;
public PSMFileWriter(PSMFile csmb)
{
_PSM = csmb;
}
public void WriteToFile(string filename)
{
using(var fs = File.OpenWrite(filename))
{
WriteToStream(fs);
}
}
public void WriteToStream(Stream stream)
{
using (var writer = new EndiannessAwareBinaryWriter(stream, Encoding.ASCII, leaveOpen: true, ByteOrder.LittleEndian))
{
writer.WriteString(PSMFile.HEADER_MAGIC);
writer.Write(_PSM.Version);
writer.Write(_PSM.SkinANIM.ToValue());
writer.Write(_PSM.Parts.Count);
foreach (SkinBOX part in _PSM.Parts)
{
WritePart(writer, part);
}
writer.Write(_PSM.Offsets.Count);
foreach (SkinPartOffset offset in _PSM.Offsets)
{
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 PSMParentType GetParentPart(string type)
{
switch (type)
{
case "HEAD":
return PSMParentType.HEAD;
case "BODY":
return PSMParentType.BODY;
case "ARM0":
return PSMParentType.ARM0;
case "ARM1":
return PSMParentType.ARM1;
case "LEG0":
return PSMParentType.LEG0;
case "LEG1":
return PSMParentType.LEG1;
default:
throw new InvalidDataException(type);
}
}
private static PSMOffsetType GetOffsetPart(string type)
{
switch (type)
{
case "HEAD":
return PSMOffsetType.HEAD;
case "BODY":
return PSMOffsetType.BODY;
case "ARM0":
return PSMOffsetType.ARM0;
case "ARM1":
return PSMOffsetType.ARM1;
case "LEG0":
return PSMOffsetType.LEG0;
case "LEG1":
return PSMOffsetType.LEG1;
case "TOOL0":
return PSMOffsetType.TOOL0;
case "TOOL1":
return PSMOffsetType.TOOL1;
case "HELMET":
return PSMOffsetType.HELMET;
case "SHOULDER0":
return PSMOffsetType.SHOULDER0;
case "SHOULDER1":
return PSMOffsetType.SHOULDER1;
case "CHEST":
return PSMOffsetType.CHEST;
case "WAIST":
return PSMOffsetType.WAIST;
case "PANTS0":
return PSMOffsetType.PANTS0;
case "PANTS1":
return PSMOffsetType.PANTS1;
case "BOOT0":
return PSMOffsetType.BOOT0;
case "BOOT1":
return PSMOffsetType.BOOT1;
default:
throw new InvalidDataException(type);
}
}
}
}