Update to TRPAK Implementation (#546)
* Move TRPAK up the list of Fileformats
prevents false detections of some of the Archives as other File Formats
* add best guess for Paths
if all known paths are the same add that one path to all other Files
* Revert "Move TRPAK up the list of Fileformats"
This reverts commit a1c0c2d630
.
* Move TRPAK up the list of Fileformats
this time dont reformat the whole Class
* Added Quick access
Added Quick access Folders in the same style as GFPAK for all Texture Files and all Model Files
* cleanup and set some ImageKeys
* Prefer BNTX Filenames that mathc the Hash
instead of relying on only getting the filenames from the file itself
This commit is contained in:
parent
6839d90a9b
commit
314a880213
@ -18,11 +18,29 @@ namespace FirstPlugin
|
|||||||
public bool CanRenameFiles => false;
|
public bool CanRenameFiles => false;
|
||||||
public bool CanReplaceFiles => false;
|
public bool CanReplaceFiles => false;
|
||||||
public bool CanSave { get; set; } = false;
|
public bool CanSave { get; set; } = false;
|
||||||
|
|
||||||
|
public Dictionary<string, string> CategoryLookup
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ ".bntx", "Textures" },
|
||||||
|
{ ".trmbf", "Models" },
|
||||||
|
{ ".trmdl", "Models" },
|
||||||
|
{ ".trmsh", "Models" },
|
||||||
|
{ ".trmtr", "Models" },
|
||||||
|
{ ".trskl", "Models" },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string[] Description { get; set; } = new string[] { "tr Package" };
|
public string[] Description { get; set; } = new string[] { "tr Package" };
|
||||||
public string[] Extension { get; set; } = new string[] { "*.trpak" };
|
public string[] Extension { get; set; } = new string[] { "*.trpak" };
|
||||||
public string FileName { get; set; }
|
public string FileName { get; set; }
|
||||||
public string FilePath { get; set; }
|
public string FilePath { get; set; }
|
||||||
public IEnumerable<ArchiveFileInfo> Files { get; set; }
|
public List<ArchiveFileInfo> files { get; set; }
|
||||||
|
public IEnumerable<ArchiveFileInfo> Files => files;
|
||||||
public FileType FileType { get; set; } = FileType.Archive;
|
public FileType FileType { get; set; } = FileType.Archive;
|
||||||
public IFileInfo IFileInfo { get; set; }
|
public IFileInfo IFileInfo { get; set; }
|
||||||
|
|
||||||
@ -58,12 +76,13 @@ namespace FirstPlugin
|
|||||||
public void Load(Stream stream)
|
public void Load(Stream stream)
|
||||||
{
|
{
|
||||||
GFPAKHashCache.EnsureHashCache();
|
GFPAKHashCache.EnsureHashCache();
|
||||||
Files = new List<ArchiveFileInfo>();
|
files = new List<ArchiveFileInfo>();
|
||||||
FlatBuffers.TRPAK.TRPAK trpak = FlatBuffers.TRPAK.TRPAK.GetRootAsTRPAK(new FlatBuffers.ByteBuffer(stream.ToBytes()));
|
FlatBuffers.TRPAK.TRPAK trpak = FlatBuffers.TRPAK.TRPAK.GetRootAsTRPAK(new FlatBuffers.ByteBuffer(stream.ToBytes()));
|
||||||
if (trpak.FilesLength != trpak.HashesLength)
|
if (trpak.FilesLength != trpak.HashesLength)
|
||||||
{
|
{
|
||||||
throw new Exception("not the same amount of Hashes and File Entries in Trpak Container");
|
throw new Exception("not the same amount of Hashes and File Entries in Trpak Container");
|
||||||
}
|
}
|
||||||
|
List<string> paths = new List<string>();
|
||||||
for (int i = 0; i < trpak.FilesLength; i++)
|
for (int i = 0; i < trpak.FilesLength; i++)
|
||||||
{
|
{
|
||||||
FlatBuffers.TRPAK.File? file = trpak.Files(i);
|
FlatBuffers.TRPAK.File? file = trpak.Files(i);
|
||||||
@ -84,10 +103,72 @@ namespace FirstPlugin
|
|||||||
}
|
}
|
||||||
AFI.FileData = FileData;
|
AFI.FileData = FileData;
|
||||||
AFI.Name = GetName(hash, FileData);
|
AFI.Name = GetName(hash, FileData);
|
||||||
|
if (AFI.Name.Contains("/"))
|
||||||
|
{
|
||||||
|
string tmppath = System.IO.Path.GetDirectoryName(AFI.Name);
|
||||||
|
if (!paths.Contains(tmppath)) paths.Add(tmppath);
|
||||||
|
}
|
||||||
AFI.FileName = AFI.Name;
|
AFI.FileName = AFI.Name;
|
||||||
((List<ArchiveFileInfo>)Files).Add(AFI);
|
files.Add(AFI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (paths.Count == 1)
|
||||||
|
{
|
||||||
|
string path = paths[0].Replace("\\", "/");
|
||||||
|
foreach (var f in files)
|
||||||
|
{
|
||||||
|
if (!f.Name.Contains("/"))
|
||||||
|
{
|
||||||
|
f.Name = Path.Combine(path, f.Name).Replace("\\", "/");
|
||||||
|
f.FileName = f.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode node = new QuickAccessFolder(this, "Quick access");
|
||||||
|
Nodes.Add(node);
|
||||||
|
Dictionary<string, TreeNode> folders = new Dictionary<string, TreeNode>();
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
string ext = Utils.GetExtension(file.FileName);
|
||||||
|
string folderName = "Other";
|
||||||
|
if (CategoryLookup.ContainsKey(ext))
|
||||||
|
folderName = CategoryLookup[ext];
|
||||||
|
|
||||||
|
if (!folders.ContainsKey(folderName))
|
||||||
|
{
|
||||||
|
TreeNode folder = new GFPAK.QuickAccessFileFolder(folderName);
|
||||||
|
if (folderName == "Textures")
|
||||||
|
folder = new TextureFolder(this, "Textures");
|
||||||
|
if (folderName == "Models")
|
||||||
|
folder = new GFPAK.QuickAccessFileFolder("Models");
|
||||||
|
|
||||||
|
node.Nodes.Add(folder);
|
||||||
|
folders.Add(folderName, folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = Path.GetFileName(file.FileName);
|
||||||
|
|
||||||
|
string imageKey = "fileBlank";
|
||||||
|
switch (ext)
|
||||||
|
{
|
||||||
|
case ".bntx": imageKey = "bntx"; break;
|
||||||
|
case ".trmdl": imageKey = "model"; break;
|
||||||
|
case ".trskl": imageKey = "bone"; break;
|
||||||
|
case ".trmbf": imageKey = "mesh"; break;
|
||||||
|
case ".trmsh": imageKey = "mesh"; break;
|
||||||
|
case ".trmtr": imageKey = "material"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode fodlerNode = folders[folderName];
|
||||||
|
fodlerNode.Nodes.Add(new QuickAccessFile(name)
|
||||||
|
{
|
||||||
|
Tag = file,
|
||||||
|
ImageKey = imageKey,
|
||||||
|
SelectedImageKey = imageKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
GFPAKHashCache.WriteCache();
|
GFPAKHashCache.WriteCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +179,7 @@ namespace FirstPlugin
|
|||||||
|
|
||||||
public void Unload()
|
public void Unload()
|
||||||
{
|
{
|
||||||
foreach (var file in Files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
if (file.FileFormat != null)
|
if (file.FileFormat != null)
|
||||||
file.FileFormat.Unload();
|
file.FileFormat.Unload();
|
||||||
@ -106,7 +187,7 @@ namespace FirstPlugin
|
|||||||
file.FileData = null;
|
file.FileData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
((List<ArchiveFileInfo>)Files).Clear();
|
files.Clear();
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
@ -142,7 +223,7 @@ namespace FirstPlugin
|
|||||||
{
|
{
|
||||||
string fileHashName = GFPAKHashCache.GetHashName(fileHash) ?? "";
|
string fileHashName = GFPAKHashCache.GetHashName(fileHash) ?? "";
|
||||||
string ext = FindMatch(Data, fileHashName);
|
string ext = FindMatch(Data, fileHashName);
|
||||||
if (ext == ".bntx" || ext == ".bfres" || ext == ".bnsh" || ext == ".bfsha")
|
if ((ext == ".bntx" && fileHashName == "") || ext == ".bfres" || ext == ".bnsh" || ext == ".bfsha")
|
||||||
{
|
{
|
||||||
string fileName = GetBinaryHeaderName(Data);
|
string fileName = GetBinaryHeaderName(Data);
|
||||||
//Check for matches for shaders
|
//Check for matches for shaders
|
||||||
@ -168,5 +249,136 @@ namespace FirstPlugin
|
|||||||
return $"{fileHash.ToString("X")}{ext}";
|
return $"{fileHash.ToString("X")}{ext}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class TextureFolder : TreeNodeCustom, IContextMenuNode
|
||||||
|
{
|
||||||
|
private IArchiveFile ArchiveFile;
|
||||||
|
private bool HasExpanded = false;
|
||||||
|
private List<STGenericTexture> Textures = new List<STGenericTexture>();
|
||||||
|
|
||||||
|
public TextureFolder(IArchiveFile archive, string text)
|
||||||
|
{
|
||||||
|
ArchiveFile = archive;
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTexture(string fileName)
|
||||||
|
{
|
||||||
|
BNTX bntx = BNTX.CreateBNTXFromTexture(fileName);
|
||||||
|
var mem = new MemoryStream();
|
||||||
|
bntx.Save(mem);
|
||||||
|
|
||||||
|
string filePath = fileName;
|
||||||
|
|
||||||
|
ArchiveFile.AddFile(new ArchiveFileInfo()
|
||||||
|
{
|
||||||
|
FileData = mem.ToArray(),
|
||||||
|
FileFormat = bntx,
|
||||||
|
FileName = filePath,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual ToolStripItem[] GetContextMenuItems()
|
||||||
|
{
|
||||||
|
List<ToolStripItem> Items = new List<ToolStripItem>();
|
||||||
|
Items.Add(new ToolStripMenuItem("Export All", null, ExportAllAction, Keys.Control | Keys.E));
|
||||||
|
return Items.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadTextures()
|
||||||
|
{
|
||||||
|
if (HasExpanded) return;
|
||||||
|
|
||||||
|
List<TreeNode> subNodes = new List<TreeNode>();
|
||||||
|
|
||||||
|
foreach (TreeNode node in Nodes)
|
||||||
|
{
|
||||||
|
var file = (ArchiveFileInfo)node.Tag;
|
||||||
|
if (file.FileFormat == null)
|
||||||
|
file.FileFormat = file.OpenFile();
|
||||||
|
|
||||||
|
BNTX bntx = file.FileFormat as BNTX;
|
||||||
|
foreach (var tex in bntx.Textures.Values)
|
||||||
|
{
|
||||||
|
tex.OnTextureDeleted += OnTextureDeleted;
|
||||||
|
//Set tree key for deletion
|
||||||
|
tex.Name = tex.Text;
|
||||||
|
tex.Tag = file;
|
||||||
|
var texNode = new TreeNode(tex.Text);
|
||||||
|
texNode.Tag = tex;
|
||||||
|
texNode.ImageKey = tex.ImageKey;
|
||||||
|
texNode.SelectedImageKey = tex.SelectedImageKey;
|
||||||
|
subNodes.Add(texNode);
|
||||||
|
Textures.Add(tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Nodes.Clear();
|
||||||
|
Nodes.AddRange(subNodes.ToArray());
|
||||||
|
|
||||||
|
HasExpanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnExpand()
|
||||||
|
{
|
||||||
|
LoadTextures();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportAllAction(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
LoadTextures();
|
||||||
|
|
||||||
|
List<string> Formats = new List<string>();
|
||||||
|
Formats.Add("Microsoft DDS (.dds)");
|
||||||
|
Formats.Add("Portable Graphics Network (.png)");
|
||||||
|
Formats.Add("Joint Photographic Experts Group (.jpg)");
|
||||||
|
Formats.Add("Bitmap Image (.bmp)");
|
||||||
|
Formats.Add("Tagged Image File Format (.tiff)");
|
||||||
|
|
||||||
|
FolderSelectDialog sfd = new FolderSelectDialog();
|
||||||
|
|
||||||
|
if (sfd.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
string folderPath = sfd.SelectedPath;
|
||||||
|
|
||||||
|
BatchFormatExport form = new BatchFormatExport(Formats);
|
||||||
|
if (form.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
foreach (STGenericTexture tex in Textures)
|
||||||
|
{
|
||||||
|
if (form.Index == 0)
|
||||||
|
tex.SaveDDS(folderPath + '\\' + tex.Text + ".dds");
|
||||||
|
else if (form.Index == 1)
|
||||||
|
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".png");
|
||||||
|
else if (form.Index == 2)
|
||||||
|
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".jpg");
|
||||||
|
else if (form.Index == 3)
|
||||||
|
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".bmp");
|
||||||
|
else if (form.Index == 4)
|
||||||
|
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".tiff");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTextureDeleted(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var tex = (TextureData)sender;
|
||||||
|
foreach (var file in ArchiveFile.Files)
|
||||||
|
{
|
||||||
|
if (file.FileFormat != null && file.FileFormat is BNTX)
|
||||||
|
{
|
||||||
|
var bntx = (BNTX)file.FileFormat;
|
||||||
|
if (bntx.Textures.ContainsKey(tex.Text))
|
||||||
|
{
|
||||||
|
bntx.RemoveTexture(tex);
|
||||||
|
bntx.Unload();
|
||||||
|
ArchiveFile.DeleteFile(file);
|
||||||
|
Nodes.RemoveByKey(tex.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -350,6 +350,7 @@ namespace FirstPlugin
|
|||||||
Formats.Add(typeof(BTI));
|
Formats.Add(typeof(BTI));
|
||||||
Formats.Add(typeof(TXE));
|
Formats.Add(typeof(TXE));
|
||||||
Formats.Add(typeof(SARC));
|
Formats.Add(typeof(SARC));
|
||||||
|
Formats.Add(typeof(TRPAK));
|
||||||
Formats.Add(typeof(BNTX));
|
Formats.Add(typeof(BNTX));
|
||||||
Formats.Add(typeof(BEA));
|
Formats.Add(typeof(BEA));
|
||||||
Formats.Add(typeof(BYAML));
|
Formats.Add(typeof(BYAML));
|
||||||
@ -460,7 +461,6 @@ namespace FirstPlugin
|
|||||||
Formats.Add(typeof(MTXT));
|
Formats.Add(typeof(MTXT));
|
||||||
Formats.Add(typeof(NKN));
|
Formats.Add(typeof(NKN));
|
||||||
Formats.Add(typeof(MetroidDreadLibrary.BSMAT));
|
Formats.Add(typeof(MetroidDreadLibrary.BSMAT));
|
||||||
Formats.Add(typeof(TRPAK));
|
|
||||||
|
|
||||||
//Formats.Add(typeof(XLINK_FILE));
|
//Formats.Add(typeof(XLINK_FILE));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user