ed78d46545
Opengl textures that are not power of 2 decode from ST decoder. This prevents those from not loading. (Common in SMM1, SMM2, and also BFLYT). Bflyt displays bounding panes, and window panes display textures. Window panes still need more work for rendering. Bflyt now uses custom shaders for more advancements with rendering. Legacy PCs should still work fine with this. Fixed uv transforms for bflyt if they are negative, which flips them. Fixed an issue loading bclyt layouts. Fixed pane trnasformation issues. They are nearly perfect, but rotations for X and Y are off. Parts now search for opened sarc archives. Fixed an issue with some spaces not quite saving for txt1 panes. This may fix some saving issues, as most i've tried output back identically. Fixed an issue displaying LA8 textures.
935 lines
34 KiB
C#
935 lines
34 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using OpenTK.Graphics.OpenGL;
|
|
using OpenTK;
|
|
using Toolbox.Library;
|
|
using Toolbox.Library.Rendering;
|
|
using Toolbox.Library.IO;
|
|
using LayoutBXLYT.Cafe;
|
|
|
|
namespace LayoutBXLYT
|
|
{
|
|
public partial class LayoutViewer : LayoutDocked
|
|
{
|
|
public List<BasePane> SelectedPanes = new List<BasePane>();
|
|
|
|
public Camera2D Camera = new Camera2D();
|
|
|
|
public class Camera2D
|
|
{
|
|
public float Zoom = 1;
|
|
public Vector2 Position;
|
|
}
|
|
|
|
private RenderableTex backgroundTex;
|
|
public BxlytHeader LayoutFile;
|
|
private Dictionary<string, STGenericTexture> Textures;
|
|
|
|
private void glControl1_Load(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
public void ResetCamera()
|
|
{
|
|
Camera = new Camera2D();
|
|
}
|
|
|
|
public void ResetLayout(BxlytHeader bxlyt)
|
|
{
|
|
LayoutFile = bxlyt;
|
|
UpdateViewport();
|
|
}
|
|
|
|
public LayoutViewer(BxlytHeader bxlyt, Dictionary<string, STGenericTexture> textures)
|
|
{
|
|
InitializeComponent();
|
|
LayoutFile = bxlyt;
|
|
Text = bxlyt.FileName;
|
|
|
|
Textures = textures;
|
|
if (bxlyt.Textures.Count > 0)
|
|
{
|
|
if (bxlyt.FileInfo is BFLYT)
|
|
Textures = ((BFLYT)bxlyt.FileInfo).GetTextures();
|
|
else if (bxlyt.FileInfo is BCLYT)
|
|
Textures = ((BCLYT)bxlyt.FileInfo).GetTextures();
|
|
}
|
|
}
|
|
|
|
protected override void OnFormClosing(FormClosingEventArgs e)
|
|
{
|
|
if (LayoutEditor.IsSaving)
|
|
{
|
|
base.OnFormClosing(e);
|
|
return;
|
|
}
|
|
|
|
var result = MessageBox.Show("Are you sure you want to close this file? You will lose any unsaved progress!", "Layout Editor", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
|
if (result != DialogResult.Yes)
|
|
e.Cancel = true;
|
|
else
|
|
LayoutFile.Dispose();
|
|
|
|
base.OnFormClosing(e);
|
|
}
|
|
|
|
public void UpdateViewport()
|
|
{
|
|
glControl1.Invalidate();
|
|
}
|
|
|
|
private void glControl1_Paint(object sender, PaintEventArgs e)
|
|
{
|
|
if (!Runtime.OpenTKInitialized)
|
|
return;
|
|
|
|
glControl1.Context.MakeCurrent(glControl1.WindowInfo);
|
|
OnRender();
|
|
}
|
|
|
|
public bool UseOrtho = true;
|
|
private Color BackgroundColor => Runtime.LayoutEditor.BackgroundColor;
|
|
private void OnRender()
|
|
{
|
|
if (LayoutFile == null) return;
|
|
|
|
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
|
|
GL.MatrixMode(MatrixMode.Projection);
|
|
GL.LoadIdentity();
|
|
if (UseOrtho)
|
|
{
|
|
GL.Ortho(-(glControl1.Width / 2.0f), glControl1.Width / 2.0f, glControl1.Height / 2.0f, -(glControl1.Height / 2.0f), -10000, 10000);
|
|
GL.MatrixMode(MatrixMode.Modelview);
|
|
GL.LoadIdentity();
|
|
}
|
|
else
|
|
{
|
|
var cameraPosition = new Vector3(Camera.Position.X, Camera.Position.Y, -(Camera.Zoom * 500));
|
|
var perspectiveMatrix = Matrix4.CreateTranslation(cameraPosition) * Matrix4.CreatePerspectiveFieldOfView(1.3f, glControl1.Width / (float)glControl1.Height, 0.01f, 100000);
|
|
GL.LoadMatrix(ref perspectiveMatrix);
|
|
GL.MatrixMode(MatrixMode.Modelview);
|
|
}
|
|
|
|
GL.ClearColor(BackgroundColor);
|
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
|
|
|
// GL.Disable(EnableCap.CullFace);
|
|
GL.Enable(EnableCap.Blend);
|
|
GL.Enable(EnableCap.AlphaTest);
|
|
GL.AlphaFunc(AlphaFunction.Always, 0f);
|
|
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
|
GL.Enable(EnableCap.ColorMaterial);
|
|
GL.Enable(EnableCap.Texture2D);
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
|
|
if (UseOrtho)
|
|
{
|
|
GL.PushMatrix();
|
|
GL.Scale(1 * Camera.Zoom, -1 * Camera.Zoom, 1);
|
|
GL.Translate(Camera.Position.X, Camera.Position.Y, 0);
|
|
}
|
|
|
|
DrawRootPane(LayoutFile.RootPane);
|
|
DrawGrid();
|
|
DrawXyLines();
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
|
|
RenderPanes(LayoutFile.RootPane, true, 255, false, null, 0);
|
|
|
|
if (UseOrtho)
|
|
GL.PopMatrix();
|
|
|
|
GL.UseProgram(0);
|
|
|
|
glControl1.SwapBuffers();
|
|
}
|
|
|
|
private void RenderPanes(BasePane pane, bool isRoot, byte parentAlpha, bool parentAlphaInfluence, BasePane partPane = null, int stage = 0)
|
|
{
|
|
if (!pane.DisplayInEditor)
|
|
return;
|
|
|
|
GL.PushMatrix();
|
|
|
|
//Check XY rotation and draw the pane before it was rotated
|
|
bool isRotatedXY = pane.Rotate.X != 0 || pane.Rotate.Y != 0;
|
|
if (isRotatedXY && SelectedPanes.Contains(pane))
|
|
{
|
|
GL.PushMatrix();
|
|
GL.Translate(pane.Translate.X, pane.Translate.Y, 0);
|
|
GL.Rotate(pane.Rotate.Z, 0, 0, 1);
|
|
GL.Scale(pane.Scale.X, pane.Scale.Y, 1);
|
|
|
|
if (pane is BFLYT.PAN1)
|
|
DrawDefaultPane((BFLYT.PAN1)pane);
|
|
else if (pane is BCLYT.PAN1)
|
|
DrawDefaultPane((BCLYT.PAN1)pane);
|
|
else if (pane is BRLYT.PAN1)
|
|
DrawDefaultPane((BRLYT.PAN1)pane);
|
|
|
|
GL.PopMatrix();
|
|
}
|
|
|
|
if (partPane != null)
|
|
{
|
|
var translate = partPane.Translate + pane.Translate;
|
|
var scale = partPane.Scale * pane.Scale;
|
|
var rotate = partPane.Rotate + pane.Rotate;
|
|
|
|
GL.Translate(translate.X + translate.X, translate.Y, 0);
|
|
GL.Rotate(rotate.X, 1,0,0);
|
|
GL.Rotate(rotate.Y, 0, 1, 0);
|
|
GL.Rotate(rotate.Z, 0, 0, 1);
|
|
GL.Scale(scale.X, scale.Y, 1);
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
if (!parentAlphaInfluence)
|
|
effectiveAlpha = pane.Alpha;
|
|
|
|
parentAlphaInfluence = parentAlphaInfluence || pane.InfluenceAlpha;
|
|
|
|
if (!isRoot)
|
|
{
|
|
if (pane is BFLYT.PIC1)
|
|
DrawPicturePane((BFLYT.PIC1)pane, effectiveAlpha, stage);
|
|
else if (pane is BCLYT.PIC1)
|
|
DrawPicturePane((BCLYT.PIC1)pane, effectiveAlpha);
|
|
else if (pane is BRLYT.PIC1)
|
|
DrawPicturePane((BRLYT.PIC1)pane, effectiveAlpha);
|
|
else if (pane is BFLYT.WND1)
|
|
DrawWindowPane((BFLYT.WND1)pane, effectiveAlpha);
|
|
else if (pane is BFLYT.BND1)
|
|
DrawBoundryPane((BFLYT.BND1)pane, effectiveAlpha);
|
|
else if (pane is BFLYT.PRT1)
|
|
DrawPartsPane((BFLYT.PRT1)pane, effectiveAlpha, parentAlphaInfluence);
|
|
else if (pane is BFLYT.PAN1)
|
|
DrawDefaultPane((BFLYT.PAN1)pane);
|
|
else if (pane is BCLYT.PAN1)
|
|
DrawDefaultPane((BCLYT.PAN1)pane);
|
|
else if (pane is BRLYT.PAN1)
|
|
DrawDefaultPane((BRLYT.PAN1)pane);
|
|
}
|
|
else
|
|
isRoot = false;
|
|
|
|
byte childAlpha = pane.InfluenceAlpha || parentAlphaInfluence ? effectiveAlpha : byte.MaxValue;
|
|
foreach (var childPane in pane.Childern)
|
|
RenderPanes(childPane, isRoot, childAlpha, parentAlphaInfluence, partPane);
|
|
|
|
GL.PopMatrix();
|
|
}
|
|
|
|
private void DrawRootPane(BasePane pane)
|
|
{
|
|
Color color = Color.Black;
|
|
if (SelectedPanes.Contains(pane))
|
|
color = Color.Red;
|
|
|
|
CustomRectangle rect = pane.CreateRectangle();
|
|
|
|
//Draw a quad which is the backcolor but lighter
|
|
GL.Begin(PrimitiveType.Quads);
|
|
GL.Color3(BackgroundColor.Lighten(10));
|
|
GL.Vertex2(rect.LeftPoint, rect.TopPoint);
|
|
GL.Vertex2(rect.RightPoint, rect.TopPoint);
|
|
GL.Vertex2(rect.RightPoint, rect.BottomPoint);
|
|
GL.Vertex2(rect.LeftPoint, rect.BottomPoint);
|
|
GL.End();
|
|
|
|
//Draw outline of root pane
|
|
GL.Begin(PrimitiveType.LineLoop);
|
|
GL.PolygonOffset(0.5f, 2);
|
|
GL.LineWidth(33);
|
|
GL.Color3(color);
|
|
GL.Vertex2(rect.LeftPoint, rect.TopPoint);
|
|
GL.Vertex2(rect.RightPoint, rect.TopPoint);
|
|
GL.Vertex2(rect.RightPoint, rect.BottomPoint);
|
|
GL.Vertex2(rect.LeftPoint, rect.BottomPoint);
|
|
GL.End();
|
|
}
|
|
|
|
private void DrawBoundryPane(BFLYT.BND1 pane, byte effectiveAlpha)
|
|
{
|
|
Vector2[] TexCoords = new Vector2[] {
|
|
new Vector2(1,1),
|
|
new Vector2(0,1),
|
|
new Vector2(0,0),
|
|
new Vector2(1,0)
|
|
};
|
|
|
|
Color color = Color.DarkGreen;
|
|
if (SelectedPanes.Contains(pane))
|
|
color = Color.Red;
|
|
|
|
color = Color.FromArgb(70, color);
|
|
|
|
Color[] Colors = new Color[] {
|
|
color,
|
|
color,
|
|
color,
|
|
color,
|
|
};
|
|
|
|
DrawRectangle(pane.Rectangle, TexCoords, Colors, false, effectiveAlpha);
|
|
}
|
|
|
|
private void DrawDefaultPane(BasePane pane)
|
|
{
|
|
Vector2[] TexCoords = new Vector2[] {
|
|
new Vector2(1,1),
|
|
new Vector2(0,1),
|
|
new Vector2(0,0),
|
|
new Vector2(1,0)
|
|
};
|
|
|
|
Color color = Color.White;
|
|
if (SelectedPanes.Contains(pane))
|
|
color = Color.Red;
|
|
|
|
Color[] Colors = new Color[] {
|
|
color,
|
|
color,
|
|
color,
|
|
color,
|
|
};
|
|
|
|
DrawRectangle(pane.Rectangle, TexCoords, Colors);
|
|
}
|
|
|
|
private void DrawPartsPane(BFLYT.PRT1 pane, byte effectiveAlpha, bool parentInfluenceAlpha)
|
|
{
|
|
pane.UpdateTextureData(this.Textures);
|
|
var partPane = pane.GetExternalPane();
|
|
if (partPane != null)
|
|
RenderPanes(partPane, true, effectiveAlpha, parentInfluenceAlpha);
|
|
else
|
|
DrawDefaultPane(pane);
|
|
|
|
if (pane.Properties != null)
|
|
{
|
|
foreach (var prop in pane.Properties)
|
|
{
|
|
if (prop.Property != null)
|
|
{
|
|
RenderPanes(prop.Property, false, effectiveAlpha, parentInfluenceAlpha || pane.InfluenceAlpha);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawWindowPane(BFLYT.WND1 pane, byte effectiveAlpha)
|
|
{
|
|
Vector2[] TexCoords = new Vector2[] {
|
|
new Vector2(1,1),
|
|
new Vector2(0,1),
|
|
new Vector2(0,0),
|
|
new Vector2(1,0)
|
|
};
|
|
|
|
Color[] Colors = new Color[] {
|
|
pane.Content.ColorTopLeft.Color,
|
|
pane.Content.ColorTopRight.Color,
|
|
pane.Content.ColorBottomRight.Color,
|
|
pane.Content.ColorBottomLeft.Color,
|
|
};
|
|
|
|
|
|
float frameLeft = 0;
|
|
float frameTop = 0;
|
|
float frameRight = 0;
|
|
float frameBottom = 0;
|
|
if (pane.FrameCount == 1)
|
|
{
|
|
|
|
}
|
|
else if (pane.FrameCount == 4)
|
|
{
|
|
|
|
}
|
|
else if (pane.FrameCount == 8)
|
|
{
|
|
|
|
}
|
|
|
|
var mat = pane.Content.Material;
|
|
if (mat.Shader == null)
|
|
{
|
|
mat.Shader = new BflytShader(mat);
|
|
mat.Shader.Compile();
|
|
}
|
|
|
|
mat.Shader.Enable();
|
|
((BflytShader)mat.Shader).SetMaterials(Textures);
|
|
if (pane.Content.TexCoords.Count > 0)
|
|
{
|
|
TexCoords = new Vector2[] {
|
|
pane.Content.TexCoords[0].TopLeft.ToTKVector2(),
|
|
pane.Content.TexCoords[0].TopRight.ToTKVector2(),
|
|
pane.Content.TexCoords[0].BottomRight.ToTKVector2(),
|
|
pane.Content.TexCoords[0].BottomLeft.ToTKVector2(),
|
|
};
|
|
}
|
|
|
|
DrawRectangle(pane.Rectangle, TexCoords, Colors, false, effectiveAlpha);
|
|
|
|
mat.Shader.Disable();
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
GL.PopAttrib();
|
|
}
|
|
|
|
private void DrawPicturePane(BCLYT.PIC1 pane, byte effectiveAlpha)
|
|
{
|
|
Vector2[] TexCoords = new Vector2[] {
|
|
new Vector2(1,1),
|
|
new Vector2(0,1),
|
|
new Vector2(0,0),
|
|
new Vector2(1,0)
|
|
};
|
|
|
|
Color[] Colors = new Color[] {
|
|
pane.ColorTopLeft.Color,
|
|
pane.ColorTopRight.Color,
|
|
pane.ColorBottomRight.Color,
|
|
pane.ColorBottomLeft.Color,
|
|
};
|
|
|
|
var mat = pane.Material;
|
|
if (pane.TexCoords.Length > 0)
|
|
{
|
|
string textureMap0 = "";
|
|
if (mat.TextureMaps.Count > 0)
|
|
textureMap0 = mat.GetTexture(0);
|
|
|
|
// if (Textures.ContainsKey(textureMap0))
|
|
// BindGLTexture(mat.TextureMaps[0], Textures[textureMap0]);
|
|
|
|
TexCoords = new Vector2[] {
|
|
pane.TexCoords[0].TopLeft.ToTKVector2(),
|
|
pane.TexCoords[0].TopRight.ToTKVector2(),
|
|
pane.TexCoords[0].BottomRight.ToTKVector2(),
|
|
pane.TexCoords[0].BottomLeft.ToTKVector2(),
|
|
};
|
|
}
|
|
|
|
DrawRectangle(pane.Rectangle, TexCoords, Colors, false, effectiveAlpha);
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
}
|
|
|
|
private void DrawPicturePane(BRLYT.PIC1 pane, byte effectiveAlpha)
|
|
{
|
|
Vector2[] TexCoords = new Vector2[] {
|
|
new Vector2(1,1),
|
|
new Vector2(0,1),
|
|
new Vector2(0,0),
|
|
new Vector2(1,0)
|
|
};
|
|
|
|
Color[] Colors = new Color[] {
|
|
pane.ColorTopLeft.Color,
|
|
pane.ColorTopRight.Color,
|
|
pane.ColorBottomRight.Color,
|
|
pane.ColorBottomLeft.Color,
|
|
};
|
|
|
|
if (pane.TexCoords.Length > 0)
|
|
{
|
|
var mat = pane.GetMaterial();
|
|
string textureMap0 = "";
|
|
if (mat.TextureMaps.Count > 0)
|
|
textureMap0 = mat.GetTexture(0);
|
|
|
|
// if (Textures.ContainsKey(textureMap0))
|
|
// BindGLTexture(mat.TextureMaps[0], Textures[textureMap0]);
|
|
if (Runtime.LayoutEditor.Shading == Runtime.LayoutEditor.DebugShading.UVTestPattern)
|
|
GL.BindTexture(TextureTarget.Texture2D, RenderTools.uvTestPattern.RenderableTex.TexID);
|
|
|
|
TexCoords = new Vector2[] {
|
|
pane.TexCoords[0].TopLeft.ToTKVector2(),
|
|
pane.TexCoords[0].TopRight.ToTKVector2(),
|
|
pane.TexCoords[0].BottomRight.ToTKVector2(),
|
|
pane.TexCoords[0].BottomLeft.ToTKVector2(),
|
|
};
|
|
}
|
|
|
|
DrawRectangle(pane.Rectangle, TexCoords, Colors, false, effectiveAlpha);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
}
|
|
|
|
private void DrawPicturePane(BFLYT.PIC1 pane, byte effectiveAlpha, int stage = 0)
|
|
{
|
|
Vector2[] TexCoords = new Vector2[] {
|
|
new Vector2(1,1),
|
|
new Vector2(0,1),
|
|
new Vector2(0,0),
|
|
new Vector2(1,0)
|
|
};
|
|
|
|
Color[] Colors = new Color[] {
|
|
pane.ColorTopLeft.Color,
|
|
pane.ColorTopRight.Color,
|
|
pane.ColorBottomRight.Color,
|
|
pane.ColorBottomLeft.Color,
|
|
};
|
|
|
|
var mat = pane.Material;
|
|
if (mat.Shader == null)
|
|
{
|
|
mat.Shader = new BflytShader(mat);
|
|
mat.Shader.Compile();
|
|
}
|
|
|
|
mat.Shader.Enable();
|
|
((BflytShader)mat.Shader).SetMaterials(Textures);
|
|
|
|
if (pane.TexCoords.Length > 0)
|
|
{
|
|
TexCoords = new Vector2[] {
|
|
pane.TexCoords[0].TopLeft.ToTKVector2(),
|
|
pane.TexCoords[0].TopRight.ToTKVector2(),
|
|
pane.TexCoords[0].BottomRight.ToTKVector2(),
|
|
pane.TexCoords[0].BottomLeft.ToTKVector2(),
|
|
};
|
|
}
|
|
|
|
DrawRectangle(pane.Rectangle, TexCoords, Colors, false, effectiveAlpha);
|
|
|
|
mat.Shader.Disable();
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
GL.PopAttrib();
|
|
}
|
|
|
|
private static BlendingFactor ConvertBlendFactor(BlendMode.GX2BlendFactor blendFactor)
|
|
{
|
|
switch (blendFactor)
|
|
{
|
|
case BlendMode.GX2BlendFactor.DestAlpha: return BlendingFactor.DstAlpha;
|
|
case BlendMode.GX2BlendFactor.DestColor: return BlendingFactor.DstColor;
|
|
case BlendMode.GX2BlendFactor.DestInvAlpha: return BlendingFactor.OneMinusDstAlpha;
|
|
case BlendMode.GX2BlendFactor.DestInvColor: return BlendingFactor.OneMinusDstColor;
|
|
case BlendMode.GX2BlendFactor.Factor0: return BlendingFactor.Zero;
|
|
case BlendMode.GX2BlendFactor.Factor1: return BlendingFactor.One;
|
|
case BlendMode.GX2BlendFactor.SourceAlpha: return BlendingFactor.SrcAlpha;
|
|
case BlendMode.GX2BlendFactor.SourceColor: return BlendingFactor.SrcColor;
|
|
case BlendMode.GX2BlendFactor.SourceInvAlpha: return BlendingFactor.OneMinusSrcAlpha;
|
|
case BlendMode.GX2BlendFactor.SourceInvColor: return BlendingFactor.OneMinusSrcColor;
|
|
default: return BlendingFactor.Zero;
|
|
}
|
|
}
|
|
|
|
private static LogicOp ConvertLogicOperation(BlendMode.GX2LogicOp blendOp)
|
|
{
|
|
switch (blendOp)
|
|
{
|
|
case BlendMode.GX2LogicOp.And: return LogicOp.And;
|
|
case BlendMode.GX2LogicOp.Clear: return LogicOp.Clear;
|
|
case BlendMode.GX2LogicOp.Copy: return LogicOp.Copy;
|
|
case BlendMode.GX2LogicOp.Equiv: return LogicOp.Equiv;
|
|
case BlendMode.GX2LogicOp.Inv: return LogicOp.Invert;
|
|
case BlendMode.GX2LogicOp.Nand: return LogicOp.Nand;
|
|
case BlendMode.GX2LogicOp.NoOp: return LogicOp.Noop;
|
|
case BlendMode.GX2LogicOp.Nor: return LogicOp.Nor;
|
|
case BlendMode.GX2LogicOp.Or: return LogicOp.Or;
|
|
case BlendMode.GX2LogicOp.RevAnd: return LogicOp.AndReverse;
|
|
case BlendMode.GX2LogicOp.RevOr: return LogicOp.OrReverse;
|
|
case BlendMode.GX2LogicOp.Set: return LogicOp.Set;
|
|
case BlendMode.GX2LogicOp.Xor: return LogicOp.Xor;
|
|
case BlendMode.GX2LogicOp.Disable:
|
|
GL.Disable(EnableCap.ColorLogicOp);
|
|
return LogicOp.Noop;
|
|
default: return LogicOp.Noop;
|
|
|
|
}
|
|
}
|
|
|
|
private static BlendEquationMode ConvertBlendOperation(BlendMode.GX2BlendOp blendOp)
|
|
{
|
|
switch (blendOp)
|
|
{
|
|
case BlendMode.GX2BlendOp.Add: return BlendEquationMode.FuncAdd;
|
|
case BlendMode.GX2BlendOp.ReverseSubtract: return BlendEquationMode.FuncReverseSubtract;
|
|
case BlendMode.GX2BlendOp.SelectMax: return BlendEquationMode.Max;
|
|
case BlendMode.GX2BlendOp.SelectMin: return BlendEquationMode.Min;
|
|
case BlendMode.GX2BlendOp.Subtract: return BlendEquationMode.FuncSubtract;
|
|
case BlendMode.GX2BlendOp.Disable:
|
|
GL.Disable(EnableCap.Blend);
|
|
return BlendEquationMode.FuncAdd;
|
|
default: return BlendEquationMode.FuncAdd;
|
|
}
|
|
}
|
|
|
|
public void DrawRectangle(CustomRectangle rect, Vector2[] texCoords,
|
|
Color[] colors, bool useLines = true, byte alpha = 255)
|
|
{
|
|
for (int i = 0; i < colors.Length; i++)
|
|
{
|
|
uint setalpha = (uint)((colors[i].A * alpha) / 255);
|
|
colors[i] = Color.FromArgb((int)setalpha, colors[i]);
|
|
}
|
|
|
|
if (useLines)
|
|
{
|
|
GL.Begin(PrimitiveType.LineLoop);
|
|
GL.Color4(colors[0]);
|
|
GL.Vertex2(rect.LeftPoint, rect.BottomPoint);
|
|
GL.Vertex2(rect.RightPoint, rect.BottomPoint);
|
|
GL.Vertex2(rect.RightPoint, rect.TopPoint);
|
|
GL.Vertex2(rect.LeftPoint, rect.TopPoint);
|
|
GL.End();
|
|
}
|
|
else
|
|
{
|
|
GL.Begin(PrimitiveType.Quads);
|
|
GL.Color4(colors[0]);
|
|
GL.MultiTexCoord2(TextureUnit.Texture0, texCoords[0].X, texCoords[0].Y);
|
|
GL.Vertex2(rect.LeftPoint, rect.BottomPoint);
|
|
GL.Color4(colors[1]);
|
|
GL.MultiTexCoord2(TextureUnit.Texture0, texCoords[1].X, texCoords[1].Y);
|
|
GL.Vertex2(rect.RightPoint, rect.BottomPoint);
|
|
GL.Color4(colors[2]);
|
|
GL.MultiTexCoord2(TextureUnit.Texture0, texCoords[2].X, texCoords[2].Y);
|
|
GL.Vertex2(rect.RightPoint, rect.TopPoint);
|
|
GL.Color4(colors[3]);
|
|
GL.MultiTexCoord2(TextureUnit.Texture0, texCoords[3].X, texCoords[3].Y);
|
|
GL.Vertex2(rect.LeftPoint, rect.TopPoint);
|
|
GL.End();
|
|
|
|
//Draw outline
|
|
GL.Begin(PrimitiveType.LineLoop);
|
|
GL.LineWidth(3);
|
|
GL.Color4(colors[0]);
|
|
GL.Vertex2(rect.LeftPoint, rect.BottomPoint);
|
|
GL.Vertex2(rect.RightPoint, rect.BottomPoint);
|
|
GL.Vertex2(rect.RightPoint, rect.TopPoint);
|
|
GL.Vertex2(rect.LeftPoint, rect.TopPoint);
|
|
GL.End();
|
|
}
|
|
}
|
|
|
|
enum TextureSwizzle
|
|
{
|
|
Zero = All.Zero,
|
|
One = All.One,
|
|
Red = All.Red,
|
|
Green = All.Green,
|
|
Blue = All.Blue,
|
|
Alpha = All.Alpha,
|
|
}
|
|
|
|
public static bool BindGLTexture(TextureRef tex, STGenericTexture texture)
|
|
{
|
|
if (texture.RenderableTex == null || !texture.RenderableTex.GLInitialized)
|
|
texture.LoadOpenGLTexture();
|
|
|
|
//If the texture is still not initialized then return
|
|
if (!texture.RenderableTex.GLInitialized)
|
|
return false;
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, texture.RenderableTex.TexID);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, ConvertChannel(texture.RedChannel));
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, ConvertChannel(texture.GreenChannel));
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, ConvertChannel(texture.BlueChannel));
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, ConvertChannel(texture.AlphaChannel));
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, ConvertTextureWrap(tex.WrapModeU));
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, ConvertTextureWrap(tex.WrapModeV));
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, ConvertMagFilterMode(tex.MaxFilterMode));
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, ConvertMinFilterMode(tex.MinFilterMode));
|
|
|
|
return true;
|
|
}
|
|
|
|
private static int ConvertChannel(STChannelType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case STChannelType.Red: return (int)TextureSwizzle.Red;
|
|
case STChannelType.Green: return (int)TextureSwizzle.Green;
|
|
case STChannelType.Blue: return (int)TextureSwizzle.Blue;
|
|
case STChannelType.Alpha: return (int)TextureSwizzle.Alpha;
|
|
case STChannelType.Zero: return (int)TextureSwizzle.Zero;
|
|
case STChannelType.One: return (int)TextureSwizzle.One;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
private static int ConvertTextureWrap(TextureRef.WrapMode wrapMode)
|
|
{
|
|
switch (wrapMode)
|
|
{
|
|
case TextureRef.WrapMode.Clamp: return (int)TextureWrapMode.Clamp;
|
|
case TextureRef.WrapMode.Mirror: return (int)TextureWrapMode.MirroredRepeat;
|
|
case TextureRef.WrapMode.Repeat: return (int)TextureWrapMode.Repeat;
|
|
default: return (int)TextureWrapMode.Clamp;
|
|
}
|
|
}
|
|
|
|
private static int ConvertMagFilterMode(TextureRef.FilterMode filterMode)
|
|
{
|
|
switch (filterMode)
|
|
{
|
|
case TextureRef.FilterMode.Linear: return (int)TextureMagFilter.Linear;
|
|
case TextureRef.FilterMode.Near: return (int)TextureMagFilter.Nearest;
|
|
default: return (int)TextureRef.FilterMode.Linear;
|
|
}
|
|
}
|
|
|
|
private static int ConvertMinFilterMode(TextureRef.FilterMode filterMode)
|
|
{
|
|
switch (filterMode)
|
|
{
|
|
case TextureRef.FilterMode.Linear: return (int)TextureMinFilter.Linear;
|
|
case TextureRef.FilterMode.Near: return (int)TextureMinFilter.Nearest;
|
|
default: return (int)TextureRef.FilterMode.Linear;
|
|
}
|
|
}
|
|
|
|
private void DrawBackground()
|
|
{
|
|
if (backgroundTex == null)
|
|
{
|
|
/* backgroundTex = RenderableTex.FromBitmap(Properties.Resources.GridBackground);
|
|
backgroundTex.TextureWrapR = TextureWrapMode.Repeat;
|
|
backgroundTex.TextureWrapT = TextureWrapMode.Repeat;
|
|
|
|
|
|
GL.Enable(EnableCap.Texture2D);
|
|
GL.BindTexture(TextureTarget.Texture2D, backgroundTex.TexID);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (float)backgroundTex.TextureWrapR);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (float)backgroundTex.TextureWrapT);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)backgroundTex.TextureMagFilter);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)backgroundTex.TextureMinFilter);
|
|
|
|
float UVscale = 15;
|
|
|
|
int PanelWidth = 9000;
|
|
int PanelWHeight = 9000;
|
|
|
|
Vector2 scaleCenter = new Vector2(0.5f, 0.5f);
|
|
|
|
Vector2[] TexCoords = new Vector2[] {
|
|
new Vector2(1,1),
|
|
new Vector2(0,1),
|
|
new Vector2(0,0),
|
|
new Vector2(1,0),
|
|
};
|
|
|
|
for (int i = 0; i < TexCoords.Length; i++)
|
|
TexCoords[i] = (TexCoords[i] - scaleCenter) * 20 + scaleCenter;
|
|
|
|
GL.MatrixMode(MatrixMode.Modelview);
|
|
GL.LoadIdentity();
|
|
GL.PushMatrix();
|
|
GL.Scale(1, 1, 1);
|
|
GL.Translate(0, 0, 0);
|
|
|
|
GL.Color4(Color.White);
|
|
|
|
GL.Begin(PrimitiveType.Quads);
|
|
GL.TexCoord2(TexCoords[0]);
|
|
GL.Vertex3(PanelWidth, PanelWHeight, 0);
|
|
GL.TexCoord2(TexCoords[1]);
|
|
GL.Vertex3(-PanelWidth, PanelWHeight, 0);
|
|
GL.TexCoord2(TexCoords[2]);
|
|
GL.Vertex3(-PanelWidth, -PanelWHeight, 0);
|
|
GL.TexCoord2(TexCoords[3]);
|
|
GL.Vertex3(PanelWidth, -PanelWHeight, 0);
|
|
GL.End();
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
GL.PopMatrix();*/
|
|
}
|
|
}
|
|
|
|
public void UpdateBackgroundColor(Color color)
|
|
{
|
|
Runtime.LayoutEditor.BackgroundColor = color;
|
|
glControl1.Invalidate();
|
|
Config.Save();
|
|
}
|
|
|
|
private void DrawXyLines()
|
|
{
|
|
int lineLength = 20;
|
|
|
|
GL.Color3(Color.Green);
|
|
GL.Begin(PrimitiveType.Lines);
|
|
GL.Vertex2(0, 0);
|
|
GL.Vertex2(0, lineLength);
|
|
GL.End();
|
|
|
|
GL.Color3(Color.Red);
|
|
GL.Begin(PrimitiveType.Lines);
|
|
GL.Vertex2(0, 0);
|
|
GL.Vertex2(lineLength, 0);
|
|
GL.End();
|
|
}
|
|
|
|
private void DrawGrid()
|
|
{
|
|
var size = 40;
|
|
var amount = 300;
|
|
|
|
GL.LineWidth(0.001f);
|
|
GL.Color3(BackgroundColor.Darken(20));
|
|
GL.Begin(PrimitiveType.Lines);
|
|
|
|
int squareGridCounter = 0;
|
|
for (var i = -amount; i <= amount; i++)
|
|
{
|
|
if (squareGridCounter > 5)
|
|
{
|
|
squareGridCounter = 0;
|
|
GL.LineWidth(33f);
|
|
}
|
|
else
|
|
{
|
|
GL.LineWidth(0.001f);
|
|
}
|
|
|
|
GL.Vertex2(new Vector2(-amount * size, i * size));
|
|
GL.Vertex2(new Vector2(amount * size, i * size));
|
|
GL.Vertex2(new Vector2(i * size, -amount * size));
|
|
GL.Vertex2(new Vector2(i * size, amount * size));
|
|
|
|
squareGridCounter++;
|
|
}
|
|
GL.End();
|
|
GL.Color3(Color.Transparent);
|
|
GL.PopAttrib();
|
|
}
|
|
|
|
private bool mouseHeldDown = false;
|
|
private bool isPicked = false;
|
|
private Point originMouse;
|
|
private void glControl1_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
SelectedPanes.Clear();
|
|
|
|
//Pick an object for moving
|
|
if (Control.ModifierKeys == Keys.Alt && e.Button == MouseButtons.Left)
|
|
{
|
|
BasePane hitPane = null;
|
|
SearchHit(LayoutFile.RootPane, e.X, e.Y, ref hitPane);
|
|
if (hitPane != null)
|
|
{
|
|
SelectedPanes.Add(hitPane);
|
|
UpdateViewport();
|
|
|
|
isPicked = true;
|
|
}
|
|
}
|
|
else if (e.Button == MouseButtons.Left)
|
|
{
|
|
mouseHeldDown = true;
|
|
originMouse = e.Location;
|
|
|
|
BasePane hitPane = null;
|
|
foreach (var child in LayoutFile.RootPane.Childern)
|
|
SearchHit(child, e.X, e.Y, ref hitPane);
|
|
Console.WriteLine($"Has Hit " + hitPane != null);
|
|
if (hitPane != null)
|
|
{
|
|
SelectedPanes.Add(hitPane);
|
|
UpdateViewport();
|
|
}
|
|
|
|
glControl1.Invalidate();
|
|
}
|
|
|
|
Console.WriteLine("SelectedPanes " + SelectedPanes.Count);
|
|
}
|
|
|
|
private void SearchHit(BasePane pane, int X, int Y, ref BasePane SelectedPane)
|
|
{
|
|
if (pane.IsHit(X, Y)){
|
|
SelectedPane = pane;
|
|
return;
|
|
}
|
|
|
|
foreach (var childPane in pane.Childern)
|
|
SearchHit(childPane, X, Y, ref SelectedPane);
|
|
}
|
|
|
|
private void glControl1_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Left)
|
|
{
|
|
mouseHeldDown = false;
|
|
isPicked = false;
|
|
glControl1.Invalidate();
|
|
}
|
|
}
|
|
|
|
private void glControl1_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (mouseHeldDown)
|
|
{
|
|
var pos = new Vector2(e.Location.X - originMouse.X, e.Location.Y - originMouse.Y);
|
|
Camera.Position.X += pos.X;
|
|
Camera.Position.Y -= pos.Y;
|
|
|
|
originMouse = e.Location;
|
|
|
|
glControl1.Invalidate();
|
|
}
|
|
}
|
|
|
|
protected override void OnClosed(EventArgs e)
|
|
{
|
|
foreach (var tex in LayoutFile.Textures)
|
|
{
|
|
if (Textures.ContainsKey(tex))
|
|
{
|
|
Textures[tex].DisposeRenderable();
|
|
Textures.Remove(tex);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnMouseWheel(MouseEventArgs e)
|
|
{
|
|
base.OnMouseWheel(e);
|
|
if (UseOrtho)
|
|
{
|
|
if (e.Delta > 0 && Camera.Zoom > 0)
|
|
Camera.Zoom += 0.1f;
|
|
if (e.Delta < 0 && Camera.Zoom < 100 && Camera.Zoom > 0.1)
|
|
Camera.Zoom -= 0.1f;
|
|
}
|
|
else
|
|
{
|
|
if (e.Delta > 0 && Camera.Zoom > 0.1)
|
|
Camera.Zoom -= 0.1f;
|
|
if (e.Delta < 0 && Camera.Zoom < 100 && Camera.Zoom > 0)
|
|
Camera.Zoom += 0.1f;
|
|
}
|
|
|
|
glControl1.Invalidate();
|
|
}
|
|
|
|
private void glControl1_Resize(object sender, EventArgs e)
|
|
{
|
|
glControl1.Invalidate();
|
|
}
|
|
}
|
|
}
|