2018-11-17 02:13:05 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using Switch_Toolbox.Library;
|
|
|
|
|
using Switch_Toolbox.Library.Forms;
|
|
|
|
|
using Syroot.NintenTools.Bfres;
|
|
|
|
|
using Syroot.NintenTools.Bfres.GX2;
|
|
|
|
|
using OpenTK;
|
|
|
|
|
using OpenTK.Graphics.OpenGL;
|
|
|
|
|
using Smash_Forge.Rendering;
|
|
|
|
|
using WeifenLuo.WinFormsUI.Docking;
|
2018-12-10 23:48:51 +00:00
|
|
|
|
using Switch_Toolbox.Library.IO;
|
2018-11-17 02:13:05 +00:00
|
|
|
|
|
|
|
|
|
namespace FirstPlugin
|
|
|
|
|
{
|
|
|
|
|
public class FTEXContainer : TreeNodeCustom
|
|
|
|
|
{
|
|
|
|
|
public Dictionary<string, FTEX> Textures = new Dictionary<string, FTEX>(); //To get instance of classes
|
|
|
|
|
|
|
|
|
|
public FTEXContainer()
|
|
|
|
|
{
|
|
|
|
|
Text = "Textures";
|
2018-12-05 02:40:03 +00:00
|
|
|
|
Name = "FTEX";
|
2018-11-17 02:13:05 +00:00
|
|
|
|
|
|
|
|
|
ContextMenu = new ContextMenu();
|
2018-12-02 20:01:51 +00:00
|
|
|
|
MenuItem importTex = new MenuItem("Import");
|
|
|
|
|
ContextMenu.MenuItems.Add(importTex);
|
|
|
|
|
importTex.Click += Import;
|
2018-11-17 02:13:05 +00:00
|
|
|
|
MenuItem exportAll = new MenuItem("Export All Textures");
|
|
|
|
|
ContextMenu.MenuItems.Add(exportAll);
|
|
|
|
|
exportAll.Click += ExportAll;
|
|
|
|
|
MenuItem clear = new MenuItem("Clear");
|
|
|
|
|
ContextMenu.MenuItems.Add(clear);
|
|
|
|
|
clear.Click += Clear;
|
|
|
|
|
}
|
|
|
|
|
private void Clear(object sender, EventArgs args)
|
|
|
|
|
{
|
|
|
|
|
Nodes.Clear();
|
|
|
|
|
Textures.Clear();
|
|
|
|
|
}
|
|
|
|
|
public void RefreshGlTexturesByName()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RemoveTexture(FTEX textureData)
|
|
|
|
|
{
|
|
|
|
|
Nodes.Remove(textureData);
|
|
|
|
|
Textures.Remove(textureData.Text);
|
|
|
|
|
Viewport.Instance.UpdateViewport();
|
|
|
|
|
}
|
2018-12-02 20:01:51 +00:00
|
|
|
|
private void Import(object sender, EventArgs args)
|
|
|
|
|
{
|
|
|
|
|
ImportTexture();
|
|
|
|
|
}
|
|
|
|
|
public void ImportTexture()
|
|
|
|
|
{
|
|
|
|
|
OpenFileDialog ofd = new OpenFileDialog();
|
|
|
|
|
ofd.Filter = "Supported Formats|*.dds; *.png;*.tga;*.jpg;*.tiff|" +
|
|
|
|
|
"Microsoft DDS |*.dds|" +
|
|
|
|
|
"Portable Network Graphics |*.png|" +
|
|
|
|
|
"Joint Photographic Experts Group |*.jpg|" +
|
|
|
|
|
"Bitmap Image |*.bmp|" +
|
|
|
|
|
"Tagged Image File Format |*.tiff|" +
|
|
|
|
|
"All files(*.*)|*.*";
|
|
|
|
|
|
|
|
|
|
ofd.Multiselect = true;
|
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
|
|
|
{
|
2018-12-13 02:28:57 +00:00
|
|
|
|
BinaryTextureImporterList importer = new BinaryTextureImporterList();
|
|
|
|
|
List<TextureImporterSettings> settings = new List<TextureImporterSettings>();
|
2018-12-02 20:01:51 +00:00
|
|
|
|
foreach (string name in ofd.FileNames)
|
|
|
|
|
{
|
2018-12-13 02:28:57 +00:00
|
|
|
|
|
2018-12-02 20:01:51 +00:00
|
|
|
|
|
|
|
|
|
settings.Clear();
|
|
|
|
|
GC.Collect();
|
|
|
|
|
Cursor.Current = Cursors.Default;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-17 02:13:05 +00:00
|
|
|
|
private void ExportAll(object sender, EventArgs args)
|
|
|
|
|
{
|
|
|
|
|
List<string> Formats = new List<string>();
|
|
|
|
|
Formats.Add("Cafe Binary Textures (.bftex)");
|
|
|
|
|
Formats.Add("Microsoft DDS (.dds)");
|
|
|
|
|
Formats.Add("Portable Graphics Network (.png)");
|
|
|
|
|
Formats.Add("Joint Photographic Experts Group (.jpg)");
|
|
|
|
|
Formats.Add("Bitmap Image (.bmp)");
|
|
|
|
|
Formats.Add("Tagged Image File Format (.tiff)");
|
|
|
|
|
|
|
|
|
|
FolderSelectDialog sfd = new FolderSelectDialog();
|
|
|
|
|
|
|
|
|
|
if (sfd.ShowDialog() == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
string folderPath = sfd.SelectedPath;
|
|
|
|
|
|
|
|
|
|
TextureFormatExport form = new TextureFormatExport(Formats);
|
|
|
|
|
if (form.ShowDialog() == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
foreach (FTEX tex in Nodes)
|
|
|
|
|
{
|
|
|
|
|
if (form.Index == 0)
|
|
|
|
|
tex.SaveBinaryTexture(folderPath + '\\' + tex.Text + ".bftex");
|
|
|
|
|
else if (form.Index == 1)
|
|
|
|
|
tex.SaveDDS(folderPath + '\\' + tex.Text + ".dds");
|
|
|
|
|
else if (form.Index == 2)
|
|
|
|
|
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".png");
|
|
|
|
|
else if (form.Index == 3)
|
|
|
|
|
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".jpg");
|
|
|
|
|
else if (form.Index == 4)
|
|
|
|
|
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".bmp");
|
|
|
|
|
else if (form.Index == 5)
|
|
|
|
|
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".tiff");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-10 23:48:51 +00:00
|
|
|
|
public class FTEX : STGenericTexture
|
2018-11-17 02:13:05 +00:00
|
|
|
|
{
|
|
|
|
|
public int format;
|
2018-12-02 20:01:51 +00:00
|
|
|
|
public Texture texture;
|
2018-11-17 02:13:05 +00:00
|
|
|
|
|
|
|
|
|
public FTEX()
|
|
|
|
|
{
|
|
|
|
|
ContextMenu = new ContextMenu();
|
|
|
|
|
MenuItem export = new MenuItem("Export");
|
|
|
|
|
ContextMenu.MenuItems.Add(export);
|
|
|
|
|
export.Click += Export;
|
2018-12-02 20:01:51 +00:00
|
|
|
|
MenuItem replace = new MenuItem("Replace");
|
|
|
|
|
ContextMenu.MenuItems.Add(replace);
|
|
|
|
|
replace.Click += Replace;
|
2018-11-17 02:13:05 +00:00
|
|
|
|
MenuItem remove = new MenuItem("Remove");
|
|
|
|
|
ContextMenu.MenuItems.Add(remove);
|
|
|
|
|
remove.Click += Remove;
|
|
|
|
|
MenuItem rename = new MenuItem("Rename");
|
|
|
|
|
ContextMenu.MenuItems.Add(rename);
|
|
|
|
|
rename.Click += Rename;
|
|
|
|
|
}
|
2018-12-10 23:48:51 +00:00
|
|
|
|
//For determining mip map file for botw (Tex2)
|
|
|
|
|
public string GetFilePath()
|
|
|
|
|
{
|
|
|
|
|
if (Parent == null)
|
|
|
|
|
throw new Exception("Parent is null!");
|
|
|
|
|
|
|
|
|
|
return ((BFRES)Parent.Parent).FilePath;
|
|
|
|
|
}
|
2018-11-17 02:13:05 +00:00
|
|
|
|
|
|
|
|
|
private void Replace(object sender, EventArgs args)
|
|
|
|
|
{
|
2018-12-02 20:01:51 +00:00
|
|
|
|
OpenFileDialog ofd = new OpenFileDialog();
|
|
|
|
|
ofd.Filter = "Supported Formats|*.dds; *.png;*.tga;*.jpg;*.tiff|" +
|
|
|
|
|
"Microsoft DDS |*.dds|" +
|
|
|
|
|
"Portable Network Graphics |*.png|" +
|
|
|
|
|
"Joint Photographic Experts Group |*.jpg|" +
|
|
|
|
|
"Bitmap Image |*.bmp|" +
|
|
|
|
|
"Tagged Image File Format |*.tiff|" +
|
|
|
|
|
"All files(*.*)|*.*";
|
|
|
|
|
|
|
|
|
|
ofd.Multiselect = false;
|
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
Replace(ofd.FileName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void Replace(string FileName)
|
|
|
|
|
{
|
|
|
|
|
string ext = System.IO.Path.GetExtension(FileName);
|
|
|
|
|
ext = ext.ToLower();
|
|
|
|
|
|
2018-12-13 02:28:57 +00:00
|
|
|
|
TextureImporterSettings setting = new TextureImporterSettings();
|
|
|
|
|
BinaryTextureImporterList importer = new BinaryTextureImporterList();
|
2018-12-02 20:01:51 +00:00
|
|
|
|
}
|
|
|
|
|
//We reuse GX2 data as it's the same thing
|
2018-12-13 02:28:57 +00:00
|
|
|
|
public Texture FromGx2Surface(GTX.GX2Surface surf, TextureImporterSettings settings)
|
2018-12-02 20:01:51 +00:00
|
|
|
|
{
|
|
|
|
|
Texture tex = new Texture();
|
|
|
|
|
tex.Name = settings.TexName;
|
|
|
|
|
tex.AAMode = (GX2AAMode)surf.aa;
|
|
|
|
|
tex.Alignment = (uint)surf.alignment;
|
|
|
|
|
tex.ArrayLength = 1;
|
|
|
|
|
tex.Data = surf.data;
|
|
|
|
|
tex.MipData = surf.mipData;
|
|
|
|
|
tex.Format = (GX2SurfaceFormat)surf.format;
|
|
|
|
|
tex.Dim = (GX2SurfaceDim)surf.dim;
|
|
|
|
|
tex.Use = (GX2SurfaceUse)surf.use;
|
|
|
|
|
tex.TileMode = (GX2TileMode)surf.tileMode;
|
2018-12-05 02:40:03 +00:00
|
|
|
|
tex.Swizzle = surf.swizzle;
|
|
|
|
|
tex.Pitch = surf.pitch;
|
|
|
|
|
tex.Depth = surf.depth;
|
|
|
|
|
tex.MipCount = surf.numMips;
|
|
|
|
|
|
|
|
|
|
tex.MipOffsets = new uint[13];
|
|
|
|
|
for (int i = 0; i < 13; i++)
|
|
|
|
|
{
|
|
|
|
|
if (i < surf.mipOffset.Length)
|
|
|
|
|
tex.MipOffsets[i] = surf.mipOffset[i];
|
|
|
|
|
}
|
|
|
|
|
tex.Height = surf.height;
|
|
|
|
|
tex.Width = surf.width;
|
|
|
|
|
tex.Regs = new uint[5];
|
|
|
|
|
tex.ArrayLength = 1;
|
2018-12-02 20:01:51 +00:00
|
|
|
|
var channels = SetChannelsByFormat((GX2SurfaceFormat)surf.format);
|
|
|
|
|
tex.CompSelR = channels[0];
|
|
|
|
|
tex.CompSelG = channels[1];
|
|
|
|
|
tex.CompSelB = channels[2];
|
|
|
|
|
tex.CompSelA = channels[3];
|
2018-12-05 02:40:03 +00:00
|
|
|
|
tex.UserData = new ResDict<UserData>();
|
2018-12-02 20:01:51 +00:00
|
|
|
|
return tex;
|
2018-11-17 02:13:05 +00:00
|
|
|
|
}
|
|
|
|
|
private void Rename(object sender, EventArgs args)
|
|
|
|
|
{
|
|
|
|
|
RenameDialog dialog = new RenameDialog();
|
|
|
|
|
dialog.SetString(Text);
|
|
|
|
|
|
|
|
|
|
if (dialog.ShowDialog() == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
((FTEXContainer)Parent).Textures.Remove(Text);
|
|
|
|
|
Text = dialog.textBox1.Text;
|
|
|
|
|
|
|
|
|
|
((FTEXContainer)Parent).Textures.Add(Text, this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private void Remove(object sender, EventArgs args)
|
|
|
|
|
{
|
|
|
|
|
((FTEXContainer)Parent).RemoveTexture(this);
|
|
|
|
|
}
|
|
|
|
|
private void Export(object sender, EventArgs args)
|
|
|
|
|
{
|
|
|
|
|
SaveFileDialog sfd = new SaveFileDialog();
|
|
|
|
|
sfd.FileName = Text;
|
|
|
|
|
sfd.DefaultExt = "bftex";
|
|
|
|
|
sfd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
|
|
|
|
|
"Binary Texture |*.bftex|" +
|
|
|
|
|
"Microsoft DDS |*.dds|" +
|
|
|
|
|
"Portable Network Graphics |*.png|" +
|
|
|
|
|
"Joint Photographic Experts Group |*.jpg|" +
|
|
|
|
|
"Bitmap Image |*.bmp|" +
|
|
|
|
|
"Tagged Image File Format |*.tiff|" +
|
|
|
|
|
"All files(*.*)|*.*";
|
|
|
|
|
|
|
|
|
|
if (sfd.ShowDialog() == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
Export(sfd.FileName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Read(Texture tex)
|
|
|
|
|
{
|
|
|
|
|
ImageKey = "Texture";
|
|
|
|
|
SelectedImageKey = "Texture";
|
|
|
|
|
Text = tex.Name;
|
|
|
|
|
|
2018-12-05 02:40:03 +00:00
|
|
|
|
texture = tex;
|
|
|
|
|
|
2018-12-10 23:48:51 +00:00
|
|
|
|
Width = tex.Width;
|
|
|
|
|
Height = tex.Height;
|
2018-12-13 02:28:57 +00:00
|
|
|
|
Format = ConvertFormat(tex.Format);
|
2018-11-17 02:13:05 +00:00
|
|
|
|
format = (int)tex.Format;
|
|
|
|
|
int swizzle = (int)tex.Swizzle;
|
|
|
|
|
int pitch = (int)tex.Pitch;
|
2018-11-28 02:21:31 +00:00
|
|
|
|
uint bpp = GTX.surfaceGetBitsPerPixel((uint)format) >> 3;
|
2018-11-23 00:40:36 +00:00
|
|
|
|
|
2018-11-28 02:21:31 +00:00
|
|
|
|
GTX.GX2Surface surf = new GTX.GX2Surface();
|
|
|
|
|
surf.bpp = bpp;
|
2018-12-02 20:01:51 +00:00
|
|
|
|
surf.height = tex.Height;
|
|
|
|
|
surf.width = tex.Width;
|
|
|
|
|
surf.aa = (uint)tex.AAMode;
|
|
|
|
|
surf.alignment = tex.Alignment;
|
|
|
|
|
surf.depth = tex.Depth;
|
|
|
|
|
surf.dim = (uint)tex.Dim;
|
|
|
|
|
surf.format = (uint)tex.Format;
|
|
|
|
|
surf.use = (uint)tex.Use;
|
|
|
|
|
surf.pitch = tex.Pitch;
|
2018-12-01 03:00:43 +00:00
|
|
|
|
surf.data = tex.Data;
|
2018-12-02 20:01:51 +00:00
|
|
|
|
surf.numMips = tex.MipCount;
|
2018-12-01 03:00:43 +00:00
|
|
|
|
surf.mipOffset = tex.MipOffsets;
|
|
|
|
|
surf.mipData = tex.MipData;
|
2018-12-02 20:01:51 +00:00
|
|
|
|
surf.tileMode = (uint)tex.TileMode;
|
|
|
|
|
surf.swizzle = tex.Swizzle;
|
2018-12-01 03:00:43 +00:00
|
|
|
|
|
2018-12-10 23:48:51 +00:00
|
|
|
|
//Determine tex2 botw files to get mip maps
|
|
|
|
|
string Tex1 = GetFilePath();
|
|
|
|
|
if (Tex1.Contains(".Tex1"))
|
|
|
|
|
{
|
|
|
|
|
string Tex2 = Tex1.Replace(".Tex1", ".Tex2");
|
|
|
|
|
Console.WriteLine(Tex2);
|
|
|
|
|
|
|
|
|
|
if (System.IO.File.Exists(Tex2))
|
|
|
|
|
{
|
|
|
|
|
ResFile resFile2 = new ResFile(new System.IO.MemoryStream(
|
|
|
|
|
EveryFileExplorer.YAZ0.Decompress(Tex2)));
|
|
|
|
|
|
|
|
|
|
if (resFile2.Textures.ContainsKey(tex.Name))
|
|
|
|
|
{
|
|
|
|
|
surf.mipData = resFile2.Textures[tex.Name].MipData;
|
|
|
|
|
surf.mipOffset = resFile2.Textures[tex.Name].MipOffsets;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (surf.mipData == null)
|
|
|
|
|
surf.numMips = 1;
|
|
|
|
|
|
2018-12-01 03:00:43 +00:00
|
|
|
|
List<byte[]> mips = GTX.Decode(surf);
|
2018-12-13 02:28:57 +00:00
|
|
|
|
Surfaces.Add(new Surface() { mipmaps = mips });
|
2018-12-01 03:00:43 +00:00
|
|
|
|
|
2018-12-13 02:28:57 +00:00
|
|
|
|
RenderableTex.LoadOpenGLTexture(this);
|
|
|
|
|
}
|
|
|
|
|
private TEX_FORMAT ConvertFormat(GX2SurfaceFormat Format)
|
|
|
|
|
{
|
|
|
|
|
return TEX_FORMAT.UNKNOWN;
|
2018-12-02 20:01:51 +00:00
|
|
|
|
}
|
|
|
|
|
public static GX2CompSel[] SetChannelsByFormat(GX2SurfaceFormat Format)
|
|
|
|
|
{
|
|
|
|
|
GX2CompSel[] channels = new GX2CompSel[4];
|
|
|
|
|
|
|
|
|
|
switch (Format)
|
|
|
|
|
{
|
|
|
|
|
case GX2SurfaceFormat.T_BC5_UNorm:
|
|
|
|
|
case GX2SurfaceFormat.T_BC5_SNorm:
|
|
|
|
|
channels[0] = GX2CompSel.ChannelR;
|
|
|
|
|
channels[1] = GX2CompSel.ChannelG;
|
|
|
|
|
channels[2] = GX2CompSel.Always0;
|
|
|
|
|
channels[3] = GX2CompSel.Always1;
|
|
|
|
|
break;
|
|
|
|
|
case GX2SurfaceFormat.T_BC4_SNorm:
|
|
|
|
|
case GX2SurfaceFormat.T_BC4_UNorm:
|
|
|
|
|
channels[0] = GX2CompSel.ChannelR;
|
|
|
|
|
channels[1] = GX2CompSel.ChannelR;
|
|
|
|
|
channels[2] = GX2CompSel.ChannelR;
|
|
|
|
|
channels[3] = GX2CompSel.ChannelR;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
channels[0] = GX2CompSel.ChannelR;
|
|
|
|
|
channels[1] = GX2CompSel.ChannelG;
|
|
|
|
|
channels[2] = GX2CompSel.ChannelB;
|
|
|
|
|
channels[3] = GX2CompSel.Always1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return channels;
|
2018-11-17 02:13:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Export(string FileName, bool ExportSurfaceLevel = false,
|
|
|
|
|
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
|
|
|
|
|
{
|
|
|
|
|
string ext = System.IO.Path.GetExtension(FileName);
|
|
|
|
|
ext = ext.ToLower();
|
|
|
|
|
|
|
|
|
|
switch (ext)
|
|
|
|
|
{
|
|
|
|
|
case ".bftex":
|
|
|
|
|
SaveBinaryTexture(FileName);
|
|
|
|
|
break;
|
|
|
|
|
case ".dds":
|
|
|
|
|
SaveDDS(FileName);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
SaveBitMap(FileName);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
internal void SaveBinaryTexture(string FileName)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("Test");
|
2018-11-22 15:20:12 +00:00
|
|
|
|
// Texture.Export(FileName, bntxFile);
|
2018-11-17 02:13:05 +00:00
|
|
|
|
}
|
2018-12-13 02:28:57 +00:00
|
|
|
|
|
2018-11-17 02:13:05 +00:00
|
|
|
|
public override void OnClick(TreeView treeView)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|