1
0
mirror of synced 2024-09-24 03:28:21 +02: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 namespace FirstPlugin
{ {
public class BFFNT : IFileFormat, IEditor<BffntEditor>, IConvertableTextFormat public class BFFNT : BXFNT, IFileFormat, IEditor<BffntEditor>, IConvertableTextFormat
{ {
public FileType FileType { get; set; } = FileType.Font; public FileType FileType { get; set; } = FileType.Font;
@ -76,6 +76,8 @@ namespace FirstPlugin
public void Load(System.IO.Stream stream) public void Load(System.IO.Stream stream)
{ {
PluginRuntime.BxfntFiles.Add(this);
CanSave = true; CanSave = true;
bffnt = new FFNT(); bffnt = new FFNT();
@ -110,9 +112,22 @@ namespace FirstPlugin
// Nodes.Add(file); // 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() public void Unload()
{ {
PluginRuntime.BxfntFiles.Remove(this);
} }
public void Save(System.IO.Stream stream) public void Save(System.IO.Stream stream)
@ -288,9 +303,21 @@ namespace FirstPlugin
return Signature; 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 FontInfo = FontSection;
var TextureGlyph = FontInfo.TextureGlyph; var TextureGlyph = FontInfo.TextureGlyph;
@ -306,6 +333,10 @@ namespace FirstPlugin
for (int sheet = 0; sheet < TextureGlyph.SheetCount; sheet++) for (int sheet = 0; sheet < TextureGlyph.SheetCount; sheet++)
{ {
Bitmap SheetBM = TextureGlyph.GetImageSheet(sheet).GetBitmap(); Bitmap SheetBM = TextureGlyph.GetImageSheet(sheet).GetBitmap();
if (UseChannelComp)
SheetBM = TextureGlyph.GetImageSheet(sheet).GetComponentBitmap(SheetBM, true);
SheetBM.RotateFlip(RotateFlipType.RotateNoneFlipY); SheetBM.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData bd = SheetBM.LockBits(new Rectangle(0, 0, SheetBM.Width, SheetBM.Height), BitmapData bd = SheetBM.LockBits(new Rectangle(0, 0, SheetBM.Width, SheetBM.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
@ -431,6 +462,10 @@ namespace FirstPlugin
Width = TextureTGLP.SheetWidth; Width = TextureTGLP.SheetWidth;
var BFNTFormat = (Gx2ImageFormats)TextureTGLP.Format; var BFNTFormat = (Gx2ImageFormats)TextureTGLP.Format;
Format = ConvertToGeneric(BFNTFormat); Format = ConvertToGeneric(BFNTFormat);
if (Format == TEX_FORMAT.BC4_UNORM)
{
AlphaChannel = STChannelType.Red;
}
ImageKey = "Texture"; ImageKey = "Texture";
SelectedImageKey = "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) public STGenericTexture GetImageSheet(int Index)
{ {
if (BinaryTextureFile != null) //BNTX uses only one image with multiple arrays 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 class BxlytShader : IDisposable
{ {
public bool Compiled = false;
public int program; public int program;
private int vertexShader; private int vertexShader;
private int fragmentShader; private int fragmentShader;
@ -125,9 +127,7 @@ namespace LayoutBXLYT
GL.GetProgram(program, GetProgramParameterName.ActiveAttributes, out activeAttributeCount); GL.GetProgram(program, GetProgramParameterName.ActiveAttributes, out activeAttributeCount);
for (int i = 0; i < activeAttributeCount; i++) for (int i = 0; i < activeAttributeCount; i++)
{ {
int size = 0; string name = GL.GetActiveAttrib(program, i, out int size, out ActiveAttribType type);
ActiveAttribType type;
string name = GL.GetActiveAttrib(program, i, out size, out type);
int location = GL.GetAttribLocation(program, name); int location = GL.GetAttribLocation(program, name);
// Overwrite existing vertex attributes. // 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) private void LoadUniorms(int program)
{ {
uniforms.Clear(); uniforms.Clear();
@ -156,8 +176,11 @@ namespace LayoutBXLYT
{ {
program = CompileShaders(); program = CompileShaders();
LoadAttributes(program);
LoadUniorms(program); LoadUniorms(program);
OnCompiled(); OnCompiled();
Compiled = true;
} }
public virtual void OnCompiled() { } public virtual void OnCompiled() { }

View File

@ -2,10 +2,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Drawing; using System.Drawing;
using System.Threading.Tasks; using System.Drawing.Imaging;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Toolbox.Library; using Toolbox.Library;
using Toolbox.Library.IO; using Toolbox.Library.IO;
using Toolbox.Library.Rendering;
using OpenTK; using OpenTK;
using LayoutBXLYT.Cafe; 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) if (!Runtime.LayoutEditor.DisplayPicturePane)
return; return;
@ -60,11 +61,15 @@ namespace LayoutBXLYT
{ {
var pic1Pane = pane as Cafe.BFLYT.PIC1; var pic1Pane = pane as Cafe.BFLYT.PIC1;
STColor8[] stColors = SetupVertexColors(pane,
pic1Pane.ColorBottomRight, pic1Pane.ColorBottomLeft,
pic1Pane.ColorTopLeft, pic1Pane.ColorTopRight);
Color[] Colors = new Color[] { Color[] Colors = new Color[] {
pic1Pane.ColorBottomRight.Color, stColors[0].Color,
pic1Pane.ColorBottomLeft.Color, stColors[1].Color,
pic1Pane.ColorTopLeft.Color, stColors[2].Color,
pic1Pane.ColorTopRight.Color, stColors[3].Color,
}; };
var mat = pic1Pane.Material; var mat = pic1Pane.Material;
@ -75,7 +80,7 @@ namespace LayoutBXLYT
} }
mat.Shader.Enable(); mat.Shader.Enable();
((BflytShader)mat.Shader).SetMaterials(Textures); ((BflytShader)mat.Shader).SetMaterials(pic1Pane,Textures);
if (pic1Pane.TexCoords.Length > 0) 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(); mat.Shader.Disable();
} }
@ -110,7 +115,7 @@ namespace LayoutBXLYT
} }
mat.Shader.Enable(); mat.Shader.Enable();
((BclytShader)mat.Shader).SetMaterials(Textures); ((BclytShader)mat.Shader).SetMaterials(pane,Textures);
if (pic1Pane.TexCoords.Length > 0) 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(); mat.Shader.Disable();
} }
@ -145,7 +150,7 @@ namespace LayoutBXLYT
} }
mat.Shader.Enable(); mat.Shader.Enable();
((BrlytShader)mat.Shader).SetMaterials(Textures); ((BrlytShader)mat.Shader).SetMaterials(pane, Textures);
if (pic1Pane.TexCoords.Length > 0) 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(); mat.Shader.Disable();
} }
@ -168,9 +173,9 @@ namespace LayoutBXLYT
GL.UseProgram(0); 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; return;
Vector2[] TexCoords = new Vector2[] { Vector2[] TexCoords = new Vector2[] {
@ -193,13 +198,13 @@ namespace LayoutBXLYT
color, 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; return;
@ -223,12 +228,12 @@ namespace LayoutBXLYT
color, 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; return;
Vector2[] TexCoords = new Vector2[] { Vector2[] TexCoords = new Vector2[] {
@ -251,13 +256,165 @@ namespace LayoutBXLYT
color, 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 //Huge thanks to layout studio for the window pane rendering code
//https://github.com/Treeki/LayoutStudio/blob/master/layoutgl/widget.cpp //https://github.com/Treeki/LayoutStudio/blob/master/layoutgl/widget.cpp
//Note i still need to fix UV coordinates being flips and transformed! //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) if (!Runtime.LayoutEditor.DisplayWindowPane)
return; return;
@ -328,8 +485,8 @@ namespace LayoutBXLYT
if (!window.NotDrawnContent && window.WindowKind != WindowKind.HorizontalNoContent) if (!window.NotDrawnContent && window.WindowKind != WindowKind.HorizontalNoContent)
{ {
SetupShaders(window.Content.Material, Textures); SetupShaders(pane, window.Content.Material, Textures);
DrawQuad(dX + frameLeft - window.StretchLeft, DrawQuad(gameWindow, dX + frameLeft - window.StretchLeft,
dY - frameTop + window.StretchTop, dY - frameTop + window.StretchTop,
contentWidth, contentWidth,
contentHeight, contentHeight,
@ -352,14 +509,17 @@ namespace LayoutBXLYT
switch (window.FrameCount) 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) case 1: //1 frame. 1 texture for corners (around) or sides (horizontal)
{ {
var windowFrame = window.WindowFrames[0]; var windowFrame = window.WindowFrames[0];
SetupShaders(windowFrame.Material, Textures); SetupShaders(pane, windowFrame.Material, Textures);
//2 sides, no corners //2 sides, no corners
if (window.WindowKind == WindowKind.Horizontal) if (window.WindowKind == WindowKind.Horizontal)
{ {
//Left
texCoords = new Vector2[] texCoords = new Vector2[]
{ {
new Vector2(1, 0), new Vector2(1, 0),
@ -368,7 +528,19 @@ namespace LayoutBXLYT
new Vector2(1, 1), 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[] texCoords = new Vector2[]
{ {
@ -378,10 +550,19 @@ namespace LayoutBXLYT
new Vector2(0, 1), 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) else if (window.WindowKind == WindowKind.HorizontalNoContent)
{ {
//Right
texCoords = new Vector2[] texCoords = new Vector2[]
{ {
new Vector2((pane.Width - frameRight) / frameRight, 0), new Vector2((pane.Width - frameRight) / frameRight, 0),
@ -390,7 +571,47 @@ namespace LayoutBXLYT
new Vector2((pane.Width - frameRight) / frameRight, 1), 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[] texCoords = new Vector2[]
{ {
@ -400,7 +621,7 @@ namespace LayoutBXLYT
new Vector2(0, 1), 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) else if (window.WindowKind == WindowKind.Around)
{ {
@ -417,7 +638,7 @@ namespace LayoutBXLYT
new Vector2(0, 1), new Vector2(0, 1),
}; };
DrawQuad(dX, dY, pieceWidth, pieceHeight, texCoords, colors); DrawQuad(gameWindow, dX, dY, pieceWidth, pieceHeight, texCoords, colors);
// top right // top right
pieceWidth = frameRight; pieceWidth = frameRight;
@ -431,7 +652,7 @@ namespace LayoutBXLYT
new Vector2(1,(pane.Height - frameTop) / frameTop), 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 // bottom left
pieceWidth = frameLeft; pieceWidth = frameLeft;
@ -445,7 +666,7 @@ namespace LayoutBXLYT
new Vector2(0, 0), new Vector2(0, 0),
}; };
DrawQuad(dX, dY - frameTop, pieceWidth, pieceHeight, texCoords, colors); DrawQuad(gameWindow, dX, dY - frameTop, pieceWidth, pieceHeight, texCoords, colors);
// bottom right // bottom right
pieceWidth = pane.Width - frameLeft; pieceWidth = pane.Width - frameLeft;
@ -459,7 +680,7 @@ namespace LayoutBXLYT
new Vector2((pane.Width - frameLeft) / frameLeft, 0), 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; break;
@ -481,7 +702,7 @@ namespace LayoutBXLYT
if (matTL.TextureMaps.Length > 0) if (matTL.TextureMaps.Length > 0)
{ {
SetupShaders(matTL, Textures); SetupShaders(pane, matTL, Textures);
matTL.Shader.SetInt("flipTexture", (int)window.WindowFrames[0].TextureFlip); matTL.Shader.SetInt("flipTexture", (int)window.WindowFrames[0].TextureFlip);
@ -496,11 +717,11 @@ namespace LayoutBXLYT
new Vector2(0, 1), new Vector2(0, 1),
}; };
DrawQuad(dX, dY, pieceWidth, pieceHeight, texCoords, colors); DrawQuad(gameWindow, dX, dY, pieceWidth, pieceHeight, texCoords, colors);
} }
if (matTR.TextureMaps.Length > 0) if (matTR.TextureMaps.Length > 0)
{ {
SetupShaders(matTR, Textures); SetupShaders(pane, matTR, Textures);
matTR.Shader.SetInt("flipTexture", (int)window.WindowFrames[1].TextureFlip); matTR.Shader.SetInt("flipTexture", (int)window.WindowFrames[1].TextureFlip);
@ -515,11 +736,11 @@ namespace LayoutBXLYT
new Vector2(0,(pane.Height - frameTop) / frameTop), 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) if (matBL.TextureMaps.Length > 0)
{ {
SetupShaders(matBL, Textures); SetupShaders(pane, matBL, Textures);
matBL.Shader.SetInt("flipTexture", (int)window.WindowFrames[2].TextureFlip); matBL.Shader.SetInt("flipTexture", (int)window.WindowFrames[2].TextureFlip);
@ -534,11 +755,11 @@ namespace LayoutBXLYT
new Vector2(0, 1), 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) if (matBR.TextureMaps.Length > 0)
{ {
SetupShaders(matBR, Textures); SetupShaders(pane, matBR, Textures);
matBR.Shader.SetInt("flipTexture", (int)window.WindowFrames[3].TextureFlip); matBR.Shader.SetInt("flipTexture", (int)window.WindowFrames[3].TextureFlip);
@ -553,7 +774,7 @@ namespace LayoutBXLYT
new Vector2(1 - ((pane.Width - frameLeft) / frameLeft), 1), 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; break;
@ -583,7 +804,7 @@ namespace LayoutBXLYT
if (matTL.TextureMaps.Length > 0) if (matTL.TextureMaps.Length > 0)
{ {
SetupShaders(matTL, Textures); SetupShaders(pane, matTL, Textures);
matTL.Shader.SetInt("flipTexture", (int)window.WindowFrames[0].TextureFlip); matTL.Shader.SetInt("flipTexture", (int)window.WindowFrames[0].TextureFlip);
texCoords = new Vector2[] texCoords = new Vector2[]
@ -594,12 +815,12 @@ namespace LayoutBXLYT
new Vector2(0, 1), new Vector2(0, 1),
}; };
DrawQuad(dX, dY, frameLeft, frameTop, texCoords, colors); DrawQuad(gameWindow, dX, dY, frameLeft, frameTop, texCoords, colors);
} }
if (matTR.TextureMaps.Length > 0) if (matTR.TextureMaps.Length > 0)
{ {
SetupShaders(matTR, Textures); SetupShaders(pane, matTR, Textures);
matTR.Shader.SetInt("flipTexture", (int)window.WindowFrames[1].TextureFlip); matTR.Shader.SetInt("flipTexture", (int)window.WindowFrames[1].TextureFlip);
texCoords = new Vector2[] texCoords = new Vector2[]
@ -610,12 +831,12 @@ namespace LayoutBXLYT
new Vector2(0, 1), 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) if (matBL.TextureMaps.Length > 0)
{ {
SetupShaders(matBL, Textures); SetupShaders(pane, matBL, Textures);
matBL.Shader.SetInt("flipTexture", (int)window.WindowFrames[2].TextureFlip); matBL.Shader.SetInt("flipTexture", (int)window.WindowFrames[2].TextureFlip);
texCoords = new Vector2[] texCoords = new Vector2[]
@ -626,12 +847,12 @@ namespace LayoutBXLYT
new Vector2(0, 1), 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) if (matBR.TextureMaps.Length > 0)
{ {
SetupShaders(matBR, Textures); SetupShaders(pane, matBR, Textures);
matBR.Shader.SetInt("flipTexture", (int)window.WindowFrames[3].TextureFlip); matBR.Shader.SetInt("flipTexture", (int)window.WindowFrames[3].TextureFlip);
texCoords = new Vector2[] texCoords = new Vector2[]
@ -642,12 +863,12 @@ namespace LayoutBXLYT
new Vector2(0, 1), 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) if (matT.TextureMaps.Length > 0)
{ {
SetupShaders(matT, Textures); SetupShaders(pane, matT, Textures);
matT.Shader.SetInt("flipTexture", (int)window.WindowFrames[4].TextureFlip); matT.Shader.SetInt("flipTexture", (int)window.WindowFrames[4].TextureFlip);
texCoords = new Vector2[] texCoords = new Vector2[]
@ -658,12 +879,12 @@ namespace LayoutBXLYT
new Vector2(0, 1), 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) if (matB.TextureMaps.Length > 0)
{ {
SetupShaders(matB, Textures); SetupShaders(pane, matB, Textures);
matB.Shader.SetInt("flipTexture", (int)window.WindowFrames[5].TextureFlip); matB.Shader.SetInt("flipTexture", (int)window.WindowFrames[5].TextureFlip);
texCoords = new Vector2[] texCoords = new Vector2[]
@ -674,12 +895,12 @@ namespace LayoutBXLYT
new Vector2(1-((pane.Width - frameLeft) / frameLeft), 1), 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) if (matL.TextureMaps.Length > 0)
{ {
SetupShaders(matL, Textures); SetupShaders(pane, matL, Textures);
matL.Shader.SetInt("flipTexture", (int)window.WindowFrames[6].TextureFlip); matL.Shader.SetInt("flipTexture", (int)window.WindowFrames[6].TextureFlip);
texCoords = new Vector2[] texCoords = new Vector2[]
@ -690,12 +911,12 @@ namespace LayoutBXLYT
new Vector2(0, 1), 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) if (matR.TextureMaps.Length > 0)
{ {
SetupShaders(matR, Textures); SetupShaders(pane, matR, Textures);
matR.Shader.SetInt("flipTexture", (int)window.WindowFrames[7].TextureFlip); matR.Shader.SetInt("flipTexture", (int)window.WindowFrames[7].TextureFlip);
texCoords = new Vector2[] texCoords = new Vector2[]
@ -706,7 +927,7 @@ namespace LayoutBXLYT
new Vector2(0,(pane.Height - frameBottom) / frameBottom), 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; 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.AlphaTest);
GL.Disable(EnableCap.Blend); GL.Disable(EnableCap.Blend);
@ -811,7 +1032,7 @@ namespace LayoutBXLYT
return pos; 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) if (mat.Shader == null)
{ {
@ -824,7 +1045,7 @@ namespace LayoutBXLYT
mat.Shader.Enable(); mat.Shader.Enable();
if (mat is Cafe.BFLYT.Material) 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, private static void RenderWindowContent(BasePane pane, uint sizeX, uint sizeY, BxlytWindowContent content,
@ -833,7 +1054,7 @@ namespace LayoutBXLYT
var mat = content.Material; var mat = content.Material;
var rect = pane.CreateRectangle(sizeX, sizeY); var rect = pane.CreateRectangle(sizeX, sizeY);
SetupShaders(mat, Textures); SetupShaders(pane, mat, Textures);
Vector2[] texCoords = new Vector2[] { Vector2[] texCoords = new Vector2[] {
new Vector2(1,1), 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) switch (blendFactor)
{ {
@ -930,7 +1151,7 @@ namespace LayoutBXLYT
} }
} }
private static LogicOp ConvertLogicOperation(BlendMode.GX2LogicOp blendOp) public static LogicOp ConvertLogicOperation(BlendMode.GX2LogicOp blendOp)
{ {
switch (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) switch (blendOp)
{ {
@ -981,7 +1218,43 @@ namespace LayoutBXLYT
Alpha = All.Alpha, 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) Color[] colors, bool useLines = true, byte alpha = 255)
{ {
for (int i = 0; i < colors.Length; i++) for (int i = 0; i < colors.Length; i++)
@ -1004,7 +1277,7 @@ namespace LayoutBXLYT
} }
else else
{ {
if (!Runtime.LayoutEditor.IsGamePreview) if (!Runtime.LayoutEditor.IsGamePreview && !gameWindow)
{ {
GL.Disable(EnableCap.Blend); GL.Disable(EnableCap.Blend);
GL.Disable(EnableCap.AlphaTest); GL.Disable(EnableCap.AlphaTest);
@ -1057,7 +1330,7 @@ namespace LayoutBXLYT
vertices[3] = new Vector3(rect.LeftPoint, rect.TopPoint, 0); vertices[3] = new Vector3(rect.LeftPoint, rect.TopPoint, 0);
Vector4[] vertexColors = new Vector4[4]; 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 namespace LayoutBXLYT
{ {
public class BFLAN : IEditorForm<LayoutEditor>, IFileFormat, IConvertableTextFormat public class BFLAN : BXLAN, IEditorForm<LayoutEditor>, IFileFormat, IConvertableTextFormat
{ {
public FileType FileType { get; set; } = FileType.Layout; public FileType FileType { get; set; } = FileType.Layout;
@ -54,29 +54,27 @@ namespace LayoutBXLYT
serializerSettings.ComparerForKeySorting = null; serializerSettings.ComparerForKeySorting = null;
serializerSettings.RegisterTagMapping("Header", typeof(Header)); serializerSettings.RegisterTagMapping("Header", typeof(Header));
return FLAN.ToXml(header); return FLAN.ToXml((Header)BxlanHeader);
var serializer = new Serializer(serializerSettings); var serializer = new Serializer(serializerSettings);
string yaml = serializer.Serialize(header, typeof(Header)); string yaml = serializer.Serialize(BxlanHeader, typeof(Header));
return yaml; return yaml;
} }
public void ConvertFromString(string text) public void ConvertFromString(string text)
{ {
header = FLAN.FromXml(text); BxlanHeader = FLAN.FromXml(text);
header.FileInfo = this; BxlanHeader.FileInfo = this;
} }
#endregion #endregion
public Header header;
public void Load(System.IO.Stream stream) public void Load(System.IO.Stream stream)
{ {
CanSave = true; CanSave = true;
header = new Header(); BxlanHeader = new Header();
header.Read(new FileReader(stream),this); BxlanHeader.Read(new FileReader(stream),this);
} }
public void Unload() public void Unload()
{ {
@ -84,20 +82,20 @@ namespace LayoutBXLYT
} }
public void Save(System.IO.Stream stream) { public void Save(System.IO.Stream stream) {
header.Write(new FileWriter(stream)); BxlanHeader.Write(new FileWriter(stream));
} }
public LayoutEditor OpenForm() public LayoutEditor OpenForm()
{ {
LayoutEditor editor = new LayoutEditor(); LayoutEditor editor = new LayoutEditor();
editor.Dock = DockStyle.Fill; editor.Dock = DockStyle.Fill;
editor.LoadBxlan(header); editor.LoadBxlan(BxlanHeader);
return editor; return editor;
} }
public void FillEditor(Form control) public void FillEditor(Form control)
{ {
((LayoutEditor)control).LoadBxlan(header); ((LayoutEditor)control).LoadBxlan(BxlanHeader);
} }
public class Header : BxlanHeader public class Header : BxlanHeader
@ -109,7 +107,7 @@ namespace LayoutBXLYT
//As of now this should be empty but just for future proofing //As of now this should be empty but just for future proofing
private List<SectionCommon> UnknownSections = new List<SectionCommon>(); 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(); AnimationTag = new PAT1();
AnimationInfo = new PAI1(); AnimationInfo = new PAI1();
@ -125,7 +123,7 @@ namespace LayoutBXLYT
ushort sectionCount = reader.ReadUInt16(); ushort sectionCount = reader.ReadUInt16();
reader.ReadUInt16(); //Padding reader.ReadUInt16(); //Padding
FileInfo = bflan; FileInfo = (IFileFormat)bflan;
IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian; IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian;
reader.SeekBegin(HeaderSize); reader.SeekBegin(HeaderSize);
@ -155,7 +153,7 @@ namespace LayoutBXLYT
} }
} }
public void Write(FileWriter writer) public override void Write(FileWriter writer)
{ {
writer.SetByteOrder(true); writer.SetByteOrder(true);
writer.WriteSignature(Magic); writer.WriteSignature(Magic);
@ -223,8 +221,12 @@ namespace LayoutBXLYT
ushort groupCount = reader.ReadUInt16(); ushort groupCount = reader.ReadUInt16();
uint animNameOffset = reader.ReadUInt32(); uint animNameOffset = reader.ReadUInt32();
uint groupNamesOffset = reader.ReadUInt32(); uint groupNamesOffset = reader.ReadUInt32();
if (header.VersionMajor >= 8)
reader.ReadUInt32(); //unk
StartFrame = reader.ReadInt16(); StartFrame = reader.ReadInt16();
EndFrame = reader.ReadInt16(); EndFrame = reader.ReadInt16();
ChildBinding = reader.ReadBoolean(); ChildBinding = reader.ReadBoolean();
UnknownData = reader.ReadBytes((int)(startPos + animNameOffset - reader.Position)); UnknownData = reader.ReadBytes((int)(startPos + animNameOffset - reader.Position));
@ -244,8 +246,12 @@ namespace LayoutBXLYT
writer.Write((ushort)Groups.Count); writer.Write((ushort)Groups.Count);
writer.Write(uint.MaxValue); //animNameOffset writer.Write(uint.MaxValue); //animNameOffset
writer.Write(uint.MaxValue); //groupNamesOffset writer.Write(uint.MaxValue); //groupNamesOffset
writer.Write(StartFrame); if (header.VersionMajor >= 8)
writer.Write(EndFrame); writer.Write(0); //unk
writer.Write((ushort)StartFrame);
writer.Write((ushort)EndFrame);
writer.Write(ChildBinding); writer.Write(ChildBinding);
writer.Write(UnknownData); writer.Write(UnknownData);
@ -281,10 +287,11 @@ namespace LayoutBXLYT
var numEntries = reader.ReadUInt16(); var numEntries = reader.ReadUInt16();
var entryOffsetTbl = reader.ReadUInt32(); var entryOffsetTbl = reader.ReadUInt32();
long texStart = reader.Position;
var texOffsets = reader.ReadUInt32s(numTextures); var texOffsets = reader.ReadUInt32s(numTextures);
for (int i = 0; i < numTextures; i++) for (int i = 0; i < numTextures; i++)
{ {
reader.SeekBegin(startPos + texOffsets[i]); reader.SeekBegin(texStart + texOffsets[i]);
Textures.Add(reader.ReadZeroTerminatedString()); Textures.Add(reader.ReadZeroTerminatedString());
} }
@ -377,7 +384,7 @@ namespace LayoutBXLYT
{ {
private uint Unknown {get;set;} 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) if ((byte)target == 2)
Unknown = reader.ReadUInt32(); //This doesn't seem to be included in the offsets to the entries (?) Unknown = reader.ReadUInt32(); //This doesn't seem to be included in the offsets to the entries (?)
@ -393,25 +400,25 @@ namespace LayoutBXLYT
switch (Tag) switch (Tag)
{ {
case "FLPA": case "FLPA":
Entries.Add(new FLPATagEntry(reader, header)); Entries.Add(new LPATagEntry(reader, header));
break; break;
case "FLTS": case "FLTS":
Entries.Add(new FLTSTagEntry(reader, header)); Entries.Add(new LTSTagEntry(reader, header));
break; break;
case "FLVI": case "FLVI":
Entries.Add(new FLVITagEntry(reader, header)); Entries.Add(new LVITagEntry(reader, header));
break; break;
case "FLVC": case "FLVC":
Entries.Add(new FLVCTagEntry(reader, header)); Entries.Add(new LVCTagEntry(reader, header));
break; break;
case "FLMC": case "FLMC":
Entries.Add(new FLMCTagEntry(reader, header)); Entries.Add(new LMCTagEntry(reader, header));
break; break;
case "FLTP": case "FLTP":
Entries.Add(new FLTPTagEntry(reader, header)); Entries.Add(new LTPTagEntry(reader, header));
break; break;
default: default:
Entries.Add(new PaiTagEntry(reader, header)); Entries.Add(new BxlanPaiTagEntry(reader, header));
break; break;
} }
} }
@ -431,122 +438,9 @@ namespace LayoutBXLYT
for (int i = 0; i < Entries.Count; i++) for (int i = 0; i < Entries.Count; i++)
{ {
writer.WriteUint32Offset(startPos + 8 + (i * 4), startPos); 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 ByteOrderMark;
private ushort HeaderSize; private ushort HeaderSize;
[Browsable(false)]
public Dictionary<string, BasePane> PaneLookup = new Dictionary<string, BasePane>();
[Browsable(false)] [Browsable(false)]
public LYT1 LayoutInfo { get; set; } public LYT1 LayoutInfo { get; set; }
[Browsable(false)] [Browsable(false)]
@ -367,6 +364,7 @@ namespace LayoutBXLYT.Cafe
public void Read(FileReader reader, BFLYT bflyt) public void Read(FileReader reader, BFLYT bflyt)
{ {
PaneLookup.Clear();
LayoutInfo = new LYT1(); LayoutInfo = new LYT1();
TextureList = new TXL1(); TextureList = new TXL1();
MaterialList = new MAT1(); 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) private void SetPane(BasePane pane, BasePane parentPane)
{ {
if (parentPane != null) 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"; 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 public OriginX HorizontalAlignment
{ {
get { return (OriginX)((TextAlignment >> 2) & 0x3); } get { return (OriginX)((TextAlignment >> 2) & 0x3); }
@ -713,6 +707,7 @@ namespace LayoutBXLYT.Cafe
} }
} }
[DisplayName("Vertical Alignment"), CategoryAttribute("Font")]
public OriginX VerticalAlignment public OriginX VerticalAlignment
{ {
get { return (OriginX)((TextAlignment) & 0x3); } get { return (OriginX)((TextAlignment) & 0x3); }
@ -723,49 +718,83 @@ namespace LayoutBXLYT.Cafe
} }
} }
[Browsable(false)]
public ushort TextLength { get; set; } public ushort TextLength { get; set; }
[Browsable(false)]
public ushort MaxTextLength { get; set; } public ushort MaxTextLength { get; set; }
[Browsable(false)]
public ushort MaterialIndex { get; set; } public ushort MaterialIndex { get; set; }
[Browsable(false)]
public ushort FontIndex { get; set; } public ushort FontIndex { get; set; }
[TypeConverter(typeof(ExpandableObjectConverter))]
public BxlytMaterial Material { get; set; }
[DisplayName("Text Alignment"), CategoryAttribute("Font")]
public byte TextAlignment { get; set; } public byte TextAlignment { get; set; }
[DisplayName("Line Alignment"), CategoryAttribute("Font")]
public LineAlign LineAlignment { get; set; } public LineAlign LineAlignment { get; set; }
[DisplayName("Italic Tilt"), CategoryAttribute("Font")]
public float ItalicTilt { get; set; } public float ItalicTilt { get; set; }
[DisplayName("Fore Color"), CategoryAttribute("Font")]
public STColor8 FontForeColor { get; set; } public STColor8 FontForeColor { get; set; }
[DisplayName("Back Color"), CategoryAttribute("Font")]
public STColor8 FontBackColor { get; set; } public STColor8 FontBackColor { get; set; }
[DisplayName("Font Size"), CategoryAttribute("Font")]
public Vector2F FontSize { get; set; } public Vector2F FontSize { get; set; }
[DisplayName("Character Space"), CategoryAttribute("Font")]
public float CharacterSpace { get; set; } public float CharacterSpace { get; set; }
[DisplayName("Line Space"), CategoryAttribute("Font")]
public float LineSpace { get; set; } public float LineSpace { get; set; }
[DisplayName("Shadow Position"), CategoryAttribute("Shadows")]
public Vector2F ShadowXY { get; set; } public Vector2F ShadowXY { get; set; }
[DisplayName("Shadow Size"), CategoryAttribute("Shadows")]
public Vector2F ShadowXYSize { get; set; } public Vector2F ShadowXYSize { get; set; }
[DisplayName("Shadow Fore Color"), CategoryAttribute("Shadows")]
public STColor8 ShadowForeColor { get; set; } public STColor8 ShadowForeColor { get; set; }
[DisplayName("Shadow Back Color"), CategoryAttribute("Shadows")]
public STColor8 ShadowBackColor { get; set; } public STColor8 ShadowBackColor { get; set; }
[DisplayName("Shadow Italic"), CategoryAttribute("Shadows")]
public float ShadowItalic { get; set; } public float ShadowItalic { get; set; }
[DisplayName("Text Box Name"), CategoryAttribute("Text Box")]
public string TextBoxName { get; set; } public string TextBoxName { get; set; }
[DisplayName("Text"), CategoryAttribute("Text Box")]
public string Text { get; set; }
[DisplayName("Per Character Transform"), CategoryAttribute("Font")]
public bool PerCharTransform public bool PerCharTransform
{ {
get { return (_flags & 0x10) != 0; } get { return (_flags & 0x10) != 0; }
set { _flags = value ? (byte)(_flags | 0x10) : unchecked((byte)(_flags & (~0x10))); } set { _flags = value ? (byte)(_flags | 0x10) : unchecked((byte)(_flags & (~0x10))); }
} }
[DisplayName("Restricted Text Length"), CategoryAttribute("Font")]
public bool RestrictedTextLengthEnabled public bool RestrictedTextLengthEnabled
{ {
get { return (_flags & 0x2) != 0; } get { return (_flags & 0x2) != 0; }
set { _flags = value ? (byte)(_flags | 0x2) : unchecked((byte)(_flags & (~0x2))); } set { _flags = value ? (byte)(_flags | 0x2) : unchecked((byte)(_flags & (~0x2))); }
} }
[DisplayName("Enable Shadows"), CategoryAttribute("Font")]
public bool ShadowEnabled public bool ShadowEnabled
{ {
get { return (_flags & 1) != 0; } get { return (_flags & 1) != 0; }
set { _flags = value ? (byte)(_flags | 1) : unchecked((byte)(_flags & (~1))); } set { _flags = value ? (byte)(_flags | 1) : unchecked((byte)(_flags & (~1))); }
} }
[DisplayName("Font Name"), CategoryAttribute("Font")]
public string FontName { get; set; } public string FontName { get; set; }
private byte _flags; private byte _flags;
@ -796,6 +825,9 @@ namespace LayoutBXLYT.Cafe
ShadowBackColor = STColor8.FromBytes(reader.ReadBytes(4)); ShadowBackColor = STColor8.FromBytes(reader.ReadBytes(4));
ShadowItalic = reader.ReadSingle(); 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) if (FontIndex != ushort.MaxValue && header.FontList.Fonts.Count > 0)
FontName = header.FontList.Fonts[FontIndex]; FontName = header.FontList.Fonts[FontIndex];
@ -867,21 +899,6 @@ namespace LayoutBXLYT.Cafe
writer.WriteString(TextBoxName); 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 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"; 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"; public override string Signature { get; } = "pic1";
@ -1737,7 +1754,7 @@ namespace LayoutBXLYT.Cafe
private byte origin; private byte origin;
[DisplayName("Is Visible"), CategoryAttribute("Flags")] [DisplayName("Is Visible"), CategoryAttribute("Flags")]
public bool Visible public override bool Visible
{ {
get { return (_flags1 & 0x1) == 0x1; } get { return (_flags1 & 0x1) == 0x1; }
set { set {
@ -1958,21 +1975,26 @@ namespace LayoutBXLYT.Cafe
public TevStage[] TevStages { get; set; } public TevStage[] TevStages { get; set; }
[DisplayName("Alpha Compare"), CategoryAttribute("Alpha")] [DisplayName("Alpha Compare"), CategoryAttribute("Alpha")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public AlphaCompare AlphaCompare { get; set; } public AlphaCompare AlphaCompare { get; set; }
[DisplayName("Blend Mode"), CategoryAttribute("Blend")] [DisplayName("Blend Mode"), CategoryAttribute("Blend")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public BlendMode BlendMode { get; set; } public BlendMode BlendMode { get; set; }
[DisplayName("Blend Mode Logic"), CategoryAttribute("Blend")] [DisplayName("Blend Mode Logic"), CategoryAttribute("Blend")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public BlendMode BlendModeLogic { get; set; } public BlendMode BlendModeLogic { get; set; }
[DisplayName("Indirect Parameter"), CategoryAttribute("Texture")] [DisplayName("Indirect Parameter"), CategoryAttribute("Texture")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public IndirectParameter IndParameter { get; set; } public IndirectParameter IndParameter { get; set; }
[DisplayName("Projection Texture Coord Parameters"), CategoryAttribute("Texture")] [DisplayName("Projection Texture Coord Parameters"), CategoryAttribute("Texture")]
public ProjectionTexGenParam[] ProjTexGenParams { get; set; } public ProjectionTexGenParam[] ProjTexGenParams { get; set; }
[DisplayName("Font Shadow Parameters"), CategoryAttribute("Font")] [DisplayName("Font Shadow Parameters"), CategoryAttribute("Font")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public FontShadowParameter FontShadowParameter { get; set; } public FontShadowParameter FontShadowParameter { get; set; }
private uint flags; private uint flags;

View File

@ -32,34 +32,102 @@ namespace LayoutBXLYT
SetInt("textures1", 0); SetInt("textures1", 0);
SetInt("textures2", 0); SetInt("textures2", 0);
SetBool("ThresholdingAlphaInterpolation", false); SetBool("ThresholdingAlphaInterpolation", false);
var rotationMatrix = Matrix4.Identity;
SetMatrix("rotationMatrix", ref rotationMatrix);
SetInt("numTevStages", 0);
SetVec2("uvScale0", new Vector2(1,1)); SetVec2("uvScale0", new Vector2(1,1));
SetFloat("uvRotate0", 0); SetFloat("uvRotate0", 0);
SetVec2("uvTranslate0", new Vector2(0, 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); var paneRotate = pane.Rotate;
SetColor("blackColor", material.BlackColor.Color); 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("debugShading", (int)Runtime.LayoutEditor.Shading);
SetInt("numTextureMaps", material.TextureMaps.Length); SetInt("numTextureMaps", material.TextureMaps.Length);
SetVec2("uvScale0", new Vector2(1, 1)); SetVec2("uvScale0", new Vector2(1, 1));
SetFloat("uvRotate0", 0); SetFloat("uvRotate0", 0);
SetVec2("uvTranslate0", new Vector2(0, 0)); SetVec2("uvTranslate0", new Vector2(0, 0));
SetInt("flipTexture", 0); SetInt("flipTexture", 0);
SetInt("numTevStages", material.TevStages.Length);
SetBool("ThresholdingAlphaInterpolation", material.ThresholdingAlphaInterpolation); 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(); BindTextureUniforms();
int id = 1; int id = 1;
for (int i = 0; i < material.TextureMaps.Length; i++) 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); GL.ActiveTexture(TextureUnit.Texture0 + id);
SetInt($"textures{i}", 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) if (isBinded)
SetInt($"hasTexture{i}", 1); 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) if (material.TextureTransforms.Length > 0)
{ {
var transform = material.TextureTransforms[0]; var transform = material.TextureTransforms[0];
SetVec2("uvScale0",new Vector2(transform.Scale.X, transform.Scale.Y)); var scale = transform.Scale;
SetFloat("uvRotate0", transform.Rotate); var rotate = transform.Rotate;
SetVec2("uvTranslate0",new Vector2(transform.Translate.X, transform.Translate.Y)); 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 class AlphaCompare
{ {
public byte CompareMode { get; set; } public GfxAlphaFunction CompareMode { get; set; }
public uint Value { get; set; } public float Value { get; set; }
public AlphaCompare(FileReader reader, BFLYT.Header header) public AlphaCompare(FileReader reader, BFLYT.Header header)
{ {
CompareMode = reader.ReadByte(); CompareMode = reader.ReadEnum<GfxAlphaFunction>(false);
reader.ReadBytes(0x3); reader.ReadBytes(0x3);
Value = reader.ReadUInt32(); Value = reader.ReadSingle();
} }
public void Write(FileWriter writer) public void Write(FileWriter writer)
{ {
writer.Write(CompareMode); writer.Write(CompareMode, false);
writer.Seek(3); writer.Seek(3);
writer.Write(Value); writer.Write(Value);
} }

View File

@ -2,12 +2,8 @@
namespace LayoutBXLYT.Cafe 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) public IndirectParameter(FileReader reader, BFLYT.Header header)
{ {
Rotation = reader.ReadSingle(); Rotation = reader.ReadSingle();

View File

@ -4,22 +4,53 @@ namespace LayoutBXLYT.Cafe
{ {
public class TevStage public class TevStage
{ {
public TevMode RGBMode { get; set; } public TevMode ColorMode { get; set; }
public TevMode AlphaMode { 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) public TevStage(FileReader reader, BFLYT.Header header)
{ {
RGBMode = (TevMode)reader.ReadByte(); colorFlags = reader.ReadByte();
AlphaMode = (TevMode)reader.ReadByte(); alphaFlags = reader.ReadByte();
unk = reader.ReadUInt16(); 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) public void Write(FileWriter writer)
{ {
writer.Write(RGBMode, false); writer.Write(colorFlags);
writer.Write(AlphaMode, false); writer.Write(alphaFlags);
writer.Write(unk); writer.Write((ushort)0);
} }
} }
} }

View File

@ -3,12 +3,8 @@ using Syroot.Maths;
namespace LayoutBXLYT.Cafe 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() { }
public TextureTransform(FileReader reader) public TextureTransform(FileReader reader)

View File

@ -217,6 +217,7 @@ namespace LayoutBXLYT
{ {
IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian; IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian;
PaneLookup.Clear();
LayoutInfo = new LYT1(); LayoutInfo = new LYT1();
TextureList = new TXL1(); TextureList = new TXL1();
MaterialList = new MAT1(); MaterialList = new MAT1();
@ -270,6 +271,8 @@ namespace LayoutBXLYT
break; break;
case "pan1": case "pan1":
var panel = new PAN1(reader); var panel = new PAN1(reader);
AddPaneToTable(panel);
if (!setRoot) if (!setRoot)
{ {
RootPane = panel; RootPane = panel;
@ -281,30 +284,36 @@ namespace LayoutBXLYT
break; break;
case "pic1": case "pic1":
var picturePanel = new PIC1(reader, this); var picturePanel = new PIC1(reader, this);
AddPaneToTable(picturePanel);
SetPane(picturePanel, parentPane); SetPane(picturePanel, parentPane);
currentPane = picturePanel; currentPane = picturePanel;
break; break;
case "txt1": case "txt1":
var textPanel = new TXT1(reader); var textPanel = new TXT1(reader);
AddPaneToTable(textPanel);
SetPane(textPanel, parentPane); SetPane(textPanel, parentPane);
currentPane = textPanel; currentPane = textPanel;
break; break;
case "bnd1": case "bnd1":
var boundsPanel = new BND1(reader); var boundsPanel = new BND1(reader);
AddPaneToTable(boundsPanel);
SetPane(boundsPanel, parentPane); SetPane(boundsPanel, parentPane);
currentPane = boundsPanel; currentPane = boundsPanel;
break; break;
case "prt1": case "prt1":
var partsPanel = new PRT1(reader); var partsPanel = new PRT1(reader);
AddPaneToTable(partsPanel);
SetPane(partsPanel, parentPane); SetPane(partsPanel, parentPane);
currentPane = partsPanel; currentPane = partsPanel;
break; break;
case "wnd1": case "wnd1":
var windowPanel = new WND1(reader); var windowPanel = new WND1(reader);
AddPaneToTable(windowPanel);
SetPane(windowPanel, parentPane); SetPane(windowPanel, parentPane);
currentPane = windowPanel; currentPane = windowPanel;
break; break;
@ -551,7 +560,7 @@ namespace LayoutBXLYT
} }
} }
public class BND1 : PAN1 public class BND1 : PAN1, IBoundryPane
{ {
public BND1() : base() public BND1() : base()
{ {
@ -625,7 +634,7 @@ namespace LayoutBXLYT
} }
} }
public class PIC1 : PAN1 public class PIC1 : PAN1, IPicturePane
{ {
[DisplayName("Texture Coordinates"), CategoryAttribute("Texture")] [DisplayName("Texture Coordinates"), CategoryAttribute("Texture")]
public TexCoord[] TexCoords { get; set; } public TexCoord[] TexCoords { get; set; }
@ -710,7 +719,7 @@ namespace LayoutBXLYT
{ {
private byte _flags1; private byte _flags1;
public bool Visible public override bool Visible
{ {
get { return (_flags1 & 0x1) == 0x1; } get { return (_flags1 & 0x1) == 0x1; }
set { set {

View File

@ -35,10 +35,22 @@ namespace LayoutBXLYT
SetVec2("uvScale0", new Vector2(1, 1)); SetVec2("uvScale0", new Vector2(1, 1));
SetFloat("uvRotate0", 0); SetFloat("uvRotate0", 0);
SetVec2("uvTranslate0", new Vector2(0, 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("whiteColor", material.TevConstantColors[0].Color);
SetColor("blackColor", material.TevColor.Color); SetColor("blackColor", material.TevColor.Color);
SetInt("debugShading", (int)Runtime.LayoutEditor.Shading); SetInt("debugShading", (int)Runtime.LayoutEditor.Shading);
@ -48,6 +60,8 @@ namespace LayoutBXLYT
SetVec2("uvTranslate0", new Vector2(0, 0)); SetVec2("uvTranslate0", new Vector2(0, 0));
SetInt("flipTexture", 0); SetInt("flipTexture", 0);
SetBool("ThresholdingAlphaInterpolation", material.ThresholdingAlphaInterpolation); SetBool("ThresholdingAlphaInterpolation", material.ThresholdingAlphaInterpolation);
SetInt($"texCoords0GenType", 0);
SetInt($"texCoords0Source", 0);
BindTextureUniforms(); BindTextureUniforms();

View File

@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Syroot.Maths; using Syroot.Maths;
using Toolbox.Library.IO; using Toolbox.Library.IO;
using Toolbox.Library.Animations;
using Toolbox.Library; using Toolbox.Library;
using WeifenLuo.WinFormsUI.Docking; using WeifenLuo.WinFormsUI.Docking;
using System.ComponentModel; using System.ComponentModel;
@ -13,6 +14,12 @@ namespace LayoutBXLYT
{ {
public class BasePane : SectionCommon 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 IsRoot = false;
public bool ParentIsRoot public bool ParentIsRoot
@ -114,7 +121,15 @@ namespace LayoutBXLYT
public CustomRectangle CreateRectangle() public CustomRectangle CreateRectangle()
{ {
//Do origin transforms //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); var parentTransform = ParentOriginTransform(transformed);
return new CustomRectangle( return new CustomRectangle(
@ -219,6 +234,47 @@ namespace LayoutBXLYT
else else
return false; 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 public enum FilterMode
@ -336,12 +392,6 @@ namespace LayoutBXLYT
Material = 1 Material = 1
} }
public enum KeyType : byte
{
Uin16 = 1,
Float = 2,
}
public enum LPATarget : byte public enum LPATarget : byte
{ {
TranslateX = 0x00, TranslateX = 0x00,
@ -353,7 +403,7 @@ namespace LayoutBXLYT
ScaleX = 0x06, ScaleX = 0x06,
ScaleY = 0x07, ScaleY = 0x07,
SizeX = 0x08, SizeX = 0x08,
SizeZ = 0x09, SizeY = 0x09,
} }
public enum LTSTarget : byte public enum LTSTarget : byte
@ -397,7 +447,9 @@ namespace LayoutBXLYT
public enum LTPTarget : byte 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 public enum LMCTarget : byte
@ -485,6 +537,18 @@ namespace LayoutBXLYT
Rotate270 = 5 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 public enum TevMode : byte
{ {
Replace, Replace,
@ -501,6 +565,100 @@ namespace LayoutBXLYT
EachIndirect, 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 public interface IWindowPane
{ {
bool UseOneMaterialForAll { get; set; } bool UseOneMaterialForAll { get; set; }
@ -523,6 +681,11 @@ namespace LayoutBXLYT
List<BxlytWindowFrame> WindowFrames { get; set; } List<BxlytWindowFrame> WindowFrames { get; set; }
} }
public class BXLAN
{
public BxlanHeader BxlanHeader;
}
public class BxlytWindowContent public class BxlytWindowContent
{ {
public STColor8 ColorTopLeft { get; set; } public STColor8 ColorTopLeft { get; set; }
@ -637,6 +800,24 @@ namespace LayoutBXLYT
{ {
public BxlanPAT1 AnimationTag; public BxlanPAT1 AnimationTag;
public BxlanPAI1 AnimationInfo; 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 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 public class BxlanPaiTagEntry
{ {
[Browsable(false)] [Browsable(false)]
@ -741,49 +1001,110 @@ namespace LayoutBXLYT
[DisplayName("Index"), CategoryAttribute("Tag")] [DisplayName("Index"), CategoryAttribute("Tag")]
public byte Index { get; set; } public byte Index { get; set; }
[DisplayName("Data Type"), CategoryAttribute("Tag")] [DisplayName("Curve Type"), CategoryAttribute("Tag")]
public KeyType DataType { get; set; } public CurveType CurveType { get; set; }
public List<KeyFrame> KeyFrames = new List<KeyFrame>(); 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 public class KeyFrame
{ {
[DisplayName("Blend"), CategoryAttribute("Key Frame")] [DisplayName("Slope"), CategoryAttribute("Key Frame")]
public float Blend { get; set; } public float Slope { get; set; }
[DisplayName("Frame"), CategoryAttribute("Key Frame")] [DisplayName("Frame"), CategoryAttribute("Key Frame")]
public float Frame { get; set; } public float Frame { get; set; }
[DisplayName("Value"), CategoryAttribute("Key Frame")] [DisplayName("Value"), CategoryAttribute("Key Frame")]
public float Value { get; set; } public float Value { get; set; }
public KeyFrame(FileReader reader, KeyType DataType) public KeyFrame(FileReader reader, CurveType curveType)
{ {
Frame = reader.ReadSingle(); switch (curveType)
switch (DataType)
{ {
case KeyType.Float: case CurveType.Hermite:
Frame = reader.ReadSingle();
Value = reader.ReadSingle(); Value = reader.ReadSingle();
Blend = reader.ReadSingle(); Slope = reader.ReadSingle();
break; break;
case KeyType.Uin16: default:
Value = (float)reader.ReadInt16(); Frame = reader.ReadSingle();
Blend = (float)reader.ReadInt16(); Value = reader.ReadInt16();
reader.ReadInt16(); //padding
break; break;
} }
} }
public void Write(FileWriter writer, KeyType DataType) public void Write(FileWriter writer, CurveType curveType)
{ {
writer.Write(Frame); switch (curveType)
switch (DataType)
{ {
case KeyType.Float: case CurveType.Hermite:
writer.Write(Frame);
writer.Write(Value); writer.Write(Value);
writer.Write(Blend); writer.Write(Slope);
break; break;
case KeyType.Uin16: default:
writer.Write(Frame);
writer.Write((ushort)Value); writer.Write((ushort)Value);
writer.Write((ushort)Blend); writer.Write((ushort)0);
break; break;
} }
} }
@ -791,6 +1112,9 @@ namespace LayoutBXLYT
public class BxlytHeader : LayoutHeader public class BxlytHeader : LayoutHeader
{ {
[Browsable(false)]
public Dictionary<string, BasePane> PaneLookup = new Dictionary<string, BasePane>();
[Browsable(false)] [Browsable(false)]
public BasePane RootPane { get; set; } public BasePane RootPane { get; set; }
@ -811,10 +1135,30 @@ namespace LayoutBXLYT
{ {
return new List<BxlytMaterial>(); 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 public class BxlytMaterial
{ {
[Browsable(false)]
public MaterialAnimController animController = new MaterialAnimController();
[DisplayName("Name"), CategoryAttribute("General")] [DisplayName("Name"), CategoryAttribute("General")]
public virtual string Name { get; set; } public virtual string Name { get; set; }
@ -828,6 +1172,36 @@ namespace LayoutBXLYT
public BxlytTextureRef[] TextureMaps { get; set; } 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 public class SectionCommon
{ {
[Browsable(false)] [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 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 public class RenderablePane
{ {
int vbo_position; int vbo_position;
int ibo_position;
public struct Vertex public struct Vertex
{ {
public Vector3 Position; public Vector2 Position;
public Vector4 Color; public Vector4 Color;
public Vector2 TexCoord0; public Vector2 TexCoord0;
public Vector2 TexCoord1; public Vector2 TexCoord1;
public Vector2 TexCoord2; 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 vbo_position);
GL.GenBuffers(1, out ibo_position);
UpdateVertexData(positions, colors, texCoords0); UpdateVertexData(positions, colors, texCoords0);
} }
public void Destroy() public void Destroy()
{ {
bool buffersWereInitialized = vbo_position != 0; bool buffersWereInitialized = vbo_position != 0 && ibo_position != 0;
if (!buffersWereInitialized) if (!buffersWereInitialized)
return; return;
GL.DeleteBuffer(vbo_position); GL.DeleteBuffer(vbo_position);
GL.DeleteBuffer(vbo_position);
} }
public Vertex[] Vertices; 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) if (!buffersWereInitialized)
GenerateBuffers(positions, colors, texCoords0); GenerateBuffers(positions, colors, texCoords0);
shader.EnableVertexAttributes();
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position); GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 0); GL.VertexAttribPointer(shader.GetAttribute("vPosition"), 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 0);
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 12); GL.VertexAttribPointer(shader.GetAttribute("vColor"), 4, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 8);
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 28); GL.VertexAttribPointer(shader.GetAttribute("vTexCoord0"), 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 24);
GL.VertexAttribPointer(3, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 36); GL.VertexAttribPointer(shader.GetAttribute("vTexCoord1"), 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 32);
GL.VertexAttribPointer(4, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 44); GL.VertexAttribPointer(shader.GetAttribute("vTexCoord2"), 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, 40);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_position);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3); 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]; Vertices = new Vertex[positions.Length];
for (int v = 0; v < Vertices.Length; v++) for (int v = 0; v < Vertices.Length; v++)
@ -67,7 +76,13 @@ namespace LayoutBXLYT
Vertices[v].TexCoord0 = texCoords0[v]; 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.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.BufferData<Vertex>(BufferTarget.ArrayBuffer, GL.BufferData<Vertex>(BufferTarget.ArrayBuffer,
new IntPtr(Vertices.Length * Vertex.SizeInBytes), new IntPtr(Vertices.Length * Vertex.SizeInBytes),

View File

@ -11,7 +11,7 @@ using SharpYaml.Serialization;
namespace LayoutBXLYT namespace LayoutBXLYT
{ {
public class BRLAN : IEditorForm<LayoutEditor>, IFileFormat, IConvertableTextFormat public class BRLAN : BXLAN, IEditorForm<LayoutEditor>, IFileFormat, IConvertableTextFormat
{ {
public FileType FileType { get; set; } = FileType.Layout; public FileType FileType { get; set; } = FileType.Layout;
@ -71,14 +71,12 @@ namespace LayoutBXLYT
#endregion #endregion
Header header;
public void Load(System.IO.Stream stream) public void Load(System.IO.Stream stream)
{ {
CanSave = true; CanSave = true;
header = new Header(); BxlanHeader = new Header();
header.Read(new FileReader(stream),this); BxlanHeader.Read(new FileReader(stream),this);
} }
public void Unload() public void Unload()
{ {
@ -86,20 +84,20 @@ namespace LayoutBXLYT
} }
public void Save(System.IO.Stream stream) { public void Save(System.IO.Stream stream) {
header.Write(new FileWriter(stream)); BxlanHeader.Write(new FileWriter(stream));
} }
public LayoutEditor OpenForm() public LayoutEditor OpenForm()
{ {
LayoutEditor editor = new LayoutEditor(); LayoutEditor editor = new LayoutEditor();
editor.Dock = DockStyle.Fill; editor.Dock = DockStyle.Fill;
editor.LoadBxlan(header); editor.LoadBxlan(BxlanHeader);
return editor; return editor;
} }
public void FillEditor(Form control) public void FillEditor(Form control)
{ {
((LayoutEditor)control).LoadBxlan(header); ((LayoutEditor)control).LoadBxlan(BxlanHeader);
} }
public class Header : BxlanHeader public class Header : BxlanHeader
@ -111,7 +109,7 @@ namespace LayoutBXLYT
//As of now this should be empty but just for future proofing //As of now this should be empty but just for future proofing
private List<SectionCommon> UnknownSections = new List<SectionCommon>(); 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(); AnimationTag = new PAT1();
AnimationInfo = new PAI1(); AnimationInfo = new PAI1();
@ -126,7 +124,7 @@ namespace LayoutBXLYT
ushort sectionCount = reader.ReadUInt16(); ushort sectionCount = reader.ReadUInt16();
reader.ReadUInt16(); //Padding reader.ReadUInt16(); //Padding
FileInfo = bflan; FileInfo = (IFileFormat)bflan;
IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian; IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian;
reader.SeekBegin(HeaderSize); reader.SeekBegin(HeaderSize);
@ -156,7 +154,7 @@ namespace LayoutBXLYT
} }
} }
public void Write(FileWriter writer) public override void Write(FileWriter writer)
{ {
writer.SetByteOrder(true); writer.SetByteOrder(true);
writer.WriteSignature(Magic); writer.WriteSignature(Magic);
@ -394,25 +392,25 @@ namespace LayoutBXLYT
switch (Tag) switch (Tag)
{ {
case "RLPA": case "RLPA":
Entries.Add(new FLPATagEntry(reader, header)); Entries.Add(new LPATagEntry(reader, header));
break; break;
case "RLTS": case "RLTS":
Entries.Add(new FLTSTagEntry(reader, header)); Entries.Add(new LTSTagEntry(reader, header));
break; break;
case "RLVI": case "RLVI":
Entries.Add(new FLVITagEntry(reader, header)); Entries.Add(new LVITagEntry(reader, header));
break; break;
case "RLVC": case "RLVC":
Entries.Add(new FLVCTagEntry(reader, header)); Entries.Add(new LVCTagEntry(reader, header));
break; break;
case "RLMC": case "RLMC":
Entries.Add(new FLMCTagEntry(reader, header)); Entries.Add(new LMCTagEntry(reader, header));
break; break;
case "RLTP": case "RLTP":
Entries.Add(new FLTPTagEntry(reader, header)); Entries.Add(new LTPTagEntry(reader, header));
break; break;
default: default:
Entries.Add(new PaiTagEntry(reader, header)); Entries.Add(new BxlanPaiTagEntry(reader, header));
break; break;
} }
} }
@ -432,122 +430,9 @@ namespace LayoutBXLYT
for (int i = 0; i < Entries.Count; i++) for (int i = 0; i < Entries.Count; i++)
{ {
writer.WriteUint32Offset(startPos + 8 + (i * 4), startPos); 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; IsBigEndian = reader.ByteOrder == Syroot.BinaryData.ByteOrder.BigEndian;
PaneLookup.Clear();
LayoutInfo = new LYT1(); LayoutInfo = new LYT1();
TextureList = new TXL1(); TextureList = new TXL1();
MaterialList = new MAT1(); MaterialList = new MAT1();
@ -276,6 +277,7 @@ namespace LayoutBXLYT
break; break;
case "pan1": case "pan1":
var panel = new PAN1(reader); var panel = new PAN1(reader);
AddPaneToTable(panel);
if (!setRoot) if (!setRoot)
{ {
RootPane = panel; RootPane = panel;
@ -287,30 +289,36 @@ namespace LayoutBXLYT
break; break;
case "pic1": case "pic1":
var picturePanel = new PIC1(reader, this); var picturePanel = new PIC1(reader, this);
AddPaneToTable(picturePanel);
SetPane(picturePanel, parentPane); SetPane(picturePanel, parentPane);
currentPane = picturePanel; currentPane = picturePanel;
break; break;
case "txt1": case "txt1":
var textPanel = new TXT1(reader); var textPanel = new TXT1(reader);
AddPaneToTable(textPanel);
SetPane(textPanel, parentPane); SetPane(textPanel, parentPane);
currentPane = textPanel; currentPane = textPanel;
break; break;
case "bnd1": case "bnd1":
var boundsPanel = new BND1(reader); var boundsPanel = new BND1(reader);
AddPaneToTable(boundsPanel);
SetPane(boundsPanel, parentPane); SetPane(boundsPanel, parentPane);
currentPane = boundsPanel; currentPane = boundsPanel;
break; break;
case "prt1": case "prt1":
var partsPanel = new PRT1(reader); var partsPanel = new PRT1(reader);
AddPaneToTable(partsPanel);
SetPane(partsPanel, parentPane); SetPane(partsPanel, parentPane);
currentPane = partsPanel; currentPane = partsPanel;
break; break;
case "wnd1": case "wnd1":
var windowPanel = new WND1(reader); var windowPanel = new WND1(reader);
AddPaneToTable(windowPanel);
SetPane(windowPanel, parentPane); SetPane(windowPanel, parentPane);
currentPane = windowPanel; currentPane = windowPanel;
break; break;
@ -554,7 +562,7 @@ namespace LayoutBXLYT
} }
} }
public class BND1 : PAN1 public class BND1 : PAN1, IBoundryPane
{ {
public BND1() : base() public BND1() : base()
{ {
@ -620,7 +628,7 @@ namespace LayoutBXLYT
} }
} }
public class PIC1 : PAN1 public class PIC1 : PAN1, IPicturePane
{ {
public TexCoord[] TexCoords { get; set; } public TexCoord[] TexCoords { get; set; }
@ -701,7 +709,7 @@ namespace LayoutBXLYT
{ {
private byte _flags1; private byte _flags1;
public bool Visible public override bool Visible
{ {
get { return (_flags1 & 0x1) == 0x1; } get { return (_flags1 & 0x1) == 0x1; }
set { set {
@ -868,7 +876,6 @@ namespace LayoutBXLYT
public STColor8 TevColor3 { get; set; } public STColor8 TevColor3 { get; set; }
public STColor8 TevColor4 { get; set; } public STColor8 TevColor4 { get; set; }
public List<TextureRef> TextureMaps { get; set; }
public List<TextureTransform> TextureTransforms { get; set; } public List<TextureTransform> TextureTransforms { get; set; }
private uint flags; private uint flags;
@ -884,7 +891,7 @@ namespace LayoutBXLYT
public Material() public Material()
{ {
TextureMaps = new List<TextureRef>(); TextureMaps = new TextureRef[0];
TextureTransforms = new List<TextureTransform>(); TextureTransforms = new List<TextureTransform>();
} }
@ -892,7 +899,6 @@ namespace LayoutBXLYT
{ {
ParentLayout = header; ParentLayout = header;
TextureMaps = new List<TextureRef>();
TextureTransforms = new List<TextureTransform>(); TextureTransforms = new List<TextureTransform>();
Name = reader.ReadString(0x14, true); Name = reader.ReadString(0x14, true);
@ -906,12 +912,15 @@ namespace LayoutBXLYT
TevColor4 = reader.ReadColor8RGBA(); TevColor4 = reader.ReadColor8RGBA();
flags = reader.ReadUInt32(); flags = reader.ReadUInt32();
uint indSrtCount = ExtractBits(flags, 2, 17); uint indSrtCount = ExtractBits(flags, 2, 17);
uint texCoordGenCount = ExtractBits(flags, 4, 20); uint texCoordGenCount = ExtractBits(flags, 4, 20);
uint mtxCount = ExtractBits(flags, 4, 24); uint mtxCount = ExtractBits(flags, 4, 24);
uint texCount = ExtractBits(flags, 4, 28); uint texCount = ExtractBits(flags, 4, 28);
TextureMaps = new TextureRef[texCount];
for (int i = 0; i < texCount; i++) 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++) for (int i = 0; i < mtxCount; i++)
TextureTransforms.Add(new TextureTransform(reader)); TextureTransforms.Add(new TextureTransform(reader));
@ -924,8 +933,8 @@ namespace LayoutBXLYT
// writer.Write(BackColor); // writer.Write(BackColor);
writer.Write(flags); writer.Write(flags);
for (int i = 0; i < TextureMaps.Count; i++) for (int i = 0; i < TextureMaps.Length; i++)
TextureMaps[i].Write(writer); ((TextureRef)TextureMaps[i]).Write(writer);
for (int i = 0; i < TextureTransforms.Count; i++) for (int i = 0; i < TextureTransforms.Count; i++)
TextureTransforms[i].Write(writer); TextureTransforms[i].Write(writer);
@ -984,12 +993,12 @@ namespace LayoutBXLYT
public TextureRef() {} public TextureRef() {}
public TextureRef(FileReader reader, Header header) { public TextureRef(FileReader reader, Header header) {
if (header.Textures.Count > 0)
Name = header.Textures[ID];
ID = reader.ReadInt16(); ID = reader.ReadInt16();
flag1 = reader.ReadByte(); flag1 = reader.ReadByte();
flag2 = reader.ReadByte(); flag2 = reader.ReadByte();
if (header.Textures.Count > 0)
Name = header.Textures[ID];
} }
public void Write(FileWriter writer) public void Write(FileWriter writer)

View File

@ -31,46 +31,140 @@ namespace LayoutBXLYT
SetInt("textures1", 0); SetInt("textures1", 0);
SetInt("textures2", 0); SetInt("textures2", 0);
SetBool("ThresholdingAlphaInterpolation", false); SetBool("ThresholdingAlphaInterpolation", false);
var rotationMatrix = Matrix4.Identity;
SetMatrix("rotationMatrix", ref rotationMatrix);
SetInt("numTevStages", 0);
SetVec2("uvScale0", new Vector2(1, 1)); SetVec2("uvScale0", new Vector2(1, 1));
SetFloat("uvRotate0", 0); SetFloat("uvRotate0", 0);
SetVec2("uvTranslate0", new Vector2(0, 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)); var paneRotate = pane.Rotate;
SetColor("blackColor", material.BlackColor.Color); 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("debugShading", (int)Runtime.LayoutEditor.Shading);
SetInt("numTextureMaps", material.TextureMaps.Count); SetInt("numTextureMaps", material.TextureMaps.Length);
SetVec2("uvScale0", new Vector2(1, 1)); SetVec2("uvScale0", new Vector2(1, 1));
SetFloat("uvRotate0", 0); SetFloat("uvRotate0", 0);
SetVec2("uvTranslate0", new Vector2(0, 0)); SetVec2("uvTranslate0", new Vector2(0, 0));
SetInt("flipTexture", 0); SetInt("flipTexture", 0);
SetInt("numTevStages", 0);
SetBool("ThresholdingAlphaInterpolation", material.ThresholdingAlphaInterpolation); 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(); BindTextureUniforms();
string textureMap0 = ""; int id = 1;
if (material.TextureMaps.Count > 0) for (int i = 0; i < material.TextureMaps.Length; i++)
textureMap0 = material.GetTexture(0);
if (textures.ContainsKey(textureMap0))
{ {
GL.ActiveTexture(TextureUnit.Texture0); string TexName = material.TextureMaps[i].Name;
SetInt("textures0", 0);
bool isBinded = BxlytToGL.BindGLTexture(material.TextureMaps[0], textures[textureMap0]); if (material.animController.TexturePatterns.ContainsKey((LTPTarget)i))
if (isBinded) TexName = material.animController.TexturePatterns[(LTPTarget)i];
SetInt("hasTexture0", 1);
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) if (material.TextureTransforms.Count > 0)
{ {
var transform = material.TextureTransforms[0]; var transform = material.TextureTransforms[0];
SetVec2("uvScale0",new Vector2(transform.Scale.X, transform.Scale.Y)); var scale = transform.Scale;
SetFloat("uvRotate0", transform.Rotate); var rotate = transform.Rotate;
SetVec2("uvTranslate0",new Vector2( transform.Translate.X, transform.Translate.Y)); 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() private void BindTextureUniforms()
@ -80,7 +174,7 @@ namespace LayoutBXLYT
GL.Uniform1(GL.GetUniformLocation(program, "uvTestPattern"), 10); GL.Uniform1(GL.GetUniformLocation(program, "uvTestPattern"), 10);
GL.BindTexture(TextureTarget.Texture2D, RenderTools.uvTestPattern.RenderableTex.TexID); GL.BindTexture(TextureTarget.Texture2D, RenderTools.uvTestPattern.RenderableTex.TexID);
if (material.TextureMaps.Count > 0) if (material.TextureMaps.Length > 0)
{ {
var tex = material.TextureMaps[0]; var tex = material.TextureMaps[0];
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, BxlytToGL.ConvertTextureWrap(tex.WrapModeU)); 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\Common.cs" />
<Compile Include="FileFormats\DKCTF\MSBT.cs" /> <Compile Include="FileFormats\DKCTF\MSBT.cs" />
<Compile Include="FileFormats\DKCTF\PAK.cs" /> <Compile Include="FileFormats\DKCTF\PAK.cs" />
<Compile Include="FileFormats\Font\BXFNT.cs" />
<Compile Include="FileFormats\HedgehogEngine\HeaderCommon.cs" /> <Compile Include="FileFormats\HedgehogEngine\HeaderCommon.cs" />
<Compile Include="FileFormats\HedgehogEngine\HedgeModel.cs" /> <Compile Include="FileFormats\HedgehogEngine\HedgeModel.cs" />
<Compile Include="FileFormats\HedgehogEngine\PACx.cs" /> <Compile Include="FileFormats\HedgehogEngine\PACx.cs" />
@ -296,6 +297,9 @@
<Compile Include="FileFormats\Font\BFTTF.cs" /> <Compile Include="FileFormats\Font\BFTTF.cs" />
<Compile Include="FileFormats\HyruleWarriors\G1M\G1M.cs" /> <Compile Include="FileFormats\HyruleWarriors\G1M\G1M.cs" />
<Compile Include="FileFormats\HyruleWarriors\LINKDATA.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\BxlytShader.cs" />
<Compile Include="FileFormats\Layout\BxlytToGL.cs" /> <Compile Include="FileFormats\Layout\BxlytToGL.cs" />
<Compile Include="FileFormats\Layout\CAFE\FLAN.cs" /> <Compile Include="FileFormats\Layout\CAFE\FLAN.cs" />
@ -311,6 +315,8 @@
<Compile Include="FileFormats\Layout\CTR\BCLYT.cs" /> <Compile Include="FileFormats\Layout\CTR\BCLYT.cs" />
<Compile Include="FileFormats\Layout\CAFE\FLYT.cs" /> <Compile Include="FileFormats\Layout\CAFE\FLYT.cs" />
<Compile Include="FileFormats\Layout\CTR\BclytShader.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\LayoutTextureLoader.cs" />
<Compile Include="FileFormats\Layout\PaneTreeWrapper.cs" /> <Compile Include="FileFormats\Layout\PaneTreeWrapper.cs" />
<Compile Include="FileFormats\Layout\Common.cs" /> <Compile Include="FileFormats\Layout\Common.cs" />
@ -385,7 +391,7 @@
<DependentUpon>LayoutTextureList.cs</DependentUpon> <DependentUpon>LayoutTextureList.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="GUI\BFLYT\LayoutViewer.cs"> <Compile Include="GUI\BFLYT\LayoutViewer.cs">
<SubType>Form</SubType> <SubType>UserControl</SubType>
</Compile> </Compile>
<Compile Include="GUI\BFLYT\LayoutViewer.Designer.cs"> <Compile Include="GUI\BFLYT\LayoutViewer.Designer.cs">
<DependentUpon>LayoutViewer.cs</DependentUpon> <DependentUpon>LayoutViewer.cs</DependentUpon>

View File

@ -55,6 +55,11 @@
this.displayyBoundryPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.displayyBoundryPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.displayWindowPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.displayWindowPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.displayPicturePanesToolStripMenuItem = 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(); ((System.ComponentModel.ISupportInitialize)(this.backColorDisplay)).BeginInit();
this.stToolStrip1.SuspendLayout(); this.stToolStrip1.SuspendLayout();
this.stMenuStrip1.SuspendLayout(); this.stMenuStrip1.SuspendLayout();
@ -150,7 +155,9 @@
this.stMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.stMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem, this.fileToolStripMenuItem,
this.editToolStripMenuItem, this.editToolStripMenuItem,
this.viewToolStripMenuItem}); this.viewToolStripMenuItem,
this.animationToolStripMenuItem,
this.windowToolStripMenuItem});
this.stMenuStrip1.Location = new System.Drawing.Point(0, 0); this.stMenuStrip1.Location = new System.Drawing.Point(0, 0);
this.stMenuStrip1.Name = "stMenuStrip1"; this.stMenuStrip1.Name = "stMenuStrip1";
this.stMenuStrip1.Size = new System.Drawing.Size(549, 24); this.stMenuStrip1.Size = new System.Drawing.Size(549, 24);
@ -172,35 +179,35 @@
// openToolStripMenuItem // openToolStripMenuItem
// //
this.openToolStripMenuItem.Name = "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.Text = "Open";
this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click);
// //
// clearWorkspaceToolStripMenuItem // clearWorkspaceToolStripMenuItem
// //
this.clearWorkspaceToolStripMenuItem.Name = "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.Text = "Clear Files";
this.clearWorkspaceToolStripMenuItem.Click += new System.EventHandler(this.clearWorkspaceToolStripMenuItem_Click); this.clearWorkspaceToolStripMenuItem.Click += new System.EventHandler(this.clearWorkspaceToolStripMenuItem_Click);
// //
// saveToolStripMenuItem1 // saveToolStripMenuItem1
// //
this.saveToolStripMenuItem1.Name = "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.Text = "Save Layout";
this.saveToolStripMenuItem1.Click += new System.EventHandler(this.saveToolStripMenuItem1_Click); this.saveToolStripMenuItem1.Click += new System.EventHandler(this.saveToolStripMenuItem1_Click);
// //
// saveAnimationToolStripMenuItem // saveAnimationToolStripMenuItem
// //
this.saveAnimationToolStripMenuItem.Name = "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.Text = "Save Animation";
this.saveAnimationToolStripMenuItem.Click += new System.EventHandler(this.saveAnimationToolStripMenuItem_Click); this.saveAnimationToolStripMenuItem.Click += new System.EventHandler(this.saveAnimationToolStripMenuItem_Click);
// //
// saveToolStripMenuItem // saveToolStripMenuItem
// //
this.saveToolStripMenuItem.Name = "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.Text = "Save As";
this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click);
// //
@ -221,7 +228,8 @@
this.displayNullPanesToolStripMenuItem, this.displayNullPanesToolStripMenuItem,
this.displayyBoundryPanesToolStripMenuItem, this.displayyBoundryPanesToolStripMenuItem,
this.displayWindowPanesToolStripMenuItem, this.displayWindowPanesToolStripMenuItem,
this.displayPicturePanesToolStripMenuItem}); this.displayPicturePanesToolStripMenuItem,
this.displayTextPanesToolStripMenuItem});
this.viewToolStripMenuItem.Name = "viewToolStripMenuItem"; this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20); this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
this.viewToolStripMenuItem.Text = "View"; this.viewToolStripMenuItem.Text = "View";
@ -306,6 +314,46 @@
this.displayPicturePanesToolStripMenuItem.Text = "Display Picture Panes"; this.displayPicturePanesToolStripMenuItem.Text = "Display Picture Panes";
this.displayPicturePanesToolStripMenuItem.Click += new System.EventHandler(this.displayPanesToolStripMenuItem_Click); 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 // LayoutEditor
// //
this.AllowDrop = true; this.AllowDrop = true;
@ -321,6 +369,7 @@
this.Controls.Add(this.stMenuStrip1); this.Controls.Add(this.stMenuStrip1);
this.IsMdiContainer = true; this.IsMdiContainer = true;
this.Name = "LayoutEditor"; this.Name = "LayoutEditor";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.LayoutEditor_FormClosed);
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.LayoutEditor_DragDrop); this.DragDrop += new System.Windows.Forms.DragEventHandler(this.LayoutEditor_DragDrop);
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.LayoutEditor_DragEnter); this.DragEnter += new System.Windows.Forms.DragEventHandler(this.LayoutEditor_DragEnter);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.LayoutEditor_KeyDown); 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 displayPicturePanesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem renderInGamePreviewToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem renderInGamePreviewToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem displayGridToolStripMenuItem; 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> /// </summary>
public static bool UseLegacyGL = true; public static bool UseLegacyGL = true;
public LayoutViewer GamePreviewWindow;
private LayoutCustomPaneMapper CustomMapper;
private Dictionary<string, STGenericTexture> Textures; private Dictionary<string, STGenericTexture> Textures;
public List<BxlytHeader> LayoutFiles = new List<BxlytHeader>(); public List<BxlytHeader> LayoutFiles = new List<BxlytHeader>();
@ -45,6 +49,7 @@ namespace LayoutBXLYT
public LayoutEditor() public LayoutEditor()
{ {
InitializeComponent(); InitializeComponent();
CustomMapper = new LayoutCustomPaneMapper();
Textures = new Dictionary<string, STGenericTexture>(); Textures = new Dictionary<string, STGenericTexture>();
@ -67,6 +72,7 @@ namespace LayoutBXLYT
displayWindowPanesToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayWindowPane; displayWindowPanesToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayWindowPane;
renderInGamePreviewToolStripMenuItem.Checked = Runtime.LayoutEditor.IsGamePreview; renderInGamePreviewToolStripMenuItem.Checked = Runtime.LayoutEditor.IsGamePreview;
displayGridToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayGrid; displayGridToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayGrid;
displayTextPanesToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayTextPane;
ObjectSelected += OnObjectSelected; ObjectSelected += OnObjectSelected;
ObjectChanged += OnObjectChanged; ObjectChanged += OnObjectChanged;
@ -85,26 +91,64 @@ namespace LayoutBXLYT
private LayoutProperties LayoutProperties; private LayoutProperties LayoutProperties;
private LayoutTextDocked TextConverter; private LayoutTextDocked TextConverter;
private LayoutPartsEditor LayoutPartsEditor; private LayoutPartsEditor LayoutPartsEditor;
private STAnimationPanel AnimationPanel;
private bool isLoaded = false; private bool isLoaded = false;
public void LoadBxlyt(BxlytHeader header) 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); LayoutFiles.Add(header);
ActiveLayout = header; ActiveLayout = header;
LayoutViewer Viewport = new LayoutViewer(header, Textures); if (ActiveViewport == null)
Viewport.Dock = DockStyle.Fill; {
Viewport.Show(dockPanel1, DockState.Document); LayoutViewer Viewport = new LayoutViewer(this,header, Textures);
Viewport.DockHandler.AllowEndUserDocking = false; Viewport.DockContent = new DockContent();
Viewports.Add(Viewport); Viewport.DockContent.Controls.Add(Viewport);
ActiveViewport = Viewport; Viewport.Dock = DockStyle.Fill;
ActiveViewport.UseOrtho = orthographicViewToolStripMenuItem.Checked; 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) if (!isLoaded)
InitializeDockPanels(); InitializeDockPanels();
AnimLayoutHierarchy?.SearchAnimations(header, ObjectSelected); AnimLayoutHierarchy?.SearchAnimations(header, ObjectSelected);
CustomMapper.LoadMK8DCharaSelect(Textures, header);
isLoaded = true; isLoaded = true;
} }
@ -128,6 +172,7 @@ namespace LayoutBXLYT
ShowPaneHierarchy(); ShowPaneHierarchy();
ShowPropertiesPanel(); ShowPropertiesPanel();
UpdateBackColor(); UpdateBackColor();
ShowAnimationPanel();
} }
private void ResetEditors() private void ResetEditors()
@ -180,6 +225,19 @@ namespace LayoutBXLYT
{ {
if (isChecked) return; 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") if (LayoutProperties != null && (string)sender == "Select")
{ {
ActiveViewport?.SelectedPanes.Clear(); 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) private void ToggleChildern(TreeNode node, bool isChecked)
{ {
if (node.Tag is BasePane) if (node.Tag is BasePane)
@ -220,9 +297,17 @@ namespace LayoutBXLYT
ToggleChildern(child, isChecked); 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) private void LayoutEditor_ParentChanged(object sender, EventArgs e)
@ -289,6 +374,21 @@ namespace LayoutBXLYT
LayoutTextureList.Show(dockPanel1, DockState.DockRight); 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) private void stComboBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{ {
@ -569,7 +669,7 @@ namespace LayoutBXLYT
{ {
if (fileFormat.CanSave) if (fileFormat.CanSave)
{ {
if (fileFormat.IFileInfo != null && if (fileFormat.IFileInfo != null &&
fileFormat.IFileInfo.ArchiveParent != null && !ForceDialog) fileFormat.IFileInfo.ArchiveParent != null && !ForceDialog)
{ {
if (fileFormat is IEditorFormParameters) if (fileFormat is IEditorFormParameters)
@ -622,7 +722,7 @@ namespace LayoutBXLYT
orthographicViewToolStripMenuItem.Checked = false; orthographicViewToolStripMenuItem.Checked = false;
else else
orthographicViewToolStripMenuItem.Checked = true; orthographicViewToolStripMenuItem.Checked = true;
ToggleOrthMode(); ToggleOrthMode();
} }
@ -630,12 +730,12 @@ namespace LayoutBXLYT
{ {
if (ActiveViewport != null) if (ActiveViewport != null)
{ {
if (orthographicViewToolStripMenuItem.Checked) if (!orthographicViewToolStripMenuItem.Checked)
toolstripOrthoBtn.Image = BitmapExtension.GrayScale(FirstPlugin.Properties.Resources.OrthoView); toolstripOrthoBtn.Image = BitmapExtension.GrayScale(FirstPlugin.Properties.Resources.OrthoView);
else else
toolstripOrthoBtn.Image = FirstPlugin.Properties.Resources.OrthoView; toolstripOrthoBtn.Image = FirstPlugin.Properties.Resources.OrthoView;
ActiveViewport.UseOrtho = orthographicViewToolStripMenuItem.Checked; Runtime.LayoutEditor.UseOrthographicView = orthographicViewToolStripMenuItem.Checked;
ActiveViewport.ResetCamera(); ActiveViewport.ResetCamera();
ActiveViewport.UpdateViewport(); ActiveViewport.UpdateViewport();
} }
@ -654,6 +754,7 @@ namespace LayoutBXLYT
Runtime.LayoutEditor.DisplayBoundryPane = displayyBoundryPanesToolStripMenuItem.Checked; Runtime.LayoutEditor.DisplayBoundryPane = displayyBoundryPanesToolStripMenuItem.Checked;
Runtime.LayoutEditor.DisplayPicturePane = displayPicturePanesToolStripMenuItem.Checked; Runtime.LayoutEditor.DisplayPicturePane = displayPicturePanesToolStripMenuItem.Checked;
Runtime.LayoutEditor.DisplayWindowPane = displayWindowPanesToolStripMenuItem.Checked; Runtime.LayoutEditor.DisplayWindowPane = displayWindowPanesToolStripMenuItem.Checked;
Runtime.LayoutEditor.DisplayTextPane = displayTextPanesToolStripMenuItem.Checked;
ActiveViewport?.UpdateViewport(); ActiveViewport?.UpdateViewport();
} }
@ -669,5 +770,31 @@ namespace LayoutBXLYT
Runtime.LayoutEditor.DisplayGrid = displayGridToolStripMenuItem.Checked; Runtime.LayoutEditor.DisplayGrid = displayGridToolStripMenuItem.Checked;
ActiveViewport?.UpdateViewport(); 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(); treeView1.BeginUpdate();
foreach (var file in parentArchive.Files) 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); LoadAnimation(file);
} }
} }
treeView1.EndUpdate(); treeView1.EndUpdate();
treeView1.Sort();
isLoaded = true; isLoaded = true;
} }
@ -124,7 +127,7 @@ namespace LayoutBXLYT
isLoaded = false; isLoaded = false;
} }
private void LoadAnimations(BxlanHeader bxlan, TreeNode root, bool LoadRoot = true) public void LoadAnimations(BxlanHeader bxlan, TreeNode root, bool LoadRoot = true)
{ {
if (LoadRoot) if (LoadRoot)
treeView1.Nodes.Add(root); treeView1.Nodes.Add(root);
@ -420,18 +423,7 @@ namespace LayoutBXLYT
//Allows for faster loading //Allows for faster loading
if (e.Node.Tag is ArchiveFileInfo) 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 namespace LayoutBXLYT
{ {
public partial class LayoutViewer : LayoutDocked public partial class LayoutViewer : LayoutControlDocked
{ {
public List<BasePane> SelectedPanes = new List<BasePane>(); public List<BasePane> SelectedPanes = new List<BasePane>();
@ -24,12 +24,16 @@ namespace LayoutBXLYT
public class Camera2D public class Camera2D
{ {
public Matrix4 ModelViewMatrix = Matrix4.Identity;
public float Zoom = 1; public float Zoom = 1;
public Vector2 Position; public Vector2 Position;
} }
private LayoutEditor ParentEditor;
private RenderableTex backgroundTex; private RenderableTex backgroundTex;
public BxlytHeader LayoutFile; public BxlytHeader LayoutFile;
public List<BxlytHeader> LayoutFiles = new List<BxlytHeader>();
private Dictionary<string, STGenericTexture> Textures; private Dictionary<string, STGenericTexture> Textures;
private void glControl1_Load(object sender, EventArgs e) private void glControl1_Load(object sender, EventArgs e)
@ -47,31 +51,44 @@ namespace LayoutBXLYT
UpdateViewport(); UpdateViewport();
} }
public LayoutViewer(BxlytHeader bxlyt, Dictionary<string, STGenericTexture> textures) public GLControl GetGLControl() => glControl1;
public LayoutViewer(LayoutEditor editor, BxlytHeader bxlyt, Dictionary<string, STGenericTexture> textures)
{ {
InitializeComponent(); InitializeComponent();
LayoutFile = bxlyt;
ParentEditor = editor;
Text = bxlyt.FileName; Text = bxlyt.FileName;
Textures = textures; Textures = textures;
LoadLayout(bxlyt);
}
public void LoadLayout(BxlytHeader bxlyt)
{
LayoutFile = bxlyt;
LayoutFiles.Add(bxlyt);
if (bxlyt.Textures.Count > 0) 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); foreach (var tex in LayoutFile.Textures)
return; {
if (Textures.ContainsKey(tex))
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) Textures[tex].DisposeRenderable();
e.Cancel = true; Textures.Remove(tex);
else }
LayoutFile.Dispose(); }
base.OnFormClosing(e);
} }
public void UpdateViewport() public void UpdateViewport()
@ -88,29 +105,81 @@ namespace LayoutBXLYT
OnRender(); 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 Color BackgroundColor => Runtime.LayoutEditor.BackgroundColor;
private void OnRender() private void OnRender()
{ {
if (LayoutFile == null) return; 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.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.MatrixMode(MatrixMode.Projection); GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity(); GL.LoadIdentity();
if (UseOrtho) 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.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 else
{ {
var cameraPosition = new Vector3(Camera.Position.X, Camera.Position.Y, -(Camera.Zoom * 500)); 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.LoadMatrix(ref perspectiveMatrix);
GL.MatrixMode(MatrixMode.Modelview); GL.MatrixMode(MatrixMode.Modelview);
Camera.ModelViewMatrix = perspectiveMatrix;
} }
RenderScene();
}
private void RenderScene()
{
GL.ClearColor(BackgroundColor); GL.ClearColor(BackgroundColor);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
@ -122,21 +191,32 @@ namespace LayoutBXLYT
GL.Enable(EnableCap.ColorMaterial); GL.Enable(EnableCap.ColorMaterial);
GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0); GL.BindTexture(TextureTarget.Texture2D, 0);
GL.BlendEquation(BlendEquationMode.FuncAdd);
if (UseOrtho) if (UseOrtho && !GameWindow)
{ {
GL.PushMatrix(); 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); GL.Translate(Camera.Position.X, Camera.Position.Y, 0);
} }
DrawRootPane(LayoutFile.RootPane); if (!GameWindow)
DrawGrid(); {
DrawXyLines(); DrawRootPane(LayoutFile.RootPane);
DrawGrid();
DrawXyLines();
}
GL.BindTexture(TextureTarget.Texture2D, 0); 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) if (UseOrtho)
GL.PopMatrix(); GL.PopMatrix();
@ -146,9 +226,10 @@ namespace LayoutBXLYT
glControl1.SwapBuffers(); 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; return;
GL.PushMatrix(); GL.PushMatrix();
@ -162,73 +243,106 @@ namespace LayoutBXLYT
GL.Rotate(pane.Rotate.Z, 0, 0, 1); GL.Rotate(pane.Rotate.Z, 0, 0, 1);
GL.Scale(pane.Scale.X, pane.Scale.Y, 1); GL.Scale(pane.Scale.X, pane.Scale.Y, 1);
if (pane is BFLYT.PAN1) DrawDefaultPane(shader, pane, true);
DrawDefaultPane((BFLYT.PAN1)pane);
else if (pane is BCLYT.PAN1)
DrawDefaultPane((BCLYT.PAN1)pane);
else if (pane is BRLYT.PAN1)
DrawDefaultPane((BRLYT.PAN1)pane);
GL.PopMatrix(); 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) if (partPane != null)
{ {
var translate = partPane.Translate + pane.Translate; translate = translate + pane.Translate;
var scale = partPane.Scale * pane.Scale; scale = scale * pane.Scale;
var rotate = partPane.Rotate + pane.Rotate; 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.X, 1, 0, 0);
GL.Rotate(rotate.Y, 0, 1, 0); GL.Rotate(rotate.Y, 0, 1, 0);
GL.Rotate(rotate.Z, 0, 0, 1); 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) if (!parentAlphaInfluence)
effectiveAlpha = pane.Alpha; effectiveAlpha = alpha;
parentAlphaInfluence = parentAlphaInfluence || pane.InfluenceAlpha; parentAlphaInfluence = parentAlphaInfluence || pane.InfluenceAlpha;
if (!isRoot) if (!isRoot)
{ {
if (pane is BFLYT.PIC1 || pane is BCLYT.PIC1 || pane is BRLYT.PIC1) if (pane is IPicturePane)
BxlytToGL.DrawPictureBox(pane, effectiveAlpha, Textures); BxlytToGL.DrawPictureBox(pane, GameWindow, effectiveAlpha, Textures);
else if (pane is IWindowPane) else if (pane is IWindowPane)
BxlytToGL.DrawWindowPane(pane, effectiveAlpha, Textures); BxlytToGL.DrawWindowPane(pane, GameWindow, effectiveAlpha, Textures);
else if (pane is BFLYT.BND1 || pane is BCLYT.BND1 || pane is BRLYT.BND1) else if (pane is IBoundryPane)
BxlytToGL.DrawBoundryPane(pane, effectiveAlpha, SelectedPanes); 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) else if (pane is BFLYT.SCR1)
BxlytToGL.DrawScissorPane(pane, effectiveAlpha, SelectedPanes); BxlytToGL.DrawScissorPane(pane, GameWindow, effectiveAlpha, SelectedPanes);
else if (pane is BFLYT.ALI1) else if (pane is BFLYT.ALI1)
BxlytToGL.DrawAlignmentPane(pane, effectiveAlpha, SelectedPanes); BxlytToGL.DrawAlignmentPane(pane, GameWindow, effectiveAlpha, SelectedPanes);
else if (pane is BFLYT.PRT1) else if (pane is BFLYT.PRT1)
DrawPartsPane((BFLYT.PRT1)pane, effectiveAlpha, parentAlphaInfluence); DrawPartsPane(shader, (BFLYT.PRT1)pane, effectiveAlpha, parentAlphaInfluence);
else else
DrawDefaultPane(pane); DrawDefaultPane(shader, pane);
} }
else else
isRoot = false; isRoot = false;
byte childAlpha = pane.InfluenceAlpha || parentAlphaInfluence ? effectiveAlpha : byte.MaxValue; byte childAlpha = pane.InfluenceAlpha || parentAlphaInfluence ? effectiveAlpha : byte.MaxValue;
foreach (var childPane in pane.Childern) foreach (var childPane in pane.Childern)
RenderPanes(childPane, isRoot, childAlpha, parentAlphaInfluence, partPane); RenderPanes(shader, childPane, isRoot, childAlpha, parentAlphaInfluence, partPane);
GL.PopMatrix(); GL.PopMatrix();
} }
@ -262,9 +376,9 @@ namespace LayoutBXLYT
GL.End(); 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; return;
Vector2[] TexCoords = new Vector2[] { Vector2[] TexCoords = new Vector2[] {
@ -285,17 +399,17 @@ namespace LayoutBXLYT
color, 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); pane.UpdateTextureData(this.Textures);
var partPane = pane.GetExternalPane(); var partPane = pane.GetExternalPane();
if (partPane != null) if (partPane != null)
RenderPanes(partPane, true, effectiveAlpha, parentInfluenceAlpha); RenderPanes(shader,partPane, true, effectiveAlpha, parentInfluenceAlpha);
else else
DrawDefaultPane(pane); DrawDefaultPane(shader, pane);
if (pane.Properties != null) if (pane.Properties != null)
{ {
@ -303,7 +417,7 @@ namespace LayoutBXLYT
{ {
if (prop.Property != null) 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() private void DrawXyLines()
{ {
if (Runtime.LayoutEditor.IsGamePreview) if (GameWindow || Runtime.LayoutEditor.IsGamePreview)
return; return;
int lineLength = 20; 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) protected override void OnMouseWheel(MouseEventArgs e)
{ {
base.OnMouseWheel(e); base.OnMouseWheel(e);

View File

@ -9,6 +9,8 @@ namespace FirstPlugin
{ {
public class PluginRuntime public class PluginRuntime
{ {
public static List<BXFNT> BxfntFiles = new List<BXFNT>();
public static List<SARC> SarcArchives = new List<SARC>(); public static List<SARC> SarcArchives = new List<SARC>();
public class MaterialReplace 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 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> /// <summary>
/// Represents a class for animating a skeleton /// Represents a class for animating a skeleton
/// </summary> /// </summary>
public class STSkeletonAnimation public class STAnimation
{ {
/// <summary> /// <summary>
/// The total amount of frames to play in the animation /// The name of the animation.
/// </summary> /// </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": case "DisplayWindowPane":
bool.TryParse(node.InnerText, out Runtime.LayoutEditor.DisplayWindowPane); bool.TryParse(node.InnerText, out Runtime.LayoutEditor.DisplayWindowPane);
break; break;
case "DisplayTextPane":
bool.TryParse(node.InnerText, out Runtime.LayoutEditor.DisplayTextPane);
break;
case "LayoutDisplayGrid": case "LayoutDisplayGrid":
bool.TryParse(node.InnerText, out Runtime.LayoutEditor.DisplayGrid); bool.TryParse(node.InnerText, out Runtime.LayoutEditor.DisplayGrid);
break; break;
@ -404,6 +407,7 @@ namespace Toolbox.Library
layoutSettingsNode.AppendChild(createNode(doc, "DisplayBoundryPane", Runtime.LayoutEditor.DisplayBoundryPane.ToString())); layoutSettingsNode.AppendChild(createNode(doc, "DisplayBoundryPane", Runtime.LayoutEditor.DisplayBoundryPane.ToString()));
layoutSettingsNode.AppendChild(createNode(doc, "DisplayPicturePane", Runtime.LayoutEditor.DisplayPicturePane.ToString())); layoutSettingsNode.AppendChild(createNode(doc, "DisplayPicturePane", Runtime.LayoutEditor.DisplayPicturePane.ToString()));
layoutSettingsNode.AppendChild(createNode(doc, "DisplayWindowPane", Runtime.LayoutEditor.DisplayWindowPane.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) private static void AppendDeveloperSettings(XmlDocument doc, XmlNode parentNode)

View File

@ -289,7 +289,7 @@ namespace Toolbox.Library
if (currentAnimation == null || totalFrame.Value <= 0) if (currentAnimation == null || totalFrame.Value <= 0)
return; return;
currentFrameUpDown.Value = animationTrackBar.CurrentFrame; currentFrameUpDown.Value = (decimal)animationTrackBar.CurrentFrame;
} }
private void OnFrameAdvanced() private void OnFrameAdvanced()
@ -301,7 +301,7 @@ namespace Toolbox.Library
UpdateViewport(); UpdateViewport();
} }
private void SetAnimationsToFrame(int frameNum) private void SetAnimationsToFrame(float frameNum)
{ {
if (currentAnimation == null) if (currentAnimation == null)
return; 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; } get { return currentFrame; }
set set
@ -81,7 +81,7 @@ namespace Toolbox.Library.Forms
} }
} }
public int FrameCount public float FrameCount
{ {
get { return lastFrame + 1; } get { return lastFrame + 1; }
set set
@ -107,8 +107,8 @@ namespace Toolbox.Library.Forms
public bool FollowCurrentFrame = true; public bool FollowCurrentFrame = true;
protected int currentFrame = 0; protected float currentFrame = 0;
protected int lastFrame = 1000; protected float lastFrame = 1000;
protected double frameLeft = 0; protected double frameLeft = 0;
protected double frameRight = 200; protected double frameRight = 200;
@ -193,6 +193,7 @@ namespace Toolbox.Library.Forms
e.Graphics.SetClip(new Rectangle(margin, 0, Width - margin, Height)); e.Graphics.SetClip(new Rectangle(margin, 0, Width - margin, Height));
double currentFrameX = 20 + margin + (currentFrame - frameLeft) * (Width - 40 - margin) / (frameRight - frameLeft); double currentFrameX = 20 + margin + (currentFrame - frameLeft) * (Width - 40 - margin) / (frameRight - frameLeft);
base.OnPaint(e); base.OnPaint(e);
e.Graphics.DrawLine(pen2, new Point((int)currentFrameX, barHeight), new Point((int)currentFrameX, Height)); 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) public static uint ExtractBits(uint val, int numBits, int startBit)
{ {
uint mask = 0; uint mask = 0;
for (int i = startBit; i < startBit + numBits; i++) for (int i = startBit; i < startBit + numBits; i++)
mask |= (0x80000000 >> i); mask |= (0x80000000 >> i);

View File

@ -107,6 +107,13 @@ namespace Toolbox.Library.Rendering
return tex; return tex;
} }
public void UpdateFromBitmap(Bitmap bitmap)
{
width = bitmap.Width;
height = bitmap.Height;
TexID = GenerateOpenGLTexture(this, bitmap);
}
private bool UseMipmaps = false; private bool UseMipmaps = false;
private bool UseOpenGLDecoder = true; private bool UseOpenGLDecoder = true;
public void LoadOpenGLTexture(STGenericTexture GenericTexture, int ArrayStartIndex = 0, bool LoadArrayLevels = false) 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 IsGamePreview = false;
public static bool DisplayNullPane = true; public static bool DisplayNullPane = true;
public static bool DisplayTextPane = true;
public static bool DisplayBoundryPane = true; public static bool DisplayBoundryPane = true;
public static bool DisplayPicturePane = true; public static bool DisplayPicturePane = true;
public static bool DisplayWindowPane = true; public static bool DisplayWindowPane = true;
@ -73,6 +74,7 @@ namespace Toolbox.Library
public static bool DisplayScissorPane = true; public static bool DisplayScissorPane = true;
public static bool DisplayGrid = true; public static bool DisplayGrid = true;
public static bool UseOrthographicView = true;
public static Color BackgroundColor = Color.FromArgb(130, 130, 130); public static Color BackgroundColor = Color.FromArgb(130, 130, 130);

View File

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

View File

@ -12,6 +12,11 @@ namespace Toolbox.Library
{ {
public class Utils public class Utils
{ {
public static bool CompareNoExtension(string a, string b)
{
return (Path.GetFileNameWithoutExtension(a) == Path.GetFileNameWithoutExtension(b));
}
public static byte[] CreateMD5Hash(string filename) public static byte[] CreateMD5Hash(string filename)
{ {
using (var md5 = System.Security.Cryptography.MD5.Create()) using (var md5 = System.Security.Cryptography.MD5.Create())

View File

@ -2,20 +2,148 @@
uniform vec4 blackColor; uniform vec4 blackColor;
uniform vec4 whiteColor; uniform vec4 whiteColor;
uniform int hasTexture0;
uniform int debugShading; uniform int debugShading;
uniform int numTextureMaps; uniform int numTextureMaps;
uniform sampler2D textures0; 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; uniform sampler2D uvTestPattern;
in vec2 uv0; in vec4 VertexColor;
in vec4 vertexColor0; 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; 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() void main()
{ {
fragColor = vec4(1);
vec4 textureMap0 = vec4(1); vec4 textureMap0 = vec4(1);
vec4 textureMap1 = vec4(1); vec4 textureMap1 = vec4(1);
vec4 textureMap2 = vec4(1); vec4 textureMap2 = vec4(1);
@ -23,22 +151,81 @@ void main()
if (numTextureMaps > 0) if (numTextureMaps > 0)
{ {
if (hasTexture0 == 1) 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) if (debugShading == 0)
{ {
vec4 colorBlend = textureMap0 * whiteColor; // Convert to sRGB.
fragColor = vertexColor0 * colorBlend; 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) else if (debugShading == 5)
fragColor = vec4(textureMap0.rgb, 1); fragColor = vec4(textureMap0.rgb, 1);
else if (debugShading == 1) else if (debugShading == 1)
fragColor = vertexColor0; fragColor = VertexColor;
else if (debugShading == 2) else if (debugShading == 2)
fragColor = whiteColor; fragColor = whiteColor;
else if (debugShading == 3) else if (debugShading == 3)
fragColor = blackColor; fragColor = blackColor;
else if (debugShading == 4) else if (debugShading == 4)
fragColor = texture2D(uvTestPattern, uv0); fragColor = texture2D(uvTestPattern, TexCoord0.st);
} }

View File

@ -1,10 +1,10 @@
#version 330 #version 330
layout(location = 0) in vec3 position; in vec2 vPosition;
layout(location = 1) in vec4 color; in vec4 vColor;
layout(location = 2) in vec2 texCoord0; in vec2 vTexCoord0;
layout(location = 3) in vec2 texCoord1; in vec2 vTexCoord1;
layout(location = 4) in vec2 texCoord2; in vec2 vTexCoord2;
uniform mat4 modelViewMatrix; uniform mat4 modelViewMatrix;
uniform vec2 uvScale0; uniform vec2 uvScale0;
@ -12,7 +12,10 @@ uniform vec2 uvRotate0;
uniform vec2 uvTranslate0; uniform vec2 uvTranslate0;
uniform int flipTexture; uniform int flipTexture;
out vec2 uv0; out vec4 VertexColor;
out vec2 TexCoord0;
out vec2 TexCoord1;
out vec2 TexCoord2;
vec2 rotateUV(vec2 uv, float rotation) vec2 rotateUV(vec2 uv, float rotation)
{ {
@ -43,7 +46,11 @@ vec2 SetFlip(vec2 tex)
void main() void main()
{ {
vec2 texCoord0Transformed = uvScale0 * texCoord0.xy + uvTranslate0; vec2 texCoord0Transformed = uvScale0 * vTexCoord0.xy + uvTranslate0;
uv0 = SetFlip(texCoord0Transformed); TexCoord0 = SetFlip(texCoord0Transformed);
gl_Position = modelViewMatrix * vec4(position,1); 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 hasTexture1;
uniform int hasTexture2; 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 ThresholdingAlphaInterpolation;
uniform int numTevStages;
uniform sampler2D uvTestPattern; uniform sampler2D uvTestPattern;
#define gamma 2.2 #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() void main()
{ {
vec4 textureMap0 = vec4(1); vec4 textureMap0 = vec4(1);
@ -28,8 +117,11 @@ void main()
{ {
if (hasTexture0 == 1) if (hasTexture0 == 1)
textureMap0 = texture2D(textures0, gl_TexCoord[0].st); 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) if (debugShading == 0)
{ {
// Convert to sRGB. // Convert to sRGB.
@ -37,19 +129,50 @@ void main()
vec3 whiteInterpolation = whiteColorSRGB.rgb * textureMap0.rgb; vec3 whiteInterpolation = whiteColorSRGB.rgb * textureMap0.rgb;
vec3 blackInterpolation = (vec3(1) - textureMap0.rgb) * blackColor.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; 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 for (int i = 0; i < numTevStages; i++)
if (textureMap0.a >= whiteColor.a) alpha = 1.0; {
if (textureMap0.a <= blackColor.a) alpha = 0.0; j1 = textureMap0;
// if (blackColor.a < alpha && alpha < whiteColor.a) j2 = textureMap1;
// alpha = mix(0.0, 1.0, textureMap0.a); 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) else if (debugShading == 5)
gl_FragColor = vec4(textureMap0.rgb, 1); gl_FragColor = vec4(textureMap0.rgb, 1);

View File

@ -2,6 +2,9 @@
uniform vec2 uvRotate0; uniform vec2 uvRotate0;
uniform vec2 uvTranslate0; uniform vec2 uvTranslate0;
uniform int flipTexture; uniform int flipTexture;
uniform mat4 rotationMatrix;
uniform int texCoords0GenType;
uniform int texCoords0Source;
vec2 rotateUV(vec2 uv, float rotation) vec2 rotateUV(vec2 uv, float rotation)
{ {
@ -30,10 +33,27 @@ vec2 SetFlip(vec2 tex)
return outTexCoord; 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() void main()
{ {
gl_FrontColor = gl_Color; gl_FrontColor = gl_Color;
vec2 texCoord0 = vec2(0.5, 0.5) + uvScale0 * (gl_MultiTexCoord0.xy + (uvTranslate0 / uvScale0 - 0.5)); 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_TexCoord[0].st = SetFlip(texCoord0);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_Position = gl_ModelViewProjectionMatrix * rotationMatrix * gl_Vertex;
} }