Files
2026-07-13 13:15:05 +08:00

167 lines
5.0 KiB
C#

using System.Numerics;
using SilkWindows;
using Silk.NET.Core.Native;
using Silk.NET.Input;
using Silk.NET.Maths;
using Silk.NET.Windowing;
namespace SilkWindows;
public sealed class WindowHelper
{
public static void RunWindow(IWindowImplementation window, IImguiDrawer drawer, FontPack? fontPack,
object imguiContextLockObj)
{
var windowHelper = new WindowHelper(window, drawer, fontPack, imguiContextLockObj);
windowHelper.RunUntilClosed();
}
private WindowHelper(IWindowImplementation window, IImguiDrawer drawer, FontPack? fontPack, object? graphicsContextLockObj)
{
_windowImpl = window;
_drawer = drawer;
_fontPack = fontPack;
_graphicsContextLock = graphicsContextLockObj ?? new object();
}
public void RunUntilClosed()
{
var window = Window.Create(_windowImpl.WindowOptions);
_window = window;
SubscribeToWindow();
_window.Run();
UnsubscribeFromWindow();
Dispose();
return;
void Dispose()
{
_windowImpl.Dispose();
_graphicsContext?.Dispose();
_inputContext?.Dispose();
_window.Dispose();
_graphicsContext = null;
_inputContext = null;
}
void SubscribeToWindow()
{
_window.Load += OnLoad;
_window.Render += RenderWindowContents;
_window.FramebufferResize += OnWindowResize;
_window.Update += OnWindowUpdate;
_window.FocusChanged += OnFocusChanged;
_window.Closing += OnClose;
_window.FileDrop += OnFileDrop;
}
void UnsubscribeFromWindow()
{
_window.Load -= OnLoad;
_window.Render -= RenderWindowContents;
_window.FramebufferResize -= OnWindowResize;
_window.Update -= OnWindowUpdate;
_window.FocusChanged -= OnFocusChanged;
_window.Closing -= OnClose;
_window.FileDrop -= OnFileDrop;
}
}
private void OnFileDrop(string[] filePaths)
{
_imguiHandler?.OnFileDrop(filePaths);
}
private void OnFocusChanged(bool isFocused)
{
if (!isFocused && _windowImpl.WindowOptions.TopMost)
{
// todo: force re-focus once silk.NET supports that ? wayland may not allow it anyway..
}
_imguiHandler?.OnWindowFocusChanged(isFocused);
}
private void RenderWindowContents(double deltaTime)
{
#if WH_DEBUG_FLOW
Console.WriteLine("Starting render");
#endif
DebugMouse("RenderWindowContents");
lock (_graphicsContextLock)
{
var windowSize = _window.Size;
var clearColor = _imguiHandler?.ClearColor ?? _windowImpl.DefaultClearColor;
if (_windowImpl.Render(clearColor, deltaTime))
{
_imguiHandler?.Draw(new Vector2(windowSize.X, windowSize.Y), deltaTime);
_windowImpl.EndRender();
}
}
}
private void DebugMouse(string callsite)
{
// var mice = _inputContext!.Mice;
// int mCounter = 0;
// int wCounter = 0;
// foreach(var mouse in mice)
// {
// mCounter++;
// foreach (var wheel in mouse.ScrollWheels)
// {
// wCounter++;
// Console.WriteLine($"scroll in mouse {mouse.Name} ({mCounter}, {wCounter}) at {callsite}:" + wheel.Y);
// }
//
// wCounter = 0;
// }
}
private void OnLoad()
{
_graphicsContext = _windowImpl.InitializeGraphicsAndInputContexts(_window, out _inputContext);
if (_drawer == null)
return;
_imguiHandler = new ImGuiHandler(_windowImpl.GetImguiImplementation(), _drawer, _fontPack, _graphicsContextLock);
}
private void OnClose()
{
_imguiHandler?.Dispose();
}
private void OnWindowUpdate(double deltaSeconds)
{
DebugMouse("OnWindowUpdate");
if (_imguiHandler == null) return;
_imguiHandler.OnWindowUpdate(deltaSeconds, out var shouldCloseWindow);
if (shouldCloseWindow)
{
_window.Close();
}
}
private void OnWindowResize(Vector2D<int> size)
{
_windowImpl.OnWindowResize(size);
}
private readonly object _graphicsContextLock;
private readonly IWindowImplementation _windowImpl;
private IWindow _window = null!;
private IInputContext? _inputContext;
private NativeAPI? _graphicsContext;
private readonly FontPack? _fontPack;
private readonly IImguiDrawer? _drawer;
private ImGuiHandler? _imguiHandler;
}