mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-06-25 19:55:33 +00:00
Merge main into 'SkinPackConversion'
This commit is contained in:
@@ -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
|
||||
|
||||
13
PCK-Studio/Classes/Extensions/BlendMode.cs
Normal file
13
PCK-Studio/Classes/Extensions/BlendMode.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace PckStudio.Extensions
|
||||
{
|
||||
public enum BlendMode
|
||||
{
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Average,
|
||||
DescendingOrder,
|
||||
AscendingOrder,
|
||||
Screen
|
||||
}
|
||||
}
|
||||
@@ -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<T>(this IEnumerable<T> array)
|
||||
{
|
||||
39
PCK-Studio/Classes/Extensions/GraphicsExtensions.cs
Normal file
39
PCK-Studio/Classes/Extensions/GraphicsExtensions.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
241
PCK-Studio/Classes/Extensions/ImageExtensions.cs
Normal file
241
PCK-Studio/Classes/Extensions/ImageExtensions.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of sub section of the image
|
||||
/// </summary>
|
||||
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<Image> 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<Image> CreateImageList(this Image source, int scalar)
|
||||
{
|
||||
return CreateImageList(source, new Size(scalar, scalar));
|
||||
}
|
||||
|
||||
public static IEnumerable<Image> 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>(T value, T min, T max) where T : IComparable<T>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<T> Swap<T>(this IList<T> list, int index1, int index2)
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of sub section of the image
|
||||
/// </summary>
|
||||
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<Image> 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<Image> CreateImageList(this Image source, int scalar)
|
||||
{
|
||||
return CreateImageList(source, new Size(scalar, scalar));
|
||||
}
|
||||
|
||||
public static IEnumerable<Image> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<string> CSMBlock = new List<string>();
|
||||
|
||||
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<string> 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")) };
|
||||
}
|
||||
}
|
||||
94
PCK-Studio/Classes/IO/3DST/3DSTextureReader.cs
Normal file
94
PCK-Studio/Classes/IO/3DST/3DSTextureReader.cs
Normal file
@@ -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<Image>, 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);
|
||||
}
|
||||
}
|
||||
47
PCK-Studio/Classes/IO/3DST/3DSTextureWriter.cs
Normal file
47
PCK-Studio/Classes/IO/3DST/3DSTextureWriter.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,35 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
using PckStudio.Classes._3ds.Utils;
|
||||
|
||||
namespace PckStudio.Classes._3ds
|
||||
{
|
||||
/// <summary>
|
||||
/// Format of the texture used on the PICA200.
|
||||
/// </summary>
|
||||
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
|
||||
{
|
||||
@@ -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<CSMBFile>
|
||||
internal class CSMBFileReader : IDataFormatReader<CSMBFile>, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<PCKAudioFile>
|
||||
internal class PCKAudioFileReader : IDataFormatReader<PCKAudioFile>, IDataFormatReader
|
||||
{
|
||||
private PCKAudioFile _file;
|
||||
private Endianness _endianness;
|
||||
private List<string> LUT = new List<string>();
|
||||
private List<PCKAudioFile.AudioCategory.EAudioType> _OriginalAudioTypeOrder = new List<PCKAudioFile.AudioCategory.EAudioType>();
|
||||
|
||||
|
||||
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<string>(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<string> credits = new List<string>();
|
||||
List<string> creditIds = new List<string>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string> LUT = new List<string>
|
||||
{
|
||||
"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;
|
||||
|
||||
@@ -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<T>
|
||||
{
|
||||
private static bool useLittleEndian;
|
||||
protected static bool IsUsingLittleEndian => useLittleEndian;
|
||||
protected abstract T ReadFromStream(Stream stream);
|
||||
|
||||
protected StreamDataReader(bool useLittleEndian)
|
||||
{
|
||||
StreamDataReader<T>.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace PckStudio.Classes._3ds.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Format of the texture used on the PICA200.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<dynamic>(JsonString);
|
||||
string NewJSON = JsonConvert.SerializeObject(jsonDe["minecraft:geometry"]);
|
||||
JObject[] NewJObject = JsonConvert.DeserializeObject<JObject[]>(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<string, object> entries = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
internal class JObject
|
||||
{
|
||||
public Dictionary<string, object> description = new Dictionary<string, object>();
|
||||
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];
|
||||
}
|
||||
}
|
||||
@@ -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<string> CSMLIST = new List<string>();
|
||||
CSMLIST.AddRange(CSMString.Split(new[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries));
|
||||
List<List<string>> CSMS = SplitToSublists(CSMLIST, 11);
|
||||
|
||||
JObject jobj = new JObject();
|
||||
List<JBone> bones = new List<JBone>();
|
||||
Dictionary<string, List<JCube>> CubeList = new Dictionary<string, List<JCube>>
|
||||
{
|
||||
{"HEAD", new List<JCube>()},
|
||||
{"BODY", new List<JCube>()},
|
||||
{"ARM0", new List<JCube>()},
|
||||
{"ARM1", new List<JCube>()},
|
||||
{"LEG0", new List<JCube>()},
|
||||
{"LEG1", new List<JCube>()}
|
||||
};
|
||||
|
||||
foreach (List<string> 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<string, List<JCube>> 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<List<string>> SplitToSublists(List<string> 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +170,9 @@
|
||||
<Compile Include="Classes\API\PCKCenter\PCKCollections.cs" />
|
||||
<Compile Include="Classes\API\PCKCenter\PCKCollectionsLocal.cs" />
|
||||
<Compile Include="Classes\API\PCKCenter\SaveLocalJSON.cs" />
|
||||
<Compile Include="Classes\Extensions\BlendMode.cs" />
|
||||
<Compile Include="Classes\Extensions\EnumerableExtensions.cs" />
|
||||
<Compile Include="Classes\Extensions\GraphicsExtensions.cs" />
|
||||
<Compile Include="Classes\Conversion\Bedrock\BedrockSkinExporter.cs" />
|
||||
<Compile Include="Classes\Conversion\Bedrock\FileExportContext.cs" />
|
||||
<Compile Include="Classes\Conversion\Bedrock\IExportContext.cs" />
|
||||
@@ -185,11 +188,11 @@
|
||||
<Compile Include="Classes\Conversion\Bedrock\ZipExportContext.cs" />
|
||||
<Compile Include="Classes\Conversion\Legacy\JsonDefinitions\BlockbenchBedrockModel.cs" />
|
||||
<Compile Include="Classes\Conversion\Legacy\LegacySkinExporter.cs" />
|
||||
<Compile Include="Classes\Extentions\EnumerableExtentions.cs" />
|
||||
<Compile Include="Classes\FileTypes\CSMBFile.cs" />
|
||||
<Compile Include="Classes\FileTypes\PCKAudioFile.cs" />
|
||||
<Compile Include="Classes\FileTypes\Binka.cs" />
|
||||
<Compile Include="Classes\FileTypes\CSM.cs" />
|
||||
<Compile Include="Classes\IO\3DST\3DSTextureReader.cs" />
|
||||
<Compile Include="Classes\IO\3DST\3DSTextureWriter.cs" />
|
||||
<Compile Include="Classes\IO\CSMB\CSMBFileReader.cs" />
|
||||
<Compile Include="Classes\IO\CSMB\CSMBFileWriter.cs" />
|
||||
<Compile Include="Classes\IO\PCK\PCKAudioFileReader.cs" />
|
||||
@@ -198,12 +201,9 @@
|
||||
<Compile Include="Classes\IO\Sounds\Sounds.cs" />
|
||||
<Compile Include="Classes\Misc\FTPClient.cs" />
|
||||
<Compile Include="Classes\Models\DefaultModels\Steve64x64Model.cs" />
|
||||
<Compile Include="Classes\Utils\3DS\3DSUtil.cs" />
|
||||
<Compile Include="Classes\Utils\ARC\ARCUtil.cs" />
|
||||
<Compile Include="Classes\Extentions\ImageExtentions.cs" />
|
||||
<Compile Include="Classes\Extensions\ImageExtensions.cs" />
|
||||
<Compile Include="Classes\Utils\SkinANIM.cs" />
|
||||
<Compile Include="Classes\IO\StreamDataReader.cs" />
|
||||
<Compile Include="Classes\IO\StreamDataWriter.cs" />
|
||||
<Compile Include="Classes\Models\DefaultModels\Steve64x32Model.cs" />
|
||||
<Compile Include="Classes\Models\DefaultModels\ModelBase.cs" />
|
||||
<Compile Include="Classes\Models\DefaultModels\Texture.cs" />
|
||||
@@ -432,7 +432,7 @@
|
||||
<Compile Include="Forms\Utilities\installWiiU.Designer.cs">
|
||||
<DependentUpon>installWiiU.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Classes\Utils\ListUtils.cs" />
|
||||
<Compile Include="Classes\Extensions\ListExtensions.cs" />
|
||||
<Compile Include="Forms\Utilities\PCK Manager.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -480,7 +480,7 @@
|
||||
<DependentUpon>CreditsForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Classes\Utils\3DS\TextureCodec.cs" />
|
||||
<Compile Include="Classes\IO\3DST\TextureCodec.cs" />
|
||||
<EmbeddedResource Include="Forms\Additional-Popups\EntityForms\AddEntry.resx">
|
||||
<DependentUpon>AddEntry.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
||||
30
README.md
30
README.md
@@ -1,8 +1,8 @@
|
||||
# PCK Studio
|
||||
Modify .PCK archives as you please!
|
||||
Modify .PCK archives as you please!<br>
|
||||
**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)<br>
|
||||
> [MattNL](https://github.com/MattN-L)<br>
|
||||
> [Miku-666](https://github.com/NessieHax)<br>
|
||||
> [EternalModz](https://github.com/EternalModz)<br>
|
||||
|
||||
## 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)<br>
|
||||
> [jam1garner](https://github.com/jam1garner)<br>
|
||||
> [XxModZxXWiiPlaza](https://github.com/XxModZxXWiiPlaza)<br>
|
||||
> [SlothWiiPlaza](https://github.com/Kashiiera)<br>
|
||||
|
||||
## Other Credits
|
||||
* [yaboiFoxx](https://github.com/yaboiFoxx) for Improved UI concept
|
||||
|
||||
2
Vendor/OMI-Lib
vendored
2
Vendor/OMI-Lib
vendored
Submodule Vendor/OMI-Lib updated: 9b991f6d1a...806fde8e51
Reference in New Issue
Block a user