211 lines
8.2 KiB
C#
211 lines
8.2 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Text;
|
|||
|
using OpenTK;
|
|||
|
using OpenTK.Input;
|
|||
|
using OpenTK.Graphics;
|
|||
|
using OpenTK.Graphics.OpenGL;
|
|||
|
using ImGuiNET;
|
|||
|
|
|||
|
namespace Ryujinx.UI
|
|||
|
{
|
|||
|
class WindowHelper : GameWindow
|
|||
|
{
|
|||
|
protected float _deltaTime;
|
|||
|
bool IsWindowOpened = false;
|
|||
|
int s_fontTexture;
|
|||
|
float _wheelPosition;
|
|||
|
|
|||
|
public WindowHelper(string title) : base(1280, 720, GraphicsMode.Default, title, GameWindowFlags.Default
|
|||
|
, DisplayDevice.Default, 3, 3, GraphicsContextFlags.ForwardCompatible)
|
|||
|
{
|
|||
|
Title = title;
|
|||
|
IsWindowOpened = true;
|
|||
|
|
|||
|
Location = new Point(
|
|||
|
(DisplayDevice.Default.Width / 2) - (Width / 2),
|
|||
|
(DisplayDevice.Default.Height / 2) - (Height / 2));
|
|||
|
}
|
|||
|
|
|||
|
public void ShowDemo()
|
|||
|
{
|
|||
|
ImGuiNative.igShowDemoWindow(ref IsWindowOpened);
|
|||
|
}
|
|||
|
|
|||
|
public void StartFrame()
|
|||
|
{
|
|||
|
IO io = ImGui.GetIO();
|
|||
|
io.DisplaySize = new System.Numerics.Vector2(Width, Height);
|
|||
|
io.DisplayFramebufferScale = new System.Numerics.Vector2(Values.CurrentWindowScale);
|
|||
|
io.DeltaTime = _deltaTime;
|
|||
|
ImGui.NewFrame();
|
|||
|
HandleInput(io);
|
|||
|
}
|
|||
|
|
|||
|
public unsafe void EndFrame()
|
|||
|
{
|
|||
|
ImGui.Render();
|
|||
|
DrawData* data = ImGui.GetDrawData();
|
|||
|
RenderImDrawData(data);
|
|||
|
}
|
|||
|
|
|||
|
protected unsafe override void OnLoad(EventArgs e)
|
|||
|
{
|
|||
|
ImGui.GetIO().FontAtlas.AddDefaultFont();
|
|||
|
|
|||
|
IO io = ImGui.GetIO();
|
|||
|
|
|||
|
io.FontAllowUserScaling = true;
|
|||
|
|
|||
|
ImGuiNative.igGetIO()->FontGlobalScale = Values.CurrentFontScale;
|
|||
|
|
|||
|
// Build texture atlas
|
|||
|
FontTextureData texData = io.FontAtlas.GetTexDataAsAlpha8();
|
|||
|
|
|||
|
// Create OpenGL texture
|
|||
|
s_fontTexture = GL.GenTexture();
|
|||
|
GL.BindTexture(TextureTarget.Texture2D, s_fontTexture);
|
|||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
|
|||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
|
|||
|
GL.TexImage2D(
|
|||
|
TextureTarget.Texture2D,
|
|||
|
0,
|
|||
|
PixelInternalFormat.Alpha,
|
|||
|
texData.Width,
|
|||
|
texData.Height,
|
|||
|
0,
|
|||
|
PixelFormat.Alpha,
|
|||
|
PixelType.UnsignedByte,
|
|||
|
new IntPtr(texData.Pixels));
|
|||
|
|
|||
|
// Store the texture identifier in the ImFontAtlas substructure.
|
|||
|
io.FontAtlas.SetTexID(s_fontTexture);
|
|||
|
|
|||
|
// Cleanup (don't clear the input data if you want to append new fonts later)
|
|||
|
//io.Fonts->ClearInputData();
|
|||
|
io.FontAtlas.ClearTexData();
|
|||
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|||
|
}
|
|||
|
|
|||
|
void HandleInput(IO io)
|
|||
|
{
|
|||
|
MouseState cursorState = Mouse.GetCursorState();
|
|||
|
MouseState mouseState = Mouse.GetState();
|
|||
|
|
|||
|
if (Focused)
|
|||
|
{
|
|||
|
Point windowPoint = PointToClient(new Point(cursorState.X, cursorState.Y));
|
|||
|
io.MousePosition = new System.Numerics.Vector2(windowPoint.X / io.DisplayFramebufferScale.X, windowPoint.Y / io.DisplayFramebufferScale.Y);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
io.MousePosition = new System.Numerics.Vector2(-1f, -1f);
|
|||
|
}
|
|||
|
|
|||
|
io.MouseDown[0] = mouseState.LeftButton == ButtonState.Pressed;
|
|||
|
io.MouseDown[1] = mouseState.RightButton == ButtonState.Pressed;
|
|||
|
io.MouseDown[2] = mouseState.MiddleButton == ButtonState.Pressed;
|
|||
|
|
|||
|
float newWheelPos = mouseState.WheelPrecise;
|
|||
|
float delta = newWheelPos - _wheelPosition;
|
|||
|
_wheelPosition = newWheelPos;
|
|||
|
io.MouseWheel = delta;
|
|||
|
}
|
|||
|
|
|||
|
private unsafe void RenderImDrawData(DrawData* draw_data)
|
|||
|
{
|
|||
|
// Rendering
|
|||
|
int display_w, display_h;
|
|||
|
display_w = Width;
|
|||
|
display_h = Height;
|
|||
|
|
|||
|
Vector4 clear_color = new Vector4(114f / 255f, 144f / 255f, 154f / 255f, 1.0f);
|
|||
|
GL.Viewport(0, 0, display_w, display_h);
|
|||
|
GL.ClearColor(clear_color.X, clear_color.Y, clear_color.Z, clear_color.W);
|
|||
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
|||
|
|
|||
|
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
|||
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
|
|||
|
int last_texture;
|
|||
|
GL.GetInteger(GetPName.TextureBinding2D, out last_texture);
|
|||
|
GL.PushAttrib(AttribMask.EnableBit | AttribMask.ColorBufferBit | AttribMask.TransformBit);
|
|||
|
GL.Enable(EnableCap.Blend);
|
|||
|
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
|||
|
GL.Disable(EnableCap.CullFace);
|
|||
|
GL.Disable(EnableCap.DepthTest);
|
|||
|
GL.Enable(EnableCap.ScissorTest);
|
|||
|
GL.EnableClientState(ArrayCap.VertexArray);
|
|||
|
GL.EnableClientState(ArrayCap.TextureCoordArray);
|
|||
|
GL.EnableClientState(ArrayCap.ColorArray);
|
|||
|
GL.Enable(EnableCap.Texture2D);
|
|||
|
|
|||
|
GL.UseProgram(0);
|
|||
|
|
|||
|
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
|
|||
|
IO io = ImGui.GetIO();
|
|||
|
ImGui.ScaleClipRects(draw_data, io.DisplayFramebufferScale);
|
|||
|
|
|||
|
// Setup orthographic projection matrix
|
|||
|
GL.MatrixMode(MatrixMode.Projection);
|
|||
|
GL.PushMatrix();
|
|||
|
GL.LoadIdentity();
|
|||
|
GL.Ortho(
|
|||
|
0.0f,
|
|||
|
io.DisplaySize.X / io.DisplayFramebufferScale.X,
|
|||
|
io.DisplaySize.Y / io.DisplayFramebufferScale.Y,
|
|||
|
0.0f,
|
|||
|
-1.0f,
|
|||
|
1.0f);
|
|||
|
GL.MatrixMode(MatrixMode.Modelview);
|
|||
|
GL.PushMatrix();
|
|||
|
GL.LoadIdentity();
|
|||
|
|
|||
|
// Render command lists
|
|||
|
|
|||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|||
|
{
|
|||
|
NativeDrawList* cmd_list = draw_data->CmdLists[n];
|
|||
|
byte* vtx_buffer = (byte*)cmd_list->VtxBuffer.Data;
|
|||
|
ushort* idx_buffer = (ushort*)cmd_list->IdxBuffer.Data;
|
|||
|
|
|||
|
GL.VertexPointer(2, VertexPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.PosOffset));
|
|||
|
GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.UVOffset));
|
|||
|
GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.ColOffset));
|
|||
|
|
|||
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
|||
|
{
|
|||
|
DrawCmd* pcmd = &(((DrawCmd*)cmd_list->CmdBuffer.Data)[cmd_i]);
|
|||
|
if (pcmd->UserCallback != IntPtr.Zero)
|
|||
|
{
|
|||
|
throw new NotImplementedException();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GL.BindTexture(TextureTarget.Texture2D, pcmd->TextureId.ToInt32());
|
|||
|
GL.Scissor(
|
|||
|
(int)pcmd->ClipRect.X,
|
|||
|
(int)(io.DisplaySize.Y - pcmd->ClipRect.W),
|
|||
|
(int)(pcmd->ClipRect.Z - pcmd->ClipRect.X),
|
|||
|
(int)(pcmd->ClipRect.W - pcmd->ClipRect.Y));
|
|||
|
GL.DrawElements(PrimitiveType.Triangles, (int)pcmd->ElemCount, DrawElementsType.UnsignedShort, new IntPtr(idx_buffer));
|
|||
|
}
|
|||
|
idx_buffer += pcmd->ElemCount;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Restore modified state
|
|||
|
GL.DisableClientState(ArrayCap.ColorArray);
|
|||
|
GL.DisableClientState(ArrayCap.TextureCoordArray);
|
|||
|
GL.DisableClientState(ArrayCap.VertexArray);
|
|||
|
GL.BindTexture(TextureTarget.Texture2D, last_texture);
|
|||
|
GL.MatrixMode(MatrixMode.Modelview);
|
|||
|
GL.PopMatrix();
|
|||
|
GL.MatrixMode(MatrixMode.Projection);
|
|||
|
GL.PopMatrix();
|
|||
|
GL.PopAttrib();
|
|||
|
|
|||
|
SwapBuffers();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|