using System;
using AcDream.UI.Abstractions.Input;
using Silk.NET.Input;
namespace AcDream.App.Input;
///
/// Bridges a Silk.NET + the active ImGui IO
/// (for / )
/// to the test-fakeable used by
/// .
///
///
/// We don't link Hexa.NET.ImGui or ImGuiNET directly here — the
/// constructor takes two delegates so the App.Rendering layer can
/// proxy ImGui.GetIO().WantCaptureMouse via whichever ImGui
/// package is currently active without leaking the type onto the
/// abstraction interface.
///
///
public sealed class SilkMouseSource : IMouseSource
{
private readonly IMouse _mouse;
private readonly Func _wantCaptureMouse;
private readonly Func _wantCaptureKeyboard;
private float _lastX;
private float _lastY;
private bool _haveLastPos;
public event Action? MouseDown;
public event Action? MouseUp;
public event Action? MouseMove;
public event Action? Scroll;
/// Caller-supplied probe for the current modifier mask. Reused
/// from the keyboard source so mouse events carry consistent modifier
/// state.
public Func ModifierProbe { get; set; } = () => ModifierMask.None;
public SilkMouseSource(
IMouse mouse,
Func wantCaptureMouse,
Func wantCaptureKeyboard)
{
_mouse = mouse ?? throw new ArgumentNullException(nameof(mouse));
_wantCaptureMouse = wantCaptureMouse ?? throw new ArgumentNullException(nameof(wantCaptureMouse));
_wantCaptureKeyboard = wantCaptureKeyboard ?? throw new ArgumentNullException(nameof(wantCaptureKeyboard));
_mouse.MouseDown += (_, btn) => MouseDown?.Invoke(btn, ModifierProbe());
_mouse.MouseUp += (_, btn) => MouseUp?.Invoke(btn, ModifierProbe());
_mouse.MouseMove += (_, pos) =>
{
float dx, dy;
if (_haveLastPos)
{
dx = pos.X - _lastX;
dy = pos.Y - _lastY;
}
else
{
dx = 0f;
dy = 0f;
_haveLastPos = true;
}
_lastX = pos.X;
_lastY = pos.Y;
MouseMove?.Invoke(dx, dy);
};
_mouse.Scroll += (_, scroll) => Scroll?.Invoke(scroll.Y);
}
public bool IsHeld(MouseButton button) => _mouse.IsButtonPressed(button);
public bool WantCaptureMouse => _wantCaptureMouse();
public bool WantCaptureKeyboard => _wantCaptureKeyboard();
}