@chestnutlabs/gcode-preview-core 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # @chestnutlabs/gcode-preview-core
2
2
 
3
3
  The **framework-neutral preview controller** for the Chestnut Labs G-code Preview stack
4
- (design: DD-007). This is the single engine under the Vue, React, and Svelte adapters — parse
4
+ (design: DD-007). This is the single engine under the Vue, React, Svelte, and Web Component
5
+ (`@chestnutlabs/gcode-preview-element`) adapters — parse
5
6
  session + renderer + progress mapper glued into one lifecycle with an **immutable-snapshot state
6
7
  model** (`getState()` returns a new identity per mutation; `onStateChange` notifies), which every
7
8
  framework's reactivity can bridge cheaply.
@@ -20,7 +21,7 @@ preview.dispose();
20
21
 
21
22
  Building an adapter for another framework? The **portable behavioral suite** is exported from
22
23
  `@chestnutlabs/gcode-preview-core/testing` — `runBehavioralSuite(...)` is the same parity
23
- contract the Vue/React/Svelte adapters pass in CI, and it is the anti-drift firewall for any new
24
- integration.
24
+ contract the Vue, React, Svelte, and Web Component adapters pass in CI, and it is the anti-drift
25
+ firewall for any new integration.
25
26
 
26
27
  Part of [Chestnut Labs G-code Preview](../../README.md) · MIT
@@ -10,7 +10,7 @@
10
10
  * only (numbers/strings): IR/typed arrays NEVER enter the state model.
11
11
  */
12
12
  import { GcodeParseSession, type ParseProgress, type ParseResult, type SessionOptions, type WireParseOptions } from '@chestnutlabs/gcode-parser';
13
- import type { BuildVolumeDef, CameraMode, CameraState, CameraView, CaptureOptions, ColorMode, GLRendererLike, ProgressPresentationMode, ProgressivePreview, QualityMode, QualityPolicy, RenderTargetCanvas, Theme, TubeOptions } from '@chestnutlabs/gcode-renderer-three';
13
+ import type { BuildVolumeDef, CameraMode, CameraState, CameraView, CaptureOptions, ColorMode, GLRendererLike, ProgressPresentationMode, ProgressivePreview, QualityMode, QualityPolicy, RenderStats, RenderTargetCanvas, Theme, TubeOptions } from '@chestnutlabs/gcode-renderer-three';
14
14
  import type { MoveKindToggle, PreviewRenderer, PreviewRendererEvent, RendererMode } from './renderer-interface.js';
15
15
  import { type Confidence, type DialectMetadata, type FeatureRoleValue, type MachineGeometry, type MappedProgress, type ProgressObservation, type Warning } from '@chestnutlabs/toolpath-core';
16
16
  /** Session/renderer events, re-emitted, plus the controller's own lifecycle events. */
@@ -141,11 +141,25 @@ export interface GcodePreviewState {
141
141
  */
142
142
  totalTimeMs: number | null;
143
143
  timeEstimateSource: 'slicer' | 'kinematic' | null;
144
+ /**
145
+ * Which color modes the current file can actually support (DD-031 G6) — the capability-aware list a
146
+ * consumer UI should offer, so it can gray out (and explain) the rest rather than fabricating colors.
147
+ * Empty before a parse / before the renderer is ready. `single`/`tool`/`moveKind` are always present.
148
+ */
149
+ availableColorModes: ColorModeName[];
150
+ /** True when the current file carries retraction/deretraction events the markers can show (DD-031 G6). */
151
+ hasRetractions: boolean;
152
+ /** True when the current file carries M600 color-change boundaries (DD-031 G6). */
153
+ hasColorChanges: boolean;
144
154
  error: {
145
155
  code: string;
146
156
  message: string;
147
157
  } | null;
148
158
  }
