1
0
mirror of synced 2024-11-30 18:24:39 +01:00

More clean up and additions

- Starting to make all texture classes use STGenericTexture. This will make all functions usable between each one and converting through other classes much easier.
- Many bug fixes to the texture importer like duped texture importing, dds opening the window, index out of range issues, etc.
- Start on titlebar information.
- Start on ASTC texture format support.
- Support TGA images.
- Support FTEX importing and saving properly.
- Export models properly along with textures (with generic classes). Todo, support rigs and bones.
This commit is contained in:
KillzXGaming 2018-12-10 18:48:51 -05:00
parent d96f4dec43
commit 716d1c4520
71 changed files with 10692 additions and 1085 deletions

3
.gitignore vendored
View File

@ -3,3 +3,6 @@
*.resources
Debug/
Release/
Switch_Toolbox/Lib/Syroot.NintenTools.Bfres.dll
Switch_Toolbox/Lib/Syroot.NintenTools.Bfres.pdb
Switch_Toolbox/Lib/Syroot.NintenTools.Bfres.xml

View File

@ -3,7 +3,6 @@ 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;

View File

@ -25,6 +25,8 @@ namespace FirstPlugin
public CompressionType CompressionType { get; set; } = CompressionType.None;
public byte[] Data { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public Type[] Types
@ -39,7 +41,6 @@ namespace FirstPlugin
public bool IsActive { get; set; } = false;
public bool UseEditMenu { get; set; } = false;
public int Alignment { get; set; } = 0;
public string FilePath { get; set; }
public bool IsWiiU
{
get
@ -353,8 +354,8 @@ namespace FirstPlugin
{
string TextureName = tex.Name;
FTEX texture = new FTEX();
texture.Read(tex);
ftexContainer.Nodes.Add(texture);
texture.Read(tex);
ftexContainer.Textures.Add(texture.Text, texture);
}
PluginRuntime.ftexContainers.Add(ftexContainer);
@ -510,7 +511,10 @@ namespace FirstPlugin
if (Nodes.ContainsKey("FTEX"))
{
foreach (FTEX tex in Nodes["FTEX"].Nodes)
{
tex.texture.Name = tex.Text;
resFileU.Textures.Add(tex.Text, tex.texture);
}
}
else
throw new Exception("Failed to find textures");
@ -526,10 +530,10 @@ namespace FirstPlugin
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)
foreach (var tex in shape.GetMaterial().TextureMaps)
{
if (!shd.samplers.ContainsValue(tex.SamplerName))
shd.samplers.Add(tex.SamplerName, tex.SamplerName);
if (!shd.samplers.ContainsValue(((MatTexture)tex).SamplerName))
shd.samplers.Add(((MatTexture)tex).SamplerName, ((MatTexture)tex).SamplerName);
}
}
@ -554,7 +558,7 @@ namespace FirstPlugin
bool ImportMissingTextures = false;
foreach (BNTX bntx in PluginRuntime.bntxContainers)
{
foreach (MatTexture tex in shape.GetMaterial().textures)
foreach (MatTexture tex in shape.GetMaterial().TextureMaps)
{
if (!bntx.Textures.ContainsKey(tex.Name))
{
@ -624,8 +628,6 @@ namespace FirstPlugin
MessageBox.Show($"Error! Sampler {samp} is unlinked!");
}
}
}
}
// ErrorList errorList = new ErrorList();

View File

@ -173,7 +173,6 @@ namespace Bfres.Structs
public Dictionary<string, float[]> anims = new Dictionary<string, float[]>();
public Dictionary<string, int> Samplers = new Dictionary<string, int>();
public List<MatTexture> textures = new List<MatTexture>();
public List<BfresRenderInfo> renderinfo = new List<BfresRenderInfo>();
public List<SamplerInfo> samplerinfo = new List<SamplerInfo>();
public Dictionary<string, BfresShaderParam> matparam = new Dictionary<string, BfresShaderParam>();

View File

