mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-12-18 17:03:42 +00:00
f51dd17f94
Add in nutexb file format. While not finished, it can preview and export them. Batch exporting for nuteb (tools menu). Rework GTX code. This is WIP and not finished. Add XTX code. Unifnished atm. Add saving for wii u and include fmat exporting. Proper error handling for assimp and texture swizzling.
701 lines
29 KiB
C#
701 lines
29 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Syroot.NintenTools.NSW.Bfres;
|
|
using System.Windows.Forms;
|
|
using Switch_Toolbox.Library;
|
|
using Switch_Toolbox.Library.Rendering;
|
|
using Switch_Toolbox.Library.Forms;
|
|
using ResU = Syroot.NintenTools.Bfres;
|
|
using ResUGX2 = Syroot.NintenTools.Bfres.GX2;
|
|
using ResGFX = Syroot.NintenTools.NSW.Bfres.GFX;
|
|
using FirstPlugin;
|
|
|
|
namespace Bfres.Structs
|
|
{
|
|
public class FmdlFolder : TreeNodeCustom
|
|
{
|
|
public FmdlFolder()
|
|
{
|
|
Text = "Models";
|
|
Name = "FMDL";
|
|
|
|
ContextMenu = new ContextMenu();
|
|
MenuItem import = new MenuItem("Import");
|
|
ContextMenu.MenuItems.Add(import);
|
|
import.Click += Import;
|
|
MenuItem exportAll = new MenuItem("Export All");
|
|
ContextMenu.MenuItems.Add(exportAll);
|
|
exportAll.Click += ExportAll;
|
|
MenuItem clear = new MenuItem("Clear");
|
|
ContextMenu.MenuItems.Add(clear);
|
|
clear.Click += Clear;
|
|
}
|
|
public void Import(object sender, EventArgs args)
|
|
{
|
|
|
|
}
|
|
public void ExportAll(object sender, EventArgs args)
|
|
{
|
|
|
|
}
|
|
private void Clear(object sender, EventArgs args)
|
|
{
|
|
DialogResult dialogResult = MessageBox.Show("Are you sure you want to remove all objects? This cannot be undone!", "", MessageBoxButtons.YesNo);
|
|
|
|
if (dialogResult == DialogResult.Yes)
|
|
{
|
|
Nodes.Clear();
|
|
((ResourceFile)Parent).BFRESRender.models.Clear();
|
|
((ResourceFile)Parent).BFRESRender.UpdateVertexData();
|
|
}
|
|
}
|
|
public override void OnClick(TreeView treeView)
|
|
{
|
|
FormLoader.LoadEditor(this, Text);
|
|
}
|
|
}
|
|
|
|
public class FMDL : STGenericModel
|
|
{
|
|
public List<FSHP> shapes = new List<FSHP>();
|
|
public Dictionary<string, FMAT> materials = new Dictionary<string, FMAT>();
|
|
public Model Model;
|
|
public ResU.Model ModelU;
|
|
|
|
public ResFile GetResFile()
|
|
{
|
|
//ResourceFile -> FMDL -> Material Folder -> this
|
|
return ((ResourceFile)Parent.Parent).resFile;
|
|
}
|
|
public ResU.ResFile GetResFileU()
|
|
{
|
|
return ((ResourceFile)Parent.Parent).resFileU;
|
|
}
|
|
public void UpdateVertexData()
|
|
{
|
|
((ResourceFile)Parent.Parent).BFRESRender.UpdateVertexData();
|
|
}
|
|
public List<FMDL> GetModelList()
|
|
{
|
|
return ((ResourceFile)Parent.Parent).BFRESRender.models;
|
|
}
|
|
|
|
|
|
public FMDL()
|
|
{
|
|
ImageKey = "model";
|
|
SelectedImageKey = "model";
|
|
|
|
Nodes.Add(new FSHPFolder());
|
|
Nodes.Add(new FMATFolder());
|
|
|
|
ContextMenu = new ContextMenu();
|
|
MenuItem export = new MenuItem("Export Model");
|
|
ContextMenu.MenuItems.Add(export);
|
|
export.Click += Export;
|
|
MenuItem replace = new MenuItem("Replace Model");
|
|
ContextMenu.MenuItems.Add(replace);
|
|
replace.Click += Replace;
|
|
MenuItem rename = new MenuItem("Rename");
|
|
ContextMenu.MenuItems.Add(rename);
|
|
rename.Click += Rename;
|
|
MenuItem calcTansBitans = new MenuItem("Calculate Tangents/Bitangents");
|
|
ContextMenu.MenuItems.Add(calcTansBitans);
|
|
calcTansBitans.Click += CalcTansBitansAllShapes;
|
|
MenuItem normals = new MenuItem("Normals");
|
|
ContextMenu.MenuItems.Add(normals);
|
|
MenuItem smoothNormals = new MenuItem("Smooth");
|
|
normals.MenuItems.Add(smoothNormals);
|
|
smoothNormals.Click += SmoothNormals;
|
|
MenuItem recalculateNormals = new MenuItem("Recalculate");
|
|
normals.MenuItems.Add(recalculateNormals);
|
|
recalculateNormals.Click += RecalculateNormals;
|
|
}
|
|
private void SmoothNormals(object sender, EventArgs args)
|
|
{
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
foreach (FSHP shp in shapes)
|
|
{
|
|
bool HasNormals = shp.vertexAttributes.Any(x => x.Name == "_n0");
|
|
if (HasNormals)
|
|
shp.SmoothNormals();
|
|
|
|
shp.SaveVertexBuffer();
|
|
}
|
|
UpdateVertexData();
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
private void RecalculateNormals(object sender, EventArgs args)
|
|
{
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
foreach (FSHP shp in shapes)
|
|
{
|
|
bool HasNormals = shp.vertexAttributes.Any(x => x.Name == "_n0");
|
|
if (HasNormals)
|
|
shp.CalculateNormals();
|
|
|
|
shp.SaveVertexBuffer();
|
|
}
|
|
UpdateVertexData();
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
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 CalcTansBitansAllShapes(object sender, EventArgs args)
|
|
{
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
foreach (FSHP shp in shapes)
|
|
{
|
|
bool HasTans = shp.vertexAttributes.Any(x => x.Name == "_t0");
|
|
bool HasBiTans = shp.vertexAttributes.Any(x => x.Name == "_b0");
|
|
|
|
if (!shp.HasUV0())
|
|
{
|
|
MessageBox.Show($"Error! {Text} does not have UVs!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
if (!HasBiTans)
|
|
{
|
|
DialogResult dialogResult2 = MessageBox.Show("Mesh does not have bitangents. Do you want to create them? (will make file size bigger)", "", MessageBoxButtons.YesNo);
|
|
|
|
FSHP.VertexAttribute att2 = new FSHP.VertexAttribute();
|
|
att2.Name = "_b0";
|
|
att2.Format = ResGFX.AttribFormat.Format_10_10_10_2_SNorm;
|
|
|
|
if (dialogResult2 == DialogResult.Yes)
|
|
{
|
|
if (!HasBiTans)
|
|
shp.vertexAttributes.Add(att2);
|
|
}
|
|
}
|
|
|
|
if (!HasTans)
|
|
{
|
|
DialogResult dialogResult = MessageBox.Show("Mesh does not have tangets. Do you want to create them? (will make file size bigger)", "", MessageBoxButtons.YesNo);
|
|
|
|
FSHP.VertexAttribute att = new FSHP.VertexAttribute();
|
|
att.Name = "_t0";
|
|
att.Format = ResGFX.AttribFormat.Format_10_10_10_2_SNorm;
|
|
|
|
|
|
if (dialogResult == DialogResult.Yes)
|
|
{
|
|
if (!HasTans)
|
|
shp.vertexAttributes.Add(att);
|
|
}
|
|
}
|
|
|
|
shp.CalculateTangentBitangent();
|
|
shp.SaveVertexBuffer();
|
|
}
|
|
|
|
UpdateVertexData();
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
public void CopyMaterial(FMAT selectedMaterial)
|
|
{
|
|
CopyMaterialMenu menu = new CopyMaterialMenu();
|
|
menu.LoadMaterials(selectedMaterial.Text, GetModelList());
|
|
if (menu.ShowDialog() == DialogResult.OK)
|
|
{
|
|
foreach (TreeNode mdl in menu.materialTreeView.Nodes)
|
|
{
|
|
foreach (TreeNode n in mdl.Nodes)
|
|
{
|
|
if (n.Checked)
|
|
{
|
|
if (materials.ContainsKey(n.Text))
|
|
SetCopiedMaterialData(menu, selectedMaterial, materials[n.Text]);
|
|
}
|
|
}
|
|
}
|
|
Viewport.Instance.UpdateViewport();
|
|
}
|
|
}
|
|
private void SetCopiedMaterialData(CopyMaterialMenu menu,
|
|
FMAT selectedMaterial, FMAT targetMaterial)
|
|
{
|
|
targetMaterial.Material.Flags = selectedMaterial.Material.Flags;
|
|
targetMaterial.Material.UserDatas = selectedMaterial.Material.UserDatas;
|
|
targetMaterial.Material.UserDataDict = selectedMaterial.Material.UserDataDict;
|
|
|
|
if (menu.chkBoxRenderInfo.Checked)
|
|
{
|
|
targetMaterial.Material.RenderInfoDict = selectedMaterial.Material.RenderInfoDict;
|
|
targetMaterial.Material.RenderInfos = selectedMaterial.Material.RenderInfos;
|
|
}
|
|
if (menu.chkBoxShaderOptions.Checked)
|
|
{
|
|
targetMaterial.Material.ShaderAssign = selectedMaterial.Material.ShaderAssign;
|
|
}
|
|
if (menu.chkBoxShaderParams.Checked)
|
|
{
|
|
targetMaterial.Material.ShaderParamData = selectedMaterial.Material.ShaderParamData;
|
|
targetMaterial.Material.ShaderParamDict = selectedMaterial.Material.ShaderParamDict;
|
|
targetMaterial.Material.ShaderParams = selectedMaterial.Material.ShaderParams;
|
|
targetMaterial.Material.VolatileFlags = selectedMaterial.Material.VolatileFlags;
|
|
}
|
|
if (menu.chkBoxTextures.Checked)
|
|
{
|
|
targetMaterial.Material.SamplerDict = selectedMaterial.Material.SamplerDict;
|
|
targetMaterial.Material.Samplers = selectedMaterial.Material.Samplers;
|
|
targetMaterial.Material.SamplerSlotArray = selectedMaterial.Material.SamplerSlotArray;
|
|
targetMaterial.Material.TextureSlotArray = selectedMaterial.Material.TextureSlotArray;
|
|
targetMaterial.Material.TextureRefs = selectedMaterial.Material.TextureRefs;
|
|
}
|
|
targetMaterial.ReadMaterial(targetMaterial.Material);
|
|
}
|
|
public void ExportAll()
|
|
{
|
|
FolderSelectDialog sfd = new FolderSelectDialog();
|
|
|
|
List<string> Formats = new List<string>();
|
|
Formats.Add("Bfres object (.bfobj)");
|
|
Formats.Add("CSV (.csv)");
|
|
|
|
if (sfd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
string folderPath = sfd.SelectedPath;
|
|
|
|
TextureFormatExport form = new TextureFormatExport(Formats);
|
|
if (form.ShowDialog() == DialogResult.OK)
|
|
{
|
|
foreach (FSHP shp in shapes)
|
|
{
|
|
if (form.Index == 0)
|
|
shp.ExportBinaryObject(folderPath + '\\' + shp.Text + ".bfobj");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public void Export(object sender, EventArgs args)
|
|
{
|
|
SaveFileDialog sfd = new SaveFileDialog();
|
|
sfd.Filter = "Supported Formats|*.bfmdl;*.fbx;*.dae; *.obj;*.csv;|" +
|
|
"Bfres Model|*.bfmdl|" +
|
|
"FBX |*.fbx|" +
|
|
"DAE |*.dae|" +
|
|
"OBJ |*.obj|" +
|
|
"CSV |*.csv|" +
|
|
"All files(*.*)|*.*";
|
|
sfd.DefaultExt = ".bfobj";
|
|
sfd.FileName = Text;
|
|
|
|
if (sfd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
string ext = System.IO.Path.GetExtension(sfd.FileName);
|
|
ext = ext.ToLower();
|
|
|
|
switch (ext)
|
|
{
|
|
case ".bfmdl":
|
|
Model.Export(sfd.FileName, GetResFile());
|
|
break;
|
|
case ".csv":
|
|
CsvModel csv = new CsvModel();
|
|
foreach (FSHP shape in shapes)
|
|
{
|
|
STGenericObject obj = new STGenericObject();
|
|
obj.ObjectName = shape.Text;
|
|
obj.vertices = shape.vertices;
|
|
obj.faces = shape.lodMeshes[shape.DisplayLODIndex].faces;
|
|
csv.objects.Add(obj);
|
|
|
|
int CurVtx = 0;
|
|
foreach (Vertex v in shape.vertices)
|
|
{
|
|
if (v.boneIds[0] != 0)
|
|
obj.vertices[CurVtx].boneNames.Add(shape.GetBoneNameFromIndex(this, v.boneIds[0]));
|
|
if (v.boneIds[1] != 0)
|
|
obj.vertices[CurVtx].boneNames.Add(shape.GetBoneNameFromIndex(this, v.boneIds[1]));
|
|
if (v.boneIds[2] != 0)
|
|
obj.vertices[CurVtx].boneNames.Add(shape.GetBoneNameFromIndex(this, v.boneIds[2]));
|
|
if (v.boneIds[3] != 0)
|
|
obj.vertices[CurVtx].boneNames.Add(shape.GetBoneNameFromIndex(this, v.boneIds[3]));
|
|
|
|
CurVtx++;
|
|
}
|
|
}
|
|
System.IO.File.WriteAllBytes(sfd.FileName, csv.Save());
|
|
break;
|
|
default:
|
|
AssimpData assimp = new AssimpData();
|
|
assimp.SaveFromModel(this, sfd.FileName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Replace(object sender, EventArgs args)
|
|
{
|
|
OpenFileDialog ofd = new OpenFileDialog();
|
|
ofd.Filter = "Supported Formats|*.bfobj;*.fbx;*.dae;*.obj;*.csv;|" +
|
|
"Bfres Object (shape/vertices) |*.bfobj|" +
|
|
"FBX |*.fbx|" +
|
|
"DAE |*.dae|" +
|
|
"OBJ |*.obj|" +
|
|
"CSV |*.csv|" +
|
|
"All files(*.*)|*.*";
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
AddOjects(ofd.FileName);
|
|
}
|
|
|
|
}
|
|
//Function addes shapes, vertices and meshes
|
|
public void AddOjects(string FileName, bool Replace = true)
|
|
{
|
|
int MatStartIndex = materials.Count;
|
|
string ext = System.IO.Path.GetExtension(FileName);
|
|
ext = ext.ToLower();
|
|
|
|
switch (ext)
|
|
{
|
|
case ".bfobj":
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
|
|
if (Replace)
|
|
{
|
|
shapes.Clear();
|
|
Nodes["FshpFolder"].Nodes.Clear();
|
|
}
|
|
|
|
Shape shpS = new Shape();
|
|
VertexBuffer vertexBuffer = new VertexBuffer();
|
|
shpS.Import(FileName, vertexBuffer);
|
|
|
|
FSHP shapeS = new FSHP();
|
|
shapeS.Shape = shpS;
|
|
BfresSwitch.ReadShapesVertices(shapeS, shpS, vertexBuffer, this);
|
|
shapes.Add(shapeS);
|
|
Nodes["FshpFolder"].Nodes.Add(shapeS);
|
|
Cursor.Current = Cursors.Default;
|
|
break;
|
|
case ".bfmdl":
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
|
|
if (Replace)
|
|
{
|
|
shapes.Clear();
|
|
Nodes["FshpFolder"].Nodes.Clear();
|
|
}
|
|
|
|
Model mdl = new Model();
|
|
mdl.Import(FileName, GetResFile());
|
|
mdl.Name = Text;
|
|
shapes.Clear();
|
|
foreach (Shape shp in mdl.Shapes)
|
|
{
|
|
FSHP shape = new FSHP();
|
|
shape.Shape = shp;
|
|
BfresSwitch.ReadShapesVertices(shape, shp, mdl.VertexBuffers[shp.VertexBufferIndex], this);
|
|
shapes.Add(shape);
|
|
Nodes["FshpFolder"].Nodes.Add(shape);
|
|
}
|
|
Cursor.Current = Cursors.Default;
|
|
break;
|
|
case ".csv":
|
|
CsvModel csvModel = new CsvModel();
|
|
csvModel.LoadFile(FileName, true);
|
|
|
|
if (csvModel.objects.Count == 0)
|
|
{
|
|
MessageBox.Show("No models found!");
|
|
return;
|
|
}
|
|
BfresModelImportSettings csvsettings = new BfresModelImportSettings();
|
|
csvsettings.DisableMaterialEdits();
|
|
csvsettings.SetModelAttributes(csvModel.objects[0]);
|
|
if (csvsettings.ShowDialog() == DialogResult.OK)
|
|
{
|
|
if (Replace)
|
|
{
|
|
shapes.Clear();
|
|
Nodes["FshpFolder"].Nodes.Clear();
|
|
}
|
|
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
|
|
foreach (STGenericObject obj in csvModel.objects)
|
|
{
|
|
FSHP shape = new FSHP();
|
|
shape.VertexBufferIndex = shapes.Count;
|
|
shape.vertices = obj.vertices;
|
|
shape.MaterialIndex = 0;
|
|
shape.VertexSkinCount = obj.GetMaxSkinInfluenceCount();
|
|
shape.vertexAttributes = csvsettings.CreateNewAttributes();
|
|
shape.boneIndx = 0;
|
|
shape.Text = obj.ObjectName;
|
|
shape.lodMeshes = obj.lodMeshes;
|
|
shape.CreateNewBoundingBoxes();
|
|
shape.CreateBoneList(obj, this);
|
|
shape.CreateIndexList(obj, this);
|
|
shape.ApplyImportSettings(csvsettings, GetMaterial(shape.MaterialIndex));
|
|
shape.SaveShape();
|
|
shape.SaveVertexBuffer();
|
|
shape.BoneIndices = new List<ushort>();
|
|
|
|
Nodes["FshpFolder"].Nodes.Add(shape);
|
|
shapes.Add(shape);
|
|
}
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
break;
|
|
default:
|
|
AssimpData assimp = new AssimpData();
|
|
assimp.LoadFile(FileName);
|
|
|
|
if (assimp.objects.Count == 0)
|
|
{
|
|
MessageBox.Show("No models found!");
|
|
return;
|
|
}
|
|
BfresModelImportSettings settings = new BfresModelImportSettings();
|
|
settings.SetModelAttributes(assimp.objects[0]);
|
|
if (settings.ShowDialog() == DialogResult.OK)
|
|
{
|
|
if (Replace)
|
|
{
|
|
shapes.Clear();
|
|
Nodes["FshpFolder"].Nodes.Clear();
|
|
}
|
|
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
if (!BFRES.IsWiiU && Replace)
|
|
{
|
|
materials.Clear();
|
|
Nodes["FmatFolder"].Nodes.Clear();
|
|
MatStartIndex = 0;
|
|
}
|
|
foreach (STGenericMaterial mat in assimp.materials)
|
|
{
|
|
FMAT fmat = new FMAT();
|
|
if (settings.ExternalMaterialPath != string.Empty)
|
|
{
|
|
if (!BFRES.IsWiiU)
|
|
{
|
|
fmat.Material = new Material();
|
|
fmat.Material.Import(settings.ExternalMaterialPath);
|
|
fmat.ReadMaterial(fmat.Material);
|
|
}
|
|
else
|
|
{
|
|
fmat.MaterialU = new ResU.Material();
|
|
fmat.MaterialU.Import(settings.ExternalMaterialPath, GetResFileU());
|
|
BfresWiiU.ReadMaterial(fmat, fmat.MaterialU);
|
|
}
|
|
}
|
|
|
|
fmat.Text = mat.Text;
|
|
//Setup placeholder textures
|
|
//Note we can't add/remove samplers so we must fill these slots
|
|
foreach (var t in fmat.textures)
|
|
{
|
|
t.wrapModeS = 0;
|
|
t.wrapModeT = 0;
|
|
|
|
switch (t.Type)
|
|
{
|
|
case STGenericMatTexture.TextureType.Diffuse:
|
|
t.Name = "Basic_Alb";
|
|
break;
|
|
case STGenericMatTexture.TextureType.Emission:
|
|
t.Name = "Basic_Emm";
|
|
break;
|
|
case STGenericMatTexture.TextureType.Normal:
|
|
t.Name = "Basic_Nrm";
|
|
break;
|
|
case STGenericMatTexture.TextureType.Specular:
|
|
t.Name = "Basic_Spm";
|
|
break;
|
|
case STGenericMatTexture.TextureType.SphereMap:
|
|
t.Name = "Basic_Sphere";
|
|
break;
|
|
case STGenericMatTexture.TextureType.Metalness:
|
|
t.Name = "Basic_Mtl";
|
|
break;
|
|
case STGenericMatTexture.TextureType.Roughness:
|
|
t.Name = "Basic_Rgh";
|
|
break;
|
|
case STGenericMatTexture.TextureType.MRA:
|
|
t.Name = "Basic_MRA";
|
|
break;
|
|
case STGenericMatTexture.TextureType.Shadow:
|
|
t.Name = "Basic_Bake_st0";
|
|
break;
|
|
case STGenericMatTexture.TextureType.Light:
|
|
t.Name = "Basic_Bake_st1";
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (PluginRuntime.bntxContainers.Count > 0)
|
|
{
|
|
foreach (var node in Parent.Parent.Nodes["EXT"].Nodes)
|
|
{
|
|
if (node is BinaryTextureContainer)
|
|
{
|
|
var bntx = (BinaryTextureContainer)node;
|
|
|
|
bntx.ImportBasicTextures("Basic_Alb");
|
|
bntx.ImportBasicTextures("Basic_Nrm");
|
|
bntx.ImportBasicTextures("Basic_Spm");
|
|
bntx.ImportBasicTextures("Basic_Sphere");
|
|
bntx.ImportBasicTextures("Basic_Mtl");
|
|
bntx.ImportBasicTextures("Basic_Rgh");
|
|
bntx.ImportBasicTextures("Basic_MRA");
|
|
bntx.ImportBasicTextures("Basic_Bake_st0");
|
|
bntx.ImportBasicTextures("Basic_Bake_st1");
|
|
bntx.ImportBasicTextures("Basic_Emm");
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var tex in mat.TextureMaps)
|
|
{
|
|
foreach (var t in fmat.textures)
|
|
{
|
|
if (t.Type == tex.Type)
|
|
{
|
|
t.Name = tex.Name;
|
|
t.wrapModeS = tex.wrapModeS;
|
|
t.wrapModeT = tex.wrapModeT;
|
|
t.wrapModeW = tex.wrapModeW;
|
|
t.Type = tex.Type;
|
|
}
|
|
}
|
|
}
|
|
|
|
List<string> keyList = new List<string>(materials.Keys);
|
|
fmat.Text = Utils.RenameDuplicateString(keyList, fmat.Text);
|
|
|
|
materials.Add(fmat.Text, fmat);
|
|
Nodes["FmatFolder"].Nodes.Add(fmat);
|
|
|
|
if (BFRES.IsWiiU)
|
|
{
|
|
fmat.MaterialU.Name = Text;
|
|
fmat.SetMaterial(fmat.MaterialU);
|
|
}
|
|
else
|
|
{
|
|
fmat.Material.Name = Text;
|
|
fmat.SetMaterial(fmat.Material);
|
|
}
|
|
}
|
|
|
|
|
|
foreach (STGenericObject obj in assimp.objects)
|
|
{
|
|
FSHP shape = new FSHP();
|
|
shape.VertexBufferIndex = shapes.Count;
|
|
shape.vertices = obj.vertices;
|
|
shape.VertexSkinCount = obj.MaxSkinInfluenceCount;
|
|
shape.vertexAttributes = settings.CreateNewAttributes();
|
|
shape.boneIndx = obj.BoneIndex;
|
|
shape.MaterialIndex = obj.MaterialIndex + MatStartIndex;
|
|
|
|
shape.Text = obj.ObjectName;
|
|
shape.lodMeshes = obj.lodMeshes;
|
|
shape.CreateNewBoundingBoxes();
|
|
shape.CreateBoneList(obj, this);
|
|
shape.CreateIndexList(obj, this);
|
|
shape.ApplyImportSettings(settings, GetMaterial(shape.MaterialIndex));
|
|
shape.SaveShape();
|
|
shape.SaveVertexBuffer();
|
|
shape.BoneIndices = new List<ushort>();
|
|
|
|
List<string> keyList = shapes.Select(o => o.Text).ToList();
|
|
shape.Text = Utils.RenameDuplicateString(keyList, shape.Text);
|
|
|
|
Nodes["FshpFolder"].Nodes.Add(shape);
|
|
shapes.Add(shape);
|
|
}
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
break;
|
|
}
|
|
UpdateVertexData();
|
|
}
|
|
public FMAT GetMaterial(int index)
|
|
{
|
|
return materials.Values.ElementAt(index);
|
|
}
|
|
public void AddMaterials(string FileName, bool Replace = true)
|
|
{
|
|
string ext = System.IO.Path.GetExtension(FileName);
|
|
ext = ext.ToLower();
|
|
|
|
switch (ext)
|
|
{
|
|
case ".bfmat":
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
if (Replace)
|
|
{
|
|
materials.Clear();
|
|
Nodes["FmatFolder"].Nodes.Clear();
|
|
}
|
|
FMAT mat = new FMAT();
|
|
mat.Material = new Material();
|
|
mat.Material.Import(FileName);
|
|
mat.ReadMaterial(mat.Material);
|
|
mat.Text = mat.Material.Name;
|
|
|
|
materials.Add(mat.Text, mat);
|
|
Nodes["FmatFolder"].Nodes.Add(mat);
|
|
break;
|
|
}
|
|
}
|
|
public override void OnClick(TreeView treeView)
|
|
{
|
|
|
|
}
|
|
private void CreateSkeleton()
|
|
{
|
|
|
|
}
|
|
private void CreateBones(STBone bone)
|
|
{
|
|
Bone bn = new Bone();
|
|
bn.BillboardIndex = (ushort)bone.BillboardIndex;
|
|
bn.Flags = BoneFlags.Visible;
|
|
bn.FlagsRotation = BoneFlagsRotation.EulerXYZ;
|
|
bn.FlagsTransform = BoneFlagsTransform.None;
|
|
bn.FlagsTransformCumulative = BoneFlagsTransformCumulative.None;
|
|
bn.Name = bone.Text;
|
|
bn.RigidMatrixIndex = 0;
|
|
bn.Rotation = new Syroot.Maths.Vector4F(bone.rotation[0],
|
|
bone.rotation[1], bone.rotation[2], bone.rotation[3]);
|
|
bn.Position = new Syroot.Maths.Vector3F(bone.position[0],
|
|
bone.position[1], bone.position[2]);
|
|
bn.Scale = new Syroot.Maths.Vector3F(bone.scale[0],
|
|
bone.scale[1], bone.scale[2]);
|
|
bn.UserData = new List<UserData>();
|
|
bn.UserDataDict = new ResDict();
|
|
}
|
|
|
|
public FSKL Skeleton
|
|
{
|
|
get
|
|
{
|
|
return skeleton;
|
|
}
|
|
set
|
|
{
|
|
skeleton = value;
|
|
}
|
|
}
|
|
private FSKL skeleton = new FSKL();
|
|
}
|
|
}
|