three-slicer 0.2.3 → 0.2.5

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.
@@ -1,10 +1,10 @@
1
- import { s as p, d as c } from "./sl1_write-UHmQ_itC.js";
2
- self.onmessage = async ({ data: { indices: f, paths: n, params: o } }) => {
3
- const a = p(o), r = new OffscreenCanvas(a.px, a.py), e = r.getContext("2d"), t = [];
4
- for (let s = 0; s < f.length; s++) {
5
- e.fillStyle = "#000", e.fillRect(0, 0, a.px, a.py), e.fillStyle = "#fff", c(e, n[s], a);
6
- const l = await r.convertToBlob({ type: "image/png" });
7
- t.push(new Uint8Array(await l.arrayBuffer())), (s & 7) === 7 && self.postMessage({ progress: s + 1 });
1
+ import { zlibSync as p } from "three/examples/jsm/libs/fflate.module.js";
2
+ import { s as m, r as l, e as g } from "./sl1_write-CtX8cVL7.js";
3
+ self.onmessage = async ({ data: { indices: r, paths: o, params: t, aa: f } }) => {
4
+ const a = m(t), e = [];
5
+ for (let s = 0; s < r.length; s++) {
6
+ const n = l(o[s], a, f || 1);
7
+ e.push(await g(n, a.px, a.py, { deflate: p })), (s & 7) === 7 && self.postMessage({ progress: s + 1 });
8
8
  }
9
- self.postMessage({ indices: f, pngs: t }, t.map((s) => s.buffer));
9
+ self.postMessage({ indices: r, pngs: e }, e.map((s) => s.buffer));
10
10
  };
@@ -0,0 +1,302 @@
1
+ import { strToU8 as I, zipSync as z, zlibSync as O } from "three/examples/jsm/libs/fflate.module.js";
2
+ let M = !0;
3
+ function it(t) {
4
+ M = !!t;
5
+ }
6
+ const j = {
7
+ info: (...t) => {
8
+ M && console.info(...t);
9
+ },
10
+ warn: (...t) => {
11
+ M && console.warn(...t);
12
+ },
13
+ error: (...t) => {
14
+ M && console.error(...t);
15
+ }
16
+ };
17
+ function X(t) {
18
+ const e = [];
19
+ let n = null;
20
+ for (let r = 0; r < t.length; r += 8) {
21
+ const a = t[r], f = t[r + 1], l = t[r + 4], s = t[r + 5];
22
+ n && Math.abs(n.lx - a) < 1e-6 && Math.abs(n.ly - f) < 1e-6 ? (n.pts.push(l, s), n.lx = l, n.ly = s) : (n = { pts: [a, f, l, s], lx: l, ly: s }, e.push(n));
23
+ }
24
+ return e.map((r) => r.pts);
25
+ }
26
+ function R(t, e, n, r, a, f) {
27
+ const l = new Array(n).fill(null);
28
+ for (const c of t) {
29
+ const i = c.length / 2;
30
+ for (let o = 0; o < i; o++) {
31
+ const d = (o + 1) % i;
32
+ let u = r(c[o * 2], c[o * 2 + 1]), p = a(c[o * 2], c[o * 2 + 1]), g = r(c[d * 2], c[d * 2 + 1]), w = a(c[d * 2], c[d * 2 + 1]);
33
+ if (p === w) continue;
34
+ if (p > w) {
35
+ const y = u;
36
+ u = g, g = y;
37
+ const b = p;
38
+ p = w, w = b;
39
+ }
40
+ const m = Math.max(0, Math.ceil(p - 0.5));
41
+ if (m >= n || w < 0.5) continue;
42
+ const _ = { x: u + (m + 0.5 - p) / (w - p) * (g - u), dx: (g - u) / (w - p), yEnd: w };
43
+ (l[m] ?? (l[m] = [])).push(_);
44
+ }
45
+ }
46
+ const s = [];
47
+ for (let c = 0; c < n; c++) {
48
+ const i = c + 0.5;
49
+ l[c] && s.push(...l[c]);
50
+ for (let o = s.length - 1; o >= 0; o--) s[o].yEnd <= i && s.splice(o, 1);
51
+ s.sort((o, d) => o.x - d.x);
52
+ for (let o = 0; o + 1 < s.length; o += 2) {
53
+ const d = Math.max(0, Math.ceil(s[o].x - 0.5)), u = Math.min(e - 1, Math.floor(s[o + 1].x - 0.5));
54
+ u >= d && f(c, d, u);
55
+ }
56
+ for (const o of s) o.x += o.dx;
57
+ }
58
+ }
59
+ function Y(t, e, n = 1) {
60
+ const { px: r, py: a } = e, f = X(t), l = new Uint8Array(r * a);
61
+ if (n <= 1)
62
+ return R(
63
+ f,
64
+ r,
65
+ a,
66
+ (i, o) => e.map(i, o)[0],
67
+ (i, o) => e.map(i, o)[1],
68
+ (i, o, d) => {
69
+ l.fill(255, i * r + o, i * r + d + 1);
70
+ }
71
+ ), l;
72
+ const s = new Uint16Array(r * a);
73
+ R(
74
+ f,
75
+ r * n,
76
+ a * n,
77
+ (i, o) => e.map(i, o)[0] * n,
78
+ (i, o) => e.map(i, o)[1] * n,
79
+ (i, o, d) => {
80
+ const u = i / n | 0;
81
+ for (let p = o; p <= d; p++) s[u * r + (p / n | 0)]++;
82
+ }
83
+ );
84
+ const c = n * n;
85
+ for (let i = 0; i < s.length; i++) l[i] = Math.round(s[i] * 255 / c);
86
+ return l;
87
+ }
88
+ const G = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]), W = (() => {
89
+ const t = new Uint32Array(256);
90
+ for (let e = 0; e < 256; e++) {
91
+ let n = e;
92
+ for (let r = 0; r < 8; r++) n = n & 1 ? 3988292384 ^ n >>> 1 : n >>> 1;
93
+ t[e] = n >>> 0;
94
+ }
95
+ return t;
96
+ })(), H = (t) => {
97
+ let e = 4294967295;
98
+ for (let n = 0; n < t.length; n++) e = W[(e ^ t[n]) & 255] ^ e >>> 8;
99
+ return (e ^ 4294967295) >>> 0;
100
+ }, E = (t, e) => {
101
+ const n = new Uint8Array(12 + e.length), r = new DataView(n.buffer);
102
+ r.setUint32(0, e.length);
103
+ for (let f = 0; f < 4; f++) n[4 + f] = t.charCodeAt(f);
104
+ n.set(e, 8);
105
+ const a = n.subarray(4, 8 + e.length);
106
+ return r.setUint32(8 + e.length, H(a)), n;
107
+ }, Z = async (t) => {
108
+ const e = new CompressionStream("deflate"), n = [], r = (async () => {
109
+ const c = e.readable.getReader();
110
+ for (; ; ) {
111
+ const { value: i, done: o } = await c.read();
112
+ if (o) break;
113
+ n.push(i);
114
+ }
115
+ })(), a = e.writable.getWriter();
116
+ await a.write(t), await a.close(), await r;
117
+ let f = 0;
118
+ for (const c of n) f += c.length;
119
+ const l = new Uint8Array(f);
120
+ let s = 0;
121
+ for (const c of n)
122
+ l.set(c, s), s += c.length;
123
+ return l;
124
+ };
125
+ async function q(t, e, n, r = {}) {
126
+ if (t.length !== e * n) throw new Error(`gray8: ${t.length} bytes for ${e}x${n}`);
127
+ const a = new Uint8Array(13), f = new DataView(a.buffer);
128
+ f.setUint32(0, e), f.setUint32(4, n), a[8] = 8, a[9] = 0;
129
+ const l = new Uint8Array(n * (1 + e));
130
+ for (let u = 0; u < n; u++) l.set(t.subarray(u * e, (u + 1) * e), u * (1 + e) + 1);
131
+ const s = typeof CompressionStream < "u" ? await Z(l) : r.deflate ? r.deflate(l) : (() => {
132
+ throw new Error("gray8: no CompressionStream and no deflate fallback injected");
133
+ })(), c = [G, E("IHDR", a), E("IDAT", s), E("IEND", new Uint8Array(0))];
134
+ let i = 0;
135
+ for (const u of c) i += u.length;
136
+ const o = new Uint8Array(i);
137
+ let d = 0;
138
+ for (const u of c)
139
+ o.set(u, d), d += u.length;
140
+ return o;
141
+ }
142
+ function J(t) {
143
+ const e = Number(t.display_width) > 0 ? Number(t.display_width) : 120.96, n = Number(t.display_height) > 0 ? Number(t.display_height) : 68.04, r = Number(t.display_pixels_x) > 0 ? Math.round(Number(t.display_pixels_x)) : 2560, a = Number(t.display_pixels_y) > 0 ? Math.round(Number(t.display_pixels_y)) : 1440, f = t.display_mirror_x !== !1, l = t.display_mirror_y === !0, s = (t.display_orientation ?? "portrait") !== "landscape", c = r / e, i = a / n, o = (u) => (f ? e / 2 - u : u + e / 2) * c, d = (u) => (l ? n / 2 - u : u + n / 2) * i;
144
+ return s ? {
145
+ px: a,
146
+ py: r,
147
+ mirrorX: f,
148
+ portrait: s,
149
+ // canvas columns run along the display's y axis, rows along the (mirrored) x axis
150
+ map: (u, p) => [d(p), o(u)]
151
+ } : {
152
+ px: r,
153
+ py: a,
154
+ mirrorX: f,
155
+ portrait: s,
156
+ map: (u, p) => [o(u), d(p)]
157
+ };
158
+ }
159
+ function K(t, e, n) {
160
+ const r = e.length / 8;
161
+ if (!r) return 0;
162
+ let a = 0;
163
+ t.beginPath();
164
+ let f = NaN, l = NaN;
165
+ for (let s = 0; s < r; s++) {
166
+ const c = e[s * 8], i = e[s * 8 + 1], o = e[s * 8 + 4], d = e[s * 8 + 5];
167
+ (c !== f || i !== l) && (t.moveTo(...n.map(c, i)), a++), t.lineTo(...n.map(o, d)), f = o, l = d;
168
+ }
169
+ return t.fill("evenodd"), a;
170
+ }
171
+ const Q = (t) => String(t ?? "");
172
+ function P({ params: t, stats: e, jobName: n, timestamp: r }) {
173
+ const a = String(t.material_print_speed ?? "fast"), f = {
174
+ action: "print",
175
+ jobDir: n,
176
+ expTime: t.exposure_time,
177
+ expTimeFirst: t.initial_exposure_time,
178
+ expUserProfile: a === "slow" ? 1 : a === "fast" ? 0 : 2,
179
+ fileCreationTimestamp: r ?? "",
180
+ hollow: t.hollowing_enable ? 1 : 0,
181
+ layerHeight: t.layer_height,
182
+ materialName: t.sla_material_settings_id ?? "",
183
+ numFade: t.faded_layers,
184
+ numFast: e.layers,
185
+ numSlow: 0,
186
+ printProfile: t.sla_print_settings_id ?? "",
187
+ printTime: Number(e.time_estimate ?? 0).toFixed(6),
188
+ printerModel: t.printer_model ?? "",
189
+ printerProfile: t.printer_settings_id ?? "",
190
+ printerVariant: t.printer_variant ?? "",
191
+ prusaSlicerVersion: "three-slicer",
192
+ usedMaterial: Number(e.resin_ml ?? 0).toFixed(6)
193
+ };
194
+ return Object.keys(f).sort().map((l) => `${l} = ${Q(f[l])}`).join(`
195
+ `) + `
196
+ `;
197
+ }
198
+ const T = (t, e) => `${t}${String(e).padStart(5, "0")}.png`, tt = "Metadata/threeslicer_roles.bin", et = "Metadata/threeslicer_scene.bin";
199
+ function nt({ modelSTL: t, supportMesh: e, padMesh: n, lift: r = 0 }) {
200
+ const a = t instanceof Uint8Array ? t : new Uint8Array(t ?? 0), f = e instanceof Float32Array ? e : new Float32Array(e ?? 0), l = n instanceof Float32Array ? n : new Float32Array(n ?? 0), s = new Uint8Array(12 + a.length + 4 + f.length * 4 + 4 + l.length * 4), c = new DataView(s.buffer);
201
+ s.set([84, 83, 83, 49], 0), c.setFloat32(4, r, !0);
202
+ let i = 8;
203
+ c.setUint32(i, a.length, !0), i += 4, s.set(a, i), i += a.length;
204
+ for (const o of [f, l]) {
205
+ c.setUint32(i, o.length, !0), i += 4;
206
+ for (let d = 0; d < o.length; d++)
207
+ c.setFloat32(i, o[d], !0), i += 4;
208
+ }
209
+ return s;
210
+ }
211
+ function ot(t) {
212
+ const e = t.map(({ paths: l }) => {
213
+ const s = [];
214
+ for (let c = 0; c + 7 < l.length; c += 8) {
215
+ const i = l[c + 3] & 15;
216
+ if (i === 5 || i === 6) for (let o = 0; o < 8; o++) s.push(l[c + o]);
217
+ }
218
+ return s;
219
+ }), n = 8 + e.reduce((l, s) => l + 4 + s.length * 4, 0), r = new Uint8Array(n), a = new DataView(r.buffer);
220
+ r.set([84, 83, 82, 49], 0), a.setUint32(4, e.length, !0);
221
+ let f = 8;
222
+ for (const l of e) {
223
+ a.setUint32(f, l.length, !0), f += 4;
224
+ for (const s of l)
225
+ a.setFloat32(f, s, !0), f += 4;
226
+ }
227
+ return r;
228
+ }
229
+ function rt({ layers: t, params: e, makeWorker: n, workerCount: r, onProgress: a, aa: f = 1 }) {
230
+ return new Promise((l, s) => {
231
+ const c = new Array(t.length), i = new Array(r).fill(0);
232
+ let o = 0, d = !1;
233
+ const u = [], p = (g) => {
234
+ d = !0, u.forEach((w) => w.terminate()), s(g);
235
+ };
236
+ for (let g = 0; g < r; g++) {
237
+ const w = [], m = [];
238
+ for (let y = g; y < t.length; y += r)
239
+ w.push(y), m.push(t[y].paths);
240
+ const _ = n();
241
+ u.push(_), _.onerror = (y) => p(new Error("SL1 encode worker: " + ((y == null ? void 0 : y.message) || "failed"))), _.onmessage = ({ data: y }) => {
242
+ if (!d) {
243
+ if (y.progress != null) {
244
+ i[g] = y.progress, a == null || a(i.reduce((b, U) => b + U, 0), t.length);
245
+ return;
246
+ }
247
+ y.indices.forEach((b, U) => {
248
+ c[b] = y.pngs[U];
249
+ }), _.terminate(), ++o === r && l(c);
250
+ }
251
+ }, _.postMessage({ indices: w, paths: m, params: e, aa: f });
252
+ }
253
+ });
254
+ }
255
+ async function lt({ layers: t, params: e, stats: n, jobName: r = "plate", timestamp: a, makeCanvas: f, onProgress: l, scene: s = null, makeWorker: c = null, workerCount: i = 0, aa: o = 1, gpuRaster: d = null }) {
256
+ const u = f ?? null, p = J(e), g = {}, w = c && typeof Worker < "u" && t.length > 1 ? {
257
+ makeWorker: c,
258
+ workerCount: Math.max(1, Math.min(i > 0 ? i : 4, t.length))
259
+ } : null, m = () => performance.now(), _ = { canvas: 0, clear: 0, draw: 0, encode: 0, read: 0 }, y = (x, h) => {
260
+ const $ = m();
261
+ return _[x] += $ - h, $;
262
+ };
263
+ let b = 0, U = 0;
264
+ const B = async (x) => {
265
+ let h = m();
266
+ if (!u) {
267
+ const V = d ? await d(t[x].paths, p, o, t[x], x) : Y(t[x].paths, p, o);
268
+ h = y("draw", h);
269
+ const D = await q(V, p.px, p.py, { deflate: O });
270
+ return y("encode", h), b += D.length, D;
271
+ }
272
+ const $ = u(p.px, p.py), S = $.getContext("2d");
273
+ h = y("canvas", h), S.fillStyle = "#000", S.fillRect(0, 0, p.px, p.py), h = y("clear", h), S.fillStyle = "#fff", U += K(S, t[x].paths, p), h = y("draw", h);
274
+ const L = await $.convertToBlob({ type: "image/png" });
275
+ h = y("encode", h);
276
+ const C = new Uint8Array(await L.arrayBuffer());
277
+ return y("read", h), b += C.length, C;
278
+ }, F = m();
279
+ if (w) {
280
+ const x = await rt({ layers: t, params: e, onProgress: l, aa: o, ...w });
281
+ for (let h = 0; h < t.length; h++)
282
+ g[T(r, h)] = [x[h], { level: 0 }], b += x[h].length;
283
+ } else
284
+ for (let x = 0; x < t.length; x++)
285
+ g[T(r, x)] = [await B(x), { level: 0 }], x & 31 || l == null || l(x, t.length);
286
+ const v = m();
287
+ g["config.ini"] = I(P({ params: e, stats: n, jobName: r, timestamp: a })), g[tt] = [ot(t), { level: 6 }], s && (g[et] = [nt(s), { level: 6 }]);
288
+ const N = m(), k = z(g), A = (x) => x.toFixed(0);
289
+ return j.info(`[vp-prof] sl1 build: ${t.length} layers ${p.px}x${p.py},` + (w ? ` raster ${A(v - F)}ms (${w.workerCount} workers),` : ` ${U} loops, raster ${A(v - F)}ms (canvas ${A(_.canvas)} + clear ${A(_.clear)} + draw ${A(_.draw)} + encode ${A(_.encode)} + read ${A(_.read)}),`) + ` sidecar ${A(N - v)}ms, zip ${A(m() - N)}ms -> ${(k.byteLength / 1e6).toFixed(1)}MB (png ${(b / 1e6).toFixed(1)}MB)`), k;
290
+ }
291
+ export {
292
+ et as S,
293
+ tt as a,
294
+ X as b,
295
+ it as c,
296
+ K as d,
297
+ q as e,
298
+ j as l,
299
+ lt as m,
300
+ Y as r,
301
+ J as s
302
+ };
@@ -1,5 +1,5 @@
1
1
  import { f as U } from "./sla_reconstruct-CXkYhux2.js";
