Loomguides

The debug panel

What a preview is actually doing — the mounted target's timings, the logical viewport, the live instance tree, which typefaces really loaded, and a stage inspector that reaches click-through frames.

A preview that renders the wrong thing rarely tells you why. The tree is a WASM layout result painted into a DOM that does not resemble it, so a browser inspector shows you divs and CSS transforms rather than a Frame with a Size. As of 0.10.0 every gallery carries a panel that reports the scene in its own terms.

Opening it

Three ways, all equivalent:

  • the debug button in the sidebar header,
  • Ctrl+Alt+D,
  • ?debug=1 on any gallery URL.

It is off by default, and while it is closed nothing it does runs at all — no observers, no timers, no tree walks. Everything it reads is read-only and outside the render path, so a scene behaves the same with the panel open as without it.

The ?debug= parameter takes the spellings a flag usually gets typed with: a bare ?debug is on, ?debug=0, false, off, no and none are off, and anything else present is on — so a host page templating the parameter can pass a boolean straight through.

What it reports

Each section folds away and keeps reporting its one headline number while folded.

target — the target’s path and title, how long its import() took, and how long from the mount to the first frame on screen. The panel’s button re-mounts the active target, which is how you take those timings for a target that was already up when the panel opened.

viewport — four numbers that agree unless the page asked for a ?base= viewport, which is the reason all four are shown: the stage in real pixels, the logical viewport the scene actually laid out against, Workspace.CurrentCamera.ViewportSize, and the scale factor with the ?base= width behind it. Plus the device pixel ratio and the theme. Together they tell a scene that laid out small from one that was painted small — see Previews on a phone.

scene — live instances, how many are GuiObjects, and how many of those are invisible, which is usually the answer when a scene looks empty. Then tree depth, the DOM nodes it became, a count per class, and each layer with its DisplayOrder and size.

fonts — every typeface the scene’s text resolved to, the weights asked for, and whether the browser really loaded it or fell back to another face. A family that never arrived still paints, just at the wrong metrics, so this is the row that explains a layout which only differs on one machine. See Fonts and text metrics.

frame — frame rate, DOM patches committed since the panel opened, and a count of what loom logged. Its warnings usually explain a scene, and nobody reads the console.

inspect — covered below.

Inspecting the stage

Hover the stage and the panel names the GuiObject under the pointer, outlines it with its size, and lists its ancestry, absolute geometry, UI* modifiers, resolved typeface and properties — colors as swatches, everything else typed and colored.

  • Alt+click pins the selection so it stops following the pointer. Escape releases it.
  • The ancestry trail and the under rows — everything else the pointer is over — are clickable, so the tree can be walked from the panel.
  • The hit test is the scene’s own PlayerGui:GetGuiObjectsAtPosition, not the browser’s. A click-through frame that no browser inspector can reach is still inspectable here.

Taking a snapshot out

copy puts the readout on the clipboard as text. json downloads the whole thing as a file — every section as data, plus the complete instance tree with each object’s absolute position and size, which is what a bug report wants instead of a screenshot of a panel.

The same object is available while the panel is open as loomDebug.snapshot(), so a devtools session or a headless harness can take one too:

In the devtools console, panel open
copy(loomDebug.snapshot());

See also