1
0
mirror of synced 2024-11-28 01:10:51 +01:00

A big layout editor update.

Added support for previewing layout animations.
This includes pane SRT, tex SRT, material color (white/black blending), texture patterns, pane visibilty, and vertex colors.
Added textbox previewing.  The scaling will be off, and more features is planned (caching font data to disk for faster loading, improve rendering, etc).
Rotations now render correctly for X/Y axis.
Added game window preview. This removes any editor only drawn objects and also fits the layout to the screen (aka root pane) size.
Add support for rendering custom blending with layout materials.
Add support for loading character icons for mk8d. These are hardcoded and have been manually set. Note these will only load if within the menu.szs.
This commit is contained in:
KillzXGaming 2019-09-28 17:27:48 -04:00
parent b75e0e3994
commit 644d94090f
55 changed files with 3834 additions and 647 deletions

View File

@ -15,7 +15,7 @@ using System.Drawing.Imaging;
namespace FirstPlugin
{
public class BFFNT : IFileFormat, IEditor<BffntEditor>, IConvertableTextFormat
public class BFFNT : BXFNT, IFileFormat, IEditor<BffntEditor>, 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

View File

@ -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;
}
}
}

View File

@ -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);
}
/// <summary>
/// Layout animation group that stores multiple tag entries.
/// These map to either pane or materials
/// </summary>
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)
{
}
}
}

View File

@ -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<KeyFrame> keyFrames)
{
for (int i = 0; i < keyFrames?.Count; i++)
KeyFrames.Add(new LytKeyFrame(keyFrames[i]));
}
}
}

View File

@ -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
{
/// <summary>
/// An animation controller from a BRLYT/BCLYT/BFLYT file.
/// </summary>
public class LytAnimation : STAnimation
{
BxlytHeader parentLayout = null;
public List<string> Textures = new List<string>();
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)
{
}
}
}

View File

@ -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;
}
}

View File

@ -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<string, int> attrib in attributes)
GL.EnableVertexAttribArray(attrib.Value);
}
public void DisableVertexAttributes()
{
foreach (KeyValuePair<string, int> 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() { }

View File

@ -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<string, STGenericTexture> Textures)
public static void DrawPictureBox(BasePane pane, bool gameWindow, byte effectiveAlpha, Dictionary<string, STGenericTexture> 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<BasePane> SelectedPanes)
public static void DrawBoundryPane(BasePane pane, bool gameWindow, byte effectiveAlpha, List<BasePane> 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<BasePane> SelectedPanes)
public static void DrawAlignmentPane(BasePane pane, bool gameWindow, byte effectiveAlpha, List<BasePane> 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<BasePane> SelectedPanes)
public static void DrawScissorPane(BasePane pane, bool gameWindow, byte effectiveAlpha, List<BasePane> 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<string, STGenericTexture> Textures, List<BasePane> 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<string, STGenericTexture> Textures)
public static void DrawWindowPane(BasePane pane,bool gameWindow, byte effectiveAlpha, Dictionary<string, STGenericTexture> 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<string, STGenericTexture> textures)
private static void SetupShaders(BasePane pane, BxlytMaterial mat, Dictionary<string, STGenericTexture> 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);
}
}
}

View File

@ -11,7 +11,7 @@ using SharpYaml.Serialization;
namespace LayoutBXLYT
{
public class BFLAN : IEditorForm<LayoutEditor>, IFileFormat, IConvertableTextFormat
public class BFLAN : BXLAN, IEditorForm<LayoutEditor>, 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<SectionCommon> UnknownSections = new List<SectionCommon>();
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<KeyType>(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) { }
}
}
}

View File

@ -266,9 +266,6 @@ namespace LayoutBXLYT.Cafe
private ushort ByteOrderMark;
private ushort HeaderSize;
[Browsable(false)]
public Dictionary<string, BasePane> PaneLookup = new Dictionary<string, BasePane>();
[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;

View File

@ -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<string, STGenericTexture> textures)
public void SetMaterials(BasePane pane, Dictionary<string, STGenericTexture> 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);
}
}

View File

@ -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<GfxAlphaFunction>(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);
}

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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)

View File

