three-slicer 0.1.7 → 0.2.1

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "three-slicer",
3
- "version": "0.1.7",
4
- "description": "Browser/WASM 3D-printing slicer reverse-engineered from OrcaSlicer: slicing engine (Arachne walls, tree/grid supports, multi-material), React viewer with GPU toolpath preview, and schema-driven settings UI.",
3
+ "version": "0.2.1",
4
+ "description": "Browser/WASM 3D-printing slicer reverse-engineered from OrcaSlicer: slicing engine (Arachne walls, tree/grid supports, multi-material), SLA resin slicing with PrusaSlicer's ported support/pad chain and .sl1 export, React viewer with GPU toolpath preview, and schema-driven settings UI.",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
7
7
  "exports": {
@@ -95,8 +95,9 @@
95
95
  "data",
96
96
  "!data/config-schema-builddump.json",
97
97
  "!data/**/.omc",
98
- "!data/printers/**",
99
98
  "README.md",
99
+ "CHANGELOG.md",
100
+ "THIRD-PARTY-NOTICES.md",
100
101
  "LICENSE.txt"
101
102
  ],
102
103
  "repository": {
@@ -109,6 +110,10 @@
109
110
  "3d-printing",
110
111
  "slicer",
111
112
  "gcode",
113
+ "sla",
114
+ "resin",
115
+ "sl1",
116
+ "msla",
112
117
  "stl",
113
118
  "wasm",
114
119
  "orcaslicer",
package/types/client.d.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  // three-slicer/client — promise wrapper over the worker protocol in three-slicer/worker.
2
2
  import type { SliceLayer, SliceResult } from '../engine/index.d.ts'
3
3
  import type { BrushArgs, PaintState, PaintTool } from './worker.d.ts'
4
+ import type { SlaJob } from './sla.d.ts'
4
5
 
5
6
  export type { BrushArgs, PaintState, PaintTool }
7
+ // Value re-exports must not name the .d.ts directly (TS2846) — the .js specifier resolves to sla.d.ts.
8
+ export { SLA_CAPABILITIES, SLA_JOB_VERSION, SlaRequestError } from './sla.js'
9
+ export type * from './sla.d.ts'
6
10
 
7
11
  export interface ClientSliceCallbacks {
8
12
  onProgress?: (done: number, total: number) => void
@@ -37,6 +41,16 @@ export interface SlicerClient {
37
41
  /** `params` may be an object; it is stringified for you, which the raw protocol does not do. */
38
42
  slice(stl: ArrayBuffer | Uint8Array, params: object | string, cb?: ClientSliceCallbacks): Promise<SliceResult>
39
43
 
44
+ /**
45
+ * Legacy single-object SLA (resin) slice. The JS fallback is contour-only and returns a typed error instead of
46
+ * silently dropping requested supports or pads. Stats carry `sla: true`, `resin_ml` and `time_estimate` instead of
47
+ * filament/G-code figures, and no G-code is produced.
48
+ */
49
+ sliceSla(stl: ArrayBuffer | Uint8Array, params: object | string, cb?: ClientSliceCallbacks): Promise<SliceResult>
50
+
51
+ /** Object-aware SLA job. Objects retain their order, instances and support context for the WASM job bridge. */
52
+ sliceSlaJob(job: SlaJob, cb?: ClientSliceCallbacks): Promise<SliceResult>
53
+
40
54
  /** Register a mesh for painting. `keepPaint` carries existing marks across a move; `kept` says whether they survived. */
41
55
  prepare(stl: ArrayBuffer | Uint8Array, opts?: { keepPaint?: boolean }): Promise<{ facets: number; kept: boolean }>
42
56
 
@@ -1,5 +1,5 @@
1
1
  // AUTO-GENERATED by types/gen_settings_types.mjs — DO NOT EDIT.
2
- // Source: data/config-schema.json (923 keys)
2
+ // Source: data/config-schema.json (976 keys)
3
3
 
4
4
  /** [x, y] — coPoint family */
5
5
  export type Point = [number, number]
@@ -96,6 +96,40 @@ export interface SlicerSettings {
96
96
  bottom_surface_fill_order?: 'default' | 'outward' | 'inward'
97
97
  /** Bottom surface pattern — This is the line pattern of bottom surface infill, not including bridge infill. */
98
98
  bottom_surface_pattern?: 'monotonic' | 'monotonicline' | 'rectilinear' | 'alignedrectilinear' | 'concentric' | 'hilbertcurve' | 'archimedeanchords' | 'octagramspiral'
99
+ /** Support base diameter — (mm) — Diameter in mm of the pillar base */
100
+ branchingsupport_base_diameter?: number
101
+ /** Support base height — (mm) — The height of the pillar base cone */
102
+ branchingsupport_base_height?: number
103
+ /** Support base safety distance — (mm) — The minimum distance of the pillar base from the model in mm. Makes sense in zero elevation mode where a gap according to this parameter is inserted between the model and the pad. */
104
+ branchingsupport_base_safety_distance?: number
105
+ /** Support on build plate only — Only create support if it lies on a build plate. Don't create support on a print. */
106
+ branchingsupport_buildplate_only?: boolean
107
+ /** Critical angle — (°) — The default angle for connecting support sticks and junctions. */
108
+ branchingsupport_critical_angle?: number
109
+ /** Pinhead front diameter — (mm) — Diameter of the pointing side of the head */
110
+ branchingsupport_head_front_diameter?: number
111
+ /** Head penetration — (mm) — How much the pinhead has to penetrate the model surface */
112
+ branchingsupport_head_penetration?: number
113
+ /** Pinhead width — (mm) — Width from the back sphere center to the front sphere center */
114
+ branchingsupport_head_width?: number
115
+ /** Max bridge length — (mm) — The max length of a bridge */
116
+ branchingsupport_max_bridge_length?: number
117
+ /** Max bridges on a pillar — Maximum number of bridges that can be placed on a pillar. Bridges hold support point pinheads and connect to pillars as small branches. */
118
+ branchingsupport_max_bridges_on_pillar?: number
119
+ /** Max pillar linking distance — (mm) — The max distance of two pillars to get linked with each other. A zero value will prohibit pillar cascading. */
120
+ branchingsupport_max_pillar_link_distance?: number
121
+ /** Max weight on model — (mm) — Maximum weight of sub-trees that terminate on the model instead of the print bed. The weight is the sum of the lenghts of all branches emanating from the endpoint. */
122
+ branchingsupport_max_weight_on_model?: number
123
+ /** Object elevation — (mm) — How much the supports should lift up the supported object. If "Pad around object" is enabled, this value is ignored. */
124
+ branchingsupport_object_elevation?: number
125
+ /** Pillar connection mode — Controls the bridge type between two neighboring pillars. Can be zig-zag, cross (double zig-zag) or dynamic which will automatically switch between the first two depending on the distance of the two pillars. */
126
+ branchingsupport_pillar_connection_mode?: string
127
+ /** Pillar diameter — (mm) — Diameter in mm of the support pillars */
128
+ branchingsupport_pillar_diameter?: number
129
+ /** Pillar widening factor — Merging bridges or pillars into another pillars can increase the radius. Zero means no increase, one means full increase. The exact amount of increase is unspecified and can change in the future. */
130
+ branchingsupport_pillar_widening_factor?: number
131
+ /** Small pillar diameter percent — (%) — The percentage of smaller pillars compared to the normal pillar diameter which are used in problematic areas where a normal pilla cannot fit. */
132
+ branchingsupport_small_pillar_diameter_percent?: number
99
133
  /** Bridge — (mm/s² or %) — Acceleration of bridges. If the value is expressed as a percentage (e.g. 50%), it will be calculated based on the outer wall acceleration. */
100
134
  bridge_acceleration?: (number | string)[] | (number | string)
101
135
  /** External bridge infill direction — (°) — External Bridging angle override. If left to zero, the bridging angle will be calculated automatically for each specific bridge. Otherwise the provided angle will be used according to: - The absolute coordinates - The absolute coordinates + Model rotation: If Align directions to model is enabled - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled Use 180° for zero absolute angle. */
@@ -201,6 +235,12 @@ export interface SlicerSettings {
201
235
  default_print_profile?: string
202
236
  default_sla_material_profile?: string
203
237
  default_sla_print_profile?: string
238
+ /** (s) — Delay after exposure before layer separation. */
239
+ delay_after_exposure?: number[] | number
240
+ /** (s) — Sets a fixed pause before an exposure of the new layer starts. This setting is ignored if 'Dynamic delay before exposure' is enabled. */
241
+ delay_before_exposure?: number[] | number
242
+ /** (s) — Defines the pause between the separation movement (tilt down, Z-hop) and the return movement (tilt up). Increasing this time allows the resin more time to fully reflood the peeled-off layer. */
243
+ delay_to_reflood?: number[] | number
204
244
  /** Deretraction speed (extruder change) — (mm/s) — Speed for reloading filament into the nozzle when switching extruder. */
205
245
  deretract_speed_extruder_change?: number[] | number
206
246
  /** Deretraction speed — (mm/s) — Speed for reloading filament into the nozzle. Zero means same speed of retraction. */
@@ -235,6 +275,14 @@ export interface SlicerSettings {
235
275
  draft_shield?: 'disabled' | 'enabled'
236
276
  /** Fan speed — (%) */
237
277
  during_print_exhaust_fan_speed?: number[] | number
278
+ /** Switches between predefined algorithms that influence how the dynamic delay before exposure function behaves. */
279
+ dynamic_delay_before_profile?: string[] | string
280
+ /** Sets the maximum allowed time for waiting for the pressure sensors to stabilize during dynamic delay before exposure. Once this timeout expires, the printer starts exposing the next layer regardless of resin pressure stabilization. */
281
+ dynamic_delay_before_timeout?: number[] | number
282
+ /** Switches between predefined algorithms that influence how the dynamic tilt down function behaves. */
283
+ dynamic_tilt_down_profile?: string[] | string
284
+ /** Switches between predefined algorithms that influence how the dynamic tilt up function behaves. */
285
+ dynamic_tilt_up_profile?: string[] | string
238
286
  /** Absolute E position — Current position of the extruder axis. Only used with absolute extruder addressing. */
239
287
  e_position?: number[] | number
240
288
  /** Extra de-retraction — Currently planned extra extruder priming after de-retraction. */
@@ -651,6 +699,8 @@ export interface SlicerSettings {
651
699
  help?: boolean
652
700
  /** High extruder current on filament swap — It may be beneficial to increase the extruder motor current during the filament exchange sequence to allow for rapid ramming feed rates and to overcome resistance when loading a filament with an ugly shaped tip. */
653
701
  high_current_on_filament_swap?: boolean
702
+ /** High viscosity — (s) — Time of the super slow tilt */
703
+ high_viscosity_tilt_time?: number
654
704
  /** Convert holes to polyholes — Search for almost-circular holes that span more than one layer and convert the geometry to polyholes. Use the nozzle size and the (biggest) diameter to compute the polyhole. See http://hydraraptor.blogspot.com/2011/02/polyholes.html */
655
705
  hole_to_polyhole?: boolean
656
706
  /** Maximum Polyhole edge count — Maximum number of polyhole edges This setting limits the amount of edges a polyhole can have */
@@ -934,8 +984,12 @@ export interface SlicerSettings {
934
984
  material_correction_y?: number
935
985
  material_correction_z?: number
936
986
  material_density?: number
987
+ /** SLA print material notes — You can put your notes regarding the SLA print material here. */
988
+ material_notes?: string
937
989
  material_print_speed?: 'slow' | 'fast'
938
990
  material_type?: string
991
+ /** Material UUID (FOR DEBUGGING ONLY) */
992
+ material_uuid?: string
939
993
  material_vendor?: string
940
994
  /** Max bridge length — (mm) — This is the maximum length of bridges that don\'t need support. Set it to 0 if you want all bridges to be supported, and set it to a very large value if you don\'t want any bridges to be supported. */
941
995
  max_bridge_length?: number
@@ -1206,6 +1260,8 @@ export interface SlicerSettings {
1206
1260
  printhost_user?: string
1207
1261
  /** Between Object G-code — Insert G-code between objects. This parameter will only come into effect when you print your models object by object. */
1208
1262
  printing_by_object_gcode?: string
1263
+ /** Printing temperature — (°C) — This value sets the target printing temperature. The printer will wait for the resin to reach this stable temperature before starting and will maintain it throughout the print. When disabled, the printer ignores the resin's current temperature and begins printing immediately. */
1264
+ printing_temperature?: number
1209
1265
  /** Change extrusion role G-code (process) — This G-code is inserted when the extrusion role is changed. It runs after the machine and filament extrusion role G-code. */
1210
1266
  process_change_extrusion_role_gcode?: string
1211
1267
  /** Purge in prime tower — Purge remaining filament into prime tower. */
@@ -1348,7 +1404,11 @@ export interface SlicerSettings {
1348
1404
  skirt_start_angle?: number
1349
1405
  /** Skirt type — Combined - single skirt for all objects, Per object - individual object skirt. */
1350
1406
  skirt_type?: 'combined' | 'perobject'
1407
+ /** Format of the output SLA archive */
1408
+ sla_archive_format?: string
1351
1409
  sla_material_settings_id?: string
1410
+ /** it_opt->second.label — (it_opt->second.sidetext) — it_opt->second.tooltip */
1411
+ sla_output_precision?: number
1352
1412
  sla_print_settings_id?: string
1353
1413
  /** Slice — Slice the plates: 0-all plates, i-plate i, others-invalid */
1354
1414
  slice?: number
@@ -1441,6 +1501,8 @@ export interface SlicerSettings {
1441
1501
  support_critical_angle?: number
1442
1502
  /** Support critical regions only — Only create support for critical regions including sharp tail, cantilever, etc. */
1443
1503
  support_critical_regions_only?: boolean
1504
+ /** Support only in enforced regions — Only create support if it lies in a support enforcer. */
1505
+ support_enforcers_only?: boolean
1444
1506
  /** Normal support expansion — (mm) — Expand (+) or shrink (-) the horizontal span of normal support. */
1445
1507
  support_expansion?: number
1446
1508
  /** Support fast purge mode — Whether this printer supports fast purge mode with optimized temperature and multiplier. */
@@ -1485,6 +1547,8 @@ export interface SlicerSettings {
1485
1547
  support_max_bridge_length?: number
1486
1548
  support_max_bridges_on_pillar?: number
1487
1549
  support_max_pillar_link_distance?: number
1550
+ /** Max weight on model — (mm) — Maximum weight of sub-trees that terminate on the model instead of the print bed. The weight is the sum of the lenghts of all branches emanating from the endpoint. */
1551
+ support_max_weight_on_model?: number
1488
1552
  /** Support multi bed types — Enable this option if you want to use multiple bed types. */
1489
1553
  support_multi_bed_types?: boolean
1490
1554
  support_object_elevation?: number
@@ -1516,6 +1580,8 @@ export interface SlicerSettings {
1516
1580
  support_threshold_overlap?: number | string
1517
1581
  /** Top Z distance — (mm) — Z gap between the support\'s top and object. */
1518
1582
  support_top_z_distance?: number
1583
+ /** Support tree type — Support tree building strategy */
1584
+ support_tree_type?: string
1519
1585
  /** Type — Normal (auto) and Tree (auto) are used to generate support automatically. If Normal (manual) or Tree (manual) is selected, only support enforcers are generated. */
1520
1586
  support_type?: 'normal(auto)' | 'tree(auto)' | 'normal(manual)' | 'tree(manual)'
1521
1587
  supports_enable?: boolean
@@ -1541,6 +1607,38 @@ export interface SlicerSettings {
1541
1607
  thumbnails?: string
1542
1608
  /** Format of G-code thumbnails — Format of G-code thumbnails: PNG for best quality, JPG for smallest size, QOI for low memory firmware. */
1543
1609
  thumbnails_format?: 'PNG' | 'JPG' | 'QOI' | 'BTT_TFT' | 'COLPIC'
1610
+ /** Number of cycles to split the rest of the tilt down move. */
1611
+ tilt_down_cycles?: number[] | number
1612
+ /** (s) — The delay between tilt-down cycles. */
1613
+ tilt_down_delay?: number[] | number
1614
+ /** (μ-steps/s) — Sets the final speed for the tilt-down separation move. Too high a speed, especially with less viscous resins, can cause resin to splash out of the tank. */
1615
+ tilt_down_finish_speed?: string[] | string
1616
+ /** (μ-steps/s) — Tilt speed used for the rest of the tilt down move. */
1617
+ tilt_down_finish_speed_slx?: string[] | string
1618
+ /** (μ-steps/s) — Sets the initial speed for the tilt-down separation move. A high speed may negatively affect print quality or success, especially with certain resins or delicate geometries, but it speeds up the overall print time. */
1619
+ tilt_down_initial_speed?: string[] | string
1620
+ /** (μ-steps/s) — Tilt speed used for an initial portion of tilt down move. */
1621
+ tilt_down_initial_speed_slx?: string[] | string
1622
+ /** (s) — Delay after the tilt reaches 'tilt_down_offset_steps' position. */
1623
+ tilt_down_offset_delay?: number[] | number
1624
+ /** (μ-steps) — Defines the distance (steps) over which the 'Tilt down initial speed' is applied. Once this distance is covered, the tilt moves at the 'Tilt down finish speed'. Setting to 0 immediately applies the finish speed. Maximum distance varies by printer, typically around 12,000 steps. */
1625
+ tilt_down_offset_steps?: number[] | number
1626
+ /** Number of cycles to split the rest of the tilt-up. */
1627
+ tilt_up_cycles?: number[] | number
1628
+ /** (s) — The delay between tilt-up cycles. */
1629
+ tilt_up_delay?: number[] | number
1630
+ /** (μ-steps/s) — Sets the final speed for the tilt-up return movement. Excessive speed, especially with highly viscous resins, can lead to a loss of print quality, or in extreme cases, tilt motor skipping or damage to the print display. */
1631
+ tilt_up_finish_speed?: string[] | string
1632
+ /** (μ-steps/s) — Tilt speed used for the rest of the tilt-up. */
1633
+ tilt_up_finish_speed_slx?: string[] | string
1634
+ /** (μ-steps/s) — Sets the initial speed for the tilt-up return movement. */
1635
+ tilt_up_initial_speed?: string[] | string
1636
+ /** (μ-steps/s) — Tilt speed used for an initial portion of tilt up move. */
1637
+ tilt_up_initial_speed_slx?: string[] | string
1638
+ /** (s) — Delay after the tilt reaches 'tilt_up_offset_steps' position. */
1639
+ tilt_up_offset_delay?: number[] | number
1640
+ /** (μ-steps) — Defines the distance over which the 'Tilt up initial speed' is applied. After this distance, the tilt moves at the 'Tilt up finish speed'. Setting to 0 immediately applies the finish speed. */
1641
+ tilt_up_offset_steps?: number[] | number
1544
1642
  /** Time cost — (money/h) — The printer cost per hour. */
1545
1643
  time_cost?: number
1546
1644
  /** Timelapse G-code */
@@ -1597,6 +1695,10 @@ export interface SlicerSettings {
1597
1695
  total_wipe_tower_cost?: number
1598
1696
  /** Wipe tower volume — Total filament volume extruded on the wipe tower. */
1599
1697
  total_wipe_tower_filament?: number
1698
+ /** (mm) — An alternative separation move to tilting. After layer exposure, the platform lifts by this distance. A minimum of 5mm is recommended if tilting is disabled. If you use tilting, we suggest 0mm, although a combination of both is possible. */
1699
+ tower_hop_height?: number[] | number
1700
+ /** (mm/s) — Tower speed used for tower raise. */
1701
+ tower_speed?: string[] | string
1600
1702
  /** Travel — (mm/s²) — Acceleration of travel moves. */
1601
1703
  travel_acceleration?: number[] | number
1602
1704
  /** Travel — (mm/s) — Jerk for travel. */
@@ -1649,6 +1751,8 @@ export interface SlicerSettings {
1649
1751
  use_firmware_retraction?: boolean
1650
1752
  /** Use relative E distances — Relative extrusion is recommended when using "label_objects" option. Some extruders work better with this option unchecked (absolute extrusion mode). Wipe tower is only compatible with relative mode. It is recommended on most printers. Default is checked. */
1651
1753
  use_relative_e_distances?: boolean
1754
+ /** Enables or disables the tilting function. If disabled, the layer separation is performed using the 'Tower hop height' parameter. */
1755
+ use_tilt?: boolean[] | boolean
1652
1756
  /** Used filament — Total length of filament used in the print. */
1653
1757
  used_filament?: number
1654
1758
  /** Filament length (meters) — Total filament length used in meters. Replaced with actual value during post-processing. */
@@ -1741,6 +1845,8 @@ export interface SlicerSettings {
1741
1845
  zaa_min_z?: number
1742
1846
  /** Minimize wall height angle — (°) — Reduce the height of top-surface perimeters to match the model edge height. Affects perimeters with a slope less than this angle (degrees). A reasonable value is 35. Set to 0 to disable. */
1743
1847
  zaa_minimize_perimeter_height?: number
1848
+ /** Z compensation — Number of layers to Z correct to avoid cross layer bleed */
1849
+ zcorrection_layers?: number
1744
1850
  /** Current Z-hop — Contains Z-hop present at the beginning of the custom G-code block. */
1745
1851
  zhop?: number
1746
1852
  }
@@ -19,6 +19,27 @@ export function settingScalar(settings: SlicerSettings | null | undefined, key:
19
19
  */
20
20
  export function deriveKernelParams(settings: SlicerSettings | null | undefined, opts?: { plate?: number }): Record<string, unknown>
21
21
 
22
+ /** Which slicing technology the settings map's printer profile declares. Defaults to FFF. */
23
+ export function printerTechnology(settings: SlicerSettings | null | undefined): 'FFF' | 'SLA'
24
+
25
+ /**
26
+ * Settings map -> SLA (resin) slice params for the pure-JS contour slicer + the display geometry the SL1 raster
27
+ * export needs. Separate from deriveKernelParams — that one feeds the WASM kernel and its key set is pinned.
28
+ */
29
+ export function deriveSlaParams(settings: SlicerSettings | null | undefined): {
30
+ layer_height: number
31
+ initial_layer_height: number
32
+ exposure_time: number
33
+ initial_exposure_time: number
34
+ faded_layers: number
35
+ display_width: number
36
+ display_height: number
37
+ display_pixels_x: number
38
+ display_pixels_y: number
39
+ supports_enable: boolean
40
+ pad_enable: boolean
41
+ }
42
+
22
43
  /**
23
44
  * A 3mf project's raw `Metadata/project_settings.config` -> a settings map this API accepts.
24
45
  * Upstream writes every option as a string ("0"/"1" for a bool, "0.2" for a float, one entry per extruder for a
@@ -109,6 +130,19 @@ export const printerKeys: string[]
109
130
  /** Vendor -> profile name -> entry, straight from the data. For building a picker. */
110
131
  export const printersByVendor: Record<string, Record<string, PrinterEntry>>
111
132
 
133
+ /** Vendor -> slicing technology. Absent means FFF; only the resin vendor bundles are marked. */
134
+ export const printerTechByVendor: Record<string, 'SLA' | 'FFF'>
135
+
136
+ /** The resin material catalog (SLA vendor bundles, inherits flattened). `layerHeight` is the preset's
137
+ * compatibility condition reduced to a number. */
138
+ export const resinCatalog: Array<{
139
+ name: string; bundle: string; type: string; vendor: string; colour: string
140
+ exposure_time?: number; initial_exposure_time?: number; initial_layer_height?: number; layerHeight?: number
141
+ }>
142
+
143
+ /** The settings a resin material applies (exposure family + the remembered pick). `null` when unknown. */
144
+ export function resinSettingsFor(name: string): SlicerSettings | null
145
+
112
146
  /** The settings a printer profile applies, ready to merge. `null` when the name is unknown. */
113
147
  export function printerSettings(profileName: string): SlicerSettings | null
114
148
 
package/types/sla.d.ts ADDED
@@ -0,0 +1,167 @@
1
+ import type { SlicerSettings } from './settings-keys.d.ts'
2
+
3
+ export type SlaSupportStrategy = 'default' | 'branching' | 'organic'
4
+ export type SlaCapability = 'defaultSupport' | 'branchingSupport' | 'organicSupport' | 'manualSupportPoints' | 'modifierVolumes' | 'pad' | 'correction' | 'hollowing' | 'drainHoles'
5
+ export type SlaCapabilityStatus = 'wasm-required' | 'unsupported' | 'single-object-contours-only'
6
+ export type SlaMatrix4 = readonly [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number]
7
+
8
+ export interface SlaSupportPoint {
9
+ readonly type: 'manual' | 'automatic' | 'island' | 'slope'
10
+ readonly position: readonly [number, number, number]
11
+ readonly radius?: number
12
+ readonly elevation?: number
13
+ readonly permanent?: boolean
14
+ readonly manual?: boolean
15
+ }
16
+
17
+ export interface SlaDrainHole {
18
+ readonly position: readonly [number, number, number]
19
+ readonly normal: readonly [number, number, number]
20
+ readonly radius: number
21
+ readonly height: number
22
+ }
23
+
24
+ export interface SlaModifierVolume {
25
+ readonly id: string
26
+ readonly kind: 'blocker' | 'enforcer'
27
+ readonly stl: ArrayBuffer | Uint8Array
28
+ readonly transform?: SlaMatrix4
29
+ readonly settings?: SlicerSettings
30
+ }
31
+
32
+ export interface SlaObjectInstance {
33
+ readonly id: string
34
+ readonly transform?: SlaMatrix4
35
+ readonly settings?: SlicerSettings
36
+ }
37
+
38
+ export interface SlaObject {
39
+ readonly id: string
40
+ readonly stl: ArrayBuffer | Uint8Array
41
+ readonly transform?: SlaMatrix4
42
+ readonly settings?: SlicerSettings
43
+ readonly instances?: readonly SlaObjectInstance[]
44
+ readonly supportPoints?: readonly SlaSupportPoint[]
45
+ readonly modifierVolumes?: readonly SlaModifierVolume[]
46
+ readonly drainHoles?: readonly SlaDrainHole[]
47
+ }
48
+
49
+ export interface SupportConfig {
50
+ readonly enabled?: boolean
51
+ readonly strategy?: SlaSupportStrategy
52
+ readonly enforcersOnly?: boolean
53
+ readonly headFrontDiameter?: number
54
+ readonly headPenetration?: number
55
+ readonly headWidth?: number
56
+ readonly pillarDiameter?: number
57
+ readonly smallPillarDiameterPercent?: number
58
+ readonly maxBridgesOnPillar?: number
59
+ readonly maxWeightOnModel?: number
60
+ readonly pillarConnectionMode?: 'zigzag' | 'cross' | 'dynamic'
61
+ readonly buildplateOnly?: boolean
62
+ readonly pillarWideningFactor?: number
63
+ readonly baseDiameter?: number
64
+ readonly baseHeight?: number
65
+ readonly baseSafetyDistance?: number
66
+ readonly criticalAngle?: number
67
+ readonly maxBridgeLength?: number
68
+ readonly maxPillarLinkDistance?: number
69
+ readonly objectElevation?: number
70
+ readonly branchingsupport_head_front_diameter?: number
71
+ readonly branchingsupport_head_penetration?: number
72
+ readonly branchingsupport_head_width?: number
73
+ readonly branchingsupport_pillar_diameter?: number
74
+ readonly branchingsupport_small_pillar_diameter_percent?: number
75
+ readonly branchingsupport_max_bridges_on_pillar?: number
76
+ readonly branchingsupport_max_weight_on_model?: number
77
+ readonly branchingsupport_pillar_connection_mode?: 'zigzag' | 'cross' | 'dynamic'
78
+ readonly branchingsupport_buildplate_only?: boolean
79
+ readonly branchingsupport_pillar_widening_factor?: number
80
+ readonly branchingsupport_base_diameter?: number
81
+ readonly branchingsupport_base_height?: number
82
+ readonly branchingsupport_base_safety_distance?: number
83
+ readonly branchingsupport_critical_angle?: number
84
+ readonly branchingsupport_max_bridge_length?: number
85
+ readonly branchingsupport_max_pillar_link_distance?: number
86
+ readonly branchingsupport_object_elevation?: number
87
+ }
88
+
89
+ export interface PadConfig {
90
+ readonly enabled?: boolean
91
+ readonly wallThickness?: number
92
+ readonly wallHeight?: number
93
+ readonly brimSize?: number
94
+ readonly maxMergeDistance?: number
95
+ readonly wallSlope?: number
96
+ readonly aroundObject?: boolean
97
+ readonly aroundObjectEverywhere?: boolean
98
+ readonly objectGap?: number
99
+ readonly objectConnectorStride?: number
100
+ readonly objectConnectorWidth?: number
101
+ readonly objectConnectorPenetration?: number
102
+ }
103
+
104
+ export interface SlaCorrectionConfig {
105
+ readonly relative?: readonly [number, number]
106
+ readonly relativeX?: number
107
+ readonly relativeY?: number
108
+ readonly relativeZ?: number
109
+ readonly absolute?: number
110
+ readonly elephantFootMinWidth?: number
111
+ readonly zCorrectionLayers?: number
112
+ readonly closingRadius?: number
113
+ }
114
+
115
+ export interface SlaDisplayConfig {
116
+ readonly width?: number
117
+ readonly height?: number
118
+ readonly pixelsX?: number
119
+ readonly pixelsY?: number
120
+ readonly mirrorX?: boolean
121
+ readonly mirrorY?: boolean
122
+ readonly orientation?: 'landscape' | 'portrait'
123
+ readonly gamma?: number
124
+ readonly archiveFormat?: 'SL1'
125
+ }
126
+
127
+ export interface SlaHollowingConfig {
128
+ readonly enabled?: boolean
129
+ readonly minThickness?: number
130
+ readonly quality?: number
131
+ readonly closingDistance?: number
132
+ }
133
+
134
+ export interface SlaJob {
135
+ readonly version?: 1
136
+ readonly objects: readonly SlaObject[]
137
+ readonly settings?: SlicerSettings
138
+ readonly support?: SupportConfig
139
+ readonly pad?: PadConfig
140
+ readonly correction?: SlaCorrectionConfig
141
+ readonly display?: SlaDisplayConfig
142
+ readonly hollowing?: SlaHollowingConfig
143
+ readonly drainHoles?: readonly unknown[]
144
+ readonly requiredCapabilities?: readonly SlaCapability[]
145
+ }
146
+
147
+ export interface SlaCapabilities {
148
+ readonly defaultSupport: SlaCapabilityStatus
149
+ readonly branchingSupport: SlaCapabilityStatus
150
+ readonly organicSupport: SlaCapabilityStatus
151
+ readonly manualSupportPoints: SlaCapabilityStatus
152
+ readonly modifierVolumes: SlaCapabilityStatus
153
+ readonly pad: SlaCapabilityStatus
154
+ readonly correction: SlaCapabilityStatus
155
+ readonly hollowing: SlaCapabilityStatus
156
+ readonly drainHoles: SlaCapabilityStatus
157
+ readonly jsFallback: SlaCapabilityStatus
158
+ }
159
+
160
+ export type SlaErrorCode = 'SLA_INVALID_REQUEST' | 'SLA_UNSUPPORTED_ORGANIC' | 'SLA_UNSUPPORTED_HOLLOWING' | 'SLA_FALLBACK_MULTI_OBJECT' | 'SLA_FALLBACK_SUPPORTS' | 'SLA_FALLBACK_PAD' | 'SLA_FALLBACK_OBJECT_CONTEXT'
161
+
162
+ export class SlaRequestError extends Error {
163
+ readonly code: SlaErrorCode
164
+ }
165
+
166
+ export const SLA_JOB_VERSION: 1
167
+ export const SLA_CAPABILITIES: SlaCapabilities
package/types/viewer.d.ts CHANGED
@@ -101,6 +101,8 @@ export type ViewportPanel =
101
101
  | 'bedWarn'
102
102
  /** The prime tower card. Only rendered anyway once a second filament exists. */
103
103
  | 'towerCard'
104
+ /** The resin (SLA) card. Takes the filament card's place when the printer profile declares SLA. */
105
+ | 'resinCard'
104
106
 
105
107
  /** Value changes reported through {@link ViewportProps.onEvent}. Not fired for the initial values. */
106
108
  export type ViewportEvent =
package/types/worker.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  // promises and is the easier way in; these types are here for hosts driving the worker directly, and because the
6
6
  // shape has traps that only a written-down contract makes visible — see the slice request and `erase`.
7
7
  import type { SliceResult } from '../engine/index.d.ts'
8
+ import type { SlaErrorCode, SlaJob } from './sla.d.ts'
8
9
 
9
10
  /** Brush geometry shared by paint and erase: the hit facet, the hit point, the camera, the radius. */
10
11
  export interface BrushArgs {
@@ -55,6 +56,13 @@ export type SlicerRequest =
55
56
  | { cmd: 'clear'; states?: PaintState[] }
56
57
  /** The painted overlay triangles. `enf`/`blk` always; `states` adds those states. Reply: `overlay`. */
57
58
  | { cmd: 'overlay'; states?: PaintState[] }
59
+ /**
60
+ * Legacy single-object SLA (resin) slice. `params` accepts a JSON string or an object (this path parses either). Same reply stream as
61
+ * a slice: `progress` and `layer` while it runs, then `done` (stats only; layers arrived as `layer`) — or `error`.
62
+ */
63
+ | { cmd: 'sla'; stl: ArrayBuffer; params: string | object }
64
+ /** Object-aware SLA protocol. The worker preserves the ordered objects; it never merges them for a fallback. */
65
+ | { cmd: 'slaJob'; job: SlaJob }
58
66
  /**
59
67
  * Slice — and note it carries **no `cmd`**: slicing is the worker's default action, and leaving the field off
60
68
  * is what selects it. `params` must be a JSON **string**; the worker hands it straight to the kernel, which
@@ -85,6 +93,6 @@ export type SlicerResponse =
85
93
  | { type: 'layer'; z: number; idx: number; gcode: string; paths: Float32Array; widths: Float32Array }
86
94
  /** `result.stats.streamed` says whether the G-code came through `layer` messages or is on the result. */
87
95
  | { type: 'done'; result: SliceResult }
88
- | { type: 'error'; error: string }
96
+ | { type: 'error'; error: string; code?: SlaErrorCode }
89
97
 
90
98
  export {}
package/viewer/README.md CHANGED
@@ -63,7 +63,13 @@ Every panel can be switched off, and the values the component owns can be seeded
63
63
  - **`panels`** — `{name: false}` hides one. Everything is visible by default, so a host only ever opts out and a
64
64
  panel added in a later version does not vanish for hosts that listed the ones they wanted. `sidebar: false` drops
65
65
  the whole right column; the rest are `topBar`, `gizmoRail`, `objectToolbar`, `paintPanel`, `statsCard`, `plateBar`,
66
- `emptyHint`, `status`, `printerCard`, `filamentCard`, `objectList`, `previewControls`, `processCard`, `sliceBar`.
66
+ `emptyHint`, `status`, `printerCard`, `filamentCard`, `resinCard`, `objectList`, `previewControls`, `processCard`,
67
+ `sliceBar`. Which of `filamentCard`/`resinCard` renders follows the printer profile's technology: a profile whose
68
+ `printer_technology` says SLA swaps the filament card (and the prime tower, and the painting brushes) for the
69
+ resin card, and slicing routes to the kernel's `slice_sla` — PrusaSlicer's ported support/pad chain — with an
70
+ `.sl1` export instead of G-code (portrait masks, like every SL1-family machine). The preview lifts the model by
71
+ `stats.lift_layers` (pad + elevation), and a request the port does not cover (hollowing, organic trees)
72
+ surfaces as a typed error instead of a wrong print.
67
73
  - **`gcode`** — G-code text drawn on the selected plate instead of a slice result. `parseGcode` recovers roles from
68
74
  `;TYPE:` (OrcaSlicer/PrusaSlicer/Cura), from `;_EXTRUSION_ROLE:` tags and from this kernel's own feature comments;
69
75
  bead width comes from `;WIDTH:` or, absent that, from E. What the file never states cannot be recovered: an