Cleanup. Start to impliment texture preview icons in tree

This commit is contained in:
KillzXGaming 2019-08-01 17:47:35 -04:00
parent aa006fd389
commit f4e4afa2f7
41 changed files with 888 additions and 231 deletions

View file

@ -314,6 +314,7 @@ namespace FirstPlugin
{ ".byaml", "byaml" },
{ ".bfres", "bfres" },
{ ".sbfres", "bfres" },
{ ".bflim", "texture" },
{ ".aamp", "aamp" },
};
}

View file

@ -10,7 +10,7 @@ using Toolbox.Library.IO;
namespace FirstPlugin
{
public class CMB : IFileFormat
public class CMB : TreeNodeFile, IFileFormat, ITextureIconLoader
{
public FileType FileType { get; set; } = FileType.Layout;
@ -39,12 +39,46 @@ namespace FirstPlugin
}
public Header header;
STTextureFolder texFolder;
public List<STGenericTexture> IconTextureList { get; set; }
public void Load(System.IO.Stream stream)
{
IconTextureList = new List<STGenericTexture>();
header = new Header();
header.Read(new FileReader(stream));
Text = header.Name;
//Load textures
if (header.SectionData.TextureChunk != null)
{
texFolder = new STTextureFolder("Texture");
Nodes.Add(texFolder);
int texIndex = 0;
foreach (var tex in header.SectionData.TextureChunk.Textures)
{
var texWrapper = new CTXB.TextureWrapper();
texWrapper.Text = $"Texture {texIndex++}";
texWrapper.ImageKey = "texture";
texWrapper.SelectedImageKey = texWrapper.ImageKey;
if (tex.Name != string.Empty)
texWrapper.Text = tex.Name;
texWrapper.Width = tex.Width;
texWrapper.Height = tex.Height;
texWrapper.Format = CTR_3DS.ConvertPICAToGenericFormat(tex.PicaFormat);
texWrapper.ImageData = tex.ImageData;
texFolder.Nodes.Add(texWrapper);
IconTextureList.Add(texWrapper);
}
}
}
public void Unload()
{
@ -67,12 +101,18 @@ namespace FirstPlugin
public CMBVersion Version;
public uint ChunkCount; //Fixed count per game
public uint Unknown;
public SectionData SectionData;
public void Read(FileReader reader)
{
string magic = reader.ReadSignature(4, "cmb ");
uint FileSize = reader.ReadUInt32();
uint ChunkCount = reader.ReadUInt32();
uint Unknown = reader.ReadUInt32();
ChunkCount = reader.ReadUInt32();
Unknown = reader.ReadUInt32();
Name = reader.ReadString(0x10).TrimEnd('\0');
@ -86,8 +126,226 @@ namespace FirstPlugin
else
throw new Exception("Unexpected chunk count! " + ChunkCount);
int chunkIdx = 0x04;
SectionData = new SectionData();
SectionData.Read(reader, this);
}
public void Write(FileWriter writer)
{
writer.WriteSignature("cmb ");
writer.Write(uint.MaxValue); //Reserve space for file size offset
writer.Write(ChunkCount);
writer.Write(Unknown);
writer.WriteString(Name, 0x10);
SectionData.Write(writer, this);
//Write the total file size
using (writer.TemporarySeek(4, System.IO.SeekOrigin.Begin))
{
writer.Write((uint)writer.BaseStream.Length);
}
}
}
public class SectionData
{
public SkeletonChunk SkeletonChunk;
public QuadTreeChunk QuadTreeChunk;
public MaterialChunk MaterialChunk;
public TextureChunk TextureChunk;
public SkeletalMeshChunk SkeletalMeshChunk;
public LUTSChunk LUTSChunk;
public VertexAttributesChunk VertexAttributesChunk;
public void Read(FileReader reader, Header header)
{
uint numIndices = reader.ReadUInt32();
SkeletonChunk = ReadChunkSection<SkeletonChunk>(reader, header);
if (header.Version >= CMBVersion.MM3DS)
QuadTreeChunk = ReadChunkSection<QuadTreeChunk>(reader, header);
MaterialChunk = ReadChunkSection<MaterialChunk>(reader, header);
TextureChunk = ReadChunkSection<TextureChunk>(reader, header);
SkeletalMeshChunk = ReadChunkSection<SkeletalMeshChunk>(reader, header);
LUTSChunk = ReadChunkSection<LUTSChunk>(reader, header);
VertexAttributesChunk = ReadChunkSection<VertexAttributesChunk>(reader, header);
uint indexBufferOffset = reader.ReadUInt32();
uint textureDataOffset = reader.ReadUInt32();
if (header.Version >= CMBVersion.MM3DS)
reader.ReadUInt32(); //Padding?
foreach (var tex in TextureChunk.Textures)
{
reader.SeekBegin(textureDataOffset + tex.DataOffset);
tex.ImageData = reader.ReadBytes((int)tex.ImageSize);
}
}
public void Write(FileWriter writer, Header header)
{
}
}
public class SkeletalMeshChunk : IChunkCommon
{
private const string Magic = "sklm";
public void Read(FileReader reader, Header header)
{
reader.ReadSignature(4, Magic);
uint sectionSize = reader.ReadUInt32();
}
public void Write(FileWriter writer, Header header)
{
writer.WriteSignature(Magic);
writer.Write(uint.MaxValue);//SectionSize
}
}
public class LUTSChunk : IChunkCommon
{
private const string Magic = "luts";
public void Read(FileReader reader, Header header)
{
reader.ReadSignature(4, Magic);
uint sectionSize = reader.ReadUInt32();
}
public void Write(FileWriter writer, Header header)
{
writer.WriteSignature(Magic);
writer.Write(uint.MaxValue);//SectionSize
}
}
public class VertexAttributesChunk : IChunkCommon
{
private const string Magic = "vatr";
public void Read(FileReader reader, Header header)
{
reader.ReadSignature(4, Magic);
uint sectionSize = reader.ReadUInt32();
}
public void Write(FileWriter writer, Header header)
{
writer.WriteSignature(Magic);
writer.Write(uint.MaxValue);//SectionSize
}
}
public class SkeletonChunk : IChunkCommon
{
private const string Magic = "skl ";
public void Read(FileReader reader, Header header)
{
reader.ReadSignature(4, Magic);
uint sectionSize = reader.ReadUInt32();
}
public void Write(FileWriter writer, Header header)
{
writer.WriteSignature(Magic);
writer.Write(uint.MaxValue);//SectionSize
}
}
public class QuadTreeChunk : IChunkCommon
{
private const string Magic = "qtrs";
public void Read(FileReader reader, Header header)
{
reader.ReadSignature(4, Magic);
uint sectionSize = reader.ReadUInt32();
}
public void Write(FileWriter writer, Header header)
{
writer.WriteSignature(Magic);
writer.Write(uint.MaxValue);//SectionSize
}
}
public class MaterialChunk : IChunkCommon
{
private const string Magic = "mats";
public void Read(FileReader reader, Header header)
{
reader.ReadSignature(4, Magic);
uint sectionSize = reader.ReadUInt32();
}
public void Write(FileWriter writer, Header header)
{
writer.WriteSignature(Magic);
writer.Write(uint.MaxValue);//SectionSize
}
}
public class TextureChunk : IChunkCommon
{
private const string Magic = "tex ";
public List<CTXB.Texture> Textures = new List<CTXB.Texture>();
public void Read(FileReader reader, Header header)
{
reader.ReadSignature(4, Magic);
uint sectionSize = reader.ReadUInt32();
uint TextureCount = reader.ReadUInt32();
for (int i = 0; i < TextureCount; i++)
Textures.Add(new CTXB.Texture(reader));
}
public void Write(FileWriter writer, Header header)
{
long pos = writer.Position;
writer.WriteSignature(Magic);
writer.Write(uint.MaxValue);//SectionSize
for (int i = 0; i < Textures.Count; i++)
Textures[i].Write(writer);
//Write the total file size
writer.WriteSectionSizeU32(pos + 4, pos, writer.Position);
}
}
public static T ReadChunkSection<T>(FileReader reader, Header header)
where T : IChunkCommon, new()
{
long pos = reader.Position;
//Read offset and seek it
uint offset = reader.ReadUInt32();
reader.SeekBegin(offset);
//Create chunk instance
T chunk = new T();
chunk.Read(reader, header);
//Seek back and shift 4 from reading offset
reader.SeekBegin(pos + 0x4);
return chunk;
}
public interface IChunkCommon
{
void Read(FileReader reader, Header header);
void Write(FileWriter writer, Header header);
}
}
}