@ -307,7 +307,12 @@ namespace Bfres.Structs
switch (ext)
{
case ".bfmdl":
Model.Export(sfd.FileName, GetResFile());
if (GetResFileU() != null)
{
}
else
Model.Export(sfd.FileName, GetResFile());
break;
case ".csv":
CsvModel csv = new CsvModel();
@ -337,8 +342,34 @@ namespace Bfres.Structs
System.IO.File.WriteAllBytes(sfd.FileName, csv.Save());
break;
default:
List<STGenericTexture> surfaces = new List<STGenericTexture>();
foreach (FSHP fshp in shapes)
{
foreach (var bntx in PluginRuntime.bntxContainers)
{
foreach (var tex in fshp.GetMaterial().TextureMaps)
{
if (bntx.Textures.ContainsKey(tex.Name))
{
surfaces.Add(bntx.Textures[tex.Name]);
}
}
}
foreach (var ftex in PluginRuntime.ftexContainers)
{
foreach (var tex in fshp.GetMaterial().TextureMaps)
{
if (ftex.Textures.ContainsKey(tex.Name))
{
surfaces.Add(ftex.Textures[tex.Name]);
}
}
}
}
Console.WriteLine("tex count " + surfaces.Count);
AssimpData assimp = new AssimpData();
assimp.SaveFromModel(this, sfd.FileName);
assimp.SaveFromModel(this, sfd.FileName, surfaces);
break;
}
}
@ -510,7 +541,7 @@ namespace Bfres.Structs
fmat.Text = mat.Text;
//Setup placeholder textures
//Note we can't add/remove samplers so we must fill these slots
foreach (var t in fmat.textures)
foreach (var t in fmat.TextureMaps)
{
t.wrapModeS = 0;
t.wrapModeT = 0;
@ -574,7 +605,7 @@ namespace Bfres.Structs
foreach (var tex in mat.TextureMaps)
{
foreach (var t in fmat.textures)
foreach (var t in fmat.TextureMaps)
{
if (t.Type == tex.Type)
{
@ -627,11 +658,14 @@ namespace Bfres.Structs
shape.BoneIndices = new List<ushort>();
List<string> keyList = shapes.Select(o => o.Text).ToList();
shape.Text = Utils.RenameDuplicateString(keyList, shape.Text);
Nodes["FshpFolder"].Nodes.Add(shape);
shapes.Add(shape);
}
Console.WriteLine("Finshed Importing Model");
Cursor.Current = Cursors.Default;
}
break;

View File

@ -492,7 +492,7 @@ namespace Bfres.Structs
settings.SetModelAttributes(assimp.objects[0]);
if (settings.ShowDialog() == DialogResult.OK)
{
GenericObject obj = selector.GetSelectedMesh();
STGenericObject obj = selector.GetSelectedMesh();
Cursor.Current = Cursors.WaitCursor;
VertexBufferIndex = obj.VertexBufferIndex;
@ -512,7 +512,7 @@ namespace Bfres.Structs
UpdateVertexData();
}
}
public void CreateIndexList(GenericObject ob, FMDL mdl = null)
public void CreateIndexList(STGenericObject ob, FMDL mdl = null)
{
BoneIndices = new List<ushort>();
@ -539,7 +539,7 @@ namespace Bfres.Structs
index++;
}
}
public void CreateBoneList(GenericObject ob, FMDL mdl)
public void CreateBoneList(STGenericObject ob, FMDL mdl)
{
string[] nodeArrStrings = new string[mdl.Skeleton.Node_Array.Length];

View File

@ -69,6 +69,7 @@ namespace Bfres.Structs
ZROT = 0x28,
}
public SkeletalAnim SkeletalAnim;
public ResU.SkeletalAnim SkeletalAnimU;
public BfresSkeletonAnim()
{
@ -103,6 +104,11 @@ namespace Bfres.Structs
//ResourceFile -> FMDL -> Material Folder -> this
return ((BFRES)Parent.Parent).resFile;
}
public ResU.ResFile GetResFileU()
{
//ResourceFile -> FMDL -> Material Folder -> this
return ((BFRES)Parent.Parent).resFileU;
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
@ -112,7 +118,14 @@ namespace Bfres.Structs
if (sfd.ShowDialog() == DialogResult.OK)
{
SkeletalAnim.Export(sfd.FileName, GetResFile());
if (GetResFileU() != null)
{
throw new Exception("Wii U unsupported!");
}
else
{
SkeletalAnim.Export(sfd.FileName, GetResFile());
}
}
}
private void Replace(object sender, EventArgs args)
@ -122,7 +135,14 @@ namespace Bfres.Structs
if (ofd.ShowDialog() == DialogResult.OK)
{
SkeletalAnim.Import(ofd.FileName);
if (GetResFileU() != null)
{
throw new Exception("Wii U unsupported!");
}
else
{
SkeletalAnim.Import(ofd.FileName);
}
}
SkeletalAnim.Name = Text;
}
@ -130,7 +150,75 @@ namespace Bfres.Structs
public static List<Animation> SkeletonAnimations = new List<Animation>();
public void Read(ResU.SkeletalAnim ska, ResU.ResFile b)
{
FrameCount = ska.FrameCount;
SkeletalAnimU = ska;
foreach (ResU.BoneAnim bn in ska.BoneAnims)
{
FSKANode bonean = new FSKANode(bn);
Animation.KeyNode bone = new Animation.KeyNode("");
Bones.Add(bone);
if (ska.FlagsRotate == ResU.SkeletalAnimFlagsRotate.EulerXYZ)
bone.RotType = Animation.RotationType.EULER;
else
bone.RotType = Animation.RotationType.QUATERNION;
bone.Text = bonean.Text;
for (int Frame = 0; Frame < ska.FrameCount; Frame++)
{
if (Frame == 0)
{
if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Scale))
{
bone.XSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.sca.X });
bone.YSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.sca.Y });
bone.ZSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.sca.Z });
}
if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Rotate))
{
bone.XROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.rot.X });
bone.YROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.rot.Y });
bone.ZROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.rot.Z });
bone.WROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.rot.W });
}
if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Translate))
{
bone.XPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.pos.X });
bone.YPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.pos.Y });
bone.ZPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bonean.pos.Z });
}
}
foreach (FSKATrack track in bonean.tracks)
{
KeyFrame frame = new KeyFrame();
frame.InterType = Animation.InterpolationType.HERMITE;
frame.Frame = Frame;
FSKAKey left = track.GetLeft(Frame);
FSKAKey right = track.GetRight(Frame);
float value;
value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1);
// interpolate the value and apply
switch (track.flag)
{
case (int)TrackType.XPOS: frame.Value = value; bone.XPOS.Keys.Add(frame); break;
case (int)TrackType.YPOS: frame.Value = value; bone.YPOS.Keys.Add(frame); break;
case (int)TrackType.ZPOS: frame.Value = value; bone.ZPOS.Keys.Add(frame); break;
case (int)TrackType.XROT: frame.Value = value; bone.XROT.Keys.Add(frame); break;
case (int)TrackType.YROT: frame.Value = value; bone.YROT.Keys.Add(frame); break;
case (int)TrackType.ZROT: frame.Value = value; bone.ZROT.Keys.Add(frame); break;
case (int)TrackType.XSCA: frame.Value = value; bone.XSCA.Keys.Add(frame); break;
case (int)TrackType.YSCA: frame.Value = value; bone.YSCA.Keys.Add(frame); break;
case (int)TrackType.ZSCA: frame.Value = value; bone.ZSCA.Keys.Add(frame); break;
}
}
}
}
}
public void Read(SkeletalAnim ska, ResFile b)
{
@ -221,7 +309,61 @@ namespace Bfres.Structs
public Vector3 sca, pos;
public Vector4 rot;
public List<FSKATrack> tracks = new List<FSKATrack>();
public FSKANode(ResU.BoneAnim b)
{
return;
Text = b.Name;
sca = new Vector3(b.BaseData.Scale.X, b.BaseData.Scale.Y, b.BaseData.Scale.Z);
rot = new Vector4(b.BaseData.Rotate.X, b.BaseData.Rotate.Y, b.BaseData.Rotate.Z, b.BaseData.Rotate.W);
pos = new Vector3(b.BaseData.Translate.X, b.BaseData.Translate.Y, b.BaseData.Translate.Z);
foreach (ResU.AnimCurve tr in b.Curves)
{
FSKATrack t = new FSKATrack();
t.flag = (int)tr.AnimDataOffset;
tracks.Add(t);
float tanscale = tr.Delta;
if (tanscale == 0)
tanscale = 1;
for (int i = 0; i < (ushort)tr.Frames.Length; i++)
{
if (tr.CurveType == ResU.AnimCurveType.Cubic)
{
int framedata = (int)tr.Frames[i];
float keydata = tr.Offset + ((tr.Keys[i, 0] * tr.Scale));
float keydata2 = tr.Offset + ((tr.Keys[i, 1] * tr.Scale));
float keydata3 = tr.Offset + ((tr.Keys[i, 2] * tr.Scale));
float keydata4 = tr.Offset + ((tr.Keys[i, 3] * tr.Scale));
}
if (tr.KeyType == ResU.AnimCurveKeyType.Int16)
{
}
else if (tr.KeyType == ResU.AnimCurveKeyType.Single)
{
}
else if (tr.KeyType == ResU.AnimCurveKeyType.SByte)
{
}
t.keys.Add(new FSKAKey()
{
frame = (int)tr.Frames[i],
unk1 = tr.Offset + ((tr.Keys[i, 0] * tr.Scale)),
unk2 = tr.Offset + ((tr.Keys[i, 1] * tr.Scale)),
unk3 = tr.Offset + ((tr.Keys[i, 2] * tr.Scale)),
unk4 = tr.Offset + ((tr.Keys[i, 3] * tr.Scale)),
});
}
}
}
public FSKANode(BoneAnim b)
{
Text = b.Name;

View File

@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Syroot.NintenTools.NSW.Bfres;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using ResU = Syroot.NintenTools.Bfres;
using FirstPlugin;
using OpenTK;
namespace Bfres.Structs
{
@ -12,6 +14,7 @@ namespace Bfres.Structs
public class FSKL : STSkeleton
{
public int[] Node_Array;
public List<Matrix3x4> matrices = new List<Matrix3x4>();
public fsklNode node;
public class fsklNode : TreeNodeCustom
{

View File

@ -21,6 +21,7 @@ namespace FirstPlugin
{
Model model = new Model();
model.Name = fmdl.Text;
model.Path = "";
model.Shapes = new List<Shape>();
model.VertexBuffers = new List<VertexBuffer>();
model.Materials = new List<Material>();
@ -590,7 +591,7 @@ namespace FirstPlugin
}
public static void ReadTextureRefs(this FMAT m, Material mat)
{
m.textures.Clear();
m.TextureMaps.Clear();
int AlbedoCount = 0;
int id = 0;
@ -790,7 +791,7 @@ namespace FirstPlugin
texture.Name = TextureName;
m.textures.Add(texture);
m.TextureMaps.Add(texture);
id++;
}
@ -872,7 +873,7 @@ namespace FirstPlugin
mat.TextureRefs = new List<string>();
mat.TextureRefs.Clear();
foreach (var textu in m.textures)
foreach (var textu in m.TextureMaps)
mat.TextureRefs.Add(textu.Name);
}

View File

@ -23,6 +23,7 @@ namespace FirstPlugin
{
Model model = new Model();
model.Name = fmdl.Text;
model.Path = "";
model.Shapes = new ResDict<Shape>();
model.VertexBuffers = new List<VertexBuffer>();
model.Materials = new ResDict<Material>();
@ -39,13 +40,11 @@ namespace FirstPlugin
{
BFRES.CheckMissingTextures(shape);
SetShape(shape, shape.ShapeU);
shape.ShapeU.SubMeshBoundingNodes = new List<BoundingNode>();
model.Shapes.Add(shape.Text, shape.ShapeU);
model.VertexBuffers.Add(shape.VertexBufferU);
shape.ShapeU.VertexBufferIndex = (ushort)(model.VertexBuffers.Count - 1);
BFRES.SetShaderAssignAttributes(shape.GetMaterial().shaderassign, shape);
// BFRES.SetShaderAssignAttributes(shape.GetMaterial().shaderassign, shape);
}
foreach (FMAT mat in fmdl.materials.Values)
@ -257,15 +256,15 @@ namespace FirstPlugin
if (fshp.VertexSkinCount == 1)
{
Matrix4 sb = model.Skeleton.bones[model.Skeleton.Node_Array[v.boneIds[0]]].transform;
v.pos = Vector3.TransformPosition(v.pos, sb);
v.nrm = Vector3.TransformNormal(v.nrm, sb);
// Matrix4 sb = model.Skeleton.bones[model.Skeleton.Node_Array[v.boneIds[0]]].transform;
// v.pos = Vector3.TransformPosition(v.pos, sb);
// v.nrm = Vector3.TransformNormal(v.nrm, sb);
}
if (fshp.VertexSkinCount == 0)
{
Matrix4 NoBindFix = model.Skeleton.bones[fshp.boneIndx].transform;
v.pos = Vector3.TransformPosition(v.pos, NoBindFix);
v.nrm = Vector3.TransformNormal(v.nrm, NoBindFix);
// Matrix4 NoBindFix = model.Skeleton.bones[fshp.boneIndx].transform;
// v.pos = Vector3.TransformPosition(v.pos, NoBindFix);
// v.nrm = Vector3.TransformNormal(v.nrm, NoBindFix);
}
fshp.vertices.Add(v);
}
@ -288,20 +287,32 @@ namespace FirstPlugin
RenderableSkeleton.Node_Array[nodes] = node;
nodes++;
}
for (int i = 0; i < skeleton.Bones.Count; i++)
{
if (skeleton.InverseModelMatrices == null)
break;
if (i < skeleton.InverseModelMatrices.Count)
RenderableSkeleton.matrices.Add(Utils.ToMat3x4(skeleton.InverseModelMatrices[i]));
else
RenderableSkeleton.matrices.Add(Matrix3x4.Zero);
}
foreach (Bone bone in skeleton.Bones.Values)
{
BfresBone STBone = new BfresBone(RenderableSkeleton);
SetBone(STBone, bone);
STBone.BFRESRender = RenderableSkeleton.node.BFRESRender; //to update viewport on bone edits
RenderableSkeleton.bones.Add(STBone);
if (bone.InverseMatrix != null)
RenderableSkeleton.matrices.Add(Utils.ToMat3x4(bone.InverseMatrix));
}
RenderableSkeleton.update();
RenderableSkeleton.reset();
foreach (var bone in RenderableSkeleton.bones)
if (bone.Parent == null)
skl.Nodes.Add(bone);
// foreach (var bone in RenderableSkeleton.bones)
// if (bone.Parent == null)
// skl.Nodes.Add(bone);
Runtime.abstractGlDrawables.Add(RenderableSkeleton);
}
@ -386,7 +397,7 @@ namespace FirstPlugin
}
public static void ReadTextureRefs(this FMAT m, Material mat)
{
m.textures.Clear();
m.TextureMaps.Clear();
int AlbedoCount = 0;
int id = 0;
@ -577,7 +588,7 @@ namespace FirstPlugin
}
}
texture.Name = TextureName;
m.textures.Add(texture);
m.TextureMaps.Add(texture);
id++;
}
@ -660,7 +671,7 @@ namespace FirstPlugin
mat.TextureRefs = new List<TextureRef>();
mat.TextureRefs.Clear();
foreach (var textu in m.textures)
foreach (var textu in m.TextureMaps)
{
TextureRef texref = new TextureRef();
texref.Name = textu.Name;

View File

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

View File

@ -84,7 +84,7 @@ namespace FirstPlugin
Model model = new Model();
STGenericObject STobj = new STGenericObject();
Vertex vtx = new Vertex();
GenericObject.LOD_Mesh lod = new GenericObject.LOD_Mesh();
STGenericObject.LOD_Mesh lod = new STGenericObject.LOD_Mesh();
int Index = 0;
int ww = 0;
while (true)
@ -101,7 +101,7 @@ namespace FirstPlugin
models.Add(model);
STobj.ObjectName = model.Name;
lod = new GenericObject.LOD_Mesh();
lod = new STGenericObject.LOD_Mesh();
lod.IndexFormat = STIndexFormat.UInt16;
lod.PrimitiveType = STPolygonType.Triangle;
STobj.lodMeshes.Add(lod);
@ -266,7 +266,7 @@ namespace FirstPlugin
if (objects[0].weightsT.Count != objects[0].vertices.Count)
throw new Exception("Incorrect vertex amount");
foreach (GenericObject obj in objects)
foreach (STGenericObject obj in objects)
{
obj.lodMeshes[0].GenerateSubMesh();
for (int v = 0; v < obj.vertices.Count; v++)
@ -302,7 +302,7 @@ namespace FirstPlugin
using (System.IO.StreamWriter file = new System.IO.StreamWriter(mem))
{
foreach (GenericObject obj in objects)
foreach (STGenericObject obj in objects)
{
file.WriteLine($"Obj Name:" + obj.ObjectName);
file.WriteLine($"Bone_Suport");

View File

@ -140,10 +140,14 @@ namespace FirstPlugin
{
string dir = Path.GetDirectoryName(sarc.FullName);
Console.WriteLine(sarc.FullName);
if (dir == string.Empty)
sarc.FullName = sarc.Text;
else
sarc.FullName = Path.Combine(dir, sarc.Text);
sarc.FullName = dir + "/" + sarc.Text;
Console.WriteLine(sarc.FullName);
sarcData.Files.Add(sarc.FullName, sarc.Data);
}

View File

@ -26,10 +26,12 @@ namespace FirstPlugin
public enum BNTXImageFormat
{
IMAGE_FORMAT_INVALID = 0x0,
IMAGE_FORMAT_R8_G8_B8_A8 = 0x0b,
IMAGE_FORMAT_R5_G6_B5 = 0x07,
IMAGE_FORMAT_R8 = 0x02,
IMAGE_FORMAT_R8_G8 = 0x09,
IMAGE_FORMAT_R16 = 0x0a,
IMAGE_FORMAT_R8_G8_B8_A8 = 0x0b,
IMAGE_FORMAT_R11_G11_B11_A10 = 0x0f,
IMAGE_FORMAT_BC1 = 0x1a,
IMAGE_FORMAT_BC2 = 0x1b,
IMAGE_FORMAT_BC3 = 0x1c,
@ -37,6 +39,20 @@ namespace FirstPlugin
IMAGE_FORMAT_BC5 = 0x1e,
IMAGE_FORMAT_BC6 = 0x1f,
IMAGE_FORMAT_BC7 = 0x20,
IMAGE_FORMAT_ASTC4x4 = 0x2d,
IMAGE_FORMAT_ASTC5x4 = 0x2e,
IMAGE_FORMAT_ASTC5x5 = 0x2f,
IMAGE_FORMAT_ASTC6x5 = 0x30,
IMAGE_FORMAT_ASTC6x6 = 0x31,
IMAGE_FORMAT_ASTC8x5 = 0x32,
IMAGE_FORMAT_ASTC8x6 = 0x33,
IMAGE_FORMAT_ASTC8x8 = 0x34,
IMAGE_FORMAT_ASTC10x5 = 0x35,
IMAGE_FORMAT_ASTC10x6 = 0x36,
IMAGE_FORMAT_ASTC10x8 = 0x37,
IMAGE_FORMAT_ASTC10x10 = 0x38,
IMAGE_FORMAT_ASTC12x10 = 0x39,
IMAGE_FORMAT_ASTC12x12 = 0x3a
};
public enum BNTXImageTypes
@ -57,22 +73,22 @@ namespace FirstPlugin
case (uint)BNTXImageFormat.IMAGE_FORMAT_BC5:
case (uint)BNTXImageFormat.IMAGE_FORMAT_BC6:
case (uint)BNTXImageFormat.IMAGE_FORMAT_BC7:
case 0x2d:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC4x4:
return 0x44;
case 0x2e: return 0x54;
case 0x2f: return 0x55;
case 0x30: return 0x65;
case 0x31: return 0x66;
case 0x32: return 0x85;
case 0x33: return 0x86;
case 0x34: return 0x88;
case 0x35: return 0xa5;
case 0x36: return 0xa6;
case 0x37: return 0xa8;
case 0x38: return 0xaa;
case 0x39: return 0xca;
case 0x3a: return 0xcc;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC5x4: return 0x54;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC5x5: return 0x55;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC6x5: return 0x65;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC6x6: return 0x66;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC8x5: return 0x85;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC8x6: return 0x86;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC8x8: return 0x88;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC10x5: return 0xa5;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC10x6: return 0xa6;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC10x8: return 0xa8;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC10x10: return 0xaa;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC12x10: return 0xca;
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC12x12: return 0xcc;
default: return 0x11;
}
@ -98,19 +114,19 @@ namespace FirstPlugin
case (uint)BNTXImageFormat.IMAGE_FORMAT_BC5:
case (uint)BNTXImageFormat.IMAGE_FORMAT_BC6:
case (uint)BNTXImageFormat.IMAGE_FORMAT_BC7:
case 0x2e:
case 0x2f:
case 0x30:
case 0x31:
case 0x32:
case 0x33:
case 0x34:
case 0x35:
case 0x36:
case 0x37:
case 0x38:
case 0x39:
case 0x3a:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC5x4:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC5x5:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC6x5:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC6x6:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC8x5:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC8x6:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC8x8:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC10x5:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC10x6:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC10x8:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC10x10:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC12x10:
case (uint)BNTXImageFormat.IMAGE_FORMAT_ASTC12x12:
return 16;
default: return 0x00;
}
@ -144,17 +160,31 @@ namespace FirstPlugin
}
class MenuExt : IFileMenuExtension
{
public ToolStripItemDark[] NewFileMenuExtensions => null;
public ToolStripItemDark[] ToolsMenuExtensions => newFileExt;
public ToolStripItemDark[] NewFileMenuExtensions => newFileExt;
public ToolStripItemDark[] ToolsMenuExtensions => toolExt;
public ToolStripItemDark[] TitleBarExtensions => null;
public ToolStripItemDark[] CompressionMenuExtensions => null;
public ToolStripItemDark[] ExperimentalMenuExtensions => null;
ToolStripItemDark[] toolExt = new ToolStripItemDark[1];
ToolStripItemDark[] newFileExt = new ToolStripItemDark[1];
public MenuExt()
{
newFileExt[0] = new ToolStripItemDark("Extract BNTX");
newFileExt[0].Click += Export;
toolExt[0] = new ToolStripItemDark("Extract BNTX");
toolExt[0].Click += Export;
newFileExt[0] = new ToolStripItemDark("BNTX");
newFileExt[0].Click += New;
}
private void New(object sender, EventArgs args)
{
BNTX bntx = new BNTX();
bntx.FileName = "textures.bntx";
bntx.Data = CreateNewBNTX("textures.bntx");
bntx.Load();
ObjectList.Instance.treeView1.Nodes.Add(bntx);
}
private void Export(object sender, EventArgs args)
{
@ -194,6 +224,7 @@ namespace FirstPlugin
MenuItem rename = new MenuItem("Rename");
MenuItem importTex = new MenuItem("Import Texture");
MenuItem exportAll = new MenuItem("Export All Textures");
MenuItem sort = new MenuItem("Sort");
MenuItem clear = new MenuItem("Clear");
private bool hasParent;
@ -232,10 +263,6 @@ namespace FirstPlugin
FileNameText = FileName;
if (Data.Length == 0)
Data = CreateNewBNTX(Name);
LoadFile(Data, Name);
PluginRuntime.bntxContainers.Add(this);
@ -249,6 +276,7 @@ namespace FirstPlugin
ContextMenu.MenuItems.Add(rename);
ContextMenu.MenuItems.Add(importTex);
ContextMenu.MenuItems.Add(exportAll);
ContextMenu.MenuItems.Add(sort);
ContextMenu.MenuItems.Add(clear);
save.Click += Save;
@ -256,13 +284,14 @@ namespace FirstPlugin
rename.Click += Rename;
importTex.Click += ImportTexture;
exportAll.Click += ExportAll;
sort.Click += SortTextures;
clear.Click += Clear;
}
public void Unload()
{
foreach (TextureData tex in Textures.Values)
{
tex.mipmaps.Clear();
tex.surfaces.Clear();
tex.renderedGLTex = null;
}
@ -270,7 +299,7 @@ namespace FirstPlugin
Nodes.Clear();
}
private byte[] CreateNewBNTX(string Name)
private static byte[] CreateNewBNTX(string Name)
{
MemoryStream mem = new MemoryStream();
@ -344,6 +373,7 @@ namespace FirstPlugin
ofd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
"TGA |*.tga|" +
"Portable Network Graphics |*.png|" +
"Joint Photographic Experts Group |*.jpg|" +
"Bitmap Image |*.bmp|" +
@ -357,9 +387,11 @@ namespace FirstPlugin
{
BinaryTextureImporterList importer = new BinaryTextureImporterList();
List<TextureImporterSettings> settings = new List<TextureImporterSettings>();
bool UseDialog = false;
foreach (string name in ofd.FileNames)
{
TextureImporterSettings setting = new TextureImporterSettings();
string ext = Path.GetExtension(name);
ext = ext.ToLower();
@ -367,60 +399,58 @@ namespace FirstPlugin
{
AddTexture(name);
}
else if (ext == ".tga")
{
setting.LoadTGA(name, BinaryTexFile);
importer.LoadSetting(setting, this);
UseDialog = true;
}
else
{
settings.Add(LoadSettings(name));
if (settings.Count == 0)
setting.LoadBitMap(name, BinaryTexFile);
importer.LoadSetting(setting, this);
UseDialog = true;
}
}
if (UseDialog && importer.ShowDialog() == DialogResult.OK)
{
Cursor.Current = Cursors.WaitCursor;
foreach (var setting in importer.settings)
{
if (setting.GenerateMipmaps)
{
importer.Dispose();
return;
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
importer.LoadSettings(settings, this);
if (importer.ShowDialog() == DialogResult.OK)
if (setting.DataBlockOutput != null)
{
Cursor.Current = Cursors.WaitCursor;
foreach (var setting in settings)
Texture tex = setting.FromBitMap(setting.DataBlockOutput[0], setting);
if (setting.textureData != null)
{
if (setting.GenerateMipmaps)
{
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null)
{
Texture tex = setting.FromBitMap(setting.DataBlockOutput[0], setting);
if (setting.textureData != null)
{
setting.textureData.LoadTexture(tex, 1);
}
else
{
setting.textureData = new TextureData(tex, setting.bntx);
}
int i = 0;
if (Textures.ContainsKey(setting.textureData.Text))
{
setting.textureData.Text = setting.textureData.Text + i++;
}
Nodes.Add(setting.textureData);
Textures.Add(setting.textureData.Text, setting.textureData);
setting.textureData.LoadOpenGLTexture();
}
else
{
MessageBox.Show("Something went wrong???");
}
setting.textureData.LoadTexture(tex, 1);
}
else
{
setting.textureData = new TextureData(tex, setting.bntx);
}
int i = 0;
if (Textures.ContainsKey(setting.textureData.Text))
{
setting.textureData.Text = setting.textureData.Text + i++;
}
Nodes.Add(setting.textureData);
Textures.Add(setting.textureData.Text, setting.textureData);
setting.textureData.LoadOpenGLTexture();
}
else
{
MessageBox.Show("Something went wrong???");
}
}
}
settings.Clear();
GC.Collect();
Cursor.Current = Cursors.Default;
}
@ -510,6 +540,9 @@ namespace FirstPlugin
case ".dds":
importer.LoadDDS(name, BinaryTexFile);
break;
case ".tga":
importer.LoadTGA(name, BinaryTexFile);
break;
default:
importer.LoadBitMap(name, BinaryTexFile);
break;
@ -595,6 +628,11 @@ namespace FirstPlugin
}
}
}
bool SortedAscending;
private void SortTextures(object sender, EventArgs args)
{
SortNodes(this);
}
public byte[] Save()
{
BinaryTexFile.Textures.Clear();
@ -692,11 +730,10 @@ namespace FirstPlugin
}
}
public class TextureData : TreeNodeCustom
public class TextureData : STGenericTexture
{
public Texture Texture;
public BntxFile bntxFile;
public List<List<byte[]>> mipmaps = new List<List<byte[]>>();
public BRTI_Texture renderedGLTex = new BRTI_Texture();
public bool GLInitialized = false;
@ -761,12 +798,12 @@ namespace FirstPlugin
LoadTexture(Texture);
if (mipmaps.Count <= 0)
if (surfaces.Count <= 0)
{
throw new Exception("No texture data found");
}
renderedGLTex.data = mipmaps[0][0];
renderedGLTex.data = surfaces[0].mipmaps[0];
renderedGLTex.width = (int)Texture.Width;
renderedGLTex.height = (int)Texture.Height;
@ -800,7 +837,7 @@ namespace FirstPlugin
renderedGLTex.type = PixelInternalFormat.CompressedRgRgtc2;
break;
case SurfaceFormat.BC5_SNORM:
renderedGLTex.data = DDSCompressor.DecompressBC5(mipmaps[0][0], (int)Texture.Width, (int)Texture.Height, true, true);
renderedGLTex.data = DDSCompressor.DecompressBC5(surfaces[0].mipmaps[0], (int)Texture.Width, (int)Texture.Height, true, true);
renderedGLTex.type = PixelInternalFormat.Rgba;
renderedGLTex.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
break;
@ -987,10 +1024,10 @@ namespace FirstPlugin
{
return ColorComponentSelector(bitmap, ChannelType.Blue, ChannelType.Green, ChannelType.Red, ChannelType.Alpha);
}
public static byte[] CompressBlock(byte[] data, int width, int height, SurfaceFormat format)
public static byte[] CompressBlock(byte[] data, int width, int height, SurfaceFormat format, float alphaRef)
{
if (IsCompressedFormat(format))
return DDSCompressor.CompressBlock(data, width, height, GetCompressedDXGI_FORMAT(format));
return DDSCompressor.CompressBlock(data, width, height, GetCompressedDXGI_FORMAT(format), alphaRef);
else if (IsAtscFormat(format))
return null;
else
@ -1092,6 +1129,7 @@ namespace FirstPlugin
ofd.Filter = "Supported Formats|*.bftex;*.dds; *.png;*.tga;*.jpg;*.tiff|" +
"Binary Texture |*.bftex|" +
"Microsoft DDS |*.dds|" +
"TGA |*.tga|" +
"Portable Network Graphics |*.png|" +
"Joint Photographic Experts Group |*.jpg|" +
"Bitmap Image |*.bmp|" +
@ -1116,39 +1154,46 @@ namespace FirstPlugin
{
case ".bftex":
Texture.Import(FileName);
ApplyImportSettings(setting);
break;
case ".dds":
setting.LoadDDS(FileName, bntxFile, null, this);
ApplyImportSettings(setting);
break;
default:
setting.LoadBitMap(FileName, bntxFile);
importer.LoadSetting(setting, (BNTX)Parent);
if (importer.ShowDialog() == DialogResult.OK)
{
ApplyImportSettings(setting);
}
break;
}
if (importer.ShowDialog() == DialogResult.OK)
}
private void ApplyImportSettings(TextureImporterSettings setting)
{
Cursor.Current = Cursors.WaitCursor;
if (setting.GenerateMipmaps)
{
Cursor.Current = Cursors.WaitCursor;
if (setting.GenerateMipmaps)
{
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null)
{
Texture = setting.FromBitMap(setting.DataBlockOutput[0], setting);
LoadOpenGLTexture();
}
else
{
MessageBox.Show("Something went wrong???");
}
Texture.Name = Text;
UpdateBfresTextureMapping();
UpdateBNTXEditor();
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null)
{
Texture = setting.FromBitMap(setting.DataBlockOutput[0], setting);
LoadOpenGLTexture();
}
else
{
MessageBox.Show("Something went wrong???");
}
Texture.Name = Text;
UpdateBfresTextureMapping();
UpdateBNTXEditor();
}
private void UpdateBfresTextureMapping()
{
@ -1193,41 +1238,22 @@ namespace FirstPlugin
case ".dds":
SaveDDS(FileName);
break;
case ".astc":
SaveASTC(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 = Texture.Width;
dds.header.height = Texture.Height;
dds.header.mipmapCount = (uint)mipmaps.Count;
dds.header.pitchOrLinearSize = (uint)mipmaps[0][0].Length;
if (IsCompressedFormat(Texture.Format))
dds.SetFlags(GetCompressedDXGI_FORMAT(Texture.Format));
else
dds.SetFlags(GetUncompressedDXGI_FORMAT(Texture.Format));
dds.Save(dds, FileName, mipmaps);
}
public void LoadTexture(Texture tex, int target = 1)
{
mipmaps.Clear();
surfaces.Clear();
try
{
@ -1259,7 +1285,7 @@ namespace FirstPlugin
mips.Add(result_);
}
mipmaps.Add(mips);
surfaces.Add(new Surface() { mipmaps = mips });
}
Texture = tex;
@ -1275,7 +1301,7 @@ namespace FirstPlugin
{
LoadTexture(Texture);
if (mipmaps.Count <= 0)
if (surfaces.Count <= 0)
{
throw new Exception("No texture data found");
}
@ -1283,7 +1309,7 @@ namespace FirstPlugin
uint width = (uint)Math.Max(1, Texture.Width >> DisplayMipIndex);
uint height = (uint)Math.Max(1, Texture.Height >> DisplayMipIndex);
byte[] data = mipmaps[ArrayIndex][DisplayMipIndex];
byte[] data = surfaces[ArrayIndex].mipmaps[DisplayMipIndex];
return DecodeBlock(data, width, height, Texture.Format);
}

View File

@ -12,6 +12,7 @@ using OpenTK;
using OpenTK.Graphics.OpenGL;
using Smash_Forge.Rendering;
using WeifenLuo.WinFormsUI.Docking;
using Switch_Toolbox.Library.IO;
namespace FirstPlugin
{
@ -91,9 +92,9 @@ namespace FirstPlugin
GTX.GX2Surface tex = setting.CreateGx2Texture(setting.DataBlockOutput[0]);
FTEX ftex = new FTEX();
ftex.texture = ftex.FromGx2Surface(tex, setting);
Nodes.Add(ftex);
ftex.Read(ftex.texture);
Nodes.Add(ftex);
Textures.Add(ftex.Text, ftex);
ftex.LoadOpenGLTexture();
}
@ -123,9 +124,9 @@ namespace FirstPlugin
GTX.GX2Surface tex = setting.CreateGx2Texture(setting.DataBlockOutput[0]);
FTEX ftex = new FTEX();
ftex.texture = ftex.FromGx2Surface(tex, setting);
Nodes.Add(ftex);
ftex.Read(ftex.texture);
Nodes.Add(ftex);
Textures.Add(ftex.Text, ftex);
ftex.LoadOpenGLTexture();
}
@ -200,7 +201,7 @@ namespace FirstPlugin
}
}
public class FTEX : TreeNodeCustom
public class FTEX : STGenericTexture
{
public int format;
public RenderableTex renderedTex = new RenderableTex();
@ -222,6 +223,14 @@ namespace FirstPlugin
ContextMenu.MenuItems.Add(rename);
rename.Click += Rename;
}
//For determining mip map file for botw (Tex2)
public string GetFilePath()
{
if (Parent == null)
throw new Exception("Parent is null!");
return ((BFRES)Parent.Parent).FilePath;
}
private void Replace(object sender, EventArgs args)
{
@ -365,26 +374,16 @@ namespace FirstPlugin
texture = tex;
renderedTex = new RenderableTex();
renderedTex.width = (int)tex.Width;
renderedTex.height = (int)tex.Height;
Width = tex.Width;
Height = tex.Height;
renderedTex.width = (int)Width;
renderedTex.height = (int)Height;
format = (int)tex.Format;
int swizzle = (int)tex.Swizzle;
int pitch = (int)tex.Pitch;
uint bpp = GTX.surfaceGetBitsPerPixel((uint)format) >> 3;
Console.WriteLine(tex.Width);
Console.WriteLine(tex.Height);
Console.WriteLine(tex.Format);
Console.WriteLine(tex.Swizzle);
Console.WriteLine(tex.Pitch);
Console.WriteLine(tex.Alignment);
Console.WriteLine(tex.Depth);
Console.WriteLine(tex.Dim);
Console.WriteLine(tex.MipCount);
Console.WriteLine(tex.MipOffsets);
Console.WriteLine(tex.AAMode);
Console.WriteLine(tex.Use);
GTX.GX2Surface surf = new GTX.GX2Surface();
surf.bpp = bpp;
surf.height = tex.Height;
@ -403,8 +402,39 @@ namespace FirstPlugin
surf.tileMode = (uint)tex.TileMode;
surf.swizzle = tex.Swizzle;
if (IsCompressedFormat(tex.Format))
Format = GetCompressedDXGI_FORMAT(tex.Format);
else
Format = GetUncompressedDXGI_FORMAT(tex.Format);
//Determine tex2 botw files to get mip maps
string Tex1 = GetFilePath();
if (Tex1.Contains(".Tex1"))
{
string Tex2 = Tex1.Replace(".Tex1", ".Tex2");
Console.WriteLine(Tex2);
if (System.IO.File.Exists(Tex2))
{
ResFile resFile2 = new ResFile(new System.IO.MemoryStream(
EveryFileExplorer.YAZ0.Decompress(Tex2)));
if (resFile2.Textures.ContainsKey(tex.Name))
{
surf.mipData = resFile2.Textures[tex.Name].MipData;
surf.mipOffset = resFile2.Textures[tex.Name].MipOffsets;
}
}
}
if (surf.mipData == null)
surf.numMips = 1;
List<byte[]> mips = GTX.Decode(surf);
renderedTex.mipmaps.Add(mips);
surfaces.Add(new Surface() { mipmaps = mips });
renderedTex.data = renderedTex.mipmaps[0][0];
@ -474,18 +504,18 @@ namespace FirstPlugin
{
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;
dds.header.width = Width;
dds.header.height = Height;
dds.header.mipmapCount = (uint)surfaces[0].mipmaps.Count;
dds.header.pitchOrLinearSize = (uint)renderedTex.mipmaps[0][0].Length;
dds.header.pitchOrLinearSize = (uint)surfaces[0].mipmaps[0].Length;
if (IsCompressedFormat((GX2SurfaceFormat)format))
dds.SetFlags(GetCompressedDXGI_FORMAT((GX2SurfaceFormat)format));
dds.SetFlags((DDS.DXGI_FORMAT)GetCompressedDXGI_FORMAT((GX2SurfaceFormat)format));
else
dds.SetFlags(GetUncompressedDXGI_FORMAT((GX2SurfaceFormat)format));
dds.SetFlags((DDS.DXGI_FORMAT)GetUncompressedDXGI_FORMAT((GX2SurfaceFormat)format));
dds.Save(dds, FileName, renderedTex.mipmaps);
dds.Save(dds, FileName, surfaces);
}
@ -497,44 +527,49 @@ namespace FirstPlugin
switch (format)
{
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM):
case ((int)GTX.GX2SurfaceFormat.T_BC1_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB):
case ((int)GTX.GX2SurfaceFormat.T_BC1_SRGB):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM):
case ((int)GTX.GX2SurfaceFormat.T_BC2_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB):
case ((int)GTX.GX2SurfaceFormat.T_BC2_SRGB):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM):
case ((int)GTX.GX2SurfaceFormat.T_BC3_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB):
case ((int)GTX.GX2SurfaceFormat.T_BC3_SRGB):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM):
case ((int)GTX.GX2SurfaceFormat.T_BC4_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRedRgtc1;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM):
case ((int)GTX.GX2SurfaceFormat.T_BC4_SNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedSignedRedRgtc1;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM):
case ((int)GTX.GX2SurfaceFormat.T_BC5_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.CompressedRgRgtc2;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM):
case ((int)GTX.GX2SurfaceFormat.T_BC5_SNORM):
//OpenTK doesn't load BC5 SNORM textures right so I'll use the same decompress method bntx has
renderedTex.data = DDSCompressor.DecompressBC5(renderedTex.mipmaps[0][0], (int)renderedTex.width, (int)renderedTex.height, true, true);
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):
case ((int)GTX.GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNORM):
renderedTex.pixelInternalFormat = PixelInternalFormat.Rgba;
renderedTex.pixelFormat = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
break;
case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB):
case ((int)GTX.GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB):
renderedTex.pixelInternalFormat = PixelInternalFormat.Rgba;
renderedTex.pixelFormat = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
break;
default:
renderedTex.data = BitmapExtension.ImageToByte(DecodeBlock(renderedTex.data, (uint)renderedTex.width, (uint)renderedTex.height, (GX2SurfaceFormat)format));
renderedTex.pixelInternalFormat = PixelInternalFormat.Rgba;
renderedTex.pixelFormat = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
break;
@ -659,16 +694,23 @@ namespace FirstPlugin
if (Format == GX2SurfaceFormat.T_BC5_SNorm)
return DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true);
if (Format == GX2SurfaceFormat.TC_R8_UNorm)
System.IO.File.WriteAllBytes("TC_R8_UNorm2.bin", data);
byte[] d = null;
if (IsCompressedFormat(Format))
d = DDSCompressor.DecompressBlock(data, (int)Width, (int)Height, GetCompressedDXGI_FORMAT(Format));
d = DDSCompressor.DecompressBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)GetCompressedDXGI_FORMAT(Format));
else
d = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, GetUncompressedDXGI_FORMAT(Format));
d = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)GetUncompressedDXGI_FORMAT(Format));
if (d != null)
{
decomp = BitmapExtension.GetBitmap(d, (int)Width, (int)Height);
return SwapBlueRedChannels(decomp);
if (Format == GX2SurfaceFormat.TCS_R5_G6_B5_UNorm)
return decomp;
else
return SwapBlueRedChannels(decomp);
}
return BitmapExtension.GetBitmap(d, (int)Width, (int)Height);;
}
@ -677,30 +719,30 @@ namespace FirstPlugin
throw new Exception($"Bad size from format {Format}");
}
}
public static byte[] CompressBlock(byte[] data, int width, int height, GTX.GX2SurfaceFormat format)
public static byte[] CompressBlock(byte[] data, int width, int height, GTX.GX2SurfaceFormat format, float alphaRef)
{
if (IsCompressedFormat((GX2SurfaceFormat)format))
return DDSCompressor.CompressBlock(data, width, height, GetCompressedDXGI_FORMAT((GX2SurfaceFormat)format));
return DDSCompressor.CompressBlock(data, width, height, (DDS.DXGI_FORMAT)GetCompressedDXGI_FORMAT((GX2SurfaceFormat)format), alphaRef);
else
return DDSCompressor.EncodePixelBlock(data, width, height, GetUncompressedDXGI_FORMAT((GX2SurfaceFormat)format));
return DDSCompressor.EncodePixelBlock(data, width, height, (DDS.DXGI_FORMAT)GetUncompressedDXGI_FORMAT((GX2SurfaceFormat)format));
}
private static DDS.DXGI_FORMAT GetUncompressedDXGI_FORMAT(GX2SurfaceFormat Format)
private static TEX_FORMAT GetUncompressedDXGI_FORMAT(GX2SurfaceFormat Format)
{
switch (Format)
{
case GX2SurfaceFormat.TC_R5_G5_B5_A1_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM;
case GX2SurfaceFormat.TC_A1_B5_G5_R5_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM;
case GX2SurfaceFormat.TC_R4_G4_B4_A4_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
case GX2SurfaceFormat.TCS_R5_G6_B5_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM;
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
case GX2SurfaceFormat.TCS_R10_G10_B10_A2_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM;
case GX2SurfaceFormat.TC_R11_G11_B10_Float: return DDS.DXGI_FORMAT.DXGI_FORMAT_R11G11B10_FLOAT;
case GX2SurfaceFormat.TCD_R16_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R16_UNORM;
case GX2SurfaceFormat.TCD_R32_Float: return DDS.DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT;
case GX2SurfaceFormat.T_R4_G4_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
case GX2SurfaceFormat.TC_R8_G8_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM;
case GX2SurfaceFormat.TC_R8_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8_UNORM;
case GX2SurfaceFormat.TC_R5_G5_B5_A1_UNorm: return TEX_FORMAT.B5G5R5A1_UNORM;
case GX2SurfaceFormat.TC_A1_B5_G5_R5_UNorm: return TEX_FORMAT.B5G5R5A1_UNORM;
case GX2SurfaceFormat.TC_R4_G4_B4_A4_UNorm: return TEX_FORMAT.B4G4R4A4_UNORM;
case GX2SurfaceFormat.TCS_R5_G6_B5_UNorm: return TEX_FORMAT.B5G6R5_UNORM;
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB: return TEX_FORMAT.R8G8B8A8_UNORM;
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNorm: return TEX_FORMAT.R8G8B8A8_UNORM;
case GX2SurfaceFormat.TCS_R10_G10_B10_A2_UNorm: return TEX_FORMAT.R10G10B10A2_UNORM;
case GX2SurfaceFormat.TC_R11_G11_B10_Float: return TEX_FORMAT.R11G11B10_FLOAT;
case GX2SurfaceFormat.TCD_R16_UNorm: return TEX_FORMAT.R16_UNORM;
case GX2SurfaceFormat.TCD_R32_Float: return TEX_FORMAT.R32_FLOAT;
case GX2SurfaceFormat.T_R4_G4_UNorm: return TEX_FORMAT.B4G4R4A4_UNORM;
case GX2SurfaceFormat.TC_R8_G8_UNorm: return TEX_FORMAT.R8G8_UNORM;
case GX2SurfaceFormat.TC_R8_UNorm: return TEX_FORMAT.R8_UNORM;
case GX2SurfaceFormat.Invalid: throw new Exception("Invalid Format");
default:
throw new Exception($"Cannot convert format {Format}");
@ -725,20 +767,20 @@ namespace FirstPlugin
return false;
}
}
private static DDS.DXGI_FORMAT GetCompressedDXGI_FORMAT(GX2SurfaceFormat Format)
private static TEX_FORMAT GetCompressedDXGI_FORMAT(GX2SurfaceFormat Format)
{
switch (Format)
{
case GX2SurfaceFormat.T_BC1_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
case GX2SurfaceFormat.T_BC1_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
case GX2SurfaceFormat.T_BC2_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
case GX2SurfaceFormat.T_BC2_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
case GX2SurfaceFormat.T_BC3_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
case GX2SurfaceFormat.T_BC3_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
case GX2SurfaceFormat.T_BC4_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
case GX2SurfaceFormat.T_BC4_SNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM;
case GX2SurfaceFormat.T_BC5_UNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
case GX2SurfaceFormat.T_BC5_SNorm: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM;
case GX2SurfaceFormat.T_BC1_UNorm: return TEX_FORMAT.BC1_UNORM;
case GX2SurfaceFormat.T_BC1_SRGB: return TEX_FORMAT.BC1_UNORM;
case GX2SurfaceFormat.T_BC2_UNorm: return TEX_FORMAT.BC2_UNORM;
case GX2SurfaceFormat.T_BC2_SRGB: return TEX_FORMAT.BC2_UNORM;
case GX2SurfaceFormat.T_BC3_UNorm: return TEX_FORMAT.BC3_UNORM;
case GX2SurfaceFormat.T_BC3_SRGB: return TEX_FORMAT.BC3_UNORM;
case GX2SurfaceFormat.T_BC4_UNorm: return TEX_FORMAT.BC4_UNORM;
case GX2SurfaceFormat.T_BC4_SNorm: return TEX_FORMAT.BC4_SNORM;
case GX2SurfaceFormat.T_BC5_UNorm: return TEX_FORMAT.BC5_UNORM;
case GX2SurfaceFormat.T_BC5_SNorm: return TEX_FORMAT.BC5_SNORM;
default:
throw new Exception($"Cannot convert format {Format}");
}

View File

@ -6,7 +6,6 @@ namespace FirstPlugin
public class GTX
{
//Some enums and parts from https://github.com/jam1garner/Smash-Forge/blob/master/Smash%20Forge/Filetypes/Textures/GTX.cs
//Todo. Add swizzling back
public class GX2Surface
{
public uint dim;
@ -110,90 +109,90 @@ namespace FirstPlugin
public enum GX2SurfaceDimension
{
GX2_SURFACE_DIM_1D = 0x0,
GX2_SURFACE_DIM_2D = 0x1,
GX2_SURFACE_DIM_3D = 0x2,
GX2_SURFACE_DIM_CUBE = 0x3,
GX2_SURFACE_DIM_1D_ARRAY = 0x4,
GX2_SURFACE_DIM_2D_ARRAY = 0x5,
GX2_SURFACE_DIM_2D_MSAA = 0x6,
GX2_SURFACE_DIM_2D_MSAA_ARRAY = 0x7,
GX2_SURFACE_DIM_FIRST = 0x0,
GX2_SURFACE_DIM_LAST = 0x7,
DIM_1D = 0x0,
DIM_2D = 0x1,
DIM_3D = 0x2,
DIM_CUBE = 0x3,
DIM_1D_ARRAY = 0x4,
DIM_2D_ARRAY = 0x5,
DIM_2D_MSAA = 0x6,
DIM_2D_MSAA_ARRAY = 0x7,
DIM_FIRST = 0x0,
DIM_LAST = 0x7,
};
public enum GX2SurfaceFormat
{
GX2_SURFACE_FORMAT_INVALID = 0x0,
GX2_SURFACE_FORMAT_TC_R8_UNORM = 0x1,
GX2_SURFACE_FORMAT_TC_R8_UINT = 0x101,
GX2_SURFACE_FORMAT_TC_R8_SNORM = 0x201,
GX2_SURFACE_FORMAT_TC_R8_SINT = 0x301,
GX2_SURFACE_FORMAT_T_R4_G4_UNORM = 0x2,
GX2_SURFACE_FORMAT_TCD_R16_UNORM = 0x5,
GX2_SURFACE_FORMAT_TC_R16_UINT = 0x105,
GX2_SURFACE_FORMAT_TC_R16_SNORM = 0x205,
GX2_SURFACE_FORMAT_TC_R16_SINT = 0x305,
GX2_SURFACE_FORMAT_TC_R16_FLOAT = 0x806,
GX2_SURFACE_FORMAT_TC_R8_G8_UNORM = 0x7,
GX2_SURFACE_FORMAT_TC_R8_G8_UINT = 0x107,
GX2_SURFACE_FORMAT_TC_R8_G8_SNORM = 0x207,
GX2_SURFACE_FORMAT_TC_R8_G8_SINT = 0x307,
GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM = 0x8,
GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM = 0xA,
GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM = 0xB,
GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM = 0xC,
GX2_SURFACE_FORMAT_TC_R32_UINT = 0x10D,
GX2_SURFACE_FORMAT_TC_R32_SINT = 0x30D,
GX2_SURFACE_FORMAT_TCD_R32_FLOAT = 0x80E,
GX2_SURFACE_FORMAT_TC_R16_G16_UNORM = 0xF,
GX2_SURFACE_FORMAT_TC_R16_G16_UINT = 0x10F,
GX2_SURFACE_FORMAT_TC_R16_G16_SNORM = 0x20F,
GX2_SURFACE_FORMAT_TC_R16_G16_SINT = 0x30F,
GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT = 0x810,
GX2_SURFACE_FORMAT_D_D24_S8_UNORM = 0x11,
GX2_SURFACE_FORMAT_T_R24_UNORM_X8 = 0x11,
GX2_SURFACE_FORMAT_T_X24_G8_UINT = 0x111,
GX2_SURFACE_FORMAT_D_D24_S8_FLOAT = 0x811,
GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT = 0x816,
GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM = 0x19,
GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT = 0x119,
GX2_SURFACE_FORMAT_T_R10_G10_B10_A2_SNORM = 0x219,
GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM = 0x219,
GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT = 0x319,
GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM = 0x1A,
GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT = 0x11A,
GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM = 0x21A,
GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT = 0x31A,
GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB = 0x41A,
GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM = 0x1B,
GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT = 0x11B,
GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24 = 0x81C,
GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24 = 0x81C,
GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24 = 0x11C,
GX2_SURFACE_FORMAT_TC_R32_G32_UINT = 0x11D,
GX2_SURFACE_FORMAT_TC_R32_G32_SINT = 0x31D,
GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT = 0x81E,
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM = 0x1F,
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT = 0x11F,
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM = 0x21F,
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT = 0x31F,
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT = 0x820,
GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT = 0x122,
GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT = 0x322,
GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT = 0x823,
GX2_SURFACE_FORMAT_T_BC1_UNORM = 0x31,
GX2_SURFACE_FORMAT_T_BC1_SRGB = 0x431,
GX2_SURFACE_FORMAT_T_BC2_UNORM = 0x32,
GX2_SURFACE_FORMAT_T_BC2_SRGB = 0x432,
GX2_SURFACE_FORMAT_T_BC3_UNORM = 0x33,
GX2_SURFACE_FORMAT_T_BC3_SRGB = 0x433,
GX2_SURFACE_FORMAT_T_BC4_UNORM = 0x34,
GX2_SURFACE_FORMAT_T_BC4_SNORM = 0x234,
GX2_SURFACE_FORMAT_T_BC5_UNORM = 0x35,
GX2_SURFACE_FORMAT_T_BC5_SNORM = 0x235,
GX2_SURFACE_FORMAT_T_NV12_UNORM = 0x81,
GX2_SURFACE_FORMAT_FIRST = 0x1,
GX2_SURFACE_FORMAT_LAST = 0x83F,
INVALID = 0x0,
TC_R8_UNORM = 0x1,
TC_R8_UINT = 0x101,
TC_R8_SNORM = 0x201,
TC_R8_SINT = 0x301,
T_R4_G4_UNORM = 0x2,
TCD_R16_UNORM = 0x5,
TC_R16_UINT = 0x105,
TC_R16_SNORM = 0x205,
TC_R16_SINT = 0x305,
TC_R16_FLOAT = 0x806,
TC_R8_G8_UNORM = 0x7,
TC_R8_G8_UINT = 0x107,
TC_R8_G8_SNORM = 0x207,
TC_R8_G8_SINT = 0x307,
TCS_R5_G6_B5_UNORM = 0x8,
TC_R5_G5_B5_A1_UNORM = 0xA,
TC_R4_G4_B4_A4_UNORM = 0xB,
TC_A1_B5_G5_R5_UNORM = 0xC,
TC_R32_UINT = 0x10D,
TC_R32_SINT = 0x30D,
TCD_R32_FLOAT = 0x80E,
TC_R16_G16_UNORM = 0xF,
TC_R16_G16_UINT = 0x10F,
TC_R16_G16_SNORM = 0x20F,
TC_R16_G16_SINT = 0x30F,
TC_R16_G16_FLOAT = 0x810,
D_D24_S8_UNORM = 0x11,
T_R24_UNORM_X8 = 0x11,
T_X24_G8_UINT = 0x111,
D_D24_S8_FLOAT = 0x811,
TC_R11_G11_B10_FLOAT = 0x816,
TCS_R10_G10_B10_A2_UNORM = 0x19,
TC_R10_G10_B10_A2_UINT = 0x119,
T_R10_G10_B10_A2_SNORM = 0x219,
TC_R10_G10_B10_A2_SNORM = 0x219,
TC_R10_G10_B10_A2_SINT = 0x319,
TCS_R8_G8_B8_A8_UNORM = 0x1A,
TC_R8_G8_B8_A8_UINT = 0x11A,
TC_R8_G8_B8_A8_SNORM = 0x21A,
TC_R8_G8_B8_A8_SINT = 0x31A,
TCS_R8_G8_B8_A8_SRGB = 0x41A,
TCS_A2_B10_G10_R10_UNORM = 0x1B,
TC_A2_B10_G10_R10_UINT = 0x11B,
D_D32_FLOAT_S8_UINT_X24 = 0x81C,
T_R32_FLOAT_X8_X24 = 0x81C,
T_X32_G8_UINT_X24 = 0x11C,
TC_R32_G32_UINT = 0x11D,
TC_R32_G32_SINT = 0x31D,
TC_R32_G32_FLOAT = 0x81E,
TC_R16_G16_B16_A16_UNORM = 0x1F,
TC_R16_G16_B16_A16_UINT = 0x11F,
TC_R16_G16_B16_A16_SNORM = 0x21F,
TC_R16_G16_B16_A16_SINT = 0x31F,
TC_R16_G16_B16_A16_FLOAT = 0x820,
TC_R32_G32_B32_A32_UINT = 0x122,
TC_R32_G32_B32_A32_SINT = 0x322,
TC_R32_G32_B32_A32_FLOAT = 0x823,
T_BC1_UNORM = 0x31,
T_BC1_SRGB = 0x431,
T_BC2_UNORM = 0x32,
T_BC2_SRGB = 0x432,
T_BC3_UNORM = 0x33,
T_BC3_SRGB = 0x433,
T_BC4_UNORM = 0x34,
T_BC4_SNORM = 0x234,
T_BC5_UNORM = 0x35,
T_BC5_SNORM = 0x235,
T_NV12_UNORM = 0x81,
FIRST = 0x1,
LAST = 0x83F,
};
public enum GX2AAMode
{
@ -206,17 +205,17 @@ namespace FirstPlugin
};
public enum GX2SurfaceUse : uint
{
GX2_SURFACE_USE_TEXTURE = 0x1,
GX2_SURFACE_USE_COLOR_BUFFER = 0x2,
GX2_SURFACE_USE_DEPTH_BUFFER = 0x4,
GX2_SURFACE_USE_SCAN_BUFFER = 0x8,
GX2_SURFACE_USE_FTV = 0x80000000,
GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE = 0x3,
GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE = 0x5,
GX2_SURFACE_USE_COLOR_BUFFER_FTV = 0x80000002,
GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV = 0x80000003,
GX2_SURFACE_USE_FIRST = 0x1,
GX2_SURFACE_USE_LAST = 0x8,
USE_TEXTURE = 0x1,
USE_COLOR_BUFFER = 0x2,
USE_DEPTH_BUFFER = 0x4,
USE_SCAN_BUFFER = 0x8,
USE_FTV = 0x80000000,
USE_COLOR_BUFFER_TEXTURE = 0x3,
USE_DEPTH_BUFFER_TEXTURE = 0x5,
USE_COLOR_BUFFER_FTV = 0x80000002,
USE_COLOR_BUFFER_TEXTURE_FTV = 0x80000003,
USE_FIRST = 0x1,
USE_LAST = 0x8,
};
public enum GX2RResourceFlags
{
@ -262,26 +261,26 @@ namespace FirstPlugin
};
public enum GX2TileMode
{
GX2_TILE_MODE_DEFAULT = 0x0,
GX2_TILE_MODE_LINEAR_SPECIAL = 0x10,
GX2_TILE_MODE_DEFAULT_FIX2197 = 0x20,
GX2_TILE_MODE_LINEAR_ALIGNED = 0x1,
GX2_TILE_MODE_1D_TILED_THIN1 = 0x2,
GX2_TILE_MODE_1D_TILED_THICK = 0x3,
GX2_TILE_MODE_2D_TILED_THIN1 = 0x4,
GX2_TILE_MODE_2D_TILED_THIN2 = 0x5,
GX2_TILE_MODE_2D_TILED_THIN4 = 0x6,
GX2_TILE_MODE_2D_TILED_THICK = 0x7,
GX2_TILE_MODE_2B_TILED_THIN1 = 0x8,
GX2_TILE_MODE_2B_TILED_THIN2 = 0x9,
GX2_TILE_MODE_2B_TILED_THIN4 = 0xA,
GX2_TILE_MODE_2B_TILED_THICK = 0xB,
GX2_TILE_MODE_3D_TILED_THIN1 = 0xC,
GX2_TILE_MODE_3D_TILED_THICK = 0xD,
GX2_TILE_MODE_3B_TILED_THIN1 = 0xE,
GX2_TILE_MODE_3B_TILED_THICK = 0xF,
GX2_TILE_MODE_FIRST = 0x0,
GX2_TILE_MODE_LAST = 0x20,
MODE_DEFAULT = 0x0,
MODE_LINEAR_SPECIAL = 0x10,
MODE_DEFAULT_FIX2197 = 0x20,
MODE_LINEAR_ALIGNED = 0x1,
MODE_1D_TILED_THIN1 = 0x2,
MODE_1D_TILED_THICK = 0x3,
MODE_2D_TILED_THIN1 = 0x4,
MODE_2D_TILED_THIN2 = 0x5,
MODE_2D_TILED_THIN4 = 0x6,
MODE_2D_TILED_THICK = 0x7,
MODE_2B_TILED_THIN1 = 0x8,
MODE_2B_TILED_THIN2 = 0x9,
MODE_2B_TILED_THIN4 = 0xA,
MODE_2B_TILED_THICK = 0xB,
MODE_3D_TILED_THIN1 = 0xC,
MODE_3D_TILED_THICK = 0xD,
MODE_3B_TILED_THIN1 = 0xE,
MODE_3B_TILED_THICK = 0xF,
MODE_FIRST = 0x0,
MODE_LAST = 0x20,
};
public enum AddrTileMode
@ -429,6 +428,10 @@ namespace FirstPlugin
public static List<byte[]> Decode(GX2Surface tex)
{
if (tex.data == null) //Some ftex will only have mip maps
throw new Exception("Data is empty! Make sure to open a Tex1.sbfres if using Tex2!");
Console.WriteLine("");
Console.WriteLine("// ----- GX2Surface Decode Info ----- ");
Console.WriteLine(" dim = " + tex.dim);
@ -496,6 +499,9 @@ namespace FirstPlugin
Array.Copy(deswizzled, 0, result_, 0, size);
result.Add(result_);
}
if (tex.format == (uint)GX2SurfaceFormat.TC_R8_UNORM)
System.IO.File.WriteAllBytes("TC_R8_UNorm.bin", result[0]);
return result;
}
@ -512,16 +518,16 @@ namespace FirstPlugin
{
switch (Format)
{
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM:
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM:
case GX2SurfaceFormat.T_BC1_UNORM:
case GX2SurfaceFormat.T_BC1_SRGB:
case GX2SurfaceFormat.T_BC2_UNORM:
case GX2SurfaceFormat.T_BC2_SRGB:
case GX2SurfaceFormat.T_BC3_UNORM:
case GX2SurfaceFormat.T_BC3_SRGB:
case GX2SurfaceFormat.T_BC4_UNORM:
case GX2SurfaceFormat.T_BC4_SNORM:
case GX2SurfaceFormat.T_BC5_SNORM:
case GX2SurfaceFormat.T_BC5_UNORM:
return true;
default:
return false;

View File

@ -30,7 +30,7 @@ namespace FirstPlugin
UserBlock = 0x16,
}
public class GTXFile : TreeNode, IFileFormat
public class GTXFile : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; } = false;
public bool FileIsEdited { get; set; } = false;
@ -95,11 +95,44 @@ namespace FirstPlugin
using (FileWriter writer = new FileWriter(mem))
{
writer.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
header.Write(writer);
uint surfBlockType;
uint dataBlockType;
uint mipBlockType;
if (header.MajorVersion == 6)
{
surfBlockType = 0x0A;
dataBlockType = 0x0B;
mipBlockType = 0x0C;
}
else if (header.MajorVersion == 7)
{
surfBlockType = 0x0B;
dataBlockType = 0x0C;
mipBlockType = 0x0D;
}
else
throw new Exception($"Unsupported GTX version {header.MajorVersion}");
writer.Seek(header.HeaderSize, System.IO.SeekOrigin.Begin);
foreach (var tex in textures)
{
tex.surface.Write(writer);
}
foreach (var block in blocks)
block.Write(writer);
{
if ((uint)block.BlockType == surfBlockType)
{
block.Write(writer);
}
else
{
block.Write(writer);
}
}
}
return mem.ToArray();
}
@ -287,7 +320,6 @@ namespace FirstPlugin
reader.Seek(blockStart + HeaderSize, System.IO.SeekOrigin.Begin);
data = reader.ReadBytes((int)DataSize);
System.IO.File.WriteAllBytes($"block {BlockType}.bin", data);
}
public void Write(FileWriter writer)
{
@ -306,7 +338,7 @@ namespace FirstPlugin
writer.Write(data);
}
}
public class TextureData : TreeNodeCustom
public class TextureData : STGenericTexture
{
public SurfaceInfoParse surface;
public RenderableTex renderedTex = new RenderableTex();
@ -384,7 +416,7 @@ namespace FirstPlugin
dds.Save(dds, FileName, renderedTex.mipmaps);
dds.Save(dds, FileName, surfaces);
}
private void Replace(object sender, EventArgs args)
{

View File

@ -11,7 +11,7 @@ using Switch_Toolbox.Library.Forms;
namespace FirstPlugin
{
public class NUTEXB : TreeNodeFile, IFileFormat
public class NUTEXB : STGenericTexture, IFileFormat
{
public bool CanSave { get; set; } = false;
public bool FileIsEdited { get; set; } = false;
@ -22,7 +22,6 @@ namespace FirstPlugin
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; }
@ -156,7 +155,7 @@ namespace FirstPlugin
{
Console.WriteLine("Something went wrong??");
}
texture.mipmaps.Clear();
texture.surfaces.Clear();
texture = null;
@ -175,7 +174,6 @@ namespace FirstPlugin
public NUTEXImageFormat Format;
public List<uint[]> mipSizes = new List<uint[]>();
public int Alignment;
public List<List<byte[]>> mipmaps = new List<List<byte[]>>();
public byte[] ImageData;
bool IsSwizzled = true;
public string ArcOffset; //Temp for exporting in batch
@ -183,24 +181,36 @@ namespace FirstPlugin
private void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Supported Formats|*.dds; *.png;*.tga;*.jpg;*.tiff|" +
"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|*.dds; *.png;*.tga;*.jpg;*.tiff|" +
"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|*.dds;" +
"Microsoft DDS |*.dds" +
"All files(*.*)|*.*";
ofd.Multiselect = false;
if (ofd.ShowDialog() == DialogResult.OK)
{
throw new Exception("Saving is not supported yet!");
var bntxFile = new BNTX();
var tex = new TextureData();
tex.Replace(ofd.FileName);
if (surfaces[0].mipmaps[0].Length != surfaces[0].mipmaps[0].Length)
throw new Exception("Image must be the same size!");
if (surfaces[0].mipmaps.Count != tex.surfaces[0].mipmaps.Count)
throw new Exception("Map map count must be the same!");
if (Width != tex.Texture.Width || Height != tex.Texture.Height)
throw new Exception("Image size must be the same!");
ImageData = tex.Texture.TextureData[0][0];
mipmaps = tex.mipmaps;
surfaces = tex.surfaces;
Width = tex.Texture.Width;
Height = tex.Texture.Height;
@ -265,8 +275,8 @@ namespace FirstPlugin
dds.header = new DDS.Header();
dds.header.width = Width;
dds.header.height = Height;
dds.header.mipmapCount = (uint)mipmaps.Count;
dds.header.pitchOrLinearSize = (uint)mipmaps[0][0].Length;
dds.header.mipmapCount = (uint)surfaces[0].mipmaps.Count;
dds.header.pitchOrLinearSize = (uint)surfaces[0].mipmaps[0].Length;
if (IsCompressedFormat((NUTEXImageFormat)Format))
dds.SetFlags(GetCompressedDXGI_FORMAT((NUTEXImageFormat)Format));
@ -274,7 +284,7 @@ namespace FirstPlugin
dds.SetFlags(GetUncompressedDXGI_FORMAT((NUTEXImageFormat)Format));
dds.Save(dds, FileName, mipmaps);
dds.Save(dds, FileName, surfaces);
}
public void Read(FileReader reader)
{
@ -368,9 +378,9 @@ namespace FirstPlugin
if (IsSwizzled)
LoadTexture();
else
mipmaps.Add(new List<byte[]>() { ImageData });
surfaces.Add(new Surface() {mipmaps = new List<byte[]>() { ImageData } } );
if (mipmaps[0].Count <= 0)
if (surfaces[0].mipmaps.Count <= 0)
{
return BitmapExtension.GetBitmap(Properties.Resources.Black, 32, 32);
}
@ -380,7 +390,7 @@ namespace FirstPlugin
uint width = (uint)Math.Max(1, Width >> DisplayMipIndex);
uint height = (uint)Math.Max(1, Height >> DisplayMipIndex);
byte[] data = mipmaps[ArrayIndex][DisplayMipIndex];
byte[] data = surfaces[ArrayIndex].mipmaps[DisplayMipIndex];
return DecodeBlock(data, width, height, (NUTEXImageFormat)Format);
}
@ -466,7 +476,7 @@ namespace FirstPlugin
public void LoadTexture(int target = 1)
{
mipmaps.Clear();
surfaces.Clear();
uint blk_dim = blk_dims((byte)Format);
uint blkWidth = blk_dim >> 4;
@ -524,7 +534,7 @@ namespace FirstPlugin
mipOffset += (uint)MipSize;
break;
}
mipmaps.Add(mips);
surfaces.Add(new Surface() { mipmaps = mips });
}
}

