Builtin Library
README.md
editorSelection
Named selection scopes for the editor. A scope is an independently tracked, ordered set of typed refs plus a primary (the last ref added or clicked). Distinct scopes never clobber each other, so viewport, outliner, inspector and asset browser share one answer to "what is selected" per kind.
A ref is { kind: string, id: string } — a stable id, never a display
string, so rename/move never invalidates a selection.
Exports
M.scope(name) -> Scope— get/create a named scope handle.M.set(scope, refs)— replace refs in order; primary becomes the last.M.get(scope) -> { Ref }— refs in click order (fresh array).M.primary(scope) -> Ref?— last-clicked ref, or nil.M.clear(scope)— empty a scope.M.toggle(scope, ref)— add if absent, remove if present.M.add(scope, refs)— add each ref not already present; primary becomes the last added.M.remove(scope, refs)— remove each ofrefs; primary becomes the last remaining or nil.M.contains(scope, ref) -> boolean— membership by(kind, id).M.count(scope) -> number— the scope's selection size.M.subscribe(scope, fn) -> handle/M.unsubscribe(scope, handle) -> boolean.M.context() -> { scope, refs, primary }— last-focused scope, for command ctx.
Usage
local Selection = require("@builtin::modules.api.editor.selection")
local scope = Selection.scope("entity")
Selection.set(scope, { { kind = "entity", id = "player_1" } })
Selection.subscribe(scope, function() refreshInspector() end)
Notes
- State lives in a fixed
_Gslot, seeded pre-seal by the boot chain (prelude.luau); it survives hot-reload and edit↔play flips. Mutations after boot write into nested tables only. set/toggle/clearmark their scope as last-focused, which drivescontext()and therefore which scope commands act on.- The service holds the editor's selection state in Luau. Refs handed back by
get/primary/contextare copies, so a caller can hold or mutate them without touching internal state.