View file

@ -113,6 +113,7 @@ namespace FirstPlugin
Textures.Add(new Texture(reader));
}
}
}
public class Texture
{
@ -127,6 +128,8 @@ namespace FirstPlugin
public CTR_3DS.PICASurfaceFormat PicaFormat;
public byte[] ImageData;
public enum TextureFormat : uint
{
ETC1 = 0x0000675A,
@ -151,11 +154,25 @@ namespace FirstPlugin
Height = reader.ReadUInt16();
TextureFormat Format = reader.ReadEnum<TextureFormat>(true);
DataOffset = reader.ReadUInt32();
Name = reader.LoadString(false, typeof(uint));
Name = reader.ReadString(16).TrimEnd('\0');
PicaFormat = ToPica(Format);
}
public void Write(FileWriter writer)
{
TextureFormat Format = TextureFormat.A8;
writer.Write(ImageSize);
writer.Write(MaxLevel);
writer.Write(Unknown);
writer.Write((ushort)Width);
writer.Write((ushort)Height);
writer.Write(Format, true);
writer.Write(DataOffset);
writer.Write(DataOffset);
}
private static CTR_3DS.PICASurfaceFormat ToPica(TextureFormat format)
{
switch (format)
@ -204,7 +221,8 @@ namespace FirstPlugin
}
}
public TextureWrapper() {
public TextureWrapper()
{
PlatformSwizzle = PlatformSwizzle.Platform_3DS;
}
@ -239,5 +257,4 @@ namespace FirstPlugin
}
}
}
}
}

