three-slicer-viewer 0.3.1 → 0.3.2
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/VIEWER.md +2 -1
- package/dist/gcode_parse.js +118 -76
- package/dist/index.js +4903 -4163
- package/dist/model_loaders-DxlFNFOu.js +196 -0
- package/dist/model_loaders.js +9 -6
- package/dist/parse_3mf-BZISF3eW.js +327 -0
- package/dist/parse_3mf.worker.js +1 -1
- package/dist/toolpath.js +117 -195
- package/dist/toolpath_palette-B8xEl-qa.js +89 -0
- package/package.json +1 -1
- package/types/gcode.d.ts +27 -1
- package/types/viewer.d.ts +3 -1
- package/dist/model_loaders-aHV5ix50.js +0 -188
- package/dist/parse_3mf-jEUAw8JM.js +0 -300
package/VIEWER.md
CHANGED
|
@@ -95,7 +95,8 @@ Every panel can be switched off, and the values the component owns can be seeded
|
|
|
95
95
|
resin masks on a filament bed. The one number it cannot supply is the display's PHYSICAL size: millimetres
|
|
96
96
|
appear nowhere in an SL1, so the preview is scaled by the printer set in the viewer and the import notice says
|
|
97
97
|
so. Export hands an imported archive back byte-identical rather than re-rasterizing empty geometry.
|
|
98
|
-
- **`gcode`** — G-code text drawn on the selected plate instead of a slice result
|
|
98
|
+
- **`gcode`** — G-code text drawn on the selected plate instead of a slice result, or a `{ plateIndex: text }` map
|
|
99
|
+
drawn plate by plate (what an opened `.gcode.3mf` becomes; the viewer is preview-only while one is shown). `parseGcode` recovers roles from
|
|
99
100
|
`;TYPE:` (OrcaSlicer/PrusaSlicer/Cura), from `;_EXTRUSION_ROLE:` tags and from this kernel's own feature comments;
|
|
100
101
|
bead width comes from `;WIDTH:` or, absent that, from E. What the file never states cannot be recovered: an
|
|
101
102
|
unmarked run reads as wall, and there is no print-time estimate (that needs the machine's acceleration limits).
|
package/dist/gcode_parse.js
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
|
-
import { D as
|
|
2
|
-
import { R as t, e as
|
|
3
|
-
|
|
1
|
+
import { D as Lt, a as Nt } from "./viewer_defaults-B7UUZ582.js";
|
|
2
|
+
import { R as t, e as Z } from "./toolpath_encoding-BuYs95qZ.js";
|
|
3
|
+
import { T as ft } from "./toolpath_palette-B8xEl-qa.js";
|
|
4
|
+
const F = 1e-6, Rt = 254, It = /^(filament|extruder)_colour\s*=\s*(.*)$/i, ut = (i) => i.split(/[;,]/).map((r) => {
|
|
5
|
+
const s = /^"?#?([0-9a-f]{6})(?:[0-9a-f]{2})?"?$/i.exec(r.trim());
|
|
6
|
+
return s ? "#" + s[1].toUpperCase() : null;
|
|
7
|
+
}), At = (i) => "#" + ft[i % ft.length].map((r) => Math.round(r * 255).toString(16).padStart(2, "0")).join("");
|
|
8
|
+
function gt(i, r) {
|
|
9
|
+
let s = [];
|
|
10
|
+
Array.isArray(i?.colors) && (s = i.colors);
|
|
11
|
+
const g = r ?? [], u = Math.max(s.length, g.length, i?.filament_mm_by_tool?.length ?? 0);
|
|
12
|
+
return Array.from({ length: u }, (m, c) => s[c] || g[c] || At(c));
|
|
13
|
+
}
|
|
14
|
+
function wt(i, r) {
|
|
15
|
+
return dt(i.gcode, gt(i.stats, r));
|
|
16
|
+
}
|
|
17
|
+
function dt(i, r) {
|
|
18
|
+
const s = String(i ?? ""), g = [r].flat().filter(Boolean);
|
|
19
|
+
if (!g.length || /^;\s*filament_colour\s*=/mi.test(s)) return s;
|
|
20
|
+
const u = "; filament_colour = " + g.join(";") + `
|
|
21
|
+
`, m = s.lastIndexOf(`
|
|
22
|
+
; CONFIG_BLOCK_END`);
|
|
23
|
+
if (m >= 0) return s.slice(0, m + 1) + u + s.slice(m + 1);
|
|
24
|
+
let c = `
|
|
25
|
+
`;
|
|
26
|
+
return (!s || s.endsWith(`
|
|
27
|
+
`)) && (c = ""), s + c + u;
|
|
28
|
+
}
|
|
29
|
+
const St = {
|
|
4
30
|
// OrcaSlicer / PrusaSlicer ;TYPE: names
|
|
5
31
|
"outer wall": t.WALL,
|
|
6
32
|
"external perimeter": t.WALL,
|
|
@@ -43,7 +69,7 @@ const F = 1e-6, lt = {
|
|
|
43
69
|
skin: t.SOLID,
|
|
44
70
|
"support-interface": t.SUPPORT,
|
|
45
71
|
"prime-tower": t.PRIME
|
|
46
|
-
},
|
|
72
|
+
}, Pt = [
|
|
47
73
|
["skirt/brim", t.SKIRT],
|
|
48
74
|
["skirt", t.SKIRT],
|
|
49
75
|
["walls", t.WALL],
|
|
@@ -54,7 +80,7 @@ const F = 1e-6, lt = {
|
|
|
54
80
|
["support", t.SUPPORT],
|
|
55
81
|
["prime tower", t.PRIME],
|
|
56
82
|
["wipe_tower_real", t.PRIME]
|
|
57
|
-
],
|
|
83
|
+
], Et = (i, r) => i === r || r.length < i.length && " (:/".includes(i[r.length]) && i.startsWith(r), Ot = {
|
|
58
84
|
1: t.WALL,
|
|
59
85
|
2: t.WALL,
|
|
60
86
|
3: t.WALL,
|
|
@@ -73,120 +99,136 @@ const F = 1e-6, lt = {
|
|
|
73
99
|
16: t.SUPPORT,
|
|
74
100
|
17: t.PRIME
|
|
75
101
|
};
|
|
76
|
-
function
|
|
77
|
-
const
|
|
78
|
-
let
|
|
79
|
-
const
|
|
80
|
-
let
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
102
|
+
function Gt(i, r = {}) {
|
|
103
|
+
const s = Math.PI / 4 * (r.filamentDiameter > 0 ? r.filamentDiameter : Lt) ** 2, g = r.defaultLayerHeight > 0 ? r.defaultLayerHeight : Nt;
|
|
104
|
+
let u = 0, m = 0, c = 0, b = 0, _ = !0, W = !0, d = 0, w = t.WALL, y = 0, R = null;
|
|
105
|
+
const E = [];
|
|
106
|
+
let D = !1, x = !0, K = NaN, q = 0, X = 0, $ = 0;
|
|
107
|
+
const v = /* @__PURE__ */ new Set([0]), H = [];
|
|
108
|
+
let z = [], k = [], j = !1;
|
|
109
|
+
const V = () => {
|
|
110
|
+
w = t.WALL, y = 0;
|
|
111
|
+
}, U = (o, a = !1) => {
|
|
112
|
+
R = { z: o, p: [], w: [] }, E.push(R), x = !1, K = NaN, (a || !j) && V();
|
|
113
|
+
}, mt = () => E.length > 1 ? E[E.length - 2].z : 0, J = (o, a, S, P, A, n, e) => {
|
|
114
|
+
const p = Math.hypot(P - o, A - a, n - S);
|
|
115
|
+
if (!(p < F))
|
|
86
116
|
if (e > F) {
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
} else
|
|
117
|
+
$ += e, H[d] = (H[d] ?? 0) + e, x ? U(Number.isNaN(K) ? n : K) : !D && n > R.z + 1e-3 && U(n);
|
|
118
|
+
const h = Z(w, d);
|
|
119
|
+
R.p.push(o, a, S, h, P, A, n, h);
|
|
120
|
+
const f = Math.max(0.02, R.z - mt() || g), L = y > 0 ? y : e * s / (p * f) + f * (1 - Math.PI / 4);
|
|
121
|
+
R.w.push(Math.min(3, Math.max(0.05, L))), q++;
|
|
122
|
+
} else R && (R.p.push(o, a, S, Z(t.TRAVEL, d), P, A, n, Z(t.TRAVEL, d)), R.w.push(0), X++);
|
|
93
123
|
};
|
|
94
|
-
for (const
|
|
124
|
+
for (const o of i.split(`
|
|
95
125
|
`)) {
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
98
|
-
const e =
|
|
126
|
+
const a = o.indexOf(";"), S = (a < 0 ? o : o.slice(0, a)).trim(), P = a < 0 ? "" : o.slice(a + 1).trim();
|
|
127
|
+
if (P && !S) {
|
|
128
|
+
const e = P.toLowerCase(), p = It.exec(P);
|
|
129
|
+
if (p) {
|
|
130
|
+
p[1].toLowerCase() === "filament" ? z = ut(p[2]) : k = ut(p[2]);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
99
133
|
if (e.startsWith("type:")) {
|
|
100
|
-
|
|
134
|
+
w = St[e.slice(5).trim()] ?? t.WALL, j = !0;
|
|
101
135
|
continue;
|
|
102
136
|
}
|
|
103
137
|
if (e.startsWith("_extrusion_role:")) {
|
|
104
|
-
|
|
138
|
+
w = Ot[parseInt(e.slice(16), 10)] ?? t.WALL, j = !0;
|
|
105
139
|
continue;
|
|
106
140
|
}
|
|
107
141
|
if (e.startsWith("width:")) {
|
|
108
|
-
const
|
|
109
|
-
|
|
142
|
+
const L = parseFloat(e.slice(6));
|
|
143
|
+
y = L > 0 ? L : 0;
|
|
110
144
|
continue;
|
|
111
145
|
}
|
|
112
146
|
if (e.startsWith("layer_change") || e.startsWith("layer:")) {
|
|
113
|
-
|
|
147
|
+
D = !0, x = !0, V();
|
|
114
148
|
continue;
|
|
115
149
|
}
|
|
116
150
|
if (e.startsWith("z:")) {
|
|
117
|
-
const
|
|
118
|
-
|
|
151
|
+
const L = parseFloat(e.slice(2));
|
|
152
|
+
x && L > 0 && (D = !0, U(L));
|
|
119
153
|
continue;
|
|
120
154
|
}
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
123
|
-
|
|
155
|
+
const h = /^layer \d+ z([-\d.]+)/.exec(e);
|
|
156
|
+
if (h) {
|
|
157
|
+
D = !0, U(parseFloat(h[1]), !0);
|
|
124
158
|
continue;
|
|
125
159
|
}
|
|
126
|
-
const
|
|
127
|
-
|
|
160
|
+
const f = Pt.find(([L]) => Et(e, L));
|
|
161
|
+
f && (w = f[1]);
|
|
128
162
|
continue;
|
|
129
163
|
}
|
|
130
|
-
if (!
|
|
131
|
-
const
|
|
132
|
-
if (
|
|
133
|
-
|
|
164
|
+
if (!S) continue;
|
|
165
|
+
const A = S.split(/\s+/), n = A[0].toUpperCase();
|
|
166
|
+
if (n === "G90") {
|
|
167
|
+
_ = !0;
|
|
134
168
|
continue;
|
|
135
169
|
}
|
|
136
|
-
if (
|
|
137
|
-
|
|
170
|
+
if (n === "G91") {
|
|
171
|
+
_ = !1;
|
|
138
172
|
continue;
|
|
139
173
|
}
|
|
140
|
-
if (
|
|
141
|
-
|
|
174
|
+
if (n === "M82") {
|
|
175
|
+
W = !0;
|
|
142
176
|
continue;
|
|
143
177
|
}
|
|
144
|
-
if (
|
|
145
|
-
|
|
178
|
+
if (n === "M83") {
|
|
179
|
+
W = !1;
|
|
146
180
|
continue;
|
|
147
181
|
}
|
|
148
|
-
if (/^T\d+$/.test(
|
|
149
|
-
|
|
182
|
+
if (/^T\d+$/.test(n)) {
|
|
183
|
+
const e = parseInt(n.slice(1), 10);
|
|
184
|
+
e <= Rt && (d = e, v.add(d));
|
|
150
185
|
continue;
|
|
151
186
|
}
|
|
152
|
-
if (
|
|
153
|
-
let e = NaN,
|
|
154
|
-
for (let
|
|
155
|
-
const
|
|
156
|
-
Number.isNaN(
|
|
187
|
+
if (n === "G92" || n === "G0" || n === "G1" || n === "G2" || n === "G3") {
|
|
188
|
+
let e = NaN, p = NaN, h = NaN, f = NaN, L = 0, tt = 0;
|
|
189
|
+
for (let I = 1; I < A.length; I++) {
|
|
190
|
+
const l = A[I][0], N = parseFloat(A[I].slice(1));
|
|
191
|
+
Number.isNaN(N) || (l === "X" || l === "x" ? e = N : l === "Y" || l === "y" ? p = N : l === "Z" || l === "z" ? h = N : l === "E" || l === "e" ? f = N : l === "I" || l === "i" ? L = N : (l === "J" || l === "j") && (tt = N));
|
|
157
192
|
}
|
|
158
|
-
if (
|
|
159
|
-
Number.isNaN(e) || (
|
|
193
|
+
if (n === "G92") {
|
|
194
|
+
Number.isNaN(e) || (u = e), Number.isNaN(p) || (m = p), Number.isNaN(h) || (c = h), Number.isNaN(f) || (b = f);
|
|
160
195
|
continue;
|
|
161
196
|
}
|
|
162
|
-
const
|
|
163
|
-
if (
|
|
164
|
-
const
|
|
165
|
-
let
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
let
|
|
170
|
-
for (let
|
|
171
|
-
const
|
|
172
|
-
|
|
197
|
+
const C = Number.isNaN(e) ? u : _ ? e : u + e, B = Number.isNaN(p) ? m : _ ? p : m + p, Y = Number.isNaN(h) ? c : _ ? h : c + h, et = Number.isNaN(f) ? 0 : W ? f - b : f;
|
|
198
|
+
if (n === "G2" || n === "G3") {
|
|
199
|
+
const I = u + L, l = m + tt, N = Math.hypot(u - I, m - l), G = Math.atan2(m - l, u - I);
|
|
200
|
+
let O = Math.atan2(B - l, C - I);
|
|
201
|
+
const nt = n === "G3";
|
|
202
|
+
nt && O <= G + F && (O += 2 * Math.PI), !nt && O >= G - F && (O -= 2 * Math.PI);
|
|
203
|
+
const M = Math.max(1, Math.min(360, Math.ceil(Math.abs(O - G) * N / 0.3)));
|
|
204
|
+
let it = u, rt = m, ot = c;
|
|
205
|
+
for (let T = 1; T <= M; T++) {
|
|
206
|
+
const st = G + (O - G) * T / M, at = T === M ? C : I + N * Math.cos(st), lt = T === M ? B : l + N * Math.sin(st), ct = c + (Y - c) * T / M;
|
|
207
|
+
J(it, rt, ot, at, lt, ct, et / M), it = at, rt = lt, ot = ct;
|
|
173
208
|
}
|
|
174
209
|
} else
|
|
175
|
-
|
|
176
|
-
|
|
210
|
+
J(u, m, c, C, B, Y, et);
|
|
211
|
+
u = C, m = B, c = Y, Number.isNaN(f) || (b = W ? f : b + f);
|
|
177
212
|
}
|
|
178
213
|
}
|
|
214
|
+
const pt = Math.max(z.length, k.length), Q = Array.from({ length: pt }, (o, a) => k[a] || z[a] || null), ht = Array.from({ length: Math.max(...v) + 1 }, (o, a) => H[a] || 0);
|
|
179
215
|
return {
|
|
180
|
-
layers:
|
|
216
|
+
layers: E.map((o) => ({ z: o.z, paths: Float32Array.from(o.p), widths: Float32Array.from(o.w) })),
|
|
181
217
|
stats: {
|
|
182
|
-
layers:
|
|
183
|
-
path_segments:
|
|
184
|
-
travel_segments:
|
|
185
|
-
filament_mm:
|
|
186
|
-
tools: [...
|
|
218
|
+
layers: E.length,
|
|
219
|
+
path_segments: q,
|
|
220
|
+
travel_segments: X,
|
|
221
|
+
filament_mm: $,
|
|
222
|
+
tools: [...v].sort((o, a) => o - a),
|
|
223
|
+
// The kernel's own stat name, so the Filament-view switch and the stats card's per-tool split work unchanged.
|
|
224
|
+
filament_mm_by_tool: ht,
|
|
225
|
+
...Q.some(Boolean) && { colors: Q }
|
|
187
226
|
}
|
|
188
227
|
};
|
|
189
228
|
}
|
|
190
229
|
export {
|
|
191
|
-
|
|
230
|
+
wt as exportedGcode,
|
|
231
|
+
Gt as parseGcode,
|
|
232
|
+
gt as resultToolColors,
|
|
233
|
+
dt as withFilamentColours
|
|
192
234
|
};
|