Table of Contents

Brand Matrix

The Controller branch is the one branch of the equipment tree whose node set is not fixed: it is grown from a snapshot of the active NC runner, and a node whose backing dependency the runner does not resolve is never created at all. This page is the index of every node that branch can grow, and it owns no node of its own — the ids it lists sit under ?tree=equipment/controller on /general-setup, on two plane stems, equipment/controller/machine and equipment/controller/program-data.

Important

Anatomy makes no claim that any id named here is stable across versions. The migration hop that keeps an older ?tree= value resolving is described in Tree Ids and Routes.

What Decides the Shape

One request returns a flat snapshot of the active runner: the brand marker, the chain-driven axis list, and a set of presence flags. Each flag is a type probe over the runner's proxy-resolved dependency list — GetEffectiveNcDependencyList(API), so what is probed is the concrete table a proxy stands in for, never the proxy. Every gate the tree reads tests a single type; two of the fields no component reads test a pair instead. The branch builder reads that snapshot once per build and pushes a node for each flag that reads true. A node that fails its gate is absent, not hidden and not disabled; the branch is regrown from a fresh snapshot whenever a panel swaps the runner. How a branch is built, rebuilt and selected is the Control-Tree engine's own subject — see Control Tree.

Five brands ship as presets: Fanuc, Siemens, Heidenhain, Syntec and Mazak. Each is a property on the engine's runner type returning a fresh instance whose dependency list is written out literally, so what a brand grows is decided by that list and by nothing else.

The snapshot also carries one non-boolean field that changes a panel rather than the tree. workCoordinateKind names which storage model backs the work coordinates, by a type switch over the first IIsoCoordinateConfig in the effective list: fanuc on Fanuc and Mazak, syntec on Syntec, siemens on Siemens (the frame table precedes the machine-data table, which is not an ISO coordinate provider), heidenhain on Heidenhain, and none when nothing resolves. Its generic arm answers for the brand-neutral IsoCoordinateTable, which no brand preset carries — it is reachable only from a runner that already holds one, so the arm is defensive rather than dead.

The Fixed Core

Both plane stems are the builder's return value rather than gated entries, so they appear together whenever a runner resolves, and neither is ever empty: each carries leaves that no flag guards. Both are Group stems, so each renders an intro line and a clickable child list rather than a field editor.

The machine plane's ungated leaves are Controller Brand, Machine Limits (Stroke), Rapid Feedrates, Home / G28 Reference, Tool-Change Position and Controller Parameters. The program-data plane's are Work Coordinates (G54…) and Tool Offsets.

Nothing in that core is gated, so no dependency decides whether those leaves exist — the builder pushes them whatever resolves. What the preset lists decide is whether they have anything to show, and on every brand they do. ControllerParameterTableBase declares the machine-config interfaces itself — home reference, axis set, rapid feedrates, stroke limits, spindle control, M-code declarations and the tool-change trigger — and every brand's parameter table derives from it, which covers the limits, rapid, home and parameters leaves at once. The other two read dependencies each preset carries in its own right: CncBrandDependency behind Controller Brand, and ToolingMcConfig behind Tool-Change Position. On the program-data plane, every preset proxies the generic ToolOffsetTable, and each brand supplies an ISO coordinate provider of its own.

The axis names the per-axis leaves list are the parameter table's own axis entries, which the machining chain adds to and re-types when a machine tool is attached — it sets a type per chain axis and removes nothing, so an attached chain yields the union of the two sets rather than a replacement. Each brand's default table already seeds a linear X, Y and Z, so those rows are populated before any chain is wired.

With No Runner

The builder returns an empty child list, so both stems and every leaf disappear and only the branch root survives. Its editor is the runner root panel, which then shows an hourglass over “No NC controller runner on this project.” and a hint pointing at the ⋮ menu's Load command; the brand badge is dropped and the file caption reads “No NC runner”.

