Skip to content

UI framework update and Quit from Main Menu - #211

Merged
Adubbz merged 5 commits into
TheMoonPeople:masterfrom
SirFancyBacon:exit-main-menu
Oct 24, 2026
Merged

Adubbz merged 5 commits into
TheMoonPeople:masterfrom
SirFancyBacon:exit-main-menu

Conversation

@SirFancyBacon

@SirFancyBacon SirFancyBacon commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • The title screen's menu gets an Exit row, which asks before closing the game. Retail's three rows are painted pictures with no Exit among them, so all four rows are now drawn from a font through the UI framework, in every language.
  • Quit in the pause menu, in a town or a dungeon, now asks "Return to the title?" and goes back to the title screen instead of the desktop. Its label stays "Quit".
  • A new font, Chronicle Title Bold: the title's painted capitals fitted into a font, with the letters and accents the painting lacks built by its rules.
  • The UI framework gains what these needed, and the battle menu's text moves out of it.
  • docs/UI_FRAMEWORK.md replaces docs/port/ui_framework.md: what the framework is today, and a proposal for where it goes next.

Closes #203

Title menu

  • START, CONTINUE, OPTION and EXIT are drawn in Chronicle Title Bold (port/src/title/title_menu.cpp). The words for Start, Continue and Option are retail's own in each language, read from its pictures (title.menu.* keys).
  • The rows stand 28 pixels apart from y 284, so the fourth clears the trademark lines. Retail's hand, blink and sounds are kept.
  • Their colour is worked out from what the GS did with the painting, not by eye. The painted letters are cream at texel alpha 0xFF, twice the GS's opaque 0x80, so the selected row (drawn at 128) shows that cream, as a real GPU measures it, and the others (drawn at 32) are half opaque. The font's rows do the same, see-through, in a soft dark halo, set by their letters' outlines so the spacing is the same at any window size.
  • Exit opens the game's yes/no box ("Return to desktop?"). The pad and the mouse both work on it.
  • Exit's row shares its number with the attract movie's, which retail only sets on the way out, so TitleLoop's handling of the other rows is retail's.

Quit

  • On Yes, the main loop leaves the town or dungeon the way the developer menu does (TakeBattleMenuTitleRequest, port/src/gameloop.cpp): it waits for loads in flight, stops the sound and jumps to map 800, so the title starts as it does at start-up. Nothing is saved on the way.
  • The help line and the box say so in every language: "Return to the title screen." and "Return to the title? Unsaved progress is lost."