View file

@ -274,7 +274,7 @@
<Compile Include="FileFormats\HyruleWarriors\G1M.cs" />
<Compile Include="FileFormats\Message\MSBP.cs" />
<Compile Include="FileFormats\Texture\CTPK.cs" />
<Compile Include="FileFormats\Texture\CTXB.cs" />
<Compile Include="FileFormats\Grezzo\CTXB.cs" />
<Compile Include="FileFormats\Texture\TPL.cs" />
<Compile Include="FileFormats\Rom\GCDisk.cs" />
<Compile Include="GL\BMD_Renderer.cs" />
@ -286,6 +286,12 @@
<Compile Include="GUI\BFFNT\BffntEditor.Designer.cs">
<DependentUpon>BffntEditor.cs</DependentUpon>
</Compile>
<Compile Include="GUI\BFLYT\LayoutEditor.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="GUI\BFLYT\LayoutEditor.Designer.cs">
<DependentUpon>LayoutEditor.cs</DependentUpon>
</Compile>
<Compile Include="GUI\BFRES\BatchEditBaseAnimDataForm.cs">
<SubType>Form</SubType>
</Compile>
@ -1007,6 +1013,9 @@
<EmbeddedResource Include="GUI\BFFNT\BffntEditor.resx">
<DependentUpon>BffntEditor.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="GUI\BFLYT\LayoutEditor.resx">
<DependentUpon>LayoutEditor.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="GUI\BFRES\BatchEditBaseAnimDataForm.resx">
<DependentUpon>BatchEditBaseAnimDataForm.cs</DependentUpon>
</EmbeddedResource>

View file

@ -0,0 +1,71 @@
namespace FirstPlugin.LayoutEditor
{
partial class LayoutEditor
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.stMenuStrip1 = new Toolbox.Library.Forms.STMenuStrip();
this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.stMenuStrip1.SuspendLayout();
this.SuspendLayout();
//
// stMenuStrip1
//
this.stMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.editToolStripMenuItem});
this.stMenuStrip1.Location = new System.Drawing.Point(0, 0);
this.stMenuStrip1.Name = "stMenuStrip1";
this.stMenuStrip1.Size = new System.Drawing.Size(836, 24);
this.stMenuStrip1.TabIndex = 0;
this.stMenuStrip1.Text = "stMenuStrip1";
//
// editToolStripMenuItem
//
this.editToolStripMenuItem.Name = "editToolStripMenuItem";
this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20);
this.editToolStripMenuItem.Text = "Edit";
//
// LayoutEditor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.stMenuStrip1);
this.Name = "LayoutEditor";
this.Size = new System.Drawing.Size(836, 518);
this.stMenuStrip1.ResumeLayout(false);
this.stMenuStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Toolbox.Library.Forms.STMenuStrip stMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem;
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FirstPlugin.LayoutEditor
{
public partial class LayoutEditor : UserControl
{
public LayoutEditor()
{
InitializeComponent();
}
}
}

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="stMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View file

@ -356,7 +356,7 @@ namespace FirstPlugin
Formats.Add(typeof(CTXB));
Formats.Add(typeof(G1T));
Formats.Add(typeof(BFLYT));
Formats.Add(typeof(CMB));
//Unfinished wip formats not ready for use
if (Runtime.DEVELOPER_DEBUG_MODE)