View File

@ -139,9 +139,12 @@ namespace FirstPlugin
foreach (FMDL mdl in models)
{
foreach (FSHP shp in mdl.shapes)
if (mdl.Checked)
{
DrawModel(shp, mdl, shader);
foreach (FSHP shp in mdl.shapes)
{
DrawModel(shp, mdl, shader);
}
}
}
@ -206,6 +209,8 @@ namespace FirstPlugin
private void SetRenderSettings(Shader shader)
{
shader.SetBoolToInt("renderVertColor", Runtime.renderVertColor);
shader.SetBoolToInt("renderTevColors", Runtime.renderTevColors);
shader.SetBoolToInt("renderMatColors", Runtime.renderMatColors);
shader.SetInt("renderType", (int)Runtime.viewportShading);
shader.SetBoolToInt("useNormalMap", Runtime.useNormalMap);
shader.SetInt("uvChannel", (int)Runtime.uvChannel);
@ -238,6 +243,12 @@ namespace FirstPlugin
{
for (int i = 0; i < fmdl.Skeleton.Node_Array.Length; i++)
{
/* Matrix3x4 transform3x4 = fmdl.Skeleton.matrices[fmdl.Skeleton.Node_Array[i]];
Matrix4 transform = new Matrix4(transform3x4.Row0, transform3x4.Row1,
transform3x4.Row2, new Vector4(0, 0, 0, 1));*/
Matrix4 transform = fmdl.Skeleton.bones[fmdl.Skeleton.Node_Array[i]].invert * fmdl.Skeleton.bones[fmdl.Skeleton.Node_Array[i]].transform;
GL.UniformMatrix4(GL.GetUniformLocation(shader.Id, String.Format("bones[{0}]", i)), false, ref transform);
}
@ -258,7 +269,7 @@ namespace FirstPlugin
// shader.SetTexture("irradianceMap", RenderTools.diffusePbr, 18);
// shader.SetTexture("specularIbl", RenderTools.specularPbr, 19);
foreach (MatTexture matex in mat.textures)
foreach (MatTexture matex in mat.TextureMaps)
{
if (matex.Type == MatTexture.TextureType.Diffuse)
TextureUniform(shader, mat, mat.HasDiffuseMap, "DiffuseMap", matex);
@ -346,7 +357,7 @@ namespace FirstPlugin
SetVertexAttributes(m, shader);
ApplyTransformFix(mdl, m, shader);
if (m.Checked)
if (m.Checked && m.Parent.Parent.Checked)
{
if ((m.IsSelected))
{
@ -452,7 +463,7 @@ namespace FirstPlugin
foreach (BNTX bntx in PluginRuntime.bntxContainers)
{
foreach (var t in mat.textures)
foreach (var t in mat.TextureMaps)
{
if (bntx.Textures.ContainsKey(t.Name))
{
@ -494,6 +505,11 @@ namespace FirstPlugin
{
shader.SetVector4("gsys_bake_st0", new Vector4(1, 1, 0, 0));
shader.SetVector4("gsys_bake_st1", new Vector4(1, 1, 0, 0));
shader.SetVector4("tev_color0", new Vector4(1, 1, 0, 0));
shader.SetVector4("tev_color1", new Vector4(1, 1, 0, 0));
shader.SetVector4("mat_color0", new Vector4(1, 1, 0, 0));
shader.SetVector4("mat_color1", new Vector4(1, 1, 0, 0));
shader.SetVector4("const_color0", new Vector4(1, 1, 1, 1));
shader.SetVector4("base_color_mul_color", new Vector4(1, 1, 1, 1));
@ -504,7 +520,11 @@ namespace FirstPlugin
SetUniformData(mat, shader, "gsys_bake_st0");
SetUniformData(mat, shader, "gsys_bake_st1");
SetUniformData(mat, shader, "const_color0");
SetUniformData(mat, shader, "base_color_mul_color");
SetUniformData(mat, shader, "tev_color0");
SetUniformData(mat, shader, "tev_color1");
SetUniformData(mat, shader, "mat_color0");
SetUniformData(mat, shader, "mat_color1");
}
private static void SetUniformData(FMAT mat, Shader shader, string propertyName)
{

View File

@ -103,7 +103,12 @@ namespace FirstPlugin
Color SetColor = Color.FromArgb(40, 40, 40);
Vector4 col = new Vector4();
bool IsColor = prm.Name.Contains("Color") || prm.Name.Contains("color");
bool IsColor = prm.Name.Contains("Color") ||
prm.Name.Contains("color") ||
prm.Name.Contains("konst0") ||
prm.Name.Contains("konst1") ||
prm.Name.Contains("konst2") ||
prm.Name.Contains("konst3");
switch (prm.Type)
{
@ -166,7 +171,7 @@ namespace FirstPlugin
textureRefListView.SmallImageList = textureImageList;
textureRefListView.FullRowSelect = true;
foreach (MatTexture tex in material.textures)
foreach (MatTexture tex in material.TextureMaps)
{
ListViewItem item = new ListViewItem();
item.Text = tex.Name;
@ -315,7 +320,7 @@ namespace FirstPlugin
tex.LoadTexture(material.GetResFileU() != null);
if (tex.ShowDialog() == DialogResult.OK)
{
material.textures[index].Name = tex.GetSelectedTexture();
material.TextureMaps[index].Name = tex.GetSelectedTexture();
InitializeTextureListView(material);
material.UpdateTextureMaps();
}
@ -346,7 +351,7 @@ namespace FirstPlugin
if (paramDialog.ShowDialog() == DialogResult.OK)
{
paramDialog.GetValues();
paramDialog.SetValues();
InitializeShaderParamList(material);
listView1.Items[index].Selected = true;
}
@ -485,7 +490,7 @@ namespace FirstPlugin
return;
SamplerEditor samplerEditor = new SamplerEditor();
foreach (MatTexture tex in material.textures)
foreach (MatTexture tex in material.TextureMaps)
{
if (tex.Name == textureRefListView.SelectedItems[0].Text)
{

View File

@ -8,6 +8,8 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Bfres.Structs;
using Syroot.NintenTools.NSW.Bfres;
namespace FirstPlugin
{
@ -17,7 +19,26 @@ namespace FirstPlugin
{
InitializeComponent();
}
public void SetValues(BfresShaderParam param)
{
switch (param.Type)
{
case ShaderParamType.Bool:
param.ValueBool = new bool[] { bool1.Visible};
break;
case ShaderParamType.Bool2:
param.ValueBool = new bool[] { bool1.Visible, bool2.Visible };
break;
case ShaderParamType.Bool3:
param.ValueBool = new bool[] { bool1.Visible, bool2.Visible,
bool3.Visible };
break;
case ShaderParamType.Bool4:
param.ValueBool = new bool[] { bool1.Visible, bool2.Visible,
bool3.Visible , bool4.Visible };
break;
}
}
public void LoadValues(bool[] values)
{
bool1.Visible = false;

View File

@ -19,13 +19,52 @@ namespace FirstPlugin
InitializeComponent();
HideControls();
}
public void GetValues(BfresShaderParam param)
public void SetValues(BfresShaderParam param)
{
switch (param.Type)
{
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.Float:
param.ValueFloat = new float[] { (float)ValueUD1.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.Float2:
param.ValueFloat = new float[] { (float)ValueUD1.Value, (float)ValueUD2.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.Float3:
param.ValueFloat = new float[] { (float)ValueUD1.Value, (float)ValueUD2.Value,
(float)ValueUD3.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.Float4:
param.ValueFloat = new float[] { (float)ValueUD1.Value, (float)ValueUD2.Value,
(float)ValueUD3.Value, (float)ValueUD4.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.UInt:
param.ValueUint = new uint[] { (uint)ValueUD1.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.UInt2:
param.ValueUint = new uint[] { (uint)ValueUD1.Value, (uint)ValueUD2.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.UInt3:
param.ValueUint = new uint[] { (uint)ValueUD1.Value, (uint)ValueUD2.Value,
(uint)ValueUD3.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.UInt4:
param.ValueUint = new uint[] { (uint)ValueUD1.Value, (uint)ValueUD2.Value,
(uint)ValueUD3.Value, (uint)ValueUD4.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.Int:
param.ValueInt = new int[] { (int)ValueUD1.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.Int2:
param.ValueInt = new int[] { (int)ValueUD1.Value, (int)ValueUD2.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.Int3:
param.ValueInt = new int[] { (int)ValueUD1.Value, (int)ValueUD2.Value,
(int)ValueUD3.Value };
break;
case Syroot.NintenTools.NSW.Bfres.ShaderParamType.Int4:
param.ValueInt = new int[] { (int)ValueUD1.Value, (int)ValueUD2.Value,
(int)ValueUD3.Value, (int)ValueUD4.Value };
break;
}
}
public void LoadValues(float[] values)

View File

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using Syroot.NintenTools.NSW.Bfres;
using Switch_Toolbox.Library;
using Bfres.Structs;
namespace FirstPlugin
{
@ -19,6 +20,47 @@ namespace FirstPlugin
InitializeComponent();
HideControls();
}
public void SetValues(BfresShaderParam param)
{
switch (param.Type)
{
case ShaderParamType.TexSrt:
param.ValueTexSrt.Scaling.X = (float)scaleUDX.Value;
param.ValueTexSrt.Scaling.Y = (float)scaleUDY.Value;
param.ValueTexSrt.Rotation = (float)rotUDX.Value;
param.ValueTexSrt.Translation.X = (float)transUDX.Value;
param.ValueTexSrt.Translation.Y = (float)transUDY.Value;
param.ValueTexSrt.Mode = (TexSrtMode)modeComboBox.SelectedItem;
break;
case ShaderParamType.TexSrtEx:
param.ValueTexSrtEx.Scaling.X = (float)scaleUDX.Value;
param.ValueTexSrtEx.Scaling.Y = (float)scaleUDY.Value;
param.ValueTexSrtEx.Rotation = (float)rotUDX.Value;
param.ValueTexSrtEx.Translation.X = (float)transUDX.Value;
param.ValueTexSrtEx.Translation.Y = (float)transUDY.Value;
param.ValueTexSrtEx.Mode = (TexSrtMode)modeComboBox.SelectedItem;
param.ValueTexSrtEx.MatrixPointer = (uint)matrixPtrNumUD.Value;
break;
case ShaderParamType.Srt2D:
param.ValueSrt2D.Scaling.X = (float)scaleUDX.Value;
param.ValueSrt2D.Scaling.Y = (float)scaleUDY.Value;
param.ValueSrt2D.Rotation = (float)rotUDX.Value;
param.ValueSrt2D.Translation.X = (float)transUDX.Value;
param.ValueSrt2D.Translation.Y = (float)transUDY.Value;
break;
case ShaderParamType.Srt3D:
param.ValueSrt3D.Scaling.X = (float)scaleUDX.Value;
param.ValueSrt3D.Scaling.Y = (float)scaleUDY.Value;
param.ValueSrt3D.Scaling.Z = (float)scaleUDZ.Value;
param.ValueSrt3D.Rotation.X = (float)rotUDX.Value;
param.ValueSrt3D.Rotation.Y = (float)rotUDY.Value;
param.ValueSrt3D.Rotation.Z = (float)rotUDZ.Value;
param.ValueSrt3D.Translation.X = (float)transUDX.Value;
param.ValueSrt3D.Translation.Y = (float)transUDY.Value;
param.ValueSrt3D.Translation.Z = (float)transUDZ.Value;
break;
}
}
public void LoadValues(Srt2D srt2D)
{
scaleUDX.Value = (decimal)srt2D.Scaling.X;

View File

@ -153,17 +153,19 @@ namespace FirstPlugin
}
}
public void GetValues()
public void SetValues()
{
if (boolPanel != null)
{
boolPanel.SetValues(activeParam);
}
if (SRTPanel != null)
{
SRTPanel.SetValues(activeParam);
}
if (FloatIntsPanel != null)
{
FloatIntsPanel.GetValues(activeParam);
FloatIntsPanel.SetValues(activeParam);
}
}

View File

@ -66,14 +66,14 @@ namespace FirstPlugin
LoadImage();
int MipCount = 1;
if (textureData.mipmaps.Count <= 0)
if (textureData.surfaces.Count <= 0)
return;
else
MipCount = textureData.mipmaps[CurArrayDisplayLevel].Count;
MipCount = textureData.surfaces[CurArrayDisplayLevel].mipmaps.Count;
mipLevelCounterLabel.Text = $"{CurMipDisplayLevel} / {textureData.mipmaps[CurArrayDisplayLevel].Count - 1}";
arrayLevelCounterLabel.Text = $"{CurArrayDisplayLevel} / {textureData.mipmaps.Count - 1}";
mipLevelCounterLabel.Text = $"{CurMipDisplayLevel} / {textureData.surfaces[CurArrayDisplayLevel].mipmaps.Count - 1}";
arrayLevelCounterLabel.Text = $"{CurArrayDisplayLevel} / {textureData.surfaces.Count - 1}";
if (CurMipDisplayLevel != MipCount - 1)
BtnMipsRight.Enabled = true;
@ -85,7 +85,7 @@ namespace FirstPlugin
else
BtmMipsLeft.Enabled = false;
if (CurArrayDisplayLevel != textureData.mipmaps.Count - 1)
if (CurArrayDisplayLevel != textureData.surfaces.Count - 1)
btnRightArray.Enabled = true;
else
btnRightArray.Enabled = false;
@ -133,7 +133,7 @@ namespace FirstPlugin
private void BtnMipsRight_Click(object sender, EventArgs e)
{
if (CurMipDisplayLevel != textureData.mipmaps[CurArrayDisplayLevel].Count - 1)
if (CurMipDisplayLevel != textureData.surfaces[CurArrayDisplayLevel].mipmaps.Count - 1)
CurMipDisplayLevel += 1;
UpdateMipDisplay();
@ -149,7 +149,7 @@ namespace FirstPlugin
private void btnRightArray_Click(object sender, EventArgs e)
{
if (CurArrayDisplayLevel != textureData.mipmaps.Count - 1)
if (CurArrayDisplayLevel != textureData.surfaces.Count - 1)
CurArrayDisplayLevel += 1;
UpdateMipDisplay();
@ -204,7 +204,7 @@ namespace FirstPlugin
throw new Exception("Invalid Width! Must be same as original!");
List<byte[]> Mipmaps = TextureImporterSettings.SwizzleSurfaceMipMaps(textureData.Texture, dds.bdata, TileMode.Default);
textureData.mipmaps[CurArrayDisplayLevel] = Mipmaps;
textureData.surfaces[CurArrayDisplayLevel].mipmaps = Mipmaps;
UpdateMipDisplay();
textureData.LoadOpenGLTexture();

View File

@ -70,22 +70,9 @@ namespace FirstPlugin
TextureImporterSettings SelectedTexSettings;
BNTX bntx;
List<TextureImporterSettings> settings = new List<TextureImporterSettings>();
public void LoadSettings(List<TextureImporterSettings> s, BNTX b)
{
settings = s;
bntx = b;
foreach (var setting in settings)
{
listViewCustom1.Items.Add(setting.TexName).SubItems.Add(setting.Format.ToString());
}
listViewCustom1.Items[0].Selected = true;
listViewCustom1.Select();
}
public List<TextureImporterSettings> settings = new List<TextureImporterSettings>();
public void LoadSetting(TextureImporterSettings setting, BNTX b)
{
settings = new List<TextureImporterSettings>();
settings.Add(setting);
bntx = b;
@ -123,29 +110,36 @@ namespace FirstPlugin
if (SelectedTexSettings.Format == SurfaceFormat.Invalid)
return;
if (Thread != null && Thread.IsAlive)
Thread.Abort();
if (formatComboBox.SelectedItem is SurfaceFormat)
try
{
SelectedTexSettings.Format = (SurfaceFormat)formatComboBox.SelectedItem;
listViewCustom1.SelectedItems[0].SubItems[1].Text = SelectedTexSettings.Format.ToString();
if (formatComboBox.SelectedItem is SurfaceFormat)
{
SelectedTexSettings.Format = (SurfaceFormat)formatComboBox.SelectedItem;
listViewCustom1.SelectedItems[0].SubItems[1].Text = SelectedTexSettings.Format.ToString();
}
Bitmap bitmap = Switch_Toolbox.Library.Imaging.GetLoadingImage();
Thread = new Thread((ThreadStart)(() =>
{
pictureBox1.Image = bitmap;
SelectedTexSettings.Compress();
bitmap = TextureData.DecodeBlock(SelectedTexSettings.DataBlockOutput[0], SelectedTexSettings.
TexWidth, SelectedTexSettings.TexHeight, SelectedTexSettings.Format);
pictureBox1.Image = bitmap;
}));
Thread.Start();
}
Bitmap bitmap = Switch_Toolbox.Library.Imaging.GetLoadingImage();
Thread = new Thread((ThreadStart)(() =>
catch
{
pictureBox1.Image = bitmap;
SelectedTexSettings.Compress();
throw new Exception("Failed to load image!");
}
bitmap = TextureData.DecodeBlock(SelectedTexSettings.DataBlockOutput[0], SelectedTexSettings.
TexWidth, SelectedTexSettings.TexHeight, SelectedTexSettings.Format);
pictureBox1.Image = bitmap;
}));
Thread.Start();
// WidthLabel.Text = $"Width {pictureBox1.Image.Width}";
// HeightLabel.Text = $"Height {pictureBox1.Image.Height}";
@ -168,6 +162,8 @@ namespace FirstPlugin
{
if (listViewCustom1.SelectedItems.Count > 0)
{
Console.WriteLine("list index " + listViewCustom1.SelectedIndices[0]);
SelectedTexSettings = settings[listViewCustom1.SelectedIndices[0]];
formatComboBox.SelectedItem = SelectedTexSettings.Format;

View File

@ -28,6 +28,7 @@ namespace FirstPlugin
public GX2CompSel[] compSel = new GX2CompSel[4];
public GX2SurfaceDim SurfaceDim = GX2SurfaceDim.Dim2D;
public GX2AAMode AAMode = GX2AAMode.Mode1X;
public float alphaRef = 0.5f;
private GTX.GX2SurfaceFormat LoadDDSFormat(uint fourCC, DDS dds = null, bool IsSRGB = false)
{
@ -37,49 +38,49 @@ namespace FirstPlugin
{
case DDS.FOURCC_DXT1:
if (IsSRGB)
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB;
return GTX.GX2SurfaceFormat.T_BC1_SRGB;
else
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM;
return GTX.GX2SurfaceFormat.T_BC1_UNORM;
case DDS.FOURCC_DXT3:
if (IsSRGB)
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB;
return GTX.GX2SurfaceFormat.T_BC2_SRGB;
else
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM;
return GTX.GX2SurfaceFormat.T_BC2_UNORM;
case DDS.FOURCC_DXT5:
if (IsSRGB)
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB;
return GTX.GX2SurfaceFormat.T_BC3_SRGB;
else
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM;
return GTX.GX2SurfaceFormat.T_BC3_UNORM;
case DDS.FOURCC_BC4U:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM;
return GTX.GX2SurfaceFormat.T_BC4_UNORM;
case DDS.FOURCC_ATI1:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM;
return GTX.GX2SurfaceFormat.T_BC4_UNORM;
case DDS.FOURCC_ATI2:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM;
return GTX.GX2SurfaceFormat.T_BC5_UNORM;
case DDS.FOURCC_BC5U:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM;
return GTX.GX2SurfaceFormat.T_BC4_UNORM;
case DDS.FOURCC_DX10:
IsDX10 = true;
break;
default:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM;
return GTX.GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNORM;
}
if (IsDX10)
{
switch (dds.DX10header.DXGI_Format)
{
case DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM;
return GTX.GX2SurfaceFormat.T_BC4_UNORM;
case DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM;
return GTX.GX2SurfaceFormat.T_BC4_SNORM;
case DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_TYPELESS:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM;
return GTX.GX2SurfaceFormat.T_BC4_UNORM;
case DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM;
return GTX.GX2SurfaceFormat.T_BC5_UNORM;
case DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM;
return GTX.GX2SurfaceFormat.T_BC5_SNORM;
case DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_TYPELESS:
return GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM;
return GTX.GX2SurfaceFormat.T_BC5_UNORM;
default:
throw new Exception($"Format {dds.DX10header.DXGI_Format} not supported!");
}
@ -115,7 +116,7 @@ namespace FirstPlugin
DecompressedData.Clear();
TexName = Path.GetFileNameWithoutExtension(FileName);
Format = GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB;
Format = GTX.GX2SurfaceFormat.T_BC1_SRGB;
GenerateMipmaps = true;
Bitmap Image = new Bitmap(FileName);
@ -163,14 +164,14 @@ namespace FirstPlugin
Bitmap Image = BitmapExtension.GetBitmap(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight);
List<byte[]> mipmaps = new List<byte[]>();
mipmaps.Add(FTEX.CompressBlock(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight, Format));
mipmaps.Add(FTEX.CompressBlock(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight, Format, alphaRef));
//while (Image.Width / 2 > 0 && Image.Height / 2 > 0)
// for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
{
Image = BitmapExtension.Resize(Image, Image.Width / 2, Image.Height / 2);
mipmaps.Add(FTEX.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, Format));
mipmaps.Add(FTEX.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, Format, alphaRef));
}
Image.Dispose();
@ -181,7 +182,7 @@ namespace FirstPlugin
DataBlockOutput.Clear();
foreach (var surface in DecompressedData)
{
DataBlockOutput.Add(FTEX.CompressBlock(surface, (int)TexWidth, (int)TexHeight, Format));
DataBlockOutput.Add(FTEX.CompressBlock(surface, (int)TexWidth, (int)TexHeight, Format, alphaRef));
}
}

View File

@ -17,47 +17,59 @@ namespace FirstPlugin
InitializeComponent();
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R8_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R8_G8_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.TCS_R10_G10_B10_A2_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.TCS_R5_G6_B5_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.TC_R5_G5_B5_A1_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.TC_R4_G4_B4_A4_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.TC_R8_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.TC_R8_G8_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC1_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC1_SRGB);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC2_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC2_SRGB);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC3_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC3_SRGB);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC4_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC4_SNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC5_UNORM);
formatComboBox.Items.Add(GTX.GX2SurfaceFormat.T_BC5_SNORM);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_DEFAULT);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_LINEAR_ALIGNED);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_1D_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_1D_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_2D_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_2D_TILED_THIN2);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_2D_TILED_THIN4);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_2D_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_2B_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_2B_TILED_THIN2);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_2B_TILED_THIN4);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_2B_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_3D_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_3D_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_3B_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_3B_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_LINEAR_SPECIAL);
tileModeCB.Items.Add(GTX.GX2TileMode.GX2_TILE_MODE_DEFAULT_FIX2197);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_DEFAULT);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_LINEAR_ALIGNED);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_1D_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_1D_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_2D_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_2D_TILED_THIN2);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_2D_TILED_THIN4);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_2D_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_2B_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_2B_TILED_THIN2);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_2B_TILED_THIN4);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_2B_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_3D_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_3D_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_3B_TILED_THIN1);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_3B_TILED_THICK);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_LINEAR_SPECIAL);
tileModeCB.Items.Add(GTX.GX2TileMode.MODE_DEFAULT_FIX2197);
tileModeCB.SelectedItem = GTX.GX2TileMode.GX2_TILE_MODE_2D_TILED_THIN1;
formatComboBox.SelectedItem = GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB;
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_1D);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_1D_ARRAY);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_2D);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_2D_ARRAY);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_2D_MSAA);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_2D_MSAA_ARRAY);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_3D);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_CUBE);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_FIRST);
ImgDimComb.Items.Add(GTX.GX2SurfaceDimension.DIM_LAST);
ImgDimComb.SelectedItem = GTX.GX2SurfaceDimension.DIM_2D;
tileModeCB.SelectedItem = GTX.GX2TileMode.MODE_2D_TILED_THIN1;
formatComboBox.SelectedItem = GTX.GX2SurfaceFormat.T_BC1_SRGB;
}
GTXImporterSettings SelectedTexSettings;
@ -86,7 +98,7 @@ namespace FirstPlugin
private Thread Thread;
public void SetupSettings()
{
if (SelectedTexSettings.Format == GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_INVALID)
if (SelectedTexSettings.Format == GTX.GX2SurfaceFormat.INVALID)
return;
@ -98,6 +110,9 @@ namespace FirstPlugin
SelectedTexSettings.Format = (GTX.GX2SurfaceFormat)formatComboBox.SelectedItem;
listViewCustom1.SelectedItems[0].SubItems[1].Text = SelectedTexSettings.Format.ToString();
}
HeightLabel.Text = $"Height: {SelectedTexSettings.TexHeight}";
WidthLabel.Text = $"Width: {SelectedTexSettings.TexWidth}";
Bitmap bitmap = Switch_Toolbox.Library.Imaging.GetLoadingImage();
Thread = new Thread((ThreadStart)(() =>

View File

@ -59,10 +59,10 @@ namespace FirstPlugin
prop.Name = textureData.Text;
prop.Width = textureData.Width;
prop.Height = textureData.Height;
if (textureData.mipmaps.Count > 0)
if (textureData.surfaces.Count > 0)
{
prop.MipCount = (uint)textureData.mipmaps[CurArrayDisplayLevel].Count;
prop.ArrayCount = (uint)textureData.mipmaps.Count;
prop.MipCount = (uint)textureData.surfaces[CurArrayDisplayLevel].mipmaps.Count;
prop.ArrayCount = (uint)textureData.surfaces.Count;
}
prop.Height = textureData.Height;
@ -87,14 +87,14 @@ namespace FirstPlugin
LoadImage();
int MipCount = 1;
if (textureData.mipmaps.Count <= 0)
if (textureData.surfaces.Count <= 0)
return;
else
MipCount = textureData.mipmaps[CurArrayDisplayLevel].Count;
MipCount = textureData.surfaces[CurArrayDisplayLevel].mipmaps.Count;
mipLevelCounterLabel.Text = $"{CurMipDisplayLevel} / {textureData.mipmaps[CurArrayDisplayLevel].Count - 1}";
arrayLevelCounterLabel.Text = $"{CurArrayDisplayLevel} / {textureData.mipmaps.Count - 1}";
mipLevelCounterLabel.Text = $"{CurMipDisplayLevel} / {textureData.surfaces[CurArrayDisplayLevel].mipmaps.Count - 1}";
arrayLevelCounterLabel.Text = $"{CurArrayDisplayLevel} / {textureData.surfaces.Count - 1}";
if (CurMipDisplayLevel != MipCount - 1)
BtnMipsRight.Enabled = true;
@ -106,7 +106,7 @@ namespace FirstPlugin
else
BtmMipsLeft.Enabled = false;
if (CurArrayDisplayLevel != textureData.mipmaps.Count - 1)
if (CurArrayDisplayLevel != textureData.surfaces.Count - 1)
btnRightArray.Enabled = true;
else
btnRightArray.Enabled = false;
@ -153,7 +153,7 @@ namespace FirstPlugin
private void BtnMipsRight_Click(object sender, EventArgs e)
{
if (CurMipDisplayLevel != textureData.mipmaps[CurArrayDisplayLevel].Count - 1)
if (CurMipDisplayLevel != textureData.surfaces[CurArrayDisplayLevel].mipmaps.Count - 1)
CurMipDisplayLevel += 1;
UpdateMipDisplay();
@ -169,7 +169,7 @@ namespace FirstPlugin
private void btnRightArray_Click(object sender, EventArgs e)
{
if (CurArrayDisplayLevel != textureData.mipmaps.Count - 1)
if (CurArrayDisplayLevel != textureData.surfaces.Count - 1)
CurArrayDisplayLevel += 1;
UpdateMipDisplay();

View File

@ -53,6 +53,7 @@ namespace FirstPlugin
public int sparseBinding = 0; //false
public bool IsSRGB = true;
public bool GenerateMipmaps = false; //If bitmap and count more that 1 then geenrate
public float alphaRef = 0.5f;
private SurfaceFormat LoadDDSFormat(uint fourCC, DDS dds = null, bool IsSRGB = false)
{
@ -161,6 +162,30 @@ namespace FirstPlugin
textureData = new TextureData(tex, bntxFile);
}
}
public void LoadTGA(string FileName, BntxFile bntxFile)
{
DecompressedData.Clear();
TexName = Path.GetFileNameWithoutExtension(FileName);
bntx = bntxFile;
Format = SurfaceFormat.BC1_SRGB;
GenerateMipmaps = true;
Bitmap Image = Paloma.TargaImage.LoadTargaImage(FileName);
Image = TextureData.SwapBlueRedChannels(Image);
TexWidth = (uint)Image.Width;
TexHeight = (uint)Image.Height;
MipCount = (uint)GetTotalMipCount();
DecompressedData.Add(BitmapExtension.ImageToByte(Image));
Image.Dispose();
if (DecompressedData.Count == 0)
{
throw new Exception("Failed to load " + Format);
}
}
public void LoadBitMap(string FileName, BntxFile bntxFile)
{
DecompressedData.Clear();
@ -215,14 +240,14 @@ namespace FirstPlugin
Bitmap Image = BitmapExtension.GetBitmap(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight);
List<byte[]> mipmaps = new List<byte[]>();
mipmaps.Add(TextureData.CompressBlock(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight, Format));
mipmaps.Add(TextureData.CompressBlock(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight, Format, alphaRef));
//while (Image.Width / 2 > 0 && Image.Height / 2 > 0)
// for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
{
Image = BitmapExtension.Resize(Image, Image.Width / 2, Image.Height / 2);
mipmaps.Add(TextureData.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, Format));
mipmaps.Add(TextureData.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, Format, alphaRef));
}
Image.Dispose();
@ -233,7 +258,7 @@ namespace FirstPlugin
DataBlockOutput.Clear();
foreach (var surface in DecompressedData)
{
DataBlockOutput.Add(TextureData.CompressBlock(surface, (int)TexWidth, (int)TexHeight, Format));
DataBlockOutput.Add(TextureData.CompressBlock(surface, (int)TexWidth, (int)TexHeight, Format, alphaRef));
}
}
public static uint DIV_ROUND_UP(uint value1, uint value2)

View File

@ -103,9 +103,9 @@
<HintPath>..\Switch_Toolbox\Lib\Syroot.Maths.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Syroot.NintenTools.Bfres">
<Reference Include="Syroot.NintenTools.Bfres, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Switch_Toolbox\Lib\Syroot.NintenTools.Bfres.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Syroot.NintenTools.NSW.Bfres">
<HintPath>..\Switch_Toolbox\Lib\Syroot.NintenTools.NSW.Bfres.dll</HintPath>
@ -170,6 +170,7 @@
<Compile Include="FileFormats\BFRES\Bfres Structs\FMDL.cs" />
<Compile Include="FileFormats\BFRES\Bfres Structs\FSKA.cs" />
<Compile Include="FileFormats\BFSAR.cs" />
<Compile Include="FileFormats\BFSHA.cs" />
<Compile Include="FileFormats\BYAML.cs" />
<Compile Include="FileFormats\CsvModels.cs" />
<Compile Include="FileFormats\GFPAK.cs" />

View File

@ -27,7 +27,6 @@ namespace FirstPlugin
ReadShaderParams(doc, n, mat);
}
}
}
}
public static void ReadShaderParams(XmlDocument doc, XmlNode parentNode, FMAT mat)

