three-slicer 0.1.2 → 0.1.4

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.
@@ -0,0 +1,23 @@
1
+ // printers.json — per-printer settings extracted from OrcaSlicer's resources/profiles/<Vendor>/machine/.
2
+ // Column layout: `keys` names the columns once and each entry in `sets` is a positional row, because
3
+ // repeating the key names per printer costs more than all the values together. Rows are deduplicated —
4
+ // a printer's nozzle variants usually share one row — so a printer holds an index rather than its own copy.
5
+ // Prefer `printerSettings()` from three-slicer/settings over decoding this by hand.
6
+
7
+ /** A positional row aligned to `keys`; `null` where the profile chain never set that option. */
8
+ export type PrinterRow = (unknown | null)[]
9
+
10
+ /** `[nozzle diameter, index into sets, model name without the nozzle suffix]` */
11
+ export type PrinterEntry = [string, number, string]
12
+
13
+ export interface PrinterData {
14
+ /** Option keys, in column order — the same keys the settings panel edits */
15
+ keys: string[]
16
+ /** Deduplicated value rows */
17
+ sets: PrinterRow[]
18
+ /** Vendor -> printer profile name -> entry */
19
+ byVendor: Record<string, Record<string, PrinterEntry>>
20
+ }
21
+
22
+ declare const printers: PrinterData
23
+ export default printers
@@ -0,0 +1,21 @@
1
+ // processes.js — print (process) presets extracted from OrcaSlicer's resources/profiles/<Vendor>/process/.
2
+ // Emitted as a JS module rather than JSON because it is loaded dynamically: see engine/src/data.js for why.
3
+ // Column layout, same as printers.json — `keys` names the columns once and each row in `sets` is positional.
4
+ // Prefer `processPresets()` from three-slicer/settings over decoding this by hand.
5
+
6
+ /** A positional row aligned to `keys`; `null` where the profile chain never set that option. */
7
+ export type ProcessRow = (unknown | null)[]
8
+
9
+ export interface ProcessData {
10
+ /** Option keys, in column order — the keys the kernel consumes, read out of engine/src/settings.js */
11
+ keys: string[]
12
+ /** Deduplicated value rows */
13
+ sets: ProcessRow[]
14
+ /** `[preset name, index into sets]`, indexed by the numbers in `byPrinter` */
15
+ presets: [string, number][]
16
+ /** Printer profile name -> indices into `presets` */
17
+ byPrinter: Record<string, number[]>
18
+ }
19
+
20
+ declare const processes: ProcessData
21
+ export default processes
package/types/data.d.ts CHANGED
@@ -1,11 +1,15 @@
1
- // three-slicer/data — the 4 extracted JSON files. Prefer this over importing the raw JSON:
1
+ // three-slicer/data — the extracted JSON files. Prefer this over importing the raw JSON:
2
2
  // the import attribute (`with { type: 'json' }`) is already applied, so it works in Node and bundlers alike.
3
3
  import type { ConfigOption } from './data/config-schema.json.d.ts'
4
4
  import type { UIPage } from './data/ui-tree.json.d.ts'
5
5
  import type { ToggleGroup } from './data/toggle-rules.json.d.ts'
6
6
  import type { InvalidationRule } from './data/invalidation-map.json.d.ts'
7
+ import type { PrinterData, PrinterRow, PrinterEntry } from './data/printers.json.d.ts'
8
+ import type { ProcessData } from './data/processes.js.d.ts'
9
+ import type { FilamentData, FilamentRow, FilamentEntry } from './data/filaments.js.d.ts'
7
10
 
8
- export type { ConfigOption, UIPage, ToggleGroup, InvalidationRule }
11
+ export type { ConfigOption, UIPage, ToggleGroup, InvalidationRule, PrinterData, PrinterRow, PrinterEntry }
12
+ export type { ProcessData, FilamentData, FilamentRow, FilamentEntry }
9
13
 
10
14
  /** The 907 option definitions */
11
15
  export const schema: Record<string, ConfigOption>