The same empty list is returned when the snapshot request throws, so a failed fetch and a genuine absence produce an identical tree shape, and the root panel renders the same hourglass block for both. What separates them is transient and comes from elsewhere: the shared snapshot's own failed read resets it to the empty value and raises an error toast. That read is a separate request from the builder's, so the two can disagree — a branch collapsed by a thrown build fetch can sit under a root panel still showing the brand badge of a snapshot that loaded.

Every leaf panel still opens with its own guard on the same flag, rendering the shared empty body “No NC runner — load a project first.” Since a leaf node is built only when the snapshot already reported a runner, that guard is a live defence against the shared snapshot emptying under a mounted panel — closing the project does exactly that — rather than a state reached by navigating.

The Matrix

Keyed on the node id, because one tree label is itself conditional: the generic tool-offsets leaf is relabelled when the Siemens $TC_DP table resolves, so an index keyed on labels would be conditional on the very thing it indexes. Rows are in the order the builder pushes them.

Machine-plane rows name the page that documents the node. The program-data leaves have no page of their own, so those rows point at the Layout section below, which names every one of them in tree order.

Node id Tree label Gate Dependency probed Brands Documented by
equipment/controller/machine/brand Controller Brand always all five Controller Brand
equipment/controller/machine/limits Machine Limits (Stroke) always all five Per-Axis Tables
equipment/controller/machine/rapid Rapid Feedrates always all five Per-Axis Tables
equipment/controller/machine/home Home / G28 Reference always all five Per-Axis Tables
equipment/controller/machine/tool-change Tool-Change Position always all five Per-Axis Tables
equipment/controller/machine/parameters Controller Parameters always all five Interface Parameters
equipment/controller/machine/m-codes M-Code Declarations hasNativeTable ControllerParameterTableBase all five M-Code Declarations
equipment/controller/machine/canned-cycle Canned Cycle (Peck) hasCannedCycle ICannedCycleConfig all five Interface Parameters
equipment/controller/machine/block-skip Block Skip / Delete hasBlockSkip IBlockSkipConfig Fanuc, Siemens, Syntec, Mazak Program Reading
equipment/controller/machine/subprograms Subprogram Folders hasSubprogramFolders SubProgramFolderConfig all five Program Reading
equipment/controller/machine/indexing-positions Indexing Position Tables hasIndexingTables SiemensMachineDataTable Siemens Indexing Position Tables
equipment/controller/machine/native Parameters (Native) hasNativeTable ControllerParameterTableBase all five Native Parameters
equipment/controller/program-data/work-coordinates Work Coordinates (G54…) always all five Layout below
equipment/controller/program-data/tool-offsets Tool Offsets, read as Tool Offsets (ISO G43 H) under hasSiemensToolOffsets always; label switched by hasSiemensToolOffsets all five Layout below
equipment/controller/program-data/siemens-tool-offsets Tool Offsets ($TC_DP) hasSiemensToolOffsets SiemensToolOffsetTable Siemens Layout below
equipment/controller/program-data/tool-names Tool Names hasSiemensToolOffsets SiemensToolOffsetTable Siemens Layout below
equipment/controller/program-data/datum-presets Datum Presets (Q339) hasDatums HeidenhainDatumTable Heidenhain Layout below
equipment/controller/program-data/datum-shifts Datum Shifts (D) hasDatums HeidenhainDatumTable Heidenhain Layout below
equipment/controller/program-data/frames Frames (Siemens) hasFrames SiemensFrameTable Siemens Layout below
equipment/controller/program-data/retained-variables Retained Common Variables hasRetainedVariables RetainedCommonVariableTable Fanuc, Syntec, Mazak Layout below
equipment/controller/program-data/r-parameters R Parameters hasRParameters SiemensRParameterTable Siemens Layout below