View File

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="OpenTK" publicKeyToken="bad199fe84eb3df4" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
<assemblyIdentity name="OpenTK" publicKeyToken="bad199fe84eb3df4" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="LZ4pn" publicKeyToken="62e1b5ec1eec9bdd" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.10.93" newVersion="1.0.10.93" />
<assemblyIdentity name="LZ4pn" publicKeyToken="62e1b5ec1eec9bdd" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.10.93" newVersion="1.0.10.93"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="K4os.Hash.xxHash" publicKeyToken="32cd54395057cec3" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.5.0" newVersion="1.0.5.0" />
<assemblyIdentity name="K4os.Hash.xxHash" publicKeyToken="32cd54395057cec3" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.5.0" newVersion="1.0.5.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/></startup></configuration>

View File

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="lib" />
<probing privatePath="lib"/>
<dependentAssembly>
<assemblyIdentity name="OpenTK" publicKeyToken="bad199fe84eb3df4" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
<assemblyIdentity name="OpenTK" publicKeyToken="bad199fe84eb3df4" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="LZ4pn" publicKeyToken="62e1b5ec1eec9bdd" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.10.93" newVersion="1.0.10.93" />
<assemblyIdentity name="LZ4pn" publicKeyToken="62e1b5ec1eec9bdd" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.10.93" newVersion="1.0.10.93"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="K4os.Hash.xxHash" publicKeyToken="32cd54395057cec3" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.5.0" newVersion="1.0.5.0" />
<assemblyIdentity name="K4os.Hash.xxHash" publicKeyToken="32cd54395057cec3" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.5.0" newVersion="1.0.5.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>

