Switch-Toolbox/Switch_Toolbox_Library/OpenGL/Viewport2D.cs
2019-10-15 19:27:17 -04:00

202 lines
6.2 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;
using OpenTK.Graphics.OpenGL;
using Toolbox.Library;
namespace Toolbox.Library.Forms
{
public class Viewport2D : UserControl
{
public virtual bool UseOrtho { get; set; } = false;
public virtual bool UseGrid { get; set; } = true;
public Camera2D Camera = new Camera2D();
public class Camera2D
{
public Matrix4 ViewMatrix = Matrix4.Identity;
public Matrix4 ModelMatrix = Matrix4.Identity;
public Matrix4 ModelViewMatrix
{
get
{
return ModelMatrix * ViewMatrix;
}
}
public float Zoom = 1;
public Vector2 Position;
}
private GLControl glControl1;
private Color BackgroundColor = Color.FromArgb(40, 40, 40);
public Viewport2D()
{
glControl1 = new GLControl();
glControl1.Dock = DockStyle.Fill;
glControl1.MouseDown += glControl1_MouseDown;
glControl1.MouseUp += glControl1_MouseUp;
glControl1.MouseMove += glControl1_MouseMove;
glControl1.Paint += glControl1_Paint;
glControl1.Resize += glControl1_Resize;
Controls.Add(glControl1);
}
public void UpdateViewport() {
glControl1.Invalidate();
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!Runtime.OpenTKInitialized)
return;
glControl1.Context.MakeCurrent(glControl1.WindowInfo);
RenderEditor();
SetupScene();
}
private void RenderEditor()
{
glControl1.MakeCurrent();
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.ViewMatrix = orthoMatrix;
}
else
{
var cameraPosition = new Vector3(Camera.Position.X, Camera.Position.Y, -(Camera.Zoom * 500));
var perspectiveMatrix = Matrix4.CreateRotationY(90) * Matrix4.CreateTranslation(cameraPosition) * Matrix4.CreatePerspectiveFieldOfView(1.3f, glControl1.Width / glControl1.Height, 0.01f, 100000);
GL.LoadMatrix(ref perspectiveMatrix);
GL.MatrixMode(MatrixMode.Modelview);
Camera.ViewMatrix = perspectiveMatrix;
}
GL.ClearColor(BackgroundColor);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
if (UseOrtho)
{
GL.PushMatrix();
GL.Scale(Camera.Zoom, Camera.Zoom, 1);
GL.Translate(Camera.Position.X, Camera.Position.Y, 0);
Matrix4 scaleMat = Matrix4.CreateScale(Camera.Zoom, Camera.Zoom, 1);
Matrix4 transMat = Matrix4.CreateTranslation(Camera.Position.X, -Camera.Position.Y, 0);
Camera.ModelMatrix = scaleMat * transMat;
}
}
private void SetupScene()
{
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);
GL.BlendEquation(BlendEquationMode.FuncAdd);
if (UseGrid)
Render2D.DrawGrid(BackgroundColor);
RenderSceme();
if (UseOrtho)
GL.PopMatrix();
GL.UseProgram(0);
glControl1.SwapBuffers();
}
public virtual void RenderSceme()
{
}
private Point originMouse;
private bool mouseCameraDown;
private void glControl1_MouseDown(object sender, MouseEventArgs e)
{
if (Control.ModifierKeys == Keys.Shift && e.Button == MouseButtons.Left ||
e.Button == MouseButtons.Middle)
{
originMouse = e.Location;
mouseCameraDown = true;
glControl1.Invalidate();
}
}
private void glControl1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Middle)
{
mouseCameraDown = false;
}
}
private void glControl1_MouseMove(object sender, MouseEventArgs e)
{
if (mouseCameraDown)
{
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();
}
}
private void glControl1_Resize(object sender, EventArgs e)
{
glControl1.Invalidate();
}
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();
}
}
}