1
0
mirror of synced 2025-01-31 12:23:52 +01:00

Add more stuff

This commit is contained in:
KillzXGaming 2018-11-16 21:13:05 -05:00
parent 98bb2c07be
commit db31730291
9 changed files with 2526 additions and 185 deletions

View File

@ -0,0 +1,334 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using Switch_Toolbox.Library.IO;
using Bfres.Structs;
namespace FirstPlugin
{
public class BFRES : IFileFormat
{
public bool CanSave { get; set; } = false;
public bool FileIsEdited { get; set; } = false;
public bool FileIsCompressed { get; set; } = false;
public string[] Description { get; set; } = new string[] { "BFRES", "*BFRES", "*BFRES" };
public string[] Extension { get; set; } = new string[] { "*.bfres", "*.sbfres" };
public string Magic { get; set; } = "FRES";
public CompressionType CompressionType { get; set; } = CompressionType.None;
public byte[] Data { get; set; }
public string FileName { get; set; }
public IFileInfo IFileInfo { get; set; }
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
private TreeNodeFile eitorRoot;
public TreeNodeFile EditorRoot
{
get
{
return eitorRoot;
}
set
{
this.eitorRoot = value;
}
}
private void SaveFile()
{
List<IFileFormat> formats = new List<IFileFormat>();
formats.Add(this);
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(formats);
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)
{
Cursor.Current = Cursors.WaitCursor;
SaveCompressFile(Save(), sfd.FileName, Alignment);
}
}
private void SaveCompressFile(byte[] data, string FileName, int Alignment = 0, bool EnableDialog = true)
{
if (EnableDialog && CompressionType != CompressionType.None)
{
DialogResult save = MessageBox.Show($"Compress file as {CompressionType}?", "File Save", MessageBoxButtons.YesNo);
if (save == DialogResult.Yes)
{
switch (CompressionType)
{
case CompressionType.Yaz0:
data = EveryFileExplorer.YAZ0.Compress(data, Runtime.Yaz0CompressionLevel, (uint)Alignment);
break;
case CompressionType.Lz4f:
data = STLibraryCompression.Type_LZ4F.Compress(data);
break;
case CompressionType.Lz4:
break;
}
}
}
File.WriteAllBytes(FileName, data);
MessageBox.Show($"File has been saved to {FileName}");
Cursor.Current = Cursors.Default;
}
public bool IsActive { get; set; } = false;
public bool UseEditMenu { get; set; } = false;
public int Alignment { get; set; } = 0;
public string FilePath { get; set; }
public static bool IsWiiU = false;
BFRESRender bfres;
public void Load()
{
IsActive = true;
CanSave = true;
using (FileReader reader = new FileReader(new MemoryStream(Data)))
{
reader.Seek(4);
if (reader.ReadInt32() != 0x20202020)
{
IsWiiU = true;
}
reader.Close();
}
bfres = new BFRESRender();
bfres.ResFileNode = new ResourceFile(this);
bfres.ResFileNode.BFRESRender = bfres;
bfres.SaveFile = SaveFile;
EditorRoot = bfres.ResFileNode;
if (IsWiiU)
{
bfres.LoadFile(new Syroot.NintenTools.Bfres.ResFile(new System.IO.MemoryStream(Data)));
}
else
{
bfres.LoadFile(new Syroot.NintenTools.NSW.Bfres.ResFile(new System.IO.MemoryStream(Data)));
}
Runtime.abstractGlDrawables.Add(bfres);
}
public void Unload()
{
bfres.Destroy();
bfres.ResFileNode.Nodes.Clear();
}
public byte[] Save()
{
MemoryStream mem = new MemoryStream();
if (IsWiiU)
SaveWiiU(mem);
else
SaveSwitch(mem);
return mem.ToArray();
}
private void SaveSwitch(MemoryStream mem)
{
int CurMdl = 0;
foreach (FMDL model in bfres.models)
{
bfres.resFile.Models[CurMdl].Shapes.Clear();
bfres.resFile.Models[CurMdl].VertexBuffers.Clear();
bfres.resFile.Models[CurMdl].Materials.Clear();
bfres.resFile.Models[CurMdl].MaterialDict.Clear();
int i = 0;
var duplicates = model.shapes.GroupBy(c => c.Text).Where(g => g.Skip(1).Any()).SelectMany(c => c);
foreach (var shape in duplicates)
shape.Text += i++;
foreach (FSHP shape in model.shapes)
{
CheckMissingTextures(shape);
BfresSwitch.SetShape(shape, shape.Shape);
bfres.resFile.Models[CurMdl].Shapes.Add(shape.Shape);
bfres.resFile.Models[CurMdl].VertexBuffers.Add(shape.VertexBuffer);
SetShaderAssignAttributes(shape.GetMaterial().shaderassign, shape);
}
foreach (FMAT mat in model.materials.Values)
{
BfresSwitch.SetMaterial(mat, mat.Material);
bfres.resFile.Models[CurMdl].Materials.Add(mat.Material);
}
CurMdl++;
}
bfres.resFile.SkeletalAnims.Clear();
if (EditorRoot.Nodes.ContainsKey("FSKA"))
{
foreach (BfresSkeletonAnim ska in EditorRoot.Nodes["FSKA"].Nodes)
{
bfres.resFile.SkeletalAnims.Add(ska.SkeletalAnim);
}
}
ErrorCheck();
BfresSwitch.WriteExternalFiles(bfres.resFile, EditorRoot);
bfres.resFile.Save(mem);
}
private void SaveWiiU(MemoryStream mem)
{
bfres.resFileU.Save(mem);
int CurMdl = 0;
foreach (FMDL model in bfres.models)
{
bfres.resFileU.Models[CurMdl].Shapes.Clear();
bfres.resFileU.Models[CurMdl].VertexBuffers.Clear();
bfres.resFileU.Models[CurMdl].Materials.Clear();
int i = 0;
var duplicates = model.shapes.GroupBy(c => c.Text).Where(g => g.Skip(1).Any()).SelectMany(c => c);
foreach (var shape in duplicates)
shape.Text += i++;
foreach (FSHP shape in model.shapes)
{
CheckMissingTextures(shape);
BfresWiiU.SetShape(shape, shape.ShapeU);
bfres.resFileU.Models[CurMdl].Shapes.Add(shape.Text, shape.ShapeU);
bfres.resFileU.Models[CurMdl].VertexBuffers.Add(shape.VertexBufferU);
SetShaderAssignAttributes(shape.GetMaterial().shaderassign, shape);
}
foreach (FMAT mat in model.materials.Values)
{
BfresWiiU.SetMaterial(mat, mat.MaterialU);
bfres.resFileU.Models[CurMdl].Materials.Add(mat.Text, mat.MaterialU);
}
CurMdl++;
}
bfres.resFile.SkeletalAnims.Clear();
if (EditorRoot.Nodes.ContainsKey("FSKA"))
{
foreach (BfresSkeletonAnim ska in EditorRoot.Nodes["FSKA"].Nodes)
{
bfres.resFile.SkeletalAnims.Add(ska.SkeletalAnim);
}
}
}
private void SetShaderAssignAttributes(FMAT.ShaderAssign shd, FSHP shape)
{
foreach (var att in shape.vertexAttributes)
{
if (!shd.attributes.ContainsValue(att.Name) && !shd.attributes.ContainsKey(att.Name))
shd.attributes.Add(att.Name, att.Name);
}
foreach (var tex in shape.GetMaterial().textures)
{
if (!shd.samplers.ContainsValue(tex.SamplerName))
shd.attributes.Add(tex.SamplerName, tex.SamplerName);
}
}
private void SetDuplicateShapeName(FSHP shape)
{
DialogResult dialogResult = MessageBox.Show($"A shape {shape.Text} already exists with that name", "", MessageBoxButtons.OK);
if (dialogResult == DialogResult.OK)
{
RenameDialog renameDialog = new RenameDialog();
renameDialog.Text = "Rename Texture";
if (renameDialog.ShowDialog() == DialogResult.OK)
{
shape.Text = renameDialog.textBox1.Text;
}
}
}
bool ImportMissingTextures = false;
private void CheckMissingTextures(FSHP shape)
{
foreach (BinaryTextureContainer bntx in PluginRuntime.bntxContainers)
{
foreach (MatTexture tex in shape.GetMaterial().textures)
{
if (!bntx.Textures.ContainsKey(tex.Name))
{
if (!ImportMissingTextures)
{
DialogResult result = MessageBox.Show("Missing textures found! Would you like to use placeholders?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
ImportMissingTextures = true;
}
else
{
return;
}
}
if (ImportMissingTextures)
bntx.ImportPlaceholderTexture(tex.Name);
}
}
}
}
public void ErrorCheck()
{
if (bfres != null)
{
List<Errors> Errors = new List<Errors>();
foreach (FMDL model in bfres.models)
{
foreach (FSHP shp in model.shapes)
{
Syroot.NintenTools.NSW.Bfres.VertexBuffer vtx = shp.VertexBuffer;
Syroot.NintenTools.NSW.Bfres.Material mat = shp.GetMaterial().Material;
Syroot.NintenTools.NSW.Bfres.ShaderAssign shdr = mat.ShaderAssign;
for (int att = 0; att < vtx.Attributes.Count; att++)
{
if (!shdr.AttribAssigns.Contains(vtx.Attributes[att].Name))
MessageBox.Show($"Error! Attribute {vtx.Attributes[att].Name} is unlinked!");
}
for (int att = 0; att < mat.TextureRefs.Count; att++)
{
if (!shdr.SamplerAssigns.Contains(mat.SamplerDict.GetKey(att))) //mat.SamplerDict[att]
MessageBox.Show($"Error! Sampler {mat.SamplerDict.GetKey(att)} is unlinked!");
}
}
}
// ErrorList errorList = new ErrorList();
// errorList.LoadList(Errors);
// errorList.Show();
}
}
public class Errors
{
public string Section = "None";
public string Section2 = "None";
public string Message = "";
public string Type = "Unkown";
}
}
}