Binary file not shown.

View File

@ -7,7 +7,7 @@ Class DirectXTex.ImageCompressor: AutoLayout, AnsiClass, Class, Public, BeforeFi
Void .ctor(): PrivateScope, Public, HideBySig, SpecialName, RTSpecialName
Methods:
Decompress(Byte[], Int32, Int32, Int32): PrivateScope, Public, Static, HideBySig
Compress(Byte[], Int32, Int32, Int32): PrivateScope, Public, Static, HideBySig
Compress(Byte[], Int32, Int32, Int32, Single): PrivateScope, Public, Static, HideBySig
Class DirectXTex.ImageConverter: AutoLayout, AnsiClass, Class, Public, BeforeFieldInit
Void .ctor(): PrivateScope, Public, HideBySig, SpecialName, RTSpecialName
Methods:

Binary file not shown.

Binary file not shown.

View File

@ -8,8 +8,25 @@
DirectXTexMipmaps.cpp
DirectXTexUtil.cpp
wrapper.cpp
.NETFramework,Version=v4.6.AssemblyAttributes.cpp
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(27): warning C4005: '_WIN32_WINNT': macro redefinition
c:\program files (x86)\windows kits\8.1\include\shared\sdkddkver.h(200): note: see previous definition of '_WIN32_WINNT'
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(48): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(83): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(101): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(102): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(127): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(145): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(146): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(173): warning C4267: 'return': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(181): warning C4267: 'return': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(202): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(203): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(204): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(207): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(208): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
c:\users\nathan\documents\github\switch_toolbox\switch-toolbox - copy\switch_toolbox\lib\directxtex\wrapper.cpp(263): warning C4267: '+=': conversion from 'size_t' to 'int', possible loss of data
.NETFramework,Version=v4.6.2.AssemblyAttributes.cpp
Generating code
All 442 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
All 441 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
Finished generating code
DirectXTex.vcxproj -> C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Release\DirectXTex.dll
DirectXTex.vcxproj -> C:\Users\Nathan\Documents\GitHub\Switch_Toolbox\Switch-Toolbox - Copy\Switch_Toolbox\Lib\DirectXTex\Release\DirectXTex.dll

View File

