private void treeView_AfterCollapse(object sender, TreeViewEventArgs e) { if (e.Node == null) { return; } EntryTreeNode node = (EntryTreeNode)e.Node; BeginMarquee(); if (node.Type == EntryTreeNodeType.FORGE) { node.Nodes.Clear(); // remove the entry nodes treeView.Refresh(); node.Nodes.Add(new EntryTreeNode()); // add a placeholder child node } else if (node.Type == EntryTreeNodeType.ENTRY) { node.Nodes.Clear(); // remove the subentry nodes treeView.Refresh(); node.Nodes.Add(new EntryTreeNode()); // add a placeholder child node } EndMarquee(); }
private void treeView_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { EntryTreeNode node = (EntryTreeNode)treeView.GetNodeAt(e.Location); if (node == null || node.Tag == null) { return; } string text = node.Text; string tag = (string)node.Tag; if (tag.EndsWith(".forge")) // forge file { UpdateContextMenu(false, true); } else // forge entry/subentry { // forge subentry if (tag.Contains(FORGE_ENTRY_IDENTIFIER) && !tag.Contains(FORGE_SUBENTRY_IDENTIFIER)) { UpdateContextMenu(true, false); } else { UpdateContextMenu(false, false); } } } }
private void extractAllToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.Forge; if (forge != null && forge.FileEntries.Length > 0) { using (FolderBrowserDialog dialog = new FolderBrowserDialog()) { if (dialog.ShowDialog() == DialogResult.OK) { BeginMarquee(); Parallel.ForEach(forge.FileEntries, (fe) => { string name = fe.NameTable.Name; byte[] data = forge.GetRawData(fe); File.WriteAllBytes(Path.Combine(dialog.SelectedPath, name), data); }); EndMarquee(); MessageBox.Show($"Extracted all of {forge.Name}.", "Done"); } } } }
// end Datafile // Forge private void createFilelistToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.Forge; if (forge != null) { string filelist = forge.CreateFilelist(); if (filelist.Length > 0) { using (SaveFileDialog dialog = new SaveFileDialog()) { dialog.FileName = $"{forge.Name}-filelist.txt"; dialog.Filter = "Text files|*.txt|All files|*.*"; if (dialog.ShowDialog() == DialogResult.OK) { File.WriteAllText(dialog.FileName, filelist); MessageBox.Show("Created filelist.", "Done"); } } } } }
// no need to convert, simply copy the file private void saveAsDDSToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode.Parent; string text = node.Text; string dds = ""; if (File.Exists($"{Helpers.GetTempPath(text)}.dds")) { dds = $"{Helpers.GetTempPath(text)}.dds"; } else if (File.Exists($"{Helpers.GetTempPath(text)}_TopMip_0.dds")) { dds = $"{Helpers.GetTempPath(text)}_TopMip_0.dds"; } else if (File.Exists($"{Helpers.GetTempPath(text)}_Mip0.dds")) { dds = $"{Helpers.GetTempPath(text)}_Mip0.dds"; } if (!string.IsNullOrEmpty(dds)) { saveFileDialog.FileName = Path.GetFileName(dds); if (saveFileDialog.ShowDialog() == DialogResult.OK) { File.Copy(dds, saveFileDialog.FileName); MessageBox.Show("Saved the texture.", "Success"); } } }
// Datafile private void saveRawDataAsToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.GetForge(); saveFileDialog.FileName = $"{node.Text}.dat"; saveFileDialog.Filter = "Raw Data|*.dat|All Files|*.*"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { Forge.FileEntry entry = forge.GetFileEntry(node.Text); byte[] data = forge.GetRawData(entry); try { File.WriteAllBytes(saveFileDialog.FileName, data); } catch (IOException ee) { Console.WriteLine(ee); } finally { MessageBox.Show("Extracted decompressed data.", "Success"); } } }
private void HandlePCKNode(EntryTreeNode node) { SoundpackBrowser browser = new SoundpackBrowser(); browser.LoadPack(node.Path); browser.Show(); }
// end Convert // Datafile private void saveRawDataAsToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.Forge; saveFileDialog.FileName = node.Text; if (saveFileDialog.ShowDialog() == DialogResult.OK) { Forge.FileEntry entry = forge.GetFileEntry(node.Text); byte[] data = forge.GetRawData(entry); try { File.WriteAllBytes(saveFileDialog.FileName, data); } catch (IOException ee) { Console.WriteLine(ee); } finally { MessageBox.Show("Done"); } } }
private void treeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) { if (e.Node == null) { return; } EntryTreeNode node = (EntryTreeNode)e.Node; if (node.Type == EntryTreeNodeType.FORGE) // populate the tree with the forge's entries { List <EntryTreeNode> nodes = new List <EntryTreeNode>(); treeView.Enabled = false; // prevent user-induced damages // work in the background Helpers.DoBackgroundWork(() => { nodes = PopulateForge(node); }, () => { // prevent a crash if (nodes == null) { treeView.Enabled = true; return; } node.Nodes.AddRange(nodes.ToArray()); node.Nodes[0].Remove(); // remove the placeholder node treeView.Enabled = true; MessageBox.Show($"Loaded the entries from {node.Text}.", "Success"); }); } else if (node.Type == EntryTreeNodeType.ENTRY) // populate with subentries (resource types) { List <EntryTreeNode> nodes = new List <EntryTreeNode>(); treeView.Enabled = false; // prevent user-induced damages // work in the background Helpers.DoBackgroundWork(() => { nodes = PopulateEntry(node); }, () => { // prevent a crash if (nodes == null) { treeView.Enabled = true; return; } node.Nodes.AddRange(nodes.ToArray()); node.Nodes[0].Remove(); // remove the placeholder node treeView.Enabled = true; MessageBox.Show($"Loaded the subentries from {node.Text}.", "Success"); }); } }
private void PopulateTreeView(string dir, EntryTreeNode parent) { foreach (string file in Directory.GetFileSystemEntries(dir)) { FileInfo info = new FileInfo(file); EntryTreeNode node = new EntryTreeNode { Game = parent.Game, Path = Path.Combine(dir, file), Size = Directory.Exists(file) ? 0 : (int)info.Length, // directories have no size Text = Path.GetFileName(file) }; if (Directory.Exists(file) || Helpers.IsSupportedFile(Path.GetExtension(file))) { // deal with each supported file type if (Helpers.IsSupportedFile(Path.GetExtension(file))) { if (Path.GetExtension(file).Equals(".forge")) // forge { node.Forge = new Forge(file); node.Type = EntryTreeNodeType.FORGE; node.Nodes.Add(new EntryTreeNode()); // used as a placeholder, will be removed later } else if (Path.GetExtension(file).Equals(".pck")) // pck { node.Type = EntryTreeNodeType.PCK; } else if (Path.GetExtension(file).Equals(".png")) // image { node.Type = EntryTreeNodeType.IMAGE; } else if (Regex.Matches(file, @"(.txt|.ini|.log)").Count > 0) // text { node.Type = EntryTreeNodeType.TEXT; } } if (parent != null) { parent.Nodes.Add(node); } else { treeView.Nodes.Add(node); } } // recursively call this function (for directories) if (Directory.Exists(file)) { node.Type = EntryTreeNodeType.DIRECTORY; PopulateTreeView(file, node); } } }
// Convert private void convertToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; string text = node.Text; MessageBox.Show("Expect the conversion feature in Version 1.2.", "Sorry"); }
private List <EntryTreeNode> PopulateForge(EntryTreeNode node) { Forge forge = node.Forge; if (forge == null) { return(null); } // read if only the forge has not been read if (!forge.IsFullyRead()) { if (forge.GetEntryCount() > 20000) { string entries = string.Format("{0:n0}", forge.GetEntryCount()); if (MessageBox.Show($"This .forge contains more than 20,000 entries ({entries} exactly). Blacksmith may freeze while loading or it may not load them at all.\nDo this at your own risk.", "Warning", MessageBoxButtons.YesNo) == DialogResult.Yes) { forge.Read(); } else { return(null); } } else { forge.Read(); } node.Forge = forge; // set again for assurance } // populate the forge tree with its entries List <EntryTreeNode> entryNodes = new List <EntryTreeNode>(); foreach (Forge.FileEntry entry in forge.FileEntries) { EntryTreeNode n = new EntryTreeNode { Game = node.Game, Offset = entry.IndexTable.OffsetToRawDataTable, Path = Path.Combine(node.Path, entry.NameTable.Name), Size = entry.IndexTable.RawDataSize, Text = entry.NameTable.Name, Type = EntryTreeNodeType.ENTRY }; n.Nodes.Add(new EntryTreeNode("")); entryNodes.Add(n); } return(entryNodes); }
private void saveDecompressedDataAsToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.GetForge(); string text = node.Text; byte[] decompressedData = null; BeginMarquee(); Helpers.DoBackgroundWork(() => { Forge.FileEntry entry = forge.GetFileEntry(text); byte[] rawData = forge.GetRawData(entry); decompressedData = Odyssey.ReadFile(rawData); }, () => { EndMarquee(); // failure if (decompressedData.Length == 0 || decompressedData == null) { MessageBox.Show("Could not decompress data.", "Failure"); return; } saveFileDialog.FileName = string.Concat(node.Text, ".", Helpers.ExtensionForGame(node.Game)); saveFileDialog.Filter = $"{Helpers.NameOfGame(node.Game)} Data|*.{Helpers.ExtensionForGame(node.Game)}|All Files|*.*"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { try { File.WriteAllBytes(saveFileDialog.FileName, decompressedData); } catch (IOException ee) { Console.WriteLine(ee); } finally { MessageBox.Show("Done"); } } }); }
private List <EntryTreeNode> PopulateEntry(EntryTreeNode node) { // extract the contents from the forge Forge forge = node.GetForge(); byte[] data = forge.GetRawData(node.Offset, node.Size); // decompress string file = $"{node.Text}.{Helpers.ExtensionForGame(node.Game)}"; if (node.Game == Game.ODYSSEY) { Helpers.WriteToFile(file, Odyssey.ReadFile(data), true); } else if (node.Game == Game.ORIGINS) { Helpers.WriteToFile(file, Odyssey.ReadFile(data), true); } else if (node.Game == Game.STEEP) { Helpers.WriteToFile(file, Steep.ReadFile(data), true); } // path will hold the file name node.Path = file; // get resource locations and create nodes List <EntryTreeNode> nodes = new List <EntryTreeNode>(); using (Stream stream = new FileStream(Helpers.GetTempPath(file), FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader reader = new BinaryReader(stream)) { Helpers.ResourceLocation[] locations = Helpers.LocateResourceIdentifiers(reader); foreach (Helpers.ResourceLocation location in locations) { nodes.Add(new EntryTreeNode { Game = node.Game, Path = file, ResourceType = location.Type, Text = location.Type.ToString(), Type = EntryTreeNodeType.SUBENTRY }); } } } return(nodes); }
private void treeView_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { EntryTreeNode node = (EntryTreeNode)treeView.GetNodeAt(e.Location); EntryTreeNode sNode = (EntryTreeNode)treeView.SelectedNode; if (node == null || node.Tag == null || sNode == null) { treeNodeContextMenuStrip.Close(); return; } string text = node.Text; string tag = (string)node.Tag; // if the user right-clicked on a game folder node, close the context menu if (node == odysseyNode || node == originsNode || node == steepNode || sNode == odysseyNode || sNode == originsNode || sNode == steepNode) { treeNodeContextMenuStrip.Close(); } if (tag.EndsWith(".forge") && node.Nodes.Count > 1) // forge file { UpdateContextMenu(false, false, true, false); } else // forge entry/subentry { // forge entry if (tag.Contains(FORGE_ENTRY_IDENTIFIER) && !tag.Contains(FORGE_SUBENTRY_IDENTIFIER)) { UpdateContextMenu(true, true, false, true); } else { if (text == ResourceType.TEXTURE_MAP.ToString()) { UpdateContextMenu(false, false, false, true); } else { UpdateContextMenu(false, false, false, false); } } } } }
private void treeView_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { EntryTreeNode node = (EntryTreeNode)treeView.GetNodeAt(e.Location); EntryTreeNode sNode = (EntryTreeNode)treeView.SelectedNode; if (node == null || sNode == null) { treeNodeContextMenuStrip.Close(); return; } // if the user right-clicked on a game folder node, close the context menu if (node == odysseyNode || node == originsNode || node == steepNode || sNode == odysseyNode || sNode == originsNode || sNode == steepNode) { treeNodeContextMenuStrip.Close(); } if ((node.Type == EntryTreeNodeType.FORGE && node.Nodes.Count > 1) || (sNode.Type == EntryTreeNodeType.FORGE && sNode.Nodes.Count > 1)) // forge { UpdateContextMenu(false, true, false); } else // forge entry or subentry { if (node.Type == EntryTreeNodeType.ENTRY || sNode.Type == EntryTreeNodeType.ENTRY) // forge entry { UpdateContextMenu(true, false, false); } else if (node.Type == EntryTreeNodeType.SUBENTRY || sNode.Type == EntryTreeNodeType.SUBENTRY) // forge subentry { if (node.ResourceType == ResourceType.TEXTURE_MAP || sNode.ResourceType == ResourceType.TEXTURE_MAP) { UpdateContextMenu(false, false, true); } else { UpdateContextMenu(false, false, false); } } } } }
private void LoadGamesIntoTreeView() { treeView.Nodes.Clear(); // Odyssey odysseyNode = new EntryTreeNode { Game = Game.ODYSSEY, Text = "Assassin's Creed: Odyssey" }; treeView.Nodes.Add(odysseyNode); if (!string.IsNullOrEmpty(Properties.Settings.Default.odysseyPath)) { odysseyNode.Path = Properties.Settings.Default.odysseyPath; PopulateTreeView(Properties.Settings.Default.odysseyPath, odysseyNode); } // Origins originsNode = new EntryTreeNode { Game = Game.ORIGINS, Text = "Assassin's Creed: Origins" }; treeView.Nodes.Add(originsNode); if (!string.IsNullOrEmpty(Properties.Settings.Default.originsPath)) { originsNode.Path = Properties.Settings.Default.originsPath; PopulateTreeView(Properties.Settings.Default.originsPath, originsNode); } // Steep steepNode = new EntryTreeNode { Game = Game.STEEP, Text = "Steep" }; treeView.Nodes.Add(steepNode); if (!string.IsNullOrEmpty(Properties.Settings.Default.steepPath)) { steepNode.Path = Properties.Settings.Default.steepPath; PopulateTreeView(Properties.Settings.Default.steepPath, steepNode); } }
private void treeView_AfterSelect(object sender, TreeViewEventArgs e) { if (e.Node == null) { return; } EntryTreeNode node = (EntryTreeNode)e.Node; // clear the 3D/Image/Text viewers ClearTheViewers(); if (node.Type == EntryTreeNodeType.ENTRY) // forge entry { HandleEntryNode(node); } else if (node.Type == EntryTreeNodeType.SUBENTRY) // forge subentry { HandleSubentryNode(node); } else if (node.Type == EntryTreeNodeType.IMAGE) // image file { HandleImageNode(node); } else if (node.Type == EntryTreeNodeType.PCK) // soundpack { HandlePCKNode(node); } else if (node.Type == EntryTreeNodeType.TEXT) // text file { HandleTextNode(node); } // update the path status label pathStatusLabel.Text = node.Path; // update size status label if (node.Size > -1) { sizeStatusLabel.Text = $"Size: {Helpers.BytesToString(node.Size)}"; } }
private void saveDecompressedDataAsToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.Forge; string text = node.Text; byte[] decompressedData = null; BeginMarquee(); Helpers.DoBackgroundWork(() => { Forge.FileEntry entry = forge.GetFileEntry(text); byte[] rawData = forge.GetRawData(entry); decompressedData = Odyssey.ReadFile(rawData); }, () => { EndMarquee(); saveFileDialog.FileName = $"{node.Text}.dec"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { try { File.WriteAllBytes(saveFileDialog.FileName, decompressedData); } catch (IOException ee) { Console.WriteLine(ee); } finally { MessageBox.Show("Done"); } } }); }
private void HandleSubentryNode(EntryTreeNode node) { if (node.ResourceType == ResourceType.MESH) // meshes/models { if (node.Game == Game.ODYSSEY) { // to be implemented } else if (node.Game == Game.ORIGINS) { /*Origins.Submesh[] submeshes = Origins.ExtractModel(Helpers.GetTempPath(node.Path), node, () => * { * Console.WriteLine("EXTRACTED MODEL"); * }); * foreach (Origins.Submesh submesh in submeshes) * { * gl.Meshes.Add(new DynamicMesh(submesh)); * }*/ } else if (node.Game == Game.STEEP) { // to be implemented } } else if (node.ResourceType == ResourceType.TEXTURE_MAP) // texture maps { if (node.Game == Game.ODYSSEY || node.Game == Game.ORIGINS) { Odyssey.ExtractTextureMap(Helpers.GetTempPath(node.Path), node, (string path) => { HandleTextureMap(path); }); } else if (node.Game == Game.STEEP) // Needs string path too { Steep.ExtractTextureMap(Helpers.GetTempPath(node.Path), node, (string path) => { HandleTextureMap(path); }); } } }
public void LoadGamesIntoTreeView() { treeView.Nodes.Clear(); // Odyssey EntryTreeNode odysseyNode = new EntryTreeNode { Text = "Assassin's Creed: Odyssey" }; treeView.Nodes.Add(odysseyNode); if (!string.IsNullOrEmpty(Properties.Settings.Default.odysseyPath)) { PopulateTreeView(Properties.Settings.Default.odysseyPath, odysseyNode); } // Origins EntryTreeNode originsNode = new EntryTreeNode { Text = "Assassin's Creed: Origins" }; treeView.Nodes.Add(originsNode); if (!string.IsNullOrEmpty(Properties.Settings.Default.originsPath)) { PopulateTreeView(Properties.Settings.Default.originsPath, originsNode); } // Steep EntryTreeNode steepNode = new EntryTreeNode { Text = "Steep" }; treeView.Nodes.Add(steepNode); if (!string.IsNullOrEmpty(Properties.Settings.Default.steepPath)) { PopulateTreeView(Properties.Settings.Default.steepPath, steepNode); } }
private void treeView_AfterCollapse(object sender, TreeViewEventArgs e) { if (e.Node == null || e.Node.Tag == null) { return; } EntryTreeNode node = (EntryTreeNode)e.Node; string tag = (string)node.Tag; // delete files from this forge's tree node if (tag.EndsWith(".forge")) { node.Nodes.Clear(); node.Nodes.Add(new EntryTreeNode()); // add an empty tree node } else if (tag.Contains(FORGE_ENTRY_IDENTIFIER)) { //node.Nodes.Clear(); //node.Nodes.Add(new EntryTreeNode()); // add an empty tree node } }
public void PopulateTreeView(string dir, EntryTreeNode parent) { foreach (string file in Directory.GetFileSystemEntries(dir)) { FileInfo info = new FileInfo(file); EntryTreeNode node = new EntryTreeNode { Text = Path.GetFileName(file), Tag = Path.Combine(dir, file), // tree node tags for files contain the file's path, Size = Directory.Exists(file) ? 0 : info.Length, // directories have no size, Game = parent.Game }; if (Directory.Exists(file) || Helpers.IsSupportedFile(Path.GetExtension(file))) { // add an empty tree node to forge tree nodes as a placeholder if (Path.GetExtension(file).Equals(".forge")) { node.Nodes.Add(""); } if (parent != null) { parent.Nodes.Add(node); } else { treeView.Nodes.Add(node); } } // recursively call this function (for directories) if (Directory.Exists(file)) { PopulateTreeView(file, node); } } }
// end Forge // Texture private void convertToAnotherFormatToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode.Parent; string text = node.Text; string tex = ""; if (File.Exists($"{Helpers.GetTempPath(text)}.dds")) { tex = $"{Helpers.GetTempPath(text)}.dds"; } else if (File.Exists($"{Helpers.GetTempPath(text)}_TopMip_0.dds")) { tex = $"{Helpers.GetTempPath(text)}_TopMip_0.dds"; } else if (File.Exists($"{Helpers.GetTempPath(text)}_Mip0.dds")) { tex = $"{Helpers.GetTempPath(text)}_Mip0.dds"; } if (!string.IsNullOrEmpty(tex)) { saveFileDialog.FileName = Path.GetFileNameWithoutExtension(tex); saveFileDialog.Filter = Helpers.TEXTURE_CONVERSION_FORMATS; if (saveFileDialog.ShowDialog() == DialogResult.OK) { Helpers.ConvertDDS(tex, Path.GetDirectoryName(saveFileDialog.FileName), () => { MessageBox.Show("Converted the texture.", "Success"); }, Path.GetExtension(saveFileDialog.FileName).Substring(1)); } } }
private void treeView_AfterSelect(object sender, TreeViewEventArgs e) { if (e.Node == null || e.Node.Tag == null) { return; } EntryTreeNode node = (EntryTreeNode)e.Node; Forge forge = node.Forge; TreeNode parent = (EntryTreeNode)node.Parent; string text = node.Text; string tag = (string)node.Tag; long size = node.Size; ResourceType type = node.ResourceType; // reset the picture box and rich text box // ToDo: empty 3D viewer pictureBox.ImageLocation = ""; richTextBox.Text = ""; if (tag.Contains(".forge")) { if (text.EndsWith(".forge")) // forge file { // dump resources used by currentForge if (currentForge != null) { currentForge.Dump(); } currentForge = new Forge(tag); node.Forge = currentForge; } else // forge entry/subentry { // forge subentry if (tag.Contains(FORGE_ENTRY_IDENTIFIER) && tag.Contains(FORGE_SUBENTRY_IDENTIFIER)) { if (type == ResourceType.TEXTURE_MAP) { string parentText = Helpers.GetTempPath(parent.Text); if (node.Game == Game.ODYSSEY || node.Game == Game.ORIGINS) { Odyssey.ExtractTextureMap(parentText, forge, () => { if (File.Exists($"{Helpers.GetTempPath(parent.Text)}.png")) { currentImgPath = $"{Helpers.GetTempPath(parent.Text)}.png"; } else if (File.Exists($"{Helpers.GetTempPath(parent.Text)}_TopMip_0.png")) { currentImgPath = $"{Helpers.GetTempPath(parent.Text)}_TopMip_0.png"; } Invoke(new Action(() => { if (!string.IsNullOrEmpty(currentImgPath)) { UpdatePictureBox(Image.FromFile(currentImgPath)); } zoomDropDownButton.Text = "Zoom Level: 100%"; tabControl.SelectedIndex = 1; })); }); } else { Steep.ExtractTextureMap(parentText, forge, () => { if (File.Exists($"{Helpers.GetTempPath(parent.Text)}.png")) { currentImgPath = $"{Helpers.GetTempPath(parent.Text)}.png"; } else if (File.Exists($"{Helpers.GetTempPath(parent.Text)}_Mip0.png")) { currentImgPath = $"{Helpers.GetTempPath(parent.Text)}_Mip0.png"; } Invoke(new Action(() => { if (!string.IsNullOrEmpty(currentImgPath)) { UpdatePictureBox(Image.FromFile(currentImgPath)); } zoomDropDownButton.Text = "Zoom Level: 100%"; tabControl.SelectedIndex = 1; })); }); } } } } } else if (text.EndsWith(".png")) { pictureBox.Image = Image.FromFile(tag); pictureBox.Refresh(); if (pictureBox.Image != null) { imageDimensStatusLabel.Text = $"Dimensions: {pictureBox.Image.Width}x{pictureBox.Image.Height}"; } tabControl.SelectedIndex = 1; } else if (text.EndsWith(".ini") || text.EndsWith(".txt") || text.EndsWith(".log")) { richTextBox.Text = string.Join("\n", File.ReadAllLines(tag)); tabControl.SelectedIndex = 2; } else if (text.EndsWith(".pck")) { SoundpackBrowser browser = new SoundpackBrowser(); browser.LoadPack(tag); browser.Show(); } // update path status label if (!tag.Contains(FORGE_ENTRY_IDENTIFIER)) { pathStatusLabel.Text = tag; } // update size status label if (size > -1) { sizeStatusLabel.Text = $"Size: {Helpers.BytesToString(size)}"; } }
private void treeView_AfterSelect(object sender, TreeViewEventArgs e) { if (e.Node == null || e.Node.Tag == null) { return; } EntryTreeNode node = (EntryTreeNode)e.Node; TreeNode parent = (EntryTreeNode)node.Parent; string text = node.Text; string tag = (string)node.Tag; long size = node.Size; ResourceType type = node.ResourceType; Console.WriteLine(tag); // reset the picture box and rich text box // ToDo: empty 3D viewer pictureBox.ImageLocation = ""; richTextBox.Text = ""; // retrieve the file names the forge if (tag.Contains(".forge")) { if (text.EndsWith(".forge")) // forge file { // dump resources used by currentForge if (currentForge != null) { currentForge.Dump(); } currentForge = new Forge(tag); } else // forge entry/subentry { // forge subentry if (tag.Contains(FORGE_ENTRY_IDENTIFIER) && tag.Contains(FORGE_SUBENTRY_IDENTIFIER)) { /*if (type == ResourceType.MIPMAP) * { * string parentText = Helpers.GetTempPath(parent.Text); * string dds = Odyssey.ExtractMipMap(parentText); * tabControl.SelectedIndex = 1; * * //scene.DisplayTexture(dds); * } * else*/if (type == ResourceType.TEXTURE_MAP) { string parentText = Helpers.GetTempPath(parent.Text); Odyssey.ExtractTextureMap(parentText, currentForge); } tabControl.SelectedIndex = 1; } } } else if (node.Text.EndsWith(".png")) { pictureBox.ImageLocation = tag; tabControl.SelectedIndex = 1; } else if (node.Text.EndsWith(".ini") || node.Text.EndsWith(".txt")) { richTextBox.Text = string.Join("\n", File.ReadAllLines(tag)); tabControl.SelectedIndex = 2; } // update path status label pathStatusLabel.Text = tag; // update size status label if (size > -1) { sizeStatusLabel.Text = "Size: " + Helpers.BytesToString(size); } // update the status labels for the picture box if (pictureBox.Image != null) { imageDimensStatusLabel.Text = string.Format("Dimensions: {0}x{1}", pictureBox.Image.Width, pictureBox.Image.Height); } }
private void HandleImageNode(EntryTreeNode node) { currentImgPath = node.Path; pictureBox.Image = Image.FromFile(currentImgPath); tabControl.SelectedIndex = 1; }
private void treeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) { if (e.Node == null || e.Node.Tag == null) { return; } EntryTreeNode curNode = (EntryTreeNode)e.Node; string text = curNode.Text; string tag = (string)curNode.Tag; // a forge file if (tag.EndsWith(".forge")) { // dump resources used by currentForge if (currentForge != null) { currentForge.Dump(); } currentForge = new Forge(tag); Helpers.DoBackgroundWork(() => { currentForge.Read(); }, () => { // show message if there are over 10000 files in the forge if (currentForge.FileEntries.Length > 10000 && MessageBox.Show("This forge file contains more " + "than 10000 entries (" + currentForge.FileEntries.Length + " exactly). Loading all these " + "entries will take a while and Blacksmith will freeze.\n\nContinue?", "Large forge file!", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } // delete the empty tree node e.Node.Nodes.RemoveAt(0); // show and update the progress bar toolStripProgressBar.Visible = true; toolStripProgressBar.Value = 0; toolStripProgressBar.Maximum = currentForge.FileEntries.Length; // load entries into this forge's tree node for (int i = 0; i < currentForge.FileEntries.Length; i++) { string name = currentForge.FileEntries[i].NameTable.Name; EntryTreeNode node = new EntryTreeNode { Text = name, Tag = string.Format("{0}{1}{2}", curNode.Tag, FORGE_ENTRY_IDENTIFIER, name), // set the tag of this file's tree node Size = currentForge.FileEntries[i].IndexTable.RawDataSize }; node.Nodes.Add(new EntryTreeNode()); // add empty node (for entry's contents) curNode.Nodes.Add(node); toolStripProgressBar.Value++; } // reset and hide the progress bar toolStripProgressBar.Value = toolStripProgressBar.Maximum = 0; toolStripProgressBar.Visible = false; }); } // forge entry else if (tag.Contains(FORGE_ENTRY_IDENTIFIER) && !tag.Contains(FORGE_SUBENTRY_IDENTIFIER)) { // extract, if the entry has an empty node or if data as a file does not exist if (curNode.Nodes.Count == 1 && curNode.Nodes[0].Text == "" && !File.Exists(Helpers.GetTempPath(text))) { BeginMarquee(); Helpers.DoBackgroundWork(() => { Forge.FileEntry entry = currentForge.GetFileEntry(text); byte[] rawData = currentForge.GetRawData(entry); Helpers.WriteToTempFile(text, rawData); Odyssey.ReadFile(Helpers.GetTempPath(text)); }, () => { EndMarquee(); // remove nodes curNode.Nodes.Clear(); string combined = $"{Helpers.GetTempPath(text)}-combined"; // look for supported resource types using (Stream stream = new FileStream(combined, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader reader = new BinaryReader(stream)) { // create nodes based on located resource types foreach (Helpers.ResourceLocation loc in Helpers.LocateResourceIdentifiers(reader)) { curNode.Nodes.Add(new EntryTreeNode { Text = loc.Type.ToString(), Tag = string.Format("{0}{1}{2}", tag, FORGE_SUBENTRY_IDENTIFIER, loc.Type.ToString()), ResourceType = loc.Type }); } } } }); } } }
private void HandleTextNode(EntryTreeNode node) { richTextBox.Text = File.ReadAllText(node.Path); tabControl.SelectedIndex = 2; }
private void treeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) { if (e.Node == null || e.Node.Tag == null) { return; } EntryTreeNode node = (EntryTreeNode)e.Node; int levels = LevelsDeep(node.FullPath); Forge forge = levels == 1 ? node.Forge : levels == 2 ? ((EntryTreeNode)node.Parent).Forge: ((EntryTreeNode)node.Parent.Parent).Forge; Console.WriteLine(levels + " deep"); string text = node.Text; string tag = (string)node.Tag; if (string.IsNullOrEmpty(text)) { return; } // a forge file if (tag.EndsWith(".forge")) { // dump resources used by currentForge if (currentForge != null) { currentForge.Dump(); } currentForge = new Forge(tag); Helpers.DoBackgroundWork(() => { currentForge.Read(); }, () => { // show message if there are over 10000 files in the forge if (forge.FileEntries.Length > 10000 && MessageBox.Show("This forge file contains more " + "than 10000 entries (" + forge.FileEntries.Length + " exactly). Loading all these " + "entries will take a while and Blacksmith will freeze.\n\nContinue?", "Large forge file!", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } // delete the empty tree node e.Node.Nodes.RemoveAt(0); // show and update the progress bar toolStripProgressBar.Visible = true; toolStripProgressBar.Value = 0; toolStripProgressBar.Maximum = forge.FileEntries.Length; Helpers.DoBackgroundWork(() => { // load entries into this forge's tree node if (!forge.IsFullyRead()) { return; } for (int i = 0; i < forge.FileEntries.Length; i++) { if (forge.FileEntries[i].NameTable == null) { continue; } string name = forge.FileEntries[i].NameTable.Name; EntryTreeNode n = new EntryTreeNode { Text = name, Forge = forge, Tag = $"{node.Tag}{FORGE_ENTRY_IDENTIFIER}{name}", // set the tag of this file's tree node Offset = forge.FileEntries[i].IndexTable.OffsetToRawDataTable, Size = forge.FileEntries[i].IndexTable.RawDataSize, Game = node.Game }; n.Nodes.Add(new EntryTreeNode()); // add empty node (for entry's contents) Invoke(new Action(() => { if (this != null && toolStripProgressBar.Value < 3001) // I recieved an error stating that the progress bar cannot go above 3001 { node.Nodes.Add(n); toolStripProgressBar.Value++; } })); } }, () => { // reset and hide the progress bar toolStripProgressBar.Value = toolStripProgressBar.Maximum = 0; toolStripProgressBar.Visible = false; }); }); } // forge entry else if (tag.Contains(FORGE_ENTRY_IDENTIFIER) && !tag.Contains(FORGE_SUBENTRY_IDENTIFIER)) { // extract, if the entry has an empty node if (node.Nodes.Count == 1 && node.Nodes[0].Text == "") { BeginMarquee(); Helpers.DoBackgroundWork(() => { byte[] rawData = forge.GetRawData(node.Offset, (int)node.Size); Helpers.WriteToFile($"{text}.ext", rawData, true); if (node.Game == Game.ODYSSEY || node.Game == Game.ORIGINS) // temporary, until this Origins no longer works like Odyssey { Odyssey.ReadFile(Helpers.GetTempPath($"{text}.ext")); } else { Steep.ReadFile(Helpers.GetTempPath($"{text}.ext")); } }, () => { EndMarquee(); // remove nodes node.Nodes.Clear(); // look for supported resource types. steep stays out, for now (because it causes crashes). string combined = $"{Helpers.GetTempPath(text)}.dec"; if (File.Exists(combined)) { using (Stream stream = new FileStream(combined, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader reader = new BinaryReader(stream)) { // create nodes based on located resource types foreach (Helpers.ResourceLocation loc in Helpers.LocateResourceIdentifiers(reader)) { node.Nodes.Add(new EntryTreeNode { Text = loc.Type.ToString(), Tag = $"{tag}{FORGE_SUBENTRY_IDENTIFIER}{loc.Type.ToString()}", ResourceType = loc.Type, Game = node.Game }); } } } } }); } } }