159
+ /** The discriminant of {@link ColorMode} — the color-mode identifiers, for capability lists. */
160
+ export type ColorModeName = ColorMode['mode'];
161
+ /** Every color mode the engine can render, in menu order — the domain `availableColorModes` filters. */
162
+ export declare const ALL_COLOR_MODES: readonly ColorModeName[];
149
163
  export interface GcodePreviewControls {
150
164
  setLayerRange(startLayer: number, endLayer: number): void;
151
165
  setScrubPosition(segIndex: number | null): void;
@@ -196,6 +210,25 @@ export interface GcodePreviewControls {
196
210
  * is ready or on the 2D renderer (which cannot render-to-target). The caller owns the `Blob`.
197
211
  */
198
212
  capture(opts?: CaptureOptions): Promise<Blob>;
213
+ /**
214
+ * Render diagnostics snapshot (DD-027, DD-031 G1) — backend, WebGL version, GPU (hardware/software),
215
+ * geometry mode, build parallelism + worker count, draw calls, tube-byte budget, and parse/build/
216
+ * first-frame timings — or null before the first render and on the 2D renderer (which produces none).
217
+ * Reachable through the public surface so a diagnostics panel needs no `raw.renderer()`.
218
+ */
219
+ getRenderStats(): RenderStats | null;
220
+ /**
221
+ * Pick the IR segment under a pointer in normalized device coords ([-1, 1], y up), or null (DD-031 G2,
222
+ * #184). Powers source-mapping/inspection UI. The 3D renderer raycasts the toolpath; the 2D renderer
223
+ * returns null (no picking yet). `threshold` widens the hit test (world units).
224
+ */
225
+ pickSegment(ndcX: number, ndcY: number, threshold?: number): number | null;
226
+ /**
227
+ * Capability gate for a color mode against the current file (DD-031 G6) — mirrors
228
+ * {@link GcodePreviewState.availableColorModes} for a one-off query. `false` when the file lacks the
229
+ * channel the mode reads; always `true` before a parse (optimistic, like `setColorMode`).
230
+ */
231
+ isColorModeAvailable(mode: ColorModeName): boolean;
199
232
  }
200
233
  export interface PreviewController {
201
234
  /** Bind/rebind the renderer to a canvas (null unbinds). Rebinding disposes safely. */
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EACL,iBAAiB,EAGjB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,SAAS,EACT,cAAc,EACd,wBAAwB,EACxB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,WAAW,EACZ,MAAM,oCAAoC,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACnH,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EAEnB,KAAK,mBAAmB,EAGxB,KAAK,OAAO,EACb,MAAM,6BAA6B,CAAC;AAGrC,uFAAuF;AACvF,MAAM,MAAM,YAAY,GACpB,oBAAoB,GACpB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GACnD;IACE,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,sGAAsG;IACtG,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACzC,oGAAoG;IACpG,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,eAAe,GAAG,SAAS,CAAC;CACvC,GACD;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACtD;IACE;uEACmE;IACnE,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,eAAe,CAAC;CAC1B,CAAC;AAEN,MAAM,WAAW,wBAAwB;IACvC,yFAAyF;IACzF,YAAY,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE;QACT;;;;WAIG;QACH,IAAI,CAAC,EAAE,YAAY,CAAC;QACpB,WAAW,CAAC,EAAE,cAAc,CAAC;QAC7B,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;QAC/B;;;;WAIG;QACH,WAAW,CAAC,EAAE,aAAa,CAAC;QAC5B;;;;;WAKG;QACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;QACxC,2EAA2E;QAC3E,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,4FAA4F;QAC5F,YAAY,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;QAChC,+FAA+F;QAC/F,kBAAkB,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;QACpC,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,IAAI,CAAC,EAAE,WAAW,CAAC;QACnB,4DAA4D;QAC5D,KAAK,CAAC,EAAE,KAAK,CAAC;QACd,2FAA2F;QAC3F,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,mDAAmD;QACnD,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB;iGACyF;QACzF,mBAAmB,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;QAC9C,sGAAsG;QACtG,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,0FAA0F;QAC1F,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,cAAc,CAAC;QAChE,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;QACzC,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,yDAAyD;IACzD,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED,6FAA6F;AAC7F,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,SAAS,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAE/E,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,wFAAwF;IACxF,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACzC,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,IAAI,CAAC;IACT,QAAQ,EAAE,eAAe,GAAG,SAAS,CAAC;IACtC,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,wBAAwB,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kBAAkB,EAAE,QAAQ,GAAG,WAAW,GAAG,IAAI,CAAC;IAClD,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAChD;;;OAGG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC,cAAc,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7D;;;;OAIG;IACH,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACtE,gFAAgF;IAChF,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3C,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IACvC,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC;IAChD,qFAAqF;IACrF,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1C,gHAAgH;IAChH,qBAAqB,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACtD,kDAAkD;IAClD,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACtC;wFACoF;IACpF,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC;uDACmD;IACnD,cAAc,IAAI,WAAW,GAAG,IAAI,CAAC;IACrC,gGAAgG;IAChG,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IACzC,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,0FAA0F;IAC1F,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,GAAG,IAAI,CAAC;IAC5D,0FAA0F;IAC1F,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3C,iGAAiG;IACjG,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAC;IAC9C,gGAAgG;IAChG,qBAAqB,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;IAClD,KAAK,IAAI,IAAI,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,iBAAiB;IAChC,sFAAsF;IACtF,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAAC;IACnD,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9F,MAAM,IAAI,IAAI,CAAC;IACf,yFAAyF;IACzF,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,cAAc,GAAG,IAAI,CAAC;IACjE,wFAAwF;IACxF,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IACnD,aAAa,IAAI,IAAI,CAAC;IACtB,iFAAiF;IACjF,QAAQ,IAAI,iBAAiB,CAAC;IAC9B,oEAAoE;IACpE,aAAa,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,QAAQ,EAAE,oBAAoB,CAAC;IAC/B;;;;OAIG;IACH,GAAG,EAAE;QAAE,OAAO,EAAE,iBAAiB,CAAC;QAAC,QAAQ,EAAE,MAAM,eAAe,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5E,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACnD,OAAO,IAAI,IAAI,CAAC;CACjB;AA8BD,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,wBAA6B,GAAG,iBAAiB,CAwWjG"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,19 @@ import { CaptureUnsupportedError } from '@chestnutlabs/gcode-renderer-three';
14
14
  import { LayerView2DRenderer } from './renderer-2d-adapter.js';
15
15
  import { createProgressMapper, computeToolpathTime, segmentsCompletedAtTime } from '@chestnutlabs/toolpath-core';
16
16
  import { resolveColorMode } from './color-resolve.js';
17
+ /** Every color mode the engine can render, in menu order — the domain `availableColorModes` filters. */
18
+ export const ALL_COLOR_MODES = [
19
+ 'single',
20
+ 'tool',
21
+ 'feature',
22
+ 'colorChange',
23
+ 'filament',
24
+ 'feedrate',
25
+ 'object',
26
+ 'layerHeight',
27
+ 'power',
28
+ 'moveKind'
29
+ ];
17
30
  const INITIAL_STATE = {
18
31
  parsing: false,
19
32
  parseProgress: null,
@@ -26,6 +39,9 @@ const INITIAL_STATE = {
26
39
  disclosure: '',
27
40
  totalTimeMs: null,
28
41
  timeEstimateSource: null,
42
+ availableColorModes: [],
43
+ hasRetractions: false,
44
+ hasColorChanges: false,
29
45
  error: null
30
46
  };
31
47
  function toBytes(input) {
@@ -143,8 +159,12 @@ export function createPreviewController(options = {}) {
143
159
  for (const op of pendingOps)
144
160
  op(r);
145
161
  pendingOps.length = 0;
146
- if (lastIR !== null)
162
+ if (lastIR !== null) {
147
163
  mutate({ layerCount: r.layerCount, segmentCount: r.segmentCount });
164
+ // The renderer bound after a parse already completed (on-demand 3D load) — refresh capability
165
+ // state so a UI that mounted pre-render still gets accurate available-mode data (DD-031 G6).
166
+ refreshCapabilityState();
167
+ }
148
168
  }
149
169
  function bindCanvas(canvas) {
150
170
  if (disposed)
@@ -287,6 +307,10 @@ export function createPreviewController(options = {}) {
287
307
  warnings: result.ir.header.warnings,
288
308
  metadata: result.metadata
289
309
  });
310
+ // DD-031 G6: populate the capability-aware state (available color modes, retraction/color-change
311
+ // presence) now the renderer holds this file's IR. No-op if the (async 3D) renderer isn't ready
312
+ // yet — applyRendererReady refreshes it when the renderer binds.
313
+ refreshCapabilityState();
290
314
  return { ok: true, result };
291
315
  }
292
316
  catch (err) {
@@ -306,6 +330,19 @@ export function createPreviewController(options = {}) {
306
330
  activeParse = null;
307
331
  }
308
332
  }
333
+ // DD-031 G6: refresh the capability-aware state a consumer UI reads to offer/explain controls
334
+ // (available color modes, retraction/color-change presence). Derived from the renderer, which owns
335
+ // the honest IR capability gates. No-op until the renderer is bound and has the IR.
336
+ function refreshCapabilityState() {
337
+ if (renderer === null)
338
+ return;
339
+ const r = renderer;
340
+ mutate({
341
+ availableColorModes: ALL_COLOR_MODES.filter((m) => r.isColorModeAvailable(m)),
342
+ hasRetractions: r.hasRetractions,
343
+ hasColorChanges: r.hasColorChanges
344
+ });
345
+ }
309
346
  const controls = {
310
347
  // Controls queue when the (async) renderer isn't ready yet, then replay in order on bind.
311
348
  setLayerRange: (a, b) => withRenderer((r) => r.setLayerRange(a, b)),
@@ -340,6 +377,11 @@ export function createPreviewController(options = {}) {
340
377
  capture: (opts) => renderer !== null && typeof renderer.capture === 'function'
341
378
  ? renderer.capture(opts)
342
379
  : Promise.reject(new CaptureUnsupportedError('capture unavailable: renderer not ready or unsupported')),
380
+ // Value-returning queries can't queue: before the renderer is ready they answer honestly
381
+ // (null diagnostics/pick; optimistic color-mode availability, re-checkable after parse-complete).
382
+ getRenderStats: () => (renderer !== null ? renderer.getRenderStats() : null),
383
+ pickSegment: (ndcX, ndcY, threshold) => (renderer !== null ? renderer.pickSegment(ndcX, ndcY, threshold) : null),
384
+ isColorModeAvailable: (mode) => (renderer !== null ? renderer.isColorModeAvailable(mode) : true),
343
385
  setCameraState: (s) => withRenderer((r) => r.setCameraState(s)),
344
386
  setTheme: (t) => withRenderer((r) => r.setTheme(t)),
345
387
  setBuildVolume: (def) => {
@@ -12,7 +12,7 @@
12
12
  * are documented no-ops. Nothing is ever drawn that the IR does not contain.
13
13
  */
14
14
  import { type ColorMode, type TravelStyle } from '@chestnutlabs/gcode-renderer-2d';
15
- import type { BuildVolumeDef, CameraMode, CameraState, CameraView, ProgressivePreview, QualityMode, QualityPolicy, Theme } from '@chestnutlabs/gcode-renderer-three';
15
+ import type { BuildVolumeDef, CameraMode, CameraState, CameraView, ProgressivePreview, QualityMode, QualityPolicy, RenderStats, Theme } from '@chestnutlabs/gcode-renderer-three';
16
16
  import type { MachineGeometry, MappedProgress, ToolpathIR } from '@chestnutlabs/toolpath-core';
17
17
  import type { MoveKindToggle, PreviewRenderer, PreviewRendererEvent } from './renderer-interface.js';
18
18
  export interface LayerView2DRendererOptions {
@@ -51,7 +51,17 @@ export declare class LayerView2DRenderer implements PreviewRenderer {
51
51
  setShowRetractions(visible: boolean): void;
52
52
  setColorMode(mode: ColorMode): boolean;
53
53
  /** Capability gate mirroring the 3D renderer (DD-001 honesty): unknown channel → unavailable. */
54
- private isColorModeAvailable;
54
+ isColorModeAvailable(mode: ColorMode['mode']): boolean;
55
+ /** Retraction markers are a 3D-only overlay — the flat 2D layer view never shows them (DD-031 G6). */
56
+ get hasRetractions(): boolean;
57
+ /** True when the current IR carries M600 color-change boundaries (DD-031 G6). */
58
+ get hasColorChanges(): boolean;
59
+ /**
60
+ * The flat 2D layer view produces no GPU/geometry render diagnostics (no WebGL backend, no tube
61
+ * geometry, no draw-call/parallelism story). Returning null is honest — never a fabricated stats
62
+ * object (DD-031 G1). A consumer's diagnostics UI should say diagnostics are unavailable in 2D mode.
63
+ */
64
+ getRenderStats(): RenderStats | null;
55
65
  setQuality(_quality: QualityMode | 'auto'): void;
56
66
  setQualityMode(_mode: QualityPolicy): void;
57
67
  setProgressivePreview(_mode: ProgressivePreview): void;
@@ -1 +1 @@
1
- {"version":3,"file":"renderer-2d-adapter.d.ts","sourceRoot":"","sources":["../src/renderer-2d-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer-2d-adapter.d.ts","sourceRoot":"","sources":["../src/renderer-2d-adapter.ts"],"names":[],"mappings":"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"}
@@ -112,8 +112,28 @@ export class LayerView2DRenderer {
112
112
  return caps?.['objects'] !== undefined && caps['objects'] !== 'unavailable';
113
113
  if (mode === 'feedrate')
114
114
  return caps?.['feedrate'] !== 'unavailable';
115
+ if (mode === 'layerHeight')
116
+ return caps?.['layers'] !== undefined && caps['layers'] !== 'unavailable';
117
+ if (mode === 'power')
118
+ return caps?.['toolPower'] !== undefined && caps['toolPower'] !== 'unavailable';
115
119
  return true;
116
120
  }
121
+ /** Retraction markers are a 3D-only overlay — the flat 2D layer view never shows them (DD-031 G6). */
122
+ get hasRetractions() {
123
+ return false;
124
+ }
125
+ /** True when the current IR carries M600 color-change boundaries (DD-031 G6). */
126
+ get hasColorChanges() {
127
+ return this.ir?.header.capabilities['colorChanges'] === 'known';
128
+ }
129
+ /**
130
+ * The flat 2D layer view produces no GPU/geometry render diagnostics (no WebGL backend, no tube
131
+ * geometry, no draw-call/parallelism story). Returning null is honest — never a fabricated stats
132
+ * object (DD-031 G1). A consumer's diagnostics UI should say diagnostics are unavailable in 2D mode.
133
+ */
134
+ getRenderStats() {
135
+ return null;
136
+ }
117
137
  setQuality(_quality) {
118
138
  this.disclose('quality', 'Quality/geometry modes apply only to the 3D renderer; the 2D view has none.');
119
139
  }
@@ -8,8 +8,8 @@
8
8
  * pull Three.js into a 2D-only bundle. The 3D renderer's *values* are reached only through a
9
9
  * dynamic `import()` in the controller, so a bundler drops Three.js when `mode` is `'2d'`.
10
10
  */
11
- import type { BuildVolumeDef, CameraMode, CameraState, CameraView, CaptureOptions, ColorMode, ProgressivePreview, QualityMode, QualityPolicy, RendererEvent, Theme } from '@chestnutlabs/gcode-renderer-three';
12
- export type { CameraState, CameraView, CaptureOptions } from '@chestnutlabs/gcode-renderer-three';
11
+ import type { BuildVolumeDef, CameraMode, CameraState, CameraView, CaptureOptions, ColorMode, ProgressivePreview, QualityMode, QualityPolicy, RendererEvent, RenderStats, Theme } from '@chestnutlabs/gcode-renderer-three';
12
+ export type { CameraState, CameraView, CaptureOptions, RenderStats } from '@chestnutlabs/gcode-renderer-three';
13
13
  import type { FeatureRoleValue, MachineGeometry, MappedProgress, ToolpathIR } from '@chestnutlabs/toolpath-core';
14
14
  /** Which renderer implementation backs the preview. `'3d'` is the default (Three.js). */
15
15
  export type RendererMode = '2d' | '3d';
@@ -57,6 +57,16 @@ export interface PreviewRenderer {
57
57
  setFeatureRoleVisible?(role: FeatureRoleValue, visible: boolean): void;
58
58
  setShowRetractions(visible: boolean): void;
59
59
  setColorMode(mode: ColorMode): boolean;
60
+ /**
61
+ * Capability gate for a color mode (DD-001 honesty): `false` when the IR lacks the channel the mode
62
+ * reads (e.g. `feature` on a file with no feature roles). Lets a consumer build capability-aware UI
63
+ * without the raw handle (DD-031 G6). `single`/`tool`/`moveKind` are always available.
64
+ */
65
+ isColorModeAvailable(mode: ColorMode['mode']): boolean;
66
+ /** True when the current IR carries retraction/deretraction events the markers can show (DD-031 G6). */
67
+ readonly hasRetractions: boolean;
68
+ /** True when the current IR carries M600 color-change boundaries (DD-031 G6). */
69
+ readonly hasColorChanges: boolean;
60
70
  setQuality(quality: QualityMode | 'auto'): void;
61
71
  /** Fidelity policy (DD-023 §4 D6): 'full' | 'adaptive' | 'fast'. 3D only; 2D is a no-op. */
62
72
  setQualityMode(mode: QualityPolicy): void;
@@ -86,6 +96,12 @@ export interface PreviewRenderer {
86
96
  * `renderer-unsupported` / rejects. Never fabricated output.
87
97
  */
88
98
  capture?(opts?: CaptureOptions): Promise<Blob>;
99
+ /**
100
+ * Render diagnostics snapshot (DD-027) — backend/GPU/geometry-mode/parallelism/timings — or null
101
+ * before the first render / on a renderer that produces none (the 2D view). Exposed through the
102
+ * public surface so diagnostics are reachable without the raw handle (DD-031 G1).
103
+ */
104
+ getRenderStats(): RenderStats | null;
89
105
  dispose(): void;
90
106
  }
91
107
  //# sourceMappingURL=renderer-interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"renderer-interface.d.ts","sourceRoot":"","sources":["../src/renderer-interface.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer-interface.d.ts","sourceRoot":"","sources":["../src/renderer-interface.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
package/dist/testing.js CHANGED
@@ -170,6 +170,91 @@ export function runBehavioralSuite(name, api, harness) {
170
170
  expect(a.observeProgress({ v: 1, timestampMs: 1, position: { percent: 0.5 } })).toBeNull();
171
171
  await a.dispose();
172
172
  });
173
+ it('layer range clips and restores draw ranges (DD-031 parity)', async () => {
174
+ const a = await harness.create();
175
+ await a.parse(new Uint8Array(1_000));
176
+ await a.settle();
177
+ // Test IR is 2 layers × 6 extrude segments (24 draw verts). Clipping to layer 0 leaves 12.
178
+ expect(a.firstChunkDrawCount()).toBe(24);
179
+ a.controls.setLayerRange(0, 0);
180
+ await a.settle();
181
+ expect(a.firstChunkDrawCount()).toBe(12);
182
+ a.controls.setLayerRange(0, Number.POSITIVE_INFINITY);
183
+ await a.settle();
184
+ expect(a.firstChunkDrawCount()).toBe(24);
185
+ await a.dispose();
186
+ });
187
+ it('color-mode gating is honest and reachable through controls (DD-031 G6)', async () => {
188
+ const a = await harness.create();
189
+ await a.parse(new Uint8Array(1_000));
190
+ await a.settle();
191
+ // The test IR carries no feature roles → feature coloring is unavailable (never fabricated),
192
+ // while single/tool/moveKind are always available.
193
+ expect(a.controls.isColorModeAvailable('single')).toBe(true);
194
+ expect(a.controls.isColorModeAvailable('moveKind')).toBe(true);
195
+ expect(a.controls.isColorModeAvailable('feature')).toBe(false);
196
+ // setColorMode reports the same gate: single applies (true), gated feature is refused (false).
197
+ expect(a.controls.setColorMode({ mode: 'single', color: [1, 1, 1] })).toBe(true);
198
+ expect(a.controls.setColorMode({ mode: 'feature', palette: [[1, 0, 0]], fallback: [0.5, 0.5, 0.5] })).toBe(false);
199
+ // The capability-aware state list mirrors the gates for capability-driven UI.
200
+ const modes = a.getState().availableColorModes;
201
+ expect(modes.includes('single')).toBe(true);
202
+ expect(modes.includes('tool')).toBe(true);
203
+ expect(modes.includes('moveKind')).toBe(true);
204
+ expect(modes.includes('feature')).toBe(false);
205
+ // Retraction/color-change presence are booleans a UI can gate on (this IR has neither).
206
+ expect(a.getState().hasRetractions).toBe(false);
207
+ expect(a.getState().hasColorChanges).toBe(false);
208
+ await a.dispose();
209
+ });
210
+ it('render diagnostics + segment picking are reachable through controls, not raw-only (DD-031 G1/G2)', async () => {
211
+ const a = await harness.create();
212
+ await a.parse(new Uint8Array(1_000));
213
+ await a.settle();
214
+ // Reachable through the public controls surface (no raw.renderer()). Honest shapes: a RenderStats
215
+ // object or null; a segment index or null — never a throw, never fabricated.
216
+ const stats = a.controls.getRenderStats();
217
+ expect(stats === null || typeof stats === 'object').toBe(true);
218
+ const hit = a.controls.pickSegment(0, 0);
219
+ expect(hit === null || typeof hit === 'number').toBe(true);
220
+ await a.dispose();
221
+ });
222
+ it('exposes the full controls contract on every adapter (DD-031 parity guard)', async () => {
223
+ const a = await harness.create();
224
+ await a.parse(new Uint8Array(1_000));
225
+ await a.settle();
226
+ // A capability that ships in core must not silently vanish from an adapter: assert each
227
+ // GcodePreviewControls method is callable here. Add new controls methods to this list.
228
+ const required = [
229
+ 'setLayerRange',
230
+ 'setScrubPosition',
231
+ 'setScrubTime',
232
+ 'setKindVisible',
233
+ 'setFeatureRoleVisible',
234
+ 'setShowRetractions',
235
+ 'setColorMode',
236
+ 'isColorModeAvailable',
237
+ 'setQuality',
238
+ 'setQualityMode',
239
+ 'setProgressivePreview',
240
+ 'setCameraMode',
241
+ 'setView',
242
+ 'getCameraState',
243
+ 'setCameraState',
244
+ 'setTheme',
245
+ 'setBuildVolume',
246
+ 'setBuildVolumeCage',
247
+ 'setFrameContent',
248
+ 'setInteractionQuality',
249
+ 'frame',
250
+ 'capture',
251
+ 'getRenderStats',
252
+ 'pickSegment'
253
+ ];
254
+ for (const name of required)
255
+ expect(typeof a.controls[name] === 'function').toBe(true);
256
+ await a.dispose();
257
+ });
173
258
  it('honors DD-005 bed precedence: consumer volume blocks auto-apply, discovery is evented', async () => {
174
259
  const a = await harness.create({ machine: TEST_MACHINE, consumerVolume: true });
175
260
  const events = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chestnutlabs/gcode-preview-core",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "Framework-neutral preview controller for the Chestnut Labs G-code viewer (DD-007 §4.6): the shared engine glue, state model, and TypeScript contracts beneath the Vue/React/Svelte adapters.",
5
5
  "keywords": [
6
6
  "gcode",
@@ -52,9 +52,9 @@
52
52
  "test": "vitest run"
53
53
  },
54
54
  "dependencies": {
55
- "@chestnutlabs/gcode-parser": "0.19.0",
56
- "@chestnutlabs/gcode-renderer-2d": "0.19.0",
57
- "@chestnutlabs/gcode-renderer-three": "0.19.0",
58
- "@chestnutlabs/toolpath-core": "0.19.0"
55
+ "@chestnutlabs/gcode-parser": "0.20.0",
56
+ "@chestnutlabs/gcode-renderer-2d": "0.20.0",
57
+ "@chestnutlabs/gcode-renderer-three": "0.20.0",
58
+ "@chestnutlabs/toolpath-core": "0.20.0"
59
59
  }
60
60
  }