View File

@ -0,0 +1,201 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using ByamlExt.Byaml;
using ByamlExt;
using WeifenLuo.WinFormsUI.Docking;
namespace FirstPlugin
{
public class BYAML : IFileFormat
{
public bool CanSave { get; set; } = false;
public bool FileIsEdited { get; set; } = false;
public bool FileIsCompressed { get; set; } = false;
public string[] Description { get; set; } = new string[] { "BYAML" };
public string[] Extension { get; set; } = new string[] { "*.byaml", "*.byml", "*.bprm", "*.sbyml" };
public string Magic { get; set; } = "YB";
public CompressionType CompressionType { get; set; } = CompressionType.None;
public byte[] Data { get; set; }
public string FileName { get; set; }
public TreeNodeFile EditorRoot { get; set; }
public bool IsActive { get; set; } = false;
public bool UseEditMenu { get; set; } = false;
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
class EditableNode
{
public Type type { get => Node[Index].GetType(); }
dynamic Node;
dynamic Index;
public dynamic Get() => Node[Index];
public void Set(dynamic value) => Node[Index] = value;
public string GetTreeViewString()
{
if (Index is int)
return Node[Index].ToString();
else
return Index + " : " + Node[Index].ToString();
}
public EditableNode(dynamic _node, dynamic _index)
{
Node = _node;
Index = _index;
}
}
public void Load()
{
IsActive = false;
CanSave = false;
// ByamlViewer.OpenByml(new System.IO.MemoryStream(Data), FileName);
// BymlFileData byamlFile = ByamlFile.LoadN(new System.IO.MemoryStream(Data), false, Syroot.BinaryData.ByteOrder.LittleEndian);
// EditorRoot = LoadByamlNodes(byamlFile.RootNode);
// LoadDockedEditor(byamlFile);
}
public void Unload()
{
}
ByamlEditor ByamlEditor;
public void LoadDockedEditor(BymlFileData byamlFile)
{
foreach (Control control in FirstPlugin.MainF.Controls)
{
if (control is DockPanel)
{
ByamlEditor = new ByamlEditor();
ByamlEditor.Dock = DockStyle.Fill;
ByamlEditor.Show(((DockPanel)control), DockState.Document);
ByamlEditor.LoadByaml(byamlFile);
}
}
}
public TreeNode LoadByamlNodes(dynamic root)
{
TreeNode node = new TreeNode();
if (root == null)
return node;
if (root is Dictionary<string, dynamic>)
{
parseDictNode(root, node.Nodes);
}
else if (root is List<dynamic>)
{
if (((List<dynamic>)root).Count == 0)
{
MessageBox.Show("This byml is empty");
}
parseArrayNode(root, node.Nodes);
}
else if (root is List<ByamlPathPoint>)
{
}
return node;
}
void parseArrayNode(IList<dynamic> list, TreeNodeCollection addto)
{
int index = 0;
foreach (dynamic k in list)
{
if (k is IDictionary<string, dynamic>)
{
TreeNode current = addto.Add("<Dictionary>");
current.Tag = ((IDictionary<string, dynamic>)k);
current.Nodes.Add("✯✯dummy✯✯");
}
else if (k is IList<dynamic>)
{
TreeNode current = addto.Add("<Array>");
current.Tag = ((IList<dynamic>)k);
current.Nodes.Add("✯✯dummy✯✯");
}
else if (k is IList<ByamlPathPoint>)
{
TreeNode current = addto.Add("<PathPointArray>");
current.Tag = ((IList<ByamlPathPoint>)k);
parsePathPointArray(k, current.Nodes);
}
else
{
var n = addto.Add(k == null ? "<NULL>" : k.ToString());
if (k != null) n.Tag = new EditableNode(list, index);
}
index++;
}
}
void parseDictNode(IDictionary<string, dynamic> node, TreeNodeCollection addto)
{
foreach (string k in node.Keys)
{
TreeNode current = addto.Add(k);
if (node[k] is IDictionary<string, dynamic>)
{
current.Text += " : <Dictionary>";
current.Tag = node[k];
current.Nodes.Add("✯✯dummy✯✯"); //a text that can't be in a byml
}
else if (node[k] is IList<dynamic>)
{
current.Text += " : <Array>";
current.Tag = ((IList<dynamic>)node[k]);
current.Nodes.Add("✯✯dummy✯✯");
}
else if (node[k] is IList<ByamlPathPoint>)
{
current.Text += " : <PathPointArray>";
current.Tag = ((IList<ByamlPathPoint>)node[k]);
parsePathPointArray(node[k], current.Nodes);
}
else
{
current.Text = current.Text + " : " + (node[k] == null ? "<NULL>" : node[k].ToString());
if (node[k] != null) current.Tag = new EditableNode(node, k);
}
}
}
void parsePathPointArray(IList<ByamlPathPoint> list, TreeNodeCollection addto)
{
int index = 0;
foreach (var k in list)
{
index++;
var n = addto.Add(k == null ? "<NULL>" : k.ToString());
if (k != null) n.Tag = new EditableNode(list, index);
}
}
public byte[] Save()
{
return null;
}
}
}