@ -73,7 +73,7 @@ namespace DirectXTex
}
}
static array<Byte>^ Compress(array<Byte>^ data, int width, int height, int format)
static array<Byte>^ Compress(array<Byte>^ data, int width, int height, int format, float alphaRef)
{
size_t rowPitch = width * 4;
size_t slicePitch = width * height * 4;
@ -93,7 +93,7 @@ namespace DirectXTex
DirectX::ScratchImage outputImage;
// compress image
DirectX::Compress(inputImage, (DXGI_FORMAT)format, 0, 1, outputImage);
DirectX::Compress(inputImage, (DXGI_FORMAT)format, 0, alphaRef, outputImage);
size_t rowPitchOut;
size_t slicePitchOut;

View File

@ -0,0 +1,83 @@
// ==========================================================
// TargaImage
//
// Design and implementation by
// - David Polomis (paloma_sw@cox.net)
//
//
// This source code, along with any associated files, is licensed under
// The Code Project Open License (CPOL) 1.02
// A copy of this license can be found in the CPOL.html file
// which was downloaded with this source code
// or at http://www.codeproject.com/info/cpol10.aspx
//
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
// WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
// INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS
// FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
// NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
// OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE
// DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY
// OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING,
// REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
// ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS
// AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
//
// Use at your own risk!
//
// ==========================================================
.NET Targa Image Reader
Current: C# (C# 1.0, C# 2.0, C# 3.0, C#), Windows (Windows, WinXP), .NET (.NET, .NET 3.5, .NET 3.0, .NET 2.0), GDI+, WebForms, VS2008, Dev, Intermediate
Loads Targa image files into a Bitmap using pure .NET code
TargaImage is availble on CodeProject.com
http://www.codeproject.com/KB/GDI-plus/dotnettargareader.aspx
TargaImage was created with Visual Studio 2008 Standard using C# 3.0 and the .NET Framework 2.0
To use TargaImage copy the TargaImage.dll file from the Release folder in the Bin folder to your own project.
Then include a reference to TargaImage.dll in your project.
To load a targa image call the LoadTargaImage() method of the Paloma.TargaImage class.
Or if you want access to the image properties create an instance of the TargaImage class.
EXAMPLES:
// C# Sample
// Loads a targa image and assigns it to the Image of a picturebox control.
this.PictureBox1.Image = Paloma.TargaImage.LoadTargaImage(@"c:\targaimage.tga");
// Creates an instance of the TargaImage class with the specifed file
// displays a few targa properties and then assigns the targa image
// to the Image of a picturebox control
Paloma.TargaImage tgaImage = new Paloma.TargaImage(@"c:\targaimage.tga");
this.Label1.Text = tgaImage.Format.ToString();
this.Label2.Text = tgaImage.Header.ImageType.ToString();
this.Label3.Text = tgaImage.Header.PixelDepth.ToString();
this.PictureBox1.Image = Paloma.TargaImage.Image;
' VB.NET Sample
' Loads a targa image and assigns it to the Image of a picturebox control.
Me.PictureBox1.Image = Paloma.TargaImage.LoadTargaImage("c:\targaimage.tga")
' Creates an instance of the TargaImage class with the specifed file
' displays a few targa properties and then assigns the targa image
' to the Image of a picturebox control
Dim tgaImage As New Paloma.TargaImage("c:\targaimage.tga")
Me.Label1.Text = tgaImage.Format.ToString()
Me.Label2.Text = tgaImage.Header.ImageType.ToString()
Me.Label3.Text = tgaImage.Header.PixelDepth.ToString()
Me.PictureBox1.Image = Paloma.TargaImage.Image

View File

@ -32,10 +32,17 @@ namespace Switch_Toolbox
private static MainForm _instance;
public static MainForm Instance { get { return _instance == null ? _instance = new MainForm() : _instance; } }
bool AttachCommit = false;
public MainForm()
{
InitializeComponent();
string commit = "";
if (AttachCommit)
commit = $"Commit: {Runtime.CommitInfo}";
Text = $"Switch Toolbox | Compile Date: {Runtime.CompileDate} Version: {Runtime.ProgramVersion} {commit}";
ShaderTools.executableDir = executableDir;
Config.StartupFromFile(MainForm.executableDir + "\\config.xml");
@ -199,8 +206,7 @@ namespace Switch_Toolbox
}
private void LoadObjectList()
{
objectList = new ObjectList();
objectList.Show(dockPanel1, Runtime.objectListDockState);
ObjectList.Instance.Show(dockPanel1, Runtime.objectListDockState);
}
public void SaveFile(IFileFormat format, string FileName)
{
@ -286,12 +292,12 @@ namespace Switch_Toolbox
format.FileIsCompressed = Compressed;
format.Data = data;
format.FileName = Path.GetFileName(FileName);
format.Load();
format.FilePath = FileName;
format.Load();
if (format is TreeNode)
{
objectList.treeView1.Nodes.Add((TreeNode)format);
ObjectList.Instance.treeView1.Nodes.Add((TreeNode)format);
}
if (format.CanSave)
@ -321,7 +327,7 @@ namespace Switch_Toolbox
if (format is TreeNode)
{
objectList.treeView1.Nodes.Add((TreeNode)format);
ObjectList.Instance.treeView1.Nodes.Add((TreeNode)format);
}
if (format.CanSave)

View File

@ -64,8 +64,15 @@ uniform int HasRoughnessMap;
uniform int HasMRA;
uniform int HasSubSurfaceScatteringMap;
uniform int renderTevColors;
uniform int renderMatColors;
uniform vec4 const_color0;
uniform vec4 base_color_mul_color;
uniform vec4 tev_color0;
uniform vec4 tev_color1;
uniform vec4 mat_color0;
uniform vec4 mat_color1;
struct VertexAttributes {
vec3 objectPosition;
@ -146,6 +153,17 @@ void main()
fragColor *= min(const_color0, vec4(1));
fragColor *= min(base_color_mul_color, vec4(1));
float colorScale = texture(DiffuseMap, f_texcoord0).r;
if (renderMatColors == 1)
{
// fragColor *= vec4(min(mat_color0, colorScale).rgb, 1.0);
// fragColor *= vec4(min(mat_color1, (1 - colorScale) + colorScale * 0).rgb, 1.0);
}
if (renderTevColors == 1)
{
// fragColor *= vec4(min(tev_color0, colorScale).rgb, 1.0);
// fragColor *= vec4(min(tev_color1, (1 - colorScale) + colorScale * 0).rgb, 1.0);
}
// if (isTransparent != 1)
// fragColor.a = 1;

View File

@ -167,6 +167,7 @@
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VersionCheck.cs" />
<EmbeddedResource Include="GUI\Credits.resx">
<DependentUpon>Credits.cs</DependentUpon>
</EmbeddedResource>
@ -275,6 +276,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Assimp32.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="libzstd.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -325,6 +329,12 @@
<Content Include="Lib\Licenses\SmashForge COPYRIGHT.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\Licenses\TargaImage COPYRIGHT.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\Licenses\TexConv COPYRIGHT.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\LZ4.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -361,6 +371,9 @@
<Content Include="Lib\Syroot.Maths.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\Syroot.NintenTools.Bfres.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\Syroot.NintenTools.NSW.Bfres.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@ -0,0 +1,3 @@
Version:
Commit:
Build Date:

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library;
namespace Switch_Toolbox
{
public class VersionCheck
{
public void ReadVersionInfo()
{
string path = MainForm.executableDir + "Version.txt";
using (StreamReader reader = new StreamReader(path))
{
string Version = reader.ReadLine();
}
}
public void WriteVersionInfo()
{
string path = MainForm.executableDir + "Version.txt";
using (StreamWriter writer = new StreamWriter(path))
{
writer.Write($"Version: {Runtime.ProgramVersion}");
writer.Write($"Commit: {Runtime.CommitInfo}");
writer.Write($"Build Date: {Runtime.CompileDate}");
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library.IO;
namespace Switch_Toolbox.Library
{
public class ASTC
{
const uint Magic = 0x5CA1AB13;
public byte BlockDimX;
public byte BlockDimY;
public byte BlockDimZ;
public int X;
public int Y;
public int Z;
public void WriteASTCHeader(FileWriter writer)
{
writer.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
writer.Write(Magic);
writer.Write(BlockDimX);
writer.Write(BlockDimY);
writer.Write(BlockDimZ);
writer.Write(X);
writer.Write(Y);
writer.Write(Z);
}
}
}

View File

@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Assimp;
using Assimp.Configs;
using OpenTK;
using Switch_Toolbox.Library.Rendering;
using System.Windows.Forms;
@ -15,10 +11,10 @@ namespace Switch_Toolbox.Library
public class AssimpData
{
public Scene scene;
private Vector3 m_sceneCenter, m_sceneMin, m_sceneMax;
public List<STGenericObject> objects = new List<STGenericObject>();
public List<STGenericMaterial> materials = new List<STGenericMaterial>();
public List<STGenericTexture> textures = new List<STGenericTexture>();
public AssimpContext Importer = new AssimpContext();
@ -36,10 +32,14 @@ namespace Switch_Toolbox.Library
{
AssimpContext Importer = new AssimpContext();
scene = Importer.ImportFile(FileName, PostProcessSteps.Triangulate | PostProcessSteps.JoinIdenticalVertices
| PostProcessSteps.FlipUVs | PostProcessSteps.LimitBoneWeights |
PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
LoadMeshes();
scene = Importer.ImportFile(FileName,
PostProcessSteps.Triangulate |
PostProcessSteps.JoinIdenticalVertices |
PostProcessSteps.FlipUVs |
PostProcessSteps.LimitBoneWeights |
PostProcessSteps.CalculateTangentSpace |
PostProcessSteps.GenerateNormals);
LoadScene();
}
catch (Exception e)
{
@ -79,9 +79,12 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
foreach (Node child in parent.Children)
BuildNode(child, ref world);
}
public void LoadMeshes()
public void LoadScene()
{
objects.Clear();
textures.Clear();
materials.Clear();
processNode();
if (scene.HasMaterials)
{
@ -94,6 +97,9 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
{
}
foreach (var tex in scene.Textures)
{
}
}
public Animation CreateGenericAnimation(Assimp.Animation animation)
{
@ -123,11 +129,34 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
return STanim;
}
public STGenericTexture CreateGenericTexture(string Path)
{
STGenericTexture tex = new STGenericTexture();
switch (System.IO.Path.GetExtension(Path))
{
case ".dds":
tex.LoadDDS(Path);
break;
case ".tga":
tex.LoadTGA(Path);
break;
default:
tex.LoadBitmap(Path);
break;
}
return tex;
}
public STGenericMaterial CreateGenericMaterial(Material material)
{
STGenericMaterial mat = new STGenericMaterial();
mat.Text = material.Name;
foreach (var slot in material.GetAllMaterialTextures())
{
textures.Add(CreateGenericTexture(slot.FilePath));
}
TextureSlot tex;
if (material.GetMaterialTexture(TextureType.Diffuse, 0, out tex))
mat.TextureMaps.Add(CreateTextureSlot(tex, TextureType.Diffuse));
@ -222,7 +251,7 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
obj.boneList = GetBoneList(msh);
obj.MaxSkinInfluenceCount = GetVertexSkinCount(msh);
GenericObject.LOD_Mesh lod = new GenericObject.LOD_Mesh();
STGenericObject.LOD_Mesh lod = new STGenericObject.LOD_Mesh();
lod.faces = GetFaces(msh);
lod.IndexFormat = STIndexFormat.UInt16;
lod.PrimitiveType = STPolygonType.Triangle;
@ -233,24 +262,19 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
return obj;
}
int NodeIndex;
public void SaveFromModel(GenericModel model, string FileName)
public void SaveFromModel(STGenericModel model, string FileName, List<STGenericTexture> Textures)
{
Scene scene = new Scene();
scene.RootNode = new Node("Root");
scene.RootNode = new Node("RootNode");
Node modelNode = new Node(model.Text);
scene.RootNode.Children.Add(modelNode);
int MeshIndex = 0;
foreach (var obj in model.Nodes[0].Nodes)
{
var genericObj = (STGenericObject)obj;
Node groupNode = new Node(genericObj.Text);
Mesh mesh = new Mesh(genericObj.Text, PrimitiveType.Triangle);
mesh.MaterialIndex = genericObj.MaterialIndex;
List<Vector3D> textureCoords0 = new List<Vector3D>();
List<Vector3D> textureCoords1 = new List<Vector3D>();
@ -269,37 +293,38 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
mesh.TextureCoordinateChannels[2] = textureCoords2;
mesh.VertexColorChannels[0] = vertexColors;
}
List<int> faces = genericObj.lodMeshes[genericObj.DisplayLODIndex].faces;
for (int f = 0; f < faces.Count; f++)
mesh.Faces.Add(new Face(new int[] { faces[f++], faces[f++], faces[f] }));
Console.WriteLine(genericObj.faces.Count);
Console.WriteLine(genericObj.vertices.Count);
Console.WriteLine(genericObj.Text);
mesh.MaterialIndex = genericObj.MaterialIndex;
mesh.TextureCoordinateChannels.SetValue(textureCoords0, 0);
groupNode.MeshIndices.Add(scene.Meshes.Count);
scene.Meshes.Add(mesh);
MeshIndex++;
modelNode.Children.Add(groupNode);
}
string TextureExtension = ".png";
string TexturePath = System.IO.Path.GetDirectoryName(FileName);
foreach (var mat in model.Nodes[1].Nodes)
{
var genericMat = (STGenericMaterial)mat;
Material material = new Material();
material.Name = genericMat.Name;
material.Name = genericMat.Text;
foreach (var tex in genericMat.TextureMaps)
{
TextureSlot slot = new TextureSlot();
slot.FilePath = tex.Name;
string path = System.IO.Path.Combine(TexturePath, tex.Name + TextureExtension);
slot.FilePath = path;
slot.UVIndex = 0;
slot.Flags = 0;
slot.TextureIndex = 0;
slot.BlendFactor = 1.0f;
slot.Mapping = TextureMapping.FromUV;
slot.Operation = TextureOperation.Add;
if (tex.Type == STGenericMatTexture.TextureType.Diffuse)
slot.TextureType = TextureType.Diffuse;
@ -311,13 +336,13 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
slot.TextureType = TextureType.Emissive;
else if (tex.Type == STGenericMatTexture.TextureType.Light)
{
slot.Mapping = TextureMapping.FromUV - 1;
slot.TextureType = TextureType.Lightmap;
slot.UVIndex = 2;
}
else if (tex.Type == STGenericMatTexture.TextureType.Shadow)
{
slot.Mapping = TextureMapping.FromUV - 1;
slot.TextureType = TextureType.Ambient;
slot.UVIndex = 1;
}
else
slot.TextureType = TextureType.Unknown;
@ -329,16 +354,27 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
if (tex.wrapModeS == 2)
slot.WrapModeU = TextureWrapMode.Clamp;
if (tex.wrapModeT == 0)
slot.WrapModeU = TextureWrapMode.Wrap;
slot.WrapModeV = TextureWrapMode.Wrap;
if (tex.wrapModeT == 1)
slot.WrapModeU = TextureWrapMode.Mirror;
slot.WrapModeV = TextureWrapMode.Mirror;
if (tex.wrapModeT == 2)
slot.WrapModeU = TextureWrapMode.Clamp;
slot.WrapModeV = TextureWrapMode.Clamp;
else
{
slot.WrapModeU = TextureWrapMode.Wrap;
slot.WrapModeV = TextureWrapMode.Wrap;
}
material.AddMaterialTexture(ref slot);
}
scene.Materials.Add(material);
}
foreach (var tex in Textures)
{
string path = System.IO.Path.Combine(TexturePath, tex.Name + TextureExtension);
if (!System.IO.File.Exists(path))
tex.GetBitmap().Save(path);
}
using (var v = new AssimpContext())
{
@ -348,16 +384,11 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
if (ext == ".obj")
formatID = "obj";
if (ext == ".fbx")
formatID = "fbx";
formatID = "collada";
if (ext == ".dae")
formatID = "dae";
formatID = "collada";
Console.WriteLine(ext);
Console.WriteLine(formatID);
bool Exported = v.ExportFile(scene, FileName, formatID);
if (Exported)
if (v.ExportFile(scene, FileName, formatID, PostProcessSteps.ValidateDataStructure))
System.Windows.Forms.MessageBox.Show($"Exported {FileName} Successfuly!");
else
System.Windows.Forms.MessageBox.Show($"Failed to export {FileName}!");
@ -396,7 +427,6 @@ PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
mesh.TextureCoordinateChannels.SetValue(textureCoords0, 0);
scene.Meshes.Add(mesh);
scene.RootNode.MeshIndices.Add(0);
Material material = new Material();
material.Name = "NewMaterial";

View File

@ -504,7 +504,36 @@ namespace Switch_Toolbox.Library
}
}
}
public void Save(DDS dds, string FileName, List<List<byte[]>> data = null)
public STGenericTexture.TEX_FORMAT GetFormat()
{
if (DX10header != null)
return (STGenericTexture.TEX_FORMAT)DX10header.DXGI_Format;
switch (header.ddspf.fourCC)
{
case FOURCC_DXT1:
return STGenericTexture.TEX_FORMAT.BC1_UNORM;
case FOURCC_DXT2:
return STGenericTexture.TEX_FORMAT.BC2_UNORM;
case FOURCC_DXT3:
return STGenericTexture.TEX_FORMAT.BC2_UNORM;
case FOURCC_DXT4:
return STGenericTexture.TEX_FORMAT.BC3_UNORM;
case FOURCC_DXT5:
return STGenericTexture.TEX_FORMAT.BC3_UNORM;
case FOURCC_ATI1:
return STGenericTexture.TEX_FORMAT.BC4_UNORM;
case FOURCC_BC4U:
return STGenericTexture.TEX_FORMAT.BC4_UNORM;
case FOURCC_ATI2:
return STGenericTexture.TEX_FORMAT.BC5_UNORM;
case FOURCC_BC5U:
return STGenericTexture.TEX_FORMAT.BC5_UNORM;
default:
return STGenericTexture.TEX_FORMAT.UNKNOWN;
}
}
public void Save(DDS dds, string FileName, List<STGenericTexture.Surface> data = null)
{
FileWriter writer = new FileWriter(new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.Write));
var header = dds.header;
@ -543,7 +572,7 @@ namespace Switch_Toolbox.Library
if (data != null)
{
writer.Write(data[0][0]);
writer.Write(data[0].mipmaps[0]);
}
else
{

View File

@ -484,9 +484,9 @@ namespace Switch_Toolbox.Library
{
return DirectXTex.ImageCompressor.Decompress(data, width, height, (int)format);
}
public static byte[] CompressBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format)
public static byte[] CompressBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format, float alphaRef)
{
return DirectXTex.ImageCompressor.Compress(data, width, height, (int)format);
return DirectXTex.ImageCompressor.Compress(data, width, height, (int)format, alphaRef);
}
public static byte[] EncodePixelBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format)
{

View File

@ -50,15 +50,6 @@ namespace Switch_Toolbox.Library
return Img;
}
private static void ConvertBgraToRgba(byte[] bytes)
{
for (int i = 0; i < bytes.Length; i += 4)
{
var temp = bytes[i];
bytes[i] = bytes[i + 2];
bytes[i + 2] = temp;
}
}
public class ColorSwapFilter
{
private ColorSwapType swapType = ColorSwapType.FixDDS;

View File

@ -16,6 +16,40 @@ namespace Switch_Toolbox.Library
public virtual void OnMouseRightClick(TreeView treeview) { }
public virtual void OnDoubleMouseClick(TreeView treeview) { }
public void Sort(TreeNode node)
{
/* string[] array = new string[Nodes.Count];
for (int i = 0; i < Nodes.Count; ++i)
array[i] = Nodes[i].Text;
Array.Sort<string>(array, (IComparer<string>)StringComparer.Ordinal);
for (int index = 0; index < Nodes.Count; ++index)
Nodes[index].Text = array[index];*/
//Good enough for now. I'll update with a more cleaner method later
foreach (TreeNode n in node.Nodes)
Sort(n);
try
{
TreeNode temp = null;
List<TreeNode> childs = new List<TreeNode>();
while (node.Nodes.Count > 0)
{
foreach (TreeNode n in node.Nodes)
if (temp == null || n.Text[0] < temp.Text[0])
temp = n;
node.Nodes.Remove(temp);
childs.Add(temp);
temp = null;
}
node.Nodes.Clear();
foreach (TreeNode a in childs)
node.Nodes.Add(a);
}
catch { }
}
public TreeNodeCustom()
{
}

View File

@ -31,7 +31,7 @@ namespace Switch_Toolbox.Library
listView1.Items.Add(msh.Name);
}
}
public GenericObject GetSelectedMesh()
public STGenericObject GetSelectedMesh()
{
assimp.processNode();
foreach (Mesh msh in assimp.scene.Meshes)

View File

@ -30,13 +30,13 @@
{
this.components = new System.ComponentModel.Container();
this.panel1 = new System.Windows.Forms.Panel();
this.treeView1 = new Switch_Toolbox.Library.TreeViewCustom();
this.contextMenuStripDark1 = new Switch_Toolbox.Library.Forms.ContextMenuStripDark();
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.smallToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mediumToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.largeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.searchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.treeView1 = new Switch_Toolbox.Library.TreeViewCustom();
this.panel1.SuspendLayout();
this.contextMenuStripDark1.SuspendLayout();
this.SuspendLayout();
@ -51,6 +51,30 @@
this.panel1.Size = new System.Drawing.Size(358, 27);
this.panel1.TabIndex = 2;
//
// treeView1
//
this.treeView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.treeView1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
this.treeView1.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.treeView1.CheckBoxes = true;
this.treeView1.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawText;
this.treeView1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.treeView1.ForeColor = System.Drawing.Color.White;
this.treeView1.ImageIndex = 0;
this.treeView1.Location = new System.Drawing.Point(0, 27);
this.treeView1.Name = "treeView1";
this.treeView1.SelectedImageIndex = 0;
this.treeView1.Size = new System.Drawing.Size(358, 423);
this.treeView1.TabIndex = 0;
this.treeView1.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterCheck);
this.treeView1.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.treeView1_DrawNode);
this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
this.treeView1.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.selectItem);
this.treeView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.treeView1_MouseClick);
this.treeView1.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.treeView1_MouseDoubleClick);
//
// contextMenuStripDark1
//
this.contextMenuStripDark1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(33)))), ((int)(((byte)(33)))));
@ -105,27 +129,6 @@
this.searchToolStripMenuItem.Text = "Search";
this.searchToolStripMenuItem.Click += new System.EventHandler(this.searchToolStripMenuItem_Click);
//
// treeView1
//
this.treeView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.treeView1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
this.treeView1.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.treeView1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.treeView1.ForeColor = System.Drawing.Color.White;
this.treeView1.ImageIndex = 0;
this.treeView1.Location = new System.Drawing.Point(0, 27);
this.treeView1.Name = "treeView1";
this.treeView1.SelectedImageIndex = 0;
this.treeView1.Size = new System.Drawing.Size(358, 423);
this.treeView1.TabIndex = 0;
this.treeView1.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterCheck);
this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
this.treeView1.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.selectItem);
this.treeView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.treeView1_MouseClick);
this.treeView1.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.treeView1_MouseDoubleClick);
//
// ObjectList
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

View File

