diff --git a/.vs/Switch_Toolbox/v15/.suo b/.vs/Switch_Toolbox/v15/.suo index baf0ef09..10836d20 100644 Binary files a/.vs/Switch_Toolbox/v15/.suo and b/.vs/Switch_Toolbox/v15/.suo differ diff --git a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide index 47c57aa2..637d66a9 100644 Binary files a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide and b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide differ diff --git a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal index f45bfc3d..7de2e08e 100644 Binary files a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal and b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal differ diff --git a/Switch_FileFormatsMain/FileFormats/Archives/SDF.cs b/Switch_FileFormatsMain/FileFormats/Archives/SDF.cs index d0faea54..f55d8356 100644 --- a/Switch_FileFormatsMain/FileFormats/Archives/SDF.cs +++ b/Switch_FileFormatsMain/FileFormats/Archives/SDF.cs @@ -7,10 +7,11 @@ using Switch_Toolbox; using System.Windows.Forms; using Switch_Toolbox.Library; using Switch_Toolbox.Library.IO; +using Switch_Toolbox.Library.Forms; namespace FirstPlugin { - public class SDF : TreeNodeFile, IFileFormat + public class SDF : IArchiveFile, IFileFormat { public FileType FileType { get; set; } = FileType.Archive; @@ -21,6 +22,11 @@ namespace FirstPlugin public string FilePath { get; set; } public IFileInfo IFileInfo { get; set; } + public bool CanAddFiles { get; set; } = false; + public bool CanRenameFiles { get; set; } = false; + public bool CanReplaceFiles { get; set; } = false; + public bool CanDeleteFiles { get; set; } = false; + public bool Identify(System.IO.Stream stream) { using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true)) @@ -38,15 +44,19 @@ namespace FirstPlugin } } + public List files = new List(); + public IEnumerable Files => files; + SDFTOC_Header Header; SDFTOC_ID startId; int[] block1; SDFTOC_ID[] blockIds; - SDFTOC_Block2[] block2Array; + public SDFTOC_Block2[] block2Array; byte[] DecompressedBlock; SDFTOC_ID endId; - List FilePaths = new List(); + //Temp but just for now as this is expeirmental. Need to optmize tree loading + private readonly int MAX_FILE_DISPLAY = 4000; //Thanks to https://github.com/GoldFarmer/rouge_sdf/blob/master/main.cpp for docs/structs public void Load(System.IO.Stream stream) @@ -97,30 +107,14 @@ namespace FirstPlugin //Read last id endId = new SDFTOC_ID(reader); - Text = FileName; + MessageBox.Show("Note! Support for this format is experimental. The tool will only load < 4000 files atm due to slow loading"); - LoadTree(); + for (int i = 0; i < FileEntries.Count; i++) + if (i < MAX_FILE_DISPLAY) + files.Add(FileEntries[i]); } } - private void LoadTree() - { - // Get a list of everything under the users' temp folder as an example - string[] fileList; - fileList = FilePaths.ToArray(); - - // Parse the file list into a TreeNode collection - TreeNode node = GetNodes(new TreeNode(), fileList); - Nodes.Add(node); // Add the new nodes - - // Copy the new nodes to an array - int nodeCount = node.Nodes.Count; - TreeNode[] nodes = new TreeNode[nodeCount]; - node.Nodes.CopyTo(nodes, 0); - - Nodes.AddRange(nodes); // Add the new nodes - } - private TreeNode GetNodes(TreeNode parent, string[] fileList) { // build a TreeNode collection from the file list @@ -151,53 +145,6 @@ namespace FirstPlugin return parent; } - void FillTreeNodes(TreeNode root, List files) - { - var rootText = root.Text; - var rootTextLength = rootText.Length; - var nodeStrings = files; - foreach (var node in nodeStrings) - { - string nodeString = node; - nodeString = nodeString.Replace(@"\", "/"); - - var roots = nodeString.Split(new char[] { '/' }, - StringSplitOptions.RemoveEmptyEntries); - - // The initial parent is the root node - var parentNode = root; - var sb = new StringBuilder(rootText, nodeString.Length + rootTextLength); - for (int rootIndex = 0; rootIndex < roots.Length; rootIndex++) - { - // Build the node name - var parentName = roots[rootIndex]; - sb.Append("/"); - sb.Append(parentName); - var nodeName = sb.ToString(); - - // Search for the node - var index = parentNode.Nodes.IndexOfKey(nodeName); - if (index == -1) - { - // Node was not found, add it - - var temp = new TreeNode(parentName, 0, 0); - if (rootIndex == roots.Length - 1) - temp = new TreeNode(parentName); //File entry - - temp.Name = nodeName; - parentNode.Nodes.Add(temp); - parentNode = temp; - } - else - { - // Node was found, set that as parent and continue - parentNode = parentNode.Nodes[index]; - } - } - } - } - public void DecompressNameBlock(uint magic, byte[] CompressedBlock, SDFTOC_Header header) { byte[] decomp = null; @@ -226,11 +173,108 @@ namespace FirstPlugin return result; } + public bool AddFile(ArchiveFileInfo archiveFileInfo) + { + return false; + } + + public bool DeleteFile(ArchiveFileInfo archiveFileInfo) + { + return false; + } + + public class FileEntry : ArchiveFileInfo + { + public SDF SDFParent; + public string FilePath; + public string FolderPath; + public string FileBlockPath; + public ulong PackageID; + public ulong Offset; + public ulong DecompressedSize; + public List CompressedSizes; + public ulong DdsType; + public bool UseDDS; + public bool IsCompressed = false; + + public override byte[] FileData + { + get => GetFileBytes(); + set => base.FileData = value; + } + + public override IFileFormat OpenFile() + { + var FileFormat = STFileLoader.OpenFileFormat( + IOExtensions.RemoveIllegaleFolderNameCharacters(FileName), FileData, true); + + if (FileFormat is DDS) + ((DDS)FileFormat).SwitchSwizzle = true; + + return FileFormat; + } + + public byte[] GetFileBytes() + { + List Data = new List(); + if (File.Exists(FileBlockPath)) + { + var block = File.Open(FileBlockPath, FileMode.Open); + using (var stream = new FileReader(block)) + { + if (CompressedSizes.Count == 0) + { + //Decompressed File + string FileNameBlock = Path.Combine(FolderPath, FilePath); + string FolerPath = Path.GetDirectoryName(FileNameBlock); + if (!Directory.Exists(FolerPath)) + Directory.CreateDirectory(FolerPath); + + return stream.getSection((int)Offset, (int)DecompressedSize); + } + else + { + var PageSize = (double)0x10000; + var DecompOffset = 0; + var CompOffset = 0; + IsCompressed = true; + + if (UseDDS) + { + Data.Add(SDFParent.block2Array[DdsType].Data); + } + + for (var i = 0; i < CompressedSizes.Count; i++) + { + var decompSize = (int)Math.Min((int)DecompressedSize - DecompOffset, PageSize); + if (CompressedSizes[i] == 0 || decompSize == (int)CompressedSizes[i]) + { + stream.Seek((int)Offset + CompOffset, SeekOrigin.Begin); + CompressedSizes[i] = (ulong)decompSize; + Data.Add( stream.ReadBytes(decompSize)); + } + else + { + stream.Seek((int)Offset + CompOffset, SeekOrigin.Begin); + Data.Add(STLibraryCompression.ZSTD.Decompress(stream.ReadBytes((int)CompressedSizes[i]))); + } + DecompOffset += (int)decompSize; + CompOffset += (int)CompressedSizes[i]; + } + } + } + + block.Dispose(); + } + + return Utils.CombineByteArray(Data.ToArray()); + } + } + + public List FileEntries = new List(); + public void ParseNames(FileReader reader, string Name = "") { - if (!Name.Contains("dummy") && FilePaths.Count < 200) - FilePaths.Add(Name); - char ch = reader.ReadChar(); if (ch == 0) @@ -253,7 +297,7 @@ namespace FirstPlugin int flag1 = (ch >> 3) & 1; // int flag1 = ch & 8; - if (count1 != 0) + if (count1 > 0) { uint strangeId = reader.ReadUInt32(); byte chr2 = reader.ReadByte(); @@ -264,10 +308,10 @@ namespace FirstPlugin for (int chunkIndex = 0; chunkIndex < count1; chunkIndex++) { byte ch3 = reader.ReadByte(); - if (ch3 == 0) - { - break; - } + // if (ch3 == 0) + // { + // break; + // } int compressedSizeByteCount = (ch3 & 3) + 1; int packageOffsetByteCount = (ch3 >> 2) & 7; @@ -295,7 +339,7 @@ namespace FirstPlugin if (packageId >= Header.Block1Count) { - throw new InvalidDataException("SDF Package ID outside of TOC range"); + // throw new InvalidDataException($"SDF Package ID ({packageId}) outside of TOC range ({ Header.Block1Count})"); } @@ -317,8 +361,8 @@ namespace FirstPlugin if (Header.Version <= 0x16) { - fileId = (long)readVariadicInteger(4, reader); - } + // fileId = (long)readVariadicInteger(4, reader); + } if (compSizeArray.Count == 0 && hasCompression) compSizeArray.Add(compressedSize); @@ -333,7 +377,7 @@ namespace FirstPlugin { reader.ReadByte(); reader.ReadByte(); - } + } } } else @@ -345,32 +389,43 @@ namespace FirstPlugin } } - public static ulong NextMultiple(ulong value, ulong multiple) => NextMultiple((long)value, multiple); - public static ulong NextMultiple(long value, ulong multiple) - { - return (ulong)Math.Ceiling(value / (double)multiple) * multiple; - } - public void DumpFile(string Name, ulong packageId, ulong packageOffset, ulong decompresedSize, List compressedSize, ulong ddsType, bool Append, bool UseDDS) { - string PathFolder = Path.GetDirectoryName(FileName); + string PathFolder = Path.GetDirectoryName(FilePath); string layer; - Console.WriteLine(Name + " " + packageId + " " + packageOffset + " " + decompresedSize + " " + ddsType + " " + UseDDS); - if (packageId < 1000) + if (packageId < 1000) layer = "A"; + else if (packageId < 2000) layer = "B"; + else if (packageId < 3000) layer = "C"; + else layer = "D"; + + string ID = packageId.ToString("D" + 4); + + string BlockFilePath = Path.Combine(PathFolder, $"sdf-{layer}-{ID}.sdfdata"); + if (Append) { - layer = "A"; - } - else if (packageId < 2000) - { - layer = "B"; - } - else - { - layer = "C"; + } + bool IsFile = !Name.Contains("dummy") && decompresedSize > 5; + if (IsFile) + { + FileEntries.Add(new FileEntry() + { + SDFParent = this, + FileName = Name, + FileBlockPath = BlockFilePath, + FilePath = Name, + FolderPath = PathFolder, + CompressedSizes = compressedSize, + DdsType = ddsType, + UseDDS = UseDDS, + DecompressedSize = decompresedSize, + PackageID = packageId, + Offset = packageOffset, + }); + } } public void Unload() diff --git a/Switch_FileFormatsMain/FileFormats/BFRES/BFRES.cs b/Switch_FileFormatsMain/FileFormats/BFRES/BFRES.cs index 0c6e7209..1290d063 100644 --- a/Switch_FileFormatsMain/FileFormats/BFRES/BFRES.cs +++ b/Switch_FileFormatsMain/FileFormats/BFRES/BFRES.cs @@ -413,15 +413,16 @@ namespace FirstPlugin if (SelectedSection is ExternalFileData) { - HexEditor editor = (HexEditor)bfresEditor.GetActiveEditor(typeof(HexEditor)); + ArchiveFilePanel editor = (ArchiveFilePanel)LibraryGUI.Instance.GetActiveContent(typeof(ArchiveFilePanel)); if (editor == null) { - editor = new HexEditor(); + editor = new ArchiveFilePanel(); editor.Dock = DockStyle.Fill; - bfresEditor.LoadEditor(editor); + LibraryGUI.Instance.LoadEditor(editor); } - editor.Text = Text; - editor.LoadData(((ExternalFileData)SelectedSection).Data); + + editor.LoadFile(((ExternalFileData)SelectedSection).ArchiveFileInfo); + editor.UpdateEditor(); return; } @@ -781,6 +782,8 @@ namespace FirstPlugin ((BNTX)node).Unload(); } Nodes.Clear(); + + GC.SuppressFinalize(this); } public byte[] Save() diff --git a/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/SubFiles/ExternalFiles.cs b/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/SubFiles/ExternalFiles.cs index 7cebae92..9895ad0e 100644 --- a/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/SubFiles/ExternalFiles.cs +++ b/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/SubFiles/ExternalFiles.cs @@ -9,23 +9,106 @@ namespace Bfres.Structs { public class ExternalFileData : STGenericWrapper { + public ArchiveFileInfo ArchiveFileInfo; + public override string ExportFilter => "All files (*.*)|*.*"; - //Format to attach - public IFileFormat FileFormat; + public byte[] Data + { + get + { + return ArchiveFileInfo.FileData; + } + set + { + ArchiveFileInfo.FileData = value; + } + } - public byte[] Data; public ExternalFileData(string name, byte[] data) { ImageKey = "folder"; Text = name; - Data = data; CanDelete = true; CanRename = true; CanReplace = true; CanExport = true; + + ArchiveFileInfo = new ArchiveFileInfo(); + ArchiveFileInfo.FileData = data; + } + + //Todo move all of this data into one single class + //Using ArchiveFileWrapper would be used wrong due to requring an IArchiveFile + public override void OnDoubleMouseClick(TreeView treeview) + { + IFileFormat file = ArchiveFileInfo.OpenFile(); + if (file == null) //Format not supported so return + return; + + ArchiveFileInfo.FileFormat = file; + + if (Utils.HasInterface(file.GetType(), typeof(IEditor<>))) + { + OpenFormDialog(file); + } + else if (file != null && file is TreeNodeFile) + ReplaceNode(this, (TreeNodeFile)file); + } + + public static void ReplaceNode(TreeNode replaceNode, TreeNodeFile NewNode) + { + if (NewNode == null) + return; + + // node.Nodes.RemoveAt(index); + // node.Nodes.Insert(index, NewNode); + + + NewNode.ImageKey = replaceNode.ImageKey; + NewNode.SelectedImageKey = replaceNode.SelectedImageKey; + NewNode.Text = replaceNode.Text; + } + + private void OpenFormDialog(IFileFormat fileFormat) + { + UserControl form = GetEditorForm(fileFormat); + form.Text = (((IFileFormat)fileFormat).FileName); + + var parentForm = LibraryGUI.Instance.GetActiveForm(); + + GenericEditorForm editorForm = new GenericEditorForm(true, form); + editorForm.FormClosing += (sender, e) => FormClosing(sender, e, fileFormat); + if (editorForm.ShowDialog() == DialogResult.OK) + { + if (fileFormat.CanSave) + { + ArchiveFileInfo.FileData = fileFormat.Save(); + UpdateEditor(); + } + } + } + + private void FormClosing(object sender, EventArgs args, IFileFormat fileFormat) + { + if (((Form)sender).DialogResult != DialogResult.OK) + return; + } + + public UserControl GetEditorForm(IFileFormat fileFormat) + { + Type objectType = fileFormat.GetType(); + foreach (var inter in objectType.GetInterfaces()) + { + if (inter.IsGenericType && inter.GetGenericTypeDefinition() == typeof(IEditor<>)) + { + System.Reflection.MethodInfo method = objectType.GetMethod("OpenForm"); + return (UserControl)method.Invoke(fileFormat, new object[0]); + } + } + return null; } public override void OnClick(TreeView treeview) { diff --git a/Switch_FileFormatsMain/FileFormats/Texture/BNTX.cs b/Switch_FileFormatsMain/FileFormats/Texture/BNTX.cs index 0540915f..8fecbabd 100644 --- a/Switch_FileFormatsMain/FileFormats/Texture/BNTX.cs +++ b/Switch_FileFormatsMain/FileFormats/Texture/BNTX.cs @@ -193,6 +193,8 @@ namespace FirstPlugin if (PluginRuntime.bntxContainers.Contains(this)) PluginRuntime.bntxContainers.Remove(this); + + GC.SuppressFinalize(this); } public static byte[] CreateNewBNTX(string Name) @@ -225,6 +227,20 @@ namespace FirstPlugin Textures.Remove(textureData.Text); LibraryGUI.Instance.UpdateViewport(); } + + public override UserControl GetEditor() + { + STPropertyGrid editor = new STPropertyGrid(); + editor.Text = Text; + editor.Dock = DockStyle.Fill; + return editor; + } + + public override void FillEditor(UserControl control) + { + ((STPropertyGrid)control).LoadProperty(BinaryTexFile, OnPropertyChanged); + } + public override void OnClick(TreeView treeView) { if (Parent != null && Parent is BFRES) diff --git a/Switch_FileFormatsMain/FileFormats/Texture/GTXFile.cs b/Switch_FileFormatsMain/FileFormats/Texture/GTXFile.cs index 3b9ea1e1..25ac46d9 100644 --- a/Switch_FileFormatsMain/FileFormats/Texture/GTXFile.cs +++ b/Switch_FileFormatsMain/FileFormats/Texture/GTXFile.cs @@ -69,17 +69,17 @@ namespace FirstPlugin public List blocks = new List(); - public override void OnClick(TreeView treeview) + public override UserControl GetEditor() { - STPropertyGrid editor = (STPropertyGrid)LibraryGUI.Instance.GetActiveContent(typeof(STPropertyGrid)); - if (editor == null) - { - editor = new STPropertyGrid(); - LibraryGUI.Instance.LoadEditor(editor); - } + STPropertyGrid editor = new STPropertyGrid(); editor.Text = Text; editor.Dock = DockStyle.Fill; - editor.LoadProperty(header, null); + return editor; + } + + public override void FillEditor(UserControl control) + { + ((STPropertyGrid)control).LoadProperty(header); } public void Load(System.IO.Stream stream) diff --git a/Switch_FileFormatsMain/Main.cs b/Switch_FileFormatsMain/Main.cs index 72feae47..b36b1577 100644 --- a/Switch_FileFormatsMain/Main.cs +++ b/Switch_FileFormatsMain/Main.cs @@ -318,12 +318,12 @@ namespace FirstPlugin Formats.Add(typeof(Turbo.Course_MapCamera_bin)); Formats.Add(typeof(Turbo.PartsBIN)); + Formats.Add(typeof(SDF)); //Unfinished wip formats not ready for use if (Runtime.DEVELOPER_DEBUG_MODE) { Formats.Add(typeof(GFBMDL)); - Formats.Add(typeof(SDF)); Formats.Add(typeof(NCA)); Formats.Add(typeof(XCI)); Formats.Add(typeof(BFLAN)); diff --git a/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache b/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache index bb7f803a..9764cab2 100644 Binary files a/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache and b/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache differ diff --git a/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache b/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache index fa35bb30..d992c804 100644 Binary files a/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache and b/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache differ diff --git a/Switch_Toolbox_Library/FileFormats/DDS.cs b/Switch_Toolbox_Library/FileFormats/DDS.cs index dc9ea9be..e668e2f0 100644 --- a/Switch_Toolbox_Library/FileFormats/DDS.cs +++ b/Switch_Toolbox_Library/FileFormats/DDS.cs @@ -766,10 +766,10 @@ namespace Switch_Toolbox.Library ArrayCount = DX10header.arrayFlag; } - public bool Swizzle = false; + public bool SwitchSwizzle = false; public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0) { - if (Swizzle) + if (SwitchSwizzle) return TegraX1Swizzle.GetImageData(this, bdata, ArrayLevel, MipLevel); return GetArrayFaces(this, ArrayCount)[ArrayLevel].mipmaps[MipLevel]; diff --git a/Switch_Toolbox_Library/FileFormats/ZIP.cs b/Switch_Toolbox_Library/FileFormats/ZIP.cs new file mode 100644 index 00000000..60392afa --- /dev/null +++ b/Switch_Toolbox_Library/FileFormats/ZIP.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO.Compression; + +namespace Switch_Toolbox.Library +{ + public class ZIP : TreeNodeFile, IFileFormat + { + const int MagicFileConstant = 0x504B0304; + + public FileType FileType { get; set; } = FileType.Archive; + + public bool CanSave { get; set; } + public string[] Description { get; set; } = new string[] { "ZIP" }; + public string[] Extension { get; set; } = new string[] { "*.zip" }; + public string FileName { get; set; } + public string FilePath { get; set; } + public IFileInfo IFileInfo { get; set; } + + public bool Identify(System.IO.Stream stream) + { + using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true)) + { + reader.SetByteOrder(true); + return reader.ReadInt32() == MagicFileConstant; + } + } + + public Type[] Types + { + get + { + List types = new List(); + return types.ToArray(); + } + } + + public void Load(System.IO.Stream stream) + { + + } + + public byte[] Save() + { + return null; + } + + public void Unload() + { + + } + } +} diff --git a/Switch_Toolbox_Library/Forms/Archive/ArchiveFilePanel.cs b/Switch_Toolbox_Library/Forms/Archive/ArchiveFilePanel.cs index 29e3a28b..e7cdaed1 100644 --- a/Switch_Toolbox_Library/Forms/Archive/ArchiveFilePanel.cs +++ b/Switch_Toolbox_Library/Forms/Archive/ArchiveFilePanel.cs @@ -52,7 +52,6 @@ namespace Switch_Toolbox.Library.Forms return null; } - public void UpdateEditor() { if (GetEditor() == 0) @@ -65,18 +64,25 @@ namespace Switch_Toolbox.Library.Forms private void UpdateFileEditor() { + if (!ArchiveFileInfo.IsSupportedFileFormat()) + { + AddControl(new STUserControl()); + return; + } + var File = ArchiveFileInfo.FileFormat; - if (File == null) + if (File == null) //If the file is not open yet, try temporarily for a preview File = ArchiveFileInfo.OpenFile(); UserControl control = GetEditorForm(File); if (control != null) { AddControl(control); - - // if (CheckActiveType(control.GetType())) - // AddControl(control); } + + //If the format isn't active we can just dispose it + if (ArchiveFileInfo.FileFormat == null) + File.Unload(); } private bool CheckActiveType(Type type) @@ -89,13 +95,30 @@ namespace Switch_Toolbox.Library.Forms if (fileFormat == null) return new STUserControl() { Dock = DockStyle.Fill }; + if (fileFormat is TreeNodeFile) + { + var Editor = ((TreeNodeFile)fileFormat).GetEditor(); + var ActiveEditor = GetActiveEditor(Editor.GetType()); + if (ActiveEditor != null) + Editor = ActiveEditor; + + ((TreeNodeFile)fileFormat).FillEditor(Editor); + + return Editor; + } + Type objectType = fileFormat.GetType(); foreach (var inter in objectType.GetInterfaces()) { if (inter.IsGenericType && inter.GetGenericTypeDefinition() == typeof(IEditor<>)) { System.Reflection.MethodInfo method = objectType.GetMethod("OpenForm"); - return (UserControl)method.Invoke(fileFormat, new object[0]); + var Editor = (UserControl)method.Invoke(fileFormat, new object[0]); + var ActiveEditor = GetActiveEditor(Editor.GetType()); + if (ActiveEditor != null) + Editor = ActiveEditor; + + return Editor; } } return null; diff --git a/Switch_Toolbox_Library/Forms/Custom/TreeViewCustom.cs b/Switch_Toolbox_Library/Forms/Custom/TreeViewCustom.cs index c2a290eb..0324269f 100644 --- a/Switch_Toolbox_Library/Forms/Custom/TreeViewCustom.cs +++ b/Switch_Toolbox_Library/Forms/Custom/TreeViewCustom.cs @@ -22,6 +22,7 @@ namespace Switch_Toolbox.Library { } } + public class TreeNodeFile : TreeNodeCustom { public bool CanDelete @@ -38,6 +39,23 @@ namespace Switch_Toolbox.Library } } + public virtual UserControl GetEditor() { return new STUserControl(); } + public virtual void FillEditor(UserControl control) { } + + public override void OnClick(TreeView treeview) + { + var Editor = GetEditor(); + Editor.Dock = DockStyle.Fill; + + var ActiveEditor = LibraryGUI.Instance.GetActiveContent(Editor.GetType()); + if (ActiveEditor != null) + Editor = ActiveEditor; + else + LibraryGUI.Instance.LoadEditor(Editor); + + FillEditor(Editor); + } + public TreeNodeFile() { diff --git a/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditor.Designer.cs b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditor.Designer.cs index ed8c0ce6..fb1d5782 100644 --- a/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditor.Designer.cs +++ b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditor.Designer.cs @@ -77,13 +77,13 @@ this.findToolStripMenuItem.Text = "Find"; this.findToolStripMenuItem.Click += new System.EventHandler(this.findToolStripMenuItem_Click); // - // HexEditor + // HexEditor2 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.hexBox1); this.Controls.Add(this.stContextMenuStrip1); - this.Name = "HexEditor"; + this.Name = "HexEditor2"; this.Size = new System.Drawing.Size(529, 454); this.stContextMenuStrip1.ResumeLayout(false); this.stContextMenuStrip1.PerformLayout(); diff --git a/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditor.cs b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditor.cs index fd1a0a11..a184858b 100644 --- a/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditor.cs +++ b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditor.cs @@ -11,10 +11,38 @@ using Be.Windows.Forms; namespace Switch_Toolbox.Library.Forms { - public partial class HexEditor : UserControl + public partial class HexEditor : STUserControl { FindOptions _findOptions = new FindOptions(); + public HexEditor() + { + InitializeComponent(); + + hexBox1.BackColor = FormThemes.BaseTheme.FormBackColor; + hexBox1.ForeColor = FormThemes.BaseTheme.FormForeColor; + hexBox1.SelectionBackColor = FormThemes.BaseTheme.FormContextMenuSelectColor; + hexBox1.SelectionForeColor = FormThemes.BaseTheme.FormForeColor; + } + + public override void OnControlClosing() + { + Cleanup(); + } + + private void Cleanup() + { + if (hexBox1.ByteProvider != null) + { + hexBox1.ByteProvider.DeleteBytes(0, hexBox1.ByteProvider.Length); + + IDisposable byteProvider = hexBox1.ByteProvider as IDisposable; + if (byteProvider != null) + byteProvider.Dispose(); + hexBox1.ByteProvider = null; + } + } + public bool EnableMenuBar { set @@ -30,18 +58,12 @@ namespace Switch_Toolbox.Library.Forms } } - public HexEditor() - { - InitializeComponent(); - - hexBox1.BackColor = FormThemes.BaseTheme.FormBackColor; - hexBox1.ForeColor = FormThemes.BaseTheme.FormForeColor; - hexBox1.SelectionBackColor = FormThemes.BaseTheme.FormContextMenuSelectColor; - hexBox1.SelectionForeColor = FormThemes.BaseTheme.FormForeColor; - } public void LoadData(byte[] data) { - hexBox1.ByteProvider = new DynamicByteProvider(data); + Cleanup(); + + IByteProvider provider = new DynamicByteProvider(data); + hexBox1.ByteProvider = provider; } private void findToolStripMenuItem_Click(object sender, EventArgs e) diff --git a/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.Designer.cs b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.Designer.cs new file mode 100644 index 00000000..fc404bcb --- /dev/null +++ b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.Designer.cs @@ -0,0 +1,56 @@ +namespace Switch_Toolbox.Library.Forms.Old +{ + partial class HexEditor + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.stPanel1 = new Switch_Toolbox.Library.Forms.STPanel(); + this.SuspendLayout(); + // + // stPanel1 + // + this.stPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.stPanel1.Location = new System.Drawing.Point(0, 0); + this.stPanel1.Name = "stPanel1"; + this.stPanel1.Size = new System.Drawing.Size(529, 454); + this.stPanel1.TabIndex = 2; + // + // HexEditor + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.stPanel1); + this.Name = "HexEditor"; + this.Size = new System.Drawing.Size(529, 454); + this.ResumeLayout(false); + + } + + #endregion + private STPanel stPanel1; + } +} diff --git a/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.cs b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.cs new file mode 100644 index 00000000..07af25e2 --- /dev/null +++ b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.ComponentModel.Design; +using System.Windows.Forms; +using Be.Windows.Forms; + +namespace Switch_Toolbox.Library.Forms.Old +{ + public partial class HexEditor : STUserControl + { + FindOptions _findOptions = new FindOptions(); + ByteViewer ByteViewer; + + public HexEditor() + { + InitializeComponent(); + + ByteViewer = new ByteViewer(); + ByteViewer.BackColor = FormThemes.BaseTheme.FormBackColor; + ByteViewer.ForeColor = FormThemes.BaseTheme.FormForeColor; + + ByteViewer.Dock = DockStyle.Fill; + stPanel1.Controls.Add(ByteViewer); + } + + public override void OnControlClosing() + { + Cleanup(); + ByteViewer.Dispose(); + } + + private void Cleanup() + { + + } + + + public void LoadData(byte[] data) + { + Cleanup(); + ByteViewer.SetBytes(data); + } + + private void findToolStripMenuItem_Click(object sender, EventArgs e) + { + + } + } +} diff --git a/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.resx b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/Switch_Toolbox_Library/Forms/Editors/HexEditor/HexEditorNew.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Switch_Toolbox_Library/Forms/Editors/Object Editor/ObjectEditor.cs b/Switch_Toolbox_Library/Forms/Editors/Object Editor/ObjectEditor.cs index 47ad35ba..1f7ce2f3 100644 --- a/Switch_Toolbox_Library/Forms/Editors/Object Editor/ObjectEditor.cs +++ b/Switch_Toolbox_Library/Forms/Editors/Object Editor/ObjectEditor.cs @@ -114,52 +114,63 @@ namespace Switch_Toolbox.Library.Forms { var rootText = root.Text; var rootTextLength = rootText.Length; - var nodeStrings = archiveFile.Files; - foreach (var node in nodeStrings) + var nodeFiles = archiveFile.Files; + if (nodeFiles.Count() > 400) { - string nodeString = node.FileName; - - var roots = nodeString.Split(new char[] { '/' }, - StringSplitOptions.RemoveEmptyEntries); - - // The initial parent is the root node - var parentNode = root; - var sb = new StringBuilder(rootText, nodeString.Length + rootTextLength); - for (int rootIndex = 0; rootIndex < roots.Length; rootIndex++) + foreach (var node in nodeFiles) { - // Build the node name - var parentName = roots[rootIndex]; - sb.Append("/"); - sb.Append(parentName); - var nodeName = sb.ToString(); + ArchiveFileWrapper wrapperFile = new ArchiveFileWrapper(node.FileName, node, archiveFile); + root.Nodes.Add(wrapperFile); + } + } + else + { + foreach (var node in nodeFiles) + { + string nodeString = node.FileName; - // Search for the node - var index = parentNode.Nodes.IndexOfKey(nodeName); - if (index == -1) + var roots = nodeString.Split(new char[] { '/' }, + StringSplitOptions.RemoveEmptyEntries); + + // The initial parent is the root node + var parentNode = root; + var sb = new StringBuilder(rootText, nodeString.Length + rootTextLength); + for (int rootIndex = 0; rootIndex < roots.Length; rootIndex++) { - // Node was not found, add it + // Build the node name + var parentName = roots[rootIndex]; + sb.Append("/"); + sb.Append(parentName); + var nodeName = sb.ToString(); - var folder = new ArchiveFolderNodeWrapper(parentName, archiveFile); - - if (rootIndex == roots.Length - 1) + // Search for the node + var index = parentNode.Nodes.IndexOfKey(nodeName); + if (index == -1) { - ArchiveFileWrapper wrapperFile = new ArchiveFileWrapper(parentName, node, archiveFile); - wrapperFile.Name = nodeName; - parentNode.Nodes.Add(wrapperFile); - parentNode = wrapperFile; + // Node was not found, add it + + var folder = new ArchiveFolderNodeWrapper(parentName, archiveFile); + + if (rootIndex == roots.Length - 1) + { + ArchiveFileWrapper wrapperFile = new ArchiveFileWrapper(parentName, node, archiveFile); + wrapperFile.Name = nodeName; + parentNode.Nodes.Add(wrapperFile); + parentNode = wrapperFile; + } + else + { + folder.Name = nodeName; + parentNode.Nodes.Add(folder); + parentNode = folder; + } } else { - folder.Name = nodeName; - parentNode.Nodes.Add(folder); - parentNode = folder; + // Node was found, set that as parent and continue + parentNode = parentNode.Nodes[index]; } } - else - { - // Node was found, set that as parent and continue - parentNode = parentNode.Nodes[index]; - } } } } diff --git a/Switch_Toolbox_Library/Interfaces/IArchiveFile.cs b/Switch_Toolbox_Library/Interfaces/IArchiveFile.cs index 1afc8b12..94181cd2 100644 --- a/Switch_Toolbox_Library/Interfaces/IArchiveFile.cs +++ b/Switch_Toolbox_Library/Interfaces/IArchiveFile.cs @@ -40,12 +40,32 @@ namespace Switch_Toolbox.Library public FileType FileDataType = FileType.Default; - public IFileFormat OpenFile() + public virtual IFileFormat OpenFile() { return STFileLoader.OpenFileFormat( IOExtensions.RemoveIllegaleFolderNameCharacters(FileName), FileData, true); } + public bool IsSupportedFileFormat() + { + if (FileData == null || FileData.Length <= 4) + return false; + + using (var stream = new MemoryStream(FileData)) + { + foreach (IFileFormat fileFormat in FileManager.GetFileFormats()) + { + fileFormat.FileName = FileName; + if (fileFormat.Identify(stream)) + return true; + } + + + return false; + } + } + + public virtual void Replace() { string fileName = Path.GetFileName(FileName.RemoveIllegaleFileNameCharacters()); diff --git a/Switch_Toolbox_Library/Switch_Toolbox_Library.csproj b/Switch_Toolbox_Library/Switch_Toolbox_Library.csproj index e08541e1..f9782592 100644 --- a/Switch_Toolbox_Library/Switch_Toolbox_Library.csproj +++ b/Switch_Toolbox_Library/Switch_Toolbox_Library.csproj @@ -35,6 +35,9 @@ 4 true + + false + ..\Toolbox\Lib\AssimpNet.dll @@ -224,6 +227,7 @@ + UserControl @@ -370,6 +374,12 @@ AudioPlayer.cs + + UserControl + + + HexEditorNew.cs + UserControl @@ -780,6 +790,9 @@ CubeMapFaceCreator.cs + + HexEditorNew.cs + HexEditor.cs diff --git a/Switch_Toolbox_Library/Util/Util.cs b/Switch_Toolbox_Library/Util/Util.cs index 7cc96476..bc5275fc 100644 --- a/Switch_Toolbox_Library/Util/Util.cs +++ b/Switch_Toolbox_Library/Util/Util.cs @@ -6,6 +6,7 @@ using System.Runtime.Serialization.Formatters.Binary; using System.Drawing; using OpenTK; using System.Reflection; +using Switch_Toolbox.Library.IO; namespace Switch_Toolbox.Library { @@ -135,6 +136,16 @@ namespace Switch_Toolbox.Library } return rv; } + + public static byte[] SubArray(Stream data, uint offset, uint length) + { + using (var reader = new FileReader(data)) + { + reader.Position = offset; + return reader.ReadBytes((int)length); + } + } + public static byte[] SubArray(byte[] data, uint offset, uint length) { return data.Skip((int)offset).Take((int)length).ToArray(); diff --git a/Toolbox/Properties/app.manifest b/Toolbox/Properties/app.manifest index 60eec770..66981ed7 100644 --- a/Toolbox/Properties/app.manifest +++ b/Toolbox/Properties/app.manifest @@ -20,7 +20,7 @@ - +