From 718876980b5c9c26b6f4aaacd38f906189a7920d Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 16 Feb 2025 15:38:01 -0500 Subject: [PATCH] fix construction of indexed animation tools, rotation sign in topo4, rotation animation --- src/kiri-mode/cam/animate2.js | 9 +++- src/kiri-mode/cam/client.js | 31 ++++++------- src/kiri-mode/cam/ops.js | 2 +- src/kiri-mode/cam/tools.js | 84 ++++++++++++++++++++--------------- src/kiri-mode/cam/topo4.js | 2 +- src/kiri/widgets.js | 10 +++++ 6 files changed, 81 insertions(+), 57 deletions(-) diff --git a/src/kiri-mode/cam/animate2.js b/src/kiri-mode/cam/animate2.js index c38909ad..4f374c32 100644 --- a/src/kiri-mode/cam/animate2.js +++ b/src/kiri-mode/cam/animate2.js @@ -40,6 +40,7 @@ kiri.load(() => { $('layer-animate').innerHTML = ''; $('layer-toolpos').innerHTML = ''; Object.keys(meshes).forEach(id => deleteMesh(id)); + api.widgets.setAxisIndex(0); } function animate2(api, delay) { @@ -194,6 +195,9 @@ kiri.load(() => { space.refresh(); } } + if (data.stock_index !== undefined) { + api.widgets.setAxisIndex(data.stock_index); + } if (data.mesh_index) { const { id, index } = data.mesh_index; const mesh = meshes[id]; @@ -550,6 +554,7 @@ kiri.load(() => { send.data(toolUpdateMsg); } if (stockIndexMsg) { + send.data({ stock_index: stockIndex }); for (let slice of stockSlices) { send.data({ mesh_index: { id: slice.id, index: -stockIndex } }); } @@ -592,8 +597,8 @@ kiri.load(() => { let { cylinder, sphere } = Instance.Manifold; let mesh; if (tool.isBallMill()) { - mesh = cylinder(flen + slen - frad, frad, frad, 20, true) - .add(sphere(frad, 20).translate(0, 0, -(flen + slen - frad)/2)); + mesh = cylinder(flen + slen - frad * 2, frad, frad, 20, true) + .add(sphere(frad, 20).translate(0, 0, -(flen + slen - frad * 2)/2)); } else if (tool.isTaperMill()) { const trad = Math.max(tool.tipDiameter() / 2, 0.001); mesh = cylinder(slen, srad, srad, 20, true).translate(0, 0, slen/2) diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js index cfb8531a..35aae1a5 100644 --- a/src/kiri-mode/cam/client.js +++ b/src/kiri-mode/cam/client.js @@ -30,7 +30,8 @@ let isAnimate, flipping, poppedRec, hoveredOp, - API, FDM, SPACE, STACKS, MODES, VIEWS, UI, UC, LANG, MCAM; + lastMode, + API, FDM, SPACE, STACKS, MODES, VIEWS, UI, UC, LANG, MCAM, WIDGETS; let zaxis = { x: 0, y: 0, z: 1 }, popOp = {}, @@ -57,6 +58,7 @@ CAM.init = function(kiri, api) { FDM = kiri.driver.FDM; // console.log({kiri,api}) + WIDGETS = api.widgets; SPACE = kiri.space; MODES = kiri.consts.MODES; VIEWS = kiri.consts.VIEWS; @@ -73,9 +75,7 @@ CAM.init = function(kiri, api) { let changed = refresh || isIndexed !== newIndexed; isIndexed = newIndexed; if (!isIndexed || !isCamMode) { - for (let widget of API.widgets.all()) { - widget.setAxisIndex(0); - } + WIDGETS.setAxisIndex(0); } if (!isCamMode) { return; @@ -95,9 +95,7 @@ CAM.init = function(kiri, api) { if (!changed) { return; } - for (let widget of api.widgets.all()) { - widget.setIndexed(isIndexed ? true : false); - } + WIDGETS.setIndexed(isIndexed ? true : false); api.platform.update_bounds(); // add or remove clock op depending on indexing const cp = current.process; @@ -189,15 +187,14 @@ CAM.init = function(kiri, api) { }); api.event.on("view.set", (mode) => { + lastMode = mode; isArrange = (mode === VIEWS.ARRANGE); isPreview = (mode === VIEWS.PREVIEW); - isAnimate = false; + isAnimate = (mode === VIEWS.ANIMATE); animFn().animate_clear(api); func.clearPops(); if (isCamMode && isPreview) { - for (let widget of API.widgets.all()) { - widget.setAxisIndex(0); - } + WIDGETS.setAxisIndex(0); } updateStock(); func.opRender(); @@ -466,7 +463,7 @@ CAM.init = function(kiri, api) { function updateIndex() { let oplist = current.process.ops; - if (!(isCamMode && oplist)) { + if (!(isCamMode && oplist) || lastMode === VIEWS.ANIMATE) { return; } let index = 0; @@ -484,9 +481,7 @@ CAM.init = function(kiri, api) { } } } - for (let widget of API.widgets.all()) { - widget.setAxisIndex(isPreview || !isIndexed ? 0 : -index); - } + WIDGETS.setAxisIndex(isPreview || !isIndexed ? 0 : -index); currentIndex = isIndexed && !isPreview ? index * DEG2RAD : 0; } @@ -728,9 +723,9 @@ CAM.init = function(kiri, api) { el.onmouseleave = onLeave; } } - // update widget rotations from timeline marker - for (let widget of API.widgets.all()) { - widget.setAxisIndex(isPreview || !isIndexed ? 0 : -index); + if (lastMode !== VIEWS.ANIMATE) { + // update widget rotations from timeline marker + WIDGETS.setAxisIndex(isPreview || !isIndexed ? 0 : -index); } currentIndex = isIndexed && !isPreview ? index * DEG2RAD : 0; updateStock(); diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index 4152d22b..5153293c 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -517,7 +517,7 @@ class OpOutline extends CamOp { let cnt = 0; let tot = 0; if (op.outside && !op.inside) { - console.log({outline_bypass: indices, down: op.down}); + // console.log({outline_bypass: indices, down: op.down}); indices.forEach((ind,i) => { if (flats.indexOf(ind) >= 0) { // exclude flats diff --git a/src/kiri-mode/cam/tools.js b/src/kiri-mode/cam/tools.js index e5764d5a..49ca8a56 100644 --- a/src/kiri-mode/cam/tools.js +++ b/src/kiri-mode/cam/tools.js @@ -87,37 +87,44 @@ gapp.register("kiri-mode.cam.tools", (root, exports) => { ui.toolTaperTip.disabled = taper ? undefined : 'true'; $('tool-view').innerHTML = ''; setTimeout(() => { - let svg = $('tool-svg'); - let pad = 10; - let dim = { w: svg.clientWidth, h: svg.clientHeight } - let max = { w: dim.w - pad * 2, h: dim.h - pad * 2}; - let off = { x: pad, y: pad }; - let shaft_fill = "#cccccc"; - let flute_fill = "#dddddd"; - let stroke = "#777777"; - let stroke_width = 3; - let stroke_thin = stroke_width / 2; - let shaft = tool.shaft_len || 1; - let flute = tool.flute_len || 1; - let tip_len = type === "ballmill" ? tool.flute_diam / 2 : 0; - let total_len = shaft + flute + tip_len; - let units = dim.h / total_len; - let shaft_len = (shaft / total_len) * max.h; - let flute_len = (flute / total_len) * max.h; - let total_wid = Math.max(tool.flute_diam, tool.shaft_diam); - let shaft_off = (max.w - tool.shaft_diam * units) / 2; - let flute_off = (max.w - tool.flute_diam * units) / 2; - let taper_off = (max.w - (tool.taper_tip || 0) * units) / 2; - let parts = [ - { rect: { - x:off.x + shaft_off, y:off.y, - width:max.w - shaft_off * 2, height:shaft_len, - stroke, fill: shaft_fill, stroke_width - } } - ]; + let svg = $('tool-svg'), + pad = 10, + dim = { w: svg.clientWidth, h: svg.clientHeight }, + max = { w: dim.w - pad * 2, h: dim.h - pad * 2}, + off = { x: pad, y: pad }, + isBall = type === "ballmill", + shaft_fill = "#cccccc", + flute_fill = "#dddddd", + stroke = "#777777", + stroke_width = 3, + stroke_thin = stroke_width / 2, + shaft = tool.shaft_len || 1, + flute = tool.flute_len || 1, + total_len = shaft + flute, + units = dim.h / total_len, + shaft_len = (shaft / total_len) * max.h, + flute_len = ((flute / total_len) * max.h), + shaft_diam = tool.shaft_diam * units, + flute_diam = tool.flute_diam * units, + // total_wid = Math.max(flute_diam, shaft_diam), + shaft_off = (max.w - shaft_diam) / 2, + flute_off = (max.w - flute_diam) / 2, + taper_off = (max.w - (tool.taper_tip || 0) * units) / 2, + parts = [ + // shaft rectangle + { rect: { + x: off.x + shaft_off, + y: off.y, + width: max.w - shaft_off * 2, + height: shaft_len, + fill: shaft_fill, + stroke_width, + stroke + } } + ]; if (type === "tapermill") { let yoff = off.y + shaft_len; - let mid = dim.w / 2; + // let mid = dim.w / 2; parts.push({path: {stroke_width, stroke, fill:flute_fill, d:[ `M ${off.x + flute_off} ${yoff}`, `L ${off.x + taper_off} ${yoff + flute_len}`, @@ -126,15 +133,22 @@ gapp.register("kiri-mode.cam.tools", (root, exports) => { `z` ].join('\n')}}); } else { + let fl = isBall ? flute_len - flute_diam/2 : flute_len; let x1 = off.x + flute_off; let y1 = off.y + shaft_len; let x2 = x1 + max.w - flute_off * 2; - let y2 = y1 + flute_len; + let y2 = y1 + fl; + // flute rectangle parts.push({ rect: { - x:off.x + flute_off, y:off.y + shaft_len, - width:max.w - flute_off * 2, height:flute_len, - stroke, fill: flute_fill, stroke_width + x: off.x + flute_off, + y: off.y + shaft_len, + width: max.w - flute_off * 2, + height: fl, + fill: flute_fill, + stroke_width, + stroke, } }); + // hatch "fill" flute parts.push({ line: { x1, y1, x2, y2, stroke, stroke_width: stroke_thin } }); parts.push({ line: { x1: (x1 + x2) / 2, y1, x2, y2: (y1 + y2) / 2, @@ -145,10 +159,10 @@ gapp.register("kiri-mode.cam.tools", (root, exports) => { stroke, stroke_width: stroke_thin } }); } - if (type === "ballmill") { + if (isBall) { let rad = (max.w - flute_off * 2) / 2; let xend = dim.w - off.x - flute_off; - let yoff = off.y + shaft_len + flute_len + stroke_width/2; + let yoff = off.y + shaft_len + flute_len + stroke_width/2 - flute_diam/2; parts.push({path: {stroke_width, stroke, fill:flute_fill, d:[ `M ${off.x + flute_off} ${yoff}`, `A ${rad} ${rad} 0 0 0 ${xend} ${yoff}`, diff --git a/src/kiri-mode/cam/topo4.js b/src/kiri-mode/cam/topo4.js index 090be98d..4e87136f 100644 --- a/src/kiri-mode/cam/topo4.js +++ b/src/kiri-mode/cam/topo4.js @@ -517,7 +517,7 @@ moto.broker.subscribe("minion.started", msg => { const { slices, tool } = cache.lathe; const axis = new THREE.Vector3(1, 0, 0); - const mrot = new THREE.Matrix4().makeRotationAxis(axis, angle); + const mrot = new THREE.Matrix4().makeRotationAxis(axis, -angle); const stmp = slices.map(s => { const lines = s.lines.slice(); rotatePoints(lines, mrot); diff --git a/src/kiri/widgets.js b/src/kiri/widgets.js index 757f26fc..bd014655 100644 --- a/src/kiri/widgets.js +++ b/src/kiri/widgets.js @@ -92,6 +92,14 @@ function opacity(value) { moto.space.update(); } +function setIndexed(value) { + api.widgets.each(w => w.setIndexed(value)); +} + +function setAxisIndex(value) { + api.widgets.each(w => w.setAxisIndex(value)); +} + // extend API (api.widgets) const widgets = Object.assign(api.widgets, { load: Widget.loadFromCatalog, @@ -102,6 +110,8 @@ const widgets = Object.assign(api.widgets, { replace, opacity, annotate, + setIndexed, + setAxisIndex, all() { return WIDGETS.slice() }, add(w) { return WIDGETS.push(w) }, remove(w) { return WIDGETS.remove(w) },