@ -17,6 +17,9 @@ namespace Switch_Toolbox.Library
{
public partial class ObjectList : DockContent
{
private static ObjectList _instance;
public static ObjectList Instance { get { return _instance == null ? _instance = new ObjectList() : _instance; } }
Thread Thread;
public ObjectList()
@ -149,16 +152,17 @@ namespace Switch_Toolbox.Library
if (treeView1.SelectedNode is TreeNodeCustom)
{
((TreeNodeCustom)treeView1.SelectedNode).OnClick(treeView1);
}
if (treeView1.SelectedNode is STGenericObject)
{
((STGenericObject)treeView1.SelectedNode).OnClick(treeView1);
Viewport.Instance.Update();
}
if (treeView1.SelectedNode is STGenericMaterial)
{
((STGenericMaterial)treeView1.SelectedNode).OnClick(treeView1);
}
Viewport.Instance.UpdateViewport();
}
private void ObjectList_DockStateChanged(object sender, EventArgs e)
@ -168,6 +172,23 @@ namespace Switch_Toolbox.Library
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
Viewport.Instance.UpdateViewport();
if (e.Node is STGenericModel)
{
CheckChildNodes(e.Node, e.Node.Checked);
}
}
private void CheckChildNodes(TreeNode node, bool IsChecked)
{
foreach (TreeNode n in node.Nodes)
{
n.Checked = IsChecked;
if (n.Nodes.Count > 0)
{
CheckChildNodes(n, IsChecked);
}
}
}
private void searchToolStripMenuItem_Click(object sender, EventArgs e)
@ -209,5 +230,16 @@ namespace Switch_Toolbox.Library
((TreeNodeCustom)treeView1.SelectedNode).OnDoubleMouseClick(treeView1);
}
}
private void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
e.DrawDefault = true;
if (e.Node is STGenericObject || e.Node is STGenericModel)
{
}
else
TreeViewExtensions.HideCheckBox(e.Node);
}
}
}

View File

@ -120,4 +120,7 @@
<metadata name="contextMenuStripDark1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="contextMenuStripDark1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL;
namespace Switch_Toolbox.Library
{
public class STGenericMatTexture
{
public int mapMode = 0;
public int wrapModeS = 1;
public int wrapModeT = 1;
public int wrapModeW = 1; //Used for 3D textures
public int minFilter = 3;
public int magFilter = 2;
public int mipDetail = 6;
public string Name;
public TextureType Type;
//An enum for the assumed texture type by sampler
//Many games have a consistant type of samplers and type. _a0 for diffuse, _n0 for normal, ect
public enum TextureType
{
Unknown = 0,
Diffuse = 1,
Normal = 2,
Specular = 3,
Emission = 4,
DiffuseLayer2 = 5,
TeamColor = 6,
Transparency = 7,
Shadow = 8,
AO = 9,
Light = 10,
Roughness = 11,
Metalness = 12,
MRA = 13, //Combined pbr texture HAL uses for KSA
SphereMap = 14,
SubSurfaceScattering = 15,
}
public static readonly Dictionary<int, TextureMinFilter> minfilter = new Dictionary<int, TextureMinFilter>()
{
{ 0x00, TextureMinFilter.LinearMipmapLinear},
{ 0x01, TextureMinFilter.Nearest},
{ 0x02, TextureMinFilter.Linear},
{ 0x03, TextureMinFilter.NearestMipmapLinear},
};
public static readonly Dictionary<int, TextureMagFilter> magfilter = new Dictionary<int, TextureMagFilter>()
{
{ 0x00, TextureMagFilter.Linear},
{ 0x01, TextureMagFilter.Nearest},
{ 0x02, TextureMagFilter.Linear}
};
public static Dictionary<int, TextureWrapMode> wrapmode = new Dictionary<int, TextureWrapMode>(){
{ 0x00, TextureWrapMode.Repeat},
{ 0x01, TextureWrapMode.MirroredRepeat},
{ 0x02, TextureWrapMode.ClampToEdge},
{ 0x03, TextureWrapMode.MirroredRepeat},
};
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Switch_Toolbox.Library
{
public class STGenericMaterial : TreeNodeCustom
{
public List<STGenericMatTexture> TextureMaps = new List<STGenericMatTexture>();
public override void OnClick(TreeView treeView)
{
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Switch_Toolbox.Library
{
public class STGenericModel : TreeNodeCustom
{
public STGenericModel()
{
Checked = true;
}
public override void OnClick(TreeView treeView)
{
}
}
}

View File

@ -0,0 +1,364 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenTK;
using System.Windows.Forms;
using Switch_Toolbox.Library.Rendering;
namespace Switch_Toolbox.Library
{
public class STGenericObject : TreeNodeCustom
{
public STGenericObject()
{
Checked = true;
}
public override void OnClick(TreeView treeView)
{
}
public bool HasPos;
public bool HasNrm;
public bool HasUv0;
public bool HasUv1;
public bool HasUv2;
public bool HasWeights;
public bool HasIndices;
public bool HasBitans;
public bool HasTans;
public bool HasVertColors;
public int MaxSkinInfluenceCount;
public string ObjectName;
public int BoneIndex;
public int MaterialIndex;
public int VertexBufferIndex;
public int DisplayLODIndex;
public int Offset;
public int GetMaxSkinInfluenceCount()
{
return vertices.Max(t => t.boneIds.Count);
}
public Vector3 GetOrigin()
{
Vector3 pos = Vector3.Zero;
foreach (Vertex vert in vertices)
{
}
return pos;
}
public List<string[]> bones = new List<string[]>();
public List<float[]> weightsT = new List<float[]>();
public List<string> boneList = new List<string>();
public List<Vertex> vertices = new List<Vertex>();
public List<LOD_Mesh> lodMeshes = new List<LOD_Mesh>();
public class LOD_Mesh
{
public STPolygonType PrimitiveType = STPolygonType.Triangle;
public STIndexFormat IndexFormat = STIndexFormat.UInt16;
public uint FirstVertex;
public List<SubMesh> subMeshes = new List<SubMesh>();
public class SubMesh
{
public uint size;
public uint offset;
}
public void GenerateSubMesh()
{
subMeshes.Clear();
SubMesh subMesh = new SubMesh();
subMesh.offset = 0;
subMesh.size = (uint)faces.Count;
subMeshes.Add(subMesh);
}
public int index = 0;
public int strip = 0x40;
public int displayFaceSize = 0;
public List<int> faces = new List<int>();
public override string ToString()
{
return "LOD Mesh " + index;
}
public List<int> getDisplayFace()
{
if ((strip >> 4) == 4)
{
displayFaceSize = faces.Count;
return faces;
}
else
{
List<int> f = new List<int>();
int startDirection = 1;
int p = 0;
int f1 = faces[p++];
int f2 = faces[p++];
int faceDirection = startDirection;
int f3;
do
{
f3 = faces[p++];
if (f3 == 0xFFFF)
{
f1 = faces[p++];
f2 = faces[p++];
faceDirection = startDirection;
}
else
{
faceDirection *= -1;
if ((f1 != f2) && (f2 != f3) && (f3 != f1))
{
if (faceDirection > 0)
{
f.Add(f3);
f.Add(f2);
f.Add(f1);
}
else
{
f.Add(f2);
f.Add(f3);
f.Add(f1);
}
}
f1 = f2;
f2 = f3;
}
} while (p < faces.Count);
displayFaceSize = f.Count;
return f;
}
}
}
public List<int> faces = new List<int>();
#region Methods
public void FlipUvsVertical()
{
foreach (Vertex v in vertices)
{
v.uv0 = new Vector2(v.uv0.X, 1 - v.uv0.Y);
}
}
public void FlipUvsHorizontal()
{
foreach (Vertex v in vertices)
{
v.uv0 = new Vector2(1 - v.uv0.X, v.uv0.Y);
}
}
public void CalculateTangentBitangent()
{
List<int> f = lodMeshes[DisplayLODIndex].getDisplayFace();
Vector3[] tanArray = new Vector3[vertices.Count];
Vector3[] bitanArray = new Vector3[vertices.Count];
CalculateTanBitanArrays(f, tanArray, bitanArray);
ApplyTanBitanArray(tanArray, bitanArray);
}
private void ApplyTanBitanArray(Vector3[] tanArray, Vector3[] bitanArray)
{
for (int i = 0; i < vertices.Count; i++)
{
Vertex v = vertices[i];
Vector3 newTan = tanArray[i];
Vector3 newBitan = bitanArray[i];
// The tangent and bitangent should be orthogonal to the normal.
// Bitangents are not calculated with a cross product to prevent flipped shading with mirrored normal maps.
v.tan = new Vector4(Vector3.Normalize(newTan - v.nrm * Vector3.Dot(v.nrm, newTan)), 1);
v.bitan = new Vector4(Vector3.Normalize(newBitan - v.nrm * Vector3.Dot(v.nrm, newBitan)), 1);
v.bitan *= -1;
}
}
private void CalculateTanBitanArrays(List<int> faces, Vector3[] tanArray, Vector3[] bitanArray)
{
for (int i = 0; i < lodMeshes[DisplayLODIndex].displayFaceSize; i += 3)
{
Vertex v1 = vertices[faces[i]];
Vertex v2 = vertices[faces[i + 1]];
Vertex v3 = vertices[faces[i + 2]];
bool UseUVLayer2 = false;
float x1 = v2.pos.X - v1.pos.X;
float x2 = v3.pos.X - v1.pos.X;
float y1 = v2.pos.Y - v1.pos.Y;
float y2 = v3.pos.Y - v1.pos.Y;
float z1 = v2.pos.Z - v1.pos.Z;
float z2 = v3.pos.Z - v1.pos.Z;
float s1, s2, t1, t2;
if (UseUVLayer2)
{
s1 = v2.uv1.X - v1.uv1.X;
s2 = v3.uv1.X - v1.uv1.X;
t1 = v2.uv1.Y - v1.uv1.Y;
t2 = v3.uv1.Y - v1.uv1.Y;
}
else
{
s1 = v2.uv0.X - v1.uv0.X;
s2 = v3.uv0.X - v1.uv0.X;
t1 = v2.uv0.Y - v1.uv0.Y;
t2 = v3.uv0.Y - v1.uv0.Y;
}
float div = (s1 * t2 - s2 * t1);
float r = 1.0f / div;
// Fix +/- infinity from division by 0.
if (r == float.PositiveInfinity || r == float.NegativeInfinity)
r = 1.0f;
float sX = t2 * x1 - t1 * x2;
float sY = t2 * y1 - t1 * y2;
float sZ = t2 * z1 - t1 * z2;
Vector3 s = new Vector3(sX, sY, sZ) * r;
float tX = s1 * x2 - s2 * x1;
float tY = s1 * y2 - s2 * y1;
float tZ = s1 * z2 - s2 * z1;
Vector3 t = new Vector3(tX, tY, tZ) * r;
// Prevents black tangents or bitangents due to having vertices with the same UV coordinates.
float delta = 0.00075f;
bool sameU, sameV;
if (UseUVLayer2)
{
sameU = (Math.Abs(v1.uv1.X - v2.uv1.X) < delta) && (Math.Abs(v2.uv1.X - v3.uv1.X) < delta);
sameV = (Math.Abs(v1.uv1.Y - v2.uv1.Y) < delta) && (Math.Abs(v2.uv1.Y - v3.uv1.Y) < delta);
}
else
{
sameU = (Math.Abs(v1.uv0.X - v2.uv0.X) < delta) && (Math.Abs(v2.uv0.X - v3.uv0.X) < delta);
sameV = (Math.Abs(v1.uv0.Y - v2.uv0.Y) < delta) && (Math.Abs(v2.uv0.Y - v3.uv0.Y) < delta);
}
if (sameU || sameV)
{
// Let's pick some arbitrary tangent vectors.
s = new Vector3(1, 0, 0);
t = new Vector3(0, 1, 0);
}
// Average tangents and bitangents.
tanArray[faces[i]] += s;
tanArray[faces[i + 1]] += s;
tanArray[faces[i + 2]] += s;
bitanArray[faces[i]] += t;
bitanArray[faces[i + 1]] += t;
bitanArray[faces[i + 2]] += t;
}
}
public void SmoothNormals()
{
Vector3[] normals = new Vector3[vertices.Count];
List<int> f = lodMeshes[DisplayLODIndex].getDisplayFace();
for (int i = 0; i < lodMeshes[DisplayLODIndex].displayFaceSize; i += 3)
{
Vertex v1 = vertices[f[i]];
Vertex v2 = vertices[f[i + 1]];
Vertex v3 = vertices[f[i + 2]];
Vector3 nrm = CalculateNormal(v1, v2, v3);
normals[f[i + 0]] += nrm;
normals[f[i + 1]] += nrm;
normals[f[i + 2]] += nrm;
}
for (int i = 0; i < normals.Length; i++)
vertices[i].nrm = normals[i].Normalized();
// Compare each vertex with all the remaining vertices. This might skip some.
for (int i = 0; i < vertices.Count; i++)
{
Vertex v = vertices[i];
for (int j = i + 1; j < vertices.Count; j++)
{
Vertex v2 = vertices[j];
if (v == v2)
continue;
float dis = (float)Math.Sqrt(Math.Pow(v.pos.X - v2.pos.X, 2) + Math.Pow(v.pos.Y - v2.pos.Y, 2) + Math.Pow(v.pos.Z - v2.pos.Z, 2));
if (dis <= 0f) // Extra smooth
{
Vector3 nn = ((v2.nrm + v.nrm) / 2).Normalized();
v.nrm = nn;
v2.nrm = nn;
}
}
}
}
public void CalculateNormals()
{
Vector3[] normals = new Vector3[vertices.Count];
for (int i = 0; i < normals.Length; i++)
normals[i] = new Vector3(0, 0, 0);
List<int> f = lodMeshes[DisplayLODIndex].getDisplayFace();
for (int i = 0; i < lodMeshes[DisplayLODIndex].displayFaceSize; i += 3)
{
Vertex v1 = vertices[f[i]];
Vertex v2 = vertices[f[i + 1]];
Vertex v3 = vertices[f[i + 2]];
Vector3 nrm = CalculateNormal(v1, v2, v3);
normals[f[i + 0]] += nrm * (nrm.Length / 2);
normals[f[i + 1]] += nrm * (nrm.Length / 2);
normals[f[i + 2]] += nrm * (nrm.Length / 2);
}
for (int i = 0; i < normals.Length; i++)
vertices[i].nrm = normals[i].Normalized();
}
private Vector3 CalculateNormal(Vertex v1, Vertex v2, Vertex v3)
{
Vector3 U = v2.pos - v1.pos;
Vector3 V = v3.pos - v1.pos;
// Don't normalize here, so surface area can be calculated.
return Vector3.Cross(U, V);
}
public void SetVertexColor(Vector4 intColor)
{
// (127, 127, 127, 255) is white.
foreach (Vertex v in vertices)
{
v.col = intColor;
}
}
#endregion
}
}

View File

@ -0,0 +1,371 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Switch_Toolbox.Library.IO;
namespace Switch_Toolbox.Library
{
public class STGenericTexture : TreeNodeCustom
{
/// <summary>
/// Stores the <see cref="Surface"/> instances for arrays of images. Cubemaps use 6 surfaces.
/// </summary>
public List<Surface> surfaces = new List<Surface>();
/// <summary>
/// The total amount of surfaces for the texture.
/// </summary>
public int ArrayCount
{
get
{
return surfaces.Count;
}
}
/// <summary>
/// The width of the image in pixels
/// </summary>
public uint Width;
/// <summary>
/// The height of the image in pixels
/// </summary>
public uint Height;
/// <summary>
/// The <see cref="TEX_FORMAT"/> Format of the image.
/// </summary>
public TEX_FORMAT Format;
/// <summary>
/// The total amount of mip maps for the texture.
/// </summary>
public uint MipmapCount;
/// <summary>
/// A Surface contains mip levels of compressed/uncompressed texture data
/// </summary>
public class Surface
{
public List<byte[]> mipmaps = new List<byte[]>();
}
/// <summary>
/// Gets a <see cref="Bitmap"/> given an array and mip index.
/// </summary>
/// <param name="ArrayIndex">The index of the surface/array. Cubemaps will have 6</param>
/// <param name="MipLevel">The index of the mip level.</param>
/// <returns></returns>
public Bitmap GetBitmap(int ArrayIndex = 0, int MipLevel = 0)
{
if (surfaces.Count == 0)
throw new Exception($"Surfaces are empty on texture {Text}! Failed to get bitmap!");
return BitmapExtension.GetBitmap(DecodeBlock(surfaces[ArrayIndex].mipmaps[MipLevel], Height, Width, Format),
(int)Width, (int)Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
}
/// <summary>
/// Decodes a byte array of image data given the source image in bytes, width, height, and DXGI format.
/// </summary>
/// <param name="byte[]">The byte array of the image</param>
/// <param name="Width">The width of the image in pixels.</param>
/// <param name="Height">The height of the image in pixels.</param>
/// <param name=" DDS.DXGI_FORMAT">The image format.</param>
/// <returns>Returns a byte array of decoded data. </returns>
public static byte[] DecodeBlock(byte[] data, uint Width, uint Height, TEX_FORMAT Format)
{
if (data.Length <= 0)
throw new Exception($"Data is empty!");
if (Width <= 0)
throw new Exception($"Invalid width size {Width}!");
if (Height <= 0)
throw new Exception($"Invalid height size {Height}!");
if (Format == TEX_FORMAT.BC5_SNORM)
return ConvertBgraToRgba(DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true, true));
if (IsCompressed(Format))
return ConvertBgraToRgba(DDSCompressor.DecompressBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format));
else
{
//If blue channel becomes first, do not swap them
if (Format.ToString().Contains("FORMAT_B"))
return DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format);
else
return ConvertBgraToRgba(DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format));
}
}
public void LoadDDS(string path)
{
SetNameFromPath(path);
DDS dds = new DDS();
LoadDDS(path);
Width = dds.header.width;
Height = dds.header.height;
Format = dds.GetFormat();
MipmapCount = dds.header.mipmapCount;
}
public void LoadTGA(string path)
{
SetNameFromPath(path);
Bitmap tga = Paloma.TargaImage.LoadTargaImage(path);
}
public void LoadBitmap(string path)
{
SetNameFromPath(path);
}
public void SaveASTC(string FileName, int SurfaceLevel = 0, int MipLevel = 0)
{
var blockDims = GetDims(Format);
ASTC atsc = new ASTC();
atsc.BlockDimX = (byte)blockDims.Item1;
atsc.BlockDimY = (byte)blockDims.Item2;
atsc.BlockDimZ = (byte)blockDims.Item3;
}
public void SaveTGA(string FileName, int SurfaceLevel = 0, int MipLevel = 0)
{
}
public void SaveBitMap(string FileName, int SurfaceLevel = 0, int MipLevel = 0)
{
Bitmap bitMap = GetBitmap(MipLevel, SurfaceLevel);
bitMap.Save(FileName);
bitMap.Dispose();
}
public void SaveDDS(string FileName, int SurfaceLevel = 0, int MipLevel = 0)
{
DDS dds = new DDS();
dds.header = new DDS.Header();
dds.header.width = Width;
dds.header.height = Height;
dds.header.mipmapCount = (uint)surfaces[SurfaceLevel].mipmaps.Count;
dds.header.pitchOrLinearSize = (uint)surfaces[SurfaceLevel].mipmaps[MipLevel].Length;
dds.SetFlags((DDS.DXGI_FORMAT)Format);
dds.Save(dds, FileName, surfaces);
}
public static Tuple<int, int, int> GetDims(TEX_FORMAT Format)
{
switch (Format)
{
case TEX_FORMAT.BC1_TYPELESS:
return Tuple.Create(4,4,4);
}
return Tuple.Create(4, 4, 4);
}
public static bool IsCompressed(TEX_FORMAT Format)
{
switch (Format)
{
case TEX_FORMAT.BC1_UNORM:
case TEX_FORMAT.BC1_UNORM_SRGB:
case TEX_FORMAT.BC1_TYPELESS:
case TEX_FORMAT.BC2_UNORM_SRGB:
case TEX_FORMAT.BC2_UNORM:
case TEX_FORMAT.BC2_TYPELESS:
case TEX_FORMAT.BC3_UNORM_SRGB:
case TEX_FORMAT.BC3_UNORM:
case TEX_FORMAT.BC3_TYPELESS:
case TEX_FORMAT.BC4_UNORM:
case TEX_FORMAT.BC4_TYPELESS:
case TEX_FORMAT.BC4_SNORM:
case TEX_FORMAT.BC5_UNORM:
case TEX_FORMAT.BC5_TYPELESS:
case TEX_FORMAT.BC5_SNORM:
return true;
default:
return false;
}
}
//DXGI formats are first, then ASTC formats after
public enum TEX_FORMAT : uint
{
UNKNOWN = 0,
R32G32B32A32_TYPELESS = 1,
R32G32B32A32_FLOAT = 2,
R32G32B32A32_UINT = 3,
R32G32B32A32_SINT = 4,
R32G32B32_TYPELESS = 5,
R32G32B32_FLOAT = 6,
R32G32B32_UINT = 7,
R32G32B32_SINT = 8,
R16G16B16A16_TYPELESS = 9,
R16G16B16A16_FLOAT = 10,
R16G16B16A16_UNORM = 11,
R16G16B16A16_UINT = 12,
R16G16B16A16_SNORM = 13,
R16G16B16A16_SINT = 14,
R32G32_TYPELESS = 15,
R32G32_FLOAT = 16,
R32G32_UINT = 17,
R32G32_SINT = 18,
R32G8X24_TYPELESS = 19,
D32_FLOAT_S8X24_UINT = 20,
R32_FLOAT_X8X24_TYPELESS = 21,
X32_TYPELESS_G8X24_UINT = 22,
R10G10B10A2_TYPELESS = 23,
R10G10B10A2_UNORM = 24,
R10G10B10A2_UINT = 25,
R11G11B10_FLOAT = 26,
R8G8B8A8_TYPELESS = 27,
R8G8B8A8_UNORM = 28,
R8G8B8A8_UNORM_SRGB = 29,
R8G8B8A8_UINT = 30,
R8G8B8A8_SNORM = 31,
R8G8B8A8_SINT = 32,
R16G16_TYPELESS = 33,
R16G16_FLOAT = 34,
R16G16_UNORM = 35,
R16G16_UINT = 36,
R16G16_SNORM = 37,
R16G16_SINT = 38,
R32_TYPELESS = 39,
D32_FLOAT = 40,
R32_FLOAT = 41,
R32_UINT = 42,
R32_SINT = 43,
R24G8_TYPELESS = 44,
D24_UNORM_S8_UINT = 45,
R24_UNORM_X8_TYPELESS = 46,
X24_TYPELESS_G8_UINT = 47,
R8G8_TYPELESS = 48,
R8G8_UNORM = 49,
R8G8_UINT = 50,
R8G8_SNORM = 51,
R8G8_SINT = 52,
R16_TYPELESS = 53,
R16_FLOAT = 54,
D16_UNORM = 55,
R16_UNORM = 56,
R16_UINT = 57,
R16_SNORM = 58,
R16_SINT = 59,
R8_TYPELESS = 60,
R8_UNORM = 61,
R8_UINT = 62,
R8_SNORM = 63,
R8_SINT = 64,
A8_UNORM = 65,
R1_UNORM = 66,
R9G9B9E5_SHAREDEXP = 67,
R8G8_B8G8_UNORM = 68,
G8R8_G8B8_UNORM = 69,
BC1_TYPELESS = 70,
BC1_UNORM = 71,
BC1_UNORM_SRGB = 72,
BC2_TYPELESS = 73,
BC2_UNORM = 74,
BC2_UNORM_SRGB = 75,
BC3_TYPELESS = 76,
BC3_UNORM = 77,
BC3_UNORM_SRGB = 78,
BC4_TYPELESS = 79,
BC4_UNORM = 80,
BC4_SNORM = 81,
BC5_TYPELESS = 82,
BC5_UNORM = 83,
BC5_SNORM = 84,
B5G6R5_UNORM = 85,
B5G5R5A1_UNORM = 86,
B8G8R8A8_UNORM = 87,
B8G8R8X8_UNORM = 88,
R10G10B10_XR_BIAS_A2_UNORM = 89,
B8G8R8A8_TYPELESS = 90,
B8G8R8A8_UNORM_SRGB = 91,
B8G8R8X8_TYPELESS = 92,
B8G8R8X8_UNORM_SRGB = 93,
BC6H_TYPELESS = 94,
BC6H_UF16 = 95,
BC6H_SF16 = 96,
BC7_TYPELESS = 97,
BC7_UNORM = 98,
BC7_UNORM_SRGB = 99,
AYUV = 100,
Y410 = 101,
Y416 = 102,
NV12 = 103,
P010 = 104,
P016 = 105,
Format_420_OPAQUE = 106,
YUY2 = 107,
Y210 = 108,
Y216 = 109,
NV11 = 110,
AI44 = 111,
IA44 = 112,
P8 = 113,
A8P8 = 114,
B4G4R4A4_UNORM = 115,
P208 = 130,
V208 = 131,
V408 = 132,
ASTC4x4 = 200,
ASTC5x4 = 201,
ASTC5x5 = 202,
ASTC6x5 = 203,
ASTC6x6 = 204,
ASTC8x5 = 205,
ASTC8x6 = 206,
ASTC8x8 = 207,
ASTC10x5 = 208,
ASTC10x6 = 209,
ASTC10x8 = 210,
ASTC10x10 = 211,
ASTC12x10 = 212,
ASTC12x12 = 213,
FORCE_UINT = 0xFFFFFFFF
}
public STGenericTexture()
{
}
public override void OnClick(TreeView treeView)
{
}
private void SetNameFromPath(string path)
{
//Replace extensions manually. This is because using the
//GetFileNameWithoutExtension function can remove .0, .1, texture names.
var name = Path.GetFileName(path);
name.Replace(".tga", string.Empty);
name.Replace(".png", string.Empty);
name.Replace(".jpg", string.Empty);
name.Replace(".dds", string.Empty);
name.Replace(".jpeg", string.Empty);
name.Replace(".tiff", string.Empty);
name.Replace(".gif", string.Empty);
name.Replace(".dds2", string.Empty);
name.Replace(".jpe", string.Empty);
name.Replace(".jfif", string.Empty);
name.Replace(".bmp", string.Empty);
name.Replace(".pdn", string.Empty);
name.Replace(".psd", string.Empty);
name.Replace(".hdr", string.Empty);
Text = name;
}
private static byte[] ConvertBgraToRgba(byte[] bytes)
{
for (int i = 0; i < bytes.Length; i += 4)
{
var temp = bytes[i];
bytes[i] = bytes[i + 2];
bytes[i + 2] = temp;
}
return bytes;
}
}
}

View File

@ -57,8 +57,8 @@ namespace Switch_Toolbox.Library.IO
}
}
File.WriteAllBytes(FileName, data);
MessageBox.Show($"File has been saved to {FileName}");
Cursor.Current = Cursors.Default;
MessageBox.Show($"File has been saved to {FileName}");
}
}
public class STFileLoader

