three-slicer 0.2.5 → 0.3.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/CHANGELOG.md +134 -0
- package/README.md +13 -8
- package/THIRD-PARTY-NOTICES.md +7 -2
- package/components/dist/SettingsPanel.js +12 -198
- package/data/config-schema-lean.json +1 -0
- package/data/processes.js +1 -1
- package/data/ui-tree-keys.json +1 -0
- package/engine/src/client.js +9 -0
- package/engine/src/data.js +6 -0
- package/engine/src/settings.js +12 -627
- package/engine/src/sla_core.js +14 -8
- package/engine/src/toggle_eval.js +9 -77
- package/package.json +24 -17
- package/types/client.d.ts +3 -0
- package/types/components.d.ts +3 -29
- package/types/settings.d.ts +15 -0
- package/types/toggle.d.ts +2 -22
- package/types/viewer-gcode.d.ts +2 -29
- package/types/viewer-loaders.d.ts +1 -33
- package/types/viewer-toolpath.d.ts +3 -113
- package/types/viewer.d.ts +6 -213
- package/viewer/dist/Viewport.js +9 -6571
- package/viewer/dist/gcode_reexport.js +1 -0
- package/viewer/dist/loaders_reexport.js +1 -0
- package/viewer/dist/toolpath_reexport.js +1 -0
- package/components/README.md +0 -44
- package/components/styles.css +0 -88
- package/engine/src/kernel_setting_keys.js +0 -132
- package/engine/src/preset_file.js +0 -99
- package/types/.omc/state/sessions/02e5ddf5-4378-46e1-8fca-e90412c30804/pre-tool-advisory-throttle.json +0 -10
- package/viewer/README.md +0 -423
- package/viewer/dist/gcode_parse.js +0 -190
- package/viewer/dist/make_worker.js +0 -31
- package/viewer/dist/model_loaders.js +0 -184
- package/viewer/dist/parse_3mf-C2X_W442.js +0 -300
- package/viewer/dist/parse_3mf.worker.js +0 -10
- package/viewer/dist/sl1_encode.worker.js +0 -10
- package/viewer/dist/sl1_write-CtX8cVL7.js +0 -302
- package/viewer/dist/sla_reconstruct-CXkYhux2.js +0 -176
- package/viewer/dist/sla_reconstruct.worker.js +0 -24
- package/viewer/dist/sla_slice.worker.js +0 -74
- package/viewer/dist/toolpath_gpu-4foc4FaU.js +0 -482
- package/viewer/dist/toolpath_gpu.js +0 -13
- package/viewer/styles.css +0 -394
package/engine/src/sla_core.js
CHANGED
|
@@ -10,7 +10,13 @@
|
|
|
10
10
|
// Determinism: iteration order is the STL's own triangle order, stitching maps insert in encounter order, and
|
|
11
11
|
// vertices on a slicing plane are pushed up by a fixed epsilon — same input bytes, same output bytes.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
// The toolpath stream and binary STL layouts. This worker is standalone (no imports), so it keeps its own copy of
|
|
14
|
+
// numbers the viewer holds in core/toolpath_encoding.js and core/stl_format.js; TOOLPATH_SPEC.md is the contract.
|
|
15
|
+
const STRIDE = 8 // floats per segment: [x0,y0,z0,enc, x1,y1,z1,enc]
|
|
16
|
+
const ROLE_CONTOUR = 1 // ROLE.WALL — rendered as 'wall' by the preview's feature colouring
|
|
17
|
+
const STL_HEADER_BYTES = 80
|
|
18
|
+
const STL_DATA_OFFSET = 84 // header + the uint32 triangle count
|
|
19
|
+
const STL_TRIANGLE_BYTES = 50
|
|
14
20
|
const CONTOUR_WIDTH = 0.2 // display width of a contour segment (SLA has no bead width)
|
|
15
21
|
const PLANE_EPS = 1e-9 // a vertex exactly on a plane counts as above it — deterministic tie-break
|
|
16
22
|
const KEY_SCALE = 1e4 // endpoint welding: 0.1 micrometre grid
|
|
@@ -18,13 +24,13 @@ const KEY_SCALE = 1e4 // endpoint welding: 0.1 micrometre grid
|
|
|
18
24
|
/** Binary STL -> Float32Array of 9 floats per triangle (vertices only; normals are recomputed). */
|
|
19
25
|
export function parseBinarySTL(bytes) {
|
|
20
26
|
if (!(bytes instanceof Uint8Array)) bytes = new Uint8Array(bytes)
|
|
21
|
-
if (bytes.byteLength <
|
|
27
|
+
if (bytes.byteLength < STL_DATA_OFFSET) return { error: 'not a binary STL (shorter than its own header)' }
|
|
22
28
|
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
23
|
-
const count = dv.getUint32(
|
|
24
|
-
if (
|
|
29
|
+
const count = dv.getUint32(STL_HEADER_BYTES, true)
|
|
30
|
+
if (STL_DATA_OFFSET + STL_TRIANGLE_BYTES * count !== bytes.byteLength) return { error: 'not a binary STL (triangle count does not match the byte length)' }
|
|
25
31
|
const tris = new Float32Array(count * 9)
|
|
26
32
|
for (let i = 0; i < count; i++) {
|
|
27
|
-
const base =
|
|
33
|
+
const base = STL_DATA_OFFSET + STL_TRIANGLE_BYTES * i + 12 // skip the stored normal — recomputed from the winding below
|
|
28
34
|
for (let f = 0; f < 9; f++) tris[i * 9 + f] = dv.getFloat32(base + 4 * f, true)
|
|
29
35
|
}
|
|
30
36
|
return { tris, count }
|
|
@@ -149,15 +155,15 @@ export function sliceSla(stlBytes, params = {}, hooks = {}) {
|
|
|
149
155
|
for (const pts of loops) { area += loopArea(pts); segCount += pts.length / 2 }
|
|
150
156
|
area = Math.max(0, area)
|
|
151
157
|
volume += area * thickness
|
|
152
|
-
const paths = new Float32Array(segCount *
|
|
158
|
+
const paths = new Float32Array(segCount * STRIDE)
|
|
153
159
|
const widths = new Float32Array(segCount)
|
|
154
160
|
let w = 0
|
|
155
161
|
for (const pts of loops) {
|
|
156
162
|
const n = pts.length / 2
|
|
157
163
|
for (let p = 0; p < n; p++) {
|
|
158
164
|
const q = (p + 1) % n
|
|
159
|
-
paths[w *
|
|
160
|
-
paths[w *
|
|
165
|
+
paths[w * STRIDE] = pts[p * 2]; paths[w * STRIDE + 1] = pts[p * 2 + 1]; paths[w * STRIDE + 2] = top; paths[w * STRIDE + 3] = ROLE_CONTOUR
|
|
166
|
+
paths[w * STRIDE + 4] = pts[q * 2]; paths[w * STRIDE + 5] = pts[q * 2 + 1]; paths[w * STRIDE + 6] = top; paths[w * STRIDE + 7] = ROLE_CONTOUR
|
|
161
167
|
widths[w] = CONTOUR_WIDTH
|
|
162
168
|
w++
|
|
163
169
|
}
|
|
@@ -1,77 +1,9 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { toggleRules
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
let v = settings ? settings[k] : undefined
|
|
11
|
-
if (v === undefined || v === '') { const d = schema[k]?.default; v = Array.isArray(d) ? d[0] : d }
|
|
12
|
-
return v
|
|
13
|
-
}
|
|
14
|
-
const num = k => { const v = val(k); const n = parseFloat(v); return Number.isFinite(n) ? n : 0 }
|
|
15
|
-
return {
|
|
16
|
-
bool: k => { const v = val(k); return v === true || v === 1 || v === '1' || v === 'true' },
|
|
17
|
-
int: k => Math.trunc(num(k)),
|
|
18
|
-
float: k => num(k),
|
|
19
|
-
has: k => k in schema,
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Upstream locals translated inline (viewer-related conditions only). Each value is a boolean.
|
|
24
|
-
function makeLocals(cfg) {
|
|
25
|
-
const have_raft = cfg.int('raft_layers') > 0
|
|
26
|
-
const has_spiral_vase = cfg.bool('spiral_mode')
|
|
27
|
-
const has_top_shell = cfg.int('top_shell_layers') > 0 || (has_spiral_vase && cfg.int('bottom_shell_layers') > 1)
|
|
28
|
-
const has_bottom_shell = cfg.int('bottom_shell_layers') > 0
|
|
29
|
-
return {
|
|
30
|
-
have_raft,
|
|
31
|
-
have_perimeters: cfg.int('wall_loops') > 0,
|
|
32
|
-
have_infill: cfg.float('sparse_infill_density') > 0,
|
|
33
|
-
has_spiral_vase,
|
|
34
|
-
has_top_shell,
|
|
35
|
-
has_bottom_shell,
|
|
36
|
-
has_solid_infill: has_top_shell || has_bottom_shell,
|
|
37
|
-
have_skirt: cfg.int('skirt_loops') > 0,
|
|
38
|
-
have_support_material: cfg.bool('enable_support') || have_raft,
|
|
39
|
-
have_support_interface: cfg.int('support_interface_top_layers') > 0 || cfg.int('support_interface_bottom_layers') > 0,
|
|
40
|
-
have_prime_tower: cfg.bool('enable_prime_tower'),
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Evaluates enable_if (up to the first comma) to a boolean. Returns null (= stays enabled) when not fully translatable.
|
|
45
|
-
export function evalEnableIf(expr, locals, cfg) {
|
|
46
|
-
let s = String(expr).split(',')[0].trim()
|
|
47
|
-
if (!s) return null
|
|
48
|
-
// Direct config access pattern -> value substitution
|
|
49
|
-
s = s.replace(/config->opt_bool\(\s*"([^"]+)"\s*\)/g, (_, k) => cfg.bool(k) ? 'true' : 'false')
|
|
50
|
-
s = s.replace(/config->opt_int\(\s*"([^"]+)"\s*\)/g, (_, k) => String(cfg.int(k)))
|
|
51
|
-
s = s.replace(/config->opt_float\(\s*"([^"]+)"\s*\)/g, (_, k) => String(cfg.float(k)))
|
|
52
|
-
// Substitute known locals (longest name first — prevents partial matches)
|
|
53
|
-
for (const name of Object.keys(locals).sort((a, b) => b.length - a.length))
|
|
54
|
-
s = s.replace(new RegExp('\\b' + name + '\\b', 'g'), locals[name] ? 'true' : 'false')
|
|
55
|
-
// Check the remaining string is a safe boolean expression (only true/false/numbers/operators/parens) — otherwise unknown -> null
|
|
56
|
-
const stripped = s.replace(/\btrue\b|\bfalse\b/g, '1')
|
|
57
|
-
if (!/^[\s()!<>=&|0-9.]*$/.test(stripped)) return null
|
|
58
|
-
try { return !!Function('"use strict";return (' + s + ')')() } catch { return null }
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Map of keys disabled under the current settings { key: condition }. Only rules that are unambiguously false.
|
|
62
|
-
export function disabledKeys(cfg) {
|
|
63
|
-
const locals = makeLocals(cfg)
|
|
64
|
-
const groups = ['toggle_print_fff_options', 'toggle_filament_options', 'toggle_printer_options',
|
|
65
|
-
'TabFilament::toggle_options', 'TabPrinter::toggle_options']
|
|
66
|
-
const out = {}
|
|
67
|
-
for (const gname of groups) {
|
|
68
|
-
const g = toggles[gname]
|
|
69
|
-
if (!g || !Array.isArray(g.rules)) continue
|
|
70
|
-
for (const rule of g.rules) {
|
|
71
|
-
if (!rule.enable_if || !Array.isArray(rule.fields)) continue
|
|
72
|
-
const en = evalEnableIf(rule.enable_if, locals, cfg)
|
|
73
|
-
if (en === false) for (const k of rule.fields) if (!(k in out)) out[k] = rule.enable_if
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return out
|
|
77
|
-
}
|
|
1
|
+
// three-slicer/toggle — the evaluator from the permissive package, bound to upstream's toggle rules.
|
|
2
|
+
// The rules (toggle-rules.json, extracted from OrcaSlicer's toggle_options) and the full schema are this
|
|
3
|
+
// package's data; the evaluator itself is three-slicer-viewer's. Same surface as before the split.
|
|
4
|
+
import { makeToggle, evalEnableIf } from 'three-slicer-viewer/toggle'
|
|
5
|
+
import { toggleRules, schema } from './data.js'
|
|
6
|
+
const bound = makeToggle(toggleRules, schema)
|
|
7
|
+
export const makeCfg = bound.makeCfg
|
|
8
|
+
export const disabledKeys = bound.disabledKeys
|
|
9
|
+
export { evalEnableIf }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "three-slicer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
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",
|
|
@@ -39,15 +39,15 @@
|
|
|
39
39
|
},
|
|
40
40
|
"./viewer/toolpath": {
|
|
41
41
|
"types": "./types/viewer-toolpath.d.ts",
|
|
42
|
-
"default": "./viewer/dist/
|
|
42
|
+
"default": "./viewer/dist/toolpath_reexport.js"
|
|
43
43
|
},
|
|
44
44
|
"./viewer/loaders": {
|
|
45
45
|
"types": "./types/viewer-loaders.d.ts",
|
|
46
|
-
"default": "./viewer/dist/
|
|
46
|
+
"default": "./viewer/dist/loaders_reexport.js"
|
|
47
47
|
},
|
|
48
48
|
"./viewer/gcode": {
|
|
49
49
|
"types": "./types/viewer-gcode.d.ts",
|
|
50
|
-
"default": "./viewer/dist/
|
|
50
|
+
"default": "./viewer/dist/gcode_reexport.js"
|
|
51
51
|
},
|
|
52
52
|
"./components": {
|
|
53
53
|
"types": "./types/components.d.ts",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
},
|
|
66
66
|
"sideEffects": false,
|
|
67
67
|
"scripts": {
|
|
68
|
-
"build": "node types/gen_settings_types.mjs && node types/gen_kernel_params.mjs && vite build --config components/vite.config.js && vite build --config viewer/vite.config.js
|
|
68
|
+
"build": "node types/gen_settings_types.mjs && node types/gen_kernel_params.mjs && vite build --config components/vite.config.js && vite build --config viewer/vite.config.js",
|
|
69
69
|
"check": "bash pack_check.sh"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
@@ -74,9 +74,15 @@
|
|
|
74
74
|
"three": "^0.160.0"
|
|
75
75
|
},
|
|
76
76
|
"peerDependenciesMeta": {
|
|
77
|
-
"react": {
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
"react": {
|
|
78
|
+
"optional": true
|
|
79
|
+
},
|
|
80
|
+
"react-dom": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"three": {
|
|
84
|
+
"optional": true
|
|
85
|
+
}
|
|
80
86
|
},
|
|
81
87
|
"devDependencies": {
|
|
82
88
|
"typescript": "^5.6.0",
|
|
@@ -84,25 +90,24 @@
|
|
|
84
90
|
},
|
|
85
91
|
"files": [
|
|
86
92
|
"engine",
|
|
87
|
-
"!engine/**/.omc",
|
|
88
93
|
"types",
|
|
89
|
-
"!**/
|
|
94
|
+
"!**/tests/**",
|
|
90
95
|
"!types/gen_*.mjs",
|
|
91
96
|
"components/dist",
|
|
92
97
|
"viewer/dist",
|
|
93
|
-
"viewer/styles.css",
|
|
94
|
-
"components/styles.css",
|
|
95
98
|
"data",
|
|
99
|
+
"data/ui-tree-keys.json",
|
|
100
|
+
"data/config-schema-lean.json",
|
|
96
101
|
"!data/config-schema-builddump.json",
|
|
97
|
-
"!data/**/.omc",
|
|
98
102
|
"README.md",
|
|
99
103
|
"CHANGELOG.md",
|
|
100
104
|
"THIRD-PARTY-NOTICES.md",
|
|
101
|
-
"LICENSE.txt"
|
|
105
|
+
"LICENSE.txt",
|
|
106
|
+
"!**/.omc"
|
|
102
107
|
],
|
|
103
108
|
"repository": {
|
|
104
109
|
"type": "git",
|
|
105
|
-
"url": "git+https://github.com/kimgh06/
|
|
110
|
+
"url": "git+https://github.com/kimgh06/Three_Slicer.git",
|
|
106
111
|
"directory": "packages"
|
|
107
112
|
},
|
|
108
113
|
"homepage": "https://slicer.kimgh06.com",
|
|
@@ -127,6 +132,8 @@
|
|
|
127
132
|
"3d",
|
|
128
133
|
"mesh",
|
|
129
134
|
"clipping"
|
|
130
|
-
]
|
|
135
|
+
],
|
|
136
|
+
"dependencies": {
|
|
137
|
+
"three-slicer-viewer": "0.3.1"
|
|
138
|
+
}
|
|
131
139
|
}
|
|
132
|
-
|
package/types/client.d.ts
CHANGED
|
@@ -86,3 +86,6 @@ export interface SlicerClient {
|
|
|
86
86
|
*/
|
|
87
87
|
export function createSlicerClient(worker?: Worker): SlicerClient
|
|
88
88
|
export default createSlicerClient
|
|
89
|
+
|
|
90
|
+
/** The WASM kernel's worker, as a factory — what `three-slicer-viewer`'s `useSlicer` takes as `deps.makeWorker`. */
|
|
91
|
+
export function makeSlicerWorker(): Worker
|
package/types/components.d.ts
CHANGED
|
@@ -1,29 +1,3 @@
|
|
|
1
|
-
// three-slicer/components
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export interface SettingsPanelProps {
|
|
6
|
-
/** Sparse map — only edited keys. Missing keys fall back to the config-schema default. */
|
|
7
|
-
settings: SlicerSettings
|
|
8
|
-
/** React setState shape. The only channel through which state leaves the component. */
|
|
9
|
-
setSettings: React.Dispatch<React.SetStateAction<SlicerSettings>>
|
|
10
|
-
/** Label click — for deep links / detail views. Omit for a plain label (zero router coupling). */
|
|
11
|
-
onOptionOpen?: (optKey: string) => void
|
|
12
|
-
/** When embedding inside another panel */
|
|
13
|
-
embedded?: boolean
|
|
14
|
-
/** Replace schema-driven widgets per key (e.g. `{ printable_area: MyBedEditor }`) */
|
|
15
|
-
customWidgets?: Record<string, React.ComponentType<any>>
|
|
16
|
-
/**
|
|
17
|
-
* Pins the panel to one builder (optionally one page) and drops the search/group/page/mode chrome, so the form
|
|
18
|
-
* can be folded into another card. This is how `<Viewport/>`'s `motionPanel` slot is meant to be filled:
|
|
19
|
-
*
|
|
20
|
-
* ```jsx
|
|
21
|
-
* <SettingsPanel settings={settings} setSettings={setSettings} embedded
|
|
22
|
-
* only={{ builder: 'TabPrinter::build_kinematics_page' }} />
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
only?: { builder: string; page?: string }
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
declare const SettingsPanel: React.FC<SettingsPanelProps>
|
|
29
|
-
export default SettingsPanel
|
|
1
|
+
// three-slicer/components — the permissive settings panel with upstream's data plugged in. Same surface.
|
|
2
|
+
export * from 'three-slicer-viewer/components'
|
|
3
|
+
export { default } from 'three-slicer-viewer/components'
|
package/types/settings.d.ts
CHANGED
|
@@ -172,6 +172,18 @@ export function printerDefaultPreset(profileName: string): string
|
|
|
172
172
|
/** The schema keys the kernel's machine limits are read from — for UI that shows which ones are in play. */
|
|
173
173
|
export const machineLimitKeys: string[]
|
|
174
174
|
|
|
175
|
+
/** deriveKernelParams' fallbacks when neither the settings map nor the schema gives a usable value, keyed by schema
|
|
176
|
+
* key. NOT the schema defaults — several differ on purpose. Frozen. */
|
|
177
|
+
export const FFF_FALLBACKS: Readonly<Record<string, number | boolean | string>>
|
|
178
|
+
/** deriveSlaParams' fallbacks (its reader treats non-positive values as absent). Frozen. */
|
|
179
|
+
export const SLA_FALLBACKS: Readonly<Record<string, number>>
|
|
180
|
+
/** What `line_width` 0 ("auto") resolves to. */
|
|
181
|
+
export const AUTO_LINE_WIDTH: number
|
|
182
|
+
/** The bed when `printable_area` is empty or malformed — the bbox of the schema's own default. */
|
|
183
|
+
export const BED_FALLBACK: Readonly<{ width: number; depth: number }>
|
|
184
|
+
/** Kernel machine-limit parameter -> [schema key, fallback]. Frozen. */
|
|
185
|
+
export const MACHINE_LIMITS: Readonly<Record<string, readonly [string, number]>>
|
|
186
|
+
|
|
175
187
|
// ---- Lazily loaded presets --------------------------------------------------
|
|
176
188
|
// Both facades hide the column layout of the artifact they wrap; the promise is created once and reused.
|
|
177
189
|
|
|
@@ -201,3 +213,6 @@ export interface FilamentPresetsApi {
|
|
|
201
213
|
settingsFor(presetName: string): SlicerSettings | null
|
|
202
214
|
}
|
|
203
215
|
export function filamentPresets(): Promise<FilamentPresetsApi>
|
|
216
|
+
|
|
217
|
+
/** The nine catalog lookups above as one object — what `three-slicer-viewer`'s `<Viewport catalog>` takes. */
|
|
218
|
+
export const bundledCatalog: import('three-slicer-viewer').Catalog
|
package/types/toggle.d.ts
CHANGED
|
@@ -1,22 +1,2 @@
|
|
|
1
|
-
// three-slicer/toggle —
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/** Settings accessor — schema default when a value is missing, [0] for vector types. */
|
|
5
|
-
export interface ToggleCfg {
|
|
6
|
-
bool(key: string): boolean
|
|
7
|
-
int(key: string): number
|
|
8
|
-
float(key: string): number
|
|
9
|
-
/** Whether the key exists in config-schema */
|
|
10
|
-
has(key: string): boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function makeCfg(settings: SlicerSettings | null | undefined): ToggleCfg
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Evaluates a single enable_if expression. Untranslatable expressions return `null` (= fail-open, stays enabled) —
|
|
17
|
-
* make sure to treat that as distinct from `false`.
|
|
18
|
-
*/
|
|
19
|
-
export function evalEnableIf(expr: string, locals: Record<string, unknown>, cfg: ToggleCfg): boolean | null
|
|
20
|
-
|
|
21
|
-
/** Keys that must be disabled under the current settings -> the enable_if expression that disabled them. Only rules that are unambiguously false. */
|
|
22
|
-
export function disabledKeys(cfg: ToggleCfg): Record<string, string>
|
|
1
|
+
// three-slicer/toggle — the permissive evaluator bound to upstream's toggle rules. Same surface.
|
|
2
|
+
export * from 'three-slicer-viewer/toggle'
|
package/types/viewer-gcode.d.ts
CHANGED
|
@@ -1,29 +1,2 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export interface GcodeLayer {
|
|
5
|
-
z: number
|
|
6
|
-
/** Stride 8: [x0,y0,z0,enc, x1,y1,z1,enc] per segment, enc = role + tool*16 (role 0 = travel). */
|
|
7
|
-
paths: Float32Array
|
|
8
|
-
/** One entry per segment; 0 means "use the default line width". */
|
|
9
|
-
widths: Float32Array
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface ParseGcodeResult {
|
|
13
|
-
layers: GcodeLayer[]
|
|
14
|
-
stats: { layers: number; path_segments: number; travel_segments: number; tools: number[] }
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface ParseGcodeOptions {
|
|
18
|
-
/** Used to derive bead width from E when the file has no ;WIDTH: comments. Default 1.75. */
|
|
19
|
-
filamentDiameter?: number
|
|
20
|
-
/** Bead-height fallback when a layer's height cannot be inferred from z steps. Default 0.2. */
|
|
21
|
-
defaultLayerHeight?: number
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Parses G0/G1/G2/G3 (I/J arcs), G90/G91, M82/M83, G92, T<n>, and the layer/role comment conventions of
|
|
26
|
-
* OrcaSlicer/PrusaSlicer (;TYPE: ;WIDTH: ;LAYER_CHANGE ;Z:), Cura (;TYPE: ;LAYER:) and this kernel's own output.
|
|
27
|
-
* Recovery is lossy where G-code carries no data: unknown roles become wall(1), widths are derived from E.
|
|
28
|
-
*/
|
|
29
|
-
export function parseGcode(text: string, opts?: ParseGcodeOptions): ParseGcodeResult
|
|
1
|
+
// Re-exported from the permissive package (MIT), where the implementation now lives.
|
|
2
|
+
export * from 'three-slicer-viewer/gcode'
|
|
@@ -1,33 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/** The 5 built-ins plus any extension registered via `registerLoader()`, which pushes onto this array. */
|
|
4
|
-
export const SUPPORTED_EXT: string[]
|
|
5
|
-
|
|
6
|
-
/** Lowercased extension. Empty string when there is no dot. */
|
|
7
|
-
export function fileExt(name: string): string
|
|
8
|
-
|
|
9
|
-
export interface LoadedObject {
|
|
10
|
-
name: string
|
|
11
|
-
/** Triangle vertex coordinates (N*9, model z-up) */
|
|
12
|
-
modelPos: Float32Array
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** A single file may contain several objects (3mf/amf/step) -> always an array. */
|
|
16
|
-
export function loadModel(name: string, buffer: ArrayBuffer): Promise<LoadedObject[]>
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Registers an extra format. Formats needing heavy dependencies (STEP=OCCT WASM, etc.) are not bundled here,
|
|
20
|
-
* so the app wires them up itself. The `<Viewport/>` file dialog and drag-and-drop filters pick them up automatically.
|
|
21
|
-
*
|
|
22
|
-
* ```js
|
|
23
|
-
* import { registerLoader } from 'three-slicer/viewer/loaders'
|
|
24
|
-
* registerLoader('step,stp', async (buffer, name) => [{ name, modelPos }])
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
export function registerLoader(
|
|
28
|
-
exts: string | string[],
|
|
29
|
-
fn: (buffer: ArrayBuffer, name: string) => LoadedObject[] | Promise<LoadedObject[]>,
|
|
30
|
-
): void
|
|
31
|
-
|
|
32
|
-
/** Connected-component split. Returns `null` when there is only one component (cannot split) — not an empty array. */
|
|
33
|
-
export function splitConnectedComponents(localPos: Float32Array): Float32Array[] | null
|
|
1
|
+
export * from 'three-slicer-viewer/loaders'
|
|
@@ -1,113 +1,3 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
/** The 24 triangle indices of the 8-vertex diamond cross-section (from SegmentTemplate.cpp:18) */
|
|
5
|
-
export const VERTEX_DATA: number[]
|
|
6
|
-
|
|
7
|
-
/** Toolpath type -> color. 0=travel, 1=wall … 11=prime */
|
|
8
|
-
export const TYPE_COLOR: Record<number, number[]>
|
|
9
|
-
export const TYPE_LABEL: Record<number, string>
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Per-extruder colors for the Filament view. Categorical, not semantic — the toolpath stream carries a tool index and
|
|
13
|
-
* nothing about the material, and a machine may have more extruders than entries, so index it modulo its length.
|
|
14
|
-
*/
|
|
15
|
-
export const TOOL_COLOR: number[][]
|
|
16
|
-
|
|
17
|
-
/** Blue-to-red 11-color heatmap (libvgcode ColorRange.hpp:14) */
|
|
18
|
-
export const DEFAULT_RANGES_COLORS: number[][]
|
|
19
|
-
|
|
20
|
-
export interface ViewTypeDef {
|
|
21
|
-
key: 'feature' | 'speed' | 'height' | 'width' | 'fan' | 'temp' | 'filament'
|
|
22
|
-
label: string
|
|
23
|
-
/** Whether values are continuous (heatmap). False means a fixed color. */
|
|
24
|
-
cont: boolean
|
|
25
|
-
unit: string
|
|
26
|
-
}
|
|
27
|
-
export const VIEW_TYPES: ViewTypeDef[]
|
|
28
|
-
|
|
29
|
-
/** Per-vertex extra data */
|
|
30
|
-
export interface SegmentMeta {
|
|
31
|
-
vType: Uint8Array
|
|
32
|
-
/** Printing extruder, decoded out of the role field's high bits. Untooled output decodes to 0, i.e. single material. */
|
|
33
|
-
vTool: Uint8Array
|
|
34
|
-
vWidth: Float32Array
|
|
35
|
-
vHeight: Float32Array
|
|
36
|
-
vLayer: Int32Array
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface SegmentData {
|
|
40
|
-
position: Float32Array
|
|
41
|
-
hwa: Float32Array
|
|
42
|
-
segIndex: Uint32Array
|
|
43
|
-
nV: number
|
|
44
|
-
nSeg: number
|
|
45
|
-
layerSegPrefix: Uint32Array
|
|
46
|
-
travelPos: Float32Array
|
|
47
|
-
travelPrefix: Uint32Array
|
|
48
|
-
nTrav: number
|
|
49
|
-
layerCount: number
|
|
50
|
-
maxAbs: number
|
|
51
|
-
hasNaN: boolean
|
|
52
|
-
meta: SegmentMeta
|
|
53
|
-
/** Total extruded length per type (index = toolpath type, length 16) */
|
|
54
|
-
typeLengths: Float64Array
|
|
55
|
-
/** Null when there is not a single vertex */
|
|
56
|
-
bbox: { min: [number, number, number]; max: [number, number, number] } | null
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** Kernel layers[{z, paths(stride8), widths[]}] -> GPU stream. */
|
|
60
|
-
export function buildSegmentData(layers: unknown[], defaultLineWidth: number): SegmentData
|
|
61
|
-
|
|
62
|
-
/** Length share per type (%), descending by pct. The kernel does not expose time per role, so length is used as an approximation. */
|
|
63
|
-
export function roleRatios(typeLengths: Float64Array | number[]): Array<{
|
|
64
|
-
type: number
|
|
65
|
-
label: string
|
|
66
|
-
pct: number
|
|
67
|
-
color: number[]
|
|
68
|
-
}>
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* speed/fan/temp are absent from the kernel toolpath and derived from settings — these are the values used for that.
|
|
72
|
-
*/
|
|
73
|
-
export interface ColorContext {
|
|
74
|
-
speedByType?: Record<number, number>
|
|
75
|
-
firstLayerSpeed?: number
|
|
76
|
-
fanByType?: Record<number, number>
|
|
77
|
-
fanFirstLayers?: number
|
|
78
|
-
tempNormal?: number
|
|
79
|
-
tempFirst?: number
|
|
80
|
-
closeFanLayers?: number
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export interface ColorResult {
|
|
84
|
-
/** Per-vertex RGBA (nV*4). The color is packed into `.r`. */
|
|
85
|
-
color: Float32Array
|
|
86
|
-
min: number
|
|
87
|
-
max: number
|
|
88
|
-
viewType: ViewTypeDef['key']
|
|
89
|
-
label: string
|
|
90
|
-
unit: string
|
|
91
|
-
/** False means fixed colors — min/max are 0 and no legend should be drawn. */
|
|
92
|
-
cont: boolean
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function computeColors(data: SegmentData, viewType: ViewTypeDef['key'], ctx: ColorContext): ColorResult
|
|
96
|
-
|
|
97
|
-
export interface ToolpathHandle {
|
|
98
|
-
/** THREE.Mesh — typed by the THREE namespace passed in */
|
|
99
|
-
mesh: any
|
|
100
|
-
/** THREE.LineSegments (travel) */
|
|
101
|
-
travLines: any
|
|
102
|
-
setLayerRange(lo: number, hi: number): void
|
|
103
|
-
/** Backwards compatible — same as setLayerRange(0, n-1). */
|
|
104
|
-
setVisibleLayers(n: number): void
|
|
105
|
-
setTravelVisible(visible: boolean): void
|
|
106
|
-
setColors(color: Float32Array): void
|
|
107
|
-
dispose(): void
|
|
108
|
-
nSeg: number
|
|
109
|
-
layerCount: number
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/** @param THREE - the `import * as THREE from 'three'` namespace. The consumer's instance is used as-is. */
|
|
113
|
-
export function makeToolpath(THREE: any, data: SegmentData): ToolpathHandle
|
|
1
|
+
// Re-exported from the permissive package (MIT), where the implementation now lives.
|
|
2
|
+
// three-slicer/viewer/toolpath stays a valid entry point for every existing consumer.
|
|
3
|
+
export * from 'three-slicer-viewer'
|