three-slicer 0.1.6 → 0.2.0
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 +35 -0
- package/README.md +310 -22
- package/THIRD-PARTY-NOTICES.md +37 -0
- package/components/README.md +2 -0
- package/components/dist/SettingsPanel.js +92 -92
- package/data/config-schema.json +698 -0
- package/data/filaments.js +1 -1
- package/data/preset-keys.json +1 -0
- package/data/printers.json +1 -1
- package/data/processes.js +1 -1
- package/data/ui-tree.json +342 -0
- package/engine/README.md +279 -3
- package/engine/examples/sla_headless.mjs +51 -0
- package/engine/index.d.ts +77 -5
- package/engine/index.js +15 -4
- package/engine/src/client.js +165 -0
- package/engine/src/data.js +3 -0
- package/engine/src/preset_file.js +99 -0
- package/engine/src/settings.js +232 -0
- package/engine/src/sla_core.js +188 -0
- package/engine/src/sla_request.js +185 -0
- package/engine/src/slicer.worker.js +76 -4
- package/engine/src/slicer_core.js +0 -0
- package/engine/src/slicer_core.mt.js +0 -0
- package/package.json +26 -11
- package/types/client.d.ts +88 -0
- package/types/components.d.ts +10 -0
- package/types/data/preset-keys.json.d.ts +20 -0
- package/types/data/printers.json.d.ts +2 -2
- package/types/data.d.ts +4 -0
- package/types/settings-keys.d.ts +107 -1
- package/types/settings.d.ts +116 -1
- package/types/sla.d.ts +167 -0
- package/types/viewer.d.ts +59 -1
- package/types/worker.d.ts +95 -0
- package/viewer/README.md +163 -3
- package/viewer/dist/Viewport.js +3633 -3137
- package/viewer/dist/model_loaders.js +1 -1
- package/viewer/dist/parse_3mf-C2X_W442.js +300 -0
- package/viewer/dist/parse_3mf.worker.js +1 -1
- package/viewer/styles.css +5 -0
- package/types/gen_settings_types.mjs +0 -70
- package/viewer/dist/parse_3mf-8oCnCJNK.js +0 -216
|
@@ -2,7 +2,7 @@ import * as L from "three";
|
|
|
2
2
|
import { OBJLoader as T } from "three/examples/jsm/loaders/OBJLoader.js";
|
|
3
3
|
import { PLYLoader as v } from "three/examples/jsm/loaders/PLYLoader.js";
|
|
4
4
|
import { AMFLoader as P } from "three/examples/jsm/loaders/AMFLoader.js";
|
|
5
|
-
import { p as E } from "./parse_3mf-
|
|
5
|
+
import { p as E } from "./parse_3mf-C2X_W442.js";
|
|
6
6
|
import { makeParse3mfWorker as W } from "./make_worker.js";
|
|
7
7
|
let h = null, M = !1, $ = 0;
|
|
8
8
|
const y = /* @__PURE__ */ new Map();
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { unzip as W, unzipSync as B } from "three/examples/jsm/libs/fflate.module.js";
|
|
2
|
+
function q(t) {
|
|
3
|
+
return new Promise((n) => {
|
|
4
|
+
let o = !1;
|
|
5
|
+
const e = (s) => {
|
|
6
|
+
o || (o = !0, n(s));
|
|
7
|
+
};
|
|
8
|
+
try {
|
|
9
|
+
W(t, (s, i) => e(s ? B(t) : i));
|
|
10
|
+
} catch {
|
|
11
|
+
e(B(t));
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
const F = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0];
|
|
16
|
+
function K(t, n) {
|
|
17
|
+
const o = new Array(12);
|
|
18
|
+
for (let e = 0; e < 4; e++)
|
|
19
|
+
for (let s = 0; s < 3; s++)
|
|
20
|
+
o[e * 3 + s] = t[e * 3] * n[s] + t[e * 3 + 1] * n[3 + s] + t[e * 3 + 2] * n[6 + s] + (e === 3 ? n[9 + s] : 0);
|
|
21
|
+
return o;
|
|
22
|
+
}
|
|
23
|
+
function C(t) {
|
|
24
|
+
if (!t) return F;
|
|
25
|
+
const n = t.trim().split(/\s+/).map(Number);
|
|
26
|
+
return n.length === 12 && n.every(Number.isFinite) ? n : F;
|
|
27
|
+
}
|
|
28
|
+
const U = {};
|
|
29
|
+
function d(t, n) {
|
|
30
|
+
const e = (U[n] || (U[n] = new RegExp(`\\b${n}\\s*=\\s*"([^"]*)"`))).exec(t);
|
|
31
|
+
return e ? e[1] : null;
|
|
32
|
+
}
|
|
33
|
+
const D = /<vertex\s+x="([^"]*)"\s+y="([^"]*)"\s+z="([^"]*)"/g, V = /<triangle\s+v1="([^"]*)"\s+v2="([^"]*)"\s+v3="([^"]*)"([^>]*)/g, $ = [
|
|
34
|
+
["paint_color", "color"],
|
|
35
|
+
// multi-material: state 1..16 == Extruder1..16
|
|
36
|
+
["paint_supports", "supports"],
|
|
37
|
+
// support enforcer/blocker: states 1 and 2
|
|
38
|
+
["paint_seam", "seam"],
|
|
39
|
+
// unsupported by the kernel — collected for the warning only
|
|
40
|
+
["paint_fuzzy_skin", "fuzzy"]
|
|
41
|
+
// ditto
|
|
42
|
+
];
|
|
43
|
+
function Y() {
|
|
44
|
+
return { color: /* @__PURE__ */ new Map(), supports: /* @__PURE__ */ new Map(), seam: /* @__PURE__ */ new Map(), fuzzy: /* @__PURE__ */ new Map() };
|
|
45
|
+
}
|
|
46
|
+
function Q(t) {
|
|
47
|
+
return !t || $.every(([, n]) => t[n].size === 0);
|
|
48
|
+
}
|
|
49
|
+
function J(t, n, o) {
|
|
50
|
+
for (const [e, s] of $) {
|
|
51
|
+
if (!t.includes(e)) continue;
|
|
52
|
+
const i = d(t, e);
|
|
53
|
+
i && o[s].set(n, i);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function Z(t) {
|
|
57
|
+
const n = [];
|
|
58
|
+
D.lastIndex = 0;
|
|
59
|
+
let o;
|
|
60
|
+
for (; o = D.exec(t); ) n.push(+o[1], +o[2], +o[3]);
|
|
61
|
+
if (!n.length)
|
|
62
|
+
for (const i of t.match(/<vertex\b[^>]*>/g) || []) n.push(+d(i, "x"), +d(i, "y"), +d(i, "z"));
|
|
63
|
+
if (n.length < 9) return null;
|
|
64
|
+
const e = [], s = Y();
|
|
65
|
+
for (V.lastIndex = 0; o = V.exec(t); ) {
|
|
66
|
+
const i = e.length / 3;
|
|
67
|
+
e.push(+o[1], +o[2], +o[3]), o[4].length > 2 && J(o[4], i, s);
|
|
68
|
+
}
|
|
69
|
+
if (!e.length)
|
|
70
|
+
for (const i of t.match(/<triangle\b[^>]*>/g) || []) {
|
|
71
|
+
const p = e.length / 3;
|
|
72
|
+
e.push(+d(i, "v1"), +d(i, "v2"), +d(i, "v3")), J(i, p, s);
|
|
73
|
+
}
|
|
74
|
+
return e.length ? { verts: n, tris: e, paint: s } : null;
|
|
75
|
+
}
|
|
76
|
+
function x(t) {
|
|
77
|
+
const n = /* @__PURE__ */ new Map(), o = /<object\b([^>]*)>([\s\S]*?)<\/object>/g;
|
|
78
|
+
let e;
|
|
79
|
+
for (; e = o.exec(t); ) {
|
|
80
|
+
const p = d(e[1], "id");
|
|
81
|
+
if (!p) continue;
|
|
82
|
+
const u = e[2], r = [];
|
|
83
|
+
for (const a of u.match(/<component\b[^>]*>/g) || []) {
|
|
84
|
+
const l = d(a, "objectid");
|
|
85
|
+
l && r.push({ objectid: l, path: d(a, "p:path") || d(a, "path"), transform: C(d(a, "transform")) });
|
|
86
|
+
}
|
|
87
|
+
n.set(p, r.length ? { components: r } : { mesh: Z(u) });
|
|
88
|
+
}
|
|
89
|
+
const s = [], i = /<build\b[^>]*>([\s\S]*?)<\/build>/.exec(t);
|
|
90
|
+
if (i)
|
|
91
|
+
for (const p of i[1].match(/<item\b[^>]*>/g) || []) {
|
|
92
|
+
const u = d(p, "objectid");
|
|
93
|
+
u && s.push({ objectid: u, path: d(p, "p:path") || d(p, "path"), transform: C(d(p, "transform")) });
|
|
94
|
+
}
|
|
95
|
+
return { objects: n, items: s };
|
|
96
|
+
}
|
|
97
|
+
function O(t) {
|
|
98
|
+
const n = String(t).replace(/^\/+/, "");
|
|
99
|
+
return n.includes("%") ? decodeURIComponent(n) : n;
|
|
100
|
+
}
|
|
101
|
+
function k(t) {
|
|
102
|
+
const n = {};
|
|
103
|
+
for (const o of t.match(/<metadata\b[^>]*>/g) || []) {
|
|
104
|
+
const e = d(o, "key");
|
|
105
|
+
e && (n[e] = d(o, "value") ?? "");
|
|
106
|
+
}
|
|
107
|
+
return n;
|
|
108
|
+
}
|
|
109
|
+
function tt(t) {
|
|
110
|
+
const n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), e = /<object\b([^>]*)>([\s\S]*?)<\/object>/g;
|
|
111
|
+
let s;
|
|
112
|
+
for (; s = e.exec(t); ) {
|
|
113
|
+
const u = d(s[1], "id");
|
|
114
|
+
if (u) {
|
|
115
|
+
const r = s[2];
|
|
116
|
+
n.set(u, k(r.replace(/<(?:part|volume)\b[\s\S]*?<\/(?:part|volume)>/g, "")));
|
|
117
|
+
const a = [];
|
|
118
|
+
for (const l of r.match(/<volume\b[\s\S]*?<\/volume>/g) || []) {
|
|
119
|
+
const b = k(l).volume_type, _ = b === "SupportBlocker" ? "blocker" : b === "SupportEnforcer" ? "enforcer" : null, j = Number(d(l, "firstid")), S = Number(d(l, "lastid"));
|
|
120
|
+
_ && Number.isInteger(j) && Number.isInteger(S) && j >= 0 && S >= j && a.push({ firstTriangle: j, lastTriangle: S, kind: _ });
|
|
121
|
+
}
|
|
122
|
+
a.length && o.set(u, a);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const i = [], p = /<plate\b[^>]*>([\s\S]*?)<\/plate>/g;
|
|
126
|
+
for (; s = p.exec(t); ) {
|
|
127
|
+
const u = s[1], r = k(u.replace(/<model_instance\b[\s\S]*?<\/model_instance>/g, "")), a = [];
|
|
128
|
+
for (const l of u.match(/<model_instance\b[\s\S]*?<\/model_instance>/g) || []) {
|
|
129
|
+
const b = k(l).object_id;
|
|
130
|
+
b && a.push(b);
|
|
131
|
+
}
|
|
132
|
+
i.push({ index: Math.max(0, (Number(r.plater_id) || i.length + 1) - 1), objectIds: a });
|
|
133
|
+
}
|
|
134
|
+
return { objects: n, plates: i, volumes: o };
|
|
135
|
+
}
|
|
136
|
+
const et = Object.freeze({
|
|
137
|
+
manualSupportPoints: "prepared-roundtrip",
|
|
138
|
+
drainHoles: "preserved-unsupported",
|
|
139
|
+
modifierVolumes: "prepared-mask-filtering",
|
|
140
|
+
uiEditing: "unavailable"
|
|
141
|
+
});
|
|
142
|
+
function X(t, n, o, e, s) {
|
|
143
|
+
const i = /* @__PURE__ */ new Map();
|
|
144
|
+
if (!(t != null && t.trim())) return i;
|
|
145
|
+
const p = t.trim().split(/\r?\n/), u = new RegExp(`^${n}_format_version=(\\d+)$`).exec(p[0]), r = u ? Number(u[1]) : 0;
|
|
146
|
+
for (const a of p.slice(u ? 1 : 0)) {
|
|
147
|
+
const l = /^object_id=(\d+)\|(.*)$/.exec(a);
|
|
148
|
+
if (!l || i.has(Number(l == null ? void 0 : l[1]))) continue;
|
|
149
|
+
const b = Number(l[1]), _ = l[2].trim() ? l[2].trim().split(/\s+/).map(Number) : [], j = o(r);
|
|
150
|
+
if (!j || _.length % j !== 0 || _.some((c) => !Number.isFinite(c))) {
|
|
151
|
+
e.push({ code: n === "support_points" ? "SLA_SUPPORT_POINT_COUNT" : "SLA_DRAIN_HOLE_COUNT", object: b }), i.set(b, []);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const S = [];
|
|
155
|
+
for (let c = 0; c < _.length; c += j) S.push(s(_.slice(c, c + j), r));
|
|
156
|
+
i.set(b, S);
|
|
157
|
+
}
|
|
158
|
+
return i;
|
|
159
|
+
}
|
|
160
|
+
function G(t, n) {
|
|
161
|
+
const [o, e, s] = n;
|
|
162
|
+
return [o * t[0] + e * t[3] + s * t[6] + t[9], o * t[1] + e * t[4] + s * t[7] + t[10], o * t[2] + e * t[5] + s * t[8] + t[11]];
|
|
163
|
+
}
|
|
164
|
+
function nt(t, n) {
|
|
165
|
+
const [o, e, s] = n, i = [o * t[0] + e * t[3] + s * t[6], o * t[1] + e * t[4] + s * t[7], o * t[2] + e * t[5] + s * t[8]], p = Math.hypot(...i);
|
|
166
|
+
return p ? i.map((u) => u / p) : i;
|
|
167
|
+
}
|
|
168
|
+
function ot(t, n) {
|
|
169
|
+
var p, u;
|
|
170
|
+
const o = (r) => {
|
|
171
|
+
const a = t.get(r);
|
|
172
|
+
return a ? n.decode(a) : null;
|
|
173
|
+
}, e = {
|
|
174
|
+
settings: null,
|
|
175
|
+
// Metadata/project_settings.config — the flattened preset (raw upstream strings)
|
|
176
|
+
objectMeta: /* @__PURE__ */ new Map(),
|
|
177
|
+
// 3mf object id -> per-object metadata (name, extruder, per-object overrides)
|
|
178
|
+
plates: [],
|
|
179
|
+
// [{index, objectIds}]
|
|
180
|
+
hasLayerHeightProfile: !1,
|
|
181
|
+
hasCustomGcodePerLayer: !1,
|
|
182
|
+
volumeMeta: /* @__PURE__ */ new Map(),
|
|
183
|
+
sla: { capabilities: { ...et }, issues: [], supportPoints: /* @__PURE__ */ new Map(), drainHoles: /* @__PURE__ */ new Map() }
|
|
184
|
+
}, s = o("Metadata/project_settings.config");
|
|
185
|
+
if (s)
|
|
186
|
+
try {
|
|
187
|
+
e.settings = JSON.parse(s);
|
|
188
|
+
} catch {
|
|
189
|
+
e.settings = null;
|
|
190
|
+
}
|
|
191
|
+
const i = o("Metadata/model_settings.config");
|
|
192
|
+
if (i) {
|
|
193
|
+
const r = tt(i);
|
|
194
|
+
e.objectMeta = r.objects, e.plates = r.plates, e.volumeMeta = r.volumes;
|
|
195
|
+
}
|
|
196
|
+
return e.sla.supportPoints = X(
|
|
197
|
+
o("Metadata/Slic3r_PE_sla_support_points.txt"),
|
|
198
|
+
"support_points",
|
|
199
|
+
(r) => r === 0 ? 3 : r === 1 ? 5 : 0,
|
|
200
|
+
e.sla.issues,
|
|
201
|
+
(r, a) => ({
|
|
202
|
+
position: r.slice(0, 3),
|
|
203
|
+
radius: a === 0 ? 0.4 : r[3],
|
|
204
|
+
type: a === 0 || r[4] === 2 ? "manual" : r[4] === 1 ? "island" : "slope"
|
|
205
|
+
})
|
|
206
|
+
), e.sla.drainHoles = X(
|
|
207
|
+
o("Metadata/Slic3r_PE_sla_drain_holes.txt"),
|
|
208
|
+
"drain_holes",
|
|
209
|
+
(r) => r === 1 ? 8 : 0,
|
|
210
|
+
e.sla.issues,
|
|
211
|
+
(r) => {
|
|
212
|
+
const a = Math.hypot(r[3], r[4], r[5]), l = a ? r.slice(3, 6).map((b) => b / a) : r.slice(3, 6);
|
|
213
|
+
return { position: r.slice(0, 3).map((b, _) => b + l[_]), normal: l, radius: r[6], height: r[7] - 1 };
|
|
214
|
+
}
|
|
215
|
+
), e.hasLayerHeightProfile = !!((p = o("Metadata/layer_heights_profile.txt")) != null && p.trim()), e.hasCustomGcodePerLayer = !!((u = o("Metadata/custom_gcode_per_layer.xml")) != null && u.trim()), e;
|
|
216
|
+
}
|
|
217
|
+
async function rt(t, n = "model") {
|
|
218
|
+
const o = ArrayBuffer.isView(t) ? new Uint8Array(t.buffer, t.byteOffset, t.byteLength) : new Uint8Array(t), e = await q(o), s = /* @__PURE__ */ new Map();
|
|
219
|
+
for (const c of Object.keys(e)) s.set(O(c), e[c]);
|
|
220
|
+
const i = new TextDecoder(), p = /* @__PURE__ */ new Map(), u = (c) => {
|
|
221
|
+
const w = O(c);
|
|
222
|
+
if (p.has(w)) return p.get(w);
|
|
223
|
+
const m = s.get(w), M = m ? x(i.decode(m)) : null;
|
|
224
|
+
return p.set(w, M), M;
|
|
225
|
+
};
|
|
226
|
+
let r = "3D/3dmodel.model";
|
|
227
|
+
const a = s.get("_rels/.rels");
|
|
228
|
+
if (a) {
|
|
229
|
+
for (const c of i.decode(a).match(/<Relationship\b[^>]*>/g) || [])
|
|
230
|
+
if ((d(c, "Type") || "").endsWith("/3dmodel")) {
|
|
231
|
+
r = O(d(c, "Target"));
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const l = u(r);
|
|
236
|
+
if (!l) throw new Error(`3MF root model not found: ${r}`);
|
|
237
|
+
const b = [], _ = ot(s, i), j = (c, w, m, M, P, z) => {
|
|
238
|
+
if (z > 16) return;
|
|
239
|
+
const T = u(w), I = T == null ? void 0 : T.objects.get(c);
|
|
240
|
+
if (!I) return;
|
|
241
|
+
if (I.components) {
|
|
242
|
+
for (const y of I.components) j(y.objectid, y.path || w, K(y.transform, m), M, P, z + 1);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (!I.mesh) return;
|
|
246
|
+
const { verts: E, tris: v, paint: A } = I.mesh, R = M.length / 9;
|
|
247
|
+
for (let y = 0; y < v.length; y++) {
|
|
248
|
+
const f = v[y] * 3, g = E[f], h = E[f + 1], N = E[f + 2];
|
|
249
|
+
M.push(
|
|
250
|
+
g * m[0] + h * m[3] + N * m[6] + m[9],
|
|
251
|
+
g * m[1] + h * m[4] + N * m[7] + m[10],
|
|
252
|
+
g * m[2] + h * m[5] + N * m[8] + m[11]
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
if (A) for (const [, y] of $)
|
|
256
|
+
for (const [f, g] of A[y]) P[y].set(R + f, g);
|
|
257
|
+
}, S = l.items.length ? l.items : [...l.objects.keys()].filter((c) => l.objects.get(c).mesh).map((c) => ({ objectid: c, path: r, transform: F }));
|
|
258
|
+
return S.forEach((c, w) => {
|
|
259
|
+
const m = [], M = Y();
|
|
260
|
+
if (j(c.objectid, c.path || r, c.transform, m, M, 0), m.length < 9) return;
|
|
261
|
+
let P = new Float32Array(m);
|
|
262
|
+
const z = [], T = _.volumeMeta.get(c.objectid) || [];
|
|
263
|
+
if (T.length) {
|
|
264
|
+
const f = /* @__PURE__ */ new Set();
|
|
265
|
+
for (let g = 0; g < T.length; g++) {
|
|
266
|
+
const h = T[g], N = h.firstTriangle * 9, H = Math.min(m.length, (h.lastTriangle + 1) * 9);
|
|
267
|
+
if (!(N >= H)) {
|
|
268
|
+
for (let L = h.firstTriangle; L <= h.lastTriangle; L++) f.add(L);
|
|
269
|
+
z.push({ id: `${c.objectid}:modifier:${g}`, kind: h.kind, tris: new Float32Array(m.slice(N, H)) });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (f.size) {
|
|
273
|
+
const g = [];
|
|
274
|
+
for (let h = 0; h < m.length / 9; h++) f.has(h) || g.push(...m.slice(h * 9, h * 9 + 9));
|
|
275
|
+
P = new Float32Array(g);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const I = (_.sla.supportPoints.get(w + 1) || []).map((f) => ({ ...f, position: G(c.transform, f.position) })), E = (_.sla.drainHoles.get(w + 1) || []).map((f) => ({
|
|
279
|
+
...f,
|
|
280
|
+
position: G(c.transform, f.position),
|
|
281
|
+
normal: nt(c.transform, f.normal)
|
|
282
|
+
}));
|
|
283
|
+
let v = 1 / 0, A = 1 / 0, R = -1 / 0, y = -1 / 0;
|
|
284
|
+
for (let f = 0; f < P.length; f += 3) {
|
|
285
|
+
const g = P[f], h = P[f + 1];
|
|
286
|
+
g < v && (v = g), g > R && (R = g), h < A && (A = h), h > y && (y = h);
|
|
287
|
+
}
|
|
288
|
+
b.push({
|
|
289
|
+
name: S.length > 1 ? `${n}#${w + 1}` : n,
|
|
290
|
+
tris: P,
|
|
291
|
+
objectid: c.objectid,
|
|
292
|
+
paint: Q(M) ? null : M,
|
|
293
|
+
sla: { supportPoints: I, drainHoles: E, modifierVolumes: z },
|
|
294
|
+
bbox: { minX: v, minY: A, maxX: R, maxY: y }
|
|
295
|
+
});
|
|
296
|
+
}), { objects: b, project: _ };
|
|
297
|
+
}
|
|
298
|
+
export {
|
|
299
|
+
rt as p
|
|
300
|
+
};
|
package/viewer/styles.css
CHANGED
|
@@ -329,3 +329,8 @@
|
|
|
329
329
|
border-radius: 4px; padding: 2px 3px; font-size: 11px; }
|
|
330
330
|
.sc-num input { width: 62px; background: #1a2027; border: 1px solid #2c353d; color: #cdd6dd; border-radius: 4px;
|
|
331
331
|
padding: 2px 5px; font-size: 12px; margin-left: 4px; }
|
|
332
|
+
|
|
333
|
+
/* A panel shown but not editable (panels={{ printerCard: 'readonly' }}). `inert` on the wrapper already blocks
|
|
334
|
+
pointer, keyboard and focus — this only has to make that legible, or the card reads as broken rather than locked. */
|
|
335
|
+
.vp-readonly { opacity: .62; cursor: default; }
|
|
336
|
+
.vp-readonly * { cursor: default !important; }
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// config-schema.json -> types/settings-keys.d.ts (the SlicerSettings interface, 907 keys).
|
|
2
|
-
// Regenerate: node types/gen_settings_types.mjs (do not hand-edit — fix this script instead)
|
|
3
|
-
//
|
|
4
|
-
// ponytail: mapping is driven purely by the schema's coXxx type. min/max and nullable are not reflected in types
|
|
5
|
-
// (they are runtime validation, not type validation, and 907 keys x branded number slows tsc down).
|
|
6
|
-
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'
|
|
7
|
-
import { dirname, resolve } from 'node:path'
|
|
8
|
-
import { fileURLToPath } from 'node:url'
|
|
9
|
-
|
|
10
|
-
const here = dirname(fileURLToPath(import.meta.url))
|
|
11
|
-
const schema = JSON.parse(readFileSync(resolve(here, '../data/config-schema.json'), 'utf8'))
|
|
12
|
-
|
|
13
|
-
const lit = (v) => "'" + String(v).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'"
|
|
14
|
-
// Some coEnum entries have no enum_values (70/64 mismatch) -> fail open to string.
|
|
15
|
-
const enumOf = (o) => (Array.isArray(o.enum_values) && o.enum_values.length)
|
|
16
|
-
? o.enum_values.map(lit).join(' | ')
|
|
17
|
-
: 'string'
|
|
18
|
-
|
|
19
|
-
// Vector types are `T[] | T` — settingScalar() accepts both, and the UI edits only the first element (settings.js:9).
|
|
20
|
-
const vec = (t) => `${/\|/.test(t) ? `(${t})` : t}[] | ${/\|/.test(t) ? `(${t})` : t}`
|
|
21
|
-
|
|
22
|
-
function tsType(o) {
|
|
23
|
-
switch (o.type) {
|
|
24
|
-
case 'coBool': return 'boolean'
|
|
25
|
-
case 'coBools': return vec('boolean')
|
|
26
|
-
case 'coInt': case 'coFloat': case 'coPercent': return 'number'
|
|
27
|
-
case 'coInts': case 'coFloats': case 'coPercents': return vec('number')
|
|
28
|
-
case 'coFloatOrPercent': return 'number | string'
|
|
29
|
-
case 'coFloatsOrPercents': return vec('number | string')
|
|
30
|
-
case 'coString': return 'string'
|
|
31
|
-
case 'coStrings': return vec('string')
|
|
32
|
-
case 'coEnum': return enumOf(o)
|
|
33
|
-
case 'coEnums': return vec(enumOf(o))
|
|
34
|
-
case 'coPoint': return 'Point'
|
|
35
|
-
case 'coPoints': return 'Point[]'
|
|
36
|
-
case 'coPointsGroups': return 'Point[][]'
|
|
37
|
-
default: return 'unknown'
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const esc = (s) => String(s).replace(/\*\//g, '*\\/')
|
|
42
|
-
const ident = (k) => /^[A-Za-z_$][\w$]*$/.test(k) ? k : lit(k).replace(/^'|'$/g, (m) => m === "'" ? "'" : m)
|
|
43
|
-
|
|
44
|
-
const lines = []
|
|
45
|
-
for (const key of Object.keys(schema).sort()) {
|
|
46
|
-
const o = schema[key]
|
|
47
|
-
const doc = [o.label, o.sidetext ? `(${o.sidetext})` : '', o.tooltip].filter(Boolean).join(' — ')
|
|
48
|
-
if (doc) lines.push(` /** ${esc(doc).replace(/\s*\n\s*/g, ' ')} */`)
|
|
49
|
-
const name = /^[A-Za-z_$][\w$]*$/.test(key) ? key : lit(key)
|
|
50
|
-
lines.push(` ${name}?: ${tsType(o)}`)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
writeFileSync(resolve(here, 'settings-keys.d.ts'), `// AUTO-GENERATED by types/gen_settings_types.mjs — DO NOT EDIT.
|
|
54
|
-
// Source: data/config-schema.json (${Object.keys(schema).length} keys)
|
|
55
|
-
|
|
56
|
-
/** [x, y] — coPoint family */
|
|
57
|
-
export type Point = [number, number]
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Slicer settings map. Sparse — it holds only edited keys; missing keys use the config-schema default.
|
|
61
|
-
* If you need arbitrary key extension, widen it with \`SlicerSettings & Record<string, unknown>\`.
|
|
62
|
-
*/
|
|
63
|
-
export interface SlicerSettings {
|
|
64
|
-
${lines.join('\n')}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** Setting keys that exist in config-schema */
|
|
68
|
-
export type SettingKey = keyof SlicerSettings & string
|
|
69
|
-
`)
|
|
70
|
-
console.log(`settings-keys.d.ts written — ${Object.keys(schema).length} keys`)
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { unzip as U, unzipSync as N } from "three/examples/jsm/libs/fflate.module.js";
|
|
2
|
-
function X(n) {
|
|
3
|
-
return new Promise((e) => {
|
|
4
|
-
let o = !1;
|
|
5
|
-
const t = (s) => {
|
|
6
|
-
o || (o = !0, e(s));
|
|
7
|
-
};
|
|
8
|
-
try {
|
|
9
|
-
U(n, (s, r) => t(s ? N(n) : r));
|
|
10
|
-
} catch {
|
|
11
|
-
t(N(n));
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
const E = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0];
|
|
16
|
-
function G(n, e) {
|
|
17
|
-
const o = new Array(12);
|
|
18
|
-
for (let t = 0; t < 4; t++)
|
|
19
|
-
for (let s = 0; s < 3; s++)
|
|
20
|
-
o[t * 3 + s] = n[t * 3] * e[s] + n[t * 3 + 1] * e[3 + s] + n[t * 3 + 2] * e[6 + s] + (t === 3 ? e[9 + s] : 0);
|
|
21
|
-
return o;
|
|
22
|
-
}
|
|
23
|
-
function O(n) {
|
|
24
|
-
if (!n) return E;
|
|
25
|
-
const e = n.trim().split(/\s+/).map(Number);
|
|
26
|
-
return e.length === 12 && e.every(Number.isFinite) ? e : E;
|
|
27
|
-
}
|
|
28
|
-
const B = {};
|
|
29
|
-
function i(n, e) {
|
|
30
|
-
const t = (B[e] || (B[e] = new RegExp(`\\b${e}\\s*=\\s*"([^"]*)"`))).exec(n);
|
|
31
|
-
return t ? t[1] : null;
|
|
32
|
-
}
|
|
33
|
-
const $ = /<vertex\s+x="([^"]*)"\s+y="([^"]*)"\s+z="([^"]*)"/g, C = /<triangle\s+v1="([^"]*)"\s+v2="([^"]*)"\s+v3="([^"]*)"([^>]*)/g, R = [
|
|
34
|
-
["paint_color", "color"],
|
|
35
|
-
// multi-material: state 1..16 == Extruder1..16
|
|
36
|
-
["paint_supports", "supports"],
|
|
37
|
-
// support enforcer/blocker: states 1 and 2
|
|
38
|
-
["paint_seam", "seam"],
|
|
39
|
-
// unsupported by the kernel — collected for the warning only
|
|
40
|
-
["paint_fuzzy_skin", "fuzzy"]
|
|
41
|
-
// ditto
|
|
42
|
-
];
|
|
43
|
-
function J() {
|
|
44
|
-
return { color: /* @__PURE__ */ new Map(), supports: /* @__PURE__ */ new Map(), seam: /* @__PURE__ */ new Map(), fuzzy: /* @__PURE__ */ new Map() };
|
|
45
|
-
}
|
|
46
|
-
function H(n) {
|
|
47
|
-
return !n || R.every(([, e]) => n[e].size === 0);
|
|
48
|
-
}
|
|
49
|
-
function D(n, e, o) {
|
|
50
|
-
for (const [t, s] of R) {
|
|
51
|
-
if (!n.includes(t)) continue;
|
|
52
|
-
const r = i(n, t);
|
|
53
|
-
r && o[s].set(e, r);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function V(n) {
|
|
57
|
-
const e = [];
|
|
58
|
-
$.lastIndex = 0;
|
|
59
|
-
let o;
|
|
60
|
-
for (; o = $.exec(n); ) e.push(+o[1], +o[2], +o[3]);
|
|
61
|
-
if (!e.length)
|
|
62
|
-
for (const r of n.match(/<vertex\b[^>]*>/g) || []) e.push(+i(r, "x"), +i(r, "y"), +i(r, "z"));
|
|
63
|
-
if (e.length < 9) return null;
|
|
64
|
-
const t = [], s = J();
|
|
65
|
-
for (C.lastIndex = 0; o = C.exec(n); ) {
|
|
66
|
-
const r = t.length / 3;
|
|
67
|
-
t.push(+o[1], +o[2], +o[3]), o[4].length > 2 && D(o[4], r, s);
|
|
68
|
-
}
|
|
69
|
-
if (!t.length)
|
|
70
|
-
for (const r of n.match(/<triangle\b[^>]*>/g) || []) {
|
|
71
|
-
const c = t.length / 3;
|
|
72
|
-
t.push(+i(r, "v1"), +i(r, "v2"), +i(r, "v3")), D(r, c, s);
|
|
73
|
-
}
|
|
74
|
-
return t.length ? { verts: e, tris: t, paint: s } : null;
|
|
75
|
-
}
|
|
76
|
-
function Y(n) {
|
|
77
|
-
const e = /* @__PURE__ */ new Map(), o = /<object\b([^>]*)>([\s\S]*?)<\/object>/g;
|
|
78
|
-
let t;
|
|
79
|
-
for (; t = o.exec(n); ) {
|
|
80
|
-
const c = i(t[1], "id");
|
|
81
|
-
if (!c) continue;
|
|
82
|
-
const p = t[2], f = [];
|
|
83
|
-
for (const u of p.match(/<component\b[^>]*>/g) || []) {
|
|
84
|
-
const m = i(u, "objectid");
|
|
85
|
-
m && f.push({ objectid: m, path: i(u, "p:path") || i(u, "path"), transform: O(i(u, "transform")) });
|
|
86
|
-
}
|
|
87
|
-
e.set(c, f.length ? { components: f } : { mesh: V(p) });
|
|
88
|
-
}
|
|
89
|
-
const s = [], r = /<build\b[^>]*>([\s\S]*?)<\/build>/.exec(n);
|
|
90
|
-
if (r)
|
|
91
|
-
for (const c of r[1].match(/<item\b[^>]*>/g) || []) {
|
|
92
|
-
const p = i(c, "objectid");
|
|
93
|
-
p && s.push({ objectid: p, path: i(c, "p:path") || i(c, "path"), transform: O(i(c, "transform")) });
|
|
94
|
-
}
|
|
95
|
-
return { objects: e, items: s };
|
|
96
|
-
}
|
|
97
|
-
function P(n) {
|
|
98
|
-
const e = String(n).replace(/^\/+/, "");
|
|
99
|
-
return e.includes("%") ? decodeURIComponent(e) : e;
|
|
100
|
-
}
|
|
101
|
-
function A(n) {
|
|
102
|
-
const e = {};
|
|
103
|
-
for (const o of n.match(/<metadata\b[^>]*>/g) || []) {
|
|
104
|
-
const t = i(o, "key");
|
|
105
|
-
t && (e[t] = i(o, "value") ?? "");
|
|
106
|
-
}
|
|
107
|
-
return e;
|
|
108
|
-
}
|
|
109
|
-
function W(n) {
|
|
110
|
-
const e = /* @__PURE__ */ new Map(), o = /<object\b([^>]*)>([\s\S]*?)<\/object>/g;
|
|
111
|
-
let t;
|
|
112
|
-
for (; t = o.exec(n); ) {
|
|
113
|
-
const c = i(t[1], "id");
|
|
114
|
-
c && e.set(c, A(t[2].replace(/<part\b[\s\S]*?<\/part>/g, "")));
|
|
115
|
-
}
|
|
116
|
-
const s = [], r = /<plate\b[^>]*>([\s\S]*?)<\/plate>/g;
|
|
117
|
-
for (; t = r.exec(n); ) {
|
|
118
|
-
const c = t[1], p = A(c.replace(/<model_instance\b[\s\S]*?<\/model_instance>/g, "")), f = [];
|
|
119
|
-
for (const u of c.match(/<model_instance\b[\s\S]*?<\/model_instance>/g) || []) {
|
|
120
|
-
const m = A(u).object_id;
|
|
121
|
-
m && f.push(m);
|
|
122
|
-
}
|
|
123
|
-
s.push({ index: Math.max(0, (Number(p.plater_id) || s.length + 1) - 1), objectIds: f });
|
|
124
|
-
}
|
|
125
|
-
return { objects: e, plates: s };
|
|
126
|
-
}
|
|
127
|
-
function q(n, e) {
|
|
128
|
-
var c, p;
|
|
129
|
-
const o = (f) => {
|
|
130
|
-
const u = n.get(f);
|
|
131
|
-
return u ? e.decode(u) : null;
|
|
132
|
-
}, t = {
|
|
133
|
-
settings: null,
|
|
134
|
-
// Metadata/project_settings.config — the flattened preset (raw upstream strings)
|
|
135
|
-
objectMeta: /* @__PURE__ */ new Map(),
|
|
136
|
-
// 3mf object id -> per-object metadata (name, extruder, per-object overrides)
|
|
137
|
-
plates: [],
|
|
138
|
-
// [{index, objectIds}]
|
|
139
|
-
hasLayerHeightProfile: !1,
|
|
140
|
-
hasCustomGcodePerLayer: !1
|
|
141
|
-
}, s = o("Metadata/project_settings.config");
|
|
142
|
-
if (s)
|
|
143
|
-
try {
|
|
144
|
-
t.settings = JSON.parse(s);
|
|
145
|
-
} catch {
|
|
146
|
-
t.settings = null;
|
|
147
|
-
}
|
|
148
|
-
const r = o("Metadata/model_settings.config");
|
|
149
|
-
if (r) {
|
|
150
|
-
const f = W(r);
|
|
151
|
-
t.objectMeta = f.objects, t.plates = f.plates;
|
|
152
|
-
}
|
|
153
|
-
return t.hasLayerHeightProfile = !!((c = o("Metadata/layer_heights_profile.txt")) != null && c.trim()), t.hasCustomGcodePerLayer = !!((p = o("Metadata/custom_gcode_per_layer.xml")) != null && p.trim()), t;
|
|
154
|
-
}
|
|
155
|
-
async function Q(n, e = "model") {
|
|
156
|
-
const o = ArrayBuffer.isView(n) ? new Uint8Array(n.buffer, n.byteOffset, n.byteLength) : new Uint8Array(n), t = await X(o), s = /* @__PURE__ */ new Map();
|
|
157
|
-
for (const l of Object.keys(t)) s.set(P(l), t[l]);
|
|
158
|
-
const r = new TextDecoder(), c = /* @__PURE__ */ new Map(), p = (l) => {
|
|
159
|
-
const g = P(l);
|
|
160
|
-
if (c.has(g)) return c.get(g);
|
|
161
|
-
const a = s.get(g), d = a ? Y(r.decode(a)) : null;
|
|
162
|
-
return c.set(g, d), d;
|
|
163
|
-
};
|
|
164
|
-
let f = "3D/3dmodel.model";
|
|
165
|
-
const u = s.get("_rels/.rels");
|
|
166
|
-
if (u) {
|
|
167
|
-
for (const l of r.decode(u).match(/<Relationship\b[^>]*>/g) || [])
|
|
168
|
-
if ((i(l, "Type") || "").endsWith("/3dmodel")) {
|
|
169
|
-
f = P(i(l, "Target"));
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
const m = p(f);
|
|
174
|
-
if (!m) throw new Error(`3MF root model not found: ${f}`);
|
|
175
|
-
const k = [], F = (l, g, a, d, y, x) => {
|
|
176
|
-
if (x > 16) return;
|
|
177
|
-
const j = p(g), b = j == null ? void 0 : j.objects.get(l);
|
|
178
|
-
if (!b) return;
|
|
179
|
-
if (b.components) {
|
|
180
|
-
for (const h of b.components) F(h.objectid, h.path || g, G(h.transform, a), d, y, x + 1);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
if (!b.mesh) return;
|
|
184
|
-
const { verts: w, tris: _, paint: M } = b.mesh, v = d.length / 9;
|
|
185
|
-
for (let h = 0; h < _.length; h++) {
|
|
186
|
-
const I = _[h] * 3, S = w[I], T = w[I + 1], z = w[I + 2];
|
|
187
|
-
d.push(
|
|
188
|
-
S * a[0] + T * a[3] + z * a[6] + a[9],
|
|
189
|
-
S * a[1] + T * a[4] + z * a[7] + a[10],
|
|
190
|
-
S * a[2] + T * a[5] + z * a[8] + a[11]
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
if (M) for (const [, h] of R)
|
|
194
|
-
for (const [I, S] of M[h]) y[h].set(v + I, S);
|
|
195
|
-
}, L = m.items.length ? m.items : [...m.objects.keys()].filter((l) => m.objects.get(l).mesh).map((l) => ({ objectid: l, path: f, transform: E }));
|
|
196
|
-
return L.forEach((l, g) => {
|
|
197
|
-
const a = [], d = J();
|
|
198
|
-
if (F(l.objectid, l.path || f, l.transform, a, d, 0), a.length < 9) return;
|
|
199
|
-
const y = new Float32Array(a);
|
|
200
|
-
let x = 1 / 0, j = 1 / 0, b = -1 / 0, w = -1 / 0;
|
|
201
|
-
for (let _ = 0; _ < y.length; _ += 3) {
|
|
202
|
-
const M = y[_], v = y[_ + 1];
|
|
203
|
-
M < x && (x = M), M > b && (b = M), v < j && (j = v), v > w && (w = v);
|
|
204
|
-
}
|
|
205
|
-
k.push({
|
|
206
|
-
name: L.length > 1 ? `${e}#${g + 1}` : e,
|
|
207
|
-
tris: y,
|
|
208
|
-
objectid: l.objectid,
|
|
209
|
-
paint: H(d) ? null : d,
|
|
210
|
-
bbox: { minX: x, minY: j, maxX: b, maxY: w }
|
|
211
|
-
});
|
|
212
|
-
}), { objects: k, project: q(s, r) };
|
|
213
|
-
}
|
|
214
|
-
export {
|
|
215
|
-
Q as p
|
|
216
|
-
};
|