Log inGet started
What it does

system_tools

The editor's dock SERVICE. A visibility-driven Z.shell.dockApp host that renders whatever panels are registered in the editor registry (modules/api/editor/registry), sorted by each panel's order. It holds NO hardcoded panel list — the panel set is entirely what has been registered, and the dock seeds from the registry at mount and stays in sync via onChanged (add/remove is live, no remount).

The shell's per-panel refresh scheduler gates every data fetch on (window_visible AND panel_open AND refresh_due), so the dock costs zero engine work when hidden / closed and polls only the panels the user opened.

The service owns a single named app "system_tools" with one main screen (system_tools/main) plus an extraScreens.details floating window — a fixed entity inspector that opens on selection from the entities panel (not a registry tab).

Where panels come from

  • Built-in tabs — modules/api/editor/system_tools/panels registers the engine's own menus + tabs through the public addPanel / addMenu API. The editor entrypoint requires that module; the require IS the registration.
  • World panels — an editorPanel asset whose onRegister(self) hook calls addPanel (see assetTypes/editorPanel.assetType). Write a panel asset into the world → it appears, no restart.

Both paths end at editor.addPanel({ id, build, label?, menu?, order?, refresh?, onCallback?, onMount?, tick?, float? }). The dock renders each registered panel as a dock tab; the top bar lists it under its menu in order.

Exports

  • M.mount(opts: MountOpts?) -> SystemToolsHandle — mount the dock service and return an opaque handle whose update / onCallback / destroy / setVisible the hosting component drives each frame. On mount it publishes its open/close/toggle/isOpen controller into the registry (EditorRegistry.dock()) so the top bar + viewport camera can drive it; destroy clears it.

Module-level introspection:

  • M._APP_NAME: string — "system_tools".
  • M._MAIN_SCREEN: string — "main".

The registered panel set is introspected through the registry itself (EditorRegistry.panelsSorted() / EditorRegistry.list()), not through fields on this module.

Types:

  • MountOpts = { include_agent: boolean?, include_graphics: boolean?, layer: string? }
  • SystemToolsHandle = { state: any, update: (dt) -> (), onCallback: (id, data) -> boolean, destroy: () -> (), setVisible: (b) -> (), screenName: string }

A panel spec

editor.addPanel({
    id      = "profiler",            -- unique key (dock tab + routing id)
    label   = "Profiler",            -- dock tab title + menu entry label
    menu    = "debug",               -- top-bar menu it opens from
    order   = 10,                    -- position within the menu / dock
    refresh = 0.1,                   -- seconds between rebuilds when open
    build   = function(state) ... end,             -- pure: returns widget
    onMount = function(state) ... end,             -- optional, run once on first open
    onCallback = function(id, data, state) -> bool, -- optional, returns handled
})

build(state) should be pure — derive everything from state plus external sources (use Cache.tracked for those). Per-panel persistent state lives at state.tabs[<id>].

Mount API

local SystemTools = require("@builtin::modules.api.editor.system_tools")
local handle = SystemTools.mount({ include_graphics = true })

-- In your component:
function update(dt) handle.update(dt) end
function onCallback(id, data) return handle.onCallback(id, data) end
function onDestroy() handle.destroy() end

-- Visibility:
handle.setVisible(true)            -- equivalent to ui.showScreen(handle.screenName)
handle.setVisible(false)           -- equivalent to ui.hideScreen(handle.screenName)

Notes

  • Work-gating compounds: window visibility, panel open-state, and per-section collapse. Hidden window → zero engine work. Closed panel → no build and no fetches. Collapsed section → use Z.dataSource(fn, { gate, ttl }).
  • The handle's state field is the live reactive State. Treat it as opaque except where documented.
  • Adding a built-in panel: add a row to panels.module pointing at the tab module. Adding a world panel: write an editorPanel asset. The next mount (or the live onChanged reconcile) picks it up.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

This asset doesn't declare a schema or structured payload.

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

0items
This part has no composite children. See the Files segment for its leaf payloads.
This part has no leaf payloads.

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.