Files
Dashboard/Dashboard.OpenTK/PAL2/Pal2Application.cs
T

233 lines
8.4 KiB
C#

using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using Dashboard.Events;
using Dashboard.OpenGL;
using Dashboard.Pal;
using Dashboard.Windowing;
using OpenTK.Platform;
using TK = OpenTK.Platform.Toolkit;
using OPENTK = OpenTK.Platform;
using DB = Dashboard.Events;
namespace Dashboard.OpenTK.PAL2
{
public class Pal2Application(ToolkitOptions? options = null) : Application
{
public override string DriverName => "Dashboard OpenTK PAL2.0 Driver";
public override string DriverVendor => "Dashboard";
public override Version DriverVersion => new Version(0, 1);
public GraphicsApiHints GraphicsApiHints { get; init; } = new OpenGLGraphicsApiHints();
private readonly List<PhysicalWindow> _windows = new List<PhysicalWindow>();
private readonly ConditionalWeakTable<WindowHandle, WindowExtraInfo> _windowHandleWindowMap =
new ConditionalWeakTable<WindowHandle, WindowExtraInfo>();
private long _tick = Stopwatch.GetTimestamp();
public override IPhysicalWindow CreatePhysicalWindow()
{
PhysicalWindow window = new PhysicalWindow(this, GraphicsApiHints);
_windows.Add(window);
_windowHandleWindowMap.Add(window.WindowHandle, new WindowExtraInfo(window));
return window;
}
public override IWindow CreateWindow()
{
return CreatePhysicalWindow();
}
protected override void InitializeInternal()
{
base.InitializeInternal();
CancellationToken?.Register(() =>
{
TK.Window.PostUserEvent(new ApplicationQuitEventArgs());
});
TK.Event.EventRaised += OnEventRaised;
TK.Init(options ?? new ToolkitOptions());
}
internal void RemoveWindow(PhysicalWindow window)
{
_windows.Remove(window);
}
public override void RunEvents(bool wait)
{
if (_windows.Count == 0)
{
Dispose();
return;
}
TK.Window.ProcessEvents(wait);
long tock = Stopwatch.GetTimestamp();
long elapsed = _tick - tock;
float delta = (float)elapsed / Stopwatch.Frequency;
TickEventArgs tickEvent = new TickEventArgs(delta);
_tick = tock;
for (int i = 0; i < _windows.Count; i++)
{
PhysicalWindow window = _windows[i];
if (window.IsDisposed)
{
_windows.RemoveAt(i);
continue;
}
window.SendEvent(this, tickEvent);
window.SendEvent(this, new PaintEventArgs(window.DeviceContext));
// For now we swap each window individually.
((GLDeviceContext)window.DeviceContext).GLContext.SwapGroup.Swap();
}
}
private void OnEventRaised(EventArgs args)
{
if (args is WindowEventArgs window)
{
OnWindowEventRaised(window.Window, window);
return;
}
else
{
// System.Diagnostics.Debugger.Break();
}
}
private void OnWindowEventRaised(WindowHandle handle, EventArgs args)
{
if (!_windowHandleWindowMap.TryGetValue(handle, out WindowExtraInfo? info))
{
Debugger?.LogDebug($"Unknown window handle {handle} received from OpenTK.");
return;
}
// TODO: fix this.
switch (args)
{
case ApplicationQuitEventArgs:
{
Quit = true;
return;
}
// Mouse Events
case MouseButtonDownEventArgs mdown:
{
MouseButtons buttons = (MouseButtons)(1 << (int)mdown.Button);
ModifierKeys modifierKeys = mdown.Modifiers.ToDashboard();
// TODO: modifier keys
MouseButtonEventArgs down2 = new MouseButtonEventArgs(info.MousePosition, buttons, modifierKeys, false);
info.Window.SendEvent(this, down2);
break;
}
case MouseButtonUpEventArgs mup:
{
MouseButtons buttons = (MouseButtons)(1 << (int)mup.Button);
ModifierKeys modifierKeys = mup.Modifiers.ToDashboard();
// TODO: modifier keys
MouseButtonEventArgs up2 = new MouseButtonEventArgs(info.MousePosition, buttons, modifierKeys, true);
info.Window.SendEvent(this, up2);
break;
}
case OPENTK.MouseMoveEventArgs mmove:
{
Vector2 position = new Vector2(mmove.ClientPosition.X, mmove.ClientPosition.Y);
DB.MouseMoveEventArgs move2 = new DB.MouseMoveEventArgs(position, position - info.MousePosition);
info.MousePosition = position;
info.Window.SendEvent(this, move2);
break;
}
case ScrollEventArgs mscroll:
{
Vector2 distance = new Vector2(mscroll.Distance.X, mscroll.Distance.Y);
Vector2 delta = new Vector2(mscroll.Delta.X, mscroll.Delta.Y);
MouseScrollEventArgs scroll2 = new MouseScrollEventArgs(distance, delta);
info.Window.SendEvent(this, scroll2);
break;
}
// Keyboard & Text Events
case KeyDownEventArgs kdown:
{
ModifierKeys modifierKeys = kdown.Modifiers.ToDashboard();
KeyCode keyCode = kdown.Key.ToDashboard();
ScanCode scanCode = kdown.Scancode.ToDashboard();
KeyboardButtonEventArgs up2 = new KeyboardButtonEventArgs(keyCode, scanCode, modifierKeys, false);
info.Window.SendEvent(this, up2);
break;
}
case KeyUpEventArgs kup:
{
ModifierKeys modifierKeys = kup.Modifiers.ToDashboard();
KeyCode keyCode = kup.Key.ToDashboard();
ScanCode scanCode = kup.Scancode.ToDashboard();
KeyboardButtonEventArgs up2 = new KeyboardButtonEventArgs(keyCode, scanCode, modifierKeys, true);
info.Window.SendEvent(this, up2);
break;
}
case OPENTK.TextInputEventArgs textInput:
{
DB.TextInputEventArgs textInput2 = new DB.TextInputEventArgs(textInput.Text);
info.Window.SendEvent(this, textInput2);
break;
}
case TextEditingEventArgs textEditing:
{
TextEditEventArgs textEditing2 = new TextEditEventArgs(textEditing.Candidate, textEditing.Cursor, textEditing.Length);
info.Window.SendEvent(this, textEditing2);
break;
}
// Window/Surface related events.
case CloseEventArgs:
{
info.Window.SendEvent(this, new WindowCloseEvent());
break;
}
case WindowFramebufferResizeEventArgs:
{
info.Window.SendEvent(this, new ResizeEventArgs());
info.Window.SendEvent(this, new PaintEventArgs(info.Window.DeviceContext));
break;
}
case WindowResizeEventArgs:
{
info.Window.SendEvent(this, new ResizeEventArgs());
info.Window.SendEvent(this, new PaintEventArgs(info.Window.DeviceContext));
break;
}
default:
Debugger?.LogDebug($"Unknown event type {args.GetType().Name} with \"{args}\".");
break;
}
}
private record WindowExtraInfo(PhysicalWindow Window)
{
public Vector2 MousePosition { get; set; } = Vector2.Zero;
}
}
internal class ApplicationQuitEventArgs() : EventArgs
{
}
}