diff --git a/File_Format_Library/FileFormats/Font/BFFNT.cs b/File_Format_Library/FileFormats/Font/BFFNT.cs index 02062016..60a2f4f1 100644 --- a/File_Format_Library/FileFormats/Font/BFFNT.cs +++ b/File_Format_Library/FileFormats/Font/BFFNT.cs @@ -15,7 +15,7 @@ using System.Drawing.Imaging; namespace FirstPlugin { - public class BFFNT : IFileFormat, IEditor, IConvertableTextFormat + public class BFFNT : BXFNT, IFileFormat, IEditor, IConvertableTextFormat { public FileType FileType { get; set; } = FileType.Font; @@ -76,6 +76,8 @@ namespace FirstPlugin public void Load(System.IO.Stream stream) { + PluginRuntime.BxfntFiles.Add(this); + CanSave = true; bffnt = new FFNT(); @@ -110,9 +112,22 @@ namespace FirstPlugin // Nodes.Add(file); } } + + public override string Name { get { return FileName; } } + + public override BitmapFont GetBitmapFont(bool UseChannelComp = false) + { + return bffnt.GetBitmapFont(UseChannelComp); + } + + public override Bitmap GetBitmap(string text, bool reversewh, LayoutBXLYT.BasePane pane) + { + return bffnt.GetBitmap(text, reversewh, pane); + } + public void Unload() { - + PluginRuntime.BxfntFiles.Remove(this); } public void Save(System.IO.Stream stream) @@ -288,9 +303,21 @@ namespace FirstPlugin return Signature; } + private BitmapFont bitmapFont; + public Bitmap GetBitmap(string text, bool reversewh, LayoutBXLYT.BasePane pane) + { + var textPane = (LayoutBXLYT.ITextPane)pane; + if (bitmapFont == null) + bitmapFont = GetBitmapFont(true); + return bitmapFont.PrintToBitmap(text, new BitmapFont.FontRenderSettings() + { + CharSpacing = (int)textPane.CharacterSpace, + LineSpacing = (int)textPane.LineSpace, + }); + } - public BitmapFont GetBitmapFont() + public BitmapFont GetBitmapFont(bool UseChannelComp = false) { var FontInfo = FontSection; var TextureGlyph = FontInfo.TextureGlyph; @@ -306,6 +333,10 @@ namespace FirstPlugin for (int sheet = 0; sheet < TextureGlyph.SheetCount; sheet++) { Bitmap SheetBM = TextureGlyph.GetImageSheet(sheet).GetBitmap(); + + if (UseChannelComp) + SheetBM = TextureGlyph.GetImageSheet(sheet).GetComponentBitmap(SheetBM, true); + SheetBM.RotateFlip(RotateFlipType.RotateNoneFlipY); BitmapData bd = SheetBM.LockBits(new Rectangle(0, 0, SheetBM.Width, SheetBM.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); @@ -431,6 +462,10 @@ namespace FirstPlugin Width = TextureTGLP.SheetWidth; var BFNTFormat = (Gx2ImageFormats)TextureTGLP.Format; Format = ConvertToGeneric(BFNTFormat); + if (Format == TEX_FORMAT.BC4_UNORM) + { + AlphaChannel = STChannelType.Red; + } ImageKey = "Texture"; SelectedImageKey = "Texture"; @@ -941,6 +976,14 @@ namespace FirstPlugin } } + public STGenericTexture[] GetImageSheets() + { + STGenericTexture[] textures = new STGenericTexture[SheetCount]; + for (int i = 0; i < SheetCount; i++) + textures[i] = GetImageSheet(i); + return textures; + } + public STGenericTexture GetImageSheet(int Index) { if (BinaryTextureFile != null) //BNTX uses only one image with multiple arrays diff --git a/File_Format_Library/FileFormats/Font/BXFNT.cs b/File_Format_Library/FileFormats/Font/BXFNT.cs new file mode 100644 index 00000000..5cf6c667 --- /dev/null +++ b/File_Format_Library/FileFormats/Font/BXFNT.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Drawing; +using Toolbox.Library; +using LibEveryFileExplorer.GFX; + +namespace FirstPlugin +{ + public class BXFNT + { + public virtual string Name { get; set; } + + public virtual Bitmap GetBitmap(string text, bool reversewh, LayoutBXLYT.BasePane pane) + { + return new Bitmap(32,32); + } + + public virtual BitmapFont GetBitmapFont(bool UseChannelComp = false) + { + return null; + } + } +} diff --git a/File_Format_Library/FileFormats/Layout/Animation/LytAnimGroup.cs b/File_Format_Library/FileFormats/Layout/Animation/LytAnimGroup.cs new file mode 100644 index 00000000..e7d4e3e4 --- /dev/null +++ b/File_Format_Library/FileFormats/Layout/Animation/LytAnimGroup.cs @@ -0,0 +1,343 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library.Animations; + +namespace LayoutBXLYT +{ + public interface IAnimationTarget + { + LytAnimTrack GetTrack(int target); + } + + /// + /// Layout animation group that stores multiple tag entries. + /// These map to either pane or materials + /// + public class LytAnimGroup : STAnimGroup + { + public BxlanPaiEntry animEntry; + + public AnimationTarget Target + { + get { return animEntry.Target; } + } + + public LytAnimGroup(BxlanPaiEntry entry) + { + animEntry = entry; + Name = entry.Name; + + //Generate sub groups which contain the track data + for (int i = 0; i < entry.Tags?.Count; i++) + { + STAnimGroup group = new STAnimGroup(); + + string tag = entry.Tags[i].Tag.Remove(0,1); + switch (tag) + { + case "LPA": + group = new LytPaneSRTGroup(entry.Tags[i]); + break; + case "LVI": + group = new LytVisibiltyGroup(entry.Tags[i]); + break; + case "LTS": + group = new LytTextureSRTGroup(entry.Tags[i]); + break; + case "LVC": + group = new LytVertexColorGroup(entry.Tags[i]); + break; + case "LMC": + group = new LytMaterialColorGroup(entry.Tags[i]); + break; + case "LIM": + group = new LytIndirectSRTGroup(entry.Tags[i]); + break; + case "LTP": + group = new LytTexturePatternGroup(entry.Tags[i]); + break; + case "LAC": + group = new LytAlphaTestGroup(entry.Tags[i]); + break; + case "LCT": + group = new LytFontShadowGroup(entry.Tags[i]); + break; + case "LCC": + group = new LytPerCharacterTransformCurveGroup(entry.Tags[i]); + break; + } + + Console.WriteLine($"tag {tag} {group}"); + + + foreach (var keyGroup in entry.Tags[i].Entries) + { + if (!(group is IAnimationTarget)) + continue; + + var targetGroup = ((IAnimationTarget)group).GetTrack(keyGroup.AnimationTarget); + if (targetGroup != null) + { + targetGroup.LoadKeyFrames(keyGroup.KeyFrames); + + if (keyGroup.CurveType == CurveType.Constant) + targetGroup.InterpolationType = STInterpoaltionType.Constant; + else if (keyGroup.CurveType == CurveType.Hermite) + targetGroup.InterpolationType = STInterpoaltionType.Hermite; + else if (keyGroup.CurveType == CurveType.Step) + targetGroup.InterpolationType = STInterpoaltionType.Step; + } + else + Console.WriteLine($"Unsupported track type for tag {keyGroup.TargetName} {keyGroup.AnimationTarget}"); + } + + group.Name = entry.Tags[i].Type; + SubAnimGroups.Add(group); + } + } + } + + public class LytAlphaTestGroup : STAnimGroup + { + public LytAlphaTestGroup(BxlanPaiTag entry) + { + + } + } + + public class LytFontShadowGroup : STAnimGroup + { + public LytFontShadowGroup(BxlanPaiTag entry) + { + + } + } + + public class LytPerCharacterTransformCurveGroup : STAnimGroup + { + public LytPerCharacterTransformCurveGroup(BxlanPaiTag entry) + { + + } + } + + public class LytPaneSRTGroup : STAnimGroup, IAnimationTarget + { + public BxlanPaiTag Tag; + + public LytAnimTrack TranslateX = new LytAnimTrack(); + public LytAnimTrack TranslateY = new LytAnimTrack(); + public LytAnimTrack TranslateZ = new LytAnimTrack(); + + public LytAnimTrack RotateX = new LytAnimTrack(); + public LytAnimTrack RotateY = new LytAnimTrack(); + public LytAnimTrack RotateZ = new LytAnimTrack(); + + public LytAnimTrack ScaleX = new LytAnimTrack(); + public LytAnimTrack ScaleY = new LytAnimTrack(); + + public LytAnimTrack SizeX = new LytAnimTrack(); + public LytAnimTrack SizeY = new LytAnimTrack(); + + public LytAnimTrack GetTrack(int target) + { + switch (target) + { + case 0: return TranslateX; + case 1: return TranslateY; + case 2: return TranslateZ; + case 3: return RotateX; + case 4: return RotateY; + case 5: return RotateZ; + case 6: return ScaleX; + case 7: return ScaleY; + case 8: return SizeX; + case 9: return SizeY; + default: return null; + } + } + + public LytPaneSRTGroup(BxlanPaiTag entry) + { + Tag = entry; + } + } + + public class LytTexturePatternGroup : STAnimGroup, IAnimationTarget + { + public LytAnimTrack Tex0AnimTrack = new LytAnimTrack(); + public LytAnimTrack Tex1AnimTrack = new LytAnimTrack(); + public LytAnimTrack Tex2AnimTrack = new LytAnimTrack(); + + public LytAnimTrack GetTrack(int target) { + if (target == 0) + return Tex0AnimTrack; + else if (target == 1) + return Tex1AnimTrack; + else if (target == 2) + return Tex2AnimTrack; + else + return Tex0AnimTrack; + } + + public LytTexturePatternGroup(BxlanPaiTag entry) + { + + } + } + + public class LytVisibiltyGroup : STAnimGroup, IAnimationTarget + { + public LytAnimTrack AnimTrack = new LytAnimTrack(); + + public LytAnimTrack GetTrack(int target) { + return AnimTrack; + } + + public LytVisibiltyGroup(BxlanPaiTag entry) + { + + } + } + + public class LytVertexColorGroup : STAnimGroup, IAnimationTarget + { + public LytAnimTrack TopLeftR = new LytAnimTrack(); + public LytAnimTrack TopLeftG = new LytAnimTrack(); + public LytAnimTrack TopLeftB = new LytAnimTrack(); + public LytAnimTrack TopLeftA = new LytAnimTrack(); + + public LytAnimTrack TopRightR = new LytAnimTrack(); + public LytAnimTrack TopRightG = new LytAnimTrack(); + public LytAnimTrack TopRightB = new LytAnimTrack(); + public LytAnimTrack TopRightA = new LytAnimTrack(); + + public LytAnimTrack BottomLeftR = new LytAnimTrack(); + public LytAnimTrack BottomLeftG = new LytAnimTrack(); + public LytAnimTrack BottomLeftB = new LytAnimTrack(); + public LytAnimTrack BottomLeftA = new LytAnimTrack(); + + public LytAnimTrack BottomRightR = new LytAnimTrack(); + public LytAnimTrack BottomRightG = new LytAnimTrack(); + public LytAnimTrack BottomRightB = new LytAnimTrack(); + public LytAnimTrack BottomRightA = new LytAnimTrack(); + + public LytAnimTrack Alpha = new LytAnimTrack(); + + public LytAnimTrack GetTrack(int target) + { + switch (target) { + case 0: return TopLeftR; + case 1: return TopLeftG; + case 2: return TopLeftB; + case 3: return TopLeftA; + case 4: return TopRightR; + case 5: return TopRightG; + case 6: return TopRightB; + case 7: return TopRightA; + case 8: return BottomLeftR; + case 9: return BottomLeftG; + case 10: return BottomLeftB; + case 11: return BottomLeftA; + case 12: return BottomRightR; + case 13: return BottomRightG; + case 14: return BottomRightB; + case 15: return BottomRightA; + case 16: return Alpha; + default: return null; + } + } + + public LytVertexColorGroup(BxlanPaiTag entry) + { + + } + } + + public class LytMaterialColorGroup : STAnimGroup, IAnimationTarget + { + public LytAnimTrack BlackColorR = new LytAnimTrack(); + public LytAnimTrack BlackColorG = new LytAnimTrack(); + public LytAnimTrack BlackColorB = new LytAnimTrack(); + public LytAnimTrack BlackColorA = new LytAnimTrack(); + + public LytAnimTrack WhiteColorR = new LytAnimTrack(); + public LytAnimTrack WhiteColorG = new LytAnimTrack(); + public LytAnimTrack WhiteColorB = new LytAnimTrack(); + public LytAnimTrack WhiteColorA = new LytAnimTrack(); + + public LytAnimTrack GetTrack(int target) + { + switch (target) + { + case 0: return BlackColorR; + case 1: return BlackColorG; + case 2: return BlackColorB; + case 3: return BlackColorA; + case 4: return WhiteColorR; + case 5: return WhiteColorG; + case 6: return WhiteColorB; + case 7: return WhiteColorA; + default: return null; + } + } + + public LytMaterialColorGroup(BxlanPaiTag entry) + { + + } + } + + public class LytTextureSRTGroup : STAnimGroup, IAnimationTarget + { + public LytAnimTrack TranslateU = new LytAnimTrack(); + public LytAnimTrack TranslateV = new LytAnimTrack(); + public LytAnimTrack Rotate = new LytAnimTrack(); + public LytAnimTrack ScaleU = new LytAnimTrack(); + public LytAnimTrack ScaleV = new LytAnimTrack(); + + public LytAnimTrack GetTrack(int target) + { + switch (target) + { + case 0: return TranslateU; + case 1: return TranslateV; + case 2: return Rotate; + case 3: return ScaleU; + case 4: return ScaleV; + default: return null; + } + } + + public LytTextureSRTGroup(BxlanPaiTag entry) + { + + } + } + + public class LytIndirectSRTGroup : STAnimGroup, IAnimationTarget + { + public LytAnimTrack Rotate = new LytAnimTrack(); + public LytAnimTrack ScaleU = new LytAnimTrack(); + public LytAnimTrack ScaleV = new LytAnimTrack(); + + public LytAnimTrack GetTrack(int target) + { + switch (target) + { + case 0: return Rotate; + case 1: return ScaleU; + case 2: return ScaleV; + default: return null; + } + } + + public LytIndirectSRTGroup(BxlanPaiTag entry) + { + + } + } +} diff --git a/File_Format_Library/FileFormats/Layout/Animation/LytAnimTrack.cs b/File_Format_Library/FileFormats/Layout/Animation/LytAnimTrack.cs new file mode 100644 index 00000000..de0b7d51 --- /dev/null +++ b/File_Format_Library/FileFormats/Layout/Animation/LytAnimTrack.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library.Animations; + +namespace LayoutBXLYT +{ + public class LytAnimTrack : STAnimationTrack + { + public void LoadKeyFrames(List keyFrames) + { + for (int i = 0; i < keyFrames?.Count; i++) + KeyFrames.Add(new LytKeyFrame(keyFrames[i])); + } + } +} diff --git a/File_Format_Library/FileFormats/Layout/Animation/LytAnimation.cs b/File_Format_Library/FileFormats/Layout/Animation/LytAnimation.cs new file mode 100644 index 00000000..a74d72c3 --- /dev/null +++ b/File_Format_Library/FileFormats/Layout/Animation/LytAnimation.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library.Animations; + +namespace LayoutBXLYT +{ + /// + /// An animation controller from a BRLYT/BCLYT/BFLYT file. + /// + public class LytAnimation : STAnimation + { + BxlytHeader parentLayout = null; + + public List Textures = new List(); + + public override void Reset() + { + if (parentLayout == null) return; + + foreach (var pane in parentLayout.PaneLookup.Values) + pane.animController.ResetAnim(); + + foreach (var mat in parentLayout.GetMaterials()) + mat.animController.ResetAnim(); + } + + public LytAnimation(BxlanHeader header, BxlytHeader layout) + { + parentLayout = layout; + + Name = header.FileName; + FrameCount = (uint)header.AnimationTag.EndFrame; + StartFrame = (uint)header.AnimationTag.StartFrame; + + Textures.Clear(); + AnimGroups.Clear(); + foreach (var tex in header.AnimationInfo.Textures) + Textures.Add(tex); + + foreach (var tag in header.AnimationInfo.Entries) + AnimGroups.Add(new LytAnimGroup(tag)); + } + + public override void NextFrame() + { + if (Frame == 0) + Reset(); + + if (Frame < StartFrame || Frame > FrameCount) return; + + if (parentLayout == null) return; + + //Loop through each group. + for (int i = 0; i < AnimGroups.Count; i++) + { + var group = AnimGroups[i] as LytAnimGroup; + + switch (group.Target) + { + case AnimationTarget.Material: + var mat = parentLayout.SearchMaterial(group.Name); + if (mat != null) LoadMaterialAnimation(mat, group); + break; + case AnimationTarget.Pane: + if (parentLayout.PaneLookup.ContainsKey(group.Name)) + LoadPaneAnimation(parentLayout.PaneLookup[group.Name], group); + break; + } + } + } + + private void LoadMaterialAnimation(BxlytMaterial material, LytAnimGroup group) + { + //Sub groups store tag entries like texture patterns, srt, etc + foreach (var subGroup in group.SubAnimGroups) + { + if (subGroup is LytTexturePatternGroup) + LoadTexturePatternGroup(material, (LytTexturePatternGroup)subGroup); + else if (subGroup is LytTextureSRTGroup) + LoadTextureSRTGroup(material, (LytTextureSRTGroup)subGroup); + else if (subGroup is LytAlphaTestGroup) + LoadAlphaTestGroup(material, (LytAlphaTestGroup)subGroup); + else if (subGroup is LytIndirectSRTGroup) + LoadIndirectSRTGroup(material, (LytIndirectSRTGroup)subGroup); + else if (subGroup is LytMaterialColorGroup) + LoadMaterialColorGroup(material, (LytMaterialColorGroup)subGroup); + } + } + + private void LoadPaneAnimation(BasePane pane, LytAnimGroup group) + { + //Sub groups store tag entries like vertex colors, srt, etc + foreach (var subGroup in group.SubAnimGroups) + { + if (subGroup is LytVertexColorGroup) + LoadVertexColorGroup(pane, (LytVertexColorGroup)subGroup); + else if (subGroup is LytPaneSRTGroup) + LoadPaneSRTGroup(pane, (LytPaneSRTGroup)subGroup); + else if (subGroup is LytVisibiltyGroup) + LoadVisibiltyGroup(pane, (LytVisibiltyGroup)subGroup); + } + } + + private void LoadVertexColorGroup(BasePane pane, LytVertexColorGroup group) + { + for (int i = 0; i < 17; i++) + { + if (group.GetTrack(i).HasKeys) + { + var track = group.GetTrack(i); + var value = track.GetFrameValue(Frame, StartFrame); + var target = (LVCTarget)i; + + if (!pane.animController.PaneVertexColors.ContainsKey(target)) + pane.animController.PaneVertexColors.Add(target, value); + else + pane.animController.PaneVertexColors[target] = value; + } + } + } + + private void LoadPaneSRTGroup(BasePane pane, LytPaneSRTGroup group) + { + for (int i = 0; i < 10; i++) + { + if (group.GetTrack(i).HasKeys) + { + var track = group.GetTrack(i); + var value = track.GetFrameValue(Frame, StartFrame); + var target = (LPATarget)i; + + Console.WriteLine($"{pane.Name} {group.Name} {value} {target}"); + + if (!pane.animController.PaneSRT.ContainsKey(target)) + pane.animController.PaneSRT.Add(target, value); + else + pane.animController.PaneSRT[target] = value; + } + } + } + + private void LoadVisibiltyGroup(BasePane pane, LytVisibiltyGroup group) + { + if (group.AnimTrack.HasKeys) + { + var track = group.AnimTrack; + var value = track.GetFrameValue(Frame, StartFrame); + pane.animController.Visibile = value == 1 ? true : false; + } + } + + private void LoadMaterialColorGroup(BxlytMaterial mat, LytMaterialColorGroup group) + { + for (int i = 0; i < 8; i++) + { + if (group.GetTrack(i).HasKeys) + { + var track = group.GetTrack(i); + var value = track.GetFrameValue(Frame, StartFrame); + var target = (LMCTarget)i; + + if (!mat.animController.MaterialColors.ContainsKey(target)) + mat.animController.MaterialColors.Add(target, value); + else + mat.animController.MaterialColors[target] = value; + } + } + } + + private void LoadTexturePatternGroup(BxlytMaterial mat, LytTexturePatternGroup group) + { + for (int i = 0; i < 1; i++) + { + if (group.GetTrack(i).HasKeys) + { + var track = group.GetTrack(i); + var value = track.GetFrameValue(Frame, StartFrame); + var target = (LTPTarget)i; + + if (Textures.Count > value && value >= 0) + { + string texName = Textures[(int)value]; + + if (!mat.animController.TexturePatterns.ContainsKey(target)) + mat.animController.TexturePatterns.Add(target, texName); + else + mat.animController.TexturePatterns[target] = texName; + } + } + } + } + + private void LoadTextureSRTGroup(BxlytMaterial mat, LytTextureSRTGroup group) + { + for (int i = 0; i < 5; i++) + { + if (group.GetTrack(i).HasKeys) + { + var track = group.GetTrack(i); + var value = track.GetFrameValue(Frame, StartFrame); + var target = (LTSTarget)i; + + if (!mat.animController.TextureSRTS.ContainsKey(target)) + mat.animController.TextureSRTS.Add(target, value); + else + mat.animController.TextureSRTS[target] = value; + } + } + } + + private void LoadIndirectSRTGroup(BxlytMaterial mat, LytIndirectSRTGroup group) + { + + } + + private void LoadAlphaTestGroup(BxlytMaterial mat, LytAlphaTestGroup group) + { + + } + } +} diff --git a/File_Format_Library/FileFormats/Layout/Animation/LytKeyFrame.cs b/File_Format_Library/FileFormats/Layout/Animation/LytKeyFrame.cs new file mode 100644 index 00000000..a1af4f8f --- /dev/null +++ b/File_Format_Library/FileFormats/Layout/Animation/LytKeyFrame.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library.Animations; + +namespace LayoutBXLYT +{ + public class LytKeyFrame : STKeyFrame + { + public KeyFrame bxlytKeyframe; + + public LytKeyFrame(KeyFrame key) + { + bxlytKeyframe = key; + } + + public override float Value => bxlytKeyframe.Value; + public override float Slope => bxlytKeyframe.Slope; + public override float Frame => bxlytKeyframe.Frame; + } +} diff --git a/File_Format_Library/FileFormats/Layout/BxlytShader.cs b/File_Format_Library/FileFormats/Layout/BxlytShader.cs index 3faca783..06132ce8 100644 --- a/File_Format_Library/FileFormats/Layout/BxlytShader.cs +++ b/File_Format_Library/FileFormats/Layout/BxlytShader.cs @@ -10,6 +10,8 @@ namespace LayoutBXLYT { public class BxlytShader : IDisposable { + public bool Compiled = false; + public int program; private int vertexShader; private int fragmentShader; @@ -125,9 +127,7 @@ namespace LayoutBXLYT GL.GetProgram(program, GetProgramParameterName.ActiveAttributes, out activeAttributeCount); for (int i = 0; i < activeAttributeCount; i++) { - int size = 0; - ActiveAttribType type; - string name = GL.GetActiveAttrib(program, i, out size, out type); + string name = GL.GetActiveAttrib(program, i, out int size, out ActiveAttribType type); int location = GL.GetAttribLocation(program, name); // Overwrite existing vertex attributes. @@ -135,6 +135,26 @@ namespace LayoutBXLYT } } + public void EnableVertexAttributes() + { + foreach (KeyValuePair attrib in attributes) + GL.EnableVertexAttribArray(attrib.Value); + } + + public void DisableVertexAttributes() + { + foreach (KeyValuePair attrib in attributes) + GL.DisableVertexAttribArray(attrib.Value); + } + + public int GetAttribute(string name) + { + if (string.IsNullOrEmpty(name) || !attributes.ContainsKey(name)) + return -1; + else + return attributes[name]; + } + private void LoadUniorms(int program) { uniforms.Clear(); @@ -156,8 +176,11 @@ namespace LayoutBXLYT { program = CompileShaders(); + LoadAttributes(program); LoadUniorms(program); OnCompiled(); + + Compiled = true; } public virtual void OnCompiled() { } diff --git a/File_Format_Library/FileFormats/Layout/BxlytToGL.cs b/File_Format_Library/FileFormats/Layout/BxlytToGL.cs index 83374307..fc07f254 100644 --- a/File_Format_Library/FileFormats/Layout/BxlytToGL.cs +++ b/File_Format_Library/FileFormats/Layout/BxlytToGL.cs @@ -2,10 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Drawing; -using System.Threading.Tasks; +using System.Drawing.Imaging; using OpenTK.Graphics.OpenGL; using Toolbox.Library; using Toolbox.Library.IO; +using Toolbox.Library.Rendering; using OpenTK; using LayoutBXLYT.Cafe; @@ -44,7 +45,7 @@ namespace LayoutBXLYT } } - public static void DrawPictureBox(BasePane pane, byte effectiveAlpha, Dictionary Textures) + public static void DrawPictureBox(BasePane pane, bool gameWindow, byte effectiveAlpha, Dictionary Textures) { if (!Runtime.LayoutEditor.DisplayPicturePane) return; @@ -60,11 +61,15 @@ namespace LayoutBXLYT { var pic1Pane = pane as Cafe.BFLYT.PIC1; + STColor8[] stColors = SetupVertexColors(pane, + pic1Pane.ColorBottomRight, pic1Pane.ColorBottomLeft, + pic1Pane.ColorTopLeft, pic1Pane.ColorTopRight); + Color[] Colors = new Color[] { - pic1Pane.ColorBottomRight.Color, - pic1Pane.ColorBottomLeft.Color, - pic1Pane.ColorTopLeft.Color, - pic1Pane.ColorTopRight.Color, + stColors[0].Color, + stColors[1].Color, + stColors[2].Color, + stColors[3].Color, }; var mat = pic1Pane.Material; @@ -75,7 +80,7 @@ namespace LayoutBXLYT } mat.Shader.Enable(); - ((BflytShader)mat.Shader).SetMaterials(Textures); + ((BflytShader)mat.Shader).SetMaterials(pic1Pane,Textures); if (pic1Pane.TexCoords.Length > 0) { @@ -87,7 +92,7 @@ namespace LayoutBXLYT }; } - DrawRectangle(pane, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); + DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); mat.Shader.Disable(); } @@ -110,7 +115,7 @@ namespace LayoutBXLYT } mat.Shader.Enable(); - ((BclytShader)mat.Shader).SetMaterials(Textures); + ((BclytShader)mat.Shader).SetMaterials(pane,Textures); if (pic1Pane.TexCoords.Length > 0) { @@ -122,7 +127,7 @@ namespace LayoutBXLYT }; } - DrawRectangle(pane, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); + DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); mat.Shader.Disable(); } @@ -145,7 +150,7 @@ namespace LayoutBXLYT } mat.Shader.Enable(); - ((BrlytShader)mat.Shader).SetMaterials(Textures); + ((BrlytShader)mat.Shader).SetMaterials(pane, Textures); if (pic1Pane.TexCoords.Length > 0) { @@ -157,7 +162,7 @@ namespace LayoutBXLYT }; } - DrawRectangle(pane, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); + DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); mat.Shader.Disable(); } @@ -168,9 +173,9 @@ namespace LayoutBXLYT GL.UseProgram(0); } - public static void DrawBoundryPane(BasePane pane, byte effectiveAlpha, List SelectedPanes) + public static void DrawBoundryPane(BasePane pane, bool gameWindow, byte effectiveAlpha, List SelectedPanes) { - if (!Runtime.LayoutEditor.DisplayBoundryPane || Runtime.LayoutEditor.IsGamePreview) + if (!Runtime.LayoutEditor.DisplayBoundryPane || gameWindow || Runtime.LayoutEditor.IsGamePreview) return; Vector2[] TexCoords = new Vector2[] { @@ -193,13 +198,13 @@ namespace LayoutBXLYT color, }; - BxlytToGL.DrawRectangle(pane, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); + BxlytToGL.DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); } - public static void DrawAlignmentPane(BasePane pane, byte effectiveAlpha, List SelectedPanes) + public static void DrawAlignmentPane(BasePane pane, bool gameWindow, byte effectiveAlpha, List SelectedPanes) { - if (!Runtime.LayoutEditor.DisplayAlignmentPane || Runtime.LayoutEditor.IsGamePreview) + if (!Runtime.LayoutEditor.DisplayAlignmentPane || gameWindow || Runtime.LayoutEditor.IsGamePreview) return; @@ -223,12 +228,12 @@ namespace LayoutBXLYT color, }; - BxlytToGL.DrawRectangle(pane, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); + BxlytToGL.DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); } - public static void DrawScissorPane(BasePane pane, byte effectiveAlpha, List SelectedPanes) + public static void DrawScissorPane(BasePane pane, bool gameWindow, byte effectiveAlpha, List SelectedPanes) { - if (!Runtime.LayoutEditor.DisplayScissorPane || Runtime.LayoutEditor.IsGamePreview) + if (!Runtime.LayoutEditor.DisplayScissorPane || gameWindow || Runtime.LayoutEditor.IsGamePreview) return; Vector2[] TexCoords = new Vector2[] { @@ -251,13 +256,165 @@ namespace LayoutBXLYT color, }; - BxlytToGL.DrawRectangle(pane, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); + BxlytToGL.DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha); + } + + public static void DrawTextbox(BasePane pane, bool gameWindow, Bitmap fontBitmap, byte effectiveAlpha, + Dictionary Textures, List SelectedPanes, bool updateBitmap) + { + var textBox = (ITextPane)pane; + + if (updateBitmap) + BindFontBitmap(pane, fontBitmap); + + int width = (int)pane.Width; + int height = (int)pane.Height; + + var mat = textBox.Material as BFLYT.Material; + if (mat.Shader == null) + { + mat.Shader = new BflytShader(mat); + mat.Shader.Compile(); + } + + mat.Shader.Enable(); + ((BflytShader)mat.Shader).SetMaterials(pane, Textures); + + GL.ActiveTexture(TextureUnit.Texture0 + 1); + mat.Shader.SetInt($"numTextureMaps", 1); + mat.Shader.SetInt($"textures0", 1); + mat.Shader.SetInt($"hasTexture0", 1); + GL.BindTexture(TextureTarget.Texture2D, textBox.RenderableFont.TexID); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, ConvertChannel(STChannelType.Red)); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, ConvertChannel(STChannelType.Green)); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, ConvertChannel(STChannelType.Blue)); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, ConvertChannel(STChannelType.Alpha)); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS,(int)TextureWrapMode.Clamp); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + + Vector2[] texCoords = new Vector2[] { + new Vector2(0, 1), + new Vector2(1, 1), + new Vector2(1, 0), + new Vector2(0, 0), + }; + + Color color = Color.White; + Color[] Colors = new Color[] { + color, + color, + color, + color, + }; + + DrawRectangle(pane, gameWindow, pane.Rectangle, texCoords, Colors, false, effectiveAlpha); + + GL.BindTexture(TextureTarget.Texture2D, 0); + } + + private static void BindFontBitmap(BasePane pane, Bitmap fontBitmap) + { + var textBox = (ITextPane)pane; + + switch ($"{textBox.HorizontalAlignment}_{textBox.VerticalAlignment}") + { + case "Center_Center": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, b.Width / 2f - fontBitmap.Width / 2f, b.Height / 2f - fontBitmap.Height / 2f); + + fontBitmap = b; + } + break; + case "Left_Center": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, 0, b.Height / 2f - fontBitmap.Height / 2f); + + fontBitmap = b; + } + break; + case "Right_Center": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, 0, b.Height / 2f - fontBitmap.Height / 2f); + + fontBitmap = b; + } + break; + case "Center_Top": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, b.Width - fontBitmap.Width, b.Height / 2f - fontBitmap.Height / 2f); + + fontBitmap = b; + } + break; + case "Center_Bottom": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, b.Width / 2f - fontBitmap.Width / 2f, b.Height - fontBitmap.Height); + + fontBitmap = b; + } + break; + case "Left_Top": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, 0, 0); + + fontBitmap = b; + } + break; + case "Right_Top": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, b.Width - fontBitmap.Width, 0); + + fontBitmap = b; + } + break; + case "Left_Bottom": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, 0, b.Height - fontBitmap.Height); + + fontBitmap = b; + } + break; + case "Right_Bottom": + { + Bitmap b = new Bitmap((int)pane.Width, (int)pane.Height); + using (Graphics g = Graphics.FromImage(b)) + g.DrawImage(fontBitmap, b.Width - fontBitmap.Width, b.Height - fontBitmap.Height); + + fontBitmap = b; + } + break; + } + if (textBox.RenderableFont == null) + textBox.RenderableFont = RenderableTex.FromBitmap(fontBitmap); + else + textBox.RenderableFont.UpdateFromBitmap(fontBitmap); + + textBox.RenderableFont.TextureWrapS = TextureWrapMode.Clamp; + textBox.RenderableFont.TextureWrapT = TextureWrapMode.Clamp; } //Huge thanks to layout studio for the window pane rendering code //https://github.com/Treeki/LayoutStudio/blob/master/layoutgl/widget.cpp //Note i still need to fix UV coordinates being flips and transformed! - public static void DrawWindowPane(BasePane pane, byte effectiveAlpha, Dictionary Textures) + public static void DrawWindowPane(BasePane pane,bool gameWindow, byte effectiveAlpha, Dictionary Textures) { if (!Runtime.LayoutEditor.DisplayWindowPane) return; @@ -328,8 +485,8 @@ namespace LayoutBXLYT if (!window.NotDrawnContent && window.WindowKind != WindowKind.HorizontalNoContent) { - SetupShaders(window.Content.Material, Textures); - DrawQuad(dX + frameLeft - window.StretchLeft, + SetupShaders(pane, window.Content.Material, Textures); + DrawQuad(gameWindow, dX + frameLeft - window.StretchLeft, dY - frameTop + window.StretchTop, contentWidth, contentHeight, @@ -352,14 +509,17 @@ namespace LayoutBXLYT switch (window.FrameCount) { + case 2: //2 frame. 2 textures for corners sides (horizontal) case 1: //1 frame. 1 texture for corners (around) or sides (horizontal) { var windowFrame = window.WindowFrames[0]; - SetupShaders(windowFrame.Material, Textures); + SetupShaders(pane, windowFrame.Material, Textures); //2 sides, no corners if (window.WindowKind == WindowKind.Horizontal) { + //Left + texCoords = new Vector2[] { new Vector2(1, 0), @@ -368,7 +528,19 @@ namespace LayoutBXLYT new Vector2(1, 1), }; - DrawQuad(dX + frameRight + contentWidth, dY, frameRight, pane.Height, texCoords, colors); + colors = new Color[] { + window.Content.ColorTopRight.Color, + window.Content.ColorTopRight.Color, + window.Content.ColorBottomRight.Color, + window.Content.ColorBottomRight.Color, + }; + + DrawQuad(gameWindow, dX + frameRight + contentWidth, dY, frameRight, pane.Height, texCoords, colors); + + //Right + + if (window.FrameCount == 2) + SetupShaders(pane, window.WindowFrames[1].Material, Textures); texCoords = new Vector2[] { @@ -378,10 +550,19 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX, dY, frameLeft, pane.Height, texCoords, colors); + colors = new Color[] { + window.Content.ColorTopLeft.Color, + window.Content.ColorTopLeft.Color, + window.Content.ColorBottomLeft.Color, + window.Content.ColorBottomLeft.Color, + }; + + DrawQuad(gameWindow, dX, dY, frameLeft, pane.Height, texCoords, colors); } else if (window.WindowKind == WindowKind.HorizontalNoContent) { + //Right + texCoords = new Vector2[] { new Vector2((pane.Width - frameRight) / frameRight, 0), @@ -390,7 +571,47 @@ namespace LayoutBXLYT new Vector2((pane.Width - frameRight) / frameRight, 1), }; - DrawQuad(dX + frameLeft, dY, pane.Width - frameLeft, pane.Height, texCoords, colors); + colors = new Color[] { + //Top Right + window.Content.ColorTopRight.Color, + + //Top Left + VertexColorHelper.Mix(window.Content.ColorTopLeft.Color, + window.Content.ColorTopRight.Color, + (frameLeft / frameLeft)), + + //Bottom Left + VertexColorHelper.Mix(window.Content.ColorBottomLeft.Color, + window.Content.ColorBottomRight.Color, + (frameLeft / frameLeft)), + + //Bottom Right + window.Content.ColorBottomRight.Color, + }; + + DrawQuad(gameWindow, dX + frameLeft, dY, pane.Width - frameLeft, pane.Height, texCoords, colors); + + //Left + + if (window.FrameCount == 2) + SetupShaders(pane, window.WindowFrames[1].Material, Textures); + + colors = new Color[] { + //Top Left + window.Content.ColorTopLeft.Color, + + //Top Right + VertexColorHelper.Mix(window.Content.ColorTopLeft.Color, + window.Content.ColorTopRight.Color, + 1), + //Bottom Right + VertexColorHelper.Mix(window.Content.ColorBottomLeft.Color, + window.Content.ColorBottomRight.Color, + 1), + + //Bottom Left + window.Content.ColorBottomLeft.Color, + }; texCoords = new Vector2[] { @@ -400,7 +621,7 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX, dY, pane.Width - frameLeft, pane.Height, texCoords, colors); + DrawQuad(gameWindow, dX, dY, pane.Width - frameLeft, pane.Height, texCoords, colors); } else if (window.WindowKind == WindowKind.Around) { @@ -417,7 +638,7 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX, dY, pieceWidth, pieceHeight, texCoords, colors); + DrawQuad(gameWindow, dX, dY, pieceWidth, pieceHeight, texCoords, colors); // top right pieceWidth = frameRight; @@ -431,7 +652,7 @@ namespace LayoutBXLYT new Vector2(1,(pane.Height - frameTop) / frameTop), }; - DrawQuad(dX + pane.Width - frameRight, dY, pieceWidth, pieceHeight, texCoords, colors); + DrawQuad(gameWindow, dX + pane.Width - frameRight, dY, pieceWidth, pieceHeight, texCoords, colors); // bottom left pieceWidth = frameLeft; @@ -445,7 +666,7 @@ namespace LayoutBXLYT new Vector2(0, 0), }; - DrawQuad(dX, dY - frameTop, pieceWidth, pieceHeight, texCoords, colors); + DrawQuad(gameWindow, dX, dY - frameTop, pieceWidth, pieceHeight, texCoords, colors); // bottom right pieceWidth = pane.Width - frameLeft; @@ -459,7 +680,7 @@ namespace LayoutBXLYT new Vector2((pane.Width - frameLeft) / frameLeft, 0), }; - DrawQuad(dX + frameLeft, dY - pane.Height + frameBottom, pieceWidth, pieceHeight, texCoords, colors); + DrawQuad(gameWindow, dX + frameLeft, dY - pane.Height + frameBottom, pieceWidth, pieceHeight, texCoords, colors); } } break; @@ -481,7 +702,7 @@ namespace LayoutBXLYT if (matTL.TextureMaps.Length > 0) { - SetupShaders(matTL, Textures); + SetupShaders(pane, matTL, Textures); matTL.Shader.SetInt("flipTexture", (int)window.WindowFrames[0].TextureFlip); @@ -496,11 +717,11 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX, dY, pieceWidth, pieceHeight, texCoords, colors); + DrawQuad(gameWindow, dX, dY, pieceWidth, pieceHeight, texCoords, colors); } if (matTR.TextureMaps.Length > 0) { - SetupShaders(matTR, Textures); + SetupShaders(pane, matTR, Textures); matTR.Shader.SetInt("flipTexture", (int)window.WindowFrames[1].TextureFlip); @@ -515,11 +736,11 @@ namespace LayoutBXLYT new Vector2(0,(pane.Height - frameTop) / frameTop), }; - DrawQuad(dX + pane.Width - frameRight, dY, pieceWidth, pieceHeight, texCoords, colors); + DrawQuad(gameWindow, dX + pane.Width - frameRight, dY, pieceWidth, pieceHeight, texCoords, colors); } if (matBL.TextureMaps.Length > 0) { - SetupShaders(matBL, Textures); + SetupShaders(pane, matBL, Textures); matBL.Shader.SetInt("flipTexture", (int)window.WindowFrames[2].TextureFlip); @@ -534,11 +755,11 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX, dY - frameTop, pieceWidth, pieceHeight, texCoords, colors); + DrawQuad(gameWindow, dX, dY - frameTop, pieceWidth, pieceHeight, texCoords, colors); } if (matBR.TextureMaps.Length > 0) { - SetupShaders(matBR, Textures); + SetupShaders(pane, matBR, Textures); matBR.Shader.SetInt("flipTexture", (int)window.WindowFrames[3].TextureFlip); @@ -553,7 +774,7 @@ namespace LayoutBXLYT new Vector2(1 - ((pane.Width - frameLeft) / frameLeft), 1), }; - DrawQuad(dX + frameLeft, dY - pane.Height + frameBottom, pieceWidth, pieceHeight, texCoords, colors); + DrawQuad(gameWindow, dX + frameLeft, dY - pane.Height + frameBottom, pieceWidth, pieceHeight, texCoords, colors); } } break; @@ -583,7 +804,7 @@ namespace LayoutBXLYT if (matTL.TextureMaps.Length > 0) { - SetupShaders(matTL, Textures); + SetupShaders(pane, matTL, Textures); matTL.Shader.SetInt("flipTexture", (int)window.WindowFrames[0].TextureFlip); texCoords = new Vector2[] @@ -594,12 +815,12 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX, dY, frameLeft, frameTop, texCoords, colors); + DrawQuad(gameWindow, dX, dY, frameLeft, frameTop, texCoords, colors); } if (matTR.TextureMaps.Length > 0) { - SetupShaders(matTR, Textures); + SetupShaders(pane, matTR, Textures); matTR.Shader.SetInt("flipTexture", (int)window.WindowFrames[1].TextureFlip); texCoords = new Vector2[] @@ -610,12 +831,12 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX + pane.Width - frameRight, dY, frameRight, frameTop, texCoords, colors); + DrawQuad(gameWindow, dX + pane.Width - frameRight, dY, frameRight, frameTop, texCoords, colors); } if (matBL.TextureMaps.Length > 0) { - SetupShaders(matBL, Textures); + SetupShaders(pane, matBL, Textures); matBL.Shader.SetInt("flipTexture", (int)window.WindowFrames[2].TextureFlip); texCoords = new Vector2[] @@ -626,12 +847,12 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX, dY - pane.Height + frameTop, frameLeft, frameBottom, texCoords, colors); + DrawQuad(gameWindow, dX, dY - pane.Height + frameTop, frameLeft, frameBottom, texCoords, colors); } if (matBR.TextureMaps.Length > 0) { - SetupShaders(matBR, Textures); + SetupShaders(pane, matBR, Textures); matBR.Shader.SetInt("flipTexture", (int)window.WindowFrames[3].TextureFlip); texCoords = new Vector2[] @@ -642,12 +863,12 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX + pane.Width - frameLeft, dY - pane.Height + frameBottom, frameRight, frameBottom, texCoords, colors); + DrawQuad(gameWindow, dX + pane.Width - frameLeft, dY - pane.Height + frameBottom, frameRight, frameBottom, texCoords, colors); } if (matT.TextureMaps.Length > 0) { - SetupShaders(matT, Textures); + SetupShaders(pane, matT, Textures); matT.Shader.SetInt("flipTexture", (int)window.WindowFrames[4].TextureFlip); texCoords = new Vector2[] @@ -658,12 +879,12 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX + frameLeft, dY, contentWidth, frameTop, texCoords, colors); + DrawQuad(gameWindow, dX + frameLeft, dY, contentWidth, frameTop, texCoords, colors); } if (matB.TextureMaps.Length > 0) { - SetupShaders(matB, Textures); + SetupShaders(pane, matB, Textures); matB.Shader.SetInt("flipTexture", (int)window.WindowFrames[5].TextureFlip); texCoords = new Vector2[] @@ -674,12 +895,12 @@ namespace LayoutBXLYT new Vector2(1-((pane.Width - frameLeft) / frameLeft), 1), }; - DrawQuad(dX + frameRight, dY - (pane.Height - frameBottom), contentWidth, frameTop, texCoords, colors); + DrawQuad(gameWindow, dX + frameRight, dY - (pane.Height - frameBottom), contentWidth, frameTop, texCoords, colors); } if (matL.TextureMaps.Length > 0) { - SetupShaders(matL, Textures); + SetupShaders(pane, matL, Textures); matL.Shader.SetInt("flipTexture", (int)window.WindowFrames[6].TextureFlip); texCoords = new Vector2[] @@ -690,12 +911,12 @@ namespace LayoutBXLYT new Vector2(0, 1), }; - DrawQuad(dX, dY - frameTop, frameLeft, contentHeight, texCoords, colors); + DrawQuad(gameWindow, dX, dY - frameTop, frameLeft, contentHeight, texCoords, colors); } if (matR.TextureMaps.Length > 0) { - SetupShaders(matR, Textures); + SetupShaders(pane, matR, Textures); matR.Shader.SetInt("flipTexture", (int)window.WindowFrames[7].TextureFlip); texCoords = new Vector2[] @@ -706,7 +927,7 @@ namespace LayoutBXLYT new Vector2(0,(pane.Height - frameBottom) / frameBottom), }; - DrawQuad(dX + (pane.Width - frameRight), dY - frameTop, frameRight, contentHeight, texCoords, colors); + DrawQuad(gameWindow, dX + (pane.Width - frameRight), dY - frameTop, frameRight, contentHeight, texCoords, colors); } } break; @@ -748,9 +969,9 @@ namespace LayoutBXLYT } } - private static void DrawQuad(float x, float y, float w, float h, Vector2[] texCoords, Color[] colors) + private static void DrawQuad(bool gameWindow, float x, float y, float w, float h, Vector2[] texCoords, Color[] colors) { - if (!Runtime.LayoutEditor.IsGamePreview) + if (!gameWindow && !Runtime.LayoutEditor.IsGamePreview) { GL.Disable(EnableCap.AlphaTest); GL.Disable(EnableCap.Blend); @@ -811,7 +1032,7 @@ namespace LayoutBXLYT return pos; } - private static void SetupShaders(BxlytMaterial mat, Dictionary textures) + private static void SetupShaders(BasePane pane, BxlytMaterial mat, Dictionary textures) { if (mat.Shader == null) { @@ -824,7 +1045,7 @@ namespace LayoutBXLYT mat.Shader.Enable(); if (mat is Cafe.BFLYT.Material) - ((BflytShader)mat.Shader).SetMaterials(textures); + ((BflytShader)mat.Shader).SetMaterials(pane, textures); } private static void RenderWindowContent(BasePane pane, uint sizeX, uint sizeY, BxlytWindowContent content, @@ -833,7 +1054,7 @@ namespace LayoutBXLYT var mat = content.Material; var rect = pane.CreateRectangle(sizeX, sizeY); - SetupShaders(mat, Textures); + SetupShaders(pane, mat, Textures); Vector2[] texCoords = new Vector2[] { new Vector2(1,1), @@ -912,7 +1133,7 @@ namespace LayoutBXLYT } - private static BlendingFactor ConvertBlendFactor(BlendMode.GX2BlendFactor blendFactor) + public static BlendingFactor ConvertBlendFactor(BlendMode.GX2BlendFactor blendFactor) { switch (blendFactor) { @@ -930,7 +1151,7 @@ namespace LayoutBXLYT } } - private static LogicOp ConvertLogicOperation(BlendMode.GX2LogicOp blendOp) + public static LogicOp ConvertLogicOperation(BlendMode.GX2LogicOp blendOp) { switch (blendOp) { @@ -955,7 +1176,23 @@ namespace LayoutBXLYT } } - private static BlendEquationMode ConvertBlendOperation(BlendMode.GX2BlendOp blendOp) + public static AlphaFunction ConvertAlphaFunc(GfxAlphaFunction alphaFunc) + { + switch (alphaFunc) + { + case GfxAlphaFunction.Always: return AlphaFunction.Always; + case GfxAlphaFunction.Equal: return AlphaFunction.Equal; + case GfxAlphaFunction.Greater: return AlphaFunction.Greater; + case GfxAlphaFunction.GreaterOrEqual: return AlphaFunction.Gequal; + case GfxAlphaFunction.Less: return AlphaFunction.Less; + case GfxAlphaFunction.LessOrEqual: return AlphaFunction.Lequal; + case GfxAlphaFunction.Never: return AlphaFunction.Never; + case GfxAlphaFunction.NotEqual: return AlphaFunction.Notequal; + default: return AlphaFunction.Always; + } + } + + public static BlendEquationMode ConvertBlendOperation(BlendMode.GX2BlendOp blendOp) { switch (blendOp) { @@ -981,7 +1218,43 @@ namespace LayoutBXLYT Alpha = All.Alpha, } - public static void DrawRectangle(BasePane pane, CustomRectangle rect, Vector2[] texCoords, + private static STColor8[] SetupVertexColors(BasePane pane, + STColor8 ColorBottomRight, STColor8 ColorBottomLeft, + STColor8 ColorTopLeft, STColor8 ColorTopRight) + { + STColor8[] outColors = new STColor8[4]; + outColors[0] = ColorBottomLeft; + outColors[1] = ColorBottomRight; + outColors[2] = ColorTopRight; + outColors[3] = ColorTopLeft; + + foreach (var animItem in pane.animController.PaneVertexColors) + { + switch (animItem.Key) + { + case LVCTarget.LeftBottomRed: outColors[0].R = (byte)animItem.Value; break; + case LVCTarget.LeftBottomGreen: outColors[0].G = (byte)animItem.Value; break; + case LVCTarget.LeftBottomBlue: outColors[0].B = (byte)animItem.Value; break; + case LVCTarget.LeftBottomAlpha: outColors[0].A = (byte)animItem.Value; break; + case LVCTarget.RightBottomRed: outColors[1].R = (byte)animItem.Value; break; + case LVCTarget.RightBottomGreen: outColors[1].G = (byte)animItem.Value; break; + case LVCTarget.RightBottomBlue: outColors[1].B = (byte)animItem.Value; break; + case LVCTarget.RightBottomAlpha: outColors[1].A = (byte)animItem.Value; break; + case LVCTarget.RightTopRed: outColors[2].R = (byte)animItem.Value; break; + case LVCTarget.RightTopGreen: outColors[2].G = (byte)animItem.Value; break; + case LVCTarget.RightTopBlue: outColors[2].B = (byte)animItem.Value; break; + case LVCTarget.RightTopAlpha: outColors[2].A = (byte)animItem.Value; break; + case LVCTarget.LeftTopRed: outColors[3].R = (byte)animItem.Value; break; + case LVCTarget.LeftTopGreen: outColors[3].G = (byte)animItem.Value; break; + case LVCTarget.LeftTopBlue: outColors[3].B = (byte)animItem.Value; break; + case LVCTarget.LeftTopAlpha: outColors[3].A = (byte)animItem.Value; break; + } + } + + return outColors; + } + + public static void DrawRectangle(BasePane pane, bool gameWindow, CustomRectangle rect, Vector2[] texCoords, Color[] colors, bool useLines = true, byte alpha = 255) { for (int i = 0; i < colors.Length; i++) @@ -1004,7 +1277,7 @@ namespace LayoutBXLYT } else { - if (!Runtime.LayoutEditor.IsGamePreview) + if (!Runtime.LayoutEditor.IsGamePreview && !gameWindow) { GL.Disable(EnableCap.Blend); GL.Disable(EnableCap.AlphaTest); @@ -1057,7 +1330,7 @@ namespace LayoutBXLYT vertices[3] = new Vector3(rect.LeftPoint, rect.TopPoint, 0); Vector4[] vertexColors = new Vector4[4]; - pane.renderablePane.Render(vertices, vertexColors, texCoords); + // pane.renderablePane.Render(vertices, vertexColors, texCoords); } } } diff --git a/File_Format_Library/FileFormats/Layout/CAFE/BFLAN.cs b/File_Format_Library/FileFormats/Layout/CAFE/BFLAN.cs index 8ff783ba..33e50dd0 100644 --- a/File_Format_Library/FileFormats/Layout/CAFE/BFLAN.cs +++ b/File_Format_Library/FileFormats/Layout/CAFE/BFLAN.cs @@ -11,7 +11,7 @@ using SharpYaml.Serialization; namespace LayoutBXLYT { - public class BFLAN : IEditorForm, IFileFormat, IConvertableTextFormat + public class BFLAN : BXLAN, IEditorForm, IFileFormat, IConvertableTextFormat { public FileType FileType { get; set; } = FileType.Layout; @@ -54,29 +54,27 @@ namespace LayoutBXLYT serializerSettings.ComparerForKeySorting = null; serializerSettings.RegisterTagMapping("Header", typeof(Header)); - return FLAN.ToXml(header); + return FLAN.ToXml((Header)BxlanHeader); var serializer = new Serializer(serializerSettings); - string yaml = serializer.Serialize(header, typeof(Header)); + string yaml = serializer.Serialize(BxlanHeader, typeof(Header)); return yaml; } public void ConvertFromString(string text) { - header = FLAN.FromXml(text); - header.FileInfo = this; + BxlanHeader = FLAN.FromXml(text); + BxlanHeader.FileInfo = this; } #endregion - public Header header; - public void Load(System.IO.Stream stream) { CanSave = true; - header = new Header(); - header.Read(new FileReader(stream),this); + BxlanHeader = new Header(); + BxlanHeader.Read(new FileReader(stream),this); } public void Unload() { @@ -84,20 +82,20 @@ namespace LayoutBXLYT } public void Save(System.IO.Stream stream) { - header.Write(new FileWriter(stream)); + BxlanHeader.Write(new FileWriter(stream)); } public LayoutEditor OpenForm() { LayoutEditor editor = new LayoutEditor(); editor.Dock = DockStyle.Fill; - editor.LoadBxlan(header); + editor.LoadBxlan(BxlanHeader); return editor; } public void FillEditor(Form control) { - ((LayoutEditor)control).LoadBxlan(header); + ((LayoutEditor)control).LoadBxlan(BxlanHeader); } public class Header : BxlanHeader @@ -109,7 +107,7 @@ namespace LayoutBXLYT //As of now this should be empty but just for future proofing private List UnknownSections = new List(); - public void Read(FileReader reader, BFLAN bflan) + public override void Read(FileReader reader, BXLAN bflan) { AnimationTag = new PAT1(); AnimationInfo = new PAI1(); @@ -125,7 +123,7 @@ namespace LayoutBXLYT ushort sectionCount = reader.ReadUInt16(); reader.ReadUInt16(); //Padding - FileInfo = bflan; + FileInfo = (IFileFormat)bflan; IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian; reader.SeekBegin(HeaderSize); @@ -155,7 +153,7 @@ namespace LayoutBXLYT } } - public void Write(FileWriter writer) + public override void Write(FileWriter writer) { writer.SetByteOrder(true); writer.WriteSignature(Magic); @@ -223,8 +221,12 @@ namespace LayoutBXLYT ushort groupCount = reader.ReadUInt16(); uint animNameOffset = reader.ReadUInt32(); uint groupNamesOffset = reader.ReadUInt32(); + if (header.VersionMajor >= 8) + reader.ReadUInt32(); //unk + StartFrame = reader.ReadInt16(); EndFrame = reader.ReadInt16(); + ChildBinding = reader.ReadBoolean(); UnknownData = reader.ReadBytes((int)(startPos + animNameOffset - reader.Position)); @@ -244,8 +246,12 @@ namespace LayoutBXLYT writer.Write((ushort)Groups.Count); writer.Write(uint.MaxValue); //animNameOffset writer.Write(uint.MaxValue); //groupNamesOffset - writer.Write(StartFrame); - writer.Write(EndFrame); + if (header.VersionMajor >= 8) + writer.Write(0); //unk + + writer.Write((ushort)StartFrame); + writer.Write((ushort)EndFrame); + writer.Write(ChildBinding); writer.Write(UnknownData); @@ -281,10 +287,11 @@ namespace LayoutBXLYT var numEntries = reader.ReadUInt16(); var entryOffsetTbl = reader.ReadUInt32(); + long texStart = reader.Position; var texOffsets = reader.ReadUInt32s(numTextures); for (int i = 0; i < numTextures; i++) { - reader.SeekBegin(startPos + texOffsets[i]); + reader.SeekBegin(texStart + texOffsets[i]); Textures.Add(reader.ReadZeroTerminatedString()); } @@ -377,7 +384,7 @@ namespace LayoutBXLYT { private uint Unknown {get;set;} - public PaiTag(FileReader reader, Header header, AnimationTarget target) + public PaiTag(FileReader reader, BxlanHeader header, AnimationTarget target) { if ((byte)target == 2) Unknown = reader.ReadUInt32(); //This doesn't seem to be included in the offsets to the entries (?) @@ -393,25 +400,25 @@ namespace LayoutBXLYT switch (Tag) { case "FLPA": - Entries.Add(new FLPATagEntry(reader, header)); + Entries.Add(new LPATagEntry(reader, header)); break; case "FLTS": - Entries.Add(new FLTSTagEntry(reader, header)); + Entries.Add(new LTSTagEntry(reader, header)); break; case "FLVI": - Entries.Add(new FLVITagEntry(reader, header)); + Entries.Add(new LVITagEntry(reader, header)); break; case "FLVC": - Entries.Add(new FLVCTagEntry(reader, header)); + Entries.Add(new LVCTagEntry(reader, header)); break; case "FLMC": - Entries.Add(new FLMCTagEntry(reader, header)); + Entries.Add(new LMCTagEntry(reader, header)); break; case "FLTP": - Entries.Add(new FLTPTagEntry(reader, header)); + Entries.Add(new LTPTagEntry(reader, header)); break; default: - Entries.Add(new PaiTagEntry(reader, header)); + Entries.Add(new BxlanPaiTagEntry(reader, header)); break; } } @@ -431,122 +438,9 @@ namespace LayoutBXLYT for (int i = 0; i < Entries.Count; i++) { writer.WriteUint32Offset(startPos + 8 + (i * 4), startPos); - ((PaiTagEntry)Entries[i]).Write(writer, header); + ((BxlanPaiTagEntry)Entries[i]).Write(writer, header); } } } - - public class PaiTagEntry : BxlanPaiTagEntry - { - public byte Unknown; - - public PaiTagEntry(FileReader reader, Header header) - { - long startPos = reader.Position; - Index = reader.ReadByte(); - AnimationTarget = reader.ReadByte(); - DataType = reader.ReadEnum(true); - Unknown = reader.ReadByte(); - var KeyFrameCount = reader.ReadUInt16(); - reader.ReadUInt16(); //Padding - uint keyFrameOffset = reader.ReadUInt32(); - - reader.SeekBegin(startPos + keyFrameOffset); - for (int i = 0; i < KeyFrameCount; i++) - KeyFrames.Add(new KeyFrame(reader, DataType)); - } - - public void Write(FileWriter writer, LayoutHeader header) - { - long startPos = writer.Position; - - writer.Write(Index); - writer.Write(AnimationTarget); - writer.Write(DataType, true); - writer.Write(Unknown); - writer.Write((ushort)KeyFrames.Count); - writer.Write((ushort)0); //padding - writer.Write(0); //key offset - - if (KeyFrames.Count > 0) - { - writer.WriteUint32Offset(startPos + 8, startPos); - for (int i = 0; i < KeyFrames.Count; i++) - KeyFrames[i].Write(writer, DataType); - } - } - } - - public class FLPATagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LPATarget Target - { - get { return (LPATarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLPATagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLTSTagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LTSTarget Target - { - get { return (LTSTarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLTSTagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLVITagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LVITarget Target - { - get { return (LVITarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLVITagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLVCTagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LVCTarget Target - { - get { return (LVCTarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLVCTagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLMCTagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LMCTarget Target - { - get { return (LMCTarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLMCTagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLTPTagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LTPTarget Target - { - get { return (LTPTarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLTPTagEntry(FileReader reader, Header header) : base(reader, header) { } - } } } diff --git a/File_Format_Library/FileFormats/Layout/CAFE/BFLYT.cs b/File_Format_Library/FileFormats/Layout/CAFE/BFLYT.cs index 2247a5c3..37bb361f 100644 --- a/File_Format_Library/FileFormats/Layout/CAFE/BFLYT.cs +++ b/File_Format_Library/FileFormats/Layout/CAFE/BFLYT.cs @@ -266,9 +266,6 @@ namespace LayoutBXLYT.Cafe private ushort ByteOrderMark; private ushort HeaderSize; - [Browsable(false)] - public Dictionary PaneLookup = new Dictionary(); - [Browsable(false)] public LYT1 LayoutInfo { get; set; } [Browsable(false)] @@ -367,6 +364,7 @@ namespace LayoutBXLYT.Cafe public void Read(FileReader reader, BFLYT bflyt) { + PaneLookup.Clear(); LayoutInfo = new LYT1(); TextureList = new TXL1(); MaterialList = new MAT1(); @@ -530,12 +528,6 @@ namespace LayoutBXLYT.Cafe } } - private void AddPaneToTable(BasePane pane) - { - if (!PaneLookup.ContainsKey(pane.Name)) - PaneLookup.Add(pane.Name, pane); - } - private void SetPane(BasePane pane, BasePane parentPane) { if (parentPane != null) @@ -692,7 +684,7 @@ namespace LayoutBXLYT.Cafe } } - public class TXT1 : PAN1 + public class TXT1 : PAN1, ITextPane { public override string Signature { get; } = "txt1"; @@ -701,8 +693,10 @@ namespace LayoutBXLYT.Cafe } - public string Text { get; set; } + [Browsable(false)] + public Toolbox.Library.Rendering.RenderableTex RenderableFont { get; set; } + [DisplayName("Horizontal Alignment"), CategoryAttribute("Font")] public OriginX HorizontalAlignment { get { return (OriginX)((TextAlignment >> 2) & 0x3); } @@ -713,6 +707,7 @@ namespace LayoutBXLYT.Cafe } } + [DisplayName("Vertical Alignment"), CategoryAttribute("Font")] public OriginX VerticalAlignment { get { return (OriginX)((TextAlignment) & 0x3); } @@ -723,49 +718,83 @@ namespace LayoutBXLYT.Cafe } } + [Browsable(false)] public ushort TextLength { get; set; } + [Browsable(false)] public ushort MaxTextLength { get; set; } + [Browsable(false)] public ushort MaterialIndex { get; set; } + [Browsable(false)] public ushort FontIndex { get; set; } + [TypeConverter(typeof(ExpandableObjectConverter))] + public BxlytMaterial Material { get; set; } + + [DisplayName("Text Alignment"), CategoryAttribute("Font")] public byte TextAlignment { get; set; } + + [DisplayName("Line Alignment"), CategoryAttribute("Font")] public LineAlign LineAlignment { get; set; } - + + [DisplayName("Italic Tilt"), CategoryAttribute("Font")] public float ItalicTilt { get; set; } + [DisplayName("Fore Color"), CategoryAttribute("Font")] public STColor8 FontForeColor { get; set; } + + [DisplayName("Back Color"), CategoryAttribute("Font")] public STColor8 FontBackColor { get; set; } + + [DisplayName("Font Size"), CategoryAttribute("Font")] public Vector2F FontSize { get; set; } + [DisplayName("Character Space"), CategoryAttribute("Font")] public float CharacterSpace { get; set; } + + [DisplayName("Line Space"), CategoryAttribute("Font")] public float LineSpace { get; set; } + [DisplayName("Shadow Position"), CategoryAttribute("Shadows")] public Vector2F ShadowXY { get; set; } + + [DisplayName("Shadow Size"), CategoryAttribute("Shadows")] public Vector2F ShadowXYSize { get; set; } + [DisplayName("Shadow Fore Color"), CategoryAttribute("Shadows")] public STColor8 ShadowForeColor { get; set; } + + [DisplayName("Shadow Back Color"), CategoryAttribute("Shadows")] public STColor8 ShadowBackColor { get; set; } + [DisplayName("Shadow Italic"), CategoryAttribute("Shadows")] public float ShadowItalic { get; set; } + [DisplayName("Text Box Name"), CategoryAttribute("Text Box")] public string TextBoxName { get; set; } + [DisplayName("Text"), CategoryAttribute("Text Box")] + public string Text { get; set; } + + [DisplayName("Per Character Transform"), CategoryAttribute("Font")] public bool PerCharTransform { get { return (_flags & 0x10) != 0; } set { _flags = value ? (byte)(_flags | 0x10) : unchecked((byte)(_flags & (~0x10))); } } + [DisplayName("Restricted Text Length"), CategoryAttribute("Font")] public bool RestrictedTextLengthEnabled { get { return (_flags & 0x2) != 0; } set { _flags = value ? (byte)(_flags | 0x2) : unchecked((byte)(_flags & (~0x2))); } } + [DisplayName("Enable Shadows"), CategoryAttribute("Font")] public bool ShadowEnabled { get { return (_flags & 1) != 0; } set { _flags = value ? (byte)(_flags | 1) : unchecked((byte)(_flags & (~1))); } } + [DisplayName("Font Name"), CategoryAttribute("Font")] public string FontName { get; set; } private byte _flags; @@ -796,6 +825,9 @@ namespace LayoutBXLYT.Cafe ShadowBackColor = STColor8.FromBytes(reader.ReadBytes(4)); ShadowItalic = reader.ReadSingle(); + if (MaterialIndex != ushort.MaxValue && header.MaterialList.Materials.Count > 0) + Material = header.MaterialList.Materials[MaterialIndex]; + if (FontIndex != ushort.MaxValue && header.FontList.Fonts.Count > 0) FontName = header.FontList.Fonts[FontIndex]; @@ -867,21 +899,6 @@ namespace LayoutBXLYT.Cafe writer.WriteString(TextBoxName); } } - - public enum BorderType : byte - { - Standard = 0, - DeleteBorder = 1, - RenderTwoCycles = 2, - }; - - public enum LineAlign : byte - { - Unspecified = 0, - Left = 1, - Center = 2, - Right = 3, - }; } public class WND1 : PAN1, IWindowPane @@ -1161,7 +1178,7 @@ namespace LayoutBXLYT.Cafe } } - public class BND1 : PAN1 + public class BND1 : PAN1, IBoundryPane { public override string Signature { get; } = "bnd1"; @@ -1635,7 +1652,7 @@ namespace LayoutBXLYT.Cafe } } - public class PIC1 : PAN1 + public class PIC1 : PAN1, IPicturePane { public override string Signature { get; } = "pic1"; @@ -1737,7 +1754,7 @@ namespace LayoutBXLYT.Cafe private byte origin; [DisplayName("Is Visible"), CategoryAttribute("Flags")] - public bool Visible + public override bool Visible { get { return (_flags1 & 0x1) == 0x1; } set { @@ -1958,21 +1975,26 @@ namespace LayoutBXLYT.Cafe public TevStage[] TevStages { get; set; } [DisplayName("Alpha Compare"), CategoryAttribute("Alpha")] + [TypeConverter(typeof(ExpandableObjectConverter))] public AlphaCompare AlphaCompare { get; set; } [DisplayName("Blend Mode"), CategoryAttribute("Blend")] + [TypeConverter(typeof(ExpandableObjectConverter))] public BlendMode BlendMode { get; set; } [DisplayName("Blend Mode Logic"), CategoryAttribute("Blend")] + [TypeConverter(typeof(ExpandableObjectConverter))] public BlendMode BlendModeLogic { get; set; } [DisplayName("Indirect Parameter"), CategoryAttribute("Texture")] + [TypeConverter(typeof(ExpandableObjectConverter))] public IndirectParameter IndParameter { get; set; } [DisplayName("Projection Texture Coord Parameters"), CategoryAttribute("Texture")] public ProjectionTexGenParam[] ProjTexGenParams { get; set; } [DisplayName("Font Shadow Parameters"), CategoryAttribute("Font")] + [TypeConverter(typeof(ExpandableObjectConverter))] public FontShadowParameter FontShadowParameter { get; set; } private uint flags; diff --git a/File_Format_Library/FileFormats/Layout/CAFE/BflytShader.cs b/File_Format_Library/FileFormats/Layout/CAFE/BflytShader.cs index b15812ec..f5da5d77 100644 --- a/File_Format_Library/FileFormats/Layout/CAFE/BflytShader.cs +++ b/File_Format_Library/FileFormats/Layout/CAFE/BflytShader.cs @@ -32,34 +32,102 @@ namespace LayoutBXLYT SetInt("textures1", 0); SetInt("textures2", 0); SetBool("ThresholdingAlphaInterpolation", false); + var rotationMatrix = Matrix4.Identity; + SetMatrix("rotationMatrix", ref rotationMatrix); + SetInt("numTevStages", 0); SetVec2("uvScale0", new Vector2(1,1)); SetFloat("uvRotate0", 0); SetVec2("uvTranslate0", new Vector2(0, 0)); + SetVec4("IndirectMat0", new Vector4(1, 1, 0, 0)); + SetVec4("IndirectMat1", new Vector4(1, 1, 0, 0)); + SetInt($"texCoords0GenType", 0); + SetInt($"texCoords0Source", 0); } - public void SetMaterials(Dictionary textures) + public void SetMaterials(BasePane pane, Dictionary textures) { - SetColor("whiteColor", material.WhiteColor.Color); - SetColor("blackColor", material.BlackColor.Color); + var paneRotate = pane.Rotate; + if (pane.animController.PaneSRT?.Count > 0) + { + foreach (var animItem in pane.animController.PaneSRT) + { + switch (animItem.Key) + { + case LPATarget.RotateX: + paneRotate.X = animItem.Value; break; + case LPATarget.RotateY: + paneRotate.Y = animItem.Value; break; + case LPATarget.RotateZ: + paneRotate.Z = animItem.Value; break; + } + } + } + + Matrix4 rotationX = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(paneRotate.X)); + Matrix4 rotationY = Matrix4.CreateRotationY(MathHelper.DegreesToRadians(paneRotate.Y)); + Matrix4 rotationZ = Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(paneRotate.Z)); + var rotationMatrix = rotationX * rotationY * rotationZ; + + SetMatrix("rotationMatrix", ref rotationMatrix); + + STColor8 WhiteColor = material.WhiteColor; + STColor8 BlackColor = material.BlackColor; + + foreach (var animItem in material.animController.MaterialColors) + { + switch (animItem.Key) + { + case LMCTarget.WhiteColorRed: + WhiteColor.R = (byte)animItem.Value; break; + case LMCTarget.WhiteColorGreen: + WhiteColor.G = (byte)animItem.Value; break; + case LMCTarget.WhiteColorBlue: + WhiteColor.B = (byte)animItem.Value; break; + case LMCTarget.WhiteColorAlpha: + WhiteColor.A = (byte)animItem.Value; break; + case LMCTarget.BlackColorRed: + BlackColor.R = (byte)animItem.Value; break; + case LMCTarget.BlackColorGreen: + BlackColor.G = (byte)animItem.Value; break; + case LMCTarget.BlackColorBlue: + BlackColor.B = (byte)animItem.Value; break; + case LMCTarget.BlackColorAlpha: + BlackColor.A = (byte)animItem.Value; break; + } + } + + SetColor("whiteColor", WhiteColor.Color); + SetColor("blackColor", BlackColor.Color); SetInt("debugShading", (int)Runtime.LayoutEditor.Shading); SetInt("numTextureMaps", material.TextureMaps.Length); SetVec2("uvScale0", new Vector2(1, 1)); SetFloat("uvRotate0", 0); SetVec2("uvTranslate0", new Vector2(0, 0)); SetInt("flipTexture", 0); + SetInt("numTevStages", material.TevStages.Length); SetBool("ThresholdingAlphaInterpolation", material.ThresholdingAlphaInterpolation); + SetVec4("IndirectMat0", new Vector4(1, 1, 0, 0)); + SetVec4("IndirectMat1", new Vector4(1, 1, 0, 0)); + SetInt("tevTexMode", 0); + SetInt($"texCoords0GenType", 0); + SetInt($"texCoords0Source", 0); BindTextureUniforms(); int id = 1; for (int i = 0; i < material.TextureMaps.Length; i++) { - if (textures.ContainsKey(material.TextureMaps[i].Name)) + string TexName = material.TextureMaps[i].Name; + + if (material.animController.TexturePatterns.ContainsKey((LTPTarget)i)) + TexName = material.animController.TexturePatterns[(LTPTarget)i]; + + if (textures.ContainsKey(TexName)) { GL.ActiveTexture(TextureUnit.Texture0 + id); SetInt($"textures{i}", id); - bool isBinded = BxlytToGL.BindGLTexture(material.TextureMaps[i], textures[material.TextureMaps[i].Name]); + bool isBinded = BxlytToGL.BindGLTexture(material.TextureMaps[i], textures[TexName]); if (isBinded) SetInt($"hasTexture{i}", 1); @@ -67,13 +135,82 @@ namespace LayoutBXLYT } } + for (int i = 0; i < material.TexCoords?.Length; i++) + { + SetInt($"texCoords{i}GenType", (int)material.TexCoords[i].GenType); + SetInt($"texCoords{i}Source", (int)material.TexCoords[i].Source); + } + + for (int i = 0; i < material.TevStages?.Length; i++) + { + SetInt($"tevStage{i}RGB", (int)material.TevStages[i].ColorMode); + SetInt($"tevStage{i}A", (int)material.TevStages[i].AlphaMode); + } if (material.TextureTransforms.Length > 0) { var transform = material.TextureTransforms[0]; - SetVec2("uvScale0",new Vector2(transform.Scale.X, transform.Scale.Y)); - SetFloat("uvRotate0", transform.Rotate); - SetVec2("uvTranslate0",new Vector2(transform.Translate.X, transform.Translate.Y)); + var scale = transform.Scale; + var rotate = transform.Rotate; + var translate = transform.Translate; + + foreach (var animItem in material.animController.TextureSRTS) + { + switch (animItem.Key) + { + case LTSTarget.ScaleS: scale.X = animItem.Value; break; + case LTSTarget.ScaleT: scale.Y = animItem.Value; break; + case LTSTarget.Rotate: rotate = animItem.Value; break; + case LTSTarget.TranslateS: translate.X = animItem.Value; break; + case LTSTarget.TranslateT: translate.Y = animItem.Value; break; + } + } + + SetVec2("uvScale0", new Vector2(scale.X, scale.Y)); + SetFloat("uvRotate0", rotate); + SetVec2("uvTranslate0", new Vector2(translate.X, translate.Y)); + } + + + GL.Enable(EnableCap.Blend); + GL.Enable(EnableCap.AlphaTest); + GL.AlphaFunc(AlphaFunction.Always, 0f); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + GL.BlendEquation(BlendEquationMode.FuncAdd); + GL.Disable(EnableCap.ColorLogicOp); + GL.LogicOp(LogicOp.Noop); + + if (material.BlendMode != null) + { + var srcFactor = BxlytToGL.ConvertBlendFactor(material.BlendMode.SourceFactor); + var destFactor = BxlytToGL.ConvertBlendFactor(material.BlendMode.DestFactor); + var blendOp = BxlytToGL.ConvertBlendOperation(material.BlendMode.BlendOp); + var logicOp = BxlytToGL.ConvertLogicOperation(material.BlendMode.LogicOp); + if (logicOp != LogicOp.Noop) + GL.Enable(EnableCap.ColorLogicOp); + + GL.BlendFunc(srcFactor, destFactor); + GL.BlendEquation(blendOp); + GL.LogicOp(logicOp); + } + if (material.BlendModeLogic != null) + { + var srcFactor = BxlytToGL.ConvertBlendFactor(material.BlendModeLogic.SourceFactor); + var destFactor = BxlytToGL.ConvertBlendFactor(material.BlendModeLogic.DestFactor); + var blendOp = BxlytToGL.ConvertBlendOperation(material.BlendModeLogic.BlendOp); + var logicOp = BxlytToGL.ConvertLogicOperation(material.BlendModeLogic.LogicOp); + if (logicOp != LogicOp.Noop) + GL.Enable(EnableCap.ColorLogicOp); + + GL.BlendFunc(srcFactor, destFactor); + GL.BlendEquation(blendOp); + GL.LogicOp(logicOp); + } + + if (material.AlphaCompare != null) + { + var alphaFunc = BxlytToGL.ConvertAlphaFunc(material.AlphaCompare.CompareMode); + GL.AlphaFunc(alphaFunc, material.AlphaCompare.Value); } } diff --git a/File_Format_Library/FileFormats/Layout/CAFE/Materials/AlphaCompare.cs b/File_Format_Library/FileFormats/Layout/CAFE/Materials/AlphaCompare.cs index 042651ca..31336656 100644 --- a/File_Format_Library/FileFormats/Layout/CAFE/Materials/AlphaCompare.cs +++ b/File_Format_Library/FileFormats/Layout/CAFE/Materials/AlphaCompare.cs @@ -4,19 +4,19 @@ namespace LayoutBXLYT.Cafe { public class AlphaCompare { - public byte CompareMode { get; set; } - public uint Value { get; set; } + public GfxAlphaFunction CompareMode { get; set; } + public float Value { get; set; } public AlphaCompare(FileReader reader, BFLYT.Header header) { - CompareMode = reader.ReadByte(); + CompareMode = reader.ReadEnum(false); reader.ReadBytes(0x3); - Value = reader.ReadUInt32(); + Value = reader.ReadSingle(); } public void Write(FileWriter writer) { - writer.Write(CompareMode); + writer.Write(CompareMode, false); writer.Seek(3); writer.Write(Value); } diff --git a/File_Format_Library/FileFormats/Layout/CAFE/Materials/IndirectParameter.cs b/File_Format_Library/FileFormats/Layout/CAFE/Materials/IndirectParameter.cs index 2b87d79d..b2017338 100644 --- a/File_Format_Library/FileFormats/Layout/CAFE/Materials/IndirectParameter.cs +++ b/File_Format_Library/FileFormats/Layout/CAFE/Materials/IndirectParameter.cs @@ -2,12 +2,8 @@ namespace LayoutBXLYT.Cafe { - public class IndirectParameter + public class IndirectParameter : BxlytIndTextureTransform { - public float Rotation { get; set; } - public float ScaleX { get; set; } - public float ScaleY { get; set; } - public IndirectParameter(FileReader reader, BFLYT.Header header) { Rotation = reader.ReadSingle(); diff --git a/File_Format_Library/FileFormats/Layout/CAFE/Materials/TevStage.cs b/File_Format_Library/FileFormats/Layout/CAFE/Materials/TevStage.cs index bc2343fd..b0989ec9 100644 --- a/File_Format_Library/FileFormats/Layout/CAFE/Materials/TevStage.cs +++ b/File_Format_Library/FileFormats/Layout/CAFE/Materials/TevStage.cs @@ -4,22 +4,53 @@ namespace LayoutBXLYT.Cafe { public class TevStage { - public TevMode RGBMode { get; set; } + public TevMode ColorMode { get; set; } public TevMode AlphaMode { get; set; } - public ushort unk { get; set; } + + private byte colorFlags; + private byte alphaFlags; public TevStage(FileReader reader, BFLYT.Header header) { - RGBMode = (TevMode)reader.ReadByte(); - AlphaMode = (TevMode)reader.ReadByte(); - unk = reader.ReadUInt16(); + colorFlags = reader.ReadByte(); + alphaFlags = reader.ReadByte(); + reader.ReadUInt16(); //padding + + ColorMode = (TevMode)colorFlags; + AlphaMode = (TevMode)colorFlags; + + /* TevSource srcRGB0 = (TevSource)Bit.ExtractBits8(colorFlags, 4, 0); + TevSource srcRGB1 = (TevSource)Bit.ExtractBits8(colorFlags, 4, 4); + TevSource srcRGB2 = (TevSource)Bit.ExtractBits8(colorFlags, 4, 8); + TevColorOp opRGB0 = (TevColorOp)Bit.ExtractBits8(colorFlags, 4, 12); + TevColorOp opRGB1 = (TevColorOp)Bit.ExtractBits8(colorFlags, 4, 16); + TevColorOp opRGB2 = (TevColorOp)Bit.ExtractBits8(colorFlags, 4, 20); + + ColorSources = new TevSource[] { srcRGB0, srcRGB1, srcRGB2 }; + ColorOperators = new TevColorOp[] { opRGB0, opRGB1, opRGB2 }; + ColorMode = (TevMode)Bit.ExtractBits8(colorFlags, 4, 24); + ColorScale = (TevScale)Bit.ExtractBits8(colorFlags, 2, 28); + ColorSavePrevReg = Bit.ExtractBits8(colorFlags, 1, 30) == 1; + + TevSource srcAlpha0 = (TevSource)Bit.ExtractBits8(alphaFlags, 4, 0); + TevSource srcAlpha1 = (TevSource)Bit.ExtractBits8(alphaFlags, 4, 4); + TevSource srcAlpha2 = (TevSource)Bit.ExtractBits8(alphaFlags, 4, 8); + TevAlphaOp opAlpha0 = (TevAlphaOp)Bit.ExtractBits8(alphaFlags, 4, 12); + TevAlphaOp opAlpha1 = (TevAlphaOp)Bit.ExtractBits8(alphaFlags, 4, 16); + TevAlphaOp opAlpha2 = (TevAlphaOp)Bit.ExtractBits8(alphaFlags, 4, 20); + + AlphaSources = new TevSource[] { srcAlpha0, srcAlpha1, srcAlpha2 }; + AlphaOperators = new TevAlphaOp[] { opAlpha0, opAlpha1, opAlpha2 }; + AlphaMode = (TevMode)Bit.ExtractBits8(alphaFlags, 4, 24); + AlphaScale = (TevScale)Bit.ExtractBits8(alphaFlags, 2, 28); + AlphaSavePrevReg = Bit.ExtractBits8(alphaFlags, 1, 30) == 1;*/ } public void Write(FileWriter writer) { - writer.Write(RGBMode, false); - writer.Write(AlphaMode, false); - writer.Write(unk); + writer.Write(colorFlags); + writer.Write(alphaFlags); + writer.Write((ushort)0); } } } diff --git a/File_Format_Library/FileFormats/Layout/CAFE/Materials/TextureTransform.cs b/File_Format_Library/FileFormats/Layout/CAFE/Materials/TextureTransform.cs index 379e0658..3a9b57b4 100644 --- a/File_Format_Library/FileFormats/Layout/CAFE/Materials/TextureTransform.cs +++ b/File_Format_Library/FileFormats/Layout/CAFE/Materials/TextureTransform.cs @@ -3,12 +3,8 @@ using Syroot.Maths; namespace LayoutBXLYT.Cafe { - public class TextureTransform + public class TextureTransform : BxlytTextureTransform { - public Vector2F Translate { get; set; } - public float Rotate { get; set; } - public Vector2F Scale { get; set; } - public TextureTransform() { } public TextureTransform(FileReader reader) diff --git a/File_Format_Library/FileFormats/Layout/CTR/BCLYT.cs b/File_Format_Library/FileFormats/Layout/CTR/BCLYT.cs index 5e191aee..c3cdf3c5 100644 --- a/File_Format_Library/FileFormats/Layout/CTR/BCLYT.cs +++ b/File_Format_Library/FileFormats/Layout/CTR/BCLYT.cs @@ -217,6 +217,7 @@ namespace LayoutBXLYT { IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian; + PaneLookup.Clear(); LayoutInfo = new LYT1(); TextureList = new TXL1(); MaterialList = new MAT1(); @@ -270,6 +271,8 @@ namespace LayoutBXLYT break; case "pan1": var panel = new PAN1(reader); + AddPaneToTable(panel); + if (!setRoot) { RootPane = panel; @@ -281,30 +284,36 @@ namespace LayoutBXLYT break; case "pic1": var picturePanel = new PIC1(reader, this); + AddPaneToTable(picturePanel); SetPane(picturePanel, parentPane); currentPane = picturePanel; break; case "txt1": var textPanel = new TXT1(reader); + AddPaneToTable(textPanel); SetPane(textPanel, parentPane); currentPane = textPanel; break; case "bnd1": var boundsPanel = new BND1(reader); + AddPaneToTable(boundsPanel); SetPane(boundsPanel, parentPane); currentPane = boundsPanel; break; case "prt1": var partsPanel = new PRT1(reader); + AddPaneToTable(partsPanel); SetPane(partsPanel, parentPane); currentPane = partsPanel; break; case "wnd1": var windowPanel = new WND1(reader); + AddPaneToTable(windowPanel); + SetPane(windowPanel, parentPane); currentPane = windowPanel; break; @@ -551,7 +560,7 @@ namespace LayoutBXLYT } } - public class BND1 : PAN1 + public class BND1 : PAN1, IBoundryPane { public BND1() : base() { @@ -625,7 +634,7 @@ namespace LayoutBXLYT } } - public class PIC1 : PAN1 + public class PIC1 : PAN1, IPicturePane { [DisplayName("Texture Coordinates"), CategoryAttribute("Texture")] public TexCoord[] TexCoords { get; set; } @@ -710,7 +719,7 @@ namespace LayoutBXLYT { private byte _flags1; - public bool Visible + public override bool Visible { get { return (_flags1 & 0x1) == 0x1; } set { diff --git a/File_Format_Library/FileFormats/Layout/CTR/BclytShader.cs b/File_Format_Library/FileFormats/Layout/CTR/BclytShader.cs index 90c1055d..c72baedb 100644 --- a/File_Format_Library/FileFormats/Layout/CTR/BclytShader.cs +++ b/File_Format_Library/FileFormats/Layout/CTR/BclytShader.cs @@ -35,10 +35,22 @@ namespace LayoutBXLYT SetVec2("uvScale0", new Vector2(1, 1)); SetFloat("uvRotate0", 0); SetVec2("uvTranslate0", new Vector2(0, 0)); + + var rotationMatrix = Matrix4.Identity; + SetMatrix("rotationMatrix", ref rotationMatrix); + SetInt($"texCoords0GenType", 0); + SetInt($"texCoords0Source", 0); } - public void SetMaterials(Dictionary textures) + public void SetMaterials(BasePane pane, Dictionary textures) { + Matrix4 rotationX = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(pane.Rotate.X)); + Matrix4 rotationY = Matrix4.CreateRotationY(MathHelper.DegreesToRadians(pane.Rotate.Y)); + Matrix4 rotationZ = Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(pane.Rotate.Z)); + var rotationMatrix = rotationX * rotationY * rotationZ; + + SetMatrix("rotationMatrix", ref rotationMatrix); + SetColor("whiteColor", material.TevConstantColors[0].Color); SetColor("blackColor", material.TevColor.Color); SetInt("debugShading", (int)Runtime.LayoutEditor.Shading); @@ -48,6 +60,8 @@ namespace LayoutBXLYT SetVec2("uvTranslate0", new Vector2(0, 0)); SetInt("flipTexture", 0); SetBool("ThresholdingAlphaInterpolation", material.ThresholdingAlphaInterpolation); + SetInt($"texCoords0GenType", 0); + SetInt($"texCoords0Source", 0); BindTextureUniforms(); diff --git a/File_Format_Library/FileFormats/Layout/Common.cs b/File_Format_Library/FileFormats/Layout/Common.cs index 16a50491..d0f582d9 100644 --- a/File_Format_Library/FileFormats/Layout/Common.cs +++ b/File_Format_Library/FileFormats/Layout/Common.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Syroot.Maths; using Toolbox.Library.IO; +using Toolbox.Library.Animations; using Toolbox.Library; using WeifenLuo.WinFormsUI.Docking; using System.ComponentModel; @@ -13,6 +14,12 @@ namespace LayoutBXLYT { public class BasePane : SectionCommon { + [Browsable(false)] + public PaneAnimController animController = new PaneAnimController(); + + [DisplayName("Is Visible"), CategoryAttribute("Flags")] + public virtual bool Visible { get; set; } + public bool IsRoot = false; public bool ParentIsRoot @@ -114,7 +121,15 @@ namespace LayoutBXLYT public CustomRectangle CreateRectangle() { //Do origin transforms - var transformed = TransformOrientation((int)Width, (int)Height, originX, originY); + var transformed = new Vector4(); + int paneWidth = (int)Width; + int paneHeight = (int)Height; + if (animController.PaneSRT.ContainsKey(LPATarget.SizeX)) + paneWidth = (int)animController.PaneSRT[LPATarget.SizeX]; + if (animController.PaneSRT.ContainsKey(LPATarget.SizeY)) + paneHeight = (int)animController.PaneSRT[LPATarget.SizeY]; + + transformed = TransformOrientation(paneWidth, paneHeight, originX, originY); var parentTransform = ParentOriginTransform(transformed); return new CustomRectangle( @@ -219,6 +234,47 @@ namespace LayoutBXLYT else return false; } + + public BasePane SearchPane(string name) + { + if (Name == name) + return this; + + foreach (var child in Childern) + { + var matchPane = child.SearchPane(name); + if (matchPane != null) return matchPane; + } + + return null; + } + } + + public class VertexColorHelper + { + public static System.Drawing.Color Mix(System.Drawing.Color colorA, System.Drawing.Color colorB, float value) + { + byte R = (byte)InterpolationHelper.Lerp(colorA.R, colorB.R, value); + byte G = (byte)InterpolationHelper.Lerp(colorA.G, colorB.G, value); + byte B = (byte)InterpolationHelper.Lerp(colorA.B, colorB.B, value); + byte A = (byte)InterpolationHelper.Lerp(colorA.A, colorB.A, value); + return System.Drawing.Color.FromArgb(A, R, G, B); + } + } + + + public class PaneAnimController + { + public Dictionary PaneSRT = new Dictionary(); + public Dictionary PaneVertexColors = new Dictionary(); + public bool Visibile = true; + + public void ResetAnim() + { + Visibile = true; + PaneSRT.Clear(); + PaneVertexColors.Clear(); + } } public enum FilterMode @@ -336,12 +392,6 @@ namespace LayoutBXLYT Material = 1 } - public enum KeyType : byte - { - Uin16 = 1, - Float = 2, - } - public enum LPATarget : byte { TranslateX = 0x00, @@ -353,7 +403,7 @@ namespace LayoutBXLYT ScaleX = 0x06, ScaleY = 0x07, SizeX = 0x08, - SizeZ = 0x09, + SizeY = 0x09, } public enum LTSTarget : byte @@ -397,7 +447,9 @@ namespace LayoutBXLYT public enum LTPTarget : byte { - Image = 0x00, + Image1 = 0x00, + Image2 = 0x01, //Unsure if mutliple are used but just in case + Image3 = 0x02, } public enum LMCTarget : byte @@ -485,6 +537,18 @@ namespace LayoutBXLYT Rotate270 = 5 } + public enum GfxAlphaFunction : byte + { + Never = 0, + Less = 1, + LessOrEqual = 2, + Equal = 3, + NotEqual = 4, + GreaterOrEqual = 5, + Greater = 6, + Always = 7, + } + public enum TevMode : byte { Replace, @@ -501,6 +565,100 @@ namespace LayoutBXLYT EachIndirect, } + + public enum TevScale + { + Scale1, + Scale2, + Scale4 + } + + public enum TevSource + { + Tex0 = 0, + Tex1 = 1, + Tex2 = 2, + Tex3 = 3, + Constant = 4, + Primary = 5, + Previous = 6, + Register = 7 + } + public enum TevColorOp + { + RGB = 0, + InvRGB = 1, + Alpha = 2, + InvAlpha = 3, + RRR = 4, + InvRRR = 5, + GGG = 6, + InvGGG = 7, + BBB = 8, + InvBBB = 9 + } + public enum TevAlphaOp + { + Alpha = 0, + InvAlpha = 1, + R = 2, + InvR = 3, + G = 4, + InvG = 5, + B = 6, + InvB = 7 + } + + public interface IPicturePane + { + + } + + public interface IBoundryPane + { + + } + + public interface ITextPane + { + string Text { get; set; } + OriginX HorizontalAlignment { get; set; } + OriginX VerticalAlignment { get; set; } + + ushort TextLength { get; set; } + ushort MaxTextLength { get; set; } + + BxlytMaterial Material { get; set; } + Toolbox.Library.Rendering.RenderableTex RenderableFont { get; set; } + + byte TextAlignment { get; set; } + LineAlign LineAlignment { get; set; } + + float ItalicTilt { get; set; } + + STColor8 FontForeColor { get; set; } + STColor8 FontBackColor { get; set; } + Vector2F FontSize { get; set; } + + float CharacterSpace { get; set; } + float LineSpace { get; set; } + + Vector2F ShadowXY { get; set; } + Vector2F ShadowXYSize { get; set; } + + STColor8 ShadowForeColor { get; set; } + STColor8 ShadowBackColor { get; set; } + + float ShadowItalic { get; set; } + + string TextBoxName { get; set; } + + bool PerCharTransform { get; set; } + bool RestrictedTextLengthEnabled { get; set; } + bool ShadowEnabled { get; set; } + string FontName { get; set; } + } + public interface IWindowPane { bool UseOneMaterialForAll { get; set; } @@ -523,6 +681,11 @@ namespace LayoutBXLYT List WindowFrames { get; set; } } + public class BXLAN + { + public BxlanHeader BxlanHeader; + } + public class BxlytWindowContent { public STColor8 ColorTopLeft { get; set; } @@ -637,6 +800,24 @@ namespace LayoutBXLYT { public BxlanPAT1 AnimationTag; public BxlanPAI1 AnimationInfo; + + public virtual void Read(FileReader reader, BXLAN header) + { + + } + + public virtual void Write(FileWriter writer) + { + + } + + private LytAnimation animation; + public LytAnimation ToGenericAnimation(BxlytHeader parentLayout) + { + if (animation == null) + animation = new LytAnimation(this, parentLayout); + return animation; + } } public class BxlanPAT1 : SectionCommon @@ -728,6 +909,85 @@ namespace LayoutBXLYT }; } + + public class LPATagEntry : BxlanPaiTagEntry + { + public override string TargetName => Target.ToString(); + [DisplayName("Target"), CategoryAttribute("Tag")] + public LPATarget Target + { + get { return (LPATarget)AnimationTarget; } + set { AnimationTarget = (byte)value; } + } + + public LPATagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { } + } + + public class LTSTagEntry : BxlanPaiTagEntry + { + public override string TargetName => Target.ToString(); + [DisplayName("Target"), CategoryAttribute("Tag")] + public LTSTarget Target + { + get { return (LTSTarget)AnimationTarget; } + set { AnimationTarget = (byte)value; } + } + + public LTSTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { } + } + + public class LVITagEntry : BxlanPaiTagEntry + { + public override string TargetName => Target.ToString(); + [DisplayName("Target"), CategoryAttribute("Tag")] + public LVITarget Target + { + get { return (LVITarget)AnimationTarget; } + set { AnimationTarget = (byte)value; } + } + + public LVITagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { } + } + + public class LVCTagEntry : BxlanPaiTagEntry + { + public override string TargetName => Target.ToString(); + [DisplayName("Target"), CategoryAttribute("Tag")] + public LVCTarget Target + { + get { return (LVCTarget)AnimationTarget; } + set { AnimationTarget = (byte)value; } + } + + public LVCTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { } + } + + public class LMCTagEntry : BxlanPaiTagEntry + { + public override string TargetName => Target.ToString(); + [DisplayName("Target"), CategoryAttribute("Tag")] + public LMCTarget Target + { + get { return (LMCTarget)AnimationTarget; } + set { AnimationTarget = (byte)value; } + } + + public LMCTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { } + } + + public class LTPTagEntry : BxlanPaiTagEntry + { + public override string TargetName => Target.ToString(); + [DisplayName("Target"), CategoryAttribute("Tag")] + public LTPTarget Target + { + get { return (LTPTarget)AnimationTarget; } + set { AnimationTarget = (byte)value; } + } + + public LTPTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { } + } + public class BxlanPaiTagEntry { [Browsable(false)] @@ -741,49 +1001,110 @@ namespace LayoutBXLYT [DisplayName("Index"), CategoryAttribute("Tag")] public byte Index { get; set; } - [DisplayName("Data Type"), CategoryAttribute("Tag")] - public KeyType DataType { get; set; } + [DisplayName("Curve Type"), CategoryAttribute("Tag")] + public CurveType CurveType { get; set; } public List KeyFrames = new List(); + + + public BxlanPaiTagEntry(FileReader reader, BxlanHeader header) + { + long startPos = reader.Position; + Index = reader.ReadByte(); + AnimationTarget = reader.ReadByte(); + CurveType = reader.ReadEnum(true); + reader.ReadByte(); //padding + var KeyFrameCount = reader.ReadUInt16(); + reader.ReadUInt16(); //Padding + uint keyFrameOffset = reader.ReadUInt32(); + + reader.SeekBegin(startPos + keyFrameOffset); + for (int i = 0; i < KeyFrameCount; i++) + KeyFrames.Add(new KeyFrame(reader, CurveType)); + } + + public void Write(FileWriter writer, LayoutHeader header) + { + long startPos = writer.Position; + + writer.Write(Index); + writer.Write(AnimationTarget); + writer.Write(CurveType, true); + writer.Write((byte)0); //padding + writer.Write((ushort)KeyFrames.Count); + writer.Write((ushort)0); //padding + writer.Write(0); //key offset + + if (KeyFrames.Count > 0) + { + writer.WriteUint32Offset(startPos + 8, startPos); + for (int i = 0; i < KeyFrames.Count; i++) + KeyFrames[i].Write(writer, CurveType); + } + } + } + + public enum BorderType : byte + { + Standard = 0, + DeleteBorder = 1, + RenderTwoCycles = 2, + }; + + public enum LineAlign : byte + { + Unspecified = 0, + Left = 1, + Center = 2, + Right = 3, + }; + + public enum CurveType : byte + { + Constant, + Step, + Hermite, } public class KeyFrame { - [DisplayName("Blend"), CategoryAttribute("Key Frame")] - public float Blend { get; set; } + [DisplayName("Slope"), CategoryAttribute("Key Frame")] + public float Slope { get; set; } [DisplayName("Frame"), CategoryAttribute("Key Frame")] public float Frame { get; set; } [DisplayName("Value"), CategoryAttribute("Key Frame")] public float Value { get; set; } - public KeyFrame(FileReader reader, KeyType DataType) + public KeyFrame(FileReader reader, CurveType curveType) { - Frame = reader.ReadSingle(); - switch (DataType) + switch (curveType) { - case KeyType.Float: + case CurveType.Hermite: + Frame = reader.ReadSingle(); Value = reader.ReadSingle(); - Blend = reader.ReadSingle(); + Slope = reader.ReadSingle(); break; - case KeyType.Uin16: - Value = (float)reader.ReadInt16(); - Blend = (float)reader.ReadInt16(); + default: + Frame = reader.ReadSingle(); + Value = reader.ReadInt16(); + reader.ReadInt16(); //padding break; } } - public void Write(FileWriter writer, KeyType DataType) + public void Write(FileWriter writer, CurveType curveType) { - writer.Write(Frame); - switch (DataType) + switch (curveType) { - case KeyType.Float: + case CurveType.Hermite: + writer.Write(Frame); writer.Write(Value); - writer.Write(Blend); + writer.Write(Slope); break; - case KeyType.Uin16: + default: + writer.Write(Frame); writer.Write((ushort)Value); - writer.Write((ushort)Blend); + writer.Write((ushort)0); break; } } @@ -791,6 +1112,9 @@ namespace LayoutBXLYT public class BxlytHeader : LayoutHeader { + [Browsable(false)] + public Dictionary PaneLookup = new Dictionary(); + [Browsable(false)] public BasePane RootPane { get; set; } @@ -811,10 +1135,30 @@ namespace LayoutBXLYT { return new List(); } + + public BxlytMaterial SearchMaterial(string name) + { + var materials = GetMaterials(); + for (int i = 0; i < materials.Count; i++) + { + if (materials[i].Name == name) + return materials[i]; + } + return null; + } + + public void AddPaneToTable(BasePane pane) + { + if (!PaneLookup.ContainsKey(pane.Name)) + PaneLookup.Add(pane.Name, pane); + } } public class BxlytMaterial { + [Browsable(false)] + public MaterialAnimController animController = new MaterialAnimController(); + [DisplayName("Name"), CategoryAttribute("General")] public virtual string Name { get; set; } @@ -828,6 +1172,36 @@ namespace LayoutBXLYT public BxlytTextureRef[] TextureMaps { get; set; } } + public class MaterialAnimController + { + public Dictionary MaterialColors = new Dictionary(); + public Dictionary TexturePatterns = new Dictionary(); + public Dictionary TextureSRTS = new Dictionary(); + public Dictionary IndTextureSRTS = new Dictionary(); + + public void ResetAnim() + { + MaterialColors.Clear(); + TexturePatterns.Clear(); + TextureSRTS.Clear(); + IndTextureSRTS.Clear(); + } + } + + public class BxlytTextureTransform + { + public Vector2F Translate { get; set; } + public float Rotate { get; set; } + public Vector2F Scale { get; set; } + } + + public class BxlytIndTextureTransform + { + public float Rotation { get; set; } + public float ScaleX { get; set; } + public float ScaleY { get; set; } + } + public class SectionCommon { [Browsable(false)] @@ -880,7 +1254,12 @@ namespace LayoutBXLYT } } + public class LayoutControlDocked : Toolbox.Library.Forms.STUserControl + { + public DockContent DockContent; + public DockPane Pane => DockContent?.Pane; + } public class LayoutDocked : DockContent { diff --git a/File_Format_Library/FileFormats/Layout/LayoutCustomPaneMapper.cs b/File_Format_Library/FileFormats/Layout/LayoutCustomPaneMapper.cs new file mode 100644 index 00000000..3e8e1bb1 --- /dev/null +++ b/File_Format_Library/FileFormats/Layout/LayoutCustomPaneMapper.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library; +using FirstPlugin; +using LayoutBXLYT.Cafe; + +namespace LayoutBXLYT +{ + /// + /// A mapper which applies hard coded panes to the proper place + /// + public class LayoutCustomPaneMapper + { + private bool Loaded = false; + //MK8 character select + public void LoadMK8DCharaSelect(Dictionary textures, BxlytHeader header) + { + var archive = header.FileInfo.IFileInfo.ArchiveParent; + + if (archive == null || !header.PaneLookup.ContainsKey("L_Chara_00")) + return; + + if (!Loaded) + { + var parentArchive = ((IFileFormat)archive).IFileInfo.ArchiveParent; + if (parentArchive == null) return; + + foreach (var files in parentArchive.Files) + { + if (files.FileName.Contains("mn_L_CharaIcon_00")) + { + var charIconSzs = (IArchiveFile)files.OpenFile(); + foreach (var file in charIconSzs.Files) + { + if (Utils.GetExtension(file.FileName) == ".bntx") + { + var bntx = (BNTX)file.OpenFile(); + foreach (var tex in bntx.Textures) + if (!textures.ContainsKey(tex.Key)) + { + Console.WriteLine("Adding icon " + tex.Key); + textures.Add(tex.Key, tex.Value); + } + + Loaded = true; + } + } + } + } + } + + //Map to all icons + for (int i = 0; i < 42; i++) + { + Console.WriteLine($"L_Chara_{i.ToString("00")}"); + if (!header.PaneLookup.ContainsKey($"L_Chara_{i.ToString("00")}")) + continue; + + var partPane = (Cafe.BFLYT.PRT1)header.PaneLookup[$"L_Chara_{i.ToString("00")}"]; + var charPane = partPane.GetExternalPane(); + var iconPane = charPane.SearchPane("P_Chara_00"); + if (iconPane == null) return; + + var mat = ((BFLYT.PIC1)iconPane).Material; + + string textureName = "Mario"; + switch (i) + { + case 0: textureName = "Mario"; break; + case 1: textureName = "Luigi"; break; + case 2: textureName = "Peach"; break; + case 3: textureName = "Daisy"; break; + case 4: textureName = "Rosetta"; break; + case 5: textureName = "TanukiMario"; break; + case 6: textureName = "CatPeach"; break; + case 7: textureName = "Yoshi00"; break; + case 8: textureName = "Kinopio"; break; //Toad + case 9: textureName = "Nokonoko"; break; //Koopa + case 10: textureName = "Heyho00"; break; + case 11: textureName = "Jugemu"; break; + case 12: textureName = "Kinopico"; break; //Toadette + case 13: textureName = "KingTeresa"; break; + case 14: textureName = "BbMario"; break; + case 15: textureName = "BbLuigi"; break; + case 16: textureName = "BbPeach"; break; + case 17: textureName = "BbDaisy"; break; + case 18: textureName = "BbRosetta"; break; + case 19: textureName = "MetalMario"; break; + case 20: textureName = "PGoldPeach"; break; + case 21: textureName = "Wario"; break; + case 22: textureName = "Waluigi"; break; + case 23: textureName = "DK"; break; + case 24: textureName = "Koopa"; break; //Bowser + case 25: textureName = "Karon"; break; + case 26: textureName = "KoopaJr"; break; + case 27: textureName = "HoneKoopa"; break; + case 28: textureName = "Lemmy"; break; + case 29: textureName = "Larry"; break; + case 30: textureName = "Wendy"; break; + case 31: textureName = "Ludwig"; break; + case 32: textureName = "Iggy"; break; + case 33: textureName = "Roy"; break; + case 34: textureName = "Morton"; break; + case 35: textureName = "SplatoonGirl00"; break; + case 36: textureName = "SplatoonBoy00"; break; + case 37: textureName = "Link"; break; + case 38: textureName = "AnimalBoyA"; break; + case 39: textureName = "AnimalGirlA"; break; + case 40: textureName = "Shizue"; break; + case 41: textureName = "MiiAmiibo"; break; + } + + textureName = $"tc_Chara_{textureName}^l"; + + if (!mat.animController.TexturePatterns.ContainsKey(LTPTarget.Image1)) + mat.animController.TexturePatterns.Add(LTPTarget.Image1, textureName); + else + mat.animController.TexturePatterns[LTPTarget.Image1] = textureName; + + } + } + } +} diff --git a/File_Format_Library/FileFormats/Layout/RenderablePane.cs b/File_Format_Library/FileFormats/Layout/RenderablePane.cs index baf9e68c..9b30c504 100644 --- a/File_Format_Library/FileFormats/Layout/RenderablePane.cs +++ b/File_Format_Library/FileFormats/Layout/RenderablePane.cs @@ -11,52 +11,61 @@ namespace LayoutBXLYT public class RenderablePane { int vbo_position; + int ibo_position; public struct Vertex { - public Vector3 Position; + public Vector2 Position; public Vector4 Color; public Vector2 TexCoord0; public Vector2 TexCoord1; public Vector2 TexCoord2; - public static int SizeInBytes = 4 * (3 + 4 + 2 + 2 + 2); + public static int SizeInBytes = 4 * (2 + 4 + 2 + 2 + 2); } - private void GenerateBuffers(Vector3[] positions, Vector4[] colors, Vector2[] texCoords0) + private void GenerateBuffers(Vector2[] positions, Vector4[] colors, Vector2[] texCoords0) { GL.GenBuffers(1, out vbo_position); + GL.GenBuffers(1, out ibo_position); + UpdateVertexData(positions, colors, texCoords0); } public void Destroy() { - bool buffersWereInitialized = vbo_position != 0; + bool buffersWereInitialized = vbo_position != 0 && ibo_position != 0; if (!buffersWereInitialized) return; GL.DeleteBuffer(vbo_position); + GL.DeleteBuffer(vbo_position); } public Vertex[] Vertices; + ushort[] Indices = new ushort[] { 0, 1, 2, 3 }; - public void Render(Vector3[] positions, Vector4[] colors, Vector2[] texCoords0) + public void Render(BxlytShader shader, Vector2[] positions, Vector4[] colors, Vector2[] texCoords0) { - bool buffersWereInitialized = vbo_position != 0; + shader.Enable(); + + bool buffersWereInitialized = vbo_position != 0 && ibo_position != 0; if (!buffersWereInitialized) GenerateBuffers(positions, colors, texCoords0); + shader.EnableVertexAttributes(); GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position); - GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 0); - GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 12); - GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 28); - GL.VertexAttribPointer(3, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 36); - GL.VertexAttribPointer(4, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 44); - - GL.DrawArrays(PrimitiveType.Triangles, 0, 3); + GL.VertexAttribPointer(shader.GetAttribute("vPosition"), 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 0); + GL.VertexAttribPointer(shader.GetAttribute("vColor"), 4, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 8); + GL.VertexAttribPointer(shader.GetAttribute("vTexCoord0"), 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 24); + GL.VertexAttribPointer(shader.GetAttribute("vTexCoord1"), 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 32); + GL.VertexAttribPointer(shader.GetAttribute("vTexCoord2"), 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 40); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_position); + GL.DrawElements(PrimitiveType.Quads, 4, DrawElementsType.UnsignedShort, IntPtr.Zero); + shader.DisableVertexAttributes(); } - public void UpdateVertexData(Vector3[] positions, Vector4[] colors, Vector2[] texCoords0) + public void UpdateVertexData(Vector2[] positions, Vector4[] colors, Vector2[] texCoords0) { Vertices = new Vertex[positions.Length]; for (int v = 0; v < Vertices.Length; v++) @@ -67,7 +76,13 @@ namespace LayoutBXLYT Vertices[v].TexCoord0 = texCoords0[v]; } - GL.GenBuffers(1, out vbo_position); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_position); + GL.BufferData( + BufferTarget.ElementArrayBuffer, + (IntPtr)(Indices.Length * sizeof(ushort)), + Indices, + BufferUsageHint.StaticDraw); + GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(Vertices.Length * Vertex.SizeInBytes), diff --git a/File_Format_Library/FileFormats/Layout/Rev/BRLAN.cs b/File_Format_Library/FileFormats/Layout/Rev/BRLAN.cs index 040cf8a8..d667db8a 100644 --- a/File_Format_Library/FileFormats/Layout/Rev/BRLAN.cs +++ b/File_Format_Library/FileFormats/Layout/Rev/BRLAN.cs @@ -11,7 +11,7 @@ using SharpYaml.Serialization; namespace LayoutBXLYT { - public class BRLAN : IEditorForm, IFileFormat, IConvertableTextFormat + public class BRLAN : BXLAN, IEditorForm, IFileFormat, IConvertableTextFormat { public FileType FileType { get; set; } = FileType.Layout; @@ -71,14 +71,12 @@ namespace LayoutBXLYT #endregion - Header header; - public void Load(System.IO.Stream stream) { CanSave = true; - header = new Header(); - header.Read(new FileReader(stream),this); + BxlanHeader = new Header(); + BxlanHeader.Read(new FileReader(stream),this); } public void Unload() { @@ -86,20 +84,20 @@ namespace LayoutBXLYT } public void Save(System.IO.Stream stream) { - header.Write(new FileWriter(stream)); + BxlanHeader.Write(new FileWriter(stream)); } public LayoutEditor OpenForm() { LayoutEditor editor = new LayoutEditor(); editor.Dock = DockStyle.Fill; - editor.LoadBxlan(header); + editor.LoadBxlan(BxlanHeader); return editor; } public void FillEditor(Form control) { - ((LayoutEditor)control).LoadBxlan(header); + ((LayoutEditor)control).LoadBxlan(BxlanHeader); } public class Header : BxlanHeader @@ -111,7 +109,7 @@ namespace LayoutBXLYT //As of now this should be empty but just for future proofing private List UnknownSections = new List(); - public void Read(FileReader reader, BRLAN bflan) + public override void Read(FileReader reader, BXLAN bflan) { AnimationTag = new PAT1(); AnimationInfo = new PAI1(); @@ -126,7 +124,7 @@ namespace LayoutBXLYT ushort sectionCount = reader.ReadUInt16(); reader.ReadUInt16(); //Padding - FileInfo = bflan; + FileInfo = (IFileFormat)bflan; IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian; reader.SeekBegin(HeaderSize); @@ -156,7 +154,7 @@ namespace LayoutBXLYT } } - public void Write(FileWriter writer) + public override void Write(FileWriter writer) { writer.SetByteOrder(true); writer.WriteSignature(Magic); @@ -394,25 +392,25 @@ namespace LayoutBXLYT switch (Tag) { case "RLPA": - Entries.Add(new FLPATagEntry(reader, header)); + Entries.Add(new LPATagEntry(reader, header)); break; case "RLTS": - Entries.Add(new FLTSTagEntry(reader, header)); + Entries.Add(new LTSTagEntry(reader, header)); break; case "RLVI": - Entries.Add(new FLVITagEntry(reader, header)); + Entries.Add(new LVITagEntry(reader, header)); break; case "RLVC": - Entries.Add(new FLVCTagEntry(reader, header)); + Entries.Add(new LVCTagEntry(reader, header)); break; case "RLMC": - Entries.Add(new FLMCTagEntry(reader, header)); + Entries.Add(new LMCTagEntry(reader, header)); break; case "RLTP": - Entries.Add(new FLTPTagEntry(reader, header)); + Entries.Add(new LTPTagEntry(reader, header)); break; default: - Entries.Add(new PaiTagEntry(reader, header)); + Entries.Add(new BxlanPaiTagEntry(reader, header)); break; } } @@ -432,122 +430,9 @@ namespace LayoutBXLYT for (int i = 0; i < Entries.Count; i++) { writer.WriteUint32Offset(startPos + 8 + (i * 4), startPos); - ((PaiTagEntry)Entries[i]).Write(writer, header); + ((BxlanPaiTagEntry)Entries[i]).Write(writer, header); } } } - - public class PaiTagEntry : BxlanPaiTagEntry - { - public byte Unknown; - - public PaiTagEntry(FileReader reader, Header header) - { - long startPos = reader.Position; - Index = reader.ReadByte(); - AnimationTarget = reader.ReadByte(); - DataType = reader.ReadEnum(true); - Unknown = reader.ReadByte(); - var KeyFrameCount = reader.ReadUInt16(); - reader.ReadUInt16(); //Padding - uint keyFrameOffset = reader.ReadUInt32(); - - reader.SeekBegin(startPos + keyFrameOffset); - for (int i = 0; i < KeyFrameCount; i++) - KeyFrames.Add(new KeyFrame(reader, DataType)); - } - - public void Write(FileWriter writer, LayoutHeader header) - { - long startPos = writer.Position; - - writer.Write(Index); - writer.Write(AnimationTarget); - writer.Write(DataType, true); - writer.Write(Unknown); - writer.Write((ushort)KeyFrames.Count); - writer.Write((ushort)0); //padding - writer.Write(0); //key offset - - if (KeyFrames.Count > 0) - { - writer.WriteUint32Offset(startPos + 8, startPos); - for (int i = 0; i < KeyFrames.Count; i++) - KeyFrames[i].Write(writer, DataType); - } - } - } - - public class FLPATagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LPATarget Target - { - get { return (LPATarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLPATagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLTSTagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LTSTarget Target - { - get { return (LTSTarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLTSTagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLVITagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LVITarget Target - { - get { return (LVITarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLVITagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLVCTagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LVCTarget Target - { - get { return (LVCTarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLVCTagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLMCTagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LMCTarget Target - { - get { return (LMCTarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLMCTagEntry(FileReader reader, Header header) : base(reader, header) { } - } - - public class FLTPTagEntry : PaiTagEntry - { - public override string TargetName => Target.ToString(); - [DisplayName("Target"), CategoryAttribute("Tag")] - public LTPTarget Target - { - get { return (LTPTarget)AnimationTarget; } - set { AnimationTarget = (byte)value; } - } - public FLTPTagEntry(FileReader reader, Header header) : base(reader, header) { } - } } } diff --git a/File_Format_Library/FileFormats/Layout/Rev/BRLYT.cs b/File_Format_Library/FileFormats/Layout/Rev/BRLYT.cs index 9374332c..830aa669 100644 --- a/File_Format_Library/FileFormats/Layout/Rev/BRLYT.cs +++ b/File_Format_Library/FileFormats/Layout/Rev/BRLYT.cs @@ -223,6 +223,7 @@ namespace LayoutBXLYT { IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian; + PaneLookup.Clear(); LayoutInfo = new LYT1(); TextureList = new TXL1(); MaterialList = new MAT1(); @@ -276,6 +277,7 @@ namespace LayoutBXLYT break; case "pan1": var panel = new PAN1(reader); + AddPaneToTable(panel); if (!setRoot) { RootPane = panel; @@ -287,30 +289,36 @@ namespace LayoutBXLYT break; case "pic1": var picturePanel = new PIC1(reader, this); + AddPaneToTable(picturePanel); SetPane(picturePanel, parentPane); currentPane = picturePanel; break; case "txt1": var textPanel = new TXT1(reader); + AddPaneToTable(textPanel); SetPane(textPanel, parentPane); currentPane = textPanel; break; case "bnd1": var boundsPanel = new BND1(reader); + AddPaneToTable(boundsPanel); SetPane(boundsPanel, parentPane); currentPane = boundsPanel; break; case "prt1": var partsPanel = new PRT1(reader); + AddPaneToTable(partsPanel); SetPane(partsPanel, parentPane); currentPane = partsPanel; break; case "wnd1": var windowPanel = new WND1(reader); + AddPaneToTable(windowPanel); + SetPane(windowPanel, parentPane); currentPane = windowPanel; break; @@ -554,7 +562,7 @@ namespace LayoutBXLYT } } - public class BND1 : PAN1 + public class BND1 : PAN1, IBoundryPane { public BND1() : base() { @@ -620,7 +628,7 @@ namespace LayoutBXLYT } } - public class PIC1 : PAN1 + public class PIC1 : PAN1, IPicturePane { public TexCoord[] TexCoords { get; set; } @@ -701,7 +709,7 @@ namespace LayoutBXLYT { private byte _flags1; - public bool Visible + public override bool Visible { get { return (_flags1 & 0x1) == 0x1; } set { @@ -868,7 +876,6 @@ namespace LayoutBXLYT public STColor8 TevColor3 { get; set; } public STColor8 TevColor4 { get; set; } - public List TextureMaps { get; set; } public List TextureTransforms { get; set; } private uint flags; @@ -884,7 +891,7 @@ namespace LayoutBXLYT public Material() { - TextureMaps = new List(); + TextureMaps = new TextureRef[0]; TextureTransforms = new List(); } @@ -892,7 +899,6 @@ namespace LayoutBXLYT { ParentLayout = header; - TextureMaps = new List(); TextureTransforms = new List(); Name = reader.ReadString(0x14, true); @@ -906,12 +912,15 @@ namespace LayoutBXLYT TevColor4 = reader.ReadColor8RGBA(); flags = reader.ReadUInt32(); + uint indSrtCount = ExtractBits(flags, 2, 17); uint texCoordGenCount = ExtractBits(flags, 4, 20); uint mtxCount = ExtractBits(flags, 4, 24); uint texCount = ExtractBits(flags, 4, 28); + + TextureMaps = new TextureRef[texCount]; for (int i = 0; i < texCount; i++) - TextureMaps.Add(new TextureRef(reader, header)); + TextureMaps[i] = new TextureRef(reader, header); for (int i = 0; i < mtxCount; i++) TextureTransforms.Add(new TextureTransform(reader)); @@ -924,8 +933,8 @@ namespace LayoutBXLYT // writer.Write(BackColor); writer.Write(flags); - for (int i = 0; i < TextureMaps.Count; i++) - TextureMaps[i].Write(writer); + for (int i = 0; i < TextureMaps.Length; i++) + ((TextureRef)TextureMaps[i]).Write(writer); for (int i = 0; i < TextureTransforms.Count; i++) TextureTransforms[i].Write(writer); @@ -984,12 +993,12 @@ namespace LayoutBXLYT public TextureRef() {} public TextureRef(FileReader reader, Header header) { - if (header.Textures.Count > 0) - Name = header.Textures[ID]; - ID = reader.ReadInt16(); flag1 = reader.ReadByte(); flag2 = reader.ReadByte(); + + if (header.Textures.Count > 0) + Name = header.Textures[ID]; } public void Write(FileWriter writer) diff --git a/File_Format_Library/FileFormats/Layout/Rev/BrlytShader.cs b/File_Format_Library/FileFormats/Layout/Rev/BrlytShader.cs index bcd44ae0..3dbe75d9 100644 --- a/File_Format_Library/FileFormats/Layout/Rev/BrlytShader.cs +++ b/File_Format_Library/FileFormats/Layout/Rev/BrlytShader.cs @@ -31,46 +31,140 @@ namespace LayoutBXLYT SetInt("textures1", 0); SetInt("textures2", 0); SetBool("ThresholdingAlphaInterpolation", false); + var rotationMatrix = Matrix4.Identity; + SetMatrix("rotationMatrix", ref rotationMatrix); + SetInt("numTevStages", 0); SetVec2("uvScale0", new Vector2(1, 1)); SetFloat("uvRotate0", 0); SetVec2("uvTranslate0", new Vector2(0, 0)); + SetVec4("IndirectMat0", new Vector4(1, 1, 0, 0)); + SetVec4("IndirectMat1", new Vector4(1, 1, 0, 0)); + SetInt($"texCoords0GenType", 0); + SetInt($"texCoords0Source", 0); } - public void SetMaterials(Dictionary textures) + public void SetMaterials(BasePane pane, Dictionary textures) { - SetColor("whiteColor", Color.FromArgb(255, material.WhiteColor.Color)); - SetColor("blackColor", material.BlackColor.Color); + var paneRotate = pane.Rotate; + if (pane.animController.PaneSRT?.Count > 0) + { + foreach (var animItem in pane.animController.PaneSRT) + { + switch (animItem.Key) + { + case LPATarget.RotateX: + paneRotate.X = animItem.Value; break; + case LPATarget.RotateY: + paneRotate.Y = animItem.Value; break; + case LPATarget.RotateZ: + paneRotate.Z = animItem.Value; break; + } + } + } + + Matrix4 rotationX = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(paneRotate.X)); + Matrix4 rotationY = Matrix4.CreateRotationY(MathHelper.DegreesToRadians(paneRotate.Y)); + Matrix4 rotationZ = Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(paneRotate.Z)); + var rotationMatrix = rotationX * rotationY * rotationZ; + + SetMatrix("rotationMatrix", ref rotationMatrix); + + var WhiteColor = material.WhiteColor; + var BlackColor = material.BlackColor; + + foreach (var animItem in material.animController.MaterialColors) + { + switch (animItem.Key) + { + case LMCTarget.WhiteColorRed: + WhiteColor.R = (byte)animItem.Value; break; + case LMCTarget.WhiteColorGreen: + WhiteColor.G = (byte)animItem.Value; break; + case LMCTarget.WhiteColorBlue: + WhiteColor.B = (byte)animItem.Value; break; + case LMCTarget.WhiteColorAlpha: + WhiteColor.A = (byte)animItem.Value; break; + case LMCTarget.BlackColorRed: + BlackColor.R = (byte)animItem.Value; break; + case LMCTarget.BlackColorGreen: + BlackColor.G = (byte)animItem.Value; break; + case LMCTarget.BlackColorBlue: + BlackColor.B = (byte)animItem.Value; break; + case LMCTarget.BlackColorAlpha: + BlackColor.A = (byte)animItem.Value; break; + } + } + + SetColor("whiteColor", Color.FromArgb(255, WhiteColor.R, WhiteColor.G, WhiteColor.B)); + SetColor("blackColor", BlackColor.Color); SetInt("debugShading", (int)Runtime.LayoutEditor.Shading); - SetInt("numTextureMaps", material.TextureMaps.Count); + SetInt("numTextureMaps", material.TextureMaps.Length); SetVec2("uvScale0", new Vector2(1, 1)); SetFloat("uvRotate0", 0); SetVec2("uvTranslate0", new Vector2(0, 0)); SetInt("flipTexture", 0); + SetInt("numTevStages", 0); SetBool("ThresholdingAlphaInterpolation", material.ThresholdingAlphaInterpolation); + SetVec4("IndirectMat0", new Vector4(1, 1, 0, 0)); + SetVec4("IndirectMat1", new Vector4(1, 1, 0, 0)); + SetInt("tevTexMode", 0); + SetInt($"texCoords0GenType", 0); + SetInt($"texCoords0Source", 0); BindTextureUniforms(); - string textureMap0 = ""; - if (material.TextureMaps.Count > 0) - textureMap0 = material.GetTexture(0); - - if (textures.ContainsKey(textureMap0)) + int id = 1; + for (int i = 0; i < material.TextureMaps.Length; i++) { - GL.ActiveTexture(TextureUnit.Texture0); - SetInt("textures0", 0); - bool isBinded = BxlytToGL.BindGLTexture(material.TextureMaps[0], textures[textureMap0]); - if (isBinded) - SetInt("hasTexture0", 1); + string TexName = material.TextureMaps[i].Name; + + if (material.animController.TexturePatterns.ContainsKey((LTPTarget)i)) + TexName = material.animController.TexturePatterns[(LTPTarget)i]; + + if (textures.ContainsKey(TexName)) + { + GL.ActiveTexture(TextureUnit.Texture0 + id); + SetInt($"textures{i}", id); + bool isBinded = BxlytToGL.BindGLTexture(material.TextureMaps[i], textures[TexName]); + if (isBinded) + SetInt($"hasTexture{i}", 1); + + id++; + } } if (material.TextureTransforms.Count > 0) { var transform = material.TextureTransforms[0]; - SetVec2("uvScale0",new Vector2(transform.Scale.X, transform.Scale.Y)); - SetFloat("uvRotate0", transform.Rotate); - SetVec2("uvTranslate0",new Vector2( transform.Translate.X, transform.Translate.Y)); + var scale = transform.Scale; + var rotate = transform.Rotate; + var translate = transform.Translate; + + foreach (var animItem in material.animController.TextureSRTS) + { + switch (animItem.Key) + { + case LTSTarget.ScaleS: scale.X = animItem.Value; break; + case LTSTarget.ScaleT: scale.Y = animItem.Value; break; + case LTSTarget.Rotate: rotate = animItem.Value; break; + case LTSTarget.TranslateS: translate.X = animItem.Value; break; + case LTSTarget.TranslateT: translate.Y = animItem.Value; break; + } + } + + SetVec2("uvScale0", new Vector2(scale.X, scale.Y)); + SetFloat("uvRotate0", rotate); + SetVec2("uvTranslate0", new Vector2(translate.X, translate.Y)); } + + GL.Enable(EnableCap.Blend); + GL.Enable(EnableCap.AlphaTest); + GL.AlphaFunc(AlphaFunction.Always, 0f); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + GL.BlendEquation(BlendEquationMode.FuncAdd); + GL.Disable(EnableCap.ColorLogicOp); + GL.LogicOp(LogicOp.Noop); } private void BindTextureUniforms() @@ -80,7 +174,7 @@ namespace LayoutBXLYT GL.Uniform1(GL.GetUniformLocation(program, "uvTestPattern"), 10); GL.BindTexture(TextureTarget.Texture2D, RenderTools.uvTestPattern.RenderableTex.TexID); - if (material.TextureMaps.Count > 0) + if (material.TextureMaps.Length > 0) { var tex = material.TextureMaps[0]; GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, BxlytToGL.ConvertTextureWrap(tex.WrapModeU)); diff --git a/File_Format_Library/File_Format_Library.csproj b/File_Format_Library/File_Format_Library.csproj index 4fdefa56..1eb75dbf 100644 --- a/File_Format_Library/File_Format_Library.csproj +++ b/File_Format_Library/File_Format_Library.csproj @@ -220,6 +220,7 @@ + @@ -296,6 +297,9 @@ + + + @@ -311,6 +315,8 @@ + + @@ -385,7 +391,7 @@ LayoutTextureList.cs - Form + UserControl LayoutViewer.cs diff --git a/File_Format_Library/GUI/BFLYT/LayoutEditor.Designer.cs b/File_Format_Library/GUI/BFLYT/LayoutEditor.Designer.cs index a252d8c4..cc6e6794 100644 --- a/File_Format_Library/GUI/BFLYT/LayoutEditor.Designer.cs +++ b/File_Format_Library/GUI/BFLYT/LayoutEditor.Designer.cs @@ -55,6 +55,11 @@ this.displayyBoundryPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.displayWindowPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.displayPicturePanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.animationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.resetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.windowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.showGameWindowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.displayTextPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)(this.backColorDisplay)).BeginInit(); this.stToolStrip1.SuspendLayout(); this.stMenuStrip1.SuspendLayout(); @@ -150,7 +155,9 @@ this.stMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem, this.editToolStripMenuItem, - this.viewToolStripMenuItem}); + this.viewToolStripMenuItem, + this.animationToolStripMenuItem, + this.windowToolStripMenuItem}); this.stMenuStrip1.Location = new System.Drawing.Point(0, 0); this.stMenuStrip1.Name = "stMenuStrip1"; this.stMenuStrip1.Size = new System.Drawing.Size(549, 24); @@ -172,35 +179,35 @@ // openToolStripMenuItem // this.openToolStripMenuItem.Name = "openToolStripMenuItem"; - this.openToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.openToolStripMenuItem.Size = new System.Drawing.Size(157, 22); this.openToolStripMenuItem.Text = "Open"; this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); // // clearWorkspaceToolStripMenuItem // this.clearWorkspaceToolStripMenuItem.Name = "clearWorkspaceToolStripMenuItem"; - this.clearWorkspaceToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.clearWorkspaceToolStripMenuItem.Size = new System.Drawing.Size(157, 22); this.clearWorkspaceToolStripMenuItem.Text = "Clear Files"; this.clearWorkspaceToolStripMenuItem.Click += new System.EventHandler(this.clearWorkspaceToolStripMenuItem_Click); // // saveToolStripMenuItem1 // this.saveToolStripMenuItem1.Name = "saveToolStripMenuItem1"; - this.saveToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + this.saveToolStripMenuItem1.Size = new System.Drawing.Size(157, 22); this.saveToolStripMenuItem1.Text = "Save Layout"; this.saveToolStripMenuItem1.Click += new System.EventHandler(this.saveToolStripMenuItem1_Click); // // saveAnimationToolStripMenuItem // this.saveAnimationToolStripMenuItem.Name = "saveAnimationToolStripMenuItem"; - this.saveAnimationToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.saveAnimationToolStripMenuItem.Size = new System.Drawing.Size(157, 22); this.saveAnimationToolStripMenuItem.Text = "Save Animation"; this.saveAnimationToolStripMenuItem.Click += new System.EventHandler(this.saveAnimationToolStripMenuItem_Click); // // saveToolStripMenuItem // this.saveToolStripMenuItem.Name = "saveToolStripMenuItem"; - this.saveToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.saveToolStripMenuItem.Size = new System.Drawing.Size(157, 22); this.saveToolStripMenuItem.Text = "Save As"; this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); // @@ -221,7 +228,8 @@ this.displayNullPanesToolStripMenuItem, this.displayyBoundryPanesToolStripMenuItem, this.displayWindowPanesToolStripMenuItem, - this.displayPicturePanesToolStripMenuItem}); + this.displayPicturePanesToolStripMenuItem, + this.displayTextPanesToolStripMenuItem}); this.viewToolStripMenuItem.Name = "viewToolStripMenuItem"; this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20); this.viewToolStripMenuItem.Text = "View"; @@ -306,6 +314,46 @@ this.displayPicturePanesToolStripMenuItem.Text = "Display Picture Panes"; this.displayPicturePanesToolStripMenuItem.Click += new System.EventHandler(this.displayPanesToolStripMenuItem_Click); // + // animationToolStripMenuItem + // + this.animationToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.resetToolStripMenuItem}); + this.animationToolStripMenuItem.Name = "animationToolStripMenuItem"; + this.animationToolStripMenuItem.Size = new System.Drawing.Size(75, 20); + this.animationToolStripMenuItem.Text = "Animation"; + // + // resetToolStripMenuItem + // + this.resetToolStripMenuItem.Name = "resetToolStripMenuItem"; + this.resetToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.resetToolStripMenuItem.Text = "Reset"; + this.resetToolStripMenuItem.Click += new System.EventHandler(this.resetToolStripMenuItem_Click); + // + // windowToolStripMenuItem + // + this.windowToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.showGameWindowToolStripMenuItem}); + this.windowToolStripMenuItem.Name = "windowToolStripMenuItem"; + this.windowToolStripMenuItem.Size = new System.Drawing.Size(63, 20); + this.windowToolStripMenuItem.Text = "Window"; + // + // showGameWindowToolStripMenuItem + // + this.showGameWindowToolStripMenuItem.Name = "showGameWindowToolStripMenuItem"; + this.showGameWindowToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.showGameWindowToolStripMenuItem.Text = "Show Game Window"; + this.showGameWindowToolStripMenuItem.Click += new System.EventHandler(this.showGameWindowToolStripMenuItem_Click); + // + // displayTextPanesToolStripMenuItem + // + this.displayTextPanesToolStripMenuItem.Checked = true; + this.displayTextPanesToolStripMenuItem.CheckOnClick = true; + this.displayTextPanesToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.displayTextPanesToolStripMenuItem.Name = "displayTextPanesToolStripMenuItem"; + this.displayTextPanesToolStripMenuItem.Size = new System.Drawing.Size(202, 22); + this.displayTextPanesToolStripMenuItem.Text = "Display Text Panes"; + this.displayTextPanesToolStripMenuItem.Click += new System.EventHandler(this.displayPanesToolStripMenuItem_Click); + // // LayoutEditor // this.AllowDrop = true; @@ -321,6 +369,7 @@ this.Controls.Add(this.stMenuStrip1); this.IsMdiContainer = true; this.Name = "LayoutEditor"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.LayoutEditor_FormClosed); this.DragDrop += new System.Windows.Forms.DragEventHandler(this.LayoutEditor_DragDrop); this.DragEnter += new System.Windows.Forms.DragEventHandler(this.LayoutEditor_DragEnter); this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.LayoutEditor_KeyDown); @@ -363,5 +412,10 @@ private System.Windows.Forms.ToolStripMenuItem displayPicturePanesToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem renderInGamePreviewToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem displayGridToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem animationToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem resetToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem windowToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem showGameWindowToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem displayTextPanesToolStripMenuItem; } } diff --git a/File_Format_Library/GUI/BFLYT/LayoutEditor.cs b/File_Format_Library/GUI/BFLYT/LayoutEditor.cs index d1fdb51c..71493905 100644 --- a/File_Format_Library/GUI/BFLYT/LayoutEditor.cs +++ b/File_Format_Library/GUI/BFLYT/LayoutEditor.cs @@ -25,6 +25,10 @@ namespace LayoutBXLYT /// public static bool UseLegacyGL = true; + public LayoutViewer GamePreviewWindow; + + private LayoutCustomPaneMapper CustomMapper; + private Dictionary Textures; public List LayoutFiles = new List(); @@ -45,6 +49,7 @@ namespace LayoutBXLYT public LayoutEditor() { InitializeComponent(); + CustomMapper = new LayoutCustomPaneMapper(); Textures = new Dictionary(); @@ -67,6 +72,7 @@ namespace LayoutBXLYT displayWindowPanesToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayWindowPane; renderInGamePreviewToolStripMenuItem.Checked = Runtime.LayoutEditor.IsGamePreview; displayGridToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayGrid; + displayTextPanesToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayTextPane; ObjectSelected += OnObjectSelected; ObjectChanged += OnObjectChanged; @@ -85,26 +91,64 @@ namespace LayoutBXLYT private LayoutProperties LayoutProperties; private LayoutTextDocked TextConverter; private LayoutPartsEditor LayoutPartsEditor; + private STAnimationPanel AnimationPanel; private bool isLoaded = false; public void LoadBxlyt(BxlytHeader header) { + /* if (PluginRuntime.BxfntFiles.Count > 0) + { + var result = MessageBox.Show("Found font files opened. Would you like to save character images to disk? " + + "(Allows for faster loading and won't need to be reopened)", "Layout Editor", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result == DialogResult.Yes) + { + var cacheDir = $"{Runtime.ExecutableDir}/Cached/Font"; + if (!System.IO.Directory.Exists(cacheDir)) + System.IO.Directory.CreateDirectory(cacheDir); + + foreach (var bffnt in PluginRuntime.BxfntFiles) + { + if (!System.IO.Directory.Exists($"{cacheDir}/{bffnt.Name}")) + System.IO.Directory.CreateDirectory($"{cacheDir}/{bffnt.Name}"); + + var fontBitmap = bffnt.GetBitmapFont(true); + foreach (var character in fontBitmap.Characters) + { + var charaMap = character.Value; + charaMap.CharBitmap.Save($"{cacheDir}/{bffnt.Name}/cmap_{Convert.ToUInt16(character.Key).ToString("x2")}_{charaMap.CharWidth}_{charaMap.GlyphWidth}_{charaMap.LeftOffset}.png"); + } + + fontBitmap.Dispose(); + } + } + }*/ + LayoutFiles.Add(header); ActiveLayout = header; - LayoutViewer Viewport = new LayoutViewer(header, Textures); - Viewport.Dock = DockStyle.Fill; - Viewport.Show(dockPanel1, DockState.Document); - Viewport.DockHandler.AllowEndUserDocking = false; - Viewports.Add(Viewport); - ActiveViewport = Viewport; - ActiveViewport.UseOrtho = orthographicViewToolStripMenuItem.Checked; + if (ActiveViewport == null) + { + LayoutViewer Viewport = new LayoutViewer(this,header, Textures); + Viewport.DockContent = new DockContent(); + Viewport.DockContent.Controls.Add(Viewport); + Viewport.Dock = DockStyle.Fill; + Viewport.DockContent.Show(dockPanel1, DockState.Document); + Viewport.DockContent.DockHandler.AllowEndUserDocking = false; + Viewports.Add(Viewport); + ActiveViewport = Viewport; + } + else + ActiveViewport.LoadLayout(header); + + orthographicViewToolStripMenuItem.Checked = Runtime.LayoutEditor.UseOrthographicView; if (!isLoaded) InitializeDockPanels(); AnimLayoutHierarchy?.SearchAnimations(header, ObjectSelected); + CustomMapper.LoadMK8DCharaSelect(Textures, header); + isLoaded = true; } @@ -128,6 +172,7 @@ namespace LayoutBXLYT ShowPaneHierarchy(); ShowPropertiesPanel(); UpdateBackColor(); + ShowAnimationPanel(); } private void ResetEditors() @@ -180,6 +225,19 @@ namespace LayoutBXLYT { if (isChecked) return; + if (AnimationPanel != null) + { + if (e is TreeViewEventArgs) + { + var node = ((TreeViewEventArgs)e).Node; + if (node.Tag is ArchiveFileInfo) { + UpdateAnimationNode(node); + } + + if (node.Tag is BxlanHeader) + UpdateAnimationPlayer((BxlanHeader)node.Tag); + } + } if (LayoutProperties != null && (string)sender == "Select") { ActiveViewport?.SelectedPanes.Clear(); @@ -210,6 +268,25 @@ namespace LayoutBXLYT } } + private void UpdateAnimationNode(TreeNode node) + { + node.Nodes.Clear(); + + var archiveNode = node.Tag as ArchiveFileInfo; + var fileFormat = archiveNode.OpenFile(); + + //Update the tag so this doesn't run again + node.Tag = "Expanded"; + + if (fileFormat != null && fileFormat is BXLAN) + { + node.Tag = ((BXLAN)fileFormat).BxlanHeader; + + LayoutHierarchy.LoadAnimations(((BXLAN)fileFormat).BxlanHeader, node, false); + AnimationFiles.Add(((BXLAN)fileFormat).BxlanHeader); + } + } + private void ToggleChildern(TreeNode node, bool isChecked) { if (node.Tag is BasePane) @@ -220,9 +297,17 @@ namespace LayoutBXLYT ToggleChildern(child, isChecked); } - public void InitalizeEditors() + private void UpdateAnimationPlayer(BxlanHeader animHeader) { + if (AnimationPanel == null) return; + if (ActiveLayout != null) + { + AnimationPanel.Reset(); + AnimationPanel.AddAnimation(animHeader.ToGenericAnimation(ActiveLayout), true); + // foreach (var anim in AnimationFiles) + // AnimationPanel.AddAnimation(anim.ToGenericAnimation(ActiveLayout), false); + } } private void LayoutEditor_ParentChanged(object sender, EventArgs e) @@ -289,6 +374,21 @@ namespace LayoutBXLYT LayoutTextureList.Show(dockPanel1, DockState.DockRight); } + public void ShowAnimationPanel() + { + DockContent dockContent = new DockContent(); + AnimationPanel = new STAnimationPanel(); + AnimationPanel.Dock = DockStyle.Fill; + AnimationPanel.SetViewport(ActiveViewport.GetGLControl()); + dockContent.Controls.Add(AnimationPanel); + LayoutTextureList.Show(dockPanel1, DockState.DockRight); + + if (ActiveViewport != null) + dockContent.Show(ActiveViewport.Pane, DockAlignment.Bottom, 0.2); + else + dockContent.Show(dockPanel1, DockState.DockBottom); + } + private void stComboBox1_MouseDoubleClick(object sender, MouseEventArgs e) { @@ -569,7 +669,7 @@ namespace LayoutBXLYT { if (fileFormat.CanSave) { - if (fileFormat.IFileInfo != null && + if (fileFormat.IFileInfo != null && fileFormat.IFileInfo.ArchiveParent != null && !ForceDialog) { if (fileFormat is IEditorFormParameters) @@ -622,7 +722,7 @@ namespace LayoutBXLYT orthographicViewToolStripMenuItem.Checked = false; else orthographicViewToolStripMenuItem.Checked = true; - + ToggleOrthMode(); } @@ -630,12 +730,12 @@ namespace LayoutBXLYT { if (ActiveViewport != null) { - if (orthographicViewToolStripMenuItem.Checked) + if (!orthographicViewToolStripMenuItem.Checked) toolstripOrthoBtn.Image = BitmapExtension.GrayScale(FirstPlugin.Properties.Resources.OrthoView); else toolstripOrthoBtn.Image = FirstPlugin.Properties.Resources.OrthoView; - ActiveViewport.UseOrtho = orthographicViewToolStripMenuItem.Checked; + Runtime.LayoutEditor.UseOrthographicView = orthographicViewToolStripMenuItem.Checked; ActiveViewport.ResetCamera(); ActiveViewport.UpdateViewport(); } @@ -654,6 +754,7 @@ namespace LayoutBXLYT Runtime.LayoutEditor.DisplayBoundryPane = displayyBoundryPanesToolStripMenuItem.Checked; Runtime.LayoutEditor.DisplayPicturePane = displayPicturePanesToolStripMenuItem.Checked; Runtime.LayoutEditor.DisplayWindowPane = displayWindowPanesToolStripMenuItem.Checked; + Runtime.LayoutEditor.DisplayTextPane = displayTextPanesToolStripMenuItem.Checked; ActiveViewport?.UpdateViewport(); } @@ -669,5 +770,31 @@ namespace LayoutBXLYT Runtime.LayoutEditor.DisplayGrid = displayGridToolStripMenuItem.Checked; ActiveViewport?.UpdateViewport(); } + + private void resetToolStripMenuItem_Click(object sender, EventArgs e) + { + AnimationPanel?.Reset(); + ActiveViewport?.UpdateViewport(); + } + + private void showGameWindowToolStripMenuItem_Click(object sender, EventArgs e) + { + if (GamePreviewWindow == null || GamePreviewWindow.Disposing || GamePreviewWindow.IsDisposed) + { + GamePreviewWindow = new LayoutViewer(this,ActiveLayout, Textures); + GamePreviewWindow.GameWindow = true; + GamePreviewWindow.Dock = DockStyle.Fill; + STForm form = new STForm(); + form.Text = "Game Preview"; + form.AddControl(GamePreviewWindow); + form.Show(); + } + } + + private void LayoutEditor_FormClosed(object sender, FormClosedEventArgs e) + { + GamePreviewWindow?.OnControlClosing(); + GamePreviewWindow?.Dispose(); + } } } diff --git a/File_Format_Library/GUI/BFLYT/LayoutHierarchy.cs b/File_Format_Library/GUI/BFLYT/LayoutHierarchy.cs index c757d584..03bfcf90 100644 --- a/File_Format_Library/GUI/BFLYT/LayoutHierarchy.cs +++ b/File_Format_Library/GUI/BFLYT/LayoutHierarchy.cs @@ -90,12 +90,15 @@ namespace LayoutBXLYT treeView1.BeginUpdate(); foreach (var file in parentArchive.Files) { - if (Utils.GetExtension(file.FileName) == ".bflan") { + if (Utils.GetExtension(file.FileName) == ".brlan" || + Utils.GetExtension(file.FileName) == ".bclan" || + Utils.GetExtension(file.FileName) == ".bflan") { LoadAnimation(file); } } treeView1.EndUpdate(); + treeView1.Sort(); isLoaded = true; } @@ -124,7 +127,7 @@ namespace LayoutBXLYT isLoaded = false; } - private void LoadAnimations(BxlanHeader bxlan, TreeNode root, bool LoadRoot = true) + public void LoadAnimations(BxlanHeader bxlan, TreeNode root, bool LoadRoot = true) { if (LoadRoot) treeView1.Nodes.Add(root); @@ -420,18 +423,7 @@ namespace LayoutBXLYT //Allows for faster loading if (e.Node.Tag is ArchiveFileInfo) { - e.Node.Nodes.Clear(); - var archiveNode = e.Node.Tag as ArchiveFileInfo; - var fileFormat = archiveNode.OpenFile(); - - //Update the tag so this doesn't run again - e.Node.Tag = "Expanded"; - - if (fileFormat != null && fileFormat is BFLAN) { - LoadAnimations(((BFLAN)fileFormat).header, e.Node, false); - ParentEditor.AnimationFiles.Add(((BFLAN)fileFormat).header); - } } } } diff --git a/File_Format_Library/GUI/BFLYT/LayoutViewer.cs b/File_Format_Library/GUI/BFLYT/LayoutViewer.cs index 5ed28fb1..f5177a41 100644 --- a/File_Format_Library/GUI/BFLYT/LayoutViewer.cs +++ b/File_Format_Library/GUI/BFLYT/LayoutViewer.cs @@ -16,7 +16,7 @@ using LayoutBXLYT.Cafe; namespace LayoutBXLYT { - public partial class LayoutViewer : LayoutDocked + public partial class LayoutViewer : LayoutControlDocked { public List SelectedPanes = new List(); @@ -24,12 +24,16 @@ namespace LayoutBXLYT public class Camera2D { + public Matrix4 ModelViewMatrix = Matrix4.Identity; public float Zoom = 1; public Vector2 Position; } + private LayoutEditor ParentEditor; + private RenderableTex backgroundTex; public BxlytHeader LayoutFile; + public List LayoutFiles = new List(); private Dictionary Textures; private void glControl1_Load(object sender, EventArgs e) @@ -47,31 +51,44 @@ namespace LayoutBXLYT UpdateViewport(); } - public LayoutViewer(BxlytHeader bxlyt, Dictionary textures) + public GLControl GetGLControl() => glControl1; + + public LayoutViewer(LayoutEditor editor, BxlytHeader bxlyt, Dictionary textures) { InitializeComponent(); - LayoutFile = bxlyt; + + ParentEditor = editor; + Text = bxlyt.FileName; Textures = textures; + LoadLayout(bxlyt); + } + + public void LoadLayout(BxlytHeader bxlyt) + { + LayoutFile = bxlyt; + LayoutFiles.Add(bxlyt); + if (bxlyt.Textures.Count > 0) { - Textures = bxlyt.GetTextures; + var textures = bxlyt.GetTextures; + foreach (var tex in textures) + if (!Textures.ContainsKey(tex.Key)) + Textures.Add(tex.Key, tex.Value); } } - protected override void OnFormClosing(FormClosingEventArgs e) + public override void OnControlClosing() { - base.OnFormClosing(e); - return; - - var result = MessageBox.Show("Are you sure you want to close this file? You will lose any unsaved progress!", "Layout Editor", MessageBoxButtons.YesNo, MessageBoxIcon.Question); - if (result != DialogResult.Yes) - e.Cancel = true; - else - LayoutFile.Dispose(); - - base.OnFormClosing(e); + foreach (var tex in LayoutFile.Textures) + { + if (Textures.ContainsKey(tex)) + { + Textures[tex].DisposeRenderable(); + Textures.Remove(tex); + } + } } public void UpdateViewport() @@ -88,29 +105,81 @@ namespace LayoutBXLYT OnRender(); } - public bool UseOrtho = true; + private BxlytShader GlobalShader; + public bool GameWindow = false; + public bool UseOrtho => Runtime.LayoutEditor.UseOrthographicView; private Color BackgroundColor => Runtime.LayoutEditor.BackgroundColor; private void OnRender() { if (LayoutFile == null) return; + if (!GameWindow) + { + if (ParentEditor != null) + ParentEditor.GamePreviewWindow?.UpdateViewport(); + } + + if (GameWindow) + RenderGameWindow(); + else + RenderEditor(); + } + + private void RenderGameWindow() + { + int WindowWidth = (int)LayoutFile.RootPane.Width; + int WindowHeight = (int)LayoutFile.RootPane.Height; + GL.Viewport(0, 0, glControl1.Width, glControl1.Height); GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); if (UseOrtho) { - GL.Ortho(-(glControl1.Width / 2.0f), glControl1.Width / 2.0f, glControl1.Height / 2.0f, -(glControl1.Height / 2.0f), -10000, 10000); + float halfW = WindowWidth, halfH = WindowHeight; + var orthoMatrix = Matrix4.CreateOrthographic(halfW, halfH, -10000, 10000); + GL.LoadMatrix(ref orthoMatrix); GL.MatrixMode(MatrixMode.Modelview); - GL.LoadIdentity(); + Camera.ModelViewMatrix = orthoMatrix; + } + else + { + var cameraPosition = new Vector3(0, 0, -600); + var perspectiveMatrix = Matrix4.CreateTranslation(cameraPosition) * Matrix4.CreatePerspectiveFieldOfView(1.3f, WindowWidth / WindowHeight, 0.01f, 100000); + GL.LoadMatrix(ref perspectiveMatrix); + GL.MatrixMode(MatrixMode.Modelview); + Camera.ModelViewMatrix = perspectiveMatrix; + } + + RenderScene(); + } + + private void RenderEditor() + { + GL.Viewport(0, 0, glControl1.Width, glControl1.Height); + GL.MatrixMode(MatrixMode.Projection); + GL.LoadIdentity(); + if (UseOrtho) + { + float halfW = glControl1.Width / 2.0f, halfH = glControl1.Height / 2.0f; + var orthoMatrix = Matrix4.CreateOrthographic(halfW, halfH, -10000, 10000); + GL.LoadMatrix(ref orthoMatrix); + GL.MatrixMode(MatrixMode.Modelview); + Camera.ModelViewMatrix = orthoMatrix; } else { var cameraPosition = new Vector3(Camera.Position.X, Camera.Position.Y, -(Camera.Zoom * 500)); - var perspectiveMatrix = Matrix4.CreateTranslation(cameraPosition) * Matrix4.CreatePerspectiveFieldOfView(1.3f, glControl1.Width / (float)glControl1.Height, 0.01f, 100000); + var perspectiveMatrix = Matrix4.CreateTranslation(cameraPosition) * Matrix4.CreatePerspectiveFieldOfView(1.3f, glControl1.Width / glControl1.Height, 0.01f, 100000); GL.LoadMatrix(ref perspectiveMatrix); GL.MatrixMode(MatrixMode.Modelview); + Camera.ModelViewMatrix = perspectiveMatrix; } + RenderScene(); + } + + private void RenderScene() + { GL.ClearColor(BackgroundColor); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); @@ -122,21 +191,32 @@ namespace LayoutBXLYT GL.Enable(EnableCap.ColorMaterial); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, 0); + GL.BlendEquation(BlendEquationMode.FuncAdd); - if (UseOrtho) + if (UseOrtho && !GameWindow) { GL.PushMatrix(); - GL.Scale(1 * Camera.Zoom, -1 * Camera.Zoom, 1); + GL.Scale(Camera.Zoom, Camera.Zoom, 1); GL.Translate(Camera.Position.X, Camera.Position.Y, 0); } - DrawRootPane(LayoutFile.RootPane); - DrawGrid(); - DrawXyLines(); + if (!GameWindow) + { + DrawRootPane(LayoutFile.RootPane); + DrawGrid(); + DrawXyLines(); + } GL.BindTexture(TextureTarget.Texture2D, 0); - RenderPanes(LayoutFile.RootPane, true, 255, false, null, 0); + if (GlobalShader == null) + { + GlobalShader = new BxlytShader(); + GlobalShader.Compile(); + } + + foreach (var layout in LayoutFiles) + RenderPanes(GlobalShader, layout.RootPane, true, 255, false, null, 0); if (UseOrtho) GL.PopMatrix(); @@ -146,9 +226,10 @@ namespace LayoutBXLYT glControl1.SwapBuffers(); } - private void RenderPanes(BasePane pane, bool isRoot, byte parentAlpha, bool parentAlphaInfluence, BasePane partPane = null, int stage = 0) + private bool test = true; + private void RenderPanes(BxlytShader shader, BasePane pane, bool isRoot, byte parentAlpha, bool parentAlphaInfluence, BasePane partPane = null, int stage = 0) { - if (!pane.DisplayInEditor) + if (!pane.DisplayInEditor || !pane.animController.Visibile) return; GL.PushMatrix(); @@ -162,73 +243,106 @@ namespace LayoutBXLYT GL.Rotate(pane.Rotate.Z, 0, 0, 1); GL.Scale(pane.Scale.X, pane.Scale.Y, 1); - if (pane is BFLYT.PAN1) - DrawDefaultPane((BFLYT.PAN1)pane); - else if (pane is BCLYT.PAN1) - DrawDefaultPane((BCLYT.PAN1)pane); - else if (pane is BRLYT.PAN1) - DrawDefaultPane((BRLYT.PAN1)pane); + DrawDefaultPane(shader, pane, true); GL.PopMatrix(); } + + var translate = pane.Translate; + var rotate = pane.Rotate; + var scale = pane.Scale; + + foreach (var animItem in pane.animController.PaneSRT) + { + switch (animItem.Key) + { + case LPATarget.RotateX: rotate.X = animItem.Value; break; + case LPATarget.RotateY: rotate.Y = animItem.Value; break; + case LPATarget.RotateZ: rotate.Z = animItem.Value; break; + case LPATarget.ScaleX: scale.X = animItem.Value; break; + case LPATarget.ScaleY: scale.Y = animItem.Value; break; + case LPATarget.TranslateX: translate.X = animItem.Value; break; + case LPATarget.TranslateY: translate.Y = animItem.Value; break; + case LPATarget.TranslateZ: translate.Z = animItem.Value; break; + } + } + if (partPane != null) { - var translate = partPane.Translate + pane.Translate; - var scale = partPane.Scale * pane.Scale; - var rotate = partPane.Rotate + pane.Rotate; + translate = translate + pane.Translate; + scale = scale * pane.Scale; + rotate = rotate + pane.Rotate; + } - GL.Translate(translate.X + translate.X, translate.Y, 0); + GL.Translate(translate.X, translate.Y, 0); + + //Rotate normally unless the object uses shaders/materials + //Rotation matrix + shaders works accurately with X/Y rotation axis + //Todo, do everything by shaders + bool HasMaterials = pane is IWindowPane || pane is IPicturePane || pane is BFLYT.PRT1; + if (!HasMaterials) + { GL.Rotate(rotate.X, 1, 0, 0); GL.Rotate(rotate.Y, 0, 1, 0); GL.Rotate(rotate.Z, 0, 0, 1); - GL.Scale(scale.X, scale.Y, 1); - } - else - { - /*Matrix4 translate = Matrix4.CreateTranslation(pane.Translate.X, pane.Translate.Y, 0); - Matrix4 rotateX = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(pane.Rotate.X)); - Matrix4 rotateY = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(pane.Rotate.Y)); - Matrix4 rotateZ = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(pane.Rotate.Z)); - Matrix4 scale = Matrix4.CreateScale(pane.Scale.X, pane.Scale.Y, 0); - Matrix4 transform = scale * (rotateX * rotateY * rotateZ) * translate;*/ - - GL.Translate(pane.Translate.X, pane.Translate.Y, 0); - GL.Rotate(pane.Rotate.X, 1, 0, 0); - GL.Rotate(pane.Rotate.Y, 0, 1, 0); - GL.Rotate(pane.Rotate.Z, 0, 0, 1); - GL.Scale(pane.Scale.X, pane.Scale.Y, 1); } - byte effectiveAlpha = (byte)(parentAlpha == 255 ? pane.Alpha : (pane.Alpha * parentAlpha) / 255); + GL.Scale(scale.X, scale.Y, 1); + + byte alpha = pane.Alpha; + if (pane.animController.PaneVertexColors.ContainsKey(LVCTarget.PaneAlpha)) + alpha = (byte)pane.animController.PaneVertexColors[LVCTarget.PaneAlpha]; + + byte effectiveAlpha = (byte)(parentAlpha == 255 ? alpha : (alpha * parentAlpha) / 255); if (!parentAlphaInfluence) - effectiveAlpha = pane.Alpha; + effectiveAlpha = alpha; parentAlphaInfluence = parentAlphaInfluence || pane.InfluenceAlpha; if (!isRoot) { - if (pane is BFLYT.PIC1 || pane is BCLYT.PIC1 || pane is BRLYT.PIC1) - BxlytToGL.DrawPictureBox(pane, effectiveAlpha, Textures); + if (pane is IPicturePane) + BxlytToGL.DrawPictureBox(pane, GameWindow, effectiveAlpha, Textures); else if (pane is IWindowPane) - BxlytToGL.DrawWindowPane(pane, effectiveAlpha, Textures); - else if (pane is BFLYT.BND1 || pane is BCLYT.BND1 || pane is BRLYT.BND1) - BxlytToGL.DrawBoundryPane(pane, effectiveAlpha, SelectedPanes); + BxlytToGL.DrawWindowPane(pane, GameWindow, effectiveAlpha, Textures); + else if (pane is IBoundryPane) + BxlytToGL.DrawBoundryPane(pane, GameWindow, effectiveAlpha, SelectedPanes); + else if (pane is ITextPane && Runtime.LayoutEditor.DisplayTextPane) + { + var textPane = (ITextPane)pane; + Bitmap bitmap = new Bitmap(32, 32); + if (textPane.RenderableFont == null) + { + if (pane is BFLYT.TXT1) + { + foreach (var fontFile in FirstPlugin.PluginRuntime.BxfntFiles) + { + if (Utils.CompareNoExtension(fontFile.Name, textPane.FontName)) + { + bitmap = fontFile.GetBitmap(textPane.Text, false, pane); + } + } + } + } + if (bitmap != null) + BxlytToGL.DrawTextbox(pane, GameWindow, bitmap, effectiveAlpha, Textures, SelectedPanes, textPane.RenderableFont == null); + } else if (pane is BFLYT.SCR1) - BxlytToGL.DrawScissorPane(pane, effectiveAlpha, SelectedPanes); + BxlytToGL.DrawScissorPane(pane, GameWindow, effectiveAlpha, SelectedPanes); else if (pane is BFLYT.ALI1) - BxlytToGL.DrawAlignmentPane(pane, effectiveAlpha, SelectedPanes); + BxlytToGL.DrawAlignmentPane(pane, GameWindow, effectiveAlpha, SelectedPanes); else if (pane is BFLYT.PRT1) - DrawPartsPane((BFLYT.PRT1)pane, effectiveAlpha, parentAlphaInfluence); + DrawPartsPane(shader, (BFLYT.PRT1)pane, effectiveAlpha, parentAlphaInfluence); else - DrawDefaultPane(pane); + DrawDefaultPane(shader, pane); } else isRoot = false; byte childAlpha = pane.InfluenceAlpha || parentAlphaInfluence ? effectiveAlpha : byte.MaxValue; foreach (var childPane in pane.Childern) - RenderPanes(childPane, isRoot, childAlpha, parentAlphaInfluence, partPane); + RenderPanes(shader, childPane, isRoot, childAlpha, parentAlphaInfluence, partPane); GL.PopMatrix(); } @@ -262,9 +376,9 @@ namespace LayoutBXLYT GL.End(); } - private void DrawDefaultPane(BasePane pane) + private void DrawDefaultPane(BxlytShader shader, BasePane pane, bool isSelectionBox = false) { - if (!Runtime.LayoutEditor.DisplayNullPane || Runtime.LayoutEditor.IsGamePreview) + if (!Runtime.LayoutEditor.DisplayNullPane && !isSelectionBox || GameWindow || Runtime.LayoutEditor.IsGamePreview) return; Vector2[] TexCoords = new Vector2[] { @@ -285,17 +399,17 @@ namespace LayoutBXLYT color, }; - BxlytToGL.DrawRectangle(pane, pane.Rectangle, TexCoords, Colors); + BxlytToGL.DrawRectangle(pane, GameWindow, pane.Rectangle, TexCoords, Colors); } - private void DrawPartsPane(BFLYT.PRT1 pane, byte effectiveAlpha, bool parentInfluenceAlpha) + private void DrawPartsPane(BxlytShader shader, BFLYT.PRT1 pane, byte effectiveAlpha, bool parentInfluenceAlpha) { pane.UpdateTextureData(this.Textures); var partPane = pane.GetExternalPane(); if (partPane != null) - RenderPanes(partPane, true, effectiveAlpha, parentInfluenceAlpha); + RenderPanes(shader,partPane, true, effectiveAlpha, parentInfluenceAlpha); else - DrawDefaultPane(pane); + DrawDefaultPane(shader, pane); if (pane.Properties != null) { @@ -303,7 +417,7 @@ namespace LayoutBXLYT { if (prop.Property != null) { - RenderPanes(prop.Property, false, effectiveAlpha, parentInfluenceAlpha || pane.InfluenceAlpha); + RenderPanes(shader,prop.Property, false, effectiveAlpha, parentInfluenceAlpha || pane.InfluenceAlpha); } } } @@ -376,7 +490,7 @@ namespace LayoutBXLYT private void DrawXyLines() { - if (Runtime.LayoutEditor.IsGamePreview) + if (GameWindow || Runtime.LayoutEditor.IsGamePreview) return; int lineLength = 20; @@ -508,18 +622,6 @@ namespace LayoutBXLYT } } - protected override void OnClosed(EventArgs e) - { - foreach (var tex in LayoutFile.Textures) - { - if (Textures.ContainsKey(tex)) - { - Textures[tex].DisposeRenderable(); - Textures.Remove(tex); - } - } - } - protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); diff --git a/File_Format_Library/PluginRuntime.cs b/File_Format_Library/PluginRuntime.cs index 0fb4171b..59da876a 100644 --- a/File_Format_Library/PluginRuntime.cs +++ b/File_Format_Library/PluginRuntime.cs @@ -9,6 +9,8 @@ namespace FirstPlugin { public class PluginRuntime { + public static List BxfntFiles = new List(); + public static List SarcArchives = new List(); public class MaterialReplace diff --git a/Switch_Toolbox_Library/Animations/AnimationRewrite/InterpolationHelper.cs b/Switch_Toolbox_Library/Animations/AnimationRewrite/InterpolationHelper.cs new file mode 100644 index 00000000..30495923 --- /dev/null +++ b/Switch_Toolbox_Library/Animations/AnimationRewrite/InterpolationHelper.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Toolbox.Library.Animations +{ + public class InterpolationHelper + { + public static float Lerp(float LHS, float RHS, float Weight) + { + return LHS * (1 - Weight) + RHS * Weight; + } + + public static float Herp(float LHS, float RHS, float LS, float RS, float Diff, float Weight) + { + float Result; + + Result = LHS + (LHS - RHS) * (2 * Weight - 3) * Weight * Weight; + Result += (Diff * (Weight - 1)) * (LS * (Weight - 1) + RS * Weight); + + return Result; + } + } +} diff --git a/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimGroup.cs b/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimGroup.cs new file mode 100644 index 00000000..0a2d01b3 --- /dev/null +++ b/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimGroup.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Toolbox.Library.Animations +{ + /// + /// Represents a group that stores animation tracks and sub groups. + /// + public class STAnimGroup + { + public string Name { get; set; } + + public List SubAnimGroups = new List(); + } +} diff --git a/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimation.cs b/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimation.cs index dee2fe3f..edf6ac08 100644 --- a/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimation.cs +++ b/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimation.cs @@ -6,14 +6,84 @@ using System.Threading.Tasks; namespace Toolbox.Library.Animations { + public enum STInterpoaltionType + { + Constant, + Step, + Linear, + Hermite, + } + + /// + /// Represents how a track is played after it reaches end frame. + /// Repeat repeats back from the start. + /// Mirror goes from the end frame to the start + /// + public enum STLoopMode + { + Repeat, + Mirror, + Clamp, + } + /// /// Represents a class for animating a skeleton /// - public class STSkeletonAnimation + public class STAnimation { /// - /// The total amount of frames to play in the animation + /// The name of the animation. /// - public uint FrameCount { get; set; } + public string Name { get; set; } + + /// + /// The frame to start playing the animation. + /// + public float StartFrame { get; set; } + + /// + /// The current frame of the animation. + /// + public float Frame { get; set; } + + /// + /// The total amount of frames to play in the animation. + /// + public float FrameCount { get; set; } + + /// + /// Whether the animation will loop or not after + /// the playback rearches the total frame count. + /// + public bool Loop { get; set; } + + /// + /// The step value when a frame advances. + /// + public float Step { get; set; } + + /// + /// A list of groups that store the animation data. + /// + public List AnimGroups = new List(); + + public void SetFrame(float frame) + { + Frame = frame; + } + + public virtual void NextFrame() + { + if (Frame < StartFrame || Frame > FrameCount) return; + } + + /// + /// Resets the animation group values + /// This should clear values from tracks, or reset them to base values. + /// + public virtual void Reset() + { + + } } } diff --git a/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimationTrack.cs b/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimationTrack.cs new file mode 100644 index 00000000..f34940d8 --- /dev/null +++ b/Switch_Toolbox_Library/Animations/AnimationRewrite/STAnimationTrack.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Toolbox.Library.Animations +{ + public class STAnimationTrack + { + public STInterpoaltionType InterpolationType { get; set; } + + public List KeyFrames = new List(); + + public bool HasKeys => KeyFrames.Count > 0; + + //Key frame setup based on + //https://github.com/gdkchan/SPICA/blob/42c4181e198b0fd34f0a567345ee7e75b54cb58b/SPICA/Formats/CtrH3D/Animation/H3DFloatKeyFrameGroup.cs + public float GetFrameValue(float frame, float startFrame = 0) + { + if (KeyFrames.Count == 0) return 0; + if (KeyFrames.Count == 1) return KeyFrames[0].Value; + + STKeyFrame LK = KeyFrames.First(); + STKeyFrame RK = KeyFrames.Last(); + + float Frame = frame - startFrame; + + foreach (STKeyFrame keyFrame in KeyFrames) + { + if (keyFrame.Frame <= Frame) LK = keyFrame; + if (keyFrame.Frame >= Frame && keyFrame.Frame < RK.Frame) RK = keyFrame; + } + + if (LK.Frame != RK.Frame) + { + float FrameDiff = Frame - LK.Frame; + float Weight = FrameDiff / (RK.Frame - LK.Frame); + + switch (InterpolationType) + { + case STInterpoaltionType.Constant: return LK.Value; + case STInterpoaltionType.Step: return LK.Value; + case STInterpoaltionType.Linear: return InterpolationHelper.Lerp(LK.Value, RK.Value, Weight); + case STInterpoaltionType.Hermite: + return InterpolationHelper.Herp( + LK.Value, RK.Value, + LK.Slope, RK.Slope, + FrameDiff, + Weight); + } + } + + return LK.Value; + } + } +} diff --git a/Switch_Toolbox_Library/Animations/AnimationRewrite/STKeyFrame.cs b/Switch_Toolbox_Library/Animations/AnimationRewrite/STKeyFrame.cs new file mode 100644 index 00000000..ae69be0c --- /dev/null +++ b/Switch_Toolbox_Library/Animations/AnimationRewrite/STKeyFrame.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Toolbox.Library.Animations +{ + public class STKeyFrame + { + public virtual float Slope { get; set; } + public virtual float Frame { get; set; } + public virtual float Value { get; set; } + } + + public class STHermiteKeyFrame : STKeyFrame + { + public float Slope { get; set; } + } + + public class STLinearKeyFrame : STKeyFrame + { + public float Delta { get; set; } + } +} diff --git a/Switch_Toolbox_Library/Animations/AnimationRewrite/STSkeletonAnimation.cs b/Switch_Toolbox_Library/Animations/AnimationRewrite/STSkeletonAnimation.cs new file mode 100644 index 00000000..2c74d36a --- /dev/null +++ b/Switch_Toolbox_Library/Animations/AnimationRewrite/STSkeletonAnimation.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Toolbox.Library.Animations +{ + public class STSkeletonAnimation : STAnimation + { + public virtual STSkeleton GetActiveSkeleton() + { + Viewport viewport = LibraryGUI.GetActiveViewport(); + if (viewport == null) return null; + + foreach (var drawable in viewport.scene.objects) { + if (drawable is STSkeleton) + return (STSkeleton)drawable; + } + + return null; + } + } +} diff --git a/Switch_Toolbox_Library/Config.cs b/Switch_Toolbox_Library/Config.cs index 302a93d1..7ad1843d 100644 --- a/Switch_Toolbox_Library/Config.cs +++ b/Switch_Toolbox_Library/Config.cs @@ -270,6 +270,9 @@ namespace Toolbox.Library case "DisplayWindowPane": bool.TryParse(node.InnerText, out Runtime.LayoutEditor.DisplayWindowPane); break; + case "DisplayTextPane": + bool.TryParse(node.InnerText, out Runtime.LayoutEditor.DisplayTextPane); + break; case "LayoutDisplayGrid": bool.TryParse(node.InnerText, out Runtime.LayoutEditor.DisplayGrid); break; @@ -404,6 +407,7 @@ namespace Toolbox.Library layoutSettingsNode.AppendChild(createNode(doc, "DisplayBoundryPane", Runtime.LayoutEditor.DisplayBoundryPane.ToString())); layoutSettingsNode.AppendChild(createNode(doc, "DisplayPicturePane", Runtime.LayoutEditor.DisplayPicturePane.ToString())); layoutSettingsNode.AppendChild(createNode(doc, "DisplayWindowPane", Runtime.LayoutEditor.DisplayWindowPane.ToString())); + layoutSettingsNode.AppendChild(createNode(doc, "DisplayTextPane", Runtime.LayoutEditor.DisplayTextPane.ToString())); } private static void AppendDeveloperSettings(XmlDocument doc, XmlNode parentNode) diff --git a/Switch_Toolbox_Library/Forms/Editors/Animation/AnimationPanel.Designer.cs b/Switch_Toolbox_Library/Forms/Animation/AnimationPanel.Designer.cs similarity index 100% rename from Switch_Toolbox_Library/Forms/Editors/Animation/AnimationPanel.Designer.cs rename to Switch_Toolbox_Library/Forms/Animation/AnimationPanel.Designer.cs diff --git a/Switch_Toolbox_Library/Forms/Editors/Animation/AnimationPanel.cs b/Switch_Toolbox_Library/Forms/Animation/AnimationPanel.cs similarity index 99% rename from Switch_Toolbox_Library/Forms/Editors/Animation/AnimationPanel.cs rename to Switch_Toolbox_Library/Forms/Animation/AnimationPanel.cs index f784d190..df4f0530 100644 --- a/Switch_Toolbox_Library/Forms/Editors/Animation/AnimationPanel.cs +++ b/Switch_Toolbox_Library/Forms/Animation/AnimationPanel.cs @@ -289,7 +289,7 @@ namespace Toolbox.Library if (currentAnimation == null || totalFrame.Value <= 0) return; - currentFrameUpDown.Value = animationTrackBar.CurrentFrame; + currentFrameUpDown.Value = (decimal)animationTrackBar.CurrentFrame; } private void OnFrameAdvanced() @@ -301,7 +301,7 @@ namespace Toolbox.Library UpdateViewport(); } - private void SetAnimationsToFrame(int frameNum) + private void SetAnimationsToFrame(float frameNum) { if (currentAnimation == null) return; diff --git a/Switch_Toolbox_Library/Forms/Editors/Animation/AnimationPanel.resx b/Switch_Toolbox_Library/Forms/Animation/AnimationPanel.resx similarity index 100% rename from Switch_Toolbox_Library/Forms/Editors/Animation/AnimationPanel.resx rename to Switch_Toolbox_Library/Forms/Animation/AnimationPanel.resx diff --git a/Switch_Toolbox_Library/Forms/Editors/Animation/BoneAnimTimeline.cs b/Switch_Toolbox_Library/Forms/Animation/BoneAnimTimeline.cs similarity index 100% rename from Switch_Toolbox_Library/Forms/Editors/Animation/BoneAnimTimeline.cs rename to Switch_Toolbox_Library/Forms/Animation/BoneAnimTimeline.cs diff --git a/Switch_Toolbox_Library/Forms/Animation/Rewrite/AnimationPanel.Designer.cs b/Switch_Toolbox_Library/Forms/Animation/Rewrite/AnimationPanel.Designer.cs new file mode 100644 index 00000000..1ab461bc --- /dev/null +++ b/Switch_Toolbox_Library/Forms/Animation/Rewrite/AnimationPanel.Designer.cs @@ -0,0 +1,175 @@ +namespace Toolbox.Library +{ + partial class STAnimationPanel + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button2 = new System.Windows.Forms.Button(); + this.panel1 = new System.Windows.Forms.Panel(); + this.loopChkBox = new Toolbox.Library.Forms.STCheckBox(); + this.totalFrame = new System.Windows.Forms.NumericUpDown(); + this.currentFrameUpDown = new System.Windows.Forms.NumericUpDown(); + this.animationPlayBtn = new System.Windows.Forms.Button(); + this.stPanel1 = new Toolbox.Library.Forms.STPanel(); + this.animationTrackBar = new Toolbox.Library.Forms.TimeLine(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.totalFrame)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.currentFrameUpDown)).BeginInit(); + this.SuspendLayout(); + // + // button2 + // + this.button2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.button2.BackgroundImage = global::Toolbox.Library.Properties.Resources.arrowL; + this.button2.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.button2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.button2.Location = new System.Drawing.Point(17, 7); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(34, 21); + this.button2.TabIndex = 2; + this.button2.UseVisualStyleBackColor = false; + // + // panel1 + // + this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45))))); + this.panel1.Controls.Add(this.loopChkBox); + this.panel1.Controls.Add(this.totalFrame); + this.panel1.Controls.Add(this.currentFrameUpDown); + this.panel1.Controls.Add(this.button2); + this.panel1.Controls.Add(this.animationPlayBtn); + this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel1.Location = new System.Drawing.Point(0, 162); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(631, 32); + this.panel1.TabIndex = 4; + this.panel1.Paint += new System.Windows.Forms.PaintEventHandler(this.panel1_Paint); + // + // loopChkBox + // + this.loopChkBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.loopChkBox.AutoSize = true; + this.loopChkBox.CheckAlign = System.Drawing.ContentAlignment.TopLeft; + this.loopChkBox.Checked = true; + this.loopChkBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.loopChkBox.Location = new System.Drawing.Point(452, 8); + this.loopChkBox.Name = "loopChkBox"; + this.loopChkBox.Size = new System.Drawing.Size(50, 17); + this.loopChkBox.TabIndex = 5; + this.loopChkBox.Text = "Loop"; + this.loopChkBox.UseVisualStyleBackColor = true; + // + // totalFrame + // + this.totalFrame.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.totalFrame.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.totalFrame.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.totalFrame.ForeColor = System.Drawing.Color.White; + this.totalFrame.Location = new System.Drawing.Point(571, 10); + this.totalFrame.Name = "totalFrame"; + this.totalFrame.Size = new System.Drawing.Size(57, 16); + this.totalFrame.TabIndex = 4; + // + // currentFrameUpDown + // + this.currentFrameUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.currentFrameUpDown.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.currentFrameUpDown.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.currentFrameUpDown.ForeColor = System.Drawing.Color.White; + this.currentFrameUpDown.Location = new System.Drawing.Point(508, 10); + this.currentFrameUpDown.Name = "currentFrameUpDown"; + this.currentFrameUpDown.Size = new System.Drawing.Size(57, 16); + this.currentFrameUpDown.TabIndex = 3; + this.currentFrameUpDown.ValueChanged += new System.EventHandler(this.currentFrameUpDown_ValueChanged); + // + // animationPlayBtn + // + this.animationPlayBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.animationPlayBtn.BackgroundImage = global::Toolbox.Library.Properties.Resources.arrowR; + this.animationPlayBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.animationPlayBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.animationPlayBtn.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.animationPlayBtn.Location = new System.Drawing.Point(57, 7); + this.animationPlayBtn.Name = "animationPlayBtn"; + this.animationPlayBtn.Size = new System.Drawing.Size(31, 21); + this.animationPlayBtn.TabIndex = 1; + this.animationPlayBtn.UseVisualStyleBackColor = false; + this.animationPlayBtn.Click += new System.EventHandler(this.animationPlayBtn_Click); + // + // stPanel1 + // + this.stPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.stPanel1.Location = new System.Drawing.Point(0, 0); + this.stPanel1.Name = "stPanel1"; + this.stPanel1.Size = new System.Drawing.Size(631, 16); + this.stPanel1.TabIndex = 5; + // + // animationTrackBar + // + this.animationTrackBar.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.animationTrackBar.CurrentFrame = 0; + this.animationTrackBar.FrameCount = 1000; + this.animationTrackBar.Location = new System.Drawing.Point(0, 14); + this.animationTrackBar.Name = "animationTrackBar"; + this.animationTrackBar.Size = new System.Drawing.Size(631, 149); + this.animationTrackBar.TabIndex = 6; + // + // AnimationPanel + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.animationTrackBar); + this.Controls.Add(this.stPanel1); + this.Controls.Add(this.panel1); + this.Name = "AnimationPanel"; + this.Size = new System.Drawing.Size(631, 194); + this.Load += new System.EventHandler(this.AnimationPanel_Load); + this.Click += new System.EventHandler(this.AnimationPanel_Click); + this.Enter += new System.EventHandler(this.AnimationPanel_Enter); + this.Leave += new System.EventHandler(this.AnimationPanel_Leave); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.totalFrame)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.currentFrameUpDown)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button animationPlayBtn; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.NumericUpDown totalFrame; + private System.Windows.Forms.NumericUpDown currentFrameUpDown; + private Forms.STPanel stPanel1; + private Forms.STCheckBox loopChkBox; + private Forms.TimeLine animationTrackBar; + } +} \ No newline at end of file diff --git a/Switch_Toolbox_Library/Forms/Animation/Rewrite/AnimationPanel.cs b/Switch_Toolbox_Library/Forms/Animation/Rewrite/AnimationPanel.cs new file mode 100644 index 00000000..a68f515a --- /dev/null +++ b/Switch_Toolbox_Library/Forms/Animation/Rewrite/AnimationPanel.cs @@ -0,0 +1,439 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; +using System.IO; +using System.Diagnostics; +using Toolbox.Library.Forms; +using Toolbox.Library.Animations; + +namespace Toolbox.Library +{ + public partial class STAnimationPanel : STUserControl + { + private OpenTK.GLControl _viewport; + public virtual OpenTK.GLControl Viewport + { + get + { + if (_viewport == null) + _viewport = GetActiveViewport(); + + return _viewport; + } + } + + private OpenTK.GLControl GetActiveViewport() + { + var viewport = LibraryGUI.GetActiveViewport(); + if (viewport == null) + return null; + + if (viewport.GL_ControlModern != null) + return viewport.GL_ControlModern; + else + return viewport.GL_ControlLegacy; + } + + public void SetViewport(OpenTK.GLControl control) + { + _viewport = control; + } + + public PlayerState AnimationPlayerState = PlayerState.Stop; + + public enum PlayerState + { + Playing, + Pause, + Stop, + } + + public bool IsLooping + { + get { return loopChkBox.Checked; } + set { loopChkBox.Checked = value; } + } + + public bool IsPlaying + { + get + { + return AnimationPlayerState == PlayerState.Playing; + } + } + + private static STAnimationPanel _instance; + public static STAnimationPanel Instance { get { return _instance == null ? _instance = new STAnimationPanel() : _instance; } } + + //Animation Functions + public int AnimationSpeed = 60; + public float Frame = 0; + + // Frame rate control + private Thread renderThread; + private bool renderThreadIsUpdating = false; + public bool isOpen = true; + + public float FrameCount + { + get + { + float frameCount = 1; + for (int i = 0; i < currentAnimations.Count; i++) + frameCount = Math.Max(frameCount, currentAnimations[i].FrameCount); + + return frameCount; + } + } + + private List currentAnimations = new List(); + + public void AddAnimation(STAnimation animation, bool reset = true) + { + if (animation == null) + return; + + if (reset) + Reset(); + + Console.WriteLine($"Add anim " + animation.Name); + + currentAnimations.Add(animation); + + ResetModels(); + animation.Reset(); + totalFrame.Maximum = (decimal)FrameCount; + totalFrame.Value = (decimal)FrameCount; + currentFrameUpDown.Maximum = (decimal)FrameCount; + animationTrackBar.FrameCount = (float)FrameCount; + currentFrameUpDown.Value = 0; + + SetAnimationsToFrame(0); + UpdateViewport(); + } + + public void Reset() + { + currentAnimations.Clear(); + Frame = 0; + } + + public void ResetModels() + { + if (Viewport == null) + return; + + foreach (var anim in currentAnimations) { + if (anim is STSkeletonAnimation) + { + ((STSkeletonAnimation)anim).GetActiveSkeleton()?.reset(); + } + } + } + + public STAnimationPanel() + { + InitializeComponent(); + + BackColor = FormThemes.BaseTheme.FormBackColor; + ForeColor = FormThemes.BaseTheme.FormForeColor; + + animationTrackBar.BackColor = FormThemes.BaseTheme.FormBackColor; + animationTrackBar.ForeColor = FormThemes.BaseTheme.FormForeColor; + animationTrackBar.FrameChanged += new EventHandler(animationTrackBar_ValueChanged); + + /* animationTrackBar.ThumbInnerColor = FormThemes.BaseTheme.TimelineThumbColor; + animationTrackBar.ThumbOuterColor = FormThemes.BaseTheme.TimelineThumbColor; + + this.animationTrackBar.BarInnerColor = FormThemes.BaseTheme.FormBackColor; + this.animationTrackBar.BarPenColorBottom = FormThemes.BaseTheme.FormBackColor; + this.animationTrackBar.BarPenColorTop = FormThemes.BaseTheme.FormBackColor; + this.animationTrackBar.ElapsedInnerColor = FormThemes.BaseTheme.FormBackColor; + this.animationTrackBar.ElapsedPenColorBottom = FormThemes.BaseTheme.FormBackColor; + this.animationTrackBar.ElapsedPenColorTop = FormThemes.BaseTheme.FormBackColor; + */ + panel1.BackColor = FormThemes.BaseTheme.FormBackColor; + animationPlayBtn.BackColor = FormThemes.BaseTheme.FormBackColor; + button2.BackColor = FormThemes.BaseTheme.FormBackColor; + animationPlayBtn.ForeColor = FormThemes.BaseTheme.FormForeColor; + button2.ForeColor = FormThemes.BaseTheme.FormForeColor; + + totalFrame.ForeColor = FormThemes.BaseTheme.FormForeColor; + totalFrame.BackColor = FormThemes.BaseTheme.FormBackColor; + currentFrameUpDown.ForeColor = FormThemes.BaseTheme.FormForeColor; + currentFrameUpDown.BackColor = FormThemes.BaseTheme.FormBackColor; + + this.LostFocus += new System.EventHandler(AnimationPanel_LostFocus); + } + + private void Play() + { + AnimationPlayerState = PlayerState.Playing; + UpdateAnimationUI(); + animationTrackBar.Play(); + } + + private void Pause() + { + AnimationPlayerState = PlayerState.Stop; + UpdateAnimationUI(); + animationTrackBar.Stop(); + } + + private void Stop() + { + currentFrameUpDown.Value = 0; + AnimationPlayerState = PlayerState.Stop; + UpdateAnimationUI(); + } + + private void UpdateAnimationUI() + { + animationPlayBtn.BackgroundImage = IsPlaying ? Properties.Resources.stop + : Properties.Resources.arrowR; + } + + private void UpdateAnimationFrame() + { + if (IsPlaying) + { + if (currentFrameUpDown.InvokeRequired) + { + currentFrameUpDown.BeginInvoke((Action)(() => + { + AdvanceNextFrame(); + })); + } + else + { + AdvanceNextFrame(); + } + } + } + + private void AdvanceNextFrame() + { + if (animationTrackBar.CurrentFrame == animationTrackBar.FrameCount - 1) + { + if (IsLooping) + currentFrameUpDown.Value = 0; + else + Stop(); + } + else if (!animationTrackBar.Locked) + { + if (currentFrameUpDown.Value < totalFrame.Value) + currentFrameUpDown.Value++; + } + + currentFrameUpDown.Refresh(); + totalFrame.Refresh(); + } + + private void animationPlayBtn_Click(object sender, EventArgs e) + { + if (currentAnimations.Count == 0 || FrameCount <= 0) + return; + + if (AnimationPlayerState == PlayerState.Playing) + Pause(); + else + Play(); + } + + private void totalFrame_ValueChanged(object sender, EventArgs e) + { + if (currentAnimations.Count == 0) return; + + if (totalFrame.Value < 1) + { + totalFrame.Value = 1; + } + else + { + animationTrackBar.CurrentFrame = 0; + animationTrackBar.FrameCount = FrameCount; + } + } + private void UpdateViewport() + { + if (IsDisposed || Viewport == null || Viewport.IsDisposed || Viewport.Disposing) + return; + + if (Viewport.InvokeRequired) { + Viewport.Invoke((MethodInvoker)delegate { + // Running on the UI thread + Viewport.Invalidate(); + }); + } + else + Viewport.Invalidate(); + } + + private void nextButton_Click(object sender, EventArgs e) { + if (animationTrackBar.CurrentFrame < animationTrackBar.FrameCount) + animationTrackBar.CurrentFrame++; + } + private void prevButton_Click(object sender, EventArgs e) { + if (animationTrackBar.CurrentFrame > 0) + animationTrackBar.CurrentFrame--; + } + + private void animationTrackBar_Scroll(object sender, EventArgs e) + { + + } + + private void animationTrackBar_ValueChanged(object sender, EventArgs e) { + if (currentAnimations.Count == 0 || totalFrame.Value <= 0) + return; + + currentFrameUpDown.Value = (decimal)animationTrackBar.CurrentFrame; + } + + private void OnFrameAdvanced() + { + UpdateViewport(); + SetAnimationsToFrame(animationTrackBar.CurrentFrame); + + if (!renderThreadIsUpdating || !IsPlaying) + UpdateViewport(); + } + + private void SetAnimationsToFrame(float frameNum) + { + if (Viewport == null || currentAnimations.Count == 0) + return; + + foreach (var anim in currentAnimations) + { + if (frameNum > anim.FrameCount) + continue; + + float animFrameNum = frameNum; + + anim.SetFrame(animFrameNum); + anim.NextFrame(); + + //Add frames to the playing animation + anim.Frame += frameNum; + + //Reset it when it reaches the total frame count + if (anim.Frame >= anim.FrameCount && anim.Loop) + { + anim.Frame = 0; + } + } + } + + private void currentFrameUpDown_ValueChanged(object sender, EventArgs e) + { + if (currentFrameUpDown.Value > totalFrame.Value) + currentFrameUpDown.Value = totalFrame.Value; + + //Check locked state current frame will change during playing + if (!animationTrackBar.Locked) + { + animationTrackBar.CurrentFrame = (int)currentFrameUpDown.Value; + } + OnFrameAdvanced(); + } + + public void AnimationPanel_FormClosed() + { + isOpen = false; + Dispose(); + } + + private void AnimationPanel_Load(object sender, EventArgs e) + { + if (Viewport != null) + Viewport.VSync = Runtime.enableVSync; + + renderThread = new Thread(new ThreadStart(RenderAndAnimationLoop)); + renderThread.Start(); + } + + private void RenderAndAnimationLoop() + { + if (IsDisposed) + return; + // TODO: We don't really need two timers. + Stopwatch animationStopwatch = Stopwatch.StartNew(); + + + // Wait for UI to load before triggering paint events. + // int waitTimeMs = 500; + // Thread.Sleep(waitTimeMs); + + // UpdateViewport(); + + int frameUpdateInterval = 5; + int animationUpdateInterval = 16; + + while (isOpen) + { + // Always refresh the viewport when animations are playing. + if (renderThreadIsUpdating || IsPlaying) + { + if (animationStopwatch.ElapsedMilliseconds > animationUpdateInterval) + { + UpdateAnimationFrame(); + animationStopwatch.Restart(); + } + } + else + { + // Avoid wasting the CPU if we don't need to render anything. + Thread.Sleep(1); + } + } + } + + private void AnimationPanel_Enter(object sender, EventArgs e) + { + } + + private void AnimationPanel_LostFocus(object sender, EventArgs e) + { + renderThreadIsUpdating = false; + } + + private void AnimationPanel_Click(object sender, EventArgs e) + { + renderThreadIsUpdating = true; + } + + private void AnimationPanel_Leave(object sender, EventArgs e) + { + renderThreadIsUpdating = false; + } + public void ClosePanel() + { + ResetModels(); + + renderThread.Abort(); + renderThreadIsUpdating = false; + currentAnimations.Clear(); + isOpen = false; + Dispose(); + + } + + private void panel1_Paint(object sender, PaintEventArgs e) + { + + } + + private void colorSlider1_Scroll(object sender, ScrollEventArgs e) + { + + } + } +} diff --git a/Switch_Toolbox_Library/Forms/Editors/Animation/TimeLine.resx b/Switch_Toolbox_Library/Forms/Animation/Rewrite/AnimationPanel.resx similarity index 100% rename from Switch_Toolbox_Library/Forms/Editors/Animation/TimeLine.resx rename to Switch_Toolbox_Library/Forms/Animation/Rewrite/AnimationPanel.resx diff --git a/Switch_Toolbox_Library/Forms/Editors/Animation/TimeLine.Designer.cs b/Switch_Toolbox_Library/Forms/Animation/TimeLine.Designer.cs similarity index 100% rename from Switch_Toolbox_Library/Forms/Editors/Animation/TimeLine.Designer.cs rename to Switch_Toolbox_Library/Forms/Animation/TimeLine.Designer.cs diff --git a/Switch_Toolbox_Library/Forms/Editors/Animation/TimeLine.cs b/Switch_Toolbox_Library/Forms/Animation/TimeLine.cs similarity index 98% rename from Switch_Toolbox_Library/Forms/Editors/Animation/TimeLine.cs rename to Switch_Toolbox_Library/Forms/Animation/TimeLine.cs index e30415bf..3cf65357 100644 --- a/Switch_Toolbox_Library/Forms/Editors/Animation/TimeLine.cs +++ b/Switch_Toolbox_Library/Forms/Animation/TimeLine.cs @@ -62,7 +62,7 @@ namespace Toolbox.Library.Forms } } - public int CurrentFrame + public float CurrentFrame { get { return currentFrame; } set @@ -81,7 +81,7 @@ namespace Toolbox.Library.Forms } } - public int FrameCount + public float FrameCount { get { return lastFrame + 1; } set @@ -107,8 +107,8 @@ namespace Toolbox.Library.Forms public bool FollowCurrentFrame = true; - protected int currentFrame = 0; - protected int lastFrame = 1000; + protected float currentFrame = 0; + protected float lastFrame = 1000; protected double frameLeft = 0; protected double frameRight = 200; @@ -193,6 +193,7 @@ namespace Toolbox.Library.Forms e.Graphics.SetClip(new Rectangle(margin, 0, Width - margin, Height)); double currentFrameX = 20 + margin + (currentFrame - frameLeft) * (Width - 40 - margin) / (frameRight - frameLeft); + base.OnPaint(e); e.Graphics.DrawLine(pen2, new Point((int)currentFrameX, barHeight), new Point((int)currentFrameX, Height)); diff --git a/Switch_Toolbox_Library/Forms/Animation/TimeLine.resx b/Switch_Toolbox_Library/Forms/Animation/TimeLine.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/Switch_Toolbox_Library/Forms/Animation/TimeLine.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Switch_Toolbox_Library/IO/Bits/Bit.cs b/Switch_Toolbox_Library/IO/Bits/Bit.cs index ea8b9ca8..a9ef662c 100644 --- a/Switch_Toolbox_Library/IO/Bits/Bit.cs +++ b/Switch_Toolbox_Library/IO/Bits/Bit.cs @@ -12,7 +12,6 @@ namespace Toolbox.Library.IO public static uint ExtractBits(uint val, int numBits, int startBit) { uint mask = 0; - for (int i = startBit; i < startBit + numBits; i++) mask |= (0x80000000 >> i); diff --git a/Switch_Toolbox_Library/Rendering/RenderableTex.cs b/Switch_Toolbox_Library/Rendering/RenderableTex.cs index 904e0dd1..e1fb98fa 100644 --- a/Switch_Toolbox_Library/Rendering/RenderableTex.cs +++ b/Switch_Toolbox_Library/Rendering/RenderableTex.cs @@ -107,6 +107,13 @@ namespace Toolbox.Library.Rendering return tex; } + public void UpdateFromBitmap(Bitmap bitmap) + { + width = bitmap.Width; + height = bitmap.Height; + TexID = GenerateOpenGLTexture(this, bitmap); + } + private bool UseMipmaps = false; private bool UseOpenGLDecoder = true; public void LoadOpenGLTexture(STGenericTexture GenericTexture, int ArrayStartIndex = 0, bool LoadArrayLevels = false) diff --git a/Switch_Toolbox_Library/Runtime.cs b/Switch_Toolbox_Library/Runtime.cs index 068b6573..22813a55 100644 --- a/Switch_Toolbox_Library/Runtime.cs +++ b/Switch_Toolbox_Library/Runtime.cs @@ -66,6 +66,7 @@ namespace Toolbox.Library { public static bool IsGamePreview = false; public static bool DisplayNullPane = true; + public static bool DisplayTextPane = true; public static bool DisplayBoundryPane = true; public static bool DisplayPicturePane = true; public static bool DisplayWindowPane = true; @@ -73,6 +74,7 @@ namespace Toolbox.Library public static bool DisplayScissorPane = true; public static bool DisplayGrid = true; + public static bool UseOrthographicView = true; public static Color BackgroundColor = Color.FromArgb(130, 130, 130); diff --git a/Switch_Toolbox_Library/Toolbox_Library.csproj b/Switch_Toolbox_Library/Toolbox_Library.csproj index 6d5c20d2..692092ba 100644 --- a/Switch_Toolbox_Library/Toolbox_Library.csproj +++ b/Switch_Toolbox_Library/Toolbox_Library.csproj @@ -199,7 +199,12 @@ + + + + + @@ -245,6 +250,12 @@ + + UserControl + + + AnimationPanel.cs + Component @@ -397,7 +408,7 @@ STSaveLogDialog.cs - + UserControl @@ -603,10 +614,10 @@ TextEditorForm.cs - + UserControl - + TimeLine.cs @@ -772,10 +783,10 @@ - + UserControl - + AnimationPanel.cs @@ -865,6 +876,9 @@ + + AnimationPanel.cs + ArchiveFilePanel.cs @@ -936,7 +950,7 @@ STErrorDialog.cs - + AnimationPanel.cs @@ -1026,7 +1040,7 @@ TextEditorForm.cs - + TimeLine.cs @@ -1305,6 +1319,7 @@ + diff --git a/Switch_Toolbox_Library/Util/Util.cs b/Switch_Toolbox_Library/Util/Util.cs index 1a1eac6f..7d776d8c 100644 --- a/Switch_Toolbox_Library/Util/Util.cs +++ b/Switch_Toolbox_Library/Util/Util.cs @@ -12,6 +12,11 @@ namespace Toolbox.Library { public class Utils { + public static bool CompareNoExtension(string a, string b) + { + return (Path.GetFileNameWithoutExtension(a) == Path.GetFileNameWithoutExtension(b)); + } + public static byte[] CreateMD5Hash(string filename) { using (var md5 = System.Security.Cryptography.MD5.Create()) diff --git a/Toolbox/Shader/Layout/Bflyt.frag b/Toolbox/Shader/Layout/Bflyt.frag index 663c8759..154cc02a 100644 --- a/Toolbox/Shader/Layout/Bflyt.frag +++ b/Toolbox/Shader/Layout/Bflyt.frag @@ -2,20 +2,148 @@ uniform vec4 blackColor; uniform vec4 whiteColor; -uniform int hasTexture0; + uniform int debugShading; uniform int numTextureMaps; uniform sampler2D textures0; +uniform sampler2D textures1; +uniform sampler2D textures2; + +uniform int hasTexture0; +uniform int hasTexture1; +uniform int hasTexture2; + +uniform int tevStage0RGB; +uniform int tevStage1RGB; +uniform int tevStage2RGB; +uniform int tevStage3RGB; +uniform int tevStage4RGB; +uniform int tevStage5RGB; + +uniform int tevStage0A; +uniform int tevStage1A; +uniform int tevStage2A; +uniform int tevStage3A; +uniform int tevStage4A; +uniform int tevStage5A; + +uniform int tevTexMode; + +uniform int ThresholdingAlphaInterpolation; +uniform int numTevStages; + +uniform vec4 IndirectMat0; +uniform vec4 IndirectMat1; + uniform sampler2D uvTestPattern; -in vec2 uv0; -in vec4 vertexColor0; +in vec4 VertexColor; +in vec2 TexCoord0; +in vec2 TexCoord1; +in vec2 TexCoord2; + +// Channel Toggles +uniform int RedChannel; +uniform int GreenChannel; +uniform int BlueChannel; +uniform int AlphaChannel; out vec4 fragColor; +const int CombineModeMask = (1 << 5) - 1; + +#define gamma 2.2 + +vec3 ColorOP(int type, vec4 color) +{ + switch (type) + { + case 0: return color.rgb; + case 1: return vec3(1) - color.rgb; + case 2: return color.aaa; + case 3: return vec3(1) - color.aaa; + case 4: return color.rrr; + case 5: return vec3(1) - color.rrr; + case 6: return color.ggg; + case 7: return vec3(1) - color.ggg; + case 8: return color.bbb; + case 9: return vec3(1) - color.bbb; + default: return color.rgb; + } +} + +float AlphaOP(int type, vec4 color) +{ + switch (type) + { + case 0: return color.a; + case 1: return 1.0 - color.a; + case 2: return color.r; + case 3: return 1.0 - color.r; + case 4: return color.g; + case 5: return 1.0 - color.g; + case 6: return color.b; + case 7: return 1.0 - color.b; + default: return color.a; + } +} + +float GetComponent(int Type, vec4 Texture) +{ + switch (Type) + { + case 0: return Texture.r; + case 1: return Texture.g; + case 2: return Texture.b; + case 3: return Texture.a; + case 4: return 1; + case 5: return 0; + default: return 1; + } +} + +vec3 Interpolate(vec4 j1, vec4 j2, vec4 j3) +{ + return j1.rgb * j3.rgb + j2.rgb * (vec3(1.0) - j3.rgb); +} + +vec4 IndTexSingle(vec4 color, sampler2D tex, vec2 texCoord) +{ + float a = color.a; + vec2 indirect; + indirect.x = dot(vec4(color.xyz,1.0), IndirectMat0); + indirect.y = dot(vec4(color.xyz,1.0), IndirectMat1); + + vec4 outColor = texture2D(tex, texCoord + indirect); + outColor.a = min(outColor.a, color.a); + return outColor; +} + +vec3 ColorCombiner(int type, vec4 j1, vec4 j2, bool maxA) +{ + switch (type) + { + case 0: return j1.rgb * j1.a + j2.rgb * (1.0 - j1.a); //Replace + case 1: return j1.rgb * j2.rgb; //Modulate + case 2: return j1.rgb + j2.rgb * j1.a; //Add + case 3: return j1.rgb + j2.rgb - vec3(0.5); //AddSigned + case 4: return j1.rgb * j2.rgb; //Interpolate + case 5: return j1.rgb - j2.rgb * j1.a; //Subtract + case 6: return clamp(j2.rgb / (1.00001 - j1.rgb * j1.a), 0.0, 1.0); //AddMultiplicate + case 7: return clamp(vec3(1.0) - (vec3(1.00001 - j2.rgb) / j1.rgb), 0.0, 1.0); //MultiplcateAdd + case 8: return j1.rgb; //Overlay + case 9: return j1.rgb; //Indirect + case 10: return j1.rgb; //BlendIndirect + case 11: return j1.rgb; //EachIndirect + default: return j1.rgb; + } +} + void main() { + fragColor = vec4(1); + vec4 textureMap0 = vec4(1); vec4 textureMap1 = vec4(1); vec4 textureMap2 = vec4(1); @@ -23,22 +151,81 @@ void main() if (numTextureMaps > 0) { if (hasTexture0 == 1) - textureMap0 = texture2D(textures0, uv0); + textureMap0 = texture2D(textures0, TexCoord0.st); + if (hasTexture1 == 1) + textureMap1 = texture2D(textures1, TexCoord0.st); + if (hasTexture2 == 1) + textureMap2 = texture2D(textures1, TexCoord0.st); } - if (debugShading == 0) { - vec4 colorBlend = textureMap0 * whiteColor; - fragColor = vertexColor0 * colorBlend; + // Convert to sRGB. + vec3 whiteColorSRGB = pow(whiteColor.rgb, vec3(1.0 / gamma)); + + vec3 whiteInterpolation = whiteColorSRGB.rgb * textureMap0.rgb; + vec3 blackInterpolation = (vec3(1) - textureMap0.rgb) * blackColor.rgb; + + //vec3 colorBlend = whiteInterpolation + blackInterpolation; + vec3 colorBlend = Interpolate(vec4(whiteColorSRGB.rgb, 1), blackColor, textureMap0); + + float alpha = textureMap0.a * whiteColor.a; + + //More that 1 texture uses texture combiners + vec4 j1; + vec4 j2; + vec4 j3; + vec4 fragOutput; + vec4 previousStage = vec4(1); + if (numTextureMaps > 1 && numTevStages > 1) + { + for (int i = 0; i < numTevStages; i++) + { + //Todo what determines the tev sources??? + if (i == 0) + { + j1 = textureMap0; + j2 = textureMap1; + j3 = vec4(1); + } + if (i == 1) + { + + } + if (numTextureMaps > 2 && tevStage0RGB == 9) + { + j3 = textureMap2; + } + vec4 comb1 = vec4(ColorCombiner(tevStage0RGB, j1, j2, false), 1); + previousStage = comb1; + } + + fragOutput = previousStage; + } + else + { + if (ThresholdingAlphaInterpolation != 0) + { + //Todo these need to interpolate and be smoother + if (textureMap0.a >= whiteColor.a) alpha = 1.0; + if (textureMap0.a <= blackColor.a) alpha = 0.0; + // if (blackColor.a < alpha && alpha < whiteColor.a) + // alpha = mix(0.0, 1.0, textureMap0.a); + } + + fragOutput = vec4(colorBlend,alpha);; + } + + fragOutput *= VertexColor; + fragColor = fragOutput; } else if (debugShading == 5) fragColor = vec4(textureMap0.rgb, 1); else if (debugShading == 1) - fragColor = vertexColor0; + fragColor = VertexColor; else if (debugShading == 2) fragColor = whiteColor; else if (debugShading == 3) fragColor = blackColor; else if (debugShading == 4) - fragColor = texture2D(uvTestPattern, uv0); + fragColor = texture2D(uvTestPattern, TexCoord0.st); } \ No newline at end of file diff --git a/Toolbox/Shader/Layout/Bflyt.vert b/Toolbox/Shader/Layout/Bflyt.vert index d6e764a8..e88d2e83 100644 --- a/Toolbox/Shader/Layout/Bflyt.vert +++ b/Toolbox/Shader/Layout/Bflyt.vert @@ -1,10 +1,10 @@ #version 330 -layout(location = 0) in vec3 position; -layout(location = 1) in vec4 color; -layout(location = 2) in vec2 texCoord0; -layout(location = 3) in vec2 texCoord1; -layout(location = 4) in vec2 texCoord2; +in vec2 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; +in vec2 vTexCoord1; +in vec2 vTexCoord2; uniform mat4 modelViewMatrix; uniform vec2 uvScale0; @@ -12,7 +12,10 @@ uniform vec2 uvRotate0; uniform vec2 uvTranslate0; uniform int flipTexture; -out vec2 uv0; +out vec4 VertexColor; +out vec2 TexCoord0; +out vec2 TexCoord1; +out vec2 TexCoord2; vec2 rotateUV(vec2 uv, float rotation) { @@ -43,7 +46,11 @@ vec2 SetFlip(vec2 tex) void main() { - vec2 texCoord0Transformed = uvScale0 * texCoord0.xy + uvTranslate0; - uv0 = SetFlip(texCoord0Transformed); - gl_Position = modelViewMatrix * vec4(position,1); + vec2 texCoord0Transformed = uvScale0 * vTexCoord0.xy + uvTranslate0; + TexCoord0 = SetFlip(texCoord0Transformed); + TexCoord1 = SetFlip(texCoord0Transformed); + TexCoord2 = SetFlip(texCoord0Transformed); + + VertexColor = vColor; + gl_Position = modelViewMatrix * vec4(vPosition, 0, 1); } \ No newline at end of file diff --git a/Toolbox/Shader/Layout/Legacy/Bflyt.frag b/Toolbox/Shader/Layout/Legacy/Bflyt.frag index 2014bc6d..94c7c34d 100644 --- a/Toolbox/Shader/Layout/Legacy/Bflyt.frag +++ b/Toolbox/Shader/Layout/Legacy/Bflyt.frag @@ -12,12 +12,101 @@ uniform int hasTexture0; uniform int hasTexture1; uniform int hasTexture2; +uniform int tevStage0RGB; +uniform int tevStage1RGB; +uniform int tevStage2RGB; +uniform int tevStage3RGB; +uniform int tevStage4RGB; +uniform int tevStage5RGB; + +uniform int tevStage0A; +uniform int tevStage1A; +uniform int tevStage2A; +uniform int tevStage3A; +uniform int tevStage4A; +uniform int tevStage5A; + uniform int ThresholdingAlphaInterpolation; +uniform int numTevStages; uniform sampler2D uvTestPattern; #define gamma 2.2 +vec3 ColorOP(int type, vec4 color) +{ + switch (type) + { + case 0: return color.rgb; + case 1: return vec3(1) - color.rgb; + case 2: return color.aaa; + case 3: return vec3(1) - color.aaa; + case 4: return color.rrr; + case 5: return vec3(1) - color.rrr; + case 6: return color.ggg; + case 7: return vec3(1) - color.ggg; + case 8: return color.bbb; + case 9: return vec3(1) - color.bbb; + default: return color.rgb; + } +} + +float AlphaOP(int type, vec4 color) +{ + switch (type) + { + case 0: return color.a; + case 1: return 1.0 - color.a; + case 2: return color.r; + case 3: return 1.0 - color.r; + case 4: return color.g; + case 5: return 1.0 - color.g; + case 6: return color.b; + case 7: return 1.0 - color.b; + default: return color.a; + } +} + +vec3 ColorCombiner(int type, vec4 j1, vec4 j2, vec4 j3) +{ + switch (type) + { + case 0: return j1.rgb; //Replace + case 1: return j1.rgb * j2.rgb; //Modulate + case 2: return j1.rgb + j2.rgb; //Add + case 3: return j1.rgb + j2.rgb - vec3(0.5); //AddSigned + case 4: return j1.rgb * j3.rgb + j2.rgb * (vec3(1.0) - j3.rgb); //Interpolate + case 5: return j1.rgb - j2.rgb; //Subtract + case 6: return clamp(j1.rgb + j2.rgb, 0.0, 1.0) * j3.rgb; //AddMultiplicate + case 7: return (j1.rgb * j2.rgb) + j3.rgb; //MultiplcateAdd + case 8: return j1.rgb; //Overlay + case 9: return j1.rgb; //Indirect + case 10: return j1.rgb; //BlendIndirect + case 11: return j1.rgb; //EachIndirect + default: return j1.rgb; + } +} + +float AlphaCombiner(int type, vec4 j1, vec4 j2, vec4 j3) +{ + switch (type) + { + case 0: return j1.a; //Replace + case 1: return j1.a * j2.a; //Modulate + case 2: return j1.a + j2.a; //Add + case 3: return j1.a + j2.a - 0.5; //AddSigned + case 4: return j3.a + j2.a * (1.0 - j3.a); //Interpolate + case 5: return j1.a - j2.a; //Subtract + case 6: return clamp(j1.a + j2.a, 0.0, 1.0) * j3.a; //AddMultiplicate + case 7: return (j1.a * j2.a) + j3.a; //MultiplcateAdd + case 8: return j1.a; //Overlay + case 9: return j1.a; //Indirect + case 10: return j1.a; //BlendIndirect + case 11: return j1.a; //EachIndirect + default: return j1.a; + } +} + void main() { vec4 textureMap0 = vec4(1); @@ -28,8 +117,11 @@ void main() { if (hasTexture0 == 1) textureMap0 = texture2D(textures0, gl_TexCoord[0].st); + if (hasTexture1 == 1) + textureMap1 = texture2D(textures1, gl_TexCoord[0].st); + if (hasTexture2 == 1) + textureMap2 = texture2D(textures1, gl_TexCoord[0].st); } - if (debugShading == 0) { // Convert to sRGB. @@ -37,19 +129,50 @@ void main() vec3 whiteInterpolation = whiteColorSRGB.rgb * textureMap0.rgb; vec3 blackInterpolation = (vec3(1) - textureMap0.rgb) * blackColor.rgb; + + //vec3 colorBlend = whiteInterpolation + blackInterpolation; + vec3 colorBlend = ColorCombiner(4, vec4(whiteColorSRGB.rgb, 1), blackColor, textureMap0); - vec3 colorBlend = whiteInterpolation + blackInterpolation; float alpha = textureMap0.a * whiteColor.a; - if (ThresholdingAlphaInterpolation != 0) + + //More that 1 texture uses texture combiners + vec4 j1; + vec4 j2; + vec4 j3; + vec4 fragOutput; + vec4 previousStage = vec4(1); + if (numTextureMaps > 1 && numTevStages > 4) { - //Todo these need to interpolate and be smoother - if (textureMap0.a >= whiteColor.a) alpha = 1.0; - if (textureMap0.a <= blackColor.a) alpha = 0.0; - // if (blackColor.a < alpha && alpha < whiteColor.a) - // alpha = mix(0.0, 1.0, textureMap0.a); + for (int i = 0; i < numTevStages; i++) + { + j1 = textureMap0; + j2 = textureMap1; + j3 = vec4(1); + if (numTextureMaps > 2) + j3 = textureMap2; + + vec4 comb1 = vec4(ColorCombiner(tevStage0RGB, j1, j2, j3), AlphaCombiner(tevStage0A, j1,j2,j3)); + previousStage = comb1; + } + + fragOutput = previousStage; + } + else + { + if (ThresholdingAlphaInterpolation != 0) + { + //Todo these need to interpolate and be smoother + if (textureMap0.a >= whiteColor.a) alpha = 1.0; + if (textureMap0.a <= blackColor.a) alpha = 0.0; + // if (blackColor.a < alpha && alpha < whiteColor.a) + // alpha = mix(0.0, 1.0, textureMap0.a); + } + + fragOutput = vec4(colorBlend,alpha);; } - gl_FragColor = gl_Color * vec4(colorBlend,alpha); + fragOutput *= gl_Color; + gl_FragColor = fragOutput; } else if (debugShading == 5) gl_FragColor = vec4(textureMap0.rgb, 1); diff --git a/Toolbox/Shader/Layout/Legacy/Bflyt.vert b/Toolbox/Shader/Layout/Legacy/Bflyt.vert index 47428ffa..4e6f2803 100644 --- a/Toolbox/Shader/Layout/Legacy/Bflyt.vert +++ b/Toolbox/Shader/Layout/Legacy/Bflyt.vert @@ -2,6 +2,9 @@ uniform vec2 uvRotate0; uniform vec2 uvTranslate0; uniform int flipTexture; +uniform mat4 rotationMatrix; +uniform int texCoords0GenType; +uniform int texCoords0Source; vec2 rotateUV(vec2 uv, float rotation) { @@ -30,10 +33,27 @@ vec2 SetFlip(vec2 tex) return outTexCoord; } +vec2 SetTexCoordType(int type, vec2 tex) +{ + vec2 outTexCoord = tex; + switch (type) + { + case 0: return tex; //Tex0 + case 1: return tex; //Tex1 + case 2: return tex; //Tex2 + case 3: return tex; //Ortho + case 4: return tex; //Pane based + case 5: return tex; //Proj + } + return outTexCoord; +} + void main() { gl_FrontColor = gl_Color; vec2 texCoord0 = vec2(0.5, 0.5) + uvScale0 * (gl_MultiTexCoord0.xy + (uvTranslate0 / uvScale0 - 0.5)); + texCoord0 = SetTexCoordType(texCoords0GenType, texCoord0); + gl_TexCoord[0].st = SetFlip(texCoord0); - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_Position = gl_ModelViewProjectionMatrix * rotationMatrix * gl_Vertex; } \ No newline at end of file