@ -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 {

View File

@ -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<string, STGenericTexture> textures)
public void SetMaterials(BasePane pane, Dictionary<string, STGenericTexture> 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();

View File

@ -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<LPATarget, float> PaneSRT = new Dictionary<LPATarget, float>();
public Dictionary<LVCTarget, float> PaneVertexColors = new Dictionary<LVCTarget, float>();
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<BxlytWindowFrame> 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<KeyFrame> KeyFrames = new List<KeyFrame>();
public BxlanPaiTagEntry(FileReader reader, BxlanHeader header)
{
long startPos = reader.Position;
Index = reader.ReadByte();
AnimationTarget = reader.ReadByte();
CurveType = reader.ReadEnum<CurveType>(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<string, BasePane> PaneLookup = new Dictionary<string, BasePane>();
[Browsable(false)]
public BasePane RootPane { get; set; }
@ -811,10 +1135,30 @@ namespace LayoutBXLYT
{
return new List<BxlytMaterial>();
}
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<LMCTarget, float> MaterialColors = new Dictionary<LMCTarget, float>();
public Dictionary<LTPTarget, string> TexturePatterns = new Dictionary<LTPTarget, string>();
public Dictionary<LTSTarget, float> TextureSRTS = new Dictionary<LTSTarget, float>();
public Dictionary<LIMTarget, float> IndTextureSRTS = new Dictionary<LIMTarget, float>();
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
{

View File

@ -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
{
/// <summary>
/// A mapper which applies hard coded panes to the proper place
/// </summary>
public class LayoutCustomPaneMapper
{
private bool Loaded = false;
//MK8 character select
public void LoadMK8DCharaSelect(Dictionary<string, STGenericTexture> 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;
}
}
}
}

View File

@ -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<Vertex>(BufferTarget.ArrayBuffer,
new IntPtr(Vertices.Length * Vertex.SizeInBytes),

View File

@ -11,7 +11,7 @@ using SharpYaml.Serialization;
namespace LayoutBXLYT
{
public class BRLAN : IEditorForm<LayoutEditor>, IFileFormat, IConvertableTextFormat
public class BRLAN : BXLAN, IEditorForm<LayoutEditor>, 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<SectionCommon> UnknownSections = new List<SectionCommon>();
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<KeyType>(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) { }
}
}
}

View File

@ -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<TextureRef> TextureMaps { get; set; }
public List<TextureTransform> TextureTransforms { get; set; }
private uint flags;
@ -884,7 +891,7 @@ namespace LayoutBXLYT
public Material()
{
TextureMaps = new List<TextureRef>();
TextureMaps = new TextureRef[0];
TextureTransforms = new List<TextureTransform>();
}
@ -892,7 +899,6 @@ namespace LayoutBXLYT
{
ParentLayout = header;
TextureMaps = new List<TextureRef>();
TextureTransforms = new List<TextureTransform>();
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)

View File

@ -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<string, STGenericTexture> textures)
public void SetMaterials(BasePane pane, Dictionary<string, STGenericTexture> 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));

View File

@ -220,6 +220,7 @@
<Compile Include="FileFormats\DKCTF\Common.cs" />
<Compile Include="FileFormats\DKCTF\MSBT.cs" />
<Compile Include="FileFormats\DKCTF\PAK.cs" />
<Compile Include="FileFormats\Font\BXFNT.cs" />
<Compile Include="FileFormats\HedgehogEngine\HeaderCommon.cs" />
<Compile Include="FileFormats\HedgehogEngine\HedgeModel.cs" />
<Compile Include="FileFormats\HedgehogEngine\PACx.cs" />
@ -296,6 +297,9 @@
<Compile Include="FileFormats\Font\BFTTF.cs" />
<Compile Include="FileFormats\HyruleWarriors\G1M\G1M.cs" />
<Compile Include="FileFormats\HyruleWarriors\LINKDATA.cs" />
<Compile Include="FileFormats\Layout\Animation\LytAnimGroup.cs" />
<Compile Include="FileFormats\Layout\Animation\LytAnimTrack.cs" />
<Compile Include="FileFormats\Layout\Animation\LytKeyFrame.cs" />
<Compile Include="FileFormats\Layout\BxlytShader.cs" />
<Compile Include="FileFormats\Layout\BxlytToGL.cs" />
<Compile Include="FileFormats\Layout\CAFE\FLAN.cs" />
@ -311,6 +315,8 @@
<Compile Include="FileFormats\Layout\CTR\BCLYT.cs" />
<Compile Include="FileFormats\Layout\CAFE\FLYT.cs" />
<Compile Include="FileFormats\Layout\CTR\BclytShader.cs" />
<Compile Include="FileFormats\Layout\Animation\LytAnimation.cs" />
<Compile Include="FileFormats\Layout\LayoutCustomPaneMapper.cs" />
<Compile Include="FileFormats\Layout\LayoutTextureLoader.cs" />
<Compile Include="FileFormats\Layout\PaneTreeWrapper.cs" />
<Compile Include="FileFormats\Layout\Common.cs" />
@ -385,7 +391,7 @@
<DependentUpon>LayoutTextureList.cs</DependentUpon>
</Compile>
<Compile Include="GUI\BFLYT\LayoutViewer.cs">
<SubType>Form</SubType>
<SubType>UserControl</SubType>
</Compile>
<Compile Include="GUI\BFLYT\LayoutViewer.Designer.cs">
<DependentUpon>LayoutViewer.cs</DependentUpon>

