Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdf78e4f826

README.md

edui.inspector

The Inspector as an ordered list of sections. A subject — an asset, or a component on an entity — gets generic sections, merged with the sections its declarer's inspector.luau adds or replaces, in the order that file names.

local Inspector = require("@builtin::editor.edui.inspector")

local sections, ctx = Inspector.assetSections(ref, asset.inspect(ref))
local nodes = Inspector.render(sections, ctx)       -- section cards
local nodes = Inspector.renderAsset(guid)           -- the same, from an asset id

local sections, ctx = Inspector.componentSections(entityId, "Camera")
local nodes = Inspector.render(sections, ctx, { nested = true })  -- a component card's body

Sections

A section is { id, title, icon?, open?, build(ctx) -> { node } }. Its title is a string or an i18n.text value, which the Inspector reads each time it draws the section, so a title read from a catalog follows the editor's language. The generic asset sections, in default order, are identity, problems (present only when asset.validate reports any), tags, move, settings, preview and operations (see assetSections.module). A type declares its own in the file its type.yaml names:

inspector: { type: "inspector.luau" }

That file returns { sections?, replace?, order? }: sections it adds (placed before operations), generic sections it replaces by id, and the ids to put first. material.assetType/inspector.luau is a worked example, and @builtin::assetTypes.assetType.shared.inspector documents the declaration.

A component on an entity has one generic section, settings: its public fields as typed controls over the live component, three-number colour and vector aliases as one grouped control, each edit checked against the schema and written as one undoable operation. A component that ships an inspector.luau beside its init.luau (named by component.assetType's inspector: { instance: "inspector.luau" }) adds, replaces and orders sections of its card the same way; its sections read ctx.component and ctx.selection.id. SceneModule.component/inspector.luau is a worked example.

A declaration that cannot be read, or that names a section that is not there, shows its problem as a first inspector-problem section while every other section still renders. Every build runs through Inspector.buildSection(section, ctx) -> (rows, problem?): a build that raises, or returns anything but a list, shows its error inside that section alone.

The Context

Every build(ctx) receives one Context, made by Inspector.valuesContext:

FieldWhat it is
refthe inspected asset (on an entity, the component asset)
infoasset.inspect(ref)
schemaasset.schema(ref), settingsOf resolved
schemaProblemwhy a declared schema did not resolve
settingsthe current values
setSettings(patch)checks the patch with Field.checkSchema, then writes it as one undoable operation named for the field; answers (ok, violations)
rejectedfield path -> the message of its last rejected edit, for this subject only
selection{ scope = "asset" | "entity", id, component?, name? }; on an entity, component is the component's identity and name the name the entity lists it by
componentthe live component proxy (entity scope)
nameOf(id)the name an entity-reference field shows for an entity id (entity scope)
widgetsthe edui framework table (field, schemaField, section, button, text, vbox, hbox, ...)
keyPrefixthe callback-key namespace for this subject
refresh()rebuild the Inspector after a write that moves no revision
actionswhen set, the ids of the Settings actions offered ({ reset = true }); nil offers every action that applies
partsthe building blocks a section composes: facts, lists, tables, asset and entity links, actions, a file opener, problems, swatches, a content-versioned cache, an lsp check and typed values (parts.module)

Inspector.valuesContext{ subject, schema?, schemaProblem?, values?, write, ref?, keyPrefix?, info?, selection, component?, nameOf?, actions? } is the one way to make a Context: write(patch) performs a patch already checked against the schema.

The rest of the API

  • Inspector.mergeSections(generic, decl, problem, file) — the merge and order.
  • Inspector.componentSections(entityId, componentName) — a component card's sections and Context; Inspector.componentSettingsRows(ctx) is its generic settings section's body.
  • Inspector.componentValuesSignature(entityId, componentName) — text that moves whenever one of the component's declared fields holds a different value (an edit, an undo, a script's write); a panel folds it into its build signature.
  • Inspector.typeSections(ref) — the sections ref's type declares, plus Settings when it has values; what the inline editor under an asset chip shows. No other generic section is built for it, so it runs no validation. Nil when the type declares no type: inspector.
  • Inspector.render(sections, ctx, { nested = true }) — titled groups inside a card, for the inline editor.
  • Inspector.signature(assetId) — text that moves whenever what the asset view shows can have moved: the asset folder's content version (the change dispatcher moves it after a write inside the asset reaches its type's hook — an edit, an undo or redo, a peer's write) and the settings values file's. A panel folds it into its build signature; edui.widgets.openEditorsSignature() is the same for every open inline editor.
  • Inspector.buildSection(section, ctx) — runs one section's build and judges it: (rows, nil), or one error row and the problem text.
  • settingsSection.fields(ctx) — the field rows of the whole schema without the actions beneath them.
  • settingsSection.fieldRows(ctx, fields) / settingsSection.actionRow(ctx) — the two halves of settingsSection.build, for a section that shows part of a schema and acts on all of it.
  • The Context, Section and Declaration shapes are exported as types: Inspector.Context, Inspector.Section, Inspector.Declaration.
  • Inspector.release(keyPrefix) — forget the rejections, section disclosures and parts state (action failures, file checks, and cached values no other open Context read) kept under a Context's key prefix and the prefixes nested in it; a closed inline editor calls it for its own.
  • Inspector.epoch() — moves on every disclosure, rejection and write the Inspector records; a panel folds it into its build signature.
  • Inspector.settingsSection — the Settings section (settingsSection.module).
  • @builtin::editor.edui.inspector.presetActions — the Settings section's Save as preset / Apply preset… actions, and presetsFor(declarer), the presets whose target is a declarer. preset.assetType/inspector.luau is the preset's own view: its target and its values edited through the target's schema.