mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-06-13 03:56:17 +00:00
Merge branch 'main' into '3dSkinRenderer'
This commit is contained in:
60
PCK-Studio/Classes/IO/TGA/TGADataTypeCode.cs
Normal file
60
PCK-Studio/Classes/IO/TGA/TGADataTypeCode.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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.
|
||||
**/
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
internal enum TGADataTypeCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// No image data included.
|
||||
/// </summary>
|
||||
NO_DATA = 0,
|
||||
/// <summary>
|
||||
/// Uncompressed, color-mapped images.
|
||||
/// </summary>
|
||||
COLORMAPPED = 1,
|
||||
/// <summary>
|
||||
/// Uncompressed, RGB images.
|
||||
/// </summary>
|
||||
RGB = 2,
|
||||
/// <summary>
|
||||
/// Uncompressed, black and white images.
|
||||
/// </summary>
|
||||
BLACK_WHITE = 3,
|
||||
/// <summary>
|
||||
/// Runlength encoded color-mapped images.
|
||||
/// </summary>
|
||||
RLE_COLORMAPPED = 9,
|
||||
/// <summary>
|
||||
/// Runlength encoded RGB images.
|
||||
/// </summary>
|
||||
RLE_RGB = 10,
|
||||
/// <summary>
|
||||
/// Compressed, black and white images.
|
||||
/// </summary>
|
||||
COMPRESSED_BLACK_WHITE = 11,
|
||||
/// <summary>
|
||||
/// Compressed color-mapped data, using Huffman, Delta, and runlength encoding.
|
||||
/// </summary>
|
||||
COMPRESSED_RLE_COLORMAPPED = 32,
|
||||
/// <summary>
|
||||
/// Compressed color-mapped data, using Huffman, Delta, and runlength encoding. 4-pass quadtree-type process.
|
||||
/// </summary>
|
||||
COMPRESSED_RLE_COLORMAPPED_4 = 33,
|
||||
}
|
||||
}
|
||||
33
PCK-Studio/Classes/IO/TGA/TGADeserializer.cs
Normal file
33
PCK-Studio/Classes/IO/TGA/TGADeserializer.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
/* 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.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
internal static class TGADeserializer
|
||||
{
|
||||
private static TGAReader reader = new TGAReader();
|
||||
|
||||
public static Image DeserializeFromStream(Stream stream)
|
||||
{
|
||||
TGAFileData tgaImg = reader.FromStream(stream);
|
||||
return tgaImg.Bitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
PCK-Studio/Classes/IO/TGA/TGAException.cs
Normal file
25
PCK-Studio/Classes/IO/TGA/TGAException.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
[Serializable]
|
||||
internal class TGAException : Exception
|
||||
{
|
||||
public TGAException()
|
||||
{
|
||||
}
|
||||
|
||||
public TGAException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public TGAException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected TGAException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
63
PCK-Studio/Classes/IO/TGA/TGAExtentionData.cs
Normal file
63
PCK-Studio/Classes/IO/TGA/TGAExtentionData.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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.Windows.Forms;
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
internal struct TGAExtentionData
|
||||
{
|
||||
public const short ExtensionSize = 0x1EF;
|
||||
public string AuthorName;
|
||||
public string AuthorComment;
|
||||
public DateTime TimeStamp;
|
||||
public string JobID;
|
||||
public TimeSpan JobTime;
|
||||
public string SoftwareID;
|
||||
public byte[] SoftwareVersion;
|
||||
public int KeyColor;
|
||||
public int PixelAspectRatio;
|
||||
public int GammaValue;
|
||||
public int ColorCorrectionOffset;
|
||||
public int PostageStampOffset;
|
||||
public int ScanLineOffset;
|
||||
public byte AttributesType;
|
||||
|
||||
public static TGAExtentionData Create()
|
||||
{
|
||||
var extensionData = new TGAExtentionData();
|
||||
extensionData.AuthorName = "";
|
||||
extensionData.AuthorComment = "";
|
||||
extensionData.AuthorComment = "";
|
||||
extensionData.TimeStamp = DateTime.Now;
|
||||
extensionData.JobID = "";
|
||||
extensionData.JobTime = new TimeSpan(extensionData.TimeStamp.Hour, extensionData.TimeStamp.Minute, extensionData.TimeStamp.Second);
|
||||
extensionData.SoftwareID = Application.ProductName;
|
||||
Version.TryParse(Application.ProductVersion, out Version currentVersion);
|
||||
extensionData.SoftwareVersion = [(byte)currentVersion.Major, (byte)currentVersion.Minor, (byte)currentVersion.Build];
|
||||
extensionData.KeyColor = 0;
|
||||
extensionData.PixelAspectRatio = 0;
|
||||
extensionData.GammaValue = 0;
|
||||
extensionData.ColorCorrectionOffset = 0;
|
||||
extensionData.PostageStampOffset = 0;
|
||||
extensionData.ScanLineOffset = 0;
|
||||
extensionData.AttributesType = 3;
|
||||
return extensionData;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
PCK-Studio/Classes/IO/TGA/TGAFileData.cs
Normal file
41
PCK-Studio/Classes/IO/TGA/TGAFileData.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
/* 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.IO;
|
||||
using System.Drawing;
|
||||
using System;
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
internal class TGAFileData
|
||||
{
|
||||
public TGAFileData(TGAHeader header, Image bitmap, TGAFooter footer, TGAExtentionData extentionData)
|
||||
{
|
||||
if (bitmap.Width != header.Width || bitmap.Height != header.Height)
|
||||
throw new InvalidDataException("Header resolution doesn't match Image resolution");
|
||||
Header = header;
|
||||
Bitmap = bitmap;
|
||||
Footer = footer;
|
||||
ExtentionData = extentionData;
|
||||
}
|
||||
|
||||
public readonly TGAHeader Header;
|
||||
public readonly Image Bitmap;
|
||||
public readonly TGAFooter Footer;
|
||||
public readonly TGAExtentionData ExtentionData;
|
||||
}
|
||||
}
|
||||
27
PCK-Studio/Classes/IO/TGA/TGAFooter.cs
Normal file
27
PCK-Studio/Classes/IO/TGA/TGAFooter.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
/* 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.
|
||||
**/
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
internal struct TGAFooter
|
||||
{
|
||||
internal const string Signature = "TRUEVISION-XFILE";
|
||||
public int ExtensionDataOffset;
|
||||
public int DeveloperAreaDataOffset;
|
||||
}
|
||||
}
|
||||
37
PCK-Studio/Classes/IO/TGA/TGAHeader.cs
Normal file
37
PCK-Studio/Classes/IO/TGA/TGAHeader.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
/* 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.
|
||||
**/
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
/// <summary>
|
||||
/// Resources:
|
||||
/// <http://www.paulbourke.net/dataformats/tga/>
|
||||
/// <https://en.wikipedia.org/wiki/Truevision_TGA>
|
||||
/// </summary>
|
||||
internal struct TGAHeader
|
||||
{
|
||||
public byte[] Id;
|
||||
public TGADataTypeCode DataTypeCode;
|
||||
public (byte Type, short Origin/*Offset*/, short Length, byte Depth) Colormap;
|
||||
public (short X, short Y) Origin;
|
||||
public short Width;
|
||||
public short Height;
|
||||
public byte BitsPerPixel;
|
||||
public byte ImageDescriptor;
|
||||
}
|
||||
}
|
||||
241
PCK-Studio/Classes/IO/TGA/TGAReader.cs
Normal file
241
PCK-Studio/Classes/IO/TGA/TGAReader.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
/* 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.IO;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using OMI.Workers;
|
||||
using OMI;
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
internal class TGAReader : IDataFormatReader<TGAFileData>, IDataFormatReader
|
||||
{
|
||||
object IDataFormatReader.FromStream(Stream stream) => FromStream(stream);
|
||||
|
||||
object IDataFormatReader.FromFile(string filename) => FromFile(filename);
|
||||
|
||||
public TGAFileData FromFile(string filename)
|
||||
{
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
using( var fs = File.OpenRead(filename) )
|
||||
{
|
||||
return FromStream(fs);
|
||||
}
|
||||
}
|
||||
throw new FileNotFoundException(filename);
|
||||
}
|
||||
|
||||
public TGAFileData FromStream(Stream stream)
|
||||
{
|
||||
using var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian);
|
||||
TGAHeader header = LoadHeader(reader);
|
||||
Image image = LoadImage(reader, header);
|
||||
TGAFooter footer = LoadFooter(reader);
|
||||
TGAExtentionData extentionData = LoadExtentionData(reader, footer);
|
||||
return new TGAFileData(header, image, footer, extentionData);
|
||||
}
|
||||
|
||||
private static void TGA_HandleRGB(EndiannessAwareBinaryReader reader, TGAHeader header, BitmapData bitmapData)
|
||||
{
|
||||
int bytesPerPixel = header.BitsPerPixel / 8;
|
||||
|
||||
byte[] data = reader.ReadBytes(header.Height * header.Width * bytesPerPixel);
|
||||
Marshal.Copy(data, 0, bitmapData.Scan0, data.Length);
|
||||
}
|
||||
|
||||
private static void TGA_HandleNoData(EndiannessAwareBinaryReader _, TGAHeader header, BitmapData bitmapData)
|
||||
{
|
||||
Random r = new Random();
|
||||
byte[] bytes = new byte[bitmapData.Width * bitmapData.Height * 4];
|
||||
r.NextBytes(bytes);
|
||||
Marshal.Copy(bytes, 0, bitmapData.Scan0, bytes.Length);
|
||||
}
|
||||
|
||||
private static TGAHeader LoadHeader(EndiannessAwareBinaryReader reader)
|
||||
{
|
||||
var header = new TGAHeader();
|
||||
byte[] bytes = reader.ReadBytes(3);
|
||||
(var headerIdLength, header.Colormap.Type, header.DataTypeCode) = (bytes[0], bytes[1], (TGADataTypeCode)bytes[2]);
|
||||
header.Colormap.Origin = reader.ReadInt16();
|
||||
header.Colormap.Length = reader.ReadInt16();
|
||||
header.Colormap.Depth = reader.ReadByte();
|
||||
header.Origin.X = reader.ReadInt16();
|
||||
header.Origin.Y = reader.ReadInt16();
|
||||
header.Width = reader.ReadInt16();
|
||||
header.Height = reader.ReadInt16();
|
||||
header.BitsPerPixel = reader.ReadByte();
|
||||
header.ImageDescriptor = reader.ReadByte();
|
||||
header.Id = reader.ReadBytes(headerIdLength);
|
||||
DebugLogHeader(header);
|
||||
return header;
|
||||
}
|
||||
|
||||
private static PixelFormat GetPixelFormat(int bytesPerPixel)
|
||||
{
|
||||
return bytesPerPixel switch
|
||||
{
|
||||
2 => PixelFormat.Format16bppArgb1555,
|
||||
3 => PixelFormat.Format24bppRgb,
|
||||
4 => PixelFormat.Format32bppArgb,
|
||||
_ => throw new NotSupportedException(nameof(bytesPerPixel))
|
||||
};
|
||||
}
|
||||
|
||||
private static Image LoadImage(EndiannessAwareBinaryReader reader, TGAHeader header)
|
||||
{
|
||||
if (header.DataTypeCode != TGADataTypeCode.RGB)
|
||||
throw new NotSupportedException(nameof(header.DataTypeCode));
|
||||
|
||||
Bitmap bitmap = new Bitmap(header.Width, header.Height);
|
||||
BitmapData bitmapData = bitmap.LockBits(
|
||||
new Rectangle(0, 0, header.Width, header.Height),
|
||||
ImageLockMode.WriteOnly,
|
||||
GetPixelFormat(header.BitsPerPixel >> 3));
|
||||
|
||||
if (header.DataTypeCode == TGADataTypeCode.NO_DATA)
|
||||
{
|
||||
TGA_HandleNoData(reader, header, bitmapData);
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
TGA_HandleRGB(reader, header, bitmapData);
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private static TGAFooter LoadFooter(EndiannessAwareBinaryReader reader)
|
||||
{
|
||||
long origin = reader.BaseStream.Position;
|
||||
reader.BaseStream.Seek(-26, SeekOrigin.End);
|
||||
|
||||
TGAFooter footer = new TGAFooter();
|
||||
|
||||
footer.ExtensionDataOffset = reader.ReadInt32(); // optional
|
||||
footer.DeveloperAreaDataOffset = reader.ReadInt32(); // optional
|
||||
string signature = reader.ReadString(16);
|
||||
Debug.Assert(signature.Equals(TGAFooter.Signature) || reader.ReadInt16() != 0x002E,
|
||||
"Footer signature invalid");
|
||||
reader.BaseStream.Seek(origin, SeekOrigin.Begin);
|
||||
DebugLogFooter(footer);
|
||||
return footer;
|
||||
}
|
||||
|
||||
private static TGAExtentionData LoadExtentionData(EndiannessAwareBinaryReader reader, TGAFooter footer)
|
||||
{
|
||||
if (footer.ExtensionDataOffset > 0)
|
||||
{
|
||||
reader.BaseStream.Seek(footer.ExtensionDataOffset, SeekOrigin.Begin);
|
||||
if (reader.ReadInt16() == TGAExtentionData.ExtensionSize)
|
||||
{
|
||||
TGAExtentionData extentionData = new TGAExtentionData();
|
||||
extentionData.AuthorName = reader.ReadString(41);
|
||||
extentionData.AuthorComment = reader.ReadString(324);
|
||||
short month = reader.ReadInt16();
|
||||
short day = reader.ReadInt16();
|
||||
short year = reader.ReadInt16();
|
||||
short hour = reader.ReadInt16();
|
||||
short minute = reader.ReadInt16();
|
||||
short second = reader.ReadInt16();
|
||||
extentionData.TimeStamp = new DateTime(year, month, day, hour, minute, second);
|
||||
extentionData.JobID = reader.ReadString(41);
|
||||
extentionData.JobTime = new TimeSpan(
|
||||
hours: reader.ReadInt16(),
|
||||
minutes: reader.ReadInt16(),
|
||||
seconds: reader.ReadInt16()
|
||||
);
|
||||
extentionData.SoftwareID = reader.ReadString(41);
|
||||
extentionData.SoftwareVersion = reader.ReadBytes(3);
|
||||
extentionData.KeyColor = reader.ReadInt32();
|
||||
extentionData.PixelAspectRatio = reader.ReadInt32();
|
||||
extentionData.GammaValue = reader.ReadInt32();
|
||||
extentionData.ColorCorrectionOffset = reader.ReadInt32();
|
||||
extentionData.PostageStampOffset = reader.ReadInt32();
|
||||
extentionData.ScanLineOffset = reader.ReadInt32();
|
||||
extentionData.AttributesType = reader.ReadByte();
|
||||
DebugLogExtentionData(extentionData);
|
||||
return extentionData;
|
||||
}
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
[DebuggerHidden]
|
||||
[DebuggerStepThrough]
|
||||
private static void DebugLogExtentionData(TGAExtentionData extentionData)
|
||||
{
|
||||
Debug.WriteLine("-------Extention Data-------", category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Author Name: {0}", args: extentionData.AuthorName), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Author Comment: {0}", args: extentionData.AuthorComment), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Time Stamp: {0}", args: extentionData.TimeStamp), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Job ID: {0}", args: extentionData.JobID), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Job Time: {0}", args: extentionData.JobTime), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("SoftwareID: {0}", args: extentionData.SoftwareID), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Software Version: {0}.{1}.{2}", extentionData.SoftwareVersion[0], extentionData.SoftwareVersion[1], extentionData.SoftwareVersion[2]), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Key Color: {0}", args: extentionData.KeyColor), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Pixel Aspect Ratio: {0}", args: extentionData.PixelAspectRatio), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Gamma Value: {0}", args: extentionData.GammaValue), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Color Correction Offset: {0}", args: extentionData.ColorCorrectionOffset), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Postage Stamp Offset: {0}", args: extentionData.PostageStampOffset), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Scan Line Offset: {0}", args: extentionData.ScanLineOffset), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Attributes Type: {0}", args: extentionData.AttributesType), category: nameof(TGAReader));
|
||||
Debug.WriteLine("----------------------------", category: nameof(TGAReader));
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
[DebuggerHidden]
|
||||
[DebuggerStepThrough]
|
||||
private static void DebugLogHeader(TGAHeader header)
|
||||
{
|
||||
Debug.WriteLine("------Header Data------", category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("ID length: {0}", args: header.Id.Length), category: nameof(TGAReader));
|
||||
Debug.WriteLineIf(header.Id.Length > 0, $"ID: {header.Id}", category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Colourmap type: {0}", args: header.Colormap.Type), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Image type: {0}", args: header.DataTypeCode), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Colour map offset: {0}", args: header.Colormap.Origin), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Colour map length: {0}", args: header.Colormap.Length), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Colour map depth: {0}", args: header.Colormap.Depth), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("X origin: {0}", args: header.Origin.X), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Y origin: {0}", args: header.Origin.Y), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Width: {0}", args: header.Width), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Height: {0}", args: header.Height), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Bits per pixel: {0}", args: header.BitsPerPixel), category: nameof(TGAReader));
|
||||
Debug.WriteLine(string.Format("Descriptor: {0}", args: header.ImageDescriptor), category: nameof(TGAReader));
|
||||
Debug.WriteLine("-----------------------", category: nameof(TGAReader));
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
[DebuggerHidden]
|
||||
[DebuggerStepThrough]
|
||||
private static void DebugLogFooter(TGAFooter footer)
|
||||
{
|
||||
Debug.WriteLine("-------Footer Data-------", category: nameof(TGAReader));
|
||||
Debug.WriteLine($"Extension Data Offset: {footer.ExtensionDataOffset:x}", category: nameof(TGAReader));
|
||||
Debug.WriteLine($"Developer Area Data Offset: {footer.DeveloperAreaDataOffset:x}", category: nameof(TGAReader));
|
||||
Debug.WriteLine("-----------------------", category: nameof(TGAReader));
|
||||
}
|
||||
}
|
||||
}
|
||||
32
PCK-Studio/Classes/IO/TGA/TGASerializer.cs
Normal file
32
PCK-Studio/Classes/IO/TGA/TGASerializer.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
/* 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.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
internal static class TGASerializer
|
||||
{
|
||||
private static TGAWriter writer = new TGAWriter();
|
||||
|
||||
public static void SerializeToStream(ref Stream stream, Image image)
|
||||
{
|
||||
writer.WriteToStream(stream, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
143
PCK-Studio/Classes/IO/TGA/TGAWriter.cs
Normal file
143
PCK-Studio/Classes/IO/TGA/TGAWriter.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
/* 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.IO;
|
||||
using System.Drawing;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using OMI;
|
||||
using System.Windows.Forms;
|
||||
using DiscordRPC;
|
||||
|
||||
namespace PckStudio.IO.TGA
|
||||
{
|
||||
internal class TGAWriter
|
||||
{
|
||||
private Bitmap _bitmap;
|
||||
private int extensionDataOffset = 0;
|
||||
|
||||
public TGAWriter()
|
||||
{
|
||||
}
|
||||
|
||||
private void WriteHeader(EndiannessAwareBinaryWriter writer)
|
||||
{
|
||||
writer.Write(new byte[]
|
||||
{
|
||||
0, // header.Id.Length
|
||||
0, // colormap type
|
||||
(byte)TGADataTypeCode.RGB
|
||||
});
|
||||
writer.Write(0); // Colormap.Origin
|
||||
writer.Write(0); // Colormap.Length
|
||||
writer.Write(0); // Colormap.Depth
|
||||
writer.Write(0); // Origin.X
|
||||
writer.Write(0); // Origin.Y
|
||||
writer.Write(_bitmap.Width);
|
||||
writer.Write(_bitmap.Height);
|
||||
writer.Write(32); // BitsPerPixel
|
||||
writer.Write(8); // ImageDescriptor
|
||||
}
|
||||
|
||||
private void WriteImage(EndiannessAwareBinaryWriter writer)
|
||||
{
|
||||
_bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||
BitmapData bitmapData = _bitmap.LockBits(
|
||||
new Rectangle(0, 0, _bitmap.Width, _bitmap.Height),
|
||||
ImageLockMode.ReadOnly,
|
||||
PixelFormat.Format32bppArgb);
|
||||
|
||||
byte[] buffer = new byte[_bitmap.Width * _bitmap.Height * 4];
|
||||
Marshal.Copy(bitmapData.Scan0, buffer, 0, _bitmap.Width * _bitmap.Height * 4);
|
||||
writer.Write(buffer);
|
||||
}
|
||||
|
||||
private void WriteFooter(EndiannessAwareBinaryWriter writer)
|
||||
{
|
||||
writer.Write(extensionDataOffset); // extensionDataOffset
|
||||
writer.Write(0); // developerAreaDataOffset
|
||||
writer.WriteString(TGAFooter.Signature);
|
||||
writer.Write((byte)0x2E);
|
||||
writer.Write((byte)0x00);
|
||||
}
|
||||
|
||||
private void WriteExtensionData(EndiannessAwareBinaryWriter writer)
|
||||
{
|
||||
extensionDataOffset = Convert.ToInt32(writer.BaseStream.Position);
|
||||
TGAExtentionData extentionData = TGAExtentionData.Create();
|
||||
writer.Write(TGAExtentionData.ExtensionSize);
|
||||
// Author Name
|
||||
writer.WriteString(extentionData.AuthorName, 41);
|
||||
// Author Comment
|
||||
writer.WriteString(extentionData.AuthorComment, 324);
|
||||
// Timestamp
|
||||
writer.Write((short)extentionData.TimeStamp.Month);
|
||||
writer.Write((short)extentionData.TimeStamp.Day);
|
||||
writer.Write((short)extentionData.TimeStamp.Year);
|
||||
writer.Write((short)extentionData.TimeStamp.Hour);
|
||||
writer.Write((short)extentionData.TimeStamp.Minute);
|
||||
writer.Write((short)extentionData.TimeStamp.Second);
|
||||
// Job id
|
||||
writer.WriteString(extentionData.JobID, 41);
|
||||
// Job time
|
||||
writer.Write((short)extentionData.JobTime.Hours);
|
||||
writer.Write((short)extentionData.JobTime.Minutes);
|
||||
writer.Write((short)extentionData.JobTime.Seconds);
|
||||
// Software Id
|
||||
writer.WriteString(extentionData.SoftwareID, 41);
|
||||
// Software version
|
||||
writer.Write(extentionData.SoftwareVersion, 0, 3);
|
||||
// Key color
|
||||
writer.Write(extentionData.KeyColor);
|
||||
// Pixel aspect ratio
|
||||
writer.Write(extentionData.PixelAspectRatio);
|
||||
// Gamma value
|
||||
writer.Write(extentionData.GammaValue);
|
||||
// Color correction offset
|
||||
writer.Write(extentionData.ColorCorrectionOffset);
|
||||
// Postage stamp offset
|
||||
writer.Write(extentionData.PostageStampOffset);
|
||||
// Scan line offset
|
||||
writer.Write(extentionData.ScanLineOffset);
|
||||
// Attributes type
|
||||
writer.Write(extentionData.AttributesType);
|
||||
}
|
||||
|
||||
public void WriteToStream(Stream stream, Image image)
|
||||
{
|
||||
_bitmap = new Bitmap(image);
|
||||
using (var writer = new EndiannessAwareBinaryWriter(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian))
|
||||
{
|
||||
WriteHeader(writer);
|
||||
WriteImage(writer);
|
||||
WriteExtensionData(writer);
|
||||
WriteFooter(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteToFile(string filename, Image image)
|
||||
{
|
||||
using (var fs = File.OpenWrite(filename))
|
||||
{
|
||||
WriteToStream(fs, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ using OMI.Formats.Languages;
|
||||
using OMI.Formats.Pck;
|
||||
using OMI.Workers;
|
||||
using PckStudio.Internal;
|
||||
using PckStudio.IO.TGA;
|
||||
|
||||
namespace PckStudio.Extensions
|
||||
{
|
||||
@@ -32,7 +33,10 @@ namespace PckStudio.Extensions
|
||||
|
||||
try
|
||||
{
|
||||
return Image.FromStream(stream);
|
||||
if (Path.GetExtension(file.Filename) == ".tga")
|
||||
return TGADeserializer.DeserializeFromStream(stream);
|
||||
else
|
||||
return Image.FromStream(stream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace PckStudio
|
||||
[PckFileType.ColourTableFile] = HandleColourFile,
|
||||
[PckFileType.GameRulesHeader] = HandleGameRuleFile,
|
||||
[PckFileType.SkinDataFile] = HandleInnerPckFile,
|
||||
[PckFileType.ModelsFile] = HandleModelsFile,
|
||||
[PckFileType.ModelsFile] = null, //HandleModelsFile, // Note: Uncomment when implemented
|
||||
[PckFileType.BehavioursFile] = HandleBehavioursFile,
|
||||
[PckFileType.MaterialFile] = HandleMaterialFile,
|
||||
};
|
||||
@@ -107,6 +107,8 @@ namespace PckStudio
|
||||
|
||||
private void HandleInnerPckFile(PckFileData file)
|
||||
{
|
||||
// TODO: decide on how to handle embedded pck files
|
||||
return;
|
||||
if (Settings.Default.LoadSubPcks &&
|
||||
(file.Filetype == PckFileType.SkinDataFile || file.Filetype == PckFileType.TexturePackInfoFile) &&
|
||||
file.Size > 0 && treeViewMain.SelectedNode.Nodes.Count == 0)
|
||||
@@ -329,7 +331,7 @@ namespace PckStudio
|
||||
_ = root ?? throw new ArgumentNullException(nameof(root));
|
||||
if (!path.Contains(seperator))
|
||||
{
|
||||
var finalNode = CreateNode(path);
|
||||
TreeNode finalNode = CreateNode(path);
|
||||
root.Add(finalNode);
|
||||
return finalNode;
|
||||
}
|
||||
@@ -343,7 +345,7 @@ namespace PckStudio
|
||||
|
||||
private void BuildPckTreeView(TreeNodeCollection root, PckFile pckFile)
|
||||
{
|
||||
foreach (var file in pckFile.GetFiles())
|
||||
foreach (PckFileData file in pckFile.GetFiles())
|
||||
{
|
||||
// fix any file paths that may be incorrect
|
||||
//if (file.Filename.StartsWith(parentPath))
|
||||
@@ -408,10 +410,10 @@ namespace PckStudio
|
||||
isMapIcons || isAdditionalMapIcons || isXPOrbs || isExplosions || isBanners
|
||||
)
|
||||
{
|
||||
var img = file.GetTexture();
|
||||
Image img = file.GetTexture();
|
||||
var tile_size = new Size();
|
||||
|
||||
var banner_scale = img.Width / Resources.banners_atlas.Width;
|
||||
int banner_scale = img.Width / Resources.banners_atlas.Width;
|
||||
|
||||
if (isBanners)
|
||||
{
|
||||
@@ -422,21 +424,21 @@ namespace PckStudio
|
||||
tile_size = new Size(42 * banner_scale, 41 * banner_scale);
|
||||
}
|
||||
|
||||
// most atlases have 4 columns
|
||||
var columnCount = isBanners ? 6 : 4;
|
||||
// most atlases have 4 columns
|
||||
int columnCount = isBanners ? 6 : 4;
|
||||
|
||||
if (isTerrain || isItems || isParticles || isPaintings) columnCount = 16;
|
||||
|
||||
if (!isBanners)
|
||||
{
|
||||
var resolution = img.Width / columnCount;
|
||||
int resolution = img.Width / columnCount;
|
||||
tile_size = new Size(resolution, resolution);
|
||||
}
|
||||
|
||||
var viewer = new TextureAtlasEditor(currentPCK, file.Filename, img, tile_size);
|
||||
if (viewer.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
var texture = viewer.FinalTexture;
|
||||
Image texture = viewer.FinalTexture;
|
||||
if(isBanners)
|
||||
{
|
||||
var graphicsConfig = new GraphicsConfig()
|
||||
@@ -448,7 +450,7 @@ namespace PckStudio
|
||||
var _img = new Bitmap((Resources.banners_atlas.Width + 4) * banner_scale,
|
||||
(Resources.banners_atlas.Height + 1) * banner_scale);
|
||||
|
||||
using (var g = Graphics.FromImage(_img))
|
||||
using (Graphics g = Graphics.FromImage(_img))
|
||||
{
|
||||
g.ApplyConfig(graphicsConfig);
|
||||
g.DrawImage(texture, 0, 0, texture.Width, texture.Height);
|
||||
@@ -466,7 +468,7 @@ namespace PckStudio
|
||||
|
||||
if (!file.Filename.StartsWith("res/textures/blocks/") && !file.Filename.StartsWith("res/textures/items/"))
|
||||
return;
|
||||
var animation = AnimationHelper.GetAnimationFromFile(file);
|
||||
Animation animation = AnimationHelper.GetAnimationFromFile(file);
|
||||
using (AnimationEditor animationEditor = new AnimationEditor(animation, Path.GetFileNameWithoutExtension(file.Filename)))
|
||||
{
|
||||
if (animationEditor.ShowDialog(this) == DialogResult.OK)
|
||||
@@ -575,11 +577,7 @@ namespace PckStudio
|
||||
case PckFileType.CapeFile:
|
||||
case PckFileType.TextureFile:
|
||||
{
|
||||
// TODO: Add tga support
|
||||
if (Path.GetExtension(file.Filename) == ".tga") break;
|
||||
using MemoryStream stream = new MemoryStream(file.Data);
|
||||
|
||||
var img = Image.FromStream(stream);
|
||||
Image img = file.GetTexture();
|
||||
|
||||
if (img.RawFormat != ImageFormat.Jpeg || img.RawFormat != ImageFormat.Png)
|
||||
{
|
||||
@@ -599,7 +597,6 @@ namespace PckStudio
|
||||
Debug.WriteLine(string.Format("An error occured of type: {0} with message: {1}", ex.GetType(), ex.Message), "Exception");
|
||||
}
|
||||
|
||||
|
||||
if ((file.Filename.StartsWith("res/textures/blocks/") || file.Filename.StartsWith("res/textures/items/")) &&
|
||||
file.Filetype == PckFileType.TextureFile
|
||||
&& !file.IsMipmappedFile())
|
||||
@@ -642,7 +639,7 @@ namespace PckStudio
|
||||
if (file.PropertyCount > 0)
|
||||
{
|
||||
using var fs = File.CreateText($"{outFilePath}.txt");
|
||||
foreach (var property in file.GetProperties())
|
||||
foreach (KeyValuePair<string, string> property in file.GetProperties())
|
||||
{
|
||||
fs.WriteLine($"{property.Key}: {property.Value}");
|
||||
}
|
||||
@@ -683,7 +680,7 @@ namespace PckStudio
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var _file in currentPCK.GetFiles())
|
||||
foreach (PckFileData _file in currentPCK.GetFiles())
|
||||
{
|
||||
if (_file.Filename.StartsWith(selectedFolder))
|
||||
{
|
||||
@@ -695,7 +692,7 @@ namespace PckStudio
|
||||
|
||||
private void extractToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var node = treeViewMain.SelectedNode;
|
||||
TreeNode node = treeViewMain.SelectedNode;
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
@@ -823,7 +820,7 @@ namespace PckStudio
|
||||
|
||||
private void deleteFileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var node = treeViewMain.SelectedNode;
|
||||
TreeNode node = treeViewMain.SelectedNode;
|
||||
if (node == null)
|
||||
return;
|
||||
|
||||
@@ -841,7 +838,7 @@ namespace PckStudio
|
||||
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
|
||||
{
|
||||
string pckFolderDir = node.FullPath;
|
||||
currentPCK.RemoveAll(file => !BeforeFileRemove(file) && file.Filename.StartsWith(pckFolderDir));
|
||||
currentPCK.RemoveAll(file => file.Filename.StartsWith(pckFolderDir) && !BeforeFileRemove(file));
|
||||
node.Remove();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -870,7 +867,7 @@ namespace PckStudio
|
||||
else // folders
|
||||
{
|
||||
node.Text = diag.NewText;
|
||||
foreach (var childNode in GetAllChildNodes(node.Nodes))
|
||||
foreach (TreeNode childNode in GetAllChildNodes(node.Nodes))
|
||||
{
|
||||
if (childNode.Tag is PckFileData folderFile)
|
||||
{
|
||||
@@ -954,10 +951,10 @@ namespace PckStudio
|
||||
|
||||
private void audiopckToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (currentPCK.Contains("audio.pck", PckFileType.AudioFile))
|
||||
if (currentPCK.Contains(PckFileType.AudioFile))
|
||||
{
|
||||
// the chance of this happening is really really slim but just in case
|
||||
MessageBox.Show("There is already a file in this PCK named \"audio.pck\"!", "Can't create audio.pck");
|
||||
MessageBox.Show("There is already an audio file in this PCK!", "Can't create audio.pck");
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(saveLocation))
|
||||
@@ -966,7 +963,7 @@ namespace PckStudio
|
||||
return;
|
||||
}
|
||||
|
||||
var file = CreateNewAudioFile(LittleEndianCheckBox.Checked);
|
||||
PckFileData file = CreateNewAudioFile(LittleEndianCheckBox.Checked);
|
||||
AudioEditor diag = new AudioEditor(file, LittleEndianCheckBox.Checked);
|
||||
if (diag.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
@@ -992,7 +989,7 @@ namespace PckStudio
|
||||
$"res/textures/{Animation.GetCategoryName(diag.Category)}/{diag.SelectedTile}.png",
|
||||
PckFileType.TextureFile);
|
||||
|
||||
var animation = AnimationHelper.GetAnimationFromFile(file);
|
||||
Animation animation = AnimationHelper.GetAnimationFromFile(file);
|
||||
|
||||
using AnimationEditor animationEditor = new AnimationEditor(animation, diag.SelectedTile);
|
||||
if (animationEditor.ShowDialog() == DialogResult.OK)
|
||||
@@ -1005,6 +1002,7 @@ namespace PckStudio
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
bool IsSubPCKNode(string nodePath, string extention = ".pck")
|
||||
{
|
||||
// written by miku, implemented and modified by MattNL
|
||||
@@ -1033,13 +1031,14 @@ namespace PckStudio
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
TreeNode GetSubPCK(string childPath)
|
||||
{
|
||||
string parentPath = childPath.Replace('\\', '/');
|
||||
Debug.WriteLine(parentPath);
|
||||
string[] s = parentPath.Split('/');
|
||||
Debug.WriteLine(s.Length);
|
||||
foreach (var node in s)
|
||||
foreach (string node in s)
|
||||
{
|
||||
TreeNode parent = treeViewMain.Nodes.Find(node, true)[0];
|
||||
if (parent.TryGetTagData(out PckFileData f) &&
|
||||
@@ -1051,6 +1050,7 @@ namespace PckStudio
|
||||
return null;
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
void RebuildSubPCK(string childPath)
|
||||
{
|
||||
// Support for if a file is edited within a nested PCK File (AKA SubPCK)
|
||||
@@ -1180,7 +1180,8 @@ namespace PckStudio
|
||||
private void cloneFileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
TreeNode node = treeViewMain.SelectedNode;
|
||||
if (node == null) return;
|
||||
if (node == null || !node.IsTagOfType<PckFileData>())
|
||||
return;
|
||||
string path = node.FullPath;
|
||||
|
||||
using TextPrompt diag = new TextPrompt(node.Tag is null ? Path.GetFileName(node.FullPath) : node.FullPath);
|
||||
@@ -1301,7 +1302,7 @@ namespace PckStudio
|
||||
{
|
||||
var pack = new PckFile(3);
|
||||
|
||||
var zeroFile = pack.CreateNewFile("0", PckFileType.InfoFile);
|
||||
PckFileData zeroFile = pack.CreateNewFile("0", PckFileType.InfoFile);
|
||||
zeroFile.AddProperty("PACKID", packId);
|
||||
zeroFile.AddProperty("PACKVERSION", packVersion);
|
||||
|
||||
@@ -1319,18 +1320,17 @@ namespace PckStudio
|
||||
|
||||
private PckFile InitializeTexturePack(int packId, int packVersion, string packName, string res, bool createSkinsPCK)
|
||||
{
|
||||
var pack = InitializePack(packId, packVersion, packName, createSkinsPCK);
|
||||
PckFile pack = InitializePack(packId, packVersion, packName, createSkinsPCK);
|
||||
|
||||
PckFile infoPCK = new PckFile(3);
|
||||
|
||||
var icon = infoPCK.CreateNewFile("icon.png", PckFileType.TextureFile);
|
||||
PckFileData icon = infoPCK.CreateNewFile("icon.png", PckFileType.TextureFile);
|
||||
icon.SetData(Resources.TexturePackIcon, ImageFormat.Png);
|
||||
|
||||
var comparison = infoPCK.CreateNewFile("comparison.png", PckFileType.TextureFile);
|
||||
PckFileData comparison = infoPCK.CreateNewFile("comparison.png", PckFileType.TextureFile);
|
||||
comparison.SetData(Resources.Comparison, ImageFormat.Png);
|
||||
|
||||
var texturepackInfo = pack.CreateNewFile($"{res}/{res}Info.pck", PckFileType.TexturePackInfoFile);
|
||||
|
||||
PckFileData texturepackInfo = pack.CreateNewFile($"{res}/{res}Info.pck", PckFileType.TexturePackInfoFile);
|
||||
texturepackInfo.AddProperty("PACKID", "0");
|
||||
texturepackInfo.AddProperty("DATAPATH", $"{res}Data.pck");
|
||||
|
||||
@@ -1341,9 +1341,9 @@ namespace PckStudio
|
||||
|
||||
private PckFile InitializeMashUpPack(int packId, int packVersion, string packName, string res)
|
||||
{
|
||||
var pack = InitializeTexturePack(packId, packVersion, packName, res, true);
|
||||
var gameRuleFile = pack.CreateNewFile("GameRules.grf", PckFileType.GameRulesFile);
|
||||
var grfFile = new GameRuleFile();
|
||||
PckFile pack = InitializeTexturePack(packId, packVersion, packName, res, true);
|
||||
PckFileData gameRuleFile = pack.CreateNewFile("GameRules.grf", PckFileType.GameRulesFile);
|
||||
GameRuleFile grfFile = new GameRuleFile();
|
||||
grfFile.AddRule("MapOptions",
|
||||
new KeyValuePair<string, string>("seed", "0"),
|
||||
new KeyValuePair<string, string>("baseSaveName", string.Empty),
|
||||
@@ -1461,7 +1461,7 @@ namespace PckStudio
|
||||
if (ofd.ShowDialog() == DialogResult.OK && sfd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
PckFile pckfile = null;
|
||||
using (var fs = File.OpenRead(ofd.FileName))
|
||||
using (FileStream fs = File.OpenRead(ofd.FileName))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1487,7 +1487,7 @@ namespace PckStudio
|
||||
//attempts to generate reimportable metadata file out of minefiles metadata
|
||||
string metaData = "";
|
||||
|
||||
foreach (var entry in file.GetProperties())
|
||||
foreach (KeyValuePair<string, string> entry in file.GetProperties())
|
||||
{
|
||||
metaData += $"{entry.Key}: {entry.Value}{Environment.NewLine}";
|
||||
}
|
||||
@@ -1839,9 +1839,9 @@ namespace PckStudio
|
||||
{
|
||||
pckOpen.Image = Resources.pckDrop;
|
||||
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
foreach (var file in files)
|
||||
foreach (string file in files)
|
||||
{
|
||||
var ext = Path.GetExtension(file);
|
||||
string ext = Path.GetExtension(file);
|
||||
if (ext.Equals(".pck", StringComparison.CurrentCultureIgnoreCase))
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
return;
|
||||
@@ -1890,6 +1890,7 @@ namespace PckStudio
|
||||
node.SelectedImageIndex = 3;
|
||||
break;
|
||||
case PckFileType.TexturePackInfoFile:
|
||||
goto default;
|
||||
node.ImageIndex = 4;
|
||||
node.SelectedImageIndex = 4;
|
||||
break;
|
||||
@@ -1898,10 +1899,12 @@ namespace PckStudio
|
||||
node.SelectedImageIndex = 6;
|
||||
break;
|
||||
case PckFileType.ModelsFile:
|
||||
goto default;
|
||||
node.ImageIndex = 8;
|
||||
node.SelectedImageIndex = 8;
|
||||
break;
|
||||
case PckFileType.SkinDataFile:
|
||||
goto default;
|
||||
node.ImageIndex = 7;
|
||||
node.SelectedImageIndex = 7;
|
||||
break;
|
||||
@@ -1955,18 +1958,23 @@ namespace PckStudio
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
private void addTextureToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
using OpenFileDialog fileDialog = new OpenFileDialog();
|
||||
fileDialog.Filter = "Texture File(*.png;*.tga)|*.png;*.tga";
|
||||
fileDialog.Filter = "Texture File(*.png,*.tga)|*.png;*.tga";
|
||||
if (fileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
using TextPrompt renamePrompt = new TextPrompt(Path.GetFileName(fileDialog.FileName));
|
||||
renamePrompt.LabelText = "Path";
|
||||
if (renamePrompt.ShowDialog() == DialogResult.OK && !string.IsNullOrEmpty(renamePrompt.NewText))
|
||||
{
|
||||
var file = currentPCK.CreateNewFile(renamePrompt.NewText, PckFileType.TextureFile);
|
||||
file.SetData(File.ReadAllBytes(fileDialog.FileName));
|
||||
if (currentPCK.Contains(renamePrompt.NewText, PckFileType.TextureFile))
|
||||
{
|
||||
MessageBox.Show($"'{renamePrompt.NewText}' already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
PckFileData file = currentPCK.CreateNewFile(renamePrompt.NewText, PckFileType.TextureFile, () => File.ReadAllBytes(fileDialog.FileName));
|
||||
BuildMainTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -1998,9 +2006,6 @@ namespace PckStudio
|
||||
|
||||
string textureExtension = Path.GetExtension(file.Filename);
|
||||
|
||||
// TGA is not yet supported
|
||||
if (textureExtension == ".tga") return;
|
||||
|
||||
using NumericPrompt numericPrompt = new NumericPrompt(0);
|
||||
numericPrompt.Minimum = 1;
|
||||
numericPrompt.Maximum = 4; // 5 is the presumed max MipMap level
|
||||
@@ -2049,7 +2054,7 @@ namespace PckStudio
|
||||
MessageBox.Show("A color table file already exists in this PCK and a new one cannot be created.", "Operation aborted");
|
||||
return;
|
||||
}
|
||||
var newColorFile = currentPCK.CreateNewFile("colours.col", PckFileType.ColourTableFile);
|
||||
PckFileData newColorFile = currentPCK.CreateNewFile("colours.col", PckFileType.ColourTableFile);
|
||||
newColorFile.SetData(Resources.tu69colours);
|
||||
BuildMainTreeView();
|
||||
}
|
||||
@@ -2084,7 +2089,7 @@ namespace PckStudio
|
||||
{
|
||||
if (input.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
foreach (var line in input.TextOutput)
|
||||
foreach (string line in input.TextOutput)
|
||||
{
|
||||
int idx = line.IndexOf(' ');
|
||||
if (idx == -1 || line.Length - 1 == idx)
|
||||
@@ -2104,7 +2109,7 @@ namespace PckStudio
|
||||
if (treeViewMain.SelectedNode.TryGetTagData(out PckFileData file) &&
|
||||
file.Filetype == PckFileType.SkinFile)
|
||||
{
|
||||
foreach (var p in file.GetProperties())
|
||||
foreach (KeyValuePair<string, string> p in file.GetProperties())
|
||||
{
|
||||
if (p.Key == "BOX" || p.Key == "OFFSET")
|
||||
file.SetProperty(file.GetPropertyIndex(p), new KeyValuePair<string, string>(p.Key, p.Value.Replace(',', '.')));
|
||||
@@ -2139,13 +2144,13 @@ namespace PckStudio
|
||||
{
|
||||
if (treeViewMain.SelectedNode.TryGetTagData(out PckFileData file))
|
||||
{
|
||||
var props = file.GetProperties().Select(p => p.Key + " " + p.Value);
|
||||
using (var input = new MultiTextPrompt(props.ToArray()))
|
||||
string[] props = file.GetProperties().Select(p => p.Key + " " + p.Value).ToArray();
|
||||
using (var input = new MultiTextPrompt(props))
|
||||
{
|
||||
if (input.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
file.ClearProperties();
|
||||
foreach (var line in input.TextOutput)
|
||||
foreach (string line in input.TextOutput)
|
||||
{
|
||||
int idx = line.IndexOf(' ');
|
||||
if (idx == -1 || line.Length - 1 == idx)
|
||||
@@ -2163,7 +2168,8 @@ namespace PckStudio
|
||||
private void addFileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
using var ofd = new OpenFileDialog();
|
||||
// Suddenly, and randomly, this started throwing an exception because it wasn't formatted correctly? So now it's formatted correctly and now displays the file type name in the dialog.
|
||||
// Suddenly, and randomly, this started throwing an exception because it wasn't formatted correctly?
|
||||
// So now it's formatted correctly and now displays the file type name in the dialog.
|
||||
ofd.Filter = "All files (*.*)|*.*";
|
||||
ofd.Multiselect = false;
|
||||
|
||||
@@ -2172,13 +2178,14 @@ namespace PckStudio
|
||||
using AddFilePrompt diag = new AddFilePrompt("res/" + Path.GetFileName(ofd.FileName));
|
||||
if (diag.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
PckFileData file = currentPCK.CreateNewFile(
|
||||
diag.Filepath,
|
||||
diag.Filetype,
|
||||
() => File.ReadAllBytes(ofd.FileName));
|
||||
if (currentPCK.Contains(diag.Filepath, diag.Filetype))
|
||||
{
|
||||
MessageBox.Show($"'{diag.Filepath}' of type {diag.Filetype} already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
PckFileData file = currentPCK.CreateNewFile(diag.Filepath, diag.Filetype, () => File.ReadAllBytes(ofd.FileName));
|
||||
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
//else treeViewMain.Nodes.Add();
|
||||
|
||||
BuildMainTreeView();
|
||||
wasModified = true;
|
||||
@@ -2316,10 +2323,11 @@ namespace PckStudio
|
||||
[Obsolete] // the move functions are to eventually be removed in favor of drag and drop
|
||||
private void moveFile(int amount)
|
||||
{
|
||||
if (treeViewMain.SelectedNode is not TreeNode t || t.Tag is null) return;
|
||||
if (treeViewMain.SelectedNode is not TreeNode t || t.Tag is not PckFileData)
|
||||
return;
|
||||
|
||||
var file = t.Tag as PckFileData;
|
||||
var path = t.FullPath;
|
||||
PckFileData file = t.Tag as PckFileData;
|
||||
string path = t.FullPath;
|
||||
|
||||
// skin and cape files only
|
||||
if (!(file.Filetype == PckFileType.SkinFile || file.Filetype == PckFileType.CapeFile)) return;
|
||||
|
||||
@@ -134,6 +134,8 @@
|
||||
<Reference Include="WindowsFormsIntegration" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Classes\IO\TGA\TGADeserializer.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGASerializer.cs" />
|
||||
<Compile Include="Extensions\LocFileExtensions.cs" />
|
||||
<Compile Include="Extensions\CursorExtensions.cs" />
|
||||
<Compile Include="Extensions\PckFileDataExtensions.cs" />
|
||||
@@ -145,6 +147,7 @@
|
||||
<Compile Include="Internal\SkinPartOffset.cs" />
|
||||
<Compile Include="Helper\AnimationHelper.cs" />
|
||||
<Compile Include="Internal\AnimationCategory.cs" />
|
||||
<Compile Include="Internal\CommitInfo.cs" />
|
||||
<Compile Include="Internal\SkinAnimFlag.cs" />
|
||||
<Compile Include="Internal\SkinAnimMask.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
@@ -264,7 +267,14 @@
|
||||
<Compile Include="Features\WiiUPanel.Designer.cs">
|
||||
<DependentUpon>WiiUPanel.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Internal\CommitInfo.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGAFileData.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGADataTypeCode.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGAException.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGAExtentionData.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGAFooter.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGAHeader.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGAReader.cs" />
|
||||
<Compile Include="Classes\IO\TGA\TGAWriter.cs" />
|
||||
<Compile Include="Forms\Additional-Popups\EntityForms\AddEntry.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
||||
2
Vendor/OMI-Lib
vendored
2
Vendor/OMI-Lib
vendored
Submodule Vendor/OMI-Lib updated: 40795ea8a5...9ec8c2228b
Reference in New Issue
Block a user