View File

@ -1,12 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.IO;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using KCLExt;
using SFGraphics.GLObjects.Shaders;
using Smash_Forge.Rendering;
using GL_Core.Interfaces;
@ -15,6 +11,8 @@ using OpenTK;
using Switch_Toolbox.Library.Rendering;
using WeifenLuo.WinFormsUI.Docking;
using GL_Core;
using System.Drawing;
using Switch_Toolbox.Library.IO;
namespace FirstPlugin
{
@ -29,11 +27,12 @@ namespace FirstPlugin
public CompressionType CompressionType { get; set; } = CompressionType.None;
public byte[] Data { get; set; }
public string FileName { get; set; }
public TreeNode EditorRoot { get; set; }
public TreeNodeFile EditorRoot { get; set; }
public bool IsActive { get; set; } = false;
public bool UseEditMenu { get; set; } = false;
public int Alignment { get; set; } = 0;
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public Type[] Types
{
get
@ -46,7 +45,8 @@ namespace FirstPlugin
public void Load()
{
IsActive = true;
EditorRoot = new KCLRoot(FileName);
EditorRoot = new KCLRoot(FileName, this);
IFileInfo = new IFileInfo();
}
public void Unload()
{
@ -54,7 +54,34 @@ namespace FirstPlugin
}
public byte[] Save()
{
return null;
KCLRoot root = (KCLRoot)EditorRoot;
return root.kcl.Write(Syroot.BinaryData.ByteOrder.LittleEndian);
}
private static void SaveCompressFile(byte[] data, string FileName, CompressionType CompressionType, int Alignment = 0, bool EnableDialog = true)
{
if (EnableDialog && CompressionType != CompressionType.None)
{
DialogResult save = MessageBox.Show($"Compress file as {CompressionType}?", "File Save", MessageBoxButtons.YesNo);
if (save == DialogResult.Yes)
{
switch (CompressionType)
{
case CompressionType.Yaz0:
data = EveryFileExplorer.YAZ0.Compress(data, Runtime.Yaz0CompressionLevel, (uint)Alignment);
break;
case CompressionType.Lz4f:
data = STLibraryCompression.Type_LZ4F.Compress(data);
break;
case CompressionType.Lz4:
break;
}
}
}
File.WriteAllBytes(FileName, data);
MessageBox.Show($"File has been saved to {FileName}");
Cursor.Current = Cursors.Default;
}
public enum GameSet : ushort
@ -117,23 +144,152 @@ namespace FirstPlugin
BoostTrick = 8202,
}
public static Shader shader = null;
public class KCLRoot : TreeNodeCustom
public class KCLRoot : TreeNodeFile
{
public KCLRoot(string Name)
public KCLRoot(string Name, IFileFormat handler)
{
Text = Name;
FileHandler = handler;
Renderer = new KCLRendering();
Read(handler.Data);
ContextMenu = new ContextMenu();
MenuItem save = new MenuItem("Save");
ContextMenu.MenuItems.Add(save);
save.Click += Save;
MenuItem export = new MenuItem("Export");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
MenuItem replace = new MenuItem("Replace");
ContextMenu.MenuItems.Add(replace);
replace.Click += Replace;
}
public void Save(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Supported Formats|*.kcl";
sfd.FileName = Text;
sfd.DefaultExt = ".kcl";
if (sfd.ShowDialog() == DialogResult.OK)
{
int Alignment = FileHandler.IFileInfo.Alignment;
SaveCompressFile(FileHandler.Save(), sfd.FileName, FileHandler.CompressionType, Alignment);
}
}
public void Export(object sender, EventArgs args)
{
if (kcl == null)
return;
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Supported Formats|*.obj";
sfd.FileName = Text;
sfd.DefaultExt = ".obj";
if (sfd.ShowDialog() == DialogResult.OK)
{
kcl.ToOBJ().toWritableObj().WriteObj(sfd.FileName + ".obj");
}
}
public void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Supported Formats|*.obj";
if (ofd.ShowDialog() == DialogResult.OK)
{
var mod = EditorCore.Common.OBJ.Read(new MemoryStream(File.ReadAllBytes(ofd.FileName)), null);
if (mod.Faces.Count > 65535)
{
MessageBox.Show("this model has too many faces, only models with less than 65535 triangles can be converted");
return;
}
kcl = MarioKart.MK7.KCL.FromOBJ(mod);
Read(kcl.Write(Syroot.BinaryData.ByteOrder.LittleEndian));
}
}
KCLRendering Renderer;
public override void OnClick(TreeView treeView)
{
//If has models
if (Nodes[0].Nodes.Count > 0)
Renderer.LoadViewport();
Renderer.UpdateVertexData();
}
public MarioKart.MK7.KCL kcl = null;
public void Read(byte[] file_data)
{
try
{
Renderer.LoadViewport();
Renderer.UpdateVertexData();
kcl = new MarioKart.MK7.KCL(file_data, Syroot.BinaryData.ByteOrder.LittleEndian);
}
catch
{
kcl = new MarioKart.MK7.KCL(file_data, Syroot.BinaryData.ByteOrder.BigEndian);
}
Read(kcl);
Renderer.UpdateVertexData();
}
public void Read(MarioKart.MK7.KCL kcl)
{
Nodes.Clear();
Renderer.models.Clear();
int CurModelIndx = 0;
foreach (MarioKart.MK7.KCL.KCLModel mdl in kcl.Models)
{
KCLModel kclmodel = new KCLModel();
kclmodel.Text = "Model " + CurModelIndx;
int ft = 0;
foreach (var plane in mdl.Planes)
{
var triangle = mdl.GetTriangle(plane);
var normal = triangle.Normal;
var pointA = triangle.PointA;
var pointB = triangle.PointB;
var pointC = triangle.PointC;
Vertex vtx = new Vertex();
Vertex vtx2 = new Vertex();
Vertex vtx3 = new Vertex();
vtx.pos = new Vector3(Vec3D_To_Vec3(pointA));
vtx2.pos = new Vector3(Vec3D_To_Vec3(pointB));
vtx3.pos = new Vector3(Vec3D_To_Vec3(pointC));
vtx.nrm = new Vector3(Vec3D_To_Vec3(normal));
vtx2.nrm = new Vector3(Vec3D_To_Vec3(normal));
vtx3.nrm = new Vector3(Vec3D_To_Vec3(normal));
KCLModel.Face face = new KCLModel.Face();
face.Text = triangle.Collision.ToString();
face.MaterialFlag = triangle.Collision;
var col = MarioKart.MK7.KCLColors.GetMaterialColor(plane.CollisionType);
Vector3 ColorSet = new Vector3(col.R, col.G, col.B);
vtx.col = new Vector4(ColorSet, 1);
vtx2.col = new Vector4(ColorSet, 1);
vtx3.col = new Vector4(ColorSet, 1);
kclmodel.faces.Add(ft);
kclmodel.faces.Add(ft + 1);
kclmodel.faces.Add(ft + 2);
ft += 3;
kclmodel.vertices.Add(vtx);
kclmodel.vertices.Add(vtx2);
kclmodel.vertices.Add(vtx3);
}
Renderer.models.Add(kclmodel);
Nodes.Add(kclmodel);
CurModelIndx++;
}
}
}
@ -147,15 +303,25 @@ namespace FirstPlugin
//Set the game's material list
public GameSet GameMaterialSet = GameSet.MarioKart8D;
public List<KCLModel> models = new List<KCLModel>();
public Shader shader = null;
public KCLRendering()
private void GenerateBuffers()
{
GL.GenBuffers(1, out vbo_position);
GL.GenBuffers(1, out ibo_elements);
}
public void Destroy()
{
GL.DeleteBuffer(vbo_position);
GL.DeleteBuffer(ibo_elements);
}
public void UpdateVertexData()
{
if (OpenTKSharedResources.SetupStatus == OpenTKSharedResources.SharedResourceStatus.Unitialized)
return;
DisplayVertex[] Vertices;
int[] Faces;
@ -169,8 +335,6 @@ namespace FirstPlugin
List<DisplayVertex> pv = m.CreateDisplayVertices();
Vs.AddRange(pv);
Console.WriteLine(m.displayFaceSize);
for (int i = 0; i < m.displayFaceSize; i++)
{
Ds.Add(m.display[i] + voffset);
@ -189,6 +353,8 @@ namespace FirstPlugin
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
GL.BufferData<int>(BufferTarget.ElementArrayBuffer, (IntPtr)(Faces.Length * sizeof(int)), Faces, BufferUsageHint.StaticDraw);
Viewport.Instance.UpdateViewport();
}
string FileName;
@ -226,9 +392,16 @@ namespace FirstPlugin
}
public override void Draw(GL_ControlModern control)
{
shader = OpenTKSharedResources.shaders["KCL"];
bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0;
if (!buffersWereInitialized)
GenerateBuffers();
if (OpenTKSharedResources.SetupStatus == OpenTKSharedResources.SharedResourceStatus.Unitialized)
return;
shader = OpenTKSharedResources.shaders["KCL"];
shader.UseProgram();
shader.EnableVertexAttributes();
SetRenderSettings(shader);
@ -237,10 +410,13 @@ namespace FirstPlugin
Matrix4 camMat = previewScale * control.mtxCam * control.mtxProj;
shader.SetVector3("difLightDirection", Vector3.TransformNormal(new Vector3(0f, 0f, -1f), camMat.Inverted()).Normalized());
shader.SetVector3("difLightColor", new Vector3(1));
shader.SetVector3("ambLightColor", new Vector3(1));
shader.EnableVertexAttributes();
SetRenderSettings(shader);
shader.SetMatrix4x4("modelview", ref camMat);
shader.SetMatrix4x4("mvpMatrix", ref camMat);
foreach (KCLModel mdl in models)
{
@ -318,138 +494,44 @@ namespace FirstPlugin
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
shader.SetInt("colorOverride", 0);
}
public MarioKart.MK7.KCL kcl = null;
public void Read(byte[] file_data)
{
try
{
kcl = new MarioKart.MK7.KCL(file_data, Syroot.BinaryData.ByteOrder.LittleEndian);
}
catch
{
kcl = new MarioKart.MK7.KCL(file_data, Syroot.BinaryData.ByteOrder.BigEndian);
}
/*
int CurModelIndx = 0;
foreach (MarioKart.MK7.KCL.KCLModel mdl in kcl.Models)
{
KCLModel kclmodel = new KCLModel();
kclmodel.Text = "Model " + CurModelIndx;
KclFace[] indicesArray = mdl.Faces;
int ft = 0;
foreach (KclFace f in mdl.Faces)
{
Vertex vtx = new Vertex();
Vertex vtx2 = new Vertex();
Vertex vtx3 = new Vertex();
Vector3 CrossA = Vector3.Cross(Vec3F_To_Vec3(mdl.Normals[f.Normal1Index]), Vec3F_To_Vec3(mdl.Normals[f.DirectionIndex]));
Vector3 CrossB = Vector3.Cross(Vec3F_To_Vec3(mdl.Normals[f.Normal2Index]), Vec3F_To_Vec3(mdl.Normals[f.DirectionIndex]));
Vector3 CrossC = Vector3.Cross(Vec3F_To_Vec3(mdl.Normals[f.Normal3Index]), Vec3F_To_Vec3(mdl.Normals[f.DirectionIndex]));
Vector3 normal_a = Vec3F_To_Vec3(mdl.Normals[f.Normal1Index]);
Vector3 normal_b = Vec3F_To_Vec3(mdl.Normals[f.Normal2Index]);
Vector3 normal_c = Vec3F_To_Vec3(mdl.Normals[f.Normal3Index]);
float result1 = Vector3.Dot(new Vector3(CrossB.X, CrossB.Y, CrossB.Z), (new Vector3(normal_c.X, normal_c.Y, normal_c.Z)));
float result2 = Vector3.Dot(new Vector3(CrossA.X, CrossA.Y, CrossA.Z), (new Vector3(normal_c.X, normal_c.Y, normal_c.Z)));
Vector3 pos = Vec3F_To_Vec3(mdl.Positions[f.PositionIndex]);
Vector3 nrm = Vec3F_To_Vec3(mdl.Normals[f.Normal1Index]);
Vector3 Vertex1 = pos;
Vector3 Vertex2 = pos + CrossB * (f.Length / result1);
Vector3 Vertex3 = pos + CrossA * (f.Length / result2);
vtx.pos = new Vector3(Vertex1.X, Vertex1.Y, Vertex1.Z);
vtx2.pos = new Vector3(Vertex2.X, Vertex2.Y, Vertex2.Z);
vtx3.pos = new Vector3(Vertex3.X, Vertex3.Y, Vertex3.Z);
var dir = Vector3.Cross(Vertex2 - Vertex1, Vertex3 - Vertex1);
var norm = Vector3.Normalize(dir);
vtx.nrm = norm;
vtx2.nrm = norm;
vtx3.nrm = norm;
KCLModel.Face face = new KCLModel.Face();
face.Text = f.CollisionFlags.ToString();
face.MaterialFlag = f.CollisionFlags;
Color color = SetMaterialColor(face);
AllFlags.Add(face.MaterialFlag);
Vector3 ColorSet = new Vector3(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f);
vtx.col = new Vector3(ColorSet);
vtx2.col = new Vector3(ColorSet);
vtx3.col = new Vector3(ColorSet);
kclmodel.faces.Add(ft);
kclmodel.faces.Add(ft + 1);
kclmodel.faces.Add(ft + 2);
ft += 3;
kclmodel.vertices.Add(vtx);
kclmodel.vertices.Add(vtx2);
kclmodel.vertices.Add(vtx3);
}
models.Add(kclmodel);
Nodes.Add(kclmodel);
CurModelIndx++;
}*/
}
//Convert KCL lib vec3 to opentk one so i can use the cross and dot methods
public static Vector3 Vec3F_To_Vec3(Syroot.Maths.Vector3F v)
{
return new Vector3(v.X, v.Y, v.Z);
}
}
//Convert KCL lib vec3 to opentk one so i can use the cross and dot methods
public static Vector3 Vec3D_To_Vec3(System.Windows.Media.Media3D.Vector3D v)
{
return new Vector3((float)v.X, (float)v.Y, (float)v.Z);
}
public struct DisplayVertex
{
// Used for rendering.
public Vector3 pos;
public Vector3 nrm;
public Vector3 tan;
public Vector3 bit;
public Vector2 uv;
public Vector4 col;
public Vector4 node;
public Vector4 weight;
public Vector2 uv2;
public Vector2 uv3;
public Vector3 pos1;
public Vector3 pos2;
public Vector3 col;
public static int Size = 4 * (3 + 3 + 3 + 3 + 2 + 4 + 4 + 4 + 2 + 2 + 3 + 3);
public static int Size = 4 * (3 + 3 + 3);
}
public class KCLModel : STGenericObject
{
public KCLModel()
{
ImageKey = "mesh";
SelectedImageKey = "mesh";
Checked = true;
}
public int[] display;
public int Offset; // For Rendering
public int strip = 0x40;
public int displayFaceSize = 0;
public class Face : TreeNode
{
public int MaterialFlag = 0;
}
public List<DisplayVertex> CreateDisplayVertices()
{
// rearrange faces
@ -466,7 +548,7 @@ namespace FirstPlugin
{
pos = v.pos,
nrm = v.nrm,
col = v.col,
col = v.col.Xyz,
};
displayVertList.Add(displayVert);

View File

@ -127,12 +127,12 @@ namespace FirstPlugin
public CompressionType CompressionType { get; set; } = CompressionType.None;
public byte[] Data { get; set; }
public string FileName { get; set; }
public TreeNode EditorRoot { get; set; }
public TreeNodeFile EditorRoot { get; set; }
public bool IsActive { get; set; } = false;
public bool UseEditMenu { get; set; } = false;
public IFileFormat ArchiveFile { get; set; }
public int Alignment { get; set; } = 0;
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public Type[] Types
{
get
@ -144,7 +144,7 @@ namespace FirstPlugin
}
class MenuExt : IFileMenuExtension
{
public ToolStripItemDark[] NewFileMenuExtensions => newFileExt;
public ToolStripItemDark[] NewFileMenuExtensions => null;
public ToolStripItemDark[] ToolsMenuExtensions => null;
public ToolStripItemDark[] TitleBarExtensions => null;
public ToolStripItemDark[] CompressionMenuExtensions => null;
@ -165,7 +165,7 @@ namespace FirstPlugin
UseEditMenu = true;
CanSave = true;
bntx = new BinaryTextureContainer(Data, FileName);
bntx = new BinaryTextureContainer(Data, FileName, "", this);
EditorRoot = bntx;
}
public void Unload()
@ -186,7 +186,7 @@ namespace FirstPlugin
}
}
public class BinaryTextureContainer : TreeNodeCustom
public class BinaryTextureContainer : TreeNodeFile
{
public Dictionary<string, TextureData> Textures;
@ -201,7 +201,7 @@ namespace FirstPlugin
SelectedImageKey = "bntx";
}
public BinaryTextureContainer(byte[] data, string Name = "", string FileName = "")
public BinaryTextureContainer(byte[] data, string Name = "", string FileName = "", IFileFormat handler = null)
{
if (data.Length == 0)
data = CreateNewBNTX(Name);
@ -260,7 +260,6 @@ namespace FirstPlugin
Textures = new Dictionary<string, TextureData>();
Data = data;
BinaryTexFile = new BntxFile(new MemoryStream(Data));
Text = BinaryTexFile.Name;
@ -305,15 +304,19 @@ namespace FirstPlugin
public void ImportTexture()
{
OpenFileDialog ofd = new OpenFileDialog();
// ofd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
ofd.Filter = "Supported Formats|*.bftex;*.dds;|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
/* "Portable Network Graphics |*.png|" +
"Joint Photographic Experts Group |*.jpg|" +
"Bitmap Image |*.bmp|" +
"Tagged Image File Format |*.tiff|" */
"All files(*.*)|*.*";
/* ofd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
"Portable Network Graphics |*.png|" +
"Joint Photographic Experts Group |*.jpg|" +
"Bitmap Image |*.bmp|" +
"Tagged Image File Format |*.tiff|" +
"All files(*.*)|*.*";*/
ofd.Filter = "Supported Formats|*.bftex;*.dds|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
"All files(*.*)|*.*";
ofd.DefaultExt = "bftex";
ofd.Multiselect = true;
@ -325,6 +328,8 @@ namespace FirstPlugin
foreach (string name in ofd.FileNames)
{
string ext = Path.GetExtension(name);
ext = ext.ToLower();
if (ext == ".dds" || ext == ".bftex")
{
AddTexture(name);
@ -445,6 +450,8 @@ namespace FirstPlugin
var importer = new TextureImporterSettings();
string ext = Path.GetExtension(name);
ext = ext.ToLower();
switch (ext)
{
case ".bftex":
@ -467,6 +474,8 @@ namespace FirstPlugin
TextureData texData = null;
string ext = Path.GetExtension(name);
ext = ext.ToLower();
switch (ext)
{
case ".bftex":
@ -627,7 +636,7 @@ namespace FirstPlugin
{
public Texture Texture;
public BntxFile bntxFile;
public List<byte[]> mipmaps = new List<byte[]>();
public List<List<byte[]>> mipmaps = new List<List<byte[]>>();
public BRTI_Texture renderedGLTex = new BRTI_Texture();
BNTXEditor BNTXEditor;
@ -723,7 +732,7 @@ namespace FirstPlugin
throw new Exception("No texture data found");
}
renderedGLTex.data = mipmaps[0];
renderedGLTex.data = mipmaps[0][0];
renderedGLTex.width = (int)Texture.Width;
renderedGLTex.height = (int)Texture.Height;
@ -757,7 +766,7 @@ namespace FirstPlugin
renderedGLTex.type = PixelInternalFormat.CompressedRgRgtc2;
break;
case SurfaceFormat.BC5_SNORM:
renderedGLTex.data = DDS_Decompress.DecompressBC5(mipmaps[0], (int)Texture.Width, (int)Texture.Height, true, true);
renderedGLTex.data = DDS_Decompress.DecompressBC5(mipmaps[0][0], (int)Texture.Width, (int)Texture.Height, true, true);
renderedGLTex.type = PixelInternalFormat.Rgba;
renderedGLTex.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
break;
@ -912,15 +921,19 @@ namespace FirstPlugin
private void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
// ofd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
ofd.Filter = "Supported Formats|*.bftex;*.dds;|" +
"Binary Texture |*.bftex|" +
/* ofd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
/* "Portable Network Graphics |*.png|" +
"Joint Photographic Experts Group |*.jpg|" +
"Bitmap Image |*.bmp|" +
"Tagged Image File Format |*.tiff|" */
"All files(*.*)|*.*";
"Portable Network Graphics |*.png|" +
"Joint Photographic Experts Group |*.jpg|" +
"Bitmap Image |*.bmp|" +
"Tagged Image File Format |*.tiff|" +
"All files(*.*)|*.*";*/
ofd.Filter = "Supported Formats|*.bftex;*.dds|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
"All files(*.*)|*.*";
ofd.Multiselect = false;
if (ofd.ShowDialog() == DialogResult.OK)
@ -931,6 +944,8 @@ namespace FirstPlugin
public void Replace(string FileName)
{
string ext = Path.GetExtension(FileName);
ext = ext.ToLower();
switch (ext)
{
case ".bftex":
@ -982,9 +997,12 @@ namespace FirstPlugin
Export(sfd.FileName);
}
}
public void Export(string FileName)
public void Export(string FileName, bool ExportSurfaceLevel = false,
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
{
string ext = Path.GetExtension(FileName);
ext = ext.ToLower();
switch (ext)
{
case ".bftex":
@ -998,9 +1016,9 @@ namespace FirstPlugin
break;
}
}
internal void SaveBitMap(string FileName)
internal void SaveBitMap(string FileName, int SurfaceLevel = 0, int MipLevel = 0)
{
Bitmap bitMap = DisplayTexture();
Bitmap bitMap = DisplayTexture(MipLevel, SurfaceLevel);
bitMap.Save(FileName);
}
@ -1091,31 +1109,39 @@ namespace FirstPlugin
uint blkHeight = blk_dim & 0xF;
int linesPerBlockHeight = (1 << (int)tex.BlockHeightLog2) * 8;
int blockHeightShift = 0;
uint bpp = Formats.bpps((uint)((int)tex.Format >> 8));
for (int mipLevel = 0; mipLevel < tex.TextureData.Length; mipLevel++)
for (int arrayLevel = 0; arrayLevel < tex.ArrayLength; arrayLevel++)
{
uint width = (uint)Math.Max(1, tex.Width >> mipLevel);
uint height = (uint)Math.Max(1, tex.Height >> mipLevel);
int blockHeightShift = 0;
uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;
List<byte[]> mips = new List<byte[]>();
for (int mipLevel = 0; mipLevel < tex.TextureData[arrayLevel].Count; mipLevel++)
{
uint width = (uint)Math.Max(1, tex.Width >> mipLevel);
uint height = (uint)Math.Max(1, tex.Height >> mipLevel);
if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
blockHeightShift += 1;
uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;
byte[] result = TegraX1Swizzle.deswizzle(width, height, blkWidth, blkHeight, target, bpp, (uint)tex.TileMode, (int)Math.Max(0, tex.BlockHeightLog2 - blockHeightShift), tex.TextureData[mipLevel]);
//Create a copy and use that to remove uneeded data
byte[] result_ = new byte[size];
Array.Copy(result, 0, result_, 0, size);
if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
blockHeightShift += 1;
mipmaps.Add(result_);
byte[] result = TegraX1Swizzle.deswizzle(width, height, blkWidth, blkHeight, target, bpp, (uint)tex.TileMode, (int)Math.Max(0, tex.BlockHeightLog2 - blockHeightShift), tex.TextureData[arrayLevel][mipLevel]);
//Create a copy and use that to remove uneeded data
byte[] result_ = new byte[size];
Array.Copy(result, 0, result_, 0, size);
mips.Add(result_);
}
mipmaps.Add(mips);
}
Texture = tex;
}
public Bitmap DisplayTexture(int DisplayMipIndex = 0)
public Bitmap DisplayTexture(int DisplayMipIndex = 0, int ArrayIndex = 0)
{
LoadTexture(Texture);
@ -1127,7 +1153,7 @@ namespace FirstPlugin
uint width = (uint)Math.Max(1, Texture.Width >> DisplayMipIndex);
uint height = (uint)Math.Max(1, Texture.Height >> DisplayMipIndex);
byte[] data = mipmaps[DisplayMipIndex];
byte[] data = mipmaps[ArrayIndex][DisplayMipIndex];
return DecodeBlock(data, width, height, Texture.Format);
}

View File

@ -0,0 +1,546 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using Syroot.NintenTools.Bfres;
using Syroot.NintenTools.Bfres.GX2;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using Smash_Forge.Rendering;
using WeifenLuo.WinFormsUI.Docking;
namespace FirstPlugin
{
public class FTEXContainer : TreeNodeCustom
{
public Dictionary<string, FTEX> Textures = new Dictionary<string, FTEX>(); //To get instance of classes
public FTEXContainer()
{
Text = "Textures";
Name = "FTEXCONT";
ContextMenu = new ContextMenu();
MenuItem exportAll = new MenuItem("Export All Textures");
ContextMenu.MenuItems.Add(exportAll);
exportAll.Click += ExportAll;
MenuItem clear = new MenuItem("Clear");
ContextMenu.MenuItems.Add(clear);
clear.Click += Clear;
}
private void Clear(object sender, EventArgs args)
{
Nodes.Clear();
Textures.Clear();
}
public void RefreshGlTexturesByName()
{
}
public override void OnClick(TreeView treeview)
{
}
public void RemoveTexture(FTEX textureData)
{
Nodes.Remove(textureData);
Textures.Remove(textureData.Text);
Viewport.Instance.UpdateViewport();
}
private void ExportAll(object sender, EventArgs args)
{
List<string> Formats = new List<string>();
Formats.Add("Cafe Binary Textures (.bftex)");
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;
TextureFormatExport form = new TextureFormatExport(Formats);
if (form.ShowDialog() == DialogResult.OK)
{
foreach (FTEX tex in Nodes)
{
if (form.Index == 0)
tex.SaveBinaryTexture(folderPath + '\\' + tex.Text + ".bftex");
else if (form.Index == 1)
tex.SaveDDS(folderPath + '\\' + tex.Text + ".dds");
else if (form.Index == 2)
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".png");
else if (form.Index == 3)
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".jpg");
else if (form.Index == 4)
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".bmp");
else if (form.Index == 5)
tex.SaveBitMap(folderPath + '\\' + tex.Text + ".tiff");
}
}
}
}
}
public class FTEX : TreeNodeCustom
{
public int format;
public RenderableTex renderedTex = new RenderableTex();
GX2CompSel ChannelRed;
GX2CompSel ChannelBlue;
GX2CompSel ChannelGreen;
GX2CompSel ChannelAlpha;
public FTEX()
{
ContextMenu = new ContextMenu();
MenuItem export = new MenuItem("Export");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
MenuItem remove = new MenuItem("Remove");
ContextMenu.MenuItems.Add(remove);
remove.Click += Remove;
MenuItem rename = new MenuItem("Rename");
ContextMenu.MenuItems.Add(rename);
rename.Click += Rename;
}
private void Replace(object sender, EventArgs args)
{
}
private void Rename(object sender, EventArgs args)
{
RenameDialog dialog = new RenameDialog();
dialog.SetString(Text);
if (dialog.ShowDialog() == DialogResult.OK)
{
((FTEXContainer)Parent).Textures.Remove(Text);
Text = dialog.textBox1.Text;
((FTEXContainer)Parent).Textures.Add(Text, this);
}
}
private void Remove(object sender, EventArgs args)
{
((FTEXContainer)Parent).RemoveTexture(this);
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Text;
sfd.DefaultExt = "bftex";
sfd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
"Portable Network Graphics |*.png|" +
"Joint Photographic Experts Group |*.jpg|" +
"Bitmap Image |*.bmp|" +
"Tagged Image File Format |*.tiff|" +
"All files(*.*)|*.*";
if (sfd.ShowDialog() == DialogResult.OK)
{
Export(sfd.FileName);
}
}
public void Read(Texture tex)
{
ImageKey = "Texture";
SelectedImageKey = "Texture";
Text = tex.Name;
ChannelRed = tex.CompSelR;
ChannelGreen = tex.CompSelG;
ChannelBlue = tex.CompSelB;
ChannelAlpha = tex.CompSelA;
renderedTex.width = (int)tex.Width;
renderedTex.height = (int)tex.Height;
format = (int)tex.Format;
int swizzle = (int)tex.Swizzle;
int pitch = (int)tex.Pitch;
renderedTex.data = GTX.swizzleBC(tex.Data, renderedTex.width, renderedTex.height, format, (int)tex.TileMode, pitch, swizzle);
}
public void Export(string FileName, bool ExportSurfaceLevel = false,
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
{
string ext = System.IO.Path.GetExtension(FileName);
ext = ext.ToLower();
switch (ext)
{
case ".bftex":
SaveBinaryTexture(FileName);
break;
case ".dds":
SaveDDS(FileName);
break;
default:
SaveBitMap(FileName);
break;
}
}
internal void SaveBitMap(string FileName, int SurfaceLevel = 0, int MipLevel = 0)
{
Bitmap bitMap = DisplayTexture(MipLevel, SurfaceLevel);
bitMap.Save(FileName);
}
internal void SaveBinaryTexture(string FileName)
{
Console.WriteLine("Test");
// Texture.Export(FileName, bntxFile);
}
internal void SaveDDS(string FileName)
{
DDS dds = new DDS();
dds.header = new DDS.Header();
dds.header.width = (uint)renderedTex.width;
dds.header.height = (uint)renderedTex.width;
dds.header.mipmapCount = (uint)renderedTex.mipmaps[0].Count;
bool IsDX10 = false;
switch (format)
{
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM):
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB):
dds.header.ddspf.fourCC = "DXT1";
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM):
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB):
dds.header.ddspf.fourCC = "DXT3";
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM):
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB):
dds.header.ddspf.fourCC = "DXT5";
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM):
IsDX10 = true;
dds.DX10header = new DDS.DX10Header();
dds.DX10header.DXGI_Format = DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM):
IsDX10 = true;
dds.DX10header = new DDS.DX10Header();
dds.DX10header.DXGI_Format = DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM):
IsDX10 = true;
dds.DX10header = new DDS.DX10Header();
dds.DX10header.DXGI_Format = DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM):
IsDX10 = true;
dds.DX10header = new DDS.DX10Header();
dds.DX10header.DXGI_Format = DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM;
break;
default:
throw new Exception($"Format {(GTX.GX2SurfaceFormat)format} not supported!");
}
if (IsDX10)
dds.header.ddspf.fourCC = "DX10";
dds.Save(dds, FileName, renderedTex.mipmaps, IsDX10);
}
public void LoadOpenGLTexture()
{
if (OpenTKSharedResources.SetupStatus == OpenTKSharedResources.SharedResourceStatus.Unitialized)
return;
switch (format)
{
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRedRgtc1;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedSignedRedRgtc1;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgRgtc2;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM):
//OpenTK doesn't load BC5 SNORM textures right so I'll use the same decompress method bntx has
byte[] fixBC5 = DDS_Decompress.DecompressBC5(renderedTex.data, renderedTex.width, renderedTex.height, true, true);
renderedTex.data = fixBC5;
renderedTex.pixelInternalFormat = PixelInternalFormat.Rgba;
renderedTex.pixelFormat = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.Rgba;
renderedTex.pixelFormat = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
break;
}
renderedTex.display = loadImage(renderedTex);
}
public static int loadImage(RenderableTex t)
{
int texID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texID);
if (t.pixelInternalFormat != PixelInternalFormat.Rgba)
{
GL.CompressedTexImage2D<byte>(TextureTarget.Texture2D, 0, (InternalFormat)t.pixelInternalFormat,
t.width, t.height, 0, getImageSize(t), t.data);
//Debug.WriteLine(GL.GetError());
}
else
{
GL.TexImage2D<byte>(TextureTarget.Texture2D, 0, t.pixelInternalFormat, t.width, t.height, 0,
t.pixelFormat, PixelType.UnsignedByte, t.data);
}
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
return texID;
}
public static int getImageSize(RenderableTex t)
{
switch (t.pixelInternalFormat)
{
case PixelInternalFormat.CompressedRgbaS3tcDxt1Ext:
case PixelInternalFormat.CompressedSrgbAlphaS3tcDxt1Ext:
case PixelInternalFormat.CompressedRedRgtc1:
case PixelInternalFormat.CompressedSignedRedRgtc1:
return (t.width * t.height / 2);
case PixelInternalFormat.CompressedRgbaS3tcDxt3Ext:
case PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext:
case PixelInternalFormat.CompressedRgbaS3tcDxt5Ext:
case PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext:
case PixelInternalFormat.CompressedSignedRgRgtc2:
case PixelInternalFormat.CompressedRgRgtc2:
return (t.width * t.height);
case PixelInternalFormat.Rgba:
return t.data.Length;
default:
return t.data.Length;
}
}
public unsafe Bitmap GLTextureToBitmap(RenderableTex t, int id)
{
Bitmap bitmap = new Bitmap(t.width, t.height);
System.Drawing.Imaging.BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, t.width, t.height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.BindTexture(TextureTarget.Texture2D, id);
GL.GetTexImage(TextureTarget.Texture2D, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bitmapData.Scan0);
bitmap.UnlockBits(bitmapData);
return bitmap;
}
public override void OnClick(TreeView treeView)
{
foreach (Control control in FirstPlugin.MainF.Controls)
{
if (control is DockPanel)
{
if (FirstPlugin.DockedEditorS == null)
{
FirstPlugin.DockedEditorS = new DockContent();
FirstPlugin.DockedEditorS.Show((DockPanel)control, PluginRuntime.FSHPDockState);
}
}
}
if (!EditorIsActive(FirstPlugin.DockedEditorS))
{
FirstPlugin.DockedEditorS.Controls.Clear();
FTEXEditor FTEXEditor = new FTEXEditor();
FTEXEditor.Text = Text;
FTEXEditor.Dock = DockStyle.Fill;
FTEXEditor.LoadPicture(DisplayTexture());
FTEXEditor.LoadProperty(this);
FirstPlugin.DockedEditorS.Controls.Add(FTEXEditor);
}
}
public bool EditorIsActive(DockContent dock)
{
foreach (Control ctrl in dock.Controls)
{
if (ctrl is FTEXEditor)
{
dock.Text = Text;
((FTEXEditor)ctrl).LoadPicture(DisplayTexture());
((FTEXEditor)ctrl).LoadProperty(this);
return true;
}
}
return false;
}
public class RenderableTex
{
public int width, height;
public int display;
public PixelInternalFormat pixelInternalFormat;
public PixelFormat pixelFormat;
public PixelType pixelType = PixelType.UnsignedByte;
public int mipMapCount;
public List<List<byte[]>> mipmaps = new List<List<byte[]>>();
public byte[] data
{
get
{
return mipmaps[0][0];
}
set
{
List<byte[]> mips = new List<byte[]>();
mips.Add(value);
mipmaps.Add(mips);
}
}
public class Surface
{
}
}
public Bitmap DisplayTexture(int DisplayMipIndex = 0, int ArrayIndex = 0)
{
if (renderedTex.mipmaps.Count <= 0)
{
throw new Exception("No texture data found");
}
uint width = (uint)Math.Max(1, renderedTex.width >> DisplayMipIndex);
uint height = (uint)Math.Max(1, renderedTex.height >> DisplayMipIndex);
byte[] data = renderedTex.mipmaps[ArrayIndex][DisplayMipIndex];
return DecodeBlock(data, width, height, format);
}
public static Bitmap DecodeBlock(byte[] data, uint Width, uint Height, int Format)
{
Bitmap decomp;
switch (Format)
{
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM):
decomp = DDS_Decompress.DecompressBC1(data, (int)Width, (int)Height, false); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB):
decomp = DDS_Decompress.DecompressBC1(data, (int)Width, (int)Height, true); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM):
decomp = DDS_Decompress.DecompressBC3(data, (int)Width, (int)Height, false); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB):
decomp = DDS_Decompress.DecompressBC3(data, (int)Width, (int)Height, true); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM):
decomp = DDS_Decompress.DecompressBC4(data, (int)Width, (int)Height, false); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM):
decomp = DDS_Decompress.DecompressBC4(data, (int)Width, (int)Height, true); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM):
decomp = DDS_Decompress.DecompressBC5(data, (int)Width, (int)Height, false); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM):
decomp = DDS_Decompress.DecompressBC5(data, (int)Width, (int)Height, true); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM):
decomp = DDS_PixelDecode.DecodeR8G8B8A8(data, (int)Width, (int)Height); break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT):
decomp = DDS_PixelDecode.DecodeR8G8B8A8(data, (int)Width, (int)Height); break;
default:
decomp = Properties.Resources.TextureError;
Console.WriteLine($"Format {Format} not supported!");
break;
}
return decomp;
}
public Bitmap UpdateBitmap(Bitmap image)
{
return ColorComponentSelector(image, ChannelRed, ChannelGreen, ChannelBlue, ChannelAlpha);
}
public static Bitmap ColorComponentSelector(Bitmap image, GX2CompSel R, GX2CompSel G, GX2CompSel B, GX2CompSel A)
{
BitmapExtension.ColorSwapFilter color = new BitmapExtension.ColorSwapFilter();
if (R == GX2CompSel.ChannelR)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.Red;
if (R == GX2CompSel.ChannelG)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.Green;
if (R == GX2CompSel.ChannelB)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.Blue;
if (R == GX2CompSel.ChannelA)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.Alpha;
if (R == GX2CompSel.Always0)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.One;
if (R == GX2CompSel.Always1)
color.CompRed = BitmapExtension.ColorSwapFilter.Red.Zero;
if (G == GX2CompSel.ChannelR)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Red;
if (G == GX2CompSel.ChannelG)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Green;
if (G == GX2CompSel.ChannelB)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Blue;
if (G == GX2CompSel.ChannelA)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Alpha;
if (G == GX2CompSel.Always0)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.One;
if (G == GX2CompSel.Always1)
color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Zero;
if (B == GX2CompSel.ChannelR)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Red;
if (B == GX2CompSel.ChannelG)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Green;
if (B == GX2CompSel.ChannelB)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Blue;
if (B == GX2CompSel.ChannelA)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Alpha;
if (B == GX2CompSel.Always0)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.One;
if (B == GX2CompSel.Always1)
color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Zero;
if (A == GX2CompSel.ChannelR)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Red;
if (A == GX2CompSel.ChannelG)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Green;
if (A == GX2CompSel.ChannelB)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Blue;
if (A == GX2CompSel.ChannelA)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Alpha;
if (A == GX2CompSel.Always0)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.One;
if (A == GX2CompSel.Always1)
color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Zero;
return BitmapExtension.SwapRGB(image, color);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FirstPlugin
{
class TexConv
{
}
}

View File

@ -20,11 +20,12 @@ namespace FirstPlugin
public CompressionType CompressionType { get; set; } = CompressionType.None;
public byte[] Data { get; set; }
public string FileName { get; set; }
public TreeNode EditorRoot { get; set; }
public TreeNodeFile EditorRoot { get; set; }
public bool IsActive { get; set; } = false;
public bool UseEditMenu { get; set; } = false;
public int Alignment { get; set; } = 0;
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public Type[] Types
{
get