mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-14 00:47:37 +00:00
Add latest code
This commit is contained in:
parent
4d16f8e10e
commit
8c25749c23
7 changed files with 446 additions and 14 deletions
411
File_Format_Library/FileFormats/Texture/TXTG.cs
Normal file
411
File_Format_Library/FileFormats/Texture/TXTG.cs
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Toolbox;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Toolbox.Library;
|
||||||
|
using Toolbox.Library.IO;
|
||||||
|
using Toolbox.Library.Forms;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using static Toolbox.Library.STGenericTexture;
|
||||||
|
using LibHac;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using VGAudio.Utilities;
|
||||||
|
|
||||||
|
namespace FirstPlugin
|
||||||
|
{
|
||||||
|
public class TXTG : STGenericTexture, IFileFormat, ILeaveOpenOnLoad
|
||||||
|
{
|
||||||
|
public FileType FileType { get; set; } = FileType.Image;
|
||||||
|
|
||||||
|
public bool CanSave { get; set; } = true;
|
||||||
|
public string[] Description { get; set; } = new string[] { "Texture To Go" };
|
||||||
|
public string[] Extension { get; set; } = new string[] { "*.txtg" };
|
||||||
|
public string FileName { get; set; }
|
||||||
|
public string FilePath { get; set; }
|
||||||
|
public IFileInfo IFileInfo { get; set; }
|
||||||
|
|
||||||
|
public TXTG()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Identify(System.IO.Stream stream)
|
||||||
|
{
|
||||||
|
using (var reader = new Toolbox.Library.IO.FileReader(stream, true)) {
|
||||||
|
return reader.CheckSignature(4, "6PK0", 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type[] Types
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<Type> types = new List<Type>();
|
||||||
|
return types.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanEdit { get; set; } = true;
|
||||||
|
|
||||||
|
public override TEX_FORMAT[] SupportedFormats
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TEX_FORMAT[]
|
||||||
|
{
|
||||||
|
TEX_FORMAT.BC1_UNORM,
|
||||||
|
TEX_FORMAT.BC2_UNORM,
|
||||||
|
TEX_FORMAT.BC3_UNORM,
|
||||||
|
TEX_FORMAT.BC4_UNORM,
|
||||||
|
TEX_FORMAT.BC5_UNORM,
|
||||||
|
TEX_FORMAT.R8_UNORM,
|
||||||
|
TEX_FORMAT.R8G8_UNORM,
|
||||||
|
TEX_FORMAT.R8G8_UNORM,
|
||||||
|
TEX_FORMAT.R10G10B10A2_UNORM,
|
||||||
|
TEX_FORMAT.B5G6R5_UNORM,
|
||||||
|
TEX_FORMAT.B5G5R5A1_UNORM,
|
||||||
|
TEX_FORMAT.B4G4R4A4_UNORM,
|
||||||
|
TEX_FORMAT.R8G8B8A8_UNORM,
|
||||||
|
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnClick(TreeView treeview)
|
||||||
|
{
|
||||||
|
UpdateEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateEditor()
|
||||||
|
{
|
||||||
|
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
|
||||||
|
if (editor == null)
|
||||||
|
{
|
||||||
|
editor = new ImageEditorBase();
|
||||||
|
editor.Dock = DockStyle.Fill;
|
||||||
|
LibraryGUI.LoadEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayProperties prop = new DisplayProperties();
|
||||||
|
prop.Width = Width;
|
||||||
|
prop.Height = Height;
|
||||||
|
prop.MipCount = MipCount;
|
||||||
|
prop.ArrayCount = ArrayCount;
|
||||||
|
prop.Format = this.Format;
|
||||||
|
prop.Hash = String.Join(String.Empty, Array.ConvertAll(this.HeaderInfo.Hash, x => x.ToString("X2")));
|
||||||
|
|
||||||
|
editor.Text = Text;
|
||||||
|
editor.LoadProperties(prop);
|
||||||
|
editor.LoadImage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
public class Header
|
||||||
|
{
|
||||||
|
public ushort HeaderSize = 0x50;
|
||||||
|
public ushort Version = 0x11;
|
||||||
|
public Magic Magic = "6PK0";
|
||||||
|
public ushort Width;
|
||||||
|
public ushort Height;
|
||||||
|
public ushort Depth = 1;
|
||||||
|
public byte MipCount;
|
||||||
|
public byte Unknown1 = 2;
|
||||||
|
public byte Unknown2 = 1;
|
||||||
|
public ushort Padding = 0;
|
||||||
|
|
||||||
|
public byte FormatFlag = 0; //Unsure how this value works
|
||||||
|
public uint FormatSetting = 0; //Varies by format flag. Sometimes a second channel layout
|
||||||
|
|
||||||
|
public byte CompSelectR = 0;
|
||||||
|
public byte CompSelectG = 1;
|
||||||
|
public byte CompSelectB = 2;
|
||||||
|
public byte CompSelectA = 3;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||||
|
public byte[] Hash; //32 byte hash, likely made off file path. Files with identical data still have unique hashes
|
||||||
|
|
||||||
|
public ushort Format;
|
||||||
|
public ushort Unknown3 = 0x300; //Always 0x300?
|
||||||
|
|
||||||
|
public uint TextureSetting1 = 1116471296; //00 00 8C 42
|
||||||
|
public uint TextureSetting2 = 32563; //Likey some setting for astc. Terrain and tree files use different values for their astc formats.
|
||||||
|
public uint TextureSetting3 = 33554944; //00 02 00 02
|
||||||
|
public uint TextureSetting4 = 67330; //02 05 01 00 Varies sometimes with second byte
|
||||||
|
}
|
||||||
|
|
||||||
|
private Header HeaderInfo;
|
||||||
|
|
||||||
|
//Image data is properly loaded afterwards
|
||||||
|
private List<List<byte[]>> ImageList = new List<List<byte[]>>();
|
||||||
|
|
||||||
|
public void Load(Stream stream)
|
||||||
|
{
|
||||||
|
Text = FileName;
|
||||||
|
Tag = this;
|
||||||
|
|
||||||
|
CanReplace = true;
|
||||||
|
|
||||||
|
ImageKey = "Texture";
|
||||||
|
SelectedImageKey = "Texture";
|
||||||
|
|
||||||
|
using (var reader = new FileReader(stream, true))
|
||||||
|
{
|
||||||
|
reader.SetByteOrder(false);
|
||||||
|
|
||||||
|
HeaderInfo = reader.ReadStruct<Header>();
|
||||||
|
|
||||||
|
Width = HeaderInfo.Width;
|
||||||
|
Height = HeaderInfo.Height;
|
||||||
|
ArrayCount = HeaderInfo.Depth;
|
||||||
|
MipCount = HeaderInfo.MipCount;
|
||||||
|
|
||||||
|
RedChannel = ChannelList[HeaderInfo.CompSelectR];
|
||||||
|
GreenChannel = ChannelList[HeaderInfo.CompSelectG];
|
||||||
|
BlueChannel = ChannelList[HeaderInfo.CompSelectB];
|
||||||
|
AlphaChannel = ChannelList[HeaderInfo.CompSelectA];
|
||||||
|
|
||||||
|
SurfaceInfo[] surfaces = new SurfaceInfo[MipCount * ArrayCount];
|
||||||
|
|
||||||
|
reader.SeekBegin(HeaderInfo.HeaderSize);
|
||||||
|
for (int i = 0; i < MipCount * ArrayCount; i++)
|
||||||
|
{
|
||||||
|
surfaces[i] = new SurfaceInfo();
|
||||||
|
surfaces[i].ArrayLevel = reader.ReadUInt16();
|
||||||
|
surfaces[i].MipLevel = reader.ReadByte();
|
||||||
|
reader.ReadByte(); //Always 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MipCount * ArrayCount; i++)
|
||||||
|
{
|
||||||
|
surfaces[i].Size = reader.ReadUInt32();
|
||||||
|
reader.ReadUInt32(); //Always 6
|
||||||
|
}
|
||||||
|
|
||||||
|
long pos = reader.Position;
|
||||||
|
|
||||||
|
if (FormatList.ContainsKey(HeaderInfo.Format))
|
||||||
|
this.Format = FormatList[HeaderInfo.Format];
|
||||||
|
else
|
||||||
|
throw new Exception($"Unsupported format! {HeaderInfo.Format.ToString("X")}");
|
||||||
|
|
||||||
|
//Dumb hack. Terrain is oddly 8x8 astc, but the format seems to be 0x101
|
||||||
|
//Use some of the different texture settings, as they likely configure the astc blocks in some way
|
||||||
|
if (this.HeaderInfo.TextureSetting2 == 32631)
|
||||||
|
{
|
||||||
|
this.Format = TEX_FORMAT.ASTC_8x8_UNORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Image data is properly loaded afterwards
|
||||||
|
List<List<byte[]>> data = new List<List<byte[]>>();
|
||||||
|
|
||||||
|
//Combine each mip and array
|
||||||
|
for (int i = 0; i < MipCount * ArrayCount; i++)
|
||||||
|
{
|
||||||
|
var imageData = reader.ReadBytes((int)(surfaces[i].Size));
|
||||||
|
|
||||||
|
//Array level
|
||||||
|
if (data.Count <= surfaces[i].ArrayLevel)
|
||||||
|
data.Add(new List<byte[]>());
|
||||||
|
|
||||||
|
data[surfaces[i].ArrayLevel].Add(Zstb.SDecompress(imageData));
|
||||||
|
}
|
||||||
|
ImageList = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Save(Stream stream)
|
||||||
|
{
|
||||||
|
//Apply generic properties
|
||||||
|
HeaderInfo.Format = FormatList.FirstOrDefault(x => x.Value == Format).Key;
|
||||||
|
HeaderInfo.Width = (ushort)this.Width;
|
||||||
|
HeaderInfo.Height = (ushort)this.Height;
|
||||||
|
HeaderInfo.Depth = (ushort)this.ArrayCount;
|
||||||
|
HeaderInfo.MipCount = (byte)this.MipCount;
|
||||||
|
|
||||||
|
using (var writer = new FileWriter(stream))
|
||||||
|
{
|
||||||
|
writer.WriteStruct(this.HeaderInfo);
|
||||||
|
writer.SeekBegin(this.HeaderInfo.HeaderSize);
|
||||||
|
|
||||||
|
List<uint> surfaceSizes = new List<uint>();
|
||||||
|
List<byte[]> surfaceData = new List<byte[]>();
|
||||||
|
|
||||||
|
//Surface index list
|
||||||
|
for (int mip = 0; mip < this.MipCount; mip++)
|
||||||
|
{
|
||||||
|
for (int array = 0; array < this.ArrayCount; array++)
|
||||||
|
{
|
||||||
|
writer.Write((ushort)array);
|
||||||
|
writer.Write((byte)mip);
|
||||||
|
writer.Write((byte)1);
|
||||||
|
|
||||||
|
var surface = Zstb.SCompress(ImageList[array][mip]);
|
||||||
|
surfaceSizes.Add((uint)surface.Length);
|
||||||
|
|
||||||
|
surfaceData.Add(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Surface sizes
|
||||||
|
foreach (var surface in surfaceSizes)
|
||||||
|
{
|
||||||
|
writer.Write(surface);
|
||||||
|
writer.Write(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Surface data
|
||||||
|
foreach (var data in surfaceData)
|
||||||
|
{
|
||||||
|
writer.Write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0, int DepthLevel = 0)
|
||||||
|
{
|
||||||
|
var data = ImageList[ArrayLevel][MipLevel];
|
||||||
|
return TegraX1Swizzle.GetDirectImageData(this, data, MipLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetImageData(Bitmap bitmap, int ArrayLevel)
|
||||||
|
{
|
||||||
|
//Set the data using an instance of a switch texture
|
||||||
|
var tex = new TextureData();
|
||||||
|
tex.Texture = new Syroot.NintenTools.NSW.Bntx.Texture();
|
||||||
|
tex.Format = this.Format;
|
||||||
|
tex.Width = this.Width;
|
||||||
|
tex.Height = this.Height;
|
||||||
|
tex.MipCount = this.MipCount;
|
||||||
|
tex.ArrayCount = this.ArrayCount;
|
||||||
|
tex.Texture.TextureData = new List<List<byte[]>>();
|
||||||
|
tex.Texture.TextureData.Add(new List<byte[]>());
|
||||||
|
|
||||||
|
tex.SetImageData(bitmap, ArrayLevel);
|
||||||
|
SetImage(tex, ArrayLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Replace(string FileName)
|
||||||
|
{
|
||||||
|
//Replace the data using an instance of a switch texture
|
||||||
|
var tex = new TextureData();
|
||||||
|
tex.Replace(FileName, MipCount, 0, Format);
|
||||||
|
|
||||||
|
//Get swappable array level
|
||||||
|
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
|
||||||
|
int targetArray = 0;
|
||||||
|
if (editor != null)
|
||||||
|
targetArray = editor.GetArrayDisplayLevel();
|
||||||
|
|
||||||
|
SetImage(tex, targetArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetImage(TextureData tex, int targetArray)
|
||||||
|
{
|
||||||
|
//If it's null, the operation is cancelled
|
||||||
|
if (tex.Texture == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Ensure the format matches if image requires multiple surface levels
|
||||||
|
if (ImageList.Count > 1 && this.Format != tex.Format)
|
||||||
|
throw new Exception($"Imported texture must use the original format for surface injecting! Expected {this.Format} but got {tex.Format}! If you need ASTC, use an astc encoder with .astc file format.");
|
||||||
|
|
||||||
|
//Swap individual image
|
||||||
|
if (tex.Texture.TextureData.Count == 1)
|
||||||
|
{
|
||||||
|
ImageList[targetArray] = tex.Texture.TextureData[0];
|
||||||
|
}
|
||||||
|
else //Swap all surfaces if multiple are imported
|
||||||
|
{
|
||||||
|
ImageList.Clear();
|
||||||
|
foreach (var surface in tex.Texture.TextureData)
|
||||||
|
ImageList.Add(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
Width = tex.Texture.Width;
|
||||||
|
Height = tex.Texture.Height;
|
||||||
|
MipCount = tex.Texture.MipCount;
|
||||||
|
ArrayCount = (uint)ImageList.Count;
|
||||||
|
Format = tex.Format;
|
||||||
|
|
||||||
|
UpdateEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SurfaceInfo
|
||||||
|
{
|
||||||
|
public byte MipLevel;
|
||||||
|
public ushort ArrayLevel;
|
||||||
|
public byte SurfaceCount; //Always 1
|
||||||
|
|
||||||
|
public uint Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Dictionary<uint, STChannelType> ChannelList = new Dictionary<uint, STChannelType>()
|
||||||
|
{
|
||||||
|
{ 0, STChannelType.Red },
|
||||||
|
{ 1, STChannelType.Green },
|
||||||
|
{ 2, STChannelType.Blue },
|
||||||
|
{ 3, STChannelType.Alpha },
|
||||||
|
{ 4, STChannelType.Zero },
|
||||||
|
{ 5, STChannelType.One },
|
||||||
|
};
|
||||||
|
|
||||||
|
static Dictionary<ushort, TEX_FORMAT> FormatList = new Dictionary<ushort, TEX_FORMAT>()
|
||||||
|
{
|
||||||
|
{ 0x101, TEX_FORMAT.ASTC_4x4_UNORM },
|
||||||
|
{ 0x102, TEX_FORMAT.ASTC_8x8_UNORM },
|
||||||
|
{ 0x105, TEX_FORMAT.ASTC_8x8_SRGB },
|
||||||
|
{ 0x202, TEX_FORMAT.BC1_UNORM },
|
||||||
|
{ 0x203, TEX_FORMAT.BC1_UNORM_SRGB },
|
||||||
|
{ 0x302, TEX_FORMAT.BC1_UNORM },
|
||||||
|
{ 0x606, TEX_FORMAT.BC4_UNORM },
|
||||||
|
{ 0x702, TEX_FORMAT.BC5_UNORM },
|
||||||
|
{ 0x703, TEX_FORMAT.BC5_UNORM },
|
||||||
|
{ 0x707, TEX_FORMAT.BC5_UNORM },
|
||||||
|
{ 0x901, TEX_FORMAT.BC7_UNORM },
|
||||||
|
};
|
||||||
|
|
||||||
|
public class DisplayProperties
|
||||||
|
{
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[Description("Height of the image.")]
|
||||||
|
[Category("Image Info")]
|
||||||
|
public uint Height { get; set; }
|
||||||
|
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[Description("Width of the image.")]
|
||||||
|
[Category("Image Info")]
|
||||||
|
public uint Width { get; set; }
|
||||||
|
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[Description("Format of the image.")]
|
||||||
|
[Category("Image Info")]
|
||||||
|
public TEX_FORMAT Format { get; set; }
|
||||||
|
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[Description("Mip map count of the image.")]
|
||||||
|
[Category("Image Info")]
|
||||||
|
public uint MipCount { get; set; }
|
||||||
|
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[Description("Array count of the image for multiple surfaces.")]
|
||||||
|
[Category("Image Info")]
|
||||||
|
public uint ArrayCount { get; set; }
|
||||||
|
|
||||||
|
[Browsable(true)]
|
||||||
|
[ReadOnly(true)]
|
||||||
|
[Description("The hash value.")]
|
||||||
|
[Category("Image Info")]
|
||||||
|
public string Hash { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ using System.Threading;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Bfres.Structs;
|
using Bfres.Structs;
|
||||||
using ResUGX2 = Syroot.NintenTools.Bfres.GX2;
|
using ResUGX2 = Syroot.NintenTools.Bfres.GX2;
|
||||||
using Syroot.NintenTools.NSW.Bfres.GX2;
|
|
||||||
using Syroot.NintenTools.NSW.Bfres;
|
using Syroot.NintenTools.NSW.Bfres;
|
||||||
using Toolbox.Library;
|
using Toolbox.Library;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace Toolbox.Library
|
||||||
|
|
||||||
static string fileNameTemp = "";
|
static string fileNameTemp = "";
|
||||||
|
|
||||||
|
public void Init(string fileName) { fileNameTemp = fileName; }
|
||||||
|
|
||||||
public bool Identify(Stream stream, string fileName)
|
public bool Identify(Stream stream, string fileName)
|
||||||
{
|
{
|
||||||
//Small hack to check current file name
|
//Small hack to check current file name
|
||||||
|
|
|
@ -722,7 +722,7 @@ namespace Ryujinx.Graphics.Gal.Texture
|
||||||
{
|
{
|
||||||
uint[] Val = ReadUintColorValues(2, ColorValues, ref ColorValuesPosition);
|
uint[] Val = ReadUintColorValues(2, ColorValues, ref ColorValuesPosition);
|
||||||
int L0 = (int)((Val[0] >> 2) | (Val[1] & 0xC0));
|
int L0 = (int)((Val[0] >> 2) | (Val[1] & 0xC0));
|
||||||
int L1 = (int)Math.Max(L0 + (Val[1] & 0x3F), 0xFFU);
|
int L1 = (int)Math.Min(L0 + (Val[1] & 0x3F), 0xFFU);
|
||||||
|
|
||||||
EndPoints[0] = new ASTCPixel(0xFF, (short)L0, (short)L0, (short)L0);
|
EndPoints[0] = new ASTCPixel(0xFF, (short)L0, (short)L0, (short)L0);
|
||||||
EndPoints[1] = new ASTCPixel(0xFF, (short)L1, (short)L1, (short)L1);
|
EndPoints[1] = new ASTCPixel(0xFF, (short)L1, (short)L1, (short)L1);
|
||||||
|
|
|
@ -15,6 +15,9 @@ namespace Toolbox.Library.Forms
|
||||||
{
|
{
|
||||||
public partial class ImageEditorBase : UserControl
|
public partial class ImageEditorBase : UserControl
|
||||||
{
|
{
|
||||||
|
public int GetArrayDisplayLevel() => CurArrayDisplayLevel;
|
||||||
|
public int GetMipmapDisplayLevel() => CurArrayDisplayLevel;
|
||||||
|
|
||||||
public class ImageReplaceEventArgs : EventArgs
|
public class ImageReplaceEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public Bitmap ReplacedTexture { get; private set; }
|
public Bitmap ReplacedTexture { get; private set; }
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace Toolbox.Library.Forms
|
||||||
}
|
}
|
||||||
|
|
||||||
textureImageFormatCB.SelectedItem = texture.Format;
|
textureImageFormatCB.SelectedItem = texture.Format;
|
||||||
|
if (textureImageFormatCB.SelectedItem == null)
|
||||||
|
textureImageFormatCB.SelectedItem = TEX_FORMAT.BC1_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TEX_FORMAT GetSelectedImageFormat()
|
public TEX_FORMAT GetSelectedImageFormat()
|
||||||
|
|
|
@ -10,6 +10,7 @@ using OpenTK.Graphics.OpenGL;
|
||||||
using Toolbox.Library.Rendering;
|
using Toolbox.Library.Rendering;
|
||||||
using Ryujinx.Graphics.Gal.Texture; //For ASTC
|
using Ryujinx.Graphics.Gal.Texture; //For ASTC
|
||||||
using Toolbox.Library.NodeWrappers;
|
using Toolbox.Library.NodeWrappers;
|
||||||
|
using Toolbox.Library.Forms;
|
||||||
|
|
||||||
namespace Toolbox.Library
|
namespace Toolbox.Library
|
||||||
{
|
{
|
||||||
|
@ -867,7 +868,7 @@ namespace Toolbox.Library
|
||||||
|
|
||||||
public override void Export(string FileName)
|
public override void Export(string FileName)
|
||||||
{
|
{
|
||||||
Export(FileName);
|
Export(FileName, false, false, GetViewedArrayLevel(), GetViewedMipLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExportArrayImage(int ArrayIndex = 0)
|
public void ExportArrayImage(int ArrayIndex = 0)
|
||||||
|
@ -883,6 +884,22 @@ namespace Toolbox.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GetViewedArrayLevel()
|
||||||
|
{
|
||||||
|
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
|
||||||
|
if (editor != null)
|
||||||
|
return editor.GetArrayDisplayLevel();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetViewedMipLevel()
|
||||||
|
{
|
||||||
|
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
|
||||||
|
if (editor != null)
|
||||||
|
return editor.GetMipmapDisplayLevel();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public void ExportImage()
|
public void ExportImage()
|
||||||
{
|
{
|
||||||
SaveFileDialog sfd = new SaveFileDialog();
|
SaveFileDialog sfd = new SaveFileDialog();
|
||||||
|
@ -892,7 +909,7 @@ namespace Toolbox.Library
|
||||||
|
|
||||||
if (sfd.ShowDialog() == DialogResult.OK)
|
if (sfd.ShowDialog() == DialogResult.OK)
|
||||||
{
|
{
|
||||||
Export(sfd.FileName, false, false, 0, 0);
|
Export(sfd.FileName, false, false, GetViewedArrayLevel(), GetViewedMipLevel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,16 +932,11 @@ namespace Toolbox.Library
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void SaveASTC(string FileName, bool ExportSurfaceLevel = false,
|
public void SaveASTC(string FileName, bool ExportSurfaceLevel = true,
|
||||||
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
|
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
|
||||||
{
|
{
|
||||||
List<Surface> surfaces = null;
|
List<Surface> surfaces = GetSurfaces(SurfaceLevel, false);
|
||||||
if (ExportSurfaceLevel)
|
|
||||||
surfaces = GetSurfaces(SurfaceLevel, false);
|
|
||||||
else if (Depth > 1)
|
|
||||||
surfaces = Get3DSurfaces();
|
|
||||||
else
|
|
||||||
surfaces = GetSurfaces();
|
|
||||||
|
|
||||||
ASTC atsc = new ASTC();
|
ASTC atsc = new ASTC();
|
||||||
atsc.Width = Width;
|
atsc.Width = Width;
|
||||||
|
@ -937,7 +949,10 @@ namespace Toolbox.Library
|
||||||
|
|
||||||
Console.WriteLine("DataBlock " + atsc.DataBlock.Length);
|
Console.WriteLine("DataBlock " + atsc.DataBlock.Length);
|
||||||
|
|
||||||
atsc.Save(new FileStream(FileName, FileMode.Create, FileAccess.ReadWrite));
|
using (var fs = new FileStream(FileName, FileMode.Create, FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
atsc.Save(fs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void SaveTGA(string FileName, bool ExportSurfaceLevel = false,
|
public void SaveTGA(string FileName, bool ExportSurfaceLevel = false,
|
||||||
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
|
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
|
||||||
|
@ -954,7 +969,7 @@ namespace Toolbox.Library
|
||||||
progressBar.Show();
|
progressBar.Show();
|
||||||
progressBar.Refresh();
|
progressBar.Refresh();
|
||||||
|
|
||||||
if (ArrayCount > 1 && !ExportSurfaceLevel)
|
if (ArrayCount > 1 && !ExportSurfaceLevel && false)
|
||||||
{
|
{
|
||||||
progressBar.Task = "Select dialog option... ";
|
progressBar.Task = "Select dialog option... ";
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue