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.
- package/README.md +67 -8
- package/components/README.md +1 -1
- package/components/dist/SettingsPanel.js +12 -12
- package/data/README.md +39 -2
- package/data/config-schema.json +1163 -900
- package/data/filaments.js +2 -0
- package/data/invalidation-map.json +5 -4
- package/data/printers.json +1 -0
- package/data/processes.js +2 -0
- package/data/toggle-rules.json +44 -44
- package/data/ui-tree.json +190 -495
- package/engine/README.md +56 -4
- package/engine/src/data.js +9 -1
- package/engine/src/settings.js +218 -6
- package/engine/src/slicer.worker.js +142 -5
- package/engine/src/slicer_core.js +0 -0
- package/engine/src/slicer_core.mt.js +0 -0
- package/package.json +18 -3
- package/types/data/filaments.js.d.ts +27 -0
- package/types/data/printers.json.d.ts +23 -0
- package/types/data/processes.js.d.ts +21 -0
- package/types/data.d.ts +12 -2
- package/types/settings-keys.d.ts +48 -3
- package/types/settings.d.ts +30 -0
- package/types/viewer-gcode.d.ts +29 -0
- package/types/viewer-toolpath.d.ts +9 -1
- package/types/viewer.d.ts +53 -0
- package/viewer/README.md +48 -2
- package/viewer/dist/Viewport.js +2484 -1521
- package/viewer/dist/gcode_parse.js +190 -0
- package/viewer/dist/toolpath_gpu.js +162 -137
- package/viewer/styles.css +71 -2
|
@@ -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
|
|
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>
|
package/types/settings-keys.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// AUTO-GENERATED by types/gen_settings_types.mjs — DO NOT EDIT.
|
|
2
|
-
// Source: data/config-schema.json (
|
|
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
|
package/types/settings.d.ts
CHANGED
|
@@ -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`,
|
|
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
|
|