405 lines
15 KiB
C#
405 lines
15 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using Syroot.NintenTools.NSW.Bfres;
|
|||
|
using System.Windows.Forms;
|
|||
|
using Switch_Toolbox.Library;
|
|||
|
using Switch_Toolbox.Library.IO;
|
|||
|
using Switch_Toolbox.Library.Rendering;
|
|||
|
using Switch_Toolbox.Library.Forms;
|
|||
|
using ResU = Syroot.NintenTools.Bfres;
|
|||
|
using FirstPlugin;
|
|||
|
using OpenTK;
|
|||
|
|
|||
|
|
|||
|
namespace Bfres.Structs
|
|||
|
{
|
|||
|
public class FMATFolder : TreeNodeCustom
|
|||
|
{
|
|||
|
public FMATFolder()
|
|||
|
{
|
|||
|
Text = "Materials";
|
|||
|
Name = "FmatFolder";
|
|||
|
|
|||
|
ContextMenu = new ContextMenu();
|
|||
|
MenuItem import = new MenuItem("Add Material");
|
|||
|
ContextMenu.MenuItems.Add(import);
|
|||
|
import.Click += Import;
|
|||
|
}
|
|||
|
public void Import(object sender, EventArgs args)
|
|||
|
{
|
|||
|
OpenFileDialog ofd = new OpenFileDialog();
|
|||
|
ofd.Filter = "Bfres Material |*.bfmat;";
|
|||
|
ofd.Multiselect = true;
|
|||
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|||
|
{
|
|||
|
foreach (string file in ofd.FileNames)
|
|||
|
((FMDL)Parent).AddMaterials(file, false);
|
|||
|
}
|
|||
|
}
|
|||
|
public override void OnClick(TreeView treeView)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
public class FMAT : STGenericMaterial
|
|||
|
{
|
|||
|
public FMAT()
|
|||
|
{
|
|||
|
Checked = true;
|
|||
|
ImageKey = "material";
|
|||
|
SelectedImageKey = "material";
|
|||
|
|
|||
|
ContextMenu = new ContextMenu();
|
|||
|
MenuItem export = new MenuItem("Export");
|
|||
|
ContextMenu.MenuItems.Add(export);
|
|||
|
export.Click += Export;
|
|||
|
MenuItem replace = new MenuItem("Replace");
|
|||
|
ContextMenu.MenuItems.Add(replace);
|
|||
|
replace.Click += Replace;
|
|||
|
MenuItem copy = new MenuItem("Copy");
|
|||
|
ContextMenu.MenuItems.Add(copy);
|
|||
|
copy.Click += Copy;
|
|||
|
MenuItem rename = new MenuItem("Rename");
|
|||
|
ContextMenu.MenuItems.Add(rename);
|
|||
|
rename.Click += Rename;
|
|||
|
}
|
|||
|
|
|||
|
public BFRESRender BFRESRender;
|
|||
|
public bool Enabled = true;
|
|||
|
|
|||
|
public override void OnClick(TreeView treeView)
|
|||
|
{
|
|||
|
FormLoader.LoadMatEditor(this);
|
|||
|
}
|
|||
|
|
|||
|
public void SetActiveGame()
|
|||
|
{
|
|||
|
string ShaderName = shaderassign.ShaderArchive;
|
|||
|
string ShaderModel = shaderassign.ShaderModel;
|
|||
|
|
|||
|
if (ShaderName == "alRenderMaterial" || ShaderName == "alRenderCloudLayer" || ShaderName == "alRenderSky")
|
|||
|
Runtime.activeGame = Runtime.ActiveGame.SMO;
|
|||
|
else if (ShaderName == "Turbo_UBER")
|
|||
|
Runtime.activeGame = Runtime.ActiveGame.MK8D;
|
|||
|
else if (ShaderName.Contains("uking_mat"))
|
|||
|
Runtime.activeGame = Runtime.ActiveGame.BOTW;
|
|||
|
else if (ShaderName.Contains("Blitz_UBER"))
|
|||
|
Runtime.activeGame = Runtime.ActiveGame.Splatoon2;
|
|||
|
else
|
|||
|
Runtime.activeGame = Runtime.ActiveGame.KSA;
|
|||
|
}
|
|||
|
private void Rename(object sender, EventArgs args)
|
|||
|
{
|
|||
|
RenameDialog dialog = new RenameDialog();
|
|||
|
dialog.SetString(Text);
|
|||
|
|
|||
|
if (dialog.ShowDialog() == DialogResult.OK)
|
|||
|
{
|
|||
|
((FMDL)Parent.Parent).materials.Remove(Text);
|
|||
|
Text = dialog.textBox1.Text;
|
|||
|
((FMDL)Parent.Parent).materials.Add(Text, this);
|
|||
|
}
|
|||
|
}
|
|||
|
private void Copy(object sender, EventArgs args)
|
|||
|
{
|
|||
|
((FMDL)Parent.Parent).CopyMaterial(this);
|
|||
|
}
|
|||
|
private void Export(object sender, EventArgs args)
|
|||
|
{
|
|||
|
SaveFileDialog sfd = new SaveFileDialog();
|
|||
|
sfd.Filter = "Supported Formats|*.bfmat;";
|
|||
|
|
|||
|
sfd.DefaultExt = ".bfmat";
|
|||
|
sfd.FileName = Text;
|
|||
|
|
|||
|
if (sfd.ShowDialog() == DialogResult.OK)
|
|||
|
{
|
|||
|
Material.Export(sfd.FileName, BFRESRender.resFile);
|
|||
|
}
|
|||
|
}
|
|||
|
private void Replace(object sender, EventArgs args)
|
|||
|
{
|
|||
|
OpenFileDialog ofd = new OpenFileDialog();
|
|||
|
ofd.Filter = "Supported Formats|*.bfmat;";
|
|||
|
|
|||
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|||
|
{
|
|||
|
Material.Import(ofd.FileName);
|
|||
|
Material.Name = Text;
|
|||
|
|
|||
|
BfresSwitch.ReadMaterial(this, Material);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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>();
|
|||
|
|
|||
|
public Material Material;
|
|||
|
public ResU.Material MaterialU;
|
|||
|
|
|||
|
public ShaderAssign shaderassign = new ShaderAssign();
|
|||
|
|
|||
|
public class ShaderAssign
|
|||
|
{
|
|||
|
public string ShaderModel = "";
|
|||
|
public string ShaderArchive = "";
|
|||
|
|
|||
|
|
|||
|
public Dictionary<string, string> options = new Dictionary<string, string>();
|
|||
|
public Dictionary<string, string> samplers = new Dictionary<string, string>();
|
|||
|
public Dictionary<string, string> attributes = new Dictionary<string, string>();
|
|||
|
}
|
|||
|
public class SamplerInfo
|
|||
|
{
|
|||
|
public int WrapModeU;
|
|||
|
public int WrapModeV;
|
|||
|
public int WrapModeW;
|
|||
|
}
|
|||
|
public bool HasDiffuseMap = false;
|
|||
|
public bool HasNormalMap = false;
|
|||
|
public bool HasSpecularMap = false;
|
|||
|
public bool HasEmissionMap = false;
|
|||
|
public bool HasDiffuseLayer = false;
|
|||
|
public bool HasTeamColorMap = false; //Splatoon uses this (TLC)
|
|||
|
public bool HasTransparencyMap = false;
|
|||
|
public bool HasShadowMap = false;
|
|||
|
public bool HasAmbientOcclusionMap = false;
|
|||
|
public bool HasLightMap = false;
|
|||
|
public bool HasSphereMap = false;
|
|||
|
public bool HasSubSurfaceScatteringMap = false;
|
|||
|
|
|||
|
//PBR (Switch) data
|
|||
|
public bool HasMetalnessMap = false;
|
|||
|
public bool HasRoughnessMap = false;
|
|||
|
public bool HasMRA = false;
|
|||
|
}
|
|||
|
public class BfresShaderParam
|
|||
|
{
|
|||
|
public ShaderParamType Type;
|
|||
|
public string Name;
|
|||
|
|
|||
|
public float[] ValueFloat;
|
|||
|
public bool[] ValueBool;
|
|||
|
public uint[] ValueUint;
|
|||
|
public int[] ValueInt;
|
|||
|
public byte[] ValueReserved;
|
|||
|
|
|||
|
public Srt2D ValueSrt2D;
|
|||
|
public Srt3D ValueSrt3D;
|
|||
|
public TexSrt ValueTexSrt;
|
|||
|
public TexSrtEx ValueTexSrtEx;
|
|||
|
|
|||
|
//If a data set is not defined then defaults in this to save back properly
|
|||
|
//Note this may be rarely needed or not at all
|
|||
|
public byte[] Value_Unk;
|
|||
|
|
|||
|
|
|||
|
private void ReadSRT2D(FileReader reader)
|
|||
|
{
|
|||
|
ValueSrt2D = new Srt2D();
|
|||
|
ValueSrt2D.Scaling = reader.ReadVec2SY();
|
|||
|
ValueSrt2D.Rotation = reader.ReadSingle();
|
|||
|
ValueSrt2D.Translation = reader.ReadVec2SY();
|
|||
|
}
|
|||
|
private void ReadSRT3D(FileReader reader)
|
|||
|
{
|
|||
|
ValueSrt3D = new Srt3D();
|
|||
|
ValueSrt3D.Scaling = reader.ReadVec3SY();
|
|||
|
ValueSrt3D.Rotation = reader.ReadVec3SY();
|
|||
|
ValueSrt3D.Translation = reader.ReadVec3SY();
|
|||
|
}
|
|||
|
private void ReadTexSrt(FileReader reader)
|
|||
|
{
|
|||
|
ValueTexSrt = new TexSrt();
|
|||
|
ValueTexSrt.Mode = reader.ReadEnum<TexSrtMode>(false);
|
|||
|
ValueTexSrt.Scaling = reader.ReadVec2SY();
|
|||
|
ValueTexSrt.Rotation = reader.ReadSingle();
|
|||
|
ValueTexSrt.Translation = reader.ReadVec2SY();
|
|||
|
}
|
|||
|
private void ReadTexSrtEx(FileReader reader)
|
|||
|
{
|
|||
|
ValueTexSrtEx = new TexSrtEx();
|
|||
|
ValueTexSrtEx.Mode = reader.ReadEnum<TexSrtMode>(true);
|
|||
|
ValueTexSrtEx.Scaling = reader.ReadVec2SY();
|
|||
|
ValueTexSrtEx.Rotation = reader.ReadSingle();
|
|||
|
ValueTexSrtEx.Translation = reader.ReadVec2SY();
|
|||
|
ValueTexSrtEx.MatrixPointer = reader.ReadUInt32();
|
|||
|
}
|
|||
|
public ShaderParamType GetTypeWiiU(ResU.ShaderParamType type)
|
|||
|
{
|
|||
|
return (ShaderParamType)System.Enum.Parse(typeof(ShaderParamType), type.ToString());
|
|||
|
}
|
|||
|
public ResU.ShaderParamType SetTypeWiiU(ShaderParamType type)
|
|||
|
{
|
|||
|
return (ResU.ShaderParamType)System.Enum.Parse(typeof(ResU.ShaderParamType), type.ToString());
|
|||
|
}
|
|||
|
|
|||
|
public void ReadValue(FileReader reader, int Size)
|
|||
|
{
|
|||
|
switch (Type)
|
|||
|
{
|
|||
|
case ShaderParamType.Bool:
|
|||
|
case ShaderParamType.Bool2:
|
|||
|
case ShaderParamType.Bool3:
|
|||
|
case ShaderParamType.Bool4:
|
|||
|
ValueBool = reader.ReadBooleans(Size / sizeof(bool)); break;
|
|||
|
case ShaderParamType.Float:
|
|||
|
case ShaderParamType.Float2:
|
|||
|
case ShaderParamType.Float3:
|
|||
|
case ShaderParamType.Float4:
|
|||
|
case ShaderParamType.Float2x2:
|
|||
|
case ShaderParamType.Float2x3:
|
|||
|
case ShaderParamType.Float2x4:
|
|||
|
case ShaderParamType.Float4x2:
|
|||
|
case ShaderParamType.Float4x3:
|
|||
|
case ShaderParamType.Float4x4:
|
|||
|
ValueFloat = reader.ReadSingles(Size / sizeof(float)); break;
|
|||
|
case ShaderParamType.Int:
|
|||
|
case ShaderParamType.Int2:
|
|||
|
case ShaderParamType.Int3:
|
|||
|
case ShaderParamType.Int4:
|
|||
|
ValueInt = reader.ReadInt32s(Size / sizeof(int)); break;
|
|||
|
case ShaderParamType.Reserved2:
|
|||
|
case ShaderParamType.Reserved3:
|
|||
|
case ShaderParamType.Reserved4:
|
|||
|
ValueReserved = reader.ReadBytes(Size / sizeof(byte)); break;
|
|||
|
case ShaderParamType.Srt2D:
|
|||
|
ReadSRT2D(reader); break;
|
|||
|
case ShaderParamType.Srt3D:
|
|||
|
ReadSRT3D(reader); break;
|
|||
|
case ShaderParamType.TexSrt:
|
|||
|
ReadTexSrt(reader); break;
|
|||
|
case ShaderParamType.TexSrtEx:
|
|||
|
ReadTexSrtEx(reader); break;
|
|||
|
case ShaderParamType.UInt:
|
|||
|
case ShaderParamType.UInt2:
|
|||
|
case ShaderParamType.UInt3:
|
|||
|
case ShaderParamType.UInt4:
|
|||
|
ValueUint = reader.ReadUInt32s(Size / sizeof(uint)); break;
|
|||
|
// Invalid
|
|||
|
default:
|
|||
|
throw new ArgumentException($"Invalid {nameof(ShaderParamType)} {Type}.",
|
|||
|
nameof(Type));
|
|||
|
}
|
|||
|
}
|
|||
|
public void WriteValue(FileWriter writer)
|
|||
|
{
|
|||
|
switch (Type)
|
|||
|
{
|
|||
|
case ShaderParamType.Bool:
|
|||
|
case ShaderParamType.Bool2:
|
|||
|
case ShaderParamType.Bool3:
|
|||
|
case ShaderParamType.Bool4:
|
|||
|
writer.Write(ValueBool); break;
|
|||
|
case ShaderParamType.Float:
|
|||
|
case ShaderParamType.Float2:
|
|||
|
case ShaderParamType.Float3:
|
|||
|
case ShaderParamType.Float4:
|
|||
|
case ShaderParamType.Float2x2:
|
|||
|
case ShaderParamType.Float2x3:
|
|||
|
case ShaderParamType.Float2x4:
|
|||
|
case ShaderParamType.Float4x2:
|
|||
|
case ShaderParamType.Float4x3:
|
|||
|
case ShaderParamType.Float4x4:
|
|||
|
writer.Write(ValueFloat); break;
|
|||
|
case ShaderParamType.Int:
|
|||
|
case ShaderParamType.Int2:
|
|||
|
case ShaderParamType.Int3:
|
|||
|
case ShaderParamType.Int4:
|
|||
|
writer.Write(ValueInt); break;
|
|||
|
case ShaderParamType.Reserved2:
|
|||
|
case ShaderParamType.Reserved3:
|
|||
|
case ShaderParamType.Reserved4:
|
|||
|
writer.Write(ValueInt); break;
|
|||
|
case ShaderParamType.Srt2D:
|
|||
|
WriteSRT2D(writer); break;
|
|||
|
case ShaderParamType.Srt3D:
|
|||
|
WriteSRT3D(writer); break;
|
|||
|
case ShaderParamType.TexSrt:
|
|||
|
WriteTexSrt(writer); break;
|
|||
|
case ShaderParamType.TexSrtEx:
|
|||
|
WriteTexSrtEx(writer); break;
|
|||
|
case ShaderParamType.UInt:
|
|||
|
case ShaderParamType.UInt2:
|
|||
|
case ShaderParamType.UInt3:
|
|||
|
case ShaderParamType.UInt4:
|
|||
|
writer.Write(ValueUint); break;
|
|||
|
// Invalid
|
|||
|
default:
|
|||
|
throw new ArgumentException($"Invalid {nameof(ShaderParamType)} {Type}.",
|
|||
|
nameof(Type));
|
|||
|
}
|
|||
|
}
|
|||
|
private void WriteSRT2D(FileWriter writer)
|
|||
|
{
|
|||
|
writer.Write(ValueSrt2D.Scaling);
|
|||
|
writer.Write(ValueSrt2D.Rotation);
|
|||
|
writer.Write(ValueSrt2D.Translation);
|
|||
|
}
|
|||
|
private void WriteSRT3D(FileWriter writer)
|
|||
|
{
|
|||
|
writer.Write(ValueSrt3D.Scaling);
|
|||
|
writer.Write(ValueSrt3D.Rotation);
|
|||
|
writer.Write(ValueSrt3D.Translation);
|
|||
|
}
|
|||
|
private void WriteTexSrt(FileWriter writer)
|
|||
|
{
|
|||
|
writer.Write((uint)ValueTexSrt.Mode);
|
|||
|
writer.Write(ValueTexSrt.Scaling);
|
|||
|
writer.Write(ValueTexSrt.Rotation);
|
|||
|
writer.Write(ValueTexSrt.Translation);
|
|||
|
}
|
|||
|
private void WriteTexSrtEx(FileWriter writer)
|
|||
|
{
|
|||
|
writer.Write((uint)ValueTexSrtEx.Mode);
|
|||
|
writer.Write(ValueTexSrtEx.Scaling);
|
|||
|
writer.Write(ValueTexSrtEx.Rotation);
|
|||
|
writer.Write(ValueTexSrtEx.Translation);
|
|||
|
writer.Write(ValueTexSrtEx.MatrixPointer);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
public class BfresRenderInfo
|
|||
|
{
|
|||
|
public string Name;
|
|||
|
public long DataOffset;
|
|||
|
public RenderInfoType Type;
|
|||
|
public int ArrayLength;
|
|||
|
|
|||
|
//Data Section by "Type"
|
|||
|
|
|||
|
public int[] ValueInt;
|
|||
|
public string[] ValueString;
|
|||
|
public float[] ValueFloat;
|
|||
|
|
|||
|
public RenderInfoType GetTypeWiiU(ResU.RenderInfoType type)
|
|||
|
{
|
|||
|
return (RenderInfoType)System.Enum.Parse(typeof(RenderInfoType), type.ToString());
|
|||
|
}
|
|||
|
public ResU.RenderInfoType SetTypeWiiU(RenderInfoType type)
|
|||
|
{
|
|||
|
return (ResU.RenderInfoType)System.Enum.Parse(typeof(ResU.RenderInfoType), type.ToString());
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
public class MatTexture : STGenericMatTexture
|
|||
|
{
|
|||
|
public int hash;
|
|||
|
public string SamplerName;
|
|||
|
//Note samplers will get converted to another sampler type sometimes in the shader assign section
|
|||
|
//Use this string if not empty for our bfres fragment shader to produce the accurate affects
|
|||
|
//An example of a conversion maybe be like a1 - t0 so texture gets used as a transparent map/alpha texture
|
|||
|
public string FragShaderSampler = "";
|
|||
|
|
|||
|
public MatTexture()
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|