Three gates never read false on a shipped preset. hasNativeTable is true wherever any brand parameter table resolves, which every preset provides. hasSubprogramFolders is true because every one of the five lists carries SubProgramFolderConfig. hasCannedCycle is true on Fanuc and Mazak through FanucParameterTable, on Syntec through SyntecParameterTable, and on Siemens and Heidenhain through the FallbackConfig those two presets carry. So M-Code Declarations, Parameters (Native), Canned Cycle (Peck) and Subprogram Folders are gated in code and unconditional in practice — they can only go missing on a runner composed by hand or loaded from a file.

Two answers are decided by list order, not only by membership, because the snapshot takes the first match rather than any match: the parameter table behind hasIndexingTables and the ISO coordinate provider behind workCoordinateKind are both first-of-type lookups over the effective list. Each has exactly one candidate in every shipped preset, so order settles nothing there; it becomes load-bearing only on a runner carrying two.

The Flag That Does Double Duty

hasSiemensToolOffsets is the only flag that both adds nodes and rewrites one. It adds Tool Offsets ($TC_DP) and Tool Names, and at the same time switches the ungated tool-offsets leaf from the label key softNc.node.toolOffsets to softNc.node.toolOffsetsIsoH, so the row reads “Tool Offsets (ISO G43 H)” instead of “Tool Offsets”. The node id is untouched by the relabel. The reason is that the two ledgers coexist on Siemens — the (T,D)-keyed $TC_DP table beside the single-index ISO G43 H table — and an unqualified “Tool Offsets” would blur them into one.

The One Brand-Shaped Hole

Block Skip / Delete is the only node that exists on four brands and not the fifth. GenericBlockSkipConfig is the sole implementer of IBlockSkipConfig in the engine, and the Heidenhain preset is the one brand list that does not carry it. Reads of the block-skip endpoint answer absent there, and writes answer unsuccessful with a message naming the missing dependency.

Mazak Resolves the Fanuc Table

The Mazak preset's dependency list differs from the Fanuc one only in the brand token it carries: it proxies the same Fanuc parameter table. Both proxies resolve the same concrete per-case table, so every downstream consequence follows — the same native parameter numbering and prefix, the same fanuc work-coordinate storage model, and the same rows under a Mazak brand badge. It is also the one brand pair whose per-case parameter table survives a switch between them, because the sweep that removes tables the new runner references through no proxy finds this one still referenced.

Flags Computed and Read By Nothing

Five snapshot fields are computed by the web service, typed and parsed by the client, and read by no component. They stay part of what the endpoint returns, so a client other than this one still receives them.

  • hasProject — a null check on the loaded project rather than a dependency probe. It is the only field the early-return snapshot sets when no runner resolves. The panels gate on the runner flag instead, and the shared state watches the project store directly.
  • hasCutterComp — would report a cutter-comp startup type on the Fanuc and Syntec tables.
  • hasToolAxisDirection — would report a tool-axis-direction parameter on the Heidenhain table.
  • hasIterationGuards — would report the iteration guards.
  • nativeIdPrefix# on Fanuc and Mazak, Pr on Syntec, MD on Siemens, MP on Heidenhain.

The screen gets the other four elsewhere. The controller-parameters panel shows its cutter-comp, tool-axis and iteration-guard controls only where its own read returns a non-null value for each, and the native-parameters panel renders the prefix from its own read, which recomputes the same switch server-side.

Two of the snapshot's own doc comments disagree with the code that ships, and the code is what the tree obeys.

  • The subprogram-folder flag is annotated as a Fanuc-family trait. All five presets carry the folder config: the Siemens entry is the L-call lookup root and the Heidenhain entry the CALL PGM lookup root, each with its own comment saying so. The node grows on every brand.
  • The iteration-guard flag is annotated as the Fanuc GOTO / WHILE-DO guards. The probe also matches the Siemens jump guard, and matches neither HeidenhainGotoIterationDependency — which the Heidenhain preset does carry — nor the Fanuc WHILE-DO guard. The flag would therefore misreport Heidenhain even if something read it.