View file

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Toolbox.Library
{
public class RGBAPixelDecoder
{
private static byte[] GetComponentsFromPixel(TEX_FORMAT format, int pixel)
{
byte[] comp = new byte[] { 0, 0xFF, 0, 0, 0, 0xFF };
switch (format)
{
case TEX_FORMAT.L8:
comp[2] = (byte)(pixel & 0xFF);
break;
case TEX_FORMAT.L4:
comp[2] = (byte)((pixel & 0xF) * 17);
comp[3] = (byte)(((pixel & 0xF0) >> 4) * 17);
break;
case TEX_FORMAT.LA8:
comp[2] = (byte)(pixel & 0xFF);
comp[3] = (byte)((pixel & 0xFF00) >> 8);
break;
case TEX_FORMAT.R5G5B5_UNORM:
comp[2] = (byte)((pixel & 0x1F) / 0x1F * 0xFF);
comp[3] = (byte)(((pixel & 0x7E0) >> 5) / 0x3F * 0xFF);
comp[4] = (byte)(((pixel & 0xF800) >> 11) / 0x1F * 0xFF);
break;
case TEX_FORMAT.B5G6R5_UNORM:
comp[2] = (byte)(((pixel & 0xF800) >> 11) / 0x1F * 0xFF);
comp[3] = (byte)(((pixel & 0x7E0) >> 5) / 0x3F * 0xFF);
comp[4] = (byte)((pixel & 0x1F) / 0x1F * 0xFF);
break;
}
return comp;
}
//Method from https://github.com/aboood40091/BNTX-Editor/blob/master/formConv.py
public static byte[] Decode(byte[] data, int width, int height, TEX_FORMAT format)
{
uint bpp = STGenericTexture.GetBytesPerPixel(format);
int size = width * height * 4;
byte[] output = new byte[size];
int inPos = 0;
int outPos = 0;
byte[] compSel = new byte[4] {0,1,2,3 };
for (int Y = 0; Y < height; Y++)
{
for (int X = 0; X < width; X++)
{
inPos = (Y * width + X) * (int)bpp;
outPos = (Y * width + X) * 4;
int pixel = 0;
for (int i = 0; i < bpp; i++)
pixel |= data[inPos + i] << (8 * i);
byte[] comp = GetComponentsFromPixel(format, pixel);
output[outPos + 3] = comp[compSel[3]];
output[outPos + 2] = comp[compSel[2]];
output[outPos + 1] = comp[compSel[1]];
output[outPos + 0] = comp[compSel[0]];
}
}
return output;
}
}
}

