Front-end visual revamp: inked gel on a membrane in the living world - #245
Draft
genixpro wants to merge 14 commits into
Draft
Front-end visual revamp: inked gel on a membrane in the living world#245genixpro wants to merge 14 commits into
genixpro wants to merge 14 commits into
Conversation
Diagnosis of why the refreshed menus read as sterile, with the measurements behind it and one demonstration spike. Nothing here is proposed for merge. The review is in docs/ui-visual-review/README.md. In short: the refresh removed the old style's bad execution (tiled grass, bevelled gold) along with three properties worth keeping — the chrome used the game's colours, controls read as objects, and menus matched the match. Flat design puts all the personality on palette, shape and type, and the current front end has a palette derived from nothing in the game, no outlines, the stock system font, and none of the game's art. Measured: the world runs 56-75% saturation, the chrome 11-38%; the greens are not even the same hue family; the theme draws a cream veil over the colony to make the pale chrome legible. Nine near-identical panel fills are spread over five drifted palette definitions. Settings and the lobby each re-implemented their own drawing layer, so a full rewrite of FrontendTheme leaves the Settings panel interior pixel-identical. The spike changes surface treatment only, in about 40 lines: chrome recoloured to the game's own hues, a drawn ink contour on panels and controls, and a dark scrim instead of the cream veil. Layout, fonts and assets are untouched. It shows the reading is right where the theme owns drawing, that palette alone does not fix the bounding-box composition, and that Settings is unreachable from the theme — which is the argument for landing the token unification first. Captures are from the real client renderer via MenuColonyHarness at 1152x720 on the software backend; before/after for four screens are alongside the document. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
Five copies of the menu palette had drifted apart (theme, main menu, lobby controls, lobby screen, settings layout). Introduce a single set of named tokens in FrontendTheme.h and route every front-end colour literal through it. Values are the ones the review settled on; Settings, which carried a third unrelated palette, shifts to match the others. No drawing logic changes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
Add FrontendTheme::blob() and ring(): a rounded contour with per-corner radii and a gentle, rect-seeded edge wobble, drawn as a two-pixel ink ring around a fill with a one-pixel gel highlight. Every theme hook, the main menu, the lobby's pad/button/dropdown/slider/popup helpers and the settings screen (through two small fill/control helpers replacing its raw rect pairs) now draw through it, so all three drawing layers share one shape language. Panels become a translucent membrane that the colony tints through (opaque under low-speed graphics); the two lobby screens paint the world only and own their page membrane, instead of layering a sheet over the theme's widget-union panel. List rows stay quiet until chosen; keyboard focus is a violet ring, distinct from the ink hover ring, which had become invisible once line and ink shared a value. Widget geometry and hit rects are unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
…drift The colony's cloud pass used to run inside drawMap, under the panel, where widgets painted after it could never receive it. Add a DRAW_NO_CLOUDS option so the menu colony skips that pass, and a Style::afterPaint hook (the same optional-hook shape as onFrame) that Screen::dispatchPaint calls once every widget has painted. FrontendTheme uses it for one shadow+cloud pass over the whole window, computed by MenuColony from the viewport of its last draw so the field stays anchored to the terrain. One compute per frame, as before; the engine's own guard keeps it OpenGL-only. MenuColony also drifts its camera about a tile and a half on a slow Lissajous, applied as a sub-tile transform on OpenGL; the software path keeps its integer-tile viewport. Both are presentation state, outside the simulation and its checksums. The harness's Preview::render now mirrors dispatchPaint by invoking the style's afterPaint, so captures and recordings show what the game shows. Measured on a 120-frame OpenGL recording: the world shifts (-9,-4) px over 80 frames and the panel band's luminance moves 198→204 as a shadow crosses it; before the harness change the band was a flat 202. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
Buttons drawn through the theme and the main menu inflate by up to two pixels as their highlight rises and shrink one pixel while pressed; lobby pads swell one pixel under the cursor. Hit rects are untouched. The front page fades in over the screen's first ten frames using Screen's existing animationFrame, panel, wordmark and buttons together. Harness previews render the settled state. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
A worker from the menu colony, in its team colour, walks the empty band under the utility buttons at about 24 px/s, turning at the panel's edges and pausing now and then. The classic sheet's frames carry a faint dark matte that never showed on grass but does on a pale membrane, so the sixteen walk frames are composited once with that matte removed, the way the wordmark is pre-fitted. It fades in with the rest of the page and cloud shadows pass over it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
Replace the review's spike captures with the shipped result on both backends, rewrite the review README as a record of what changed and how it was verified, and update the front-end refresh notes for the membrane palette, camera drift and the cloud pass. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
Lower the front-page membrane to alpha 140 (from 214), so the terrain shows through the sheet rather than only tinting it. panelAlpha() takes the normal-mode value as a parameter; other screens keep theirs. Buttons are opaque gel, so legibility is unchanged. Refresh the two main-menu captures. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
blob() painted every row full-width in ink and laid the fill over it, so a translucent fill blended against opaque ink rather than the world: lowering the alpha only turned the sheet gray. Draw the ink as a true two-pixel ring and the fill only between, so nothing overlaps. Every membrane is brighter and warmer as a result, and the colony now reads through the front page at alpha 140. Refresh all captures. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
The settings screen darkened the world with its own alpha-200 scrim and drew a near-opaque sheet over the theme's widget-union panel, so nothing read through and its colour sat apart from the front page. Paint the world and the shared scrim only, then one sheet at the common membrane alpha. Refresh the settings captures. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRgZCRPabZw9EKnhWNJG1S
Playtesting surfaced three concrete bugs behind an overall "feels 90s" reaction: - Button hover swell was computed as int(hi)*2/255 -- integer division on a smooth 0-255 highlight collapsed it to 2-3 whole-pixel states instead of a continuous grow. Add FrontendTheme::swell(), which draws the base size opaque and crossfades a one-pixel-larger outline over the fractional remainder, so hover/press reads as continuous. Used by the main menu buttons and the shared theme's button background. - MenuColony's camera drift floored to a whole pixel before splitting into tile + sub-tile fraction, so the camera sat still for seconds near the drift's turning points and then hopped a pixel. Keep the drift a double all the way to the GL transform, matching how the in-game camera's own fraction is already a float (TorusView::draw) for the same reason. - blob()/ring() rounded every corner and wobble offset to a whole pixel with no anti-aliasing, and the wobble was applied inside the rounded-corner curves themselves, chipping them into notches. Carry fractional insets through to the boundary pixel, blended by coverage, and fade the wobble to zero inside the corner curves. None of this changes layout, hit rects or the simulation: re-ran MenuColonyHarness check/navigation/sessions, CustomGameSetupHarness, and run-game-speed-tests.py (checksum 8b9c6da6, unchanged). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WkvtS9itQDnSNEqi6M3CbR
Regenerate all after-*/after-gl-* captures via MenuColonyHarness capture (software and GL) so the documentation matches the current render exactly, and record the three fixes and their re-verification in the review README. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WkvtS9itQDnSNEqi6M3CbR
Contributor
Author
|
Pushed a follow-up after playtesting the built client: three concrete rendering bugs behind the "feels a bit 90s" reaction, all draw-only fixes (no layout/hit-rect/simulation change, re-verified — see
All 11 🤖 Generated with Claude Code |
Playtesting pushed back on the cream/sand chrome itself, and separately on how see-through the front page had become: - FrontendPalette::membrane/gel/gelDisabled are a green tint instead of sand, at the hue actually sampled off the rendered terrain (~HSL 120/52/25), rotated onto the cream tokens' existing saturation/ lightness shape and then pushed a step more saturated. ink, gold and violet are unchanged. - The front page's membrane alpha, deliberately dropped to 140 earlier in this branch to let the colony read through, overshot -- raised to 210. The shared panelAlpha() default used by Settings and custom-game moved from 214 to 235 to match. Re-ran the same harness gates and run-game-speed-tests.py; checksum unchanged (8b9c6da6). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WkvtS9itQDnSNEqi6M3CbR
Regenerate all after-*/after-gl-* captures via MenuColonyHarness capture (software and GL) to match the green chrome and reduced transparency, and record the change in the review README. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WkvtS9itQDnSNEqi6M3CbR
Contributor
Author
|
Second follow-up: the cream/sand chrome itself was the remaining complaint ("still feels a bit 90s"), plus the front page had gotten too see-through.
Screenshots refreshed again. Simulation checksum still unchanged ( 🤖 Generated with Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft — this is a stylistic direction, and I want feedback on the direction before polishing it. Please look at it in motion, not only in the captures: the fade, the hover swell, the cloud shadows, the camera drift and the glob are all things a screenshot can't show.
The problem
The recent front-end work (#202, #236, #237) is a real UX improvement, and people are right that it feels sterile. The review in
docs/ui-visual-review/README.mdmeasured why: the chrome ran 11–38% saturation over a world at 56–75%, in a gray-cream nothing in the game uses; it separated surfaces with 4%-lightness steps and hairlines where every Glob sprite is a heavy ink contour; and the "live colony" behind it had a fixed camera, cloud shadows that never reached the panel, and a 97%-opaque sheet plus a cream veil on top — functionally a wallpaper.Why not just bring back the grass?
We looked at it. The old front end — grass texture tiled across the window, gold bevelled buttons — is what people say they miss:
I think what they actually miss are three properties it had, not the execution: the chrome used the game's colours, the controls read as physical objects, and the menu felt like it was standing in the world. The execution — a seamless tile repeating at 1:1, bevel-embossed gradients — is what dates it, and going back would also throw away the hierarchy and layout work the refresh got right. So this branch tries to restore those three properties without the texture.
The style we're going for
A membrane over a living colony, drawn by the same hand as the sprites.
FrontendPalette.datasrc/gfx/concept-art/and every sprite are wobbly hand-inked contours around soft forms. Controls are nowblob()s: per-corner radii, a gentle rect-seeded wobble, a 2 px ink ring, a gel highlight. That's the wordmark's shape language extended to the chrome.Style::afterPaint), and the camera drifts slowly. The interface is a thing in the world, not a window over a screenshot.Settings, with the same treatment:
More captures (lobby, load, campaign, results, credits, software-backend variants) are in
docs/ui-visual-review/.What I'd like feedback on
frontPageAlpha, currently 140): too open, or not open enough?cloudMaxAlpha; easy to scale down if it reads as mottling.Scope and constraints
Draw-only: no hit rects or widget geometry change; no new assets, no new widget framework;
Glob2Styleand the in-game HUD are untouched. Engine additions are aStyle::afterPainthook (3 lines, same optional-hook pattern asonFrame) and aDRAW_NO_CLOUDSoption nothing else passes. Cloud shadows over the UI and the camera drift are OpenGL-only by the engine's existing guards; the software backend gets everything else.Feel note per
AGENTS.md: this changes how the front end feels, on purpose. Nothing here touches gameplay, simulation, saves, replays or the network.Verification
All run on this branch,
SDL_VIDEODRIVER=dummyunless noted:MenuColonyHarness check— presentation counts, text bounds, colony checksums, main-menu routesMenuColonyHarness navigation— enter/cancel 14 real screen loopsMenuColonyHarness sessions— play/quit, replay, results, editor round tripCustomGameSetupHarnessmodel + visual (Xvfb)test/run-game-speed-tests.py(Xvfb) — simulation checksums identical (8b9c6da6), confirming drift and clouds are presentation-onlyMeasured on a 120-frame OpenGL recording: world shifts (−9, −4) px over 80 frames; panel-band luminance moves 198→204 as a shadow crosses. The harness's
Preview::rendernow mirrorsdispatchPaint, so captures show what the game shows.Copied from genixpro#1.
🤖 Generated with Claude Code
https://claude.ai/code/session_012MQFLk4h8B69C9PvvHfGE5