Chronicle Title Bold

  • Retail's menu rows are lettered in a bold geometric sans that exists only as those 16-pixel pictures. As Chronicle Sharp's letters were reshaped until they match the game's, Chronicle Title's capitals are the painting's own:
    • Each painted capital (A C E I M N O P R S T U W Z, the brackets, and the acute over Spanish OPCIÓN) is an outline of TrueType curves, fitted until, drawn at the painting's size, it covers each texel as the painted letter does, kept smooth where the painting's pixels step. This keeps the painting's rounded edges and its letters' weights, such as the S's heavy spine.
    • The capitals the painting lacks are built from its strokes by its rules: stems are its I, horizontal strokes its E's arms, bowls its P's, diagonals as thick as its A's legs with their ends rounded as its feet are, and the valleys where diagonals meet left sharp.
    • Every accent is drawn from the painted acute (the grave its mirror, the circumflex and caron the two together, the dots, ring, tilde and others in its stroke), and every accented capital, with Æ, Œ, Ø, Ð, Ł and Þ, is built from these.
  • Spacing follows the usual method for capitals (Walter Tracy's): each side of a letter gets a share of a straight stem's space by its shape, with the painting's S and T kept as far apart as it has them. The painting's T and A, where the A tucks under the T, is made a rule, which gives the familiar pairs (AT, AV, LT, TA, VA, YA, ...). The renderer sets letters by their ink, so all of this is GPOS class kerning; accented capitals kern as their letter.
  • The lower case, digits and punctuation are Albert Sans at weight 650 (SIL Open Font License 1.1, no reserved font name), which the title doesn't draw. Chronicle Title is renamed and keeps the licence in its own fields. tools/font/README.md has its provenance.
  • Regular is kept for the thinner lettering of PUSH START BUTTON, for later.

UI framework

  • Title font: FontWeight::Title and a fourth caption font slot, embedded in the executable as the status font is.
  • New text options, all off by default, so no existing text changes:
    • see_through: alpha makes the text transparent, as retail's sprites fade, instead of darkening it.
    • halo and halo_strength: a soft dark halo that fades out from the letters.
    • kern: the font's kerning, through the new capfont::KernPixels (a kern table or GPOS pair kerning). It is applied when a line is both measured and drawn, so a kerned label still aligns, and it is skipped for words placed letter by letter into retail's painted slots.
    • ink_spacing: letters set by their outlines (the new capfont::GetInkExtent) rather than their pictures. A picture's soft edge is a window pixel, so with picture spacing a word tightens as the window grows (CONTINUE measured 125, 118 and 114 logical pixels at 640×480, 1280×960 and 2560×1920); with ink spacing it stays within a pixel.
  • Hit-testing: UI::ConfirmModal::Hit and ConfirmModal::ButtonRect give a yes/no box's buttons from the layout Draw uses. The pause menu's Quit and Save/Load boxes now take the mouse through them. Their old hard-coded coordinates assumed 100×26 buttons at fixed places; the plates are 96×23, and they move as the text grows.
  • Cleanup:
    • The battle menu's text moves from ui_framework/lang.cpp to battlemenu/strings.cpp, since the framework holds no menu's content.
    • The Save/Load words for French, German, Italian and Spanish move out of the code into battlemenu.saveload.* keys, with the same text.
    • UI::JournalStrings is declared with the journal (menu_manual_port.hpp).
    • The duplicate public copy of the framework's internal.hpp is removed, along with an include it didn't use.

Docs

  • docs/UI_FRAMEWORK.md, moved from docs/port/ (which otherwise holds the review ledger and the truncation report), rewritten:
    • It describes the framework as it is: fonts, effects, widgets and texture state.
    • It proposes a cleanup, named looks, hit-testing from layout, and the order in which retail's screens move onto it.
    • Its "Matching retail's 2D look" section records the GS rules for reproducing a retail picture's colour and opacity, with the title as the worked example.
  • docs/PC.md: "The title menu, Exit and Quit".
  • tools/font/README.md: Chronicle Title Bold.

Testing

  • Linux, in the Flatpak SDK on lavapipe:
    • It builds with no new warnings.
    • 566 of 568 tests pass. The two failures are GfxValidation.*, which need a Vulkan validation layer the SDK doesn't ship.
    • New tests: CaptionFont.KernsThePairsTheFontKerns, CaptionFont.InkExtentIsTheOutlineAtAnySize.
    • scripts/port/truncations.py --check passes.
  • Headless captures:
    • the title menu in all five languages;
    • Exit selected, and its confirmation;
    • Quit → Yes in Norune, landing on the title.
    • The title menu at 640×480, 1280×960 and 2560×1920: each row's width within a pixel at all three.
  • On a real GPU, the title menu was compared against retail's over several rounds.
  • Not tested yet: Quit from inside a dungeon floor; the mouse on the title's Exit box; Windows and macOS beyond CI.

Notes for reviewers

  • @Tororoi: this touches the caption renderer (font slot 3, kerning, see-through, halo, ink spacing). Everything new is opt-in, and kerning and ink spacing leave slot-placed painted words alone.
  • The French, German, Italian and Spanish text for the new Quit wording and the Exit row wasn't written by native speakers; corrections are welcome. The Start, Continue and Option words are retail's.

@SirFancyBacon

Copy link
Copy Markdown
Contributor Author

Closes #203

@Adubbz
Adubbz merged commit a14d000 into TheMoonPeople:master Oct 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhancement] - Quit Game to exit to Main Main with an "Exit" option added

2 participants