View file

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
@ -80,10 +80,13 @@ namespace Toolbox.Library
}
}
public class TreeViewCustom : TreeView
{
private readonly Dictionary<int, TreeNode> _treeNodes = new Dictionary<int, TreeNode>();
public List<ITextureIconLoader> TextureIcons = new List<ITextureIconLoader>();
public TreeViewCustom()
{
ReloadImages();
@ -99,13 +102,65 @@ namespace Toolbox.Library
imgList.Images.Add(image);
}
public int ImageWidth = 21;
public int ImageHeight = 21;
public void ReloadImages()
public void ReloadTextureIcons()
{
Thread Thread = new Thread((ThreadStart)(() =>
{
foreach (var textureIconList in TextureIcons)
{
foreach (TreeNode node in textureIconList.IconTextureList)
{
if (node is STGenericTexture)
{
var image = ((STGenericTexture)node).GetBitmap();
AddImageOnThread(image, node);
}
}
}
}));
Thread.Start();
}
public void ReloadTextureIcons(ITextureIconLoader textureIconList)
{
Thread Thread = new Thread((ThreadStart)(() =>
{
foreach (TreeNode node in textureIconList.IconTextureList)
{
if (node is STGenericTexture)
{
var image = ((STGenericTexture)node).GetBitmap();
AddImageOnThread(image, node);
}
}
}));
Thread.Start();
}
public void AddImageOnThread(Image image, TreeNode node)
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate {
// Running on the UI thread
node.ImageIndex = this.ImageList.Images.Count;
node.SelectedImageIndex = node.ImageIndex;
this.ImageList.Images.Add(image);
var dummy = this.ImageList.Handle;
this.Refresh();
image.Dispose();
});
}
}
public void ReloadImages(int Width = 22, int Height = 22)
{
imgList = new ImageList();
imgList.ColorDepth = ColorDepth.Depth32Bit;
imgList.ImageSize = new Size(ImageWidth, ImageHeight);
imgList.ImageSize = new Size(Width, Height);
imgList.Images.Add("folder", Properties.Resources.Folder);
imgList.Images.Add("resource", Properties.Resources.Folder);
imgList.Images.Add("Texture", Properties.Resources.Texture);

View file

@ -5,7 +5,7 @@ using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using GL_EditorFramework.Interfaces;
using GL_EditorFramework.EditorDrawables;
@ -99,6 +99,10 @@ namespace Toolbox.Library.Forms
stPanel1.Controls.Add(ObjectTree);
AddNode((TreeNode)FileFormat);
}
if (FileFormat is ITextureIconLoader) {
ObjectTree.LoadGenericTextureIcons((ITextureIconLoader)FileFormat);
}
}
public void AddIArchiveFile(IFileFormat FileFormat){

View file

@ -32,6 +32,7 @@
this.splitter1 = new System.Windows.Forms.Splitter();
this.stPanel2 = new Toolbox.Library.Forms.STPanel();
this.stPanel1 = new Toolbox.Library.Forms.STPanel();
this.nodeSizeCB = new Toolbox.Library.Forms.STComboBox();
this.stPanel4 = new Toolbox.Library.Forms.STPanel();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.treeViewCustom1 = new Toolbox.Library.TreeViewCustom();
@ -79,6 +80,7 @@
//
// stPanel1
//
this.stPanel1.Controls.Add(this.nodeSizeCB);
this.stPanel1.Controls.Add(this.stPanel4);
this.stPanel1.Controls.Add(this.stToolStrip1);
this.stPanel1.Controls.Add(this.stPanel3);
@ -89,6 +91,20 @@
this.stPanel1.TabIndex = 11;
this.stPanel1.Resize += new System.EventHandler(this.stPanel1_Resize);
//
// nodeSizeCB
//
this.nodeSizeCB.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.nodeSizeCB.BorderColor = System.Drawing.Color.Empty;
this.nodeSizeCB.BorderStyle = System.Windows.Forms.ButtonBorderStyle.Solid;
this.nodeSizeCB.ButtonColor = System.Drawing.Color.Empty;
this.nodeSizeCB.FormattingEnabled = true;
this.nodeSizeCB.Location = new System.Drawing.Point(172, 29);
this.nodeSizeCB.Name = "nodeSizeCB";
this.nodeSizeCB.ReadOnly = true;
this.nodeSizeCB.Size = new System.Drawing.Size(136, 21);
this.nodeSizeCB.TabIndex = 5;
this.nodeSizeCB.SelectedIndexChanged += new System.EventHandler(this.nodeSizeCB_SelectedIndexChanged);
//
// stPanel4
//
this.stPanel4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -106,6 +122,7 @@
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
this.splitContainer1.Name = "splitContainer1";
this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
this.splitContainer1.Panel1Collapsed = true;
//
// splitContainer1.Panel2
//
@ -113,7 +130,6 @@
this.splitContainer1.Size = new System.Drawing.Size(305, 485);
this.splitContainer1.SplitterDistance = 201;
this.splitContainer1.TabIndex = 1;
this.splitContainer1.Panel1Collapsed = true;
//
// treeViewCustom1
//
@ -125,7 +141,7 @@
this.treeViewCustom1.Location = new System.Drawing.Point(0, 0);
this.treeViewCustom1.Name = "treeViewCustom1";
this.treeViewCustom1.SelectedImageIndex = 0;
this.treeViewCustom1.Size = new System.Drawing.Size(305, 280);
this.treeViewCustom1.Size = new System.Drawing.Size(305, 485);
this.treeViewCustom1.TabIndex = 0;
this.treeViewCustom1.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeViewCustom1_AfterCheck);
this.treeViewCustom1.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.treeViewCustom1_DrawNode);
@ -240,7 +256,7 @@
// sortToolStripMenuItem
//
this.sortToolStripMenuItem.Name = "sortToolStripMenuItem";
this.sortToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
this.sortToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.sortToolStripMenuItem.Text = "Sort";
this.sortToolStripMenuItem.Click += new System.EventHandler(this.sortToolStripMenuItem_Click);
//
@ -248,7 +264,7 @@
//
this.dockSearchListToolStripMenuItem.CheckOnClick = true;
this.dockSearchListToolStripMenuItem.Name = "dockSearchListToolStripMenuItem";
this.dockSearchListToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
this.dockSearchListToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.dockSearchListToolStripMenuItem.Text = "Dock Search List";
this.dockSearchListToolStripMenuItem.Click += new System.EventHandler(this.dockSearchListToolStripMenuItem_Click);
//
@ -302,5 +318,6 @@
private STPanel stPanel4;
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.ToolStripMenuItem dockSearchListToolStripMenuItem;
private STComboBox nodeSizeCB;
}
}

View file

