1
0
mirror of synced 2024-12-12 07:41:11 +01:00
Switch-Toolbox/Switch_FileFormatsMain/FileFormats/BFRES/Bfres Structs/FMAT.cs

444 lines
16 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 bool Enabled = true;
public override void OnClick(TreeView treeView)
{
UpdateFMATEditor();
}
public void UpdateFMATEditor()
{
FMATEditor docked = (FMATEditor)LibraryGUI.Instance.GetContentDocked(new FMATEditor());
if (docked == null)
{
docked = new FMATEditor();
LibraryGUI.Instance.LoadDockContent(docked, PluginRuntime.FSHPDockState);
}
docked.Text = Text;
docked.Dock = DockStyle.Fill;
docked.LoadMaterial(this);
}
public ResFile GetResFile()
{
//ResourceFile -> FMDL -> Material Folder -> this
return ((FMDL)Parent.Parent).GetResFile();
}
public ResU.ResFile GetResFileU()
{
return ((FMDL)Parent.Parent).GetResFileU();
}
public void UpdateTextureMaps()
{
((BFRES)Parent.Parent.Parent.Parent).BFRESRender.UpdateSingleMaterialTextureMaps(this);
}
public void SetActiveGame()
{
Runtime.activeGame = Runtime.ActiveGame.SMO;
return;
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)
{
if (GetResFileU() != null)
MaterialU.Export(sfd.FileName, GetResFileU());
else
Material.Export(sfd.FileName, GetResFile());
}
}
private void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Supported Formats|*.bfmat;";
if (ofd.ShowDialog() == DialogResult.OK)
{
if (GetResFileU() != null)
{
MaterialU.Import(ofd.FileName, GetResFileU());
MaterialU.Name = Text;
BfresWiiU.ReadMaterial(this, MaterialU);
}
else
{
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()
{
}
}
}