View File

@ -24,439 +24,6 @@ namespace Switch_Toolbox.Library.Rendering
UInt16 = 1,
UInt32 = 2,
}
public class STGenericObject : GenericObject
{
public override void OnClick(TreeView treeView)
{
}
}
public abstract class STGenericModel : GenericModel
{
public override void OnClick(TreeView treeView)
{
}
}
public abstract class GenericModel : TreeNode
{
public abstract void OnClick(TreeView treeview);
}
public class STGenericMaterial : GenericMaterial
{
public override void OnClick(TreeView treeView)
{
}
}
public class STGenericMatTexture
{
public int mapMode = 0;
public int wrapModeS = 1;
public int wrapModeT = 1;
public int wrapModeW = 1; //Used for 3D textures
public int minFilter = 3;
public int magFilter = 2;
public int mipDetail = 6;
public string Name;
public TextureType Type;
//An enum for the assumed texture type by sampler
//Many games have a consistant type of samplers and type. _a0 for diffuse, _n0 for normal, ect
public enum TextureType
{
Unknown = 0,
Diffuse = 1,
Normal = 2,
Specular = 3,
Emission = 4,
DiffuseLayer2 = 5,
TeamColor = 6,
Transparency = 7,
Shadow = 8,
AO = 9,
Light = 10,
Roughness = 11,
Metalness = 12,
MRA = 13, //Combined pbr texture HAL uses for KSA
SphereMap = 14,
SubSurfaceScattering = 15,
}
public static readonly Dictionary<int, TextureMinFilter> minfilter = new Dictionary<int, TextureMinFilter>()
{
{ 0x00, TextureMinFilter.LinearMipmapLinear},
{ 0x01, TextureMinFilter.Nearest},
{ 0x02, TextureMinFilter.Linear},
{ 0x03, TextureMinFilter.NearestMipmapLinear},
};
public static readonly Dictionary<int, TextureMagFilter> magfilter = new Dictionary<int, TextureMagFilter>()
{
{ 0x00, TextureMagFilter.Linear},
{ 0x01, TextureMagFilter.Nearest},
{ 0x02, TextureMagFilter.Linear}
};
public static Dictionary<int, TextureWrapMode> wrapmode = new Dictionary<int, TextureWrapMode>(){
{ 0x00, TextureWrapMode.Repeat},
{ 0x01, TextureWrapMode.MirroredRepeat},
{ 0x02, TextureWrapMode.ClampToEdge},
{ 0x03, TextureWrapMode.MirroredRepeat},
};
}
public abstract class GenericMaterial : TreeNode
{
public abstract void OnClick(TreeView treeview);
public List<STGenericMatTexture> TextureMaps = new List<STGenericMatTexture>();
}
public abstract class GenericObject : TreeNode
{
public abstract void OnClick(TreeView treeview);
public bool HasPos;
public bool HasNrm;
public bool HasUv0;
public bool HasUv1;
public bool HasUv2;
public bool HasWeights;
public bool HasIndices;
public bool HasBitans;
public bool HasTans;
public bool HasVertColors;
public int MaxSkinInfluenceCount;
public string ObjectName;
public int BoneIndex;
public int MaterialIndex;
public int VertexBufferIndex;
public int DisplayLODIndex;
public int Offset;
public int GetMaxSkinInfluenceCount()
{
return vertices.Max(t => t.boneIds.Count);
}
public Vector3 GetOrigin()
{
Vector3 pos = Vector3.Zero;
foreach (Vertex vert in vertices)
{
}
return pos;
}
public List<string[]> bones = new List<string[]>();
public List<float[]> weightsT = new List<float[]>();
public List<string> boneList = new List<string>();
public List<Vertex> vertices = new List<Vertex>();
public List<LOD_Mesh> lodMeshes = new List<LOD_Mesh>();
public class LOD_Mesh
{
public STPolygonType PrimitiveType = STPolygonType.Triangle;
public STIndexFormat IndexFormat = STIndexFormat.UInt16;
public uint FirstVertex;
public List<SubMesh> subMeshes = new List<SubMesh>();
public class SubMesh
{
public uint size;
public uint offset;
}
public void GenerateSubMesh()
{
subMeshes.Clear();
SubMesh subMesh = new SubMesh();
subMesh.offset = 0;
subMesh.size = (uint)faces.Count;
subMeshes.Add(subMesh);
}
public int index = 0;
public int strip = 0x40;
public int displayFaceSize = 0;
public List<int> faces = new List<int>();
public override string ToString()
{
return "LOD Mesh " + index;
}
public List<int> getDisplayFace()
{
if ((strip >> 4) == 4)
{
displayFaceSize = faces.Count;
return faces;
}
else
{
List<int> f = new List<int>();
int startDirection = 1;
int p = 0;
int f1 = faces[p++];
int f2 = faces[p++];
int faceDirection = startDirection;
int f3;
do
{
f3 = faces[p++];
if (f3 == 0xFFFF)
{
f1 = faces[p++];
f2 = faces[p++];
faceDirection = startDirection;
}
else
{
faceDirection *= -1;
if ((f1 != f2) && (f2 != f3) && (f3 != f1))
{
if (faceDirection > 0)
{
f.Add(f3);
f.Add(f2);
f.Add(f1);
}
else
{
f.Add(f2);
f.Add(f3);
f.Add(f1);
}
}
f1 = f2;
f2 = f3;
}
} while (p < faces.Count);
displayFaceSize = f.Count;
return f;
}
}
}
public List<int> faces = new List<int>();
#region Methods
public void FlipUvsVertical()
{
foreach (Vertex v in vertices)
{
v.uv0 = new Vector2(v.uv0.X, 1 - v.uv0.Y);
}
}
public void FlipUvsHorizontal()
{
foreach (Vertex v in vertices)
{
v.uv0 = new Vector2(1 - v.uv0.X, v.uv0.Y);
}
}
public void CalculateTangentBitangent()
{
List<int> f = lodMeshes[DisplayLODIndex].getDisplayFace();
Vector3[] tanArray = new Vector3[vertices.Count];
Vector3[] bitanArray = new Vector3[vertices.Count];
CalculateTanBitanArrays(f, tanArray, bitanArray);
ApplyTanBitanArray(tanArray, bitanArray);
}
private void ApplyTanBitanArray(Vector3[] tanArray, Vector3[] bitanArray)
{
for (int i = 0; i < vertices.Count; i++)
{
Vertex v = vertices[i];
Vector3 newTan = tanArray[i];
Vector3 newBitan = bitanArray[i];
// The tangent and bitangent should be orthogonal to the normal.
// Bitangents are not calculated with a cross product to prevent flipped shading with mirrored normal maps.
v.tan = new Vector4(Vector3.Normalize(newTan - v.nrm * Vector3.Dot(v.nrm, newTan)), 1);
v.bitan = new Vector4(Vector3.Normalize(newBitan - v.nrm * Vector3.Dot(v.nrm, newBitan)), 1);
v.bitan *= -1;
}
}
private void CalculateTanBitanArrays(List<int> faces, Vector3[] tanArray, Vector3[] bitanArray)
{
for (int i = 0; i < lodMeshes[DisplayLODIndex].displayFaceSize; i += 3)
{
Vertex v1 = vertices[faces[i]];
Vertex v2 = vertices[faces[i + 1]];
Vertex v3 = vertices[faces[i + 2]];
bool UseUVLayer2 = false;
float x1 = v2.pos.X - v1.pos.X;
float x2 = v3.pos.X - v1.pos.X;
float y1 = v2.pos.Y - v1.pos.Y;
float y2 = v3.pos.Y - v1.pos.Y;
float z1 = v2.pos.Z - v1.pos.Z;
float z2 = v3.pos.Z - v1.pos.Z;
float s1, s2, t1, t2;
if (UseUVLayer2)
{
s1 = v2.uv1.X - v1.uv1.X;
s2 = v3.uv1.X - v1.uv1.X;
t1 = v2.uv1.Y - v1.uv1.Y;
t2 = v3.uv1.Y - v1.uv1.Y;
}
else
{
s1 = v2.uv0.X - v1.uv0.X;
s2 = v3.uv0.X - v1.uv0.X;
t1 = v2.uv0.Y - v1.uv0.Y;
t2 = v3.uv0.Y - v1.uv0.Y;
}
float div = (s1 * t2 - s2 * t1);
float r = 1.0f / div;
// Fix +/- infinity from division by 0.
if (r == float.PositiveInfinity || r == float.NegativeInfinity)
r = 1.0f;
float sX = t2 * x1 - t1 * x2;
float sY = t2 * y1 - t1 * y2;
float sZ = t2 * z1 - t1 * z2;
Vector3 s = new Vector3(sX, sY, sZ) * r;
float tX = s1 * x2 - s2 * x1;
float tY = s1 * y2 - s2 * y1;
float tZ = s1 * z2 - s2 * z1;
Vector3 t = new Vector3(tX, tY, tZ) * r;
// Prevents black tangents or bitangents due to having vertices with the same UV coordinates.
float delta = 0.00075f;
bool sameU, sameV;
if (UseUVLayer2)
{
sameU = (Math.Abs(v1.uv1.X - v2.uv1.X) < delta) && (Math.Abs(v2.uv1.X - v3.uv1.X) < delta);
sameV = (Math.Abs(v1.uv1.Y - v2.uv1.Y) < delta) && (Math.Abs(v2.uv1.Y - v3.uv1.Y) < delta);
}
else
{
sameU = (Math.Abs(v1.uv0.X - v2.uv0.X) < delta) && (Math.Abs(v2.uv0.X - v3.uv0.X) < delta);
sameV = (Math.Abs(v1.uv0.Y - v2.uv0.Y) < delta) && (Math.Abs(v2.uv0.Y - v3.uv0.Y) < delta);
}
if (sameU || sameV)
{
// Let's pick some arbitrary tangent vectors.
s = new Vector3(1, 0, 0);
t = new Vector3(0, 1, 0);
}
// Average tangents and bitangents.
tanArray[faces[i]] += s;
tanArray[faces[i + 1]] += s;
tanArray[faces[i + 2]] += s;
bitanArray[faces[i]] += t;
bitanArray[faces[i + 1]] += t;
bitanArray[faces[i + 2]] += t;
}
}
public void SmoothNormals()
{
Vector3[] normals = new Vector3[vertices.Count];
List<int> f = lodMeshes[DisplayLODIndex].getDisplayFace();
for (int i = 0; i < lodMeshes[DisplayLODIndex].displayFaceSize; i += 3)
{
Vertex v1 = vertices[f[i]];
Vertex v2 = vertices[f[i + 1]];
Vertex v3 = vertices[f[i + 2]];
Vector3 nrm = CalculateNormal(v1, v2, v3);
normals[f[i + 0]] += nrm;
normals[f[i + 1]] += nrm;
normals[f[i + 2]] += nrm;
}
for (int i = 0; i < normals.Length; i++)
vertices[i].nrm = normals[i].Normalized();
// Compare each vertex with all the remaining vertices. This might skip some.
for (int i = 0; i < vertices.Count; i++)
{
Vertex v = vertices[i];
for (int j = i + 1; j < vertices.Count; j++)
{
Vertex v2 = vertices[j];
if (v == v2)
continue;
float dis = (float)Math.Sqrt(Math.Pow(v.pos.X - v2.pos.X, 2) + Math.Pow(v.pos.Y - v2.pos.Y, 2) + Math.Pow(v.pos.Z - v2.pos.Z, 2));
if (dis <= 0f) // Extra smooth
{
Vector3 nn = ((v2.nrm + v.nrm) / 2).Normalized();
v.nrm = nn;
v2.nrm = nn;
}
}
}
}
public void CalculateNormals()
{
Vector3[] normals = new Vector3[vertices.Count];
for (int i = 0; i < normals.Length; i++)
normals[i] = new Vector3(0, 0, 0);
List<int> f = lodMeshes[DisplayLODIndex].getDisplayFace();
for (int i = 0; i < lodMeshes[DisplayLODIndex].displayFaceSize; i += 3)
{
Vertex v1 = vertices[f[i]];
Vertex v2 = vertices[f[i + 1]];
Vertex v3 = vertices[f[i + 2]];
Vector3 nrm = CalculateNormal(v1, v2, v3);
normals[f[i + 0]] += nrm * (nrm.Length / 2);
normals[f[i + 1]] += nrm * (nrm.Length / 2);
normals[f[i + 2]] += nrm * (nrm.Length / 2);
}
for (int i = 0; i < normals.Length; i++)
vertices[i].nrm = normals[i].Normalized();
}
private Vector3 CalculateNormal(Vertex v1, Vertex v2, Vertex v3)
{
Vector3 U = v2.pos - v1.pos;
Vector3 V = v3.pos - v1.pos;
// Don't normalize here, so surface area can be calculated.
return Vector3.Cross(U, V);
}
public void SetVertexColor(Vector4 intColor)
{
// (127, 127, 127, 255) is white.
foreach (Vertex v in vertices)
{
v.col = intColor;
}
}
#endregion
}
public class Vertex
{

View File

@ -62,6 +62,8 @@ namespace Switch_Toolbox.Library
public static bool renderNormalMap = true;
public static bool renderVertColor = true;
public static bool renderBfresPbr = false;
public static bool renderTevColors = true;
public static bool renderMatColors = true;
public static bool stereoscopy = false;
public static bool UseLegacyGL = false;
@ -77,6 +79,10 @@ namespace Switch_Toolbox.Library
public static float CameraFar = 100000.0f;
public static ActiveGame activeGame = ActiveGame.SMO;
public static string ProgramVersion = "0.0.0";
public static string CompileDate = "0/0/0000";
public static string CommitInfo = "";
public enum ActiveGame
{
SMO,

View File

@ -43,8 +43,9 @@
<Reference Include="CsvHelper, Version=8.0.0.0, Culture=neutral, PublicKeyToken=8c4959082be5c823, processorArchitecture=MSIL">
<HintPath>..\Switch_Toolbox\Lib\CsvHelper.dll</HintPath>
</Reference>
<Reference Include="DirectXTex">
<HintPath>..\..\Switch-Toolbox\Switch_Toolbox\Lib\DirectXTex.dll</HintPath>
<Reference Include="DirectXTex, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Switch_Toolbox\Lib\DirectXTex.dll</HintPath>
</Reference>
<Reference Include="K4os.Compression.LZ4, Version=1.1.0.0, Culture=neutral, PublicKeyToken=27d14aecb5186925, processorArchitecture=MSIL">
<HintPath>..\Switch_Toolbox\Lib\K4os.Compression.LZ4.dll</HintPath>
@ -113,8 +114,14 @@
<Compile Include="FileFormats\ANIM.cs" />
<Compile Include="FileFormats\Assimp\Assimp.cs" />
<Compile Include="FileFormats\Assimp\AssimpHelper.cs" />
<Compile Include="FileFormats\ASTC.cs" />
<Compile Include="FileFormats\DDS.cs" />
<Compile Include="FileFormats\DDSCompressor.cs" />
<Compile Include="Externals\TargaImage.cs" />
<Compile Include="Generics\GenericMaterial.cs" />
<Compile Include="Generics\GenericMatTexture.cs" />
<Compile Include="Generics\GenericModel.cs" />
<Compile Include="Generics\GenericObject.cs" />
<Compile Include="GUI Custom\ListViewCustom.cs">
<SubType>Component</SubType>
</Compile>
@ -147,6 +154,7 @@
</Compile>
<Compile Include="Helpers\TextureHelper.cs" />
<Compile Include="Interfaces\IMenuExtension.cs" />
<Compile Include="Generics\GenericTexture.cs" />
<Compile Include="Plugin\GenericPluginLoader.cs" />
<Compile Include="GUI Custom\DockContentST.cs">
<SubType>Form</SubType>
@ -359,6 +367,9 @@
<ItemGroup>
<None Include="Resources\normalMapSphere.png" />
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Connected Services\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Fody.3.2.9\build\Fody.targets" Condition="Exists('..\packages\Fody.3.2.9\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -33,6 +33,23 @@ namespace Switch_Toolbox.Library
{
return new Vector4(v.X, v.Y, v.Z, v.W);
}
public static Matrix3x4 ToMat3x4(Syroot.Maths.Matrix3x4 mat4)
{
Matrix3x4 mat = new Matrix3x4();
mat.M11 = mat4.M11;
mat.M12 = mat4.M12;
mat.M13 = mat4.M13;
mat.M14 = mat4.M14;
mat.M21 = mat4.M21;
mat.M22 = mat4.M22;
mat.M23 = mat4.M23;
mat.M24 = mat4.M24;
mat.M31 = mat4.M31;
mat.M32 = mat4.M32;
mat.M33 = mat4.M33;
mat.M34 = mat4.M34;
return mat;
}
public static byte[] CombineByteArray(params byte[][] arrays)
{
byte[] rv = new byte[arrays.Sum(a => a.Length)];
@ -56,7 +73,7 @@ namespace Switch_Toolbox.Library
{
if (strings.Contains(oldString))
{
oldString += i.ToString();
oldString = $"{oldString}_0{i++}";
if (strings.Contains(oldString))
RenameDuplicateString(strings, oldString);

View File

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="OpenTK" publicKeyToken="bad199fe84eb3df4" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
<assemblyIdentity name="OpenTK" publicKeyToken="bad199fe84eb3df4" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="LZ4pn" publicKeyToken="62e1b5ec1eec9bdd" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.10.93" newVersion="1.0.10.93" />
<assemblyIdentity name="LZ4pn" publicKeyToken="62e1b5ec1eec9bdd" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.10.93" newVersion="1.0.10.93"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="K4os.Hash.xxHash" publicKeyToken="32cd54395057cec3" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.5.0" newVersion="1.0.5.0" />
<assemblyIdentity name="K4os.Hash.xxHash" publicKeyToken="32cd54395057cec3" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.5.0" newVersion="1.0.5.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/></startup></configuration>

Binary file not shown.

Binary file not shown.

5763
Syroot.NintenTools.Bfres.xml Normal file

File diff suppressed because it is too large Load Diff