@ -33,6 +33,14 @@ namespace Toolbox.Library.Forms
}
}
private enum TreeNodeSize
{
Small,
Normal,
Large,
ExtraLarge,
}
public ObjectEditor ObjectEditor;
public void BeginUpdate() { treeViewCustom1.BeginUpdate(); }
@ -127,6 +135,11 @@ namespace Toolbox.Library.Forms
treeViewCustom1.BackColor = FormThemes.BaseTheme.ObjectEditorBackColor;
AddFilesToActiveEditor = Runtime.AddFilesToActiveObjectEditor;
foreach (TreeNodeSize nodeSize in (TreeNodeSize[])Enum.GetValues(typeof(TreeNodeSize)))
nodeSizeCB.Items.Add(nodeSize);
nodeSizeCB.SelectedIndex = 1;
}
public Viewport GetViewport() => viewport;
@ -309,6 +322,8 @@ namespace Toolbox.Library.Forms
var result = MessageBox.Show("If you remove this file, any unsaved progress will be lost! Continue?",
"Remove Dialog", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (result == DialogResult.Yes)
{
if (node is IFileFormat)
{
((IFileFormat)node).Unload();
@ -326,6 +341,7 @@ namespace Toolbox.Library.Forms
((IUpdateForm)Runtime.MainForm).UpdateForm();
}
}
}
private void ResetEditor()
{
@ -622,7 +638,6 @@ namespace Toolbox.Library.Forms
UpdateSearchPanelDockState();
}
private void UpdateSearchPanelDockState()
{
if (IsSearchPanelDocked)
@ -640,5 +655,34 @@ namespace Toolbox.Library.Forms
}
}
public void LoadGenericTextureIcons(ITextureIconLoader iconList) {
treeViewCustom1.TextureIcons.Add(iconList);
treeViewCustom1.ReloadTextureIcons(iconList);
}
private void nodeSizeCB_SelectedIndexChanged(object sender, EventArgs e)
{
var nodeSize = nodeSizeCB.SelectedItem;
if (nodeSize != null)
{
int Size = 22;
switch ((TreeNodeSize)nodeSize)
{
case TreeNodeSize.Small: Size = 18;
break;
case TreeNodeSize.Normal: Size = 22;
break;
case TreeNodeSize.Large: Size = 30;
break;
case TreeNodeSize.ExtraLarge: Size = 35;
break;
}
treeViewCustom1.ItemHeight = Size;
treeViewCustom1.ReloadImages(Size, Size);
treeViewCustom1.ReloadTextureIcons();
}
}
}
}

View file

@ -123,6 +123,9 @@
<metadata name="objectEditorMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="objectEditorMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="treeNodeContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>166, 17</value>
</metadata>

View file

@ -98,21 +98,18 @@
this.smallToolStripMenuItem.Name = "smallToolStripMenuItem";
this.smallToolStripMenuItem.Size = new System.Drawing.Size(119, 22);
this.smallToolStripMenuItem.Text = "Small";
this.smallToolStripMenuItem.Click += new System.EventHandler(this.smallToolStripMenuItem_Click);
//
// mediumToolStripMenuItem
//
this.mediumToolStripMenuItem.Name = "mediumToolStripMenuItem";
this.mediumToolStripMenuItem.Size = new System.Drawing.Size(119, 22);
this.mediumToolStripMenuItem.Text = "Medium";
this.mediumToolStripMenuItem.Click += new System.EventHandler(this.mediumToolStripMenuItem_Click);
//
// largeToolStripMenuItem
//
this.largeToolStripMenuItem.Name = "largeToolStripMenuItem";
this.largeToolStripMenuItem.Size = new System.Drawing.Size(119, 22);
this.largeToolStripMenuItem.Text = "Large";
this.largeToolStripMenuItem.Click += new System.EventHandler(this.largeToolStripMenuItem_Click);
//
// searchToolStripMenuItem
//

View file

