Advance AXIS-style Three.js simulation UI

This commit is contained in:
2026-06-17 09:59:22 +08:00
parent d6a623308b
commit 656cddf73a
24 changed files with 84658 additions and 75 deletions

View File

@@ -127,7 +127,9 @@ Current implemented regions:
### Phase 2: Program Execution Workflow
Status: active; custom text/file execution and editor-text execution are implemented.
Status: active; custom text/file/editor execution and OPFS program persistence
are implemented. MDI scratch text can now be loaded into the AXIS G-code pane
or executed through the same LinuxCNC-backed WASM path.
Upgrade the G-code pane and execution controls:
@@ -135,12 +137,26 @@ Upgrade the G-code pane and execution controls:
- run through LinuxCNC WASM;
- reset/step/play/pause/finish playback from toolbar and keyboard-accessible
buttons;
- reload the current built-in, editor, MDI, file, or OPFS-backed program
through the same LinuxCNC-backed execution path;
- highlight active G-code line and current motion row;
- show run status, source program, motion count, and current frame.
- load operator-provided G-code text through `runProgramText()`;
- stage operator-provided G-code text without executing through
`loadProgramText()`;
- load browser `File` objects through `loadProgramFile()`;
- edit visible G-code in the AXIS shell and run it through
`runEditorProgramText()`;
- load or run the MDI panel scratch program through LinuxCNC-backed text
execution;
- record successful LinuxCNC-backed MDI executions in an AXIS-style MDI
history list, with click-to-restore and clear controls;
- record successful LinuxCNC-backed built-in, text, editor, file, OPFS, MDI,
and session-backed executions in an AXIS-style recent program list, with
click-to-stage and clear controls;
- save the current editor G-code through OPFS with `saveProgramToOpfs()`;
- load an OPFS G-code program through `loadProgramFromOpfs()` and execute it
through LinuxCNC WASM;
Built-in test programs must live in:
@@ -158,9 +174,23 @@ Validation:
- browser smoke runs at least one linear program, one arc program, and one
canned-cycle program through toolbar actions;
- active-line, toolhead, executed path, and status bar update together.
- browser smoke saves an edited G-code program to OPFS, changes the editor
text, reloads the OPFS program, and verifies the reloaded text executes
through LinuxCNC WASM.
- browser smoke verifies `loadProgramText()` stages text without executing and
that MDI text execution produces LinuxCNC canonical output.
- browser smoke verifies successful MDI execution records history, restores
history text into the MDI pane, and clears history without changing
LinuxCNC-produced motion state.
- browser smoke verifies successful LinuxCNC-backed executions populate recent
programs, recent entries stage text back into the editor without implicit
execution, and the recent list can be cleared.
### Phase 3: DRO and Modal Display
Status: partially implemented; actual axis readout and LinuxCNC `UPDATE_TAG`
modal display are implemented.
Add a DRO panel modeled after AXIS:
- relative actual X/Y/Z/A/B/C;
@@ -174,6 +204,19 @@ Add a DRO panel modeled after AXIS:
Fallback values must be marked as unavailable rather than invented.
Current implemented behavior:
- relative actual X/Y/Z/A/B/C values are rendered from LinuxCNC canonical
motion frames;
- distance-to-go, G54, G92, tool-length offset, and velocity fields render as
explicit `n/a` until LinuxCNC-produced or validated runtime fields are
available;
- modal rows are derived from LinuxCNC `canon_event=UPDATE_TAG` output;
- spindle, coolant, tool, and override rows are derived from LinuxCNC canonical
events when present and otherwise remain explicit `n/a`;
- browser API exposes `getDroState()`, `getModalState()`, and
`getMachineStatusState()`.
Validation:
- Node and browser tests verify no unavailable field is silently fabricated;
@@ -182,6 +225,10 @@ Validation:
### Phase 4: Preview Upgrade
Status: implemented for the current browser simulation scope; AXIS-like
Three.js viewport controls are available with SVG fallback state for
compatibility tests.
Improve the preview from a simple SVG polyline into an AXIS-like viewport:
- dark viewport theme;
@@ -189,17 +236,85 @@ Improve the preview from a simple SVG polyline into an AXIS-like viewport:
- full path versus executed path;
- active tool marker;
- zoom fit / pan / reset view;
- optional orthographic 3D using Three.js only if it stays stable in browser
smoke and canvas-pixel checks.
- orthographic 3D using Three.js `^0.183.2`, kept stable in browser smoke.
Current implemented behavior:
- dark viewport theme;
- full path versus executed path;
- active tool marker;
- motion-derived extents rectangle, origin axes/marker, and preview legend;
- Three.js canvas renders the primary toolpath preview from LinuxCNC canonical
motion, while SVG remains a hidden fallback/state surface for compatibility;
- runtime imports the local `runtime/ui/simulation/vendor/three/three.module.js`
build, with `runtime/ui/simulation/package.json` documenting the requested
`three` dependency range;
- Three.js preview includes dynamic grid lines and X/Y/Z axis labels;
- Three.js preview renders coordinate axes, motion-type segment metadata,
active toolhead coordinates, renderer revision, and canvas size into the
preview state API for smoke validation;
- Three.js preview samples `ARC_FEED` display curves from LinuxCNC-produced
canonical center, rotation, active-plane, and endpoint fields, while keeping
SVG fallback state endpoint-compatible for existing browser tests;
- Three.js preview now renders AXIS-style tool geometry with a visible tool
body, optional LinuxCNC-produced tool-length-offset indicator, current tool
label when available, and a viewport scale bar surfaced through
`getPreviewState()`;
- Three.js preview renders a compact X/Y/Z orientation triad in the viewport
and surfaces its structured display state through `getPreviewState()`;
- AXIS-style preview HUD overlays the Three.js stage with view/zoom/pan,
toolhead XYZ, machine envelope, grid step, and renderer/path counts derived
from LinuxCNC canonical motion and Three.js render state;
- AXIS-style bottom status bar is structured into E-stop, tool, program
source, active line, position/run mode, and preview state fields, with
`getAxisStatusbarState()` exposing the same browser state for smoke tests;
- fit, zoom in, zoom out, pan, Top/Front/Side/Iso view modes, and reset view
controls;
- AXIS-style preview layer toggles can show/hide rapid traverse, feed, arc,
tool, envelope, and scale-bar display layers without changing the
LinuxCNC-produced motion state;
- Three.js canvas exposes an AXIS-style cursor crosshair and live X/Y preview
coordinate readout derived from the current rendered viewBox; this is display
state only and does not change machine or G-code state;
- Three.js canvas supports wheel zoom, pointer-drag pan, and double-click fit;
- browser resize refreshes the Three.js viewport while preserving playback,
zoom, pan, and view-mode state;
- dedicated desktop/mobile screenshot smoke validates the Three.js viewport,
preview legend, diagnostics, compact tool table, status history, and
G-code/Machine State layout in real browser viewports;
- screenshot smoke captures Preview, DRO, and MDI entry states through stable
URL view parameters;
- screenshot smoke can persist desktop/mobile PNGs and screenshot metadata JSON
when `AXIS_SCREENSHOT_ARTIFACT_DIR` is provided; full
`exportDiagnosticsArtifact()` JSON is available behind
`AXIS_SCREENSHOT_FULL_DIAGNOSTICS=1` for CI jobs that opt into CDP capture;
- release-readiness artifact generation summarizes persisted AXIS screenshot
diagnostics when `AXIS_SCREENSHOT_ARTIFACT_DIR` points at the screenshot
artifact directory, without changing the fixed release gate count;
- browser API exposes `fitPreview()`, `zoomPreview(factor)`,
`panPreview(dx, dy)`, `setPreviewViewMode(mode)`, `getPreviewState()`, and
`resetPreview()`;
- browser API exposes `getPreviewLayerState()` and
`setPreviewLayer(name, enabled)` for AXIS-style display layer controls.
- browser API exposes `getPreviewCursorState()` for the current preview
cursor/crosshair readout.
Validation:
- browser smoke verifies nonblank preview, executed path growth, toolhead
movement, and stable viewport controls;
- mobile and desktop screenshots must not show overlapping UI.
movement, Three.js canvas pixels, sampled canonical arc rendering, structured
tool geometry, scale bar state, AXIS preview layer toggles, and stable
viewport controls;
- browser smoke verifies pointer-driven preview cursor/crosshair coordinate
readout and pointer-leave clearing;
- mobile and desktop screenshot smoke verifies nonblank Three.js rendering,
visible compact panels, and non-overlapping AXIS shell sections.
### Phase 5: Machine/Session Integration
Status: partially implemented; OPFS machine/session readiness, session
staging, and loaded-session program execution are visible in the AXIS shell.
Connect the AXIS-style shell to the existing OPFS/session workflow:
- load machine session from OPFS;
@@ -208,6 +323,75 @@ Connect the AXIS-style shell to the existing OPFS/session workflow:
- stage files into WASM before execution;
- block run controls with explicit reasons when session readiness is missing.
Current implemented behavior:
- Manual Control panel includes machine id, session id, and G-code filename
inputs;
- Manual Control also renders explicit blocked state for real jog/spindle and
coolant controls that are not backed by the browser runtime;
- `Check Session` calls existing `readMachineSessionReadiness()`;
- readiness phase, missing checks, INI path, and G-code path render in the
AXIS shell;
- browser API exposes `getMachineReadiness()` and
`checkMachineSessionReadiness(options)`;
- AXIS panels show LinuxCNC canonical machine status for spindle, coolant,
tool, and override fields when available;
- `Load Session` calls existing LinuxCNC-backed `loadMachineSessionFromOpfs()`
after readiness passes;
- staged INI, parameter, and tool-table WASM paths render in the AXIS shell;
- browser API exposes `getMachineSessionLoadState()` and
`loadReadyMachineSession(options)`;
- staged LinuxCNC tool-table load results are summarized in Machine State with
OPFS/WASM paths, tool count, and the first loaded tool row;
- staged LinuxCNC tool-table rows also render in a compact AXIS-style table
with T/P/Z/D/comment columns;
- editor/custom/built-in program execution uses `runProgramWithIni()` with the
loaded session INI path when a session has been staged;
- toolbar and status bar expose the current run mode as standalone or
session-backed with the active INI path;
- Manual Control exposes a `Use Session` toggle so a staged machine session can
be enabled or bypassed for subsequent runs;
- Machine State includes a compact run summary for execution mode, session INI,
OPFS program path, readiness phase, and session load phase;
- browser API exposes `getRunMode()`, `setUseLoadedSession(value)`, and
`getRunSummary()`;
- toolbar and Machine State expose run-control ready/fallback state so operators
can see whether a requested session-backed run will actually use a loaded INI
or fall back to standalone LinuxCNC WASM;
- AXIS-style keyboard bindings route F3/F5/F6/F7, run, playback stepping,
finish/reset, and preview fit through the same browser API as toolbar
controls;
- Machine State includes a compact diagnostics panel for the last LinuxCNC
canonical event, last surfaced error, readiness/load phase, and most recent
shortcut action;
- Machine State includes a compact status-history ring for recent run,
readiness, session, OPFS, shortcut, and error events;
- Machine State includes a compact limits/home panel that explicitly reports
`n/a` until LinuxCNC-produced runtime fields are available;
- diagnostics can be exported as a structured browser artifact containing run
summary, preview state, status history, tool-table summary, and limits/home
state;
- browser API exposes `getDiagnosticsState()`, `getStatusHistory()`,
`getToolTableSummary()`, `getLimitsHomeState()`,
`exportDiagnosticsArtifact()`, and `handleAxisShortcut(event)`;
- browser smoke covers run and play/pause keyboard shortcuts after waiting for
their async UI/API side effects;
- browser smoke verifies blocked readiness before OPFS files exist, then writes
machine files, G-code, and a session snapshot through existing OPFS helpers
and verifies readiness becomes `ready`;
- browser smoke verifies a ready machine session stages INI, parameter, and
tool-table files into the WASM filesystem through LinuxCNC-backed SDKs.
- browser smoke verifies editor G-code execution uses the loaded session INI
path and still renders LinuxCNC canonical output/playback state.
- browser smoke verifies OPFS-loaded G-code also uses the loaded session INI
path and that run-mode UI/API state switches to session-backed.
- browser smoke verifies disabling `Use Session` returns editor execution to
standalone mode while leaving the staged session available.
- browser smoke verifies run summary API/DOM values for standalone,
session-backed, and OPFS program execution.
- browser smoke verifies AXIS URL view parameters can open Manual/MDI and
Preview/DRO panels without bypassing the normal tab controls.
Validation:
- OPFS/session browser smoke covers load -> run -> playback;
@@ -226,22 +410,56 @@ Required methods:
- `getState()`;
- `getPrograms()`;
- `runProgramById(programId)`;
- `reloadCurrentProgram()`;
- `getPlaybackFrame()`;
- `isPlaybackRunning()`;
- `resetPlayback()`;
- `stepPlayback(delta)`;
- `play()`;
- `pause()`;
- `finishPlayback()`;
- `runProgramText(programText, metadata)`;
- `loadProgramText(text, metadata)`;
- `loadProgramFile(file)`;
- `getProgramText()`;
- `setProgramText(text, metadata)`;
- `runEditorProgramText()`;
- future: `loadProgramText(text, metadata)`;
- future: `loadMachineSessionFromOpfs(options)`;
- future: `getMachineReadiness()`;
- future: `getDroState()`;
- future: `getModalState()`.
- `runMdiProgramText(text)`;
- `getMdiHistory()`;
- `clearMdiHistory()`;
- `getRecentPrograms()`;
- `clearRecentPrograms()`;
- `getOpfsProgramState()`;
- `saveProgramToOpfs(filename)`;
- `loadProgramFromOpfs(filename)`;
- `getDroState()`;
- `getModalState()`;
- `getMachineStatusState()`;
- `fitPreview()`;
- `zoomPreview(factor)`;
- `panPreview(dx, dy)`;
- `setPreviewViewMode(mode)`;
- `getPreviewState()`;
- `getPreviewLayerState()`;
- `setPreviewLayer(name, enabled)`;
- `getPreviewCursorState()`;
- `resetPreview()`;
- `getMachineReadiness()`;
- `checkMachineSessionReadiness(options)`;
- `getMachineSessionLoadState()`;
- `loadReadyMachineSession(options)`;
- `getRunMode()`;
- `getRunControlState()`;
- `getAxisStatusbarState()`;
- `setUseLoadedSession(value)`;
- `getRunSummary()`;
- `getDiagnosticsState()`;
- `getStatusHistory()`;
- `getToolTableSummary()`;
- `getLimitsHomeState()`;
- `exportDiagnosticsArtifact()`;
- `handleAxisShortcut(event)`;
- `applyAxisViewFromUrl(search)`;
API additions must be covered by Node or browser smoke before being relied on
by UI controls.
@@ -267,6 +485,7 @@ Every implementation batch must keep these passing:
```bash
wasm-port/tests/ui/node/verify_real_simulation_programs.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_axis_screenshot_browser.sh
wasm-port/tests/docs/node/verify_real_browser_simulation_priority_docs.sh
wasm-port/tests/host/verify_project_release_gate.sh
```
@@ -285,16 +504,14 @@ When AXIS-style shell work starts, add or extend browser assertions for:
## Immediate Next Batch
Implement Phase 1 without removing current functionality:
Continue AXIS by deepening operator workflow coverage without adding
browser-side CNC semantics:
1. Restructure `runtime/ui/simulation/index.html` into the AXIS-style shell.
2. Preserve existing program selector and playback API.
3. Move current playback buttons into the toolbar.
4. Add Manual Control and MDI tabs with readiness/blocked state.
5. Add Preview and DRO tabs with current preview and readout.
6. Add bottom status bar.
7. Extend `real_simulation_page_smoke.html` to verify the new shell regions.
The first implementation batch should be UI structure plus smoke coverage; it
must not invent machine-control behavior that is not backed by LinuxCNC/WASM or
existing session/readiness APIs.
1. Add limits/home real data mapping only when LinuxCNC-produced runtime fields
are available.
2. Keep unavailable DRO and machine fields explicit `n/a` until
LinuxCNC-produced runtime data exists.
3. Promote AXIS screenshot artifact summaries into CI retention once the
release job has a stable artifact directory.
4. Harden the optional CDP diagnostics capture path before making full
`exportDiagnosticsArtifact()` retention mandatory in CI.