diff --git a/BrawlboxHelper/BrawlboxHelper.dll b/BrawlboxHelper/BrawlboxHelper.dll index a0a78e03..8564fa74 100644 Binary files a/BrawlboxHelper/BrawlboxHelper.dll and b/BrawlboxHelper/BrawlboxHelper.dll differ diff --git a/BrawlboxHelper/Syroot.NintenTools.NSW.Bfres.xml b/BrawlboxHelper/Syroot.NintenTools.NSW.Bfres.xml index c5634109..3755baae 100644 --- a/BrawlboxHelper/Syroot.NintenTools.NSW.Bfres.xml +++ b/BrawlboxHelper/Syroot.NintenTools.NSW.Bfres.xml @@ -2013,7 +2013,7 @@ - Reads BFRES offsets which is the absolute addresses. + Reads BFRES offsets which is the absolute addresses.+ The number of offsets to read. The absolute addresses of the offsets. @@ -2275,7 +2275,7 @@ The name to save. The in which the name will be stored. - + Reserves space for offsets to the written later in the string pool with the specified @@ -3160,6 +3160,11 @@ Gets or sets the instance applied on the to color their surface. + + + + + Gets or sets customly attached names. @@ -3713,7 +3718,7 @@ rigidbodies (no skinning), 1 equal rigid skinning and 2 or more smooth skinning. - + Gets the number of vertices stored by the . It is calculated from the size of the first in bytes divided by the . @@ -4850,6 +4855,16 @@ Gets or sets instances animating properties of objects stored in this section. + + + Gets or sets customly attached names. + + + + + Gets or sets customly attached instances. + + Gets or sets initial transformation values. Only stores specific transformations according to @@ -5173,6 +5188,12 @@ Euler XYZ, 3 components. + + + A cache of strings that are saved through raw IDs in place of the pointer field of a name offset. + This is used and required for TOTK models. + + Represents an FVIS subfile in a , storing visibility animations of or diff --git a/File_Format_Library/FileFormats/BFRES/BFRES.cs b/File_Format_Library/FileFormats/BFRES/BFRES.cs index 43488fca..0a5a7d27 100644 --- a/File_Format_Library/FileFormats/BFRES/BFRES.cs +++ b/File_Format_Library/FileFormats/BFRES/BFRES.cs @@ -811,13 +811,13 @@ namespace FirstPlugin var externalFlags = MeshCodec.GetExternalFlags(stream); //External flags used - if (externalFlags != (MeshCodec.ExternalFlags)0) + if (externalFlags != 0 || this.FileName.EndsWith(".mc")) { //Ensure it uses mc compressor for save this.IFileInfo.FileIsCompressed = true; if (this.IFileInfo.FileCompression == null) { - // this.IFileInfo.FileCompression = new MeshCodecFormat(); + this.IFileInfo.FileCompression = new MeshCodecFormat(); if (!this.FileName.EndsWith(".mc")) this.FileName += ".mc"; if (!this.FilePath.EndsWith(".mc")) @@ -852,12 +852,8 @@ namespace FirstPlugin if (externalFlags != (MeshCodec.ExternalFlags)0) { MeshCodec.PrepareTexToGo(resFile); - STTextureFolder texfolder = new STTextureFolder("TexToGo"); - this.Nodes.Add(texfolder); - foreach (var tex in MeshCodec.TextureList) - { - texfolder.Nodes.Add(tex); - } + MeshCodec.TextureFolder = new TexToGoFolder(MeshCodec); + this.Nodes.Add(MeshCodec.TextureFolder); } DrawableContainer.Drawables.Add(BFRESRender); @@ -971,6 +967,9 @@ namespace FirstPlugin SaveWiiU(stream); else SaveSwitch(stream); + + if (MeshCodec.TextureList.Count > 0) + MeshCodec.SaveTexToGo(); } public TreeNodeCollection GetModels() diff --git a/File_Format_Library/FileFormats/MeshCodec/MeshCodec.cs b/File_Format_Library/FileFormats/MeshCodec/MeshCodec.cs index a501b064..35507d11 100644 --- a/File_Format_Library/FileFormats/MeshCodec/MeshCodec.cs +++ b/File_Format_Library/FileFormats/MeshCodec/MeshCodec.cs @@ -18,8 +18,12 @@ namespace FirstPlugin { static ResFile ExternalStringBinary; + public TexToGoFolder TextureFolder; + public List TextureList = new List(); + public bool IsAnyTextureEdited => TextureList.Any(x => x.IsEdited); + public static ExternalFlags GetExternalFlags(Stream stream) { using (var reader = new FileReader(stream, true)) @@ -179,6 +183,15 @@ namespace FirstPlugin TextureList.Clear(); } + public void SaveTexToGo() + { + if (!IsAnyTextureEdited) + return; + + var msg = MessageBox.Show("Textures have been edited. Select the save location"); + TextureFolder.SaveEdited(); + } + public void PrepareTexToGo(ResFile resFile) { var materials = resFile.Models.SelectMany(x => x.Materials); diff --git a/File_Format_Library/FileFormats/MeshCodec/MeshCodecFormat.cs b/File_Format_Library/FileFormats/MeshCodec/MeshCodecFormat.cs new file mode 100644 index 00000000..8f47af56 --- /dev/null +++ b/File_Format_Library/FileFormats/MeshCodec/MeshCodecFormat.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.IO.Compression; +using System.Threading.Tasks; +using Toolbox.Library.IO; +using FirstPlugin; + +namespace Toolbox.Library +{ + public class MeshCodecFormat : ICompressionFormat + { + public string[] Description { get; set; } = new string[] { "Mesh Codec Compression" }; + public string[] Extension { get; set; } = new string[] { "*.mc" }; + + public bool Identify(Stream stream, string fileName) + { + using (var reader = new FileReader(stream, true)) { + return reader.CheckSignature(4, "MCPK"); + } + } + + public bool CanCompress { get; } = true; + + public Stream Decompress(Stream stream) + { + return new MemoryStream(MeshCodec.DecompressMeshCodec(stream)); + } + + public Stream Compress(Stream stream) + { + return new MemoryStream(MeshCodec.CompressMeshCodec(stream)); + } + } +} diff --git a/File_Format_Library/FileFormats/MeshCodec/TexToGoFolder.cs b/File_Format_Library/FileFormats/MeshCodec/TexToGoFolder.cs new file mode 100644 index 00000000..1578412b --- /dev/null +++ b/File_Format_Library/FileFormats/MeshCodec/TexToGoFolder.cs @@ -0,0 +1,80 @@ +using GL_EditorFramework.EditorDrawables; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Toolbox.Library; +using Toolbox.Library.IO; + +namespace FirstPlugin +{ + internal class TexToGoFolder : STTextureFolder + { + private MeshCodec MeshCodec; + + public TexToGoFolder(MeshCodec codec) : base("TexToGo") + { + MeshCodec = codec; + foreach (var tex in MeshCodec.TextureList) + Nodes.Add(tex); + } + + public override ToolStripItem[] GetContextMenuItems() + { + List Items = new List(); + Items.Add(new ToolStripMenuItem("Save Edited Textures", null, (o, e) => SaveEdited(), Keys.Control | Keys.E)); + Items.Add(new ToolStripSeparator()); + Items.AddRange(base.GetContextMenuItems()); + Items.Add(new ToolStripSeparator()); + Items.Add(new ToolStripMenuItem("Import TXTG", null, (o, e) => AddTexture(), Keys.Control | Keys.E)); + + return Items.ToArray(); + } + + public void SaveEdited() + { + if (MeshCodec.TextureList.Count == 0) + return; + + var folder = System.IO.Path.GetDirectoryName(MeshCodec.TextureList[0].FilePath); + FolderSelectDialog dlg = new FolderSelectDialog(folder); + + if (dlg.ShowDialog() == DialogResult.OK) + { + foreach (var tex in MeshCodec.TextureList) + if (tex.IsEdited) + STFileSaver.SaveFileFormat(tex, System.IO.Path.Combine(dlg.SelectedPath, $"{tex.Text}.txtg"), false); + } + } + + private void AddTexture() + { + Dictionary extensions = new Dictionary(); + extensions.Add(".txtg", "Tex To Go"); + + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Filter = FileFilters.GetCompleteFilter(extensions); + + ofd.Multiselect = false; + + if (ofd.ShowDialog() == DialogResult.OK) + { + AddTexture(ofd.FileName); + } + } + + private void AddTexture(string filePath) + { + TXTG txtg = STFileLoader.OpenFileFormat(filePath) as TXTG; + if (txtg == null) + { + MessageBox.Show($"File {filePath} not a valid TXTG file!"); + return; + } + this.MeshCodec.TextureList.Add(txtg); + Nodes.Add(txtg); + } + } +} diff --git a/File_Format_Library/FileFormats/Texture/TXTG.cs b/File_Format_Library/FileFormats/Texture/TXTG.cs index 78b14734..657d5ba9 100644 --- a/File_Format_Library/FileFormats/Texture/TXTG.cs +++ b/File_Format_Library/FileFormats/Texture/TXTG.cs @@ -367,7 +367,11 @@ namespace FirstPlugin ArrayCount = (uint)ImageList.Count; Format = tex.Format; + IsEdited = true; + UpdateEditor(); + + this.LoadOpenGLTexture(); } class SurfaceInfo diff --git a/File_Format_Library/File_Format_Library.csproj b/File_Format_Library/File_Format_Library.csproj index 267a54da..e910a088 100644 --- a/File_Format_Library/File_Format_Library.csproj +++ b/File_Format_Library/File_Format_Library.csproj @@ -346,6 +346,8 @@ + + diff --git a/File_Format_Library/Main.cs b/File_Format_Library/Main.cs index 25bb6a86..2ce2f7b6 100644 --- a/File_Format_Library/Main.cs +++ b/File_Format_Library/Main.cs @@ -334,6 +334,7 @@ namespace FirstPlugin private Type[] LoadCompressionFormats() { List Formats = new List(); + Formats.Add(typeof(MeshCodecFormat)); return Formats.ToArray(); } diff --git a/Switch_Toolbox_Library/Forms/Dialogs/FolderSelectDialog.cs b/Switch_Toolbox_Library/Forms/Dialogs/FolderSelectDialog.cs index 1dbd3e64..a51e9f8b 100644 --- a/Switch_Toolbox_Library/Forms/Dialogs/FolderSelectDialog.cs +++ b/Switch_Toolbox_Library/Forms/Dialogs/FolderSelectDialog.cs @@ -1,4 +1,5 @@ using System.ComponentModel; +using System.IO; using System.Reflection; namespace System.Windows.Forms @@ -18,15 +19,16 @@ namespace System.Windows.Forms /// /// Default constructor /// - public FolderSelectDialog() + public FolderSelectDialog(string folder = "") { ofd = new System.Windows.Forms.OpenFileDialog(); - ofd.Filter = "Folders|\n"; ofd.AddExtension = false; ofd.CheckFileExists = false; ofd.DereferenceLinks = true; ofd.Multiselect = false; + if (Directory.Exists(folder)) + ofd.InitialDirectory = folder; } #region Properties diff --git a/Switch_Toolbox_Library/IO/STFileSaver.cs b/Switch_Toolbox_Library/IO/STFileSaver.cs index 0039c2ac..c836936e 100644 --- a/Switch_Toolbox_Library/IO/STFileSaver.cs +++ b/Switch_Toolbox_Library/IO/STFileSaver.cs @@ -97,12 +97,15 @@ namespace Toolbox.Library.IO } } - if (compressionLog != string.Empty) - MessageBox.Show($"File has been saved to {FileName}. Compressed time: {compressionLog}", "Save Notification"); - else - MessageBox.Show($"File has been saved to {FileName}", "Save Notification"); + if (EnableDialog) + { + if (compressionLog != string.Empty) + MessageBox.Show($"File has been saved to {FileName}. Compressed time: {compressionLog}", "Save Notification"); + else + MessageBox.Show($"File has been saved to {FileName}", "Save Notification"); + } - // STSaveLogDialog.Show($"File has been saved to {FileName}", "Save Notification", DetailsLog); + // STSaveLogDialog.Show($"File has been saved to {FileName}", "Save Notification", DetailsLog); Cursor.Current = Cursors.Default; }