/// <summary> /// /// </summary> /// <param name="writer"></param> /// <param name="model"></param> public void WriteFMDLData(XmlWriter writer, ResU.Model model) { writer.WriteStartElement("FMDL"); writer.WriteAttributeString("Name", model.Name); // TODO Wrap these functions in if exists conditions, so that the xml only contains relevant data JPSkeleton jpSkeleton = new JPSkeleton(); jpSkeleton.ReadSkeleton(model.Skeleton); FSKL.WriteSkeleton(writer, model.Skeleton); writer.WriteStartElement("Materials"); writer.WriteAttributeString("FMATCount", model.Materials.Count.ToString()); foreach (Material mat in model.Materials.Values) { FMAT.ReadMaterial(writer, mat); } writer.WriteEndElement(); writer.WriteStartElement("Shapes"); writer.WriteAttributeString("FSHPCount", model.Shapes.Count.ToString()); writer.WriteAttributeString("FVTXCount", model.VertexBuffers.Count.ToString()); writer.WriteAttributeString("TotalVertices", model.TotalVertexCount.ToString()); foreach (Shape shp in model.Shapes.Values) { writer.WriteStartElement("FSHP"); VertexBuffer vertexBuffer = model.VertexBuffers[shp.VertexBufferIndex]; Material material = model.Materials[shp.MaterialIndex]; WriteShapesVertices(writer, shp, vertexBuffer, model, jpSkeleton); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndElement(); writer.Flush(); }
/// <summary> /// /// </summary> /// <param name="writer"></param> /// <param name="shp"></param> /// <param name="vertexBuffer"></param> /// <param name="model"></param> public static void WriteShapesVertices(XmlWriter writer, Shape shp, VertexBuffer vertexBuffer, ResU.Model model, JPSkeleton jpSkeleton) { writer.WriteAttributeString("Name", shp.Name); writer.WriteAttributeString("Flags", shp.Flags.ToString()); writer.WriteAttributeString("MaterialIndex", shp.MaterialIndex.ToString()); Program.AssertAndLog(Program.ErrorType.eBoneIndexSet, shp.BoneIndex == 0, $"{shp.Name}: Bone index is set. Why?"); writer.WriteAttributeString("BoneIndex", shp.BoneIndex.ToString()); writer.WriteAttributeString("VertexBufferIndex", shp.VertexBufferIndex.ToString()); // Write Bounding Radius string tempRadiusArray = ""; foreach (float rad in shp.RadiusArray) { tempRadiusArray += (rad.ToString() + ','); } tempRadiusArray = tempRadiusArray.Trim(','); writer.WriteAttributeString("RadiusArray", tempRadiusArray); writer.WriteAttributeString("VertexSkinCount", shp.VertexSkinCount.ToString()); Program.AssertAndLog(Program.ErrorType.eShapeTargetAttributeCountGreaterThanZero, shp.TargetAttribCount == 0, $"{shp.Name}: target attribute count of greater than 0. Unsure of this meaning."); writer.WriteAttributeString("TargetAttributeCount", shp.TargetAttribCount.ToString()); // Write Skin Bone Indices if (shp.SkinBoneIndices != null) { string tempSkinBoneIndices = ""; foreach (ushort bn in shp.SkinBoneIndices) { tempSkinBoneIndices += (bn + ","); } tempSkinBoneIndices = tempSkinBoneIndices.Trim(','); writer.WriteAttributeString("SkinBoneIndices", tempSkinBoneIndices); } // Write Key Shapes Program.AssertAndLog(Program.ErrorType.eKeyShapes, shp.KeyShapes.Count == 0, "If you hit this assert, write KeyShapes you lazy f**k."); // Write Bounding Boxes // // Summary: // Represents a spatial bounding box. writer.WriteStartElement("SubMeshBoundings"); writer.WriteAttributeString("SubMeshBoundingsCount", shp.SubMeshBoundings.Count.ToString()); foreach (Bounding bnd in shp.SubMeshBoundings) { writer.WriteStartElement("SubMeshBounding"); writer.WriteAttributeString("Center", Program.Vector3FToString(bnd.Center)); writer.WriteAttributeString("Extent", Program.Vector3FToString(bnd.Extent)); writer.WriteEndElement(); } writer.WriteEndElement(); // // Summary: // Represents a node in a Syroot.NintenTools.Bfres.SubMesh bounding tree to determine // when to show which sub mesh of a Syroot.NintenTools.Bfres.Mesh. writer.WriteStartElement("SubMeshBoundingNodes"); writer.WriteAttributeString("SubMeshBoundingNodesCount", shp.SubMeshBoundingNodes.Count.ToString()); foreach (BoundingNode node in shp.SubMeshBoundingNodes) { writer.WriteStartElement("SubMeshBoundingNode"); writer.WriteAttributeString("LeftChildIndex", node.LeftChildIndex.ToString()); writer.WriteAttributeString("NextSibling", node.NextSibling.ToString()); writer.WriteAttributeString("RightChildIndex", node.RightChildIndex.ToString()); writer.WriteAttributeString("Unknown", node.Unknown.ToString()); writer.WriteAttributeString("SubMeshIndex", node.SubMeshIndex.ToString()); writer.WriteAttributeString("SubMeshCount", node.SubMeshCount.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); // Write SubMesh Bounding Indices writer.WriteStartElement("SubMeshBoundingIndices"); writer.WriteAttributeString("SubMeshBoundingIndicesCount", shp.SubMeshBoundingIndices.Count.ToString()); if (shp.SubMeshBoundingIndices != null) { string tempSubMeshBoundingIndices = ""; foreach (ushort smbi in shp.SubMeshBoundingIndices) { tempSubMeshBoundingIndices += (smbi + ","); } tempSubMeshBoundingIndices = tempSubMeshBoundingIndices.Trim(','); writer.WriteAttributeString("SubMeshBoundingIndices", tempSubMeshBoundingIndices); } writer.WriteEndElement(); WriteMeshes(writer, shp); WriteVertexBuffer(writer, shp, vertexBuffer, model, jpSkeleton); }
/// <summary> /// /// </summary> /// <param name="writer"></param> /// <param name="shp"></param> /// <param name="vtx"></param> /// <param name="model"></param> private static void WriteVertexBuffer(XmlWriter writer, Shape shp, VertexBuffer vtx, ResU.Model model, JPSkeleton jPSkeleton) { //Create a buffer instance which stores all the buffer data VertexBufferHelper helper = new VertexBufferHelper(vtx, Syroot.BinaryData.ByteOrder.BigEndian); // TODO if this supports Switch files, you will need to re-look at this //Set each array first from the lib if exist. Then add the data all in one loop Syroot.Maths.Vector4F[] vec4Positions = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4Normals = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4uv0 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4uv1 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4uv2 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4c0 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4c1 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4t0 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4b0 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4w0 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4i0 = new Syroot.Maths.Vector4F[0]; //For shape morphing Syroot.Maths.Vector4F[] vec4Positions1 = new Syroot.Maths.Vector4F[0]; Syroot.Maths.Vector4F[] vec4Positions2 = new Syroot.Maths.Vector4F[0]; List <VertexAttrib> SortedList = vtx.Attributes.Values.OrderBy(o => o.BufferIndex).ToList(); foreach (VertexAttrib att in vtx.Attributes.Values) { if (att.Name == "_p0") { vec4Positions = AttributeData(att, helper, "_p0"); } else if (att.Name == "_n0") { vec4Normals = AttributeData(att, helper, "_n0"); } else if (att.Name == "_u0") { vec4uv0 = AttributeData(att, helper, "_u0"); } else if (att.Name == "_u1") { vec4uv1 = AttributeData(att, helper, "_u1"); } else if (att.Name == "_u2") { vec4uv2 = AttributeData(att, helper, "_u2"); } else if (att.Name == "_c0") { vec4c0 = AttributeData(att, helper, "_c0"); } else if (att.Name == "_c1") { vec4c1 = AttributeData(att, helper, "_c1"); } else if (att.Name == "_t0") { vec4t0 = AttributeData(att, helper, "_t0"); } else if (att.Name == "_b0") { vec4b0 = AttributeData(att, helper, "_b0"); } else if (att.Name == "_w0") { vec4w0 = AttributeData(att, helper, "_w0"); } else if (att.Name == "_i0") { vec4i0 = AttributeData(att, helper, "_i0"); } else if (att.Name == "_p1") { vec4Positions1 = AttributeData(att, helper, "_p1"); } else if (att.Name == "_p2") { vec4Positions2 = AttributeData(att, helper, "_p2"); } else { Program.AssertAndLog(Program.ErrorType.eUnhandledVertexAttrType, false, $"Vertex Attribute type {att.Name} not handled."); } } List <Vertex> vertices = new List <Vertex>(); for (int i = 0; i < vec4Positions.Length; i++) { Vertex v = new Vertex(); if (vec4Positions.Length > 0) { v.pos = new OpenTK.Vector3(vec4Positions[i].X, vec4Positions[i].Y, vec4Positions[i].Z); } if (vec4Positions1.Length > 0) { v.pos1 = new OpenTK.Vector3(vec4Positions1[i].X, vec4Positions1[i].Y, vec4Positions1[i].Z); } if (vec4Positions2.Length > 0) { v.pos2 = new OpenTK.Vector3(vec4Positions2[i].X, vec4Positions2[i].Y, vec4Positions2[i].Z); } if (vec4Normals.Length > 0) { v.nrm = new OpenTK.Vector3(vec4Normals[i].X, vec4Normals[i].Y, vec4Normals[i].Z); } if (vec4uv0.Length > 0) { v.uv0 = new OpenTK.Vector2(vec4uv0[i].X, vec4uv0[i].Y); } if (vec4uv1.Length > 0) { v.uv1 = new OpenTK.Vector2(vec4uv1[i].X, vec4uv1[i].Y); } if (vec4uv2.Length > 0) { v.uv2 = new OpenTK.Vector2(vec4uv2[i].X, vec4uv2[i].Y); } if (vec4w0.Length > 0) { v.boneWeights.Add(vec4w0[i].X); v.boneWeights.Add(vec4w0[i].Y); v.boneWeights.Add(vec4w0[i].Z); v.boneWeights.Add(vec4w0[i].W); } if (vec4i0.Length > 0) { v.boneIds.Add((int)vec4i0[i].X); v.boneIds.Add((int)vec4i0[i].Y); v.boneIds.Add((int)vec4i0[i].Z); v.boneIds.Add((int)vec4i0[i].W); } if (vec4t0.Length > 0) { v.tan = new OpenTK.Vector4(vec4t0[i].X, vec4t0[i].Y, vec4t0[i].Z, vec4t0[i].W); } if (vec4b0.Length > 0) { v.bitan = new OpenTK.Vector4(vec4b0[i].X, vec4b0[i].Y, vec4b0[i].Z, vec4b0[i].W); } if (vec4c0.Length > 0) { v.col = new OpenTK.Vector4(vec4c0[i].X, vec4c0[i].Y, vec4c0[i].Z, vec4c0[i].W); } if (vec4c1.Length > 0) { v.col2 = new OpenTK.Vector4(vec4c1[i].X, vec4c1[i].Y, vec4c1[i].Z, vec4c1[i].W); } int[] boneList = new int[model.Skeleton.MatrixToBoneList.Count]; int uiBone = 0; foreach (ushort node in model.Skeleton.MatrixToBoneList) { boneList[uiBone] = node; uiBone++; } if (shp.VertexSkinCount == 1) { int boneIndex = shp.BoneIndex; if (v.boneIds.Count > 0) { boneIndex = boneList[v.boneIds[0]]; } //Check if the bones are a rigid type //In game it seems to not transform if they are not rigid if (model.Skeleton.Bones[boneIndex].RigidMatrixIndex != -1) { OpenTK.Matrix4 absTransform = jPSkeleton.bones[boneIndex].Transform; v.pos = OpenTK.Vector3.TransformPosition(v.pos, absTransform); v.nrm = OpenTK.Vector3.TransformNormal(v.nrm, absTransform); } } if (shp.VertexSkinCount == 0) { try { if (model.Skeleton.Bones.Count > 0) { int boneIndex = shp.BoneIndex; // Create the Transform Matrix4 OpenTK.Vector3 mPos = new OpenTK.Vector3( model.Skeleton.Bones[boneIndex].Position.X, model.Skeleton.Bones[boneIndex].Position.Y, model.Skeleton.Bones[boneIndex].Position.Z); OpenTK.Quaternion mRot; OpenTK.Vector3 v3 = new OpenTK.Vector3( model.Skeleton.Bones[boneIndex].Rotation.X, model.Skeleton.Bones[boneIndex].Rotation.Y, model.Skeleton.Bones[boneIndex].Rotation.Z ); if (model.Skeleton.Bones[boneIndex].FlagsRotation == BoneFlagsRotation.Quaternion) { mRot = new OpenTK.Quaternion(v3, model.Skeleton.Bones[boneIndex].Rotation.W); } else if (model.Skeleton.Bones[boneIndex].FlagsRotation == BoneFlagsRotation.EulerXYZ) { mRot = new OpenTK.Quaternion(v3); } else { mRot = new OpenTK.Quaternion(); } OpenTK.Vector3 mSca = new OpenTK.Vector3( model.Skeleton.Bones[boneIndex].Scale.X, model.Skeleton.Bones[boneIndex].Scale.Y, model.Skeleton.Bones[boneIndex].Scale.Z); OpenTK.Matrix4 NoBindFix = OpenTK.Matrix4.CreateScale(mSca) * OpenTK.Matrix4.CreateFromQuaternion(mRot) * OpenTK.Matrix4.CreateTranslation(mPos); v.pos = OpenTK.Vector3.TransformPosition(v.pos, NoBindFix); v.nrm = OpenTK.Vector3.TransformNormal(v.nrm, NoBindFix); } } catch //Matrix failed. Print the coordinate data of the bone { //Console.WriteLine(model.Skeleton.bones[fshp.BoneIndex].Text); //Console.WriteLine(model.Skeleton.bones[fshp.BoneIndex].GetPosition()); //Console.WriteLine(model.Skeleton.bones[fshp.BoneIndex].GetRotation()); //Console.WriteLine(model.Skeleton.bones[fshp.BoneIndex].GetScale()); } } vertices.Add(v); } // Write Vertex Data writer.WriteStartElement("Vertices"); writer.WriteAttributeString("VertexCount", vtx.VertexCount.ToString()); for (int i = 0; i < vertices.Count; i++) { writer.WriteStartElement("Vertex"); writer.WriteAttributeString("Index", i.ToString()); writer.WriteAttributeString("Position0", Program.Vector3ToString(vertices[i].pos)); writer.WriteAttributeString("Position1", Program.Vector3ToString(vertices[i].pos1)); Program.AssertAndLog(Program.ErrorType.eVertexPosSet, vertices[i].pos1 == OpenTK.Vector3.Zero, $"Vertex index {i} pos1 is set to {vertices[i].pos1} and not 0"); // Add C++ support writer.WriteAttributeString("Position2", Program.Vector3ToString(vertices[i].pos2)); Program.AssertAndLog(Program.ErrorType.eVertexPosSet, vertices[i].pos2 == OpenTK.Vector3.Zero, $"Vertex index {i} pos2 is set to {vertices[i].pos2} and not 0"); // Add C++ support writer.WriteAttributeString("Normal", Program.Vector3ToString(vertices[i].nrm)); writer.WriteAttributeString("UV0", Program.Vector2ToString(vertices[i].uv0)); writer.WriteAttributeString("UV1", Program.Vector2ToString(vertices[i].uv1)); writer.WriteAttributeString("UV2", Program.Vector2ToString(vertices[i].uv2)); writer.WriteAttributeString("Color0", Program.Vector4ToString(vertices[i].col)); writer.WriteAttributeString("Color1", Program.Vector4ToString(vertices[i].col2)); Program.AssertAndLog(Program.ErrorType.eVertexPosSet, vertices[i].col2 == OpenTK.Vector4.One, $"Vertex index {i} col2 is set to {vertices[i].col2} and not One"); // Add C++ support. Unknown use of col2 writer.WriteAttributeString("Tangent", Program.Vector4ToString(vertices[i].tan)); writer.WriteAttributeString("Binormal", Program.Vector4ToString(vertices[i].bitan)); string tempBoneWeights = ""; foreach (var w in vertices[i].boneWeights) { tempBoneWeights += (w.ToString() + ','); } tempBoneWeights = tempBoneWeights.Trim(','); writer.WriteAttributeString("BlendWeights", tempBoneWeights); string tempBoneIds = ""; foreach (var w in vertices[i].boneIds) { tempBoneIds += (w.ToString() + ','); } tempBoneIds = tempBoneIds.Trim(','); writer.WriteAttributeString("BlendIndex", tempBoneIds); writer.WriteEndElement(); } writer.WriteEndElement(); }
//Function addes shapes, vertices and meshes public void AddOjects(string FileName, ResFile resFileNX, ResU.ResFile resFileU, bool Replace = true) { int totalSkinCountLimiter = 0; bool IsWiiU = (resFileU != null); if (shapes.Count > 0) { totalSkinCountLimiter = shapes[0].VertexSkinCount; } 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(); } if (IsWiiU) { var shpS = new ResU.Shape(); var vertexBufferU = new ResU.VertexBuffer(); shpS.Import(FileName, vertexBufferU, resFileU); FSHP shapeS = new FSHP(); shapeS.ShapeU = shpS; BfresWiiU.ReadShapesVertices(shapeS, shpS, vertexBufferU, this); shapes.Add(shapeS); Nodes["FshpFolder"].Nodes.Add(shapeS); } else { 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); } IsEdited = true; Cursor.Current = Cursors.Default; break; case ".bfmdl": Cursor.Current = Cursors.WaitCursor; if (Replace) { shapes.Clear(); Nodes["FshpFolder"].Nodes.Clear(); materials.Clear(); Nodes["FmatFolder"].Nodes.Clear(); } if (IsWiiU) { var mdlU = new ResU.Model(); mdlU.Import(FileName, resFileU); mdlU.Name = Text; BfresWiiU.ReadModel(this, mdlU); } else { Model mdl = new Model(); mdl.Import(FileName, resFileNX); mdl.Name = Text; Console.WriteLine(mdl.ShapeCount); Console.WriteLine(mdl.MaterialCount); Console.WriteLine(mdl.VertexBufferCount); Console.WriteLine(mdl.Skeleton.Bones.Count); BfresSwitch.ReadModel(this, mdl); } IsEdited = true; Cursor.Current = Cursors.Default; break; case ".csv": CsvModel csvModel = new CsvModel(); csvModel.LoadFile(new System.IO.FileStream(FileName, System.IO.FileMode.Open), true); if (csvModel.objects.Count == 0) { MessageBox.Show("No models found!"); return; } BfresModelImportSettings csvsettings = new BfresModelImportSettings(); csvsettings.DisableMaterialEdits(); csvsettings.SkinCountLimit = totalSkinCountLimiter; 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(); Nodes["FshpFolder"].Nodes.Add(shape); shapes.Add(shape); shape.VertexBufferIndex = shapes.Count; shape.vertices = obj.vertices; shape.MaterialIndex = 0; shape.vertexAttributes = csvsettings.CreateNewAttributes(); shape.BoneIndex = 0; shape.Text = obj.ObjectName; shape.lodMeshes = obj.lodMeshes; shape.CreateNewBoundingBoxes(); shape.CreateBoneList(obj, this); shape.CreateIndexList(obj, this); //Todo find better way. Currently uses import settings now shape.ApplyImportSettings(csvsettings, GetMaterial(shape.MaterialIndex)); shape.VertexSkinCount = obj.GetMaxSkinInfluenceCount(); shape.BoneIndices = shape.GetIndices(Skeleton); shape.SaveShape(IsWiiU); shape.SaveVertexBuffer(); if (IsWiiU) { shape.ShapeU.SubMeshBoundingIndices = new List <ushort>(); shape.ShapeU.SubMeshBoundingIndices.Add(0); shape.ShapeU.SubMeshBoundingNodes = new List <ResU.BoundingNode>(); shape.ShapeU.SubMeshBoundingNodes.Add(new ResU.BoundingNode() { LeftChildIndex = 0, NextSibling = 0, SubMeshIndex = 0, RightChildIndex = 0, Unknown = 0, SubMeshCount = 1, }); } if (IsWiiU) { BfresWiiU.ReadShapesVertices(shape, shape.ShapeU, shape.VertexBufferU, this); } else { BfresSwitch.ReadShapesVertices(shape, shape.Shape, shape.VertexBuffer, this); } } Cursor.Current = Cursors.Default; } IsEdited = true; 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) { bool UseMats = settings.ExternalMaterialPath != string.Empty; if (Replace) { shapes.Clear(); Nodes["FshpFolder"].Nodes.Clear(); } Cursor.Current = Cursors.WaitCursor; if (Replace && UseMats) { materials.Clear(); Nodes["FmatFolder"].Nodes.Clear(); MatStartIndex = 0; } if (UseMats) { foreach (STGenericMaterial mat in assimp.materials) { FMAT fmat = new FMAT(); if (IsWiiU) { fmat.MaterialU = new ResU.Material(); fmat.MaterialU.Import(settings.ExternalMaterialPath, resFileU); BfresWiiU.ReadMaterial(fmat, fmat.MaterialU); } else { fmat.Material = new Material(); fmat.Material.Import(settings.ExternalMaterialPath); fmat.ReadMaterial(fmat.Material); } 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.TextureMaps) { 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 && Parent != null) { foreach (var node in Parent.Parent.Nodes) { if (node is BNTX) { var bntx = (BNTX)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"); } } } if (PluginRuntime.ftexContainers.Count > 0 && Parent != null) { foreach (var node in Parent.Parent.Nodes) { if (node is BFRESGroupNode) { if (((BFRESGroupNode)node).Type == BRESGroupType.Textures) { var ftexCont = (BFRESGroupNode)node; ftexCont.ImportBasicTextures("Basic_Alb"); ftexCont.ImportBasicTextures("Basic_Nrm"); ftexCont.ImportBasicTextures("Basic_Spm"); ftexCont.ImportBasicTextures("Basic_Sphere"); ftexCont.ImportBasicTextures("Basic_Mtl"); ftexCont.ImportBasicTextures("Basic_Rgh"); ftexCont.ImportBasicTextures("Basic_MRA"); ftexCont.ImportBasicTextures("Basic_Bake_st0"); ftexCont.ImportBasicTextures("Basic_Bake_st1"); ftexCont.ImportBasicTextures("Basic_Emm"); } } } } foreach (var tex in mat.TextureMaps) { foreach (var t in fmat.TextureMaps) { 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); if (IsWiiU) { fmat.MaterialU.Name = Text; fmat.SetMaterial(fmat.MaterialU, resFileU); } else { fmat.Material.Name = Text; fmat.SetMaterial(fmat.Material); } materials.Add(fmat.Text, fmat); Nodes["FmatFolder"].Nodes.Add(fmat); } } if (settings.ImportBones) { if (assimp.skeleton.bones.Count > 0) { Skeleton.bones.Clear(); Skeleton.node.Nodes.Clear(); if (IsWiiU) { BfresWiiU.SaveSkeleton(Skeleton, assimp.skeleton.bones); } else { BfresSwitch.SaveSkeleton(Skeleton, assimp.skeleton.bones); } } } if (materials.Count <= 0) { //Force material creation if there is none present FMAT fmat = new FMAT(); fmat.Text = "NewMaterial"; materials.Add(fmat.Text, fmat); Nodes["FmatFolder"].Nodes.Add(fmat); if (IsWiiU) { fmat.MaterialU = new ResU.Material(); fmat.MaterialU.Name = "NewMaterial"; BfresWiiU.ReadMaterial(fmat, fmat.MaterialU); } else { fmat.Material = new Material(); fmat.Material.Name = "NewMaterial"; fmat.ReadMaterial(fmat.Material); } } foreach (STGenericObject obj in assimp.objects) { FSHP shape = new FSHP(); Nodes["FshpFolder"].Nodes.Add(shape); shapes.Add(shape); shape.VertexBufferIndex = shapes.Count; shape.vertices = obj.vertices; shape.vertexAttributes = settings.CreateNewAttributes(); shape.BoneIndex = obj.BoneIndex; STConsole.WriteLine(Text + " " + obj.MaterialIndex); if (UseMats) { shape.MaterialIndex = obj.MaterialIndex + MatStartIndex; } else { shape.MaterialIndex = 0; } if (shape.MaterialIndex >= materials.Count) { shape.MaterialIndex = 0; } 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.VertexSkinCount = obj.GetMaxSkinInfluenceCount(); shape.BoneIndices = shape.GetIndices(Skeleton); shape.SaveShape(IsWiiU); shape.SaveVertexBuffer(); if (IsWiiU) { shape.ShapeU.SubMeshBoundingIndices = new List <ushort>(); shape.ShapeU.SubMeshBoundingIndices.Add(0); shape.ShapeU.SubMeshBoundingNodes = new List <ResU.BoundingNode>(); shape.ShapeU.SubMeshBoundingNodes.Add(new ResU.BoundingNode() { LeftChildIndex = 0, NextSibling = 0, SubMeshIndex = 0, RightChildIndex = 0, Unknown = 0, SubMeshCount = 1, }); } List <string> keyList = shapes.Select(o => o.Text).ToList(); shape.Text = Utils.RenameDuplicateString(keyList, shape.Text); if (IsWiiU) { BfresWiiU.ReadShapesVertices(shape, shape.ShapeU, shape.VertexBufferU, this); } else { BfresSwitch.ReadShapesVertices(shape, shape.Shape, shape.VertexBuffer, this); } } IsEdited = true; Cursor.Current = Cursors.Default; } break; } if (IsEdited) { UpdateVertexData(); } }