2
- import { d as q } from "./sl1_write-UHmQ_itC.js";
2
+ import { d as q } from "./sl1_write-CtX8cVL7.js";
3
3
  let i = 6;
4
4
  const D = (u, B) => {
5
5
  const m = [];
package/viewer/styles.css CHANGED
@@ -82,6 +82,30 @@
82
82
  .plate-tab.on { background: #00ae42; color: #fff; border-color: #00ae42; }
83
83
  .plate-add { color: #7ad19a !important; } .plate-del { color: #e08a8a !important; }
84
84
  .plate-bar button:disabled { opacity: .4; cursor: not-allowed; }
85
+ /* Per-plate override marker: this plate slices with something other than the global settings. */
86
+ .plate-tab { position: relative; }
87
+ .plate-dot { position: absolute; top: 2px; right: 2px; width: 5px; height: 5px; border-radius: 50%; background: #f0a542; }
88
+ .plate-tab.on .plate-dot { background: #fff; }
89
+ /* An all-plates run: what each plate is doing, independent of which one is selected. */
90
+ .plate-tab.run-queued { border-style: dashed; }
91
+ .plate-tab.run-busy { border-color: #00ae42; animation: tb-pulse 1s ease-in-out infinite; }
92
+ .plate-tab.run-busy.on { animation: none; }
93
+ .plate-tab.run-done { box-shadow: inset 0 -3px 0 #00ae42; }
94
+ .plate-tab.run-failed { border-color: #d9534f; }
95
+ /* Settings-scope toggle in the process card head: writes go to the global map or the selected plate's override. */
96
+ .scope-toggle { margin-left: auto; display: flex; gap: 0; border: 1px solid #d5d8dd; border-radius: 6px; overflow: hidden; }
97
+ .scope-toggle button { border: 0; background: #f3f5f7; color: #5a6472; font-size: 11px; font-weight: 600; padding: 3px 8px; cursor: pointer; }
98
+ .scope-toggle button.on { background: #00ae42; color: #fff; }
99
+ .sc-bed-warn { color: #a86a12; background: #fdf4e3; border-radius: 6px; padding: 5px 8px; font-size: 12px; line-height: 1.4; }
100
+ /* Object-list plate headers: which plate a row's object slices on (same colour language as the PlateBar). */
101
+ .obj-plate-head { display: flex; align-items: center; gap: 6px; padding: 4px 2px 2px; margin-top: 4px; cursor: pointer;
102
+ border-bottom: 1px solid #e6e9ec; font-size: 12px; font-weight: 700; color: #5a6472; list-style: none; }
103
+ .obj-plate-head.on { color: #00913a; border-bottom-color: #9adfb6; }
104
+ .obj-plate-head .obj-plate-tech { background: #6d7ce0; color: #fff; border-radius: 7px; padding: 0 6px; font-size: 10px; font-weight: 700; }
105
+ .obj-plate-head .obj-plate-dot { width: 6px; height: 6px; border-radius: 50%; background: #f0a542; }
106
+ .obj-plate-head .obj-plate-count { margin-left: auto; font-weight: 400; color: #97a1ac; }
107
+ .obj-plate-head .obj-plate-sup { display: inline-flex; align-items: center; gap: 3px; font-weight: 400; font-size: 11px; color: #5a6472; cursor: pointer; }
108
+ .obj-plate-head .obj-plate-sup input { margin: 0; }
85
109
  .slice-dd { position: relative; flex: 1.4; }
86
110
  .slice-dd .slice-btn { width: 100%; }
87
111
  .slice-menu { position: absolute; bottom: calc(100% + 6px); left: 0; right: 0; background: #fff; border: 1px solid #d5d8dd;
@@ -89,6 +113,19 @@
89
113
  .slice-menu button { display: block; width: 100%; text-align: left; padding: 9px 12px; border: 0; background: #fff;
90
114
  color: #24282e; cursor: pointer; font-size: 13px; }
91
115
  .slice-menu button:hover { background: #eef7f1; }
116
+ /* The worker-count row inside the menu: a value, not an action, so it is a label with a select. */
117
+ .slice-workers { display: flex; align-items: center; gap: 8px; padding: 7px 12px; font-size: 12px; color: #3b434b;
118
+ border-top: 1px solid #edf0f2; border-bottom: 1px solid #edf0f2; }
119
+ .slice-workers select { flex: 1; font-size: 12px; padding: 2px 4px; }
120
+ .kernel-badge { font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 4px; letter-spacing: .04em; text-transform: uppercase; }
121
+ .kernel-badge.mt { background: #e2f5e8; color: #167a3a; }
122
+ .kernel-badge.st { background: #fbeaea; color: #a33b37; }
123
+ /* One entry per plate while an all-plates run is on — same colours as the plate tabs. */
124
+ .slice-plates { flex: 0 0 100%; display: flex; flex-wrap: wrap; gap: 4px 8px; margin: -2px 2px 0; font-size: 11px;
125
+ color: #5a646d; font-variant-numeric: tabular-nums; }
126
+ .slice-plate.busy { color: #167a3a; font-weight: 600; }
127
+ .slice-plate.done { color: #167a3a; }
128
+ .slice-plate.failed { color: #a33b37; }
92
129
 
93
130
  /* Floating painting panel */
94
131
  .brush-panel { position: absolute; top: 58px; left: 14px; width: 214px; background: rgba(22,27,33,.95);
@@ -106,6 +143,10 @@
106
143
  .bp-radius { display: block; font-size: 12px; color: #aebcc6; margin-top: 8px; }
107
144
  .bp-radius input { width: 100%; }
108
145
  .bp-counts { margin-top: 6px; font-size: 11px; }
146
+ /* "On overhangs only" — a checkbox row in a panel whose other rows are buttons, so it borrows the label styling
147
+ of .bp-radius and only adds the inline layout a checkbox needs. */
148
+ .bp-check { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #aebcc6; margin-top: 8px; cursor: pointer; }
149
+ .bp-check input { margin: 0; }
109
150
  /* Material brush: the chip IS the filament colour, so its background is inline and only the framing is here.
110
151
  The active ring is drawn outside the box (outline, not border) — a border would resize the chip on selection. */
111
152
  .bp-chip { min-width: 30px; font-weight: 700; border-color: rgba(0,0,0,.35) !important; }
@@ -347,3 +388,7 @@
347
388
  pointer, keyboard and focus — this only has to make that legible, or the card reads as broken rather than locked. */
348
389
  .vp-readonly { opacity: .62; cursor: default; }
349
390
  .vp-readonly * { cursor: default !important; }
391
+
392
+ /* The scope toggle's ↺ — drops the plate's whole override (ScopeToggle onReset). */
393
+ .scope-toggle .scope-reset { margin-left: 4px; padding: 0 6px; font-size: 12px; line-height: 18px; border: 1px solid #c9d3de; border-radius: 4px; background: transparent; cursor: pointer; }
394
+ .scope-toggle .scope-reset:hover { background: #eef2f6; }
@@ -1,170 +0,0 @@
1
- import { strToU8 as R, zipSync as T } from "three/examples/jsm/libs/fflate.module.js";
2
- let F = !0;
3
- function Z(e) {
4
- F = !!e;
5
- }
6
- const C = {
7
- info: (...e) => {
8
- F && console.info(...e);
9
- },
10
- warn: (...e) => {
11
- F && console.warn(...e);
12
- },
13
- error: (...e) => {
14
- F && console.error(...e);
15
- }
16
- };
17
- function O(e) {
18
- const t = Number(e.display_width) > 0 ? Number(e.display_width) : 120.96, u = Number(e.display_height) > 0 ? Number(e.display_height) : 68.04, o = Number(e.display_pixels_x) > 0 ? Math.round(Number(e.display_pixels_x)) : 2560, i = Number(e.display_pixels_y) > 0 ? Math.round(Number(e.display_pixels_y)) : 1440, s = e.display_mirror_x !== !1, r = e.display_mirror_y === !0, n = (e.display_orientation ?? "portrait") !== "landscape", a = o / t, l = i / u, f = (p) => (s ? t / 2 - p : p + t / 2) * a, c = (p) => (r ? u / 2 - p : p + u / 2) * l;
19
- return n ? {
20
- px: i,
21
- py: o,
22
- mirrorX: s,
23
- portrait: n,
24
- // canvas columns run along the display's y axis, rows along the (mirrored) x axis
25
- map: (p, y) => [c(y), f(p)]
26
- } : {
27
- px: o,
28
- py: i,
29
- mirrorX: s,
30
- portrait: n,
31
- map: (p, y) => [f(p), c(y)]
32
- };
33
- }
34
- function k(e, t, u) {
35
- const o = t.length / 8;
36
- if (!o) return 0;
37
- let i = 0;
38
- e.beginPath();
39
- let s = NaN, r = NaN;
40
- for (let n = 0; n < o; n++) {
41
- const a = t[n * 8], l = t[n * 8 + 1], f = t[n * 8 + 4], c = t[n * 8 + 5];
42
- (a !== s || l !== r) && (e.moveTo(...u.map(a, l)), i++), e.lineTo(...u.map(f, c)), s = f, r = c;
43
- }
44
- return e.fill("evenodd"), i;
45
- }
46
- const V = (e) => String(e ?? "");
47
- function X({ params: e, stats: t, jobName: u, timestamp: o }) {
48
- const i = String(e.material_print_speed ?? "fast"), s = {
49
- action: "print",
50
- jobDir: u,
51
- expTime: e.exposure_time,
52
- expTimeFirst: e.initial_exposure_time,
53
- expUserProfile: i === "slow" ? 1 : i === "fast" ? 0 : 2,
54
- fileCreationTimestamp: o ?? "",
55
- hollow: e.hollowing_enable ? 1 : 0,
56
- layerHeight: e.layer_height,
57
- materialName: e.sla_material_settings_id ?? "",
58
- numFade: e.faded_layers,
59
- numFast: t.layers,
60
- numSlow: 0,
61
- printProfile: e.sla_print_settings_id ?? "",
62
- printTime: Number(t.time_estimate ?? 0).toFixed(6),
63
- printerModel: e.printer_model ?? "",
64
- printerProfile: e.printer_settings_id ?? "",
65
- printerVariant: e.printer_variant ?? "",
66
- prusaSlicerVersion: "three-slicer",
67
- usedMaterial: Number(t.resin_ml ?? 0).toFixed(6)
68
- };
69
- return Object.keys(s).sort().map((r) => `${r} = ${V(s[r])}`).join(`
70
- `) + `
71
- `;
72
- }
73
- const L = (e, t) => `${e}${String(t).padStart(5, "0")}.png`, Y = "Metadata/threeslicer_roles.bin", D = "Metadata/threeslicer_scene.bin";
74
- function j({ modelSTL: e, supportMesh: t, padMesh: u, lift: o = 0 }) {
75
- const i = e instanceof Uint8Array ? e : new Uint8Array(e ?? 0), s = t instanceof Float32Array ? t : new Float32Array(t ?? 0), r = u instanceof Float32Array ? u : new Float32Array(u ?? 0), n = new Uint8Array(12 + i.length + 4 + s.length * 4 + 4 + r.length * 4), a = new DataView(n.buffer);
76
- n.set([84, 83, 83, 49], 0), a.setFloat32(4, o, !0);
77
- let l = 8;
78
- a.setUint32(l, i.length, !0), l += 4, n.set(i, l), l += i.length;
79
- for (const f of [s, r]) {
80
- a.setUint32(l, f.length, !0), l += 4;
81
- for (let c = 0; c < f.length; c++)
82
- a.setFloat32(l, f[c], !0), l += 4;
83
- }
84
- return n;
85
- }
86
- function z(e) {
87
- const t = e.map(({ paths: r }) => {
88
- const n = [];
89
- for (let a = 0; a + 7 < r.length; a += 8) {
90
- const l = r[a + 3] & 15;
91
- if (l === 5 || l === 6) for (let f = 0; f < 8; f++) n.push(r[a + f]);
92
- }
93
- return n;
94
- }), u = 8 + t.reduce((r, n) => r + 4 + n.length * 4, 0), o = new Uint8Array(u), i = new DataView(o.buffer);
95
- o.set([84, 83, 82, 49], 0), i.setUint32(4, t.length, !0);
96
- let s = 8;
97
- for (const r of t) {
98
- i.setUint32(s, r.length, !0), s += 4;
99
- for (const n of r)
100
- i.setFloat32(s, n, !0), s += 4;
101
- }
102
- return o;
103
- }
104
- function H({ layers: e, params: t, makeWorker: u, workerCount: o, onProgress: i }) {
105
- return new Promise((s, r) => {
106
- const n = new Array(e.length), a = new Array(o).fill(0);
107
- let l = 0, f = !1;
108
- const c = [], p = (y) => {
109
- f = !0, c.forEach((_) => _.terminate()), r(y);
110
- };
111
- for (let y = 0; y < o; y++) {
112
- const _ = [], m = [];
113
- for (let g = y; g < e.length; g += o)
114
- _.push(g), m.push(e[g].paths);
115
- const w = u();
116
- c.push(w), w.onerror = (g) => p(new Error("SL1 encode worker: " + ((g == null ? void 0 : g.message) || "failed"))), w.onmessage = ({ data: g }) => {
117
- if (!f) {
118
- if (g.progress != null) {
119
- a[y] = g.progress, i == null || i(a.reduce((b, $) => b + $, 0), e.length);
120
- return;
121
- }
122
- g.indices.forEach((b, $) => {
123
- n[b] = g.pngs[$];
124
- }), w.terminate(), ++l === o && s(n);
125
- }
126
- }, w.postMessage({ indices: _, paths: m, params: t });
127
- }
128
- });
129
- }
130
- async function q({ layers: e, params: t, stats: u, jobName: o = "plate", timestamp: i, makeCanvas: s, onProgress: r, scene: n = null, makeWorker: a = null, workerCount: l = 0 }) {
131
- const f = s ?? (typeof OffscreenCanvas < "u" ? (h, d) => new OffscreenCanvas(h, d) : null), c = O(t), p = {}, y = a && typeof Worker < "u" && e.length > 1 ? {
132
- makeWorker: a,
133
- workerCount: Math.max(1, Math.min(l > 0 ? l : 4, e.length))
134
- } : null;
135
- if (!y && !f) throw new Error("SL1 export needs a canvas (OffscreenCanvas or an injected factory)");
136
- const _ = () => performance.now(), m = { canvas: 0, clear: 0, draw: 0, encode: 0, read: 0 }, w = (h, d) => {
137
- const S = _();
138
- return m[h] += S - d, S;
139
- };
140
- let g = 0, b = 0;
141
- const $ = async (h) => {
142
- let d = _();
143
- const S = f(c.px, c.py), v = S.getContext("2d");
144
- d = w("canvas", d), v.fillStyle = "#000", v.fillRect(0, 0, c.px, c.py), d = w("clear", d), v.fillStyle = "#fff", b += k(v, e[h].paths, c), d = w("draw", d);
145
- const B = await S.convertToBlob({ type: "image/png" });
146
- d = w("encode", d);
147
- const U = new Uint8Array(await B.arrayBuffer());
148
- return w("read", d), g += U.length, U;
149
- }, E = _();
150
- if (y) {
151
- const h = await H({ layers: e, params: t, onProgress: r, ...y });
152
- for (let d = 0; d < e.length; d++)
153
- p[L(o, d)] = [h[d], { level: 0 }], g += h[d].length;
154
- } else
155
- for (let h = 0; h < e.length; h++)
156
- p[L(o, h)] = [await $(h), { level: 0 }], h & 31 || r == null || r(h, e.length);
157
- const N = _();
158
- p["config.ini"] = R(X({ params: t, stats: u, jobName: o, timestamp: i })), p[Y] = [z(e), { level: 6 }], n && (p[D] = [j(n), { level: 6 }]);
159
- const A = _(), M = T(p), x = (h) => h.toFixed(0);
160
- return C.info(`[vp-prof] sl1 build: ${e.length} layers ${c.px}x${c.py},` + (y ? ` raster ${x(N - E)}ms (${y.workerCount} workers),` : ` ${b} loops, raster ${x(N - E)}ms (canvas ${x(m.canvas)} + clear ${x(m.clear)} + draw ${x(m.draw)} + encode ${x(m.encode)} + read ${x(m.read)}),`) + ` sidecar ${x(A - N)}ms, zip ${x(_() - A)}ms -> ${(M.byteLength / 1e6).toFixed(1)}MB (png ${(g / 1e6).toFixed(1)}MB)`), M;
161
- }
162
- export {
163
- D as S,
164
- Y as a,
165
- Z as b,
166
- k as d,
167
- C as l,
168
- q as m,
169
- O as s
170
- };