|
@@ -13,12 +13,12 @@ using Squish;
|
|
namespace ArcToolkitCLI.Commands.Converters
|
|
namespace ArcToolkitCLI.Commands.Converters
|
|
{
|
|
{
|
|
[Verb("tex", HelpText = "Convert TEX files into PNG and back")]
|
|
[Verb("tex", HelpText = "Convert TEX files into PNG and back")]
|
|
- internal class TexConverter : IConverterCommand, IInputOptions, IOutputOptions
|
|
|
|
|
|
+ internal class TexConverter : BaseConverter
|
|
{
|
|
{
|
|
private const string TEX_TAG = "CM3D2_TEX";
|
|
private const string TEX_TAG = "CM3D2_TEX";
|
|
private const int TEX_VERSION = 1010;
|
|
private const int TEX_VERSION = 1010;
|
|
|
|
|
|
- private readonly byte[] PNG_HEADER =
|
|
|
|
|
|
+ private readonly byte[] pngHeader =
|
|
{
|
|
{
|
|
137,
|
|
137,
|
|
80,
|
|
80,
|
|
@@ -34,58 +34,24 @@ namespace ArcToolkitCLI.Commands.Converters
|
|
|
|
|
|
public TexConverter()
|
|
public TexConverter()
|
|
{
|
|
{
|
|
- textureLoaders = new Dictionary<TextureFormat, Action<string, byte[], int, int, TextureFormat>>
|
|
|
|
|
|
+ Converters = new Dictionary<string, Func<string, int>>
|
|
{
|
|
{
|
|
- [TextureFormat.ARGB32] = ConvertFromPng,
|
|
|
|
- [TextureFormat.RGB24] = ConvertFromPng,
|
|
|
|
- [TextureFormat.DXT1] = ConvertFromDxt,
|
|
|
|
- [TextureFormat.DXT5] = ConvertFromDxt
|
|
|
|
|
|
+ [".tex"] = TexToPng,
|
|
|
|
+ [".png"] = PngToTex
|
|
};
|
|
};
|
|
- }
|
|
|
|
-
|
|
|
|
- public int Run()
|
|
|
|
- {
|
|
|
|
- var files = Glob.EnumerateFiles(Input);
|
|
|
|
- Directory.CreateDirectory(Output);
|
|
|
|
-
|
|
|
|
- if (!files.Any())
|
|
|
|
- {
|
|
|
|
- Console.WriteLine("No files specified. Run `convert help tex` for help.");
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- foreach (var file in files)
|
|
|
|
|
|
+
|
|
|
|
+ textureLoaders = new Dictionary<TextureFormat, Action<string, byte[], int, int, TextureFormat>>
|
|
{
|
|
{
|
|
- var result = 0;
|
|
|
|
- switch (file.Extension.ToLowerInvariant())
|
|
|
|
- {
|
|
|
|
- case ".png":
|
|
|
|
- if ((result = PngToTex(file.FullName)) != 0)
|
|
|
|
- return result;
|
|
|
|
- break;
|
|
|
|
- case ".tex":
|
|
|
|
- if ((result = TexToPng(file.FullName)) != 0)
|
|
|
|
- return result;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- Console.WriteLine($"File {file.FullName} is neither .png nor .tex file. Skipping...");
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
|
|
+ [TextureFormat.Argb32] = ConvertFromPng,
|
|
|
|
+ [TextureFormat.Rgb24] = ConvertFromPng,
|
|
|
|
+ [TextureFormat.Dxt1] = ConvertFromDxt,
|
|
|
|
+ [TextureFormat.Dxt5] = ConvertFromDxt
|
|
|
|
+ };
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- [Value(0, HelpText = "Input PNG or TEX files")]
|
|
|
|
- public IEnumerable<string> Input { get; set; }
|
|
|
|
-
|
|
|
|
- public string Output { get; set; }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- private bool ByteEquals(byte[] b1, byte[] b2)
|
|
|
|
|
|
+ private static bool ByteEquals(IReadOnlyList<byte> b1, IReadOnlyList<byte> b2)
|
|
{
|
|
{
|
|
- var len = Math.Min(b1.Length, b2.Length);
|
|
|
|
|
|
+ var len = Math.Min(b1.Count, b2.Count);
|
|
|
|
|
|
for (var i = 0; i < len; i++)
|
|
for (var i = 0; i < len; i++)
|
|
if (b1[i] != b2[i])
|
|
if (b1[i] != b2[i])
|
|
@@ -97,14 +63,14 @@ namespace ArcToolkitCLI.Commands.Converters
|
|
{
|
|
{
|
|
var img = File.ReadAllBytes(file);
|
|
var img = File.ReadAllBytes(file);
|
|
|
|
|
|
- if (!ByteEquals(img, PNG_HEADER))
|
|
|
|
|
|
+ if (!ByteEquals(img, pngHeader))
|
|
{
|
|
{
|
|
Console.WriteLine($"File {file} is not a PNG file!");
|
|
Console.WriteLine($"File {file} is not a PNG file!");
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
- var w = BitConverter.ToInt32(img, PNG_HEADER.Length + 4 + 4);
|
|
|
|
- var h = BitConverter.ToInt32(img, PNG_HEADER.Length + 4 + 4 + 4);
|
|
|
|
|
|
+ var w = BitConverter.ToInt32(img, pngHeader.Length + 4 + 4);
|
|
|
|
+ var h = BitConverter.ToInt32(img, pngHeader.Length + 4 + 4 + 4);
|
|
using var bw =
|
|
using var bw =
|
|
new BinaryWriter(File.Create(Path.Combine(Output, $"{Path.GetFileNameWithoutExtension(file)}.tex")));
|
|
new BinaryWriter(File.Create(Path.Combine(Output, $"{Path.GetFileNameWithoutExtension(file)}.tex")));
|
|
bw.Write(TEX_TAG);
|
|
bw.Write(TEX_TAG);
|
|
@@ -112,7 +78,7 @@ namespace ArcToolkitCLI.Commands.Converters
|
|
bw.Write(string.Empty);
|
|
bw.Write(string.Empty);
|
|
bw.Write(w);
|
|
bw.Write(w);
|
|
bw.Write(h);
|
|
bw.Write(h);
|
|
- bw.Write((int)TextureFormat.ARGB32);
|
|
|
|
|
|
+ bw.Write((int)TextureFormat.Argb32);
|
|
bw.Write(img.Length);
|
|
bw.Write(img.Length);
|
|
bw.Write(img);
|
|
bw.Write(img);
|
|
return 0;
|
|
return 0;
|
|
@@ -134,7 +100,7 @@ namespace ArcToolkitCLI.Commands.Converters
|
|
var width = 0;
|
|
var width = 0;
|
|
var height = 0;
|
|
var height = 0;
|
|
|
|
|
|
- var format = TextureFormat.ARGB32;
|
|
|
|
|
|
+ var format = TextureFormat.Argb32;
|
|
|
|
|
|
if (version >= 1010)
|
|
if (version >= 1010)
|
|
{
|
|
{
|
|
@@ -155,8 +121,8 @@ namespace ArcToolkitCLI.Commands.Converters
|
|
|
|
|
|
if (version == 1000)
|
|
if (version == 1000)
|
|
{
|
|
{
|
|
- width = BitConverter.ToInt32(data, PNG_HEADER.Length + 4 + 4);
|
|
|
|
- height = BitConverter.ToInt32(data, PNG_HEADER.Length + 4 + 4 + 4);
|
|
|
|
|
|
+ width = BitConverter.ToInt32(data, pngHeader.Length + 4 + 4);
|
|
|
|
+ height = BitConverter.ToInt32(data, pngHeader.Length + 4 + 4 + 4);
|
|
}
|
|
}
|
|
|
|
|
|
if (textureLoaders.TryGetValue(format, out var saveTex))
|
|
if (textureLoaders.TryGetValue(format, out var saveTex))
|
|
@@ -182,8 +148,12 @@ namespace ArcToolkitCLI.Commands.Converters
|
|
private void ConvertFromDxt(string file, byte[] data, int width, int height, TextureFormat format)
|
|
private void ConvertFromDxt(string file, byte[] data, int width, int height, TextureFormat format)
|
|
{
|
|
{
|
|
var squishFlags =
|
|
var squishFlags =
|
|
- format switch { TextureFormat.DXT1 => SquishFlags.kDxt1, TextureFormat.DXT5 => SquishFlags.kDxt5, _ =>
|
|
|
|
- throw new ArgumentException($"Invalid DXT texture format: {format}", nameof(format)) };
|
|
|
|
|
|
+ format switch
|
|
|
|
+ {
|
|
|
|
+ TextureFormat.Dxt1 => SquishFlags.kDxt1,
|
|
|
|
+ TextureFormat.Dxt5 => SquishFlags.kDxt5,
|
|
|
|
+ _ => throw new ArgumentException($"Invalid DXT texture format: {format}", nameof(format))
|
|
|
|
+ };
|
|
|
|
|
|
var outData = new byte[width * height * 4];
|
|
var outData = new byte[width * height * 4];
|
|
Squish.Squish.DecompressImage(outData, width, height, ref data, squishFlags);
|
|
Squish.Squish.DecompressImage(outData, width, height, ref data, squishFlags);
|
|
@@ -207,10 +177,10 @@ namespace ArcToolkitCLI.Commands.Converters
|
|
|
|
|
|
private enum TextureFormat
|
|
private enum TextureFormat
|
|
{
|
|
{
|
|
- ARGB32 = 5,
|
|
|
|
- RGB24 = 3,
|
|
|
|
- DXT1 = 10,
|
|
|
|
- DXT5 = 12
|
|
|
|
|
|
+ Argb32 = 5,
|
|
|
|
+ Rgb24 = 3,
|
|
|
|
+ Dxt1 = 10,
|
|
|
|
+ Dxt5 = 12
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|