Skip to content

Mouse Input Quick Start

Isthimius edited this page Jul 31, 2026 · 1 revision

A compact, code-first reference for mouse clicks, movement, dragging, and wheel input in Gondwana.


Contents


The Basic Pattern

Mouse input uses one consolidated event:

Initialize adapter
    ↓
Subscribe to MouseEvent
    ↓
Start monitoring
    ↓
Inspect position, buttons, wheel, and modifiers

In a Gondwana game host:

protected override void OnMouseAdapterInitialized()
{
    var mouse = Engine.Input.MouseEventPoller;
    if (mouse is null)
        return;

    mouse.MouseEvent += OnMouseEvent;

    mouse.StartMonitoringMouse(
        trackMouseMovement: true);
}

Show a Left Mouse Click

using Gondwana.Input.Mouse;
private void OnMouseEvent(MouseEventArgs e)
{
    if (e.LeftButtonJustPressed)
    {
        Console.WriteLine(
            $"Left mouse pressed at {e.CurrentPosition}.");
    }
}

LeftButtonJustPressed is true only when the button transitions from up to down.

To act when the button is released:

if (e.LeftButtonJustReleased)
{
    Console.WriteLine(
        $"Left mouse released at {e.CurrentPosition}.");
}

Show a Right Mouse Click

private void OnMouseEvent(MouseEventArgs e)
{
    if (e.RightButtonJustPressed)
    {
        OpenContextMenu(
            e.CurrentPosition);
    }
}

Middle-button helpers are available too:

e.MiddleButtonDown
e.MiddleButtonJustPressed
e.MiddleButtonJustReleased

Or use the generic form:

if (e.IsButtonJustPressed(MouseButton.Middle))
{
}

Track Pointer Movement

private void OnMouseEvent(MouseEventArgs e)
{
    if (e.CurrentPosition == e.PreviousPosition)
        return;

    int dx =
        e.CurrentPosition.X -
        e.PreviousPosition.X;

    int dy =
        e.CurrentPosition.Y -
        e.PreviousPosition.Y;

    Console.WriteLine(
        $"Mouse moved by ({dx}, {dy}).");
}

Make sure movement tracking is enabled:

mouse.StartMonitoringMouse(
    trackMouseMovement: true);

Implement a Drag

private Point? _dragStart;
private void OnMouseEvent(MouseEventArgs e)
{
    if (e.LeftButtonJustPressed)
    {
        _dragStart = e.CurrentPosition;
        return;
    }

    if (e.LeftButtonDown &&
        _dragStart is { } start)
    {
        var delta = new Point(
            e.CurrentPosition.X - start.X,
            e.CurrentPosition.Y - start.Y);

        DragSelection(
            start,
            e.CurrentPosition,
            delta);

        return;
    }

    if (e.LeftButtonJustReleased)
    {
        _dragStart = null;
    }
}

For Gondwana widgets, prefer the widget input router and widget drag events. Use raw mouse dragging for world interaction, camera controls, editors, and custom tools.


Read the Scroll Wheel

private void OnMouseEvent(MouseEventArgs e)
{
    if (e.ScrollDelta > 0)
    {
        ZoomIn();
    }
    else if (e.ScrollDelta < 0)
    {
        ZoomOut();
    }
}

The magnitude is adapter-defined. On WinForms it commonly arrives in wheel-detent-sized increments.

For smooth zoom, convert the delta into a target and let the view animate:

if (e.ScrollDelta != 0)
{
    var view =
        RenderSurface.Host.ViewManager.Views[0];

    var layer = Scene![0];

    float targetZoom = Math.Clamp(
        view.Viewport.Zoom +
        e.ScrollDelta * 0.001f,
        view.MinZoom,
        view.MaxZoom);

    view.ZoomAroundScreenPoint(
        layer,
        e.CurrentPosition,
        targetZoom,
        0.25f);
}

Convert the Pointer to World Coordinates

The mouse reports render-surface coordinates. Convert through the intended View.

private void OnMouseEvent(MouseEventArgs e)
{
    var view =
        RenderSurface.Host.ViewManager.Views[0];

    var layer = Scene![0];

    PointF worldPx =
        view.ScreenPxToWorldPx(
            layer,
            e.CurrentPosition);

    Console.WriteLine(
        $"World pixel: {worldPx}");
}

Convert directly to the layer's grid:

PointF grid =
    view.ScreenPxToGrid(
        layer,
        e.CurrentPosition);

Select a tile:

var tile = layer[grid];

if (tile is not null &&
    e.LeftButtonJustPressed)
{
    SelectTile(tile);
}

Use Modifier Keys

Mouse events include keyboard modifiers:

e.IsShift
e.IsCtrl
e.IsAlt

Example:

if (e.LeftButtonJustPressed)
{
    if (e.IsCtrl)
        AddToSelection(e.CurrentPosition);
    else
        ReplaceSelection(e.CurrentPosition);
}

Control Event Frequency

Use the engine default:

mouse.StartMonitoringMouse(
    trackMouseMovement: true,
    timeBetweenEvents: -1);

No added throttle:

mouse.StartMonitoringMouse(
    trackMouseMovement: true,
    timeBetweenEvents: 0);

Disable free movement events:

mouse.StartMonitoringMouse(
    trackMouseMovement: false);

Pause:

mouse.Configuration!.IsPaused = true;

Resume:

mouse.Configuration!.IsPaused = false;

Stop monitoring:

mouse.StopMonitoringMouse();

Cleanup

protected override void UnhookEvents()
{
    if (Engine.Input.MouseEventPoller is { } mouse)
        mouse.MouseEvent -= OnMouseEvent;
}

Cheat Sheet

Left press

if (e.LeftButtonJustPressed)
{
}

Left held

if (e.LeftButtonDown)
{
}

Left release

if (e.LeftButtonJustReleased)
{
}

Pointer position

Point p = e.CurrentPosition;

Movement delta

int dx =
    e.CurrentPosition.X -
    e.PreviousPosition.X;

Wheel

if (e.ScrollDelta != 0)
{
}

Screen to world

PointF world =
    view.ScreenPxToWorldPx(
        layer,
        e.CurrentPosition);

Common Problems

Clicks work, but hover does not

Enable pointer movement tracking:

mouse.StartMonitoringMouse(
    trackMouseMovement: true);

The event fires repeatedly during a drag

That is expected while a button remains held. Use:

JustPressed
JustReleased

for edge-only behavior.

The pointer selects the wrong world location

Use the correct View and SceneLayer when converting screen coordinates.

Input feels delayed

Reduce timeBetweenEvents. A value of 0 removes interval throttling, but it also increases event frequency.

A UI control must be changed

Mouse handlers normally run in the engine cycle. Dispatch platform UI changes:

Engine.UiDispatcher?.Post(() =>
{
    label.Text = "Clicked";
});

Further Reading

Clone this wiki locally