@ -25,8 +25,6 @@ namespace Toolbox.Library
public ObjectList()
{
InitializeComponent();
ApplyThumbnailSetting(Runtime.thumbnailSize);
// treeView1.Sort();
}
private void selectItem(object sender, TreeNodeMouseClickEventArgs e)
@ -93,47 +91,6 @@ namespace Toolbox.Library
}
}
private void ApplyThumbnailSetting(Runtime.ThumbnailSize size)
{
switch (size)
{
case Runtime.ThumbnailSize.Small:
treeView1.ImageHeight = 21;
treeView1.ImageWidth = 21;
smallToolStripMenuItem.BackColor = Color.FromArgb(80, 80, 80);
break;
case Runtime.ThumbnailSize.Medium:
treeView1.ImageHeight = 27;
treeView1.ImageWidth = 27;
mediumToolStripMenuItem.BackColor = Color.FromArgb(80, 80, 80);
break;
case Runtime.ThumbnailSize.Large:
treeView1.ImageHeight = 34;
treeView1.ImageWidth = 34;
largeToolStripMenuItem.BackColor = Color.FromArgb(80, 80, 80);
break;
}
treeView1.ReloadImages();
}
private void largeToolStripMenuItem_Click(object sender, EventArgs e)
{
Runtime.thumbnailSize = Runtime.ThumbnailSize.Large;
ApplyThumbnailSetting(Runtime.thumbnailSize);
}
private void mediumToolStripMenuItem_Click(object sender, EventArgs e)
{
Runtime.thumbnailSize = Runtime.ThumbnailSize.Medium;
ApplyThumbnailSetting(Runtime.thumbnailSize);
}
private void smallToolStripMenuItem_Click(object sender, EventArgs e)
{
Runtime.thumbnailSize = Runtime.ThumbnailSize.Small;
ApplyThumbnailSetting(Runtime.thumbnailSize);
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
if (treeView1.SelectedNode is TreeNodeCustom)

View file

@ -417,7 +417,7 @@ namespace Toolbox.Library
return BitmapExtension.GetBitmap(ETC1.ETC1Decompress(data, (int)width, (int)height, true),
(int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
case TEX_FORMAT.LA8:
return BitmapExtension.GetBitmap(DecodeLA8(data, (int)width, (int)height),
return BitmapExtension.GetBitmap(RGBAPixelDecoder.Decode(data, (int)width, (int)height, Format),
(int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
}
@ -449,44 +449,6 @@ namespace Toolbox.Library
}
}
//Method from https://github.com/aboood40091/BNTX-Editor/blob/master/formConv.py
private static byte[] DecodeLA8(byte[] Input, int Width, int Height)
{
int bpp = 16;
if (Input.Length != Width * Height * bpp)
throw new Exception($"Unexpected size! {Input.Length}. Expected {Width * Height * bpp}");
byte[] Output = new byte[Width * Height * 4];
int inPos = 0;
int outPos = 0;
for (int Y = 0; Y < Height; Y++)
{
for (int X = 0; X < Width; X++)
{
inPos = (Y * Width + X) * bpp;
outPos = (Y * Width + X) * 4;
int pixel = 0;
for (int i = 0; i < bpp; i++)
pixel |= Input[inPos + i] << (8 * i);
byte[] Components = new byte[4];
Components[2] = (byte)(pixel & 0xFF);
Components[3] = (byte)((pixel & 0xFF00) >> 8);
Output[outPos + 3] = Components[3];
Output[outPos + 2] = Components[2];
Output[outPos + 1] = Components[1];
Output[outPos + 0] = Components[0];
}
}
return Output;
}
private Bitmap DecodeNotDirectXTex(byte[] data, uint Width, uint Height, TEX_FORMAT Format)
{
if (Format == TEX_FORMAT.R8G8B8A8_UNORM)
@ -575,6 +537,8 @@ namespace Toolbox.Library
imageData = ASTCDecoder.DecodeToRGBA8888(data, (int)GetBlockWidth(Format), (int)GetBlockHeight(Format), 1, (int)Width, (int)Height, 1);
else
imageData = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format);
// imageData = RGBAPixelDecoder.Decode(data, (int)Width, (int)Height, Format);
}
if (parameters.DontSwapRG || DontSwapRG)

View file

@ -127,10 +127,12 @@ namespace Toolbox.Library.IO
ByteOrder = ByteOrder.LittleEndian;
}
public string ReadSignature(int length, string ExpectedSignature)
public string ReadSignature(int length, string ExpectedSignature, bool TrimEnd = false)
{
string RealSignature = ReadString(length, Encoding.ASCII);
if (TrimEnd) RealSignature = RealSignature.TrimEnd(' ');
if (RealSignature != ExpectedSignature)
throw new Exception($"Invalid signature {RealSignature}! Expected {ExpectedSignature}.");

View file

@ -70,6 +70,22 @@ namespace Toolbox.Library.IO
ByteOrder = ByteOrder.LittleEndian;
}
public void WriteString(string text, uint fixedSize)
{
long pos = Position;
WriteString(text);
Seek(pos + fixedSize);
}
//Writes the total size of a section as a uint.
public void WriteSectionSizeU32(long position, long startPosition, long endPosition)
{
using (TemporarySeek(position, System.IO.SeekOrigin.Begin))
{
Write((uint)endPosition - startPosition);
}
}
//
// RelativeOffsetPosition controls the relative position the offset starts at
//

View file

@ -6,6 +6,7 @@ using System.Threading.Tasks;
namespace Toolbox.Library
{
//Represents a node from an IArchive file
public interface INode
{
string Name { get; set; }

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Toolbox.Library
{
//A texture list to display icons on a treeview
//Attach this to an IFileFormat
public interface ITextureIconLoader
{
List<STGenericTexture> IconTextureList { get; set; }
}
}

View file

@ -7,6 +7,7 @@ using System.Windows.Forms;
namespace Toolbox.Library
{
//A custom clonable treenode
public interface ICloneableNode
{
TreeNode CloneNode();

View file

@ -216,6 +216,7 @@
<Compile Include="Compression\Yaz0.cs" />
<Compile Include="Compression\ZCMP.cs" />
<Compile Include="Config.cs" />
<Compile Include="FileFormats\DDS\RGBAPixelDecoder.cs" />
<Compile Include="Forms\ColorAlphaBox.cs">
<SubType>Component</SubType>
</Compile>
@ -245,11 +246,12 @@
</Compile>
<Compile Include="Generics\Texture\ImageParameters.cs" />
<Compile Include="Generics\Texture\STTextureFolder.cs" />
<Compile Include="Interfaces\ILeaveOpenOnLoad.cs" />
<Compile Include="Interfaces\ICloneableNode.cs" />
<Compile Include="Interfaces\IMeshContainer.cs" />
<Compile Include="Interfaces\ITextureContainer.cs" />
<Compile Include="Interfaces\IUpdateForm.cs" />
<Compile Include="Interfaces\FileFormatting\ILeaveOpenOnLoad.cs" />
<Compile Include="Interfaces\Textures\ITextureIconLoader.cs" />
<Compile Include="Interfaces\Utility\ICloneableNode.cs" />
<Compile Include="Interfaces\ModelData\IMeshContainer.cs" />
<Compile Include="Interfaces\Textures\ITextureContainer.cs" />
<Compile Include="Interfaces\Forms\IUpdateForm.cs" />
<Compile Include="IO\Extensions\UintExtension.cs" />
<Compile Include="IO\STColor.cs" />
<Compile Include="Rendering\GenericModelRenderer\GenericModelRenderer.cs" />
@ -610,9 +612,9 @@
<Compile Include="Generics\GenericPolygonGroup.cs" />
<Compile Include="Generics\Texture\GenericTexture.cs" />
<Compile Include="Generics\OpenGLTexture.cs" />
<Compile Include="Interfaces\ICompressionFormat.cs" />
<Compile Include="Interfaces\IDirectoryNode.cs" />
<Compile Include="Interfaces\INode.cs" />
<Compile Include="Interfaces\FileFormatting\ICompressionFormat.cs" />
<Compile Include="Interfaces\FileFormatting\IDirectoryNode.cs" />
<Compile Include="Interfaces\FileFormatting\INode.cs" />
<Compile Include="IO\Extensions\ByteArrayExtensions.cs" />
<Compile Include="Rendering\RenderableTex.cs" />
<Compile Include="Generics\STBone.cs" />
@ -657,14 +659,14 @@
</Compile>
<Compile Include="Helpers\TextureHelper.cs" />
<Compile Include="Helpers\TreeHelper.cs" />
<Compile Include="Interfaces\IContextMenuNode.cs" />
<Compile Include="Interfaces\IConvertableTextFormat.cs" />
<Compile Include="Interfaces\IEditor.cs" />
<Compile Include="Interfaces\IFIleEditor.cs" />
<Compile Include="Interfaces\IMdiContainer.cs" />
<Compile Include="Interfaces\IMenuExtension.cs" />
<Compile Include="Interfaces\ITexture.cs" />
<Compile Include="Interfaces\IViewportContainer.cs" />
<Compile Include="Interfaces\Forms\IContextMenuNode.cs" />
<Compile Include="Interfaces\FileFormatting\IConvertableTextFormat.cs" />
<Compile Include="Interfaces\Forms\IEditor.cs" />
<Compile Include="Interfaces\Forms\IFIleEditor.cs" />
<Compile Include="Interfaces\Forms\IMdiContainer.cs" />
<Compile Include="Interfaces\Forms\IMenuExtension.cs" />
<Compile Include="Interfaces\Textures\ITexture.cs" />
<Compile Include="Interfaces\Forms\IViewportContainer.cs" />
<Compile Include="Compression\CompressionMenus.cs" />
<Compile Include="IO\DWord.cs" />
<Compile Include="IO\FileReader.cs" />
@ -726,8 +728,8 @@
<Compile Include="Forms\Dialogs\RenameDialog.Designer.cs">
<DependentUpon>RenameDialog.cs</DependentUpon>
</Compile>
<Compile Include="Interfaces\IArchiveFile.cs" />
<Compile Include="Interfaces\IFileFormat.cs" />
<Compile Include="Interfaces\FileFormatting\IArchiveFile.cs" />
<Compile Include="Interfaces\FileFormatting\IFileFormat.cs" />
<Compile Include="IO\FileIO.cs" />
<Compile Include="Interfaces\IPlugin.cs" />
<Compile Include="Format Managers\FileManager.cs" />