PrivatecontrolsPrivaterangePrivategammaPrivateopacityPrivateabsorptionPrivatebrightnessPrivateambientPrivateshadePrivatespecularPrivateshininessPrivatealphaPrivatephysicalThe knob group a material="physical" mesh layer shows IN PLACE of the five
sliders above (spec MESH_PHYSICAL_MATERIALS_SPEC.md §4): one live slider per
numeric knob in PHYSICAL_MESH_KNOBS, built once, plus read-only rows for the
colour knobs and the cutout, rebuilt per render from the layer's authored attrs.
PrivatephysicalPrivaterefractThe physical block's "Refract data" switch (spec §3.4 Phase 3).
PrivatephysicalPrivateblendPrivatelayerPrivatecolormapPrivatecustomThe 'custom' entry, attached only while the primary layer has an authored LUT.
PrivatelabelPrivatelabelPrivatelod"Active level" dropdown for lod_group layers. Shown only when
the primary selected layer is an lod_group; hidden otherwise.
Options: auto plus one lock to level <n> entry per child
(1-based label; the option value stays 0-based for the registry's
lockLevel API).
PrivatelodStatus span next to the dropdown showing the currently-rendering
level (e.g. "L3/5", 1-based to match the data-monitor chip). Kept
live by a per-frame callback (layers-lod-status) registered by
the panel in buildPanel(), so it tracks auto-selection swaps driven
by camera motion — not only render() state changes.
PrivatelastLast text written to lodLevelStatus. The per-frame callback compares against this and only touches the DOM when the readout actually changes, so a static scene costs a string compare per frame rather than a DOM write. Reset in dispose().
PrivatecontrolEach section control's group element, keyed by its LAYER_CONTROL_RULES id
(also stamped as data-control), so one pass shows exactly what the table says.
PrivatecontrolsPrivateeventsTracks every event listener attached during build() so dispose() can tear them all down with a single call (the panel-wide listener-tracking pattern).
PrivatedepsTrue while a user-driven control interaction is applying state — the panel's state-change subscription skips control re-renders meanwhile.
Tear down the widgets + listeners so a subsequent build() starts fresh. Mirrors the panel's clear(): the EventGroup is re-instantiated (not left disposed) and the cached LOD readout text is reset so the fresh panel writes its first readout unconditionally.
PrivatedisposeDispose and drop every single-thumb slider of the section.
PrivateregisterRegister a section control's group element under its rule id.
Build the control widgets into container (the panel's controls div).
PrivategetLook up the LOD-group registry for the currently-loaded scene.
Lazy lookup via the SceneLoaderManager (the layers panel can't
import scene/ directly without violating the data → ui layer
direction; the SceneLoaderManager hands us the loader's registry
field). Returns null when no scene is loaded or the loader
was created without a registry factory wired up.
PrivateapplyPoint every lod_group the Active-level control drives for layer at mode:
a kind=lod layer drives itself, a kind=partition layer every nested lod_group
(clamped per group by setSelectorMode on ragged ladders).
Return a locked Active level to auto — the authored state, since every
lod_group loads in auto. Part of the panel's reset apply set; a no-op for a
layer whose groups are already in auto (or not registered yet).
PrivaterenderPopulate the lod-level dropdown's options for the given child count.
PrivatebuildThe gsplats Brightness (display_gain) slider, directly under the display
range it is independent of. The value is RELATIVE to the authored gain
(×1 = the opening exposure, which double-click restores); the stored attr
stays absolute and the tooltip names it. A log track; the readout is a ×
multiplier and takes exact entry. A multi-selection gets the same relative
factor on each layer's own authored gain.
PrivaterenderThe data-unit pieces of the section: readout formatting, the read-only data reference (shown for direct-colour layers too) and the relative Brightness.
Update controls to reflect the primary selected layer's values
PrivatesyncShow the colormap dropdown for layers that support one, offering the
'custom' entry only to a layer with an authored LUT (any other layer would
fall back to viridis under that name), and seat it on the layer's palette.
PrivatesyncShow exactly the section controls LAYER_CONTROL_RULES allows for the primary
selection — every gate (the κ slider's volumetric mode, the mesh appearance
sliders' house/physical/shading/cutout gates, Blend, Gamma, colormap, classes,
active level) is a row of that table. Called from render() and the
blend-dropdown handler (a mode switch must reveal/hide κ and the cutoff at once).
PrivatedisposeTear down the physical knob group (sliders own DOM + listeners).
PrivatebuildThe "Refract data" switch (spec §3.4 Phase 3), after the knob sliders: a glass that draws after — and refracts — the emissive data behind it. Rides the same knob record and apply path as the sliders, so Reset restores it the same way.
PrivatebuildOne live slider for a physical knob, from its table spec: the track spans the
spec's slider domain (a log track for a length spanning decades, its top stop
meaning ∞ where the spec says so), and a drag follows the mesh-appearance
pattern — map the slider value into material space, mutate every selected
layer's record, then push each through the apply engine.
PrivatesyncGrey out the knobs that change nothing in the current state of their siblings,
with the reason as hover text (physicalKnobInertReason). Measured, not
guessed: on a metal the whole glass family is inert, and a clearcoat roughness
without clearcoat is too — a live slider that does nothing reads as broken.
PrivaterenderSeat the physical sliders on primary's live knob record and rebuild the
read-only rows beneath them. sheen_color, attenuation_color and
alpha_cutoff appear only when authored — their defaults are the material's own
business, and a colour picker is not a slider.
PrivatecomputeCompute the "Active level" readout text for the primary-selected
layer, or null when no LOD readout applies (non-LOD layer, or the
lod_group registry isn't populated yet). 1-based ("L3/5") to match
the data-monitor chip (data-loading-monitor/templates/scene-graph.ts) and the
dropdown labels. Reads the live active level straight from the
registry, so it is correct on any frame — including auto-selection
swaps driven by camera motion.
PrivatesetWrite the LOD readout, skipping the DOM touch when the text is unchanged. Lets the per-frame callback run every frame at the cost of a string compare on a static scene rather than a DOM write.
Per-frame: keep the LOD readout in sync with the live active level
chosen by the auto-selector. Cheap — early-returns when the panel is
hidden or the primary layer has no LOD readout, and setLodStatusText
skips the DOM write unless the text actually changed. A null text
(non-LOD layer / registry not ready) leaves whatever render()
last set in place rather than clobbering it.
Mesh-only appearance sliders (spec §6.2). Hidden for every other geometry type — mesh is the only SHADED type, so a shade floor and a falloff exponent have nothing to act on elsewhere.
alphaCutoffis gated more narrowly still: only inopaque, the one mode that applies the cutout.