Repository navigation
Widgets Overview
Widgets are Gondwana’s system for interactive, reusable interface elements built on top of DirectDrawing.
They are intended for interface elements rendered inside the game itself rather than platform-native UI. This includes things like:
- buttons, check boxes, radio buttons, and text boxes
- labels, lists, combo boxes, and progress indicators
- panels and layout containers
- dialogs and conversation boxes
- menus
- health bars and name tags
- splash screens, notifications, popups, and other overlays
Widgets use the same Gondwana rendering pipeline as the rest of the game and can participate in either screen-space or world-space rendering.
Desktop video has an optional companion package:
Gondwana.Video.Widgets.
VideoWidget wraps the DirectVideo primitive with normal Widget input, focus,
opacity/fades, lifecycle and composite movement. Set IsDragEnabled = true to opt
into inherited dragging; its default is false. Pointer/keyboard events belong to
game-specific behavior, with no default play/pause command. Show()/Hide() do
not change playback. Both View and SceneLayer targets and URI/stream/GAF sources
are supported. Neither Widgets nor Video depends on the other; the bridge references
both and retains Video's native desktop LibVLC requirements.
A widget uses DirectDrawing for its visual representation, but adds the lifecycle, composition, focus, and input behavior expected from a user-interface element.
Depending on how it is associated, a widget can appear as:
- a SceneLayer-bound world-space element
- a View-bound screen-space interface element
That means the same widget system can support both in-world interaction and traditional HUD, menu, dialog, and overlay interfaces.
As a general rule:
- Use a View when the widget should remain screen-relative, such as menus, HUD text, settings panels, dialogs, and most conventional UI.
- Use a SceneLayer when the widget should exist in world coordinates and move through the scene with that layer.
-
HealthBarWidgetandNameTagWidgetare world-space widgets designed to follow aSprite. -
ToastWidgetandSplashScreenare view-level overlays.
All widgets ultimately derive from WidgetBase, which provides the common widget lifecycle and interaction model.
This includes:
- showing and hiding
- activation and cancellation
- focus participation
- pointer hit testing
- pointer enter and leave events
- pointer down, up, and click events
- keyboard input
- optional drag behavior
Specialized widget base classes add behavior where it is useful.
For example, container widgets add ownership and lifecycle propagation for child widgets, while draggable widgets build on the shared pointer pipeline rather than implementing platform-specific mouse or touch handling.
Application code normally works with the concrete widget classes rather than deriving directly from WidgetBase.
Interactive widget input is coordinated by WidgetInputRouter.
It:
- tracks widgets associated with a render surface
- determines which widget is under the pointer
- routes mouse or touch input to that widget
- manages pointer capture during clicks and drags
- manages keyboard focus
- routes keyboard input to the focused widget, then offers unhandled keys to eligible menu bars and tab controls
- provides a platform-agnostic input path
The platform hosts translate native input into Gondwana input events. Widgets themselves do not need to know whether they are running under WinForms, Avalonia, or Blazor.
The normal GameHostBase initialization path creates and starts the widget input router automatically, so most Gondwana games do not need to create one manually.
If you are implementing a custom host, you can create the router using whatever input pollers that host provides:
using Gondwana.Widgets;
using var widgetInputRouter = new WidgetInputRouter(
host,
keyboardEventPoller,
mouseEventPoller,
touchEventPoller);
widgetInputRouter.Start();An input poller can be null when that input source is not available.
Subscribe to WidgetInputRouter.UnhandledPrimaryAction when a game needs
the same board/sprite selection behavior for a left mouse press and a
single-finger tap. This event only fires inside a view when no widget has
claimed the input. Widget hit testing and the original touch ownership are
handled centrally: a widget that hides on touch-down does not leak that tap
into the game. A mouse action fires on press; a touch action fires only after
a completed recognized tap. Drags, cancellations, swipes, and multi-touch do
not count.
private WidgetInputRouter? _gameInput;
protected override void OnSceneGraphCreated()
{
_gameInput = WidgetInputRouter;
if (_gameInput is not null)
_gameInput.UnhandledPrimaryAction += OnPrimaryAction;
}
protected override void OnTouchAdapterInitialized()
{
// GameHostBase starts mouse monitoring automatically, but touch monitoring
// must be started explicitly for touch taps to reach UnhandledPrimaryAction.
Engine.Input.TouchEventPoller?.StartMonitoringTouch();
}
private void OnPrimaryAction(PrimaryPointerActionEventArgs e)
{
// e.View, e.ScreenPositionPx, e.IsTouch, e.PointerId
var grid = e.View.ScreenPxToGrid(mySceneLayer, e.ScreenPositionPx);
SelectGameCell(grid); // Game-specific behavior
}
protected override void UnhookEvents()
{
if (_gameInput is not null)
_gameInput.UnhandledPrimaryAction -= OnPrimaryAction;
_gameInput = null;
}Keep the router reference for cleanup: GameHostBase.Dispose() disposes
its router before calling UnhookEvents(). Note that GameHostBase.InitializeWidgetInput
starts mouse monitoring only; hosts targeting touch devices must also override
OnTouchAdapterInitialized() and call StartMonitoringTouch() on TouchEventPoller
so that touch events are polled. The event does not
automatically select sprites; games use the logical position and reported
view to hit-test tiles, sprites, or objects. Game-specific rules such as
turn ownership or modal state remain the game's responsibility. WinForms
only receives mouse input unless an additional touch adapter is supplied.
DirectDrawing can render almost any custom visual, but rendering alone does not provide the lifecycle and input behavior expected from a user-interface control.
Widgets provide that higher-level structure while remaining:
- engine-native
- code-first
- platform-agnostic
- compatible with Gondwana's existing View and SceneLayer rendering models
A useful mental model is:
Direct drawings are engine-managed custom visuals. Widgets are interactive or reusable direct-drawing components with a shared lifecycle and input model.
Not every widget is interactive. Display-oriented widgets such as labels, progress bars, health bars, name tags, and popups still benefit from the same composition and lifecycle model without needing direct user input.
The following pages cover the current widgets available in Gondwana.Widgets.
Callback-based menu bars with stable item keys, check/radio commands, recursive submenus, icons, typed keyboard shortcuts, and explicit mnemonics. Closed menus receive unhandled accelerators after the focused widget has its opportunity to handle input.
A clickable text button for commands and actions. Supports pointer activation as well as keyboard activation with Enter or Space.
A two-state control for independent Boolean options such as enabling music, showing diagnostics, or toggling gameplay settings.
A compact single-selection control that expands into a ListBoxWidget. Useful for difficulty, resolution, character class, or other enumerated choices.
Interactive text that opens an external absolute URI through a platform-provided IExternalUriLauncher.
A retained-mode, non-interactive text widget for captions, headings, status displays, instructions, and other interface text.
A vertically scrolling list of strings with pointer and keyboard selection.
A rectangular container used to group other widgets. Supports solid or image backgrounds, borders, rounded corners, and child-widget positioning.
A generic horizontal or vertical progress indicator representing a normalized value from 0.0 through 1.0.
A single-choice control that can participate in a RadioButtonGroup so selecting one option automatically clears the others.
A single-line editable text control with caret movement, insertion, deletion, placeholder text, length limits, and submit behavior.
A tabbed container whose pages own ordinary widgets. Headers resize across configurable rows, pages can use Alt mnemonics, and optional pointer dragging can reorder tabs.
A lightweight layout container that arranges child widgets sequentially in a horizontal or vertical stack with configurable spacing.
A ready-to-use application information dialog with application name, version, optional description, copyright, logo, and external hyperlink.
The base class for custom Gondwana dialogs. Provides a panel, title bar, optional close button, dragging, keyboard accept/cancel behavior, and DialogResult semantics.
An NPC-style dialogue panel with speaker name, wrapped body text, continue indicator, and pointer or keyboard advance behavior.
A world-space health bar that automatically follows a Sprite and displays current health relative to a configurable maximum.
A world-space text label that automatically follows a Sprite, suitable for NPC names, player names, unit labels, or similar identifiers.
A view-level, scrollable runtime diagnostics HUD backed by Engine.Instance.Profiler.
It owns telemetry collection only while shown, can include or suppress individual
measurements and sources, can opt into Scene/View/backbuffer/configuration/MSAA
context, supports application-defined extension lines, hover definitions, and a
built-in Metrics selector for toggling individual diagnostics at runtime. The
saved-scene Scene Viewer dogfoods this widget for its F3 diagnostics overlay.
Short-lived text or image content that can move, accelerate, fade, and originate from view coordinates, world coordinates, a tile, or a grid cell.
Typical uses include damage numbers, healing values, XP gains, item pickups, and status effects.
A full-view splash image that fades in, holds for a minimum duration, optionally performs startup work, and then fades out.
A lightweight, non-interactive view overlay for contextual hover help. It positions near the pointer, clamps to the owning View, and does not intercept underlying input.
A temporary view-level notification that can slide or fade into place, remain visible for a configured duration, and dismiss automatically or on user input.
Interactive widgets such as buttons, check boxes, radio buttons, list boxes, combo boxes, text boxes, tab controls, conversation boxes, dialogs, hyperlinks, and dismissible toasts participate in normal widget focus, pointer, and keyboard routing.
Display and layout widgets such as:
LabelWidgetPanelWidgetProgressBarWidgetHealthBarWidgetNameTagWidgetProfilerWidgetTooltipWidgetPopupWidgetStackPanelWidget
do not normally require direct input.
Add the Widgets package to your game project:
dotnet add package Gondwana.WidgetsThen import the widget namespace or the namespace containing the widget family you are using:
using Gondwana.Widgets;
using Gondwana.Widgets.Controls;
using Gondwana.Widgets.Dialogs;
using Gondwana.Widgets.Dialogue;
using Gondwana.Widgets.Hud;
using Gondwana.Widgets.Layout;
using Gondwana.Widgets.Overlays;Start with the individual widget pages above for normal game development.
For lower-level details about the shared widget system, see:
Gondwana.Widgets/WidgetBase.csGondwana.Widgets/ContainerWidget.csGondwana.Widgets/WidgetInputRouter.csGondwana.Widgets/*
For the underlying rendering model, see the DirectDrawing documentation.
World-space widget children repeat with their SceneLayer; View-bound UI never wraps. Following widgets share their target's translations. Hit testing returns the canonical widget, while pointer capture retains the chosen image in WrappedOffsetWorldPx. See SceneLayer Wrapping for dragging and custom-control coordinate handling.
- Home
- Make Your First Game in 30 Minutes
- Engine Architecture Overview
- Game Hosts and Application Startup
- Gondwana Engine Lifecycle
- Gondwana CLI Cheatsheet
- Using Gondwana with ChatGPT and Codex
Core Concepts
Systems
Rendering
Widgets
-
Controls
-
Dialogs
- AboutBox
- ConversationBox
- DialogBox — base class for custom dialogs
-
Hud
-
Layout
-
Menus
-
Overlays