View File

@ -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;
}
}

View File

@ -25,6 +25,10 @@ namespace LayoutBXLYT
/// </summary>
public static bool UseLegacyGL = true;
public LayoutViewer GamePreviewWindow;
private LayoutCustomPaneMapper CustomMapper;
private Dictionary<string, STGenericTexture> Textures;
public List<BxlytHeader> LayoutFiles = new List<BxlytHeader>();
@ -45,6 +49,7 @@ namespace LayoutBXLYT
public LayoutEditor()
{
InitializeComponent();
CustomMapper = new LayoutCustomPaneMapper();
Textures = new Dictionary<string, STGenericTexture>();
@ -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();
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -16,7 +16,7 @@ using LayoutBXLYT.Cafe;
namespace LayoutBXLYT
{
public partial class LayoutViewer : LayoutDocked
public partial class LayoutViewer : LayoutControlDocked
{
public List<BasePane> SelectedPanes = new List<BasePane>();
@ -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<BxlytHeader> LayoutFiles = new List<BxlytHeader>();
private Dictionary<string, STGenericTexture> Textures;
private void glControl1_Load(object sender, EventArgs e)
@ -47,31 +51,44 @@ namespace LayoutBXLYT
UpdateViewport();
}
public LayoutViewer(BxlytHeader bxlyt, Dictionary<string, STGenericTexture> textures)
public GLControl GetGLControl() => glControl1;
public LayoutViewer(LayoutEditor editor, BxlytHeader bxlyt, Dictionary<string, STGenericTexture> 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);

View File

@ -9,6 +9,8 @@ namespace FirstPlugin
{
public class PluginRuntime
{
public static List<BXFNT> BxfntFiles = new List<BXFNT>();
public static List<SARC> SarcArchives = new List<SARC>();
public class MaterialReplace

View File

@ -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;
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Toolbox.Library.Animations
{
/// <summary>
/// Represents a group that stores animation tracks and sub groups.
/// </summary>
public class STAnimGroup
{
public string Name { get; set; }
public List<STAnimGroup> SubAnimGroups = new List<STAnimGroup>();
}
}

View File

@ -6,14 +6,84 @@ using System.Threading.Tasks;
namespace Toolbox.Library.Animations
{
public enum STInterpoaltionType
{
Constant,
Step,
Linear,
Hermite,
}
/// <summary>
/// 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
/// </summary>
public enum STLoopMode
{
Repeat,
Mirror,
Clamp,
}
/// <summary>
/// Represents a class for animating a skeleton
/// </summary>
public class STSkeletonAnimation
public class STAnimation
{
/// <summary>
/// The total amount of frames to play in the animation
/// The name of the animation.
/// </summary>
public uint FrameCount { get; set; }
public string Name { get; set; }
/// <summary>
/// The frame to start playing the animation.
/// </summary>
public float StartFrame { get; set; }
/// <summary>
/// The current frame of the animation.
/// </summary>
public float Frame { get; set; }
/// <summary>
/// The total amount of frames to play in the animation.
/// </summary>
public float FrameCount { get; set; }
/// <summary>
/// Whether the animation will loop or not after
/// the playback rearches the total frame count.
/// </summary>
public bool Loop { get; set; }
/// <summary>
/// The step value when a frame advances.
/// </summary>
public float Step { get; set; }
/// <summary>
/// A list of groups that store the animation data.
/// </summary>
public List<STAnimGroup> AnimGroups = new List<STAnimGroup>();
public void SetFrame(float frame)
{
Frame = frame;
}
public virtual void NextFrame()
{
if (Frame < StartFrame || Frame > FrameCount) return;
}
/// <summary>
/// Resets the animation group values
/// This should clear values from tracks, or reset them to base values.
/// </summary>
public virtual void Reset()
{
}
}
}

View File

@ -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<STKeyFrame> KeyFrames = new List<STKeyFrame>();
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;
}
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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)

View File

@ -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;

View File

@ -0,0 +1,175 @@
namespace Toolbox.Library
{
partial class STAnimationPanel
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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<STAnimation> currentAnimations = new List<STAnimation>();
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)
{
}
}
}