What This Table Cannot Check

The two halves of every brand column live in different repositories and nothing in either build joins them.

  • The flags are computed in the web service. The snapshot builder in Mech/SoftNcRunnerController.cs holds one probe per flag. Changing a probe's type, or reordering the first-of-type lookups it depends on, moves a whole row of this table.
  • What each brand carries is written in the engine. The five brand presets in HiMech/NcParsers/SoftNcRunner.cs are literal dependency lists. Adding or removing one entry changes a brand column here, with no compile error and no failing test to mark it.

The brand columns above are read from those preset lists. Re-deriving them means diffing those two files against each other — the probe list on one side, the five preset lists on the other — and nothing else reports the drift.

Two narrower falsifiers sit under the same join. The interface list on ControllerParameterTableBase is why the machine plane's ungated leaves have a live table behind them on every brand; if a brand table ever implements IBlockSkipConfig, the Heidenhain hole closes silently. And the label strings in the English locale bundle currently match the hard-coded labels in the branch builder one for one; the tree renders the label key, so a drift there changes what the tree reads without changing any id in this table.

Layout

  • Control Tree — the General Setup root
    • Controller Node Row — the branch root; its editor carries the Object-Management ⋮ button, the brand badge and the runner-file caption, or the hourglass no-runner block
      • Machine / Controller Group Stem — intro line plus a clickable list of its children
        • Controller Brand Node Row
        • Machine Limits (Stroke) Node Row
        • Rapid Feedrates Node Row
        • Home / G28 Reference Node Row
        • Tool-Change Position Node Row
        • Controller Parameters Node Row
        • M-Code Declarations Node Row — gated
        • Canned Cycle (Peck) Node Row — gated
        • Block Skip / Delete Node Row — gated; absent on Heidenhain
        • Subprogram Folders Node Row — gated
        • Indexing Position Tables Node Row — gated; Siemens only
        • Parameters (Native) Node Row — gated
      • Program Data Group Stem — intro line plus a clickable list of its children
        • Work Coordinates (G54…) Node Row
        • Tool Offsets Node Row — reads Tool Offsets (ISO G43 H) where the Siemens $TC_DP table resolves
        • Tool Offsets ($TC_DP) Node Row — gated; Siemens only
        • Tool Names Node Row — gated; Siemens only
        • Datum Presets (Q339) Node Row — gated; Heidenhain only
        • Datum Shifts (D) Node Row — gated; Heidenhain only
        • Frames (Siemens) Node Row — gated; Siemens only
        • Retained Common Variables Node Row — gated; absent on Siemens and Heidenhain
        • R Parameters Node Row — gated; Siemens only

The rows marked gated are the ones this page's table keys; the rest are the fixed core. Every row is a plain label with no icon and no checkbox, since the tick column belongs to the mission branch alone.

Source Code Path

See HiNC App Anatomy for git repository links.

Web Application

HiNC-2025-webservice (Quasar CLI SPA):

  • wwwroot-src/src/components/controlTree/softNcItemTypes.ts — the branch builder: it mints every node id in the table above, holds each leaf's gate, carries the tool-offsets relabel, and returns an empty child list both when no runner resolves and when the snapshot request throws.
  • wwwroot-src/src/components/controlTree/useControlTreeHost.ts — declares the equipment/controller root that prefixes every id in the table, and rebuilds the branch when a panel reports a structural change scoped to it.
  • wwwroot-src/src/api/softNcRunner.ts — the snapshot type, its empty value and its parser; the five fields with no reader are declared, defaulted and parsed here.
  • wwwroot-src/src/composables/useSoftNcRunner.ts — the shared snapshot the leaf panels gate on, the project watch that empties it, and the brand switch and Object-Management install that re-read it.
  • wwwroot-src/src/components/controlTree/SoftNcRunnerRootPanel.vue — the branch root's editor and the no-runner block the branch collapses to.
  • wwwroot-src/src/components/controlTree/SoftNcEmptyState.vue — the shared no-runner body every leaf panel falls back to.
  • wwwroot-src/src/components/controlTree/SoftNcWorkCoordinatesPanel.vue — the one consumer of the snapshot's work-coordinate kind.
  • wwwroot-src/src/components/controlTree/SoftNcControllerParamsPanel.vue — gates the cutter-comp, tool-axis and iteration-guard controls on its own read rather than on the snapshot flags.
  • wwwroot-src/src/components/controlTree/SoftNcNativeParamsPanel.vue — renders the native id prefix from its own read.
  • wwwroot-src/src/i18n/en/softNc.ts — the node label strings the tree renders, the two group intros, and the empty-state bodies.
  • Mech/SoftNcRunnerController.cs — builds the snapshot: one probe per flag over the proxy-resolved dependency list, the early-return form used when no runner resolves, and the brand switch that swaps the whole runner and sweeps the orphaned per-case tables.

