Menus and screens

Usage guide of ui.menu, ui.theme, ui.prompts, ui.endscreen and ui.cursor: screens, settings and defaults, theme groups and presets, key prompts that follow the bindings, end conditions, recap and credits, the game cursor.

Source: module-kits:kits/ui_menu/usage/en.mdView Markdown source

Also read offline — CLI: grip-forge docs ui-screensMCP tool: gripforge_docs { "topic": "ui-screens" }

Menus, theme, prompts and end screen (ui.* kits) #

The screens around your game: title and pause menus, options, the interface theme, key prompts, the end screen with credits and the game cursor. Readable offline: gripforge docs ui-screens, or the MCP tool gripforge_docs (topic ui-screens). To draw your own interface as a web page, see gripforge docs ui-webui.

What it is for #

Each kit builds one model that every engine draws (the web and native players, Godot, Unity, Unreal), so the same buttons, texts, tabs and behaviour come out everywhere.

KitRoleIn a new game
ui.menutitle screen, pause menu, Options, Load / Save screen, loading lineyes (with input.remap, settings.graphics, save.persistence)
ui.themeone interface theme per game, as datayes, with every value unset
ui.promptskey hints drawn from the live bindingsyes, with the help bar off
ui.endscreenvictory, defeat and game over screen, recap, creditsyes (needs ui.menu)
ui.cursora game cursor and the marker where an order is givenno
gripforge_gamekit_configure { project_id: "gkp_…", id: "ui.menu",
                              config: { "title": "My game", "titleButtons": ["play", "continue", "options", "quit"] } }
gripforge_gamekit_configure { project_id: "gkp_…", id: "ui.theme", config: { "preset": "fantasy-medieval" } }
gripforge_gamekit_remove    { project_id: "gkp_…", id: "ui.menu" }     # the game then starts straight into play

Remove a default kit only when you mean to. The full reference of each is gripforge kit api <id>.

ui.menu #

  • Title (titleScreen, on): the game waits, paused. Buttons Play, Continue (only when save.persistence holds a save, the most recent one is loaded), Load, Options, Quit. With game.engine's sceneFlow.menu: "scene" (every new game) the title is a scene of its own; see gripforge docs scenes.
  • Pause (pauseKey Escape, or the gamepad Start button pausePad): Resume, Save, Load, Options, Restart, Quit to title.
  • Load / Save: one row per slot with picture, date, play time, location and version; overwriting and deleting ask first.
  • Options: tabs general (language), controls (input.remap), graphics (settings.graphics), then tabs other kits register. A tab whose kit is absent is hidden.
