Switch-Toolbox/File_Format_Library/FileFormats/BFRES/BFRES.cs
KillzXGaming cb13c0a00a Some fixes
Fixed loading files from clicked on when a single instance of the tool is used.
Fixed the UV editor, which loads materails and texture maps properly.
Adjusted loading archives which produced some duplicate file issues when the archive loads the file, and a tree node is clicked on. Ie bntx clearing, but another one would stay in memory.
Fixed bntx replacing.
2019-08-12 15:19:30 -04:00

1966 lines
77 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Data;
using System.Threading;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.Forms;
using Toolbox.Library.IO;
using Bfres.Structs;
using ResU = Syroot.NintenTools.Bfres;
using Syroot.NintenTools.NSW.Bfres;
using Toolbox.Library.Animations;
using Toolbox.Library.NodeWrappers;
using GL_EditorFramework.Interfaces;
using FirstPlugin.Forms;
using FirstPlugin.NodeWrappers;
using OpenTK;
namespace FirstPlugin
{
public class BFRES : BFRESWrapper, IFileFormat
{
public FileType FileType { get; set; } = FileType.Resource;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "BFRES" };
public string[] Extension { get; set; } = new string[] {
"*.bfres", "*.sbfres", "*.sbmapopen", "*.sbstftex", "*.sbitemico", "*.sbmaptex", "*.sbreviewtex" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
return reader.CheckSignature(4, "FRES");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
types.Add(typeof(MenuExt));
return types.ToArray();
}
}
public override string ExportFilter => Utils.GetAllFilters(new BFRES());
//Stores the skeleton and models in this
public DrawableContainer DrawableContainer = new DrawableContainer();
class MenuExt : IFileMenuExtension
{
public STToolStripItem[] NewFileMenuExtensions => newFileExt;
public STToolStripItem[] NewFromFileMenuExtensions => null;
public STToolStripItem[] EditMenuExtensions => editExt;
public STToolStripItem[] ToolsMenuExtensions => toolExt;
public STToolStripItem[] TitleBarExtensions => null;
public STToolStripItem[] CompressionMenuExtensions => null;
public STToolStripItem[] ExperimentalMenuExtensions => null;
public ToolStripButton[] IconButtonMenuExtensions => null;
STToolStripItem[] toolExt = new STToolStripItem[1];
STToolStripItem[] newFileExt = new STToolStripItem[2];
STToolStripItem[] editExt = new STToolStripItem[1];
public MenuExt()
{
// toolExt[0] = new STToolStripItem("Models");
// toolExt[0].DropDownItems.Add(new STToolStripItem("Batch Export (BFRES)", Export));
editExt[0] = new STToolStripItem("Use Advanced Editor As Default", AdvancedEditor);
newFileExt[0] = new STToolStripItem("BFRES (Switch)", NewSwitchBfres);
newFileExt[1] = new STToolStripItem("BFRES (Wii U)", NewWiiUBfres);
editExt[0].Checked = !PluginRuntime.UseSimpleBfresEditor;
}
private void AdvancedEditor(object sender, EventArgs args)
{
BFRES file = null;
ObjectEditor editor = (ObjectEditor)LibraryGUI.GetActiveForm();
if (editor != null)
{
file = (BFRES)editor.GetActiveFile();
}
if (editExt[0].Checked)
{
editExt[0].Checked = false;
PluginRuntime.UseSimpleBfresEditor = true;
if (file != null)
file.LoadSimpleMode();
}
else
{
editExt[0].Checked = true;
PluginRuntime.UseSimpleBfresEditor = false;
if (file != null)
file.LoadAdvancedMode();
}
}
private void NewWiiUBfres(object sender, EventArgs args)
{
BFRES bfres = new BFRES();
bfres.IFileInfo = new IFileInfo();
bfres.FileName = "Untitled.bfres";
bfres.Load(new MemoryStream(BfresWiiU.CreateNewBFRES("Untitled.bfres")));
ObjectEditor editor = new ObjectEditor(bfres);
editor.Text = "Untitled-" + 0;
LibraryGUI.CreateMdiWindow(editor);
}
private void NewSwitchBfres(object sender, EventArgs args)
{
BFRES bfres = new BFRES();
bfres.IFileInfo = new IFileInfo();
bfres.FileName = "Untitled.bfres";
bfres.Load(new MemoryStream(CreateNewBFRESSwitch("Untitled.bfres")));
ObjectEditor editor = new ObjectEditor(bfres);
editor.Text = "Untitled-" + 0;
LibraryGUI.CreateMdiWindow(editor);
}
private void DebugInfo(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = Utils.GetAllFilters(new BFRES());
if (ofd.ShowDialog() != DialogResult.OK)
return;
var debugInfo = new DebugInfoBox();
debugInfo.Show();
debugInfo.PrintDebugInfo(ofd.FileName);
}
private void Export(object sender, EventArgs args)
{
string formats = FileFilters.FMDL_EXPORT;
string[] forms = formats.Split('|');
List<string> Formats = new List<string>();
for (int i = 0; i < forms.Length; i++)
{
if (i > 1 || i == (forms.Length - 1)) //Skip lines with all extensions
{
if (!forms[i].StartsWith("*"))
Formats.Add(forms[i]);
}
}
BatchFormatExport form = new BatchFormatExport(Formats);
if (form.ShowDialog() == DialogResult.OK)
{
string Extension = form.GetSelectedExtension();
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
ofd.Filter = Utils.GetAllFilters(new Type[] { typeof(BFRES), typeof(SARC) });
if (ofd.ShowDialog() == DialogResult.OK)
{
FolderSelectDialog folderDialog = new FolderSelectDialog();
if (folderDialog.ShowDialog() == DialogResult.OK)
{
foreach (string file in ofd.FileNames)
{
var FileFormat = STFileLoader.OpenFileFormat(file, new Type[] { typeof(BFRES), typeof(SARC) });
if (FileFormat == null)
continue;
SearchBinary(FileFormat, folderDialog.SelectedPath, Extension);
}
}
}
}
}
private void SearchBinary(IFileFormat FileFormat, string Folder, string Extension)
{
if (FileFormat is SARC)
{
foreach (var file in ((SARC)FileFormat).Files)
{
var archiveFile = STFileLoader.OpenFileFormat(file.FileName, new Type[] { typeof(BFRES), typeof(SARC) }, file.FileData);
if (archiveFile == null)
continue;
SearchBinary(archiveFile, Folder, Extension);
}
}
if (FileFormat is BFRES)
{
// ((BFRES)FileFormat).Export(Path.Combine(Folder, $"{FileFormat.FileName}{Extension}"));
}
FileFormat.Unload();
}
}
private static byte[] CreateNewBFRESSwitch(string Name)
{
MemoryStream mem = new MemoryStream();
ResFile resFile = new ResFile();
resFile.Name = Name;
resFile.Save(mem);
var data = mem.ToArray();
mem.Close();
mem.Dispose();
return data;
}
public BoundingBox GetBoundingBox()
{
Vector3 Min = new Vector3(0);
Vector3 Max = new Vector3(0);
var Models = GetModels();
if (Models == null)
return new BoundingBox();
foreach (FMDL model in Models)
{
foreach (var shape in model.shapes)
{
foreach (var vertex in shape.vertices)
{
Min.X = Math.Min(Min.X, vertex.pos.X);
Min.Y = Math.Min(Min.Y, vertex.pos.Y);
Min.Z = Math.Min(Min.Z, vertex.pos.Z);
Max.X = Math.Max(Max.X, vertex.pos.X);
Max.Y = Math.Max(Max.Y, vertex.pos.Y);
Max.Z = Math.Max(Max.Z, vertex.pos.Z);
}
}
}
return new BoundingBox()
{
Max = Max,
Min = Min,
};
}
public void OnPropertyChanged()
{
if (resFile != null)
{
Text = resFile.Name;
}
else
{
Text = resFileU.Name;
}
STPropertyGrid editor = (STPropertyGrid)LibraryGUI.GetActiveContent(typeof(STPropertyGrid));
if (editor != null)
editor.Refresh();
}
public void LoadAdvancedMode()
{
foreach (var model in BFRESRender.models)
{
foreach (var mat in model.materials.Values)
{
foreach (var tex in mat.TextureMaps)
{
mat.Nodes.RemoveByKey(tex.Name);
}
}
}
}
public void LoadSimpleMode()
{
ObjectEditor editor = (ObjectEditor)LibraryGUI.GetActiveForm();
if (editor == null)
return;
editor.BeginUpdate();
foreach (var model in BFRESRender.models)
{
foreach (var mat in model.materials.Values)
{
mat.Nodes.Clear();
foreach (MatTexture tex in mat.TextureMaps)
{
mat.Nodes.Add(new MatTextureWrapper(tex.Name, tex.Name, tex));
}
}
}
foreach (TreeNode node in Nodes)
{
if (node is BFRESAnimFolder)
{
foreach (BFRESGroupNode animFolder in node.Nodes)
{
if (animFolder.Type == BRESGroupType.SkeletalAnim)
{
foreach (FSKA anim in animFolder.Nodes)
{
foreach (FSKA.BoneAnimNode bone in ((FSKA)anim).Bones)
{
int index = 0;
if (bone.BoneAnimU != null)
{
foreach (var curve in bone.BoneAnimU.Curves)
GetSkeletonAnimCurveOffset(curve.AnimDataOffset);
}
else
{
foreach (var curve in bone.BoneAnim.Curves)
GetSkeletonAnimCurveOffset(curve.AnimDataOffset);
}
}
}
}
if (animFolder.Type == BRESGroupType.ColorAnim)
{
foreach (var anim in animFolder.Nodes)
{
if (anim is FMAA)
{
foreach (FMAA.MaterialAnimEntry mat in ((FMAA)anim).Nodes)
{
}
}
}
}
}
}
}
editor.EndUpdate();
}
private string GetSkeletonAnimCurveOffset(uint offset)
{
switch ((FSKA.TrackType)offset)
{
case FSKA.TrackType.XPOS: return "Translate_X";
case FSKA.TrackType.YPOS: return "Translate_Y";
case FSKA.TrackType.ZPOS: return "Translate_Z";
case FSKA.TrackType.XROT: return "Rotate_X";
case FSKA.TrackType.YROT: return "Rotate_Y";
case FSKA.TrackType.ZROT: return "Rotate_Z";
case FSKA.TrackType.WROT: return "Rotate_W";
case FSKA.TrackType.XSCA: return "Scale_X";
case FSKA.TrackType.YSCA: return "Scale_Y";
case FSKA.TrackType.ZSCA: return "Scale_Z";
default: offset.ToString(); break;
}
return "";
}
public bool HasShapes()
{
BFRESRender.UpdateModelList();
for (int i = 0; i < BFRESRender.models.Count; i++)
{
if (BFRESRender.models[i].shapes.Count > 0)
return true;
}
return false;
}
public STForm ActiveFormEditor; //For active form windows as editors
private bool DrawablesLoaded = false;
public void LoadEditors(object SelectedSection)
{
BfresEditor bfresEditor = (BfresEditor)LibraryGUI.GetActiveContent(typeof(BfresEditor));
bool HasModels = false;
bool hasShapes = HasShapes();
if (bfresEditor == null)
{
HasModels = BFRESRender.models.Count > 0;
bfresEditor = new BfresEditor(HasModels);
bfresEditor.Dock = DockStyle.Fill;
LibraryGUI.LoadEditor(bfresEditor);
}
bool ViewportToggled = bfresEditor.DisplayViewport;
if (SelectedSection is FTEX)
{
ImageEditorBase editorFtex = (ImageEditorBase)bfresEditor.GetActiveEditor(typeof(ImageEditorBase));
if (editorFtex == null)
{
editorFtex = new ImageEditorBase();
editorFtex.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editorFtex);
}
editorFtex.Text = Text;
editorFtex.LoadProperties(((FTEX)SelectedSection).texture);
editorFtex.LoadImage((FTEX)SelectedSection);
if (Runtime.DisplayViewport && ViewportToggled)
editorFtex.SetEditorOrientation(true);
if (((FTEX)SelectedSection).texture.UserData != null)
{
UserDataEditor userEditor = (UserDataEditor)editorFtex.GetActiveTabEditor(typeof(UserDataEditor));
if (userEditor == null)
{
userEditor = new UserDataEditor();
userEditor.Name = "User Data";
editorFtex.AddCustomControl(userEditor, typeof(UserDataEditor));
}
userEditor.LoadUserData(((FTEX)SelectedSection).texture.UserData);
}
return;
}
if (SelectedSection is TextureData)
{
ImageEditorBase editor = (ImageEditorBase)bfresEditor.GetActiveEditor(typeof(ImageEditorBase));
if (editor == null)
{
editor = new ImageEditorBase();
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
if (((TextureData)SelectedSection).Texture.UserData != null)
{
UserDataEditor userEditor = (UserDataEditor)editor.GetActiveTabEditor(typeof(UserDataEditor));
if (userEditor == null)
{
userEditor = new UserDataEditor();
userEditor.Name = "User Data";
editor.AddCustomControl(userEditor, typeof(UserDataEditor));
}
userEditor.LoadUserData(((TextureData)SelectedSection).Texture.UserData.ToList());
}
editor.Text = Text;
if (Runtime.DisplayViewport && ViewportToggled)
editor.SetEditorOrientation(true);
editor.LoadProperties(((TextureData)SelectedSection).Texture);
editor.LoadImage((TextureData)SelectedSection);
return;
}
if (SelectedSection is BNTX)
{
STPropertyGrid editor = (STPropertyGrid)bfresEditor.GetActiveEditor(typeof(STPropertyGrid));
if (editor == null)
{
editor = new STPropertyGrid();
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadProperty(((BNTX)SelectedSection).BinaryTexFile, OnPropertyChanged);
return;
}
if (SelectedSection is ExternalFileData)
{
ArchiveFilePanel editor = (ArchiveFilePanel)LibraryGUI.GetActiveContent(typeof(ArchiveFilePanel));
if (editor == null)
{
editor = new ArchiveFilePanel();
editor.Dock = DockStyle.Fill;
LibraryGUI.LoadEditor(editor);
}
editor.LoadFile(((ExternalFileData)SelectedSection).ArchiveFileInfo);
editor.UpdateEditor();
return;
}
if (!DrawablesLoaded)
{
ObjectEditor.AddContainer(DrawableContainer);
DrawablesLoaded = true;
}
if (Runtime.UseOpenGL)
bfresEditor.LoadViewport(this, hasShapes, DrawableContainer);
if (SelectedSection is BFRES && hasShapes)
bfresEditor.FrameCamera(BFRESRender);
bool IsSimpleEditor = PluginRuntime.UseSimpleBfresEditor;
if (IsSimpleEditor)
{
if (SelectedSection is MatTextureWrapper)
{
SamplerEditorSimple editorT = (SamplerEditorSimple)bfresEditor.GetActiveEditor(typeof(SamplerEditorSimple));
if (editorT == null)
{
editorT = new SamplerEditorSimple();
editorT.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editorT);
}
editorT.Text = Text;
editorT.LoadTexture(((MatTextureWrapper)SelectedSection).textureMap);
return;
}
STPropertyGrid editor = (STPropertyGrid)bfresEditor.GetActiveEditor(typeof(STPropertyGrid));
if (editor == null)
{
editor = new STPropertyGrid();
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.Text = Text;
if (SelectedSection is BFRES)
{
if (resFile != null)
editor.LoadProperty(resFile, OnPropertyChanged);
else
editor.LoadProperty(resFileU, OnPropertyChanged);
}
else if (SelectedSection is FMDL)
{
if (((FMDL)SelectedSection).ModelU != null)
{
editor.LoadProperty(((FMDL)SelectedSection).ModelU, OnPropertyChanged);
}
else
editor.LoadProperty(((FMDL)SelectedSection).Model, OnPropertyChanged);
}
else if (SelectedSection is FSHP)
{
if (((FSHP)SelectedSection).ShapeU != null)
editor.LoadProperty(((FSHP)SelectedSection).ShapeU, OnPropertyChanged);
else
editor.LoadProperty(((FSHP)SelectedSection).Shape, OnPropertyChanged);
}
else if (SelectedSection is FMAT)
{
if (((FMAT)SelectedSection).MaterialU != null)
editor.LoadProperty(((FMAT)SelectedSection).MaterialU, OnPropertyChanged);
else
editor.LoadProperty(((FMAT)SelectedSection).Material, OnPropertyChanged);
}
else if (SelectedSection is BfresBone)
{
if (((BfresBone)SelectedSection).BoneU != null)
editor.LoadProperty(((BfresBone)SelectedSection).BoneU, OnPropertyChanged);
else
editor.LoadProperty(((BfresBone)SelectedSection).Bone, OnPropertyChanged);
}
else if (SelectedSection is FSKL.fsklNode)
{
if (((FSKL.fsklNode)SelectedSection).SkeletonU != null)
editor.LoadProperty(((FSKL.fsklNode)SelectedSection).SkeletonU, OnPropertyChanged);
else
editor.LoadProperty(((FSKL.fsklNode)SelectedSection).Skeleton, OnPropertyChanged);
}
else if (SelectedSection is FSKA)
{
if (((FSKA)SelectedSection).SkeletalAnimU != null)
editor.LoadProperty(((FSKA)SelectedSection).SkeletalAnimU, OnPropertyChanged);
else
editor.LoadProperty(((FSKA)SelectedSection).SkeletalAnim, OnPropertyChanged);
}
else if (SelectedSection is FMAA)
{
editor.LoadProperty(((FMAA)SelectedSection).MaterialAnim, OnPropertyChanged);
}
else
editor.LoadProperty(null, OnPropertyChanged);
}
else
{
if (SelectedSection is BFRES)
{
STPropertyGrid editor = (STPropertyGrid)bfresEditor.GetActiveEditor(typeof(STPropertyGrid));
if (editor == null)
{
editor = new STPropertyGrid();
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.Text = Text;
if (resFile != null)
editor.LoadProperty(resFile, OnPropertyChanged);
else
editor.LoadProperty(resFileU, OnPropertyChanged);
}
else if (SelectedSection is BFRESGroupNode)
{
STPropertyGrid editor = (STPropertyGrid)bfresEditor.GetActiveEditor(typeof(STPropertyGrid));
if (editor == null)
{
editor = new STPropertyGrid();
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.Text = Text;
editor.LoadProperty(null, null);
}
else if (SelectedSection is FSKL.fsklNode)
{
FSKLEditor editor = (FSKLEditor)bfresEditor.GetActiveEditor(typeof(FSKLEditor));
if (editor == null)
{
editor = new FSKLEditor();
editor.Text = Text;
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadSkeleton(((FSKL.fsklNode)SelectedSection).fskl);
}
else if (SelectedSection is BfresBone)
{
BfresBoneEditor editor = (BfresBoneEditor)bfresEditor.GetActiveEditor(typeof(BfresBoneEditor));
if (editor == null)
{
editor = new BfresBoneEditor();
editor.Text = Text;
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadBone((BfresBone)SelectedSection);
}
else if (SelectedSection is FSHP)
{
BfresShapeEditor editor = (BfresShapeEditor)bfresEditor.GetActiveEditor(typeof(BfresShapeEditor));
if (editor == null)
{
editor = new BfresShapeEditor();
editor.Text = Text;
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadShape((FSHP)SelectedSection);
}
else if (SelectedSection is FMAT)
{
FMATEditor editor = (FMATEditor)bfresEditor.GetActiveEditor(typeof(FMATEditor));
if (editor == null)
{
editor = new FMATEditor();
editor.Text = Text;
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadMaterial((FMAT)SelectedSection);
}
else if (SelectedSection is FSKA.BoneAnimNode)
{
BoneAnimEditor editor = (BoneAnimEditor)bfresEditor.GetActiveEditor(typeof(BoneAnimEditor));
if (editor == null)
{
editor = new BoneAnimEditor();
editor.Text = Text;
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadBoneAnim((FSKA.BoneAnimNode)SelectedSection);
}
else if (SelectedSection is FSCN.BfresCameraAnim)
{
SceneAnimEditor editor = (SceneAnimEditor)bfresEditor.GetActiveEditor(typeof(SceneAnimEditor));
if (editor == null)
{
editor = new SceneAnimEditor();
editor.Text = Text;
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadCameraAnim((FSCN.BfresCameraAnim)SelectedSection);
}
else if (SelectedSection is FSCN.BfresLightAnim)
{
SceneAnimEditor editor = (SceneAnimEditor)bfresEditor.GetActiveEditor(typeof(SceneAnimEditor));
if (editor == null)
{
editor = new SceneAnimEditor();
editor.Text = Text;
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadLightAnim((FSCN.BfresLightAnim)SelectedSection);
}
else if (SelectedSection is FSCN.BfresFogAnim)
{
SceneAnimEditor editor = (SceneAnimEditor)bfresEditor.GetActiveEditor(typeof(SceneAnimEditor));
if (editor == null)
{
editor = new SceneAnimEditor();
editor.Text = Text;
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadFogAnim((FSCN.BfresFogAnim)SelectedSection);
}
else if (SelectedSection is FMDL)
OpenSubFileEditor<FMDL>(SelectedSection, bfresEditor);
else if (SelectedSection is FSKA)
OpenSubFileEditor<FSKA>(SelectedSection, bfresEditor);
else if (SelectedSection is FSHU)
OpenSubFileEditor<FSHU>(SelectedSection, bfresEditor);
else if (SelectedSection is FSCN)
OpenSubFileEditor<FSCN>(SelectedSection, bfresEditor);
else if (SelectedSection is FSHA)
OpenSubFileEditor<FSHA>(SelectedSection, bfresEditor);
else if (SelectedSection is FTXP)
OpenSubFileEditor<FTXP>(SelectedSection, bfresEditor);
else if (SelectedSection is FMAA)
OpenSubFileEditor<FMAA>(SelectedSection, bfresEditor);
else if (SelectedSection is FVIS)
OpenSubFileEditor<FVIS>(SelectedSection, bfresEditor);
}
}
private SubFileEditor OpenSubFileEditor<T>(object node, BfresEditor bfresEditor) where T : STGenericWrapper
{
SubFileEditor editor = (SubFileEditor)bfresEditor.GetActiveEditor(typeof(SubFileEditor));
if (editor == null)
{
editor = new SubFileEditor();
editor.Dock = DockStyle.Fill;
bfresEditor.LoadEditor(editor);
}
editor.LoadSubFile<T>(node);
return editor;
}
public BFRESRender BFRESRender;
public void Load(System.IO.Stream stream)
{
CanSave = true;
ImageKey = "bfres";
SelectedImageKey = "bfres";
using (FileReader reader = new FileReader(stream, true))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
reader.Position = 4;
if (reader.ReadInt32() != 0x20202020)
IsWiiU = true;
reader.Position = 0;
}
LoadMenus(IsWiiU);
BFRESRender = new BFRESRender();
DrawableContainer.Drawables.Add(BFRESRender);
DrawableContainer.Name = FileName;
BFRESRender.ModelTransform = MarioCostumeEditor.SetTransform(FileName);
BFRESRender.ResFileNode = this;
if (IsWiiU)
{
LoadFile(new Syroot.NintenTools.Bfres.ResFile(stream));
}
else
{
LoadFile(new Syroot.NintenTools.NSW.Bfres.ResFile(stream));
}
var Models = GetModels();
if (Models != null)
{
foreach (FMDL mdl in Models)
{
BFRESRender.models.Add(mdl);
DrawableContainer.Drawables.Add(mdl.Skeleton);
}
}
}
public void Unload()
{
BFRESRender.Destroy();
DrawableContainer.Drawables.Clear();
ObjectEditor.RemoveContainer(DrawableContainer);
if (resFile != null)
{
resFile.Models.Clear();
resFile.SkeletalAnims.Clear();
resFile.MaterialAnims.Clear();
resFile.SceneAnims.Clear();
resFile.ShapeAnims.Clear();
resFile.BoneVisibilityAnims.Clear();
resFile.ModelDict.Clear();
resFile.SkeletalAnimDict.Clear();
resFile.MaterialAnimDict.Clear();
resFile.SceneAnimDict.Clear();
resFile.ShapeAnimDict.Clear();
resFile.BoneVisibilityAnimDict.Clear();
resFile.ExternalFiles.Clear();
resFile.ExternalFileDict.Clear();
}
else if (resFileU != null)
{
resFileU.Models.Clear();
resFileU.Textures.Clear();
resFileU.SkeletalAnims.Clear();
resFileU.ShaderParamAnims.Clear();
resFileU.ColorAnims.Clear();
resFileU.TexSrtAnims.Clear();
resFileU.TexPatternAnims.Clear();
resFileU.BoneVisibilityAnims.Clear();
resFileU.MatVisibilityAnims.Clear();
resFileU.ShapeAnims.Clear();
resFileU.SceneAnims.Clear();
resFileU.ExternalFiles.Clear();
}
foreach (var node in TreeViewExtensions.Collect(BFRESRender.ResFileNode.Nodes))
{
if (node is BFRESGroupNode)
{
if (((BFRESGroupNode)node).Type == BRESGroupType.Models)
{
for (int i = 0; i < ((BFRESGroupNode)node).Nodes.Count; i++)
{
FMDL model = ((FMDL)((BFRESGroupNode)node).Nodes[i]);
for (int shp = 0; shp < model.shapes.Count; shp++)
{
model.shapes[shp].vertices.Clear();
model.shapes[shp].faces.Clear();
foreach (var lod in model.shapes[shp].lodMeshes)
lod.faces.Clear();
}
}
}
if (((BFRESGroupNode)node).Type == BRESGroupType.Textures)
{
for (int i = 0; i < ((BFRESGroupNode)node).Nodes.Count; i++)
((FTEX)((BFRESGroupNode)node).Nodes[i]).Unload();
if (PluginRuntime.ftexContainers.Contains(((BFRESGroupNode)node)))
PluginRuntime.ftexContainers.Remove(((BFRESGroupNode)node));
}
((BFRESGroupNode)node).ResourceNodes.Clear();
((BFRESGroupNode)node).Nodes.Clear();
}
if (node is BNTX)
((BNTX)node).Unload();
}
Nodes.Clear();
GC.SuppressFinalize(this);
}
public void Save(System.IO.Stream stream)
{
var Models = GetModels();
if (Models != null)
{
foreach (FMDL mdl in Models)
{
for (int s = 0; s < mdl.shapes.Count; s++)
{
SetShaderAssignAttributes(mdl.shapes[s]);
}
}
}
if (IsWiiU)
SaveWiiU(stream);
else
SaveSwitch(stream);
}
public TreeNodeCollection GetModels()
{
foreach (var folder in Nodes)
{
if (folder is BFRESGroupNode && ((BFRESGroupNode)folder).Type == BRESGroupType.Models)
return ((BFRESGroupNode)folder).Nodes;
}
return null;
}
public ResFile resFile = null;
public ResU.ResFile resFileU = null;
public override void OnClick(TreeView treeView)
{
LoadEditors(this);
}
public BFRESGroupNode GetFTEXContainer
{
get
{
foreach (TreeNode folder in Nodes)
{
if (folder is BFRESGroupNode)
{
if (((BFRESGroupNode)folder).Type == BRESGroupType.Textures)
return (BFRESGroupNode)folder;
}
}
return null;
}
}
public BNTX GetBNTX
{
get
{
foreach (TreeNode folder in Nodes)
{
if (folder is BNTX)
return (BNTX)folder;
}
return null;
}
}
public bool HasTextures
{
get
{
foreach (TreeNode folder in Nodes)
{
if (folder is BFRESGroupNode)
{
bool hasTextures = (((BFRESGroupNode)folder).Type == BRESGroupType.Textures &&
folder.Nodes.Count > 0);
if (hasTextures) return true;
}
if (folder is BNTX)
{
return ((BNTX)folder).Textures.Count > 0;
}
}
return false;
}
}
public void LoadFile(ResU.ResFile res)
{
resFileU = res;
Text = resFileU.Name;
var modelFolder = new BFRESGroupNode(BRESGroupType.Models, true);
var texturesFolder = new BFRESGroupNode(BRESGroupType.Textures, true);
var animFolder = new BFRESAnimFolder();
var externalFilesFolder = new BFRESGroupNode(BRESGroupType.Embedded, true);
texturesFolder.ShowNewContextMenu = false;
Nodes.Add(modelFolder);
Nodes.Add(texturesFolder);
Nodes.Add(animFolder);
Nodes.Add(externalFilesFolder);
animFolder.LoadMenus(IsWiiU);
PluginRuntime.ftexContainers.Add(texturesFolder);
if (resFileU.Models.Count > 0)
{
for (int i = 0; i < resFileU.Models.Count; i++)
{
var fmdl = new FMDL();
BfresWiiU.ReadModel(fmdl, resFileU.Models[i]);
modelFolder.AddNode(fmdl);
}
}
if (resFileU.Textures.Count > 0)
{
for (int i = 0; i < resFileU.Textures.Count; i++)
{
var ftex = new FTEX(resFileU.Textures[i]);
texturesFolder.AddNode(ftex);
ftex.UpdateMipMaps();
}
}
if (resFileU.SkeletalAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.SkeletalAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.SkeletalAnims.Count; i++)
group.AddNode(new FSKA(resFileU.SkeletalAnims[i]));
}
if (resFileU.ShaderParamAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.ShaderParamAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.ShaderParamAnims.Count; i++)
group.AddNode(new FSHU(resFileU.ShaderParamAnims[i], MaterialAnimation.AnimationType.ShaderParam));
}
if (resFileU.ColorAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.ColorAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.ColorAnims.Count; i++)
group.AddNode(new FSHU(resFileU.ColorAnims[i], MaterialAnimation.AnimationType.Color));
}
if (resFileU.TexSrtAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.TexSrtAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.TexSrtAnims.Count; i++)
group.AddNode(new FSHU(resFileU.TexSrtAnims[i], MaterialAnimation.AnimationType.TexturePattern));
}
if (resFileU.TexPatternAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.TexPatAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.TexPatternAnims.Count; i++)
group.AddNode(new FTXP(resFileU.TexPatternAnims[i]));
}
if (resFileU.ShapeAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.ShapeAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.ShapeAnims.Count; i++)
group.AddNode(new FSHA(resFileU.ShapeAnims[i]));
}
if (resFileU.BoneVisibilityAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.BoneVisAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.BoneVisibilityAnims.Count; i++)
group.AddNode(new FVIS(resFileU.BoneVisibilityAnims[i]));
}
if (resFileU.MatVisibilityAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.MatVisAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.MatVisibilityAnims.Count; i++)
group.AddNode(new FVIS(resFileU.MatVisibilityAnims[i]));
}
if (resFileU.SceneAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.SceneAnim, true);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFileU.SceneAnims.Count; i++)
group.AddNode(new FSCN(resFileU.SceneAnims[i]));
}
if (resFileU.ExternalFiles.Count > 0)
{
foreach (var anim in resFileU.ExternalFiles)
{
externalFilesFolder.AddNode(new ExternalFileData(anim.Key, anim.Value.Data));
}
}
if (PluginRuntime.UseSimpleBfresEditor)
LoadSimpleMode();
}
public void LoadFile(ResFile res)
{
resFile = res;
Text = resFile.Name;
var modelFolder = new BFRESGroupNode(BRESGroupType.Models);
var texturesFolder = new BNTX() { ImageKey = "folder", SelectedImageKey = "folder", Text = "Textures" };
var animFolder = new BFRESAnimFolder();
var externalFilesFolder = new BFRESGroupNode(BRESGroupType.Embedded);
//Texture folder acts like a bntx for saving back
//This will only save if the user adds textures to it or the file has a bntx already
texturesFolder.IFileInfo = new IFileInfo();
texturesFolder.FileName = "Textures";
texturesFolder.Load(new MemoryStream(BNTX.CreateNewBNTX("Textures")));
animFolder.LoadMenus(IsWiiU);
Nodes.Add(modelFolder);
Nodes.Add(texturesFolder);
Nodes.Add(animFolder);
Nodes.Add(externalFilesFolder);
if (resFile.Models.Count > 0)
{
for (int i = 0; i < resFile.Models.Count; i++)
{
var fmdl = new FMDL();
BfresSwitch.ReadModel(fmdl, resFile.Models[i]);
modelFolder.AddNode(fmdl);
}
}
if (resFile.SkeletalAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.SkeletalAnim);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFile.SkeletalAnims.Count; i++)
group.AddNode(new FSKA(resFile.SkeletalAnims[i]));
}
if (resFile.MaterialAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.ShaderParamAnim);
var group2 = new BFRESGroupNode(BRESGroupType.TexSrtAnim);
var group3 = new BFRESGroupNode(BRESGroupType.TexPatAnim);
var group4 = new BFRESGroupNode(BRESGroupType.ColorAnim);
var group5 = new BFRESGroupNode(BRESGroupType.MatVisAnim);
var group6 = new BFRESGroupNode(BRESGroupType.MaterialAnim);
bool HasShaderParamsAnim = false;
bool HasTextureSrtAnim = false;
bool HasTexturePatternAnim = false;
bool HasColorAnim = false;
bool HasMatVisAnim = false;
bool HasMaterialAnim = false;
for (int i = 0; i < resFile.MaterialAnims.Count; i++)
{
var anim = resFile.MaterialAnims[i];
if (FMAA.IsShaderParamAnimation(anim.Name))
{
group.AddNode(new FMAA(anim, MaterialAnimation.AnimationType.ShaderParam));
HasShaderParamsAnim = true;
}
else if (FMAA.IsSRTAnimation(anim.Name))
{
group2.AddNode(new FMAA(anim, MaterialAnimation.AnimationType.TextureSrt));
HasTextureSrtAnim = true;
}
else if(FMAA.IsTexturePattern(anim.Name))
{
group3.AddNode(new FMAA(anim, MaterialAnimation.AnimationType.TexturePattern));
HasTexturePatternAnim = true;
}
else if (FMAA.IsColorAnimation(anim.Name))
{
group4.AddNode(new FMAA(anim, MaterialAnimation.AnimationType.Color));
HasColorAnim = true;
}
else if (FMAA.IsVisibiltyAnimation(anim.Name))
{
group5.AddNode(new FMAA(anim, MaterialAnimation.AnimationType.Visibilty));
HasMatVisAnim = true;
}
else
{
group6.AddNode(new FMAA(anim, MaterialAnimation.AnimationType.ShaderParam));
HasMaterialAnim = true;
}
}
if (HasShaderParamsAnim)
animFolder.Nodes.Add(group);
if (HasTextureSrtAnim)
animFolder.Nodes.Add(group2);
if (HasTexturePatternAnim)
animFolder.Nodes.Add(group3);
if (HasColorAnim)
animFolder.Nodes.Add(group4);
if (HasMatVisAnim)
animFolder.Nodes.Add(group5);
if (HasMaterialAnim)
animFolder.Nodes.Add(group6);
}
if (resFile.BoneVisibilityAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.BoneVisAnim);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFile.BoneVisibilityAnims.Count; i++)
group.AddNode(new FVIS(resFile.BoneVisibilityAnims[i]));
}
if (resFile.SceneAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.SceneAnim);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFile.SceneAnims.Count; i++)
group.AddNode(new FSCN(resFile.SceneAnims[i]));
}
if (resFile.ShapeAnims.Count > 0)
{
var group = new BFRESGroupNode(BRESGroupType.ShapeAnim);
animFolder.Nodes.Add(group);
for (int i = 0; i < resFile.ShapeAnims.Count; i++)
group.AddNode(new FSHA(resFile.ShapeAnims[i]));
}
if (resFile.ExternalFiles.Count > 0)
{
int index = 0;
//This also can be set to true if we don't want to rebuild the bntx for debug purposes
bool IsTexturesReplaced = false;
foreach (var anim in resFile.ExternalFiles)
{
// group.AddNode(new ExternalFileData(Name, anim.Data) { FileFormat = file });
string Name = resFile.ExternalFileDict.GetKey(index++);
var file = STFileLoader.OpenFileFormat(Name, anim.Data, false, true);
//Only do once. There's usually one bntx embedded but incase there are multiple
if (file is BNTX && !IsTexturesReplaced)
{
((TreeNode)file).Text = texturesFolder.Text;
((TreeNode)file).ImageKey = texturesFolder.ImageKey;
((TreeNode)file).SelectedImageKey = texturesFolder.SelectedImageKey;
//Remove temporary bntx file with file one
PluginRuntime.bntxContainers.Remove(texturesFolder);
ReplaceNode(texturesFolder.Parent, texturesFolder, (TreeNode)file);
IsTexturesReplaced = true;
}
else
{
externalFilesFolder.AddNode(new ExternalFileData(Name, anim.Data));
}
}
}
if (PluginRuntime.UseSimpleBfresEditor)
LoadSimpleMode();
}
public static void ReplaceNode(TreeNode node, TreeNode replaceNode, TreeNode NewNode)
{
if (NewNode == null)
return;
int index = node.Nodes.IndexOf(replaceNode);
node.Nodes.RemoveAt(index);
node.Nodes.Insert(index, NewNode);
}
public override void Export(string FileName)
{
bool IsTex1 = FileName.Contains("Tex1");
bool HasTextures = false;
foreach (TreeNode group in Nodes)
{
if (group is BFRESGroupNode)
{
if (((BFRESGroupNode)group).Type == BRESGroupType.Textures && group.Nodes.Count > 0)
HasTextures = true;
}
}
if (IsTex1 && HasTextures)
{
STFileSaver.SaveFileFormat(this, FileName);
byte[] Tex2 = GenerateTex2();
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Path.GetFileName(FileName.Replace("Tex1", "Tex2"));
sfd.DefaultExt = ".sbfres";
List<IFileFormat> formats = new List<IFileFormat>();
formats.Add(this);
sfd.Filter = Utils.GetAllFilters(formats);
if (sfd.ShowDialog() == DialogResult.OK)
STFileSaver.SaveFileFormat(Tex2, true, 0, CompressionType.Yaz0, sfd.FileName);
}
else
STFileSaver.SaveFileFormat(this, FileName);
}
private byte[] GenerateTex2()
{
STProgressBar progressBar = new STProgressBar();
progressBar.Task = "Generating Tex2...";
progressBar.Value = 0;
progressBar.StartPosition = FormStartPosition.CenterScreen;
progressBar.Show();
progressBar.Refresh();
var mem = new MemoryStream();
var resFileU = BFRESRender.ResFileNode.resFileU;
//Create a tex2 file
ResU.ResFile resFileTex2 = new ResU.ResFile();
resFileTex2.Alignment = resFileU.Alignment;
resFileTex2.Name = resFileU.Name.Replace("Tex1", "Tex2");
resFileTex2.VersionMajor = resFileU.VersionMajor;
resFileTex2.VersionMajor2 = resFileU.VersionMajor2;
resFileTex2.VersionMinor = resFileU.VersionMinor;
resFileTex2.VersionMinor2 = resFileU.VersionMinor2;
resFileTex2.Textures = resFileU.Textures;
int curTex = 0;
foreach (var group in Nodes)
{
if (group is BFRESGroupNode)
{
if (((BFRESGroupNode)group).Type != BRESGroupType.Textures)
continue;
foreach (FTEX tex in ((BFRESGroupNode)group).Nodes)
{
if (resFileTex2.Textures.ContainsKey(tex.Text))
{
if (tex.texture.MipData == null || tex.texture.MipData.Length <= 0)
{
progressBar.Task = $"Generating Mipmaps for {tex.Text}";
progressBar.Value = ((curTex * 100) / resFileTex2.Textures.Count);
progressBar.Refresh();
FTEX.GenerateMipmaps(tex.texture.MipCount, tex.Format, tex.GetBitmap(), resFileTex2.Textures[tex.Text]);
}
else
{
resFileTex2.Textures[tex.Text].MipData = tex.texture.MipData;
resFileTex2.Textures[tex.Text].MipOffsets = tex.texture.MipOffsets;
resFileTex2.Textures[tex.Text].MipCount = tex.texture.MipCount;
resFileTex2.Textures[tex.Text].Swizzle = tex.Tex2Swizzle;
}
curTex++;
}
}
}
}
progressBar.Task = $"Saving File";
progressBar.Value = 90;
resFileTex2.Save(mem);
progressBar.Value = 100;
progressBar.Close();
progressBar.Dispose();
return mem.ToArray();
}
private void SaveTex2(string fileName)
{
bool Compressed = fileName.EndsWith("sbfres");
byte[] data;
if (Compressed)
data = EveryFileExplorer.YAZ0.Decompress(fileName);
else
data = File.ReadAllBytes(fileName);
ResU.ResFile resFileTex2 = new ResU.ResFile(new MemoryStream(data));
foreach (BFRESGroupNode group in Nodes)
{
if (group.Type != BRESGroupType.Textures)
return;
foreach (FTEX tex in group.Nodes)
{
if (resFileTex2.Textures.ContainsKey(tex.Text))
{
resFileTex2.Textures[tex.Text].MipData = tex.texture.MipData;
resFileTex2.Textures[tex.Text].MipOffsets = tex.texture.MipOffsets;
resFileTex2.Textures[tex.Text].MipCount = tex.texture.MipCount;
}
}
}
MemoryStream mem2 = new MemoryStream();
resFileTex2.Save(mem2);
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = FileName + "NewTex2.sbfres";
List<IFileFormat> formats = new List<IFileFormat>();
formats.Add(this);
sfd.Filter = Utils.GetAllFilters(formats);
if (sfd.ShowDialog() == DialogResult.OK)
STFileSaver.SaveFileFormat(mem2.ToArray(), Compressed, 0, CompressionType.Yaz0, sfd.FileName);
}
private void Rename(object sender, EventArgs args)
{
RenameDialog dialog = new RenameDialog();
dialog.SetString(Text);
if (dialog.ShowDialog() == DialogResult.OK)
{
Text = dialog.textBox1.Text;
}
}
private void Remove(object sender, EventArgs args)
{
Unload();
}
private void SaveSwitch(Stream stream)
{
var resFile = BFRESRender.ResFileNode.resFile;
resFile.Models.Clear();
resFile.SkeletalAnims.Clear();
resFile.MaterialAnims.Clear();
resFile.SceneAnims.Clear();
resFile.ShapeAnims.Clear();
resFile.BoneVisibilityAnims.Clear();
resFile.ModelDict.Clear();
resFile.SkeletalAnimDict.Clear();
resFile.MaterialAnimDict.Clear();
resFile.SceneAnimDict.Clear();
resFile.ShapeAnimDict.Clear();
resFile.BoneVisibilityAnimDict.Clear();
resFile.ExternalFiles.Clear();
resFile.ExternalFileDict.Clear();
foreach (TreeNode node in Nodes)
{
if (node is BFRESGroupNode)
SaveBfresSwitchGroup((BFRESGroupNode)node, resFile);
if (node is BFRESAnimFolder)
{
foreach (var animGroup in node.Nodes)
SaveBfresSwitchGroup((BFRESGroupNode)animGroup, resFile);
}
if (node is BNTX)
{
if (SettingRemoveUnusedTextures)
RemoveUnusedTextures((BNTX)node);
if (((BNTX)node).Textures.Count > 0)
{
var mem = new System.IO.MemoryStream();
((BNTX)node).Save(mem);
resFile.ExternalFiles.Add(new ExternalFile() { Data = mem.ToArray() });
resFile.ExternalFileDict.Add("textures.bntx");
}
}
}
ErrorCheck();
resFile.Save(stream);
}
private void RemoveUnusedTextures(BFRESGroupNode ftexGroup)
{
var models = GetModels();
if (models == null)
return;
List<string> Keys = ftexGroup.ResourceNodes.Select(x => x.Key).ToList();
var AllTextures = GetAllTextures();
for (int i = 0; i < Keys.Count; i++)
{
//If nowhere in the bfres contains the key, we can remove it
if (!AllTextures.Contains(Keys[i]))
{
ftexGroup.RemoveChild(ftexGroup.ResourceNodes[Keys[i]]);
}
}
}
private void RemoveUnusedTextures(BNTX bntx)
{
var models = GetModels();
if (models == null)
return;
List<string> Keys = bntx.Textures.Select(x => x.Key).ToList();
var AllTextures = GetAllTextures();
for (int i = 0; i < Keys.Count; i++)
{
//If nowhere in the bfres contains the key, we can remove it
if (!AllTextures.Contains(Keys[i]))
{
bntx.RemoveTexture(bntx.Textures[Keys[i]]);
}
}
}
private List<string> GetAllTextures()
{
List<string> AllTextures = new List<string>();
foreach (TreeNode group in Nodes)
{
if (group is BFRESGroupNode && ((BFRESGroupNode)group).Type == BRESGroupType.Models)
{
for (int i = 0; i < group.Nodes.Count; i++)
{
foreach (var material in ((FMDL)group.Nodes[i]).materials.Values)
{
foreach (var tex in material.TextureMaps)
{
if (!AllTextures.Contains(tex.Name))
AllTextures.Add(tex.Name);
}
}
}
}
if (group is BFRESAnimFolder)
{
foreach (BFRESGroupNode animGroup in group.Nodes)
{
if (animGroup.Type == BRESGroupType.TexPatAnim)
{
for (int i = 0; i < group.Nodes.Count; i++)
{
foreach (var tex in ((MaterialAnimation)group.Nodes[i]).Textures)
{
if (!AllTextures.Contains(tex))
AllTextures.Add(tex);
}
}
}
}
}
}
return AllTextures;
}
private static void SaveBfresSwitchGroup(BFRESGroupNode group, ResFile resFile)
{
switch (group.Type)
{
case BRESGroupType.Models:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FMDL)group.Nodes[i]).Model.Name = ((FMDL)group.Nodes[i]).Text;
resFile.Models.Add(BfresSwitch.SetModel((FMDL)group.Nodes[i]));
}
break;
case BRESGroupType.SkeletalAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSKA)group.Nodes[i]).SkeletalAnim.BoneAnims.Clear();
((FSKA)group.Nodes[i]).SkeletalAnim.Name = ((FSKA)group.Nodes[i]).Text;
for (int b = 0; b < ((FSKA)group.Nodes[i]).Bones.Count; b++)
((FSKA)group.Nodes[i]).SkeletalAnim.BoneAnims.Add(
((FSKA.BoneAnimNode)((FSKA)group.Nodes[i]).Bones[b]).SaveData(((FSKA)group.Nodes[i]).IsEdited));
resFile.SkeletalAnims.Add(((FSKA)group.Nodes[i]).SkeletalAnim);
}
break;
case BRESGroupType.TexPatAnim:
case BRESGroupType.ShaderParamAnim:
case BRESGroupType.ColorAnim:
case BRESGroupType.TexSrtAnim:
case BRESGroupType.MatVisAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FMAA)group.Nodes[i]).SaveAnimData();
resFile.MaterialAnims.Add(((FMAA)group.Nodes[i]).MaterialAnim);
}
break;
case BRESGroupType.BoneVisAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FVIS)group.Nodes[i]).SaveAnimData();
resFile.BoneVisibilityAnims.Add(((FVIS)group.Nodes[i]).VisibilityAnim);
}
break;
case BRESGroupType.ShapeAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSHA)group.Nodes[i]).SaveAnimData();
resFile.ShapeAnims.Add(((FSHA)group.Nodes[i]).ShapeAnim);
}
break;
case BRESGroupType.SceneAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSCN)group.Nodes[i]).SaveAnimData();
resFile.SceneAnims.Add(((FSCN)group.Nodes[i]).SceneAnim);
}
break;
case BRESGroupType.Embedded:
foreach (var ext in group.Nodes)
{
if (ext is ExternalFileData)
{
resFile.ExternalFiles.Add(new ExternalFile() { Data = ((ExternalFileData)ext).Data });
resFile.ExternalFileDict.Add(((ExternalFileData)ext).Text);
}
else if (ext is TreeNodeFile)
{
var mem = new System.IO.MemoryStream();
((IFileFormat)ext).Save(mem);
resFile.ExternalFiles.Add(new ExternalFile()
{
Data = mem.ToArray(),
});
resFile.ExternalFileDict.Add(((TreeNodeFile)ext).Text);
}
}
break;
}
}
private void SaveMaterialAnims(TreeNodeCollection nodes)
{
}
private void SaveWiiU(Stream mem)
{
var resFileU = BFRESRender.ResFileNode.resFileU;
resFileU.Models.Clear();
resFileU.Textures.Clear();
resFileU.SkeletalAnims.Clear();
resFileU.ShaderParamAnims.Clear();
resFileU.ColorAnims.Clear();
resFileU.TexSrtAnims.Clear();
resFileU.TexPatternAnims.Clear();
resFileU.BoneVisibilityAnims.Clear();
resFileU.MatVisibilityAnims.Clear();
resFileU.ShapeAnims.Clear();
resFileU.SceneAnims.Clear();
resFileU.ExternalFiles.Clear();
bool IsTex1 = FilePath.Contains("Tex1");
foreach (TreeNode node in Nodes)
{
if (node is BFRESGroupNode)
SaveBfresWiiUGroup(this, (BFRESGroupNode)node, resFileU);
if (node is BFRESAnimFolder)
{
foreach (var animGroup in node.Nodes)
SaveBfresWiiUGroup(this, (BFRESGroupNode)animGroup, resFileU);
}
}
// ErrorCheck();
resFileU.Save(mem);
}
private static void SaveBfresWiiUGroup(BFRES bfres, BFRESGroupNode group, ResU.ResFile resFileU)
{
switch (group.Type)
{
case BRESGroupType.Models:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FMDL)group.Nodes[i]).ModelU.Name = group.Nodes[i].Text;
resFileU.Models.Add(group.Nodes[i].Text, BfresWiiU.SetModel((FMDL)group.Nodes[i]));
}
break;
case BRESGroupType.Textures:
if (bfres.SettingRemoveUnusedTextures)
bfres.RemoveUnusedTextures(group);
for (int i = 0; i < group.Nodes.Count; i++)
{
((FTEX)group.Nodes[i]).texture.Name = group.Nodes[i].Text;
resFileU.Textures.Add(group.Nodes[i].Text, ((FTEX)group.Nodes[i]).texture);
}
break;
case BRESGroupType.SkeletalAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSKA)group.Nodes[i]).SkeletalAnimU.BoneAnims.Clear();
((FSKA)group.Nodes[i]).SkeletalAnimU.Name = ((FSKA)group.Nodes[i]).Text;
for (int b = 0; b < ((FSKA)group.Nodes[i]).Bones.Count; b++)
((FSKA)group.Nodes[i]).SkeletalAnimU.BoneAnims.Add(
((FSKA.BoneAnimNode)((FSKA)group.Nodes[i]).Bones[b]).SaveDataU(((FSKA)group.Nodes[i]).IsEdited));
resFileU.SkeletalAnims.Add(group.Nodes[i].Text, ((FSKA)group.Nodes[i]).SkeletalAnimU);
}
break;
case BRESGroupType.ShaderParamAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSHU)group.Nodes[i]).SaveAnimData();
resFileU.ShaderParamAnims.Add(group.Nodes[i].Text, ((FSHU)group.Nodes[i]).ShaderParamAnim);
}
break;
case BRESGroupType.ColorAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSHU)group.Nodes[i]).SaveAnimData();
resFileU.ColorAnims.Add(group.Nodes[i].Text, ((FSHU)group.Nodes[i]).ShaderParamAnim);
}
break;
case BRESGroupType.TexSrtAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSHU)group.Nodes[i]).SaveAnimData();
resFileU.TexSrtAnims.Add(group.Nodes[i].Text, ((FSHU)group.Nodes[i]).ShaderParamAnim);
}
break;
case BRESGroupType.TexPatAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FTXP)group.Nodes[i]).SaveAnimData();
resFileU.TexPatternAnims.Add(group.Nodes[i].Text, ((FTXP)group.Nodes[i]).TexPatternAnim);
}
break;
case BRESGroupType.MatVisAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FVIS)group.Nodes[i]).SaveAnimData();
resFileU.MatVisibilityAnims.Add(group.Nodes[i].Text, ((FVIS)group.Nodes[i]).VisibilityAnimU);
}
break;
case BRESGroupType.BoneVisAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FVIS)group.Nodes[i]).SaveAnimData();
resFileU.BoneVisibilityAnims.Add(group.Nodes[i].Text, ((FVIS)group.Nodes[i]).VisibilityAnimU);
}
break;
case BRESGroupType.ShapeAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSHA)group.Nodes[i]).SaveAnimData();
resFileU.ShapeAnims.Add(group.Nodes[i].Text, ((FSHA)group.Nodes[i]).ShapeAnimU);
}
break;
case BRESGroupType.SceneAnim:
for (int i = 0; i < group.Nodes.Count; i++)
{
((FSCN)group.Nodes[i]).SaveAnimData();
resFileU.SceneAnims.Add(group.Nodes[i].Text, ((FSCN)group.Nodes[i]).SceneAnimU);
}
break;
case BRESGroupType.Embedded:
foreach (TreeNode ext in group.Nodes)
{
if (ext is ExternalFileData)
{
resFileU.ExternalFiles.Add(ext.Text, new ResU.ExternalFile() { Data = ((ExternalFileData)ext).Data });
}
}
break;
}
}
public static void SetShaderAssignAttributes(FSHP shape)
{
var shd = shape.GetFMAT().shaderassign;
foreach (var att in shape.vertexAttributes)
{
if (!shd.attributes.ContainsValue(att.Name))
{
try
{
shd.attributes.Add(att.Name, att.Name);
}
catch (Exception ex)
{
Console.WriteLine("Attribute link failed! \n " + ex);
}
}
}
foreach (var tex in shape.GetMaterial().TextureMaps)
{
if (!shd.samplers.ContainsValue(tex.SamplerName))
{
try
{
shd.samplers.Add(tex.SamplerName, tex.SamplerName);
}
catch (Exception ex)
{
Console.WriteLine("Sampler link failed! \n " + ex);
}
}
}
}
private void SetDuplicateShapeName(FSHP shape)
{
DialogResult dialogResult = MessageBox.Show($"A shape {shape.Text} already exists with that name", "", MessageBoxButtons.OK);
if (dialogResult == DialogResult.OK)
{
RenameDialog renameDialog = new RenameDialog();
renameDialog.Text = "Rename Texture";
if (renameDialog.ShowDialog() == DialogResult.OK)
{
shape.Text = renameDialog.textBox1.Text;
}
}
}
static bool ImportMissingTextures = false;
public static void CheckMissingTextures(FSHP shape)
{
// FSHP > Objects > FMDL > Models > BFRES
BFRES root = (BFRES)shape.Parent.Parent.Parent.Parent;
foreach (var node in root.Nodes)
{
if (node is BNTX)
{
BNTX bntx = (BNTX)node;
if (bntx.Textures.Count == 0)
return;
foreach (MatTexture tex in shape.GetMaterial().TextureMaps)
{
if (!bntx.Textures.ContainsKey(tex.Name))
{
if (!ImportMissingTextures)
{
DialogResult result = MessageBox.Show("Missing textures found! Would you like to use placeholders?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
ImportMissingTextures = true;
}
else
return;
}
if (ImportMissingTextures)
bntx.ImportPlaceholderTexture(tex.Name);
}
}
}
}
foreach (var node in root.Nodes)
{
if (node is BFRESGroupNode && ((BFRESGroupNode)node).Type == BRESGroupType.Textures)
{
if (((BFRESGroupNode)node).ResourceNodes.Count <= 0)
return;
foreach (MatTexture tex in shape.GetMaterial().TextureMaps)
{
if (!((BFRESGroupNode)node).ResourceNodes.ContainsKey(tex.Name))
{
if (!ImportMissingTextures)
{
DialogResult result = MessageBox.Show("Missing textures found! Would you like to use placeholders?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
ImportMissingTextures = true;
}
else
{
return;
}
}
if (ImportMissingTextures)
((BFRESGroupNode)node).ImportPlaceholderTexture(tex.Name);
}
}
}
}
}
public void ErrorCheck()
{
if (BFRESRender != null)
{
List<Errors> Errors = new List<Errors>();
foreach (FMDL model in BFRESRender.models)
{
foreach (FSHP shp in model.shapes)
{
if (!IsWiiU)
{
Syroot.NintenTools.NSW.Bfres.VertexBuffer vtx = shp.VertexBuffer;
Syroot.NintenTools.NSW.Bfres.Material mat = shp.GetFMAT().Material;
Syroot.NintenTools.NSW.Bfres.ShaderAssign shdr = mat.ShaderAssign;
for (int att = 0; att < vtx.Attributes.Count; att++)
{
if (!shdr.AttribAssigns.Contains(vtx.Attributes[att].Name))
STConsole.WriteLine($"Error! Attribute {vtx.Attributes[att].Name} is unlinked!");
}
for (int att = 0; att < mat.Samplers.Count; att++)
{
if (!shdr.SamplerAssigns.Contains(mat.SamplerDict.GetKey(att))) //mat.SamplerDict[att]
STConsole.WriteLine($"Error! Sampler {mat.Samplers[att].Name} is unlinked!");
}
}
else
{
Syroot.NintenTools.Bfres.VertexBuffer vtx = shp.VertexBufferU;
Syroot.NintenTools.Bfres.Material mat = shp.GetFMAT().MaterialU;
Syroot.NintenTools.Bfres.ShaderAssign shdr = mat.ShaderAssign;
for (int att = 0; att < vtx.Attributes.Count; att++)
{
ResU.ResString str = new ResU.ResString();
str.String = vtx.Attributes[att].Name;
if (!shdr.AttribAssigns.ContainsValue(str))
STConsole.WriteLine($"Error! Attribute {vtx.Attributes[att].Name} is unlinked!");
}
for (int att = 0; att < mat.Samplers.Count; att++)
{
ResU.ResString str2 = new ResU.ResString();
str2.String = mat.Samplers[att].Name;
if (!shdr.SamplerAssigns.ContainsValue(str2)) //mat.SamplerDict[att]
STConsole.WriteLine($"Error! Sampler {mat.Samplers[att].Name} is unlinked!");
}
}
}
}
// ErrorList errorList = new ErrorList();
// errorList.LoadList(Errors);
// errorList.Show();
}
}
public class Errors
{
public string Section = "None";
public string Section2 = "None";
public string Message = "";
public string Type = "Unkown";
}
}
}