Builtin Library
README.md
viewport_select
Turns a viewport pointer gesture into an editor selection change, applying the
standard modifier semantics, and drives the per-frame bridge that reads real
pointer + modifier input. Selection is written into the shared
modules.api.editor.selection service's entity scope, so the viewport, the
selection outline, and the outliner stay in lockstep.
A left press+release within a few pixels is a click-select; a larger left drag
is a marquee (rubber-band) that selects every entity whose screen position
falls inside the band. The band is drawn by modules.api.editor.marquee_overlay.
Exports
M.applyClick(Sel, scope, hitId, mods)— pure decision:hitId == nilclears (unless a modifier is held); ctrl toggles the hit; shift adds it; neither replaces. Entity ids become{ kind = "entity", id }refs.M.applyMarquee(Sel, scope, ids, mods)— pure decision for a completed marquee: an empty band with no modifier clears, an empty band with a modifier leaves the selection unchanged; ctrl toggles each id, shift adds the set, neither replaces with the set.M.worldToScreen(m, w, h, p)— project a world point through a 16-float column-major view-projection matrix and viewport size to viewport pixels (sx, sy), or nil when the point is at/behind the camera. Mirrors the engine's ownworld_to_screen_px.M.pointInRect(rect, sx, sy)— inclusive screen-rect hit test.M.nearestIcon(cands, cx, cy, thresholdPx)— the nearest icon candidate{ id, sx, sy }to the cursor within a pixel threshold, or nil.M.entitiesInRect(rect)— engine-driven: the selectable entity ids whose world position projects insiderect(viewport-pixel space) this frame.M.iconPick(cx, cy)— engine-driven: the entity whose meshless icon is nearest the cursor withinICON_PICK_PX, or nil.M.tick(dt?)— call once per editor frame; prunes dead selection refs, reads pointer press/drag/release + modifiers, and routes a click or a marquee through the pure decisions above.
Notes
- The decision functions are pure so they can be unit-tested against the real selection service.
- Icon-pick fallback. A click that hits no mesh/collider (the engine pointer
pick returns nil) falls back to selecting the nearest meshless-entity icon
(light / camera / audio source / reflection probe) within
ICON_PICK_PX, so lights and cameras — invisible to the raycast — are selectable by their billboard. The engine pointer pick wins whenever it hits. - Gizmo precedence. A marquee only starts on a frame where the pointer has
moved past the click slop AND the transform gizmo is not dragging.
tickruns before the gizmo's tick in the editor entrypoint, so by the time a drag passes the slop the gizmo has already had a frame to claim a grabbed handle.