three-slicer 0.3.1 → 0.3.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,176 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.3 — 2026-10-01
4
+
5
+ ### Added
6
+
7
+ - The layer contours can be computed on the GPU. The viewer's slice bar has a GPU select (`gpu_acceleration`:
8
+ `auto`, `on`, `off`), and the worker's slice message takes `gpu: true`. `auto` uses it on the single-threaded
9
+ kernel only, where a 3M-facet slice went from 9.8 to 7.6 s; the threaded kernel gains nothing measurable. A GPU
10
+ slice's G-code differs from the CPU slice's in its vertices (same contour area), and the result's
11
+ `stats.contour_engine` says which engine ran.
12
+ - On the single-threaded kernel the GPU also cuts the mesh into layers and chains the loops (`stats.contour_front`
13
+ `'gpu'`; the slice card reads "Contours cut and unioned on the GPU"). The kernel hands its mesh over instead of
14
+ cutting every layer itself: on a 3M-facet model that part went from 419-442 ms to 34-154 ms plus 64-153 ms on the
15
+ GPU. A layer the GPU cannot close is cut by the kernel as before.
16
+ - `support_style` `tree_slim`, `tree_strong` and `tree_hybrid` reach the kernel as `tree_style`. They used to slice
17
+ as organic.
18
+
19
+ ### Changed
20
+
21
+ - The threaded kernel ships its wasm as a file, `engine/src/slicer_core.mt.wasm`, instead of inlining it in
22
+ `slicer_core.mt.js` (6.4 MB -> 107 KB). Every pthread worker loads the glue, and the inlined bytes cost each of
23
+ them about 60 MB of V8 heap; Chrome holds every isolate of a tab in one 4 GB heap region, so slicing several plates
24
+ at once crashed the tab ("V8 javascript OOM"; 3 workers on a 6-plate project: 4 crashes in 6 runs). With the file,
25
+ 3 to 8 workers ran without a crash and peaked at 1.2-1.9 GB. A bundler emits the file as an asset; see
26
+ "Multithreaded WASM" in the README for serving it.
27
+ - Tree support (slim, strong, hybrid) runs four of its loops on every thread of the threaded kernel: a 1.13M-facet
28
+ hybrid plate went from 91 to 21 s, with the same G-code as the single-threaded kernel.
29
+ - Tree support unions each layer's support circles per group of overlapping circles instead of all at once. On the
30
+ same plate the slice went from 21.2-21.6 to 18.9-19.0 s (threaded) and from 110.3 to 98.0 s (single-threaded).
31
+ The support area is unchanged; its G-code vertices come out in another order (support extrusion 4113.49 ->
32
+ 4113.50 mm, every model path unchanged).
33
+ - Tree support finds overhangs on every thread of the threaded kernel (it ran on one): on the same plate the slice
34
+ went from 18.6-18.9 to 17.6-17.7 s, with the same G-code.
35
+ - Tree support no longer recomputes the same offsets while it drops branches and groups overhangs (a dilation per
36
+ node move, a whole-layer line clip per segment, a region offset per cluster tried): on the same plate the slice
37
+ went from 17.1-17.3 to 15.5-15.6 s, with the same G-code.
38
+ - Tree support's threads no longer queue on two locks while they move branches (one over the line-cut cache, one
39
+ around every new node), the branch spanning trees are built in one pass per vertex and per part on threads, and the
40
+ layer outlines are prepared beside overhang detection instead of after it: on the same plate 15.6 -> 13.9-14.1 s,
41
+ then 10.2-10.3 -> 9.7-9.8 s, with the same G-code.
42
+ - Tree support unions each group of overlapping circles as a tree of smaller unions, split by position: draw_circles
43
+ 4.6 -> 2.3 s on the same plate (11.6-11.8 s slice). The support area is the same; the intermediate unions round
44
+ their crossings once more, so the support G-code moves slightly (support extrusion 4113.50 -> 4113.56 mm, the worst
45
+ layer 0.27 %, every model path unchanged). Clipper2's union measured slower and is not used.
46
+ - Arachne walls are written by the threaded kernel's G-code writers like every other path (they were written on one
47
+ thread): on the same plate emit 3.2 -> 1.7 s (11.7 -> 10.2 s slice), with the same G-code, toolpaths and widths as
48
+ the single-threaded kernel.
49
+
50
+ - The toolpath preview culls back faces and, far from the camera, draws every 2nd or 4th layer that many layers
51
+ thick (raft and skirt layers and a cut layer range keep full detail). Measured on a 6-plate project with 14.6M
52
+ segments: 67.8 -> 34.8 ms per frame, the overview 27.6 -> 9.6 ms.
53
+ - Switching plates no longer recolours every plate or builds the focused plate's G-code Blob (332-574 ms -> no task
54
+ over 50 ms). "Export G-code" builds its plain `.gcode` on click and hands it to the host's `onExport` like the other
55
+ exports; it used to be a prefilled download link that bypassed `onExport`.
56
+ - A 3mf loads with each part inflated by `DecompressionStream`, read from its bytes and baked (normals, bounds) in
57
+ the parse worker, with the build items spread over copies of that worker: 1338-1352 -> 367-372 ms on a 52 MB
58
+ project, with the same meshes. zip64 and encrypted archives keep the previous reader.
59
+
60
+ ### Fixed
61
+
62
+ - A click on a plate in Preview did nothing; it now selects the plate.
63
+ - Tree support could lose a whole support island's paths on a layer: reordering a layer's paths dropped any group of
64
+ paths whose first or last member was empty, with every path in it (a 3M-facet tree-slim model lost 64.6 mm of
65
+ support paths over three layers). Only the empty members are dropped now. Models where it did not happen slice to
66
+ the same G-code.
67
+ - Tree slim, strong and hybrid crashed the kernel on any model.
68
+ - The same tree slim or strong input could slice to different G-code from run to run (a tie in the minimum spanning
69
+ tree was broken by memory address).
70
+ - A Bambu Lab X2D or H2D project failed every slice with `CUSTOM_GCODE_ERROR`: the start G-code reads
71
+ `first_filaments` and `first_non_support_filaments` per physical nozzle, which were missing or not mapped.
72
+ - A plate whose objects are all on one filament other than the first printed with filament 1: the start G-code
73
+ loaded it (`M620 S0A` on a Bambu Lab printer) and its temperature, flow and retraction were used. The kernel
74
+ takes `single_tool`, which the viewer sends for such a plate, and prints with that filament's values; the
75
+ start and end G-code see it as `initial_extruder` / `current_extruder` and the footer reports its use.
76
+
77
+ ## 0.3.2 — 2026-09-21
78
+
79
+ ### Added
80
+
81
+ - The prime tower is set per plate. The Prime tower card carries the same Global | Plate switch as the Process,
82
+ Printer and Filament cards: in plate scope its mode, width, purge destination and purging table become that
83
+ plate's override. The position was already per plate (`wipe_tower_x/y[plate]`) and stays in the global map.
84
+ - A saved `.3mf` carries the per-plate overrides and the global map's non-schema keys (`wipe_tower_real`,
85
+ `sla_antialias`) in a member of its own, `Metadata/three_slicer_settings.json`, and an import restores them.
86
+ Upstream has no place for either and ignores the member, so OrcaSlicer still opens the file on the global preset.
87
+ - The kernel can tag every extrusion run with upstream's `;TYPE:` (`gcode_role_tags`, opt-in; the viewer turns it
88
+ on), from the same role the preview draws. A saved G-code read back as text colours as the slice did.
89
+ - "Export all" writes one `.gcode.3mf` (upstream's "Export all plate sliced file") instead of one `.gcode` download
90
+ per plate: each plate's G-code as `Metadata/plate_N.gcode` with its MD5, the estimate in `slice_info.config`, no
91
+ meshes. Opening one (drop, picker or `files`) puts every plate's G-code back on its plate and makes the viewer
92
+ preview-only until it is closed from the top bar or a model is loaded. The `gcode` prop also takes a
93
+ `{ plateIndex: text }` map. A resin plate still exports as its own `.sl1`.
94
+ - The sidebar's Export G-code button saves every sliced plate in one `.gcode.3mf` (upstream's "Export all sliced
95
+ file"). Its ▾ menu holds the viewed plate alone as a `.gcode.3mf` and the plain `.gcode`. It also works on an
96
+ opened `.gcode.3mf`, so a print job can be saved again.
97
+
98
+ - The Open button and the drop target take a plain `.gcode` / `.gco` / `.g`. It opens on the selected plate
99
+ through the same path a `.gcode.3mf` takes: the top bar names it and closes it. A file with no printable move is
100
+ refused before it opens. The demo app's own Open G-code button is gone.
101
+ - An exported G-code states its filament colours (`; filament_colour` in the config block, where upstream reads
102
+ settings), so it opens in its colours here and in OrcaSlicer. A file that already states a palette keeps it; the
103
+ kernel's G-code itself is unchanged.
104
+
105
+ ### Changed
106
+
107
+ - The ring / real tower choice is the settings key `wipe_tower_real` (a viewer knob, like `sla_antialias`) instead
108
+ of component state, so it follows plate overrides and survives a save. Absent means the ring, as before.
109
+ - The tower stand-ins are decided per plate: a plate gets one only when it changes tools itself, and each plate
110
+ draws its own width and on/off. A dragged or typed tower position is kept on the bed.
111
+ - The tower stand-in is selected alone and only translated. It no longer joins a multi-selection, takes a
112
+ rotate/scale gizmo, or adds an undo entry that undid nothing.
113
+
114
+ ### Fixed
115
+
116
+ - An opened multi-material G-code drew its model as prime tower in the Feature view: the multi-material path wrote
117
+ no role marks, so everything after a tower's comment inherited it until the next layer.
118
+ - A loaded G-code was drawn in the session's palette instead of its own. The Filament view reads each plate's
119
+ palette from its result (the file's, with the session's filling the holes), and every tool the result used gets
120
+ a colour, so a file with more tools than the session has filaments no longer shows T3 in three different colours
121
+ across the toolpath, the stats card and the legend. The G-code reader reports per-tool filament
122
+ (`filament_mm_by_tool`).
123
+ - The drop overlay and the load-rejection message listed STL/OBJ/3MF/AMF/PLY by hand: neither named STEP, which the
124
+ demo registers, and the overlay named neither SL1 nor G-code. Both now read `SUPPORTED_EXT`.
125
+ - The G-code reader dropped a `;TYPE:` written between a layer marker and the layer's first move (Cura's
126
+ `;LAYER:` files, this kernel's raft layers), reading that run as wall.
127
+ - The drop highlight stayed on after a drop the host handled itself (the demo app's `.gcode` drop): the canvas's
128
+ own handler never ran and a drop fires no `dragleave`. The window's capture phase now clears it.
129
+ - Injected G-code moved half a bed off its plate whenever the plate grid was re-laid out (adding a plate, editing
130
+ the bed): the re-layout set every display offset to the plate origin, dropping the bed-corner offset injected
131
+ G-code carries. Offsets now move by the origin's delta.
132
+ - Two objects on the same spot sliced to nothing. The kernel slices the merge of every object as one mesh and filled
133
+ the layer loops even-odd, so coincident shells counted as "inside twice". Segments are now oriented by the facet
134
+ normal and filled NonZero, upstream's Regular slicing mode, in the FFF, multi-material and SLA paths. Measured: a
135
+ project imported twice printed 1,210 mm of a 42,984 mm model before, the full model now. Clean meshes slice the
136
+ same regions (0 area difference on the fixtures, under 0.0003 mm² per layer on the Benchy), but a loop can start
137
+ at a different vertex, so G-code of models other than the golden fixtures may differ in point order.
138
+ - A saved `.3mf` with a tower position on some plates and automatic placement on others wrote `null` into
139
+ `wipe_tower_x/y`. OrcaSlicer's loader stops reading the whole file at an array entry that is not a string, which
140
+ dropped the 17 settings after it, `z_hop` and `z_offset` among them. The hole is now written as the schema default
141
+ for upstream and kept as a hole in `Metadata/three_slicer_settings.json`.
142
+ - The GPU SL1 mask path (`sla_antialias`, `sl1_parity_gpu.js`) counted surfaces above the plane as a parity, so two
143
+ coincident objects came out empty in the masks while the slice and its supports treated them as solid. The count
144
+ is now signed by facing (NonZero), the kernel's fill rule.
145
+ - Painting one plate and then another discarded the first plate's paint, and a copy placed where the original sits on
146
+ its own plate took the original's paint over (the original then sliced single-material, the copy printed both).
147
+ Paint now lives on each object (`core/paint_store.js`): the selector is written back to it before it switches
148
+ mesh and loaded from it after; slice-all pool workers load their plate's paint; a 3mf save writes every plate's
149
+ brush strokes (it used to save them only for a single-plate project); copy, duplicate and paste carry the paint,
150
+ and a split hands each part the marks on its own facets.
151
+ - A brush stroke painted only the first object of the plate being painted: the hit facet was sent in the hit
152
+ object's own numbering, not the plate merge's. A stroke now also carries across plates — reaching an object on
153
+ another plate selects that plate and keeps painting there, and an object added to the plate while the brush is
154
+ open is painted too.
155
+ - Dragging a painted object no longer drags the paint of the other objects on its plate along with it.
156
+ - A paste pressed right after a copy pastes that copy; a double-pressed delete records one undo step; a drag
157
+ committed while a slice loads its plate's paint no longer reaches the worker before that slice.
158
+ - A paint export the worker fails no longer discards the unsaved strokes (the swap stops instead), and Clear
159
+ pressed during a plate switch clears the plate it lands on instead of doing nothing. Strokes made right after
160
+ switching between the support and material brushes are no longer saved as the other kind of paint.
161
+ - Switching between the support and material brushes with the section plane on no longer leaves the kernel a
162
+ shifted plane on plates past the first; support-only paint stays drawn after a drag on its plate; a slice that
163
+ leaves support paint out under material paint says so again.
164
+ - Paint for a filament that is not configured (T3 painted, then the list cut to two) no longer widens the extruder
165
+ count on a slice-all pool worker only; every path leaves it out and the slice says so.
166
+ Every plate's paint stays drawn, not only the plate being painted.
167
+ - Review fixes to the paint store, each reproduced before the fix: a slice-all pool worker printed the previous
168
+ plate's paint on an unpainted plate; opening the support brush filed another plate's material paint as support
169
+ paint; a 3mf save wrote every object under one paint attribute and let an empty support map hide material paint;
170
+ a worker replaced by the watchdog wiped the stored paint of the plate it held; and a save waiting on a worker
171
+ that was then terminated stayed on "Saving…" with the viewport blank. Worker replies now echo a `requestId`, so
172
+ an error reply ends only the request it belongs to.
173
+
3
174
  ## 0.3.1 — 2026-09-16
4
175
 
5
176
  ### Added
package/README.md CHANGED
@@ -679,6 +679,11 @@ Cross-Origin-Embedder-Policy: require-corp
679
679
 
680
680
  Without those headers, the engine falls back to the single-threaded kernel.
681
681
 
682
+ The multithreaded kernel's wasm is a file beside its glue, `engine/src/slicer_core.mt.wasm`, reached through
683
+ `new URL('slicer_core.mt.wasm', import.meta.url)`; Vite and webpack emit it as an asset. Serve it as
684
+ `application/wasm`, and from another origin (a CDN) with `Cross-Origin-Resource-Policy: cross-origin`, or the
685
+ cross-origin isolated page cannot load it. The single-threaded kernel still inlines its wasm.
686
+
682
687
  ## Data Files
683
688
 
684
689
  The package includes extracted OrcaSlicer metadata for custom interfaces:
@@ -737,6 +742,7 @@ the layout by hand.
737
742
  | `printerSettings(name)` | Settings a vendor machine profile applies |
738
743
  | `printerKeys` | Every key a printer profile can set — clear these before applying another |
739
744
  | `printerDefaultPreset(name)` | The vendor's recommended process preset for that printer |
745
+ | `printerDefaultBedType(name)` | The bed type the printer's model defaults to — the viewer writes it to `curr_bed_type` on a pick |
740
746
  | `machineLimitKeys` | The schema keys the kernel's machine limits are read from |
741
747
  | `processPresets()` | Lazy facade over the print (process) preset catalog |
742
748
  | `filamentPresets()` | Lazy facade over the material preset catalog |