diff --git a/PCK-Studio/Classes/Conversion/Legacy/LegacySkinExporter.cs b/PCK-Studio/Classes/Conversion/Legacy/LegacySkinExporter.cs index f63676fd..8b1c5eec 100644 --- a/PCK-Studio/Classes/Conversion/Legacy/LegacySkinExporter.cs +++ b/PCK-Studio/Classes/Conversion/Legacy/LegacySkinExporter.cs @@ -10,7 +10,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OMI.Formats.Pck; using PckStudio.Classes.Conversion.Legacy.JsonDefinitions; -using PckStudio.Classes.Extentions; +using PckStudio.Extensions; using PckStudio.Conversion.Common.JsonDefinitions; namespace PckStudio.Conversion.Legacy diff --git a/PCK-Studio/Classes/Extensions/BlendMode.cs b/PCK-Studio/Classes/Extensions/BlendMode.cs new file mode 100644 index 00000000..7fb02709 --- /dev/null +++ b/PCK-Studio/Classes/Extensions/BlendMode.cs @@ -0,0 +1,13 @@ +namespace PckStudio.Extensions +{ + public enum BlendMode + { + Add, + Subtract, + Multiply, + Average, + DescendingOrder, + AscendingOrder, + Screen + } +} \ No newline at end of file diff --git a/PCK-Studio/Classes/Extentions/EnumerableExtentions.cs b/PCK-Studio/Classes/Extensions/EnumerableExtensions.cs similarity index 79% rename from PCK-Studio/Classes/Extentions/EnumerableExtentions.cs rename to PCK-Studio/Classes/Extensions/EnumerableExtensions.cs index cda71bba..ed95e29f 100644 --- a/PCK-Studio/Classes/Extentions/EnumerableExtentions.cs +++ b/PCK-Studio/Classes/Extensions/EnumerableExtensions.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -namespace PckStudio.Classes.Extentions +namespace PckStudio.Extensions { - internal static class EnumerableExtentions + internal static class EnumerableExtensions { public static IEnumerable<(int index, T type)>enumerate(this IEnumerable array) { diff --git a/PCK-Studio/Classes/Extensions/GraphicsExtensions.cs b/PCK-Studio/Classes/Extensions/GraphicsExtensions.cs new file mode 100644 index 00000000..22f7885d --- /dev/null +++ b/PCK-Studio/Classes/Extensions/GraphicsExtensions.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Text; + +namespace PckStudio.Extensions +{ + public struct GraphicsConfig + { + public GraphicsConfig() + { + CompositingQuality = CompositingQuality.Default; + InterpolationMode = InterpolationMode.Default; + SmoothingMode = SmoothingMode.Default; + PixelOffsetMode = PixelOffsetMode.Default; + CompositingMode = CompositingMode.SourceOver; + } + + public CompositingMode CompositingMode { get; set; } + public CompositingQuality CompositingQuality { get; set; } + public InterpolationMode InterpolationMode { get; set; } + public SmoothingMode SmoothingMode { get; set; } + public PixelOffsetMode PixelOffsetMode { get; set; } + } + + internal static class GraphicsExtensions + { + public static void ApplyConfig(this Graphics graphics, GraphicsConfig config) + { + graphics.CompositingMode = config.CompositingMode; + graphics.CompositingQuality = config.CompositingQuality; + graphics.InterpolationMode = config.InterpolationMode; + graphics.SmoothingMode = config.SmoothingMode; + graphics.PixelOffsetMode = config.PixelOffsetMode; + } + } +} diff --git a/PCK-Studio/Classes/Extensions/ImageExtensions.cs b/PCK-Studio/Classes/Extensions/ImageExtensions.cs new file mode 100644 index 00000000..b2e5a5df --- /dev/null +++ b/PCK-Studio/Classes/Extensions/ImageExtensions.cs @@ -0,0 +1,241 @@ +using System; +using System.Drawing; +using System.Diagnostics; +using System.Drawing.Imaging; +using System.Drawing.Drawing2D; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Linq; + +namespace PckStudio.Extensions +{ + public enum ImageLayoutDirection + { + Horizontal, + Vertical + } + + internal static class ImageExtensions + { + private struct ImageLayoutInfo + { + /// + /// Size of sub section of the image + /// + public readonly Size SectionSize; + public readonly Point SectionPoint; + public readonly Rectangle SectionArea; + + public ImageLayoutInfo(int width, int height, int index, ImageLayoutDirection layoutDirection) + { + bool horizontal = layoutDirection == ImageLayoutDirection.Horizontal; + SectionSize = horizontal ? new Size(width, width) : new Size(height, height); + SectionPoint = horizontal ? new Point(0, index * width) : new Point(index * height, 0); + SectionArea = new Rectangle(SectionPoint, SectionSize); + } + } + + public static Image GetArea(this Image source, Rectangle area) + { + Image tileImage = new Bitmap(area.Width, area.Height); + using (Graphics gfx = Graphics.FromImage(tileImage)) + { + gfx.SmoothingMode = SmoothingMode.None; + gfx.InterpolationMode = InterpolationMode.NearestNeighbor; + gfx.PixelOffsetMode = PixelOffsetMode.HighQuality; + gfx.DrawImage(source, new Rectangle(Point.Empty, area.Size), area, GraphicsUnit.Pixel); + } + return tileImage; + } + + public static IEnumerable CreateImageList(this Image source, Size size) + { + int rowCount = source.Width / size.Width; + int columnCount = source.Height / size.Height; + Debug.WriteLine($"{source.Width} {source.Height} {size} {columnCount} {rowCount}"); + for (int i = 0; i < columnCount * rowCount; i++) + { + int row = Math.DivRem(i, rowCount, out int column); + Rectangle tileArea = new Rectangle(new Point(column * size.Height, row * size.Width), size); + yield return source.GetArea(tileArea); + } + yield break; + } + + public static IEnumerable CreateImageList(this Image source, int scalar) + { + return CreateImageList(source, new Size(scalar, scalar)); + } + + public static IEnumerable CreateImageList(this Image source, ImageLayoutDirection layoutDirection) + { + for (int i = 0; i < source.Height / source.Width; i++) + { + ImageLayoutInfo locationInfo = new ImageLayoutInfo(source.Width, source.Height, i, layoutDirection); + yield return source.GetArea(locationInfo.SectionArea); + } + yield break; + } + + public static Image ImageFromImageArray(Image[] sources, ImageLayoutDirection layoutDirection) + { + Size imageSize = CalculateImageSize(sources, layoutDirection); + var result = new Bitmap(imageSize.Width, imageSize.Height); + + using (var graphic = Graphics.FromImage(result)) + { + foreach (var (i, texture) in sources.enumerate()) + { + var info = new ImageLayoutInfo(imageSize.Width, imageSize.Height, i, layoutDirection); + graphic.DrawImage(texture, info.SectionPoint); + }; + } + return result; + } + + private static Size CalculateImageSize(Image[] sources, ImageLayoutDirection layoutDirection) + { + var horizontal = layoutDirection == ImageLayoutDirection.Horizontal; + + int width = sources[0].Width; + int height = sources[0].Height; + if (!sources.All(img => img.Width.Equals(width) && img.Height.Equals(height))) + throw new InvalidOperationException("Images must have the same width and height."); + + if (horizontal) + width *= sources.Length; + else + height *= sources.Length; + + return new Size(width, height); + } + + public static Image ResizeImage(this Image image, int width, int height, GraphicsConfig graphicsConfig) + { + var destRect = new Rectangle(0, 0, width, height); + var destImage = new Bitmap(width, height); + + destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); + + using (var graphics = Graphics.FromImage(destImage)) + { + graphics.ApplyConfig(graphicsConfig); + using (var wrapMode = new ImageAttributes()) + { + wrapMode.SetWrapMode(WrapMode.TileFlipXY); + graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode); + } + } + return destImage; + } + + public static Image Fill(this Image image, Color color) + { + using (var g = Graphics.FromImage(image)) + { + using (SolidBrush brush = new SolidBrush(color)) + { + g.FillRectangle(brush, new Rectangle(Point.Empty, image.Size)); + } + } + return image; + } + + public static Image Blend(this Image image, Color foregroundColor, BlendMode mode) + { + if (image is not Bitmap baseImage) + return image; + + BitmapData baseImageData = baseImage.LockBits(new Rectangle(Point.Empty, baseImage.Size), + ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); + byte[] baseImageBuffer = new byte[baseImageData.Stride * baseImageData.Height]; + + Marshal.Copy(baseImageData.Scan0, baseImageBuffer, 0, baseImageBuffer.Length); + + float overlayR = foregroundColor.R / 255f; + float overlayG = foregroundColor.G / 255f; + float overlayB = foregroundColor.B / 255f; + + for (int k = 0; k < baseImageBuffer.Length; k += 4) + { + baseImageBuffer[k + 0] = CalculateColorComponentBlendValue(baseImageBuffer[k + 0] / 255f, overlayR, mode); + baseImageBuffer[k + 1] = CalculateColorComponentBlendValue(baseImageBuffer[k + 1] / 255f, overlayG, mode); + baseImageBuffer[k + 2] = CalculateColorComponentBlendValue(baseImageBuffer[k + 2] / 255f, overlayB, mode); + } + + Bitmap bitmapResult = new Bitmap(baseImage.Width, baseImage.Height, PixelFormat.Format32bppArgb); + BitmapData resultImageData = bitmapResult.LockBits(new Rectangle(Point.Empty, bitmapResult.Size), + ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + + Marshal.Copy(baseImageBuffer, 0, resultImageData.Scan0, baseImageBuffer.Length); + + bitmapResult.UnlockBits(resultImageData); + baseImage.UnlockBits(baseImageData); + + return bitmapResult; + } + + public static Image Blend(this Image image, Image overlay, BlendMode mode) + { + if (image is not Bitmap baseImage || overlay is not Bitmap overlayImage || + image.Width != overlay.Width || image.Height != overlay.Height) + return image; + + BitmapData baseImageData = baseImage.LockBits(new Rectangle(Point.Empty, baseImage.Size), + ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); + byte[] baseImageBuffer = new byte[baseImageData.Stride * baseImageData.Height]; + + Marshal.Copy(baseImageData.Scan0, baseImageBuffer, 0, baseImageBuffer.Length); + + BitmapData overlayImageData = overlayImage.LockBits(new Rectangle(Point.Empty, overlayImage.Size), + ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + byte[] overlayImageBuffer = new byte[overlayImageData.Stride * overlayImageData.Height]; + + Marshal.Copy(overlayImageData.Scan0, overlayImageBuffer, 0, overlayImageBuffer.Length); + + for (int k = 0; k < baseImageBuffer.Length && k < overlayImageBuffer.Length; k += 4) + { + baseImageBuffer[k + 0] = CalculateColorComponentBlendValue(baseImageBuffer[k + 0] / 255f, overlayImageBuffer[k + 0] / 255f, mode); + baseImageBuffer[k + 1] = CalculateColorComponentBlendValue(baseImageBuffer[k + 1] / 255f, overlayImageBuffer[k + 1] / 255f, mode); + baseImageBuffer[k + 2] = CalculateColorComponentBlendValue(baseImageBuffer[k + 2] / 255f, overlayImageBuffer[k + 2] / 255f, mode); + } + + Bitmap bitmapResult = new Bitmap(baseImage.Width, baseImage.Height, PixelFormat.Format32bppArgb); + BitmapData resultImageData = bitmapResult.LockBits(new Rectangle(Point.Empty, bitmapResult.Size), + ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + + Marshal.Copy(baseImageBuffer, 0, resultImageData.Scan0, baseImageBuffer.Length); + + bitmapResult.UnlockBits(resultImageData); + baseImage.UnlockBits(baseImageData); + overlayImage.UnlockBits(overlayImageData); + return bitmapResult; + } + + private static T Clamp(T value, T min, T max) where T : IComparable + { + if (value.CompareTo(min) < 0) return min; + else if (value.CompareTo(max) > 0) return max; + else return value; + } + + private static byte CalculateColorComponentBlendValue(float source, float overlay, BlendMode blendType) + { + source = Clamp(source, 0.0f, 1.0f); + overlay = Clamp(overlay, 0.0f, 1.0f); + + float resultValue = blendType switch + { + BlendMode.Add => source + overlay, + BlendMode.Subtract => source - overlay, + BlendMode.Multiply => source * overlay, + BlendMode.Average => (source + overlay) / 2.0f, + BlendMode.AscendingOrder => source > overlay ? overlay : source, + BlendMode.DescendingOrder => source < overlay ? overlay : source, + BlendMode.Screen => 1f - (1f - source)*(1f - overlay), + _ => 0.0f + }; + return (byte)Clamp(resultValue * 255, 0, 255); + } + } +} diff --git a/PCK-Studio/Classes/Utils/ListUtils.cs b/PCK-Studio/Classes/Extensions/ListExtensions.cs similarity index 80% rename from PCK-Studio/Classes/Utils/ListUtils.cs rename to PCK-Studio/Classes/Extensions/ListExtensions.cs index ff200c6b..8ec3b636 100644 --- a/PCK-Studio/Classes/Utils/ListUtils.cs +++ b/PCK-Studio/Classes/Extensions/ListExtensions.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -namespace PckStudio.Forms.Utilities +namespace PckStudio.Extensions { - public static class ListUtils + public static class ListExtensions { public static IList Swap(this IList list, int index1, int index2) { diff --git a/PCK-Studio/Classes/Extentions/ImageExtentions.cs b/PCK-Studio/Classes/Extentions/ImageExtentions.cs deleted file mode 100644 index 6743d1de..00000000 --- a/PCK-Studio/Classes/Extentions/ImageExtentions.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System.Collections.Generic; -using System.Drawing.Drawing2D; -using System.Drawing; -using System.Diagnostics; -using System; -using System.Drawing.Imaging; - -namespace PckStudio.Classes.Extentions -{ - internal static class ImageExtentions - { - public enum ImageLayoutDirection - { - Horizontal, - Vertical - } - - private struct ImageLayoutInfo - { - /// - /// Size of sub section of the image - /// - public Size SectionSize; - public Point SectionPoint; - - public ImageLayoutInfo(int width, int height, int index, ImageLayoutDirection layoutDirection) - { - bool horizontal = layoutDirection == ImageLayoutDirection.Horizontal; - SectionSize = horizontal ? new Size(width, width) : new Size(height, height); - SectionPoint = horizontal ? new Point(0, index * width) : new Point(index * height, 0); - } - } - - private static Image GetTileImage(Image source, Rectangle area, Size size, GraphicsUnit unit = GraphicsUnit.Pixel) - { - Image tileImage = new Bitmap(size.Width, size.Height); - using (Graphics gfx = Graphics.FromImage(tileImage)) - { - gfx.SmoothingMode = SmoothingMode.None; - gfx.InterpolationMode = InterpolationMode.NearestNeighbor; - gfx.PixelOffsetMode = PixelOffsetMode.HighQuality; - gfx.DrawImage(source, new Rectangle(Point.Empty, size), area, unit); - } - return tileImage; - } - - public static IEnumerable CreateImageList(this Image source, Size size) - { - int img_row_count = source.Width / size.Width; - int img_column_count = source.Height / size.Height; - Debug.WriteLine($"{source.Width} {source.Height} {size} {img_column_count} {img_row_count}"); - for (int i = 0; i < img_column_count * img_row_count; i++) - { - int row = i / img_row_count; - int column = i % img_row_count; - Rectangle tileArea = new Rectangle(new Point(column * size.Height, row * size.Width), size); - yield return GetTileImage(source, tileArea, size); - } - yield break; - } - - public static IEnumerable CreateImageList(this Image source, int scalar) - { - return CreateImageList(source, new Size(scalar, scalar)); - } - - public static IEnumerable CreateImageList(this Image source, ImageLayoutDirection layoutDirection) - { - for (int i = 0; i < source.Height / source.Width; i++) - { - ImageLayoutInfo locationInfo = new ImageLayoutInfo(source.Width, source.Height, i, layoutDirection); - Rectangle tileArea = new Rectangle(locationInfo.SectionPoint, locationInfo.SectionSize); - yield return GetTileImage(source, tileArea, locationInfo.SectionSize); - } - yield break; - } - - public static Image ImageFromImageArray(Image[] sources, ImageLayoutDirection layoutDirection) - { - Size imageSize = CalculateImageSize(sources, layoutDirection); - var result = new Bitmap(imageSize.Width, imageSize.Height); - - using (var graphic = Graphics.FromImage(result)) - { - foreach (var (i, texture) in sources.enumerate()) - { - var info = new ImageLayoutInfo(imageSize.Width, imageSize.Height, i, layoutDirection); - graphic.DrawImage(texture, info.SectionPoint); - }; - } - return result; - } - - private static Size CalculateImageSize(Image[] sources, ImageLayoutDirection layoutDirection) - { - var horizontal = layoutDirection == ImageLayoutDirection.Horizontal; - - // TODO: Validate all source images to be the same size. - int width = sources[0].Width; - int heigh = sources[0].Height; - - if (horizontal) - width *= sources.Length; - else - heigh *= sources.Length; - - return new Size(width, heigh); - } - - public struct GraphicsConfig - { - public CompositingMode CompositingMode { get; set; } - public CompositingQuality CompositingQuality { get; set; } - public InterpolationMode InterpolationMode { get; set; } - public SmoothingMode SmoothingMode {get; set; } - public PixelOffsetMode PixelOffsetMode { get; set; } - } - - public static Image ResizeImage(this Image image, int width, int height, GraphicsConfig graphicsConfig) - { - var destRect = new Rectangle(0, 0, width, height); - var destImage = new Bitmap(width, height); - - destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); - - using (var graphics = Graphics.FromImage(destImage)) - { - graphics.CompositingMode = graphicsConfig.CompositingMode; - graphics.CompositingQuality = graphicsConfig.CompositingQuality; - graphics.InterpolationMode = graphicsConfig.InterpolationMode; - graphics.SmoothingMode = graphicsConfig.SmoothingMode; - graphics.PixelOffsetMode = graphicsConfig.PixelOffsetMode; - - using (var wrapMode = new ImageAttributes()) - { - wrapMode.SetWrapMode(WrapMode.TileFlipXY); - graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode); - } - } - return destImage; - } - } -} diff --git a/PCK-Studio/Classes/FileTypes/CSM.cs b/PCK-Studio/Classes/FileTypes/CSM.cs deleted file mode 100644 index 5c8e27ff..00000000 --- a/PCK-Studio/Classes/FileTypes/CSM.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Drawing; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using PckStudio.Models; - -namespace PckStudio.Classes -{ - class CSM - { - - //Part Name - //Part Parent(HEAD, BODY, LEG0, LEG1, ARM0, ARM1) - //Part Name - //Position-X - //Position-Y - //Position-Z - //Size-X - //Size-Y - //Size-Z - //UV-Y - //UV-X - - public static List CSMBlock = new List(); - - public static void TryParse(string CSM, MinecraftModelView modelView) - { - try - { - int i = 0; - string[] CSMLines = CSM.Split(new[] { "\n", "\r\n" }, StringSplitOptions.None); - foreach (string line in CSMLines) - { - if (i > 10) - { - GetModelPartFromCSM(CSMBlock, modelView); - CSMBlock.Clear(); - i = 0; - } - CSMBlock.Add(line + "\n"); - i++; - } - - modelView.Invalidate(); - } - catch { } - } - - public static void GetModelPartFromCSM(List CSM, MinecraftModelView modelView) - { - string PartName = CSM[0]; - string PartParent = CSM[1]; - string PartName2 = CSM[2]; - int PositionX = int.Parse(CSM[3]); - int PositionY = int.Parse(CSM[4]); - int PositionZ = int.Parse(CSM[5]); - int SizeX = int.Parse(CSM[6]); - int SizeY = int.Parse(CSM[7]); - int SizeZ = int.Parse(CSM[8]); - int UVY = int.Parse(CSM[9]); - int UVX = int.Parse(CSM[10]); - - //RenderBox - System.Drawing.Image source = Textures[0].Source; - Object3D object3D = new Box(source, new Rectangle(8, 0, 0x10, 8), new Rectangle(0, 8, 0x20, 8), new Point3D(0f, 0f, 0f), Effects.None); - Object3D object3D2 = new Box(source, new Rectangle(0x28, 0, 0x10, 8), new Rectangle(0x20, 8, 0x20, 8), new Point3D(0f, 0f, 0f), Effects.None); - Object3D object3D3 = new Box(source, new Rectangle(0x2C, 0x10, 8, 4), new Rectangle(0x28, 0x14, 0x20, 0xC), new Point3D(0f, 4f, 0f), Effects.FlipHorizontally); - - - //RenderGroup - Object3DGroup object3DGroup = new Object3DGroup(); - object3D2.Scale = 1.16f; - object3DGroup.RotationOrder = RotationOrders.XY; - object3DGroup.MinDegrees1 = -80f; - object3DGroup.MaxDegrees1 = 80f; - object3DGroup.MinDegrees2 = -57f; - object3DGroup.MaxDegrees2 = 57f; - object3DGroup.Add(object3D); - object3DGroup.Add(object3D2); - object3DGroup.Position = new Point3D(0f, 8f, 0f); - object3DGroup.Origin = new Point3D(0f, -4f, 0f); - object3DGroup.RotationOrder = RotationOrders.XY; - modelView.AddDynamic(object3DGroup); - } - - public static Texture[] Textures = new Texture[] { new Texture(Bitmap.FromFile(Environment.CurrentDirectory + "\\default.png")) }; - } -} diff --git a/PCK-Studio/Classes/IO/3DST/3DSTextureReader.cs b/PCK-Studio/Classes/IO/3DST/3DSTextureReader.cs new file mode 100644 index 00000000..e944003f --- /dev/null +++ b/PCK-Studio/Classes/IO/3DST/3DSTextureReader.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OMI.Workers; +using PckStudio.Classes._3ds; +using OMI; + +namespace PckStudio.Classes.IO._3DST +{ + internal class _3DSTextureReader : IDataFormatReader, IDataFormatReader + { + public Image FromFile(string filename) + { + if (File.Exists(filename)) + { + Image img = null; + using (var fs = File.OpenRead(filename)) + { + img = FromStream(fs); + } + return img; + } + throw new FileNotFoundException(filename); + } + + public Image FromStream(Stream stream) + { + Image img = null; + using (var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian)) + { + if (reader.ReadString(4) == "3DST") + { + const int offset = 32; + reader.ReadInt32(); // unknown value + _3DSTextureFormat format = reader.ReadInt32() switch + { + 0 => _3DSTextureFormat.argb8, + 1 => _3DSTextureFormat.rgb8, + 2 => _3DSTextureFormat.rgba5551, + 3 => _3DSTextureFormat.rgb8, + 4 => _3DSTextureFormat.rgba4, + 9 => _3DSTextureFormat.la4, + _ => _3DSTextureFormat.dontCare, + }; + int width = reader.ReadInt32(); + int height = reader.ReadInt32(); + int bufferSize = CalcBufferSize(format, width, height); + stream.Seek(offset, SeekOrigin.Begin); + byte[] buffer = new byte[bufferSize]; + reader.Read(buffer, 0, bufferSize); + img = TextureCodec.Decode(buffer, width, height, format); + img.RotateFlip(RotateFlipType.RotateNoneFlipY); + } + } + return img; + } + + private static int CalcBufferSize(_3DSTextureFormat textureFormat, int width, int height) + { + switch (textureFormat) + { + case _3DSTextureFormat.argb8: + return width * height * 4; + case _3DSTextureFormat.rgb8: + return width * height * 3; + case _3DSTextureFormat.rgba5551: + case _3DSTextureFormat.rgb565: + case _3DSTextureFormat.rgba4: + case _3DSTextureFormat.la8: + case _3DSTextureFormat.hilo8: + return width * height * 2; + case _3DSTextureFormat.l8: + case _3DSTextureFormat.a8: + case _3DSTextureFormat.la4: + case _3DSTextureFormat.etc1a4: + return width * height; + case _3DSTextureFormat.l4: + case _3DSTextureFormat.a4: + case _3DSTextureFormat.etc1: + return width * height >> 1; + default: + throw new InvalidDataException("Invalid texture format on BCH!"); + } + } + + object IDataFormatReader.FromFile(string filename) => FromFile(filename); + + object IDataFormatReader.FromStream(Stream stream) => FromStream(stream); + } +} diff --git a/PCK-Studio/Classes/IO/3DST/3DSTextureWriter.cs b/PCK-Studio/Classes/IO/3DST/3DSTextureWriter.cs new file mode 100644 index 00000000..28864ed2 --- /dev/null +++ b/PCK-Studio/Classes/IO/3DST/3DSTextureWriter.cs @@ -0,0 +1,47 @@ +using System; +using System.Drawing; +using System.IO; +using System.Text; +using OMI; +using OMI.Workers; +using PckStudio.Classes._3ds; + +namespace PckStudio.Classes.IO._3DST +{ + internal class _3DSTextureWriter : IDataFormatWriter + { + private Image _image; + private _3DSTextureFormat _format; + public _3DSTextureWriter(Image image, _3DSTextureFormat format = _3DSTextureFormat.argb8) + { + _image = image; + _format = format; + } + + 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, Endianness.LittleEndian)) + { + writer.WriteString("3DST"); // 0 + writer.Write(2); // 4 unknown + writer.Write((int)_format); // 8 + writer.Write(_image.Width); // 12 + writer.Write(_image.Height); // 16 + writer.Write(0); // 20 + writer.Write(0); // 24 + writer.Write(0); // 28 + _image.RotateFlip(RotateFlipType.RotateNoneFlipY); + byte[] buffer = TextureCodec.Encode(new Bitmap(_image), _format); + stream.Write(buffer, 0, buffer.Length); + } + } + } +} diff --git a/PCK-Studio/Classes/Utils/3DS/TextureCodec.cs b/PCK-Studio/Classes/IO/3DST/TextureCodec.cs similarity index 96% rename from PCK-Studio/Classes/Utils/3DS/TextureCodec.cs rename to PCK-Studio/Classes/IO/3DST/TextureCodec.cs index aa0b963a..2f208a2f 100644 --- a/PCK-Studio/Classes/Utils/3DS/TextureCodec.cs +++ b/PCK-Studio/Classes/IO/3DST/TextureCodec.cs @@ -2,14 +2,35 @@ using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; -using PckStudio.Classes._3ds.Utils; namespace PckStudio.Classes._3ds { + /// + /// Format of the texture used on the PICA200. + /// + public enum _3DSTextureFormat + { + argb8 = 0, + rgb8 = 1, + rgba5551 = 2, + rgb565 = 3, + rgba4 = 4, + la8 = 5, + hilo8 = 6, + l8 = 7, + a8 = 8, + la4 = 9, + l4 = 0xa, + a4 = 0xb, + etc1 = 0xc, + etc1a4 = 0xd, + dontCare + } + class TextureCodec { - private static int[] tileOrder = { 0, 1, 8, 9, 2, 3, 10, 11, 16, 17, 24, 25, 18, 19, 26, 27, 4, 5, 12, 13, 6, 7, 14, 15, 20, 21, 28, 29, 22, 23, 30, 31, 32, 33, 40, 41, 34, 35, 42, 43, 48, 49, 56, 57, 50, 51, 58, 59, 36, 37, 44, 45, 38, 39, 46, 47, 52, 53, 60, 61, 54, 55, 62, 63 }; - private static int[,] etc1LUT = { { 2, 8, -2, -8 }, { 5, 17, -5, -17 }, { 9, 29, -9, -29 }, { 13, 42, -13, -42 }, { 18, 60, -18, -60 }, { 24, 80, -24, -80 }, { 33, 106, -33, -106 }, { 47, 183, -47, -183 } }; + private static readonly int[] tileOrder = { 0, 1, 8, 9, 2, 3, 10, 11, 16, 17, 24, 25, 18, 19, 26, 27, 4, 5, 12, 13, 6, 7, 14, 15, 20, 21, 28, 29, 22, 23, 30, 31, 32, 33, 40, 41, 34, 35, 42, 43, 48, 49, 56, 57, 50, 51, 58, 59, 36, 37, 44, 45, 38, 39, 46, 47, 52, 53, 60, 61, 54, 55, 62, 63 }; + private static readonly int[,] etc1LUT = { { 2, 8, -2, -8 }, { 5, 17, -5, -17 }, { 9, 29, -9, -29 }, { 13, 42, -13, -42 }, { 18, 60, -18, -60 }, { 24, 80, -24, -80 }, { 33, 106, -33, -106 }, { 47, 183, -47, -183 } }; private static class TextureConverter { diff --git a/PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs b/PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs index 0e1313a1..6144150a 100644 --- a/PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs +++ b/PCK-Studio/Classes/IO/CSMB/CSMBFileReader.cs @@ -1,57 +1,66 @@ using System.IO; using System.Text; +using OMI; +using OMI.Workers; using PckStudio.Classes.FileTypes; namespace PckStudio.Classes.IO.CSMB { - internal class CSMBFileReader : StreamDataReader + internal class CSMBFileReader : IDataFormatReader, IDataFormatReader { - public static CSMBFile Read(Stream stream) - { - return new CSMBFileReader().ReadFromStream(stream); - } - - private CSMBFileReader() : base(false) + private CSMBFileReader() { } - protected override CSMBFile ReadFromStream(Stream stream) + public CSMBFile FromFile(string filename) { - CSMBFile BinFile = new CSMBFile(); - ReadInt(stream); - int NumOfParts = ReadInt(stream); - for(int i = 0; i < NumOfParts; i++) - { - CSMBPart part = new CSMBPart(); - part.Name = ReadString(stream); - part.Parent = (CSMBParentPart)ReadInt(stream); - part.posX = ReadFloat(stream); - part.posY = ReadFloat(stream); - part.posZ = ReadFloat(stream); - part.sizeX = ReadFloat(stream); - part.sizeY = ReadFloat(stream); - part.sizeZ = ReadFloat(stream); - part.uvX = ReadInt(stream); - part.uvY = ReadInt(stream); - part.MirrorTexture = ReadBool(stream); - part.HideWArmour = ReadBool(stream); - part.Inflation = ReadFloat(stream); - BinFile.Parts.Add(part); - } - int NumOfOffsets = ReadInt(stream); - for (int i = 0; i < NumOfOffsets; i++) - { - CSMBOffset offset = new CSMBOffset(); - offset.offsetPart = (CSMBOffsetPart)ReadInt(stream); - offset.VerticalOffset = ReadFloat(stream); - BinFile.Offsets.Add(offset); - } - return BinFile; + throw new System.NotImplementedException(); } - private string ReadString(Stream stream) + public CSMBFile FromStream(Stream stream) { - short strlen = ReadShort(stream); - return ReadString(stream, strlen, Encoding.ASCII); + CSMBFile csmbFile = new CSMBFile(); + using (var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian)) + { + 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); + } + } + return csmbFile; } + + private string ReadString(EndiannessAwareBinaryReader reader) + { + ushort strlen = reader.ReadUInt16(); + return reader.ReadString(strlen); + } + + object IDataFormatReader.FromStream(Stream stream) => FromStream(stream); + + object IDataFormatReader.FromFile(string filename) => FromFile(filename); } } diff --git a/PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs b/PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs index 5855c6e0..0481f3db 100644 --- a/PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs +++ b/PCK-Studio/Classes/IO/CSMB/CSMBFileWriter.cs @@ -1,54 +1,58 @@ using System.IO; using System.Text; using PckStudio.Classes.FileTypes; +using OMI.Workers; +using OMI; namespace PckStudio.Classes.IO.CSMB { - internal class CSMBFileWriter : StreamDataWriter + internal class CSMBFileWriter : IDataFormatWriter { CSMBFile _CSMB; - public static void Write(Stream stream, CSMBFile file) - { - new CSMBFileWriter(file).WriteToStream(stream); - } - public CSMBFileWriter(CSMBFile csmb) : base(false) + public CSMBFileWriter(CSMBFile csmb) { _CSMB = csmb; } - protected override void WriteToStream(Stream stream) + public void WriteToFile(string filename) { - WriteInt(stream, 0); - WriteInt(stream, _CSMB.Parts.Count); - foreach(CSMBPart part in _CSMB.Parts) + using(var fs = File.OpenWrite(filename)) { - WriteString(stream, part.Name); - WriteInt(stream, (int)part.Parent); - WriteFloat(stream, part.posX); - WriteFloat(stream, part.posY); - WriteFloat(stream, part.posZ); - WriteFloat(stream, part.sizeX); - WriteFloat(stream, part.sizeY); - WriteFloat(stream, part.sizeZ); - WriteInt(stream, part.uvX); - WriteInt(stream, part.uvY); - WriteBool(stream, part.MirrorTexture); - WriteBool(stream, part.HideWArmour); - WriteFloat(stream, part.Inflation); - } - WriteInt(stream, _CSMB.Offsets.Count); - foreach (CSMBOffset offset in _CSMB.Offsets) - { - WriteInt(stream, (int)offset.offsetPart); - WriteFloat(stream, offset.VerticalOffset); + WriteToStream(fs); } } - private void WriteString(Stream stream, string s) + public void WriteToStream(Stream stream) { - WriteShort(stream, (short)s.Length); - WriteString(stream, s, Encoding.ASCII); + using (var writer = new EndiannessAwareBinaryWriter(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian)) + { + writer.Write(0); + writer.Write(_CSMB.Parts.Count); + foreach (CSMBPart 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); + } + writer.Write(_CSMB.Offsets.Count); + foreach (CSMBOffset offset in _CSMB.Offsets) + { + writer.Write((int)offset.offsetPart); + writer.Write(offset.VerticalOffset); + } + } } } } diff --git a/PCK-Studio/Classes/IO/PCK/PCKAudioFileReader.cs b/PCK-Studio/Classes/IO/PCK/PCKAudioFileReader.cs index 53d5a793..4eb1710a 100644 --- a/PCK-Studio/Classes/IO/PCK/PCKAudioFileReader.cs +++ b/PCK-Studio/Classes/IO/PCK/PCKAudioFileReader.cs @@ -1,6 +1,9 @@ -using PckStudio.Classes.FileTypes; +using OMI; +using OMI.Workers; +using PckStudio.Classes.FileTypes; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; @@ -14,55 +17,73 @@ namespace PckStudio.Classes.IO.PCK { } } - internal class PCKAudioFileReader : StreamDataReader + internal class PCKAudioFileReader : IDataFormatReader, IDataFormatReader { private PCKAudioFile _file; + private Endianness _endianness; private List LUT = new List(); private List _OriginalAudioTypeOrder = new List(); - - public static PCKAudioFile Read(Stream stream, bool isLittleEndian) + public PCKAudioFileReader(Endianness endianness) { - return new PCKAudioFileReader(isLittleEndian).ReadFromStream(stream); + _endianness = endianness; } - private PCKAudioFileReader(bool isLittleEndian) : base(isLittleEndian) + public PCKAudioFile FromFile(string filename) { + if(File.Exists(filename)) + { + PCKAudioFile file; + using(var fs = File.OpenRead(filename)) + { + file = FromStream(fs); + } + return file; + } + throw new FileNotFoundException(filename); } - protected override PCKAudioFile ReadFromStream(Stream stream) + public PCKAudioFile FromStream(Stream stream) { - int pck_type = ReadInt(stream); - if (pck_type > 0xf00000) // 03 00 00 00 == true - throw new OverflowException(nameof(pck_type)); - if (pck_type > 1) - throw new InvalidAudioPckException(nameof(pck_type)); - _file = new PCKAudioFile(); - ReadLookUpTable(stream); - ReadCategories(stream); - ReadCategorySongs(stream); + using (var reader = new EndiannessAwareBinaryReader(stream, + _endianness == Endianness.BigEndian + ? Encoding.BigEndianUnicode + : Encoding.Unicode, + leaveOpen: true, _endianness)) + { + int pck_type = reader.ReadInt32(); + if (pck_type > 0xf00000) // 03 00 00 00 == true + throw new OverflowException(nameof(pck_type)); + if (pck_type > 1) + throw new InvalidAudioPckException(nameof(pck_type)); + _file = new PCKAudioFile(); + ReadLookUpTable(reader); + ReadCategories(reader); + ReadCategorySongs(reader); + } return _file; } - private void ReadLookUpTable(Stream stream) + private void ReadLookUpTable(EndiannessAwareBinaryReader reader) { - int count = ReadInt(stream); + int count = reader.ReadInt32(); LUT = new List(count); for (int i = 0; i < count; i++) { - int index = ReadInt(stream); - LUT.Insert(index, ReadString(stream)); + int index = reader.ReadInt32(); + string value = ReadString(reader); + LUT.Insert(index, value); } } - private void ReadCategories(Stream stream) + private void ReadCategories(EndiannessAwareBinaryReader reader) { - int categoryEntryCount = ReadInt(stream); + int categoryEntryCount = reader.ReadInt32(); for (; 0 < categoryEntryCount; categoryEntryCount--) { - var parameterType = (PCKAudioFile.AudioCategory.EAudioParameterType)ReadInt(stream); - var audioType = (PCKAudioFile.AudioCategory.EAudioType)ReadInt(stream); - string name = ReadString(stream); + var parameterType = (PCKAudioFile.AudioCategory.EAudioParameterType)reader.ReadInt32(); + var audioType = (PCKAudioFile.AudioCategory.EAudioType)reader.ReadInt32(); + string name = ReadString(reader); // AddCategory puts the file's categories out of order and causes some songs to be put in the wrong categories // This is my simple fix for the issue. _OriginalAudioTypeOrder.Add(audioType); @@ -70,17 +91,17 @@ namespace PckStudio.Classes.IO.PCK } } - private void ReadCategorySongs(Stream stream) + private void ReadCategorySongs(EndiannessAwareBinaryReader reader) { List credits = new List(); List creditIds = new List(); foreach (var c in _OriginalAudioTypeOrder) { - int audioCount = ReadInt(stream); + int audioCount = reader.ReadInt32(); for (; 0 < audioCount; audioCount--) { - string key = LUT[ReadInt(stream)]; - string value = ReadString(stream); + string key = LUT[reader.ReadInt32()]; + string value = ReadString(reader); switch (key) { case "CUENAME": @@ -104,12 +125,16 @@ namespace PckStudio.Classes.IO.PCK } } - private string ReadString(Stream stream) + private string ReadString(EndiannessAwareBinaryReader reader) { - int len = ReadInt(stream); - string s = ReadString(stream, len, IsUsingLittleEndian ? Encoding.Unicode : Encoding.BigEndianUnicode); - ReadInt(stream); // padding + int len = reader.ReadInt32(); + string s = reader.ReadString(len); + reader.ReadInt32(); // padding return s; } + + object IDataFormatReader.FromStream(Stream stream) => FromStream(stream); + + object IDataFormatReader.FromFile(string filename) => FromFile(filename); } } diff --git a/PCK-Studio/Classes/IO/PCK/PCKAudioFileWriter.cs b/PCK-Studio/Classes/IO/PCK/PCKAudioFileWriter.cs index 129861d7..3a1d9223 100644 --- a/PCK-Studio/Classes/IO/PCK/PCKAudioFileWriter.cs +++ b/PCK-Studio/Classes/IO/PCK/PCKAudioFileWriter.cs @@ -1,14 +1,17 @@ -using PckStudio.Classes.FileTypes; +using OMI; +using OMI.Workers; +using PckStudio.Classes.FileTypes; using System.Collections.Generic; using System.IO; using System.Text; namespace PckStudio.Classes.IO.PCK { - internal class PCKAudioFileWriter : StreamDataWriter + internal class PCKAudioFileWriter : IDataFormatWriter { private PCKAudioFile _file; + private Endianness _endianness; private static readonly List LUT = new List { "CUENAME", @@ -16,71 +19,82 @@ namespace PckStudio.Classes.IO.PCK "CREDITID" }; - public static void Write(Stream stream, PCKAudioFile file, bool isLittleEndian) - { - new PCKAudioFileWriter(file, isLittleEndian).WriteToStream(stream); - } - - private PCKAudioFileWriter(PCKAudioFile file, bool isLittleEndian) : base(isLittleEndian) + public PCKAudioFileWriter(PCKAudioFile file, Endianness endianness) { _file = file; + _endianness = endianness; } - protected override void WriteToStream(Stream stream) + public void WriteToFile(string filename) { - WriteInt(stream, _file.type); - WriteLookUpTable(stream); - WriteCategories(stream); - WriteCategorySongs(stream); + using(var fs = File.OpenWrite(filename)) + { + WriteToStream(fs); + } } - private void WriteString(Stream stream, string s) + public void WriteToStream(Stream stream) { - WriteInt(stream, s.Length); - WriteString(stream, s, IsUsingLittleEndian ? Encoding.Unicode : Encoding.BigEndianUnicode); - WriteInt(stream, 0); // padding + using (var writer = new EndiannessAwareBinaryWriter(stream, + _endianness == Endianness.BigEndian + ? Encoding.BigEndianUnicode + : Encoding.Unicode, + leaveOpen: true, _endianness)) + { + writer.Write(_file.type); + WriteLookUpTable(writer); + WriteCategories(writer); + WriteCategorySongs(writer); + } } - private void WriteLookUpTable(Stream stream) + private void WriteString(EndiannessAwareBinaryWriter writer, string s) { - WriteInt(stream, 3); + writer.Write(s.Length); + writer.WriteString(s); + writer.Write(0); // padding + } + + private void WriteLookUpTable(EndiannessAwareBinaryWriter writer) + { + writer.Write(3); for (int i = 0; i < 3; i++) { - WriteInt(stream, i); - WriteString(stream, LUT[i]); + writer.Write(i); + WriteString(writer, LUT[i]); } } - private void WriteCategories(Stream stream) + private void WriteCategories(EndiannessAwareBinaryWriter writer) { - WriteInt(stream, _file.Categories.Length); + writer.Write(_file.Categories.Length); foreach (var category in _file.Categories) { - WriteInt(stream, (int)category.parameterType); - WriteInt(stream, (int)category.audioType); - WriteString(stream, category.Name); + writer.Write((int)category.parameterType); + writer.Write((int)category.audioType); + WriteString(writer, category.Name); } } - private void WriteCategorySongs(Stream stream) + private void WriteCategorySongs(EndiannessAwareBinaryWriter writer) { bool addCredit = true; foreach (var category in _file.Categories) { - WriteInt(stream, category.SongNames.Count + (addCredit ? _file.Credits.Count * 2 : 0)); + writer.Write(category.SongNames.Count + (addCredit ? _file.Credits.Count * 2 : 0)); foreach (var name in category.SongNames) { - WriteInt(stream, LUT.IndexOf("CUENAME")); - WriteString(stream, name); + writer.Write(LUT.IndexOf("CUENAME")); + WriteString(writer, name); } if (addCredit) { foreach (var credit in _file.Credits) { - WriteInt(stream, LUT.IndexOf("CREDIT")); - WriteString(stream, credit.Value); - WriteInt(stream, LUT.IndexOf("CREDITID")); - WriteString(stream, credit.Key); + writer.Write(LUT.IndexOf("CREDIT")); + WriteString(writer, credit.Value); + writer.Write(LUT.IndexOf("CREDITID")); + WriteString(writer, credit.Key); } } addCredit = false; diff --git a/PCK-Studio/Classes/IO/StreamDataReader.cs b/PCK-Studio/Classes/IO/StreamDataReader.cs deleted file mode 100644 index 91e0fb97..00000000 --- a/PCK-Studio/Classes/IO/StreamDataReader.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2022-present miku-666 - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1.The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. -**/ -using PckStudio.Classes.FileTypes; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace PckStudio.Classes.IO -{ - public abstract class StreamDataReader - { - private static bool useLittleEndian; - protected static bool IsUsingLittleEndian => useLittleEndian; - protected abstract T ReadFromStream(Stream stream); - - protected StreamDataReader(bool useLittleEndian) - { - StreamDataReader.useLittleEndian = useLittleEndian; - } - - protected static string ReadString(Stream stream, int length, Encoding encoding) - { - byte[] buffer = ReadBytes(stream, length << Convert.ToInt32(encoding is UnicodeEncoding)); - return encoding.GetString(buffer).TrimEnd('\0'); - } - - protected static byte[] ReadBytes(Stream stream, int count) - { - byte[] buffer = new byte[count]; - stream.Read(buffer, 0, count); - return buffer; - } - - protected static bool ReadBool(Stream stream) - { - return stream.ReadByte() != 0; - } - - protected static ushort ReadUShort(Stream stream) => (ushort)ReadShort(stream); - protected static short ReadShort(Stream stream) - { - byte[] bytes = ReadBytes(stream, 2); - if (BitConverter.IsLittleEndian && !useLittleEndian) - Array.Reverse(bytes); - return BitConverter.ToInt16(bytes, 0); - } - - protected static uint ReadUInt(Stream stream) => (uint)ReadInt(stream); - protected static int ReadInt(Stream stream) - { - byte[] buffer = ReadBytes(stream, 4); - if (BitConverter.IsLittleEndian && !useLittleEndian) - Array.Reverse(buffer); - return BitConverter.ToInt32(buffer, 0); - } - - protected static ulong ReadULong(Stream stream) => (ulong)ReadLong(stream); - protected static long ReadLong(Stream stream) - { - byte[] buffer = ReadBytes(stream, 8); - if (BitConverter.IsLittleEndian && !useLittleEndian) - Array.Reverse(buffer); - return BitConverter.ToInt64(buffer, 0); - } - - protected static float ReadFloat(Stream stream) - { - byte[] buffer = ReadBytes(stream, 4); - if (BitConverter.IsLittleEndian && !useLittleEndian) - Array.Reverse(buffer); - return BitConverter.ToSingle(buffer, 0); - } - } -} diff --git a/PCK-Studio/Classes/IO/StreamDataWriter.cs b/PCK-Studio/Classes/IO/StreamDataWriter.cs deleted file mode 100644 index 594621f0..00000000 --- a/PCK-Studio/Classes/IO/StreamDataWriter.cs +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright (c) 2022-present miku-666 - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1.The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. -**/ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace PckStudio.Classes.IO -{ - public abstract class StreamDataWriter - { - private static bool useLittleEndian; - protected static bool IsUsingLittleEndian => useLittleEndian; - - protected StreamDataWriter(bool littleEndian) - { - useLittleEndian = littleEndian; - } - - protected abstract void WriteToStream(Stream stream); - - protected static void WriteBool(Stream stream, bool state) - { - stream.WriteByte((byte)(state ? 1 : 0)); - } - - protected static void WriteUShort(Stream stream, ushort value) => WriteShort(stream, (short)value); - - protected static void WriteShort(Stream stream, short value) - { - byte[] bytes = BitConverter.GetBytes(value); - if (BitConverter.IsLittleEndian && !useLittleEndian) - Array.Reverse(bytes); - WriteBytes(stream, bytes, 2); - } - - protected static void WriteUInt(Stream stream, uint value) => WriteInt(stream, (int)value); - protected static void WriteInt(Stream stream, int value) - { - byte[] buffer = BitConverter.GetBytes(value); - if (BitConverter.IsLittleEndian && !useLittleEndian) - Array.Reverse(buffer); - WriteBytes(stream, buffer, 4); - } - - protected static void WriteULong(Stream stream, ulong value) => WriteLong(stream, (long)value); - protected static void WriteLong(Stream stream, long value) - { - byte[] buffer = BitConverter.GetBytes(value); - if (BitConverter.IsLittleEndian && !useLittleEndian) - Array.Reverse(buffer); - WriteBytes(stream, buffer, 8); - } - - protected static void WriteString(Stream stream, string s, Encoding encoding) - => WriteBytes(stream, encoding.GetBytes(s)); - - protected static void WriteBytes(Stream stream, byte[] bytes) => WriteBytes(stream, bytes, bytes.Length); - protected static void WriteBytes(Stream stream, byte[] bytes, int count) - { - stream.Write(bytes, 0, count); - } - - protected static void WriteFloat(Stream stream, float value) - { - byte[] buffer = BitConverter.GetBytes(value); - if (BitConverter.IsLittleEndian && !useLittleEndian) - Array.Reverse(buffer); - WriteBytes(stream, buffer, 4); - } - } -} diff --git a/PCK-Studio/Classes/Utils/3DS/3DSUtil.cs b/PCK-Studio/Classes/Utils/3DS/3DSUtil.cs deleted file mode 100644 index 485420a7..00000000 --- a/PCK-Studio/Classes/Utils/3DS/3DSUtil.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System; -using System.Drawing; -using System.IO; -using System.Text; - -namespace PckStudio.Classes._3ds.Utils -{ - /// - /// Format of the texture used on the PICA200. - /// - public enum _3DSTextureFormat - { - argb8 = 0, - rgb8 = 1, - rgba5551 = 2, - rgb565 = 3, - rgba4 = 4, - la8 = 5, - hilo8 = 6, - l8 = 7, - a8 = 8, - la4 = 9, - l4 = 0xa, - a4 = 0xb, - etc1 = 0xc, - etc1a4 = 0xd, - dontCare - } - - internal class _3DSUtil - { - private static string ReadString(Stream stream, int len) - { - byte[] buffer = new byte[len]; - stream.Read(buffer, 0, len); - return Encoding.ASCII.GetString(buffer); - } - - private static int ReadInt32(Stream stream) - { - byte[] buffer = new byte[4]; - stream.Read(buffer, 0, 4); - return BitConverter.ToInt32(buffer, 0); - } - - private static void WriteString(Stream stream, string s) - { - byte[] buffer = Encoding.ASCII.GetBytes(s); - stream.Write(buffer, 0, buffer.Length); - } - - private static void WriteInt32(Stream stream, int value) - { - byte[] buffer = BitConverter.GetBytes(value); - stream.Write(buffer, 0, 4); - } - - public static int CalcBufferSize(_3DSTextureFormat textureFormat, int width, int height) - { - switch (textureFormat) - { - case _3DSTextureFormat.argb8: - return width * height * 4; - case _3DSTextureFormat.rgb8: - return width * height * 3; - case _3DSTextureFormat.rgba5551: - case _3DSTextureFormat.rgb565: - case _3DSTextureFormat.rgba4: - case _3DSTextureFormat.la8: - case _3DSTextureFormat.hilo8: - return width * height * 2; - case _3DSTextureFormat.l8: - case _3DSTextureFormat.a8: - case _3DSTextureFormat.la4: - case _3DSTextureFormat.etc1a4: - return width * height; - case _3DSTextureFormat.l4: - case _3DSTextureFormat.a4: - case _3DSTextureFormat.etc1: - return width * height >> 1; - default: - throw new InvalidDataException("Invalid texture format on BCH!"); - } - } - - public static Image GetImageFrom3DST(Stream stream) - { - if (ReadString(stream, 4) == "3DST") - { - const int offset = 32; - stream.Seek(8L, SeekOrigin.Begin); - _3DSTextureFormat format = ReadInt32(stream) switch - { - 0 => _3DSTextureFormat.argb8, - 1 => _3DSTextureFormat.rgb8, - 2 => _3DSTextureFormat.rgba5551, - 3 => _3DSTextureFormat.rgb8, - 4 => _3DSTextureFormat.rgba4, - 9 => _3DSTextureFormat.la4, - _ => _3DSTextureFormat.dontCare, - }; - int width = ReadInt32(stream); - int height = ReadInt32(stream); - int bufferSize = CalcBufferSize(format, width, height); - stream.Seek(offset, SeekOrigin.Begin); - byte[] buffer = new byte[bufferSize]; - stream.Read(buffer, 0, bufferSize); - var img = TextureCodec.Decode(buffer, width, height, format); - img.RotateFlip(RotateFlipType.RotateNoneFlipY); - return img; - } - return null; - } - - public static void SetImageTo3DST(Stream stream, Image source, _3DSTextureFormat format = _3DSTextureFormat.argb8) - { - // TODO: fix Encoding - WriteString(stream, "3DST"); // 0 - WriteInt32(stream, 2); // 4 unknown - WriteInt32(stream, (int)format); // 8 - WriteInt32(stream, source.Width); // 12 - WriteInt32(stream, source.Height); // 16 - WriteInt32(stream, 0); // 20 - WriteInt32(stream, 0); // 24 - WriteInt32(stream, 0); // 28 - source.RotateFlip(RotateFlipType.RotateNoneFlipY); - byte[] buffer = TextureCodec.Encode(new Bitmap(source), format); - stream.Write(buffer, 0, buffer.Length); - } - } -} diff --git a/PCK-Studio/Classes/Utils/BedrockJSONtoCSM.cs b/PCK-Studio/Classes/Utils/BedrockJSONtoCSM.cs deleted file mode 100644 index b9989707..00000000 --- a/PCK-Studio/Classes/Utils/BedrockJSONtoCSM.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json; - -namespace PckStudio.Classes.Utils.ModelConversion -{ - public class BedrockJSONtoCSM - { - public string JSONtoCSM(string JsonString) - { - dynamic jsonDe = JsonConvert.DeserializeObject(JsonString); - string NewJSON = JsonConvert.SerializeObject(jsonDe["minecraft:geometry"]); - JObject[] NewJObject = JsonConvert.DeserializeObject(NewJSON); - - string CSMData = ""; - foreach (JBone bone in NewJObject[0].bones) - { - int i = 0; - string PARENT = bone.name; - foreach (JCube Cube in bone.cubes) - { - string name = PARENT + " " + i; - - float PosXModifier = 0; - float PosYModifier = 0; - float PosZModifier = 0; - - switch (PARENT) - { - case "ARM0": - PosXModifier = 5; - PosYModifier = 22; - break; - case "ARM1": - PosXModifier = -5; - PosYModifier = 22; - break; - case "LEG0": - PosXModifier = 1.9f; - PosYModifier = 12; - break; - case "LEG1": - PosXModifier = -1.9f; - PosYModifier = 12; - break; - case "BODY": - PosYModifier = 24; - break; - case "HEAD": - PosYModifier = 24; - break; - } - - - float PosX = Cube.origin[0] + PosXModifier; - float PosY = Cube.origin[1] + PosYModifier; - float PosZ = Cube.origin[2] + PosZModifier; - float SizeX = Cube.size[0]; - float SizeY = Cube.size[1]; - float SizeZ = Cube.size[2]; - float UvX = Cube.uv[0]; - float UvY = Cube.uv[1]; - - CSMData += name + "\n" + PARENT + "\n" + name + "\n" + PosX + "\n" + PosY + "\n" + PosZ + "\n" + SizeX + "\n" + SizeY + "\n" + SizeZ + "\n" + UvX + "\n" + UvY + "\n"; - i++; - } - } - return CSMData; - } - } - - internal class WholeJSON - { - public string format_version = "1.12.0"; - public Dictionary entries = new Dictionary(); - } - - internal class JObject - { - public Dictionary description = new Dictionary(); - public JBone[] bones = { }; - } - internal class JBone - { - public string name = ""; - public int[] pivot = {0, 0, 0}; - public JCube[] cubes = { }; - } - internal class JCube - { - public float[] origin = new float[3]; - public float[] size = new float [3]; - public float[] uv = new float[2]; - } -} diff --git a/PCK-Studio/Classes/Utils/CSMtoBedrockJSON.cs b/PCK-Studio/Classes/Utils/CSMtoBedrockJSON.cs deleted file mode 100644 index 93df0546..00000000 --- a/PCK-Studio/Classes/Utils/CSMtoBedrockJSON.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json; - -namespace PckStudio.Classes.Utils.ModelConversion -{ - public class CSMtoBedrockJSON - { - public string CSMtoJSON(string CSMString) - { - List CSMLIST = new List(); - CSMLIST.AddRange(CSMString.Split(new[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)); - List> CSMS = SplitToSublists(CSMLIST, 11); - - JObject jobj = new JObject(); - List bones = new List(); - Dictionary> CubeList = new Dictionary> - { - {"HEAD", new List()}, - {"BODY", new List()}, - {"ARM0", new List()}, - {"ARM1", new List()}, - {"LEG0", new List()}, - {"LEG1", new List()} - }; - - foreach (List CSMItem in CSMS) - { - JCube NewCube = new JCube(); - - - float PosXModifier = 0; - float PosYModifier = 0; - float PosZModifier = 0; - - switch (CSMItem[1]) - { - case "ARM0": - PosXModifier = -5; - PosYModifier = -22; - break; - case "ARM1": - PosXModifier = 5; - PosYModifier = -22; - break; - case "LEG0": - PosXModifier = -1.9f; - PosYModifier = -12; - break; - case "LEG1": - PosXModifier = 1.9f; - PosYModifier = -12; - break; - case "BODY": - PosYModifier = -24; - break; - case "HEAD": - PosYModifier = -24; - break; - } - NewCube.origin[0] = float.Parse(CSMItem[3]) + PosXModifier; - NewCube.origin[1] = float.Parse(CSMItem[4]) + PosYModifier; - NewCube.origin[2] = float.Parse(CSMItem[5]) + PosZModifier; - NewCube.size[0] = float.Parse(CSMItem[6]); - NewCube.size[1] = float.Parse(CSMItem[7]); - NewCube.size[2] = float.Parse(CSMItem[8]); - NewCube.uv[0] = float.Parse(CSMItem[9]); - NewCube.uv[1] = float.Parse(CSMItem[10]); - CubeList[CSMItem[1]].Add(NewCube); - } - foreach (KeyValuePair> bone in CubeList) - { - JBone jb = new JBone(); - jb.name = bone.Key; - jb.cubes = bone.Value.ToArray(); - bones.Add(jb); - } - jobj.bones = bones.ToArray(); - jobj.description.Add("identifier", "geometry.steve"); - jobj.description.Add("texture_width", 64); - jobj.description.Add("texture_height", 64); - jobj.description.Add("visible_bounds_width", 2); - jobj.description.Add("visible_bounds_height", 3.5f); - jobj.description.Add("visible_bounds_offset", new float[] { 0, 1.25f, 0 }); - WholeJSON WJ = new WholeJSON(); - WJ.entries.Add("format_version", "1.12.0"); - WJ.entries.Add("minecraft:geometry", new JObject[] { jobj }); - string JSONDATA = JsonConvert.SerializeObject(WJ.entries, Formatting.Indented); - return JSONDATA; - } - - public List> SplitToSublists(List source, int size) - { - return source - .Select((x, i) => new { Index = i, Value = x }) - .GroupBy(x => x.Index / size) - .Select(x => x.Select(v => v.Value).ToList()) - .ToList(); - } - } - -} diff --git a/PCK-Studio/Forms/Editor/Animation.cs b/PCK-Studio/Forms/Editor/Animation.cs index ad8a1ccd..1f1f8065 100644 --- a/PCK-Studio/Forms/Editor/Animation.cs +++ b/PCK-Studio/Forms/Editor/Animation.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Drawing; -using PckStudio.Classes.Extentions; +using PckStudio.Extensions; using System.Text; @@ -140,7 +140,7 @@ namespace PckStudio.Forms.Editor var textures = isClockOrCompass ? linearImages : frameTextures; - return ImageExtentions.ImageFromImageArray(textures.ToArray(), ImageExtentions.ImageLayoutDirection.Vertical); + return ImageExtensions.ImageFromImageArray(textures.ToArray(), ImageLayoutDirection.Vertical); } } } diff --git a/PCK-Studio/Forms/Editor/AnimationEditor.cs b/PCK-Studio/Forms/Editor/AnimationEditor.cs index 7f921db2..b538538b 100644 --- a/PCK-Studio/Forms/Editor/AnimationEditor.cs +++ b/PCK-Studio/Forms/Editor/AnimationEditor.cs @@ -3,15 +3,13 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Drawing; -using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Windows.Forms; -using PckStudio.Classes.FileTypes; using PckStudio.Forms.Additional_Popups.Animation; using PckStudio.Forms.Utilities; -using PckStudio.Classes.Extentions; +using PckStudio.Extensions; using OMI.Formats.Pck; namespace PckStudio.Forms.Editor @@ -51,7 +49,7 @@ namespace PckStudio.Forms.Editor using MemoryStream textureMem = new MemoryStream(animationFile.Data); var texture = new Bitmap(textureMem); - var frameTextures = texture.CreateImageList(ImageExtentions.ImageLayoutDirection.Horizontal); + var frameTextures = texture.CreateImageList(ImageLayoutDirection.Horizontal); currentAnimation = animationFile.Properties.HasProperty("ANIM") ? new Animation(frameTextures, animationFile.Properties.GetPropertyValue("ANIM")) @@ -296,7 +294,7 @@ namespace PckStudio.Forms.Editor return; } using MemoryStream textureMem = new MemoryStream(File.ReadAllBytes(textureFile)); - var textures = Image.FromStream(textureMem).CreateImageList(ImageExtentions.ImageLayoutDirection.Horizontal); + var textures = Image.FromStream(textureMem).CreateImageList(ImageLayoutDirection.Horizontal); var new_animation = new Animation(textures); try { diff --git a/PCK-Studio/Forms/Editor/AudioEditor.cs b/PCK-Studio/Forms/Editor/AudioEditor.cs index 5f47eb52..746e1eec 100644 --- a/PCK-Studio/Forms/Editor/AudioEditor.cs +++ b/PCK-Studio/Forms/Editor/AudioEditor.cs @@ -64,7 +64,8 @@ namespace PckStudio.Forms.Editor audioPCK = file; using (var stream = new MemoryStream(file.Data)) { - audioFile = PCKAudioFileReader.Read(stream, isLittleEndian); + var reader = new PCKAudioFileReader(isLittleEndian ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian); + audioFile = reader.FromStream(stream); } SetUpTree(); @@ -396,7 +397,8 @@ namespace PckStudio.Forms.Editor using (var stream = new MemoryStream()) { - PCKAudioFileWriter.Write(stream, audioFile, _isLittleEndian); + var writer = new PCKAudioFileWriter(audioFile, _isLittleEndian ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian); + writer.WriteToStream(stream); audioPCK.SetData(stream.ToArray()); } DialogResult = DialogResult.OK; diff --git a/PCK-Studio/Forms/Skins-And-Textures/addnewskin.cs b/PCK-Studio/Forms/Skins-And-Textures/addnewskin.cs index 1fda9bed..76a66e8c 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/addnewskin.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/addnewskin.cs @@ -5,10 +5,10 @@ using System.Windows.Forms; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using PckStudio.Classes.Utils; -using PckStudio.Classes._3ds.Utils; using OMI.Formats.Languages; using OMI.Formats.Pck; using PckStudio.Forms.Editor; +using PckStudio.Classes.IO._3DST; namespace PckStudio { @@ -347,7 +347,8 @@ namespace PckStudio { using (var fs = File.OpenRead(ofdd.FileName)) { - CheckImage(_3DSUtil.GetImageFrom3DST(fs)); + var reader = new _3DSTextureReader(); + CheckImage(reader.FromStream(fs)); textSkinName.Text = Path.GetFileNameWithoutExtension(ofdd.FileName); } return; diff --git a/PCK-Studio/Forms/Utilities/AnimationResources.cs b/PCK-Studio/Forms/Utilities/AnimationResources.cs index 4d8c1f4a..237d153a 100644 --- a/PCK-Studio/Forms/Utilities/AnimationResources.cs +++ b/PCK-Studio/Forms/Utilities/AnimationResources.cs @@ -1,12 +1,9 @@ using Newtonsoft.Json.Linq; using System.Drawing; using System.Linq; -using System.IO; using PckStudio.Properties; -using System.Drawing.Imaging; -using PckStudio.Classes.Extentions; -using OMI.Formats.Pck; +using PckStudio.Extensions; namespace PckStudio.Forms.Utilities { diff --git a/PCK-Studio/Forms/Utilities/BehaviourResources.cs b/PCK-Studio/Forms/Utilities/BehaviourResources.cs index 763c4e71..8eed8e50 100644 --- a/PCK-Studio/Forms/Utilities/BehaviourResources.cs +++ b/PCK-Studio/Forms/Utilities/BehaviourResources.cs @@ -4,11 +4,9 @@ using System.Linq; using System.IO; using PckStudio.Properties; -using PckStudio.Classes.Extentions; +using PckStudio.Extensions; using OMI.Formats.Behaviour; using OMI.Workers.Behaviour; -using OMI.Formats.Pck; -using System; namespace PckStudio.Forms.Utilities { diff --git a/PCK-Studio/Forms/Utilities/MaterialResources.cs b/PCK-Studio/Forms/Utilities/MaterialResources.cs index 7d27eda1..94cd2e4a 100644 --- a/PCK-Studio/Forms/Utilities/MaterialResources.cs +++ b/PCK-Studio/Forms/Utilities/MaterialResources.cs @@ -4,7 +4,7 @@ using System.Linq; using System.IO; using PckStudio.Properties; -using PckStudio.Classes.Extentions; +using PckStudio.Extensions; using OMI.Formats.Pck; using OMI.Formats.Material; using OMI.Workers.Material; diff --git a/PCK-Studio/Forms/Utilities/ModelsResources.cs b/PCK-Studio/Forms/Utilities/ModelsResources.cs index cdf91454..f61e6ee1 100644 --- a/PCK-Studio/Forms/Utilities/ModelsResources.cs +++ b/PCK-Studio/Forms/Utilities/ModelsResources.cs @@ -4,7 +4,7 @@ using System.Linq; using System.IO; using PckStudio.Properties; -using PckStudio.Classes.Extentions; +using PckStudio.Extensions; using OMI.Formats.Model; using OMI.Formats.Pck; using OMI.Workers.Model; diff --git a/PCK-Studio/Forms/Utilities/pckCenterOpen.cs b/PCK-Studio/Forms/Utilities/pckCenterOpen.cs index c16ab9a7..7a978f68 100644 --- a/PCK-Studio/Forms/Utilities/pckCenterOpen.cs +++ b/PCK-Studio/Forms/Utilities/pckCenterOpen.cs @@ -19,7 +19,7 @@ using PckStudio.Classes.FileTypes; using PckStudio.Classes.IO.PCK; using OMI.Formats.Pck; using OMI.Workers.Pck; -using PckStudio.Classes.Extentions; +using PckStudio.Extensions; namespace PckStudio.Forms { @@ -1027,7 +1027,7 @@ namespace PckStudio.Forms { var ms = new MemoryStream(skinTexture.Data); Bitmap saveSkin = new Bitmap(Image.FromStream(ms)); - var config = new ImageExtentions.GraphicsConfig() + var config = new GraphicsConfig() { CompositingMode = CompositingMode.SourceCopy, CompositingQuality = CompositingQuality.HighQuality, diff --git a/PCK-Studio/MainForm.cs b/PCK-Studio/MainForm.cs index c32c86f4..becb5841 100644 --- a/PCK-Studio/MainForm.cs +++ b/PCK-Studio/MainForm.cs @@ -19,7 +19,6 @@ using PckStudio.Properties; using PckStudio.Classes.FileTypes; using PckStudio.Classes.Utils; using PckStudio.Classes.Utils.ARC; -using PckStudio.Classes._3ds.Utils; using PckStudio.Forms; using PckStudio.Forms.Utilities; using PckStudio.Forms.Editor; @@ -27,6 +26,7 @@ using PckStudio.Forms.Additional_Popups.Animation; using PckStudio.Forms.Additional_Popups; using PckStudio.Classes.Misc; using PckStudio.Classes.IO.PCK; +using PckStudio.Classes.IO._3DST; using PckStudio.Conversion.Bedrock; namespace PckStudio @@ -840,12 +840,15 @@ namespace PckStudio audioPck.AddCategory(PCKAudioFile.AudioCategory.EAudioType.Overworld); audioPck.AddCategory(PCKAudioFile.AudioCategory.EAudioType.Nether); audioPck.AddCategory(PCKAudioFile.AudioCategory.EAudioType.End); - PckFile.FileData pckFileData = currentPCK.CreateNewFile("audio.pck", PckFile.FileData.FileType.AudioFile); - using (var stream = new MemoryStream()) - { - PCKAudioFileWriter.Write(stream, audioPck, isLittle); - pckFileData.SetData(stream.ToArray()); - } + PckFile.FileData pckFileData = currentPCK.CreateNewFile("audio.pck", PckFile.FileData.FileType.AudioFile, () => + { + using (var stream = new MemoryStream()) + { + var writer = new PCKAudioFileWriter(audioPck, isLittle ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian); + writer.WriteToStream(stream); + return stream.ToArray(); + } + }); return pckFileData; } @@ -2078,11 +2081,11 @@ namespace PckStudio saveFileDialog.DefaultExt = ".3dst"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { - using (var fs = saveFileDialog.OpenFile()) + using (var ms = new MemoryStream(file.Data)) { - using var ms = new MemoryStream(file.Data); Image img = Image.FromStream(ms); - _3DSUtil.SetImageTo3DST(fs, img); + var writer = new _3DSTextureWriter(img); + writer.WriteToFile(saveFileDialog.FileName); } } } diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 35cc3698..9d115ce7 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -170,6 +170,9 @@ + + + @@ -185,11 +188,11 @@ - - + + @@ -198,12 +201,9 @@ - - + - - @@ -432,7 +432,7 @@ installWiiU.cs - + Form @@ -480,7 +480,7 @@ CreditsForm.cs - + AddEntry.cs diff --git a/README.md b/README.md index 48f1f058..e918ecda 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # PCK Studio -Modify .PCK archives as you please! +Modify .PCK archives as you please!
+**If you have any issues or would like to suggested a feature, we encourage you to open a new [issue](https://github.com/PhoenixARC/-PCK-Studio/issues) on the github.** ## Features: -#### If you'd like to suggested a feature to be added open an [issue](https://github.com/PhoenixARC/-PCK-Studio/issues) on the github. * Open, Edit and Save .PCK archives (this means models, animations, entire custom packs, etc.) * Add / Remove / Replace skins, audios, textures, animations and much more. * Edit localization data to make your mods support every language supported by minecraft itself! @@ -23,8 +23,8 @@ Modify .PCK archives as you please! ### Setup: ```shell -$ git clone https://github.com/PhoenixARC/-PCK-Studio.git -$ cd "-PCK-Studio" +$ git clone --recursive https://github.com/PhoenixARC/-PCK-Studio.git PCK-Studio +$ cd PCK-Studio ``` ## How to Build: @@ -44,21 +44,19 @@ $ cd "-PCK-Studio" ``` ### A quick note: - * Forms will not load in viewer until the solution is build _at least_ once +## Active Developers: +> [PhoenixARC](https://github.com/PhoenixARC)
+> [MattNL](https://github.com/MattN-L)
+> [Miku-666](https://github.com/NessieHax)
+> [EternalModz](https://github.com/EternalModz)
-## Active Dev Team: -* [PhoenixARC](https://github.com/PhoenixARC) -* [MattNL](https://github.com/MattN-L) -* [Miku-666](https://github.com/NessieHax) -* [EternalModz](https://github.com/EternalModz) - -## Legacy PCK Studio Devs and contributors: -* [Nobledez](https://github.com/Nobledez) -* [XxModZxXWiiPlaza](https://github.com/XxModZxXWiiPlaza) -* [SlothWiiPlaza](https://github.com/Kashiiera) -* [jam1garner](https://github.com/jam1garner) +## Previous Developers and Contributors: +> [Nobledez](https://github.com/Nobledez)
+> [jam1garner](https://github.com/jam1garner)
+> [XxModZxXWiiPlaza](https://github.com/XxModZxXWiiPlaza)
+> [SlothWiiPlaza](https://github.com/Kashiiera)
## Other Credits * [yaboiFoxx](https://github.com/yaboiFoxx) for Improved UI concept diff --git a/Vendor/OMI-Lib b/Vendor/OMI-Lib index 9b991f6d..806fde8e 160000 --- a/Vendor/OMI-Lib +++ b/Vendor/OMI-Lib @@ -1 +1 @@ -Subproject commit 9b991f6d1a3591b92693aaff8a39fbe68803f7db +Subproject commit 806fde8e511de473b885fd7e7311e6f05c05ef47