View File

@ -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));

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -199,7 +199,12 @@
<ItemGroup>
<Compile Include="Animations\Animation.cs" />
<Compile Include="Animations\AnimationGroupNode.cs" />
<Compile Include="Animations\AnimationRewrite\InterpolationHelper.cs" />
<Compile Include="Animations\AnimationRewrite\STAnimation.cs" />
<Compile Include="Animations\AnimationRewrite\STAnimationTrack.cs" />
<Compile Include="Animations\AnimationRewrite\STKeyFrame.cs" />
<Compile Include="Animations\AnimationRewrite\STAnimGroup.cs" />
<Compile Include="Animations\AnimationRewrite\STSkeletonAnimation.cs" />
<Compile Include="Animations\ImageKeyFrame.cs" />
<Compile Include="Animations\VisibilityAnimation.cs" />
<Compile Include="Animations\BooleanKeyFrame.cs" />
@ -245,6 +250,12 @@
<Compile Include="FileFormats\DDS\RGBAPixelDecoder.cs" />
<Compile Include="FileSystem\VirtualFileTreeNode.cs" />
<Compile Include="FileSystem\VirtualTreeNode.cs" />
<Compile Include="Forms\Animation\Rewrite\AnimationPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\Animation\Rewrite\AnimationPanel.Designer.cs">
<DependentUpon>AnimationPanel.cs</DependentUpon>
</Compile>
<Compile Include="Forms\ColorAlphaBox.cs">
<SubType>Component</SubType>
</Compile>
@ -397,7 +408,7 @@
<Compile Include="Forms\Dialogs\STSaveLogDialog.Designer.cs">
<DependentUpon>STSaveLogDialog.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Editors\Animation\BoneAnimTimeline.cs">
<Compile Include="Forms\Animation\BoneAnimTimeline.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\Custom\DropdownPanel\ExpandCollapseEventArgs.cs" />
@ -603,10 +614,10 @@
<Compile Include="Forms\Editors\TextEditor\TextEditorForm.Designer.cs">
<DependentUpon>TextEditorForm.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Editors\Animation\TimeLine.cs">
<Compile Include="Forms\Animation\TimeLine.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\Editors\Animation\TimeLine.Designer.cs">
<Compile Include="Forms\Animation\TimeLine.Designer.cs">
<DependentUpon>TimeLine.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Editors\UV\UVEditor2.cs">
@ -772,10 +783,10 @@
<Compile Include="IO\STStream.cs" />
<Compile Include="Maths\Math.cs" />
<Compile Include="Plugin\GenericPluginLoader.cs" />
<Compile Include="Forms\Editors\Animation\AnimationPanel.cs">
<Compile Include="Forms\Animation\AnimationPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\Editors\Animation\AnimationPanel.Designer.cs">
<Compile Include="Forms\Animation\AnimationPanel.Designer.cs">
<DependentUpon>AnimationPanel.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Editors\AssimpMeshSelector.cs">
@ -865,6 +876,9 @@
<Compile Include="XML\XmlDoc.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Forms\Animation\Rewrite\AnimationPanel.resx">
<DependentUpon>AnimationPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Archive\ArchiveFilePanel.resx">
<DependentUpon>ArchiveFilePanel.cs</DependentUpon>
</EmbeddedResource>
@ -936,7 +950,7 @@
<EmbeddedResource Include="Forms\Dialogs\STErrorDialog.resx">
<DependentUpon>STErrorDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Editors\Animation\AnimationPanel.resx">
<EmbeddedResource Include="Forms\Animation\AnimationPanel.resx">
<DependentUpon>AnimationPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Editors\Assimp Settings.resx">
@ -1026,7 +1040,7 @@
<EmbeddedResource Include="Forms\Editors\TextEditor\TextEditorForm.resx">
<DependentUpon>TextEditorForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Editors\Animation\TimeLine.resx">
<EmbeddedResource Include="Forms\Animation\TimeLine.resx">
<DependentUpon>TimeLine.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Editors\TextureImport\3DS\CTR_3DSTextureImporter.resx">
@ -1305,6 +1319,7 @@
<None Include="Resources\Playback\PauseBtn.png" />
</ItemGroup>
<ItemGroup>
<Folder Include="Externals\" />
<Folder Include="FileFormats\Compression\" />
<Folder Include="FileFormats\DAE\COLLADA\" />
<Folder Include="FileFormats\DAE\Custom\" />

View File

@ -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())

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}