@@ -15,3 +19,9 @@ export const uiTree: Record<string, UIPage[]>
15
19
  export const toggleRules: Record<string, ToggleGroup>
16
20
  /** Setting key change -> invalidated steps */
17
21
  export const invalidationMap: Record<string, InvalidationRule[]>
22
+ /** Machine limits per printer, from the upstream vendor profiles */
23
+ export const printers: PrinterData
24
+ // The two large artifacts load on demand — read them through processPresets()/filamentPresets()
25
+ // in three-slicer/settings rather than decoding the column layout here.
26
+ export function loadProcesses(): Promise<ProcessData>
27
+ export function loadFilaments(): Promise<FilamentData>
@@ -1,5 +1,5 @@
1
1
  // AUTO-GENERATED by types/gen_settings_types.mjs — DO NOT EDIT.
2
- // Source: data/config-schema.json (907 keys)
2
+ // Source: data/config-schema.json (923 keys)
3
3
 
4
4
  /** [x, y] — coPoint family */
5
5
  export type Point = [number, number]
@@ -391,6 +391,8 @@ export interface SlicerSettings {
391
391
  filament_cost?: number[] | number
392
392
  /** Density — (g/cm³) — Filament density, for statistical purposes only. */
393
393
  filament_density?: number[] | number
394
+ /** Deretraction speed — (mm/s) — Speed for reloading filament into the nozzle. Zero means same speed of retraction. */
395
+ filament_deretraction_speed?: number[] | number
394
396
  filament_dev_ams_drying_ams_limitations?: string[] | string
395
397
  filament_dev_ams_drying_heat_distortion_temperature?: number[] | number
396
398
  filament_dev_ams_drying_temperature?: number[] | number
@@ -433,6 +435,8 @@ export interface SlicerSettings {
433
435
  filament_loading_speed?: number[] | number
434
436
  /** Loading speed at the start — (mm/s) — Speed used at the very beginning of loading phase. */
435
437
  filament_loading_speed_start?: number[] | number
438
+ /** Long retraction when cut (beta) — Experimental feature: Retracting and cutting off the filament at a longer distance during changes to minimize purge. While this reduces flush significantly, it may also raise the risk of nozzle clogs or other printing problems. */
439
+ filament_long_retractions_when_cut?: boolean[] | boolean
436
440
  /** Filament map to extruder — Filament map to extruder. */
437
441
  filament_map?: number[] | number
438
442
  /** Filament map plus for multi nozzle — Filament map to the index identified by extruder and nozzle_volume_type */
@@ -478,8 +482,30 @@ export interface SlicerSettings {
478
482
  filament_ramming_volumetric_speed?: number[] | number
479
483
  /** Hotend change — (mm³/s) — The maximum volumetric speed for ramming before a hotend change, where -1 means using the maximum volumetric speed. */
480
484
  filament_ramming_volumetric_speed_nc?: number[] | number
485
+ /** Retract amount after wipe — (%) — The length of fast retraction after wipe, relative to retraction length. The value will be clamped by 100% minus the retract amount before the wipe value. */
486
+ filament_retract_after_wipe?: number[] | number
487
+ /** Retract amount before wipe — (%) — This is the length of fast retraction before a wipe, relative to retraction length. */
488
+ filament_retract_before_wipe?: number[] | number
481
489
  /** length when change hotend — (mm) — When this retraction value is modified, it will be used as the amount of filament retracted inside the hotend before changing hotends. */
482
490
  filament_retract_length_nc?: number[] | number
491
+ /** Only lift Z above — (mm) — If you set this to a positive value, Z lift will only take place above the specified absolute Z. */
492
+ filament_retract_lift_above?: number[] | number
493
+ /** Only lift Z below — (mm) — If you set this to a positive value, Z lift will only take place below the specified absolute Z. */
494
+ filament_retract_lift_below?: number[] | number
495
+ /** On surfaces — Enforce Z-Hop behavior. This setting is impacted by the above settings (Only lift Z above/below). */
496
+ filament_retract_lift_enforce?: ('All Surfaces' | 'Top Only' | 'Bottom Only' | 'Top and Bottom')[] | ('All Surfaces' | 'Top Only' | 'Bottom Only' | 'Top and Bottom')
497
+ /** Extra length on restart — (mm) — When the retraction is compensated after the travel move, the extruder will push this additional amount of filament. This setting is rarely needed. */
498
+ filament_retract_restart_extra?: number[] | number
499
+ /** Retract on layer change — This forces a retraction on layer changes. */
500
+ filament_retract_when_changing_layer?: boolean[] | boolean
501
+ /** Retraction distance when cut — Experimental feature: Retraction length before cutting off during filament change. */
502
+ filament_retraction_distances_when_cut?: number[] | number
503
+ /** Length — (mm) — Some amount of material in extruder is pulled back to avoid ooze during long travel. Set zero to disable retraction. */
504
+ filament_retraction_length?: number[] | number
505
+ /** Travel distance threshold — (mm) — Only trigger retraction when the travel distance is longer than this threshold. */
506
+ filament_retraction_minimum_travel?: number[] | number
507
+ /** Retraction speed — (mm/s) — Speed for retracting filament from the nozzle. */
508
+ filament_retraction_speed?: number[] | number
483
509
  /** Filament self index — Filament self index. */
484
510
  filament_self_index?: number[] | number
485
511
  filament_settings_id?: string[] | string
@@ -516,6 +542,14 @@ export interface SlicerSettings {
516
542
  /** Vendor — Vendor of filament. For show only. */
517
543
  filament_vendor?: string[] | string
518
544
  filament_volume_map?: number[] | number
545
+ /** Wipe while retracting — This moves the nozzle along the last extrusion path when retracting to clean any leaked material on the nozzle. This can minimize blobs when printing a new part after traveling. */
546
+ filament_wipe?: boolean[] | boolean
547
+ /** Wipe distance — (mm) — Describe how long the nozzle will move along the last path when retracting. Depending on how long the wipe operation lasts, how fast and long the extruder/filament retraction settings are, a retraction move may be needed to retract the remaining filament. Setting a value in the retract amount before wipe setting below will perform any excess retraction before the wipe, else it will be performed after. */
548
+ filament_wipe_distance?: number[] | number
549
+ /** Z-hop height — (mm) — Whenever there is a retraction, the nozzle is lifted a little to create clearance between the nozzle and the print. This prevents the nozzle from hitting the print when traveling more. Using spiral lines to lift z can prevent stringing. */
550
+ filament_z_hop?: number[] | number
551
+ /** Z-hop type — Type of Z-hop. */
552
+ filament_z_hop_types?: ('Auto Lift' | 'Normal Lift' | 'Slope Lift' | 'Spiral Lift')[] | ('Auto Lift' | 'Normal Lift' | 'Slope Lift' | 'Spiral Lift')
519
553
  /** File header G-code — G-code written at the very top of the output file, before any other content. Useful for adding metadata that printer firmware reads from the first lines of the file (e.g. estimated print time, filament usage). Supports placeholders like {print_time_sec} and {used_filament_length}. */
520
554
  file_start_gcode?: string
521
555
  /** Filename format — Users can decide project file names when exporting. */
@@ -831,6 +865,7 @@ export interface SlicerSettings {
831
865
  machine_hotend_change_time?: number
832
866
  /** Filament load time — (s) — Time to load new filament when switch filament. It's usually applicable for single-extruder multi-material machines. For tool changers or multi-tool machines, it's typically 0. For statistics only. */
833
867
  machine_load_filament_time?: number
868
+ /** (mm/s²) — Maximum acceleration of the E axis */
834
869
  machine_max_acceleration_e?: number[] | number
835
870
  /** (mm/s²) — Maximum acceleration for extruding (M204 P) */
836
871
  machine_max_acceleration_extruding?: number[] | number
@@ -838,22 +873,33 @@ export interface SlicerSettings {
838
873
  machine_max_acceleration_retracting?: number[] | number
839
874
  /** (mm/s²) — Maximum acceleration for travel (M204 T), it only applies to Marlin 2. */
840
875
  machine_max_acceleration_travel?: number[] | number
876
+ /** (mm/s²) — Maximum acceleration of the X axis */
841
877
  machine_max_acceleration_x?: number[] | number
878
+ /** (mm/s²) — Maximum acceleration of the Y axis */
842
879
  machine_max_acceleration_y?: number[] | number
880
+ /** (mm/s²) — Maximum acceleration of the Z axis */
843
881
  machine_max_acceleration_z?: number[] | number
844
882
  /** (N) — The allowed maximum output force of Y axis */
845
883
  machine_max_force_Y?: number
884
+ /** (mm/s) — Maximum jerk of the E axis */
846
885
  machine_max_jerk_e?: number[] | number
886
+ /** (mm/s) — Maximum jerk of the X axis */
847
887
  machine_max_jerk_x?: number[] | number
888
+ /** (mm/s) — Maximum jerk of the Y axis */
848
889
  machine_max_jerk_y?: number[] | number
890
+ /** (mm/s) — Maximum jerk of the Z axis */
849
891
  machine_max_jerk_z?: number[] | number
850
892
  /** (mm) — Maximum junction deviation (M205 J, only apply if JD > 0 for Marlin Firmware If your Marlin 2 printer uses Classic Jerk set this value to 0.) */
851
893
  machine_max_junction_deviation?: number[] | number
852
894
  /** (g) — The allowed max printed mass on a plate */
853
895
  machine_max_printed_mass?: number
896
+ /** (mm/s) — Maximum speed of E axis */
854
897
  machine_max_speed_e?: number[] | number
898
+ /** (mm/s) — Maximum speed of X axis */
855
899
  machine_max_speed_x?: number[] | number
900
+ /** (mm/s) — Maximum speed of Y axis */
856
901
  machine_max_speed_y?: number[] | number
902
+ /** (mm/s) — Maximum speed of Z axis */
857
903
  machine_max_speed_z?: number[] | number
858
904
  /** (mm/s) — Minimum speed for extruding (M205 S) */
859
905
  machine_min_extruding_rate?: number[] | number
@@ -1056,8 +1102,6 @@ export interface SlicerSettings {
1056
1102
  physical_printer_preset?: string
1057
1103
  /** Send progress to pipe — Send progress to pipe. */
1058
1104
  pipe?: string
1059
- /** Capabilities — Configuration for the plugin capabilities this preset uses, overriding the global Capabilities configuration. Stored as a raw JSON array and edited through the dialog behind the button, never typed in directly. */
1060
- plugin_config_overrides?: string
1061
1105
  /** Plugins Used — Plugin capabilities referenced by this preset, stored as name;uuid;capability. */
1062
1106
  plugins?: string[] | string
1063
1107
  /** Position — Position of the extruder at the beginning of the custom G-code block. If the custom G-code travels somewhere else, it should write to this variable so OrcaSlicer knows where it travels from when it gets control back. */
@@ -1074,6 +1118,7 @@ export interface SlicerSettings {
1074
1118
  preheat_steps?: number
1075
1119
  /** Preheat time — (s) — To reduce the waiting time after tool change, Orca can preheat the next tool while the current tool is still in use. This setting specifies the time in seconds to preheat the next tool. Orca will insert a M104 command to preheat the tool in advance. */
1076
1120
  preheat_time?: number
1121
+ /** Capabilities — Configuration for the plugin capabilities this preset uses, overriding the global Capabilities configuration. Stored as a raw JSON array and edited through the dialog behind the button, never typed in directly. */
1077
1122
  preset_name?: string
1078
1123
  /** Printer preset names — Names of presets related to the physical printer. */
1079
1124
  preset_names?: string[] | string
@@ -17,3 +17,33 @@ export function settingScalar(settings: SlicerSettings | null | undefined, key:
17
17
  * not an API consumers read field by field. Expand it when field access is actually needed.
18
18
  */
19
19
  export function deriveKernelParams(settings: SlicerSettings | null | undefined): Record<string, unknown>
20
+
21
+ // ---- Lazily loaded presets --------------------------------------------------
22
+ // Both facades hide the column layout of the artifact they wrap; the promise is created once and reused.
23
+
24
+ export interface ProcessPresetsApi {
25
+ /** Every key a process preset can set — clear these before applying a different one */
26
+ keys: string[]
27
+ /** Preset names compatible with a printer profile, in upstream order */
28
+ listFor(printerProfileName: string): string[]
29
+ /** The settings a preset applies, ready to merge. `null` when unknown. */
30
+ settingsFor(presetName: string): SlicerSettings | null
31
+ }
32
+ export function processPresets(): Promise<ProcessPresetsApi>
33
+
34
+ /** A material as a picker shows it. `type`/`vendor` are `''` when the profile chain declares neither. */
35
+ export interface FilamentPreset { name: string, type: string, vendor: string }
36
+
37
+ export interface FilamentPresetsApi {
38
+ /** Every key a filament preset can set — clear these before applying a different material */
39
+ keys: string[]
40
+ /** Every material in the catalog, in upstream order — for a picker shown before any printer is chosen */
41
+ all(): FilamentPreset[]
42
+ /** Materials compatible with a printer profile, in upstream order */
43
+ listFor(printerProfileName: string): FilamentPreset[]
44
+ /** The vendor's recommended materials for that printer's model — a subset of listFor */
45
+ recommendedFor(printerProfileName: string): FilamentPreset[]
46
+ /** The settings a material applies, ready to merge. `null` when unknown. */
47
+ settingsFor(presetName: string): SlicerSettings | null
48
+ }
49
+ export function filamentPresets(): Promise<FilamentPresetsApi>
@@ -0,0 +1,29 @@
1
+ // three-slicer/viewer/gcode — G-code text -> kernel-shaped layer stream (renderable without slicing).
2
+ // Feed the returned layers straight into buildSegmentData (three-slicer/viewer/toolpath).
3
+
4
+ export interface GcodeLayer {
5
+ z: number
6
+ /** Stride 8: [x0,y0,z0,enc, x1,y1,z1,enc] per segment, enc = role + tool*16 (role 0 = travel). */
7
+ paths: Float32Array
8
+ /** One entry per segment; 0 means "use the default line width". */
9
+ widths: Float32Array
10
+ }
11
+
12
+ export interface ParseGcodeResult {
13
+ layers: GcodeLayer[]
14
+ stats: { layers: number; path_segments: number; travel_segments: number; tools: number[] }
15
+ }
16
+
17
+ export interface ParseGcodeOptions {
18
+ /** Used to derive bead width from E when the file has no ;WIDTH: comments. Default 1.75. */
19
+ filamentDiameter?: number
20
+ /** Bead-height fallback when a layer's height cannot be inferred from z steps. Default 0.2. */
21
+ defaultLayerHeight?: number
22
+ }
23
+
24
+ /**
25
+ * Parses G0/G1/G2/G3 (I/J arcs), G90/G91, M82/M83, G92, T<n>, and the layer/role comment conventions of
26
+ * OrcaSlicer/PrusaSlicer (;TYPE: ;WIDTH: ;LAYER_CHANGE ;Z:), Cura (;TYPE: ;LAYER:) and this kernel's own output.
27
+ * Recovery is lossy where G-code carries no data: unknown roles become wall(1), widths are derived from E.
28
+ */
29
+ export function parseGcode(text: string, opts?: ParseGcodeOptions): ParseGcodeResult
@@ -8,11 +8,17 @@ export const VERTEX_DATA: number[]
8
8
  export const TYPE_COLOR: Record<number, number[]>
9
9
  export const TYPE_LABEL: Record<number, string>
10
10
 
11
+ /**
12
+ * Per-extruder colors for the Filament view. Categorical, not semantic — the toolpath stream carries a tool index and
13
+ * nothing about the material, and a machine may have more extruders than entries, so index it modulo its length.
14
+ */
15
+ export const TOOL_COLOR: number[][]
16
+
11
17
  /** Blue-to-red 11-color heatmap (libvgcode ColorRange.hpp:14) */
12
18
  export const DEFAULT_RANGES_COLORS: number[][]
13
19
 
14
20
  export interface ViewTypeDef {
15
- key: 'feature' | 'speed' | 'height' | 'width' | 'fan' | 'temp'
21
+ key: 'feature' | 'speed' | 'height' | 'width' | 'fan' | 'temp' | 'filament'
16
22
  label: string
17
23
  /** Whether values are continuous (heatmap). False means a fixed color. */
18
24
  cont: boolean
@@ -23,6 +29,8 @@ export const VIEW_TYPES: ViewTypeDef[]
23
29
  /** Per-vertex extra data */
24
30
  export interface SegmentMeta {
25
31
  vType: Uint8Array
32
+ /** Printing extruder, decoded out of the role field's high bits. Untooled output decodes to 0, i.e. single material. */
33
+ vTool: Uint8Array
26
34
  vWidth: Float32Array
27
35
  vHeight: Float32Array
28
36
  vLayer: Int32Array
package/types/viewer.d.ts CHANGED
@@ -9,7 +9,60 @@ export interface ViewportProps {
9
9
  setSettings?: React.Dispatch<React.SetStateAction<SlicerSettings>>
10
10
  /** Left process-panel slot — usually `<SettingsPanel embedded/>`. Defaults to null. */
11
11
  processPanel?: React.ReactNode
12
+ /** Motion-limits editor, folded into the printer card — usually `<SettingsPanel only={{builder:'TabPrinter::build_kinematics_page'}}/>`. */
13
+ motionPanel?: React.ReactNode
14
+ /**
15
+ * Filament editor, folded into the filament card. Pass a function rather than a node: with more than one
16
+ * extruder loaded the card projects that extruder's slice of the per-extruder columns and writes the form's
17
+ * edits back at its index, so the panel must bind to the pair it is given.
18
+ */
19
+ filamentPanel?: React.ReactNode
20
+ | ((settings: SlicerSettings, setSettings: React.Dispatch<React.SetStateAction<SlicerSettings>>) => React.ReactNode)
21
+ /**
22
+ * Per-panel visibility. Every panel is visible unless its key is explicitly `false`, so a host only opts out —
23
+ * and a panel added in a later version does not disappear for hosts that listed the ones they wanted.
24
+ */
25
+ panels?: Partial<Record<ViewportPanel, boolean>>
26
+ /**
27
+ * G-code text to render instead of a slice result. Parsed into the same layer stream the kernel produces and
28
+ * shown on the selected plate; the kernel is never started. While it is set, auto re-slice leaves that plate alone.
29
+ */
30
+ gcode?: string | null
31
+ /** Initial filament colours (hex), one per extruder. Defaults to the built-in T1/T2 pair. */
32
+ defaultExtruderColors?: string[] | null
33
+ /**
34
+ * Start with auto re-slice on. Unlike the in-app toggle's original behaviour this also performs the FIRST slice,
35
+ * which is what makes a panel-less embed able to slice at all.
36
+ */
37
+ defaultAutoSlice?: boolean
38
+ /** Every value change in one channel. See {@link ViewportEvent}. */
39
+ onEvent?: (event: ViewportEvent) => void
40
+ /** A finished slice, fired where the result is cached — switching plate tabs does not re-fire it. */
41
+ onSliced?: (result: { plate: number; stats: Record<string, unknown>; gcode: string }) => void
12
42
  }
13
43
 
44
+ /** Panel keys accepted by {@link ViewportProps.panels}. `sidebar: false` hides the whole right column at once. */
45
+ export type ViewportPanel =
46
+ | 'topBar' | 'gizmoRail' | 'objectToolbar' | 'paintPanel' | 'statsCard' | 'plateBar' | 'emptyHint' | 'status'
47
+ | 'sidebar' | 'printerCard' | 'filamentCard' | 'objectList' | 'previewControls' | 'processCard' | 'sliceBar'
48
+
49
+ /** Value changes reported through {@link ViewportProps.onEvent}. Not fired for the initial values. */
50
+ export type ViewportEvent =
51
+ | { type: 'canvasMode'; value: 'prepare' | 'preview' }
52
+ | { type: 'objects'; value: Array<{ id: number; name: string; extruder: number; visible: boolean }> }
53
+ | { type: 'selectedPlate'; value: number }
54
+ | { type: 'plateCount'; value: number }
55
+ | { type: 'extruderColors'; value: string[] }
56
+ | { type: 'autoSlice'; value: boolean }
57
+ | { type: 'slicing'; value: boolean }
58
+ /** 0..1. Fires several times a second while slicing — throttle on the host side if that matters. */
59
+ | { type: 'progress'; value: number }
60
+ | { type: 'viewType'; value: 'feature' | 'speed' | 'height' | 'width' | 'fan' | 'temp' | 'filament' }
61
+ | { type: 'paintMode'; value: 'off' | 'enforcer' | 'blocker' | 'material' }
62
+ | { type: 'layerCount'; value: number }
63
+ | { type: 'layerRange'; value: { lo: number; hi: number } }
64
+ | { type: 'error'; value: string }
65
+ | { type: 'notice'; value: string }
66
+
14
67
  declare const Viewport: React.FC<ViewportProps>
15
68
  export default Viewport
package/viewer/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # three-slicer/viewer
2
2
 
3
- 3D slicer viewer as a React component: three.js viewport (orbit/transform gizmos), model import (STL/OBJ/3MF/AMF/PLY + pluggable formats such as STEP, multi-object, drag & drop), Web Worker slicing via `three-slicer`, support painting, multi-plate, and a GPU-instanced volumetric toolpath preview ported from OrcaSlicer's libvgcode (millions of segments in a single draw path, per-feature colors, layer range slider, G-code export).
3
+ 3D slicer viewer as a React component: three.js viewport (orbit/transform gizmos), model import (STL/OBJ/3MF/AMF/PLY + pluggable formats such as STEP, multi-object, drag & drop), Web Worker slicing via `three-slicer`, support and material painting, per-extruder filament presets, multi-plate, and a GPU-instanced volumetric toolpath preview ported from OrcaSlicer's libvgcode (millions of segments in a single draw path, per-feature colors, layer range slider, G-code export).
4
4
 
5
5
  ```bash
6
6
  npm i three-slicer/viewer react react-dom three@^0.160.0
@@ -19,11 +19,57 @@ function App() {
19
19
 
20
20
  Slice parameters are derived from `settings` via `three-slicer`'s schema mapping — pair it with `three-slicer/components`' `<SettingsPanel/>` sharing the same state for a full slicer UI.
21
21
 
22
- Props: `settings`, `setSettings`, `processPanel` (optional React node rendered in the right sidebar).
22
+ Props: `settings`, `setSettings`, and three optional React-node slots rendered in the right sidebar —
23
+ `processPanel` (the process card), `motionPanel` (folded into the printer card) and `filamentPanel`
24
+ (folded into the filament card, next to the material picker).
23
25
 
24
26
  Subpath exports for custom UIs (framework-free, no React):
25
27
  - `three-slicer/viewer/toolpath` — GPU toolpath renderer (`buildSegmentData`, `makeToolpath`, view-type colorers)
26
28
  - `three-slicer/viewer/loaders` — model loaders returning unified triangle soup
29
+ - `three-slicer/viewer/gcode` — `parseGcode(text)`, G-code back into the layer stream the renderer consumes
30
+
31
+ ## Embedding it without the panels
32
+
33
+ Every panel can be switched off, and the values the component owns can be seeded and watched, so the same
34
+ `<Viewport/>` also works as a bare G-code viewer or as a headless slicer inside another app's UI.
35
+
36
+ ```jsx
37
+ // A G-code viewer: no kernel run, no panels.
38
+ <Viewport gcode={text} panels={{ sidebar: false, topBar: false, gizmoRail: false, plateBar: false }} />
39
+
40
+ // A headless slicer: the host drives it and takes the result.
41
+ <Viewport panels={{ sidebar: false }} defaultAutoSlice onSliced={({ stats, gcode }) => save(gcode)} />
42
+ ```
43
+
44
+ - **`panels`** — `{name: false}` hides one. Everything is visible by default, so a host only ever opts out and a
45
+ panel added in a later version does not vanish for hosts that listed the ones they wanted. `sidebar: false` drops
46
+ the whole right column; the rest are `topBar`, `gizmoRail`, `objectToolbar`, `paintPanel`, `statsCard`, `plateBar`,
47
+ `emptyHint`, `status`, `printerCard`, `filamentCard`, `objectList`, `previewControls`, `processCard`, `sliceBar`.
48
+ - **`gcode`** — G-code text drawn on the selected plate instead of a slice result. `parseGcode` recovers roles from
49
+ `;TYPE:` (OrcaSlicer/PrusaSlicer/Cura), from `;_EXTRUSION_ROLE:` tags and from this kernel's own feature comments;
50
+ bead width comes from `;WIDTH:` or, absent that, from E. What the file never states cannot be recovered: an
51
+ unmarked run reads as wall, and there is no print-time estimate (that needs the machine's acceleration limits).
52
+ - **`defaultExtruderColors`**, **`defaultAutoSlice`** — initial values for state the component owns. Unlike the
53
+ in-app toggle, `defaultAutoSlice` also performs the *first* slice, which is what makes a panel-less embed able to
54
+ slice at all.
55
+ - **`onEvent`** — one channel for every change: `canvasMode`, `objects`, `selectedPlate`, `plateCount`,
56
+ `extruderColors`, `autoSlice`, `slicing`, `progress`, `viewType`, `paintMode`, `layerCount`, `layerRange`,
57
+ `error`, `notice`. Initial values are not announced — the host passed them. `progress` fires several times a
58
+ second while slicing.
59
+ - **`onSliced`** — `{plate, stats, gcode}` when a slice is cached. Switching plate tabs does not re-fire it.
60
+
61
+ ## Materials and painting
62
+
63
+ The filament card holds **one material per extruder**: add an extruder, pick its colour, and pick its filament preset from the vendor catalog (`filamentPresets()` in `three-slicer/settings` — the shortlist is the printer model's own recommendation, the full list everything compatible). Selecting a row aims the material picker and the settings form at that extruder; the colours feed the object meshes, the prime tower and the preview's **Filament** view type, which colours every segment by the extruder that printed it.
64
+
65
+ The brush has two targets sharing one shell: **support painting** (enforcer / blocker) and **material painting** (one chip per extruder, plus an eraser that returns facets to the default extruder). They are mutually exclusive, and that is a data constraint rather than a UI choice — upstream's `EnforcerBlockerType` is a single enum in which ENFORCER *is* Extruder1 and BLOCKER *is* Extruder2, so one integer per facet means a support mark and a material mark cannot coexist there.
66
+
67
+ Two limits to expect while using it:
68
+
69
+ - Painting a region onto a second extruder only takes effect with **support turned off**. The painted multi-material path emits no support, so a support-enabled slice deliberately stays on the single-material path (where painted support keeps working as before).
70
+ - On a machine with two or more extruders, a support *blocker* paint and an *Extruder 2* paint are the same mark and cannot be told apart.
71
+
72
+ If you consume `three-slicer/viewer/toolpath` directly, note that the stride-8 role field `paths[k+3]` now carries the printing extruder alongside the role as `role + tool * 16`. Mask it — `& 15` for the role, `>>> 4` for the tool. Streams produced before this encoding are entirely below 16 and decode to their own role with tool 0, so older data still reads correctly.
27
73
 
28
74
  ## Multithreaded slicing (automatic)
29
75