diff --git a/package.json b/package.json index 045791b1..19c473d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grid-apps", - "version": "2.5.6D", + "version": "2.5.7D", "description": "grid.space 3d slice & modeling tools", "author": "Stewart Allen ", "license": "MIT", diff --git a/src/kiri.js b/src/kiri.js index 1eeb5296..4eca351d 100644 --- a/src/kiri.js +++ b/src/kiri.js @@ -6,7 +6,7 @@ if (!self.kiri) { self.kiri = { - beta: 2506, + beta: 2507, driver: {}, // driver modules loader: [] // module loading: array of functions }; diff --git a/src/kiri/conf.js b/src/kiri/conf.js index d1c9c89b..997b3059 100644 --- a/src/kiri/conf.js +++ b/src/kiri/conf.js @@ -456,7 +456,8 @@ camDepthFirst: false, camEaseDown: false, camOriginTop: true, - camZTopOffset: 0, + camZAnchor: "top", + camZOffset: 0, camZBottom: 0, camZClearance: 1, camZThru: 0, @@ -616,7 +617,6 @@ showSpeeds: true, freeLayout: true, autoLayout: true, - alignTop: true, units: "mm", exportOcto: false, exportGhost: false, diff --git a/src/kiri/init.js b/src/kiri/init.js index 0e0d50c2..212aeef6 100644 --- a/src/kiri/init.js +++ b/src/kiri/init.js @@ -130,6 +130,11 @@ API.platform.update_speeds(); } + function zAnchorSave() { + API.conf.update(); + API.platform.update_top_z(); + } + function booleanSave() { let control = settings().controller; let isDark = control.dark; @@ -139,7 +144,6 @@ control.showRulers = UI.showRulers.checked; control.autoLayout = UI.autoLayout.checked; control.freeLayout = UI.freeLayout.checked; - control.alignTop = UI.alignTop.checked; control.autoSave = UI.autoSave.checked; control.reverseZoom = UI.reverseZoom.checked; control.dark = UI.dark.checked; @@ -1554,7 +1558,6 @@ units: UC.newSelect(LANG.op_unit_s, {title: LANG.op_unit_l, action:unitsSave, modes:CAM, trace:true}, "units"), layout: UC.newGroup(LANG.lo_menu, $('prefs-lay'), {inline: true}), - alignTop: UC.newBoolean(LANG.op_alig_s, booleanSave, {title:LANG.op_alig_l}), autoLayout: UC.newBoolean(LANG.op_auto_s, booleanSave, {title:LANG.op_auto_l}), freeLayout: UC.newBoolean(LANG.op_free_s, booleanSave, {title:LANG.op_free_l}), autoSave: UC.newBoolean(LANG.op_save_s, booleanSave, {title:LANG.op_save_l}), @@ -1751,10 +1754,13 @@ camStockOn: UC.newBoolean(LANG.cs_offe_s, onBooleanClick, {title:LANG.cs_offe_l, modes:CAM}), camCommon: UC.newGroup(LANG.cc_menu, null, {modes:CAM}), - camZTopOffset: UC.newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:UC.toFloat, modes:CAM, units:true}), + camZAnchor: UC.newSelect(LANG.ou_zanc_s, {title: LANG.ou_zanc_l, action:zAnchorSave, modes:CAM, trace:true}, "zanchor"), + camZOffset: UC.newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:UC.toFloat, modes:CAM, units:true}), camZBottom: UC.newInput(LANG.ou_zbot_s, {title:LANG.ou_zbot_l, convert:UC.toFloat, modes:CAM, units:true, trigger: true}), - camZClearance: UC.newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:UC.toFloat, bound:UC.bound(0.01,100), modes:CAM, units:true}), camZThru: UC.newInput(LANG.ou_ztru_s, {title:LANG.ou_ztru_l, convert:UC.toFloat, bound:UC.bound(0.0,100), modes:CAM, units:true, show:() => { return UI.camZBottom.value == 0 }}), + camSep: UC.newBlank({class:"pop-sep"}), + camZClearance: UC.newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:UC.toFloat, bound:UC.bound(0.01,100), modes:CAM, units:true}), + camSep: UC.newBlank({class:"pop-sep"}), camFastFeedZ: UC.newInput(LANG.cc_rzpd_s, {title:LANG.cc_rzpd_l, convert:UC.toFloat, modes:CAM, units:true}), camFastFeed: UC.newInput(LANG.cc_rapd_s, {title:LANG.cc_rapd_l, convert:UC.toFloat, modes:CAM, units:true}), @@ -2280,7 +2286,6 @@ UI.showSpeeds.checked = control.showSpeeds; UI.freeLayout.checked = control.freeLayout; UI.autoLayout.checked = control.autoLayout; - UI.alignTop.checked = control.alignTop; UI.reverseZoom.checked = control.reverseZoom; UI.autoSave.checked = control.autoSave; UI.decimate.checked = control.decimate; diff --git a/src/kiri/main.js b/src/kiri/main.js index 840fd256..1cdabadc 100644 --- a/src/kiri/main.js +++ b/src/kiri/main.js @@ -190,6 +190,11 @@ { name: "follow" }, // { name: "out" }, // { name: "in" } + ], + zanchor: [ + { name: "top" }, + { name: "middle" }, + { name: "bottom" } ] }; @@ -1206,7 +1211,7 @@ let y = 0; let z = 0; if (MODE === MODES.CAM && proc.camOriginTop) { - z = (topZ + topZD) + 0.01; + z = (hasStock ? stock.z : topZ) + 0.01; } if (!center) { if (hasStock) { @@ -1236,15 +1241,30 @@ } function platformUpdateTopZ(zdelta) { + // preserve topZD and re-use when not supplied as argument topZD = zdelta !== undefined ? zdelta : topZD; let stock = settings.stock; let hasStock = stock.x && stock.y && stock.z; - let alignTopOk = WIDGETS.length > 1 && settings.controller.alignTop; - let camz = (MODE === MODES.CAM) && (hasStock || alignTopOk); - let czto = hasStock ? settings.process.camZTopOffset : 0; - let ztop = camz ? (topZ + topZD) - czto : 0; forAllWidgets(function(widget) { - widget.setTopZ(ztop); + if (MODE === MODES.CAM) { + let bounds = widget.getBoundingBox(); + let wzmax = bounds.max.z; + let topz = hasStock ? stock.z : topZ; + let zdelta = settings.process.camZOffset || 0; + switch (settings.process.camZAnchor) { + case 'top': + widget.setTopZ(stock.z - zdelta); + break; + case 'middle': + widget.setTopZ(stock.z - (stock.z - wzmax) / 2); + break; + case 'bottom': + widget.setTopZ(wzmax + zdelta); + break; + } + } else { + widget.setTopZ(0); + } }); } diff --git a/src/kiri/widget.js b/src/kiri/widget.js index bd94f85a..9af9587b 100644 --- a/src/kiri/widget.js +++ b/src/kiri/widget.js @@ -147,6 +147,7 @@ y: 0, z: 0 }, + top: 0, // z top mirror: false }, this.stats = { @@ -391,13 +392,16 @@ PRO.setTopZ = function(z) { let mesh = this.mesh, pos = this.track.pos, - ltz = this.last_top_z || {}; + ltz = this.last_top_z || {}, + mbz = mesh.getBoundingBox().max.z; if (z) { - pos.z = mesh.getBoundingBox().max.z - z; + pos.z = mbz - z; mesh.position.z = -pos.z - 0.01; + this.track.top = z; } else { pos.z = 0; mesh.position.z = 0; + this.track.top = mbz; } let ntz = { pz: pos.z, diff --git a/src/license.js b/src/license.js index 170ca849..3025a735 100644 --- a/src/license.js +++ b/src/license.js @@ -3,7 +3,7 @@ let terms = { COPYRIGHT: "Copyright (C) Stewart Allen - All Rights Reserved", LICENSE: "See the license.md file included with the source distribution", - VERSION: "2.5.D6" + VERSION: "2.5.D7" }; if (typeof(module) === 'object') { diff --git a/src/mode/cam/client.js b/src/mode/cam/client.js index b1981799..ec79baea 100644 --- a/src/mode/cam/client.js +++ b/src/mode/cam/client.js @@ -704,7 +704,8 @@ const { stock, bounds, process } = API.conf.get(); const { camTabsWidth, camTabsHeight, camTabsDepth } = process; const sz = stock.z || bounds.max.z; - const zp = sz - track.box.d + process.camZBottom - process.camZTopOffset + camTabsHeight / 2; + const zto = sz - iw.track.top; + const zp = sz - track.box.d + process.camZBottom - zto + camTabsHeight / 2; ic.x += n.x * camTabsDepth / 2; // offset from part ic.z -= n.y * camTabsDepth / 2; // offset swap z,y ic.y = zp; // offset swap in world space y,z diff --git a/src/mode/cam/export.js b/src/mode/cam/export.js index 0f335405..7cd531fe 100644 --- a/src/mode/cam/export.js +++ b/src/mode/cam/export.js @@ -58,7 +58,7 @@ points = 0, stock = settings.stock, hasStock = spro.camStockOn && stock.x && stock.y && stock.z, - ztOff = hasStock ? spro.camZTopOffset : 0, + ztOff = hasStock ? stock.z - widget.track.top : 0, bounds = widget.getBoundingBox(), zmax = hasStock ? stock.z : bounds.max.z, runbox = { diff --git a/src/mode/cam/ops.js b/src/mode/cam/ops.js index aad3462b..5e92f066 100644 --- a/src/mode/cam/ops.js +++ b/src/mode/cam/ops.js @@ -58,12 +58,14 @@ let facing = POLY.offset(inset, -(roughToolDiam * op.step), { count: 999, flat: true }); let zdiv = ztOff / roughDown; let zstep = (zdiv % 1 > 0) ? ztOff / (Math.floor(zdiv) + 1) : roughDown; - if (roughTop && ztOff === 0) { + if (ztOff === 0) { // compensate for lack of z top offset in this scenario ztOff = zstep; } + let zsteps = Math.round(ztOff / zstep); let camFaces = this.camFaces = []; - for (let z = zMax + ztOff - zstep; z >= zMax; z -= zstep) { + let zstart = zMax + ztOff - zstep; + for (let z = zstart; zsteps > 0; zsteps--) { let slice = shadowTop.slice.clone(false); slice.z = z; slice.camMode = PRO.LEVEL; @@ -73,6 +75,7 @@ .addPolys(slice.camLines); sliceAll.push(slice); camFaces.push(slice); + z -= zstep; } } diff --git a/src/mode/cam/prepare.js b/src/mode/cam/prepare.js index be656145..95e8d26a 100644 --- a/src/mode/cam/prepare.js +++ b/src/mode/cam/prepare.js @@ -63,7 +63,8 @@ alignTop = settings.controller.alignTop, zclear = (process.camZClearance || 1), zmax_outer = hasStock ? stock.z + zclear : outerz + zclear, - ztOff = hasStock ? process.camZTopOffset : 0, + wztop = widget.track.top, + ztOff = hasStock ? stock.z - wztop : 0, bounds = widget.getBoundingBox(), boundsz = bounds.max.z + ztOff, zadd = hasStock ? stock.z - boundsz : alignTop ? outerz - boundsz : 0, diff --git a/src/mode/cam/slice.js b/src/mode/cam/slice.js index 9a07e400..f1a786a8 100644 --- a/src/mode/cam/slice.js +++ b/src/mode/cam/slice.js @@ -34,7 +34,8 @@ zMin = Math.max(bounds.min.z, zBottom), zMax = bounds.max.z, zThru = zBottom === 0 ? (proc.camZThru || 0) : 0, - ztOff = hasStock ? proc.camZTopOffset : 0, + wztop = widget.track.top, + ztOff = hasStock ? stock.z - wztop : 0, minToolDiam = Infinity, maxToolDiam = -Infinity, thruHoles, diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index f939f8a4..d6cc5aac 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -136,8 +136,6 @@ kiri.lang['en-us'] = { op_shru_l: "show axes rulers\non major gridlines", op_sped_s: "show speeds", op_sped_l: "show speed to color bar\nin preview mode", - op_alig_s: "align top", - op_alig_l: "align parts to the\ntallest part when\nno stock is set", op_auto_s: "auto layout", op_auto_l: "automatically layout platform\nwhen new items added", op_free_s: "free layout", @@ -403,12 +401,14 @@ kiri.lang['en-us'] = { // OUTPUT CAM ou_toll_s: "tolerance", ou_toll_l: "surface precision\nin workspace units\nlower is slower and\nuses more memory\n0 = automatic based\non animate preference", - ou_ztof_s: "z top offset", - ou_ztof_l: "offset from stock surface\nto top face of part\nin workspace units", + ou_zanc_s: "z anchor", + ou_zanc_l: "controls the position of the part\nwhen stock Z exceeds part Z", + ou_ztof_s: "z offset", + ou_ztof_l: "offset z anchor\nin workspace units\nhas no effect when\nanchor is middle", ou_zbot_s: "z bottom", ou_zbot_l: "offset from part bottom\nto limit cutting depth\nin workspace units", ou_zclr_s: "z clearance", - ou_zclr_l: "travel offset from z top\nin workspace units", + ou_zclr_l: "safe travel offset\nfrom top of part\nin workspace units", ou_ztru_s: "z thru", ou_ztru_l: "extend cutout pass down\nin workspace units", ou_conv_s: "conventional",