HiAPI Engine

  • HiMech/NcParsers/SoftNcRunner.cs — the five brand presets as literal dependency lists, and the proxy resolution every flag probe reads through.
  • HiMech/NcParsers/ControllerPresetWriter.cs — the brand token list and the factory that turns one token into a preset runner, for the shipped preset files.
  • HiMech/NcParsers/Dependencys/ControllerParameterTableBase.cs — the machine-config interfaces every brand table inherits, which is why the machine plane's ungated leaves have data on all five brands.
  • HiMech/NcParsers/Dependencys/CncBrandDependency.cs — the brand marker the snapshot reports, and the five brand tokens.
  • HiMech/NcParsers/Dependencys/Generic/GenericBlockSkipConfig.cs — the sole implementer of the block-skip interface, and therefore the whole reason one node is missing on one brand.
  • HiMech/NcParsers/Dependencys/Generic/FallbackConfig.cs — the peck-retraction provider that makes the canned-cycle gate true on the two brands whose own table has none.
  • HiMech/NcParsers/Dependencys/Generic/SubProgramFolderConfig.cs — the folder config every preset carries, against the snapshot comment that calls it a Fanuc-family trait.
  • HiMech/NcParsers/Dependencys/Fanuc/FanucParameterTable.cs, HiMech/NcParsers/Dependencys/Syntec/SyntecParameterTable.cs, HiMech/NcParsers/Dependencys/Siemens/SiemensMachineDataTable.cs, HiMech/NcParsers/Dependencys/Heidenhain/HeidenhainParameterTable.cs — the four brand tables and the extra interfaces that decide the canned-cycle, indexing and work-coordinate answers.
  • HiMech/NcParsers/Dependencys/Fanuc/FanucParameterTableProxy.cs — the per-case resolution the Fanuc and Mazak presets share, which is why those two survive each other's brand switch.

See Also

  • Controller Branch — the branch this table indexes, its two planes and the runner behind them
  • Editing Contract — the rules every leaf panel in this table obeys when it reads, commits and rolls back
  • Machine and Controller Plane — the machine plane, whose leaves make up most of this table
  • Program Data Plane — the program-data plane, whose per-case leaves are the rest of this table's rows
  • Controller Brand — the control that changes which rows of this table exist, and what it resets on the way
  • Per-Axis Tables — the four ungated per-axis leaves: stroke limits, rapid rates, home reference and the tool-change position
  • Interface Parameters — the interface parameter form and the canned-cycle leaf, two of the rows above
  • M-Code Declarations — the M-code declaration leaf, gated by the native-table flag
  • Program Reading — the block-skip and subprogram leaves, and the one gate that switches a node off for exactly one brand
  • Indexing Position Tables — the one row that appears on a single brand only
  • Native Parameters — the native parameter form behind the id prefix this page reports as unread
  • Hidden Controller Branches — the other kind of withheld node: the two equipment branches a device preference hides, which a link can reveal where none of these can