Merge branch 'rel-4.5'
This commit is contained in:
commit
afbbb13e9c
31 changed files with 268 additions and 207 deletions
|
|
@ -661,7 +661,7 @@ self.kiri.load(api => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
api.event.on("init-done", function() {
|
api.event.on("load-done", function() {
|
||||||
if (init) {
|
if (init) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
package.json
14
package.json
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "grid-apps",
|
"name": "grid-apps",
|
||||||
"version": "4.4.0",
|
"version": "4.5.0",
|
||||||
"description": "grid.space 3d slicing & modeling tools",
|
"description": "grid.space 3d slicing & modeling tools",
|
||||||
"author": "Stewart Allen <sa@grid.space>",
|
"author": "Stewart Allen <sa@grid.space>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
"@gridspace/app-server": "^0.0.20",
|
"@gridspace/app-server": "^0.0.20",
|
||||||
"@gridspace/basic-ftp": "github:gridspace/basic-ftp#v5.0.5-gridspace",
|
"@gridspace/basic-ftp": "github:gridspace/basic-ftp#v5.0.5-gridspace",
|
||||||
"@gridspace/net-level-client": "^0.2.3",
|
"@gridspace/net-level-client": "^0.2.3",
|
||||||
"@gridspace/raster-path": "^1.0.6",
|
"@gridspace/raster-path": "^1.0.7",
|
||||||
"@tracespace/parser": "^5.0.0-next.0",
|
"@tracespace/parser": "^5.0.0-next.0",
|
||||||
"@tweenjs/tween.js": "^16.6.0",
|
"@tweenjs/tween.js": "^16.6.0",
|
||||||
"aedes": "^0.51.3",
|
"aedes": "^0.51.3",
|
||||||
|
|
@ -73,6 +73,7 @@
|
||||||
"@docusaurus/preset-classic": "^3.9.0",
|
"@docusaurus/preset-classic": "^3.9.0",
|
||||||
"@electron/notarize": "^3.0.0",
|
"@electron/notarize": "^3.0.0",
|
||||||
"copy-webpack-plugin": "^12.0.2",
|
"copy-webpack-plugin": "^12.0.2",
|
||||||
|
"cross-env": "^10.1.0",
|
||||||
"docusaurus-lunr-search": "^3.6.0",
|
"docusaurus-lunr-search": "^3.6.0",
|
||||||
"dotenv": "latest",
|
"dotenv": "latest",
|
||||||
"electron": "^35.0.1",
|
"electron": "^35.0.1",
|
||||||
|
|
@ -86,7 +87,7 @@
|
||||||
"webpack-cli": "^5.1.4"
|
"webpack-cli": "^5.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-debug": "npm run prebuild && DEBUG=electron-builder electron-builder",
|
"build-debug": "npm run prebuild && cross-env DEBUG=electron-builder electron-builder",
|
||||||
"build-linux-arm": "npm run build -- --linux --arm64",
|
"build-linux-arm": "npm run build -- --linux --arm64",
|
||||||
"build-linux": "npm run build -- --linux --x64",
|
"build-linux": "npm run build -- --linux --x64",
|
||||||
"build-mac-intel": "npm run build -- --mac --x64",
|
"build-mac-intel": "npm run build -- --mac --x64",
|
||||||
|
|
@ -97,7 +98,7 @@
|
||||||
"build": "npm run prebuild && electron-builder",
|
"build": "npm run prebuild && electron-builder",
|
||||||
"bundle:dev": "node bin/bundler.mjs bin/bundle.config.json",
|
"bundle:dev": "node bin/bundler.mjs bin/bundle.config.json",
|
||||||
"bundle:prod": "node bin/bundler.mjs bin/bundle-prod.config.json",
|
"bundle:prod": "node bin/bundler.mjs bin/bundle-prod.config.json",
|
||||||
"bundle": "COMPRESS=1 npm run bundle:prod",
|
"bundle": "cross-env COMPRESS=1 npm run bundle:prod",
|
||||||
"clean": "rm -rf alt build data dist src/pack src.old tmp web.old .bcache",
|
"clean": "rm -rf alt build data dist src/pack src.old tmp web.old .bcache",
|
||||||
"dev": "npm run pack-dev && gs-app-server --debug --single",
|
"dev": "npm run pack-dev && gs-app-server --debug --single",
|
||||||
"docs-build": "docusaurus build --config conf/docusaurus.config.js",
|
"docs-build": "docusaurus build --config conf/docusaurus.config.js",
|
||||||
|
|
@ -111,11 +112,10 @@
|
||||||
"pack-dev": "npm run webpack-src && npm run dryrun && npm run bundle:dev",
|
"pack-dev": "npm run webpack-src && npm run dryrun && npm run bundle:dev",
|
||||||
"pack-prod": "npm run webpack-src prod && npm run dryrun && npm run bundle",
|
"pack-prod": "npm run webpack-src prod && npm run dryrun && npm run bundle",
|
||||||
"postbuild": "node bin/electron-post.js",
|
"postbuild": "node bin/electron-post.js",
|
||||||
"prebuild": "export ELECTRON_BUILD=1 && npm run setup && npm run pack-dev && node bin/electron-pre.js",
|
"prebuild": "npm run setup && cross-env ELECTRON_BUILD=1 npm run pack-dev && node bin/electron-pre.js",
|
||||||
"preinstall": "node bin/install-pre.js",
|
"preinstall": "node bin/install-pre.js",
|
||||||
"prod": "npm run pack-prod && gs-app-server",
|
"prod": "npm run pack-prod && gs-app-server",
|
||||||
"setup-mods": "cd mods && npm i",
|
"setup": "npm run clean && npm i && npm run webpack-ext",
|
||||||
"setup": "npm run clean && npm run setup-mods && npm i && npm run webpack-ext",
|
|
||||||
"start-dbg": "npm run prebuild && electron . --debugg",
|
"start-dbg": "npm run prebuild && electron . --debugg",
|
||||||
"start-ddb": "npm run prebuild && electron . --devel --debugg",
|
"start-ddb": "npm run prebuild && electron . --devel --debugg",
|
||||||
"start-dev": "npm run prebuild prod && electron . --devel",
|
"start-dev": "npm run prebuild prod && electron . --devel",
|
||||||
|
|
|
||||||
|
|
@ -537,7 +537,7 @@ export const conf = {
|
||||||
camPocketOver: 0.25,
|
camPocketOver: 0.25,
|
||||||
camPocketPlunge: 200,
|
camPocketPlunge: 200,
|
||||||
camPocketRefine: 20,
|
camPocketRefine: 20,
|
||||||
camPocketSmooth: 0,
|
camPocketSmooth: 1,
|
||||||
camPocketSpeed: 250,
|
camPocketSpeed: 250,
|
||||||
camPocketSpindle: 1000,
|
camPocketSpindle: 1000,
|
||||||
camPocketTool: 1000,
|
camPocketTool: 1000,
|
||||||
|
|
@ -932,6 +932,7 @@ export const conf = {
|
||||||
freeLayout: true,
|
freeLayout: true,
|
||||||
healMesh: false,
|
healMesh: false,
|
||||||
lineType: "path",
|
lineType: "path",
|
||||||
|
manifold: false,
|
||||||
ortho: false,
|
ortho: false,
|
||||||
reverseZoom: true,
|
reverseZoom: true,
|
||||||
scrolls: true,
|
scrolls: true,
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ function booleanSave() {
|
||||||
control.freeLayout = ui.freeLayout.checked;
|
control.freeLayout = ui.freeLayout.checked;
|
||||||
control.healMesh = ui.healMesh.checked;
|
control.healMesh = ui.healMesh.checked;
|
||||||
control.ortho = ui.ortho.checked;
|
control.ortho = ui.ortho.checked;
|
||||||
|
control.manifold = ui.manifold.checked;
|
||||||
control.reverseZoom = ui.reverseZoom.checked;
|
control.reverseZoom = ui.reverseZoom.checked;
|
||||||
control.scrolls = ui.scrolls.checked;
|
control.scrolls = ui.scrolls.checked;
|
||||||
control.shiny = ui.shiny.checked;
|
control.shiny = ui.shiny.checked;
|
||||||
|
|
@ -1046,6 +1047,7 @@ function init_one() {
|
||||||
showSpeeds: newBoolean(LANG.op_sped_s, speedSave, {title:LANG.op_sped_l}),
|
showSpeeds: newBoolean(LANG.op_sped_s, speedSave, {title:LANG.op_sped_l}),
|
||||||
shiny: newBoolean(LANG.op_shny_s, booleanSave, {title:LANG.op_shny_l, modes:FDM}),
|
shiny: newBoolean(LANG.op_shny_s, booleanSave, {title:LANG.op_shny_l, modes:FDM}),
|
||||||
lineType: newSelect(LANG.op_line_s, {title: LANG.op_line_l, action: lineTypeSave, modes:FDM}, "linetype"),
|
lineType: newSelect(LANG.op_line_s, {title: LANG.op_line_l, action: lineTypeSave, modes:FDM}, "linetype"),
|
||||||
|
manifold: newBoolean(LANG.op_mani_s, booleanSave, {title: LANG.op_mani_l, modes:CAM}, "manifold"),
|
||||||
animesh: newSelect(LANG.op_anim_s, {title: LANG.op_anim_l, action: aniMeshSave, modes:CAM}, "animesh"),
|
animesh: newSelect(LANG.op_anim_s, {title: LANG.op_anim_l, action: aniMeshSave, modes:CAM}, "animesh"),
|
||||||
units: newSelect(LANG.op_unit_s, {title: LANG.op_unit_l, action: unitsSave, modes:CAM}, "units"),
|
units: newSelect(LANG.op_unit_s, {title: LANG.op_unit_l, action: unitsSave, modes:CAM}, "units"),
|
||||||
edgeangle: newInput(LANG.op_spoa_s, {title:LANG.op_spoa_l, convert:toFloat, size:3}),
|
edgeangle: newInput(LANG.op_spoa_s, {title:LANG.op_spoa_l, convert:toFloat, size:3}),
|
||||||
|
|
@ -1639,6 +1641,7 @@ function init_two() {
|
||||||
ui.devel.checked = control.devel;
|
ui.devel.checked = control.devel;
|
||||||
ui.freeLayout.checked = control.freeLayout;
|
ui.freeLayout.checked = control.freeLayout;
|
||||||
ui.healMesh.checked = control.healMesh;
|
ui.healMesh.checked = control.healMesh;
|
||||||
|
ui.manifold.checked = control.manifold;
|
||||||
ui.ortho.checked = control.ortho;
|
ui.ortho.checked = control.ortho;
|
||||||
ui.reverseZoom.checked = control.reverseZoom;
|
ui.reverseZoom.checked = control.reverseZoom;
|
||||||
ui.showOrigin.checked = control.showOrigin;
|
ui.showOrigin.checked = control.showOrigin;
|
||||||
|
|
|
||||||
|
|
@ -163,19 +163,19 @@ function platformUpdateTopZ() {
|
||||||
const wzmax = bounds.max.z;
|
const wzmax = bounds.max.z;
|
||||||
const zdelta = process.camZOffset || 0;
|
const zdelta = process.camZOffset || 0;
|
||||||
switch (process.camZAnchor) {
|
switch (process.camZAnchor) {
|
||||||
case 'top':
|
case 'top':
|
||||||
widget.setTopZ(stock.z - zdelta);
|
widget.setTopZ(stock.z - zdelta, true);
|
||||||
break;
|
break;
|
||||||
case 'middle':
|
case 'middle':
|
||||||
if (widget.isIndexed) {
|
if (widget.isIndexed) {
|
||||||
widget.setTopZ(zdelta);
|
widget.setTopZ(zdelta, true);
|
||||||
} else {
|
} else {
|
||||||
widget.setTopZ(stock.z - (stock.z - wzmax) / 2 + zdelta);
|
widget.setTopZ(stock.z - (stock.z - wzmax) / 2 + zdelta, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
widget.setTopZ(wzmax + zdelta);
|
widget.setTopZ(wzmax + zdelta, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
widget.setTopZ(0);
|
widget.setTopZ(0);
|
||||||
|
|
|
||||||
|
|
@ -473,10 +473,12 @@ class Widget {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* moves top of widget to given Z
|
* moves top of widget to given Z
|
||||||
|
* only non-zero in CAM mode
|
||||||
*
|
*
|
||||||
* @param {number} z position
|
* @param {number} z position
|
||||||
|
* @param {boolean} cam mode
|
||||||
*/
|
*/
|
||||||
setTopZ(z) {
|
setTopZ(z, cam) {
|
||||||
let mesh = this.mesh,
|
let mesh = this.mesh,
|
||||||
track = this.track,
|
track = this.track,
|
||||||
mbb = mesh.getBoundingBox(),
|
mbb = mesh.getBoundingBox(),
|
||||||
|
|
@ -488,7 +490,7 @@ class Widget {
|
||||||
track.top = mbz;
|
track.top = mbz;
|
||||||
}
|
}
|
||||||
// difference between top of stock/bounds and top of widget (cam mode)
|
// difference between top of stock/bounds and top of widget (cam mode)
|
||||||
track.tzoff = mbz - z;
|
track.tzoff = cam ? mbz - z : 0;
|
||||||
this._updateMeshPosition();
|
this._updateMeshPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -503,8 +505,7 @@ class Widget {
|
||||||
}
|
}
|
||||||
|
|
||||||
_move(x, y, z, abs) {
|
_move(x, y, z, abs) {
|
||||||
let mesh = this.mesh,
|
let mat = this.getMaterial(),
|
||||||
mat = this.getMaterial(),
|
|
||||||
pos = this.track.pos;
|
pos = this.track.pos;
|
||||||
// do not allow moves in pure slice view
|
// do not allow moves in pure slice view
|
||||||
if (!mat.visible) return;
|
if (!mat.visible) return;
|
||||||
|
|
@ -528,13 +529,10 @@ class Widget {
|
||||||
track = this.track,
|
track = this.track,
|
||||||
tzoff = track.tzoff,
|
tzoff = track.tzoff,
|
||||||
top = track.top,
|
top = track.top,
|
||||||
tz = tzoff !== top ? -tzoff : 0,
|
tz = -tzoff,
|
||||||
{ x, y, z } = track.pos;
|
{ x, y, z } = track.pos;
|
||||||
if (track.indexed) {
|
if (track.indexed) {
|
||||||
let rad = track.indexRad;
|
let rad = track.indexRad;
|
||||||
let ln = track.box.d / 2;
|
|
||||||
let dx = Math.sin(rad) * ln;
|
|
||||||
let dy = ln - Math.cos(rad) * ln;
|
|
||||||
this.mesh.rotation.x = -rad;
|
this.mesh.rotation.x = -rad;
|
||||||
z = top;
|
z = top;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ let nextMeshID = 1,
|
||||||
toolMesh,
|
toolMesh,
|
||||||
toolRadius,
|
toolRadius,
|
||||||
toolUpdateMsg,
|
toolUpdateMsg,
|
||||||
showStock = false,
|
|
||||||
animateClear = false,
|
animateClear = false,
|
||||||
animating = false,
|
animating = false,
|
||||||
renderDone = false,
|
renderDone = false,
|
||||||
|
|
@ -36,7 +35,7 @@ export function init(worker) {
|
||||||
|
|
||||||
dispatch.animate_setup2 = function (data, send) {
|
dispatch.animate_setup2 = function (data, send) {
|
||||||
const { settings } = data;
|
const { settings } = data;
|
||||||
const { process } = settings;
|
const { controller, process } = settings;
|
||||||
const print = worker.current.print;
|
const print = worker.current.print;
|
||||||
const density = parseInt(settings.controller.animesh) * 1000;
|
const density = parseInt(settings.controller.animesh) * 1000;
|
||||||
const isIndexed = process.camStockIndexed;
|
const isIndexed = process.camStockIndexed;
|
||||||
|
|
@ -61,14 +60,14 @@ export function init(worker) {
|
||||||
const sliceCount = parseInt(settings.controller.animesh || 2000) / 100;
|
const sliceCount = parseInt(settings.controller.animesh || 2000) / 100;
|
||||||
const sliceWidth = stock.x / sliceCount;
|
const sliceWidth = stock.x / sliceCount;
|
||||||
|
|
||||||
if (showStock)
|
if (controller.manifold)
|
||||||
for (let i = 0; i < sliceCount; i++) {
|
for (let i = 0; i < sliceCount; i++) {
|
||||||
let xmin = -(x / 2) + (i * sliceWidth) + sliceWidth / 2;
|
let xmin = -(x / 2) + (i * sliceWidth) + sliceWidth / 2;
|
||||||
let slice = new Stock(sliceWidth, y, z).translate(xmin, 0, 0);
|
let slice = new Stock(sliceWidth, y, z).translate(xmin, 0, 0);
|
||||||
stockSlices.push(slice);
|
stockSlices.push(slice);
|
||||||
slice.updateMesh([]);
|
slice.updateMesh([]);
|
||||||
slice.send(send);
|
slice.send(send);
|
||||||
// send({ mesh_move: { id: slice.id, pos: { x:0, y:0, z: stock.z/2} } });
|
// send.data({ mesh_move: { id: slice.id, pos: { x:0, y:0, z: stock.z/2} } });
|
||||||
}
|
}
|
||||||
|
|
||||||
send.done();
|
send.done();
|
||||||
|
|
@ -175,7 +174,7 @@ function renderPath(send) {
|
||||||
const sp = next.speed;
|
const sp = next.speed;
|
||||||
const moves = [];
|
const moves = [];
|
||||||
for (let i = 0, x = lp.x, y = lp.y, z = lp.z, a = lp.a; i < st; i++) {
|
for (let i = 0, x = lp.x, y = lp.y, z = lp.z, a = lp.a; i < st; i++) {
|
||||||
moves.push({ x, y, z, a, md: sd, dx, dy, dz, sp });
|
moves.push({ x, y, z, a, md: sd, dx, dy, dz, da, sp });
|
||||||
x += mx;
|
x += mx;
|
||||||
y += my;
|
y += my;
|
||||||
z += mz;
|
z += mz;
|
||||||
|
|
@ -202,11 +201,11 @@ function renderMoves(id, moves, send, seed = 0) {
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
throw `no pos @ ${index} of ${moves.length}`;
|
throw `no pos @ ${index} of ${moves.length}`;
|
||||||
}
|
}
|
||||||
const { dx, dy, dz, sp, md } = pos;
|
const { dx, dy, dz, da, sp, md } = pos;
|
||||||
toolMove(pos);
|
toolMove(pos);
|
||||||
// console.log('renderMoves', {id, moves, seed});
|
// console.log('renderMoves', {id, moves, seed});
|
||||||
let subs = 0;
|
let subs = 0;
|
||||||
if (dx || dy || dz < 0)
|
if (dx || dy || dz < 0 || da)
|
||||||
for (let slice of stockSlices) {
|
for (let slice of stockSlices) {
|
||||||
if (slice.bounds.intersectsBox(toolMesh.bounds)) {
|
if (slice.bounds.intersectsBox(toolMesh.bounds)) {
|
||||||
slice.subtractTool(toolMesh);
|
slice.subtractTool(toolMesh);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ let meshes = {},
|
||||||
speed,
|
speed,
|
||||||
origin,
|
origin,
|
||||||
color = 0,
|
color = 0,
|
||||||
|
dark = false,
|
||||||
|
manifold = false,
|
||||||
A2R = Math.PI / 180;
|
A2R = Math.PI / 180;
|
||||||
|
|
||||||
export function animate_clear2(api) {
|
export function animate_clear2(api) {
|
||||||
|
|
@ -35,6 +37,8 @@ export function animate_clear2(api) {
|
||||||
export function animate2(api, delay) {
|
export function animate2(api, delay) {
|
||||||
let alert = api.alerts.show("building animation");
|
let alert = api.alerts.show("building animation");
|
||||||
let settings = api.conf.get();
|
let settings = api.conf.get();
|
||||||
|
dark = settings.controller.dark;
|
||||||
|
manifold = settings.controller.manifold;
|
||||||
client.animate_setup2(settings, data => {
|
client.animate_setup2(settings, data => {
|
||||||
handleUpdate(data);
|
handleUpdate(data);
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|
@ -50,7 +54,8 @@ export function animate2(api, delay) {
|
||||||
speed: anim.speed,
|
speed: anim.speed,
|
||||||
trans: anim.trans,
|
trans: anim.trans,
|
||||||
model: anim.model,
|
model: anim.model,
|
||||||
shade: anim.shade
|
shade: anim.shade,
|
||||||
|
path: anim.path
|
||||||
});
|
});
|
||||||
Object.assign(label, {
|
Object.assign(label, {
|
||||||
progress: anim.progress,
|
progress: anim.progress,
|
||||||
|
|
@ -61,6 +66,14 @@ export function animate2(api, delay) {
|
||||||
a: anim.vala
|
a: anim.vala
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (manifold) {
|
||||||
|
anim.trans.classList.remove('hide');
|
||||||
|
// anim.shade.classList.remove('hide');
|
||||||
|
} else {
|
||||||
|
anim.trans.classList.add('hide');
|
||||||
|
// anim.shade.classList.add('hide');
|
||||||
|
}
|
||||||
|
|
||||||
updateSpeed(0);
|
updateSpeed(0);
|
||||||
setTimeout(step, delay || 0);
|
setTimeout(step, delay || 0);
|
||||||
toggleTrans(undefined, false);
|
toggleTrans(undefined, false);
|
||||||
|
|
@ -74,6 +87,7 @@ export function animate2(api, delay) {
|
||||||
button.trans.onclick = toggleTrans;
|
button.trans.onclick = toggleTrans;
|
||||||
button.model.onclick = toggleModel;
|
button.model.onclick = toggleModel;
|
||||||
button.shade.onclick = toggleStock;
|
button.shade.onclick = toggleStock;
|
||||||
|
button.path.onclick = togglePath;
|
||||||
button.play.style.display = '';
|
button.play.style.display = '';
|
||||||
button.pause.style.display = 'none';
|
button.pause.style.display = 'none';
|
||||||
|
|
||||||
|
|
@ -89,7 +103,7 @@ Object.assign(client, {
|
||||||
|
|
||||||
animate_setup2(settings, ondone) {
|
animate_setup2(settings, ondone) {
|
||||||
initPathMesh();
|
initPathMesh();
|
||||||
color = settings.controller.dark ? 0x888888 : 0;
|
color = dark ? 0x888888 : 0;
|
||||||
material = material ?? new THREE.MeshPhongMaterial({
|
material = material ?? new THREE.MeshPhongMaterial({
|
||||||
flatShading: true,
|
flatShading: true,
|
||||||
transparent: false,
|
transparent: false,
|
||||||
|
|
@ -113,11 +127,12 @@ function initPathMesh() {
|
||||||
max = 10000,
|
max = 10000,
|
||||||
rot = new THREE.Euler(0,0,0),
|
rot = new THREE.Euler(0,0,0),
|
||||||
geo = new THREE.BufferGeometry(),
|
geo = new THREE.BufferGeometry(),
|
||||||
mat = new THREE.LineBasicMaterial({ color: 0xffff00 }),
|
mat = new THREE.LineBasicMaterial({ color: dark ? 0xffff00 : 0x771100 }),
|
||||||
pos = new Float32Array(max * 6),
|
pos = new Float32Array(max * 6),
|
||||||
lines = new THREE.LineSegments(geo, mat),
|
lines = new THREE.LineSegments(geo, mat),
|
||||||
vec = new THREE.Vector3(0,0,0),
|
vec = new THREE.Vector3(0,0,0),
|
||||||
ang = new THREE.Vector3(1,0,0);
|
ang = new THREE.Vector3(1,0,0),
|
||||||
|
show = api.local.get('cam.anim.path') ?? true;
|
||||||
geo.setAttribute('position', new THREE.BufferAttribute(pos, 3));
|
geo.setAttribute('position', new THREE.BufferAttribute(pos, 3));
|
||||||
let track = lineTracker = {
|
let track = lineTracker = {
|
||||||
xro(p) {
|
xro(p) {
|
||||||
|
|
@ -157,9 +172,15 @@ function initPathMesh() {
|
||||||
lines.setRotationFromEuler(rot);
|
lines.setRotationFromEuler(rot);
|
||||||
},
|
},
|
||||||
visible(bool) {
|
visible(bool) {
|
||||||
if (bool !== lines.visible) {
|
if (show && bool !== lines.visible) {
|
||||||
lines.visible = bool;
|
lines.visible = bool;
|
||||||
|
} else if (!show) {
|
||||||
|
lines.visible = false;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
show(bool) {
|
||||||
|
show = bool;
|
||||||
|
lines.visible = bool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
space.world.add(lines);
|
space.world.add(lines);
|
||||||
|
|
@ -205,8 +226,15 @@ function toggleModel(ev, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleStock(ev, bool, set) {
|
function toggleStock(ev, bool, set) {
|
||||||
set !== false && api.local.toggle('cam.anim.stock', bool);
|
bool = api.local.toggle('cam.anim.stock', bool);
|
||||||
return api.event.emit('cam.stock.toggle', bool ?? undefined);
|
for (let [ id, mesh ] of Object.entries(meshes)) {
|
||||||
|
if (id >= 0) mesh.visible = bool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function togglePath(ev, bool, set) {
|
||||||
|
bool = api.local.toggle('cam.anim.path', bool);
|
||||||
|
lineTracker?.show(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleTrans(ev, bool) {
|
function toggleTrans(ev, bool) {
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ export function createPopOps() {
|
||||||
plunge: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
plunge: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
||||||
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0), show: () => env.popOp.outline.rec.wide }),
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0), show: () => env.popOp.outline.rec.wide }),
|
||||||
steps: UC.newInput(LANG.cc_sovc_s, { title: LANG.cc_sovc_l, convert: UC.toInt, bound: UC.bound(1, 5), show: () => env.popOp.outline.rec.wide }),
|
steps: UC.newInput(LANG.cc_sovc_s, { title: LANG.cc_sovc_l, convert: UC.toInt, bound: UC.bound(1, 500), show: () => env.popOp.outline.rec.wide }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
top: UC.newBoolean(LANG.co_clrt_s, undefined, { title: LANG.co_clrt_l }),
|
top: UC.newBoolean(LANG.co_clrt_s, undefined, { title: LANG.co_clrt_l }),
|
||||||
inside: UC.newBoolean(LANG.co_olin_s, undefined, { title: LANG.co_olin_l, show: (op) => { return !op.inputs.outside.checked } }),
|
inside: UC.newBoolean(LANG.co_olin_s, undefined, { title: LANG.co_olin_l, show: (op) => { return !op.inputs.outside.checked } }),
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,8 @@ function pointHoverUp(int, ev) {
|
||||||
x += stock.x / 2;
|
x += stock.x / 2;
|
||||||
y += stock.y / 2;
|
y += stock.y / 2;
|
||||||
}
|
}
|
||||||
process.camOriginOffX = x;
|
process.camOriginOffX = x - stock.center.x;
|
||||||
process.camOriginOffY = y;
|
process.camOriginOffY = y - stock.center.y;
|
||||||
process.camOriginOffZ = z;
|
process.camOriginOffZ = z;
|
||||||
api.settings.update_fields(process);
|
api.settings.update_fields(process);
|
||||||
api.platform.update_origin();
|
api.platform.update_origin();
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ export function traceHoverUp(int, ev) {
|
||||||
|
|
||||||
export function traceToggle(obj, skip) {
|
export function traceToggle(obj, skip) {
|
||||||
let material = obj.material[0] || obj.material;
|
let material = obj.material[0] || obj.material;
|
||||||
if (!material) return;
|
if (!(material && obj.trace)) return;
|
||||||
let { color, colorSave } = material;
|
let { color, colorSave } = material;
|
||||||
let { widget, poly } = obj.trace;
|
let { widget, poly } = obj.trace;
|
||||||
let areas = env.poppedRec.areas;
|
let areas = env.poppedRec.areas;
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ export function menu() {
|
||||||
anim.trans = newButton(null,null,{icon:'<i class="fa-solid fa-border-none"></i>',title:"transparency",class:"padleft"}),
|
anim.trans = newButton(null,null,{icon:'<i class="fa-solid fa-border-none"></i>',title:"transparency",class:"padleft"}),
|
||||||
anim.model = newButton(null,null,{icon:'<i class="fa-solid fa-eye"></i>',title:"show model"}),
|
anim.model = newButton(null,null,{icon:'<i class="fa-solid fa-eye"></i>',title:"show model"}),
|
||||||
anim.shade = newButton(null,null,{icon:'<i class="fa-solid fa-cube"></i>',title:"stock box"}),
|
anim.shade = newButton(null,null,{icon:'<i class="fa-solid fa-cube"></i>',title:"stock box"}),
|
||||||
|
anim.path = newButton(null,null,{icon:'<i class="fa-solid fa-draw-polygon"></i>',title:"path"}),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,11 @@ class OpOutline extends CamOp {
|
||||||
|
|
||||||
async slice(progress) {
|
async slice(progress) {
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { settings, widget, slicer, addSlices, tshadow, thruHoles, unsafe, color } = state;
|
let { settings, slicer, addSlices, tshadow, thruHoles, unsafe, color, widget } = state;
|
||||||
let { updateToolDiams, tabs, cutTabs, cutPolys, workarea, zMax, shadowAt } = state;
|
let { updateToolDiams, tabs, cutTabs, cutPolys, workarea, zMax, shadowAt } = state;
|
||||||
let { process, stock } = settings;
|
let { process, stock } = settings;
|
||||||
|
let { controller } = settings;
|
||||||
|
let center_off = widget.track.pos ?? { x: 0, y: 0, z: 0};
|
||||||
|
|
||||||
if (op.down <= 0) {
|
if (op.down <= 0) {
|
||||||
throw `invalid step down "${op.down}"`;
|
throw `invalid step down "${op.down}"`;
|
||||||
|
|
@ -39,6 +41,8 @@ class OpOutline extends CamOp {
|
||||||
let indices = slicer.interval(op.down, intopt);
|
let indices = slicer.interval(op.down, intopt);
|
||||||
let trueShadow = process.camTrueShadow === true;
|
let trueShadow = process.camTrueShadow === true;
|
||||||
let lastShadowZ;
|
let lastShadowZ;
|
||||||
|
let stockClip;
|
||||||
|
|
||||||
// shift out first (top-most) slice
|
// shift out first (top-most) slice
|
||||||
indices.shift();
|
indices.shift();
|
||||||
// add flats to shadow
|
// add flats to shadow
|
||||||
|
|
@ -168,16 +172,12 @@ class OpOutline extends CamOp {
|
||||||
let stepover = toolDiam * op.step;
|
let stepover = toolDiam * op.step;
|
||||||
let wideCuts = [] //accumulator for wide cuts
|
let wideCuts = [] //accumulator for wide cuts
|
||||||
for (let c = (op.steps || 1); c > 0; c--){
|
for (let c = (op.steps || 1); c > 0; c--){
|
||||||
offset.slice().forEach(op => {
|
let wideCut = POLY.expand(offset.clone(true), stepover * c, slice.z, [], 1);
|
||||||
// clone removes inners but the real solution is
|
wideCut.forEach(cut =>{ //set order of cuts when wide
|
||||||
// to limit expanded shells to through holes
|
cut.order = c
|
||||||
let wideCut = POLY.expand([op.clone(true)], stepover*c, slice.z, [], 1);
|
if(cut.inner) cut.inner.forEach(inn =>{ inn.order = c })
|
||||||
wideCut.forEach(cut =>{ //set order of cuts when wide
|
|
||||||
cut.order = c
|
|
||||||
if(cut.inner) cut.inner.forEach(inn =>{ inn.order = c })
|
|
||||||
});
|
|
||||||
wideCuts.push(...wideCut)
|
|
||||||
});
|
});
|
||||||
|
wideCuts.push(...wideCut)
|
||||||
}
|
}
|
||||||
offset.appendAll(wideCuts);
|
offset.appendAll(wideCuts);
|
||||||
}
|
}
|
||||||
|
|
@ -187,16 +187,19 @@ class OpOutline extends CamOp {
|
||||||
addDogbones(offset, toolDiam / 5);
|
addDogbones(offset, toolDiam / 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.camStockClipTo && stock.x && stock.y && stock.center) {
|
||||||
|
let { center } = stock;
|
||||||
|
let x = center.x - center_off.x;
|
||||||
|
let y = center.y - center_off.y;
|
||||||
|
stockClip = newPolygon().centerRectangle({ x, y }, stock.x + 0.001, stock.y + 0.001);
|
||||||
|
offset = cutPolys([stockClip], offset, slice.z, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (tabs) {
|
if (tabs) {
|
||||||
tabs.forEach(tab => {
|
tabs.forEach(tab => {
|
||||||
tab.off = POLY.expand([tab.poly], toolDiam / 2).flat();
|
tab.off = POLY.expand([tab.poly], toolDiam / 2).flat();
|
||||||
});
|
});
|
||||||
offset = cutTabs(tabs, offset, slice.z);
|
offset = cutTabs(tabs, offset);
|
||||||
}
|
|
||||||
|
|
||||||
if (process.camStockClipTo && stock.x && stock.y && stock.center) {
|
|
||||||
let rect = newPolygon().centerRectangle({x:0,y:0}, stock.x, stock.y);
|
|
||||||
offset = cutPolys([rect], offset, slice.z, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// offset.xout(`slice ${slice.z}`);
|
// offset.xout(`slice ${slice.z}`);
|
||||||
|
|
@ -208,9 +211,15 @@ class OpOutline extends CamOp {
|
||||||
|
|
||||||
// project empty up and render
|
// project empty up and render
|
||||||
for (let slice of slices) {
|
for (let slice of slices) {
|
||||||
if (false) slice.output()
|
if (controller.devel) slice.output()
|
||||||
.setLayer("slice", {line: 0xaaaa00}, false)
|
.setLayer("slice", {line: 0xaaaa00}, false)
|
||||||
.addPolys(slice.topPolys())
|
.addPolys(slice.topPolys())
|
||||||
|
if (controller.devel) slice.output()
|
||||||
|
.setLayer("shadow", {line: 0x557799}, false)
|
||||||
|
.addPolys(slice.shadow)
|
||||||
|
if (controller.devel && stockClip) slice.output()
|
||||||
|
.setLayer("stock clip", {line: 0x557799}, false)
|
||||||
|
.addPolys([ stockClip ])
|
||||||
slice.output()
|
slice.output()
|
||||||
.setLayer(state.layername, {face: color, line: color})
|
.setLayer(state.layername, {face: color, line: color})
|
||||||
.addPolys(slice.camLines);
|
.addPolys(slice.camLines);
|
||||||
|
|
@ -224,9 +233,9 @@ class OpOutline extends CamOp {
|
||||||
let { op, state, sliceOut } = this;
|
let { op, state, sliceOut } = this;
|
||||||
let { setTool, setSpindle, setPrintPoint } = ops;
|
let { setTool, setSpindle, setPrintPoint } = ops;
|
||||||
let { polyEmit, depthOutlinePath } = ops;
|
let { polyEmit, depthOutlinePath } = ops;
|
||||||
let { camOut, newLayer, printPoint } = ops;
|
let { newLayer, printPoint } = ops;
|
||||||
let { settings, widget } = state;
|
let { settings } = state;
|
||||||
let { process, controller } = settings;
|
let { process } = settings;
|
||||||
|
|
||||||
let easeDown = process.camEaseDown;
|
let easeDown = process.camEaseDown;
|
||||||
let toolDiam = this.toolDiam;
|
let toolDiam = this.toolDiam;
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,11 @@ class OpPocket extends CamOp {
|
||||||
|
|
||||||
async slice(progress) {
|
async slice(progress) {
|
||||||
const pocket = this;
|
const pocket = this;
|
||||||
const debug = false;
|
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { tool, rate, down, plunge, expand, contour, smooth, tolerance } = op;
|
let { tool, rate, down, plunge, expand, contour, smooth, tolerance } = op;
|
||||||
let { ov_botz, ov_conv } = op;
|
let { ov_botz, ov_conv } = op;
|
||||||
let { settings, widget, addSlices, zBottom, zThru, tabs, color } = state;
|
let { settings, widget, addSlices, zBottom, tabs, color } = state;
|
||||||
let { updateToolDiams, cutTabs, healPolys, shadowAt, workarea } = state;
|
let { updateToolDiams, cutTabs, healPolys, shadowAt, workarea } = state;
|
||||||
let { process } = settings;
|
|
||||||
zBottom = ov_botz ? workarea.bottom_stock + ov_botz : zBottom;
|
zBottom = ov_botz ? workarea.bottom_stock + ov_botz : zBottom;
|
||||||
// generate tracing offsets from chosen features
|
// generate tracing offsets from chosen features
|
||||||
let sliceOut;
|
let sliceOut;
|
||||||
|
|
@ -36,24 +34,18 @@ class OpPocket extends CamOp {
|
||||||
let cutdir = ov_conv;
|
let cutdir = ov_conv;
|
||||||
let engrave = contour && op.engrave;
|
let engrave = contour && op.engrave;
|
||||||
let zTop = workarea.top_z;
|
let zTop = workarea.top_z;
|
||||||
|
let devel = settings.controller.devel;
|
||||||
|
let smoothVal = (smooth ?? 0) / 10;
|
||||||
if (contour) {
|
if (contour) {
|
||||||
down = 0;
|
down = 0;
|
||||||
this.topo = await Topo({
|
this.contour = {
|
||||||
// onupdate: (update, msg) => {
|
axis: "-",
|
||||||
onupdate: (index, total, msg) => {
|
inside: true,
|
||||||
progress((index / total) * 0.9, msg);
|
nogpu: true,
|
||||||
},
|
step: toolOver,
|
||||||
ondone: (slices) => {
|
tolerance,
|
||||||
// console.log({ contour: slices });
|
tool,
|
||||||
},
|
};
|
||||||
contour: {
|
|
||||||
tool,
|
|
||||||
tolerance,
|
|
||||||
inside: true,
|
|
||||||
axis: "-"
|
|
||||||
},
|
|
||||||
state: state
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
updateToolDiams(toolDiam);
|
updateToolDiams(toolDiam);
|
||||||
if (tabs) {
|
if (tabs) {
|
||||||
|
|
@ -69,7 +61,7 @@ class OpPocket extends CamOp {
|
||||||
sliceOut.push(slice);
|
sliceOut.push(slice);
|
||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
function clearZ(polys, z, down) {
|
async function clearZ(polys, z, down) {
|
||||||
if (down) {
|
if (down) {
|
||||||
// adjust step down to a value <= down that
|
// adjust step down to a value <= down that
|
||||||
// ends on the lowest z specified
|
// ends on the lowest z specified
|
||||||
|
|
@ -92,14 +84,14 @@ class OpPocket extends CamOp {
|
||||||
let clip = [], shadow;
|
let clip = [], shadow;
|
||||||
if (contour) {
|
if (contour) {
|
||||||
if (smooth) {
|
if (smooth) {
|
||||||
clip = POLY.offset(POLY.offset([ poly ], smooth), -smooth);
|
clip = POLY.offset(POLY.offset([ poly ], smoothVal), -smoothVal);
|
||||||
} else {
|
} else {
|
||||||
clip = [ poly ];
|
clip = [ poly ];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
shadow = shadowAt(z);
|
shadow = shadowAt(z);
|
||||||
if (smooth) {
|
if (smooth) {
|
||||||
shadow = POLY.setZ(POLY.offset(POLY.offset(shadow, smooth), -smooth), z);
|
shadow = POLY.setZ(POLY.offset(POLY.offset(shadow, smoothVal), -smoothVal), z);
|
||||||
}
|
}
|
||||||
POLY.subtract([ poly ], shadow, clip, undefined, undefined, 0);
|
POLY.subtract([ poly ], shadow, clip, undefined, undefined, 0);
|
||||||
if (op.outline) {
|
if (op.outline) {
|
||||||
|
|
@ -130,16 +122,16 @@ class OpPocket extends CamOp {
|
||||||
}
|
}
|
||||||
POLY.setWinding(slice.camLines, cutdir, false);
|
POLY.setWinding(slice.camLines, cutdir, false);
|
||||||
if (contour) {
|
if (contour) {
|
||||||
slice.camLines = pocket.conform(slice.camLines, op.refine, engrave, pct => {
|
slice.camLines = await pocket.conform(slice.camLines, op.refine, engrave, pct => {
|
||||||
progress(0.9 + (zpro + zinc * pct) * 0.1, "conform");
|
progress(0.9 + (zpro + zinc * pct) * 0.1, "conform");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
slice.output()
|
slice.output()
|
||||||
.setLayer(state.layername, {line: color}, false)
|
.setLayer(state.layername, {line: color}, false)
|
||||||
.addPolys(slice.camLines)
|
.addPolys(slice.camLines)
|
||||||
if (debug && shadow) slice.output()
|
if (devel && shadow) slice.output()
|
||||||
.setLayer("pocket shadow", {line: 0xff8811}, false)
|
.setLayer("pocket shadow", {line: 0xff8811}, false)
|
||||||
.addPolys(shadow)
|
.addPolys(shadow);
|
||||||
if (!contour) {
|
if (!contour) {
|
||||||
progress(zpro, "pocket");
|
progress(zpro, "pocket");
|
||||||
}
|
}
|
||||||
|
|
@ -168,23 +160,37 @@ class OpPocket extends CamOp {
|
||||||
outline = POLY.setWinding(outline, cutdir, false);
|
outline = POLY.setWinding(outline, cutdir, false);
|
||||||
outline = healPolys(outline);
|
outline = healPolys(outline);
|
||||||
if (smooth) {
|
if (smooth) {
|
||||||
outline = POLY.offset(POLY.offset(outline, smooth), -smooth);
|
outline = POLY.offset(POLY.offset(outline, smoothVal), -smoothVal);
|
||||||
}
|
}
|
||||||
if (outline.length) {
|
if (outline.length) {
|
||||||
// option to skip interior features (holes, pillars)
|
// option to skip interior features (holes, pillars)
|
||||||
if (op.outline) {
|
if (op.outline) {
|
||||||
POLY.clearInner(outline);
|
POLY.clearInner(outline);
|
||||||
}
|
}
|
||||||
if (debug) newSliceOut(zmin).output()
|
await clearZ(outline, zmin + 0.0001, down);
|
||||||
|
if (devel && sliceOut?.length) sliceOut[0].output()
|
||||||
.setLayer("pocket area", {line: 0x1188ff}, false)
|
.setLayer("pocket area", {line: 0x1188ff}, false)
|
||||||
.addPolys(outline)
|
.addPolys(outline)
|
||||||
clearZ(outline, zmin + 0.0001, down);
|
|
||||||
progress(1, "pocket");
|
progress(1, "pocket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mold cam output lines to the surface of the topo offset by tool geometry
|
// mold cam output lines to the surface of the topo offset by tool geometry
|
||||||
conform(camLines, refine, engrave, progress) {
|
async conform(camLines, refine, engrave, progress) {
|
||||||
|
if (!this.topo) {
|
||||||
|
console.log('deferred topo');
|
||||||
|
this.topo = await Topo({
|
||||||
|
// onupdate: (update, msg) => {
|
||||||
|
onupdate: (index, total, msg) => {
|
||||||
|
progress((index / total) * 0.9, msg);
|
||||||
|
},
|
||||||
|
ondone: (slices) => {
|
||||||
|
// console.log({ contour: slices });
|
||||||
|
},
|
||||||
|
contour: this.contour,
|
||||||
|
state: this.state
|
||||||
|
});
|
||||||
|
}
|
||||||
const topo = this.topo;
|
const topo = this.topo;
|
||||||
// re-segment polygon to a higher resolution
|
// re-segment polygon to a higher resolution
|
||||||
const hirez = camLines.map(p => p.segment(topo.tolerance * 2));
|
const hirez = camLines.map(p => p.segment(topo.tolerance * 2));
|
||||||
|
|
@ -236,7 +242,7 @@ class OpPocket extends CamOp {
|
||||||
|
|
||||||
prepare(ops, progress) {
|
prepare(ops, progress) {
|
||||||
let { op, state, pockets } = this;
|
let { op, state, pockets } = this;
|
||||||
let { setTool, setSpindle, setTolerance, sliceOutput, getPrintPoint } = ops;
|
let { getPrintPoint , pocket, setTool, setSpindle, setTolerance } = ops;
|
||||||
let { process } = state.settings;
|
let { process } = state.settings;
|
||||||
|
|
||||||
setTool(op.tool, op.rate);
|
setTool(op.tool, op.rate);
|
||||||
|
|
@ -269,11 +275,12 @@ class OpPocket extends CamOp {
|
||||||
}
|
}
|
||||||
if (min.pocket) {
|
if (min.pocket) {
|
||||||
min.pocket.used = true;
|
min.pocket.used = true;
|
||||||
sliceOutput(min.pocket, {
|
pocket({
|
||||||
cutdir: op.ov_conv,
|
cutdir: op.ov_conv,
|
||||||
depthFirst: process.camDepthFirst && !state.isIndexed,
|
depthFirst: process.camDepthFirst && !state.isIndexed,
|
||||||
easeDown: op.down && process.easeDown ? op.down : 0,
|
easeDown: op.down && process.easeDown ? op.down : 0,
|
||||||
progress: (n,m) => progress(n/m, "pocket")
|
progress: (n,m) => progress(n/m, "pocket"),
|
||||||
|
slices: min.pocket
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,12 @@ class OpRough extends CamOp {
|
||||||
|
|
||||||
async slice(progress) {
|
async slice(progress) {
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { settings, slicer, addSlices, unsafe, color } = state;
|
let { settings, slicer, addSlices, unsafe, color, widget } = state;
|
||||||
let { updateToolDiams, thruHoles, tabs, cutTabs, cutPolys } = state;
|
let { updateToolDiams, thruHoles, tabs, cutTabs, cutPolys } = state;
|
||||||
let { ztOff, zMax, shadowAt, isIndexed} = state;
|
let { ztOff, zMax, shadowAt, isIndexed} = state;
|
||||||
let { workarea } = state;
|
let { workarea } = state;
|
||||||
let { process, stock } = settings;
|
let { controller, process, stock } = settings;
|
||||||
|
let center_off = widget.track.pos ?? { x: 0, y: 0, z: 0};
|
||||||
|
|
||||||
if (op.down <= 0) {
|
if (op.down <= 0) {
|
||||||
throw `invalid step down "${op.down}"`;
|
throw `invalid step down "${op.down}"`;
|
||||||
|
|
@ -36,6 +37,12 @@ class OpRough extends CamOp {
|
||||||
|
|
||||||
updateToolDiams(toolDiam);
|
updateToolDiams(toolDiam);
|
||||||
|
|
||||||
|
if (tabs) {
|
||||||
|
tabs.forEach(tab => {
|
||||||
|
tab.off = POLY.expand([tab.poly], toolDiam / 2).flat();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// clear the stock above the area to be roughed out
|
// clear the stock above the area to be roughed out
|
||||||
if (workarea.top_z > workarea.top_part && !cutThruBypass) {
|
if (workarea.top_z > workarea.top_part && !cutThruBypass) {
|
||||||
let shadow = state.shadow.base.clone();
|
let shadow = state.shadow.base.clone();
|
||||||
|
|
@ -58,9 +65,6 @@ class OpRough extends CamOp {
|
||||||
slice.z = z;
|
slice.z = z;
|
||||||
let polys = POLY.setZ(facing.clone(true), slice.z + roughLeaveZ);
|
let polys = POLY.setZ(facing.clone(true), slice.z + roughLeaveZ);
|
||||||
if (tabs) {
|
if (tabs) {
|
||||||
tabs.forEach(tab => {
|
|
||||||
tab.off = POLY.expand([tab.poly], toolDiam / 2).flat();
|
|
||||||
});
|
|
||||||
polys = cutTabs(tabs, polys, slice.z);
|
polys = cutTabs(tabs, polys, slice.z);
|
||||||
}
|
}
|
||||||
slice.camLines = polys;
|
slice.camLines = polys;
|
||||||
|
|
@ -206,20 +210,6 @@ class OpRough extends CamOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tabs) {
|
|
||||||
tabs.forEach(tab => {
|
|
||||||
tab.off = POLY.expand([tab.poly], toolDiam / 2).flat();
|
|
||||||
});
|
|
||||||
offset = cutTabs(tabs, offset, slice.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!offset) return;
|
|
||||||
|
|
||||||
if (process.camStockClipTo && stock.x && stock.y && stock.center) {
|
|
||||||
let rect = newPolygon().centerRectangle(stock.center, stock.x, stock.y);
|
|
||||||
offset = cutPolys([rect], offset, slice.z, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// elimate double inset on inners
|
// elimate double inset on inners
|
||||||
offset.forEach(op => {
|
offset.forEach(op => {
|
||||||
if (op.inner) {
|
if (op.inner) {
|
||||||
|
|
@ -236,24 +226,38 @@ class OpRough extends CamOp {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (process.camStockClipTo && stock.x && stock.y && stock.center) {
|
||||||
|
let { center } = stock;
|
||||||
|
let x = center.x - center_off.x;
|
||||||
|
let y = center.y - center_off.y;
|
||||||
|
let rect = newPolygon().centerRectangle({ x, y }, stock.x + 0.001, stock.y + 0.001);
|
||||||
|
offset = cutPolys([rect], offset, slice.z, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!offset) return;
|
||||||
|
|
||||||
slice.camLines = offset;
|
slice.camLines = offset;
|
||||||
if (roughLeaveZ) {
|
if (roughLeaveZ) {
|
||||||
// offset roughing in Z as well to minimize
|
// offset roughing in Z as well to minimize tool marks on curved surfaces
|
||||||
// tool marks on curved surfaces
|
|
||||||
// const roughLeaveZ = 1 * Math.min(roughDown, roughLeave / 2);
|
// const roughLeaveZ = 1 * Math.min(roughDown, roughLeave / 2);
|
||||||
slice.camLines.forEach(p => {
|
for (let poly of slice.camLines) {
|
||||||
p.setZ(p.getZ() + roughLeaveZ);
|
for (let point of poly.points) point.z += roughLeaveZ;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
if (controller.devel) {
|
||||||
|
if (tabs) slice.output()
|
||||||
|
.setLayer("tabs clip", {line: 0xaa00aa}, true)
|
||||||
|
.addPolys(tabs.map(tab => tab.off).flat());
|
||||||
|
slice.output()
|
||||||
|
.setLayer("slice", {line: 0xaaaa00}, true)
|
||||||
|
.addPolys(slice.topPolys())
|
||||||
|
// .setLayer("top shadow", {line: 0x0000aa})
|
||||||
|
// .addPolys(tshadow)
|
||||||
|
// .setLayer("rough shadow", {line: 0x00aa00})
|
||||||
|
// .addPolys(shadow)
|
||||||
|
.setLayer("shadow clip", {line: 0xaa0000})
|
||||||
|
.addPolys(shell);
|
||||||
}
|
}
|
||||||
if (false) slice.output()
|
|
||||||
.setLayer("slice", {line: 0xaaaa00}, true)
|
|
||||||
.addPolys(slice.topPolys())
|
|
||||||
// .setLayer("top shadow", {line: 0x0000aa})
|
|
||||||
// .addPolys(tshadow)
|
|
||||||
// .setLayer("rough shadow", {line: 0x00aa00})
|
|
||||||
// .addPolys(shadow)
|
|
||||||
.setLayer("rough shell", {line: 0xaa0000})
|
|
||||||
.addPolys(shell);
|
|
||||||
progress(0.5 + 0.5 * (index / slices.length));
|
progress(0.5 + 0.5 * (index / slices.length));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -278,6 +282,9 @@ class OpRough extends CamOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
slices.forEach(slice => {
|
slices.forEach(slice => {
|
||||||
|
if (slice.camLines && tabs) {
|
||||||
|
slice.camLines = cutTabs(tabs, slice.camLines);
|
||||||
|
}
|
||||||
slice.output()
|
slice.output()
|
||||||
.setLayer(state.layername, {face: color, line: color})
|
.setLayer(state.layername, {face: color, line: color})
|
||||||
.addPolys(slice.camLines);
|
.addPolys(slice.camLines);
|
||||||
|
|
@ -289,15 +296,13 @@ class OpRough extends CamOp {
|
||||||
|
|
||||||
prepare(ops, progress) {
|
prepare(ops, progress) {
|
||||||
let { op, state, sliceOut, camFaces } = this;
|
let { op, state, sliceOut, camFaces } = this;
|
||||||
let { setTool, setSpindle, setPrintPoint, sliceOutput, polyEmit } = ops;
|
let { setTool, setSpindle, setPrintPoint, pocket, polyEmit, newLayer, printPoint } = ops;
|
||||||
let { camOut, newLayer, printPoint } = ops;
|
|
||||||
let { settings } = state;
|
let { settings } = state;
|
||||||
let { process } = settings;
|
let { process } = settings;
|
||||||
|
|
||||||
let easeDown = process.camEaseDown;
|
let easeDown = process.camEaseDown;
|
||||||
let cutdir = op.ov_conv;
|
let cutdir = op.ov_conv;
|
||||||
let depthFirst = process.camDepthFirst && !state.isIndexed;
|
let depthFirst = process.camDepthFirst && !state.isIndexed;
|
||||||
let depthData = [];
|
|
||||||
|
|
||||||
setTool(op.tool, op.rate, op.plunge);
|
setTool(op.tool, op.rate, op.plunge);
|
||||||
setSpindle(op.spindle);
|
setSpindle(op.spindle);
|
||||||
|
|
@ -325,11 +330,12 @@ class OpRough extends CamOp {
|
||||||
|
|
||||||
// output the roughing passes
|
// output the roughing passes
|
||||||
setPrintPoint(printPoint);
|
setPrintPoint(printPoint);
|
||||||
sliceOutput(sliceOut, {
|
pocket({
|
||||||
cutdir,
|
cutdir,
|
||||||
depthFirst,
|
depthFirst,
|
||||||
easeDown: op.down && easeDown ? 0.001 : 0,
|
easeDown: op.down && easeDown ? 0.001 : 0,
|
||||||
progress: (n,m) => progress(n/m, "routing")
|
progress: (n,m) => progress(n/m, "routing"),
|
||||||
|
slices: sliceOut
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,6 @@ class OpTrace extends CamOp {
|
||||||
|
|
||||||
prepare(ops, progress) {
|
prepare(ops, progress) {
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { settings } = state;
|
|
||||||
let { setTool, setSpindle } = ops;
|
let { setTool, setSpindle } = ops;
|
||||||
|
|
||||||
setTool(op.tool, op.rate);
|
setTool(op.tool, op.rate);
|
||||||
|
|
|
||||||
|
|
@ -337,8 +337,10 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
// 1. move to safe z of current point preserving angle
|
// 1. move to safe z of current point preserving angle
|
||||||
// 2. move to safe z of new point preserving old angle
|
// 2. move to safe z of new point preserving old angle
|
||||||
// 3. move to safe z of new point with new angle
|
// 3. move to safe z of new point with new angle
|
||||||
if (lop !== currentOp && lastPoint) {
|
if (lop && lop !== currentOp && lastPoint) {
|
||||||
camOut(lastPoint.clone().setZ(zsafe).setA(lastPoint.a), 0);
|
// compensate for applyWidgetMovement() applied to lastPoint
|
||||||
|
let lpo = lastPoint.clone().move({ x: -wmx, y: -wmy, z: -zadd });
|
||||||
|
camOut(lpo.clone().setZ(zsafe).setA(lastPoint.a), 0);
|
||||||
camOut(point.clone().setZ(zsafe).setA(lastPoint.a), 0);
|
camOut(point.clone().setZ(zsafe).setA(lastPoint.a), 0);
|
||||||
camOut(point.clone().setZ(zsafe), 0);
|
camOut(point.clone().setZ(zsafe), 0);
|
||||||
}
|
}
|
||||||
|
|
@ -552,16 +554,15 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
* output an array of slices that form a pocket
|
* output an array of slices that form a pocket
|
||||||
* used by rough and pocket ops, does not support arcs
|
* used by rough and pocket ops, does not support arcs
|
||||||
*
|
*
|
||||||
* @param {Slice[]} top-down Z stack of slices
|
* @param {Slice[]} slices top-down Z stack of slices
|
||||||
* @param {*} opts
|
* @param {boolean} cutdir true=CW false=CCW
|
||||||
|
* @param {boolean} depthFirst prioritize cut depth in pockets by nesting
|
||||||
*/
|
*/
|
||||||
function sliceOutput(sliceOut, opts = {}) {
|
function pocket({ slices, cutdir, depthFirst, easeDown, progress }) {
|
||||||
const { cutdir, depthFirst, easeDown, progress } = opts;
|
|
||||||
|
|
||||||
let total = 0;
|
let total = 0;
|
||||||
let depthData = [];
|
let depthData = [];
|
||||||
|
|
||||||
for (let slice of sliceOut) {
|
for (let slice of slices) {
|
||||||
let polys = [], t = [], c = [];
|
let polys = [], t = [], c = [];
|
||||||
POLY.flatten(slice.camLines).forEach(function (poly) {
|
POLY.flatten(slice.camLines).forEach(function (poly) {
|
||||||
let child = poly.parent;
|
let child = poly.parent;
|
||||||
|
|
@ -588,7 +589,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
}, { swapdir: false });
|
}, { swapdir: false });
|
||||||
newLayer();
|
newLayer();
|
||||||
}
|
}
|
||||||
progress(++total, sliceOut.length);
|
progress(++total, slices.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// crucially returns true for -0 as well as other negative #s
|
// crucially returns true for -0 as well as other negative #s
|
||||||
|
|
@ -682,45 +683,32 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
// make top start offset configurable
|
// make top start offset configurable
|
||||||
printPoint = firstPoint || origin;
|
printPoint = firstPoint || origin;
|
||||||
|
|
||||||
// accumulated data for depth-first optimizations
|
|
||||||
// let depthData = {
|
|
||||||
// rough: [],
|
|
||||||
// outline: [],
|
|
||||||
// roughDiam: 0,
|
|
||||||
// outlineDiam: 0,
|
|
||||||
// contourx: [],
|
|
||||||
// contoury: [],
|
|
||||||
// trace: [],
|
|
||||||
// drill: [],
|
|
||||||
// layer: 0,
|
|
||||||
// };
|
|
||||||
|
|
||||||
let ops = {
|
let ops = {
|
||||||
stock,
|
|
||||||
setTool,
|
|
||||||
setDrill,
|
|
||||||
setSpindle,
|
|
||||||
setTolerance,
|
|
||||||
setPrintPoint,
|
|
||||||
setLasering,
|
|
||||||
getPrintPoint() { return printPoint },
|
|
||||||
printPoint,
|
|
||||||
newLayer,
|
|
||||||
addGCode,
|
addGCode,
|
||||||
|
bounds,
|
||||||
camOut,
|
camOut,
|
||||||
polyEmit,
|
|
||||||
poly2polyEmit,
|
|
||||||
tip2tipEmit,
|
|
||||||
depthRoughPath,
|
|
||||||
depthOutlinePath,
|
depthOutlinePath,
|
||||||
sliceOutput,
|
depthRoughPath,
|
||||||
emitDrills,
|
emitDrills,
|
||||||
emitTrace,
|
emitTrace,
|
||||||
bounds,
|
getPrintPoint() { return printPoint },
|
||||||
|
lastPoint: () => { return lastPoint },
|
||||||
|
newLayer,
|
||||||
|
pocket,
|
||||||
|
poly2polyEmit,
|
||||||
|
polyEmit,
|
||||||
|
printPoint,
|
||||||
|
setDrill,
|
||||||
|
setLasering,
|
||||||
|
setPrintPoint,
|
||||||
|
setSpindle,
|
||||||
|
setTolerance,
|
||||||
|
setTool,
|
||||||
|
stock,
|
||||||
|
tip2tipEmit,
|
||||||
zclear,
|
zclear,
|
||||||
zmax,
|
zmax,
|
||||||
zsafe,
|
zsafe,
|
||||||
lastPoint: () => { return lastPoint }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let opSum = 0;
|
let opSum = 0;
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,10 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
ondone(msg);
|
ondone(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function alert(msg) {
|
||||||
|
onupdate(null,null,msg);
|
||||||
|
}
|
||||||
|
|
||||||
if (unsafe) {
|
if (unsafe) {
|
||||||
console.log("disabling overhang safeties");
|
console.log("disabling overhang safeties");
|
||||||
}
|
}
|
||||||
|
|
@ -135,20 +139,20 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
let maxDelta = 1e-3;
|
let maxDelta = 1e-3;
|
||||||
|
|
||||||
if (stock.x + maxDelta < (bounds.max.x - bounds.min.x)) {
|
if (stock.x + maxDelta < (bounds.max.x - bounds.min.x)) {
|
||||||
return error('stock X too small for part. resize stock or use offset stock');
|
alert('stock X too small for part');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stock.y + maxDelta < (bounds.max.y - bounds.min.y)) {
|
if (stock.y + maxDelta < (bounds.max.y - bounds.min.y)) {
|
||||||
return error('stock Y too small for part. resize stock or use offset stock');
|
alert('stock Y too small for part');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stock.z + maxDelta < (bounds.max.z - bounds.min.z)) {
|
if (stock.z + maxDelta < (bounds.max.z - bounds.min.z)) {
|
||||||
return error('stock Z too small for part. resize stock or use offset stock');
|
alert('stock Z too small for part');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zMin >= bounds.max.z) {
|
if (zMin >= bounds.max.z) {
|
||||||
return error(`invalid z bottom ${(zMin / units).round(3)} >= bounds z max ${(zMax / units).round(3)}`);
|
alert(`invalid z bottom ${(zMin / units).round(3)} >= bounds z max ${(zMax / units).round(3)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mark = Date.now();
|
let mark = Date.now();
|
||||||
|
|
@ -158,31 +162,31 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
let shadows = {};
|
let shadows = {};
|
||||||
let slicer;
|
let slicer;
|
||||||
let state = {
|
let state = {
|
||||||
settings,
|
addSlices,
|
||||||
widget,
|
|
||||||
bounds,
|
bounds,
|
||||||
tabs,
|
color,
|
||||||
cutTabs,
|
computeShadows,
|
||||||
cutPolys,
|
|
||||||
contourPolys,
|
contourPolys,
|
||||||
|
cutPolys,
|
||||||
|
cutTabs,
|
||||||
|
dark,
|
||||||
healPolys,
|
healPolys,
|
||||||
|
isIndexed,
|
||||||
|
ops: opList,
|
||||||
|
setAxisIndex,
|
||||||
|
settings,
|
||||||
shadowAt,
|
shadowAt,
|
||||||
slicer,
|
slicer,
|
||||||
addSlices,
|
tabs,
|
||||||
isIndexed,
|
unsafe,
|
||||||
setAxisIndex,
|
|
||||||
updateToolDiams,
|
|
||||||
updateSlicer,
|
updateSlicer,
|
||||||
computeShadows,
|
updateToolDiams,
|
||||||
|
widget,
|
||||||
zBottom,
|
zBottom,
|
||||||
|
zMax,
|
||||||
zThru,
|
zThru,
|
||||||
ztOff,
|
ztOff,
|
||||||
zMax,
|
zTop
|
||||||
zTop,
|
|
||||||
unsafe,
|
|
||||||
color,
|
|
||||||
dark,
|
|
||||||
ops: opList
|
|
||||||
};
|
};
|
||||||
let tracker = setSliceTracker({ rotation: 0 });
|
let tracker = setSliceTracker({ rotation: 0 });
|
||||||
|
|
||||||
|
|
@ -801,7 +805,7 @@ function cutTabs(tabs, offset) {
|
||||||
|
|
||||||
function cutPolys(polys, offset) {
|
function cutPolys(polys, offset) {
|
||||||
let noff = [];
|
let noff = [];
|
||||||
offset.forEach(op => noff.appendAll(op.cut(POLY.union(polys, 0, true))));
|
offset.forEach(op => noff.appendAll( op.cut(POLY.union(polys, 0, true), true) ));
|
||||||
return healPolys(noff);
|
return healPolys(noff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ export class Topo {
|
||||||
newslices.push(debug);
|
newslices.push(debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (webGPU) {
|
if (webGPU && !contour.nogpu) {
|
||||||
// invert tool Z offset for gpu code
|
// invert tool Z offset for gpu code
|
||||||
let toolBounds = new THREE.Box3()
|
let toolBounds = new THREE.Box3()
|
||||||
.expandByPoint({ x: -toolDiameter/2, y: -toolDiameter/2, z: 0 })
|
.expandByPoint({ x: -toolDiameter/2, y: -toolDiameter/2, z: 0 })
|
||||||
|
|
@ -137,8 +137,9 @@ export class Topo {
|
||||||
// console.timeEnd('swap XY vertices');
|
// console.timeEnd('swap XY vertices');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let trace = contour.trace;
|
||||||
let gpu = await self.get_raster_gpu({
|
let gpu = await self.get_raster_gpu({
|
||||||
mode: "planar",
|
mode: trace ? "tracing" : "planar",
|
||||||
resolution
|
resolution
|
||||||
});
|
});
|
||||||
let xStep = density;
|
let xStep = density;
|
||||||
|
|
|
||||||
|
|
@ -291,8 +291,9 @@ export function fdm_export(print, online, ondone, ondebug) {
|
||||||
append(`; Bed type: ${bedType}`);
|
append(`; Bed type: ${bedType}`);
|
||||||
append(`; Target: ${filter[mode]}`);
|
append(`; Target: ${filter[mode]}`);
|
||||||
// inject thumbnail preview
|
// inject thumbnail preview
|
||||||
if (exportThumb && worker.snap) {
|
let { current } = self.kiri_worker ?? {};
|
||||||
let { width, height, url } = worker.snap;
|
if (exportThumb && current?.snap) {
|
||||||
|
let { width, height, url } = current.snap;
|
||||||
let data = url.substring(url.indexOf(',') + 1);
|
let data = url.substring(url.indexOf(',') + 1);
|
||||||
append(`; thumbnail begin ${width} ${height} ${data.length}`);
|
append(`; thumbnail begin ${width} ${height} ${data.length}`);
|
||||||
for (let i=0; i<data.length; i += 78) {
|
for (let i=0; i<data.length; i += 78) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
const terms = {
|
const terms = {
|
||||||
COPYRIGHT: "Copyright (C) Stewart Allen <sa@grid.space> - All Rights Reserved",
|
COPYRIGHT: "Copyright (C) Stewart Allen <sa@grid.space> - All Rights Reserved",
|
||||||
LICENSE: "See the license.md file included with the source distribution",
|
LICENSE: "See the license.md file included with the source distribution",
|
||||||
VERSION: "4.4.0"
|
VERSION: "4.5.0"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const beta = 0;
|
export const beta = 0;
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ async function _fetch(e) {
|
||||||
|
|
||||||
if (url.pathname.endsWith("/")) {
|
if (url.pathname.endsWith("/")) {
|
||||||
return e.respondWith(redirectOr404(appendURL(url, 'index.html').pathname));
|
return e.respondWith(redirectOr404(appendURL(url, 'index.html').pathname));
|
||||||
} else if (url.pathname.indexOf(".") < 0) {
|
} else if (url.pathname.indexOf(".") < 0 || url.pathname.endsWith("/boot")) {
|
||||||
return e.respondWith(redirectOr404(appendURL(url, '/index.html').pathname));
|
return e.respondWith(redirectOr404(appendURL(url, '/index.html').pathname));
|
||||||
} else {
|
} else {
|
||||||
e.respondWith(fromCacheOrNetwork(request));
|
e.respondWith(fromCacheOrNetwork(request));
|
||||||
|
|
|
||||||
|
|
@ -318,6 +318,8 @@ self.lang['da-dk'] = {
|
||||||
op_unit_l: ["arbejdsområde enheder påvirker","hastigheder og distancer"],
|
op_unit_l: ["arbejdsområde enheder påvirker","hastigheder og distancer"],
|
||||||
op_anim_s: "animer",
|
op_anim_s: "animer",
|
||||||
op_anim_l: ["animation mesh tæthed","højere er mere tæt","tager mere hukommelse","og er langsommere"],
|
op_anim_l: ["animation mesh tæthed","højere er mere tæt","tager mere hukommelse","og er langsommere"],
|
||||||
|
op_mani_s: "mangfoldig",
|
||||||
|
op_mani_l: ["i indekseret materiale tilstand","brug boolesk visualisering","dette er meget dyrt","og sandsynligvis meget langsom"],
|
||||||
op_exgl_l: ["vis Grid:Local enheder i eksport dialog","inkluderer Grid:Bots og OctoPrint plugins"],
|
op_exgl_l: ["vis Grid:Local enheder i eksport dialog","inkluderer Grid:Bots og OctoPrint plugins"],
|
||||||
op_exgh_l: ["legacy Grid:Host lokalt netværk support"],
|
op_exgh_l: ["legacy Grid:Host lokalt netværk support"],
|
||||||
op_exop_l: ["legacy OctoPrint lokalt netværk support","Grid:Space OctoPrint plugin anbefalet"],
|
op_exop_l: ["legacy OctoPrint lokalt netværk support","Grid:Space OctoPrint plugin anbefalet"],
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,8 @@ self.lang['de-de'] = {
|
||||||
op_unit_l: ["Arbeitsbereich-Einheiten beeinflussen","Geschwindigkeiten und Distanzen"],
|
op_unit_l: ["Arbeitsbereich-Einheiten beeinflussen","Geschwindigkeiten und Distanzen"],
|
||||||
op_anim_s: "Animieren",
|
op_anim_s: "Animieren",
|
||||||
op_anim_l: ["Animations-Mesh-Dichte","höher ist dichter","benötigt mehr Speicher","und ist langsamer"],
|
op_anim_l: ["Animations-Mesh-Dichte","höher ist dichter","benötigt mehr Speicher","und ist langsamer"],
|
||||||
|
op_mani_s: "mannigfaltig",
|
||||||
|
op_mani_l: ["im indizierten Materialvorrat-Modus","boolesche Visualisierung verwenden","dies ist sehr rechenintensiv","und wahrscheinlich sehr langsam"],
|
||||||
op_exgl_l: ["Grid:Local Geräte im Export-Dialog anzeigen","inkludiert Grid:Bots und OctoPrint Plugins"],
|
op_exgl_l: ["Grid:Local Geräte im Export-Dialog anzeigen","inkludiert Grid:Bots und OctoPrint Plugins"],
|
||||||
op_exgh_l: ["Legacy Grid:Host lokale Netzwerkunterstützung"],
|
op_exgh_l: ["Legacy Grid:Host lokale Netzwerkunterstützung"],
|
||||||
op_exop_l: ["Legacy OctoPrint lokale Netzwerkunterstützung","Grid:Space OctoPrint Plugin empfohlen"],
|
op_exop_l: ["Legacy OctoPrint lokale Netzwerkunterstützung","Grid:Space OctoPrint Plugin empfohlen"],
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,8 @@ self.lang['en-us'] = {
|
||||||
op_unit_l: ["workspace units affects","speeds and distances"],
|
op_unit_l: ["workspace units affects","speeds and distances"],
|
||||||
op_anim_s: "animate",
|
op_anim_s: "animate",
|
||||||
op_anim_l: ["animation mesh density","higher is more dense","takes more memory","and is slower"],
|
op_anim_l: ["animation mesh density","higher is more dense","takes more memory","and is slower"],
|
||||||
|
op_mani_s: "manifold",
|
||||||
|
op_mani_l: ["in stock indexed mode","use boolean visualiation","this is very expensive","and likely very slow"],
|
||||||
op_exgl_l: ["show Grid:Local devices in export dialog","includes Grid:Bots and OctoPrint plugins"],
|
op_exgl_l: ["show Grid:Local devices in export dialog","includes Grid:Bots and OctoPrint plugins"],
|
||||||
op_exgh_l: ["legacy Grid:Host local network support"],
|
op_exgh_l: ["legacy Grid:Host local network support"],
|
||||||
op_exop_l: ["legacy OctoPrint local network support","Grid:Space OctoPrint plugin recommended"],
|
op_exop_l: ["legacy OctoPrint local network support","Grid:Space OctoPrint plugin recommended"],
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,8 @@ self.lang['es-es'] = {
|
||||||
op_unit_l: ["las unidades del espacio de trabajo afectan","velocidades y distancias"],
|
op_unit_l: ["las unidades del espacio de trabajo afectan","velocidades y distancias"],
|
||||||
op_anim_s: "animar",
|
op_anim_s: "animar",
|
||||||
op_anim_l: ["densidad de malla de animación","mayor es más denso","requiere más memoria","y es más lento"],
|
op_anim_l: ["densidad de malla de animación","mayor es más denso","requiere más memoria","y es más lento"],
|
||||||
|
op_mani_s: "variedad",
|
||||||
|
op_mani_l: ["en modo de material indexado","usar visualización booleana","esto es muy costoso","y probablemente muy lento"],
|
||||||
op_exgl_l: ["mostrar dispositivos Grid:Local en diálogo de exportación","incluye Grid:Bots y plugins de OctoPrint"],
|
op_exgl_l: ["mostrar dispositivos Grid:Local en diálogo de exportación","incluye Grid:Bots y plugins de OctoPrint"],
|
||||||
op_exgh_l: ["soporte heredado de red local Grid:Host"],
|
op_exgh_l: ["soporte heredado de red local Grid:Host"],
|
||||||
op_exop_l: ["soporte heredado de red local OctoPrint","se recomienda el plugin Grid:Space OctoPrint"],
|
op_exop_l: ["soporte heredado de red local OctoPrint","se recomienda el plugin Grid:Space OctoPrint"],
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,8 @@ self.lang['fr-fr'] = {
|
||||||
op_unit_l: ["les unités de l'espace de travail affectent","les vitesses et distances"],
|
op_unit_l: ["les unités de l'espace de travail affectent","les vitesses et distances"],
|
||||||
op_anim_s: "animer",
|
op_anim_s: "animer",
|
||||||
op_anim_l: ["densité du maillage d'animation","plus élevé est plus dense","nécessite plus de mémoire","et est plus lent"],
|
op_anim_l: ["densité du maillage d'animation","plus élevé est plus dense","nécessite plus de mémoire","et est plus lent"],
|
||||||
|
op_mani_s: "variété",
|
||||||
|
op_mani_l: ["en mode matériau indexé","utiliser la visualisation booléenne","ceci est très coûteux","et probablement très lent"],
|
||||||
op_exgl_l: ["afficher les appareils Grid:Local dans le dialogue d'export","inclut les plugins Grid:Bots et OctoPrint"],
|
op_exgl_l: ["afficher les appareils Grid:Local dans le dialogue d'export","inclut les plugins Grid:Bots et OctoPrint"],
|
||||||
op_exgh_l: ["support réseau local Grid:Host legacy"],
|
op_exgh_l: ["support réseau local Grid:Host legacy"],
|
||||||
op_exop_l: ["support réseau local OctoPrint legacy","plugin Grid:Space OctoPrint recommandé"],
|
op_exop_l: ["support réseau local OctoPrint legacy","plugin Grid:Space OctoPrint recommandé"],
|
||||||
|
|
|
||||||
|
|
@ -318,6 +318,8 @@ self.lang['pl-pl'] = {
|
||||||
op_unit_l: ["jednostki przestrzeni roboczej wpływają","na prędkości i odległości"],
|
op_unit_l: ["jednostki przestrzeni roboczej wpływają","na prędkości i odległości"],
|
||||||
op_anim_s: "animuj",
|
op_anim_s: "animuj",
|
||||||
op_anim_l: ["gęstość siatki animacji","wyższa jest bardziej gęsta","zajmuje więcej pamięci","i jest wolniejsza"],
|
op_anim_l: ["gęstość siatki animacji","wyższa jest bardziej gęsta","zajmuje więcej pamięci","i jest wolniejsza"],
|
||||||
|
op_mani_s: "rozmaitość",
|
||||||
|
op_mani_l: ["w trybie indeksowanego materiału","użyj wizualizacji boolowskiej","to jest bardzo kosztowne","i prawdopodobnie bardzo wolne"],
|
||||||
op_exgl_l: ["pokaż urządzenia Grid:Local w oknie dialogowym eksportu","zawiera Grid:Bots i wtyczki OctoPrint"],
|
op_exgl_l: ["pokaż urządzenia Grid:Local w oknie dialogowym eksportu","zawiera Grid:Bots i wtyczki OctoPrint"],
|
||||||
op_exgh_l: ["starsze wsparcie sieci lokalnej Grid:Host"],
|
op_exgh_l: ["starsze wsparcie sieci lokalnej Grid:Host"],
|
||||||
op_exop_l: ["starsze wsparcie sieci lokalnej OctoPrint","zalecana wtyczka Grid:Space OctoPrint"],
|
op_exop_l: ["starsze wsparcie sieci lokalnej OctoPrint","zalecana wtyczka Grid:Space OctoPrint"],
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,8 @@ self.lang['pt-pt'] = {
|
||||||
op_unit_l: ["unidades de espaço de trabalho afecta","velocidades e distâncias"],
|
op_unit_l: ["unidades de espaço de trabalho afecta","velocidades e distâncias"],
|
||||||
op_anim_s: "animar",
|
op_anim_s: "animar",
|
||||||
op_anim_l: ["densidade da malha de animação","mais alto é mais denso","usa mais memória","e é mais lento"],
|
op_anim_l: ["densidade da malha de animação","mais alto é mais denso","usa mais memória","e é mais lento"],
|
||||||
|
op_mani_s: "variedade",
|
||||||
|
op_mani_l: ["no modo de material indexado","usar visualização booleana","isso é muito caro","e provavelmente muito lento"],
|
||||||
op_exgl_l: ["mostrar dispositivos Grid:Local no diálogo de exportação","inclui Grid:Bots e plugins OctoPrint"],
|
op_exgl_l: ["mostrar dispositivos Grid:Local no diálogo de exportação","inclui Grid:Bots e plugins OctoPrint"],
|
||||||
op_exgh_l: ["suporte de rede local Grid:Host legado"],
|
op_exgh_l: ["suporte de rede local Grid:Host legado"],
|
||||||
op_exop_l: ["suporte de rede local OctoPrint legado","plugin Grid:Space OctoPrint recomendado"],
|
op_exop_l: ["suporte de rede local OctoPrint legado","plugin Grid:Space OctoPrint recomendado"],
|
||||||
|
|
|
||||||
|
|
@ -318,6 +318,8 @@ self.lang['zh'] = {
|
||||||
op_unit_l: ["工作区单位影响","速度和距离"],
|
op_unit_l: ["工作区单位影响","速度和距离"],
|
||||||
op_anim_s: "动画",
|
op_anim_s: "动画",
|
||||||
op_anim_l: ["动画网格密度","更高则更密集","占用更多内存","速度更慢"],
|
op_anim_l: ["动画网格密度","更高则更密集","占用更多内存","速度更慢"],
|
||||||
|
op_mani_s: "流形",
|
||||||
|
op_mani_l: ["在索引材料模式下","使用布尔可视化","这非常昂贵","而且可能非常慢"],
|
||||||
op_exgl_l: ["在导出对话框中显示Grid:Local设备","包括Grid:Bots和OctoPrint插件"],
|
op_exgl_l: ["在导出对话框中显示Grid:Local设备","包括Grid:Bots和OctoPrint插件"],
|
||||||
op_exgh_l: ["传统Grid:Host本地网络支持"],
|
op_exgh_l: ["传统Grid:Host本地网络支持"],
|
||||||
op_exop_l: ["传统OctoPrint本地网络支持","推荐使用Grid:Space OctoPrint插件"],
|
op_exop_l: ["传统OctoPrint本地网络支持","推荐使用Grid:Space OctoPrint插件"],
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Kiri:Moto 4.4.0",
|
"name": "Kiri:Moto 4.5.0",
|
||||||
"short_name": "Kiri:Moto",
|
"short_name": "Kiri:Moto",
|
||||||
"description": "Slicer for 3D printers, CNC mills, laser cutters and more",
|
"description": "Slicer for 3D printers, CNC mills, laser cutters and more",
|
||||||
"start_url": "/boot/",
|
"start_url": "/boot/index.html",
|
||||||
"id": "/kiri/",
|
"id": "/kiri/",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"theme_color": "#7e99b7",
|
"theme_color": "#7e99b7",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue