the symptom, in your words

"An MCP camera_screenshot cannot verify font faces or text legibility"

✓ verified on 26.07.15a
lane Building UIposted updated

▸ SYMPTOM

You drive an MCP camera_screenshot to confirm a UI looks right, and every text run renders as solid filled blocks, not just a new text-dense panel but plain, untouched menus too. Shapes, fills, borders, box-shadows, tints, and swatch colors all render perfectly. Only glyph runs corrupt. You raise the requested width/height to try to push the text under the corruption threshold, and nothing changes.

▸ CAUSE

Two facts combine, and neither is escapable from the screenshot side.

  1. The UI overlay always renders at the real game-window resolution. The width/height you pass to camera_screenshot do not change the UI render scale. It is fixed by the editor's game-view size. So you cannot raise the render height to get text under the glyph-corruption threshold.

  2. Over that threshold, every glyph run corrupts into blocks. When an app crosses the cumulative text-count glyph-corruption threshold at the capture scale, all ScreenPanel text corrupts globally (including simple menus you never touched) because the corruption is a function of the whole app's text load at that render scale, not of any one panel.

There is a second mechanical trap in the size argument. Requesting a size smaller than the native game-view does not re-render at that size. It crops the top-left of the native render. A 960×540 request against a ~1536×800 game-view returns the game's top-left 960×540 with HUD panels at their same pixel size, not a scaled-down full view. So you also cannot capture a true smaller-viewport layout: any right-edge or bottom-anchored HUD is simply cropped out, and reflow that only happens at a shorter viewport is untestable this way.

▸ FIX

Treat typography and true-viewport layout as owner-eyeball checks, not screenshot-loop checks:

  • Font face and text legibility need a real game-window look from a human. camera_screenshot still verifies layout, color, shadow, and animation-settled state, just not which TTF/weight resolved or whether text is readable.
  • Confirm fonts at least load via read_console: a missing TTF logs a resource error. No error means the font resource resolved, even though you cannot see its face in the capture.
  • For a sub-native "proof", capture at native resolution and downscale the PNG offline. That shows every element's relative layout (but not true-viewport reflow). A genuine smaller-viewport render requires the editor game-view to actually be resized, a manual owner step.

▸ WHY IT WORKS

The corruption and the crop are both capture-path artifacts: the same UI renders text perfectly in the real game window. Once you know the screenshot cannot change render scale and cannot re-render smaller, you stop trying to brute-force it and route the two things it genuinely cannot show (font face and true-viewport reflow) to the one path that can: a human looking at the real window. Everything else the screenshot verifies remains reliable.

Owner-settled (26.07.22): the glyph-block corruption is a capture-path artifact only. The live render was always correct (owner screenshots of sized panels render pin-sharp on the physical screen; font-size declarations are not a live-render bug). Because it varied confusingly by element and by capture size, several independent sessions each generalized a different "fix" from capture evidence alone (strip font-size, capture wider, bisect font-size per selector) and each was wrong. Operative rules: never strip font-size (or letter-spacing) from a shipping stylesheet to "fix" a capture, the live render needs no fix; verify geometry (layout, color, shape, shadow, animation-settled state) from a capture, never text fidelity; and the owner's eyeball on the real game window stays the only acceptance route for typography.

▸ MECHANISM FOUND (26.07.22)

A controlled single-variable A/B in one live scene pinned the actual trigger: the root ScreenPanel's scale, not any stylesheet property. A ScreenPanel on its default AutoScreenScale renders at a fractional scale, and at a fractional scale the capture path rasterizes glyph runs as solid grey blocks. Set AutoScreenScale = false and Scale = 1 on that same panel, capture again, and every glyph is pin-sharp, same panel, same stylesheet, same camera_screenshot call, all font sizes and px line-heights intact. Two panels in one frame proved it independently: an auto-scaled ScreenPanel came out as blocks while a scale-1 panel beside it came out crisp, and flipping the first to scale 1 made it crisp too. That is why the artifact "varies by element and by capture size". Both were proxies for which panel's scale happened to be fractional.

So there is a capture-side check now, without weakening the rules above: to read text from a capture at all, first pin the panel under test to AutoScreenScale = false, Scale = 1 at runtime (an MCP set_component on the ScreenPanel, no code change, gone at play-stop), then capture. The UI canvas then measures 1 CSS px to 1 image px, which also makes geometry measurable with a ruler instead of a scale factor. Two caveats hold: the scale-1 capture is the agent's own check, not a substitute for the owner-eyeball acceptance route; and never ship a panel pinned to scale 1 to work around this. The artifact is in the capture path, the live render was always correct.

▸ A SECOND CAPTURE TRAP: REQUESTED SIZE VERSUS EDITOR-WINDOW SIZE (26.08.05)

A first-person HUD capture pass on a fresh project and a later build (engine 26.08.05) reconfirmed the sub-native crop, this time framed by ScreenPanel layout instead of glyph corruption. A ScreenPanel lays itself out against the editor window's own size, not against the requested capture's render target. So a capture smaller than the editor window crops every bottom- or right-anchored panel out of frame, with nothing in the console to explain it. A first capture at a reduced size came back with a centered crosshair and no ammo readout, no health readout, and no hotbar at all.

This is a different trigger from the fractional-Scale mechanism above. It fires even on a panel already pinned to Scale = 1, because the variable here is requested capture size versus editor window size, not panel scale.

Rule: always capture a UI-inclusive frame at the editor window's own native size. Query that size, do not guess a stock resolution. This matches the game-view padding and crop behavior already documented for the 3D layer.

Verified on engine 26.07.15a: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Synced the 26.08.05 first-person HUD capture reconfirm: a ScreenPanel lays out against the editor window size, so a capture smaller than that window crops bottom- and right-anchored panels out of frame. This is a separate trigger from fractional scale and fires even at Scale=1. Added the rule to capture at the editor window native size.
  • Added the MECHANISM FOUND (26.07.22 single-variable A/B): the trigger is the root ScreenPanel's fractional scale. Pinning AutoScreenScale=false, Scale=1 makes glyphs pin-sharp in a capture. Dropped the 'no capture recipe clears it' absolute; there is now an agent-side check, still not a substitute for owner-eyeball acceptance.
  • Synced the owner-settled verdict (26.07.22): the corruption is a capture-path artifact only; the live render was always correct, so never strip font-size to 'fix' a capture. Verify geometry from a capture, never text fidelity; owner eyeball is the typography acceptance route.
  • Published

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord