1
0
mirror of synced 2024-12-11 15:25:59 +01:00
Switch-Toolbox/Switch_FileFormatsMain/FileFormats/BFRES/BFRESGroupNode.cs
KillzXGaming 2a92afa122 Chr0 animation importing, dae exporting and tons more improvements!
Chr0 can be imported/replaced.
More fixes to importing sections including some errors and proper filtering.
Dae epxorting now has a progress bar and an option to idsable texture exporting.
Bfska can now be swapped between platforms. More sections will handle this method soon!.
Fixed spaces on files from "Export All".
Display multiple texture maps in bcres materials
2019-05-24 15:15:35 -04:00

686 lines
27 KiB
C#

using Switch_Toolbox.Library.NodeWrappers;
using Switch_Toolbox.Library;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System;
using FirstPlugin;
using ResU = Syroot.NintenTools.Bfres;
using ResNX = Syroot.NintenTools.NSW.Bfres;
using Switch_Toolbox.Library.Animations;
using Switch_Toolbox.Library.Forms;
namespace Bfres.Structs
{
public enum BRESGroupType
{
None,
Models,
Textures,
SkeletalAnim,
MaterialAnim,
ShaderParamAnim,
ColorAnim,
TexSrtAnim,
TexPatAnim,
BoneVisAnim,
MatVisAnim,
ShapeAnim,
SceneAnim,
Embedded,
}
public class BFRESGroupNode : STGenericWrapper
{
public bool ShowNewContextMenu
{
set { ContextMenuStrip.Items[0].Visible = value; }
get { return ContextMenuStrip.Items[0].Visible; }
}
public bool IsWiiU;
public override void OnClick(TreeView treeview)
{
if (Parent is BFRES)
((BFRES)Parent).LoadEditors(this);
else if (Parent.Parent is BFRES) {
((BFRES)Parent.Parent).LoadEditors(this);
}else {
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
}
public BFRESGroupNode(bool isWiiU) : base()
{
ImageKey = "folder";
IsWiiU = isWiiU;
LoadContextMenus();
}
public override void LoadContextMenus()
{
ContextMenuStrip = new STContextMenuStrip();
CanExport = false;
CanReplace = false;
CanRename = false;
CanDelete = false;
//Folder Operations
ContextMenuStrip.Items.Add(new STToolStipMenuItem("New", null, NewAction, Keys.Control | Keys.N));
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Import", null, ImportAction, Keys.Control | Keys.I));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Export All", null, ExportAllAction, Keys.Control | Keys.E));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Replace (From Folder)", null, ReplaceAllAction, Keys.Control | Keys.R));
ContextMenuStrip.Items.Add(new STToolStripSeparator());
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Sort", null, SortAction, Keys.Control | Keys.S));
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Clear", null, ClearAction, Keys.Control | Keys.C));
if (Type == BRESGroupType.Textures)
{
ContextMenuStrip.Items.Add(new STToolStripSeparator());
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Batch Generate Mipmaps", null, BatchGenerateMipmapsAction, Keys.Control | Keys.M));
}
if (Type == BRESGroupType.Models)
{
ContextMenuStrip.Items.Add(new STToolStripSeparator());
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Show All Models", null, ShowAllModelsAction, Keys.Control | Keys.A));
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Hide All Models", null, HideAllModelsAction, Keys.Control | Keys.H));
}
}
public override string ExportFilter { get { return GetSubfileExtensions(); } }
public override string ImportFilter { get { return GetSubfileExtensions(); } }
protected void NewAction(object sender, EventArgs e) { NewSubFile(); }
protected void BatchGenerateMipmapsAction(object sender, EventArgs e) { BatchGenerateMipmaps(); }
protected void HideAllModelsAction(object sender, EventArgs e) { HideAllModels(); }
protected void ShowAllModelsAction(object sender, EventArgs e) { ShowAllModels(); }
public void BatchGenerateMipmaps()
{
foreach (FTEX texture in Nodes)
{
texture.SetImageData(texture.GetBitmap(), 0);
}
}
public void ShowAllModels()
{
for (int i = 0; i < Nodes.Count; i++)
{
Nodes[i].Checked = true;
}
}
public void HideAllModels()
{
for (int i = 0; i < Nodes.Count; i++)
{
Nodes[i].Checked = false;
}
}
public BFRESGroupNode(string name) : base() { Text = name; }
public BFRESGroupNode(BRESGroupType type) : base() { Type = type; SetNameByType(); }
public BRESGroupType Type { get; set; }
public Dictionary<string, STGenericWrapper> ResourceNodes = new Dictionary<string, STGenericWrapper>(); //To get instance of classes
public ResNX.ResFile GetResFile() {
if (Parent is BFRES)
return ((BFRES)Parent).resFile;
else
return ((BFRES)Parent.Parent).resFile;
}
public ResU.ResFile GetResFileU() {
if (Parent is BFRES)
return ((BFRES)Parent).resFileU;
else
return ((BFRES)Parent.Parent).resFileU;
}
public void NewSubFile()
{
switch (Type)
{
case BRESGroupType.Models: NewModel(); break;
case BRESGroupType.SkeletalAnim: ((BFRESAnimFolder)Parent).NewSkeletalAnim(); break;
case BRESGroupType.ShaderParamAnim: ((BFRESAnimFolder)Parent).ImportShaderParamAnim(); break;
case BRESGroupType.ColorAnim: ((BFRESAnimFolder)Parent).NewColorAnim(); break;
case BRESGroupType.TexSrtAnim: ((BFRESAnimFolder)Parent).NewTexSrtAnim(); break;
case BRESGroupType.TexPatAnim: ((BFRESAnimFolder)Parent).NewTexPatAnim(); break;
case BRESGroupType.BoneVisAnim: ((BFRESAnimFolder)Parent).NewBoneVisAnim(); break;
case BRESGroupType.MatVisAnim: ((BFRESAnimFolder)Parent).NewMatVisAnim(); break;
case BRESGroupType.ShapeAnim: ((BFRESAnimFolder)Parent).NewShapeAnim(); break;
case BRESGroupType.SceneAnim: ((BFRESAnimFolder)Parent).NewSceneAnim(); break;
case BRESGroupType.Embedded: NewExternalFile(); break;
}
}
public FMDL NewModel(bool AddTreeNode = true)
{
FMDL fmdl = new FMDL();
if (IsWiiU)
{
fmdl.ModelU = new ResU.Model();
//Create skeleton with empty bone
var skeleton = new ResU.Skeleton();
//Create skeleton with empty bone
skeleton.Bones.Add("Root", new ResU.Bone() { Name = "Root" });
fmdl.ModelU.Skeleton = skeleton;
var shape = new ResU.Shape() { Name = "NewShape" };
shape.CreateEmptyMesh();
var VertexBuffer = new ResU.VertexBuffer();
VertexBuffer.CreateEmptyVertexBuffer();
fmdl.ModelU.VertexBuffers.Add(VertexBuffer);
fmdl.ModelU.Shapes.Add("NewShape", shape);
fmdl.ModelU.Materials.Add("NewMaterial", new ResU.Material() { Name = "NewMaterial" });
BfresWiiU.ReadModel(fmdl, fmdl.ModelU);
((BFRES)Parent).AddSkeletonDrawable(fmdl.Skeleton);
}
else
{
fmdl.Model = new ResNX.Model();
//Create skeleton with empty bone
var skeleton = new ResNX.Skeleton();
//Create skeleton with empty bone
skeleton.Bones.Add(new ResNX.Bone() { Name = "Root" });
fmdl.Model.Skeleton = skeleton;
var shape = new ResNX.Shape() { Name = "NewShape" };
shape.CreateEmptyMesh();
fmdl.Model.Shapes.Add(shape);
fmdl.Model.Materials.Add(new ResNX.Material() { Name = "NewMaterial" });
var VertexBuffer = new ResNX.VertexBuffer();
VertexBuffer.CreateEmptyVertexBuffer();
fmdl.Model.VertexBuffers.Add(VertexBuffer);
BfresSwitch.ReadModel(fmdl, fmdl.Model);
((BFRES)Parent).AddSkeletonDrawable(fmdl.Skeleton);
}
if (AddTreeNode)
AddNode(fmdl, "NewModel");
return fmdl;
}
public void NewExternalFile()
{
ExternalFileData externalFileData = new ExternalFileData("NewExternalFile", new byte[0]);
AddNode(externalFileData, "NewExternalFile");
}
private string GetSubfileExtensions()
{
switch (Type)
{
case BRESGroupType.Models: return FileFilters.GetFilter(typeof(FMDL));
case BRESGroupType.Textures: return FileFilters.GetFilter(typeof(FTEX));
case BRESGroupType.SkeletalAnim: return FileFilters.GetFilter(typeof(FSKA));
case BRESGroupType.MaterialAnim: return FileFilters.GetFilter(typeof(FMAA));
case BRESGroupType.ShaderParamAnim: return FileFilters.GetFilter(typeof(FSHU));
case BRESGroupType.ColorAnim: return FileFilters.GetFilter(typeof(FSHU));
case BRESGroupType.TexSrtAnim: return FileFilters.GetFilter(typeof(FSHU));
case BRESGroupType.TexPatAnim: return FileFilters.GetFilter(typeof(FTXP));
case BRESGroupType.BoneVisAnim: return FileFilters.GetFilter(typeof(FVIS));
case BRESGroupType.MatVisAnim: return FileFilters.GetFilter(typeof(FVIS));
case BRESGroupType.ShapeAnim: return FileFilters.GetFilter(typeof(FSHA));
case BRESGroupType.SceneAnim: return FileFilters.GetFilter(typeof(FSCN));
case BRESGroupType.Embedded: return FileFilters.GetFilter(typeof(ExternalFileData));
default: return "All files(*.*)|*.*";
}
}
public override void Import(string[] FileNames) {
Import(FileNames, GetResFile(), GetResFileU());
}
public void Import(string[] FileNames, ResNX.ResFile resFileNX, ResU.ResFile resFileU)
{
if (Type == BRESGroupType.Textures)
{
ImportTexture(FileNames);
return;
}
foreach (string FileName in FileNames)
{
string ResourceName = Path.GetFileNameWithoutExtension(FileName);
string extension = Path.GetExtension(FileName);
switch (Type)
{
case BRESGroupType.Models:
FMDL fmdl = NewModel(false);
fmdl.Text = ResourceName;
fmdl.Replace(FileName, resFileNX, resFileU);
AddNode(fmdl);
break;
case BRESGroupType.SkeletalAnim:
FSKA fska = new FSKA();
fska.Text = ResourceName;
if (IsWiiU)
fska.SkeletalAnimU = new ResU.SkeletalAnim();
else
fska.SkeletalAnim = new ResNX.SkeletalAnim();
fska.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fska);
break;
case BRESGroupType.ShaderParamAnim:
FSHU fshu = new FSHU(new ResU.ShaderParamAnim(), MaterialAnimation.AnimationType.ShaderParam);
fshu.Text = ResourceName;
fshu.Replace(FileName, resFileU);
Nodes.Add(fshu);
break;
case BRESGroupType.ColorAnim:
FSHU fclh = new FSHU(new ResU.ShaderParamAnim(), MaterialAnimation.AnimationType.Color);
fclh.Text = ResourceName;
fclh.Replace(FileName, resFileU);
Nodes.Add(fclh);
break;
case BRESGroupType.TexSrtAnim:
FSHU fsth = new FSHU(new ResU.ShaderParamAnim(), MaterialAnimation.AnimationType.TextureSrt);
fsth.Text = ResourceName;
fsth.Replace(FileName, resFileU);
Nodes.Add(fsth);
break;
case BRESGroupType.TexPatAnim:
FTXP ftxp = new FTXP(new ResU.TexPatternAnim());
ftxp.Text = ResourceName;
ftxp.Replace(FileName, resFileU);
Nodes.Add(ftxp);
break;
case BRESGroupType.BoneVisAnim:
FVIS fbnv = new FVIS();
fbnv.Text = ResourceName;
if (IsWiiU)
fbnv.VisibilityAnimU = new ResU.VisibilityAnim() { Type = ResU.VisibilityAnimType.Bone };
else
fbnv.VisibilityAnim = new ResNX.VisibilityAnim();
fbnv.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fbnv);
break;
case BRESGroupType.MatVisAnim:
FVIS fmtv = new FVIS(new ResU.VisibilityAnim() { Type = ResU.VisibilityAnimType.Material });
fmtv.Text = ResourceName;
fmtv.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fmtv);
break;
case BRESGroupType.ShapeAnim:
FSHA fsha = new FSHA();
fsha.Text = ResourceName;
if (IsWiiU)
fsha.ShapeAnimU = new ResU.ShapeAnim();
else
fsha.ShapeAnim = new ResNX.ShapeAnim();
fsha.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fsha);
break;
case BRESGroupType.SceneAnim:
FSCN fscn = new FSCN();
fscn.Text = ResourceName;
if (IsWiiU)
fscn.SceneAnimU = new ResU.SceneAnim();
else
fscn.SceneAnim = new ResNX.SceneAnim();
fscn.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fscn);
break;
case BRESGroupType.Embedded:
ExternalFileData ext = new ExternalFileData(ResourceName, File.ReadAllBytes(FileName));
ext.Replace(FileName);
Nodes.Add(ext);
break;
case BRESGroupType.MaterialAnim:
FMAA fmaa = new FMAA(new ResNX.MaterialAnim(), MaterialAnimation.AnimationType.ShaderParam);
fmaa.Replace(FileName);
Nodes.Add(fmaa);
break;
}
}
}
public void AddNode(STGenericWrapper node, string Name)
{
node.Text = SearchDuplicateName(Name);
AddNode(node);
}
public void AddNode(STGenericWrapper node)
{
if (node.Text == string.Empty)
throw new System.Exception("Text invalid. Must not be empty! ");
Nodes.Add(node);
ResourceNodes.Add(node.Text, node);
}
public void RemoveChild(STGenericWrapper node)
{
Nodes.Remove(node);
ResourceNodes.Remove(node.Text);
}
public override void Clear()
{
var result = MessageBox.Show("Are you sure you want to clear this section? This cannot be undone!",
"", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
foreach (TreeNode node in Nodes)
{
if (node is STGenericWrapper)
{
((STGenericWrapper)node).Unload();
RemoveChild(((STGenericWrapper)node));
}
}
ResourceNodes.Clear();
Nodes.Clear();
}
}
public STGenericWrapper GetFirstChild()
{
if (Nodes.Count > 0 && Nodes[0] is STGenericWrapper)
return (STGenericWrapper)Nodes[0];
else
return new STGenericWrapper();
}
public void SetNameByType()
{
Text = SetName();
}
private string SetName()
{
switch (Type)
{
case BRESGroupType.Models: return "Models";
case BRESGroupType.Textures: return "Textures";
case BRESGroupType.SkeletalAnim: return "Skeletal Animations";
case BRESGroupType.ShaderParamAnim: return "Shader Param Animations";
case BRESGroupType.ColorAnim: return "Color Animations";
case BRESGroupType.TexSrtAnim: return "Texture SRT Animations";
case BRESGroupType.TexPatAnim: return "Texture Pattern Animations";
case BRESGroupType.BoneVisAnim: return "Bone Visibilty Animations";
case BRESGroupType.MatVisAnim: return "Material Visibilty Animations";
case BRESGroupType.ShapeAnim: return "Shape Animations";
case BRESGroupType.SceneAnim: return "Scene Animations";
case BRESGroupType.Embedded: return "Embedded Files";
case BRESGroupType.MaterialAnim: return "Material Animations";
default:
throw new System.Exception("Unknown type? " + Type);
}
}
public void GetFileType()
{
var child = GetFirstChild();
if (Text == "Models" || child is FMDL)
Type = BRESGroupType.Models;
if (Text == "Textures" || child is FTEX)
Type = BRESGroupType.Textures;
if (Text == "Skeleton Animations" || child is FSKA)
Type = BRESGroupType.SkeletalAnim;
if (Text == "Material Animations" || child is FMAA)
Type = BRESGroupType.MaterialAnim;
if (Text == "Shader Param Animations" || child is FSHU)
Type = BRESGroupType.ShaderParamAnim;
if (Text == "Color Animations" || child is FSHU)
Type = BRESGroupType.ColorAnim;
if (Text == "Texture Srt Animations" || child is FSHU)
Type = BRESGroupType.TexSrtAnim;
if (Text == "Texture Pattern Animations" || child is FTXP)
Type = BRESGroupType.TexPatAnim;
if (Text == "Bone Visibilty Animations" || child is FVIS)
Type = BRESGroupType.BoneVisAnim;
if (Text == "Material Visibilty Animations" || child is FVIS)
Type = BRESGroupType.MatVisAnim;
if (Text == "Embedded Files" || child is ExternalFileData)
Type = BRESGroupType.Embedded;
}
int IndexStr = 0;
public string SearchDuplicateName(string Name)
{
if (ResourceNodes.ContainsKey(Name))
return SearchDuplicateName($"{Name}{IndexStr++}");
else
return Name;
}
public void ImportTexture(string[] FileNames)
{
GTXTextureImporter importer = new GTXTextureImporter();
List<GTXImporterSettings> settings = new List<GTXImporterSettings>();
foreach (string name in FileNames)
{
string TextureName = Path.GetFileNameWithoutExtension(name);
string ext = Path.GetExtension(name);
ext = ext.ToLower();
if (ext == ".bftex")
{
FTEX ftex = new FTEX();
ftex.texture = new ResU.Texture();
ftex.texture.Import(name, GetResFileU());
ftex.IsEdited = true;
ftex.Read(ftex.texture);
AddNode(ftex);
}
else if (ext == ".dds" || ext == ".dds2")
{
FTEX ftex = new FTEX();
ftex.texture = new ResU.Texture();
GTXImporterSettings setting = FTEX.SetImporterSettings(name);
if (setting.DataBlockOutput != null)
{
var surface = GTXSwizzle.CreateGx2Texture(setting.DataBlockOutput[0], setting);
var tex = FTEX.FromGx2Surface(surface, setting.TexName);
ftex.UpdateTex(tex);
ftex.IsEdited = true;
ftex.Read(ftex.texture);
ftex.LoadOpenGLTexture();
AddNode(ftex);
}
}
else
{
settings.Add(FTEX.SetImporterSettings(name));
}
}
if (settings.Count == 0)
{
importer.Dispose();
}
else
{
importer.LoadSettings(settings);
if (importer.ShowDialog() == DialogResult.OK)
{
ImportTexture(settings);
settings.Clear();
GC.Collect();
Cursor.Current = Cursors.Default;
}
}
}
public GTXImporterSettings LoadSettings(System.Drawing.Image image, string Name)
{
var importer = new GTXImporterSettings();
importer.LoadBitMap(image, Name);
return importer;
}
private void ImportTexture(List<GTXImporterSettings> settings)
{
Cursor.Current = Cursors.WaitCursor;
foreach (var setting in settings)
{
if (setting.GenerateMipmaps)
{
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null)
{
FTEX ftex = new FTEX();
ftex.texture = new ResU.Texture();
var surface = GTXSwizzle.CreateGx2Texture(setting.DataBlockOutput[0], setting);
var tex = FTEX.FromGx2Surface(surface, setting.TexName);
ftex.UpdateTex(tex);
ftex.IsEdited = true;
ftex.Read(ftex.texture);
ftex.LoadOpenGLTexture();
AddNode(ftex);
}
else
{
MessageBox.Show("Something went wrong???");
}
}
}
public void ImportTexture(ImageKeyFrame[] Keys, string TextureName)
{
if (ResourceNodes.ContainsKey(TextureName) || Type != BRESGroupType.Textures)
return;
GTXTextureImporter importer = new GTXTextureImporter();
List<GTXImporterSettings> settings = new List<GTXImporterSettings>();
foreach (var key in Keys) {
settings.Add(FTEX.SetImporterSettings(key.Image, $"{TextureName}{key.Frame}"));
}
importer.LoadSettings(settings);
if (importer.ShowDialog() == DialogResult.OK) {
ImportTexture(settings);
}
settings.Clear();
GC.Collect();
Cursor.Current = Cursors.Default;
}
public void ImportPlaceholderTexture(string TextureName)
{
if (ResourceNodes.ContainsKey(TextureName) || Type != BRESGroupType.Textures)
return;
if (TextureName == "Basic_Alb")
ImportBasicTextures("Basic_Alb");
else if (TextureName == "Basic_Nrm")
ImportBasicTextures("Basic_Nrm");
else if (TextureName == "Basic_Spm")
ImportBasicTextures("Basic_Spm");
else if (TextureName == "Basic_Sphere")
ImportBasicTextures("Basic_Sphere");
else if (TextureName == "Basic_Mtl")
ImportBasicTextures("Basic_Mtl");
else if (TextureName == "Basic_Rgh")
ImportBasicTextures("Basic_Rgh");
else if (TextureName == "Basic_MRA")
ImportBasicTextures("Basic_MRA");
else if (TextureName == "Basic_Bake_st0")
ImportBasicTextures("Basic_Bake_st0");
else if (TextureName == "Basic_Bake_st1")
ImportBasicTextures("Basic_Bake_st1");
else if (TextureName == "Basic_Emm")
ImportBasicTextures("Basic_Emm");
else
{
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.InjectTexErrored, TextureName);
}
}
private void ImportPlaceholderTexture(byte[] data, string TextureName)
{
GTXImporterSettings setting = new GTXImporterSettings();
setting.LoadDDS(TextureName, data);
var surface = GTXSwizzle.CreateGx2Texture(setting.DataBlockOutput[0], setting);
FTEX ftex = new FTEX();
ftex.texture = new ResU.Texture();
ftex.texture = FTEX.FromGx2Surface(surface, setting.TexName);
ftex.IsEdited = true;
ftex.Read(ftex.texture);
AddNode(ftex);
ftex.LoadOpenGLTexture();
}
public void ImportBasicTextures(string TextureName, bool BC5Nrm = true)
{
if (ResourceNodes.ContainsKey(TextureName) || Type != BRESGroupType.Textures)
return;
if (TextureName == "Basic_Alb")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.InjectTexErrored, TextureName);
if (TextureName == "Basic_Nrm" && BC5Nrm)
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Basic_NrmBC5, TextureName);
if (TextureName == "Basic_Nrm" && BC5Nrm == false)
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Basic_Nrm, TextureName);
if (TextureName == "Basic_Spm")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Black, TextureName);
if (TextureName == "Basic_Sphere")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Black, TextureName);
if (TextureName == "Basic_Mtl")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Black, TextureName);
if (TextureName == "Basic_Rgh")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.White, TextureName);
if (TextureName == "Basic_MRA")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Black, TextureName);
if (TextureName == "Basic_Bake_st0")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Basic_Bake_st0, TextureName);
if (TextureName == "Basic_Bake_st1")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Basic_Bake_st1, TextureName);
}
}
}