From 87e4a32092570ac7db95d342a763c4c0af55bf58 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sat, 3 Jan 2026 11:42:37 -0500 Subject: [PATCH] add global slicePre similar to sliceAll (which should be renamed slicePost) add shared cam operational state so index+stock can run once for all instances --- src/kiri/app/function.js | 9 +++++++-- src/kiri/app/workers.js | 7 +++++++ src/kiri/mode/cam/driver-be.js | 3 ++- src/kiri/mode/cam/op-level.js | 24 +++++++++++++++++++++--- src/kiri/mode/cam/slice.js | 28 +++++++++++++++++++++------- src/kiri/run/worker.js | 12 ++++++++++++ 6 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/kiri/app/function.js b/src/kiri/app/function.js index a5f027fc..0b3cb9e8 100644 --- a/src/kiri/app/function.js +++ b/src/kiri/app/function.js @@ -137,6 +137,10 @@ function prepareSlices(callback, scale = 1, offset = 0) { client.rotate(settings); } + function sliceSetup() { + client.slicePre(settings, sliceNext); + } + function sliceNext() { if (toSlice.length) { // while more widgets to slice @@ -309,8 +313,9 @@ function prepareSlices(callback, scale = 1, offset = 0) { space.refresh(); } - // kick off slicing chain - sliceNext(); + // do any global setup / state management + // then kick off slicing chain + sliceSetup(); } /** diff --git a/src/kiri/app/workers.js b/src/kiri/app/workers.js index c508d10e..06503bdb 100644 --- a/src/kiri/app/workers.js +++ b/src/kiri/app/workers.js @@ -211,6 +211,13 @@ export const client = { }); }, + + // called once at the beginning of slice operations + // setup any global shared state + slicePre(settings, callback) { + send("slicePre", { settings }, callback); + }, + // called once for each widget slice(settings, widget, callback) { send("slice", { diff --git a/src/kiri/mode/cam/driver-be.js b/src/kiri/mode/cam/driver-be.js index 2212908e..35a2a9e4 100644 --- a/src/kiri/mode/cam/driver-be.js +++ b/src/kiri/mode/cam/driver-be.js @@ -1,7 +1,7 @@ /** Copyright Stewart Allen -- All Rights Reserved */ import { codec } from '../../core/codec.js'; -import { cam_slice, holes, traces } from './slice.js'; +import { cam_slice_pre, cam_slice, holes, traces } from './slice.js'; import { cam_prepare } from './prepare.js'; import { cam_export } from './export.js'; import { tool as mesh_tool } from '../../../mesh/tool.js'; @@ -114,6 +114,7 @@ export const CAM = { init, surface_prep, surface_find, + slicePre: cam_slice_pre, slice: cam_slice, prepare: cam_prepare, export: cam_export diff --git a/src/kiri/mode/cam/op-level.js b/src/kiri/mode/cam/op-level.js index 39260ba6..2ef30a70 100644 --- a/src/kiri/mode/cam/op-level.js +++ b/src/kiri/mode/cam/op-level.js @@ -14,9 +14,11 @@ class OpLevel extends CamOp { async slice(progress) { let { op, state } = this; - let { addSlices, color, settings, shadow, updateToolDiams, zMax, ztOff } = state; + let { addSlices, color, settings, shadow } = state; + let { share, updateToolDiams, zMax, ztOff } = state; let { down, tool, step, stepz, inset } = op; let { stock } = settings; + let { center } = stock; let toolDiam = new Tool(settings, tool).fluteDiameter(); let stepOver = this.stepOver = toolDiam * step; @@ -25,11 +27,23 @@ class OpLevel extends CamOp { let zBot = zTop - down; let zList = stepz && down ? util.lerp(zTop, zBot, stepz) : [ zBot ]; + if (share.ran) { + console.log('skip'); + this.skip = true; + return; + } else if (op.stock) { + share.ran = true; + } + updateToolDiams(toolDiam); let points = []; let clear = op.stock ? - [ newPolygon().centerRectangle({x:-wpos.x,y:-wpos.y,z:wpos.z}, stock.x + toolDiam/2, stock.y) ] : + [ newPolygon().centerRectangle({ + x: -wpos.x + center.x, + y: -wpos.y + center.y, + z: wpos.z + center.z + }, stock.x + toolDiam/2, stock.y) ] : POLY.outer(POLY.offset(shadow.base, toolDiam * (inset || 0))); POLY.fillArea(clear, 1090, stepOver, points); @@ -50,10 +64,14 @@ class OpLevel extends CamOp { } prepare(ops, progress) { - let { layers, stepOver } = this; + let { layers, skip, stepOver } = this; let { printPoint } = ops; let { newLayer, tip2tipEmit, camOut } = ops; + if (skip) { + return; + } + for (let lines of layers) { lines = lines.map(p => { return { first: p.first(), last: p.last(), poly: p } }); printPoint = tip2tipEmit(lines, printPoint, (el, point, count) => { diff --git a/src/kiri/mode/cam/slice.js b/src/kiri/mode/cam/slice.js index 49a75492..8007959a 100644 --- a/src/kiri/mode/cam/slice.js +++ b/src/kiri/mode/cam/slice.js @@ -11,6 +11,13 @@ import { Slicer as cam_slicer } from './slicer_cam.js'; import { Tool } from './tool.js'; import { util } from '../../../geo/base.js'; +// state shared across all widget slicing +let shared; + +export function cam_slice_pre(settings) { + shared = { ops: { } }; +} + /** * DRIVER SLICE CONTRACT * @@ -306,7 +313,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) { } if (false) { - opList.push(new OPS.xray(state, { type: "xray" })); + opList.push({ op: new OPS.xray(state, { type: "xray" }) }); } // find index ops @@ -315,14 +322,14 @@ export async function cam_slice(settings, widget, onupdate, ondone) { if (isIndexed) { // preface op list with OpIndex if (activeOps.length === 0 || activeOps[0].type !== 'index') { - opList.push(new OPS.index(state, { type: "index", degrees: 0, absolute: true })); - opTot += opList.peek().weight(); + opList.push({ op: new OPS.index(state, { type: "index", degrees: 0, absolute: true }) }); + opTot += opList.peek().op.weight(); } } else { // preface op list with OpShadow - opList.push(new OPS.shadow(state, { type: "shadow", silent: true })); - opTot += opList.peek().weight(); + opList.push({ op: new OPS.shadow(state, { type: "shadow", silent: true }) }); + opTot += opList.peek().op.weight(); } // LOOP EXPANSION - duplicate next N operations M times @@ -354,6 +361,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) { activeOps = expandedOps; // determine # of steps and step weighting for progress bar + let opos = 0; for (let op of activeOps) { if (op.type === '|') { break; @@ -361,15 +369,20 @@ export async function cam_slice(settings, widget, onupdate, ondone) { let opfn = OPS[op.type]; if (opfn) { let opin = new opfn(state, op); - opList.push(opin); opTot += opin.weight(); + opos++; + let share = shared.ops[opos]; + if (!share) { + share = shared.ops[opos] = {}; + } + opList.push({ op: opin, share }); } } // call slice() function on all ops in order await setAxisIndex(); updateSlicer(); - for (let op of opList) { + for (let { op, share } of opList) { let weight = op.weight(); // apply operation override vars let workover = var_compute(); @@ -392,6 +405,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) { let layername = named.length ? named : (note ? `${type} (${note})` : type); Object.assign(state, { layername, + share, stock, tool, zBottom, diff --git a/src/kiri/run/worker.js b/src/kiri/run/worker.js index 84d4f339..e5a5f974 100644 --- a/src/kiri/run/worker.js +++ b/src/kiri/run/worker.js @@ -420,6 +420,18 @@ const dispatch = { send.done({}); }, + slicePre(data, send) { + const { settings } = data; + const { mode } = settings; + const driver = drivers[mode]; + + if (driver.slicePre) { + driver.slicePre(settings); + } + + send.done(); + }, + slice(data, send) { send.data({ update:0.001, updateStatus:"slicing" });