Merge branch 'rel-4.3' into helical-op
This commit is contained in:
commit
45ba762d1e
60 changed files with 1116 additions and 639 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -5,10 +5,11 @@ app.json
|
|||
build
|
||||
data
|
||||
dist
|
||||
jszip-esm.js
|
||||
logs
|
||||
mod
|
||||
node_modules
|
||||
package-lock.json
|
||||
three.js
|
||||
tmp
|
||||
pack
|
||||
pack
|
||||
|
|
|
|||
153
app.js
153
app.js
|
|
@ -36,6 +36,7 @@ let http;
|
|||
let util;
|
||||
let dir;
|
||||
let log;
|
||||
let pre;
|
||||
|
||||
const EventEmitter = require('events');
|
||||
class AppEmitter extends EventEmitter {}
|
||||
|
|
@ -46,9 +47,13 @@ netdb.create = async function(map = {}) {
|
|||
Object.assign(map, JSON.parse(fs.readFileSync(map.conf)));
|
||||
}
|
||||
const client = new netdb();
|
||||
if (map.host && map.port) await client.open(map.host, map.port);
|
||||
if (map.user && map.pass) await client.auth(map.user, map.pass);
|
||||
if (map.base) await client.use(map.base);
|
||||
try {
|
||||
if (map.host && map.port) await client.open(map.host, map.port);
|
||||
if (map.user && map.pass) await client.auth(map.user, map.pass);
|
||||
if (map.base) await client.use(map.base);
|
||||
} catch (e) {
|
||||
logger.log({ netdb_setup_error: e });
|
||||
}
|
||||
logger.log({ netdb: map.host, user: map.user, base: map.base });
|
||||
return client;
|
||||
};
|
||||
|
|
@ -59,6 +64,7 @@ function init(mod) {
|
|||
startTime = time();
|
||||
lastmod = mod.util.lastmod;
|
||||
logger = mod.log;
|
||||
pre = ENV.pre || mod.meta.pre;
|
||||
debug = ENV.debug || mod.meta.debug;
|
||||
oversion = ENV.over || mod.meta.over;
|
||||
crossOrigin = ENV.xorigin || mod.meta.xorigin || false;
|
||||
|
|
@ -72,17 +78,24 @@ function init(mod) {
|
|||
dversion = debug ? `_${version}` : version;
|
||||
forceUseCache = ENV.cache ? true : false;
|
||||
|
||||
const approot = PATH.join("main","gapp");
|
||||
const refcache = {};
|
||||
const callstack = [];
|
||||
let xxxx = false;
|
||||
|
||||
if (!ENV.electron) {
|
||||
generateDevices();
|
||||
}
|
||||
|
||||
if (pre) {
|
||||
for (let [k,v] of Object.entries(productionMap)) {
|
||||
productionMap[`${pre}${k}`] = `${pre}${v}`;
|
||||
}
|
||||
}
|
||||
|
||||
mod.on.test((req) => {
|
||||
let cookie = cookieValue(req.headers.cookie, "version") || undefined;
|
||||
if (req.app?.path?.startsWith(pre)) {
|
||||
req.url = req.url.substring(pre.length);
|
||||
req.app.path = req.app.path.substring(pre.length);
|
||||
req.app.ispre = true;
|
||||
return true;
|
||||
}
|
||||
let cookie = cookieValue(req.headers.cookie, "version") || '';
|
||||
let vmatch = mod.meta.version || "*";
|
||||
if (!Array.isArray(vmatch)) {
|
||||
vmatch = [ vmatch ];
|
||||
|
|
@ -93,17 +106,28 @@ function init(mod) {
|
|||
return vmatch.indexOf(cookie) >= 0;
|
||||
});
|
||||
|
||||
mod.on.testv((version) => {
|
||||
let vmatch = mod.meta.version || "*";
|
||||
if (!Array.isArray(vmatch)) {
|
||||
vmatch = [ vmatch ];
|
||||
}
|
||||
if (vmatch.indexOf("*") >= 0) {
|
||||
return true;
|
||||
}
|
||||
return vmatch.indexOf(version) >= 0;
|
||||
});
|
||||
|
||||
mod.add(handleSetup);
|
||||
mod.add(handleOptions);
|
||||
mod.add(serveWasm);
|
||||
mod.add(serveCode);
|
||||
mod.add(fullpath({
|
||||
"/kiri" : redir("/kiri/", 301),
|
||||
"/mesh" : redir("/mesh/", 301),
|
||||
"/meta" : redir("/meta/", 301),
|
||||
"/kiri/index.html" : redir("/kiri/", 301),
|
||||
"/mesh/index.html" : redir("/mesh/", 301),
|
||||
"/meta/index.html" : redir("/meta/", 301)
|
||||
"/kiri" : redir((pre??"") + "/kiri/", 301),
|
||||
"/mesh" : redir((pre??"") + "/mesh/", 301),
|
||||
"/meta" : redir((pre??"") + "/meta/", 301),
|
||||
"/kiri/index.html" : redir((pre??"") + "/kiri/", 301),
|
||||
"/mesh/index.html" : redir((pre??"") + "/mesh/", 301),
|
||||
"/meta/index.html" : redir((pre??"") + "/meta/", 301)
|
||||
}));
|
||||
mod.add(handleVersion);
|
||||
mod.add(fixedmap("/api/", api));
|
||||
|
|
@ -116,8 +140,6 @@ function init(mod) {
|
|||
});
|
||||
}
|
||||
mod.add(rewriteHtmlVersion);
|
||||
// example of how to use the new middleware
|
||||
// mod.add(appendContent('/kiri/index.html', '<script>console.log("hello")</script>'));
|
||||
mod.static("/lib/", "src");
|
||||
mod.static("/obj/", "web/obj");
|
||||
mod.static("/font/", "web/font");
|
||||
|
|
@ -126,8 +148,8 @@ function init(mod) {
|
|||
mod.static("/moto/", "web/moto");
|
||||
mod.static("/kiri/", "web/kiri");
|
||||
|
||||
// module loader
|
||||
function load_modules(root, force) {
|
||||
// load modules
|
||||
lastmod(`${dir}/${root}`) && fs.readdirSync(`${dir}/${root}`).forEach(mdir => {
|
||||
const modpath = `${root}/${mdir}`;
|
||||
if (dir.charAt(0) === '.' && !ENV.single) return;
|
||||
|
|
@ -152,7 +174,7 @@ function init(mod) {
|
|||
// load optional local modules
|
||||
load_modules('mods');
|
||||
|
||||
// run loads injected by modules
|
||||
// run load functions injected by modules
|
||||
while (load.length) {
|
||||
try {
|
||||
load.shift()();
|
||||
|
|
@ -161,7 +183,7 @@ function init(mod) {
|
|||
}
|
||||
}
|
||||
|
||||
// minify appends
|
||||
// minify appends in production mode
|
||||
if (!debug) {
|
||||
for (let key of Object.keys(append)) {
|
||||
append[key] = minify(append[key]);
|
||||
|
|
@ -177,6 +199,9 @@ function loadModule(mod, dir) {
|
|||
if (lastmod(`${mod.dir}/${dir}/.ignore`)) {
|
||||
return;
|
||||
}
|
||||
// either load the module, or if it's not a module
|
||||
// directory, serve the module as static content
|
||||
// bound to the root
|
||||
lastmod(`${mod.dir}/${dir}/init.js`) ?
|
||||
initModule(mod, `./${dir}/init.js`, dir) :
|
||||
mod.static("/", `${mod.dir}/${dir}`);
|
||||
|
|
@ -189,14 +214,14 @@ function initModule(mod, file, dir) {
|
|||
// express functions added here show up at "/api/" url root
|
||||
api: api,
|
||||
adm: {
|
||||
setver: (ver) => { oversion = ver },
|
||||
crossOrigin: (bool) => { crossOrigin = bool }
|
||||
setver(ver) { oversion = ver },
|
||||
crossOrigin(bool) { crossOrigin = bool }
|
||||
},
|
||||
events,
|
||||
const: {
|
||||
args: {},
|
||||
meta: mod.meta,
|
||||
debug: debug,
|
||||
debug,
|
||||
moddir: dir,
|
||||
rootdir: mod.dir,
|
||||
version: oversion || version
|
||||
|
|
@ -209,35 +234,21 @@ function initModule(mod, file, dir) {
|
|||
},
|
||||
mod: mods,
|
||||
util: {
|
||||
guid,
|
||||
time,
|
||||
log: logger.log,
|
||||
time: time,
|
||||
guid: guid,
|
||||
logger: log.new,
|
||||
mkdirs: util.mkdir,
|
||||
isfile: util.isfile,
|
||||
confdir: util.confdir,
|
||||
datadir: util.datadir,
|
||||
lastmod: lastmod,
|
||||
obj2string: obj2string,
|
||||
string2obj: string2obj,
|
||||
isfile: util.isfile,
|
||||
getCookieValue: cookieValue,
|
||||
logger: log.new
|
||||
},
|
||||
inject: (code, file, opt = {}) => {
|
||||
const path = mod.dir + '/' + dir + '/' + file;
|
||||
try {
|
||||
const body = fs.readFileSync(path);
|
||||
// console.log({ inject: code, file, opt });
|
||||
if (opt.first) {
|
||||
append[code] = body.toString() + '\n' + append[code];
|
||||
} else {
|
||||
append[code] += body.toString() + '\n';
|
||||
}
|
||||
} catch (e) {
|
||||
console.log({ missing_file: path, dir, mod });
|
||||
}
|
||||
obj2string(o) { return JSON.stringify(o) },
|
||||
string2obj(s) { return JSON.parse(s) },
|
||||
},
|
||||
path: {
|
||||
any: arg => { mod.add(arg) },
|
||||
any(arg) { mod.add(arg) },
|
||||
code() {
|
||||
const [ path, file ] = [ ...arguments ];
|
||||
if (lastmod(file)) {
|
||||
|
|
@ -251,13 +262,13 @@ function initModule(mod, file, dir) {
|
|||
console.log({ MISSING_CODE: path, file });
|
||||
}
|
||||
},
|
||||
full: arg => { mod.add(fullpath(arg)) },
|
||||
map: arg => { mod.add(fixedmap(arg)) },
|
||||
pre: arg => { mod.add(prepath(arg)) },
|
||||
full(arg) { mod.add(fullpath(arg)) },
|
||||
map(arg) { mod.add(fixedmap(arg)) },
|
||||
pre(arg) { mod.add(prepath(arg)) },
|
||||
redir: redir,
|
||||
remap: remap,
|
||||
setup: fn => { setupFn = fn },
|
||||
static: (root, pre) => {
|
||||
setup(fn) { setupFn = fn },
|
||||
static(root, pre) {
|
||||
mod.static(pre || "/", root);
|
||||
},
|
||||
},
|
||||
|
|
@ -271,22 +282,29 @@ function initModule(mod, file, dir) {
|
|||
ws: {
|
||||
register: mod.wss
|
||||
},
|
||||
onload: (fn) => {
|
||||
inject(code, file, opt = {}) {
|
||||
const path = mod.dir + '/' + dir + '/' + file;
|
||||
try {
|
||||
const body = fs.readFileSync(path);
|
||||
// console.log({ inject: code, file, opt });
|
||||
if (opt.first) {
|
||||
append[code] = body.toString() + '\n' + append[code];
|
||||
} else {
|
||||
append[code] += body.toString() + '\n';
|
||||
}
|
||||
} catch (e) {
|
||||
console.log({ missing_file: path, dir, mod });
|
||||
}
|
||||
},
|
||||
onload(fn) {
|
||||
load.push(fn);
|
||||
},
|
||||
onexit: (fn) => {
|
||||
onexit(fn) {
|
||||
mod.on.exit(fn);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// prevent caching of specified modules
|
||||
const cachever = {};
|
||||
|
||||
function promise(resolve, reject) {
|
||||
return new Promise(resolve, reject);
|
||||
}
|
||||
|
||||
function rval() {
|
||||
return (Math.round(Math.random()*0xffffffff)).toString(36);
|
||||
}
|
||||
|
|
@ -299,14 +317,6 @@ function time() {
|
|||
return Date.now();
|
||||
}
|
||||
|
||||
function obj2string(o) {
|
||||
return JSON.stringify(o);
|
||||
}
|
||||
|
||||
function string2obj(s) {
|
||||
return JSON.parse(s);
|
||||
}
|
||||
|
||||
function handleSetup(req, res, next) {
|
||||
if (setupFn) {
|
||||
setupFn(req, res, next);
|
||||
|
|
@ -322,12 +332,16 @@ const productionMap = {
|
|||
'/lib/kiri/run/engine.js' : '/lib/pack/kiri-eng.js',
|
||||
'/lib/kiri/run/minion.js' : '/lib/pack/kiri-pool.js',
|
||||
'/lib/kiri/run/worker.js' : '/lib/pack/kiri-work.js',
|
||||
// '/lib/kiri/run/frame.js' : '/lib/pack/kiri-frame.js',
|
||||
};
|
||||
|
||||
const redirList = [
|
||||
"/kiri/",
|
||||
"/mesh/"
|
||||
];
|
||||
|
||||
function handleVersion(req, res, next) {
|
||||
let vstr = oversion || dversion || version;
|
||||
if (["/kiri/","/mesh/"].indexOf(req.app.path) >= 0 && req.url.indexOf(vstr) < 0) {
|
||||
if (!req.app.ispre && redirList.indexOf(req.app.path) === 0 && req.url.indexOf(vstr) < 0) {
|
||||
if (req.url.indexOf("?") > 0) {
|
||||
return http.redirect(res, `${req.url},ver:${vstr}`);
|
||||
} else {
|
||||
|
|
@ -550,7 +564,8 @@ function rewriteHtmlVersion(req, res, next) {
|
|||
"/lib/main/mesh.js"
|
||||
].indexOf(req.app.path) >= 0) {
|
||||
addCorsHeaders(req, res);
|
||||
const data = append[req.app.path.split('/')[3].split('.')[0]];
|
||||
// const data = append[req.app.path.split('/')[3].split('.')[0]];
|
||||
const data = append[req.app.path.split('.')[0].split('/').pop()];
|
||||
|
||||
if (!data) return next();
|
||||
if (debug) logger.log({ append: req.app.path, data: data.length });
|
||||
|
|
|
|||
7
bin/webpack-jszip-bundle.js
Normal file
7
bin/webpack-jszip-bundle.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import * as JSZip from "../node_modules/jszip/dist/jszip.js";
|
||||
|
||||
export default JSZip;
|
||||
|
||||
export {
|
||||
JSZip
|
||||
};
|
||||
38
bin/webpack-jszip-esm.js
Normal file
38
bin/webpack-jszip-esm.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: path.resolve(__dirname, './webpack-jszip-bundle.js'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../src/ext'),
|
||||
filename: 'jszip-esm.js',
|
||||
library: {
|
||||
type: 'module'
|
||||
},
|
||||
module: true
|
||||
},
|
||||
experiments: {
|
||||
outputModule: true
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.mjs', '.js'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.m?js$/,
|
||||
resolve: {
|
||||
fullySpecified: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
minimize: false
|
||||
},
|
||||
performance: {
|
||||
hints: false,
|
||||
maxAssetSize: 2 * 1024 * 1024,
|
||||
maxEntrypointSize: 2 * 1024 * 1024,
|
||||
},
|
||||
};
|
||||
27
notes.md
27
notes.md
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
## `C` cosmetic, `F` functional, `P` performance, `B` bug fix
|
||||
|
||||
* `F` experiment with structuredClone(), SharedArrayBuffer, createImageBitmap()
|
||||
* `F` test #private fields, array.at() for negative indices
|
||||
* `F` option to hide platform when viewing from below
|
||||
|
||||
# Kiri:Moto
|
||||
|
|
@ -14,7 +12,6 @@
|
|||
|
||||
* `P` refactor vertex replacement and widget update matrix tracking
|
||||
* `P` duplicate objects should share same slice data unless rotated or scaled
|
||||
* `P` allow selection to be decimated on demand (context menu?)
|
||||
* `P` move all persisted / workspace settings/data to IndexedDB (LS limitations)
|
||||
* `P` faster ray intersect https://github.com/gkjohnson/three-mesh-bvh/
|
||||
* `P` try material clipping planes for slice range selection
|
||||
|
|
@ -26,7 +23,7 @@
|
|||
* `F` complete and expose grouping feature
|
||||
* `F` add svgnest-like arrange algorithm
|
||||
* `F` date column and sorting in recent files list
|
||||
* `F` warn if part hanging in negative Z space or off bed in general
|
||||
* `F` highlight part outside workspace bounds (like can neg Z shader)
|
||||
|
||||
# FDM
|
||||
|
||||
|
|
@ -34,6 +31,7 @@
|
|||
* `B` multi-extruder rendering of raft fails to offset the rest of the print
|
||||
* `B` multi-extruder purge blocks fail to generate properly for rafts
|
||||
|
||||
* `F` better thin-wall (like arachne)
|
||||
* `F` add scarf seams
|
||||
* `F` add 'random' and 'seam' start point options
|
||||
* `F` convert ranges to z offsets while continuing to show layer #
|
||||
|
|
@ -52,12 +50,6 @@
|
|||
* `P` extruder + filament max flow rate cap in planner
|
||||
* `P` solid fill the tops of supports for down facing flats
|
||||
|
||||
# FDM - SLA
|
||||
|
||||
# `P` common support area detection (fork new fdm code)
|
||||
* `P` prioritize supports by length of unsupported span. mandatory when circularity > X
|
||||
* or % area of inner to outer poly is high (making it a thin shell)
|
||||
|
||||
# FDM - BELT
|
||||
|
||||
* `B` auto bed resizing leaves the origin in the wrong place at first
|
||||
|
|
@ -69,7 +61,6 @@
|
|||
|
||||
# CAM
|
||||
|
||||
* `B` roughing leave stock should also increase Z slightly (sqrt(2) * leave)
|
||||
* `B` rapid moves should be max of terrain zmax and last cut layer height (roughing)
|
||||
* `B` feed rate for next tool set before tool change (push/pop feed rates?)
|
||||
* `B` tab cuts cause loss of direction, parenting, depth, and it's hard to fix
|
||||
|
|
@ -84,18 +75,14 @@
|
|||
* `F` add `match faces` option in `outline` operation
|
||||
* `F` add {progress} substitution and maybe {time-remaining} if can be calc'd
|
||||
* `F` import and follow 2D paths (conformed like pocket contours)
|
||||
* `F` add user-defined origin (issue #28)
|
||||
* `F` intelligently turn circle hole pocket clear into spiral down
|
||||
* `F` add `plunge max` to contouring that can override z feed limit
|
||||
* `F` add lead-in milling (requires adding clamp / no go areas)
|
||||
* `F` add linear clearing strategy
|
||||
* `F` add adaptive clearing strategy
|
||||
* `F` add ease-down support to trace op
|
||||
* `F` add support for tapered ball mills
|
||||
* `F` change color of line selection in trace op when not a closed poly
|
||||
* `F` limit cut depth to flute length of selected tool (or warn)
|
||||
* `F` validate muti-part layout and spacing exceeds largest outside tool diameter
|
||||
* `F` parameterize dropping close points in prep.js. ensure long segments remain straight
|
||||
* `F` trapezoidal tabs in Z
|
||||
* `F` ease-in and ease-out especially on tab cut-out start/stop
|
||||
* `F` maintain several part orientations + op chains in a single profile
|
||||
|
|
@ -104,14 +91,8 @@
|
|||
* `P` outer corner arc moves
|
||||
* `P` log Z interpolation for contour XYZ moves
|
||||
* `P` option to start with the smallest poly by area on layer change
|
||||
* `P` refactor slicing engine to add minion threading
|
||||
* `P` port arc code from FDM export to CAM export
|
||||
* `P` redo all path route / planning in prepare to account for terrain before camOut
|
||||
|
||||
# SLA
|
||||
|
||||
* `P` blit layers w/ 3JS ortho camera to canvas
|
||||
|
||||
# Laser
|
||||
|
||||
* `F` add PLT / HP-GL output format (https://en.wikipedia.org/wiki/HP-GL)
|
||||
|
|
@ -124,8 +105,9 @@
|
|||
|
||||
# Mesh:Tool
|
||||
|
||||
* font to path with https://github.com/paulzi/svg-text-to-path
|
||||
* add undo/redo
|
||||
* add TextGeometry
|
||||
* font to path with https://github.com/paulzi/svg-text-to-path
|
||||
* click to repair normals based on a known good (selected) face
|
||||
* send to Kiri:Moto workspace (or update model vertices in place)
|
||||
* better z snap using just vertexes from face intersected
|
||||
|
|
@ -134,6 +116,5 @@
|
|||
* add flatten/crush op: for z bottoms (or surfaces?)
|
||||
* allow setting model/group origin for scale/rotate
|
||||
* fix mirror to work with groups (just models currently)
|
||||
* bounding box toggle should be global, not selection
|
||||
* add analyze results dialog
|
||||
* remove/hide auto-repair function
|
||||
|
|
|
|||
19
package.json
19
package.json
|
|
@ -36,7 +36,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.1.1",
|
||||
"@gridspace/app-server": "^0.0.17",
|
||||
"@gridspace/app-server": "^0.0.18",
|
||||
"@gridspace/basic-ftp": "^5.0.5",
|
||||
"@gridspace/net-level-client": "^0.2.3",
|
||||
"@tracespace/parser": "^5.0.0-next.0",
|
||||
|
|
@ -49,9 +49,11 @@
|
|||
"earcut": "^3.0.1",
|
||||
"express-useragent": "^1.0.13",
|
||||
"fast-glob": "^3.3.3",
|
||||
"i": "^0.3.7",
|
||||
"jszip": "^3.7.1",
|
||||
"manifold-3d": "^3.1.1",
|
||||
"moment": "^2.29.4",
|
||||
"npm": "^11.4.2",
|
||||
"prettier": "^3.5.3",
|
||||
"react-responsive-carousel": "^3.2.23",
|
||||
"serve-static": "^1.14.1",
|
||||
|
|
@ -79,7 +81,7 @@
|
|||
"webpack-cli": "^5.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"setup": "npm i && npm run clean && npm run dev -- --dryrun && npm run webpack3",
|
||||
"setup": "npm i && npm run clean && npm run dev -- --dryrun && npm run webpack-ext",
|
||||
"build": "npm run prebuild && electron-builder",
|
||||
"build-nopublish": "npm run prebuild && electron-builder --publish never",
|
||||
"build-debug": "npm run prebuild && DEBUG=electron-builder electron-builder",
|
||||
|
|
@ -94,8 +96,9 @@
|
|||
"docs-build": "docusaurus build --config conf/docusaurus.config.js",
|
||||
"docs-serve": "docusaurus serve --config conf/docusaurus.config.js",
|
||||
"docs-check": "prettier --config ./conf/prettier.config.js ./docs --check",
|
||||
"dev": "npm run webpack3 && gs-app-server --debug --single",
|
||||
"prod": "npm run webpack prod && gs-app-server",
|
||||
"dev": "npm run webpack-ext && gs-app-server --debug --single",
|
||||
"prod": "npm run webpack-ext && npm run webpack-src prod && gs-app-server",
|
||||
"prod-pack": "npm run webpack-ext && npm run webpack-src prod",
|
||||
"prod-dryrun": "gs-app-server --dryrun",
|
||||
"start": "npm run prebuild prod && electron .",
|
||||
"start-dev": "npm run prebuild prod && electron . --devel",
|
||||
|
|
@ -103,11 +106,13 @@
|
|||
"start-ddb": "npm run prebuild && electron . --devel --debugg",
|
||||
"mk-links": "find src web -type l | xargs -I{} sh -c 'echo \"{},$(readlink {})\"' > conf/links.csv",
|
||||
"mac-verify": "spctl --assess -vv --type install dist/*/*.app",
|
||||
"prebuild": "npm run setup && npm run webpack prod && node bin/electron-pre.js",
|
||||
"prebuild": "npm run setup && npm run webpack-src prod && node bin/electron-pre.js",
|
||||
"postbuild": "node bin/electron-post.js",
|
||||
"preinstall": "node bin/install-pre.js",
|
||||
"webpack": "npm run webpack3 && node bin/esbuild.config.mjs",
|
||||
"webpack3": "npx webpack --config bin/webpack-three-esm.js"
|
||||
"webpack-ext": "npm run webpack-three && npm run webpack-zip",
|
||||
"webpack-src": "node bin/esbuild.config.mjs",
|
||||
"webpack-three": "npx webpack --config bin/webpack-three-esm.js",
|
||||
"webpack-zip": "npx webpack --config bin/webpack-jszip-esm.js"
|
||||
},
|
||||
"main": "app-el.js",
|
||||
"build": {
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
//import original library
|
||||
import * as JSZip from "./jszip.js";
|
||||
|
||||
//export object attached to the window object
|
||||
export default self.JSZip;
|
||||
|
|
@ -117,7 +117,7 @@ function indexVertices(pos) {
|
|||
|
||||
let Instance;
|
||||
manifold({
|
||||
locateFile() { return "/wasm/manifold.wasm" }
|
||||
locateFile() { return "../wasm/manifold.wasm" }
|
||||
}).then(inst => {
|
||||
inst.setup();
|
||||
Instance = inst;
|
||||
|
|
|
|||
|
|
@ -843,6 +843,7 @@ export class Polygon {
|
|||
* scale polygon around origin
|
||||
*/
|
||||
scale(scale, round) {
|
||||
this.area2 = undefined;
|
||||
let x, y, z;
|
||||
if (typeof(scale) === 'number') {
|
||||
x = y = z = scale;
|
||||
|
|
@ -1073,6 +1074,7 @@ export class Polygon {
|
|||
* append point to polygon and return point
|
||||
*/
|
||||
push(p) {
|
||||
this.area2 = undefined;
|
||||
// clone any point belonging to another polygon
|
||||
if (p.poly) p = p.clone();
|
||||
p.poly = this;
|
||||
|
|
@ -1117,6 +1119,14 @@ export class Polygon {
|
|||
return this.first().isEqual(this.last());
|
||||
}
|
||||
|
||||
fixClosed() {
|
||||
if (this.appearsClosed()) {
|
||||
this.points.pop();
|
||||
this.open = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
setClockwise() {
|
||||
if (!this.isClockwise()) this.reverse();
|
||||
return this;
|
||||
|
|
@ -1552,7 +1562,12 @@ export class Polygon {
|
|||
* @returns {number} 0.0 - 1.0 from flat to perfectly circular
|
||||
*/
|
||||
circularity() {
|
||||
return (4 * Math.PI * this.area()) / util.sqr(this.perimeter());
|
||||
try {
|
||||
return (4 * Math.PI * this.area()) / util.sqr(this.perimeter());
|
||||
} catch (e) {
|
||||
console.log(this.perimeter(), e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
circularityDeep() {
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ export function subtract(setA, setB, outA, outB, z, minArea, opt = {}) {
|
|||
|
||||
function filter(from, to = []) {
|
||||
from.forEach(function(poly) {
|
||||
if (poly.area() >= min) {
|
||||
if (poly.area() >= min && poly.length > 2) {
|
||||
to.push(poly);
|
||||
out.push(poly);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { base } from '../geo/base.js';
|
||||
import { newPolygon } from './polygon.js';
|
||||
|
||||
const { config } = base;
|
||||
|
||||
const factor = config.clipper;
|
||||
|
||||
export const wasm_ctrl = {
|
||||
|
|
@ -54,7 +54,7 @@ function writePoly(view, poly, inner) {
|
|||
function readPoly(view, z) {
|
||||
let points = view.readU16(true);
|
||||
if (points === 0) return;
|
||||
let poly = base.newPolygon();
|
||||
let poly = newPolygon();
|
||||
while (points-- > 0) {
|
||||
poly.add(view.readI32(true)/factor, view.readI32(true)/factor, z || 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import STACKS from './stacks.js';
|
|||
|
||||
import { broker } from '../../moto/broker.js';
|
||||
import { client as work } from './client.js';
|
||||
import { consts, COLOR as color, LISTS as lists, MODES, VIEWS, PATHS } from './consts.js';
|
||||
import { consts, COLOR as color, LISTS as lists } from './consts.js';
|
||||
import { device, devices } from './devices.js';
|
||||
import { catalog, dialog, event, group, help, hide, image } from './main.js';
|
||||
import { modal, mode, probe, process, show, space, util, view } from './main.js';
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ const boxes = [];
|
|||
|
||||
let lastBox;
|
||||
|
||||
export function clearboxes() {
|
||||
boxes.length = 0;
|
||||
}
|
||||
|
||||
export function getlastbox() {
|
||||
return lastBox;
|
||||
}
|
||||
|
|
@ -19,7 +23,7 @@ export function delbox(name) {
|
|||
export function addbox(point, color, name, dim = {x:1,y:1,z:1,rz:0}, opt = {}) {
|
||||
delbox(name);
|
||||
|
||||
const box = boxes[name] = new Mesh(
|
||||
const box = new Mesh(
|
||||
new BoxGeometry(dim.x, dim.y, dim.z),
|
||||
new MeshPhongMaterial({
|
||||
transparent: true,
|
||||
|
|
@ -28,6 +32,10 @@ export function addbox(point, color, name, dim = {x:1,y:1,z:1,rz:0}, opt = {}) {
|
|||
})
|
||||
);
|
||||
|
||||
if (name) {
|
||||
boxes[name] = box;
|
||||
}
|
||||
|
||||
box.position.x = point.x;
|
||||
box.position.y = point.y;
|
||||
box.position.z = point.z;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
import { api } from './api.js';
|
||||
import { noop } from './utils.js';
|
||||
import { codec } from './codec.js';
|
||||
import { Widget } from './widget.js';
|
||||
import { newPrint } from './print.js';
|
||||
|
||||
// this code runs in kiri's main loop
|
||||
let debug = self.debug === true,
|
||||
|
|
@ -199,7 +202,7 @@ export const client = {
|
|||
send("rotate", { settings }, reply => {
|
||||
if (reply.group) {
|
||||
// collect post-rotation data for slice/preview renders
|
||||
for (let widget of kiri.Widget.Groups.forid(reply.group)) {
|
||||
for (let widget of Widget.Groups.forid(reply.group)) {
|
||||
widget.belt = reply.belt;
|
||||
}
|
||||
} else if (callback) {
|
||||
|
|
@ -280,10 +283,10 @@ export const client = {
|
|||
y: -origin.y,
|
||||
z: origin.z
|
||||
};
|
||||
const output = kiri.newPrint().parseSVG(code, offset);
|
||||
const output = newPrint().parseSVG(code, offset);
|
||||
send("parse_svg", output, reply => {
|
||||
if (reply.parsed) {
|
||||
done(kiri.codec.decode(reply.parsed));
|
||||
done(codec.decode(reply.parsed));
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
|
@ -293,7 +296,7 @@ export const client = {
|
|||
progress(reply.progress);
|
||||
}
|
||||
if (reply.parsed) {
|
||||
done(kiri.codec.decode(reply.parsed), reply.maxSpeed, reply.minSpeed);
|
||||
done(codec.decode(reply.parsed), reply.maxSpeed, reply.minSpeed);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -581,7 +581,8 @@ export const conf = {
|
|||
outputInvertY: false,
|
||||
camExpertFast: false,
|
||||
camTrueShadow: false,
|
||||
camArcTolerance: 0.006,
|
||||
camArcEnabled: false,
|
||||
camArcTolerance: 0.15,
|
||||
camArcResolution: 5,
|
||||
camForceZMax: false,
|
||||
camFirstZMax: false,
|
||||
|
|
|
|||
|
|
@ -147,8 +147,8 @@ const PMODES = {
|
|||
};
|
||||
|
||||
const PATHS = {
|
||||
work: "/lib/kiri/run/worker.js",
|
||||
pool: "/lib/kiri/run/minion.js"
|
||||
work: "../lib/kiri/run/worker.js",
|
||||
pool: "./minion.js"
|
||||
};
|
||||
|
||||
const SEED = 'kiri-seed';
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ function prepareSlices(callback, scale = 1, offset = 0) {
|
|||
if (msg && msg !== lastMsg) {
|
||||
let mark = Date.now();
|
||||
if (lastMsg) {
|
||||
let key = widgets.length > 1 ?
|
||||
let key = slicing.length > 1 ?
|
||||
`${widget.id}_${segNumber++}_${lastMsg}` :
|
||||
`${segNumber++}_${lastMsg}`
|
||||
segtimes[key] = mark - startTime;
|
||||
|
|
@ -158,7 +158,10 @@ function prepareSlices(callback, scale = 1, offset = 0) {
|
|||
if (sliced) {
|
||||
// update segment time
|
||||
if (lastMsg) {
|
||||
segtimes[`${widget.id}_${segNumber++}_${lastMsg}`] = mark - startTime;
|
||||
let key = slicing.length > 1 ?
|
||||
`${widget.id}_${segNumber++}_${lastMsg}` :
|
||||
`${segNumber++}_${lastMsg}`
|
||||
segtimes[`${key}`] = mark - startTime;
|
||||
}
|
||||
event.emit('slice', settings.mode);
|
||||
}
|
||||
|
|
@ -237,7 +240,10 @@ function prepareSlices(callback, scale = 1, offset = 0) {
|
|||
};
|
||||
for (let widget of slicing) {
|
||||
// on done
|
||||
segtimes[`${widget.id}_${segNumber++}_draw`] = widget.render(widget.stack);
|
||||
let key = slicing.length > 1 ?
|
||||
`${widget.id}_${segNumber++}_draw` :
|
||||
`${segNumber++}_draw`
|
||||
segtimes[`${key}`] = widget.render(widget.stack);
|
||||
// rotate stack for belt beds
|
||||
if (widget.belt) {
|
||||
widget.stack.obj.rotate(widget.belt);
|
||||
|
|
@ -452,8 +458,7 @@ function cancelWorker() {
|
|||
}
|
||||
|
||||
function parseCode(code, type) {
|
||||
const { conf, event, show, widgets, view } = api;
|
||||
const { stacks } = kiri;
|
||||
const { conf, event, show, stacks, widgets, view } = api;
|
||||
const settings = conf.get();
|
||||
|
||||
event.emit("code.load", {code, type});
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ import { init as initLaser } from '../mode/laser/client.js';
|
|||
import { init as initSLA } from '../mode/sla/client.js';
|
||||
import { init as initWEDM } from '../mode/wedm/client.js';
|
||||
import { init as initWJET } from '../mode/wjet/client.js';
|
||||
import { menu as menuCAM } from '../mode/cam/init-menu.js';
|
||||
import { menu as menuFDM } from '../mode/fdm/init-menu.js';
|
||||
import { menu as menuLaser } from '../mode/laser/init-menu.js';
|
||||
import { menu as menuSLA } from '../mode/sla/init-menu.js';
|
||||
|
||||
let { CAM, SLA, FDM, LASER, DRAG, WJET, WEDM } = MODES,
|
||||
{ client, catalog, platform, selection, stats } = api,
|
||||
|
|
@ -90,15 +94,6 @@ function lineTypeSave() {
|
|||
}
|
||||
}
|
||||
|
||||
function thinWallSave() {
|
||||
let opt = ui.sliceDetectThin;
|
||||
let level = opt.options[opt.selectedIndex];
|
||||
if (level) {
|
||||
settings().process.sliceDetectThin = level.value;
|
||||
api.conf.save();
|
||||
}
|
||||
}
|
||||
|
||||
function detailSave() {
|
||||
let level = ui.detail.options[ui.detail.selectedIndex];
|
||||
if (level) {
|
||||
|
|
@ -123,11 +118,6 @@ function speedSave() {
|
|||
api.view.update_speeds();
|
||||
}
|
||||
|
||||
function zAnchorSave() {
|
||||
api.conf.update();
|
||||
api.platform.update_top_z();
|
||||
}
|
||||
|
||||
function setThreaded(bool) {
|
||||
if (bool) {
|
||||
client.pool.start();
|
||||
|
|
@ -234,6 +224,8 @@ function onBooleanClick(el) {
|
|||
api.devices.update_laser_state();
|
||||
}
|
||||
|
||||
api.event.on('click.boolean', onBooleanClick);
|
||||
|
||||
function onButtonClick(ev) {
|
||||
let target = ev.target;
|
||||
while (target && target.tagName !== 'BUTTON') {
|
||||
|
|
@ -242,6 +234,8 @@ function onButtonClick(ev) {
|
|||
api.event.emit("button.click", target);
|
||||
}
|
||||
|
||||
api.event.on('click.button', onButtonClick);
|
||||
|
||||
function inputHasFocus() {
|
||||
let active = DOC.activeElement;
|
||||
return active && (active.nodeName === "INPUT" || active.nodeName === "TEXTAREA");
|
||||
|
|
@ -769,11 +763,6 @@ function updateCatalog(files) {
|
|||
}
|
||||
}
|
||||
|
||||
function isMultiHead() {
|
||||
let dev = api.conf.get().device;
|
||||
return isNotBelt() && dev.extruders && dev.extruders.length > 1;
|
||||
}
|
||||
|
||||
function isBelt() {
|
||||
return api.device.isBelt();
|
||||
}
|
||||
|
|
@ -845,7 +834,6 @@ function init_one() {
|
|||
|
||||
// api augmentation with local functions
|
||||
api.device.export = deviceExport;
|
||||
let anim = ui.anim = {};
|
||||
|
||||
Object.assign(ui, {
|
||||
tracker: tracker,
|
||||
|
|
@ -982,33 +970,6 @@ function init_one() {
|
|||
stockDepth: $('stock-width'),
|
||||
stockHeight: $('stock-width'),
|
||||
|
||||
/** CAM Animation Bar */
|
||||
|
||||
_____: {
|
||||
_____: newDiv({ addto: $('layer-animate'), set:true }),
|
||||
row: newRow([
|
||||
anim.replay = newButton(null,"anim.replay",{icon:'<i class="fas fa-fast-backward"></i>',title:"restart"}),
|
||||
anim.play = newButton(null,"anim.play",{icon:'<i class="fas fa-play"></i>',title:"play"}),
|
||||
anim.pause = newButton(null,"anim.pause",{icon:'<i class="fas fa-pause"></i>',title:"pause"}),
|
||||
anim.step = newButton(null,"anim.step",{icon:'<i class="fas fa-step-forward"></i>',title:"single step"}),
|
||||
anim.speed = newButton(null,"anim.fast",{icon:'<i class="fas fa-forward"></i>',title:"toggle speed"}),
|
||||
anim.labspd = newValue(3, {class:"center padleft"}),
|
||||
anim.labx = newLabel("X", {class:"padleft"}),
|
||||
anim.valx = newValue(7, {class:"center"}),
|
||||
anim.laby = newLabel("Y", {class:"padleft"}),
|
||||
anim.valy = newValue(7, {class:"center"}),
|
||||
anim.labz = newLabel("Z", {class:"padleft"}),
|
||||
anim.valz = newValue(6, {class:"center"}),
|
||||
anim.laba = newLabel("A", {class:"padleft hide"}),
|
||||
anim.vala = newValue(6, {class:"center hide"}),
|
||||
anim.labpro = newLabel("%", {class:"padleft"}),
|
||||
anim.progress = newValue(5, {class:"center"}),
|
||||
anim.trans = newButton(null,"anim.trans",{icon:'<i class="fa-solid fa-border-none"></i>',title:"transparency",class:"padleft"}),
|
||||
anim.model = newButton(null,"anim.model",{icon:'<i class="fa-solid fa-eye"></i>',title:"show model"}),
|
||||
anim.shade = newButton(null,"anim.stock",{icon:'<i class="fa-solid fa-cube"></i>',title:"stock box"}),
|
||||
])
|
||||
},
|
||||
|
||||
/** Device Browser / Editor */
|
||||
|
||||
_____: newDiv({ class: "f-col t-body t-inset", addto: $('dev-config'), set:true }),
|
||||
|
|
@ -1110,255 +1071,16 @@ function init_one() {
|
|||
prefadd: uc.checkpoint($('prefs-add')),
|
||||
|
||||
/** FDM Settings */
|
||||
|
||||
_____: newGroup(LANG.sl_menu, $('fdm-layers'), { modes:FDM, driven, hideable, separator, group:"fdm-layers" }),
|
||||
sliceHeight: newInput(LANG.sl_lahi_s, { title:LANG.sl_lahi_l, convert:toFloat }),
|
||||
sliceMinHeight: newInput(LANG.ad_minl_s, { title:LANG.ad_minl_l, convert:toFloat, bound:bound(0,3.0), show:() => ui.sliceAdaptive.checked }),
|
||||
sliceTopLayers: newInput(LANG.sl_ltop_s, { title:LANG.sl_ltop_l, convert:toInt }),
|
||||
sliceBottomLayers: newInput(LANG.sl_lbot_s, { title:LANG.sl_lbot_l, convert:toInt }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceAdaptive: newBoolean(LANG.ad_adap_s, onBooleanClick, { title: LANG.ad_adap_l }),
|
||||
_____: newGroup(LANG.sw_menu, $('fdm-walls'), { modes:FDM, driven, hideable, separator, group:"fdm-walls" }),
|
||||
sliceShells: newInput(LANG.sl_shel_s, { title:LANG.sl_shel_l, convert:toFloat }),
|
||||
sliceLineWidth: newInput(LANG.sl_line_s, { title:LANG.sl_line_l, convert:toFloat, bound:bound(0,5) }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceShellOrder: newSelect(LANG.sl_ordr_s, { title:LANG.sl_ordr_l}, "shell"),
|
||||
sliceDetectThin: newSelect(LANG.ad_thin_s, { title: LANG.ad_thin_l, action: thinWallSave }, "thin"),
|
||||
outputAlternating: newBoolean(LANG.ad_altr_s, onBooleanClick, {title:LANG.ad_altr_l}),
|
||||
sliceZInterleave: newBoolean(LANG.ad_zint_s, onBooleanClick, {title:LANG.ad_zint_l, show:zIntShow}),
|
||||
_____: newGroup(LANG.fi_menu, $('fdm-fill'), { modes:FDM, driven, hideable, separator, group:"fdm-fill" }),
|
||||
sliceFillType: newSelect(LANG.fi_type, {trigger}, "infill"),
|
||||
sliceFillSparse: newInput(LANG.fi_pcnt_s, {title:LANG.fi_pcnt_l, convert:toFloat, bound:bound(0.0,1.0), show:hasInfill}),
|
||||
sliceFillRepeat: newInput(LANG.fi_rept_s, {title:LANG.fi_rept_l, convert:toInt, bound:bound(1,10), show:fillIsLinear}),
|
||||
sliceFillOverlap: newInput(LANG.fi_over_s, {title:LANG.fi_over_l, convert:toFloat, bound:bound(0.0,2.0), show:hasInfill}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceFillRate: newInput(LANG.ou_feed_s, {title:LANG.ou_feed_l, convert:toInt, bound:bound(0,500)}),
|
||||
sliceSolidRate: newInput(LANG.ou_fini_s, {title:LANG.ou_fini_l, convert:toInt, bound:bound(0,500)}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceFillGrow: newInput(LANG.fi_grow_s, {title:LANG.fi_grow_l, convert:toFloat}),
|
||||
sliceFillAngle: newInput(LANG.fi_angl_s, {title:LANG.fi_angl_l, convert:toFloat}),
|
||||
_____: newGroup(LANG.fh_menu, $('fdm-heat'), { modes:FDM, driven, hideable, separator, group:"fdm-heat" }),
|
||||
outputTemp: newInput(LANG.ou_nozl_s, {title:LANG.ou_nozl_l, convert:toInt}),
|
||||
outputBedTemp: newInput(LANG.ou_bedd_s, {title:LANG.ou_bedd_l, convert:toInt}),
|
||||
_____: newGroup(LANG.fc_menu, $('fdm-cool'), { modes:FDM, driven, hideable, separator, group:"fdm-cool" }),
|
||||
outputFanLayer: newInput(LANG.ou_fanl_s, { title:LANG.ou_fanl_l, convert:toInt, bound:bound(0,255) }),
|
||||
outputFanSpeed: newInput(LANG.ou_fans_s, {title:LANG.ou_fans_l, convert:toInt, bound:bound(0,255)}),
|
||||
_____: newGroup(LANG.sp_menu, $('fdm-support'), { modes:FDM, driven, hideable, separator, group:"fdm-supp" }),
|
||||
sliceSupportNozzle: newSelect(LANG.sp_nozl_s, {title:LANG.sp_nozl_l, show:isMultiHead}, "extruders"),
|
||||
sliceSupportDensity: newInput(LANG.sp_dens_s, {title:LANG.sp_dens_l, convert:toFloat, bound:bound(0.0,1.0)}),
|
||||
sliceSupportSize: newInput(LANG.sp_size_s, {title:LANG.sp_size_l, convert:toFloat, bound:bound(1.0,200.0)}),
|
||||
sliceSupportOffset: newInput(LANG.sp_offs_s, {title:LANG.sp_offs_l, convert:toFloat, bound:bound(0.0,200.0)}),
|
||||
sliceSupportGap: newInput(LANG.sp_gaps_s, {title:LANG.sp_gaps_l, convert:toInt, bound:bound(0,5)}),
|
||||
sliceSupportArea: newInput(LANG.sp_area_s, {title:LANG.sp_area_l, convert:toFloat, bound:bound(0.0,200.0)}),
|
||||
sliceSupportExtra: newInput(LANG.sp_xpnd_s, {title:LANG.sp_xpnd_l, convert:toFloat, bound:bound(0.0,10.0)}),
|
||||
sliceSupportGrow: newInput(LANG.sp_grow_s, {title:LANG.sp_grow_l, convert:toFloat, bound:bound(0.0,10.0)}),
|
||||
sliceSupportAngle: newInput(LANG.sp_angl_s, {title:LANG.sp_angl_l, convert:toFloat, bound:bound(0.0,90.0)}),
|
||||
sliceSupportSpan: newInput(LANG.sp_span_s, {title:LANG.sp_span_l, convert:toFloat, bound:bound(0.0,200.0), show:() => ui.sliceSupportEnable.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceSupportEnable: newBoolean(LANG.sp_auto_s, onBooleanClick, {title:LANG.sp_auto_l, show:isNotBelt}),
|
||||
sliceSupportOutline: newBoolean(LANG.sp_outl_s, onBooleanClick, {title:LANG.sp_outl_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceSupportGen: newRow([
|
||||
ui.ssaGen = newButton(LANG.sp_detect, onButtonClick, {class: "f-col grow a-center"})
|
||||
], { modes: FDM, class: "ext-buttons f-row grow" }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceSupportManual: newRow([
|
||||
(ui.ssmAdd = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})),
|
||||
(ui.ssmDun = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})),
|
||||
(ui.ssmClr = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-trash-alt"></i>'}))
|
||||
], {class:"ext-buttons f-row"}),
|
||||
_____: newGroup(LANG.fl_menu, $('fdm-base'), { modes:FDM, driven, hideable, separator, group:"fdm-base" }),
|
||||
firstSliceHeight: newInput(LANG.fl_lahi_s, {title:LANG.fl_lahi_l, convert:toFloat, show:isNotBelt}),
|
||||
firstLayerNozzleTemp:newInput(LANG.fl_nozl_s, {title:LANG.fl_nozl_l, convert:toInt, show:isNotBelt}),
|
||||
firstLayerBedTemp: newInput(LANG.fl_bedd_s, {title:LANG.fl_bedd_l, convert:toInt, show:isNotBelt}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
firstLayerFanSpeed: newInput(LANG.ou_fans_s, {title:LANG.ou_fans_l, convert:toInt, bound:bound(0,255), show:isBelt}),
|
||||
firstLayerYOffset: newInput(LANG.fl_zoff_s, {title:LANG.fl_zoff_l, convert:toFloat, show:isBelt}),
|
||||
firstLayerFlatten: newInput(LANG.fl_flat_s, {title:LANG.fl_flat_l, convert:toFloat, show:isBelt}),
|
||||
firstLayerRate: newInput(LANG.fl_rate_s, {title:LANG.fl_rate_l, convert:toFloat}),
|
||||
firstLayerFillRate: newInput(LANG.fl_frat_s, {title:LANG.fl_frat_l, convert:toFloat, show:isNotBelt}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isNotBelt }),
|
||||
firstLayerLineMult: newInput(LANG.fl_sfac_s, {title:LANG.fl_sfac_l, convert:toFloat, bound:bound(0.5,2), show:isNotBelt}),
|
||||
firstLayerPrintMult: newInput(LANG.fl_mult_s, {title:LANG.fl_mult_l, convert:toFloat}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isBelt }),
|
||||
firstLayerBrim: newInput(LANG.fl_brim_s, {title:LANG.fl_brim_l, convert:toInt, show:isBelt}),
|
||||
firstLayerBrimIn: newInput(LANG.fl_brin_s, {title:LANG.fl_brin_l, convert:toInt, show:isBelt}),
|
||||
firstLayerBrimTrig: newInput(LANG.fl_brmn_s, {title:LANG.fl_brmn_l, convert:toInt, show:isBelt}),
|
||||
firstLayerBrimGap: newInput(LANG.fl_brgp_s, {title:LANG.fl_brgp_l, convert:toFloat, show:isBelt}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isBelt }),
|
||||
firstLayerBeltLead: newInput(LANG.fl_bled_s, {title:LANG.fl_bled_l, convert:toFloat, show:isBelt}),
|
||||
firstLayerBeltBump: newInput(LANG.fl_blmp_s, {title:LANG.fl_blmp_l, convert:toFloat, bound:bound(0, 10), show:isBelt}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isNotBelt }),
|
||||
outputBrimCount: newInput(LANG.fl_skrt_s, {title:LANG.fl_skrt_l, convert:toInt, show:isNotBelt}),
|
||||
outputBrimOffset: newInput(LANG.fl_skro_s, {title:LANG.fl_skro_l, convert:toFloat, show:isNotBelt}),
|
||||
outputRaftSpacing: newInput(LANG.fr_spac_s, {title:LANG.fr_spac_l, convert:toFloat, bound:bound(0.0,3.0), show: () => ui.outputRaft.checked && isNotBelt() }),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isNotBelt }),
|
||||
outputRaft: newBoolean(LANG.fr_nabl_s, onBooleanClick, {title:LANG.fr_nabl_l, trigger, show:() => isNotBelt()}),
|
||||
outputDraftShield: newBoolean(LANG.fr_draf_s, onBooleanClick, {title:LANG.fr_draf_l, trigger, show:() => isNotBelt()}),
|
||||
_____: newGroup(LANG.ou_menu, $('fdm-output'), { modes:FDM, driven, hideable, separator, group:"fdm-out" }),
|
||||
outputFeedrate: newInput(LANG.ou_feed_s, {title:LANG.ou_feed_l, convert:toInt}),
|
||||
outputFinishrate: newInput(LANG.ou_fini_s, {title:LANG.ou_fini_l, convert:toInt}),
|
||||
outputSeekrate: newInput(LANG.ou_move_s, {title:LANG.ou_move_l, convert:toInt}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
outputShellMult: newInput(LANG.ou_shml_s, {title:LANG.ou_exml_l, convert:toFloat, bound:bound(0.0,2.0)}),
|
||||
outputFillMult: newInput(LANG.ou_flml_s, {title:LANG.ou_exml_l, convert:toFloat, bound:bound(0.0,2.0)}),
|
||||
outputSparseMult: newInput(LANG.ou_spml_s, {title:LANG.ou_exml_l, convert:toFloat, bound:bound(0.0,2.0)}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
outputRetractDist: newInput(LANG.ad_rdst_s, {title:LANG.ad_rdst_l, convert:toFloat}),
|
||||
outputRetractSpeed: newInput(LANG.ad_rrat_s, {title:LANG.ad_rrat_l, convert:toInt}),
|
||||
outputRetractWipe: newInput(LANG.ad_wpln_s, {title:LANG.ad_wpln_l, convert:toFloat, bound:bound(0.0,10)}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceLayerStart: newSelect(LANG.sl_strt_s, {title:LANG.sl_strt_l}, "start"),
|
||||
outputLayerRetract: newBoolean(LANG.ad_lret_s, onBooleanClick, {title:LANG.ad_lret_l}),
|
||||
outputAvoidGaps: newBoolean(LANG.ad_agap_s, onBooleanClick, {title:LANG.ad_agap_l}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isBelt }),
|
||||
outputBeltFirst: newBoolean(LANG.ad_lbir_s, onBooleanClick, {title:LANG.ad_lbir_l, show:isBelt}),
|
||||
_____: newGroup(LANG.ad_menu, $('fdm-expert'), { modes:FDM, driven, hideable, separator, group:"fdm-xprt" }),
|
||||
sliceAngle: newInput(LANG.sl_angl_s, {title:LANG.sl_angl_l, convert:toFloat, show:isBelt}),
|
||||
outputRetractDwell: newInput(LANG.ad_rdwl_s, {title:LANG.ad_rdwl_l, convert:toInt}),
|
||||
sliceSolidMinArea: newInput(LANG.ad_msol_s, {title:LANG.ad_msol_l, convert:toFloat}),
|
||||
outputMinSpeed: newInput(LANG.ad_mins_s, {title:LANG.ad_mins_l, convert:toFloat, bound:bound(1,200)}),
|
||||
outputShortPoly: newInput(LANG.ad_spol_s, {title:LANG.ad_spol_l, convert:toFloat, bound:bound(0,10000)}),
|
||||
outputCoastDist: newInput(LANG.ad_scst_s, {title:LANG.ad_scst_l, convert:toFloat, bound:bound(0.0,10)}),
|
||||
zHopDistance: newInput(LANG.ad_zhop_s, {title:LANG.ad_zhop_l, convert:toFloat, bound:bound(0,3.0)}),
|
||||
arcTolerance: newInput(LANG.ad_arct_s, {title:LANG.ad_arct_l, convert:toFloat, bound:bound(0,1.0), show:() => { return isNotBelt() }}),
|
||||
antiBacklash: newInput(LANG.ad_abkl_s, {title:LANG.ad_abkl_l, convert:toInt, bound:bound(0,3)}),
|
||||
outputLoops: newInput(LANG.ag_loop_s, {title:LANG.ag_loop_l, convert:toInt, bound:bound(-1,1000), show:isBelt}),
|
||||
outputPurgeTower: newInput(LANG.ad_purg_s, {title:LANG.ad_purg_l, convert:toInt, bound:bound(0,1000)}),
|
||||
|
||||
fdmRanges: $('fdm-ranges'),
|
||||
...menuFDM(),
|
||||
|
||||
/** CAM Settings */
|
||||
|
||||
_____: newGroup(LANG.ct_menu, $('cam-tabs'), { modes:CAM, marker:true, driven, separator }),
|
||||
camTabsWidth: newInput(LANG.ct_wdth_s, {title:LANG.ct_wdth_l, convert:toFloat, bound:bound(0.005,100), units}),
|
||||
camTabsHeight: newInput(LANG.ct_hght_s, {title:LANG.ct_hght_l, convert:toFloat, bound:bound(0.005,100), units}),
|
||||
camTabsDepth: newInput(LANG.ct_dpth_s, {title:LANG.ct_dpth_l, convert:toFloat, bound:bound(0.005,100), units}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camTabsMidline: newBoolean(LANG.ct_midl_s, onBooleanClick, {title:LANG.ct_midl_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camTabsManual: newRow([
|
||||
(ui.tabAdd = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})),
|
||||
(ui.tabDun = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})),
|
||||
(ui.tabClr = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-trash-alt"></i>'}))
|
||||
], {class:"ext-buttons f-row"}),
|
||||
_____: newGroup(LANG.cs_menu, $('cam-stock'), { modes:CAM, driven, separator }),
|
||||
camStockX: newInput(LANG.cs_wdth_s, {title:LANG.cs_wdth_l, convert:toFloat, bound:bound(0,9999), units}),
|
||||
camStockY: newInput(LANG.cs_dpth_s, {title:LANG.cs_dpth_l, convert:toFloat, bound:bound(0,9999), units}),
|
||||
camStockZ: newInput(LANG.cs_hght_s, {title:LANG.cs_hght_l, convert:toFloat, bound:bound(0,9999), units}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camStockOffset: newBoolean(LANG.cs_offs_s, onBooleanClick, {title:LANG.cs_offs_l}),
|
||||
camStockClipTo: newBoolean(LANG.cs_clip_s, onBooleanClick, {title:LANG.cs_clip_l}),
|
||||
camStockIndexed: newBoolean(LANG.cs_indx_s, onBooleanClick, {title:LANG.cs_indx_l}),
|
||||
camStockIndexGrid: newBoolean(LANG.cs_ishg_s, onBooleanClick, {title:LANG.cs_ishg_l, show:() => ui.camStockIndexed.checked}),
|
||||
_____: newGroup(LANG.cc_menu, $('cam-limits'), { modes:CAM, driven, separator }),
|
||||
camZAnchor: newSelect(LANG.ou_zanc_s, {title: LANG.ou_zanc_l, action:zAnchorSave, show:() => !ui.camStockIndexed.checked}, "zanchor"),
|
||||
camZOffset: newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:toFloat, units}),
|
||||
camZTop: newInput(LANG.ou_ztop_s, {title:LANG.ou_ztop_l, convert:toFloat, units, trigger}),
|
||||
camZBottom: newInput(LANG.ou_zbot_s, {title:LANG.ou_zbot_l, convert:toFloat, units, trigger}),
|
||||
camZThru: newInput(LANG.ou_ztru_s, {title:LANG.ou_ztru_l, convert:toFloat, bound:bound(0.0,100), units }),
|
||||
camZClearance: newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:toFloat, bound:bound(0.01,100), units }),
|
||||
camFastFeedZ: newInput(LANG.cc_rzpd_s, {title:LANG.cc_rzpd_l, convert:toFloat, units}),
|
||||
camFastFeed: newInput(LANG.cc_rapd_s, {title:LANG.cc_rapd_l, convert:toFloat, units}),
|
||||
_____: newGroup(LANG.ou_menu, $('cam-output'), { modes:CAM, driven, separator, group:"cam-output" }),
|
||||
camConventional: newBoolean(LANG.ou_conv_s, onBooleanClick, {title:LANG.ou_conv_l}),
|
||||
camEaseDown: newBoolean(LANG.cr_ease_s, onBooleanClick, {title:LANG.cr_ease_l}),
|
||||
camDepthFirst: newBoolean(LANG.ou_depf_s, onBooleanClick, {title:LANG.ou_depf_l}),
|
||||
camToolInit: newBoolean(LANG.ou_toin_s, onBooleanClick, {title:LANG.ou_toin_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camFirstZMax: newBoolean(LANG.ou_z1st_s, onBooleanClick, {title:LANG.ou_z1st_l}),
|
||||
camForceZMax: newBoolean(LANG.ou_forz_s, onBooleanClick, {title:LANG.ou_forz_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camEaseAngle: newInput(LANG.ou_eang_s, {title:LANG.ou_eang_l, convert:toFloat, bound:bound(0.1,85), show:() => ui.camEaseDown.checked}),
|
||||
camFullEngage: newInput(LANG.ou_feng_s, {title:LANG.ou_feng_l, convert:toFloat, bound:bound(0.1,1.0)}),
|
||||
_____: newGroup(LANG.co_menu, $('cam-origin'), { modes:CAM, driven, separator }),
|
||||
camOriginTop: newBoolean(LANG.or_topp_s, onBooleanClick, {title:LANG.or_topp_l}),
|
||||
camOriginCenter: newBoolean(LANG.or_cntr_s, onBooleanClick, {title:LANG.or_cntr_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camOriginOffX: newInput(LANG.co_offx_s, {title:LANG.co_offx_l, convert:toFloat, units}),
|
||||
camOriginOffY: newInput(LANG.co_offy_s, {title:LANG.co_offy_l, convert:toFloat, units}),
|
||||
camOriginOffZ: newInput(LANG.co_offz_s, {title:LANG.co_offz_l, convert:toFloat, units}),
|
||||
_____: newGroup(LANG.op_xprt_s, $('cam-expert'), { group:"cam_expert", modes:CAM, marker: false, driven, separator }),
|
||||
camExpertFast: newBoolean(LANG.cx_fast_s, onBooleanClick, {title:LANG.cx_fast_l, show: () => !ui.camTrueShadow.checked }),
|
||||
camTrueShadow: newBoolean(LANG.cx_true_s, onBooleanClick, {title:LANG.cx_true_l, show: () => !ui.camExpertFast.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camArcTolerance: newInput(LANG.cx_arct_s, {title:LANG.cx_arct_l, convert:toFloat, units, bound:bound(0,100)}),
|
||||
camArcResolution: newInput(LANG.cx_arcr_s, {title:LANG.cx_arcr_l, convert:toFloat, bound:bound(0,180), show:() => ui.camArcTolerance.value > 0}),
|
||||
...menuCAM(),
|
||||
|
||||
/** LASER/DRAG/WJET/WEDM cut tool Settings */
|
||||
|
||||
_____: newGroup(LANG.sl_menu, $('lzr-slice'), { modes:TWOD, driven, separator }),
|
||||
ctSliceKerf: newInput(LANG.ls_offs_s, {title:LANG.ls_offs_l, convert:toFloat}),
|
||||
ctSliceHeight: newInput(LANG.ls_lahi_s, {title:LANG.ls_lahi_l, convert:toFloat, trigger}),
|
||||
ctSliceHeightMin: newInput(LANG.ls_lahm_s, {title:LANG.ls_lahm_l, convert:toFloat, show:() => ui.ctSliceHeight.value == 0 && !ui.ctSliceSingle.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
ctSliceSingle: newBoolean(LANG.ls_sngl_s, onBooleanClick, {title:LANG.ls_sngl_l}),
|
||||
ctOmitInner: newBoolean(LANG.we_omit_s, onBooleanClick, {title:LANG.we_omit_l, modes:WEDM}),
|
||||
_____: newGroup('surfaces', $('lzr-surface'), { modes:[-1], driven, separator }),
|
||||
ctSurfaces: newRow([
|
||||
(ui.faceAdd = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})),
|
||||
(ui.faceDun = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})),
|
||||
(ui.faceClr = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-trash-alt"></i>'}))
|
||||
], {class:"ext-buttons f-row", modes:WEDM}),
|
||||
_____: newGroup(LANG.dk_menu, $('lzr-knife'), { modes:DRAG, marker:true, driven, separator }),
|
||||
ctOutKnifeDepth: newInput(LANG.dk_dpth_s, { title:LANG.dk_dpth_l, convert:toFloat, bound:bound(0.0,5.0) }),
|
||||
ctOutKnifePasses: newInput(LANG.dk_pass_s, { title:LANG.dk_pass_l, convert:toInt, bound:bound(0,5) }),
|
||||
ctOutKnifeTip: newInput(LANG.dk_offs_s, { title:LANG.dk_offs_l, convert:toFloat, bound:bound(0.0,10.0) }),
|
||||
_____: newGroup(LANG.lo_menu, $('lzr-layout'), { modes:TWOD, driven, separator }),
|
||||
ctOutTileSpacing: newInput(LANG.ou_spac_s, { title:LANG.ou_spac_l, convert:toInt }),
|
||||
ctOutMerged: newBoolean(LANG.ou_mrgd_s, onBooleanClick, {title:LANG.ou_mrgd_l, modes:TWONED, show:() => !ui.ctOutStack.checked }),
|
||||
ctOutGroup: newBoolean(LANG.ou_grpd_s, onBooleanClick, {title:LANG.ou_grpd_l, show:() => !(ui.ctOutMark.checked || ui.ctOutStack.checked) }),
|
||||
_____: newGroup(LANG.ou_menu, $('lzr-output'), { modes:TWOD, driven, separator, group:"lzr-output" }),
|
||||
ctOutPower: newInput(LANG.ou_powr_s, {title:LANG.ou_powr_l, convert:toInt, bound:bound(1,100), modes:TWONED }),
|
||||
ctOutSpeed: newInput(LANG.ou_sped_s, {title:LANG.ou_sped_l, convert:toInt }),
|
||||
ctAdaptive: newBoolean('adaptive speed', onBooleanClick, {modes:WEDM, title:'controller determines best cutting speed based on material feedback at runtime'}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
ctOriginBounds: newBoolean(LANG.or_bnds_s, onBooleanClick, { title:LANG.or_bnds_l, show:() => !ui.ctOriginCenter.checked }),
|
||||
ctOriginCenter: newBoolean(LANG.or_cntr_s, onBooleanClick, { title:LANG.or_cntr_l, show:() => !ui.ctOriginBounds.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven, modes:WEDM, show:() => ui.ctOriginBounds.checked }),
|
||||
ctOriginOffX: newInput(LANG.or_offx_s, { title:LANG.or_offx_l, convert:toFloat, modes:WEDM, show:() => ui.ctOriginBounds.checked }),
|
||||
ctOriginOffY: newInput(LANG.or_offy_s, { title:LANG.or_offy_l, convert:toFloat, modes:WEDM, show:() => ui.ctOriginBounds.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven, modes:TWONED }),
|
||||
ctOutZColor: newBoolean(LANG.ou_layo_s, onBooleanClick, { title:LANG.ou_layo_l, modes:TWONED, show:() => !ui.ctOutMerged.checked }),
|
||||
ctOutLayer: newBoolean(LANG.ou_layr_s, onBooleanClick, { title:LANG.ou_layr_l, modes:TWONED, show:() => !ui.ctOutStack.checked }),
|
||||
ctOutMark: newBoolean(LANG.ou_lays_s, onBooleanClick, { title:LANG.ou_lays_l, modes:TWONED, show:() => !ui.ctOutStack.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven, modes:LASER }),
|
||||
ctOutInches: newBoolean(LANG.ou_inch_s, onBooleanClick, { title:LANG.ou_inch_l, modes:LASER }),
|
||||
ctOutStack: newBoolean(LANG.ou_stak_s, onBooleanClick, { title:LANG.ou_stak_l, modes:LASER }),
|
||||
ctOutShaper: newBoolean(LANG.ou_shap_s, onBooleanClick, { title:LANG.ou_shap_l, modes:LASER, show:() => ui.ctOutStack.checked }),
|
||||
...menuLaser(),
|
||||
|
||||
/** SLA SETTINGS */
|
||||
|
||||
slaProc: newGroup(LANG.sa_menu, $('sla-slice'), { modes:SLA, group:"sla-slice", driven, separator }),
|
||||
slaSlice: newInput(LANG.sa_lahe_s, {title:LANG.sa_lahe_l, convert:toFloat}),
|
||||
slaShell: newInput(LANG.sa_shel_s, {title:LANG.sa_shel_l, convert:toFloat}),
|
||||
slaOpenTop: newBoolean(LANG.sa_otop_s, onBooleanClick, {title:LANG.sa_otop_l}),
|
||||
slaOpenBase: newBoolean(LANG.sa_obas_s, onBooleanClick, {title:LANG.sa_obas_l}),
|
||||
slaLayers: newGroup(LANG.sa_layr_m, $('sla-layers'), { modes:SLA, group:"sla-layers", driven, separator }),
|
||||
slaLayerOn: newInput(LANG.sa_lton_s, {title:LANG.sa_lton_l, convert:toFloat}),
|
||||
slaLayerOff: newInput(LANG.sa_ltof_s, {title:LANG.sa_ltof_l, convert:toFloat}),
|
||||
slaPeelDist: newInput(LANG.sa_pldi_s, {title:LANG.sa_pldi_l, convert:toFloat}),
|
||||
slaPeelLiftRate: newInput(LANG.sa_pllr_s, {title:LANG.sa_pllr_l, convert:toFloat}),
|
||||
slaPeelDropRate: newInput(LANG.sa_pldr_s, {title:LANG.sa_pldr_l, convert:toFloat}),
|
||||
slaBase: newGroup(LANG.sa_base_m, $('sla-base'), { modes:SLA, group:"sla-base", driven, separator }),
|
||||
slaBaseLayers: newInput(LANG.sa_balc_s, {title:LANG.sa_balc_l, convert:toInt}),
|
||||
slaBaseOn: newInput(LANG.sa_lton_s, {title:LANG.sa_bltn_l, convert:toFloat}),
|
||||
slaBaseOff: newInput(LANG.sa_ltof_s, {title:LANG.sa_bltf_l, convert:toFloat}),
|
||||
slaBasePeelDist: newInput(LANG.sa_pldi_s, {title:LANG.sa_pldi_l, convert:toFloat}),
|
||||
slaBasePeelLiftRate: newInput(LANG.sa_pllr_s, {title:LANG.sa_pllr_l, convert:toFloat}),
|
||||
slaFill: newGroup(LANG.sa_infl_m, $('sla-fill'), { modes:SLA, group:"sla-infill", driven, separator }),
|
||||
slaFillDensity: newInput(LANG.sa_ifdn_s, {title:LANG.sa_ifdn_l, convert:toFloat, bound:bound(0,1)}),
|
||||
slaFillLine: newInput(LANG.sa_iflw_s, {title:LANG.sa_iflw_l, convert:toFloat, bound:bound(0,5)}),
|
||||
slaSupport: newGroup(LANG.sa_supp_m, $('sla-support'), { modes:SLA, group:"sla-support", driven, separator }),
|
||||
slaSupportLayers: newInput(LANG.sa_slyr_s, {title:LANG.sa_slyr_l, convert:toInt, bound:bound(5,100)}),
|
||||
slaSupportGap: newInput(LANG.sa_slgp_s, {title:LANG.sa_slgp_l, convert:toInt, bound:bound(3,30)}),
|
||||
slaSupportDensity: newInput(LANG.sa_sldn_s, {title:LANG.sa_sldn_l, convert:toFloat, bound:bound(0.01,0.9)}),
|
||||
slaSupportSize: newInput(LANG.sa_slsz_s, {title:LANG.sa_slsz_l, convert:toFloat, bound:bound(0.1,1)}),
|
||||
slaSupportPoints: newInput(LANG.sa_slpt_s, {title:LANG.sa_slpt_l, convert:toInt, bound:bound(3,10)}),
|
||||
slaSupportEnable: newBoolean(LANG.enable, onBooleanClick, {title:LANG.sl_slen_l}),
|
||||
slaOutput: newGroup(LANG.sa_outp_m, $('sla-output'), { modes:SLA, driven, separator, group:"sla-output" }),
|
||||
slaFirstOffset: newInput(LANG.sa_opzo_s, {title:LANG.sa_opzo_l, convert:toFloat, bound:bound(0,1)}),
|
||||
slaAntiAlias: newSelect(LANG.sa_opaa_s, {title:LANG.sa_opaa_l}, "antialias"),
|
||||
...menuSLA(),
|
||||
|
||||
layers: uc.setGroup($("layers")),
|
||||
|
||||
|
|
@ -1367,6 +1089,8 @@ function init_one() {
|
|||
});
|
||||
|
||||
// run client mode initializations right after UI is bound
|
||||
// MUST run after main ui menu inits since they rely on passed state
|
||||
// that createPopOps disrupts (should be refactored)
|
||||
initCAM();
|
||||
initDRAG();
|
||||
initFDM();
|
||||
|
|
@ -1380,27 +1104,6 @@ function init_one() {
|
|||
settingsSave(undefined, ui.settingsName.value);
|
||||
};
|
||||
|
||||
function optSelected(sel) {
|
||||
let opt = sel.options[sel.selectedIndex];
|
||||
return opt ? opt.value : undefined;
|
||||
}
|
||||
|
||||
function hasInfill() {
|
||||
return optSelected(ui.sliceFillType) !== 'none'
|
||||
}
|
||||
|
||||
function fillIsLinear() {
|
||||
return hasInfill() && optSelected(ui.sliceFillType) === 'linear';
|
||||
}
|
||||
|
||||
function spindleShow() {
|
||||
return settings().device.spindleMax > 0;
|
||||
}
|
||||
|
||||
function zIntShow() {
|
||||
return settings().controller.devel;
|
||||
}
|
||||
|
||||
// slider setup
|
||||
const mobile = space.info.mob;
|
||||
const slbar = mobile ? 80 : 30;
|
||||
|
|
@ -2099,8 +1802,12 @@ function init_two() {
|
|||
sdb.kiri_beta = beta;
|
||||
}
|
||||
|
||||
// hide url params
|
||||
history.replaceState({}, '', '/kiri/');
|
||||
// hide url params but preserve version root (when present)
|
||||
let wlp = WIN.location.pathname;
|
||||
let kio = wlp.indexOf('/kiri/');
|
||||
if (kio >= 0) {
|
||||
history.replaceState({}, '', wlp.substring(0,kio + 6));
|
||||
}
|
||||
|
||||
// lift curtain
|
||||
$('curtain').style.display = 'none';
|
||||
|
|
@ -2165,7 +1872,7 @@ function init_lang() {
|
|||
}
|
||||
|
||||
export function run() {
|
||||
init_lang();
|
||||
client.start();
|
||||
init_lang();
|
||||
return api;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -613,10 +613,15 @@ class Print {
|
|||
scope.belt = belt;
|
||||
|
||||
if (scope.debugE) {
|
||||
console.log({ bounds, print_time: time.round(2) });
|
||||
console.log({
|
||||
bounds,
|
||||
minf,
|
||||
maxf,
|
||||
print_time: time.round(2),
|
||||
output: scope.output
|
||||
});
|
||||
}
|
||||
|
||||
console.log(scope.output)
|
||||
done({ output: scope.output });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { space } from '../../moto/space.js';
|
|||
import { local } from '../../data/local.js';
|
||||
import { utils } from './utils.js';
|
||||
import { version } from '../../moto/license.js';
|
||||
import { JSZip } from '../../ext/jszip-esm.js';
|
||||
|
||||
const { areEqual, ls2o, js2o } = utils;
|
||||
const { COLOR } = consts;
|
||||
|
|
@ -221,7 +222,7 @@ function updateSettingsFromFields(setrec, uirec = api.ui, changes) {
|
|||
}
|
||||
|
||||
// given a settings region, update values of matching bound UI fields
|
||||
function updateFieldsFromSettings(setrec, uirec = api.ui, trace) {
|
||||
function updateFieldsFromSettings(setrec, uirec = api.ui, opt = {}) {
|
||||
if (!setrec) {
|
||||
updateFieldsFromSettings(settings.device);
|
||||
updateFieldsFromSettings(settings.process);
|
||||
|
|
@ -229,6 +230,9 @@ function updateFieldsFromSettings(setrec, uirec = api.ui, trace) {
|
|||
updateExtruderFields(settings.device);
|
||||
return;
|
||||
}
|
||||
if (opt.trace) {
|
||||
console.log({ setrec, uirec });
|
||||
}
|
||||
for (let key in setrec) {
|
||||
if (!setrec.hasOwnProperty(key)) {
|
||||
continue;
|
||||
|
|
@ -238,6 +242,9 @@ function updateFieldsFromSettings(setrec, uirec = api.ui, trace) {
|
|||
continue;
|
||||
}
|
||||
let uie = uirec[key], typ = uie ? uie.type : null;
|
||||
if (opt.trace) {
|
||||
console.log({ key, uie, typ, val });
|
||||
}
|
||||
if (typ === 'text') {
|
||||
if (uie.setv) {
|
||||
uie.setv(val);
|
||||
|
|
@ -271,6 +278,8 @@ function updateFieldsFromSettings(setrec, uirec = api.ui, trace) {
|
|||
} else {
|
||||
uie.value = '';
|
||||
}
|
||||
} else if (opt.trace) {
|
||||
console.log('skipped', { key, val, typ });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -651,7 +660,7 @@ function settingsImportUrl(url, ask) {
|
|||
|
||||
function settingsImportZip(data, ask) {
|
||||
let alert = api.show.alert("Importing Workspace");
|
||||
JSZip.loadAsync(data).then(zip => {
|
||||
new JSZip().loadAsync(data).then(zip => {
|
||||
for (let [key,value] of Object.entries(zip.files)) {
|
||||
if (key === "workspace.json") {
|
||||
value.async("string").then(json => {
|
||||
|
|
|
|||
|
|
@ -434,8 +434,13 @@ function newDiv(opt = {}) {
|
|||
(opt.addto || addTo).appendChild(div);
|
||||
if (opt.addto) lastDiv = addTo = div;
|
||||
if (opt.class) div.setAttribute('class', opt.class);
|
||||
lastGroup?.push(div);
|
||||
div._group = groupName;
|
||||
if (opt.group !== false) {
|
||||
lastGroup?.push(div);
|
||||
div._group = groupName;
|
||||
} else {
|
||||
lastGroup = undefined;
|
||||
groupName = undefined;
|
||||
}
|
||||
return div;
|
||||
}
|
||||
|
||||
|
|
@ -685,6 +690,7 @@ function addUnits(input, round) {
|
|||
} else {
|
||||
input.value = value;
|
||||
}
|
||||
// console.log({ value }, input.real, input.value );
|
||||
return input.real;
|
||||
};
|
||||
return input;
|
||||
|
|
|
|||
|
|
@ -104,16 +104,16 @@
|
|||
"sliceFillWidth": 1,
|
||||
"sliceFillRate": 0,
|
||||
"sliceSupportEnable": false,
|
||||
"firstSliceHeight": 0.25,
|
||||
"firstSliceHeight": 0.5,
|
||||
"firstLayerFillRate": 20,
|
||||
"firstLayerLineMult": 1,
|
||||
"firstLayerNozzleTemp": 0,
|
||||
"firstLayerBedTemp": 0,
|
||||
"firstLayerBrimTrig": 0,
|
||||
"firstLayerBrimGap": 0,
|
||||
"outputRaft": true,
|
||||
"outputRaft": false,
|
||||
"outputRaftSpacing": 0.2,
|
||||
"outputBrimCount": 5,
|
||||
"outputBrimCount": 0,
|
||||
"outputBrimOffset": 2,
|
||||
"outputPurgeTower": 0,
|
||||
"outputInvertX": false,
|
||||
|
|
|
|||
|
|
@ -104,16 +104,16 @@
|
|||
"sliceFillWidth": 1,
|
||||
"sliceFillRate": 0,
|
||||
"sliceSupportEnable": false,
|
||||
"firstSliceHeight": 0.25,
|
||||
"firstSliceHeight": 0.5,
|
||||
"firstLayerFillRate": 20,
|
||||
"firstLayerLineMult": 1,
|
||||
"firstLayerNozzleTemp": 0,
|
||||
"firstLayerBedTemp": 0,
|
||||
"firstLayerBrimTrig": 0,
|
||||
"firstLayerBrimGap": 0,
|
||||
"outputRaft": true,
|
||||
"outputRaft": false,
|
||||
"outputRaftSpacing": 0.2,
|
||||
"outputBrimCount": 5,
|
||||
"outputBrimCount": 0,
|
||||
"outputBrimOffset": 2,
|
||||
"outputPurgeTower": 0,
|
||||
"outputInvertX": false,
|
||||
|
|
|
|||
|
|
@ -87,10 +87,10 @@ Object.assign(client, {
|
|||
|
||||
animate_setup2(settings, ondone) {
|
||||
color = settings.controller.dark ? 0x888888 : 0;
|
||||
material = new THREE.MeshMatcapMaterial({
|
||||
material = new THREE.MeshPhongMaterial({
|
||||
flatShading: true,
|
||||
transparent: false,
|
||||
opacity: 0.9,
|
||||
opacity: 0.5,
|
||||
color: 0x888888,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
|
|
|
|||
140
src/kiri/mode/cam/cl-origin.js
Normal file
140
src/kiri/mode/cam/cl-origin.js
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from '../../core/api.js';
|
||||
import { env, clearPops } from './client.js';
|
||||
import { CAM } from './driver-fe.js';
|
||||
import { addbox, clearboxes } from '../../core/boxes.js';
|
||||
|
||||
export let originSelectOn = false;
|
||||
|
||||
let { world } = api.SPACE;
|
||||
let alert, lastHover, lastPoints;
|
||||
|
||||
export function originSelect() {
|
||||
if (originSelectOn) {
|
||||
return originSelectDone();
|
||||
}
|
||||
|
||||
clearPops();
|
||||
|
||||
alert = api.show.alert("analyzing parts...", 1000);
|
||||
originSelectOn = true;
|
||||
|
||||
api.feature.hover = true;
|
||||
api.feature.hoverAdds = true;
|
||||
env.hover = pointHover;
|
||||
env.hoverUp = pointHoverUp;
|
||||
|
||||
CAM.traces((ids) => {
|
||||
api.hide.alert(alert);
|
||||
alert = api.show.alert("select origin<br>[esc] to cancel", 1000);
|
||||
let ends = {};
|
||||
let points = {};
|
||||
let color = new THREE.Color( 0xff0000 );
|
||||
function incpoint(widget, point) {
|
||||
let rec = ends[point.key];
|
||||
if (rec && rec.count++ === 2) {
|
||||
addpoint(widget, point);
|
||||
} else if (!rec) {
|
||||
rec = ends[point.key] = { count: 1 };
|
||||
}
|
||||
}
|
||||
function addpoint(widget, center) {
|
||||
let box = addbox(center, color, undefined, undefined, { opacity: 1 });
|
||||
widget.adds.push(box);
|
||||
world.add(box);
|
||||
box._origin = center;
|
||||
points[center.key] = { box, center };
|
||||
}
|
||||
api.widgets.for(widget => {
|
||||
let { pos, tzoff } = widget.track;
|
||||
let polys = widget.traces.map(trace => {
|
||||
return trace.fixClosed().clone().move(pos).move({ x:0, y:0, z: -tzoff });
|
||||
});
|
||||
for (let poly of polys) {
|
||||
if (poly.circularity() >= 0.99) {
|
||||
let center = poly.calcCircleCenter();
|
||||
if (points[center.key]) {
|
||||
continue;
|
||||
}
|
||||
addpoint(widget, center);
|
||||
} else if (poly.isOpen()) {
|
||||
incpoint(widget, poly.first());
|
||||
incpoint(widget, poly.last());
|
||||
}
|
||||
}
|
||||
});
|
||||
lastPoints = Object.values(points);
|
||||
});
|
||||
}
|
||||
|
||||
export function originReset() {
|
||||
let { process} = api.conf.get();
|
||||
process.camOriginOffX = 0;
|
||||
process.camOriginOffY = 0;
|
||||
process.camOriginOffZ = 0;
|
||||
api.settings.update_fields(process);
|
||||
api.platform.update_origin();
|
||||
api.conf.save();
|
||||
originSelectDone();
|
||||
}
|
||||
|
||||
export function originSelectDone() {
|
||||
if (!originSelectOn) {
|
||||
return;
|
||||
}
|
||||
api.hide.alert(alert);
|
||||
api.feature.hover = false;
|
||||
api.feature.hoverAdds = false;
|
||||
api.widgets.for(widget => {
|
||||
for (let box of widget.adds) {
|
||||
world.remove(box);
|
||||
}
|
||||
widget.adds.length = 0;
|
||||
});
|
||||
clearboxes();
|
||||
originSelectOn = false;
|
||||
}
|
||||
|
||||
function pointHover(data) {
|
||||
if (lastHover) {
|
||||
let { color, colorSave } = lastHover.material[0] || lastHover.material;
|
||||
color.r = colorSave.r;
|
||||
color.g = colorSave.g;
|
||||
color.b = colorSave.b;
|
||||
}
|
||||
lastHover = null;
|
||||
if (data.type === 'platform') {
|
||||
return;
|
||||
}
|
||||
if (!data.int.object._origin) {
|
||||
return;
|
||||
}
|
||||
lastHover = data.int.object;
|
||||
let material = lastHover.material[0] || lastHover.material;
|
||||
let color = material.color;
|
||||
material.colorSave = color.clone();
|
||||
color.setHex(0x00ff00);
|
||||
}
|
||||
|
||||
function pointHoverUp(int, ev) {
|
||||
if (!int?.object?._origin) return;
|
||||
let { _origin } = int.object;
|
||||
let { process, stock } = api.conf.get();
|
||||
let { x, y, z } = _origin;
|
||||
let { camOriginTop, camOriginCenter } = process;
|
||||
if (camOriginTop) {
|
||||
z = z - stock.z;
|
||||
}
|
||||
if (!camOriginCenter) {
|
||||
x += stock.x / 2;
|
||||
y += stock.y / 2;
|
||||
}
|
||||
process.camOriginOffX = x;
|
||||
process.camOriginOffY = y;
|
||||
process.camOriginOffZ = z;
|
||||
api.settings.update_fields(process);
|
||||
api.platform.update_origin();
|
||||
api.conf.save();
|
||||
originSelectDone();
|
||||
}
|
||||
|
|
@ -52,7 +52,6 @@ export function updateStock() {
|
|||
});
|
||||
env.camStock = new THREE.Mesh(geo, mat);
|
||||
env.camStock.renderOrder = 2;
|
||||
|
||||
let lo = 0.5;
|
||||
let lidat = [
|
||||
lo, lo, lo, lo, lo, -lo,
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
import { api } from '../../core/api.js';
|
||||
import { env, isDark } from './client.js';
|
||||
import { addbox, delbox } from '../../core/boxes.js';
|
||||
import { addbox, delbox, clearboxes } from '../../core/boxes.js';
|
||||
import { traceDone } from './cl-trace.js';
|
||||
import { space as SPACE } from '../../../moto/space.js';
|
||||
|
||||
let showTab, lastTab, tab, iw, ic;
|
||||
|
||||
|
|
@ -107,6 +108,7 @@ export function clearTabs(widget, skiprec) {
|
|||
if (!skiprec) {
|
||||
delete api.widgets.annotate(widget.id).tab;
|
||||
}
|
||||
clearboxes();
|
||||
}
|
||||
|
||||
export function updateTabs() {
|
||||
|
|
@ -198,6 +200,7 @@ export function tabAdd() {
|
|||
|
||||
export function tabDone() {
|
||||
delbox('tabb');
|
||||
clearboxes();
|
||||
api.hide.alert(alert);
|
||||
api.feature.hover = false;
|
||||
if (lastTab) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from '../../core/api.js';
|
||||
import { env, clearPops } from './client.js';
|
||||
import { env, clearPops, isDark } from './client.js';
|
||||
import { CAM } from './driver-fe.js';
|
||||
import { Layers } from '../../core/layers.js';
|
||||
import { Stack } from '../../core/stack.js';
|
||||
|
|
@ -123,7 +123,7 @@ export function traceHover(data) {
|
|||
let material = lastTrace.material[0] || lastTrace.material;
|
||||
let color = material.color;
|
||||
material.colorSave = color.clone();
|
||||
color.setHex(env.isDark() ? 0x0066ff : 0x0000ff);
|
||||
color.setHex(isDark() ? 0x0066ff : 0x0000ff);
|
||||
}
|
||||
|
||||
export function traceHoverUp(int, ev) {
|
||||
|
|
@ -157,7 +157,7 @@ export function traceToggle(obj, skip) {
|
|||
colorSave = material.colorSave = color.clone();
|
||||
}
|
||||
if (obj.selected) {
|
||||
color.setHex(env.isDark() ? 0xdd0011 : 0xff0033);
|
||||
color.setHex(isDark() ? 0xdd0011 : 0xff0033);
|
||||
colorSave.r = color.r;
|
||||
colorSave.g = color.g;
|
||||
colorSave.b = color.b;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { $, h } from '../../../moto/webui.js';
|
||||
import { $ } from '../../../moto/webui.js';
|
||||
import { api } from '../../core/api.js';
|
||||
import { load } from '../../../load/file.js';
|
||||
import { animate as anim_2d, animate_clear as anim_2d_clear } from './anim-2d-fe.js';
|
||||
|
|
@ -10,18 +10,19 @@ import { Layers } from '../../core/layers.js';
|
|||
import { Stack } from '../../core/stack.js';
|
||||
import { updateStock } from './cl-stock.js';
|
||||
import { createPopOps } from './cl-ops.js';
|
||||
import { tabAdd, tabDone, tabClear, restoreTabs, updateTabs } from './cl-tab.js';
|
||||
import { tabAdd, tabDone, tabClear, restoreTabs, rotateTabs, updateTabs } from './cl-tab.js';
|
||||
import { traceOn, traceDone, unselectTraces } from './cl-trace.js';
|
||||
import { holeSelOn, selectHolesDone, clearHolesRec } from './cl-hole.js';
|
||||
import { surfaceOn, surfaceDone } from './cl-surface.js';
|
||||
import { helicalOn, helicalDone } from './cl-helical.js';
|
||||
import { originSelectDone } from './cl-origin.js';
|
||||
|
||||
const DEG2RAD = Math.PI / 180;
|
||||
const RAD2DEG = 180 / Math.PI;
|
||||
const hasSharedArrays = self.SharedArrayBuffer ? true : false;
|
||||
|
||||
const { VIEWS, STACKS } = api.const;
|
||||
const { noop, space } = api;
|
||||
const { noop } = api;
|
||||
const { ui: UI, uc: UC } = api;
|
||||
const { widgets: WIDGETS } = api;
|
||||
|
||||
|
|
@ -55,6 +56,9 @@ export function isDark() {
|
|||
|
||||
export function clearPops() {
|
||||
if (env.func.unpop) env.func.unpop();
|
||||
originSelectDone();
|
||||
selectHolesDone();
|
||||
surfaceDone();
|
||||
tabDone();
|
||||
traceDone();
|
||||
surfaceDone();
|
||||
|
|
|
|||
128
src/kiri/mode/cam/init-menu.js
Normal file
128
src/kiri/mode/cam/init-menu.js
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from '../../core/api.js';
|
||||
import { originReset, originSelect } from './cl-origin.js';
|
||||
|
||||
let LANG = api.language.current;
|
||||
let { CAM } = api.const.MODES,
|
||||
{ $ } = api.web,
|
||||
{ uc, ui } = api,
|
||||
{ bound, toInt, toFloat } = uc,
|
||||
{ newBlank, newButton, newBoolean, newGroup, newInput } = uc,
|
||||
{ newSelect, newLabel, newValue, newRow, newDiv } = uc,
|
||||
driven = true,
|
||||
separator = true,
|
||||
trigger = true,
|
||||
units = true
|
||||
;
|
||||
|
||||
function onBooleanClick(el) {
|
||||
api.event.emit('click.boolean', el);
|
||||
}
|
||||
|
||||
function onButtonClick(el) {
|
||||
api.event.emit('click.button', el);
|
||||
}
|
||||
|
||||
function zAnchorSave() {
|
||||
api.conf.update();
|
||||
api.platform.update_top_z();
|
||||
}
|
||||
|
||||
export function menu() {
|
||||
let anim = ui.anim = {};
|
||||
|
||||
return {
|
||||
|
||||
/** Animation Bar */
|
||||
|
||||
_____: {
|
||||
_____: newDiv({ addto: $('layer-animate'), set:true, group:false }),
|
||||
row: newRow([
|
||||
anim.replay = newButton(null,"anim.replay",{icon:'<i class="fas fa-fast-backward"></i>',title:"restart"}),
|
||||
anim.play = newButton(null,"anim.play",{icon:'<i class="fas fa-play"></i>',title:"play"}),
|
||||
anim.pause = newButton(null,"anim.pause",{icon:'<i class="fas fa-pause"></i>',title:"pause"}),
|
||||
anim.step = newButton(null,"anim.step",{icon:'<i class="fas fa-step-forward"></i>',title:"single step"}),
|
||||
anim.speed = newButton(null,"anim.fast",{icon:'<i class="fas fa-forward"></i>',title:"toggle speed"}),
|
||||
anim.labspd = newValue(3, {class:"center padleft"}),
|
||||
anim.labx = newLabel("X", {class:"padleft"}),
|
||||
anim.valx = newValue(7, {class:"center"}),
|
||||
anim.laby = newLabel("Y", {class:"padleft"}),
|
||||
anim.valy = newValue(7, {class:"center"}),
|
||||
anim.labz = newLabel("Z", {class:"padleft"}),
|
||||
anim.valz = newValue(6, {class:"center"}),
|
||||
anim.laba = newLabel("A", {class:"padleft hide"}),
|
||||
anim.vala = newValue(6, {class:"center hide"}),
|
||||
anim.labpro = newLabel("%", {class:"padleft"}),
|
||||
anim.progress = newValue(5, {class:"center"}),
|
||||
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.shade = newButton(null,null,{icon:'<i class="fa-solid fa-cube"></i>',title:"stock box"}),
|
||||
])
|
||||
},
|
||||
|
||||
/** Left Side Menu */
|
||||
|
||||
_____: newGroup(LANG.ct_menu, $('cam-tabs'), { modes:CAM, marker:true, driven, separator }),
|
||||
camTabsWidth: newInput(LANG.ct_wdth_s, {title:LANG.ct_wdth_l, convert:toFloat, bound:bound(0.005,100), units}),
|
||||
camTabsHeight: newInput(LANG.ct_hght_s, {title:LANG.ct_hght_l, convert:toFloat, bound:bound(0.005,100), units}),
|
||||
camTabsDepth: newInput(LANG.ct_dpth_s, {title:LANG.ct_dpth_l, convert:toFloat, bound:bound(0.005,100), units}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camTabsMidline: newBoolean(LANG.ct_midl_s, onBooleanClick, {title:LANG.ct_midl_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camTabsManual: newRow([
|
||||
(ui.tabAdd = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})),
|
||||
(ui.tabDun = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})),
|
||||
(ui.tabClr = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-trash-alt"></i>'}))
|
||||
], {class:"ext-buttons f-row"}),
|
||||
_____: newGroup(LANG.cs_menu, $('cam-stock'), { modes:CAM, driven, separator }),
|
||||
camStockX: newInput(LANG.cs_wdth_s, {title:LANG.cs_wdth_l, convert:toFloat, bound:bound(0,9999), units}),
|
||||
camStockY: newInput(LANG.cs_dpth_s, {title:LANG.cs_dpth_l, convert:toFloat, bound:bound(0,9999), units}),
|
||||
camStockZ: newInput(LANG.cs_hght_s, {title:LANG.cs_hght_l, convert:toFloat, bound:bound(0,9999), units}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camStockOffset: newBoolean(LANG.cs_offs_s, onBooleanClick, {title:LANG.cs_offs_l}),
|
||||
camStockClipTo: newBoolean(LANG.cs_clip_s, onBooleanClick, {title:LANG.cs_clip_l}),
|
||||
camStockIndexed: newBoolean(LANG.cs_indx_s, onBooleanClick, {title:LANG.cs_indx_l}),
|
||||
camStockIndexGrid: newBoolean(LANG.cs_ishg_s, onBooleanClick, {title:LANG.cs_ishg_l, show:() => ui.camStockIndexed.checked}),
|
||||
_____: newGroup(LANG.cc_menu, $('cam-limits'), { modes:CAM, driven, separator }),
|
||||
camZAnchor: newSelect(LANG.ou_zanc_s, {title: LANG.ou_zanc_l, action:zAnchorSave, show:() => !ui.camStockIndexed.checked}, "zanchor"),
|
||||
camZOffset: newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:toFloat, units}),
|
||||
camZTop: newInput(LANG.ou_ztop_s, {title:LANG.ou_ztop_l, convert:toFloat, units, trigger}),
|
||||
camZBottom: newInput(LANG.ou_zbot_s, {title:LANG.ou_zbot_l, convert:toFloat, units, trigger}),
|
||||
camZThru: newInput(LANG.ou_ztru_s, {title:LANG.ou_ztru_l, convert:toFloat, bound:bound(0.0,100), units }),
|
||||
camZClearance: newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:toFloat, bound:bound(0.01,100), units }),
|
||||
camFastFeedZ: newInput(LANG.cc_rzpd_s, {title:LANG.cc_rzpd_l, convert:toFloat, units}),
|
||||
camFastFeed: newInput(LANG.cc_rapd_s, {title:LANG.cc_rapd_l, convert:toFloat, units}),
|
||||
_____: newGroup(LANG.ou_menu, $('cam-output'), { modes:CAM, driven, separator, group:"cam-output" }),
|
||||
camConventional: newBoolean(LANG.ou_conv_s, onBooleanClick, {title:LANG.ou_conv_l}),
|
||||
camEaseDown: newBoolean(LANG.cr_ease_s, onBooleanClick, {title:LANG.cr_ease_l}),
|
||||
camDepthFirst: newBoolean(LANG.ou_depf_s, onBooleanClick, {title:LANG.ou_depf_l}),
|
||||
camToolInit: newBoolean(LANG.ou_toin_s, onBooleanClick, {title:LANG.ou_toin_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camFirstZMax: newBoolean(LANG.ou_z1st_s, onBooleanClick, {title:LANG.ou_z1st_l}),
|
||||
camForceZMax: newBoolean(LANG.ou_forz_s, onBooleanClick, {title:LANG.ou_forz_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camEaseAngle: newInput(LANG.ou_eang_s, {title:LANG.ou_eang_l, convert:toFloat, bound:bound(0.1,85), show:() => ui.camEaseDown.checked}),
|
||||
camFullEngage: newInput(LANG.ou_feng_s, {title:LANG.ou_feng_l, convert:toFloat, bound:bound(0.1,1.0)}),
|
||||
_____: newGroup(LANG.co_menu, $('cam-origin'), { modes:CAM, driven, separator }),
|
||||
camOriginTop: newBoolean(LANG.or_topp_s, onBooleanClick, {title:LANG.or_topp_l}),
|
||||
camOriginCenter: newBoolean(LANG.or_cntr_s, onBooleanClick, {title:LANG.or_cntr_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camOriginOffX: newInput(LANG.co_offx_s, {title:LANG.co_offx_l, convert:toFloat, units}),
|
||||
camOriginOffY: newInput(LANG.co_offy_s, {title:LANG.co_offy_l, convert:toFloat, units}),
|
||||
camOriginOffZ: newInput(LANG.co_offz_s, {title:LANG.co_offz_l, convert:toFloat, units}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camOriginSelect: newRow([
|
||||
newButton("select", originSelect),
|
||||
newButton("reset", originReset),
|
||||
], { class: "ext-buttons f-row" }),
|
||||
_____: newGroup(LANG.op_xprt_s, $('cam-expert'), { group:"cam_expert", modes:CAM, marker: false, driven, separator }),
|
||||
camExpertFast: newBoolean(LANG.cx_fast_s, onBooleanClick, {title:LANG.cx_fast_l, show: () => !ui.camTrueShadow.checked }),
|
||||
camTrueShadow: newBoolean(LANG.cx_true_s, onBooleanClick, {title:LANG.cx_true_l, show: () => !ui.camExpertFast.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
camArcEnabled: newBoolean(LANG.cx_arce_s, onBooleanClick, {title:LANG.cx_arce_l}),
|
||||
camArcTolerance: newInput(LANG.cx_arct_s, {title:LANG.cx_arct_l, convert:toFloat, bound:bound(0,100), units, trigger, show:() => ui.camArcEnabled.checked}),
|
||||
camArcResolution: newInput(LANG.cx_arcr_s, {title:LANG.cx_arcr_l, convert:toFloat, bound:bound(0,180), trigger, show:() => ui.camArcEnabled.checked}),
|
||||
|
||||
};
|
||||
};
|
||||
|
|
@ -15,7 +15,7 @@ function createFilter(op) {
|
|||
let idx = 0;
|
||||
if (obj && obj.slices) {
|
||||
const nadd = [];
|
||||
filter = function(slices) {
|
||||
filter = function (slices) {
|
||||
for (let slice of slices) {
|
||||
if (obj.slices(slice, idx++)) {
|
||||
nadd.push(slice);
|
||||
|
|
@ -38,8 +38,10 @@ class OpContour extends CamOp {
|
|||
|
||||
async slice(progress) {
|
||||
let { op, state } = this;
|
||||
let { addSlices } = state;
|
||||
let { addSlices, settings, updateToolDiams } = state;
|
||||
let filter = createFilter(op);
|
||||
let toolDiam = this.toolDiam = new Tool(settings, op.tool).fluteDiameter();
|
||||
updateToolDiams(toolDiam);
|
||||
// we need topo for safe travel moves when roughing and outlining
|
||||
// not generated when drilling-only. then all z moves use bounds max.
|
||||
// also generates x and y contouring when selected
|
||||
|
|
@ -69,7 +71,7 @@ class OpContour extends CamOp {
|
|||
let { camOut, polyEmit, newLayer, printPoint, lastPoint } = ops;
|
||||
let { bounds, zmax } = ops;
|
||||
|
||||
let toolDiam = this.toolDiam = new Tool(settings, op.tool).fluteDiameter();
|
||||
let toolDiam = this.toolDiam;
|
||||
let stepover = toolDiam * op.step * 2;
|
||||
let depthFirst = process.camDepthFirst;
|
||||
let depthData = [];
|
||||
|
|
@ -78,7 +80,7 @@ class OpContour extends CamOp {
|
|||
setSpindle(op.spindle);
|
||||
setTolerance(this.tolerance);
|
||||
|
||||
printPoint = newPoint(bounds.min.x,bounds.min.y,zmax);
|
||||
printPoint = newPoint(bounds.min.x, bounds.min.y, zmax);
|
||||
|
||||
for (let slice of sliceOut) {
|
||||
// ignore debug slices
|
||||
|
|
@ -88,17 +90,17 @@ class OpContour extends CamOp {
|
|||
let polys = [], poly, emit;
|
||||
slice.camLines.forEach(function (poly) {
|
||||
if (depthFirst) poly = poly.clone(true);
|
||||
polys.push({first:poly.first(), last:poly.last(), poly:poly});
|
||||
polys.push({ first: poly.first(), last: poly.last(), poly: poly });
|
||||
});
|
||||
if (depthFirst) {
|
||||
depthData.appendAll(polys);
|
||||
} else {
|
||||
printPoint = tip2tipEmit(polys, printPoint, function(el, point, count) {
|
||||
printPoint = tip2tipEmit(polys, printPoint, function (el, point, count) {
|
||||
poly = el.poly;
|
||||
if (poly.last() === point) {
|
||||
poly.reverse();
|
||||
}
|
||||
poly.forEachPoint(function(point, pidx) {
|
||||
poly.forEachPoint(function (point, pidx) {
|
||||
camOut(point.clone(), pidx > 0, stepover);
|
||||
}, false);
|
||||
});
|
||||
|
|
@ -107,12 +109,12 @@ class OpContour extends CamOp {
|
|||
}
|
||||
|
||||
if (depthFirst) {
|
||||
printPoint = tip2tipEmit(depthData, printPoint, function(el, point, count) {
|
||||
printPoint = tip2tipEmit(depthData, printPoint, function (el, point, count) {
|
||||
let poly = el.poly;
|
||||
if (poly.last() === point) {
|
||||
poly.reverse();
|
||||
}
|
||||
poly.forEachPoint(function(point, pidx) {
|
||||
poly.forEachPoint(function (point, pidx) {
|
||||
camOut(point.clone(), pidx > 0, stepover);
|
||||
}, false);
|
||||
newLayer();
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class OpDrill extends CamOp {
|
|||
let { op, state } = this;
|
||||
let { settings, addSlices, widget, updateToolDiams } = state;
|
||||
let { zBottom, zThru, thruHoles, color } = state;
|
||||
let { drills, drillThrough} = op
|
||||
let { drills, drillThrough } = op
|
||||
|
||||
let drillTool = new Tool(settings, op.tool),
|
||||
drillToolDiam = drillTool.fluteDiameter(),
|
||||
|
|
@ -25,8 +25,8 @@ class OpDrill extends CamOp {
|
|||
|
||||
const allDrills = drills[widget.id] ?? []
|
||||
// drill points to use center (average of all points) of the polygon
|
||||
allDrills.forEach((drill)=> {
|
||||
if(!drill.selected){
|
||||
allDrills.forEach((drill) => {
|
||||
if (!drill.selected) {
|
||||
return
|
||||
}
|
||||
let slice = newSlice(0);
|
||||
|
|
@ -36,10 +36,10 @@ class OpDrill extends CamOp {
|
|||
}
|
||||
drill.zBottom = drill.z - drill.depth;
|
||||
// for thru holes, follow z thru when set
|
||||
if ((op.thru>0) ) {
|
||||
if ((op.thru > 0)) {
|
||||
drill.zBottom -= op.thru;
|
||||
}
|
||||
const poly = newPolygon()
|
||||
const poly = newPolygon()
|
||||
poly.points.push(newPoint(drill.x, drill.y, drill.z))
|
||||
poly.points.push(newPoint(drill.x, drill.y, drill.zBottom))
|
||||
// poly.points.pop();
|
||||
|
|
@ -47,7 +47,7 @@ class OpDrill extends CamOp {
|
|||
slice.camLines = [poly];
|
||||
|
||||
slice.output()
|
||||
.setLayer("drill", {face: color, line: color})
|
||||
.setLayer("drill", { face: color, line: color })
|
||||
.addPolys(slice.camLines);
|
||||
addSlices(slice);
|
||||
sliceOut.push(slice);
|
||||
|
|
@ -59,7 +59,7 @@ class OpDrill extends CamOp {
|
|||
let { settings, widget, addSlices, updateToolDiams } = state;
|
||||
let { setTool, setSpindle, setDrill, emitDrills } = ops;
|
||||
setTool(op.tool, undefined, op.rate);
|
||||
setDrill(op.down, op.lift, op.dwell,op.thru);
|
||||
setDrill(op.down, op.lift, op.dwell, op.thru);
|
||||
setSpindle(op.spindle);
|
||||
emitDrills(this.sliceOut.map(slice => slice.camLines).flat());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ export class OpIndex extends CamOp {
|
|||
super(state, op);
|
||||
}
|
||||
|
||||
weight() {
|
||||
return 0.1;
|
||||
}
|
||||
|
||||
async slice() {
|
||||
let { op, state } = this;
|
||||
if (!state.isIndexed) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { CamOp } from './op.js';
|
||||
import { Tool } from './tool.js';
|
||||
import { generate as topo4_generate } from './topo4.js';
|
||||
import { newPoint } from '../../../geo/point.js';
|
||||
|
||||
function createFilter(op) {
|
||||
|
|
@ -12,7 +13,7 @@ function createFilter(op) {
|
|||
let idx = 0;
|
||||
if (obj && obj.slices) {
|
||||
const nadd = [];
|
||||
filter = function(slices) {
|
||||
filter = function (slices) {
|
||||
for (let slice of slices) {
|
||||
if (obj.slices(slice, idx++)) {
|
||||
nadd.push(slice);
|
||||
|
|
@ -38,7 +39,7 @@ class OpLathe extends CamOp {
|
|||
let { addSlices } = state;
|
||||
let filter = createFilter(op);
|
||||
|
||||
this.topo = await Topo4({
|
||||
this.topo = await topo4_generate({
|
||||
op,
|
||||
state,
|
||||
onupdate: (pct, msg) => {
|
||||
|
|
@ -109,7 +110,7 @@ class OpLathe extends CamOp {
|
|||
// camOut(last = last.clone().setZ(zmax), 0);
|
||||
// camOut(last = last.clone().setA(amax), 0);
|
||||
newLayer();
|
||||
ops.addGCode([`G0 Z${zmax.round(2)}`,`G0 A${amax}`,"G92 A0"]);
|
||||
ops.addGCode([`G0 Z${zmax.round(2)}`, `G0 A${amax}`, "G92 A0"]);
|
||||
|
||||
setPrintPoint(last);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class OpOutline extends CamOp {
|
|||
async slice(progress) {
|
||||
let { op, state } = this;
|
||||
let { settings, widget, slicer, addSlices, tshadow, thruHoles, unsafe, color } = state;
|
||||
let { updateToolDiams, tabs, cutTabs, cutPolys, workarea, zMax } = state;
|
||||
let { updateToolDiams, tabs, cutTabs, cutPolys, workarea, zMax, shadowAt } = state;
|
||||
let { process, stock } = settings;
|
||||
|
||||
if (op.down <= 0) {
|
||||
|
|
@ -37,6 +37,7 @@ class OpOutline extends CamOp {
|
|||
};
|
||||
let indices = slicer.interval(op.down, intopt);
|
||||
let trueShadow = process.camTrueShadow === true;
|
||||
let lastShadowZ;
|
||||
// shift out first (top-most) slice
|
||||
indices.shift();
|
||||
// add flats to shadow
|
||||
|
|
@ -44,7 +45,6 @@ class OpOutline extends CamOp {
|
|||
.map(v => (parseFloat(v) - 0.01).round(5))
|
||||
.filter(v => v > 0 && indices.indexOf(v) < 0);
|
||||
indices = indices.appendAll(flats).sort((a,b) => b-a);
|
||||
|
||||
let cnt = 0;
|
||||
let tot = 0;
|
||||
if (op.outside && !op.inside) {
|
||||
|
|
@ -65,7 +65,7 @@ class OpOutline extends CamOp {
|
|||
// exclude flats injected to complete shadow
|
||||
return;
|
||||
}
|
||||
data.shadow = trueShadow ? shadowAt(widget, data.z) : shadow.clone(true);
|
||||
data.shadow = trueShadow ? shadowAt(data.z, lastShadowZ) : shadow.clone(true);
|
||||
data.slice.shadow = data.shadow;
|
||||
// data.slice.tops[0].inner = data.shadow;
|
||||
// data.slice.tops[0].inner = POLY.setZ(tshadow.clone(true), data.z);
|
||||
|
|
@ -73,6 +73,7 @@ class OpOutline extends CamOp {
|
|||
// data.slice.xray();
|
||||
// onupdate(0.2 + (index/total) * 0.1, "outlines");
|
||||
progress(0.5 + 0.5 * (++cnt / tot));
|
||||
lastShadowZ = data.z;
|
||||
}, progress: (index, total) => {
|
||||
tot = total;
|
||||
progress((index / total) * 0.5);
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class OpRegister extends CamOp {
|
|||
poly, cp, cz;
|
||||
function start(z) {
|
||||
cz = z;
|
||||
cp = {x:x0 + o2 * 0.5, y:y0 + o2 * 1.5};
|
||||
cp = { x: x0 + o2 * 0.5, y: y0 + o2 * 1.5 };
|
||||
poly = newPolygon().add(cp.x, cp.y, z);
|
||||
}
|
||||
function move(dx, dy) {
|
||||
|
|
@ -115,16 +115,16 @@ class OpRegister extends CamOp {
|
|||
});
|
||||
poly.points.pop();
|
||||
slice.camTrace = { tool: tool.getID(), rate: op.feed, plunge: op.rate };
|
||||
slice.camLines = [ poly ];
|
||||
slice.camLines = [poly];
|
||||
slice.output()
|
||||
.setLayer("register", {line: color}, false)
|
||||
.setLayer("register", { line: color }, false)
|
||||
.addPolys(slice.camLines)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (points.length) {
|
||||
let slice = newSlice(0,null), polys = [];
|
||||
let slice = newSlice(0, null), polys = [];
|
||||
points.forEach(point => {
|
||||
polys.push(newPolygon()
|
||||
.append(point.clone().setZ(z1))
|
||||
|
|
@ -132,7 +132,7 @@ class OpRegister extends CamOp {
|
|||
});
|
||||
slice.camLines = polys;
|
||||
slice.output()
|
||||
.setLayer("register", {face: color, line: color})
|
||||
.setLayer("register", { face: color, line: color })
|
||||
.addPolys(polys);
|
||||
addSlices(slice);
|
||||
sliceOut.push(slice);
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class OpRough extends CamOp {
|
|||
indices = indices.filter(v => v >= workarea.bottom_z);
|
||||
// console.log('indices', ...indices, {zBottom});
|
||||
|
||||
let lsz;
|
||||
let cnt = 0;
|
||||
let tot = 0;
|
||||
await slicer.slice(indices, { each: data => {
|
||||
|
|
@ -125,9 +126,10 @@ class OpRough extends CamOp {
|
|||
if (data.z > workarea.top_z) {
|
||||
return;
|
||||
}
|
||||
data.shadow = trueShadow ? shadowAt(data.z) : shadow.clone(true);
|
||||
data.shadow = trueShadow ? shadowAt(data.z, lsz) : shadow.clone(true);
|
||||
data.slice.shadow = data.shadow;
|
||||
slices.push(data.slice);
|
||||
lsz = data.z;
|
||||
progress(0.25 + 0.25 * (++cnt / tot));
|
||||
}, progress: (index, total) => {
|
||||
tot = total;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ class OpShadow extends CamOp {
|
|||
super(state, op);
|
||||
}
|
||||
|
||||
weight() {
|
||||
return 0.1;
|
||||
}
|
||||
|
||||
async slice(progress) {
|
||||
let state = this.state;
|
||||
let { ops, slicer, widget, unsafe, addSlices, shadowAt } = state;
|
||||
|
|
|
|||
|
|
@ -107,15 +107,28 @@ class OpTrace extends CamOp {
|
|||
for (let z of zs) {
|
||||
let clip = [], shadow;
|
||||
shadow = shadowAt(z);
|
||||
POLY.subtract([ poly ], shadow, clip, undefined, undefined, 0);
|
||||
// for cases where the shadow IS the poly like
|
||||
// with lettering without a bounding frame, clip
|
||||
// will fail and we need to restore the matching poly
|
||||
let subshadow = true;
|
||||
for (let spo of shadow) {
|
||||
if (poly.isInside(spo, 0.01)) {
|
||||
subshadow = false;
|
||||
clip = [ poly ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (subshadow) {
|
||||
POLY.subtract([ poly ], shadow, clip, undefined, undefined, 0);
|
||||
}
|
||||
if (op.outline) {
|
||||
POLY.clearInner(clip);
|
||||
}
|
||||
if (clip.length === 0) {
|
||||
continue;
|
||||
}
|
||||
let slice = newSliceOut(z);
|
||||
let count = 999;
|
||||
let slice = newSliceOut(z);
|
||||
slice.camTrace = { tool, rate, plunge };
|
||||
if (toolDiam) {
|
||||
const offs = [ -toolDiam / 2, -toolOver ];
|
||||
|
|
@ -132,12 +145,15 @@ class OpTrace extends CamOp {
|
|||
slice.camLines = POLY.flatten(slice.camLines, null, true);
|
||||
}
|
||||
POLY.setWinding(slice.camLines, cutdir, false);
|
||||
slice.output()
|
||||
.setLayer("trace", {line: color}, false)
|
||||
.addPolys(slice.camLines)
|
||||
if (debug && shadow) slice.output()
|
||||
.setLayer("trace shadow", {line: 0xff8811}, false)
|
||||
.addPolys(shadow)
|
||||
if (debug) slice.output()
|
||||
.setLayer("trace poly", {line: 0x1188ff}, false)
|
||||
.addPolys([ poly ])
|
||||
slice.output()
|
||||
.setLayer("trace", {line: color}, false)
|
||||
.addPolys(slice.camLines)
|
||||
progress(zpro, "trace");
|
||||
zpro += zinc;
|
||||
addSlices(slice);
|
||||
|
|
@ -254,6 +270,7 @@ class OpTrace extends CamOp {
|
|||
case "clear":
|
||||
const zbo = widget.track.top - widget.track.box.d;
|
||||
let zmap = {};
|
||||
polys = POLY.nest(polys);
|
||||
for (let poly of polys) {
|
||||
let z = minZ(poly.minZ());
|
||||
if (offover) {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
engageFactor = process.camFullEngage,
|
||||
arcTolerance = process.camArcTolerance,
|
||||
arcRes = toRadians(process.camArcResolution),
|
||||
arcEnabled = process.camArcEnabled && arcTolerance > 0 && arcRes > 0,
|
||||
tolerance = 0,
|
||||
drillDown = 0,
|
||||
drillLift = 0,
|
||||
|
|
@ -177,6 +178,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
}
|
||||
feedRate = feed || feedRate || plunge;
|
||||
plungeRate = Math.min(feedRate || plunge, plunge || plungeRate || feedRate);
|
||||
// console.log({ setTool: toolID, feed, plunge, plungeRate });
|
||||
}
|
||||
|
||||
function setLasering(bool, power = 0) {
|
||||
|
|
@ -241,7 +243,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
camOut(point.clone().setZ(zmax));
|
||||
camOut(point.clone().setZ(zmax_outer));
|
||||
points.forEach(function (point, index) {
|
||||
camOut(point, 1);
|
||||
if (index > 0 && index < points.length - 1) {
|
||||
|
|
@ -249,7 +251,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
if (lift) camOut(point.clone().setZ(point.z + lift), 0);
|
||||
}
|
||||
})
|
||||
camOut(point.clone().setZ(zmax), 0);
|
||||
camOut(point.clone().setZ(zmax_outer), 0);
|
||||
newLayer();
|
||||
}
|
||||
|
||||
|
|
@ -317,7 +319,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
p.x + wmx,
|
||||
p.y + wmy,
|
||||
p.z + zadd
|
||||
)
|
||||
).setA(p.a ?? lastPoint?.a);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -342,7 +344,8 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
// console.log({radius})
|
||||
const isArc = emit == 2 || emit == 3;
|
||||
|
||||
//apply widget movement pos
|
||||
// apply widget movement pos
|
||||
const pointA = point.a;
|
||||
point = applyWidgetMovement(point);
|
||||
|
||||
// console.log(point.z);
|
||||
|
|
@ -354,15 +357,13 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
let rate = feedRate * factor;
|
||||
|
||||
// carry rotation forward when not overridden
|
||||
if (point.a === undefined && lastPoint) {
|
||||
point.a = lastPoint.a;
|
||||
} else if (lastPoint && point.a !== undefined && lastPoint.a !== undefined) {
|
||||
let DA = lastPoint.a - point.a;
|
||||
if (lastPoint && pointA !== undefined && lastPoint.a !== undefined) {
|
||||
let DA = lastPoint.a - pointA;
|
||||
let MZ = Math.max(lastPoint.z, point.z)
|
||||
// find arc length
|
||||
let AL = (Math.abs(DA) / 360) * (2 * Math.PI * MZ);
|
||||
if (AL >= 1) {
|
||||
let lerp = base.util.lerp(lastPoint.a, point.a, 1);
|
||||
let lerp = base.util.lerp(lastPoint.a, pointA, 1);
|
||||
// create interpolated point set for rendering and animation
|
||||
// console.log({ DA, MZ, AL }, lerp.length);
|
||||
for (let a of lerp) {
|
||||
|
|
@ -461,16 +462,27 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
}
|
||||
|
||||
// set new plunge rate
|
||||
if (!lasering && deltaZ < -tolerance && !isLathe) {
|
||||
if (!lasering && !isLathe && deltaZ < -tolerance) {
|
||||
let threshold = Math.min(deltaXY / 2, absDeltaZ),
|
||||
modifier = threshold / absDeltaZ;
|
||||
if (synthPlunge && threshold && modifier && deltaXY > tolerance) {
|
||||
// use modifier to speed up long XY move plunge rates
|
||||
// console.log('modifier', modifier);
|
||||
rate = Math.round(plungeRate + ((feedRate - plungeRate) * modifier));
|
||||
cut = 1;
|
||||
rate = Math.max(
|
||||
plungeRate,
|
||||
Math.round(plungeRate + ((feedRate - plungeRate) * modifier))
|
||||
);
|
||||
} else {
|
||||
rate = 1 / Math.hypot(deltaXY / feedRate, absDeltaZ / plungeRate);
|
||||
let L = Math.hypot(deltaXY, absDeltaZ);
|
||||
let limXY = feedRate * L / deltaXY;
|
||||
let limZ = plungeRate * L / Math.abs(deltaZ);
|
||||
rate = Math.min(feedRate, limXY, limZ);
|
||||
// let zps = len / absDeltaZ;
|
||||
// rate = Math.max(
|
||||
// plungeRate,
|
||||
// 1 / Math.hypot(deltaXY / feedRate, absDeltaZ / plungeRate)
|
||||
// );
|
||||
// console.log({ rate, deltaXY, deltaZ });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -765,7 +777,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
if (indexA == startIndex) {
|
||||
camOut(pointA.clone(), 0, { factor: engageFactor });
|
||||
// if first point, move to and call export function
|
||||
arcQ.push(pointA);
|
||||
if (arcEnabled) arcQ.push(pointA);
|
||||
}
|
||||
lastPoint = arcExport(pointB, pointA);
|
||||
}, !poly.isClosed(), startIndex);
|
||||
|
|
@ -782,7 +794,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
function arcExport(point, lastp) {
|
||||
let dist = lastp ? point.distTo2D(lastp) : 0;
|
||||
if (lastp) {
|
||||
if (dist > lineTolerance && lastp) {
|
||||
if (arcEnabled && dist > lineTolerance && lastp) {
|
||||
let rec = Object.assign(point, { dist });
|
||||
arcQ.push(rec);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,15 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
|||
top_stock, top_part, top_gap, top_z,
|
||||
workarea;
|
||||
|
||||
axisRotation = axisIndex = undefined;
|
||||
dark = settings.controller.dark;
|
||||
color = dark ? 0xbbbbbb : 0;
|
||||
minToolDiam = Infinity;
|
||||
maxToolDiam = -Infinity;
|
||||
tabs = widget.anno.tab;
|
||||
unsafe = proc.camExpertFast;
|
||||
units = settings.controller.units === 'in' ? 25.4 : 1;
|
||||
|
||||
// allow recomputing later if widget or settings changes
|
||||
const var_compute = () => {
|
||||
let { camStockX, camStockY, camStockZ, camStockOffset } = proc;
|
||||
|
|
@ -46,9 +55,9 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
|||
x: camStockX,
|
||||
y: camStockY,
|
||||
z: camStockZ
|
||||
}
|
||||
track = widget.track;
|
||||
};
|
||||
({ camZTop, camZBottom, camZThru } = proc);
|
||||
track = widget.track;
|
||||
wztop = track.top;
|
||||
ztOff = isIndexed ? (stock.z - bounds.dim.z) / 2 : (stock.z - wztop);
|
||||
zbOff = isIndexed ? (stock.z - bounds.dim.z) / 2 : (wztop - track.box.d);
|
||||
|
|
@ -57,14 +66,6 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
|||
zMax = bounds.max.z;
|
||||
zThru = camZThru;
|
||||
zTop = zMax + ztOff;
|
||||
minToolDiam = Infinity;
|
||||
maxToolDiam = -Infinity;
|
||||
dark = !!settings.controller.dark;
|
||||
color = dark ? 0xbbbbbb : 0;
|
||||
tabs = widget.anno.tab;
|
||||
unsafe = proc.camExpertFast;
|
||||
units = settings.controller.units === 'in' ? 25.4 : 1;
|
||||
axisRotation = axisIndex = undefined;
|
||||
part_size = bounds.dim;
|
||||
bottom_gap = zbOff;
|
||||
bottom_part = 0;
|
||||
|
|
@ -223,7 +224,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
|||
}
|
||||
|
||||
function setAxisIndex(degrees = 0, absolute = true) {
|
||||
axisIndex = absolute ? degrees : axisIndex + degrees;
|
||||
axisIndex = absolute ? degrees : (axisIndex || 0) + degrees;
|
||||
axisRotation = (Math.PI / 180) * axisIndex;
|
||||
widget.setAxisIndex(isIndexed ? -axisIndex : 0);
|
||||
return isIndexed ? -axisIndex : 0;
|
||||
|
|
@ -266,10 +267,14 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
|||
|
||||
// silently preface op list with OpShadow
|
||||
if (isIndexed) {
|
||||
if (activeOps.length === 0 || activeOps[0].type !== 'index')
|
||||
if (activeOps.length === 0 || activeOps[0].type !== 'index') {
|
||||
opList.push(new OPS.index(state, { type: "index", index: 0 }));
|
||||
opTot += opList.peek().weight();
|
||||
|
||||
}
|
||||
} else {
|
||||
opList.push(new OPS.shadow(state, { type: "shadow", silent: true }));
|
||||
opTot += opList.peek().weight();
|
||||
}
|
||||
|
||||
// determing # of steps and step weighting for progress bar
|
||||
|
|
@ -399,7 +404,7 @@ export function addDogbones(poly, dist, reverse) {
|
|||
}
|
||||
};
|
||||
|
||||
export async function traces(settings, widget, single) {
|
||||
export async function traces(settings, widget) {
|
||||
if (widget.traces) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -652,7 +657,6 @@ export async function holes(settings, widget, individual, rec, onProgress) {
|
|||
// keeps the z bottom relative to the part when z align changes
|
||||
zBottom = isIndexed ? camZBottom : camZBottom - zbOff;
|
||||
|
||||
|
||||
let slicerOpts = { flatoff: 0.001 }
|
||||
let slicer = new cam_slicer(widget, slicerOpts);
|
||||
let zFlats = Object.keys(slicer.zFlat).map(Number).map(z => [z, z - 0.002]).flat()
|
||||
|
|
@ -920,7 +924,7 @@ export function computeShadowAt(widget, z, ztop) {
|
|||
.add(a[2].x, a[2].y, a[2].z);
|
||||
});
|
||||
|
||||
polys = POLY.union(polys, 0.001, true);
|
||||
polys = POLY.union(polys, 0, true);
|
||||
|
||||
return polys;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ export class Slicer {
|
|||
const max = options.max || Infinity;
|
||||
const len = position.length;
|
||||
const pts = this.points = [];
|
||||
for (let i=0; i<len; ) {
|
||||
for (let i = 0; i < len;) {
|
||||
const x0 = position[i++];
|
||||
const y0 = position[i++];
|
||||
const z0 = position[i++];
|
||||
|
|
@ -57,7 +57,7 @@ export class Slicer {
|
|||
const len = points.length;
|
||||
const min = options.min || -Infinity;
|
||||
const max = options.max || Infinity;
|
||||
for (let i=0; i<len; ) {
|
||||
for (let i = 0; i < len;) {
|
||||
const p0 = points[i++];
|
||||
const p1 = points[i++];
|
||||
const p2 = points[i++];
|
||||
|
|
@ -95,11 +95,11 @@ export class Slicer {
|
|||
if (!under && !both) over = true;
|
||||
|
||||
// iterate over matching buckets for this z offset
|
||||
for (let i = 0; i < points.length; ) {
|
||||
for (let i = 0; i < points.length;) {
|
||||
p1 = points[i++];
|
||||
p2 = points[i++];
|
||||
p3 = points[i++];
|
||||
let where = {under: [], over: [], on: []};
|
||||
let where = { under: [], over: [], on: [] };
|
||||
checkOverUnderOn(p1, z, where);
|
||||
checkOverUnderOn(p2, z, where);
|
||||
checkOverUnderOn(p3, z, where);
|
||||
|
|
@ -130,7 +130,7 @@ export class Slicer {
|
|||
if (line.length === 2) {
|
||||
lines.push(makeZLine(phash, line[0], line[1]));
|
||||
} else {
|
||||
console.log({msg: "invalid ips", line: line, where: where});
|
||||
console.log({ msg: "invalid ips", line: line, where: where });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -210,7 +210,7 @@ function getCachedPoint(phash, p) {
|
|||
function makeZLine(phash, p1, p2, coplanar, edge) {
|
||||
p1 = getCachedPoint(phash, p1);
|
||||
p2 = getCachedPoint(phash, p2);
|
||||
let line = newOrderedLine(p1,p2);
|
||||
let line = newOrderedLine(p1, p2);
|
||||
line.coplanar = coplanar || false;
|
||||
line.edge = edge || false;
|
||||
return line;
|
||||
|
|
@ -243,7 +243,7 @@ function removeDuplicateLines(lines, debug) {
|
|||
|
||||
function addLinesToPoint(point, line) {
|
||||
cachePoint(point);
|
||||
if (!point.group) point.group = [ line ];
|
||||
if (!point.group) point.group = [line];
|
||||
else point.group.push(line);
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +261,7 @@ function removeDuplicateLines(lines, debug) {
|
|||
});
|
||||
|
||||
// associate points with their lines, cull deleted
|
||||
lines.forEach(function(line) {
|
||||
lines.forEach(function (line) {
|
||||
if (!line.del) {
|
||||
tmplines.push(line);
|
||||
addLinesToPoint(line.p1, line);
|
||||
|
|
@ -270,7 +270,7 @@ function removeDuplicateLines(lines, debug) {
|
|||
});
|
||||
|
||||
// merge collinear lines
|
||||
points.forEach(function(point) {
|
||||
points.forEach(function (point) {
|
||||
if (point.group.length != 2) return;
|
||||
let l1 = point.group[0],
|
||||
l2 = point.group[1];
|
||||
|
|
@ -280,7 +280,7 @@ function removeDuplicateLines(lines, debug) {
|
|||
// find new endpoints that are not shared point
|
||||
let p1 = l1.p1 != point ? l1.p1 : l1.p2,
|
||||
p2 = l2.p1 != point ? l2.p1 : l2.p2,
|
||||
newline = newOrderedLine(p1,p2);
|
||||
newline = newOrderedLine(p1, p2);
|
||||
// remove deleted lines from associated points
|
||||
p1.group.remove(l1);
|
||||
p1.group.remove(l2);
|
||||
|
|
@ -307,7 +307,7 @@ function removeDuplicateLines(lines, debug) {
|
|||
});
|
||||
|
||||
// create new line array culling deleted
|
||||
tmplines.forEach(function(line) {
|
||||
tmplines.forEach(function (line) {
|
||||
if (!line.del) {
|
||||
output.push(line);
|
||||
line.p1.group = null;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
const HPI = Math.PI/2;
|
||||
const RAD2DEG = 180/Math.PI;
|
||||
const HPI = Math.PI / 2;
|
||||
const RAD2DEG = 180 / Math.PI;
|
||||
|
||||
class Tool {
|
||||
constructor(settings, id, number) {
|
||||
|
|
@ -102,7 +102,7 @@ class Tool {
|
|||
return this.tool.type === "tapermill";
|
||||
}
|
||||
|
||||
isDrill(){
|
||||
isDrill() {
|
||||
return this.tool.type === "drill";
|
||||
}
|
||||
|
||||
|
|
@ -162,8 +162,8 @@ class Tool {
|
|||
// z_offset = (1 - Math.cos((dist_from_center / flute_radius_pix_float) * HPI)) * -flute_radius;
|
||||
} else if (taper && dist_from_center >= tip_radius_pix_float) {// if tapered and not in the flat tip radius
|
||||
z_offset = ((dist_from_center - tip_radius_pix_float) / tip_max_radius_offset) * -shaft_offset;
|
||||
}else if(drill){
|
||||
z_offset = -dist_from_center /45;
|
||||
} else if (drill) {
|
||||
z_offset = -dist_from_center / 45;
|
||||
}
|
||||
toolOffset.push(dx, dy, z_offset);
|
||||
} else if (shaft_offset && larger_shaft && dist_from_center <= shaft_radius_pix_float) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { Tool } from './tool.js';
|
|||
const RAD2DEG = 180 / Math.PI;
|
||||
const DEG2RAD = Math.PI / 180;
|
||||
|
||||
class Topo {
|
||||
export class Topo {
|
||||
constructor() { }
|
||||
|
||||
async generate(opt = {}) {
|
||||
|
|
@ -37,7 +37,7 @@ class Topo {
|
|||
boundsY = maxY - minY,
|
||||
inside = contour.inside,
|
||||
density = 1 + (contour.reduction || 0),
|
||||
resolution = tolerance ? tolerance : 1/Math.sqrt(animesh/(boundsX * boundsY)),
|
||||
resolution = tolerance ? tolerance : 1 / Math.sqrt(animesh / (boundsX * boundsY)),
|
||||
tool = new Tool(settings, contour.tool),
|
||||
toolOffset = tool.generateProfile(resolution).profile,
|
||||
toolDiameter = tool.fluteDiameter(),
|
||||
|
|
@ -68,11 +68,11 @@ class Topo {
|
|||
},
|
||||
data = topo.data,
|
||||
newslices = [],
|
||||
tabsMax = tabs ? Math.max(...tabs.map(tab => tab.dim.z/2 + tab.pos.z)) : 0,
|
||||
tabsMax = tabs ? Math.max(...tabs.map(tab => tab.dim.z / 2 + tab.pos.z)) : 0,
|
||||
tabsOn = tabs,
|
||||
tabHeight = Math.max(process.camTabsHeight + zBottom, tabsMax),
|
||||
clipTab = tabsOn ? [] : null,
|
||||
clipTo = inside ? shadow : POLY.expand(shadow, toolDiameter/2 + resolution * 3),
|
||||
clipTo = inside ? shadow : POLY.expand(shadow, toolDiameter / 2 + resolution * 3),
|
||||
partOff = inside ? 0 : toolDiameter / 2 + resolution,
|
||||
gridDelta = Math.floor(partOff / resolution),
|
||||
debug = false,
|
||||
|
|
@ -92,8 +92,8 @@ class Topo {
|
|||
|
||||
if (tabs) {
|
||||
clipTab.appendAll(tabs.map(tab => {
|
||||
let ctab = POLY.expand([tab.poly], toolDiameter/2);
|
||||
ctab.forEach(ct => ct.z = tab.dim.z/2 + tab.pos.z);
|
||||
let ctab = POLY.expand([tab.poly], toolDiameter / 2);
|
||||
ctab.forEach(ct => ct.z = tab.dim.z / 2 + tab.pos.z);
|
||||
return ctab;
|
||||
}).flat());
|
||||
}
|
||||
|
|
@ -197,7 +197,7 @@ class Topo {
|
|||
const range = { min: Infinity, max: -Infinity };
|
||||
|
||||
// swap XZ in shared array
|
||||
for (let i=0,l=vertices.length; i<l; i += 3) {
|
||||
for (let i = 0, l = vertices.length; i < l; i += 3) {
|
||||
const x = vertices[i];
|
||||
const z = vertices[i + 2];
|
||||
vertices[i] = z;
|
||||
|
|
@ -226,9 +226,11 @@ class Topo {
|
|||
// define sharded ranges
|
||||
if (minions.running > 1) {
|
||||
|
||||
dispatch.putCache({ key: widget.id, data: vertices }, { done: data => {
|
||||
// console.log({ put_cache_done: data });
|
||||
}});
|
||||
dispatch.putCache({ key: widget.id, data: vertices }, {
|
||||
done: data => {
|
||||
// console.log({ put_cache_done: data });
|
||||
}
|
||||
});
|
||||
|
||||
let promises = slices.map(slice => {
|
||||
return new Promise(resolve => {
|
||||
|
|
@ -256,9 +258,11 @@ class Topo {
|
|||
return box2;
|
||||
});
|
||||
|
||||
dispatch.clearCache({}, { done: data => {
|
||||
// console.log({ clear_cache_done: data });
|
||||
}});
|
||||
dispatch.clearCache({}, {
|
||||
done: data => {
|
||||
// console.log({ clear_cache_done: data });
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -340,8 +344,8 @@ class Topo {
|
|||
let promise = new Promise(resolve => {
|
||||
resolver = () => {
|
||||
// sort output slices (required for async)
|
||||
slicesY.sort((a,b) => a.z - b.z);
|
||||
slicesX.sort((a,b) => a.z - b.z);
|
||||
slicesY.sort((a, b) => a.z - b.z);
|
||||
slicesX.sort((a, b) => a.z - b.z);
|
||||
newslices.appendAll(slicesY);
|
||||
newslices.appendAll(slicesX);
|
||||
resolve();
|
||||
|
|
@ -369,7 +373,7 @@ class Topo {
|
|||
let slice = newSlice(gridx);
|
||||
slice.camLines = segments;
|
||||
slice.output()
|
||||
.setLayer("contour y", {face: color, line: color})
|
||||
.setLayer("contour y", { face: color, line: color })
|
||||
.addPolys(segments);
|
||||
slicesY.push(slice);
|
||||
}
|
||||
|
|
@ -398,7 +402,7 @@ class Topo {
|
|||
let slice = newSlice(gridy);
|
||||
slice.camLines = segments;
|
||||
slice.output()
|
||||
.setLayer("contour x", {face: color, line: color})
|
||||
.setLayer("contour x", { face: color, line: color })
|
||||
.addPolys(segments);
|
||||
slicesX.push(slice);
|
||||
}
|
||||
|
|
@ -431,7 +435,7 @@ export class Probe {
|
|||
this.params = params;
|
||||
|
||||
// return the touching z given topo x,y and a tool profile
|
||||
const toolAtZ = this.toolAtZ = function(x,y) {
|
||||
const toolAtZ = this.toolAtZ = function (x, y) {
|
||||
let sx = stepsX,
|
||||
sy = stepsY,
|
||||
xl = sx - 1,
|
||||
|
|
@ -461,13 +465,13 @@ export class Probe {
|
|||
// export z probe function
|
||||
const rx = stepsX / boundsX;
|
||||
const ry = stepsX / boundsX;
|
||||
const toolAtXY = this.toolAtXY = function(px, py) {
|
||||
const toolAtXY = this.toolAtXY = function (px, py) {
|
||||
px = Math.round(rx * (px - minX));
|
||||
py = Math.round(ry * (py - minY));
|
||||
return toolAtZ(px, py);
|
||||
};
|
||||
|
||||
const zAtXY = this.zAtXY = function(px, py) {
|
||||
const zAtXY = this.zAtXY = function (px, py) {
|
||||
let ix = Math.round(rx * (px - minX));
|
||||
let iy = Math.round(ry * (py - minY));
|
||||
return data[ix * stepsY + iy] || zMin;
|
||||
|
|
@ -496,11 +500,11 @@ export class Trace {
|
|||
this.slice = slice = [];
|
||||
}
|
||||
|
||||
const newtrace = this.newtrace = function() {
|
||||
const newtrace = this.newtrace = function () {
|
||||
trace = newPolygon().setOpen();
|
||||
}
|
||||
|
||||
const end_poly = this.end_poly = function(point) {
|
||||
const end_poly = this.end_poly = function (point) {
|
||||
if (latent) {
|
||||
trace.push(latent);
|
||||
}
|
||||
|
|
@ -520,7 +524,7 @@ export class Trace {
|
|||
}
|
||||
}
|
||||
|
||||
const log = function(map) {
|
||||
const log = function (map) {
|
||||
for (let key in map) {
|
||||
const val = map[key];
|
||||
if (typeof val === 'number') {
|
||||
|
|
@ -530,7 +534,7 @@ export class Trace {
|
|||
console.log(...arguments);
|
||||
}
|
||||
|
||||
const push_point = this.push_point = function(x, y, z) {
|
||||
const push_point = this.push_point = function (x, y, z) {
|
||||
const newP = newPoint(x, y, z);
|
||||
const lastP = lastPP;//trace.last();
|
||||
|
||||
|
|
@ -550,7 +554,7 @@ export class Trace {
|
|||
if (curvesOnly) {
|
||||
const dv = contourX ? Math.abs(lastP.x - x) : Math.abs(lastP.y - y);
|
||||
// const dz = lastPP.z - z;
|
||||
const angle = Math.atan2( Math.abs(dz), dv) * RAD2DEG;
|
||||
const angle = Math.atan2(Math.abs(dz), dv) * RAD2DEG;
|
||||
if (angle > maxangle) {
|
||||
end_poly();
|
||||
}
|
||||
|
|
@ -568,7 +572,7 @@ export class Trace {
|
|||
const object = this.object = this;
|
||||
|
||||
this.inClip = function (clips, checkZ, point) {
|
||||
for (let i=0; i<clips.length; i++) {
|
||||
for (let i = 0; i < clips.length; i++) {
|
||||
let poly = clips[i];
|
||||
let zok = checkZ ? checkZ <= poly.z : true;
|
||||
object.tabZ = poly.z;
|
||||
|
|
@ -590,9 +594,9 @@ export class Trace {
|
|||
// in this case, z is appended to clip tabs in topo constructor
|
||||
// we pass it as a side-channel and re-consitute here
|
||||
if (clipTab)
|
||||
for (let i=0, l=clipTab.length; i<l; i++) {
|
||||
clipTab[i].z = clipTabZ[i];
|
||||
}
|
||||
for (let i = 0, l = clipTab.length; i < l; i++) {
|
||||
clipTab[i].z = clipTabZ[i];
|
||||
}
|
||||
|
||||
if (minions && this.cross.concurrent) {
|
||||
minions.broadcast("trace_init", codec.encode({
|
||||
|
|
@ -649,7 +653,7 @@ export class Trace {
|
|||
let { from, to, x, gridx, gridy } = params;
|
||||
|
||||
const step = resolution * density;
|
||||
const checkr = newPoint(0,0);
|
||||
const checkr = newPoint(0, 0);
|
||||
newslice();
|
||||
newtrace();
|
||||
for (let y = from; y < to; y += step) {
|
||||
|
|
@ -687,7 +691,7 @@ export class Trace {
|
|||
let { from, to, y, gridx, gridy } = params;
|
||||
|
||||
const step = resolution * density;
|
||||
const checkr = newPoint(0,0);
|
||||
const checkr = newPoint(0, 0);
|
||||
newslice();
|
||||
newtrace();
|
||||
for (let x = from; x < to; x += step) {
|
||||
|
|
@ -734,7 +738,7 @@ export function raster_slice(inputs) {
|
|||
// emit an array of valid line-pairs
|
||||
const len = lines.length;
|
||||
|
||||
outer: for (let i=0; i<len; i++) {
|
||||
outer: for (let i = 0; i < len; i++) {
|
||||
let l1 = lines[i], p1 = l1.p1, p2 = l1.p2;
|
||||
// eliminate vertical
|
||||
if (Math.abs(p1.y - p2.y) < flatness) continue;
|
||||
|
|
@ -743,14 +747,14 @@ export function raster_slice(inputs) {
|
|||
// sort p1,p2 by y for comparison
|
||||
if (p1.y > p2.y) { const tp = p1; p1 = p2; p2 = tp };
|
||||
// eliminate if points "under" other lines
|
||||
for (let j=0; j<len; j++) {
|
||||
for (let j = 0; j < len; j++) {
|
||||
// skip self and adjacent
|
||||
if (j >= i-1 && j <= i+1) continue;
|
||||
if (j >= i - 1 && j <= i + 1) continue;
|
||||
let l2 = lines[j], p3 = l2.p1, p4 = l2.p2;
|
||||
// sort p3,p4 by y for comparison
|
||||
if (p3.y > p4.y) { const tp = p3; p3 = p4; p4 = tp };
|
||||
// it's under the other line
|
||||
if (Math.max(p1.z,p2.z) < Math.min(p3.z,p4.z)) {
|
||||
if (Math.max(p1.z, p2.z) < Math.min(p3.z, p4.z)) {
|
||||
// it's inside the other line, too, so skip
|
||||
if (p1.y >= p3.y && p2.y <= p4.y) continue outer;
|
||||
}
|
||||
|
|
@ -766,8 +770,8 @@ export function raster_slice(inputs) {
|
|||
gridi = gridx * stepsY + gridy;
|
||||
gridv = data[gridi] || zMin;
|
||||
// strategy using raw lines (faster slice, but more lines)
|
||||
for (i=0, il=points.length; i<il; i += 2) {
|
||||
const p1 = points[i], p2 = points[i+1];
|
||||
for (i = 0, il = points.length; i < il; i += 2) {
|
||||
const p1 = points[i], p2 = points[i + 1];
|
||||
// one endpoint above grid
|
||||
const crossz = (p1.z > gridv || p2.z > gridv);
|
||||
// segment crosses grid y
|
||||
|
|
@ -783,7 +787,7 @@ export function raster_slice(inputs) {
|
|||
if (nz > gridv) {
|
||||
gridv = data[gridi] = Math.max(nz, zMin);
|
||||
if (slice) slice.output()
|
||||
.setLayer("heights", {face: 0, line: 0})
|
||||
.setLayer("heights", { face: 0, line: 0 })
|
||||
.addLine(
|
||||
newPoint(p1.x, y, 0),
|
||||
newPoint(p1.x, y, gridv)
|
||||
|
|
@ -797,9 +801,9 @@ export function raster_slice(inputs) {
|
|||
// remove flat lines when curvesOnly
|
||||
if (curvesOnly) {
|
||||
let nup = [];
|
||||
for (let i=0, p=points, l=p.length; i<l; i += 2) {
|
||||
for (let i = 0, p = points, l = p.length; i < l; i += 2) {
|
||||
const p1 = p[i];
|
||||
const p2 = p[i+1];
|
||||
const p2 = p[i + 1];
|
||||
if (Math.abs(p1.z - p2.z) >= flatness) {
|
||||
nup.push(p1, p2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { codec } from '../../core/codec.js';
|
|||
import { newPoint } from '../../../geo/point.js';
|
||||
import { newPolygon } from '../../../geo/polygon.js';
|
||||
import { sliceConnect } from '../../../geo/slicer.js';
|
||||
import { newSlice } from '../../core/slice.js';
|
||||
import { Tool } from './tool.js';
|
||||
import { Slicer as topo_slicer } from './slicer_topo.js';
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ function scale(fn, factor = 1, base = 0) {
|
|||
}
|
||||
}
|
||||
|
||||
class Topo4 {
|
||||
export class Topo {
|
||||
constructor() { }
|
||||
|
||||
async generate(opt = {}) {
|
||||
|
|
@ -91,7 +92,7 @@ class Topo4 {
|
|||
const box = this.box = new THREE.Box2();
|
||||
|
||||
// swap XZ in shared array
|
||||
for (let i=0, l=vertices.length; i<l; i += 3) {
|
||||
for (let i = 0, l = vertices.length; i < l; i += 3) {
|
||||
const x = vertices[i];
|
||||
const z = vertices[i + 2] + zoff;
|
||||
vertices[i] = z;
|
||||
|
|
@ -105,7 +106,7 @@ class Topo4 {
|
|||
range.max += this.diam / 2;
|
||||
|
||||
// merge in tab vertices here so they don't affect slice range / dimensions
|
||||
for (let i=0, l=tabverts.length; i<l; i += 3) {
|
||||
for (let i = 0, l = tabverts.length; i < l; i += 3) {
|
||||
const x = tabverts[i];
|
||||
const z = tabverts[i + 2] + zoff;
|
||||
tabverts[i] = z;
|
||||
|
|
@ -132,7 +133,8 @@ class Topo4 {
|
|||
slices.push(slice);
|
||||
// console.log({ shards, range, step, slices });
|
||||
|
||||
if (kiri.minions.running > 1) {
|
||||
const { minions } = self.kiri_worker;
|
||||
if (minions?.running > 1) {
|
||||
return await this.sliceMinions(onupdate);
|
||||
} else {
|
||||
return await this.sliceWorker(onupdate);
|
||||
|
|
@ -158,7 +160,7 @@ class Topo4 {
|
|||
slice.index = rec.index;
|
||||
slice.addTops(sliceConnect(rec.lines));
|
||||
|
||||
const points = codec.encodePointArray(rec.lines.map(l => [ l.p1, l.p2 ]).flat());
|
||||
const points = codec.encodePointArray(rec.lines.map(l => [l.p1, l.p2]).flat());
|
||||
const shared = new Float32Array(new SharedArrayBuffer(points.length * 4));
|
||||
shared.set(points);
|
||||
slice.shared = shared;
|
||||
|
|
@ -166,7 +168,7 @@ class Topo4 {
|
|||
return slice;
|
||||
});
|
||||
output.appendAll(recs);
|
||||
onupdate(++complete /slices.length);
|
||||
onupdate(++complete / slices.length);
|
||||
}
|
||||
|
||||
return output;
|
||||
|
|
@ -195,14 +197,15 @@ class Topo4 {
|
|||
.map(rec => newSlice(rec.z)
|
||||
.addTops(rec.polys)
|
||||
.setFields({ shared: rec.shared }))
|
||||
.sort((a,b) => a.z - b.z);
|
||||
.sort((a, b) => a.z - b.z);
|
||||
|
||||
clearCache();
|
||||
return output;
|
||||
}
|
||||
|
||||
async lathe(onupdate) {
|
||||
if (kiri.minions.running > 1) {
|
||||
const { minions } = self.kiri_worker;
|
||||
if (minions?.running > 1) {
|
||||
return await this.latheMinions(onupdate);
|
||||
} else {
|
||||
return await this.latheWorker(onupdate);
|
||||
|
|
@ -223,7 +226,7 @@ class Topo4 {
|
|||
const lines = slice.lines;
|
||||
const plen = lines.length;
|
||||
const rec = { z: slice.z, lines: [] };
|
||||
for (let i = 0; i < plen; ) {
|
||||
for (let i = 0; i < plen;) {
|
||||
++i; // skip x which should match slice.z
|
||||
let py0 = lines[i++];
|
||||
const pz0 = lines[i++];
|
||||
|
|
@ -245,7 +248,7 @@ class Topo4 {
|
|||
const rx = oslices[si].z;
|
||||
let mz = -Infinity;
|
||||
// iterate over tool offsets
|
||||
for (let ti = 0; ti < tlen; ) {
|
||||
for (let ti = 0; ti < tlen;) {
|
||||
// tool offset in grid units from present x (si)
|
||||
const xo = tool[ti++]; // x grid offset (slice)
|
||||
const yo = tool[ti++] * resolution; // y grid offset (mult rez to get real y)
|
||||
|
|
@ -259,7 +262,7 @@ class Topo4 {
|
|||
const slice = oslices[ts];
|
||||
const lines = slice.lines;
|
||||
const plen = lines.length;
|
||||
for (let i = 0; i < plen; ) {
|
||||
for (let i = 0; i < plen;) {
|
||||
++i; // skip x which should match slice.z
|
||||
let py0 = lines[i++];
|
||||
const pz0 = lines[i++];
|
||||
|
|
@ -293,7 +296,7 @@ class Topo4 {
|
|||
}
|
||||
|
||||
async latheWorker(onupdate) {
|
||||
const { sliced, tool, zoff, leave } = this;
|
||||
const { sliced, tool, zoff, leave, linear } = this;
|
||||
|
||||
const rota = this.angle * DEG2RAD;
|
||||
const steps = (Math.PI * 2) / rota;
|
||||
|
|
@ -316,19 +319,32 @@ class Topo4 {
|
|||
onupdate(count / steps);
|
||||
}
|
||||
|
||||
count = recs[0].heights.length / 3;
|
||||
count = linear ? recs.length : recs[0].heights.length / 3;
|
||||
// count = recs[0].heights.length / 3;
|
||||
while (count-- > 0) {
|
||||
let slice = newSlice(count);
|
||||
slice.camLines = [ newPolygon().setOpen() ];
|
||||
slice.camLines = [newPolygon().setOpen()];
|
||||
paths.push(slice);
|
||||
}
|
||||
|
||||
for (let rec of recs) {
|
||||
const { degrees, heights } = rec;
|
||||
[...heights].group(3).forEach((a,i) => {
|
||||
// progress each path 360 degrees to prevent A rolling backwards
|
||||
paths[i].camLines[0].push( newPoint(a[0], a[1], a[2] + leave).setA(degrees + i * -360) );
|
||||
if (linear) {
|
||||
recs.forEach((rec, i) => {
|
||||
const { degrees, heights } = rec;
|
||||
[...heights].group(3).forEach((a) => {
|
||||
paths[i].camLines[0].push(newPoint(a[0], a[1], a[2] + leave).setA(degrees));
|
||||
});
|
||||
if (i % 2 === 1) {
|
||||
paths[i].camLines[0].reverse();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (let rec of recs) {
|
||||
const { degrees, heights } = rec;
|
||||
[...heights].group(3).forEach((a, i) => {
|
||||
// progress each path 360 degrees to prevent A rolling backwards
|
||||
paths[i].camLines[0].push(newPoint(a[0], a[1], a[2] + leave).setA(degrees + i * -360));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (let slice of paths) {
|
||||
|
|
@ -342,7 +358,7 @@ class Topo4 {
|
|||
slice.camLines[0].push(repeat.clone().setA(repeat.a - 360));
|
||||
slice.output()
|
||||
.setLayer("lathe", { line: this.lineColor })
|
||||
.addPoly(poly.clone().applyRotations().move({ z: -zoff, x:0, y:0 }));
|
||||
.addPoly(poly.clone().applyRotations().move({ z: -zoff, x: 0, y: 0 }));
|
||||
}
|
||||
|
||||
// console.log({ tool, slices, paths });
|
||||
|
|
@ -392,20 +408,18 @@ class Topo4 {
|
|||
await Promise.all(promises);
|
||||
recs.sort((a, b) => { return b.angle - a.angle });
|
||||
|
||||
// let linear = true;
|
||||
|
||||
count = linear ? recs.length : recs[0].heights.length / 3;
|
||||
while (count-- > 0) {
|
||||
let slice = newSlice(count);
|
||||
slice.camLines = [ newPolygon().setOpen() ];
|
||||
slice.camLines = [newPolygon().setOpen()];
|
||||
paths.push(slice);
|
||||
}
|
||||
|
||||
if (linear) {
|
||||
recs.forEach((rec,i) => {
|
||||
recs.forEach((rec, i) => {
|
||||
const { degrees, heights } = rec;
|
||||
[...heights].group(3).forEach((a) => {
|
||||
paths[i].camLines[0].push( newPoint(a[0], a[1], a[2] + leave).setA(degrees) );
|
||||
paths[i].camLines[0].push(newPoint(a[0], a[1], a[2] + leave).setA(degrees));
|
||||
});
|
||||
if (i % 2 === 1) {
|
||||
paths[i].camLines[0].reverse();
|
||||
|
|
@ -414,9 +428,9 @@ class Topo4 {
|
|||
} else {
|
||||
for (let rec of recs) {
|
||||
const { degrees, heights } = rec;
|
||||
[...heights].group(3).forEach((a,i) => {
|
||||
[...heights].group(3).forEach((a, i) => {
|
||||
// progress each path 360 degrees to prevent A rolling backwards
|
||||
paths[i].camLines[0].push( newPoint(a[0], a[1], a[2] + leave).setA(degrees + i * -360) );
|
||||
paths[i].camLines[0].push(newPoint(a[0], a[1], a[2] + leave).setA(degrees + i * -360));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -434,7 +448,7 @@ class Topo4 {
|
|||
}
|
||||
slice.output()
|
||||
.setLayer("lathe", { line: this.lineColor })
|
||||
.addPoly(poly.clone().applyRotations().move({ z: -zoff, x:0, y:0 }));
|
||||
.addPoly(poly.clone().applyRotations().move({ z: -zoff, x: 0, y: 0 }));
|
||||
}
|
||||
|
||||
// console.log({ tool, slices, paths });
|
||||
|
|
@ -444,24 +458,27 @@ class Topo4 {
|
|||
}
|
||||
|
||||
putCache(key, data) {
|
||||
kiri.worker.putCache({ key, data }, { done: data => { } });
|
||||
const { dispatch } = self.kiri_worker;
|
||||
dispatch.putCache({ key, data }, { done: data => { } });
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
kiri.worker.clearCache({}, { done: data => { } });
|
||||
const { dispatch } = self.kiri_worker;
|
||||
dispatch.clearCache({}, { done: data => { } });
|
||||
}
|
||||
|
||||
queue(cmd, params) {
|
||||
const { minions } = self.kiri_worker;
|
||||
return new Promise(resolve => {
|
||||
kiri.minions.queue({ cmd, ...params }, resolve);
|
||||
minions.queue({ cmd, ...params }, resolve);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function rotatePoints(lines, rot) {
|
||||
export function rotatePoints(lines, rot) {
|
||||
new THREE.BufferAttribute(lines, 3).applyMatrix4(rot);
|
||||
}
|
||||
|
||||
export function Topo4(opt) {
|
||||
return new Topo4().generate(opt);
|
||||
export async function generate(opt) {
|
||||
return new Topo().generate(opt);
|
||||
};
|
||||
|
|
|
|||
188
src/kiri/mode/fdm/init-menu.js
Normal file
188
src/kiri/mode/fdm/init-menu.js
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from '../../core/api.js';
|
||||
|
||||
let LANG = api.language.current;
|
||||
let { FDM } = api.const.MODES,
|
||||
{ $ } = api.web,
|
||||
{ uc, ui } = api,
|
||||
{ bound, toInt, toFloat } = uc,
|
||||
{ newBlank, newButton, newBoolean, newGroup, newInput, newSelect, newRow } = uc,
|
||||
driven = true,
|
||||
hideable = true,
|
||||
separator = true,
|
||||
trigger = true
|
||||
;
|
||||
|
||||
function onBooleanClick(el) {
|
||||
api.event.emit('click.boolean', el);
|
||||
}
|
||||
|
||||
function onButtonClick(el) {
|
||||
api.event.emit('click.button', el);
|
||||
}
|
||||
|
||||
function thinWallSave() {
|
||||
let opt = ui.sliceDetectThin;
|
||||
let level = opt.options[opt.selectedIndex];
|
||||
if (level) {
|
||||
api.conf.get().process.sliceDetectThin = level.value;
|
||||
api.conf.save();
|
||||
}
|
||||
}
|
||||
|
||||
function isMultiHead() {
|
||||
let dev = api.conf.get().device;
|
||||
return isNotBelt() && dev.extruders && dev.extruders.length > 1;
|
||||
}
|
||||
|
||||
function optSelected(sel) {
|
||||
let opt = sel.options[sel.selectedIndex];
|
||||
return opt ? opt.value : undefined;
|
||||
}
|
||||
|
||||
function hasInfill() {
|
||||
return optSelected(ui.sliceFillType) !== 'none'
|
||||
}
|
||||
|
||||
function fillIsLinear() {
|
||||
return hasInfill() && optSelected(ui.sliceFillType) === 'linear';
|
||||
}
|
||||
|
||||
function zIntShow() {
|
||||
return settings().controller.devel;
|
||||
}
|
||||
|
||||
function isBelt() {
|
||||
return api.device.isBelt();
|
||||
}
|
||||
|
||||
function isNotBelt() {
|
||||
return !isBelt();
|
||||
}
|
||||
|
||||
export function menu() {
|
||||
|
||||
return {
|
||||
|
||||
/** Left Side Menu */
|
||||
|
||||
_____: newGroup(LANG.sl_menu, $('fdm-layers'), { modes:FDM, driven, hideable, separator, group:"fdm-layers" }),
|
||||
sliceHeight: newInput(LANG.sl_lahi_s, { title:LANG.sl_lahi_l, convert:toFloat }),
|
||||
sliceMinHeight: newInput(LANG.ad_minl_s, { title:LANG.ad_minl_l, convert:toFloat, bound:bound(0,3.0), show:() => ui.sliceAdaptive.checked }),
|
||||
sliceTopLayers: newInput(LANG.sl_ltop_s, { title:LANG.sl_ltop_l, convert:toInt }),
|
||||
sliceBottomLayers: newInput(LANG.sl_lbot_s, { title:LANG.sl_lbot_l, convert:toInt }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceAdaptive: newBoolean(LANG.ad_adap_s, onBooleanClick, { title: LANG.ad_adap_l }),
|
||||
_____: newGroup(LANG.sw_menu, $('fdm-walls'), { modes:FDM, driven, hideable, separator, group:"fdm-walls" }),
|
||||
sliceShells: newInput(LANG.sl_shel_s, { title:LANG.sl_shel_l, convert:toFloat }),
|
||||
sliceLineWidth: newInput(LANG.sl_line_s, { title:LANG.sl_line_l, convert:toFloat, bound:bound(0,5) }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceShellOrder: newSelect(LANG.sl_ordr_s, { title:LANG.sl_ordr_l}, "shell"),
|
||||
sliceDetectThin: newSelect(LANG.ad_thin_s, { title: LANG.ad_thin_l, action: thinWallSave }, "thin"),
|
||||
outputAlternating: newBoolean(LANG.ad_altr_s, onBooleanClick, {title:LANG.ad_altr_l}),
|
||||
sliceZInterleave: newBoolean(LANG.ad_zint_s, onBooleanClick, {title:LANG.ad_zint_l, show:zIntShow}),
|
||||
_____: newGroup(LANG.fi_menu, $('fdm-fill'), { modes:FDM, driven, hideable, separator, group:"fdm-fill" }),
|
||||
sliceFillType: newSelect(LANG.fi_type, {trigger}, "infill"),
|
||||
sliceFillSparse: newInput(LANG.fi_pcnt_s, {title:LANG.fi_pcnt_l, convert:toFloat, bound:bound(0.0,1.0), show:hasInfill}),
|
||||
sliceFillRepeat: newInput(LANG.fi_rept_s, {title:LANG.fi_rept_l, convert:toInt, bound:bound(1,10), show:fillIsLinear}),
|
||||
sliceFillOverlap: newInput(LANG.fi_over_s, {title:LANG.fi_over_l, convert:toFloat, bound:bound(0.0,2.0), show:hasInfill}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceFillRate: newInput(LANG.ou_feed_s, {title:LANG.ou_feed_l, convert:toInt, bound:bound(0,500)}),
|
||||
sliceSolidRate: newInput(LANG.ou_fini_s, {title:LANG.ou_fini_l, convert:toInt, bound:bound(0,500)}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceFillGrow: newInput(LANG.fi_grow_s, {title:LANG.fi_grow_l, convert:toFloat}),
|
||||
sliceFillAngle: newInput(LANG.fi_angl_s, {title:LANG.fi_angl_l, convert:toFloat}),
|
||||
_____: newGroup(LANG.fh_menu, $('fdm-heat'), { modes:FDM, driven, hideable, separator, group:"fdm-heat" }),
|
||||
outputTemp: newInput(LANG.ou_nozl_s, {title:LANG.ou_nozl_l, convert:toInt}),
|
||||
outputBedTemp: newInput(LANG.ou_bedd_s, {title:LANG.ou_bedd_l, convert:toInt}),
|
||||
_____: newGroup(LANG.fc_menu, $('fdm-cool'), { modes:FDM, driven, hideable, separator, group:"fdm-cool" }),
|
||||
outputFanLayer: newInput(LANG.ou_fanl_s, { title:LANG.ou_fanl_l, convert:toInt, bound:bound(0,255) }),
|
||||
outputFanSpeed: newInput(LANG.ou_fans_s, {title:LANG.ou_fans_l, convert:toInt, bound:bound(0,255)}),
|
||||
_____: newGroup(LANG.sp_menu, $('fdm-support'), { modes:FDM, driven, hideable, separator, group:"fdm-supp" }),
|
||||
sliceSupportNozzle: newSelect(LANG.sp_nozl_s, {title:LANG.sp_nozl_l, show:isMultiHead}, "extruders"),
|
||||
sliceSupportDensity: newInput(LANG.sp_dens_s, {title:LANG.sp_dens_l, convert:toFloat, bound:bound(0.0,1.0)}),
|
||||
sliceSupportSize: newInput(LANG.sp_size_s, {title:LANG.sp_size_l, convert:toFloat, bound:bound(1.0,200.0)}),
|
||||
sliceSupportOffset: newInput(LANG.sp_offs_s, {title:LANG.sp_offs_l, convert:toFloat, bound:bound(0.0,200.0)}),
|
||||
sliceSupportGap: newInput(LANG.sp_gaps_s, {title:LANG.sp_gaps_l, convert:toInt, bound:bound(0,5)}),
|
||||
sliceSupportArea: newInput(LANG.sp_area_s, {title:LANG.sp_area_l, convert:toFloat, bound:bound(0.0,200.0)}),
|
||||
sliceSupportExtra: newInput(LANG.sp_xpnd_s, {title:LANG.sp_xpnd_l, convert:toFloat, bound:bound(0.0,10.0)}),
|
||||
sliceSupportGrow: newInput(LANG.sp_grow_s, {title:LANG.sp_grow_l, convert:toFloat, bound:bound(0.0,10.0)}),
|
||||
sliceSupportAngle: newInput(LANG.sp_angl_s, {title:LANG.sp_angl_l, convert:toFloat, bound:bound(0.0,90.0)}),
|
||||
sliceSupportSpan: newInput(LANG.sp_span_s, {title:LANG.sp_span_l, convert:toFloat, bound:bound(0.0,200.0), show:() => ui.sliceSupportEnable.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceSupportEnable: newBoolean(LANG.sp_auto_s, onBooleanClick, {title:LANG.sp_auto_l, show:isNotBelt}),
|
||||
sliceSupportOutline: newBoolean(LANG.sp_outl_s, onBooleanClick, {title:LANG.sp_outl_l}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceSupportGen: newRow([
|
||||
ui.ssaGen = newButton(LANG.sp_detect, onButtonClick, {class: "f-col grow a-center"})
|
||||
], { modes: FDM, class: "ext-buttons f-row grow" }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceSupportManual: newRow([
|
||||
(ui.ssmAdd = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})),
|
||||
(ui.ssmDun = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})),
|
||||
(ui.ssmClr = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-trash-alt"></i>'}))
|
||||
], {class:"ext-buttons f-row"}),
|
||||
_____: newGroup(LANG.fl_menu, $('fdm-base'), { modes:FDM, driven, hideable, separator, group:"fdm-base" }),
|
||||
firstSliceHeight: newInput(LANG.fl_lahi_s, {title:LANG.fl_lahi_l, convert:toFloat, show:isNotBelt}),
|
||||
firstLayerNozzleTemp:newInput(LANG.fl_nozl_s, {title:LANG.fl_nozl_l, convert:toInt, show:isNotBelt}),
|
||||
firstLayerBedTemp: newInput(LANG.fl_bedd_s, {title:LANG.fl_bedd_l, convert:toInt, show:isNotBelt}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
firstLayerFanSpeed: newInput(LANG.ou_fans_s, {title:LANG.ou_fans_l, convert:toInt, bound:bound(0,255), show:isBelt}),
|
||||
firstLayerYOffset: newInput(LANG.fl_zoff_s, {title:LANG.fl_zoff_l, convert:toFloat, show:isBelt}),
|
||||
firstLayerFlatten: newInput(LANG.fl_flat_s, {title:LANG.fl_flat_l, convert:toFloat, show:isBelt}),
|
||||
firstLayerRate: newInput(LANG.fl_rate_s, {title:LANG.fl_rate_l, convert:toFloat}),
|
||||
firstLayerFillRate: newInput(LANG.fl_frat_s, {title:LANG.fl_frat_l, convert:toFloat, show:isNotBelt}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isNotBelt }),
|
||||
firstLayerLineMult: newInput(LANG.fl_sfac_s, {title:LANG.fl_sfac_l, convert:toFloat, bound:bound(0.5,2), show:isNotBelt}),
|
||||
firstLayerPrintMult: newInput(LANG.fl_mult_s, {title:LANG.fl_mult_l, convert:toFloat}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isBelt }),
|
||||
firstLayerBrim: newInput(LANG.fl_brim_s, {title:LANG.fl_brim_l, convert:toInt, show:isBelt}),
|
||||
firstLayerBrimIn: newInput(LANG.fl_brin_s, {title:LANG.fl_brin_l, convert:toInt, show:isBelt}),
|
||||
firstLayerBrimTrig: newInput(LANG.fl_brmn_s, {title:LANG.fl_brmn_l, convert:toInt, show:isBelt}),
|
||||
firstLayerBrimGap: newInput(LANG.fl_brgp_s, {title:LANG.fl_brgp_l, convert:toFloat, show:isBelt}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isBelt }),
|
||||
firstLayerBeltLead: newInput(LANG.fl_bled_s, {title:LANG.fl_bled_l, convert:toFloat, show:isBelt}),
|
||||
firstLayerBeltBump: newInput(LANG.fl_blmp_s, {title:LANG.fl_blmp_l, convert:toFloat, bound:bound(0, 10), show:isBelt}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isNotBelt }),
|
||||
outputBrimCount: newInput(LANG.fl_skrt_s, {title:LANG.fl_skrt_l, convert:toInt, show:isNotBelt}),
|
||||
outputBrimOffset: newInput(LANG.fl_skro_s, {title:LANG.fl_skro_l, convert:toFloat, show:isNotBelt}),
|
||||
outputRaftSpacing: newInput(LANG.fr_spac_s, {title:LANG.fr_spac_l, convert:toFloat, bound:bound(0.0,3.0), show: () => ui.outputRaft.checked && isNotBelt() }),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isNotBelt }),
|
||||
outputRaft: newBoolean(LANG.fr_nabl_s, onBooleanClick, {title:LANG.fr_nabl_l, trigger, show:() => isNotBelt()}),
|
||||
outputDraftShield: newBoolean(LANG.fr_draf_s, onBooleanClick, {title:LANG.fr_draf_l, trigger, show:() => isNotBelt()}),
|
||||
_____: newGroup(LANG.ou_menu, $('fdm-output'), { modes:FDM, driven, hideable, separator, group:"fdm-out" }),
|
||||
outputFeedrate: newInput(LANG.ou_feed_s, {title:LANG.ou_feed_l, convert:toInt}),
|
||||
outputFinishrate: newInput(LANG.ou_fini_s, {title:LANG.ou_fini_l, convert:toInt}),
|
||||
outputSeekrate: newInput(LANG.ou_move_s, {title:LANG.ou_move_l, convert:toInt}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
outputShellMult: newInput(LANG.ou_shml_s, {title:LANG.ou_exml_l, convert:toFloat, bound:bound(0.0,2.0)}),
|
||||
outputFillMult: newInput(LANG.ou_flml_s, {title:LANG.ou_exml_l, convert:toFloat, bound:bound(0.0,2.0)}),
|
||||
outputSparseMult: newInput(LANG.ou_spml_s, {title:LANG.ou_exml_l, convert:toFloat, bound:bound(0.0,2.0)}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
outputRetractDist: newInput(LANG.ad_rdst_s, {title:LANG.ad_rdst_l, convert:toFloat}),
|
||||
outputRetractSpeed: newInput(LANG.ad_rrat_s, {title:LANG.ad_rrat_l, convert:toInt}),
|
||||
outputRetractWipe: newInput(LANG.ad_wpln_s, {title:LANG.ad_wpln_l, convert:toFloat, bound:bound(0.0,10)}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
sliceLayerStart: newSelect(LANG.sl_strt_s, {title:LANG.sl_strt_l}, "start"),
|
||||
outputLayerRetract: newBoolean(LANG.ad_lret_s, onBooleanClick, {title:LANG.ad_lret_l}),
|
||||
outputAvoidGaps: newBoolean(LANG.ad_agap_s, onBooleanClick, {title:LANG.ad_agap_l}),
|
||||
separator: newBlank({ class:"set-sep", driven, show:isBelt }),
|
||||
outputBeltFirst: newBoolean(LANG.ad_lbir_s, onBooleanClick, {title:LANG.ad_lbir_l, show:isBelt}),
|
||||
_____: newGroup(LANG.ad_menu, $('fdm-expert'), { modes:FDM, driven, hideable, separator, group:"fdm-xprt" }),
|
||||
sliceAngle: newInput(LANG.sl_angl_s, {title:LANG.sl_angl_l, convert:toFloat, show:isBelt}),
|
||||
outputRetractDwell: newInput(LANG.ad_rdwl_s, {title:LANG.ad_rdwl_l, convert:toInt}),
|
||||
sliceSolidMinArea: newInput(LANG.ad_msol_s, {title:LANG.ad_msol_l, convert:toFloat}),
|
||||
outputMinSpeed: newInput(LANG.ad_mins_s, {title:LANG.ad_mins_l, convert:toFloat, bound:bound(1,200)}),
|
||||
outputShortPoly: newInput(LANG.ad_spol_s, {title:LANG.ad_spol_l, convert:toFloat, bound:bound(0,10000)}),
|
||||
outputCoastDist: newInput(LANG.ad_scst_s, {title:LANG.ad_scst_l, convert:toFloat, bound:bound(0.0,10)}),
|
||||
zHopDistance: newInput(LANG.ad_zhop_s, {title:LANG.ad_zhop_l, convert:toFloat, bound:bound(0,3.0)}),
|
||||
arcTolerance: newInput(LANG.ad_arct_s, {title:LANG.ad_arct_l, convert:toFloat, bound:bound(0,1.0), show:() => { return isNotBelt() }}),
|
||||
antiBacklash: newInput(LANG.ad_abkl_s, {title:LANG.ad_abkl_l, convert:toInt, bound:bound(0,3)}),
|
||||
outputLoops: newInput(LANG.ag_loop_s, {title:LANG.ag_loop_l, convert:toInt, bound:bound(-1,1000), show:isBelt}),
|
||||
outputPurgeTower: newInput(LANG.ad_purg_s, {title:LANG.ad_purg_l, convert:toInt, bound:bound(0,1000)}),
|
||||
|
||||
fdmRanges: $('fdm-ranges'),
|
||||
|
||||
};
|
||||
}
|
||||
74
src/kiri/mode/laser/init-menu.js
Normal file
74
src/kiri/mode/laser/init-menu.js
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from '../../core/api.js';
|
||||
|
||||
let LANG = api.language.current;
|
||||
let { LASER, DRAG, WJET, WEDM } = api.const.MODES,
|
||||
TWOD = [ LASER, DRAG, WJET, WEDM ],
|
||||
TWONED = [ LASER, DRAG, WJET ],
|
||||
{ $ } = api.web,
|
||||
{ uc, ui } = api,
|
||||
{ bound, toInt, toFloat } = uc,
|
||||
{ newBlank, newButton, newBoolean, newGroup, newInput, newRow } = uc,
|
||||
driven = true,
|
||||
separator = true,
|
||||
trigger = true
|
||||
;
|
||||
|
||||
function onBooleanClick(el) {
|
||||
api.event.emit('click.boolean', el);
|
||||
}
|
||||
|
||||
function onButtonClick(el) {
|
||||
api.event.emit('click.button', el);
|
||||
}
|
||||
|
||||
export function menu() {
|
||||
|
||||
return {
|
||||
|
||||
/** Left Side Menu */
|
||||
|
||||
_____: newGroup(LANG.sl_menu, $('lzr-slice'), { modes:TWOD, driven, separator }),
|
||||
ctSliceKerf: newInput(LANG.ls_offs_s, {title:LANG.ls_offs_l, convert:toFloat}),
|
||||
ctSliceHeight: newInput(LANG.ls_lahi_s, {title:LANG.ls_lahi_l, convert:toFloat, trigger}),
|
||||
ctSliceHeightMin: newInput(LANG.ls_lahm_s, {title:LANG.ls_lahm_l, convert:toFloat, show:() => ui.ctSliceHeight.value == 0 && !ui.ctSliceSingle.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
ctSliceSingle: newBoolean(LANG.ls_sngl_s, onBooleanClick, {title:LANG.ls_sngl_l}),
|
||||
ctOmitInner: newBoolean(LANG.we_omit_s, onBooleanClick, {title:LANG.we_omit_l, modes:WEDM}),
|
||||
_____: newGroup('surfaces', $('lzr-surface'), { modes:[-1], driven, separator }),
|
||||
ctSurfaces: newRow([
|
||||
(ui.faceAdd = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})),
|
||||
(ui.faceDun = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})),
|
||||
(ui.faceClr = newButton(undefined, onButtonClick, {icon:'<i class="fas fa-trash-alt"></i>'}))
|
||||
], {class:"ext-buttons f-row", modes:WEDM}),
|
||||
_____: newGroup(LANG.dk_menu, $('lzr-knife'), { modes:DRAG, marker:true, driven, separator }),
|
||||
ctOutKnifeDepth: newInput(LANG.dk_dpth_s, { title:LANG.dk_dpth_l, convert:toFloat, bound:bound(0.0,5.0) }),
|
||||
ctOutKnifePasses: newInput(LANG.dk_pass_s, { title:LANG.dk_pass_l, convert:toInt, bound:bound(0,5) }),
|
||||
ctOutKnifeTip: newInput(LANG.dk_offs_s, { title:LANG.dk_offs_l, convert:toFloat, bound:bound(0.0,10.0) }),
|
||||
_____: newGroup(LANG.lo_menu, $('lzr-layout'), { modes:TWOD, driven, separator }),
|
||||
ctOutTileSpacing: newInput(LANG.ou_spac_s, { title:LANG.ou_spac_l, convert:toInt }),
|
||||
ctOutMerged: newBoolean(LANG.ou_mrgd_s, onBooleanClick, {title:LANG.ou_mrgd_l, modes:TWONED, show:() => !ui.ctOutStack.checked }),
|
||||
ctOutGroup: newBoolean(LANG.ou_grpd_s, onBooleanClick, {title:LANG.ou_grpd_l, show:() => !(ui.ctOutMark.checked || ui.ctOutStack.checked) }),
|
||||
_____: newGroup(LANG.ou_menu, $('lzr-output'), { modes:TWOD, driven, separator, group:"lzr-output" }),
|
||||
ctOutPower: newInput(LANG.ou_powr_s, {title:LANG.ou_powr_l, convert:toInt, bound:bound(1,100), modes:TWONED }),
|
||||
ctOutSpeed: newInput(LANG.ou_sped_s, {title:LANG.ou_sped_l, convert:toInt }),
|
||||
ctAdaptive: newBoolean('adaptive speed', onBooleanClick, {modes:WEDM, title:'controller determines best cutting speed based on material feedback at runtime'}),
|
||||
separator: newBlank({ class:"set-sep", driven }),
|
||||
ctOriginBounds: newBoolean(LANG.or_bnds_s, onBooleanClick, { title:LANG.or_bnds_l, show:() => !ui.ctOriginCenter.checked }),
|
||||
ctOriginCenter: newBoolean(LANG.or_cntr_s, onBooleanClick, { title:LANG.or_cntr_l, show:() => !ui.ctOriginBounds.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven, modes:WEDM, show:() => ui.ctOriginBounds.checked }),
|
||||
ctOriginOffX: newInput(LANG.or_offx_s, { title:LANG.or_offx_l, convert:toFloat, modes:WEDM, show:() => ui.ctOriginBounds.checked }),
|
||||
ctOriginOffY: newInput(LANG.or_offy_s, { title:LANG.or_offy_l, convert:toFloat, modes:WEDM, show:() => ui.ctOriginBounds.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven, modes:TWONED }),
|
||||
ctOutZColor: newBoolean(LANG.ou_layo_s, onBooleanClick, { title:LANG.ou_layo_l, modes:TWONED, show:() => !ui.ctOutMerged.checked }),
|
||||
ctOutLayer: newBoolean(LANG.ou_layr_s, onBooleanClick, { title:LANG.ou_layr_l, modes:TWONED, show:() => !ui.ctOutStack.checked }),
|
||||
ctOutMark: newBoolean(LANG.ou_lays_s, onBooleanClick, { title:LANG.ou_lays_l, modes:TWONED, show:() => !ui.ctOutStack.checked }),
|
||||
separator: newBlank({ class:"set-sep", driven, modes:LASER }),
|
||||
ctOutInches: newBoolean(LANG.ou_inch_s, onBooleanClick, { title:LANG.ou_inch_l, modes:LASER }),
|
||||
ctOutStack: newBoolean(LANG.ou_stak_s, onBooleanClick, { title:LANG.ou_stak_l, modes:LASER }),
|
||||
ctOutShaper: newBoolean(LANG.ou_shap_s, onBooleanClick, { title:LANG.ou_shap_l, modes:LASER, show:() => ui.ctOutStack.checked }),
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
58
src/kiri/mode/sla/init-menu.js
Normal file
58
src/kiri/mode/sla/init-menu.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from '../../core/api.js';
|
||||
|
||||
let LANG = api.language.current;
|
||||
let { SLA } = api.const.MODES,
|
||||
{ $ } = api.web,
|
||||
{ uc, ui } = api,
|
||||
{ bound, toInt, toFloat } = uc,
|
||||
{ newBoolean, newGroup, newInput, newSelect } = uc,
|
||||
driven = true,
|
||||
separator = true
|
||||
;
|
||||
|
||||
function onBooleanClick(el) {
|
||||
api.event.emit('click.boolean', el);
|
||||
}
|
||||
|
||||
export function menu() {
|
||||
|
||||
return {
|
||||
|
||||
/** Left Side Menu */
|
||||
|
||||
slaProc: newGroup(LANG.sa_menu, $('sla-slice'), { modes:SLA, group:"sla-slice", driven, separator }),
|
||||
slaSlice: newInput(LANG.sa_lahe_s, {title:LANG.sa_lahe_l, convert:toFloat}),
|
||||
slaShell: newInput(LANG.sa_shel_s, {title:LANG.sa_shel_l, convert:toFloat}),
|
||||
slaOpenTop: newBoolean(LANG.sa_otop_s, onBooleanClick, {title:LANG.sa_otop_l}),
|
||||
slaOpenBase: newBoolean(LANG.sa_obas_s, onBooleanClick, {title:LANG.sa_obas_l}),
|
||||
slaLayers: newGroup(LANG.sa_layr_m, $('sla-layers'), { modes:SLA, group:"sla-layers", driven, separator }),
|
||||
slaLayerOn: newInput(LANG.sa_lton_s, {title:LANG.sa_lton_l, convert:toFloat}),
|
||||
slaLayerOff: newInput(LANG.sa_ltof_s, {title:LANG.sa_ltof_l, convert:toFloat}),
|
||||
slaPeelDist: newInput(LANG.sa_pldi_s, {title:LANG.sa_pldi_l, convert:toFloat}),
|
||||
slaPeelLiftRate: newInput(LANG.sa_pllr_s, {title:LANG.sa_pllr_l, convert:toFloat}),
|
||||
slaPeelDropRate: newInput(LANG.sa_pldr_s, {title:LANG.sa_pldr_l, convert:toFloat}),
|
||||
slaBase: newGroup(LANG.sa_base_m, $('sla-base'), { modes:SLA, group:"sla-base", driven, separator }),
|
||||
slaBaseLayers: newInput(LANG.sa_balc_s, {title:LANG.sa_balc_l, convert:toInt}),
|
||||
slaBaseOn: newInput(LANG.sa_lton_s, {title:LANG.sa_bltn_l, convert:toFloat}),
|
||||
slaBaseOff: newInput(LANG.sa_ltof_s, {title:LANG.sa_bltf_l, convert:toFloat}),
|
||||
slaBasePeelDist: newInput(LANG.sa_pldi_s, {title:LANG.sa_pldi_l, convert:toFloat}),
|
||||
slaBasePeelLiftRate: newInput(LANG.sa_pllr_s, {title:LANG.sa_pllr_l, convert:toFloat}),
|
||||
slaFill: newGroup(LANG.sa_infl_m, $('sla-fill'), { modes:SLA, group:"sla-infill", driven, separator }),
|
||||
slaFillDensity: newInput(LANG.sa_ifdn_s, {title:LANG.sa_ifdn_l, convert:toFloat, bound:bound(0,1)}),
|
||||
slaFillLine: newInput(LANG.sa_iflw_s, {title:LANG.sa_iflw_l, convert:toFloat, bound:bound(0,5)}),
|
||||
slaSupport: newGroup(LANG.sa_supp_m, $('sla-support'), { modes:SLA, group:"sla-support", driven, separator }),
|
||||
slaSupportLayers: newInput(LANG.sa_slyr_s, {title:LANG.sa_slyr_l, convert:toInt, bound:bound(5,100)}),
|
||||
slaSupportGap: newInput(LANG.sa_slgp_s, {title:LANG.sa_slgp_l, convert:toInt, bound:bound(3,30)}),
|
||||
slaSupportDensity: newInput(LANG.sa_sldn_s, {title:LANG.sa_sldn_l, convert:toFloat, bound:bound(0.01,0.9)}),
|
||||
slaSupportSize: newInput(LANG.sa_slsz_s, {title:LANG.sa_slsz_l, convert:toFloat, bound:bound(0.1,1)}),
|
||||
slaSupportPoints: newInput(LANG.sa_slpt_s, {title:LANG.sa_slpt_l, convert:toInt, bound:bound(3,10)}),
|
||||
slaSupportEnable: newBoolean(LANG.enable, onBooleanClick, {title:LANG.sl_slen_l}),
|
||||
slaOutput: newGroup(LANG.sa_outp_m, $('sla-output'), { modes:SLA, driven, separator, group:"sla-output" }),
|
||||
slaFirstOffset: newInput(LANG.sa_opzo_s, {title:LANG.sa_opzo_l, convert:toFloat, bound:bound(0,1)}),
|
||||
slaAntiAlias: newSelect(LANG.sa_opaa_s, {title:LANG.sa_opaa_l}, "antialias"),
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import { load } from '../../load/file.js';
|
|||
import { newWidget } from '../core/widget.js';
|
||||
|
||||
class Engine {
|
||||
constructor() {
|
||||
constructor({ workURL, poolURL } = {}) {
|
||||
this.widget = newWidget();
|
||||
this.settings = {
|
||||
mode: "FDM",
|
||||
|
|
@ -22,7 +22,13 @@ class Engine {
|
|||
widget: { [this.widget.id]: {} }
|
||||
};
|
||||
this.listener = () => { };
|
||||
client.start();
|
||||
try {
|
||||
client.setWorkPath(workURL);
|
||||
client.setPoolPath(poolURL);
|
||||
client.restart();
|
||||
} catch (error) {
|
||||
console.log({ error });
|
||||
}
|
||||
}
|
||||
|
||||
load(url) {
|
||||
|
|
@ -190,7 +196,7 @@ class Engine {
|
|||
}
|
||||
|
||||
export function newEngine() {
|
||||
return new Engine();
|
||||
return new Engine(...arguments);
|
||||
}
|
||||
|
||||
export { Engine };
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@ import { codec, encode, encodePointArray } from '../core/codec.js';
|
|||
import { doTopShells } from '../mode/fdm/post.js';
|
||||
import { newPoint } from '../../geo/point.js';
|
||||
import { polygons as POLY } from '../../geo/polygons.js';
|
||||
import { sliceZ } from '../../geo/slicer.js';
|
||||
import { sliceZ, sliceConnect } from '../../geo/slicer.js';
|
||||
import { Slicer as cam_slicer } from '../mode/cam/slicer.js';
|
||||
import { Slicer as topo_slicer } from '../mode/cam/slicer_topo.js';
|
||||
import { Probe, Trace, raster_slice } from '../mode/cam/topo3.js';
|
||||
import { Topo as Topo4, rotatePoints } from '../mode/cam/topo4.js';
|
||||
import { wasm_ctrl } from '../../geo/wasm.js';
|
||||
|
||||
const clib = self.ClipperLib;
|
||||
|
|
@ -53,9 +54,13 @@ function debug() {
|
|||
// console.log(`[${name}]`, ...arguments);
|
||||
}
|
||||
|
||||
let invalid = 0;
|
||||
const funcs = self.minion = {
|
||||
invalid(data, seq, cmd) {
|
||||
console.error({ invalid_minion_command: cmd, data });
|
||||
if (invalid++ < 20) {
|
||||
// prevent flooding console and killing session
|
||||
console.error({ invalid_minion_command: cmd, data });
|
||||
}
|
||||
reply({ seq, error: `invalid command (${cmd})` });
|
||||
},
|
||||
|
||||
|
|
@ -271,7 +276,7 @@ const funcs = self.minion = {
|
|||
topo4_slice(data, seq) {
|
||||
const { slice, resolution } = data;
|
||||
const vertices = cache.vertices;
|
||||
const recs = new kiri.topo_slicer(slice.index)
|
||||
const recs = new topo_slicer(slice.index)
|
||||
.setFromArray(vertices, slice)
|
||||
.slice(resolution)
|
||||
.map(rec => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
import '../../add/array.js';
|
||||
import '../../add/class.js';
|
||||
import '../../add/three.js';
|
||||
import '../../ext/jszip.js';
|
||||
|
||||
import { base } from '../../geo/base.js';
|
||||
import { codec } from '../core/codec.js';
|
||||
|
|
@ -17,6 +16,7 @@ import { wasm_ctrl } from '../../geo/wasm.js';
|
|||
import { version } from '../../moto/license.js';
|
||||
import { Widget, newWidget } from '../core/widget.js';
|
||||
import { load } from "../../load/png.js";
|
||||
import { JSZip } from '../../ext/jszip-esm.js';
|
||||
|
||||
import { CAM } from '../mode/cam/driver-be.js';
|
||||
import { DRAG } from '../mode/drag/driver.js';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
'use strict';
|
||||
|
||||
import { THREE } from '../ext/three.js';
|
||||
import JSZip from '../ext/jszip.esm.js';
|
||||
import { JSZip } from '../ext/jszip-esm.js';
|
||||
|
||||
let { BufferAttribute, Matrix4 } = THREE;
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ function extractItems(records) {
|
|||
*/
|
||||
export function parseAsync(data) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let zip = await JSZip.loadAsync(data);
|
||||
let zip = await new JSZip().loadAsync(data);
|
||||
let models = {};
|
||||
for (let [key, value] of Object.entries(zip.files)) {
|
||||
if (key.endsWith(".model")) {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ function init() {
|
|||
motoClient.on('ready', restore_space);
|
||||
|
||||
// start worker
|
||||
motoClient.start('/lib/mesh/work.js?' + version);
|
||||
motoClient.start('../lib/mesh/work.js?' + version);
|
||||
|
||||
// trigger space event binding
|
||||
call.space_init({ space: space, platform });
|
||||
|
|
@ -91,7 +91,11 @@ function init() {
|
|||
call.ui_build();
|
||||
|
||||
// hide url params
|
||||
history.replaceState({}, '', '/mesh/');
|
||||
let wlp = window.location.pathname;
|
||||
let mio = wlp.indexOf('/mesh/');
|
||||
if (mio >= 0) {
|
||||
history.replaceState({}, '', wlp.substring(0,mio + 6));
|
||||
}
|
||||
|
||||
// for electron
|
||||
self.mesh = { api };
|
||||
|
|
|
|||
|
|
@ -88,8 +88,7 @@
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
|
||||
<!-- <script src="/lib/kiri-run/engine.js" type="module"></script> -->
|
||||
<script type="module">
|
||||
import { Engine } from '/lib/kiri-run/engine.js';
|
||||
const engine = new Engine();
|
||||
import { Engine } from '/lib/kiri/run/engine.js';
|
||||
let edit, saveit = "";
|
||||
function $(id) { return document.getElementById(id) }
|
||||
function onload() {
|
||||
|
|
@ -127,7 +126,7 @@
|
|||
eval(`(function(){${code}})()`);
|
||||
}
|
||||
function demoFDM() {
|
||||
engine
|
||||
new Engine()
|
||||
.setListener(display_message)
|
||||
.load("/obj/cube.stl")
|
||||
.then(eng => eng.setProcess({
|
||||
|
|
@ -144,7 +143,7 @@
|
|||
}
|
||||
|
||||
function demoCAM(){
|
||||
engine
|
||||
new Engine()
|
||||
.setListener(display_message)
|
||||
.load("/obj/cube.stl")
|
||||
// should to call widget.setTopZ here ideally
|
||||
|
|
@ -244,7 +243,7 @@
|
|||
}
|
||||
|
||||
function demoLASER(){
|
||||
engine
|
||||
new Engine()
|
||||
.setListener(display_message)
|
||||
.load("/obj/cube.stl")
|
||||
// should to call widget.setTopZ here ideally
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@
|
|||
}
|
||||
</style>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
|
||||
<script src="/lib/kiri-run/frame.js"></script>
|
||||
<script src="/lib/kiri/run/frame.js"></script>
|
||||
<script>
|
||||
let defc = [
|
||||
"let api = kiri.frame;",
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
/* surface size configuration and font import */
|
||||
@font-face {
|
||||
font-family: 'Russo One';
|
||||
src: url('/moto/russo-one.ttf');
|
||||
src: url('../moto/russo-one.ttf');
|
||||
}
|
||||
@media only screen and (max-width : 1000px) {
|
||||
.top-menu > span > label {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
<meta http-equiv="origin-trial" content="Aixo1di7jfA+ystPFy70vGYyODYVAju1y8EQWwdkdtl5sB7i990oDCnqLQntpfl7NsW74wz99Og7xgQqeLKiBQsAAAB0eyJvcmlnaW4iOiJodHRwczovL2dyaWQuc3BhY2U6NDQzIiwiZmVhdHVyZSI6IlVucmVzdHJpY3RlZFNoYXJlZEFycmF5QnVmZmVyIiwiZXhwaXJ5IjoxNzUzMTQyNDAwLCJpc1N1YmRvbWFpbiI6dHJ1ZX0=">
|
||||
<meta http-equiv="origin-trial" content="AobHyD9RXtmfFOTcY506ANNJjG8lYuuvQ3/C7YJvprSP6Kk2pjKIBSKAUbUh64Nx6aCZaqlZ+7sSSswiIFHflgYAAAB0eyJvcmlnaW4iOiJodHRwczovL2dyaWQuc3BhY2U6NDQzIiwiZmVhdHVyZSI6IlVucmVzdHJpY3RlZFNoYXJlZEFycmF5QnVmZmVyIiwiZXhwaXJ5IjoxNzY5NDcyMDAwLCJpc1N1YmRvbWFpbiI6dHJ1ZX0=">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<title>Kiri:Moto</title>
|
||||
<link rel="icon" href="favicon.ico">
|
||||
|
|
|
|||
|
|
@ -875,6 +875,8 @@ self.lang['en-us'] = {
|
|||
cx_fast_l: ["disable overhang detection","can be faster and use less","memory with complex models","but fails with overhangs","try enabling if slicing","hangs during shadowing"],
|
||||
cx_true_s: "true shadow",
|
||||
cx_true_l: ["computationally correct shadow","will be slower but produce","better cuts for complex parts"],
|
||||
cx_arce_s: "arc output",
|
||||
cx_arce_l: ["EXPERIMENTAL: enable path to arc conversion"],
|
||||
cx_arct_s: "arc tolerance",
|
||||
cx_arct_l: ["convert cicrular paths to arcs;","center point drift tolerance","when matching arc points","consider values around 0.15","in mm, or 0.006 inches;","High values may cause","unexpected behavior","0 to disable"],
|
||||
cx_arcr_s: "arc resolution",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "Kiri:Moto 4.2.0",
|
||||
"name": "Kiri:Moto 4.3.0",
|
||||
"short_name": "Kiri:Moto",
|
||||
"description": "Slicer for 3D printers, CNC mills, laser cutters and more",
|
||||
"start_url": "/kiri/",
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
"background_color": "#ffffff",
|
||||
"orientation": "landscape-primary",
|
||||
"icons": [
|
||||
{ "src": "/kiri/logo-cube-512.png", "type": "image/png", "sizes": "512x512" },
|
||||
{ "src": "/kiri/logo-cube-144.png", "type": "image/png", "sizes": "144x144" }
|
||||
{ "src": "./logo-cube-512.png", "type": "image/png", "sizes": "512x512" },
|
||||
{ "src": "./logo-cube-144.png", "type": "image/png", "sizes": "144x144" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
@font-face {
|
||||
font-family: 'Russo One';
|
||||
src: url('/moto/russo-one.ttf');
|
||||
src: url('../moto/russo-one.ttf');
|
||||
}
|
||||
|
||||
/** defaults */
|
||||
|
|
|
|||
Loading…
Reference in a new issue