From b52ab788e57c5d0a381f4f63375489b91cac7989 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 26 Oct 2025 18:15:13 -0400 Subject: [PATCH] disable step debug. add mesh script persistance, control, error dialog --- src/load/step.js | 15 +++++++++------ src/main/mesh.js | 6 +++++- src/mesh/api.js | 3 ++- src/mesh/build.js | 11 ++++++++--- src/mesh/script.js | 28 ++++++++++++++++++++++++---- web/mesh/index.css | 30 +++++++++++++++++++++++++----- 6 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/load/step.js b/src/load/step.js index f8852cbe..8245db53 100644 --- a/src/load/step.js +++ b/src/load/step.js @@ -3,6 +3,9 @@ import { tool as MeshTool } from '../mesh/tool.js'; const { Vector3 } = THREE; +function debug() { + if (false) console.log(...arguments); +} /** * Convert STL triangles to STEP file format @@ -279,9 +282,9 @@ export function meshToSTEPWithFaces(triangles, options = {}) { const outlines = tool.generateOutlines(connectedFaces); if (outlines.length > 1) { - console.log(`Surface with ${connectedFaces.length} faces has ${outlines.length} outlines:`); + debug(`Surface with ${connectedFaces.length} faces has ${outlines.length} outlines:`); outlines.forEach((outline, idx) => { - console.log(` Outline ${idx}: ${outline.length} vertices`); + debug(` Outline ${idx}: ${outline.length} vertices`); }); } @@ -305,7 +308,7 @@ export function meshToSTEPWithFaces(triangles, options = {}) { } } - console.log(`[v4] Merged ${totalFaces} triangles into ${surfaces.length} faces`); + debug(`[v4] Merged ${totalFaces} triangles into ${surfaces.length} faces`); // Generate STEP file let step = `ISO-10303-21; @@ -519,7 +522,7 @@ DATA; outline = mergeColinearEdges(outline); if (originalLength !== outline.length) { - console.log(` Merged outline ${outlineIdx}: ${originalLength} -> ${outline.length} vertices`); + debug(` Merged outline ${outlineIdx}: ${originalLength} -> ${outline.length} vertices`); } if (outline.length < 3) { @@ -655,8 +658,8 @@ DATA; } // Now write CLOSED_SHELL with only the faces that were actually created - console.log(`[v4] Created ${createdFaceIds.length} faces for CLOSED_SHELL (expected ${surfaces.length})`); - console.log(`[v4] Shared ${edgeMap.size} unique edges across all faces`); + debug(`[v4] Created ${createdFaceIds.length} faces for CLOSED_SHELL (expected ${surfaces.length})`); + debug(`[v4] Shared ${edgeMap.size} unique edges across all faces`); step += `#${closedShellId}=CLOSED_SHELL('',(${createdFaceIds.map(fid => `#${fid}`).join(',')}));\n`; // Append all the face geometry diff --git a/src/main/mesh.js b/src/main/mesh.js index 1ef33ee0..5be86f84 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -187,7 +187,11 @@ async function restore_space() { // hide loading curtain $d('curtain','none'); // restore handles visibility - handles.setEnabled(api.prefs.map.space.bounds); + handles.setEnabled(api.prefs.map.space.bounds ?? false); + // restore script if was showing + if (api.prefs.map.space.script) { + api.script.show(); + } if (api.prefs.map.info.welcome !== false) { api.welcome(version); } diff --git a/src/mesh/api.js b/src/mesh/api.js index b68a9509..080ab478 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -815,7 +815,7 @@ let add = { }, cube() { - const [ x,y,z ] = [ ...arguments ]; + const [ x,y,z ] = [ ...arguments ].map(v => parseFloat(v) || undefined); const box = new THREE.BoxGeometry(1,1,1).toNonIndexed(); const vert = box.attributes.position.array; const nmdl = new meshModel({ file: "box", mesh: vert }); @@ -1445,6 +1445,7 @@ const prefs = { dark: false, floor: false, grid: true, + script: false, select: [], snap: 1, snapon: false, diff --git a/src/mesh/build.js b/src/mesh/build.js index 97e886ed..b2942c6c 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -383,7 +383,7 @@ function menu_item(text, fn, short, id) { // create html elements function ui_build() { - let { bind, div, input, hr, label, textarea } = h; + let { bind, button, div, input, hr, label, span, textarea } = h; let { file, selection, mode, tool, sketch, prefs, add } = api; let trash = FontAwesome.icon({ prefix: "fas", iconName: "trash" }).html[0]; let eye_open = FontAwesome.icon({ prefix: "fas", iconName: "eye" }).html[0]; @@ -581,8 +581,13 @@ function ui_build() { div({ id: 'logger', onmouseover() { log.show() } }), ]), div({ id: 'script', class: "hide" }, [ - div({ id: 'script-header', _: "script" }), - textarea({ id: 'script-editor', rows: 50, cols: 60 }), + div({ id: 'script-header' }, [ + span("script"), + div({ class: "grow" }), + button({ _: "run", onclick: api.script.execute }), + button({ _: "×", class: "close", onclick: api.script.hide }) + ]), + textarea({ id: 'script-editor', rows: 30, cols: 65 }), ]), div({ id: 'grouplist' }), div({ id: 'selectlist' }), diff --git a/src/mesh/script.js b/src/mesh/script.js index 31e19498..4a1d8079 100644 --- a/src/mesh/script.js +++ b/src/mesh/script.js @@ -4,18 +4,25 @@ import { api } from '../mesh/api.js'; import { $, h, estop } from '../moto/webui.js'; export const script = { + running: false, visible: false, changed() { localStorage.script = $('script-editor').value; }, + error(e) { + api.modal.dialog({ + title: "script error", + body: [ h.div({ id: "script-error", _: e.message || e.toString() }) ] + }); + }, hide() { $('script').classList.add('hide'); - script.visible = false; + api.prefs.save(api.prefs.map.space.script = script.visible = false); }, show() { $('script').classList.remove('hide'); $('script-editor').value = localStorage.script ?? ''; - script.visible = true; + api.prefs.save(api.prefs.map.space.script = script.visible = true); }, toggle() { if (script.visible) { @@ -27,12 +34,25 @@ export const script = { execute() { let cmd = localStorage.script || `console.log('no script')`; if (cmd) { + if (script.running) { + return script.error('script running'); + } cmd = [ '(async () => {', cmd, - '})();' + '})()', + '.catch(error => {', + 'api.script.error(error)', + '})', + '.finally(() => {', + 'api.script.running = false;', + '});' ].join('\n'); - eval(`{ \n ${cmd} \n }`); + try { + eval(`{ \n ${cmd} \n }`); + } catch (e) { + script.error(e); + } } } }; diff --git a/web/mesh/index.css b/web/mesh/index.css index b69a1ca4..218f306c 100644 --- a/web/mesh/index.css +++ b/web/mesh/index.css @@ -144,6 +144,10 @@ button:hover { /** misc ui **/ +.grow { + flex-grow: 1; +} + .hide { display: none; } @@ -209,10 +213,6 @@ button:hover { padding: 4px 8px 4px 8px; } -.menu-items .grow { - flex-grow: 1; -} - .menu-items .short { gap: 1px; } @@ -630,10 +630,13 @@ button:hover { } #script { - margin-left: 5px; + margin: 5px 0px 5px 5px; + /* margin-top: 5px; + margin-left: 5px; */ flex-direction: column; justify-content: end; color: white; + height: calc(100% - 10px); } #script-header { @@ -645,12 +648,29 @@ button:hover { border-left: 1px solid #999; border-right: 1px solid #999; flex-direction: row; + gap: 3px; +} + +#script-header button { + border-radius: 3px; +} + +#script-header .close { + font-weight: bold; + line-height: 1; } #script-editor { color: white; background-color: #222; outline: none; + height: 100%; + resize: none; +} + +#script-error { + flex-direction: column; + font-family: monospace; } /** group/model buttons top/right of workspace **/