KeyDefaultMeaning
title, subtitleproject name, ""texts of the title screen
logo, background""image paths (a web URL, res:// on Godot, a Resources path on Unity, an asset path on Unreal)
titleModeartworkweb: artwork, scene (the paused game behind), character (the bound model and its idle animation)
characterSlotplayer_charactermodel used by the character mode
titleLayout, titleText, playLabel, titleHelp, pageBarside, "", "", [], truelayout and texts of the title
themeaccent #ff6b2c, panel #161a22, text #f4f1ea, background #0d1016, scale 1colours and size
languageautoauto, en, fr; the player can change it (kept in the player settings, outside saves)
titleButtonsplay, continue, load, options, quitbuttons and order
pauseButtonsresume, save, load, options, restart, quit_to_titlebuttons and order (quit can be added)
tabsgeneral, controls, graphicsOptions tabs; add saves to manage saves from Options
pauseKey, pausePadEscape, 9pause controls (not moddable)
pauseGametruepause while a menu is open (not moddable)
loadingLinetitlewhere the loading progress of asset.preload shows: title, menus, off
waitFirstReadyfalsePlay stays disabled until the start scene is loaded (Continue and Load stay usable)
keyHintsfalsekey hints under the buttons

Loading line: while asset.preload loads, the title shows one line with a bar (Loading 42% - 12.3 / 29.0 MB - 14/30 files - from the cache), and nothing once it is done.

Add an Options tab: expose on your kit's service optionsTab() ({ id, order, label }), optionFields(lang) (fields of kind choice, toggle, slider, binding, button, actions) and setOption(id, value), then call ui.menu.registerTab("<your capability>").

Service: view(lang?), open(screen), back(), navigate(delta), focus(id), activate(id?), pause(), resume(), togglePause(), perform(action), press(control), tabs(), selectTab(id), nextTab(delta), fields(tab?), setOption(tab, id, value), registerTab(capability), canContinue(), setLanguage(lang), text(key), loading(lang?). Events: menu.screen, menu.action { action, slot } (play, continue, load, save, options, resume, restart, quit_to_title, quit), menu.tab, menu.language. The menu declares no hook: the player decides, and the kit that carries an action out owns the decision (a save goes through save.write of save.persistence). A mod can change texts, theme, staging, buttons and tabs, not images, the character slot, pause controls or pauseGame.

ui.theme #

Every default is unset, and unset means each kit keeps its built-in look: a game that does not configure the theme looks as before.

GroupKeysValues
colorsaccent, accentText, panel, text, muted, background, danger, success, focus#rrggbb or #rrggbbaa
typographyfont, fontFile, scale, size, titleSize, weight, letterCasefamily, font file, scale 0.5 to 2, body 10 to 32, title 20 to 96, regular/medium/bold, none/upper
shapesradius, borderWidth, buttonShape, padding0 to 32, 0 to 8, square/rounded/pill, 0 to 64
glyphsstyle, setoutlined/filled/text; letters/shapes/positions for the gamepad face buttons
imageslogo, backgroundsame path rules as fontFile

preset picks a complete look in one value; any explicit value of the config wins over it. Presets: scifi-lowpoly, military, fantasy-medieval, cyberpunk-neon, cartoon-bright, horror-dark, minimal-clean, retro-pixel. A preset never sets a file (fontFile, images).

{ "preset": "scifi-lowpoly", "colors": { "accent": "#f2c14e" } }

Run time: presets(), preset(), applyPreset(id), apply(...), reset(); ui.theme.changed { revision, theme } makes interfaces redraw. Fonts: the web page loads the first family of the stack from a bundled open-licence file; Godot and Unity try the families in order; Unreal uses its own font unless fontFile is set. A mod can change colors, shapes and glyphs.

ui.prompts #

Key hints such as [E] Open door, or [A] Continue with a gamepad. No key is written in the kit: every label comes from input.actions (labelFor, promptFor), so it follows the player's remapping and the device used last. No key is shown on screen by default: the help bar (bar) and the context row (context) are off, and the controls live in Options, Controls. Turn one on for a tutorial or a game that lives on contextual prompts; a tutorial step pushes a prompt with show().

Keys: bar (false), context (false), barActions ([], the automatic bar), exclude, maxItems (6), interaction (true), contexts, position (bottom), device (auto), language (auto), hideInMenus (true); all moddable. Event prompts.changed.

ui.endscreen #

Opens once, pausing the game (pauseGame), when:

  • a kit, script or code calls show(result, stats?) with victory, defeat or end;
  • an event of victoryEvents (game.won) or defeatEvents (game.lost) is emitted (patterns * and family.* work);
  • a mission listed in missions completes (victory) or fails (defeat), * for any;
  • the player dies (onDeath), or the game enters the finished phase (onFinished, on).
KeyDefaultMeaning
templateclassicscreen layout
victoryEvents, defeatEvents["game.won"], ["game.lost"]events that end the game
missions[]missions that end the game
onFinished, onDeathtrue, false
showTimetrueplay time in the recap
statsscore, money, room{ id, var, label, format } lines read from variables (int, number, time, money, percent, text)
buttonsretry, menu, creditsorder; quit can be added. retry and menu go through ui.menu.perform
victoryTitle, defeatTitle, victoryText, defeatTextbuilt-in{ en, fr } texts
creditsTitle, credits, creditsSpeed, poweredByproject name, [], 1.5, truecredits is [{ title, names }], scrolled in order
loadingLinenextprogress of the next scenes' preload by the buttons: next, all, off

A kit adds recap lines by exposing endStats(lang) on its service and calling ui.endscreen.registerStats("<capability>"); a kit may set the variables endscreen.title and endscreen.text to replace the heading (game.endings does). Hook endscreen.show { result, trigger, mission, time }: mutable result (a defeat that is the true ending), cancellable (the screen stays closed and show() answers false). The credits are the authors' and not moddable.

ui.cursor #

Replaces the system pointer with a game cursor and marks the ground where the player gives an order. Any kit that turns a click into an order emits pointer.command { point, kind: "move" | "attack", target? }; this kit answers with the event fx.ground_marker (green arrows closing on the point for a move, red for an attack) and the host draws it.

KeyDefaultMeaning
cursorgauntletgauntlet, arrow, crosshair, system
cursorColor, cursorSize#d8dde6, 32
markerarrowsarrows, ring, none
moveColor, attackColor#3ee06a, #ff4d4dthe cursor turns attackColor over an enemy
markerSeconds, markerSize0.55, 1.8life in seconds, radius in metres

When it does not do what you expect #

SymptomCause and fix
The game starts without a titleui.menu was removed, or titleScreen: false
Continue is missingsave.persistence holds no save
A key hint is missingui.prompts bar and context are off on purpose: turn one on for a tutorial
The end screen never opensno victoryEvents, defeatEvents, mission or show() call reaches it, or a tap of endscreen.show cancelled it
The theme looks unchangedthe value is unset in ui.theme (each kit keeps its look) or the ui.menu theme is used instead