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 (BFRES.Instance.IsWiiU) 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 (BFRES.Instance.IsWiiU) { 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 anims = new Dictionary(); public Dictionary Samplers = new Dictionary(); public List textures = new List(); public List renderinfo = new List(); public List samplerinfo = new List(); public Dictionary matparam = new Dictionary(); public Material Material; public ResU.Material MaterialU; public ShaderAssign shaderassign = new ShaderAssign(); public class ShaderAssign { public string ShaderModel = ""; public string ShaderArchive = ""; public Dictionary options = new Dictionary(); public Dictionary samplers = new Dictionary(); public Dictionary attributes = new Dictionary(); } 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(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(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() { } } }