commit
365427ede7
76 changed files with 7225 additions and 2047 deletions
201
app.js
201
app.js
|
|
@ -21,10 +21,10 @@ const load = [];
|
|||
const synth = {};
|
||||
const api = {};
|
||||
|
||||
let level;
|
||||
let setupFn;
|
||||
let cacheDir;
|
||||
let startTime;
|
||||
let oversion;
|
||||
let lastmod;
|
||||
let logger;
|
||||
let debug;
|
||||
|
|
@ -43,25 +43,8 @@ function init(mod) {
|
|||
dir = mod.dir;
|
||||
log = mod.log;
|
||||
|
||||
if (mod.util.globdir) {
|
||||
// when globdir available, look for shared kvstore
|
||||
// and if not present, create and share in through env
|
||||
if (mod.env._level) {
|
||||
level = mod.env._level;
|
||||
logger.log("using shared kvstore");
|
||||
} else {
|
||||
level = require('level')(mod.util.globdir("kvstore"), {valueEncoding:"json"});
|
||||
mod.env._level = level;
|
||||
logger.log("creating shared kvstore");
|
||||
}
|
||||
} else {
|
||||
logger.log("fallback to local kvstore");
|
||||
level = require('level')(mod.util.datadir("kvstore"), {valueEncoding:"json"});
|
||||
}
|
||||
|
||||
cacheDir = mod.util.datadir("cache");
|
||||
|
||||
mod.on.reload(() => level.close());
|
||||
mod.on.test((req) => {
|
||||
let cookie = cookieValue(req.headers.cookie, "version") || undefined;
|
||||
let vmatch = mod.meta.version || "*";
|
||||
|
|
@ -85,7 +68,6 @@ function init(mod) {
|
|||
mod.add(handleVersion);
|
||||
mod.add(prepath([
|
||||
[ "/code/", handleCode ],
|
||||
[ "/data/", handleData ],
|
||||
[ "/wasm/", handleWasm ]
|
||||
]));
|
||||
mod.add(fixedmap("/api/", api));
|
||||
|
|
@ -144,7 +126,8 @@ function initModule(mod, file, dir) {
|
|||
require_fresh(file)({
|
||||
api: api,
|
||||
adm: {
|
||||
reload: prepareScripts
|
||||
reload: prepareScripts,
|
||||
setver: (ver) => { oversion = ver }
|
||||
},
|
||||
const: {
|
||||
args: {},
|
||||
|
|
@ -166,6 +149,8 @@ function initModule(mod, file, dir) {
|
|||
time: time,
|
||||
guid: guid,
|
||||
mkdirs: util.mkdir,
|
||||
isfile: util.isfile,
|
||||
confdir: util.confdir,
|
||||
datadir: util.datadir,
|
||||
lastmod: lastmod,
|
||||
obj2string: obj2string,
|
||||
|
|
@ -173,10 +158,6 @@ function initModule(mod, file, dir) {
|
|||
getCookieValue: cookieValue,
|
||||
logger: log.new
|
||||
},
|
||||
db: {
|
||||
api: db,
|
||||
level: level
|
||||
},
|
||||
inject: (code, file, options) => {
|
||||
if (!script[code]) {
|
||||
return logger.log(`inject missing target "${code}"`);
|
||||
|
|
@ -239,11 +220,13 @@ const script = {
|
|||
kiri : [
|
||||
"kiri",
|
||||
"ext/three",
|
||||
"ext/three-bgu",
|
||||
"license",
|
||||
"ext/clip2", // work.test
|
||||
"ext/tween",
|
||||
"ext/fsave",
|
||||
"ext/earcut", // work.test
|
||||
"ext/base64",
|
||||
"add/array",
|
||||
"add/three",
|
||||
"geo/base",
|
||||
|
|
@ -267,11 +250,11 @@ const script = {
|
|||
"kiri/ui",
|
||||
"kiri/lang",
|
||||
"kiri/lang-en",
|
||||
"kiri/fill",
|
||||
"kiri/db",
|
||||
"kiri/slice",
|
||||
"kiri/layers",
|
||||
"kiri/client",
|
||||
"mode/fdm/fill",
|
||||
"mode/fdm/driver",
|
||||
"mode/fdm/client",
|
||||
"mode/sla/driver",
|
||||
|
|
@ -297,6 +280,7 @@ const script = {
|
|||
"kiri",
|
||||
"ext/three",
|
||||
"ext/pngjs",
|
||||
"ext/jszip",
|
||||
"license",
|
||||
"ext/clip2",
|
||||
"ext/earcut",
|
||||
|
|
@ -315,11 +299,11 @@ const script = {
|
|||
"geo/polygons",
|
||||
"geo/gyroid",
|
||||
"moto/pack",
|
||||
"kiri/fill",
|
||||
"kiri/slice",
|
||||
"kiri/slicer",
|
||||
"kiri/slicer2",
|
||||
"kiri/layers",
|
||||
"mode/fdm/fill",
|
||||
"mode/fdm/driver",
|
||||
"mode/fdm/slice",
|
||||
"mode/fdm/prepare",
|
||||
|
|
@ -404,40 +388,6 @@ const script = {
|
|||
// prevent caching of specified modules
|
||||
const cachever = {};
|
||||
|
||||
const db = {
|
||||
// --------
|
||||
key: arr => arr.join("/"),
|
||||
// --------
|
||||
get: key => {
|
||||
if (Array.isArray(key)) key = db.key(key);
|
||||
return promise((resolve,reject) => {
|
||||
level.get(key,(err,record) => {
|
||||
resolve(record,err);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// --------
|
||||
put: (key, value) => {
|
||||
if (Array.isArray(key)) key = db.key(key);
|
||||
return promise((resolve,reject) => {
|
||||
level.put(key,value,(err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
// --------
|
||||
del: key => {
|
||||
return promise((resolve,reject) => {
|
||||
level.del(key, (err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function promise(resolve, reject) {
|
||||
return new Promise(resolve, reject);
|
||||
}
|
||||
|
|
@ -471,11 +421,12 @@ function handleSetup(req, res, next) {
|
|||
}
|
||||
|
||||
function handleVersion(req, res, next) {
|
||||
if (req.app.path === "/kiri/" && req.url.indexOf(version) < 0) {
|
||||
let vstr = oversion || version;
|
||||
if (req.app.path === "/kiri/" && req.url.indexOf(vstr) < 0) {
|
||||
if (req.url.indexOf("?") > 0) {
|
||||
return http.redirect(res, `${req.url},ver:${version}`);
|
||||
return http.redirect(res, `${req.url},ver:${vstr}`);
|
||||
} else {
|
||||
return http.redirect(res, `${req.url}?ver:${version}`);
|
||||
return http.redirect(res, `${req.url}?ver:${vstr}`);
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
|
|
@ -496,118 +447,6 @@ function handleOptions(req, res, next) {
|
|||
}
|
||||
}
|
||||
|
||||
function handleData(req, res, next) {
|
||||
addCorsHeaders(req, res);
|
||||
res.setHeader('Cache-Control', 'private, no-cache, max-age=0');
|
||||
|
||||
let tok = req.app.path.split('/'),
|
||||
muid = req.headers['x-moto-ajax'],
|
||||
space = tok[2] || null,
|
||||
version = tok[3],
|
||||
valid = space && space.length >= 4 && space.length <= 8;
|
||||
|
||||
function genKey() {
|
||||
while (true) {
|
||||
let k = Math.round(Math.random() * 9999999999).toString(36);
|
||||
if (k.length >= 4 && k.length <= 8) return k;
|
||||
}
|
||||
}
|
||||
|
||||
function countKey(space) {
|
||||
return db.key(['meta/counter',space]);
|
||||
}
|
||||
|
||||
function ownerKey(space) {
|
||||
return db.key(['meta/owner',muid,'space',space]);
|
||||
}
|
||||
|
||||
function recordKey(space, version) {
|
||||
return db.key(["meta/space",space,version]);
|
||||
}
|
||||
|
||||
// retrieve latest space data
|
||||
if (valid && req.method === 'GET' && valid) {
|
||||
function send(rec, version) {
|
||||
if (rec) {
|
||||
res.write(obj2string({space:space,ver:version,rec:rec}));
|
||||
res.end();
|
||||
} else {
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
|
||||
function retrieve(version) {
|
||||
return db.get(recordKey(space,version))
|
||||
.then(record => {
|
||||
send(record || null, version);
|
||||
})
|
||||
}
|
||||
|
||||
if (version) {
|
||||
retrieve(version)
|
||||
} else {
|
||||
db.get(countKey(space)).then(version => retrieve(version));
|
||||
}
|
||||
} else if (valid && req.method === 'POST') {
|
||||
let dbOwner = null,
|
||||
dbVersion = null,
|
||||
postBody = null,
|
||||
spacein = space,
|
||||
version = 0,
|
||||
body = '';
|
||||
|
||||
function checkDone() {
|
||||
if (!(dbVersion && postBody)) return;
|
||||
// if not owner, assign new space id
|
||||
if (dbVersion > 1) {
|
||||
if (!dbOwner) {
|
||||
space = genKey();
|
||||
version = 1;
|
||||
logger.log({forked:space,from:spacein,by:muid});
|
||||
}
|
||||
}
|
||||
// log what we have
|
||||
logger.log({
|
||||
space: space,
|
||||
ver: dbVersion,
|
||||
uid: muid,
|
||||
size: postBody.length
|
||||
});
|
||||
if (muid && muid.length > 0) {
|
||||
level.put(recordKey(space, dbVersion), body);
|
||||
level.put(ownerKey(space), {time: time(), ver: dbVersion});
|
||||
level.put(countKey(space), dbVersion);
|
||||
}
|
||||
res.end(obj2string({space: space, ver: dbVersion}));
|
||||
}
|
||||
|
||||
// accumulate post body
|
||||
req.on('data', data => { body += data });
|
||||
req.on('end', () => {
|
||||
postBody = body;
|
||||
checkDone();
|
||||
});
|
||||
|
||||
// fetch owner and version information
|
||||
db.get(ownerKey(space))
|
||||
.then(owner => {
|
||||
dbOwner = owner;
|
||||
return db.get(countKey(space));
|
||||
})
|
||||
.then(version => {
|
||||
dbVersion = parseInt(version || "0") + 1;
|
||||
checkDone();
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
next();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function handleWasm(req, res, next) {
|
||||
let [root, file] = req.app.path.split('/').slice(1);
|
||||
let ext = (file || '').split('.')[1];
|
||||
|
|
@ -775,10 +614,14 @@ function getCachedFile(file, fn) {
|
|||
let smod = lastmod(filePath),
|
||||
cmod = cached.mtime;
|
||||
|
||||
if (!smod) throw "missing source file";
|
||||
if (smod > cmod) cached = null;
|
||||
|
||||
cached.lastcheck = now;
|
||||
if (!smod) {
|
||||
throw "missing source file";
|
||||
}
|
||||
if (smod > cmod) {
|
||||
cached = null;
|
||||
} else {
|
||||
cached.lastcheck = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
65
notes.md
65
notes.md
|
|
@ -2,46 +2,49 @@
|
|||
|
||||
## `C` cosmetic, `F` functional, `P` performance, `B` bug fix
|
||||
|
||||
* `B` saved profile should be restored / defaulted when switching devices?
|
||||
* `B` normals possibly inverted on faces in 2D to 3D conversion
|
||||
* `B` normalize left, bottom, right pop menu time/click and value persistence
|
||||
* `B` origin bug (Onshape?) when switching modes in 2.5 and 2.6
|
||||
* `B` origin (and bed size) bug (Onshape?) when switching modes in 2.5 and 2.6
|
||||
|
||||
* `P` duplicate objects should share same slice data unless rotated or scaled
|
||||
* `P` allow selection to me decimated on demand (context menu?)
|
||||
* `P` improve decimation speed: omit point conversion or use wasm
|
||||
* `P` client/worker interface normalization
|
||||
* `P` explore widget vertex reloading / replacing
|
||||
* `P` client/worker message interface normalization
|
||||
* `P` explore widget vertex reloading / replacing (Onshape) (issue #48)
|
||||
|
||||
* `F` SVG import to 3D part like images
|
||||
* `F` show slider range values in workspace units (on hover?)
|
||||
* `F` allow select of a range by typing in values in slices or workspace units
|
||||
* `F` add % field type with conversion (like units)
|
||||
* `F` complete G2/G3 arc output / input (85% now)
|
||||
* `F` expose grouping feature
|
||||
* `F` add svgnest-like arrange algorithm
|
||||
|
||||
# FDM
|
||||
|
||||
* `B` large # linear points with linear infill (belt only?)
|
||||
* `B` fix adaptive slicing with multi-extruder
|
||||
* `B` fix supports with grouped parts
|
||||
* `B` re-calibrate slicing progress weighting
|
||||
* `B` infill densities are inaccurate
|
||||
* `B` fix support projection/end with grouped parts
|
||||
* `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` slicing controls per user-defined z-region
|
||||
* `F` support pillar should conform to part
|
||||
* `F` support pillar should have solid top/bottom
|
||||
* `F` more explicit line width control with ranges and min/max adaptive
|
||||
* `F` test outlining solid projected areas (internally)
|
||||
* `F` control for size of purge block (with 0=disabled)
|
||||
* `F` add separate fill speed control
|
||||
* `F` polishing and other non-planar work
|
||||
* `F` gradient infill https://www.youtube.com/watch?v=hq53gsYREHU&feature=emb_logo
|
||||
* `F` first layer segment large flat areas for better fill reliability
|
||||
* `F` feather sharp tips by reducing extrusion in area of overlap
|
||||
* `F` first layer segment large flat areas for better fill reliability
|
||||
* `F` enable purge blocks when quick layers are detected
|
||||
* `F` option to support interior bridges when 0% infill
|
||||
* `F` trim support offset from layer below
|
||||
* `F` calculate filament use per extruder per print
|
||||
* `F` first layer support speed should be same as shell speed
|
||||
* `F` apply finish speed to exposed top and underside flat areas
|
||||
* `F` expand internal supporting flats / solids before projection
|
||||
|
||||
* `P` extruder + filament max flow rate cap in planner
|
||||
* `P` revisit path routing / optimization
|
||||
* `P` implement infill clipping in wasm
|
||||
* `P` solid fill the tops of supports for down facing flats
|
||||
* `P` sparse infill should follow polys between intersect points
|
||||
|
||||
# FDM - SLA
|
||||
|
||||
|
|
@ -51,27 +54,33 @@
|
|||
|
||||
# FDM - BELT
|
||||
|
||||
* `B` fix supports for belt printing
|
||||
* `B` auto bed resizing leaves the origin in the wrong place at first
|
||||
* `B` ranges don't work with anchors
|
||||
* `B` multiple parts with one angled against origin "floats" in preview
|
||||
* `B` re-add progress calls for all work units
|
||||
|
||||
* `F` slightly angle supports to lean into the Z of the part
|
||||
* `F` arrange should just align down Z, not side to side.
|
||||
|
||||
# CAM
|
||||
|
||||
* `B` tabs are not cut to exact height
|
||||
* `B` first rough step too far down in certain circumstances?
|
||||
* `B` trace open polys are not wound consistently
|
||||
* `B` path routing with tabs sometimes makes no sense
|
||||
* `B` clicking on a pop-op should pin it until clicked or [esc]
|
||||
* `B` need to force cut line at synthetic z bottom (midlines, etc)
|
||||
* `B` non-clear-voids duplicates thru-holes
|
||||
* `B` failure to go *up* when moving between parts?
|
||||
* `B` starting export during animation unleashes chaos
|
||||
* `B` climb vs conventional not fully consistent after refactor
|
||||
* `B` outside cutting direction in roughing mode inverted
|
||||
|
||||
* `F` limit cut depth to flute length of selected tool
|
||||
* `F` add ease-down support to trace op
|
||||
* `F` add linear clearing strategy
|
||||
* `F` add adaptive clearing strategy
|
||||
* `F` user-selectable origin (issue #28)
|
||||
* `F` intelligently turn circle hole pocket clear into spiral down
|
||||
* `F` trace follow hole that matches endmill should turn into a drill op
|
||||
* `F` add climb/conventional into each operation
|
||||
* `F` update analyzer to detect overhangs
|
||||
* `F` add linear clearing strategy option for roughing / pocket
|
||||
* `F` adaptive clearing in roughing mode
|
||||
* `F` extend acute roughing on inside polys to clear small voids
|
||||
* `F` option to use part / STL coordinate space to determine X,Y origin
|
||||
* `F` validate muti-part layout and spacing exceeds largest outside tool diameter
|
||||
|
|
@ -88,14 +97,13 @@
|
|||
* `F` can animation clear the mesh in areas where the cuts go through the stock?
|
||||
* `F` support lathe mode / A-axis / rotary
|
||||
* `F` gcode output option as zip for multiple or flip ops or tool change
|
||||
* `F` ease-down should be engaged in all descending cutting operations
|
||||
* `F` entirely user-selectable origin
|
||||
|
||||
* `F` maintain several part orientations + op chains in a single profile
|
||||
|
||||
* `P` common part pre-analyze to speed up 'slice' and improve shadow (overhangs)
|
||||
* `P` redo all path route / planning in prepare to account for terrain before camOut
|
||||
* `P` detect render message backlog and pause or warn
|
||||
* `P` detect render message backlog and pause or warn?
|
||||
* `P` allow faster z movements when contouring (not plunging)
|
||||
* `P` common / faster shadow generator using vertices shared with ledges
|
||||
|
||||
# Laser
|
||||
|
||||
|
|
@ -108,6 +116,7 @@
|
|||
* http://wiki.imal.org/howto/cnc-milling-introduction-cutting-tools
|
||||
* http://www.twak.co.uk/2011/01/degeneracy-in-weighted-straight.html
|
||||
* http://photon.chrisgraf.de/
|
||||
* https://github.com/Jack000/SVGnest
|
||||
|
||||
# More CNC
|
||||
|
||||
|
|
@ -118,3 +127,7 @@
|
|||
* https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html
|
||||
* https://en.wikipedia.org/wiki/ZIP_(file_format)
|
||||
* https://stuk.github.io/jszip/
|
||||
|
||||
# Meta
|
||||
|
||||
* free-space tetrahedron modeler with vertex mating
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "grid-apps",
|
||||
"version": "2.6.8D",
|
||||
"version": "2.8.1D",
|
||||
"description": "grid.space 3d slice & modeling tools",
|
||||
"author": "Stewart Allen <sa@grid.space>",
|
||||
"license": "MIT",
|
||||
|
|
@ -21,18 +21,17 @@
|
|||
"slicer"
|
||||
],
|
||||
"dependencies": {
|
||||
"base64-js": "^1.5.1",
|
||||
"buffer-crc32": "^0.2.13",
|
||||
"compression": "^1.7.4",
|
||||
"connect": "^3.7.0",
|
||||
"earcut": "^2.2.2",
|
||||
"express-useragent": "^1.0.13",
|
||||
"level": "^6.0.1",
|
||||
"leveldown": "^5.6.0",
|
||||
"levelup": "^4.4.0",
|
||||
"jszip": "^3.5.0",
|
||||
"moment": "^2.24.0",
|
||||
"pixi.js": "^4.8.9",
|
||||
"serve-static": "^1.14.1",
|
||||
"three": "^0.122.0",
|
||||
"three": "^0.126.0",
|
||||
"tween.js": "^0.14.0",
|
||||
"uglify-es": "3.3.9",
|
||||
"validator": "^8.2.0",
|
||||
|
|
|
|||
26
readme.md
26
readme.md
|
|
@ -1,6 +1,6 @@
|
|||
[](https://paypal.me/gridspace3d?locale.x=en_US)
|
||||
|
||||
Contributions in all forms (code, bug reports, community engagenment, cash money, etc) are warmly welcomed. They all go to the bottom line of making better apps.
|
||||
Contributions in all forms (code, bug reports, community engagement, localization, etc) are warmly welcomed.
|
||||
|
||||
[](https://discord.com/channels/688863523207774209/688863523211968535)
|
||||

|
||||
|
|
@ -19,6 +19,8 @@ Contributions in all forms (code, bug reports, community engagenment, cash money
|
|||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### Development Activity
|
||||
|
||||
|
|
@ -54,6 +56,21 @@ to start a local instance of the apps. then open
|
|||
[Kiri:Moto](http://localhost:8080/kiri) or
|
||||
[Meta:Moto](http://localhost:8080/meta) on your local host
|
||||
|
||||
Alternatively, if you are using a packaged version of npm that ships with
|
||||
a Linux distribution, but still want to install in your home directory, you
|
||||
can use
|
||||
|
||||
```
|
||||
npm config set prefix ~/.local
|
||||
```
|
||||
|
||||
If gs-app-server is not found, then perhaps ~/.local/bin is not in
|
||||
your path. You can either add it to your path, or you can run:
|
||||
|
||||
```
|
||||
~/local/bin/gs-app-server --debug
|
||||
```
|
||||
|
||||
### Windows Developers
|
||||
|
||||
this git repo requires symbolic link support. on Windows, this means you have to clone the repo in a command shell with Administrator privileges.
|
||||
|
|
@ -68,8 +85,9 @@ web site.
|
|||
|
||||
requires node.js 12+
|
||||
|
||||
### Javascript Slicing API
|
||||
### Javascript Slicing APIs
|
||||
|
||||
A script include that injects a web worker into the page that will asynchronously perform any of Kiri’s slicing and gcode generation functions.
|
||||
A script include that injects a web worker into the page that will asynchronously perform any of Kiri’s slicing and gcode generation functions. And a frame messaging API for controlling Kiri:Moto inside an IFrame.
|
||||
|
||||
https://grid.space/kiri/engine.html
|
||||
* https://grid.space/kiri/engine.html
|
||||
* https://grid.space/kiri/frame.html
|
||||
|
|
|
|||
|
|
@ -162,6 +162,10 @@
|
|||
})
|
||||
};
|
||||
|
||||
AP.uniq = function() {
|
||||
return this.slice().sort().filter((x, i, a) => !i || x != a[i-1]);
|
||||
};
|
||||
|
||||
/** ******************************************************************
|
||||
* String prototype helpers
|
||||
******************************************************************* */
|
||||
|
|
|
|||
|
|
@ -5,9 +5,18 @@
|
|||
(function() {
|
||||
|
||||
var MP = THREE.Mesh.prototype,
|
||||
GP = THREE.Geometry.prototype,
|
||||
BP = THREE.BufferGeometry.prototype;
|
||||
|
||||
THREE.computeFaceNormal = function(vA,vB,vC) {
|
||||
const ab = new THREE.Vector3();
|
||||
const cb = new THREE.Vector3();
|
||||
cb.subVectors( vC, vB );
|
||||
ab.subVectors( vA, vB );
|
||||
cb.cross( ab );
|
||||
cb.normalize();
|
||||
return cb;
|
||||
};
|
||||
|
||||
MP.getBoundingBox = function(update) {
|
||||
return this.geometry.getBoundingBox(update);
|
||||
};
|
||||
|
|
@ -46,7 +55,7 @@
|
|||
};
|
||||
|
||||
// center geometry on x,y,z coordinates (defaults to 0,0,0)
|
||||
GP.center = function(x,y,z) {
|
||||
BP.center = function(x,y,z) {
|
||||
var box = this.getBoundingBox(),
|
||||
mid = box.dim.clone().multiplyScalar(0.5),
|
||||
dif = mid.clone().add(box.min),
|
||||
|
|
@ -69,14 +78,17 @@
|
|||
};
|
||||
|
||||
// return cached or refreshed (when update = true) bounding box
|
||||
GP.getBoundingBox = function(update) {
|
||||
if (update || !this.boundingBox) this.computeBoundingBox();
|
||||
BP.getBoundingBox = function(update) {
|
||||
if (update || !this.boundingBox) {
|
||||
this.boundingBox = null;
|
||||
this.computeBoundingBox();
|
||||
}
|
||||
this.boundingBox.dim = this.boundingBox.max.clone().sub(this.boundingBox.min);
|
||||
return this.boundingBox;
|
||||
};
|
||||
|
||||
// uniformly scale any mesh to a max x/y/z dim of 'unit' (defaults to 1)
|
||||
GP.unitScale = function(unit) {
|
||||
BP.unitScale = function(unit) {
|
||||
var bbox = this.getBoundingBox().clone(),
|
||||
scale = (unit || 1) / Math.max(
|
||||
bbox.max.x - bbox.min.x,
|
||||
|
|
@ -89,20 +101,21 @@
|
|||
return this;
|
||||
};
|
||||
|
||||
BP.center = GP.center;
|
||||
BP.getBoundingBox = GP.getBoundingBox;
|
||||
BP.unitScale = GP.unitScale;
|
||||
|
||||
BP.fixNormals = function() {
|
||||
this.computeVertexNormals();
|
||||
return this;
|
||||
};
|
||||
|
||||
THREE.Geometry.fromVertices = function(vertices) {
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
|
||||
return geometry;
|
||||
};
|
||||
// may be faster than the equivalent matrix transform. to be tested
|
||||
// BP.translate = function(x,y,z) {
|
||||
// let off = [x,y,z],
|
||||
// arr = this.attributes.position.array,
|
||||
// len = arr.length;
|
||||
// for (let i=0; i<len; i++) {
|
||||
// arr[i] += off[i%3];
|
||||
// }
|
||||
// return this;
|
||||
// }
|
||||
|
||||
THREE.Object3D.prototype.newGroup = function() {
|
||||
var group = new THREE.Group();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"M03 S20000 ; spindle on"
|
||||
],
|
||||
"post":[
|
||||
"M05 ; spindle off",
|
||||
"M05 ; spindle off",
|
||||
"M30 ; program end"
|
||||
],
|
||||
"tool-change":[
|
||||
|
|
|
|||
21
src/dev/cam/Roland.MDX-50
Normal file
21
src/dev/cam/Roland.MDX-50
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"file-ext": "rml",
|
||||
"token-space": "",
|
||||
"strip-comments": true,
|
||||
"pre":[
|
||||
"PA;PA;VS4;!VZ4;!PZ0,80;!MC1;"
|
||||
],
|
||||
"post":[
|
||||
"PA;PA;!PZ0,2420;PU0,6096;!MC0;"
|
||||
],
|
||||
"dwell":[
|
||||
"W{time};"
|
||||
],
|
||||
"spindle": [
|
||||
"!RC{speed};"
|
||||
],
|
||||
"settings": {
|
||||
"bed_width": 400,
|
||||
"bed_depth": 305
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,7 @@
|
|||
"G1 X200 E50 F800 ; extruder purge line",
|
||||
"G1 Z0.3 ; shift belt away 0.3mm",
|
||||
"G1 X0 E100 ; extruder purge line",
|
||||
"G1 Z2 E98 ; shift belt away 2mm, retract extruder",
|
||||
"G92 Z0 E-2 ; reset bed + extruder position",
|
||||
"G92 Z0 E0 ; reset bed + extruder position",
|
||||
"M117 CR-30 Printing..."
|
||||
],
|
||||
"post":[
|
||||
|
|
@ -54,12 +53,12 @@
|
|||
"origin_center": false,
|
||||
"extrude_abs": true,
|
||||
"bed_belt": true,
|
||||
"bed_width": 215,
|
||||
"bed_width": 220,
|
||||
"bed_depth": 300,
|
||||
"build_height": 170
|
||||
},
|
||||
"profiles":[{
|
||||
"processName": "CR30",
|
||||
"processName": "CR30 PLA",
|
||||
"sliceHeight": 0.25,
|
||||
"sliceShells": 3,
|
||||
"sliceShellOrder": "in-out",
|
||||
|
|
@ -68,43 +67,100 @@
|
|||
"sliceFillOverlap": 0.3,
|
||||
"sliceFillSparse": 0.2,
|
||||
"sliceFillType": "hex",
|
||||
"sliceAdaptive": false,
|
||||
"sliceMinHeight": 0,
|
||||
"sliceSupportDensity": 0.25,
|
||||
"sliceSupportOffset": 1.0,
|
||||
"sliceSupportGap": 0.75,
|
||||
"sliceSupportSize": 5,
|
||||
"sliceSupportArea": 0.1,
|
||||
"sliceSupportOffset": 0.4,
|
||||
"sliceSupportGap": 0,
|
||||
"sliceSupportSize": 6,
|
||||
"sliceSupportArea": 0.25,
|
||||
"sliceSupportExtra": 0,
|
||||
"sliceSupportAngle": 50,
|
||||
"sliceSupportAngle": 1,
|
||||
"sliceSupportNozzle": 0,
|
||||
"sliceSolidMinArea": 1,
|
||||
"sliceSolidLayers": 3,
|
||||
"sliceBottomLayers": 3,
|
||||
"sliceTopLayers": 3,
|
||||
"firstLayerRate": 15,
|
||||
"firstLayerPrintMult": 1.1,
|
||||
"firstLayerRate": 10,
|
||||
"firstLayerPrintMult": 1.10,
|
||||
"firstLayerYOffset": 0,
|
||||
"firstLayerBrim": 0,
|
||||
"firstLayerBeltLead": 0,
|
||||
"firstLayerFanSpeed": 0,
|
||||
"outputTemp": 210,
|
||||
"outputFanMax": 255,
|
||||
"outputBedTemp": 70,
|
||||
"outputFanSpeed": 255,
|
||||
"outputFeedrate": 50,
|
||||
"outputFinishrate": 50,
|
||||
"outputFinishrate": 40,
|
||||
"outputSeekrate": 80,
|
||||
"outputShellMult": 1.25,
|
||||
"outputFillMult": 1.25,
|
||||
"outputSparseMult": 1.25,
|
||||
"outputFanLayer": 1,
|
||||
"outputRetractDist": 3,
|
||||
"outputShellMult": 1.2,
|
||||
"outputFillMult": 1.2,
|
||||
"outputSparseMult": 1.2,
|
||||
"outputFanLayer": 0,
|
||||
"outputRetractDist": 5,
|
||||
"outputRetractSpeed": 40,
|
||||
"outputRetractDwell": 30,
|
||||
"outputShortPoly": 100.0,
|
||||
"outputRetractWipe": 1,
|
||||
"outputRetractDwell": 20,
|
||||
"outputShortPoly": 60.0,
|
||||
"outputMinSpeed": 10.0,
|
||||
"outputCoastDist": 0,
|
||||
"outputWipeDistance": 0,
|
||||
"outputCoastDist": 0.1,
|
||||
"outputWipeDistance": 1,
|
||||
"outputLayerRetract": false,
|
||||
"detectThinWalls": true,
|
||||
"sliceMinHeight": 0,
|
||||
"zHopDistance": 0,
|
||||
"antiBacklash": 0
|
||||
},{
|
||||
"processName": "CR30 PETG",
|
||||
"sliceHeight": 0.25,
|
||||
"sliceShells": 3,
|
||||
"sliceShellOrder": "in-out",
|
||||
"sliceLayerStart": "last",
|
||||
"sliceFillAngle": 45,
|
||||
"sliceFillOverlap": 0.3,
|
||||
"sliceFillSparse": 0.2,
|
||||
"sliceFillType": "hex",
|
||||
"sliceAdaptive": false,
|
||||
"sliceMinHeight": 0,
|
||||
"sliceSupportDensity": 0.25,
|
||||
"sliceSupportOffset": 0.4,
|
||||
"sliceSupportGap": 0,
|
||||
"sliceSupportSize": 6,
|
||||
"sliceSupportArea": 0.25,
|
||||
"sliceSupportExtra": 0,
|
||||
"sliceSupportAngle": 1,
|
||||
"sliceSupportNozzle": 0,
|
||||
"sliceSolidMinArea": 1,
|
||||
"sliceSolidLayers": 3,
|
||||
"sliceBottomLayers": 3,
|
||||
"sliceTopLayers": 3,
|
||||
"firstLayerRate": 10,
|
||||
"firstLayerPrintMult": 1.15,
|
||||
"firstLayerYOffset": 0,
|
||||
"firstLayerBrim": 0,
|
||||
"firstLayerBeltLead": 0,
|
||||
"firstLayerFanSpeed": 0,
|
||||
"outputTemp": 240,
|
||||
"outputFanMax": 0,
|
||||
"outputBedTemp": 70,
|
||||
"outputFanSpeed": 0,
|
||||
"outputFeedrate": 40,
|
||||
"outputFinishrate": 30,
|
||||
"outputSeekrate": 80,
|
||||
"outputShellMult": 1.2,
|
||||
"outputFillMult": 1.2,
|
||||
"outputSparseMult": 1.2,
|
||||
"outputFanLayer": 0,
|
||||
"outputRetractDist": 5.5,
|
||||
"outputRetractSpeed": 30,
|
||||
"outputRetractWipe": 1,
|
||||
"outputRetractDwell": 20,
|
||||
"outputShortPoly": 60.0,
|
||||
"outputMinSpeed": 10.0,
|
||||
"outputCoastDist": 0.1,
|
||||
"outputWipeDistance": 1,
|
||||
"outputLayerRetract": false,
|
||||
"detectThinWalls": true,
|
||||
"zHopDistance": 0,
|
||||
"antiBacklash": 0
|
||||
}]
|
||||
|
|
|
|||
|
|
@ -39,5 +39,59 @@
|
|||
"bed_width": 220,
|
||||
"bed_depth": 220,
|
||||
"build_height": 300
|
||||
}
|
||||
},
|
||||
"profiles":[{
|
||||
"processName": "Ender3 PLA",
|
||||
"sliceHeight": 0.25,
|
||||
"sliceShells": 3,
|
||||
"sliceShellOrder": "in-out",
|
||||
"sliceLayerStart": "last",
|
||||
"sliceFillAngle": 45,
|
||||
"sliceFillOverlap": 0.3,
|
||||
"sliceFillSparse": 0.2,
|
||||
"sliceFillType": "hex",
|
||||
"sliceAdaptive": false,
|
||||
"sliceMinHeight": 0,
|
||||
"sliceSupportDensity": 0.25,
|
||||
"sliceSupportOffset": 0.4,
|
||||
"sliceSupportGap": 0,
|
||||
"sliceSupportSize": 6,
|
||||
"sliceSupportArea": 0.25,
|
||||
"sliceSupportExtra": 0,
|
||||
"sliceSupportAngle": 1,
|
||||
"sliceSupportNozzle": 0,
|
||||
"sliceSolidMinArea": 1,
|
||||
"sliceSolidLayers": 3,
|
||||
"sliceBottomLayers": 3,
|
||||
"sliceTopLayers": 3,
|
||||
"firstLayerRate": 10,
|
||||
"firstLayerPrintMult": 1.10,
|
||||
"firstLayerYOffset": 0,
|
||||
"firstLayerBrim": 0,
|
||||
"firstLayerBeltLead": 0,
|
||||
"firstLayerFanSpeed": 0,
|
||||
"outputTemp": 210,
|
||||
"outputFanMax": 255,
|
||||
"outputBedTemp": 70,
|
||||
"outputFanSpeed": 255,
|
||||
"outputFeedrate": 50,
|
||||
"outputFinishrate": 40,
|
||||
"outputSeekrate": 80,
|
||||
"outputShellMult": 1.2,
|
||||
"outputFillMult": 1.2,
|
||||
"outputSparseMult": 1.2,
|
||||
"outputFanLayer": 0,
|
||||
"outputRetractDist": 5,
|
||||
"outputRetractSpeed": 40,
|
||||
"outputRetractWipe": 1,
|
||||
"outputRetractDwell": 20,
|
||||
"outputShortPoly": 60.0,
|
||||
"outputMinSpeed": 10.0,
|
||||
"outputCoastDist": 0.1,
|
||||
"outputWipeDistance": 1,
|
||||
"outputLayerRetract": false,
|
||||
"detectThinWalls": true,
|
||||
"zHopDistance": 0,
|
||||
"antiBacklash": 0
|
||||
}]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
"G1 Z0.25 F180 ; move z to 0.25mm over bed",
|
||||
"G92 E0 ; zero the extruded",
|
||||
"M109 S{temp} T{tool} ; wait for extruder to reach target temp",
|
||||
"G1 E15 F200 ; purge 15mm from extruder",
|
||||
"G92 E0 ; zero the extruded",
|
||||
"G1 F225 ; set feed speed"
|
||||
],
|
||||
|
|
@ -19,7 +18,6 @@
|
|||
"M107 ; turn off filament cooling fan",
|
||||
"M104 S0 T{tool} ; turn off right extruder",
|
||||
"M140 S0 T{tool} ; turn off bed",
|
||||
"G1 Z{z_max} F1200 ; drop bed",
|
||||
"G28 X0 Y0 ; home XY axes",
|
||||
"M84 ; disable stepper motors"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
"G1 Z0.25 F180 ; move z to 0.25mm over bed",
|
||||
"G92 E0 ; zero the extruded",
|
||||
"M109 S{temp} T{tool} ; wait for extruder to reach target temp",
|
||||
"G1 E15 F200 ; purge 15mm from extruder",
|
||||
"G92 E0 ; zero the extruded",
|
||||
"G1 F225 ; set feed speed"
|
||||
],
|
||||
|
|
@ -19,7 +18,6 @@
|
|||
"M107 ; turn off filament cooling fan",
|
||||
"M104 S0 T{tool} ; turn off right extruder",
|
||||
"M140 S0 T{tool} ; turn off bed",
|
||||
"G1 Z{z_max} F1200 ; drop bed",
|
||||
"G28 X0 Y0 ; home XY axes",
|
||||
"M84 ; disable stepper motors"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
"G1 Z0.25 F180 ; move z to 0.25mm over bed",
|
||||
"G92 E0 ; zero the extruded",
|
||||
"M109 S{temp} T{tool} ; wait for extruder to reach target temp",
|
||||
"G1 E15 F200 ; purge 15mm from extruder",
|
||||
"G92 E0 ; zero the extruded",
|
||||
"G1 F225 ; set feed speed"
|
||||
],
|
||||
|
|
@ -19,7 +18,6 @@
|
|||
"M107 ; turn off filament cooling fan",
|
||||
"M104 S0 T{tool} ; turn off right extruder",
|
||||
"M140 S0 T{tool} ; turn off bed",
|
||||
"G1 Z{z_max} F1200 ; drop bed",
|
||||
"G28 X0 Y0 ; home XY axes",
|
||||
"M84 ; disable stepper motors"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
"G1 Z0.25 F180 ; move z to 0.25mm over bed",
|
||||
"G92 E0 ; zero the extruded",
|
||||
"M109 S{temp} T{tool} ; wait for extruder to reach target temp",
|
||||
"G1 E15 F200 ; purge 15mm from extruder",
|
||||
"G92 E0 ; zero the extruded",
|
||||
"G1 F225 ; set feed speed"
|
||||
],
|
||||
|
|
@ -19,7 +18,6 @@
|
|||
"M107 ; turn off filament cooling fan",
|
||||
"M104 S0 T{tool} ; turn off right extruder",
|
||||
"M140 S0 T{tool} ; turn off bed",
|
||||
"G1 Z{z_max} F1200 ; drop bed",
|
||||
"G28 X0 Y0 ; home XY axes",
|
||||
"M84 ; disable stepper motors"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@
|
|||
"cmd":{
|
||||
"fan_power": "M106 S{fan_speed}"
|
||||
},
|
||||
"proc": "kiri_fdm_xyz_mini_w",
|
||||
"file-ext": "3w",
|
||||
"settings":{
|
||||
"origin_center": false,
|
||||
"extrude_abs": true,
|
||||
|
|
|
|||
1
src/ext/base64.js
Symbolic link
1
src/ext/base64.js
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../node_modules/base64-js/base64js.min.js
|
||||
1
src/ext/jszip.js
Symbolic link
1
src/ext/jszip.js
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../node_modules/jszip/dist/jszip.js
|
||||
1
src/ext/three-bgu.js
Symbolic link
1
src/ext/three-bgu.js
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../node_modules/three/examples/js/utils/BufferGeometryUtils.js
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
function time() { return Date.now() }
|
||||
|
||||
function lerp(from, to, maxInc) {
|
||||
function lerp(from, to, maxInc, incFrom) {
|
||||
let dir = Math.sign(to - from);
|
||||
let delta = Math.abs(to - from);
|
||||
let steps = Math.floor(delta / maxInc);
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
steps++;
|
||||
per = delta / steps;
|
||||
}
|
||||
let out = [];
|
||||
let out = incFrom ? [from] : [];
|
||||
while (steps-- > 0) {
|
||||
from += per * dir;
|
||||
out.push(from);
|
||||
|
|
@ -316,6 +316,94 @@
|
|||
return (d2y * d1x) - (d2x * d1y);
|
||||
}
|
||||
|
||||
/**
|
||||
* return circle center given three points
|
||||
* from https://math.stackexchange.com/questions/1076177/3d-coordinates-of-circle-center-given-three-point-on-the-circle
|
||||
*/
|
||||
function center3d(a,b,c) {
|
||||
let ax = a.x,
|
||||
ay = a.y,
|
||||
az = a.z || 0,
|
||||
bx = b.x,
|
||||
by = b.y,
|
||||
bz = b.z || 0,
|
||||
cx = c.x,
|
||||
cy = c.y,
|
||||
cz = c.z || 0,
|
||||
Cx = bx-ax,
|
||||
Cy = by-ay,
|
||||
Cz = bz-az,
|
||||
Bx = cx-ax,
|
||||
By = cy-ay,
|
||||
Bz = cz-az,
|
||||
B2 = (ax*ax)-(cx*cx)+(ay*ay)-(cy*cy)+(az*az)-(cz*cz),
|
||||
C2 = (ax*ax)-(bx*bx)+(ay*ay)-(by*by)+(az*az)-(bz*bz),
|
||||
CByz = Cy*Bz-Cz*By,
|
||||
CBxz = Cx*Bz-Cz*Bx,
|
||||
CBxy = Cx*By-Cy*Bx,
|
||||
ZZ1 = -(Bz-Cz*Bx/Cx)/(By-Cy*Bx/Cx),
|
||||
Z01 = -(B2-Bx/Cx*C2)/(2*(By-Cy*Bx/Cx)),
|
||||
ZZ2 = -(ZZ1*Cy+Cz)/Cx,
|
||||
Z02 = -(2*Z01*Cy+C2)/(2*Cx),
|
||||
dz = -((Z02-ax)*CByz-(Z01-ay)*CBxz-az*CBxy)/(ZZ2*CByz-ZZ1*CBxz+CBxy),
|
||||
dx = ZZ2*dz + Z02,
|
||||
dy = ZZ1*dz + Z01;
|
||||
|
||||
return {x:dx, y:dy, z:dz};
|
||||
}
|
||||
|
||||
/**
|
||||
* return circle center given three points
|
||||
* from https://stackoverflow.com/questions/4103405/what-is-the-algorithm-for-finding-the-center-of-a-circle-from-three-points
|
||||
*/
|
||||
function center2d(A,B,C,rad) {
|
||||
// let yDelta_a = B.y - A.y,
|
||||
// xDelta_a = B.x - A.x,
|
||||
// yDelta_b = C.y - B.y,
|
||||
// xDelta_b = C.x - B.x,
|
||||
// aSlope = yDelta_a/xDelta_a,
|
||||
// bSlope = yDelta_b/xDelta_b,
|
||||
// center = {x:0, y:0, z:0};
|
||||
// center.x = (aSlope*bSlope*(A.y - C.y) + bSlope*(A.x + B.x) - aSlope*(B.x+C.x) )/(2* (bSlope-aSlope) );
|
||||
// center.y = -1*(center.x - (A.x+B.x)/2)/aSlope + (A.y+B.y)/2;
|
||||
let center = center3d(A,B,C);
|
||||
if (rad) {
|
||||
let dx = center.x - A.x;
|
||||
let dy = center.y - A.y;
|
||||
center.r = Math.sqrt(dx*dx + dy*dy)
|
||||
// if (isNaN(center.r)) console.log('NaN',{dx,dy,A,B,C,center,xDelta_a,xDelta_b,yDelta_a,yDelta_b,aSlope,bSlope});
|
||||
}
|
||||
return center;
|
||||
}
|
||||
|
||||
/**
|
||||
* return two possible circle centers given two points and a radius
|
||||
* https://stackoverflow.com/questions/36211171/finding-center-of-a-circle-given-two-points-and-radius
|
||||
*/
|
||||
function center2pr(p1, p2, r) {
|
||||
let x1 = p1.x,
|
||||
x2 = p2.x,
|
||||
y1 = p1.y,
|
||||
y2 = p2.y,
|
||||
q = Math.sqrt(Math.pow((x2-x1),2) + Math.pow((y2-y1),2)),
|
||||
y3 = (y1+y2)/2,
|
||||
x3 = (x1+x2)/2,
|
||||
basex = Math.sqrt(Math.pow(r,2)-Math.pow((q/2),2))*(y1-y2)/q, //calculate once
|
||||
basey = Math.sqrt(Math.pow(r,2)-Math.pow((q/2),2))*(x2-x1)/q, //calculate once
|
||||
centerx1 = x3 + basex, //center x of circle 1
|
||||
centery1 = y3 + basey, //center y of circle 1
|
||||
centerx2 = x3 - basex, //center x of circle 2
|
||||
centery2 = y3 - basey; //center y of circle 2
|
||||
return [{x:centerx1, y:centery1}, {x:centerx2, y:centery2}];
|
||||
}
|
||||
|
||||
function thetaDiff(n1, n2, sign) {
|
||||
let diff = n2 - n1;
|
||||
while (diff < -Math.PI) diff += Math.PI * 2;
|
||||
while (diff > Math.PI) diff -= Math.PI * 2;
|
||||
return sign ? diff : Math.abs(diff);
|
||||
}
|
||||
|
||||
/** ******************************************************************
|
||||
* Connect to base
|
||||
******************************************************************* */
|
||||
|
|
@ -399,6 +487,10 @@
|
|||
time,
|
||||
round,
|
||||
area2,
|
||||
center2d,
|
||||
center3d,
|
||||
center2pr,
|
||||
thetaDiff,
|
||||
distSq : dist2,
|
||||
distSqv2 : dist2v2,
|
||||
inRange,
|
||||
|
|
|
|||
|
|
@ -260,6 +260,198 @@
|
|||
return Math.abs(diff);
|
||||
}
|
||||
|
||||
// generate center crossing point cloud
|
||||
PRO.centers = function(step, z, min, max, opt = {}) {
|
||||
let cloud = [],
|
||||
bounds = this.bounds,
|
||||
lines = opt.lines || false,
|
||||
stepoff = step / 2,
|
||||
set = [this.points];
|
||||
|
||||
if (this.inner) {
|
||||
for (let inner of this.inner) {
|
||||
set.push(inner.points);
|
||||
}
|
||||
}
|
||||
|
||||
for (let y of UTIL.lerp(bounds.miny + stepoff, bounds.maxy - stepoff, step, true)) {
|
||||
let ints = [];
|
||||
for (let points of set) {
|
||||
let length = points.length;
|
||||
for (let i=0; i<length; i++) {
|
||||
let p1 = points[i % length];
|
||||
let p2 = points[(i+1) % length];
|
||||
if (
|
||||
(p1.y <= y && p2.y > y) ||
|
||||
(p1.y > y && p2.y <= y)
|
||||
) ints.push([p1,p2]);
|
||||
}
|
||||
}
|
||||
let cntr = [];
|
||||
if (ints.length && ints.length % 2 === 0) {
|
||||
for (let int of ints) {
|
||||
let [p1, p2] = int;
|
||||
if (p2.y < p1.y) {
|
||||
let tp = p1;
|
||||
p1 = p2;
|
||||
p2 = tp;
|
||||
}
|
||||
let minx = Math.min(p1.x, p2.x);
|
||||
let maxx = Math.max(p1.x, p2.x);
|
||||
let miny = Math.min(p1.y, p2.y);
|
||||
let maxy = Math.max(p1.y, p2.y);
|
||||
let dx = p2.x - p1.x;
|
||||
let dy = maxy - miny;
|
||||
let pct = (y - miny) / dy;
|
||||
let xpo = p1.x + pct * dx;
|
||||
cntr.push(xpo);
|
||||
}
|
||||
}
|
||||
cntr.sort((a, b) => {
|
||||
return b - a;
|
||||
});
|
||||
let lp, eo = 0;
|
||||
for (let x of cntr) {
|
||||
let p = BASE.newPoint(x, y, z);
|
||||
if (eo++ % 2) {
|
||||
let d = lp.distTo2D(p);
|
||||
if (d >= min && d <= max) {
|
||||
if (lines) {
|
||||
cloud.push(lp);
|
||||
cloud.push(p);
|
||||
} else {
|
||||
cloud.push(BASE.newPoint(
|
||||
(lp.x + p.x) / 2, y, z
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lp = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let x of UTIL.lerp(bounds.minx + stepoff, bounds.maxx - stepoff, step, true)) {
|
||||
let ints = [];
|
||||
for (let points of set) {
|
||||
let length = points.length;
|
||||
for (let i=0; i<length; i++) {
|
||||
let p1 = points[i % length];
|
||||
let p2 = points[(i+1) % length];
|
||||
if (
|
||||
(p1.x <= x && p2.x > x) ||
|
||||
(p1.x > x && p2.x <= x)
|
||||
) ints.push([p1,p2]);
|
||||
}
|
||||
}
|
||||
let cntr = [];
|
||||
if (ints.length && ints.length % 2 === 0) {
|
||||
for (let int of ints) {
|
||||
let [p1, p2] = int;
|
||||
if (p2.x < p1.x) {
|
||||
let tp = p1;
|
||||
p1 = p2;
|
||||
p2 = tp;
|
||||
}
|
||||
let minx = Math.min(p1.x, p2.x);
|
||||
let maxx = Math.max(p1.x, p2.x);
|
||||
let miny = Math.min(p1.y, p2.y);
|
||||
let maxy = Math.max(p1.y, p2.y);
|
||||
let dx = maxx - minx;
|
||||
let dy = p2.y - p1.y;
|
||||
let pct = (x - minx) / dx;
|
||||
let ypo = p1.y + pct * dy;
|
||||
cntr.push(ypo);
|
||||
}
|
||||
}
|
||||
cntr.sort((a, b) => {
|
||||
return b - a;
|
||||
});
|
||||
let lp, eo = 0;
|
||||
for (let y of cntr) {
|
||||
let p = BASE.newPoint(x, y, z);
|
||||
if (eo++ % 2) {
|
||||
let d = lp.distTo2D(p);
|
||||
if (d >= min && d <= max) {
|
||||
if (lines) {
|
||||
cloud.push(lp);
|
||||
cloud.push(p);
|
||||
} else {
|
||||
cloud.push(BASE.newPoint(
|
||||
x, (lp.y + p.y) / 2, z
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lp = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lines) {
|
||||
return cloud;
|
||||
}
|
||||
|
||||
let mindist = opt.mindist || step * 1.5;
|
||||
|
||||
function build(poly) {
|
||||
let lastp = poly.last();
|
||||
let minp;
|
||||
let mind = Infinity;
|
||||
for (let point of cloud) {
|
||||
let dist = point.distTo2D(lastp);
|
||||
if (dist < mindist && dist < mind) {
|
||||
mind = dist;
|
||||
minp = point;
|
||||
}
|
||||
}
|
||||
if (minp) {
|
||||
cloud = cloud.filter(p => p !== minp);
|
||||
poly.push(minp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// join points into polys
|
||||
let polys = [];
|
||||
let poly = [];
|
||||
while (cloud.length) {
|
||||
if (poly.length === 0) {
|
||||
poly = [ cloud.shift() ];
|
||||
polys.push(poly);
|
||||
continue;
|
||||
}
|
||||
if (build(poly)) {
|
||||
continue;
|
||||
}
|
||||
if (!poly.flip) {
|
||||
poly.reverse();
|
||||
poly.flip = true;
|
||||
continue;
|
||||
}
|
||||
if (poly.length) {
|
||||
poly = [];
|
||||
} else {
|
||||
throw "whoop there it is";
|
||||
}
|
||||
}
|
||||
|
||||
return polys
|
||||
.filter(poly => poly.length > 1)
|
||||
.map(poly => {
|
||||
let np = BASE.newPolygon().setOpen();
|
||||
for (let p of poly) {
|
||||
np.push(p);
|
||||
}
|
||||
if (np.last().distTo2D(np.first()) <= max) {
|
||||
np.setClosed();
|
||||
}
|
||||
np = np.clean();
|
||||
return np;
|
||||
});
|
||||
};
|
||||
|
||||
PRO.debur = function(dist) {
|
||||
if (this.len < 2) {
|
||||
return null;
|
||||
|
|
@ -666,6 +858,16 @@
|
|||
return this;
|
||||
};
|
||||
|
||||
PRO.addObj = function(obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
for (let o of obj) {
|
||||
this.addObj(o);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return this.add(obj.x, obj.y, obj.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* append array of points to polygon and return polygon
|
||||
*
|
||||
|
|
@ -1201,9 +1403,11 @@
|
|||
return this;
|
||||
};
|
||||
|
||||
function fromClipperPath(path,z) {
|
||||
function fromClipperPath(path, z) {
|
||||
let poly = newPolygon(), i = 0, l = path.length;
|
||||
while (i < l) poly.push(newPoint(null,null,z,null,path[i++]));
|
||||
while (i < l) {
|
||||
poly.push(newPoint(null,null,z,null,path[i++]));
|
||||
}
|
||||
return poly;
|
||||
};
|
||||
|
||||
|
|
@ -1223,6 +1427,31 @@
|
|||
poly.parent = parent || this.parent;
|
||||
poly.area2 = this.area2;
|
||||
poly.open = this.open;
|
||||
if (this.open) {
|
||||
// when open, ensure first point on new poly matches old
|
||||
let start = this.points[0];
|
||||
let points = poly.points;
|
||||
let length = points.length;
|
||||
let mi, min = Infinity;
|
||||
for (let i=0; i<length; i++) {
|
||||
let d = points[i].distTo2D(start);
|
||||
if (d < min) {
|
||||
min = d;
|
||||
mi = i;
|
||||
}
|
||||
}
|
||||
// mi > 0 means first point didn't match
|
||||
if (mi) {
|
||||
let nupoints = [];
|
||||
for (let i=mi; i<length; i++) {
|
||||
nupoints.push(points[i]);
|
||||
}
|
||||
for (let i=0; i<mi; i++) {
|
||||
nupoints.push(points[i]);
|
||||
}
|
||||
poly.points = nupoints;
|
||||
}
|
||||
}
|
||||
return poly;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
expand,
|
||||
expand_lines,
|
||||
union,
|
||||
inset,
|
||||
nest,
|
||||
diff,
|
||||
setZ,
|
||||
|
|
@ -540,6 +541,43 @@
|
|||
return opts.flat ? opts.outs : polys;
|
||||
}
|
||||
|
||||
/**
|
||||
* progressive insetting that does inset + outset to debur as well
|
||||
* as performing subtractive analysis between initial layer shell (ref)
|
||||
* and last offset (cmp) to produce gap candidates (for thinfill)
|
||||
*/
|
||||
function inset(polys, dist, count, z) {
|
||||
let total = count;
|
||||
let layers = [];
|
||||
let ref = polys;
|
||||
let depth = 0;
|
||||
while (count-- > 0 && ref && ref.length) {
|
||||
let off = offset(ref, -dist, {z});
|
||||
let mid = offset(off, dist / 2, {z});
|
||||
let cmp = offset(off, dist, {z});
|
||||
let gap = [];
|
||||
let aref = ref.map(p => p.areaDeep()).reduce((a,p) => a +p);
|
||||
let cref = cmp.length ? cmp.map(p => p.areaDeep()).reduce((a,p) => a + p) : 0;
|
||||
// threshold subtraction to area deltas > 0.1 % to filter out false
|
||||
// positives where inset/outset are identical floating point error
|
||||
if (Math.abs(aref - cref) > 1 - (Math.abs(aref / cref) / 1000)) {
|
||||
subtract(ref, cmp, gap, null, z);
|
||||
}
|
||||
layers.push({idx: total-count, off, mid, gap});
|
||||
// fixup depth cues
|
||||
for (let m of mid) {
|
||||
m.depth = depth++;
|
||||
if (m.inner) {
|
||||
for (let mi of m.inner) {
|
||||
mi.depth = m.depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
ref = off;
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
/**
|
||||
* todo use clipper opne poly clipping?
|
||||
*
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@
|
|||
*/
|
||||
function wireframe(group, points, color) {
|
||||
if (points.length % 3 != 0) throw "invalid line : "+points.length;
|
||||
let lines = new THREE.Geometry(),
|
||||
let lines = new THREE.BufferGeometry(),
|
||||
hash = {},
|
||||
added = 0;
|
||||
added = 0,
|
||||
vertices = [];
|
||||
for (let i = 0; i < points.length; i += 3) {
|
||||
let p1 = points[i],
|
||||
p2 = points[i + 1],
|
||||
|
|
@ -41,22 +42,28 @@
|
|||
l2 = newOrderedLine(p2, p3),
|
||||
l3 = newOrderedLine(p3, p1);
|
||||
if (!hash[l1.key]) {
|
||||
lines.vertices.push(new THREE.Vector3(p1.x, p1.y, p1.z));
|
||||
lines.vertices.push(new THREE.Vector3(p2.x, p2.y, p2.z));
|
||||
vertices.appendAll([
|
||||
p1.x, p1.y, p1.z,
|
||||
p2.x, p2.y, p2.z
|
||||
]);
|
||||
hash[l1.key] = ++added;
|
||||
}
|
||||
if (!hash[l2.key]) {
|
||||
lines.vertices.push(new THREE.Vector3(p2.x, p2.y, p2.z));
|
||||
lines.vertices.push(new THREE.Vector3(p3.x, p3.y, p3.z));
|
||||
vertices.appendAll([
|
||||
p2.x, p2.y, p2.z,
|
||||
p3.x, p3.y, p3.z
|
||||
]);
|
||||
hash[l2.key] = ++added;
|
||||
}
|
||||
if (!hash[l3.key]) {
|
||||
lines.vertices.push(new THREE.Vector3(p3.x, p3.y, p3.z));
|
||||
lines.vertices.push(new THREE.Vector3(p1.x, p1.y, p1.z));
|
||||
vertices.appendAll([
|
||||
p3.x, p3.y, p3.z,
|
||||
p1.x, p1.y, p1.z
|
||||
]);
|
||||
hash[l3.key] = ++added;
|
||||
}
|
||||
}
|
||||
lines.verticesNeedUpdate = true;
|
||||
lines.setAttribute('position', new THREE.BufferAttribute( vertices.toFloat32(), 3 ) );
|
||||
let mesh = new THREE.LineSegments(lines, getMaterial(color));
|
||||
group.add(mesh);
|
||||
return mesh;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
if (!self.kiri) {
|
||||
self.kiri = {
|
||||
beta: 2608,
|
||||
beta: 2801,
|
||||
driver: {}, // driver modules
|
||||
loader: [] // module loading: array of functions
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ let KIRI = self.kiri = self.kiri || {},
|
|||
seqid = 1,
|
||||
syncd = {},
|
||||
running = {},
|
||||
slicing = {},
|
||||
worker = null;
|
||||
worker = null,
|
||||
restarting = false
|
||||
// occ = new Worker("/kiri/ext/occ-worker.js", {type:"module"}),
|
||||
;
|
||||
|
||||
/**
|
||||
* @param {Function} fn name of function in KIRI.worker
|
||||
|
|
@ -26,8 +28,11 @@ let KIRI = self.kiri = self.kiri || {},
|
|||
function send(fn, data, onreply, zerocopy) {
|
||||
let seq = seqid++;
|
||||
|
||||
running[seq] = { fn:onreply };
|
||||
// console.log('send', data);
|
||||
if (onreply) {
|
||||
// track it only when we expect and can handle a reply
|
||||
running[seq] = { fn:onreply };
|
||||
}
|
||||
// console.log('send', {fn, data, onreply});
|
||||
|
||||
try {
|
||||
worker.postMessage({
|
||||
|
|
@ -55,25 +60,35 @@ KIRI.work = {
|
|||
}
|
||||
},
|
||||
|
||||
isSlicing: function() {
|
||||
isBusy: function() {
|
||||
let current = 0;
|
||||
for (let key in slicing) {
|
||||
current++;
|
||||
|
||||
for (let rec of Object.values(running)) {
|
||||
if (rec.fn) current++;
|
||||
}
|
||||
return current > 0;
|
||||
},
|
||||
|
||||
restart: function() {
|
||||
// prevent re-entry from cancel callback
|
||||
if (restarting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (worker) {
|
||||
worker.terminate();
|
||||
}
|
||||
|
||||
for (let key in slicing) {
|
||||
slicing[key]({error: "cancelled slicing"});
|
||||
restarting = true;
|
||||
|
||||
for (let key in running) {
|
||||
let rec = running[key];
|
||||
if (rec.fn) {
|
||||
rec.fn({error: "cancelled operation"});
|
||||
}
|
||||
}
|
||||
|
||||
syncd = {};
|
||||
slicing = {};
|
||||
running = {};
|
||||
worker = KIRI.work.newWorker();
|
||||
|
||||
|
|
@ -81,7 +96,7 @@ KIRI.work = {
|
|||
let now = time(),
|
||||
reply = e.data,
|
||||
record = running[reply.seq],
|
||||
onreply = record.fn;
|
||||
onreply = record ? record.fn : undefined;
|
||||
|
||||
// console.log('recv', reply.data)
|
||||
if (reply.done) {
|
||||
|
|
@ -91,8 +106,14 @@ KIRI.work = {
|
|||
// calculate and replace recv time
|
||||
reply.time_recv = now - reply.time_recv;
|
||||
|
||||
onreply(reply.data, reply);
|
||||
if (onreply) {
|
||||
onreply(reply.data, reply);
|
||||
} else {
|
||||
console.log({unexpected_reply: reply});
|
||||
}
|
||||
};
|
||||
|
||||
restarting = false;
|
||||
},
|
||||
|
||||
decimate: function(vertices, options, callback) {
|
||||
|
|
@ -105,35 +126,36 @@ KIRI.work = {
|
|||
},
|
||||
|
||||
config: function(obj) {
|
||||
send("config", obj, function(reply) {
|
||||
// console.log({config:reply});
|
||||
});
|
||||
send("config", obj, function(reply) { });
|
||||
},
|
||||
|
||||
clear: function(widget) {
|
||||
send("clear", widget ? {id:widget.id} : {}, function(reply) {
|
||||
syncd = {};
|
||||
});
|
||||
clear: function() {
|
||||
syncd = {};
|
||||
send("clear", {}, function(reply) { });
|
||||
},
|
||||
|
||||
snap: function(data) {
|
||||
send("snap", data, function(reply) {
|
||||
// console.log({snap:reply})
|
||||
});
|
||||
send("snap", data, function(reply) { });
|
||||
},
|
||||
|
||||
// widget sync
|
||||
sync: function(widget) {
|
||||
let widgets = widget ? [ widget ] : KIRI.api.widgets.all();
|
||||
sync: function(widgets) {
|
||||
if (!widgets) {
|
||||
widgets = KIRI.api.widgets.all();
|
||||
}
|
||||
// send list of currently valid widgets
|
||||
send("sync", { valid: widgets.map(w => w.id) }, () => {});
|
||||
// sync any widget that has changed
|
||||
widgets.forEach(widget => {
|
||||
if (widget.modified || !syncd[widget.id]) {
|
||||
syncd[widget.id] = true;
|
||||
let vertices = widget.getGeoVertices().buffer.slice(0);
|
||||
send("sync", {
|
||||
id: widget.id,
|
||||
group: widget.group.id,
|
||||
track: widget.track,
|
||||
vertices: vertices,
|
||||
position: widget.mesh.position,
|
||||
tracking: widget.track
|
||||
}, done => {
|
||||
widget.modified = false;
|
||||
}, [vertices]);
|
||||
|
|
@ -141,18 +163,42 @@ KIRI.work = {
|
|||
});
|
||||
},
|
||||
|
||||
slice: function(settings, widget, callback) {
|
||||
CLIENT.sync(widget);
|
||||
slicing[widget.id] = callback;
|
||||
rotate: function(settings, callback) {
|
||||
send("rotate", { settings }, reply => {
|
||||
if (reply.group) {
|
||||
for (let widget of KIRI.Widget.Groups.forid(reply.group)) {
|
||||
widget.belt = reply.belt;
|
||||
}
|
||||
} else if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
unrotate: function(settings, callback) {
|
||||
send("unrotate", { settings }, reply => {
|
||||
if (reply.group) {
|
||||
for (let widget of KIRI.Widget.Groups.forid(reply.group)) {
|
||||
widget.rotinfo = reply.rotinfo;
|
||||
}
|
||||
} else if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
slice: function(settings, widget, callback) {
|
||||
send("slice", {
|
||||
id: widget.id,
|
||||
settings: settings
|
||||
}, function(reply) {
|
||||
if (reply.done || reply.error) {
|
||||
delete slicing[widget.id];
|
||||
}
|
||||
callback(reply);
|
||||
if (reply.done || reply.error) {
|
||||
// in belt mode, slicing modifies a widget and requires re-sync
|
||||
if (settings.device.bedBelt) {
|
||||
widget.modified = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -164,6 +210,9 @@ KIRI.work = {
|
|||
if (reply.done) {
|
||||
done(reply.output, reply.maxSpeed);
|
||||
}
|
||||
if (reply.error) {
|
||||
done(reply);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -175,6 +224,9 @@ KIRI.work = {
|
|||
if (reply.done) {
|
||||
ondone(reply.output);
|
||||
}
|
||||
if (reply.error) {
|
||||
ondone(null, reply.error);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -204,7 +256,7 @@ KIRI.work = {
|
|||
}
|
||||
send("parse", args, function(reply) {
|
||||
if (reply.progress) {
|
||||
progress(reply);
|
||||
progress(reply.progress);
|
||||
}
|
||||
if (reply.parsed) {
|
||||
done(KIRI.codec.decode(reply.parsed), reply.maxSpeed);
|
||||
|
|
@ -221,6 +273,16 @@ KIRI.work = {
|
|||
output(reply.done);
|
||||
}
|
||||
}, [ data.png ]);
|
||||
},
|
||||
|
||||
zip: function(files, progress, output) {
|
||||
send("zip", {files}, reply => {
|
||||
if (reply.percent !== undefined) {
|
||||
progress(reply);
|
||||
} else {
|
||||
output(reply);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
const zeroOut = true;
|
||||
|
||||
const codec = KIRI.codec = {
|
||||
undef: undefined,
|
||||
encode: encode,
|
||||
decode: decode,
|
||||
registerDecoder: registerDecoder,
|
||||
|
|
@ -154,7 +155,7 @@
|
|||
polys: encode(layer.polys, state),
|
||||
lines: encodePointArray(layer.lines, state),
|
||||
faces: codec.allocFloat32Array(layer.faces),
|
||||
cface: layer.cface,
|
||||
cface: layer.cface || codec.undef,
|
||||
color: layer.color,
|
||||
paths: layer.paths.map(lp => {
|
||||
const pe = {
|
||||
|
|
@ -167,13 +168,13 @@
|
|||
}
|
||||
return pe;
|
||||
}),
|
||||
cpath: layer.cpath,
|
||||
cpath: layer.cpath || codec.undef,
|
||||
off: layer.off
|
||||
};
|
||||
if (zeroOut && state.zeros && e.faces.length) {
|
||||
state.zeros.push(e.faces.buffer);
|
||||
}
|
||||
// console.log('-->',e);
|
||||
// console.log('-->',layer,e);
|
||||
return e;
|
||||
})
|
||||
};
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@
|
|||
extFilament: device.filamentSize,
|
||||
extNozzle: device.nozzleSize,
|
||||
extSelect: ["T0"],
|
||||
extDeselect: [],
|
||||
extOffsetX: 0,
|
||||
extOffsetY: 0
|
||||
}];
|
||||
|
|
@ -143,6 +144,7 @@
|
|||
if (rec.offset_x) e.extOffsetX = rec.offset_x;
|
||||
if (rec.offset_y) e.extOffsetY = rec.offset_y;
|
||||
if (rec.select) e.extSelect = rec.select;
|
||||
if (rec.deselect) e.extDeselect = rec.deselect;
|
||||
device.extruders.push(e);
|
||||
});
|
||||
} else {
|
||||
|
|
@ -259,6 +261,7 @@
|
|||
bedHeight: 2.5,
|
||||
bedRound: false,
|
||||
bedBelt: false,
|
||||
fwRetract: false,
|
||||
originCenter: false,
|
||||
maxHeight: 150,
|
||||
gcodePre: [],
|
||||
|
|
@ -273,6 +276,7 @@
|
|||
extFilament: 1.75,
|
||||
extNozzle: 0.4,
|
||||
extSelect: ["T0"],
|
||||
extDeselect: [],
|
||||
extOffsetX: 0,
|
||||
extOffsetY: 0
|
||||
}]
|
||||
|
|
@ -285,12 +289,14 @@
|
|||
sliceShellOrder: "in-out",
|
||||
sliceLayerStart: "last",
|
||||
sliceFillAngle: 45,
|
||||
sliceFillWidth: 1,
|
||||
sliceFillOverlap: 0.3,
|
||||
sliceFillSparse: 0.5,
|
||||
sliceFillRate: 0,
|
||||
sliceFillType: "hex",
|
||||
sliceSupportDensity: 0.25,
|
||||
sliceSupportOffset: 1.0,
|
||||
sliceSupportGap: 0.75,
|
||||
sliceSupportGap: 1,
|
||||
sliceSupportSize: 5,
|
||||
sliceSupportArea: 0.1,
|
||||
sliceSupportExtra: 0,
|
||||
|
|
@ -311,10 +317,11 @@
|
|||
firstLayerBedTemp: 0,
|
||||
firstLayerBrim: 0,
|
||||
firstLayerBrimTrig: 0,
|
||||
firstLayerBeltLead: 3,
|
||||
firstLayerFanSpeed: 0,
|
||||
outputRaft: false,
|
||||
outputRaftSpacing: 0.2,
|
||||
outputTemp: 200,
|
||||
outputFanMax: 255,
|
||||
outputBedTemp: 60,
|
||||
outputFeedrate: 50,
|
||||
outputFinishrate: 50,
|
||||
|
|
@ -322,27 +329,30 @@
|
|||
outputShellMult: 1.25,
|
||||
outputFillMult: 1.25,
|
||||
outputSparseMult: 1.25,
|
||||
outputFanLayer: 1,
|
||||
outputFanSpeed: 255,
|
||||
outputRetractDist: 1.5,
|
||||
outputRetractSpeed: 40,
|
||||
outputRetractWipe: 0,
|
||||
outputRetractDwell: 20,
|
||||
outputBrimCount: 2,
|
||||
outputBrimOffset: 2,
|
||||
outputShortPoly: 100.0,
|
||||
outputMinSpeed: 10.0,
|
||||
outputCoastDist: 0,
|
||||
outputWipeDistance: 0,
|
||||
outputLayerRetract: false,
|
||||
outputOriginCenter: true,
|
||||
outputLoopLayers: "",
|
||||
outputPeelGuard: 0,
|
||||
outputInvertX: false,
|
||||
outputInvertY: false,
|
||||
detectThinWalls: false,
|
||||
sliceMinHeight: 0,
|
||||
sliceAdaptive: false,
|
||||
zHopDistance: 0.2,
|
||||
arcTolerance: 0,
|
||||
antiBacklash: 1,
|
||||
gcodePause: ""
|
||||
gcodePause: "",
|
||||
ranges: []
|
||||
}
|
||||
},
|
||||
sla:{
|
||||
|
|
@ -458,6 +468,7 @@
|
|||
camTraceDown: 0,
|
||||
camTraceSpeed: 250,
|
||||
camTracePlunge: 200,
|
||||
camTraceLines: false,
|
||||
camDrillTool: 1000,
|
||||
camDrillSpindle: 1000,
|
||||
camDrillDownSpeed: 250,
|
||||
|
|
@ -630,6 +641,7 @@
|
|||
view: null,
|
||||
dark: false,
|
||||
decals: true,
|
||||
danger: false,
|
||||
zoomSpeed: 1.0,
|
||||
lineType: "path",
|
||||
autoSave: true,
|
||||
|
|
@ -639,6 +651,7 @@
|
|||
showSpeeds: true,
|
||||
freeLayout: true,
|
||||
autoLayout: true,
|
||||
spaceLayout: 1,
|
||||
units: "mm",
|
||||
exportOcto: false,
|
||||
exportGhost: false,
|
||||
|
|
@ -646,7 +659,16 @@
|
|||
exportPreview: false,
|
||||
decimate: true,
|
||||
detail: "good",
|
||||
animesh: "200"
|
||||
animesh: "200",
|
||||
healMesh: false,
|
||||
ortho: false
|
||||
},
|
||||
// label state preferences
|
||||
labels: {
|
||||
'FDM-3-engage': false,
|
||||
'FDM-3-retract': false,
|
||||
'FDM-3-arrows': false,
|
||||
'FDM-3-move': false
|
||||
},
|
||||
// for passing temporary slice hints (topo currently)
|
||||
synth: {},
|
||||
|
|
|
|||
|
|
@ -7,6 +7,14 @@
|
|||
let KIRI = self.kiri = self.kiri || {};
|
||||
KIRI.newEngine = ()=> { return new Engine ()};
|
||||
|
||||
if (!KIRI.api) {
|
||||
KIRI.api = {
|
||||
event: {
|
||||
emit: () => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class Engine {
|
||||
constructor() {
|
||||
this.widget = KIRI.newWidget();
|
||||
|
|
@ -27,7 +35,7 @@ class Engine {
|
|||
try {
|
||||
new moto.STL().load(url, vertices => {
|
||||
this.listener({loaded: url, vertices});
|
||||
this.widget.loadVertices(vertices)
|
||||
this.widget.loadVertices(vertices).center();
|
||||
accept(this);
|
||||
});
|
||||
} catch (error) {
|
||||
|
|
@ -39,11 +47,10 @@ class Engine {
|
|||
parse(data) {
|
||||
return new Promise((accept, reject) => {
|
||||
try {
|
||||
new moto.STL().parse(data, vertices => {
|
||||
this.listener({parsed: data, vertices});
|
||||
this.widget.loadVertices(vertices)
|
||||
accept(this);
|
||||
});
|
||||
let vertices = new moto.STL().parse(data);
|
||||
this.listener({parsed: data, vertices});
|
||||
this.widget.loadVertices(vertices).center();
|
||||
accept(this);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
|
@ -97,6 +104,8 @@ class Engine {
|
|||
|
||||
slice() {
|
||||
return new Promise((accept, reject) => {
|
||||
KIRI.client.clear();
|
||||
KIRI.client.sync([ this.widget ]);
|
||||
KIRI.client.slice(this.settings, this.widget, msg => {
|
||||
this.listener({slice:msg});
|
||||
if (msg.error) {
|
||||
|
|
|
|||
|
|
@ -31,11 +31,15 @@
|
|||
}
|
||||
|
||||
function callExport(callback, mode) {
|
||||
let alert = API.feature.work_alerts ? API.show.alert("Exporting") : null;
|
||||
const gcode = [];
|
||||
KIRI.client.export(API.conf.get(), (line) => {
|
||||
gcode.push(line);
|
||||
}, (output) => {
|
||||
if (callback) {
|
||||
}, (output, error) => {
|
||||
API.hide.alert(alert);
|
||||
if (error) {
|
||||
API.show.alert(error, 5);
|
||||
} else if (callback) {
|
||||
callback(gcode.join('\r\n'), output);
|
||||
} else {
|
||||
exportGCodeDialog(gcode.join('\r\n'), output);
|
||||
|
|
@ -46,8 +50,12 @@
|
|||
function callExportLaser(options) {
|
||||
KIRI.client.export(API.conf.get(), (line) => {
|
||||
console.log({unexpected_line: line});
|
||||
}, (output) => {
|
||||
exportLaserDialog(output);
|
||||
}, (output, error) => {
|
||||
if (error) {
|
||||
API.show.alert(error, 5);
|
||||
} else {
|
||||
exportLaserDialog(output);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -58,9 +66,13 @@
|
|||
if (line.data) {
|
||||
preview.push(line.data);
|
||||
}
|
||||
}, (output) => {
|
||||
}, (output, error) => {
|
||||
API.show.progress(0);
|
||||
KIRI.driver.SLA.printDownload(preview, output, API);
|
||||
if (error) {
|
||||
API.show.alert(error, 5);
|
||||
} else {
|
||||
KIRI.driver.SLA.printDownload(preview, output, API);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +124,14 @@
|
|||
|
||||
let settings = API.conf.get(),
|
||||
MODE = API.mode.get_id(),
|
||||
pre = (MODE === MODES.CAM ? "cnc-" : "print-") + (printSeq.toString().padStart(3,"0")),
|
||||
names = API.widgets.all()
|
||||
.map(w => w.meta ? w.meta.file : undefined)
|
||||
.filter(v => v)
|
||||
.map(v => v.replace(/ /g,'-'))
|
||||
.map(v => v.substring(0,20))
|
||||
.map(v => v.split('.')[0]),
|
||||
name = names[0] || (MODE === MODES.CAM ? "cnc" : "print"),
|
||||
pre = `${name}-${(printSeq.toString().padStart(3,"0"))}`,
|
||||
filename = pre,// + (new Date().getTime().toString(36)),
|
||||
fileext = settings.device.gcodeFExt || "gcode",
|
||||
codeproc = settings.device.gcodeProc,
|
||||
|
|
@ -489,8 +508,8 @@
|
|||
$('admin-gridlocal').onclick = admin_gridlocal;
|
||||
} catch (e) { console.log(e) }
|
||||
|
||||
// preview of the generated GCODE
|
||||
if (preview && gcode) $('code-preview-textarea').value = gcode;
|
||||
// preview of the generated GCODE (first 64k max)
|
||||
if (preview && gcode) $('code-preview-textarea').value = gcode.substring(0,65535);
|
||||
|
||||
// show dialog
|
||||
API.modal.show('print');
|
||||
|
|
|
|||
471
src/kiri/init.js
471
src/kiri/init.js
|
|
@ -46,7 +46,6 @@
|
|||
platform = API.platform,
|
||||
selection = API.selection,
|
||||
proto = location.protocol,
|
||||
root = "grid.space",
|
||||
ver = Date.now().toString(36);
|
||||
|
||||
let currentDevice = null,
|
||||
|
|
@ -58,7 +57,8 @@
|
|||
editTools = null,
|
||||
maxTool = 0,
|
||||
fpsTimer = null,
|
||||
platformColor;
|
||||
platformColor,
|
||||
contextInt;
|
||||
|
||||
// extend KIRI API with local functions
|
||||
API.show.devices = showDevices;
|
||||
|
|
@ -138,7 +138,9 @@
|
|||
function booleanSave() {
|
||||
let control = settings().controller;
|
||||
let isDark = control.dark;
|
||||
let doAlert = UI.ortho.checked !== control.ortho;
|
||||
control.decals = UI.decals.checked;
|
||||
control.danger = UI.danger.checked;
|
||||
control.showOrigin = UI.showOrigin.checked;
|
||||
control.showRulers = UI.showRulers.checked;
|
||||
control.autoLayout = UI.autoLayout.checked;
|
||||
|
|
@ -151,8 +153,10 @@
|
|||
control.exportLocal = UI.exportLocal.checked;
|
||||
control.exportPreview = UI.exportPreview.checked;
|
||||
control.decimate = UI.decimate.checked;
|
||||
control.healMesh = UI.healMesh.checked;
|
||||
control.ortho = UI.ortho.checked;
|
||||
SPACE.view.setZoom(control.reverseZoom, control.zoomSpeed);
|
||||
platform.layout();
|
||||
// platform.layout();
|
||||
API.conf.save();
|
||||
API.platform.update_size();
|
||||
API.catalog.setOptions({
|
||||
|
|
@ -166,6 +170,9 @@
|
|||
clearDeviceTexture();
|
||||
}
|
||||
API.event.emit('boolean.update');
|
||||
if (doAlert) {
|
||||
API.show.alert("change requires page refresh");
|
||||
}
|
||||
}
|
||||
|
||||
function updateFPS() {
|
||||
|
|
@ -191,7 +198,7 @@
|
|||
// }
|
||||
API.conf.update();
|
||||
DOC.activeElement.blur();
|
||||
// API.event.emit("boolean.click");
|
||||
API.event.emit("boolean.click");
|
||||
}
|
||||
|
||||
function onButtonClick(ev) {
|
||||
|
|
@ -240,7 +247,7 @@
|
|||
// hide all dialogs
|
||||
API.dialog.hide();
|
||||
// cancel slicing
|
||||
if (KIRI.work.isSlicing()) KIRI.work.restart();
|
||||
API.function.cancel();
|
||||
// kill any poppers in compact mode
|
||||
UC.hidePoppers();
|
||||
// and send an event (used by FDM client)
|
||||
|
|
@ -321,16 +328,19 @@
|
|||
}
|
||||
|
||||
function keyHandler(evt) {
|
||||
let handled = true,
|
||||
current = settings(),
|
||||
style, sel, i, m, bb,
|
||||
ncc = evt.charCode - 48;
|
||||
let handled = true;
|
||||
if (API.modal.visible() || inputHasFocus()) {
|
||||
return false;
|
||||
}
|
||||
if (API.feature.on_key) {
|
||||
if (API.feature.on_key({key:evt})) return;
|
||||
}
|
||||
if (evt.ctrlKey) {
|
||||
switch (evt.key) {
|
||||
case 'g': return API.group.merge();
|
||||
case 'u': return API.group.split();
|
||||
}
|
||||
}
|
||||
switch (evt.charCode) {
|
||||
case cca('`'): API.show.slices(0); break;
|
||||
case cca('0'): API.show.slices(API.var.layer_max); break;
|
||||
|
|
@ -357,14 +367,6 @@
|
|||
case cca('i'): // file import
|
||||
API.event.import();
|
||||
break;
|
||||
case cca('U'): // full settings url
|
||||
storeSettingsToServer(true);
|
||||
break;
|
||||
case cca('u'): // full settings url
|
||||
UC.prompt("settings id to load", "").then(id => {
|
||||
if (id) loadSettingsFromServer(id);
|
||||
});
|
||||
break;
|
||||
case cca('S'): // slice
|
||||
case cca('s'): // slice
|
||||
if (evt.shiftKey) {
|
||||
|
|
@ -414,6 +416,9 @@
|
|||
API.show.local();
|
||||
break;
|
||||
case cca('v'): // toggle single slice view mode
|
||||
if (API.view.get() === VIEWS.ARRANGE) {
|
||||
API.space.set_focus(API.selection.widgets());
|
||||
}
|
||||
if (API.var.layer_hi == API.var.layer_lo) {
|
||||
API.var.layer_lo = 0;
|
||||
} else {
|
||||
|
|
@ -422,52 +427,75 @@
|
|||
API.show.slices();
|
||||
break;
|
||||
case cca('d'): // duplicate object
|
||||
sel = API.selection.meshes();
|
||||
platform.deselect();
|
||||
for (i=0; i<sel.length; i++) {
|
||||
let mesh = sel[i].clone();
|
||||
mesh.geometry = mesh.geometry.clone();
|
||||
mesh.material = mesh.material.clone();
|
||||
bb = mesh.getBoundingBox();
|
||||
let ow = sel[i].widget;
|
||||
let nw = API.widgets.new().loadGeometry(mesh.geometry);
|
||||
nw.meta.file = ow.meta.file;
|
||||
nw.meta.vertices = ow.meta.vertices;
|
||||
nw.move(bb.max.x - bb.min.x + 1, 0, 0);
|
||||
platform.add(nw,true);
|
||||
let owa = API.widgets.annotate(ow.id);
|
||||
let nwa = API.widgets.annotate(nw.id);
|
||||
if (owa.tab) {
|
||||
nwa.tab = Object.clone(owa.tab);
|
||||
nwa.tab.forEach((tab,i) => {
|
||||
tab.id = Date.now() + i
|
||||
});
|
||||
}
|
||||
KIRI.driver.CAM.restoreTabs([nw]);
|
||||
}
|
||||
duplicateSelection();
|
||||
break;
|
||||
case cca('m'): // mirror object
|
||||
API.selection.for_widgets(function(widget) {
|
||||
widget.mirror();
|
||||
});
|
||||
SPACE.update();
|
||||
mirrorSelection();
|
||||
break;
|
||||
case cca('R'): // toggle slice render mode
|
||||
renderMode++;
|
||||
API.function.slice();
|
||||
break;
|
||||
case cca('a'): // auto arrange items on platform
|
||||
platform.layout();
|
||||
case cca('a'):
|
||||
if (API.view.get() === VIEWS.ARRANGE) {
|
||||
// auto arrange items on platform
|
||||
platform.layout();
|
||||
API.space.set_focus(API.selection.widgets());
|
||||
} else {
|
||||
// go to arrange view
|
||||
API.view.set(VIEWS.ARRANGE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
API.event.emit('keypress', evt);
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
if (handled) evt.preventDefault();
|
||||
if (handled) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function layFlat() {
|
||||
let int = contextInt[0];
|
||||
if (int && int.object && int.object.widget) {
|
||||
let q = new THREE.Quaternion();
|
||||
q.setFromUnitVectors(contextInt[0].face.normal, new THREE.Vector3(0,0,-1));
|
||||
API.selection.rotate(q);
|
||||
}
|
||||
}
|
||||
|
||||
function duplicateSelection() {
|
||||
API.selection.for_widgets(function(widget) {
|
||||
let mesh = widget.mesh;
|
||||
let bb = mesh.getBoundingBox();
|
||||
let ow = widget;
|
||||
let nw = API.widgets.new().loadGeometry(mesh.geometry.clone());
|
||||
nw.meta.file = ow.meta.file;
|
||||
nw.meta.vertices = ow.meta.vertices;
|
||||
nw.move(bb.max.x - bb.min.x + 1, 0, 0);
|
||||
platform.add(nw,true);
|
||||
let owa = API.widgets.annotate(ow.id);
|
||||
let nwa = API.widgets.annotate(nw.id);
|
||||
if (owa.tab) {
|
||||
nwa.tab = Object.clone(owa.tab);
|
||||
nwa.tab.forEach((tab,i) => {
|
||||
tab.id = Date.now() + i
|
||||
});
|
||||
}
|
||||
KIRI.driver.CAM.restoreTabs([nw]);
|
||||
});
|
||||
}
|
||||
|
||||
function mirrorSelection() {
|
||||
API.selection.for_widgets(function(widget) {
|
||||
widget.mirror();
|
||||
});
|
||||
SPACE.update();
|
||||
}
|
||||
|
||||
function keys(o) {
|
||||
let key, list = [];
|
||||
for (key in o) { if (o.hasOwnProperty(key)) list.push(key) }
|
||||
|
|
@ -515,43 +543,6 @@
|
|||
moveSelection(x, y, z, true);
|
||||
}
|
||||
|
||||
function loadSettingsFromServer(tok) {
|
||||
let hash = (tok || LOC.hash.substring(1)).split("/");
|
||||
if (hash.length === 2) {
|
||||
new moto.Ajax(function(reply) {
|
||||
if (reply) {
|
||||
let res = JSON.parse(reply);
|
||||
if (res && res.ver && res.rec) {
|
||||
let set = JSON.parse(atob(res.rec));
|
||||
set.id = res.space;
|
||||
set.ver = res.ver;
|
||||
API.conf.put(set);
|
||||
API.event.settings();
|
||||
API.ui.sync();
|
||||
LOC.hash = '';
|
||||
}
|
||||
}
|
||||
}).request("/data/"+ hash[0] + "/" + hash[1]);
|
||||
}
|
||||
}
|
||||
|
||||
function storeSettingsToServer(display) {
|
||||
let set = btoa(JSON.stringify(settings()));
|
||||
new moto.Ajax(function(reply) {
|
||||
if (reply) {
|
||||
let res = JSON.parse(reply);
|
||||
if (res && res.ver) {
|
||||
LOC.hash = res.space + "/" + res.ver;
|
||||
if (display) {
|
||||
UC.alert(`unique settings id is: <b>${res.space}/${res.ver}</b>`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateSpaceState();
|
||||
}
|
||||
}).request("/data/"+ settings().id + "/" + settings().ver, set);
|
||||
}
|
||||
|
||||
function deviceExport(exp, name) {
|
||||
name = (name || "device")
|
||||
.toLowerCase()
|
||||
|
|
@ -559,10 +550,7 @@
|
|||
.replace(/\./g,'_');
|
||||
UC.prompt("Export Device Filename", name).then(name => {
|
||||
if (name) {
|
||||
let blob = new Blob([exp], {type: "octet/stream"}),
|
||||
url = WIN.URL.createObjectURL(blob);
|
||||
$('mod-any').innerHTML = `<a id="sexport" href="${url}" download="${name}.km">x</a>`;
|
||||
$('sexport').click();
|
||||
API.util.download(exp, `${name}.km`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -574,13 +562,7 @@
|
|||
if (name.toLowerCase().indexOf(".stl") < 0) {
|
||||
name = `${name}.stl`;
|
||||
}
|
||||
let xprt = API.selection.export(),
|
||||
blob = new Blob([xprt], {type: "octet/stream"}),
|
||||
url = WIN.URL.createObjectURL(blob);
|
||||
$('mod-any').innerHTML = [
|
||||
`<a id="sexport" href="${url}" download="${name}">x</a>`
|
||||
].join('');
|
||||
$('sexport').click();
|
||||
API.util.download(API.selection.export(), name);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -601,13 +583,8 @@
|
|||
UC.confirm("Export Filename", {ok:true, cancel: false}, "workspace", opt).then(name => {
|
||||
if (name) {
|
||||
let work = $('incwork').checked,
|
||||
json = API.conf.export({work}),
|
||||
blob = new Blob([json], {type: "octet/stream"}),
|
||||
url = WIN.URL.createObjectURL(blob);
|
||||
$('mod-any').innerHTML = [
|
||||
`<a id="sexport" href="${url}" download="${name}.km">x</a>`
|
||||
].join('');
|
||||
$('sexport').click();
|
||||
json = API.conf.export({work});
|
||||
API.util.download(json, `${name}.km`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -630,10 +607,12 @@
|
|||
if (name) {
|
||||
let np = pl[name] = {};
|
||||
cp.processName = name;
|
||||
pl[name] = Object.clone(cp);
|
||||
for (let k in cp) {
|
||||
if (!cp.hasOwnProperty(k)) continue;
|
||||
np[k] = cp[k];
|
||||
}
|
||||
s.cproc[mode] = name;
|
||||
s.devproc[s.device.deviceName] = name;
|
||||
API.conf.save();
|
||||
API.conf.update();
|
||||
|
|
@ -694,28 +673,28 @@
|
|||
let mode = API.mode.get(),
|
||||
current = settings(),
|
||||
local = isLocalDevice(devicename),
|
||||
dproc = current.devproc[devicename],
|
||||
dev = current.device = CONF.device_from_code(code,mode),
|
||||
proc = current.process,
|
||||
newdev = dproc === undefined;
|
||||
dproc = current.devproc[devicename], // last process name for this device
|
||||
newdev = dproc === undefined, // first time device is selected
|
||||
predev = current.filter[mode], // previous device selection
|
||||
chgdev = predev !== devicename; // device is changing
|
||||
|
||||
// first time device use, add any print profiles and set to default if present
|
||||
// if (newdev) {
|
||||
// console.log('new device', code);
|
||||
if (code.profiles) {
|
||||
for (let profile of code.profiles) {
|
||||
let profname = profile.processName;
|
||||
if (!current.sproc[mode][profname]) {
|
||||
console.log('adding profile', profname, 'to', mode);
|
||||
current.sproc[mode][profname] = profile;
|
||||
}
|
||||
if (newdev && !current.devproc[devicename]) {
|
||||
console.log('setting default profile for new device', devicename, 'to', profname);
|
||||
current.devproc[devicename] = dproc = profname;
|
||||
}
|
||||
if (code.profiles) {
|
||||
for (let profile of code.profiles) {
|
||||
let profname = profile.processName;
|
||||
// if no saved profile by that name for this mode...
|
||||
if (!current.sproc[mode][profname]) {
|
||||
console.log('adding profile', profname, 'to', mode);
|
||||
current.sproc[mode][profname] = profile;
|
||||
}
|
||||
// if it's a new device, seed the new profile name as last profile
|
||||
if (newdev && !current.devproc[devicename]) {
|
||||
console.log('setting default profile for new device', devicename, 'to', profname);
|
||||
current.devproc[devicename] = dproc = profname;
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
dev.new = false;
|
||||
dev.deviceName = devicename;
|
||||
|
|
@ -724,9 +703,16 @@
|
|||
UI.deviceBelt.checked = dev.bedBelt;
|
||||
UI.deviceRound.checked = dev.bedRound;
|
||||
UI.deviceOrigin.checked = dev.outputOriginCenter || dev.originCenter;
|
||||
UI.fwRetract.checked = dev.fwRetract;
|
||||
|
||||
// add extruder selection buttons
|
||||
if (dev.extruders) {
|
||||
for (let ext of dev.extruders) {
|
||||
// add missing deselect field from legacy configs
|
||||
if (!ext.extDeselect) {
|
||||
ext.extDeselect = [];
|
||||
}
|
||||
}
|
||||
let ext = API.lists.extruders = [];
|
||||
dev.internal = 0;
|
||||
let selext = $('pop-nozzle');
|
||||
|
|
@ -756,10 +742,10 @@
|
|||
UI.bedDepth,
|
||||
UI.bedWidth,
|
||||
UI.maxHeight,
|
||||
UI.extrudeAbs,
|
||||
UI.deviceOrigin,
|
||||
UI.deviceRound,
|
||||
UI.deviceBelt,
|
||||
UI.fwRetract,
|
||||
UI.gcodeFan,
|
||||
UI.gcodeTrack,
|
||||
UI.gcodeLayer,
|
||||
|
|
@ -780,12 +766,12 @@
|
|||
UI.extDel,
|
||||
UI.extOffsetX,
|
||||
UI.extOffsetY,
|
||||
UI.extSelect
|
||||
UI.extSelect,
|
||||
UI.extDeselect
|
||||
].forEach(function(e) {
|
||||
e.disabled = !local;
|
||||
});
|
||||
|
||||
UI.extrudeAbs.style.display = mode === 'CAM' ? 'none' : 'flex';
|
||||
UI.deviceSave.disabled = !local;
|
||||
UI.deviceDelete.disabled = !local;
|
||||
UI.deviceExport.disabled = !local;
|
||||
|
|
@ -802,8 +788,12 @@
|
|||
|
||||
API.view.update_fields();
|
||||
platform.update_size();
|
||||
platform.update_origin();
|
||||
platform.update();
|
||||
|
||||
// store current device name for this mode
|
||||
current.filter[mode] = devicename;
|
||||
// cache device record for this mode (restored in setMode)
|
||||
current.cdev[mode] = currentDevice = dev;
|
||||
|
||||
if (dproc) {
|
||||
|
|
@ -814,6 +804,13 @@
|
|||
}
|
||||
|
||||
API.conf.save();
|
||||
|
||||
API.const.SPACE.view.setHome(dev.bedBelt ? Math.PI/2 : 0);
|
||||
// when changing devices, update focus on widgets
|
||||
if (chgdev) {
|
||||
setTimeout(API.space.set_focus, 0);
|
||||
}
|
||||
|
||||
UC.refresh();
|
||||
|
||||
if (dev.imageURL) {
|
||||
|
|
@ -844,12 +841,14 @@
|
|||
}
|
||||
|
||||
function loadDeviceImage(dev, url) {
|
||||
new THREE.TextureLoader().load(url || dev.imageURL, texture => {
|
||||
let turl = url || dev.imageURL;
|
||||
if (!turl) return;
|
||||
new THREE.TextureLoader().load(turl, texture => {
|
||||
loadDeviceTexture(dev, texture);
|
||||
}, inc => {
|
||||
console.log({load_inc: inc});
|
||||
}, error => {
|
||||
console.log({load_error: error});
|
||||
console.log({load_error: error, turl});
|
||||
clearDeviceTexture();
|
||||
});
|
||||
}
|
||||
|
|
@ -949,12 +948,13 @@
|
|||
showDevices();
|
||||
};
|
||||
UI.deviceExport.onclick = function() {
|
||||
let exp = btoa(JSON.stringify({
|
||||
let exp = API.util.b64enc({
|
||||
version: KIRI.version,
|
||||
device: selected,
|
||||
process: API.process.code(),
|
||||
code: devs[selected],
|
||||
time: Date.now()
|
||||
}));
|
||||
});
|
||||
deviceExport(exp, selected);
|
||||
};
|
||||
|
||||
|
|
@ -1236,6 +1236,12 @@
|
|||
function dragOverHandler(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
|
||||
// prevent drop actions when a dialog is open
|
||||
if (API.modal.visible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
evt.dataTransfer.dropEffect = 'copy';
|
||||
let oldcolor = SPACE.platform.setColor(0x00ff00);
|
||||
if (oldcolor !== 0x00ff00) platformColor = oldcolor;
|
||||
|
|
@ -1249,6 +1255,11 @@
|
|||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
|
||||
// prevent drop actions when a dialog is open
|
||||
if (API.modal.visible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SPACE.platform.setColor(platformColor);
|
||||
|
||||
let files = evt.dataTransfer.files;
|
||||
|
|
@ -1352,13 +1363,15 @@
|
|||
return !isBelt();
|
||||
}
|
||||
|
||||
function isDanger() {
|
||||
return UI.danger.checked;
|
||||
}
|
||||
|
||||
// MAIN INITIALIZATION FUNCTION
|
||||
|
||||
function init_one() {
|
||||
API.event.emit('init.one');
|
||||
|
||||
$('gsbox').src = `${proto}//${root}/kiri/gsbox.png?ver=${ver}`;
|
||||
|
||||
// ensure we have settings from last session
|
||||
API.conf.restore();
|
||||
|
||||
|
|
@ -1387,7 +1400,7 @@
|
|||
SPACE.setSkyColor(controller.dark ? 0 : 0xffffff);
|
||||
SPACE.init(container, function (delta) {
|
||||
if (API.var.layer_max === 0 || !delta) return;
|
||||
if (settings().controller.reverseZoom) delta = -delta;
|
||||
if (controller.reverseZoom) delta = -delta;
|
||||
let same = API.var.layer_hi === API.var.layer_lo;
|
||||
let track = API.var.layer_lo > 0;
|
||||
if (delta > 0) {
|
||||
|
|
@ -1406,7 +1419,7 @@
|
|||
}
|
||||
API.view.update_slider();
|
||||
API.show.slices();
|
||||
});
|
||||
}, controller.ortho);
|
||||
SPACE.platform.onMove(API.conf.save);
|
||||
SPACE.platform.setRound(true);
|
||||
SPACE.useDefaultKeys(API.feature.on_key === undefined || API.feature.on_key_defaults);
|
||||
|
|
@ -1448,6 +1461,10 @@
|
|||
|
||||
back: $('lt-back'),
|
||||
trash: $('lt-trash'),
|
||||
ltsetup: $('lt-setup'),
|
||||
ltfile: $('lt-file'),
|
||||
ltview: $('lt-view'),
|
||||
ltact: $('act-slice'),
|
||||
rotate: $('lt-rotate'),
|
||||
scale: $('lt-scale'),
|
||||
nozzle: $('lt-nozzle'),
|
||||
|
|
@ -1534,6 +1551,7 @@
|
|||
deviceOrigin: UC.newBoolean(LANG.dv_orgc_s, onBooleanClick, {title:LANG.dv_orgc_l, modes:FDM_LASER_SLA}),
|
||||
deviceRound: UC.newBoolean(LANG.dv_bedc_s, onBooleanClick, {title:LANG.dv_bedc_l, modes:FDM, trigger:true, show:isNotBelt}),
|
||||
deviceBelt: UC.newBoolean(LANG.dv_belt_s, onBooleanClick, {title:LANG.dv_belt_l, modes:FDM, trigger:true, show:() => !UI.deviceRound.checked}),
|
||||
fwRetract: UC.newBoolean(LANG.dv_retr_s, onBooleanClick, {title:LANG.dv_retr_l, modes:FDM}),
|
||||
|
||||
extruder: UC.newGroup(LANG.dv_gr_ext, $('device2'), {group:"dext", inline:true, modes:FDM}),
|
||||
extFilament: UC.newInput(LANG.dv_fila_s, {title:LANG.dv_fila_l, convert:UC.toFloat, modes:FDM}),
|
||||
|
|
@ -1541,7 +1559,7 @@
|
|||
extOffsetX: UC.newInput(LANG.dv_exox_s, {title:LANG.dv_exox_l, convert:UC.toFloat, modes:FDM}),
|
||||
extOffsetY: UC.newInput(LANG.dv_exoy_s, {title:LANG.dv_exoy_l, convert:UC.toFloat, modes:FDM}),
|
||||
extSelect: UC.newText(LANG.dv_exts_s, {title:LANG.dv_exts_l, modes:FDM, size:14, height:3, modes:FDM, area:gcode}),
|
||||
extrudeAbs: UC.newBoolean(LANG.dv_xtab_s, onBooleanClick, {title:LANG.dv_xtab_l, modes:FDM}),
|
||||
extDeselect: UC.newText(LANG.dv_dext_s, {title:LANG.dv_dext_l, modes:FDM, size:14, height:3, modes:FDM, area:gcode}),
|
||||
extActions: UC.newRow([
|
||||
UI.extPrev = UC.newButton(undefined, undefined, {icon:'<i class="fas fa-less-than"></i>'}),
|
||||
UI.extAdd = UC.newButton(undefined, undefined, {icon:'<i class="fas fa-plus"></i>'}),
|
||||
|
|
@ -1571,8 +1589,10 @@
|
|||
|
||||
lprefs: UC.newGroup(LANG.op_menu, $('prefs-gen1'), {inline: true}),
|
||||
reverseZoom: UC.newBoolean(LANG.op_invr_s, booleanSave, {title:LANG.op_invr_l}),
|
||||
ortho: UC.newBoolean(LANG.op_orth_s, booleanSave, {title:LANG.op_orth_l}),
|
||||
dark: UC.newBoolean(LANG.op_dark_s, booleanSave, {title:LANG.op_dark_l}),
|
||||
decals: UC.newBoolean(LANG.op_decl_s, booleanSave, {title:LANG.op_decl_s}),
|
||||
danger: UC.newBoolean(LANG.op_dang_s, booleanSave, {title:LANG.op_dang_l}),
|
||||
|
||||
lprefs: UC.newGroup(LANG.op_disp, $('prefs-gen2'), {inline: true}),
|
||||
showOrigin: UC.newBoolean(LANG.op_shor_s, booleanSave, {title:LANG.op_shor_l}),
|
||||
|
|
@ -1580,12 +1600,13 @@
|
|||
showSpeeds: UC.newBoolean(LANG.op_sped_s, speedSave, {title:LANG.op_sped_l}),
|
||||
lineType: UC.newSelect(LANG.op_line_s, {title: LANG.op_line_l, action: lineTypeSave, modes:FDM}, "linetype"),
|
||||
animesh: UC.newSelect(LANG.op_anim_s, {title: LANG.op_anim_l, action: aniMeshSave, modes:CAM}, "animesh"),
|
||||
units: UC.newSelect(LANG.op_unit_s, {title: LANG.op_unit_l, action:unitsSave, modes:CAM, trace:true}, "units"),
|
||||
units: UC.newSelect(LANG.op_unit_s, {title: LANG.op_unit_l, action: unitsSave, modes:CAM, trace:true}, "units"),
|
||||
|
||||
layout: UC.newGroup(LANG.lo_menu, $('prefs-lay'), {inline: true}),
|
||||
autoSave: UC.newBoolean(LANG.op_save_s, booleanSave, {title:LANG.op_save_l}),
|
||||
autoLayout: UC.newBoolean(LANG.op_auto_s, booleanSave, {title:LANG.op_auto_l}),
|
||||
freeLayout: UC.newBoolean(LANG.op_free_s, booleanSave, {title:LANG.op_free_l}),
|
||||
autoSave: UC.newBoolean(LANG.op_save_s, booleanSave, {title:LANG.op_save_l}),
|
||||
spaceLayout: UC.newInput(LANG.op_spcr_s, {title:LANG.op_spcr_l, convert:UC.toFloat, size:3, units:true}),
|
||||
|
||||
export: UC.newGroup(LANG.xp_menu, $('prefs-xpo'), {inline: true}),
|
||||
exportOcto: UC.newBoolean(`OctoPrint`, booleanSave),
|
||||
|
|
@ -1596,6 +1617,7 @@
|
|||
parts: UC.newGroup(LANG.pt_menu, $('prefs-prt'), {inline: true}),
|
||||
detail: UC.newSelect(LANG.pt_qual_s, {title: LANG.pt_qual_l, action: detailSave}, "detail"),
|
||||
decimate: UC.newBoolean(LANG.pt_deci_s, booleanSave, {title: LANG.pt_deci_l}),
|
||||
healMesh: UC.newBoolean(LANG.pt_heal_s, booleanSave, {title: LANG.pt_heal_l}),
|
||||
|
||||
prefadd: UC.checkpoint($('prefs-add')),
|
||||
|
||||
|
|
@ -1603,7 +1625,7 @@
|
|||
sliceHeight: UC.newInput(LANG.sl_lahi_s, {title:LANG.sl_lahi_l, convert:UC.toFloat, modes:FDM}),
|
||||
sliceMinHeight: UC.newInput(LANG.ad_minl_s, {title:LANG.ad_minl_l, bound:UC.bound(0,3.0), convert:UC.toFloat, modes:FDM, show: () => UI.sliceAdaptive.checked}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
sliceShells: UC.newInput(LANG.sl_shel_s, {title:LANG.sl_shel_l, convert:UC.toInt, modes:FDM}),
|
||||
sliceShells: UC.newInput(LANG.sl_shel_s, {title:LANG.sl_shel_l, convert:UC.toFloat, modes:FDM}),
|
||||
sliceTopLayers: UC.newInput(LANG.sl_ltop_s, {title:LANG.sl_ltop_l, convert:UC.toInt, modes:FDM}),
|
||||
sliceSolidLayers: UC.newInput(LANG.sl_lsld_s, {title:LANG.sl_lsld_l, convert:UC.toInt, modes:FDM}),
|
||||
sliceBottomLayers: UC.newInput(LANG.sl_lbot_s, {title:LANG.sl_lbot_l, convert:UC.toInt, modes:FDM}),
|
||||
|
|
@ -1621,15 +1643,20 @@
|
|||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM, show:isNotBelt}),
|
||||
firstLayerNozzleTemp:UC.newInput(LANG.fl_nozl_s, {title:LANG.fl_nozl_l, convert:UC.toInt, modes:FDM, show:isNotBelt}),
|
||||
firstLayerBedTemp: UC.newInput(LANG.fl_bedd_s, {title:LANG.fl_bedd_l, convert:UC.toInt, modes:FDM, show:isNotBelt}),
|
||||
firstLayerFanSpeed: UC.newInput(LANG.ou_fans_s, {title:LANG.ou_fans_l, convert:UC.toInt, bound:UC.bound(0,255), modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM, show:isNotBelt}),
|
||||
firstLayerYOffset: UC.newInput(LANG.fl_zoff_s, {title:LANG.fl_zoff_l, convert:UC.toFloat, modes:FDM, show:isBelt}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM, show:isBelt}),
|
||||
firstLayerRate: UC.newInput(LANG.fl_rate_s, {title:LANG.fl_rate_l, convert:UC.toFloat, modes:FDM}),
|
||||
firstLayerFillRate: UC.newInput(LANG.fl_frat_s, {title:LANG.fl_frat_l, convert:UC.toFloat, modes:FDM, show:isNotBelt}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM, show:isNotBelt}),
|
||||
firstLayerLineMult: UC.newInput(LANG.fl_sfac_s, {title:LANG.fl_sfac_l, convert:UC.toFloat, bound:UC.bound(0.5,2), modes:FDM, show:isNotBelt}),
|
||||
firstLayerPrintMult: UC.newInput(LANG.fl_mult_s, {title:LANG.fl_mult_l, convert:UC.toFloat, modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM, show:isBelt}),
|
||||
firstLayerBrim: UC.newInput(LANG.fl_brim_s, {title:LANG.fl_brim_l, convert:UC.toFloat, modes:FDM, show:isBelt}),
|
||||
firstLayerBrimTrig: UC.newInput(LANG.fl_brmn_s, {title:LANG.fl_brmn_l, convert:UC.toFloat, modes:FDM, show:isBelt}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM, show:isBelt}),
|
||||
firstLayerBeltLead: UC.newInput(LANG.fl_bled_s, {title:LANG.fl_bled_l, convert:UC.toFloat, modes:FDM, show:isBelt}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM, show:isNotBelt}),
|
||||
outputBrimCount: UC.newInput(LANG.fl_skrt_s, {title:LANG.fl_skrt_l, convert:UC.toInt, modes:FDM, show:isNotBelt}),
|
||||
outputBrimOffset: UC.newInput(LANG.fl_skro_s, {title:LANG.fl_skro_l, convert:UC.toFloat, modes:FDM, show:isNotBelt}),
|
||||
|
|
@ -1639,29 +1666,32 @@
|
|||
|
||||
fdmInfill: UC.newGroup(LANG.fi_menu, $('settings'), {modes:FDM}),
|
||||
sliceFillType: UC.newSelect(LANG.fi_type, {modes:FDM}, "infill"),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
sliceFillSparse: UC.newInput(LANG.fi_pcnt_s, {title:LANG.fi_pcnt_l, convert:UC.toFloat, bound:UC.bound(0.0,1.0), modes:FDM}),
|
||||
sliceFillAngle: UC.newInput(LANG.fi_angl_s, {title:LANG.fi_angl_l, convert:UC.toFloat, modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
sliceFillOverlap: UC.newInput(LANG.fi_over_s, {title:LANG.fi_over_l, convert:UC.toFloat, bound:UC.bound(0.0,2.0), modes:FDM}),
|
||||
sliceFillRate: UC.newInput(LANG.ou_feed_s, {title:LANG.fi_rate_l, convert:UC.toInt, bound:UC.bound(0,300), modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
sliceFillAngle: UC.newInput(LANG.fi_angl_s, {title:LANG.fi_angl_l, convert:UC.toFloat, modes:FDM}),
|
||||
// sliceFillWidth: UC.newInput(LANG.fi_wdth_s, {title:LANG.fi_wdth_l, convert:UC.toFloat, modes:FDM}),
|
||||
|
||||
fdmSupport: UC.newGroup(LANG.sp_menu, null, {modes:FDM, marker:false}),
|
||||
sliceSupportNozzle: UC.newSelect(LANG.sp_nozl_s, {title:LANG.sp_nozl_l, modes:FDM}, "extruders"),
|
||||
sliceSupportDensity: UC.newInput(LANG.sp_dens_s, {title:LANG.sp_dens_l, convert:UC.toFloat, bound:UC.bound(0.05,1.0), modes:FDM}),
|
||||
sliceSupportDensity: UC.newInput(LANG.sp_dens_s, {title:LANG.sp_dens_l, convert:UC.toFloat, bound:UC.bound(0.0,1.0), modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
sliceSupportSize: UC.newInput(LANG.sp_size_s, {title:LANG.sp_size_l, bound:UC.bound(1.0,200.0), convert:UC.toFloat, modes:FDM}),
|
||||
sliceSupportOffset: UC.newInput(LANG.sp_offs_s, {title:LANG.sp_offs_l, bound:UC.bound(0.0,200.0), convert:UC.toFloat, modes:FDM}),
|
||||
sliceSupportGap: UC.newInput(LANG.sp_gaps_s, {title:LANG.sp_gaps_l, bound:UC.bound(0,5), convert:UC.toInt, modes:FDM}),
|
||||
sliceSupportGap: UC.newInput(LANG.sp_gaps_s, {title:LANG.sp_gaps_l, bound:UC.bound(0,5), convert:UC.toInt, modes:FDM, show:isNotBelt}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
sliceSupportArea: UC.newInput(LANG.sp_area_s, {title:LANG.sp_area_l, bound:UC.bound(0.0,200.0), convert:UC.toFloat, modes:FDM}),
|
||||
sliceSupportExtra: UC.newInput(LANG.sp_xpnd_s, {title:LANG.sp_xpnd_l, bound:UC.bound(0.0,200.0), convert:UC.toFloat, modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
sliceSupportAngle: UC.newInput(LANG.sp_angl_s, {title:LANG.sp_angl_l, bound:UC.bound(0.0,90.0), convert:UC.toFloat, modes:FDM}),
|
||||
sliceSupportAngle: UC.newInput(LANG.sp_angl_s, {title:LANG.sp_angl_l, bound:UC.bound(0.0,90.0), convert:UC.toFloat, modes:FDM, xshow:isNotBelt}),
|
||||
sliceSupportEnable: UC.newBoolean(LANG.sp_auto_s, onBooleanClick, {title:LANG.sp_auto_l, modes:FDM, show:isNotBelt}),
|
||||
|
||||
sliceSupportGen: UC.newRow([
|
||||
UI.ssaGen = UC.newButton(LANG.sp_detect, onButtonClick, {class: "f-col grow a-center"})
|
||||
], { modes: FDM, class: "ext-buttons f-row grow" }),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM, show:isNotBelt}),
|
||||
sliceSupportManual: UC.newRow([
|
||||
(UI.ssmAdd = UC.newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})),
|
||||
(UI.ssmDun = UC.newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})),
|
||||
|
|
@ -1720,6 +1750,7 @@
|
|||
|
||||
outputTemp: UC.newInput(LANG.ou_nozl_s, {title:LANG.ou_nozl_l, convert:UC.toInt, modes:FDM}),
|
||||
outputBedTemp: UC.newInput(LANG.ou_bedd_s, {title:LANG.ou_bedd_l, convert:UC.toInt, modes:FDM}),
|
||||
outputFanSpeed: UC.newInput(LANG.ou_fans_s, {title:LANG.ou_fans_l, convert:UC.toInt, bound:UC.bound(0,255), modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
outputFeedrate: UC.newInput(LANG.ou_feed_s, {title:LANG.ou_feed_l, convert:UC.toInt, modes:FDM}),
|
||||
outputFinishrate: UC.newInput(LANG.ou_fini_s, {title:LANG.ou_fini_l, convert:UC.toInt, modes:FDM}),
|
||||
|
|
@ -1729,7 +1760,6 @@
|
|||
outputFillMult: UC.newInput(LANG.ou_flml_s, {title:LANG.ou_exml_l, convert:UC.toFloat, bound:UC.bound(0.0,2.0), modes:FDM}),
|
||||
outputSparseMult: UC.newInput(LANG.ou_spml_s, {title:LANG.ou_exml_l, convert:UC.toFloat, bound:UC.bound(0.0,2.0), modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
outputFanLayer: UC.newInput(LANG.ou_fanl_s, {title:LANG.ou_fanl_l, convert:UC.toInt, bound:UC.bound(0,100), modes:FDM}),
|
||||
sliceShellOrder: UC.newSelect(LANG.sl_ordr_s, {title:LANG.sl_ordr_l, modes:FDM}, "shell"),
|
||||
sliceLayerStart: UC.newSelect(LANG.sl_strt_s, {title:LANG.sl_strt_l, modes:FDM}, "start"),
|
||||
camConventional: UC.newBoolean(LANG.ou_conv_s, onBooleanClick, {title:LANG.ou_conv_l, modes:CAM}),
|
||||
|
|
@ -1745,18 +1775,20 @@
|
|||
advanced: UC.newGroup(LANG.ad_menu, null, {modes:FDM}),
|
||||
outputRetractDist: UC.newInput(LANG.ad_rdst_s, {title:LANG.ad_rdst_l, convert:UC.toFloat, modes:FDM}),
|
||||
outputRetractSpeed: UC.newInput(LANG.ad_rrat_s, {title:LANG.ad_rrat_l, convert:UC.toInt, modes:FDM}),
|
||||
outputRetractWipe: UC.newInput(LANG.ad_wpln_s, {title:LANG.ad_wpln_l, bound:UC.bound(0.0,10), convert:UC.toFloat, modes:FDM}),
|
||||
outputRetractDwell: UC.newInput(LANG.ad_rdwl_s, {title:LANG.ad_rdwl_l, convert:UC.toInt, modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
// outputWipeDistance: UC.newInput("wipe", {title:"non-printing move at\close of polygon\nin millimeters", bound:UC.bound(0.0,10), convert:UC.toFloat, modes:FDM}),
|
||||
sliceSolidMinArea: UC.newInput(LANG.ad_msol_s, {title:LANG.ad_msol_l, convert:UC.toFloat, modes:FDM}),
|
||||
outputMinSpeed: UC.newInput(LANG.ad_mins_s, {title:LANG.ad_mins_l, bound:UC.bound(5,200), convert:UC.toFloat, modes:FDM}),
|
||||
outputCoastDist: UC.newInput(LANG.ad_scst_s, {title:LANG.ad_scst_l, bound:UC.bound(0.0,10), convert:UC.toFloat, modes:FDM}),
|
||||
outputShortPoly: UC.newInput(LANG.ad_spol_s, {title:LANG.ad_spol_l, bound:UC.bound(0,10000), convert:UC.toFloat, modes:FDM}),
|
||||
outputCoastDist: UC.newInput(LANG.ad_scst_s, {title:LANG.ad_scst_l, bound:UC.bound(0.0,10), convert:UC.toFloat, modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
zHopDistance: UC.newInput(LANG.ad_zhop_s, {title:LANG.ad_zhop_l, bound:UC.bound(0,3.0), convert:UC.toFloat, modes:FDM}),
|
||||
arcTolerance: UC.newInput(LANG.ad_arct_s, {title:LANG.ad_arct_l, bound:UC.bound(0,1.0), convert:UC.toFloat, modes:FDM, show:() => { return isDanger() && isNotBelt() }}),
|
||||
antiBacklash: UC.newInput(LANG.ad_abkl_s, {title:LANG.ad_abkl_l, bound:UC.bound(0,3), convert:UC.toInt, modes:FDM}),
|
||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||
gcodePauseLayers: UC.newInput(LANG.ag_paws_s, {title:LANG.ag_paws_l, modes:FDM, comma:true}),
|
||||
outputPeelGuard: UC.newInput(LANG.ag_peel_s, {title:LANG.ag_peel_l, convert:UC.toInt, modes:FDM, comma:true, show:isBelt}),
|
||||
gcodePauseLayers: UC.newInput(LANG.ag_paws_s, {title:LANG.ag_paws_l, modes:FDM, comma:true, show:isNotBelt}),
|
||||
outputLoopLayers: UC.newInput(LANG.ag_loop_s, {title:LANG.ag_loop_l, modes:FDM, comma:true, show:isBelt}),
|
||||
outputLayerRetract: UC.newBoolean(LANG.ad_lret_s, onBooleanClick, {title:LANG.ad_lret_l, modes:FDM}),
|
||||
|
||||
|
|
@ -1798,6 +1830,9 @@
|
|||
slaFirstOffset: UC.newInput(LANG.sa_opzo_s, {title:LANG.sa_opzo_l, convert:UC.toFloat, bound:UC.bound(0,1), modes:SLA}),
|
||||
slaAntiAlias: UC.newSelect(LANG.sa_opaa_s, {title:LANG.sa_opaa_l, modes:SLA}, "antialias"),
|
||||
|
||||
rangeGroup: UC.newGroup("ranges", null, {modes:FDM, group:"ranges"}),
|
||||
rangeList: UC.newRow([], {}),
|
||||
|
||||
settingsGroup: UC.newGroup(LANG.se_menu, $('settings')),
|
||||
settingsTable: UC.newRow([ UI.settingsLoad = UC.newButton(LANG.se_load, settingsLoad) ]),
|
||||
settingsTable: UC.newRow([ UI.settingsSave = UC.newButton(LANG.se_save, settingsSave) ]),
|
||||
|
|
@ -1955,6 +1990,19 @@
|
|||
UI.sliderHold.style.marginRight = `${hival}px`;
|
||||
});
|
||||
|
||||
// store layer preferences
|
||||
API.event.on('stack.show', label => {
|
||||
let mode = API.mode.get();
|
||||
let view = API.view.get();
|
||||
API.conf.get().labels[`${mode}-${view}-${label}`] = true;
|
||||
});
|
||||
|
||||
API.event.on('stack.hide', label => {
|
||||
let mode = API.mode.get();
|
||||
let view = API.view.get();
|
||||
API.conf.get().labels[`${mode}-${view}-${label}`] = false;
|
||||
});
|
||||
|
||||
// bind language choices
|
||||
$('lset-en').onclick = function() {
|
||||
SDB.setItem('kiri-lang', 'en-us');
|
||||
|
|
@ -1964,6 +2012,18 @@
|
|||
SDB.setItem('kiri-lang', 'da-dk');
|
||||
API.space.reload();
|
||||
};
|
||||
$('lset-de').onclick = function() {
|
||||
SDB.setItem('kiri-lang', 'de-de');
|
||||
API.space.reload();
|
||||
};
|
||||
$('lset-fr').onclick = function() {
|
||||
SDB.setItem('kiri-lang', 'fr-fr');
|
||||
API.space.reload();
|
||||
};
|
||||
$('lset-pl').onclick = function() {
|
||||
SDB.setItem('kiri-lang', 'pl-pl');
|
||||
API.space.reload();
|
||||
};
|
||||
|
||||
SPACE.addEventHandlers(self, [
|
||||
'keyup', keyUpHandler,
|
||||
|
|
@ -1981,9 +2041,17 @@
|
|||
xv = parseFloat(UI.sizeX.was),
|
||||
yv = parseFloat(UI.sizeY.was),
|
||||
zv = parseFloat(UI.sizeZ.was),
|
||||
xr = (UI.lockX.checked ? ra : 1),
|
||||
yr = (UI.lockY.checked ? ra : 1),
|
||||
zr = (UI.lockZ.checked ? ra : 1);
|
||||
ta = e.target,
|
||||
xc = UI.lockX.checked,
|
||||
yc = UI.lockY.checked,
|
||||
zc = UI.lockZ.checked,
|
||||
xt = ta === UI.sizeX,
|
||||
yt = ta === UI.sizeY,
|
||||
zt = ta === UI.sizeZ,
|
||||
tl = (xt && xc) || (yt && yc) || (zt && zc),
|
||||
xr = ((tl && xc) || (!tl && xt) ? ra : 1),
|
||||
yr = ((tl && yc) || (!tl && yt) ? ra : 1),
|
||||
zr = ((tl && zc) || (!tl && zt) ? ra : 1);
|
||||
API.selection.scale(xr,yr,zr);
|
||||
UI.sizeX.was = UI.sizeX.value = xv * xr;
|
||||
UI.sizeY.was = UI.sizeY.value = yv * yr;
|
||||
|
|
@ -1997,9 +2065,17 @@
|
|||
xv = parseFloat(UI.scaleX.was),
|
||||
yv = parseFloat(UI.scaleY.was),
|
||||
zv = parseFloat(UI.scaleZ.was),
|
||||
xr = (UI.lockX.checked ? ra : 1),
|
||||
yr = (UI.lockY.checked ? ra : 1),
|
||||
zr = (UI.lockZ.checked ? ra : 1);
|
||||
ta = e.target,
|
||||
xc = UI.lockX.checked,
|
||||
yc = UI.lockY.checked,
|
||||
zc = UI.lockZ.checked,
|
||||
xt = ta === UI.scaleX,
|
||||
yt = ta === UI.scaleY,
|
||||
zt = ta === UI.scaleZ,
|
||||
tl = (xt && xc) || (yt && yc) || (zt && zc),
|
||||
xr = ((tl && xc) || (!tl && xt) ? ra : 1),
|
||||
yr = ((tl && yc) || (!tl && yt) ? ra : 1),
|
||||
zr = ((tl && zc) || (!tl && zt) ? ra : 1);
|
||||
API.selection.scale(xr,yr,zr);
|
||||
UI.scaleX.was = UI.scaleX.value = xv * xr;
|
||||
UI.scaleY.was = UI.scaleY.value = yv * yr;
|
||||
|
|
@ -2035,6 +2111,35 @@
|
|||
$('rot_z'), selectionRotate
|
||||
]);
|
||||
|
||||
$('lab-axis').onclick = () => {
|
||||
UI.lockX.checked =
|
||||
UI.lockY.checked =
|
||||
UI.lockZ.checked = !(
|
||||
UI.lockX.checked ||
|
||||
UI.lockY.checked ||
|
||||
UI.lockZ.checked
|
||||
);
|
||||
};
|
||||
|
||||
$('lab-scale').onclick = () => {
|
||||
API.selection.scale(1 / UI.scaleX.was, 1 / UI.scaleY.was, 1 / UI.scaleZ.was);
|
||||
UI.scaleX.value = UI.scaleY.value = UI.scaleZ.value =
|
||||
UI.scaleX.was = UI.scaleY.was = UI.scaleZ.was = 1;
|
||||
};
|
||||
|
||||
let hpops = [];
|
||||
UC.hoverPop(UI.ltsetup, { group: hpops, target: $('set-pop') });
|
||||
UC.hoverPop(UI.ltfile, { group: hpops, target: $('file-pop') });
|
||||
UC.hoverPop(UI.ltview, { group: hpops, target: $('pop-view') });
|
||||
UC.hoverPop(UI.ltact, { group: hpops, target: $('pop-slice') });
|
||||
UC.hoverPop(UI.render, { group: hpops, target: $('pop-render'), sticky: true });
|
||||
UC.hoverPop(UI.rotate, { group: hpops, target: $('pop-rotate'), sticky: true });
|
||||
UC.hoverPop(UI.scale, { group: hpops, target: $('pop-scale'), sticky: true });
|
||||
UC.hoverPop(UI.nozzle, { group: hpops, target: $('pop-nozzle'), sticky: true });
|
||||
UC.hoverPop($('app-acct'), { group: hpops, target: $('acct-pop') } );
|
||||
UC.hoverPop($('app-mode'), { group: hpops, target: $('mode-info') } );
|
||||
UC.hoverPop($('app-name'), { group: hpops, target: $('app-info') } );
|
||||
|
||||
UC.onBlur([
|
||||
UI.toolName,
|
||||
UI.toolNum,
|
||||
|
|
@ -2080,8 +2185,21 @@
|
|||
if (int) API.event.emit('mouse.hover', {point: int, event, type: 'platform'});
|
||||
});
|
||||
|
||||
// block standard browser context menu
|
||||
DOC.oncontextmenu = (event) => {
|
||||
if (event.target.tagName === 'CANVAS') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
SPACE.mouse.up((event, int) => {
|
||||
if (event.button === 2 && API.view.isArrange()) {
|
||||
if (event.button === 2) {
|
||||
let full = API.view.isArrange();
|
||||
for (let key of ["layflat","mirror","duplicate"]) {
|
||||
$(`context-${key}`).disabled = !full;
|
||||
}
|
||||
let style = UI.context.style;
|
||||
style.display = 'flex';
|
||||
style.left = `${event.clientX-3}px`;
|
||||
|
|
@ -2089,6 +2207,9 @@
|
|||
UI.context.onmouseleave = () => {
|
||||
style.display = '';
|
||||
};
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
contextInt = int;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -2114,6 +2235,10 @@
|
|||
// return selected meshes for further mouse processing
|
||||
return API.feature.hovers || API.selection.meshes();
|
||||
}
|
||||
if (event.button === 2 && API.view.isArrange()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
SPACE.mouse.upSelect(function(object, event) {
|
||||
|
|
@ -2172,6 +2297,8 @@
|
|||
function init_two() {
|
||||
API.event.emit('init.two');
|
||||
|
||||
// API.space.set_focus();
|
||||
|
||||
// call driver initializations, if present
|
||||
Object.values(KIRI.driver).forEach(driver => {
|
||||
if (driver.init) try {
|
||||
|
|
@ -2238,6 +2365,8 @@
|
|||
UI.reverseZoom.checked = control.reverseZoom;
|
||||
UI.autoSave.checked = control.autoSave;
|
||||
UI.decimate.checked = control.decimate;
|
||||
UI.healMesh.checked = control.healMesh;
|
||||
UI.ortho.checked = control.ortho;
|
||||
lineTypeSave();
|
||||
detailSave();
|
||||
updateFPS();
|
||||
|
|
@ -2272,9 +2401,6 @@
|
|||
|
||||
UI.sync();
|
||||
|
||||
// load settings provided in url hash
|
||||
loadSettingsFromServer();
|
||||
|
||||
// clear alerts as they build up
|
||||
setInterval(API.event.alerts, 1000);
|
||||
|
||||
|
|
@ -2292,7 +2418,7 @@
|
|||
API.event.emit('init-done', STATS);
|
||||
|
||||
// show gdpr if it's never been seen and we're not iframed
|
||||
if (!SDB.gdpr && WIN.self === WIN.top) {
|
||||
if (!SDB.gdpr && WIN.self === WIN.top && !SETUP.debug) {
|
||||
$('gdpr').style.display = 'flex';
|
||||
}
|
||||
|
||||
|
|
@ -2359,7 +2485,14 @@
|
|||
// context menu
|
||||
$('context-export-stl').onclick = () => { objectsExport() };
|
||||
$('context-export-workspace').onclick = () => { profileExport(true) };
|
||||
$('context-clear-workspace').onclick = () => { API.platform.clear(); UI.context.onmouseleave() };
|
||||
$('context-clear-workspace').onclick = () => {
|
||||
API.view.set(VIEWS.ARRANGE);
|
||||
API.platform.clear();
|
||||
UI.context.onmouseleave();
|
||||
};
|
||||
$('context-duplicate').onclick = duplicateSelection;
|
||||
$('context-mirror').onclick = mirrorSelection;
|
||||
$('context-layflat').onclick = layFlat;
|
||||
|
||||
UI.modal.onclick = API.modal.hide;
|
||||
UI.modalBox.onclick = (ev) => { ev.stopPropagation() };
|
||||
|
|
@ -2376,21 +2509,38 @@
|
|||
}
|
||||
}
|
||||
|
||||
// update static html elements with language overrides
|
||||
UI.lang = function() {
|
||||
for (let el of [...DOC.querySelectorAll("[lk]")]) {
|
||||
let key = el.getAttribute('lk');
|
||||
let val = LANG[key];
|
||||
if (val) {
|
||||
el.innerText = val;
|
||||
} else {
|
||||
console.log({missing_ln: key});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// if a language needs to load, the script is injected and loaded
|
||||
// first. once this loads, or doesn't, the initialization begins
|
||||
let lang_load = false;
|
||||
let lang_set = undefined;
|
||||
let lang = SETUP.ln ? SETUP.ln[0] : SDB.getItem('kiri-lang') || KIRI.lang.get();
|
||||
|
||||
// inject language script if not english
|
||||
if (lang && lang !== 'en' && lang !== 'en-us') {
|
||||
lang_set = lang;
|
||||
let map = KIRI.lang.map(lang);
|
||||
let scr = DOC.createElement('script');
|
||||
// scr.setAttribute('defer',true);
|
||||
scr.setAttribute('src',`/kiri/lang/${lang}.js`);
|
||||
scr.setAttribute('src',`/kiri/lang/${map}.js?${KIRI.version}`);
|
||||
(DOC.body || DOC.head).appendChild(scr);
|
||||
STATS.set('ll',lang);
|
||||
scr.onload = function() {
|
||||
KIRI.lang.set(lang);
|
||||
lang_load = true;
|
||||
KIRI.lang.set(map);
|
||||
UI.lang();
|
||||
init_one();
|
||||
};
|
||||
scr.onerror = function(err) {
|
||||
|
|
@ -2401,7 +2551,10 @@
|
|||
|
||||
// set to browser default which will be overridden
|
||||
// by any future script loads (above)
|
||||
KIRI.lang.set();
|
||||
if (!lang_load) {
|
||||
KIRI.lang.set();
|
||||
UI.lang();
|
||||
}
|
||||
|
||||
// schedule init_one to run after all page content is loaded
|
||||
// unless a languge script is loading first, in which case it
|
||||
|
|
|
|||
|
|
@ -7,9 +7,25 @@
|
|||
if (self.kiri.lang) return;
|
||||
|
||||
const KIRI = self.kiri, LANG = self.kiri.lang = { current: {} };
|
||||
const KDFL = 'en-us';
|
||||
|
||||
let lset = navigator.language.toLocaleLowerCase();
|
||||
|
||||
LANG.map = function(key) {
|
||||
if (!key) {
|
||||
return KDFL;
|
||||
}
|
||||
let tok = key.split('-');
|
||||
switch (tok[0]) {
|
||||
case 'da': return 'da-dk';
|
||||
case 'de': return 'de-de';
|
||||
case 'en': return 'en-us';
|
||||
case 'fr': return 'fr-fr';
|
||||
case 'pl': return 'pl-pl';
|
||||
}
|
||||
return KDFL;
|
||||
};
|
||||
|
||||
LANG.get = function() {
|
||||
return lset;
|
||||
};
|
||||
|
|
@ -39,7 +55,12 @@
|
|||
// update current map from chosen map
|
||||
Object.keys(map).forEach(key => {
|
||||
if (LANG.en[key]) {
|
||||
LANG.current[key] = map[key];
|
||||
let val = map[key];
|
||||
// turn arrays into newline separated strings
|
||||
if (Array.isArray(val)) {
|
||||
val = val.join('\n');
|
||||
}
|
||||
LANG.current[key] = val;
|
||||
} else {
|
||||
invalid.push(key);
|
||||
}
|
||||
|
|
|
|||
734
src/kiri/main.js
734
src/kiri/main.js
File diff suppressed because it is too large
Load diff
|
|
@ -133,33 +133,102 @@
|
|||
maxf = 0,
|
||||
seq = [],
|
||||
autolayer = true,
|
||||
newlayer = false;
|
||||
newlayer = false,
|
||||
arcdivs = Math.PI / 12,
|
||||
hasmoved = false;
|
||||
|
||||
const output = scope.output = [ seq ];
|
||||
const beltaxis = { X: "X", Y: "Z", Z: "Y", E: "E", F: "F" };
|
||||
const beltfact = Math.cos(Math.PI/4);
|
||||
|
||||
function LOG() {
|
||||
console.log(...[...arguments].map(o => Object.clone(o)));
|
||||
}
|
||||
|
||||
function G2G3(g2, line) {
|
||||
const rec = {};
|
||||
|
||||
line.forEach(function(tok) {
|
||||
rec[tok.charAt(0)] = parseFloat(tok.substring(1));
|
||||
});
|
||||
|
||||
let center = { x:0, y:0, r:0 };
|
||||
|
||||
if (rec.I !== undefined && rec.J !== undefined) {
|
||||
center.x = pos.X + rec.I;
|
||||
center.y = pos.Y + rec.J;
|
||||
//center.r = TODO
|
||||
console.log("G[2,3] IJ not supported");
|
||||
} else if (rec.R !== undefined) {
|
||||
let pd = { x: rec.X - pos.X, y: rec.Y - pos.Y };
|
||||
let dst = Math.sqrt(pd.x * pd.x + pd.y * pd.y) / 2;
|
||||
let pr2;
|
||||
if (Math.abs(dst - rec.R) < 0.001) {
|
||||
// center point radius
|
||||
pr2 = { x: (rec.X + pos.X) / 2, y: (rec.Y + pos.Y) / 2};
|
||||
} else {
|
||||
// triangulate
|
||||
pr2 = BASE.util.center2pr({
|
||||
x: pos.X,
|
||||
y: pos.Y
|
||||
}, {
|
||||
x: rec.X,
|
||||
y: rec.Y
|
||||
}, rec.R)[g2 ? 1 : 0];
|
||||
}
|
||||
center.x = pr2.x;
|
||||
center.y = pr2.y;
|
||||
center.r = rec.R;
|
||||
} else {
|
||||
console.log({malfomed_arc: line});
|
||||
}
|
||||
|
||||
// line angles
|
||||
let a1 = Math.atan2(center.y - pos.Y, center.x - pos.X) + Math.PI;
|
||||
let a2 = Math.atan2(center.y - rec.Y, center.x - rec.X) + Math.PI;
|
||||
let ad = BASE.util.thetaDiff(a1, a2, true);
|
||||
let steps = Math.floor(Math.abs(ad) / arcdivs);
|
||||
let step = (Math.abs(ad) > 0.001 ? ad : Math.PI * 2) / steps;
|
||||
let rot = a1 + step;
|
||||
|
||||
// LOG({first: pos, last: rec, center, a1, a2, ad, step, rot, line});
|
||||
// G0G1(false, [`X${center.x}`, `Y${center.y}`, `E1`]);
|
||||
|
||||
let pc = { X: pos.X, Y: pos.Y };
|
||||
for (let i=0; i<=steps-2; i++) {
|
||||
let np = {
|
||||
X: center.x + Math.cos(rot) * center.r,
|
||||
Y: center.y + Math.sin(rot) * center.r
|
||||
};
|
||||
rot += step;
|
||||
G0G1(false, [`X${np.X}`, `Y${np.Y}`, `E1`]);
|
||||
}
|
||||
|
||||
G0G1(false, [`X${rec.X}`, `Y${rec.Y}`, `E1`]);
|
||||
|
||||
pos.X = rec.X;
|
||||
pos.Y = rec.Y;
|
||||
}
|
||||
|
||||
function G0G1(g0, line) {
|
||||
const mov = {};
|
||||
const axes = {};
|
||||
|
||||
line.forEach(function(tok) {
|
||||
let axis = tok.charAt(0);
|
||||
if (morph && belt) {
|
||||
axis = beltaxis[axis];
|
||||
}
|
||||
let val = parseFloat(tok.substring(1));
|
||||
axes[axis] = val;
|
||||
if (abs) {
|
||||
pos[axis] = parseFloat(tok.substring(1));
|
||||
pos[axis] = val;
|
||||
} else {
|
||||
mov[axis] = parseFloat(tok.substring(1));
|
||||
mov[axis] = val;
|
||||
pos[axis] += val;
|
||||
}
|
||||
});
|
||||
|
||||
if (!abs) {
|
||||
for (let [k,v] of Object.entries(mov)) {
|
||||
pos[k] += v;
|
||||
}
|
||||
}
|
||||
|
||||
const point = newPoint(
|
||||
factor * pos.X + off.X + xoff.X,
|
||||
factor * pos.Y + off.Y + xoff.Y,
|
||||
|
|
@ -172,7 +241,7 @@
|
|||
}
|
||||
|
||||
const retract = (fdm && pos.E < 0) || undefined;
|
||||
const moving = g0 || (fdm && pos.E <= 0);
|
||||
const moving = g0 || (fdm && (pos.E <= 0 || !(axes.X || axes.Y || axes.Z)));
|
||||
|
||||
if (!moving && point.x) bounds.min.x = Math.min(bounds.min.x, point.x);
|
||||
if (!moving && point.x) bounds.max.x = Math.max(bounds.max.x, point.x);
|
||||
|
|
@ -210,6 +279,11 @@
|
|||
output.push(seq);
|
||||
}
|
||||
|
||||
if (!hasmoved && !moving) {
|
||||
seq.height = seq.Z = pos.Z;
|
||||
hasmoved = true;
|
||||
}
|
||||
|
||||
// debug extrusion rate
|
||||
if (false && fdm && lastPos) {
|
||||
let dE = (absE ? pos.E - lastPos.E : pos.E);
|
||||
|
|
@ -278,12 +352,25 @@
|
|||
pos[tok.charAt(0)] = parseFloat(tok.substring(1));
|
||||
});
|
||||
break;
|
||||
case 'G10':
|
||||
seq.last().retract = true;
|
||||
break;
|
||||
case 'G11':
|
||||
break;
|
||||
case 'G0':
|
||||
G0G1(true, line);
|
||||
break;
|
||||
case 'G1':
|
||||
G0G1(false, line);
|
||||
break;
|
||||
case 'G2':
|
||||
// turn arc into a series of points
|
||||
G2G3(true, line)
|
||||
break;
|
||||
case 'G3':
|
||||
// turn arc into a series of points
|
||||
G2G3(false, line);
|
||||
break;
|
||||
case 'M6':
|
||||
tool = parseInt(line[0].substring(1));
|
||||
break;
|
||||
|
|
@ -371,7 +458,6 @@
|
|||
first = true,
|
||||
close = !options.open,
|
||||
last = startPoint,
|
||||
wipeDist = options.wipe || 0,
|
||||
coastDist = options.coast || 0,
|
||||
tool = options.tool;
|
||||
|
||||
|
|
@ -385,7 +471,7 @@
|
|||
if (options.onfirst) {
|
||||
options.onfirst(point);
|
||||
}
|
||||
// move from startPoint to point
|
||||
// move to first output point on poly
|
||||
addOutput(output, point, 0, moveSpeed, tool);
|
||||
first = false;
|
||||
} else {
|
||||
|
|
@ -418,19 +504,18 @@
|
|||
*/
|
||||
PRO.slicePrintPath = function(slice, startPoint, offset, output, opt = {}) {
|
||||
// console.log({slicePrintPath: slice.index, ext:slice.extruder});
|
||||
|
||||
let i,
|
||||
preout = [],
|
||||
scope = this,
|
||||
settings = this.settings,
|
||||
device = settings.device,
|
||||
process = settings.process,
|
||||
process = opt.params || settings.process,
|
||||
extruder = slice.extruder || 0,
|
||||
nozzleSize = device.extruders[extruder].extNozzle,
|
||||
firstLayer = opt.first || false,
|
||||
minSeek = nozzleSize * (opt.minSeek || 1.5),
|
||||
thinWall = nozzleSize * (opt.thinWall || 1.75),
|
||||
retractDist = opt.retractOver || 2,
|
||||
solidWidth = process.sliceFillWidth || 1,
|
||||
fillMult = opt.mult || process.outputFillMult,
|
||||
shellMult = opt.mult || process.outputShellMult || (process.laserSliceHeight >= 0 ? 1 : 0),
|
||||
shellOrder = {"out-in":-1,"in-out":1}[process.sliceShellOrder] || -1,
|
||||
|
|
@ -442,14 +527,17 @@
|
|||
firstPrintMult = process.firstLayerPrintMult,
|
||||
printSpeed = opt.speed || (firstLayer ? firstShellSpeed : process.outputFeedrate),
|
||||
fillSpeed = opt.speed || opt.fillSpeed || (firstLayer ? firstFillSpeed || firstShellSpeed : process.outputFeedrate),
|
||||
infillSpeed = process.sliceFillRate || opt.infillSpeed || fillSpeed || printSpeed,
|
||||
moveSpeed = process.outputSeekrate,
|
||||
origin = startPoint.add(offset),
|
||||
zhop = process.zHopDistance || 0,
|
||||
antiBacklash = process.antiBacklash,
|
||||
doSupport = opt.support,
|
||||
wipeDist = process.outputRetractWipe || 0,
|
||||
isBelt = device.bedBelt,
|
||||
startClone = startPoint.clone(),
|
||||
z = slice.z;
|
||||
seedPoint = opt.seedPoint || startPoint,
|
||||
z = slice.z,
|
||||
lastPoly;
|
||||
|
||||
// apply first layer extrusion multipliers
|
||||
if (firstLayer) {
|
||||
|
|
@ -459,28 +547,202 @@
|
|||
}
|
||||
|
||||
function retract() {
|
||||
if (preout.length) preout.last().retract = true;
|
||||
let array = preout.length ? preout : output;
|
||||
if (array.length) {
|
||||
let last = array.last();
|
||||
last.retract = true;
|
||||
if (wipeDist && lastPoly && last.point) {
|
||||
let endpoint = last.point.followTo(lastPoly.center(true), wipeDist);
|
||||
if (endpoint.inPolygon(lastPoly)) {
|
||||
addOutput(array, endpoint);
|
||||
}
|
||||
}
|
||||
} else if (opt.pretract) {
|
||||
opt.pretract(wipeDist);
|
||||
} else {
|
||||
console.log('unable to retract. no preout or output');
|
||||
}
|
||||
}
|
||||
|
||||
function intersectsTop(p1, p2) {
|
||||
if (opt.danger) {
|
||||
return retractRequired(p1, p2);
|
||||
}
|
||||
let int = false;
|
||||
POLY.flatten(slice.topPolys().clone(true)).forEach(function(poly) {
|
||||
if (!int) poly.forEachSegment(function(s1, s2) {
|
||||
if (UTIL.intersect(p1,p2,s1,s2,BASE.key.SEGINT)) {
|
||||
int = true;
|
||||
return int;
|
||||
return int = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
return int;
|
||||
}
|
||||
|
||||
function outputTraces(poly, extrude) {
|
||||
// returns true if no path around and retract required
|
||||
// returns false if routed around or no retract
|
||||
function retractRequired(p1, p2) {
|
||||
const dbug = false;
|
||||
|
||||
let ints = [];
|
||||
let tops = POLY.flatten(slice.topPolys().clone(true));
|
||||
for (let poly of tops) {
|
||||
poly.forEachSegment(function(s1, s2) {
|
||||
let ip = UTIL.intersect(p1,p2,s1,s2,BASE.key.SEGINT);
|
||||
if (ip) {
|
||||
ints.push({ip, poly});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// no intersections
|
||||
if (ints.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// odd # of intersections ?!? do retraction
|
||||
if (ints.length && ints.length % 2 !== 0) {
|
||||
if (dbug === slice.index) console.log(slice.index, {odd_intersects: ints});
|
||||
return true;
|
||||
}
|
||||
|
||||
// sort by distance
|
||||
ints.sort((a, b) => {
|
||||
return a.ip.dist - b.ip.dist;
|
||||
});
|
||||
|
||||
let valid = ints.length;
|
||||
|
||||
// check pairs. eliminate too close points.
|
||||
// pairs must intersect same poly or retract.
|
||||
for (let i=0; i<ints.length; i += 2) {
|
||||
let i1 = ints[0];
|
||||
let i2 = ints[1];
|
||||
// different poly. force retract
|
||||
if (i1.poly !== i2.poly) {
|
||||
if (dbug === slice.index) console.log(slice.index, {int_diff_poly: ints, i});
|
||||
return true;
|
||||
}
|
||||
if (i1.ip.distTo2D(i2.ip) < retractDist) {
|
||||
if (dbug === slice.index) console.log(slice.index, {int_dist_too_small: i1.ip.distTo2D(i2.ip), retractDist});
|
||||
valid -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid > 2) {
|
||||
if (dbug === slice.index) console.log(slice.index, {complex_route: valid});
|
||||
return true;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
// can route around intersected top polys
|
||||
for (let i=0; i<ints.length; i += 2) {
|
||||
let i1 = ints[0];
|
||||
let i2 = ints[1];
|
||||
|
||||
// output first point
|
||||
addOutput(preout, i1.ip, 0, moveSpeed, extruder);
|
||||
|
||||
// create two loops around poly
|
||||
// find shortest of two paths and emit poly points
|
||||
let poly = i1.poly;
|
||||
let isCW = poly.isClockwise();
|
||||
let points = poly.points;
|
||||
|
||||
let p1p = isCW ? points : points.slice().reverse(); // CW
|
||||
let p2p = isCW ? points.slice().reverse() : points; // CCW
|
||||
|
||||
let r1s = p1p.indexOf(isCW ? i1.ip.p2 : i1.ip.p1);
|
||||
let r1e = p1p.indexOf(isCW ? i2.ip.p1 : i2.ip.p2);
|
||||
|
||||
let r1 = r1s === r1e ?
|
||||
[ p1p[r1s] ] : r1s < r1e ?
|
||||
[ ...p1p.slice(r1s,r1e+1) ] :
|
||||
[ ...p1p.slice(r1s), ...p1p.slice(0,r1e+1) ];
|
||||
|
||||
let r1d = 0;
|
||||
for (let i=1; i<r1.length; i++) {
|
||||
r1d += r1[i-1].distTo2D(r1[i]);
|
||||
}
|
||||
|
||||
let r2s = p2p.indexOf(isCW ? i1.ip.p1 : i1.ip.p2);
|
||||
let r2e = p2p.indexOf(isCW ? i2.ip.p2 : i2.ip.p1);
|
||||
|
||||
let r2 = r2s === r2e ?
|
||||
[ p2p[r2s] ] : r2s < r2e ?
|
||||
[ ...p2p.slice(r2s,r2e+1) ] :
|
||||
[ ...p2p.slice(r2s), ...p2p.slice(0,r2e+1) ];
|
||||
|
||||
let r2d = 0;
|
||||
for (let i=1; i<r2.length; i++) {
|
||||
r2d += r2[i-1].distTo2D(r2[i]);
|
||||
}
|
||||
|
||||
let route = r1d <= r2d ? r1 : r2;
|
||||
|
||||
if (dbug === slice.index) console.log(slice.index, {
|
||||
ints: ints.map(i=>i.ip.dist),
|
||||
i1, i2, same: i1.poly === i2.poly,
|
||||
route,
|
||||
r1, r1d, r1s, r1e,
|
||||
r2, r2d, r2s, r2e,
|
||||
isCW});
|
||||
|
||||
for (let p of route) {
|
||||
addOutput(preout, p, 0, moveSpeed, extruder);
|
||||
}
|
||||
|
||||
// output last point
|
||||
addOutput(preout, i2.ip, 0, moveSpeed, extruder);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function outputTraces(poly, opt = {}) {
|
||||
if (!poly) return;
|
||||
if (Array.isArray(poly)) {
|
||||
outputOrderClosest(poly, function(next) {
|
||||
outputTraces(next, extrude);
|
||||
}, null);
|
||||
if (opt.sort) {
|
||||
let polys = poly.slice().sort(function(a,b) {
|
||||
return (a.perimeter() - b.perimeter()) * opt.sort;
|
||||
});
|
||||
let debug = polys.length > 3;
|
||||
let last;
|
||||
while (polys.length) {
|
||||
let next;
|
||||
for (let p of polys) {
|
||||
if (!last) {
|
||||
next = p;
|
||||
break;
|
||||
}
|
||||
if (opt.sort > 0) {
|
||||
// in-out
|
||||
if (last.isInside(p)) {
|
||||
next = p;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// out-in
|
||||
if (p.isInside(last)) {
|
||||
next = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next) {
|
||||
last = next;
|
||||
polys.remove(next);
|
||||
outputTraces(next, opt);
|
||||
} else {
|
||||
last = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
outputOrderClosest(poly, function(next) {
|
||||
outputTraces(next, opt);
|
||||
}, null);
|
||||
}
|
||||
} else {
|
||||
let finishShell = poly.depth === 0 && !firstLayer;
|
||||
startPoint = scope.polyPrintPath(poly, startPoint, preout, {
|
||||
|
|
@ -489,13 +751,18 @@
|
|||
accel: finishShell,
|
||||
wipe: process.outputWipeDistance || 0,
|
||||
coast: firstLayer ? 0 : coastDist,
|
||||
extrude: pref(extrude, shellMult),
|
||||
extrude: pref(opt.extrude, shellMult),
|
||||
onfirst: function(firstPoint) {
|
||||
if (startPoint.distTo2D(firstPoint) > retractDist) {
|
||||
retract();
|
||||
let from = seedPoint || startPoint;
|
||||
if (from.distTo2D(firstPoint) > retractDist) {
|
||||
if (intersectsTop(from, firstPoint)) {
|
||||
retract();
|
||||
}
|
||||
}
|
||||
seedPoint = null;
|
||||
}
|
||||
});
|
||||
lastPoly = slice.lastPoly = poly;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -530,12 +797,12 @@
|
|||
// let emit = i === 0 ? 0 : extrude;
|
||||
addOutput(preout, p, emit, speed || printSpeed, extruder);
|
||||
lp = p;
|
||||
});
|
||||
}, !poly.open);
|
||||
return lp;
|
||||
});
|
||||
}
|
||||
|
||||
function outputFills(lines, options) {
|
||||
function outputFills(lines, opt = {}) {
|
||||
if (!lines || lines.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -544,10 +811,10 @@
|
|||
start = 0,
|
||||
skip = false,
|
||||
lastIndex = -1,
|
||||
opt = options || {},
|
||||
flow = opt.flow || 1,
|
||||
near = opt.near || false,
|
||||
fast = opt.fast || false,
|
||||
fill = opt.fill >= 0 ? opt.fill : fillMult,
|
||||
fill = (opt.fill >= 0 ? opt.fill : fillMult) * flow,
|
||||
thinDist = near ? thinWall : thinWall;
|
||||
|
||||
while (lines && marked < lines.length) {
|
||||
|
|
@ -684,11 +951,11 @@
|
|||
* the special exception that depth is considered into distance
|
||||
* so that inner polygons are emitted first.
|
||||
*
|
||||
* @param {Array} array of Polygon or Polygon wrappers
|
||||
* @param {Function} fn
|
||||
* @param {Function} fnp convert 'next' object into a Polygon
|
||||
* @param {Array} array of Polygons or Polygon wrappers (tops)
|
||||
* @param {Function} fn call to emit next candidate
|
||||
* @param {Function} fnp convert 'next' object into a Polygon for closeness
|
||||
*/
|
||||
function outputOrderClosest(array, fn, fnp, newTop) {
|
||||
function outputOrderClosest(array, fn, fnp) {
|
||||
if (array.length === 1) {
|
||||
return fn(array[0]);
|
||||
}
|
||||
|
|
@ -708,7 +975,6 @@
|
|||
d: find.distance - (poly.depth * thinWall),
|
||||
});
|
||||
}
|
||||
newTop = false;
|
||||
if (order.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -753,37 +1019,31 @@
|
|||
// and enforce optimal shell order (outer first)
|
||||
if (isBelt && opt.onBelt) {
|
||||
startPoint = startClone;
|
||||
shellOrder = 1;
|
||||
shellOrder = -1;
|
||||
}
|
||||
|
||||
// top object
|
||||
let bounds = POLY.flatten(next.shellsAtDepth(0).clone(true));
|
||||
// innermost shells
|
||||
let inner = next.innerShells() || [];
|
||||
|
||||
// output inner polygons
|
||||
if (shellOrder === 1)
|
||||
outputTraces([].appendAll(next.innerShells() || []));
|
||||
if (shellOrder === 1) outputTraces(inner, { sort: shellOrder });
|
||||
|
||||
// sort perimeter polygon by length to go out-to-in or in-to-out
|
||||
(next.shells || []).sort(function(a,b) {
|
||||
return a.perimeter() > b.perimeter() ? shellOrder : -shellOrder;
|
||||
}).forEach(function(poly, index) {
|
||||
outputTraces(poly);
|
||||
});
|
||||
outputTraces(next.shells, { sort: shellOrder });
|
||||
|
||||
// output outer polygons
|
||||
if (shellOrder === -1)
|
||||
outputTraces([].appendAll(next.innerShells() || []));
|
||||
if (shellOrder === -1) outputTraces(inner, { sort: shellOrder });
|
||||
|
||||
// output thin fill
|
||||
outputFills(next.thin_fill, {near: true});
|
||||
|
||||
// then output solid and sparse fill
|
||||
outputFills(next.fill_lines);
|
||||
outputSparse(next.fill_sparse, sparseMult);
|
||||
outputFills(next.fill_lines, {flow: solidWidth});
|
||||
outputSparse(next.fill_sparse, sparseMult, infillSpeed);
|
||||
|
||||
lastTop = next;
|
||||
}
|
||||
}, function(obj) {
|
||||
// for tops
|
||||
return obj instanceof Polygon ? obj : obj.poly;
|
||||
});
|
||||
|
||||
|
|
@ -971,15 +1231,15 @@
|
|||
function constOp(tok, consts, opch, op) {
|
||||
let pos, v1, v2;
|
||||
if ((pos = tok.indexOf(opch)) > 0) {
|
||||
v1 = consts[tok.substring(0,pos)] || 0;
|
||||
v2 = parseInt(tok.substring(pos+1)) || 0;
|
||||
return op(v1,v2);
|
||||
v1 = parseFloat(consts[tok.substring(0,pos)] || 0);
|
||||
v2 = parseFloat(tok.substring(pos+1)) || 0;
|
||||
return op(v1,v2).round(4);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function constReplace(str, consts, start) {
|
||||
function constReplace(str, consts, start, pad, short) {
|
||||
let cs = str.indexOf("{", start || 0),
|
||||
ce = str.indexOf("}", cs),
|
||||
tok, nutok, nustr;
|
||||
|
|
@ -991,9 +1251,24 @@
|
|||
constOp(tok, consts, "/", function(v1,v2) { return v1/v2 }) ||
|
||||
constOp(tok, consts, "*", function(v1,v2) { return v1*v2 }) ||
|
||||
consts[tok] || 0;
|
||||
if (pad) {
|
||||
nutok = nutok.toString();
|
||||
let oldln = ce-cs+1;
|
||||
let tokln = nutok.length;
|
||||
if (tokln < oldln) {
|
||||
short = (short || 1) + (oldln - tokln);
|
||||
}
|
||||
}
|
||||
nustr = str.replace("{"+tok+"}",nutok);
|
||||
return constReplace(nustr, consts, ce+1+(nustr.length-str.length));
|
||||
return constReplace(nustr, consts, ce+1+(nustr.length-str.length), pad, short);
|
||||
} else {
|
||||
// insert compensating spaces for accumulated replace string shortages
|
||||
if (short) {
|
||||
let si = str.indexOf(';');
|
||||
if (si > 0) {
|
||||
str = str.replace(';', ';'.padStart(short,' '));
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@
|
|||
zM = Math.max(p1.z, p2.z, p3.z),
|
||||
bm = Math.floor(zm * zScale),
|
||||
bM = Math.ceil(zM * zScale);
|
||||
if (bm < 0) bm = 0;
|
||||
for (j = bm; j < bM; j++) {
|
||||
buckets[j].push(p1);
|
||||
buckets[j].push(p2);
|
||||
|
|
@ -529,6 +530,9 @@
|
|||
// for topo slices, we just need the raw lines
|
||||
if (!topoMode && !simpleMode) {
|
||||
slice.groups = connectLines(slice.lines, slice.z);
|
||||
if (options.union) {
|
||||
slice.groups = POLY.flatten(POLY.union(POLY.nest(slice.groups), null, true), null, true);
|
||||
}
|
||||
if ((debug && slice.lines.excessive) || xray) {
|
||||
const dash = xray || 3;
|
||||
slice.lines.forEach((line, i) => {
|
||||
|
|
|
|||
|
|
@ -722,7 +722,11 @@
|
|||
}
|
||||
} else {
|
||||
// no more closest polys (open set)
|
||||
emit(BASE.newPolygon().addPoints(array));
|
||||
if (opt.openok) {
|
||||
emit(BASE.newPolygon().addPoints(array).setOpen());
|
||||
} else {
|
||||
emit(BASE.newPolygon().addPoints(array));
|
||||
}
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,17 @@
|
|||
this.show();
|
||||
for (let i=0, s=this.slices, len=s.length; i<len; i++) {
|
||||
s[i].visible = i >= newMin && i <= newMax;
|
||||
if (s[i].visible) this.lastVis = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
setLastFraction(frac = 1) {
|
||||
if (this.lastVis)
|
||||
for (let mesh of this.lastVis.children) {
|
||||
let geo = mesh.geometry;
|
||||
let pos = geo.attributes.position;
|
||||
let len = frac === 1 ? Infinity : Math.round(pos.count * frac);
|
||||
geo.setDrawRange(0, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,24 @@
|
|||
return stacks[name];
|
||||
}
|
||||
|
||||
function getStacks() {
|
||||
return Object.entries(stacks);
|
||||
}
|
||||
|
||||
function getLabels() {
|
||||
return Object.keys(DYN);
|
||||
}
|
||||
|
||||
function setVisible(label, bool) {
|
||||
let ctrl = DYN[label];
|
||||
if (ctrl) {
|
||||
ctrl.toggle.checked = bool;
|
||||
ctrl.group.forEach(mat => {
|
||||
mat.visible = bool;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function create(name, view) {
|
||||
if (stacks[name]) {
|
||||
return stacks[name];
|
||||
|
|
@ -70,6 +88,11 @@
|
|||
ctrl.group.forEach(mat => {
|
||||
mat.visible = ctrl.toggle.checked;
|
||||
});
|
||||
if (ctrl.toggle.checked) {
|
||||
KIRI.api.event.emit("stack.show", label);
|
||||
} else {
|
||||
KIRI.api.event.emit("stack.hide", label)
|
||||
}
|
||||
})
|
||||
};
|
||||
let color = lmap[label].color.check;
|
||||
|
|
@ -120,14 +143,24 @@
|
|||
max = newMax;
|
||||
}
|
||||
|
||||
function setFraction(frac) {
|
||||
Object.values(stacks).forEach(stack => {
|
||||
stack.obj.setLastFraction(frac);
|
||||
});
|
||||
}
|
||||
|
||||
KIRI.stacks = {
|
||||
clear,
|
||||
create,
|
||||
rotate,
|
||||
remove,
|
||||
getStack,
|
||||
getStacks,
|
||||
getRange,
|
||||
setRange,
|
||||
getLabels,
|
||||
setVisible,
|
||||
setFraction,
|
||||
setFreeMem
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
prefix = "tab",
|
||||
state = {},
|
||||
units = 1,
|
||||
lastChange = null,
|
||||
lastBtn = null,
|
||||
lastTxt = null,
|
||||
lastPop = null,
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
KIRI.ui = {
|
||||
prefix: function(pre) { prefix = pre; return kiri.ui },
|
||||
inputAction: function(fn) { inputAction = fn; return kiri.ui },
|
||||
lastChange: function() { return lastChange },
|
||||
checkpoint,
|
||||
restore,
|
||||
refresh,
|
||||
|
|
@ -47,6 +49,7 @@
|
|||
setExpert,
|
||||
setHoverPop,
|
||||
hidePoppers,
|
||||
hoverPop,
|
||||
bound,
|
||||
toInt,
|
||||
toFloat,
|
||||
|
|
@ -683,6 +686,7 @@
|
|||
}
|
||||
});
|
||||
ip.addEventListener('blur', function(event) {
|
||||
lastChange = ip;
|
||||
action(event);
|
||||
if (opt.trigger) {
|
||||
refresh();
|
||||
|
|
@ -761,6 +765,7 @@
|
|||
}
|
||||
ip.setVisible = row.setVisible;
|
||||
ip.onchange = function(ev) {
|
||||
lastChange = ip;
|
||||
action();
|
||||
};
|
||||
ip.onclick = (ev) => {
|
||||
|
|
@ -882,4 +887,54 @@
|
|||
return array;
|
||||
}
|
||||
|
||||
function hoverPop(el, opt = {}) {
|
||||
if (Array.isArray(el)) {
|
||||
opt.group = [];
|
||||
return el.forEach(ev => hoverPop(ev, opt));
|
||||
}
|
||||
let group = opt.group || [];
|
||||
let closes = opt.closes || group;
|
||||
let target = opt.target || el;
|
||||
let popped = false;
|
||||
group.push(target);
|
||||
if (closes !== group) {
|
||||
closes.push(target);
|
||||
}
|
||||
let openit = () => {
|
||||
clearTimeout(closes.timer);
|
||||
for (let close of closes) {
|
||||
close.classList.remove("hoverpop");
|
||||
}
|
||||
target.classList.add("hoverpop");
|
||||
popped = true;
|
||||
};
|
||||
let closeit = () => {
|
||||
target.classList.remove("hoverpop");
|
||||
clearTimeout(closes.timer);
|
||||
popped = false;
|
||||
};
|
||||
if (opt.auto !== false) {
|
||||
el.addEventListener("mouseenter", openit);
|
||||
}
|
||||
el.addEventListener("mouseleave", (ev) => {
|
||||
closes.timer = setTimeout(() => {
|
||||
target.classList.remove("hoverpop");
|
||||
}, 750);
|
||||
});
|
||||
if (!opt.sticky) {
|
||||
el.addEventListener("mouseup", (ev) => {
|
||||
if (popped) {
|
||||
closeit();
|
||||
} else {
|
||||
openit();
|
||||
}
|
||||
});
|
||||
}
|
||||
document.addEventListener("keydown", (ev) => {
|
||||
if (ev.keyCode === 27 || ev.code === 'Escape') {
|
||||
closeit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -32,6 +32,39 @@
|
|||
|
||||
let Group = Widget.Groups = {
|
||||
|
||||
list: () => {
|
||||
return groups.slice()
|
||||
},
|
||||
|
||||
merge: (widgets) => {
|
||||
let grps = widgets.map(w => w.group).uniq();
|
||||
if (grps.length > 1) {
|
||||
let root = grps.shift();
|
||||
let rpos = root[0].track.pos;
|
||||
for (let grp of grps) {
|
||||
for (let w of grp) {
|
||||
let wpos = w.track.pos;
|
||||
w.group = root;
|
||||
w.moveMesh(rpos.x - wpos.x, rpos.y - wpos.y, rpos.z - wpos.z);
|
||||
w._move(rpos.x, rpos.y, rpos.z, true);
|
||||
root.push(w);
|
||||
}
|
||||
groups.splice(groups.indexOf(grp),1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
split: (widgets) => {
|
||||
for (let group of widgets.map(w => w.group).uniq()) {
|
||||
groups.splice(groups.indexOf(group),1);
|
||||
for (let widget of group) {
|
||||
let nugroup = Group.forid(widget.id);
|
||||
nugroup.push(widget);
|
||||
widget.group = nugroup;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
forid: function(id) {
|
||||
for (let i=0; i<groups.length; i++) {
|
||||
if (groups[i].id === id) return groups[i];
|
||||
|
|
@ -101,7 +134,7 @@
|
|||
* @params {String} [id]
|
||||
* @constructor
|
||||
*/
|
||||
function Widget(id,group) {
|
||||
function Widget(id, group) {
|
||||
this.id = id || new Date().getTime().toString(36)+(nextId++);
|
||||
this.group = group || [];
|
||||
this.group.push(this);
|
||||
|
|
@ -254,6 +287,10 @@
|
|||
}
|
||||
};
|
||||
|
||||
PRO.getVertices = function() {
|
||||
return this.mesh.geometry.attributes.position;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {THREE.Geometry} geometry
|
||||
* @returns {Widget}
|
||||
|
|
@ -461,11 +498,11 @@
|
|||
this.modified = true;
|
||||
};
|
||||
|
||||
PRO.rotate = function(x, y, z) {
|
||||
PRO.rotate = function(x, y, z, temp) {
|
||||
this.group.forEach(w => {
|
||||
w._rotate(x, y, z, false);
|
||||
w._rotate(x, y, z, temp);
|
||||
});
|
||||
this.center();
|
||||
this.center(false);
|
||||
};
|
||||
|
||||
PRO._rotate = function(x, y, z, temp) {
|
||||
|
|
@ -509,20 +546,55 @@
|
|||
};
|
||||
|
||||
PRO._mirror = function() {
|
||||
this.setWireframe(false);
|
||||
this.clearSlices();
|
||||
this.mesh.applyMatrix4(new THREE.Matrix4().makeScale(-1, 1, 1));
|
||||
let geo = this.mesh.geometry,
|
||||
o = this.track;
|
||||
this.setWireframe(false);
|
||||
let geo = this.mesh.geometry, ot = this.track;
|
||||
let pos = geo.attributes.position;
|
||||
let arr = pos.array;
|
||||
let count = pos.count;
|
||||
// invert x
|
||||
for (let i=0; i<count; i++) {
|
||||
arr[i*3] = -arr[i*3];
|
||||
}
|
||||
// invert face vertices
|
||||
for (let i=0; i<count; i+=3) {
|
||||
let x = arr[i*3+0];
|
||||
let y = arr[i*3+1];
|
||||
let z = arr[i*3+2];
|
||||
arr[i*3+0] = arr[i*3+6];
|
||||
arr[i*3+1] = arr[i*3+7];
|
||||
arr[i*3+2] = arr[i*3+8];
|
||||
arr[i*3+6] = x;
|
||||
arr[i*3+7] = y;
|
||||
arr[i*3+8] = z;
|
||||
}
|
||||
pos.needsUpdate = true;
|
||||
geo.computeFaceNormals();
|
||||
geo.computeVertexNormals();
|
||||
this.mesh.position.x = -this.mesh.position.x;
|
||||
o.mirror = !o.mirror;
|
||||
ot.mirror = !ot.mirror;
|
||||
this.modified = true;
|
||||
this.points = null;
|
||||
};
|
||||
|
||||
PRO.getGeoVertices = function() {
|
||||
return this.mesh.geometry.getAttribute('position').array;
|
||||
let geo = this.mesh.geometry;
|
||||
let pos = geo.getAttribute('position').array;
|
||||
if (geo.index) {
|
||||
let idx = geo.index.array;
|
||||
let len = idx.length;
|
||||
let p2 = new Float32Array(len * 3);
|
||||
let inc = 0;
|
||||
for (let i=0; i<len; i++) {
|
||||
let iv = idx[i];
|
||||
let ip = iv * 3;
|
||||
p2[inc++] = pos[ip++];
|
||||
p2[inc++] = pos[ip++];
|
||||
p2[inc++] = pos[ip];
|
||||
}
|
||||
return p2;
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
PRO.getPoints = function() {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ let BASE = self.base,
|
|||
print: null,
|
||||
snap: null
|
||||
},
|
||||
cache = {};
|
||||
wgroup = {},
|
||||
wcache = {};
|
||||
|
||||
// catch clipper alerts and convert to console messages
|
||||
self.alert = function(o) {
|
||||
|
|
@ -24,7 +25,9 @@ BASE.debug.disable();
|
|||
const dispatch =
|
||||
KIRI.server =
|
||||
KIRI.worker = {
|
||||
cache: cache,
|
||||
group: wgroup,
|
||||
|
||||
cache: wcache,
|
||||
|
||||
decimate: function(data, send) {
|
||||
let { vertices, options } = data;
|
||||
|
|
@ -38,65 +41,128 @@ KIRI.worker = {
|
|||
send.done();
|
||||
},
|
||||
|
||||
clear: function(data, send) {
|
||||
current.snap = null;
|
||||
current.print = null;
|
||||
dispatch.group = wgroup = {};
|
||||
dispatch.cache = wcache = {};
|
||||
send.done({ clear: true });
|
||||
},
|
||||
|
||||
// widget sync
|
||||
sync: function(data, send) {
|
||||
if (data.valid) {
|
||||
// remove widgets not present in valid list
|
||||
for (let key in wcache) {
|
||||
if (data.valid.indexOf(key) < 0) {
|
||||
delete wcache[key];
|
||||
for (let [id,group] of Object.entries(wgroup)) {
|
||||
wgroup[id] = group = group.filter(v => v.id !== key);
|
||||
group.id = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
send.done(data.id);
|
||||
return;
|
||||
}
|
||||
|
||||
let group = wgroup[data.group];
|
||||
if (!group) {
|
||||
group = [];
|
||||
group.id = data.group;
|
||||
wgroup[data.group] = group;
|
||||
}
|
||||
let vertices = new Float32Array(data.vertices),
|
||||
points = BASE.verticesToPoints(vertices, { maxpass: 0 }),
|
||||
widget = KIRI.newWidget(data.id).setPoints(points);
|
||||
widget = KIRI.newWidget(data.id, group).loadVertices(vertices);
|
||||
|
||||
// do it here so cancel can work
|
||||
cache[data.id] = widget;
|
||||
wcache[data.id] = widget;
|
||||
// stored for possible future rotations
|
||||
widget.vertices = vertices;
|
||||
|
||||
// fake mesh object to satisfy printing
|
||||
widget.track = data.tracking;
|
||||
widget.mesh = {
|
||||
widget: widget,
|
||||
position: data.position
|
||||
};
|
||||
|
||||
// restore tracking object
|
||||
widget.track = data.track;
|
||||
send.done(data.id);
|
||||
},
|
||||
|
||||
slice: function(data, send) {
|
||||
let { id, settings } = data;
|
||||
rotate: function(data, send) {
|
||||
let { settings } = data;
|
||||
if (!settings.device.bedBelt) {
|
||||
return send.done({});
|
||||
}
|
||||
|
||||
send.data({update:0.05, updateStatus:"slicing"});
|
||||
|
||||
let widget = cache[data.id],
|
||||
last = time(),
|
||||
xpos,
|
||||
ypos,
|
||||
now;
|
||||
|
||||
try {
|
||||
|
||||
let rotation = (Math.PI/180) * (settings.device.bedBelt ? 45 : 0);
|
||||
if (rotation) {
|
||||
// need min y for post-rotation offset in prepare
|
||||
let vert = widget.vertices;
|
||||
let miny = Infinity;
|
||||
function mins(vert, last = {}) {
|
||||
let miny = last.miny || Infinity,
|
||||
maxy = last.maxy || -Infinity;
|
||||
for (let i=0, l=vert.length; i<l; ) {
|
||||
let x = vert[i++];
|
||||
let y = vert[i++];
|
||||
let z = vert[i++];
|
||||
if (z < 0.01) miny = Math.min(miny, y);
|
||||
if (z < 0.01) {
|
||||
miny = Math.min(miny, y);
|
||||
maxy = Math.max(maxy, y);
|
||||
}
|
||||
}
|
||||
return { miny, maxy };
|
||||
}
|
||||
|
||||
function gmin(group) {
|
||||
let minv = {};
|
||||
for (let w of group) {
|
||||
minv = mins(w.vertices, minv);
|
||||
}
|
||||
return minv;
|
||||
}
|
||||
|
||||
for (let group of Object.values(wgroup)) {
|
||||
let { miny, maxy } = gmin(group);
|
||||
|
||||
let widget = group[0];
|
||||
let track = widget.track;
|
||||
let xpos = track.pos.x;
|
||||
let ypos = settings.device.bedDepth / 2 + track.pos.y + miny;
|
||||
let rotation = (Math.PI / 180) * 45;
|
||||
|
||||
widget.rotate(rotation,0,0,true);
|
||||
let minr = gmin(group);
|
||||
widget.belt = { xpos, ypos, yadd: minr.maxy - minr.miny };
|
||||
for (let others of group.slice(1)) {
|
||||
others.belt = widget.belt;
|
||||
}
|
||||
|
||||
widget.getBoundingBox(true);
|
||||
let track = widget.track;
|
||||
xpos = track.pos.x;
|
||||
ypos = settings.device.bedDepth / 2 + track.pos.y + miny;
|
||||
|
||||
widget.mesh = null;
|
||||
widget.points = null;
|
||||
widget.loadVertices(widget.vertices);
|
||||
widget._rotate(rotation,0,0,true);
|
||||
widget.center(false, true);
|
||||
widget.getBoundingBox(true);
|
||||
widget.belt = { xpos, ypos };
|
||||
send.data({group: group.id, belt: widget.belt});
|
||||
}
|
||||
send.done({});
|
||||
},
|
||||
|
||||
unrotate: function(data, send) {
|
||||
let { settings } = data;
|
||||
if (!settings.device.bedBelt) {
|
||||
return send.done({});
|
||||
}
|
||||
let rotation = (Math.PI / 180) * 45;
|
||||
for (let group of Object.values(wgroup)) {
|
||||
let widget = group[0];
|
||||
widget.groupBounds();
|
||||
widget.rotate(-rotation,0,0,true);
|
||||
let { dy, dz } = widget.track.center;
|
||||
widget.groupBounds();
|
||||
let { xpos, ypos } = widget.belt;
|
||||
widget.rotinfo = { angle: 45, dy, dz, xpos, ypos };
|
||||
for (let others of group.slice(1)) {
|
||||
others.rotinfo = widget.rotinfo;
|
||||
}
|
||||
send.data({group: group.id, rotinfo: widget.rotinfo});
|
||||
}
|
||||
send.done({});
|
||||
},
|
||||
|
||||
slice: function(data, send) {
|
||||
send.data({update:0.001, updateStatus:"slicing"});
|
||||
|
||||
let settings = data.settings,
|
||||
widget = wcache[data.id],
|
||||
last = time(),
|
||||
now;
|
||||
|
||||
widget.slice(settings, function(error) {
|
||||
if (error) {
|
||||
|
|
@ -113,19 +179,7 @@ KIRI.worker = {
|
|||
send.data({index: index, slice: slice.encode(state)}, state.zeros);
|
||||
})
|
||||
send.data({send_end: time()});
|
||||
// unrotate and send delta coordinates
|
||||
if (rotation) {
|
||||
widget.setPoints(null);
|
||||
widget._rotate(-rotation,0,0,true);
|
||||
let wbb = widget.getBoundingBox(true);
|
||||
widget.center(false, true);
|
||||
let dy = (wbb.max.y + wbb.min.y)/2;
|
||||
let dz = wbb.min.z;
|
||||
widget.rotinfo = { angle: 45, dy, dz, xpos, ypos };
|
||||
send.data({ rotinfo: widget.rotinfo });
|
||||
}
|
||||
}
|
||||
|
||||
send.done({done: true});
|
||||
}, function(update, msg) {
|
||||
now = time();
|
||||
|
|
@ -134,16 +188,11 @@ KIRI.worker = {
|
|||
send.data({update: (0.05 + update * 0.95), updateStatus: msg});
|
||||
last = now;
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
send.data({error: error.toString()});
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
|
||||
prepare: function(data, send) {
|
||||
// create widget array from id:widget cache
|
||||
const widgets = Object.values(cache);
|
||||
const widgets = Object.values(wcache);
|
||||
|
||||
// let client know we've started
|
||||
send.data({update:0.05, updateStatus:"preview"});
|
||||
|
|
@ -222,7 +271,7 @@ KIRI.worker = {
|
|||
z: origin.z
|
||||
};
|
||||
const device = settings.device;
|
||||
const print = current.print = KIRI.newPrint(settings, Object.values(cache));
|
||||
const print = current.print = KIRI.newPrint(settings, Object.values(wcache));
|
||||
const tools = device.extruders;
|
||||
const mode = settings.mode;
|
||||
const thin = settings.controller.lineType === 'line' || mode !== 'FDM';
|
||||
|
|
@ -248,30 +297,13 @@ KIRI.worker = {
|
|||
out.point = BASE.newPoint(x,y,z || 0);
|
||||
});
|
||||
});
|
||||
const print = current.print = KIRI.newPrint(null, Object.values(cache));
|
||||
const print = current.print = KIRI.newPrint(null, Object.values(wcache));
|
||||
const layers = KIRI.driver.FDM.prepareRender(parsed, progress => {
|
||||
send.data({ progress });
|
||||
}, { thin: true });
|
||||
send.done({parsed: KIRI.codec.encode(layers)});
|
||||
},
|
||||
|
||||
clear: function(data, send) {
|
||||
current.snap = null;
|
||||
current.print = null;
|
||||
if (!data.id) {
|
||||
cache = {};
|
||||
send.done({ clear: true });
|
||||
return;
|
||||
}
|
||||
let had = cache[data.id] !== undefined;
|
||||
delete cache[data.id];
|
||||
send.done({
|
||||
id: data.id,
|
||||
had: had,
|
||||
has: cache[data.id] !== undefined
|
||||
});
|
||||
},
|
||||
|
||||
config: function(data, send) {
|
||||
const update = {};
|
||||
if (data.base) {
|
||||
|
|
@ -383,11 +415,11 @@ KIRI.worker = {
|
|||
let p3 = (x - 0) * height + (y - 0);
|
||||
let p4 = (x - 1) * height + (y - 1);
|
||||
faces[ii++] = p1;
|
||||
faces[ii++] = p2;
|
||||
faces[ii++] = p3;
|
||||
faces[ii++] = p1;
|
||||
faces[ii++] = p4;
|
||||
faces[ii++] = p2;
|
||||
faces[ii++] = p1;
|
||||
faces[ii++] = p2;
|
||||
faces[ii++] = p4;
|
||||
}
|
||||
}
|
||||
send.data({progress: x / width});
|
||||
|
|
@ -504,6 +536,24 @@ KIRI.worker = {
|
|||
// send.done({done: {verts, faces, bigv, vi, ii}}, [ bigv.buffer ]);
|
||||
send.done({done: {bigv}}, [ bigv.buffer ]);
|
||||
});
|
||||
},
|
||||
|
||||
zip: function(data, send) {
|
||||
let { files } = data;
|
||||
let zip = new JSZip();
|
||||
for (let file of files) {
|
||||
zip.file(file.name, file.data);
|
||||
}
|
||||
zip.generateAsync({
|
||||
type: "uint8array",
|
||||
compression: "DEFLATE",
|
||||
compressionOptions: { level: 3 },
|
||||
streamFiles: true
|
||||
}, progress => {
|
||||
send.data(progress);
|
||||
}).then(output => {
|
||||
send.done(output);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -543,20 +593,26 @@ self.onmessage = function(e) {
|
|||
};
|
||||
|
||||
if (run) {
|
||||
let time_xfer = (time_recv - msg.time),
|
||||
output = run(msg.data, send),
|
||||
time_send = time(),
|
||||
time_proc = time_send - time_recv;
|
||||
try {
|
||||
let time_xfer = (time_recv - msg.time),
|
||||
output = run(msg.data, send),
|
||||
time_send = time(),
|
||||
time_proc = time_send - time_recv;
|
||||
|
||||
if (output) self.postMessage({
|
||||
seq: msg.seq,
|
||||
task: msg.task,
|
||||
time_send: time_xfer,
|
||||
time_proc: time_proc,
|
||||
// replaced on reply side
|
||||
time_recv: time(),
|
||||
data: output
|
||||
});
|
||||
if (output) self.postMessage({
|
||||
seq: msg.seq,
|
||||
task: msg.task,
|
||||
time_send: time_xfer,
|
||||
time_proc: time_proc,
|
||||
// replaced on reply side
|
||||
time_recv: time(),
|
||||
data: output
|
||||
});
|
||||
} catch (wrkerr) {
|
||||
// console.log(wrkerr);
|
||||
console.trace(wrkerr.stack);
|
||||
send.done({error: wrkerr.toString()});
|
||||
}
|
||||
} else {
|
||||
console.log({kiri_msg:e});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
let terms = {
|
||||
COPYRIGHT: "Copyright (C) Stewart Allen <sa@grid.space> - All Rights Reserved",
|
||||
LICENSE: "See the license.md file included with the source distribution",
|
||||
VERSION: "2.6.D8"
|
||||
VERSION: "2.8.D1"
|
||||
};
|
||||
|
||||
if (typeof(module) === 'object') {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,10 @@
|
|||
API = api;
|
||||
|
||||
// wire up animate button in ui
|
||||
api.function.animate = () => {
|
||||
api.event.on("function.animate", (mode) => {
|
||||
if (isAnimate) {
|
||||
return;
|
||||
}
|
||||
if (isCamMode && !camStock) {
|
||||
return api.show.alert("animation requires stock to be enabled");
|
||||
}
|
||||
|
|
@ -50,7 +53,7 @@
|
|||
animate();
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
api.event.on("mode.set", (mode) => {
|
||||
isCamMode = mode === 'CAM';
|
||||
|
|
@ -61,11 +64,11 @@
|
|||
if (!isCamMode) {
|
||||
func.tabClear();
|
||||
func.traceDone();
|
||||
UI.label.slice.innerText = 'slice';
|
||||
UI.label.preview.innerText = 'preview';
|
||||
UI.label.export.innerText = 'export';
|
||||
UI.label.slice.innerText = LANG.slice;
|
||||
UI.label.preview.innerText = LANG.preview;
|
||||
UI.label.export.innerText = LANG.export;
|
||||
} else {
|
||||
UI.label.slice.innerText = 'start';
|
||||
UI.label.slice.innerText = LANG.start;
|
||||
}
|
||||
// do not persist traces across page reloads
|
||||
func.traceClear();
|
||||
|
|
@ -534,7 +537,7 @@
|
|||
KIRI.api.widgets.opacity(0.8);
|
||||
KIRI.api.widgets.for(widget => {
|
||||
if (ids.indexOf(widget.id) >= 0) {
|
||||
unselectTraces(widget);
|
||||
unselectTraces(widget, true);
|
||||
widget.trace_stack = null;
|
||||
}
|
||||
if (widget.trace_stack) {
|
||||
|
|
@ -578,7 +581,7 @@
|
|||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}, poppedRec.single);
|
||||
api.feature.hover = true;
|
||||
api.feature.hoverAdds = true;
|
||||
func.hover = func.traceHover;
|
||||
|
|
@ -831,7 +834,7 @@
|
|||
dogbones: UC.newBoolean(LANG.co_dogb_s, undefined, {title:LANG.co_dogb_l, show:(op) => { return !op.inputs.wide.checked }}),
|
||||
inside: UC.newBoolean(LANG.co_olin_s, undefined, {title:LANG.co_olin_l, show:(op) => { return !op.inputs.outside.checked }}),
|
||||
outside: UC.newBoolean(LANG.co_olot_s, undefined, {title:LANG.co_olot_l, show:(op) => { return !op.inputs.inside.checked }}),
|
||||
omitthru: UC.newBoolean(LANG.co_omit_s, undefined, {title:LANG.co_omit_l, show:(op) => { return op.inputs.outside.checked }}),
|
||||
omitthru: UC.newBoolean(LANG.co_omit_s, undefined, {title:LANG.co_omit_l, xshow:(op) => { return op.inputs.outside.checked }}),
|
||||
wide: UC.newBoolean(LANG.co_wide_s, undefined, {title:LANG.co_wide_l, show:(op) => { return !op.inputs.inside.checked }})
|
||||
};
|
||||
|
||||
|
|
@ -867,7 +870,8 @@
|
|||
step: 'camTraceOver',
|
||||
down: 'camTraceDown',
|
||||
rate: 'camTraceSpeed',
|
||||
plunge: 'camTracePlunge'
|
||||
plunge: 'camTracePlunge',
|
||||
single: 'camTraceLines',
|
||||
}).inputs = {
|
||||
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||
sep: UC.newBlank({class:"pop-sep"}),
|
||||
|
|
@ -879,6 +883,7 @@
|
|||
rate: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, units:true}),
|
||||
plunge: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:UC.toInt, units:true}),
|
||||
sep: UC.newBlank({class:"pop-sep"}),
|
||||
single: UC.newBoolean(LANG.cc_sngl_s, undefined, {title:LANG.cc_sngl_l}),
|
||||
select: UC.newRow([
|
||||
UC.newButton(undefined, func.traceAdd, {icon:'<i class="fas fa-plus"></i>'}),
|
||||
UC.newButton(undefined, func.traceDone, {icon:'<i class="fas fa-check"></i>'}),
|
||||
|
|
@ -1044,11 +1049,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
function unselectTraces(widget) {
|
||||
function unselectTraces(widget, skip) {
|
||||
if (widget.trace_stack) {
|
||||
widget.trace_stack.meshes.forEach(mesh => {
|
||||
if (mesh.selected) {
|
||||
func.traceToggle(mesh);
|
||||
func.traceToggle(mesh, skip);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
KIRI.loader.push(function(API) {
|
||||
|
||||
if (KIRI.client)
|
||||
CAM.traces = function(ondone) {
|
||||
CAM.traces = function(ondone, single) {
|
||||
KIRI.client.sync();
|
||||
let settings = API.conf.get();
|
||||
let widgets = API.widgets.map();
|
||||
KIRI.client.send("cam_traces", { settings }, output => {
|
||||
KIRI.client.send("cam_traces", { settings, single }, output => {
|
||||
let ids = [];
|
||||
KIRI.codec.decode(output).forEach(rec => {
|
||||
ids.push(rec.id);
|
||||
|
|
@ -41,9 +41,9 @@
|
|||
|
||||
if (KIRI.worker)
|
||||
KIRI.worker.cam_traces = function(data, send) {
|
||||
const { settings } = data;
|
||||
const widgets = Object.values(cache);
|
||||
const fresh = widgets.filter(widget => CAM.traces(settings, widget));
|
||||
const { settings, single } = data;
|
||||
const widgets = Object.values(wcache);
|
||||
const fresh = widgets.filter(widget => CAM.traces(settings, widget, single));
|
||||
send.done(KIRI.codec.encode(fresh.map(widget => { return {
|
||||
id: widget.id,
|
||||
traces: widget.traces,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
gcodes = settings.device || {},
|
||||
tools = settings.tools,
|
||||
space = gcodes.gcodeSpace ? ' ' : '',
|
||||
isRML = device.gcodeFExt.toLowerCase() === 'rml',
|
||||
stripComments = gcodes.gcodeStrip || false,
|
||||
cmdToolChange = gcodes.gcodeChange || [ "M6 T{tool}" ],
|
||||
cmdSpindle = gcodes.gcodeSpindle || [ "M3 S{speed}" ],
|
||||
|
|
@ -88,7 +89,7 @@
|
|||
if (!array) return;
|
||||
for (i=0; i<array.length; i++) {
|
||||
line = print.constReplace(array[i], consts);
|
||||
if (stripComments && (cidx = line.indexOf(";")) >= 0) {
|
||||
if (!isRML && stripComments && (cidx = line.indexOf(";")) >= 0) {
|
||||
line = line.substring(0, cidx).trim();
|
||||
if (line.length === 0) continue;
|
||||
}
|
||||
|
|
@ -179,7 +180,8 @@
|
|||
dz = newpos.z - pos.z,
|
||||
maxf = dz ? maxZd : maxXYd,
|
||||
feed = Math.min(speed || maxf, maxf),
|
||||
dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
dist = Math.sqrt(dx * dx + dy * dy + dz * dz),
|
||||
newFeed = feed && feed !== pos.f;
|
||||
|
||||
// drop dup points (all deltas are 0)
|
||||
if (!(dx || dy || dz)) {
|
||||
|
|
@ -204,11 +206,23 @@
|
|||
runbox.max.z = Math.max(runbox.max.z, pos.z);
|
||||
nl.append(space).append("Z").append(add0(pos.z * factor));
|
||||
}
|
||||
if (feed && feed !== pos.f) {
|
||||
if (newFeed) {
|
||||
pos.f = feed;
|
||||
nl.append(space).append("F").append(add0(feed * factor, true));
|
||||
}
|
||||
|
||||
// temp hack to support RML1 dialect from a file extensions trigger
|
||||
if (isRML) {
|
||||
if (speed) {
|
||||
if (newFeed) {
|
||||
append(`VS${feed};`);
|
||||
}
|
||||
nl = [ "Z", add0(pos.x * factor), ",", add0(pos.y * factor), ",", add0(pos.z * factor), ";" ];
|
||||
} else {
|
||||
nl = [ "PU", add0(pos.x * factor), ",", add0(pos.y * factor), ";" ];
|
||||
}
|
||||
}
|
||||
|
||||
// update time calculation
|
||||
time += (dist / (pos.f || 1000)) * 60;
|
||||
|
||||
|
|
@ -279,7 +293,10 @@
|
|||
if (layerout.spindle && layerout.spindle !== spindle) {
|
||||
spindle = layerout.spindle;
|
||||
if (spindle > 0) {
|
||||
filterEmit(cmdSpindle, {speed: Math.abs(spindle)});
|
||||
let speed = Math.abs(spindle);
|
||||
filterEmit(cmdSpindle, {
|
||||
speed, spindle: speed, rpm: speed
|
||||
});
|
||||
} else {
|
||||
append("M4");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,10 @@
|
|||
let { tshadow, shadowTop, ztOff, zBottom, zMax } = state;
|
||||
let { process, stock } = settings;
|
||||
|
||||
if (op.down <= 0) {
|
||||
throw `invalid step down "${op.down}"`;
|
||||
}
|
||||
|
||||
let roughIn = op.inside;
|
||||
let roughTop = op.top;
|
||||
let roughDown = op.down;
|
||||
|
|
@ -219,7 +223,7 @@
|
|||
});
|
||||
shadow = POLY.nest(shadow);
|
||||
|
||||
// expand shadow by half tool diameter + stock to leave
|
||||
// shell = shadow expanded by half tool diameter + leave stock
|
||||
const sadd = roughIn ? toolDiam / 2 : toolDiam / 2;
|
||||
const shell = POLY.offset(shadow, sadd + roughLeave);
|
||||
|
||||
|
|
@ -262,7 +266,7 @@
|
|||
|
||||
if (!offset) return;
|
||||
|
||||
if (process.camStockClipTo) {
|
||||
if (process.camStockClipTo && stock.x && stock.y && stock.center) {
|
||||
let rect = newPolygon().centerRectangle(stock.center, stock.x, stock.y);
|
||||
offset = cutPolys([rect], offset, slice.z, true);
|
||||
}
|
||||
|
|
@ -270,10 +274,12 @@
|
|||
// elimate double inset on inners
|
||||
offset.forEach(op => {
|
||||
if (op.inner) {
|
||||
let operim = op.perimeter();
|
||||
let pv1 = op.perimeter();
|
||||
let newinner = [];
|
||||
op.inner.forEach(oi => {
|
||||
if (Math.abs(oi.perimeter() - operim) > 0.01) {
|
||||
let pv2 = oi.perimeter();
|
||||
let pct = pv1 > pv2 ? pv2/pv1 : pv1/pv2;
|
||||
if (pct < 0.98) {
|
||||
newinner.push(oi);
|
||||
}
|
||||
});
|
||||
|
|
@ -307,8 +313,10 @@
|
|||
let { polyEmit, poly2polyEmit, depthRoughPath } = ops;
|
||||
let { camOut, newLayer, printPoint } = ops;
|
||||
let { settings, widget } = state;
|
||||
let { process } = settings;
|
||||
let { process, controller } = settings;
|
||||
|
||||
let danger = controller.danger;
|
||||
let easeDown = process.camEaseDown;
|
||||
let cutdir = process.camConventional;
|
||||
let depthFirst = process.camDepthFirst;
|
||||
let depthData = [];
|
||||
|
|
@ -368,7 +376,9 @@
|
|||
// return POLY.nest(level.filter(poly => poly.depth === 0));
|
||||
return POLY.nest(level.filter(poly => poly.depth === 0).clone());
|
||||
});
|
||||
printPoint = depthRoughPath(printPoint, 0, depthData, tops, polyEmit);
|
||||
// experimental start of ease down
|
||||
let ease = danger && op.down && easeDown ? op.down : 0;
|
||||
printPoint = depthRoughPath(printPoint, 0, depthData, tops, polyEmit, false, ease);
|
||||
// printPoint = depthRoughPath(printPoint, 0, depthData, tops, (poly, index, count, start) => {
|
||||
// console.log({z: poly.getZ(), i: poly.id, index, poly});
|
||||
// return polyEmit(poly, index, count, start);
|
||||
|
|
@ -390,6 +400,10 @@
|
|||
let { updateToolDiams, zThru, zBottom, shadowTop, tabs, cutTabs, cutPolys } = state;
|
||||
let { process, stock } = settings;
|
||||
|
||||
if (op.down <= 0) {
|
||||
throw `invalid step down "${op.down}"`;
|
||||
}
|
||||
|
||||
let toolDiam = this.toolDiam = new CAM.Tool(settings, op.tool).fluteDiameter();
|
||||
updateToolDiams(toolDiam);
|
||||
|
||||
|
|
@ -405,7 +419,7 @@
|
|||
indices = indices.appendAll(flats).sort((a,b) => b-a);
|
||||
// console.log('indices', ...indices, {zBottom, slicer});
|
||||
if (op.outside && !op.inside) {
|
||||
console.log({outline_bypass: indices, down: op.down});
|
||||
// console.log({outline_bypass: indices, down: op.down});
|
||||
indices.forEach((ind,i) => {
|
||||
if (flats.indexOf(ind) >= 0) {
|
||||
// exclude flats
|
||||
|
|
@ -509,7 +523,7 @@
|
|||
CAM.addDogbones(offset, toolDiam / 5);
|
||||
}
|
||||
|
||||
if (process.camStockClipTo) {
|
||||
if (process.camStockClipTo && stock.x && stock.y && stock.center) {
|
||||
let rect = newPolygon().centerRectangle(stock.center, stock.x, stock.y);
|
||||
offset = cutPolys([rect], offset, slice.z, true);
|
||||
}
|
||||
|
|
@ -534,8 +548,10 @@
|
|||
let { polyEmit, poly2polyEmit, depthOutlinePath } = ops;
|
||||
let { camOut, newLayer, printPoint } = ops;
|
||||
let { settings, widget } = state;
|
||||
let { process } = settings;
|
||||
let { process, controller } = settings;
|
||||
|
||||
let danger = controller.danger;
|
||||
let easeDown = process.camEaseDown;
|
||||
let toolDiam = this.toolDiam;
|
||||
let cutdir = process.camConventional;
|
||||
let depthFirst = process.camDepthFirst;
|
||||
|
|
@ -584,8 +600,10 @@
|
|||
printPoint = flatLevels[0]
|
||||
.sort((a,b) => { return a.area() - b.area() })[0]
|
||||
.average();
|
||||
printPoint = depthOutlinePath(printPoint, 0, flatLevels, toolDiam, polyEmit, false);
|
||||
printPoint = depthOutlinePath(printPoint, 0, flatLevels, toolDiam, polyEmit, true);
|
||||
// experimental start of ease down
|
||||
let ease = danger && op.down && easeDown ? op.down : 0;
|
||||
printPoint = depthOutlinePath(printPoint, 0, flatLevels, toolDiam, polyEmit, false, ease);
|
||||
printPoint = depthOutlinePath(printPoint, 0, flatLevels, toolDiam, polyEmit, true, ease);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -629,7 +647,8 @@
|
|||
let { settings, widget } = state;
|
||||
let { process } = settings;
|
||||
|
||||
let toolDiam = this.toolDiam;
|
||||
let toolDiam = this.toolDiam = new CAM.Tool(settings, op.tool).fluteDiameter();
|
||||
let stepover = toolDiam * op.step * 2;
|
||||
let cutdir = process.camConventional;
|
||||
let depthFirst = process.camDepthFirst;
|
||||
let depthData = [];
|
||||
|
|
@ -656,7 +675,7 @@
|
|||
poly.reverse();
|
||||
}
|
||||
poly.forEachPoint(function(point, pidx) {
|
||||
camOut(point.clone(), pidx > 0);
|
||||
camOut(point.clone(), pidx > 0, stepover);
|
||||
}, false);
|
||||
});
|
||||
newLayer();
|
||||
|
|
@ -670,7 +689,7 @@
|
|||
poly.reverse();
|
||||
}
|
||||
poly.forEachPoint(function(point, pidx) {
|
||||
camOut(point.clone(), pidx > 0);
|
||||
camOut(point.clone(), pidx > 0, stepover);
|
||||
}, false);
|
||||
newLayer();
|
||||
return lastPoint();
|
||||
|
|
@ -700,7 +719,8 @@
|
|||
let toolOver = toolDiam * op.step;
|
||||
let cutdir = process.camConventional;
|
||||
let polys = [];
|
||||
let stockRect = newPolygon().centerRectangle(stock.center, stock.x, stock.y);
|
||||
let stockRect = stock.center && stock.x && stock.y ?
|
||||
newPolygon().centerRectangle(stock.center, stock.x, stock.y) : undefined;
|
||||
updateToolDiams(toolDiam);
|
||||
if (tabs) {
|
||||
tabs.forEach(tab => {
|
||||
|
|
@ -727,7 +747,7 @@
|
|||
} else {
|
||||
slice.camLines = [ poly ];
|
||||
}
|
||||
if (process.camStockClipTo) {
|
||||
if (process.camStockClipTo && stockRect) {
|
||||
slice.camLines = cutPolys([stockRect], slice.camLines, z, true);
|
||||
}
|
||||
slice.output()
|
||||
|
|
@ -771,19 +791,22 @@
|
|||
case "inside": offdist = -toolDiam / 2; break;
|
||||
}
|
||||
if (offdist) {
|
||||
let pnew = POLY.offset([poly], offdist)[0];
|
||||
let pnew = POLY.offset([poly], offdist);
|
||||
if (pnew) {
|
||||
poly = pnew.setZ(poly.getZ());
|
||||
poly = POLY.setZ(pnew, poly.getZ());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
poly = [ poly ];
|
||||
}
|
||||
for (let pi of poly)
|
||||
if (down) {
|
||||
for (let z of BASE.util.lerp(zMax, poly.getZ(), down)) {
|
||||
followZ(poly.clone().setZ(z));
|
||||
for (let z of BASE.util.lerp(zMax, pi.getZ(), down)) {
|
||||
followZ(pi.clone().setZ(z));
|
||||
}
|
||||
} else {
|
||||
followZ(poly);
|
||||
followZ(pi);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -904,6 +927,7 @@
|
|||
updateToolDiams(tool.fluteDiameter());
|
||||
|
||||
let { stock } = settings,
|
||||
tz = widget.track.pos.z,
|
||||
lx = bounds.min.x,
|
||||
hx = bounds.max.x,
|
||||
ly = bounds.min.y,
|
||||
|
|
@ -915,7 +939,10 @@
|
|||
dx = (stock.x - (hx - lx)) / 4,
|
||||
dy = (stock.y - (hy - ly)) / 4,
|
||||
dz = stock.z,
|
||||
points = [];
|
||||
points = [],
|
||||
wo = stock.z - bounds.max.z,
|
||||
z1 = bounds.max.z + wo + tz,
|
||||
z2 = tz - mz;
|
||||
|
||||
if (!(stock.x && stock.y && stock.z)) {
|
||||
return;
|
||||
|
|
@ -969,7 +996,7 @@
|
|||
tv = -tv;
|
||||
}
|
||||
}
|
||||
for (let z of BASE.util.lerp(zMax, -zThru, op.down)) {
|
||||
for (let z of BASE.util.lerp(z1, z2, op.down)) {
|
||||
let slice = newSlice(z);
|
||||
sliceAll.push(slice);
|
||||
sliceOut.push(slice);
|
||||
|
|
@ -1005,8 +1032,8 @@
|
|||
let slice = newSlice(0,null), polys = [];
|
||||
points.forEach(point => {
|
||||
polys.push(newPolygon()
|
||||
.append(point.clone().setZ(bounds.max.z))
|
||||
.append(point.clone().setZ(bounds.max.z - stock.z - mz)));
|
||||
.append(point.clone().setZ(z1))
|
||||
.append(point.clone().setZ(z2)));
|
||||
});
|
||||
slice.camLines = polys;
|
||||
slice.output()
|
||||
|
|
@ -1096,7 +1123,7 @@
|
|||
let terrain = slicer.slice(tzindex, { each: (data, index, total) => {
|
||||
tshadow = POLY.union(tshadow.slice().appendAll(data.tops), 0.01, true);
|
||||
tslices.push(data.slice);
|
||||
if (true) {
|
||||
if (false) {
|
||||
const slice = data.slice;
|
||||
sliceAll.push(slice);
|
||||
slice.output()
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
boundsz = bounds.max.z + ztOff,
|
||||
zadd = hasStock ? stock.z - boundsz : alignTop ? outerz - boundsz : 0,
|
||||
zmax = outerz + zclear,
|
||||
wmpos = widget.mesh.position,
|
||||
wmpos = widget.track.pos,
|
||||
wmx = wmpos.x,
|
||||
wmy = wmpos.y,
|
||||
originx = startCenter ? 0 : hasStock ? -stock.x / 2 : bounds.min.x,
|
||||
|
|
@ -231,7 +231,7 @@
|
|||
);
|
||||
}
|
||||
|
||||
function camOut(point, cut) {
|
||||
function camOut(point, cut, moveLen = toolDiamMove) {
|
||||
point = point.clone();
|
||||
point.x += wmx;
|
||||
point.y += wmy;
|
||||
|
|
@ -264,7 +264,7 @@
|
|||
}
|
||||
|
||||
// convert short planar moves to cuts in some cases
|
||||
if (isMove && deltaXY <= toolDiamMove) {
|
||||
if (isMove && deltaXY <= moveLen) {
|
||||
let iscontour = tolerance > 0;
|
||||
let isflat = absDeltaZ < 0.001;
|
||||
// restrict this to contouring
|
||||
|
|
@ -279,7 +279,7 @@
|
|||
}
|
||||
} else if (isMove) {
|
||||
// for longer moves, check the terrain to see if we need to go up and over
|
||||
const bigXY = (deltaXY > toolDiamMove);
|
||||
const bigXY = (deltaXY > moveLen);
|
||||
const bigZ = (deltaZ > toolDiam/2 && deltaXY > tolerance);
|
||||
const midZ = (absDeltaZ >= tolerance);
|
||||
if ((bigXY || bigZ) && (isMove || midZ)) {
|
||||
|
|
@ -296,11 +296,8 @@
|
|||
) + ztOff,
|
||||
mustGoUp = Math.max(maxz - point.z, maxz - lastPoint.z) >= tolerance,
|
||||
clearz = maxz;
|
||||
// up if any point between higher than start/outline, go up
|
||||
// up if any point between higher than start/outline, go up first
|
||||
if (mustGoUp) {
|
||||
if (bigXY) {
|
||||
clearz += zclear;
|
||||
}
|
||||
layerPush(lastPoint.clone().setZ(clearz), 0, 0, tool.getNumber());
|
||||
}
|
||||
// move to point above target point
|
||||
|
|
@ -414,7 +411,7 @@
|
|||
return last;
|
||||
}
|
||||
|
||||
function depthRoughPath(start, depth, levels, tops, emitter, fit) {
|
||||
function depthRoughPath(start, depth, levels, tops, emitter, fit, ease) {
|
||||
let level = levels[depth];
|
||||
if (!level) {
|
||||
return start;
|
||||
|
|
@ -424,13 +421,19 @@
|
|||
fitted.filter(top => !top.level_emit).forEach(top => {
|
||||
top.level_emit = true;
|
||||
let inside = level.filter(poly => poly.isInside(top));
|
||||
if (ease) {
|
||||
start.z += ease;
|
||||
}
|
||||
start = poly2polyEmit(inside, start, emitter, { mark: "emark", perm: true });
|
||||
start = depthRoughPath(start, depth + 1, levels, tops, emitter, top);
|
||||
if (ease) {
|
||||
start.z += ease;
|
||||
}
|
||||
start = depthRoughPath(start, depth + 1, levels, tops, emitter, top, ease);
|
||||
});
|
||||
return start;
|
||||
}
|
||||
|
||||
function depthOutlinePath(start, depth, levels, radius, emitter, clr) {
|
||||
function depthOutlinePath(start, depth, levels, radius, emitter, clr, ease) {
|
||||
let bottm = depth < levels.length - 1 ? levels[levels.length - 1] : null;
|
||||
let above = levels[depth-1];
|
||||
let level = levels[depth];
|
||||
|
|
@ -458,8 +461,14 @@
|
|||
// omit polys that match bottom level polys unless level above is cleared
|
||||
start = poly2polyEmit(level, start, (poly, index, count, fromPoint) => {
|
||||
poly.level_emit = true;
|
||||
if (ease) {
|
||||
fromPoint.z += ease;
|
||||
}
|
||||
fromPoint = polyEmit(poly, index, count, fromPoint);
|
||||
fromPoint = depthOutlinePath(fromPoint, depth + 1, levels, radius, emitter, clr);
|
||||
if (ease) {
|
||||
fromPoint.z += ease;
|
||||
}
|
||||
fromPoint = depthOutlinePath(fromPoint, depth + 1, levels, radius, emitter, clr, ease);
|
||||
return fromPoint;
|
||||
}, {weight: true});
|
||||
return start;
|
||||
|
|
@ -479,8 +488,9 @@
|
|||
* return tool Z clearance height for a line segment movement path
|
||||
*/
|
||||
function getZClearPath(terrain, x1, y1, x2, y2, z, zadd, off, over) {
|
||||
// when terrain skipped, top + pass used
|
||||
if (terrain > 0) {
|
||||
return terrain + zadd + over;
|
||||
return terrain;
|
||||
}
|
||||
let maxz = z;
|
||||
let check = [];
|
||||
|
|
|
|||
|
|
@ -221,8 +221,8 @@
|
|||
}
|
||||
};
|
||||
|
||||
CAM.traces = function(settings, widget) {
|
||||
if (widget.traces) {
|
||||
CAM.traces = function(settings, widget, single) {
|
||||
if (widget.traces && widget.trace_single === single) {
|
||||
// do no work if cached
|
||||
return false;
|
||||
}
|
||||
|
|
@ -242,6 +242,13 @@
|
|||
let traces = [];
|
||||
// find and trim polys (including open) to shadow
|
||||
let oneach = (data, index, total) => {
|
||||
if (single) {
|
||||
for (let line of data.lines) {
|
||||
if (line.p1.distTo2D(line.p2) > 1) {
|
||||
traces.push(newPolygon().append(line.p1).append(line.p2).setOpen());
|
||||
}
|
||||
}
|
||||
} else
|
||||
BASE.polygons.flatten(data.tops,null,true).forEach(poly => {
|
||||
poly.inner = null;
|
||||
poly.parent = null;
|
||||
|
|
@ -265,6 +272,7 @@
|
|||
opts.over = true;
|
||||
slicer.slice(indices, opts);
|
||||
widget.traces = traces;
|
||||
widget.trace_single = single;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -154,8 +154,8 @@
|
|||
if (curvesOnly && lastP) {
|
||||
// maxangle
|
||||
const dz = Math.abs(lastP.z - z);
|
||||
const dxy = Math.max(Math.abs(lastP.x - x), Math.abs(lastP.y - y));
|
||||
const angle = Math.atan2(dz, dxy) * RAD2DEG;
|
||||
const dv = contourX ? Math.abs(lastP.x - x) : Math.abs(lastP.y - y);
|
||||
const angle = Math.atan2(dz, dv) * RAD2DEG;
|
||||
// if (lastP.z < 0.1) console.log('pp', {dz, dxy, angle});
|
||||
if (angle > maxangle) {
|
||||
lastP = newP;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@
|
|||
BASE = self.base,
|
||||
UTIL = BASE.util,
|
||||
FDM = KIRI.driver.FDM,
|
||||
SPACE, API,
|
||||
SPACE, API, VIEWS, LANG, PROC, UI, UC,
|
||||
nextID = Date.now(),
|
||||
p1, p2, iw,
|
||||
lastMode, lastView, lastPillar,
|
||||
lastBox,
|
||||
lastMode, lastView,
|
||||
lastPillar, fromPillar,
|
||||
isFdmMode = false,
|
||||
addingSupports = false,
|
||||
alert = [],
|
||||
|
|
@ -18,8 +21,133 @@
|
|||
func = {};
|
||||
|
||||
FDM.init = function(kiri, api) {
|
||||
UI = api.ui;
|
||||
UC = api.uc;
|
||||
API = api;
|
||||
SPACE = api.const.SPACE;
|
||||
VIEWS = api.const.VIEWS;
|
||||
LANG = KIRI.lang.current;
|
||||
PROC = Object.keys(kiri.conf.defaults.fdm.p);
|
||||
|
||||
let rangeVars = {
|
||||
// slice
|
||||
"sliceShells": LANG.sl_shel_s,
|
||||
"sliceFillType": LANG.fi_type,
|
||||
"sliceFillWidth": LANG.fi_wdth_s,
|
||||
"sliceFillSparse": LANG.fi_pcnt_s,
|
||||
"sliceSolidMinArea": LANG.ad_msol_s,
|
||||
// prepare
|
||||
"sliceShellOrder": LANG.sl_ordr_s,
|
||||
"sliceFillOverlap": LANG.fi_over_s,
|
||||
"outputFeedrate": LANG.ou_feed_s,
|
||||
"outputFinishrate": LANG.ou_fini_s,
|
||||
"outputShellMult": LANG.ou_shml_s,
|
||||
"outputFillMult": LANG.ou_flml_s,
|
||||
"outputSparseMult": LANG.ou_spml_s,
|
||||
"outputRetractWipe": LANG.ad_wpln_s,
|
||||
"outputShortPoly": LANG.ad_spol_s,
|
||||
"outputMinSpeed": LANG.ad_mins_s,
|
||||
"outputCoastDist": LANG.ad_scst_s,
|
||||
"sliceSupportDensity": LANG.sp_dens_s,
|
||||
"sliceSupportOffset": LANG.sp_offs_s,
|
||||
"sliceLayerStart": LANG.sl_strt_s,
|
||||
// export
|
||||
"zHopDistance": LANG.ad_zhop_s,
|
||||
"arcTolerance": LANG.ad_zhop_s,
|
||||
"antiBacklash": LANG.ad_abkl_s,
|
||||
"outputTemp": LANG.ou_nozl_s,
|
||||
"outputBedTemp": LANG.ou_bedd_s,
|
||||
"outputFanSpeed": LANG.ou_fans_s,
|
||||
"outputRetractDist": LANG.ad_rdst_s,
|
||||
"outputRetractSpeed": LANG.outputRetractSpeed,
|
||||
"outputRetractDwell": LANG.ad_rdwl_s,
|
||||
};
|
||||
|
||||
for (let key of Object.keys(rangeVars)) {
|
||||
if (UI[key]) {
|
||||
UI[key].range = true;
|
||||
}
|
||||
}
|
||||
|
||||
function filterSynth() {
|
||||
api.widgets.filter((widget) => {
|
||||
if (widget.track.synth) {
|
||||
api.const.SPACE.platform.remove(widget.mesh);
|
||||
kiri.Widget.Groups.remove(widget);
|
||||
}
|
||||
return !widget.track.synth
|
||||
});
|
||||
}
|
||||
|
||||
function updateRanges(ranges = []) {
|
||||
UI.rangeGroup.style.display = isFdmMode && ranges && ranges.length ? 'flex' : 'none';
|
||||
let html = [];
|
||||
let bind = [];
|
||||
let now = Date.now();
|
||||
let sorted = ranges.sort((a,b) => b.lo - a.lo);
|
||||
for (let range of sorted) {
|
||||
let id = (now++).toString(36);
|
||||
let rows = Object.entries(range.fields).map(a => `<div><label class="pad">${rangeVars[a[0]]}</label><span></span><label class="val">${a[1]}</label></div>`).join('');
|
||||
let hover = `<div id="hov_${id}" class="range-detail">${rows}</div>`;
|
||||
let info = `<button id="sel_${id}" class="j-center grow">${range.lo} - ${range.hi}</button><button id="del_${id}"><i class="far fa-trash-alt"></i></button>`;
|
||||
html.appendAll([
|
||||
`<div id="rng_${id}" class="range-info">${hover}${info}</div>`
|
||||
]);
|
||||
bind.push({id, range});
|
||||
}
|
||||
UI.rangeGroup.firstElementChild.innerHTML = html.join('');
|
||||
for (let rec of bind) {
|
||||
$(`sel_${rec.id}`).onclick = () => {
|
||||
api.show.layer(rec.range.hi, rec.range.lo);
|
||||
};
|
||||
$(`del_${rec.id}`).onclick = () => {
|
||||
let io = ranges.indexOf(rec.range);
|
||||
ranges.splice(io,1);
|
||||
updateRanges(ranges);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
api.event.on("boolean.click", func.updateSupportButtons = () => {
|
||||
if (!isFdmMode) {
|
||||
return;
|
||||
}
|
||||
for (let btn of [
|
||||
UI.ssaGen,
|
||||
UI.ssmAdd,
|
||||
UI.ssmDun,
|
||||
UI.ssmClr
|
||||
]) {
|
||||
btn.disabled = UI.sliceSupportEnable.checked;
|
||||
}
|
||||
if (UI.sliceSupportEnable.checked) {
|
||||
func.sclear();
|
||||
}
|
||||
});
|
||||
|
||||
api.event.on("function.animate", (mode) => {
|
||||
if (!isFdmMode) {
|
||||
return;
|
||||
}
|
||||
if (!API.conf.get().controller.danger) {
|
||||
return;
|
||||
}
|
||||
let pct = 0;
|
||||
let int = setInterval(function() {
|
||||
if (pct <= 1) {
|
||||
api.const.STACKS.setFraction(pct);
|
||||
pct += 0.05;
|
||||
} else {
|
||||
api.const.STACKS.setFraction(1);
|
||||
clearTimeout(int);
|
||||
}
|
||||
}, 50);
|
||||
// let slider = $('top-slider');
|
||||
// slider.style.display = 'flex';
|
||||
// slider.oninput = slider.onchange = (ev) => {
|
||||
// api.const.STACKS.setFraction(parseInt(ev.target.value)/100);
|
||||
// };
|
||||
});
|
||||
api.event.on("mode.set", mode => {
|
||||
isFdmMode = mode === 'FDM';
|
||||
lastMode = mode;
|
||||
|
|
@ -28,14 +156,36 @@
|
|||
api.event.on("view.set", view => {
|
||||
lastView = view;
|
||||
updateVisiblity();
|
||||
filterSynth();
|
||||
func.sdone();
|
||||
// let ranges = API.conf.get().process.ranges;
|
||||
if (isFdmMode) {
|
||||
if (lastView === VIEWS.SLICE) {
|
||||
for (let key of PROC) {
|
||||
if (UI[key] && !UI[key].range) {
|
||||
UI[key].disabled = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let key of PROC) {
|
||||
if (UI[key]) UI[key].disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// UI.rangeGroup.style.display = ranges && ranges.length ? 'flex' : 'none';
|
||||
});
|
||||
api.event.on("range.updates", updateRanges);
|
||||
api.event.on("settings.load", (settings) => {
|
||||
if (settings.mode !== 'FDM') return;
|
||||
settings.process.outputOriginCenter = (settings.device.originCenter || false);
|
||||
restoreSupports(api.widgets.all());
|
||||
updateRanges(settings.process.ranges);
|
||||
});
|
||||
api.event.on("settings.saved", (settings) => {
|
||||
api.ui.fdmSupport.style.display = lastMode !== 'FDM' || settings.device.bedBelt ? 'none' : 'flex';
|
||||
updateRanges(settings.process.ranges);
|
||||
func.updateSupportButtons();
|
||||
// let ranges = settings.process.ranges;
|
||||
// UI.rangeGroup.style.display = isFdmMode && ranges && ranges.length ? 'flex' : 'none';
|
||||
});
|
||||
api.event.on("button.click", target => {
|
||||
switch (target) {
|
||||
|
|
@ -43,9 +193,10 @@
|
|||
case api.ui.ssmAdd: return func.sadd();
|
||||
case api.ui.ssmDun: return func.sdone();
|
||||
case api.ui.ssmClr:
|
||||
return api.uc.confirm("clear supports?").then(ok => {
|
||||
if (ok) func.sclear();
|
||||
});
|
||||
// return api.uc.confirm("clear supports?").then(ok => {
|
||||
// if (ok) func.sclear();
|
||||
// });
|
||||
func.sclear();
|
||||
}
|
||||
});
|
||||
api.event.on("fdm.supports.detect", func.sgen = () => {
|
||||
|
|
@ -86,11 +237,13 @@
|
|||
delbox('supp');
|
||||
api.hide.alert(alert);
|
||||
api.feature.hover = addingSupports = false;
|
||||
fromPillar = undefined;
|
||||
});
|
||||
api.event.on("fdm.supports.clear", func.sclear = () => {
|
||||
func.sdone();
|
||||
clearAllWidgetSupports();
|
||||
API.conf.save();
|
||||
if (clearAllWidgetSupports()) {
|
||||
API.conf.save();
|
||||
}
|
||||
});
|
||||
api.event.on("slice.begin", () => {
|
||||
if (!isFdmMode) {
|
||||
|
|
@ -98,6 +251,37 @@
|
|||
}
|
||||
func.sdone();
|
||||
updateVisiblity();
|
||||
|
||||
// synth support widget for each widget group
|
||||
let synth = [];
|
||||
for (let group of kiri.Widget.Groups.list()) {
|
||||
let merge = group.filter(w => w.sups).map(w => Object.values(w.sups)).flat();
|
||||
if (!merge.length) {
|
||||
continue;
|
||||
}
|
||||
let boxen = merge.map(m => {
|
||||
let geo = m.box.geometry.clone();
|
||||
if (geo.index) geo = geo.toNonIndexed();
|
||||
return geo.translate(m.x, m.y, m.z);
|
||||
});
|
||||
for (let box of boxen) {
|
||||
// eliminate / normalize uv to allow other widget merge
|
||||
box.setAttribute('uv',new THREE.BufferAttribute(new Float32Array(0), 3));
|
||||
}
|
||||
let bbg = THREE.BufferGeometryUtils.mergeBufferGeometries(boxen);
|
||||
let sw = kiri.newWidget(null, group);
|
||||
let fwp = group[0].track.pos;
|
||||
sw.loadGeometry(bbg);
|
||||
sw._move(fwp.x, fwp.y, fwp.z);
|
||||
api.widgets.add(sw);
|
||||
sw.track.synth = true;
|
||||
api.const.SPACE.platform.add(sw.mesh);
|
||||
}
|
||||
});
|
||||
api.event.on("slice.end", () => {
|
||||
if (!isFdmMode) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
api.event.on("key.esc", () => {
|
||||
if (!isFdmMode) {
|
||||
|
|
@ -132,8 +316,8 @@
|
|||
});
|
||||
}
|
||||
});
|
||||
api.event.on("mouse.hover.up", on => {
|
||||
let { object, event } = on;
|
||||
api.event.on("mouse.hover.up", func.hoverup = (on = {}) => {
|
||||
let { event } = on;
|
||||
if (!isFdmMode) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -142,34 +326,77 @@
|
|||
}
|
||||
delbox('supp');
|
||||
if (lastPillar) {
|
||||
const {widget, box, id} = lastPillar;
|
||||
widget.adds.remove(box);
|
||||
widget.mesh.remove(box);
|
||||
delete widget.sups[id];
|
||||
let sa = API.widgets.annotate(widget.id).support;
|
||||
let ix = 0;
|
||||
sa.forEach((rec,i) => {
|
||||
if (rec.id === id) {
|
||||
ix = i;
|
||||
}
|
||||
});
|
||||
sa.splice(ix,1);
|
||||
API.conf.save();
|
||||
removeWidgetSupport(lastPillar.widget, lastPillar);
|
||||
return;
|
||||
}
|
||||
if (!iw) return;
|
||||
let hy = (p1.y + p2.y) / 2;
|
||||
let dh = Math.abs(p1.y - p2.y);
|
||||
let { point, dim } = lastBox;
|
||||
p1.y = Math.max(0, p1.y);
|
||||
p2.y = Math.max(0, p2.y);
|
||||
let rz = dim.rz;
|
||||
let dh = dim.z;
|
||||
let dw = api.conf.get().process.sliceSupportSize / 2;
|
||||
let ip = iw.track.pos;
|
||||
let wa = api.widgets.annotate(iw.id);
|
||||
let ws = (wa.support = wa.support || []);
|
||||
let x = p1.x - ip.x, y = -p1.z - ip.y, z = hy, id = Date.now();
|
||||
let rec = {x, y, z, dw, dh, id};
|
||||
let id = ++nextID;
|
||||
let rec = {x: point.x - ip.x, y: -point.z - ip.y, z: point.y, rz, dw, dh, id};
|
||||
if (fromPillar && event && event.shiftKey) {
|
||||
let targets = api.widgets.meshes().append(SPACE.internals().platform);
|
||||
let from = fromPillar,
|
||||
d = {
|
||||
x: rec.x - from.x,
|
||||
y: rec.y - from.y,
|
||||
z: rec.z - from.z
|
||||
};
|
||||
let dist = Math.sqrt(d.x*d.x + d.y*d.y + d.z*d.z);
|
||||
let lerp = UTIL.lerp(0,dist,dw).map(v => v/dist);
|
||||
let angle = rec.rz = Math.atan2(d.y,d.x);
|
||||
let fromrec = ws.filter(r => r.id === from.id)[0];
|
||||
if (fromrec) {
|
||||
from.rz = fromrec.rz = angle;
|
||||
removeWidgetSupport(iw, fromPillar);
|
||||
ws.push(Object.clone(fromrec));
|
||||
addWidgetSupport(iw, fromrec);
|
||||
}
|
||||
lerp.pop();
|
||||
let seed = Math.random();
|
||||
for (let pct of lerp) {
|
||||
let point = new THREE.Vector3(from.x + d.x * pct, from.z + d.z * pct, from.y + d.y * pct);
|
||||
addSupportAtPoint(targets, point, ip, angle, seed++);
|
||||
}
|
||||
}
|
||||
ws.push(Object.clone(rec));
|
||||
addWidgetSupport(iw, rec);
|
||||
fromPillar = addWidgetSupport(iw, rec);
|
||||
API.conf.save();
|
||||
});
|
||||
function addSupportAtPoint(targets, point, ip, angle, id) {
|
||||
let up = new THREE.Vector3(0,1,0)
|
||||
let dn = new THREE.Vector3(0,-1,0)
|
||||
let rp = new THREE.Vector3(point.x + ip.x, point.y, -point.z - ip.y);
|
||||
let iup = new THREE.Raycaster(rp, up)
|
||||
.intersectObjects(targets, false)
|
||||
.filter(t => !t.object.pillar);
|
||||
if (iup.length && iup.length % 2 === 0) {
|
||||
let idn = new THREE.Raycaster(rp, dn)
|
||||
.intersectObjects(targets, false)
|
||||
.filter(t => !t.object.pillar);
|
||||
if (idn.length && idn.length % 2 === 0) {
|
||||
iw = iup[0].object.widget || iw;
|
||||
let wa = api.widgets.annotate(iw.id);
|
||||
let ws = (wa.support = wa.support || []);
|
||||
let phi = iup[0].point;
|
||||
let plo = idn[0].point;
|
||||
let ply = Math.max(0, plo.y);
|
||||
let mp = (phi.y + ply) / 2;
|
||||
let dy = Math.abs(phi.y - ply);
|
||||
let dw = api.conf.get().process.sliceSupportSize / 2;
|
||||
let rec = { rz:angle, x:point.x, y:point.z, z:mp, dw, dh:dy, id };
|
||||
ws.push(Object.clone(rec));
|
||||
fromPillar = addWidgetSupport(iw, rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
api.event.on("mouse.hover", data => {
|
||||
if (!isFdmMode) {
|
||||
return;
|
||||
|
|
@ -177,11 +404,8 @@
|
|||
if (!addingSupports) {
|
||||
return;
|
||||
}
|
||||
// delbox('intZ');
|
||||
// delbox('intW');
|
||||
// addbox(point, 0xff0000, 'intZ');
|
||||
delbox('supp');
|
||||
const { int, type, point } = data;
|
||||
const { int, type, point, event } = data;
|
||||
const pillar = int ? int.object.pillar : undefined;
|
||||
if (lastPillar) {
|
||||
lastPillar.box.material.color.r = 0;
|
||||
|
|
@ -190,6 +414,9 @@
|
|||
if (pillar) {
|
||||
pillar.box.material.color.r = 0.5;
|
||||
lastPillar = pillar;
|
||||
if (event && (event.metaKey || event.ctrlKey)) {
|
||||
return func.hoverup();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (int && type === 'widget') {
|
||||
|
|
@ -200,30 +427,29 @@
|
|||
p1 = point;
|
||||
let dir = new THREE.Vector3(0,1,0)
|
||||
let ray = new THREE.Raycaster(point, dir);
|
||||
let rz = int && int.face ? Math.atan2(int.face.normal.y, int.face.normal.x) : 0;
|
||||
// when on object, project down on downward faces
|
||||
if (int && int.face && int.face.normal.z < -0.1) {
|
||||
dir.y = -1;
|
||||
}
|
||||
let targets = api.widgets.meshes()
|
||||
.append(SPACE.internals().platform)
|
||||
.appendAll(activeSupports())
|
||||
;
|
||||
let i2 = ray.intersectObjects(targets, false);
|
||||
if (i2 && i2.length > 0) {
|
||||
// prevent false matches close to origin of ray
|
||||
i2 = i2.filter(i => i.distance > 0.01);
|
||||
// prevent single point base to top matches
|
||||
if (i2.length > 1) {
|
||||
p2 = i2[0].point;
|
||||
iw = i2[0].object.widget || iw;
|
||||
let hy = (p1.y + p2.y) / 2;
|
||||
let dy = Math.abs(p1.y - p2.y);
|
||||
let dw = api.conf.get().process.sliceSupportSize / 2;
|
||||
// addbox(p2, 0x00ff00, 'intW');
|
||||
addbox({x:p1.x, y:hy, z:p1.z}, 0x0000dd, 'supp', {
|
||||
x:dw, y:dw, z:dy
|
||||
});
|
||||
}
|
||||
let targets = api.widgets.meshes().append(SPACE.internals().platform);
|
||||
let i2 = ray.intersectObjects(targets, false)
|
||||
.filter(t => !t.object.pillar) // eliminate other pillars
|
||||
.filter(i => i.distance > 0.1); // false matches close to origin of ray
|
||||
if (i2.length && i2.length % 2 === 0) {
|
||||
p2 = i2[0].point;
|
||||
iw = i2[0].object.widget || iw;
|
||||
let p1y = Math.max(0, p1.y);
|
||||
let p2y = Math.max(0, p2.y);
|
||||
let hy = (p1y + p2y) / 2;
|
||||
let dy = Math.abs(p1y - p2y);
|
||||
let dw = api.conf.get().process.sliceSupportSize / 2;
|
||||
addbox({x:p1.x, y:hy, z:p1.z}, 0x0000dd, 'supp', {
|
||||
x:dw, y:dw, z:dy, rz
|
||||
});
|
||||
}
|
||||
if (event && event.altKey) {
|
||||
return func.hoverup();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -234,7 +460,6 @@
|
|||
Object.values(widget.sups || {}).forEach(support => {
|
||||
active.push(support.box);
|
||||
support.box.support = true;
|
||||
// console.log({support});
|
||||
});
|
||||
});
|
||||
return active;
|
||||
|
|
@ -250,23 +475,41 @@
|
|||
}
|
||||
|
||||
function addWidgetSupport(widget, pos) {
|
||||
const { x, y, z, dw, dh, id } = pos;
|
||||
const { x, y, z, rz, dw, dh, id } = pos;
|
||||
const sups = widget.sups = (widget.sups || {});
|
||||
// prevent duplicate restore from repeated settings load calls
|
||||
if (!sups[id]) {
|
||||
pos.box = addbox(
|
||||
{ x, y, z }, 0x0000dd, id,
|
||||
{ x:dw, y:dw, z:dh }, { group: widget.mesh }
|
||||
{ x:dw, y:dw, z:dh, rz }, { group: widget.mesh }
|
||||
);
|
||||
pos.box.pillar = Object.assign({widget}, pos);
|
||||
sups[id] = pos;
|
||||
widget.adds.push(pos.box);
|
||||
}
|
||||
return sups[id];
|
||||
}
|
||||
|
||||
function removeWidgetSupport(widget, rec) {
|
||||
const {box, id} = rec;
|
||||
widget.adds.remove(box);
|
||||
widget.mesh.remove(box);
|
||||
delete widget.sups[id];
|
||||
let sa = API.widgets.annotate(widget.id).support;
|
||||
let ix = 0;
|
||||
sa.forEach((rec,i) => {
|
||||
if (rec.id === id) {
|
||||
ix = i;
|
||||
}
|
||||
});
|
||||
sa.splice(ix,1);
|
||||
API.conf.save();
|
||||
fromPillar = undefined;
|
||||
}
|
||||
|
||||
function updateVisiblity() {
|
||||
API.widgets.all().forEach(w => {
|
||||
setSupportVisiblity(w, lastMode === 'FDM' && lastView === API.const.VIEWS.ARRANGE);
|
||||
setSupportVisiblity(w, lastMode === 'FDM' && lastView === VIEWS.ARRANGE);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -277,18 +520,23 @@
|
|||
}
|
||||
|
||||
function clearAllWidgetSupports() {
|
||||
let cleared = 0;
|
||||
API.widgets.all().forEach(widget => {
|
||||
clearWidgetSupports(widget);
|
||||
cleared += clearWidgetSupports(widget);
|
||||
});
|
||||
return cleared;
|
||||
}
|
||||
|
||||
function clearWidgetSupports(widget) {
|
||||
let cleared = 0;
|
||||
Object.values(widget.sups || {}).forEach(support => {
|
||||
widget.adds.remove(support.box);
|
||||
widget.mesh.remove(support.box);
|
||||
cleared++;
|
||||
});
|
||||
widget.sups = {};
|
||||
delete API.widgets.annotate(widget.id).support;
|
||||
return cleared;
|
||||
}
|
||||
|
||||
function delbox(name) {
|
||||
|
|
@ -298,7 +546,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function addbox(point, color, name, dim = {x:1,y:1,z:1}, opt = {}) {
|
||||
function addbox(point, color, name, dim = {x:1,y:1,z:1,rz:0}, opt = {}) {
|
||||
delbox(name);
|
||||
const box = boxes[name] = new THREE.Mesh(
|
||||
new THREE.BoxGeometry(dim.x, dim.y, dim.z),
|
||||
|
|
@ -312,10 +560,15 @@
|
|||
box.position.y = point.y;
|
||||
box.position.z = point.z;
|
||||
|
||||
lastBox = {point, dim};
|
||||
|
||||
const group = opt.group || SPACE.scene
|
||||
group.add(box);
|
||||
box.groupTo = group;
|
||||
|
||||
if (dim.rz) {
|
||||
opt.rotate = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), dim.rz);
|
||||
}
|
||||
if (opt.rotate) {
|
||||
opt.matrix = new THREE.Matrix4().makeRotationFromQuaternion(opt.rotate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
// slice, // src/mode/fdm/slice.js
|
||||
// prepare, // src/mode/fdm/prepare.js
|
||||
// export, // src/mode/fdm/export.js
|
||||
getRangeParameters,
|
||||
fixExtruders
|
||||
};
|
||||
|
||||
|
|
@ -28,10 +29,25 @@
|
|||
return settings;
|
||||
}
|
||||
|
||||
// customer gcode post function for XYZ daVinci Mini W
|
||||
self.kiri_fdm_xyz_mini_w = function(gcode, options) {
|
||||
return btoa("; filename = kirimoto.gcode\n; machine = dv1MW0A000\n" + gcode);
|
||||
};
|
||||
function getRangeParameters(settings, index) {
|
||||
if (index === undefined || index === null || index < 0) {
|
||||
return settings.process;
|
||||
}
|
||||
let ranges = settings.process.ranges;
|
||||
if (!(ranges && ranges.length)) {
|
||||
return settings.process;
|
||||
}
|
||||
let params = Object.clone(settings.process);
|
||||
for (let range of ranges) {
|
||||
if (index >= range.lo && index <= range.hi) {
|
||||
for (let [key,value] of Object.entries(range.fields)) {
|
||||
params[key] = value;
|
||||
params._range = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
// defer loading until KIRI.client and KIRI.worker exist
|
||||
KIRI.loader.push(function(API) {
|
||||
|
|
@ -39,6 +55,7 @@
|
|||
if (KIRI.client)
|
||||
// FDM.support_generate = KIRI.client.fdm_support_generate = function(ondone) {
|
||||
FDM.support_generate = function(ondone) {
|
||||
KIRI.client.clear();
|
||||
KIRI.client.sync();
|
||||
let settings = API.conf.get();
|
||||
let widgets = API.widgets.map();
|
||||
|
|
@ -51,7 +68,7 @@
|
|||
if (KIRI.worker)
|
||||
KIRI.worker.fdm_support_generate = function(data, send) {
|
||||
const { settings } = data;
|
||||
const widgets = Object.values(cache);
|
||||
const widgets = Object.values(wcache);
|
||||
const fresh = widgets.filter(widget => FDM.supports(settings, widget));
|
||||
send.done(KIRI.codec.encode(fresh.map(widget => { return {
|
||||
id: widget.id,
|
||||
|
|
|
|||
|
|
@ -15,25 +15,28 @@
|
|||
FDM.export = function(print, online) {
|
||||
let layers = print.output,
|
||||
settings = FDM.fixExtruders(print.settings),
|
||||
getRangeParameters = FDM.getRangeParameters,
|
||||
device = settings.device,
|
||||
extruders = device.extruders,
|
||||
process = settings.process,
|
||||
gcodeFan = device.gcodeFan,
|
||||
gcodeLayer = device.gcodeLayer,
|
||||
gcodeTrack = device.gcodeTrack,
|
||||
tool = 0,
|
||||
fwRetract = device.fwRetract,
|
||||
isDanger = settings.controller.danger,
|
||||
isBelt = device.bedBelt,
|
||||
bedType = isBelt ? "belt" : "fixed",
|
||||
extruder = extruders[tool],
|
||||
offset_x = extruder.extOffsetX,
|
||||
offset_y = extruder.extOffsetY,
|
||||
extrudeAbs = device.extrudeAbs,
|
||||
extrudeAbs = device.extrudeAbs || false,
|
||||
extrudeSet = false,
|
||||
time = 0,
|
||||
layer = 0,
|
||||
pause = [],
|
||||
pauseCmd = device.gcodePause,
|
||||
output = [],
|
||||
outputLength = 0,
|
||||
outputLength = 0, // absolute extruder position
|
||||
lastProgress = 0,
|
||||
decimals = BASE.config.gcode_decimals || 4,
|
||||
progress = 0,
|
||||
|
|
@ -44,26 +47,39 @@
|
|||
lout = null,
|
||||
last = null,
|
||||
zpos = 0,
|
||||
zhop = process.zHopDistance || 0,
|
||||
bmax = 0,
|
||||
blast = 0,
|
||||
blastz = 0,
|
||||
process = settings.process,
|
||||
loops = process.outputLoopLayers,
|
||||
zhop = process.zHopDistance || 0, // range
|
||||
seekMMM = process.outputSeekrate * 60,
|
||||
retDist = process.outputRetractDist,
|
||||
retSpeed = process.outputRetractSpeed * 60,
|
||||
retDwell = process.outputRetractDwell || 0,
|
||||
retDist = process.outputRetractDist || 0, // range
|
||||
retSpeed = process.outputRetractSpeed * 60, // range
|
||||
retDwell = process.outputRetractDwell || 0, // range
|
||||
timeDwell = retDwell / 1000,
|
||||
peelGuard = process.outputPeelGuard || 0,
|
||||
arcDist = isBelt || !isDanger ? 0 : (process.arcTolerance || 0),
|
||||
originCenter = process.outputOriginCenter,
|
||||
offset = originCenter ? null : {
|
||||
x: device.bedWidth/2,
|
||||
y: isBelt ? 0 : device.bedDepth/2
|
||||
},
|
||||
nozzleTemp = process.firstLayerNozzleTemp || process.outputTemp,
|
||||
bedTemp = process.firstLayerBedTemp || process.outputBedTemp,
|
||||
fanSpeed = undefined,
|
||||
lastNozzleTemp = nozzleTemp,
|
||||
lastBedTemp = bedTemp,
|
||||
lastFanSpeed = fanSpeed,
|
||||
subst = {
|
||||
travel_speed: seekMMM,
|
||||
retract_speed: retSpeed,
|
||||
retract_distance: retDist,
|
||||
temp: process.firstLayerNozzleTemp || process.outputTemp,
|
||||
temp_bed: process.firstLayerBedTemp || process.outputBedTemp,
|
||||
bed_temp: process.firstLayerBedTemp || process.outputBedTemp,
|
||||
fan_speed: process.outputFanMax,
|
||||
speed: process.outputFanMax, // legacy
|
||||
temp: nozzleTemp,
|
||||
temp_bed: bedTemp,
|
||||
bed_temp: bedTemp,
|
||||
fan_speed: fanSpeed,
|
||||
speed: fanSpeed, // legacy
|
||||
top: offset ? device.bedDepth : device.bedDepth/2,
|
||||
left: offset ? 0 : -device.bedWidth/2,
|
||||
right: offset ? device.bedWidth : device.bedWidth/2,
|
||||
|
|
@ -79,8 +95,38 @@
|
|||
bytes = 0,
|
||||
bcos = Math.cos(Math.PI/4),
|
||||
icos = 1 / bcos,
|
||||
loops = process.outputLoopLayers,
|
||||
inLoop;
|
||||
inLoop,
|
||||
arcQ = [];
|
||||
|
||||
// smallish band-aid. refactor above to remove redundancy
|
||||
function updateParams(layer) {
|
||||
let process = getRangeParameters(settings, layer);
|
||||
zhop = process.zHopDistance || 0; // range
|
||||
retDist = process.outputRetractDist || 0; // range
|
||||
retSpeed = process.outputRetractSpeed * 60; // range
|
||||
retDwell = process.outputRetractDwell || 0; // range
|
||||
timeDwell = retDwell / 1000;
|
||||
nozzleTemp = layer === 0 ?
|
||||
process.firstLayerNozzleTemp || process.outputTemp :
|
||||
process.outputTemp || process.firstLayerNozzleTemp;
|
||||
bedTemp = layer === 0 ?
|
||||
process.firstLayerBedTemp || process.outputBedTemp :
|
||||
process.outputBedTemp || process.firstLayerBedTemp;
|
||||
fanSpeed = layer === 0 ?
|
||||
process.firstLayerFanSpeed || 0 :
|
||||
process.outputFanSpeed || 0;
|
||||
Object.assign(subst, {
|
||||
temp_bed: bedTemp,
|
||||
bed_temp: bedTemp,
|
||||
fan_speed: fanSpeed,
|
||||
speed: fanSpeed, // legacy
|
||||
retract_speed: retSpeed,
|
||||
retract_distance: retDist,
|
||||
temp: process.outputTemp, // range
|
||||
temp_bed: process.outputBedTemp, // range
|
||||
bed_temp: process.outputBedTemp, // range
|
||||
});
|
||||
}
|
||||
|
||||
if (isBelt && loops) {
|
||||
loops = loops.split(',').map(range => {
|
||||
|
|
@ -116,8 +162,12 @@
|
|||
}
|
||||
};
|
||||
|
||||
function appendSub(line) {
|
||||
append(print.constReplace(line, subst));
|
||||
function appendSubPad(line, pad) {
|
||||
appendSub(line, true);
|
||||
}
|
||||
|
||||
function appendSub(line, pad) {
|
||||
append(print.constReplace(line, subst, 0, pad));
|
||||
}
|
||||
|
||||
function appendAll(arr) {
|
||||
|
|
@ -126,10 +176,10 @@
|
|||
arr.forEach(function(line) { append(line) });
|
||||
}
|
||||
|
||||
function appendAllSub(arr) {
|
||||
if (!arr) return;
|
||||
function appendAllSub(arr, pad) {
|
||||
if (!arr || arr.length === 0) return;
|
||||
if (!Array.isArray(arr)) arr = [ arr ];
|
||||
arr.forEach(function(line) { appendSub(line) });
|
||||
arr.forEach(function(line) { appendSub(line, pad) });
|
||||
}
|
||||
|
||||
append(`; Generated by Kiri:Moto ${KIRI.version}`);
|
||||
|
|
@ -146,12 +196,18 @@
|
|||
let t1 = false;
|
||||
for (let i=0; i<device.gcodePre.length; i++) {
|
||||
let line = device.gcodePre[i];
|
||||
if (line.indexOf('T0') >= 0) t0 = true; else
|
||||
if (line.indexOf('T1') >= 0) t1 = true; else
|
||||
if (line.indexOf('M82') >= 0) extrudeAbs = true; else
|
||||
if (line.indexOf('M83') >= 0) extrudeAbs = false; else
|
||||
if (line.indexOf('G90') >= 0) extrudeAbs = true; else
|
||||
if (line.indexOf('G91') >= 0) extrudeAbs = false; else
|
||||
if (line.indexOf('T0') === 0) t0 = true; else
|
||||
if (line.indexOf('T1') === 0) t1 = true; else
|
||||
if (line.indexOf('M82') === 0) {
|
||||
extrudeAbs = true;
|
||||
extrudeSet = true;
|
||||
} else
|
||||
if (line.indexOf('M83') === 0) {
|
||||
extrudeAbs = false;
|
||||
extrudeSet = true;
|
||||
} else
|
||||
if (line.indexOf('G90') === 0 && !extrudeSet) extrudeAbs = true; else
|
||||
if (line.indexOf('G91') === 0 && !extrudeSet) extrudeAbs = false; else
|
||||
if (line.indexOf('G92') === 0) {
|
||||
line.split(";")[0].split(' ').forEach(function (tok) {
|
||||
let val = parseFloat(tok.substring(1) || 0) || 0;
|
||||
|
|
@ -174,11 +230,11 @@
|
|||
if (line.indexOf("{tool}") > 0 && extruders.length > 1) {
|
||||
for (let i=0; i<extruders.length; i++) {
|
||||
subst.tool = i;
|
||||
appendSub(line);
|
||||
appendSubPad(line);
|
||||
}
|
||||
subst.tool = 0;
|
||||
} else {
|
||||
appendSub(line);
|
||||
appendSubPad(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,8 +244,16 @@
|
|||
}
|
||||
|
||||
function retract(zhop) {
|
||||
if (retracted) {
|
||||
// console.log({double_retract: zhop});
|
||||
return;
|
||||
}
|
||||
retracted = retDist;
|
||||
moveTo({e:-retracted}, retSpeed, `e-retract ${retDist}`);
|
||||
if (fwRetract) {
|
||||
append('G10');
|
||||
} else {
|
||||
moveTo({e:-retracted}, retSpeed, `e-retract ${retDist}`);
|
||||
}
|
||||
if (zhop) moveTo({z:zpos + zhop}, seekMMM, "z-hop start");
|
||||
time += (retDist / retSpeed) * 60 * 2; // retraction time
|
||||
}
|
||||
|
|
@ -199,9 +263,6 @@
|
|||
let angle = -Math.PI / 4;
|
||||
|
||||
function moveTo(newpos, rate, comment) {
|
||||
if (comment) {
|
||||
append(";; " + comment);
|
||||
}
|
||||
let o = [!rate && !newpos.e ? 'G0' : 'G1'];
|
||||
let emit = { x: false, y: false, z: false };
|
||||
if (typeof newpos.x === 'number' && newpos.x !== pos.x) {
|
||||
|
|
@ -221,7 +282,7 @@
|
|||
let epos = isBelt ? { x: pos.x, y: pos.y, z: pos.z } : pos;
|
||||
if (isBelt) {
|
||||
epos.x = originCenter ? -pos.x : device.bedWidth - pos.x;
|
||||
epos.z = pos.z * icos;
|
||||
epos.z = blastz = pos.z * icos;
|
||||
epos.y = -pos.y + epos.z * bcos;
|
||||
lout = epos;
|
||||
}
|
||||
|
|
@ -241,6 +302,13 @@
|
|||
o.append(" F").append(Math.round(rate));
|
||||
pos.f = rate
|
||||
}
|
||||
if (comment) {
|
||||
o.append(` ; ${comment}`);
|
||||
}
|
||||
if (o.length === 1) {
|
||||
// console.trace({no_move: o, out, newpos, pos, lastp, emit});
|
||||
return;
|
||||
}
|
||||
let line = o.join('');
|
||||
if (last == line) {
|
||||
// console.log({dup:line});
|
||||
|
|
@ -264,20 +332,33 @@
|
|||
|
||||
while (layer < layers.length) {
|
||||
path = layers[layer];
|
||||
|
||||
// range overrides
|
||||
if (path.layer >= 0) {
|
||||
updateParams(path.layer);
|
||||
}
|
||||
|
||||
emitPerMM = print.extrudePerMM(
|
||||
extruder.extNozzle,
|
||||
extruder.extFilament,
|
||||
path.layer === 0 ?
|
||||
(process.firstSliceHeight || process.sliceHeight) : path.height);
|
||||
|
||||
subst.z = zpos = path.z;
|
||||
subst.Z = subst.z;
|
||||
zpos = path.z || zpos;
|
||||
bmax = Math.max(bmax, pos.z * icos);
|
||||
subst.z = subst.Z = zpos.round(3);
|
||||
subst.e = subst.E = outputLength;
|
||||
subst.layer = layer;
|
||||
subst.height = path.height.toFixed(3);
|
||||
|
||||
if (isBelt) {
|
||||
pos.z = zpos;
|
||||
if (peelGuard && bmax > peelGuard && blast < peelGuard) {
|
||||
peelGuard += 50;
|
||||
append(`G0 Z${(blast + 55).round(decimals)} F200 ; peel guard`);
|
||||
append(`G0 Z${blastz.round(decimals)} F200 ; unpeel`);
|
||||
}
|
||||
blast = bmax;
|
||||
}
|
||||
|
||||
if (pauseCmd && pause.indexOf(layer) >= 0) {
|
||||
|
|
@ -309,31 +390,23 @@
|
|||
if (gcodeLayer && gcodeLayer.length) {
|
||||
appendAllSub(gcodeLayer);
|
||||
} else {
|
||||
append(`;; --- layer ${layer} (${subst.height} @ ${subst.z}) ---`);
|
||||
append(`;; --- layer ${layer} (${subst.height} @ ${subst.z.round(3)}) ---`);
|
||||
}
|
||||
|
||||
if (layer > 0 && process.outputLayerRetract) {
|
||||
retract();
|
||||
}
|
||||
|
||||
// enable fan at fan layer
|
||||
if (gcodeFan && layer === process.outputFanLayer) {
|
||||
// layer temp and fan overrides at layer changes
|
||||
if (fanSpeed !== lastFanSpeed) {
|
||||
appendAllSub(gcodeFan);
|
||||
lastFanSpeed = fanSpeed;
|
||||
}
|
||||
|
||||
// second layer transitions
|
||||
if (layer === 1) {
|
||||
// update temps when first layer overrides are present
|
||||
if (process.firstLayerNozzleTemp) {
|
||||
subst.temp = process.outputTemp;
|
||||
if (t0) appendSub("M104 S{temp} T0");
|
||||
if (t1) appendSub("M104 S{temp} T1");
|
||||
if (!(t0 || t1)) appendSub("M104 S{temp} T{tool}");
|
||||
}
|
||||
if (process.firstLayerBedTemp) {
|
||||
subst.bed_temp = subst.temp_bed = process.outputBedTemp;
|
||||
appendSub("M140 S{temp_bed} T0");
|
||||
}
|
||||
if (bedTemp !== lastBedTemp) {
|
||||
append(`M140 S${bedTemp} T0`);
|
||||
lastBedTemp = bedTemp;
|
||||
}
|
||||
if (nozzleTemp !== lastNozzleTemp) {
|
||||
if (t0) append(`M104 S${nozzleTemp} T0`);
|
||||
if (t1) append(`M104 S${nozzleTemp} T1`);
|
||||
if (!(t0 || t1)) append(`M104 S${nozzleTemp} T${tool}`);
|
||||
lastNozzleTemp = nozzleTemp;
|
||||
}
|
||||
|
||||
// move Z to layer height
|
||||
|
|
@ -344,10 +417,11 @@
|
|||
// iterate through layer outputs
|
||||
for (pidx=0; pidx<path.length; pidx++) {
|
||||
out = path[pidx];
|
||||
speedMMM = (out.speed || process.outputFeedrate) * 60;
|
||||
speedMMM = (out.speed || process.outputFeedrate) * 60; // range
|
||||
|
||||
// look for extruder change and recalc emit factor
|
||||
// look for extruder change, run scripts, recalc emit factor
|
||||
if (out.tool !== undefined && out.tool !== tool) {
|
||||
appendAllSub(extruder.extDeselect);
|
||||
tool = out.tool;
|
||||
subst.nozzle = subst.tool = tool;
|
||||
extruder = extruders[tool];
|
||||
|
|
@ -383,10 +457,16 @@
|
|||
|
||||
// re-engage post-retraction before new extrusion
|
||||
if (out.emit && retracted) {
|
||||
drainQ();
|
||||
// console.log({engage:zhop});
|
||||
// when enabled, resume previous Z
|
||||
if (zhop && pos.z != zpos) moveTo({z:zpos}, seekMMM, "z-hop end");
|
||||
// re-engage retracted filament
|
||||
moveTo({e:retracted}, retSpeed, `e-engage ${retracted}`);
|
||||
if (fwRetract) {
|
||||
append('G11');
|
||||
} else {
|
||||
moveTo({e:retracted}, retSpeed, `e-engage ${retracted}`);
|
||||
}
|
||||
retracted = 0;
|
||||
// optional dwell after re-engaging filament to allow pressure to build
|
||||
if (retDwell) dwell(retDwell);
|
||||
|
|
@ -394,10 +474,58 @@
|
|||
}
|
||||
|
||||
if (lastp && out.emit) {
|
||||
emitMM = emitPerMM * out.emit * dist;
|
||||
moveTo({x:x, y:y, e:emitMM}, speedMMM);
|
||||
emitted += emitMM;
|
||||
if (arcDist) {
|
||||
let rec = {e:out.emit, x, y, z, dist, emitPerMM, speedMMM};
|
||||
arcQ.push(rec);
|
||||
let deem = false;
|
||||
let depm = false;
|
||||
let desp = false;
|
||||
if (arcQ.length > 1) {
|
||||
deem = arcQ[0].e !== rec.e;
|
||||
depm = arcQ[0].emitPerMM !== rec.emitPerMM;
|
||||
desp = arcQ[0].speedMMM !== rec.speedMMM;
|
||||
}
|
||||
if (arcQ.length > 2) {
|
||||
let el = arcQ.length;
|
||||
let e1 = arcQ[el-3];
|
||||
let e2 = arcQ[el-2];
|
||||
let e3 = arcQ[el-1];
|
||||
let cc = BASE.util.center2d(e1, e2, e3, 1);
|
||||
let dc = 0;
|
||||
if (arcQ.length === 3) {
|
||||
arcQ.center = [ cc ];
|
||||
} else {
|
||||
// check center point delta
|
||||
let dx = cc.x - arcQ.center[0].x;
|
||||
let dy = cc.y - arcQ.center[0].y;
|
||||
dc = Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
// if new point is off the arc
|
||||
if (deem || depm || desp || dc > arcDist) {
|
||||
// console.log({dc, depm, desp});
|
||||
if (arcQ.length === 4) {
|
||||
// not enough points for an arc, drop first point and recalc center
|
||||
emitQrec(arcQ.shift());
|
||||
arcQ.center = [ BASE.util.center2d(arcQ[0], arcQ[1], arcQ[2], 1) ];
|
||||
} else {
|
||||
// enough to consider an arc, emit and start new arc
|
||||
let defer = arcQ.pop();
|
||||
drainQ();
|
||||
// re-add point that was off the last arc
|
||||
arcQ.push(defer);
|
||||
}
|
||||
} else {
|
||||
// new point is on the arc
|
||||
arcQ.center.push(cc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
emitMM = emitPerMM * out.emit * dist;
|
||||
moveTo({x:x, y:y, e:emitMM}, speedMMM);
|
||||
emitted += emitMM;
|
||||
}
|
||||
} else {
|
||||
drainQ();
|
||||
moveTo({x:x, y:y}, seekMMM);
|
||||
// TODO disabling out of plane z moves until a better mechanism
|
||||
// can be built that doesn't rely on computed zpos from layer heights...
|
||||
|
|
@ -407,7 +535,8 @@
|
|||
}
|
||||
|
||||
// retract filament if point retract flag set
|
||||
if (!retracted && out.retract) {
|
||||
if (out.retract) {
|
||||
drainQ();
|
||||
retract(zhop);
|
||||
}
|
||||
|
||||
|
|
@ -427,13 +556,72 @@
|
|||
}
|
||||
layer++;
|
||||
}
|
||||
drainQ();
|
||||
|
||||
function emitQrec(rec) {
|
||||
let {e, x, y, dist, emitPerMM, speedMMM} = rec;
|
||||
emitMM = emitPerMM * e * dist;
|
||||
moveTo({x:x, y:y, e:emitMM}, speedMMM);
|
||||
emitted += emitMM;
|
||||
}
|
||||
|
||||
function drainQ() {
|
||||
if (!arcDist) {
|
||||
return;
|
||||
}
|
||||
if (arcQ.length > 4) {
|
||||
let area = BASE.newPolygon().addObj(arcQ).area();
|
||||
let from = arcQ[0];
|
||||
let to = arcQ.peek();
|
||||
let cc = {x:0, y:0, z:0, r:0};
|
||||
let cl = 0;
|
||||
for (let center of arcQ.center.filter(rec => !isNaN(rec.r))) {
|
||||
cc.x += center.x;
|
||||
cc.y += center.y;
|
||||
cc.z += center.z;
|
||||
cc.r += center.r;
|
||||
cl++;
|
||||
}
|
||||
cc.x /= cl;
|
||||
cc.y /= cl;
|
||||
cc.z /= cl;
|
||||
cc.r /= cl;
|
||||
// first arc point
|
||||
emitQrec(from);
|
||||
// console.log(arcQ.slice(), arcQ.center);
|
||||
// console.log({first: from, last: arcQ.peek(), center: cc});
|
||||
// rest of arc to final point
|
||||
let dist = arcQ.slice(1).map(v => v.dist).reduce((a,v) => a+v);
|
||||
let emit = from.e;//arcQ.slice(1).map(v => v.e).reduce((a,v) => a+v);
|
||||
emit = (from.emitPerMM * emit * dist);
|
||||
outputLength += emit;
|
||||
emitted += emit;
|
||||
if (extrudeAbs) {
|
||||
emit = outputLength;
|
||||
}
|
||||
let gc = area > 0 ? 'G2' : 'G3';
|
||||
let pre = `${gc} X${to.x.toFixed(decimals)} Y${to.y.toFixed(decimals)} R${cc.r.toFixed(decimals)} E${emit.toFixed(decimals)}`;
|
||||
let add = pos.f !== from.speedMMM ? ` E${from.speedMMM}` : '';
|
||||
append(`${pre}${add} ; merged=${cl-1} len=${dist.toFixed(decimals)} cp=${cc.x.round(2)},${cc.y.round(2)}`);
|
||||
pos.x = to.x;
|
||||
pos.y = to.y;
|
||||
pos.z = to.z;
|
||||
} else {
|
||||
for (let rec of arcQ) {
|
||||
emitQrec(rec);
|
||||
}
|
||||
}
|
||||
arcQ.length = 0;
|
||||
arcQ.center = undefined;
|
||||
}
|
||||
|
||||
if (inLoop) {
|
||||
append(`M808`);
|
||||
}
|
||||
|
||||
subst.time = UTIL.round(time,2);
|
||||
subst.material = UTIL.round(emitted,2);
|
||||
subst.time = UTIL.round(time,2);
|
||||
subst['print-time'] = subst.time;
|
||||
|
||||
append("; --- shutdown ---");
|
||||
appendAllSub(device.gcodePost);
|
||||
|
|
|
|||
|
|
@ -155,25 +155,28 @@
|
|||
function fillLinear(target) {
|
||||
let bounds = target.bounds();
|
||||
let height = target.zHeight();
|
||||
|
||||
let density = target.density();
|
||||
let line = target.lineWidth();
|
||||
|
||||
let span_x = bounds.max.x - bounds.min.x;
|
||||
let span_y = bounds.max.y - bounds.min.y;
|
||||
let density = target.density();
|
||||
let offset = target.offset() / 2;
|
||||
let tile = 1 + (1 - density);
|
||||
let tile_xc = Math.ceil(span_x / tile);
|
||||
let tile_yc = Math.ceil(span_y / tile);
|
||||
let steps_x = (span_x / line) * density;
|
||||
let steps_y = (span_y / line) * density;
|
||||
let step_x = span_x / steps_x;
|
||||
let step_y = span_x / steps_x;
|
||||
|
||||
if (target.zIndex() % 2 === 1) {
|
||||
for (let tx=0; tx<=tile_xc; tx++) {
|
||||
for (let tx=bounds.min.x; tx<=bounds.max.x; tx += step_x) {
|
||||
target.newline();
|
||||
target.emit(tx * tile + bounds.min.x, bounds.min.y);
|
||||
target.emit(tx * tile + bounds.min.x, bounds.max.y);
|
||||
target.emit(tx, bounds.min.y);
|
||||
target.emit(tx, bounds.max.y);
|
||||
}
|
||||
} else {
|
||||
for (let ty=0; ty<=tile_yc; ty++) {
|
||||
for (let ty=bounds.min.y; ty<=bounds.max.y; ty += step_y) {
|
||||
target.newline();
|
||||
target.emit(bounds.min.x, ty * tile + bounds.min.y);
|
||||
target.emit(bounds.max.x, ty * tile + bounds.min.y);
|
||||
target.emit(bounds.min.x, ty);
|
||||
target.emit(bounds.max.x, ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,8 @@
|
|||
POLY = BASE.polygons,
|
||||
FDM = KIRI.driver.FDM,
|
||||
newPoint = BASE.newPoint,
|
||||
newPolygon = BASE.newPolygon;
|
||||
newPolygon = BASE.newPolygon,
|
||||
getRangeParameters = FDM.getRangeParameters;
|
||||
|
||||
/**
|
||||
* DRIVER PRINT CONTRACT
|
||||
|
|
@ -19,34 +20,31 @@
|
|||
* @returns {Object[]} returns array of render objects
|
||||
*/
|
||||
FDM.prepare = function(widgets, settings, update) {
|
||||
settings = FDM.fixExtruders(settings);
|
||||
// filter ignored widgets
|
||||
widgets = widgets.filter(w => !w.track.ignore);
|
||||
|
||||
settings = FDM.fixExtruders(settings);
|
||||
let render = settings.render !== false,
|
||||
{ device, process, controller, bounds, mode } = settings,
|
||||
{ bedWidth, bedDepth } = device,
|
||||
output = [],
|
||||
printPoint = newPoint(0,0,0),
|
||||
nozzle = device.extruders[0].extNozzle,
|
||||
isBelt = device.bedBelt,
|
||||
isThin = controller.lineType === "line",
|
||||
isFlat = controller.lineType === "flat",
|
||||
isDanger = controller.danger || false,
|
||||
firstLayerHeight = isBelt ? process.sliceHeight : process.firstSliceHeight || process.sliceHeight,
|
||||
firstLayerSeek = process.outputSeekrate,
|
||||
firstLayerRate = process.firstLayerRate,
|
||||
firstLayerMult = process.firstLayerPrintMult,
|
||||
firstLayerBrim = process.firstLayerBrim,
|
||||
firstLayerBrimTrig = process.firstLayerBrimTrig,
|
||||
maxLayers = 0,
|
||||
layer = 0,
|
||||
layerRetract = process.outputLayerRetract,
|
||||
layerno = 0,
|
||||
zoff = 0,
|
||||
meshIndex,
|
||||
lastIndex,
|
||||
closest,
|
||||
mindist,
|
||||
minidx,
|
||||
find,
|
||||
layerout = [],
|
||||
slices = [],
|
||||
sliceEntry,
|
||||
print = self.worker.print = KIRI.newPrint(settings, widgets),
|
||||
beltYoff = device.bedDepth / 2,
|
||||
beltfact = Math.cos(Math.PI/4),
|
||||
|
|
@ -75,7 +73,7 @@
|
|||
offset = process.outputBrimOffset || (process.outputRaft ? 4 : 0);
|
||||
|
||||
// compute first brim
|
||||
widgets.forEach(function(widget) {
|
||||
widgets.filter(w => w.slices.length).forEach(function(widget) {
|
||||
let tops = [];
|
||||
// collect top outer polygons
|
||||
widget.slices[0].tops.forEach(function(top) {
|
||||
|
|
@ -88,15 +86,16 @@
|
|||
});
|
||||
// nest and offset tops
|
||||
POLY.nest(tops).forEach(function(poly) {
|
||||
poly.offset(-offset + nozzle / 2).forEach(function(brim) {
|
||||
brim.move(widget.mesh.position);
|
||||
let off = poly.offset(-offset + nozzle / 2);
|
||||
if (off) off.forEach(function(brim) {
|
||||
brim.move(widget.track.pos);
|
||||
brims.push(brim);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// merge brims
|
||||
brims = POLY.union(brims);
|
||||
brims = POLY.union(brims, undefined, true);
|
||||
|
||||
// if brim is offset, over-expand then shrink to induce brims to merge
|
||||
if (offset && brims.length) {
|
||||
|
|
@ -132,6 +131,7 @@
|
|||
speed: speed,
|
||||
mult: extrude,
|
||||
});
|
||||
layerout.z = zoff + height;
|
||||
layerout.height = height;
|
||||
output.append(layerout);
|
||||
|
||||
|
|
@ -139,14 +139,15 @@
|
|||
zoff += height;
|
||||
};
|
||||
|
||||
raft(nozzle/1, process.sliceFillAngle + 0 , nozzle * 6.0, firstLayerRate / 3, 4);
|
||||
raft(nozzle/1, process.sliceFillAngle + 0 , nozzle * 6.0, firstLayerRate / 2, 4);
|
||||
raft(nozzle/1, process.sliceFillAngle + 0 , nozzle * 5.0, firstLayerRate / 3, 4);
|
||||
raft(nozzle/1, process.sliceFillAngle + 0 , nozzle * 5.0, firstLayerRate / 2, 4);
|
||||
raft(nozzle/2, process.sliceFillAngle + 90, nozzle * 3.0, process.outputFeedrate, 2.5);
|
||||
raft(nozzle/2, process.sliceFillAngle + 0 , nozzle * 1.0, process.outputFeedrate, 1.5);
|
||||
raft(nozzle/2, process.sliceFillAngle + 0 , nozzle * 1.0, process.outputFeedrate, 1.0);
|
||||
raft(nozzle/2, process.sliceFillAngle + 90 , nozzle * 0.7, process.outputFeedrate, 0.75);
|
||||
|
||||
// raise first layer off raft slightly to lessen adhesion
|
||||
firstLayerHeight += process.outputRaftSpacing || 0;
|
||||
zoff += process.outputRaftSpacing || 0;
|
||||
|
||||
// retract after last raft layer
|
||||
output.last().last().retract = true;
|
||||
|
|
@ -169,7 +170,8 @@
|
|||
});
|
||||
|
||||
// output brim points
|
||||
printPoint = print.poly2polyEmit(polys, printPoint, function(poly, index, count, startPoint) {
|
||||
let brimStart = offset < nozzle * 2 ? newPoint(-bedWidth, -bedDepth, 0) : printPoint;
|
||||
printPoint = print.poly2polyEmit(polys, brimStart, (poly, index, count, startPoint) => {
|
||||
return print.polyPrintPath(poly, startPoint, preout, {
|
||||
rate: firstLayerRate,
|
||||
onfirst: function(point) {
|
||||
|
|
@ -203,6 +205,10 @@
|
|||
// so that they can use a separate extruder
|
||||
for (let widget of widgets.slice()) {
|
||||
let sslices = [];
|
||||
if (!widget.slices) {
|
||||
console.log('invalid widget', widget);
|
||||
continue;
|
||||
}
|
||||
for (let slice of widget.slices) {
|
||||
if (!slice.supports) {
|
||||
continue;
|
||||
|
|
@ -210,25 +216,30 @@
|
|||
let sslice = KIRI.newSlice(slice.z);
|
||||
sslice.extruder = process.sliceSupportNozzle;
|
||||
sslice.supports = slice.supports.slice();
|
||||
sslice.height = slice.height;
|
||||
sslices.push(sslice);
|
||||
}
|
||||
if (sslices.length) {
|
||||
let swidget = KIRI.newWidget();
|
||||
let swidget = KIRI.newWidget(null,widget.group);
|
||||
swidget.slices = sslices;
|
||||
swidget.support = true;
|
||||
swidget.mesh = { widget: swidget, position: widget.mesh.position };
|
||||
swidget.rotinfo = widget.rotinfo;
|
||||
swidget.belt = widget.belt;
|
||||
swidget.track = Object.clone(widget.track);
|
||||
swidget.mesh = { widget: swidget, position: swidget.track.pos };
|
||||
settings.widget[swidget.id] = { extruder: process.sliceSupportNozzle };
|
||||
widgets.push(swidget);
|
||||
}
|
||||
}
|
||||
|
||||
let lastPoly;
|
||||
let lastLayer;
|
||||
let extruders = [];
|
||||
let extcount = 0;
|
||||
|
||||
// find max layers (for updates)
|
||||
// generate list of used extruders for purge blocks
|
||||
for (let widget of widgets) {
|
||||
maxLayers = Math.max(maxLayers, widget.slices.length);
|
||||
let extruder = (settings.widget[widget.id] || {}).extruder || 0;
|
||||
if (!extruders[extruder]) {
|
||||
extruders[extruder] = {};
|
||||
|
|
@ -265,13 +276,15 @@
|
|||
|
||||
// generate purge block for given nozzle
|
||||
function purge(nozzle, track, layer, start, z, using) {
|
||||
if (extcount < 2) {
|
||||
if (extcount < 2 || isBelt) {
|
||||
return start;
|
||||
}
|
||||
let rec = track[nozzle];
|
||||
if (rec) {
|
||||
track[nozzle] = null;
|
||||
if (layer.last()) layer.last().retract = true;
|
||||
if (layer.last()) {
|
||||
layer.last().retract = true;
|
||||
}
|
||||
start = print.polyPrintPath(rec.poly.clone().setZ(z), start, layer, {
|
||||
tool: using || nozzle,
|
||||
open: true,
|
||||
|
|
@ -288,13 +301,15 @@
|
|||
// establish offsets
|
||||
for (let widget of widgets) {
|
||||
let { rotinfo, belt } = widget;
|
||||
// console.log({rotinfo, belt});
|
||||
let offset = widget.mesh ? Object.clone(widget.mesh.position) : {x:0, y:0, z:0};
|
||||
let offset = Object.clone(widget.track.pos);
|
||||
if (isBelt) {
|
||||
offset.x = rotinfo.xpos;
|
||||
offset.y = -belt.midy;
|
||||
offset.y += rotinfo.ypos * beltfact;
|
||||
offset.z = rotinfo.ypos * beltfact;
|
||||
let o = rotinfo.ypos * beltfact;
|
||||
offset = {
|
||||
x: rotinfo.xpos,
|
||||
y: o - belt.midy - belt.yadd/2,
|
||||
z: o,
|
||||
};
|
||||
// offset = { x:0, y:0, z:0 };
|
||||
// locate the lowest point in slices and widget overall
|
||||
let minby = Infinity;
|
||||
for (let slice of widget.slices) {
|
||||
|
|
@ -308,10 +323,11 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
// todo remove b/c this is now calculated at slice time
|
||||
// flag slices as being on or off the bed / belt
|
||||
for (let slice of widget.slices) {
|
||||
slice.onbelt = Math.abs(minby - slice.minby) < 0.01;
|
||||
}
|
||||
// for (let slice of widget.slices) {
|
||||
// slice.onbelt = Math.abs(minby - slice.minby) < 0.01;
|
||||
// }
|
||||
} else {
|
||||
// when rafts used this is non-zero
|
||||
offset.z = zoff;
|
||||
|
|
@ -341,6 +357,8 @@
|
|||
return a.z - b.z;
|
||||
});
|
||||
|
||||
let lastWidget;
|
||||
|
||||
// walk cake layers bottom up
|
||||
for (let layer of cake) {
|
||||
// track purge blocks generated for each layer
|
||||
|
|
@ -376,41 +394,63 @@
|
|||
return a.dst - b.dst;
|
||||
});
|
||||
let { z, slice, offset } = order[0];
|
||||
let params = getRangeParameters(settings, slice.index);
|
||||
slice.prep = true;
|
||||
// retract between widgets
|
||||
if (layerout.length && minidx !== lastIndex) {
|
||||
// retract between widgets or layers (when set)
|
||||
if (layerout.length && slice.widget !== lastWidget) {
|
||||
layerout.last().retract = true;
|
||||
}
|
||||
layerout.z = z;
|
||||
lastWidget = slice.widget;
|
||||
layerout.z = z + slice.height / 2;
|
||||
layerout.height = layerout.height || slice.height;
|
||||
layerout.slice = slice;
|
||||
// mark layer as anchor if slice is belt and flag set
|
||||
layerout.anchor = slice.belt && slice.belt.anchor;
|
||||
// detect extruder change and print purge block
|
||||
if (!lastOut || lastOut.extruder !== slice.extruder) {
|
||||
printPoint = purge(slice.extruder, track, layerout, printPoint, slice.z);
|
||||
}
|
||||
let tmpout = [];
|
||||
let wtb = slice.widget.track.box;
|
||||
// output seek to start point between mesh slices if previous data
|
||||
printPoint = print.slicePrintPath(
|
||||
slice,
|
||||
isBelt ? newPoint(-wtb.w, wtb.d * 2, 0) : printPoint.sub(offset),
|
||||
slice.belt && slice.belt.touch ? newPoint(-wtb.w, wtb.d * 2, 0) : printPoint.sub(offset),
|
||||
offset,
|
||||
tmpout, //layerout,
|
||||
layerout,
|
||||
{
|
||||
seedPoint: printPoint.sub(offset),
|
||||
danger: isDanger,
|
||||
params, // range parameters
|
||||
first: slice.index === 0,
|
||||
support: slice.widget.support,
|
||||
onBelt: slice.onbelt
|
||||
onBelt: slice.belt && slice.belt.touch,
|
||||
pretract: (wipeDist) => {
|
||||
if (lastLayer && lastLayer.length) {
|
||||
let lastOut = lastLayer.last();
|
||||
lastOut.retract = true;
|
||||
if (wipeDist && lastPoly && lastOut.point) {
|
||||
let endpoint = lastOut.point.followTo(lastPoly.center(true).add(offset), wipeDist);
|
||||
if (endpoint.inPolygon(lastPoly)) {
|
||||
print.addOutput(lastLayer, endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
layerout.appendAll(tmpout);
|
||||
lastOut = slice;
|
||||
lastExt = lastOut.ext
|
||||
lastIndex = minidx;
|
||||
lastPoly = slice.lastPoly;
|
||||
lastLayer = layerout;
|
||||
if (layerRetract && layerout.length) {
|
||||
layerout.last().retract = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if a declared extruder isn't used in a layer, use selected
|
||||
// extruder to fill the relevant purge blocks for later support
|
||||
track.forEach(ext => {
|
||||
if (ext) {
|
||||
if (ext && lastOut) {
|
||||
printPoint = purge(ext.extruder, track, layerout, printPoint, lastOut.z, lastExt);
|
||||
}
|
||||
});
|
||||
|
|
@ -421,13 +461,13 @@
|
|||
}
|
||||
|
||||
// retract after last layer
|
||||
if (layer === maxLayers && layerout.length) {
|
||||
if (layerno === cake.length - 1 && layerout.length) {
|
||||
layerout.last().retract = true;
|
||||
}
|
||||
|
||||
// notify progress
|
||||
layerout.layer = layer++;
|
||||
update((layer / maxLayers) * 0.5, "prepare");
|
||||
layerout.layer = layerno++;
|
||||
update((layerno / cake.length) * 0.5, "prepare");
|
||||
|
||||
slices = [];
|
||||
layerout = [];
|
||||
|
|
@ -454,6 +494,13 @@
|
|||
rec.point.y += poff;
|
||||
}
|
||||
}
|
||||
|
||||
// add lead in, when specified
|
||||
// if (process.firstLayerBeltLead) {
|
||||
// // add belt lead in
|
||||
// console.log({process, output});
|
||||
// }
|
||||
|
||||
let thresh = firstLayerHeight * 1.05;
|
||||
// iterate over layers, find extrusion on belt and
|
||||
// apply corrections and add brim when specified
|
||||
|
|
@ -479,13 +526,17 @@
|
|||
}
|
||||
lastout = rec;
|
||||
}
|
||||
// skip if brig trigger not met
|
||||
if (firstLayerBrimTrig && mins > firstLayerBrimTrig) {
|
||||
// skip if brim trigger not met
|
||||
if (firstLayerBrimTrig > 0 && mins > firstLayerBrimTrig) {
|
||||
continue;
|
||||
}
|
||||
// do not add brims to anchor layers
|
||||
if (layer.anchor) {
|
||||
continue;
|
||||
}
|
||||
// add brim, if specified
|
||||
if (first && firstLayerBrim) {
|
||||
let {emit, tool } = first;
|
||||
let { emit, tool } = first;
|
||||
let y = maxy;
|
||||
let z = minz;
|
||||
let b = Math.max(firstLayerBrim, 1);
|
||||
|
|
@ -541,8 +592,11 @@
|
|||
const flat = opts.flat;
|
||||
const thin = opts.thin && !flat;
|
||||
const ckspeed = opts.speed !== false;
|
||||
const headColor = 0x888888;
|
||||
const moveColor = opts.move >= 0 ? opts.move : 0xaaaaaa;
|
||||
const printColor = opts.print >= 0 ? opts.print : 0x777700;
|
||||
const arrowAll = false;
|
||||
const arrowSize = arrowAll ? 0.2 : 0.4;
|
||||
const layers = [];
|
||||
|
||||
const moveOpt = {
|
||||
|
|
@ -569,6 +623,7 @@
|
|||
let lastOut = null;
|
||||
let current = null;
|
||||
let retracted = false;
|
||||
let retractz = 0;
|
||||
|
||||
function color(point) {
|
||||
return FDM.rateToColor(point.speed, maxspd);
|
||||
|
|
@ -604,6 +659,7 @@
|
|||
if (out.retract) {
|
||||
retracts.push(out.point);
|
||||
retracted = true;
|
||||
retractz++;
|
||||
}
|
||||
if (!out.point) {
|
||||
// in cam mode, these are drilling or dwell ops
|
||||
|
|
@ -611,7 +667,7 @@
|
|||
}
|
||||
|
||||
if (lastOut) {
|
||||
if (lastOut.emit !== out.emit) {
|
||||
if (arrowAll || lastOut.emit !== out.emit) {
|
||||
heads.push({p1: lastOut.point, p2: out.point});
|
||||
}
|
||||
const op = out.point, lp = lastOut.point;
|
||||
|
|
@ -670,14 +726,14 @@
|
|||
}
|
||||
if (heads.length) {
|
||||
output
|
||||
.setLayer('arrows', { face: moveColor, line: 0x555555, opacity: 0.5 }, true)
|
||||
.setLayer('arrows', { face: headColor, line: 0x112233, opacity: 0.5 }, true)
|
||||
.addAreas(heads.map(points => {
|
||||
const {p1, p2} = points;
|
||||
const slope = p2.slopeTo(p1);
|
||||
const s1 = BASE.newSlopeFromAngle(slope.angle + 20);
|
||||
const s2 = BASE.newSlopeFromAngle(slope.angle - 20);
|
||||
const p3 = points.p2.projectOnSlope(s1, 0.4);
|
||||
const p4 = points.p2.projectOnSlope(s2, 0.4);
|
||||
const p3 = points.p2.projectOnSlope(s1, arrowSize);
|
||||
const p4 = points.p2.projectOnSlope(s2, arrowSize);
|
||||
return newPolygon().addPoints([p2,p3,p4]).setZ(p2.z + 0.01);
|
||||
}), { thin: true, outline: true });
|
||||
}
|
||||
|
|
@ -685,9 +741,7 @@
|
|||
.setLayer(opts.other || 'move', moveOpt, opts.moves !== true)
|
||||
.addPolys(moves, { thin: true, z: opts.z });
|
||||
// force level when present
|
||||
if (level.z) {
|
||||
opts.z = level.z;
|
||||
}
|
||||
let pz = level.z ? level.z - height : opts.z;
|
||||
Object.values(prints).forEach(array => {
|
||||
array.forEach(poly => {
|
||||
if (flat && poly.appearsClosed()) {
|
||||
|
|
@ -700,10 +754,10 @@
|
|||
.addPolys([ poly ],
|
||||
thin ? { thin, z: opts.z, color: poly.color } :
|
||||
flat ? {
|
||||
flat, z: opts.z, color: poly.color,
|
||||
flat, z: pz, color: poly.color,
|
||||
outline: true, offset: array.width, open: poly.open } :
|
||||
{
|
||||
offset: array.width, height, z: opts.z,
|
||||
offset: array.width, height, z: pz,
|
||||
color: { face: poly.color, line: poly.color }
|
||||
})
|
||||
});
|
||||
|
|
@ -711,7 +765,7 @@
|
|||
|
||||
update(index / levels.length, output);
|
||||
});
|
||||
|
||||
// console.log({retractz});
|
||||
return layers;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,9 +21,13 @@
|
|||
shell: { check: 0x0077bb, face: 0x0077bb, line: 0x0077bb, opacity: 1 },
|
||||
fill: { check: 0x00bb77, face: 0x00bb77, line: 0x00bb77, opacity: 1 },
|
||||
infill: { check: 0x3322bb, face: 0x3322bb, line: 0x3322bb, opacity: 1 },
|
||||
support: { check: 0xaa5533, face: 0xaa5533, line: 0xaa5533, opacity: 1 }
|
||||
support: { check: 0xaa5533, face: 0xaa5533, line: 0xaa5533, opacity: 1 },
|
||||
gaps: { check: 0xaa3366, face: 0xaa3366, line: 0xaa3366, opacity: 1 }
|
||||
},
|
||||
PROTO = Object.clone(COLOR);
|
||||
PROTO = Object.clone(COLOR),
|
||||
bwcomp = (1 / Math.cos(Math.PI/4)),
|
||||
getRangeParameters = FDM.getRangeParameters,
|
||||
debug = false;
|
||||
|
||||
let isThin = false; // force line rendering
|
||||
let isFlat = false; // force flat rendering
|
||||
|
|
@ -57,14 +61,16 @@
|
|||
FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||
FDM.fixExtruders(settings);
|
||||
let render = settings.render !== false,
|
||||
ctrl = settings.controller,
|
||||
spro = settings.process,
|
||||
sdev = settings.device,
|
||||
isBelt = sdev.bedBelt,
|
||||
isSynth = widget.track.synth,
|
||||
update_start = Date.now(),
|
||||
minSolid = spro.sliceSolidMinArea,
|
||||
solidLayers = spro.sliceSolidLayers,
|
||||
vaseMode = spro.sliceFillType === 'vase',
|
||||
doSolidLayers = solidLayers && !vaseMode,
|
||||
vaseMode = spro.sliceFillType === 'vase' && !isSynth,
|
||||
doSolidLayers = solidLayers && !vaseMode && !isSynth,
|
||||
metadata = settings.widget[widget.id] || {},
|
||||
extruder = metadata.extruder || 0,
|
||||
sliceHeight = spro.sliceHeight,
|
||||
|
|
@ -77,10 +83,13 @@
|
|||
fillSpacing = lineWidth,
|
||||
fillOffset = lineWidth * fillOffsetMult,
|
||||
sliceFillAngle = spro.sliceFillAngle,
|
||||
view = widget.mesh && widget.mesh.newGroup ? widget.mesh.newGroup() : null;
|
||||
supportDensity = spro.sliceSupportDensity,
|
||||
view = widget.mesh && widget.mesh.newGroup ? widget.mesh.newGroup() : null,
|
||||
beltfact = Math.cos(Math.PI/4),
|
||||
invbfact = 1 / beltfact;
|
||||
|
||||
isFlat = settings.controller.lineType === "flat";
|
||||
isThin = !isFlat && settings.controller.lineType === "line";
|
||||
isFlat = ctrl.lineType === "flat";
|
||||
isThin = !isFlat && ctrl.lineType === "line";
|
||||
offset = lineWidth / 2;
|
||||
|
||||
if (isFlat) {
|
||||
|
|
@ -145,6 +154,7 @@
|
|||
height: sliceHeight,
|
||||
minHeight: sliceMinHeight,
|
||||
firstHeight: firstSliceHeight,
|
||||
union: ctrl.healMesh,
|
||||
// debug: true,
|
||||
// xray: 3,
|
||||
// view: view
|
||||
|
|
@ -155,9 +165,9 @@
|
|||
}
|
||||
|
||||
function onSliceDone(slices) {
|
||||
// slices = slices.filter(slice => slice.tops.length);
|
||||
// remove all empty slices above part but leave below
|
||||
// for multi-part (multi-extruder) setups where the void is ok
|
||||
// also reverse because slicing occurs bottom-up
|
||||
let found = false;
|
||||
slices = slices.reverse().filter(slice => {
|
||||
if (slice.tops.length) {
|
||||
|
|
@ -173,6 +183,61 @@
|
|||
return;
|
||||
}
|
||||
|
||||
// for synth support widgets, merge tops
|
||||
if (isSynth) {
|
||||
for (let slice of slices) {
|
||||
// union top support polys
|
||||
let tops = slice.topPolys();
|
||||
let union = POLY.union(tops, null, true);
|
||||
if (union.length < tops.length) {
|
||||
slice.tops = [];
|
||||
for (let u of union) {
|
||||
slice.addTop(u);
|
||||
}
|
||||
}
|
||||
let gap = sliceHeight * (isBelt ? 0 : spro.sliceSupportGap);
|
||||
// clip tops to other widgets in group
|
||||
tops = slice.topPolys();
|
||||
for (let peer of widget.group) {
|
||||
// skip self
|
||||
if (peer === widget) {
|
||||
continue;
|
||||
}
|
||||
for (let pslice of peer.slices) {
|
||||
if (Math.abs(Math.abs(pslice.z - slice.z) - gap) > 0.1) {
|
||||
continue;
|
||||
}
|
||||
// offset pslice tops by spro.sliceSupportOffset
|
||||
if (!pslice.synth_off) {
|
||||
pslice.synth_off = POLY.offset(pslice.topPolys(), spro.sliceSupportOffset);
|
||||
}
|
||||
let ptops = pslice.synth_off;
|
||||
let ntops = [];
|
||||
POLY.subtract(tops, ptops, ntops, null, slice.z, 0);
|
||||
tops = ntops;
|
||||
}
|
||||
// trim to group's shadow if not in belt mode
|
||||
if (!isBelt) {
|
||||
let group = widget.group[0];
|
||||
if (!group.shadow) {
|
||||
let gs = [];
|
||||
for (let w of group) {
|
||||
if (w.shadow) {
|
||||
gs = POLY.union([w.shadow,...gs],null,0.1);
|
||||
}
|
||||
}
|
||||
group.shadow = gs;
|
||||
}
|
||||
tops = POLY.setZ(POLY.trimTo(tops, group.shadow), slice.z);
|
||||
}
|
||||
}
|
||||
slice.tops = [];
|
||||
for (let t of tops) {
|
||||
slice.addTop(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate % complete and call onupdate()
|
||||
function doupdate(index, from, to, msg) {
|
||||
onupdate(0.5 + (from + ((index/slices.length) * (to-from))) * 0.5, msg);
|
||||
|
|
@ -197,16 +262,15 @@
|
|||
slice.solids = [];
|
||||
});
|
||||
|
||||
// fixed supports (generated ahead of time)
|
||||
const fixed = Object.values(settings.widget[widget.id].support || {});
|
||||
// create shadow for clipping supports
|
||||
let shadow = null;
|
||||
if (fixed.length || spro.sliceSupportEnable) {
|
||||
// create shadow. TODO test if any supports set
|
||||
if (true || spro.sliceSupportEnable) {
|
||||
let alltops = slices.map(slice => slice.topPolys()).flat();
|
||||
shadow = POLY.union(alltops,null,0.1);
|
||||
if (spro.sliceSupportExtra) {
|
||||
shadow = POLY.offset(shadow, spro.sliceSupportExtra);
|
||||
}
|
||||
widget.shadow = shadow;
|
||||
// slices[0].output()
|
||||
// .setLayer('shadow', { line: 0xff0000, check: 0xff0000 })
|
||||
// .addPolys(shadow);
|
||||
|
|
@ -214,28 +278,100 @@
|
|||
|
||||
// create shells and diff inner fillable areas
|
||||
forSlices(0.0, 0.2, slice => {
|
||||
let params = getRangeParameters(settings, slice.index);
|
||||
let shellFrac = (params.sliceShells - (params.sliceShells | 0));
|
||||
let sliceShells = params.sliceShells | 0;
|
||||
if (ctrl.danger && shellFrac) {
|
||||
let v1 = shellFrac > 0.5 ? 1 - shellFrac : shellFrac;
|
||||
let v2 = 1 - v1;
|
||||
let parts = Math.round(v2/v1) + 1;
|
||||
let rem = slice.index % parts;
|
||||
let trg = shellFrac > 0.5 ? 1 : parts - 1;
|
||||
sliceShells += rem >= trg ? 1 : 0;
|
||||
}
|
||||
let first = slice.index === 0;
|
||||
let solid = (
|
||||
slice.index < spro.sliceBottomLayers ||
|
||||
slice.index > slices.length - spro.sliceTopLayers-1 ||
|
||||
spro.sliceFillSparse > 0.95
|
||||
) && !vaseMode;
|
||||
let isBottom = slice.index < spro.sliceBottomLayers;
|
||||
let isTop = slice.index > slices.length - spro.sliceTopLayers-1;
|
||||
let isDense = params.sliceFillSparse > 0.98;
|
||||
let solid = (isBottom || ((isTop || isDense) && !vaseMode)) && !isSynth;
|
||||
let solidWidth = params.sliceFillWidth || 1;
|
||||
let spaceMult = first ? spro.firstLayerLineMult || 1 : 1;
|
||||
let offset = shellOffset * spaceMult;
|
||||
let fillOff = fillOffset * spaceMult;
|
||||
doShells(slice, spro.sliceShells, offset, fillOff, {
|
||||
let count = isSynth ? 1 : sliceShells;
|
||||
doShells(slice, count, offset, fillOff, {
|
||||
vase: vaseMode,
|
||||
thin: spro.detectThinWalls,
|
||||
belt0: isBelt && first,
|
||||
widget: widget
|
||||
thin: spro.detectThinWalls && !isSynth,
|
||||
widget: widget,
|
||||
danger: ctrl.danger
|
||||
});
|
||||
if (solid) {
|
||||
let fillSpace = fillSpacing * spaceMult;
|
||||
let fillSpace = fillSpacing * spaceMult * solidWidth;
|
||||
doSolidLayerFill(slice, fillSpace, sliceFillAngle);
|
||||
}
|
||||
sliceFillAngle += 90.0;
|
||||
}, "offsets");
|
||||
|
||||
// add lead in when specified in belt mode
|
||||
if (!isSynth && isBelt) {
|
||||
let wb = widget.bounds;
|
||||
// find adjusted zero point from slices
|
||||
let smin = Infinity;
|
||||
for (let slice of slices) {
|
||||
let miny = Infinity;
|
||||
for (let poly of slice.topPolys()) {
|
||||
let y = poly.bounds.maxy;
|
||||
let z = slice.z;
|
||||
let by = -y + z;
|
||||
if (by < miny) miny = by;
|
||||
if (by < smin) smin = by;
|
||||
}
|
||||
slice.belt = { miny, touch: false };
|
||||
}
|
||||
// mark slices with tops touching belt
|
||||
// also find max width of first 5 layers
|
||||
let start;
|
||||
let minx = Infinity, maxx = -Infinity;
|
||||
for (let slice of slices) {
|
||||
if (slice.index < 5) {
|
||||
for (let poly of slice.topPolys()) {
|
||||
minx = Math.min(minx, poly.bounds.minx);
|
||||
maxx = Math.max(maxx, poly.bounds.maxx);
|
||||
}
|
||||
}
|
||||
if (Math.abs(slice.belt.miny - smin) < 0.001) {
|
||||
slice.belt.touch = true;
|
||||
if (!start) start = slice;
|
||||
}
|
||||
}
|
||||
// console.log({smin: smin.round(4)});
|
||||
let offset = spro.firstLayerBeltLead * beltfact;
|
||||
// ensure we start against a layer with shells
|
||||
while (start.up && start.topShells().length === 0) {
|
||||
start = start.up;
|
||||
}
|
||||
while (offset && start && offset >= sliceHeight) {
|
||||
let addto = start.down;
|
||||
if (!addto) {
|
||||
addto = newSlice(start.z - sliceHeight);
|
||||
addto.belt = { };
|
||||
addto.height = start.height;
|
||||
addto.up = start;
|
||||
start.down = addto;
|
||||
slices.splice(0,0,addto);
|
||||
}
|
||||
addto.index = -1;
|
||||
addto.belt.anchor = true;
|
||||
let z = addto.z;
|
||||
let y = z - smin - (nozzleSize / 2);
|
||||
// let splat = BASE.newPolygon().add(wb.min.x, y, z).add(wb.max.x, y, z).setOpen();
|
||||
let splat = BASE.newPolygon().add(minx, y, z).add(maxx, y, z).setOpen();
|
||||
addto.addTop(splat).fill_sparse = [ splat ];
|
||||
start = addto;
|
||||
offset -= sliceHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// calculations only relevant when solid layers are used
|
||||
if (doSolidLayers) {
|
||||
forSlices(0.2, 0.34, slice => {
|
||||
|
|
@ -246,48 +382,68 @@
|
|||
projectBridges(slice, solidLayers);
|
||||
}, "solids");
|
||||
forSlices(0.35, 0.5, slice => {
|
||||
let params = getRangeParameters(settings, slice.index);
|
||||
let first = slice.index === 0;
|
||||
let spaceMult = first ? spro.firstLayerLineMult || 1 : 1;
|
||||
let fillSpace = fillSpacing * spaceMult;
|
||||
let solidWidth = params.sliceFillWidth || 1;
|
||||
let spaceMult = first ? params.firstLayerLineMult || 1 : 1;
|
||||
let fillSpace = fillSpacing * spaceMult * solidWidth;
|
||||
doSolidsFill(slice, fillSpace, sliceFillAngle, minSolid);
|
||||
sliceFillAngle += 90.0;
|
||||
}, "solids");
|
||||
}
|
||||
|
||||
// sparse layers only present when non-vase mose and sparse % > 0
|
||||
if (!vaseMode && spro.sliceFillSparse > 0.0) {
|
||||
if (!isSynth) {
|
||||
let lastType;
|
||||
forSlices(0.5, 0.7, slice => {
|
||||
let params = getRangeParameters(settings, slice.index);
|
||||
if (vaseMode || !params.sliceFillSparse) {
|
||||
return;
|
||||
}
|
||||
let newType = params.sliceFillType;
|
||||
doSparseLayerFill(slice, {
|
||||
settings: settings,
|
||||
process: spro,
|
||||
device: sdev,
|
||||
lineWidth: lineWidth,
|
||||
spacing: fillOffset,
|
||||
density: spro.sliceFillSparse,
|
||||
density: params.sliceFillSparse,
|
||||
bounds: widget.getBoundingBox(),
|
||||
height: sliceHeight,
|
||||
type: spro.sliceFillType
|
||||
type: newType,
|
||||
cache: params._range !== true && lastType === newType
|
||||
});
|
||||
lastType = newType;
|
||||
}, "infill");
|
||||
} else if (isSynth) {
|
||||
forSlices(0.5, 0.7, slice => {
|
||||
let params = getRangeParameters(settings, slice.index);
|
||||
let density = params.sliceSupportDensity;
|
||||
if (density)
|
||||
for (let top of slice.tops) {
|
||||
let offset = [];
|
||||
POLY.expand(top.shells, -nozzleSize/4, slice.z, offset);
|
||||
fillSupportPolys(offset, lineWidth, density, slice.z);
|
||||
top.fill_lines = offset.map(o => o.fill).flat().filter(v => v);
|
||||
}
|
||||
}, "infill");
|
||||
}
|
||||
|
||||
// calculations only relevant when supports are enabled
|
||||
if (!isBelt) {
|
||||
let auto = spro.sliceSupportEnable && spro.sliceSupportDensity > 0.0,
|
||||
minArea = spro.sliceSupportArea;
|
||||
|
||||
// auto support generation
|
||||
if (!isBelt && !isSynth && supportDensity && spro.sliceSupportEnable) {
|
||||
forSlices(0.7, 0.8, slice => {
|
||||
doSupport(slice, spro, auto, fixed, shadow);
|
||||
doSupport(slice, spro, shadow);
|
||||
}, "support");
|
||||
forSlices(0.8, 0.9, slice => {
|
||||
doSupportFill(slice, lineWidth, spro.sliceSupportDensity, minArea);
|
||||
doSupportFill(slice, lineWidth, supportDensity, spro.sliceSupportArea);
|
||||
}, "support");
|
||||
}
|
||||
|
||||
// render if not explicitly disabled
|
||||
if (render) {
|
||||
forSlices(0.9, 1.0, slice => {
|
||||
doRender(slice);
|
||||
let params = getRangeParameters(settings, slice.index);
|
||||
doRender(slice, isSynth, params);
|
||||
}, "render");
|
||||
}
|
||||
|
||||
|
|
@ -310,32 +466,35 @@
|
|||
return Math.max(min,Math.min(max,v));
|
||||
}
|
||||
|
||||
function doRender(slice) {
|
||||
function doRender(slice, isSynth, params) {
|
||||
const output = slice.output();
|
||||
const height = slice.height / 2;
|
||||
const solidWidth = params.sliceFillWidth || 1;
|
||||
|
||||
slice.tops.forEach(top => {
|
||||
if (isThin) {
|
||||
output
|
||||
.setLayer('slice', { line: 0x000066, check: 0x000066 })
|
||||
.addPolys(top.poly);
|
||||
}
|
||||
if (isThin) output
|
||||
.setLayer('slice', { line: 0x000066, check: 0x000066 })
|
||||
.addPolys(top.poly);
|
||||
|
||||
output
|
||||
.setLayer("shells", COLOR.shell)
|
||||
if (top.shells) output
|
||||
.setLayer("shells", isSynth ? COLOR.support : COLOR.shell)
|
||||
.addPolys(top.shells, vopt({ offset, height }));
|
||||
|
||||
// if (isThin && debug) {
|
||||
// slice.output()
|
||||
// .setLayer('offset', { face: 0, line: 0x888888 })
|
||||
// .addPolys(top.fill_off)
|
||||
// .setLayer('last', { face: 0, line: 0x008888 })
|
||||
// .addPolys(top.last);
|
||||
// }
|
||||
if (top.gaps) output
|
||||
.setLayer("gaps", COLOR.gaps)
|
||||
.addPolys(top.gaps, vopt({ offset, height, thin: true }));
|
||||
|
||||
if (top.fill_lines) output
|
||||
.setLayer("fill", COLOR.fill)
|
||||
.addLines(top.fill_lines, vopt({ offset, height }));
|
||||
if (isThin && debug) {
|
||||
slice.output()
|
||||
.setLayer('offset', { face: 0, line: 0x888888 })
|
||||
.addPolys(top.fill_off)
|
||||
.setLayer('last', { face: 0, line: 0x008888 })
|
||||
.addPolys(top.last);
|
||||
}
|
||||
|
||||
if (top.fill_lines && top.fill_lines.length) output
|
||||
.setLayer("fill", isSynth ? COLOR.support : COLOR.fill)
|
||||
.addLines(top.fill_lines, vopt({ offset: offset * solidWidth, height }));
|
||||
|
||||
if (top.fill_sparse) output
|
||||
.setLayer("infill", COLOR.infill)
|
||||
|
|
@ -344,15 +503,22 @@
|
|||
if (top.thin_fill) output
|
||||
.setLayer("fill", COLOR.fill)
|
||||
.addLines(top.thin_fill, vopt({ offset, height }));
|
||||
|
||||
// emit solid areas
|
||||
// if (isThin && debug) {
|
||||
// output
|
||||
// .setLayer("solids", { face: 0x00dd00 })
|
||||
// .addAreas(slice.solids);
|
||||
// }
|
||||
});
|
||||
|
||||
if (isThin && debug) {
|
||||
if (slice.solids) output
|
||||
.setLayer("solids", { face: 0x00dd00 })
|
||||
.addAreas(slice.solids);
|
||||
|
||||
if (slice.bridges) output
|
||||
.setLayer("bridges", { face: 0x00aaaa, line: 0x00aaaa })
|
||||
.addAreas(slice.bridges);
|
||||
|
||||
if (slice.flats) output
|
||||
.setLayer("flats", { face: 0xaa00aa, line: 0xaa00aa })
|
||||
.addAreas(slice.flats);
|
||||
}
|
||||
|
||||
if (slice.supports) output
|
||||
.setLayer("support", COLOR.support)
|
||||
.addPolys(slice.supports, vopt({ offset, height }));
|
||||
|
|
@ -363,16 +529,6 @@
|
|||
.addLines(poly.fill, vopt({ offset, height }));
|
||||
});
|
||||
|
||||
// if (isThin && debug) {
|
||||
// output
|
||||
// .setLayer("bridges", { face: 0x00aaaa, line: 0x00aaaa })
|
||||
// .addAreas(top.bridges);
|
||||
//
|
||||
// output
|
||||
// .setLayer("flats", { face: 0xaa00aa, line: 0xaa00aa })
|
||||
// .addAreas(top.flats);
|
||||
// }
|
||||
|
||||
// console.log(slice.index, slice.render.stats);
|
||||
}
|
||||
|
||||
|
|
@ -433,7 +589,22 @@
|
|||
let dist = p.first().distTo2D(p.last());
|
||||
if (dist < 1) p.open = false;
|
||||
} });
|
||||
if (opt.thin) {
|
||||
if (opt.danger && opt.thin) {
|
||||
top.thin_fill = [];
|
||||
top.fill_sparse = [];
|
||||
let layers = POLY.inset(top_poly, offsetN, count, z);
|
||||
last = layers.last().mid;
|
||||
top.shells = layers.map(r => r.mid).flat();
|
||||
top.gaps = layers.map(r => r.gap).flat();
|
||||
let off = offsetN;
|
||||
let min = off * 0.75;
|
||||
let max = off * 4;
|
||||
for (let poly of layers.map(r => r.gap).flat()) {
|
||||
let centers = poly.centers(off/2, z, min, max, {lines:false});
|
||||
top.fill_sparse.appendAll(centers);
|
||||
// top.fill_lines.appendAll(centers);
|
||||
}
|
||||
} else if (opt.thin) {
|
||||
top.thin_fill = [];
|
||||
let oso = {z, count, gaps: [], outs: [], minArea: 0.05};
|
||||
POLY.offset(top_poly, [-offset1, -offsetN], oso);
|
||||
|
|
@ -444,6 +615,11 @@
|
|||
if (p.fill_off) {
|
||||
p.fill_off.forEach(pi => pi.depth = i);
|
||||
}
|
||||
if (p.inner) {
|
||||
for (let pi of p.inner) {
|
||||
pi.depth = p.depth;
|
||||
}
|
||||
}
|
||||
top.shells.push(p);
|
||||
});
|
||||
last = polys;
|
||||
|
|
@ -453,12 +629,9 @@
|
|||
oso.gaps.forEach((polys, i) => {
|
||||
let off = (i == 0 ? offset1 : offsetN);
|
||||
polys = POLY.offset(polys, -off * 0.8, {z, minArea: 0});
|
||||
// polys.forEach(p => { slice.solids.trimmed.push(p); });
|
||||
top.thin_fill.appendAll(cullIntersections(
|
||||
fillArea(polys, 45, off/2, [], 0.01, off*2),
|
||||
fillArea(polys, 135, off/2, [], 0.01, off*2),
|
||||
// fillArea(polys, 90, off, [], 0.05, off*4),
|
||||
// fillArea(polys, 180, off, [], 0.05, off*4),
|
||||
));
|
||||
gaps = polys;
|
||||
});
|
||||
|
|
@ -481,6 +654,11 @@
|
|||
// use negative offset for inners
|
||||
pi.depth = -(count - countNow);
|
||||
});
|
||||
if (p.inner) {
|
||||
for (let pi of p.inner) {
|
||||
pi.depth = p.depth;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -507,23 +685,6 @@
|
|||
top.last = last;
|
||||
|
||||
shellout += top.shells.length;
|
||||
|
||||
// add anchor extrusion if missing on the first belt layer
|
||||
// todo: fix. disabled because throws off layer min y calculations in some cases
|
||||
if (false && opt.belt0 && top.shells.length === 0 && slice.up && slice.up.tops.length) {
|
||||
for (let up of slice.up.tops) {
|
||||
let bounds = up.poly.bounds,
|
||||
midy = (bounds.miny + bounds.maxy) / 2;
|
||||
if (top.poly.isInside(up.poly, 1)) {
|
||||
slice.widget.belt.ymid = midy;
|
||||
slice.widget.belt.zmid = slice.z;
|
||||
top.shells.push(BASE.newPolygon()
|
||||
.setOpen()
|
||||
.add(bounds.minx,midy,slice.z)
|
||||
.add(bounds.maxx,midy,slice.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -559,6 +720,7 @@
|
|||
density = options.density, // density of infill 0.0 - 1.0
|
||||
bounds = options.bounds, // bounding box of widget
|
||||
height = options.height, // z layer height
|
||||
cache = !(options.cache === false),
|
||||
type = options.type || 'hex';
|
||||
|
||||
if (slice.tops.length === 0 || density === 0.0 || slice.isSolidLayer) {
|
||||
|
|
@ -622,7 +784,7 @@
|
|||
|
||||
// prepare top infill structure
|
||||
tops.forEach(function(top) {
|
||||
top.fill_sparse = [];
|
||||
top.fill_sparse = top.fill_sparse || [];
|
||||
polys.appendAll(top.fill_off);
|
||||
polys.appendAll(top.solids);
|
||||
});
|
||||
|
|
@ -630,7 +792,7 @@
|
|||
// update fill fingerprint for this slice
|
||||
slice._fill_finger = POLY.fingerprint(polys);
|
||||
|
||||
let skippable = FILLFIXED[type] ? true : false;
|
||||
let skippable = cache && FILLFIXED[type] ? true : false;
|
||||
let miss = false;
|
||||
// if the layer below has the same fingerprint,
|
||||
// we may be able to clone the infill instead of regenerating it
|
||||
|
|
@ -779,25 +941,27 @@
|
|||
|
||||
let minarea = minArea || 1,
|
||||
tops = slice.tops,
|
||||
solids = slice.solids,
|
||||
unioned = POLY.union(solids, undefined, true).flat(), // TODO verify
|
||||
solids = slice.solids;
|
||||
|
||||
if (!(tops && solids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let unioned = POLY.union(solids, undefined, true).flat(), // TODO verify
|
||||
isSLA = (spacing === undefined && angle === undefined);
|
||||
|
||||
if (solids.length === 0) return false;
|
||||
if (unioned.length === 0) return false;
|
||||
|
||||
let masks,
|
||||
trims = [],
|
||||
let trims = [],
|
||||
inner = isSLA ? slice.topPolys() : slice.topFillOff();
|
||||
|
||||
// trim each solid to the inner bounds
|
||||
unioned.forEach(function(p) {
|
||||
p.setZ(slice.z);
|
||||
inner.forEach(function(i) {
|
||||
if (p.del) return;
|
||||
masks = p.mask(i);
|
||||
let masks = p.mask(i);
|
||||
if (masks && masks.length > 0) {
|
||||
p.del = true;
|
||||
trims.appendAll(masks);
|
||||
}
|
||||
});
|
||||
|
|
@ -832,6 +996,10 @@
|
|||
|
||||
// create empty filled line array for each top
|
||||
tops.forEach(function(top) {
|
||||
// synth belt anchor tops don't want fill
|
||||
if (!top.fill_lines) {
|
||||
return;
|
||||
}
|
||||
const tofill = [];
|
||||
const angfill = [];
|
||||
const newfill = [];
|
||||
|
|
@ -857,7 +1025,6 @@
|
|||
top.fill_lines_ang.poly.push(af.clone());
|
||||
});
|
||||
}
|
||||
|
||||
top.fill_lines.appendAll(newfill);
|
||||
});
|
||||
|
||||
|
|
@ -865,12 +1032,10 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* calculate external overhangs requiring support.
|
||||
* this is done bottom-up except for fixed supports (manual)
|
||||
* calculate external overhangs requiring support
|
||||
*/
|
||||
function doSupport(slice, proc, auto, fixed, shadow) {
|
||||
let minOffset = proc.sliceSupportOffset,
|
||||
maxBridge = proc.sliceSupportSpan || 5,
|
||||
function doSupport(slice, proc, shadow) {
|
||||
let maxBridge = proc.sliceSupportSpan || 5,
|
||||
minArea = proc.supportMinArea,
|
||||
pillarSize = proc.sliceSupportSize,
|
||||
offset = proc.sliceSupportOffset,
|
||||
|
|
@ -900,7 +1065,7 @@
|
|||
let supported = point.isInPolygonOnly(down_tops);
|
||||
if (!supported) down_traces.forEach(function(trace) {
|
||||
trace.forEachSegment(function(p1, p2) {
|
||||
if (point.distToLine(p1, p2) <= minOffset) {
|
||||
if (point.distToLine(p1, p2) <= offset) {
|
||||
return supported = true;
|
||||
}
|
||||
});
|
||||
|
|
@ -927,7 +1092,7 @@
|
|||
let supports = [];
|
||||
|
||||
// generate support polys from unsupported points
|
||||
if (auto && slice.down) (function() {
|
||||
if (slice.down) (function() {
|
||||
// check trace line support needs
|
||||
traces.forEach(function(trace) {
|
||||
trace.forEachSegment(function(p1, p2) { checkLineSupport(p1, p2, true) });
|
||||
|
|
@ -952,21 +1117,10 @@
|
|||
});
|
||||
})();
|
||||
|
||||
if (supports.length === 0 && !(fixed && fixed.length)) {
|
||||
if (supports.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fixed && fixed.length) {
|
||||
for (let sup of fixed) {
|
||||
let zmin = sup.z - sup.dh / 2;
|
||||
let zmax = sup.z + sup.dh / 2;
|
||||
if (slice.z >= zmin && slice.z <= zmax) {
|
||||
let center = BASE.newPoint(sup.x, sup.y, slice.z);
|
||||
supports.push(BASE.newPolygon().centerRectangle(center, sup.dw, sup.dw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then union supports
|
||||
supports = POLY.union(supports, null, true);
|
||||
|
||||
|
|
@ -984,7 +1138,7 @@
|
|||
|
||||
// set depth hint on support polys for infill density
|
||||
trimmed.forEach(function(trim) {
|
||||
if (trim.area() < 0.1) return;
|
||||
// if (trim.area() < 0.1) return;
|
||||
culled.push(trim.setZ(down.z));
|
||||
});
|
||||
|
||||
|
|
@ -1031,23 +1185,29 @@
|
|||
supports = nsC;
|
||||
}
|
||||
|
||||
if (supports) supports.forEach(function (poly) {
|
||||
if (supports) {
|
||||
fillSupportPolys(supports, linewidth, density, slice.z);
|
||||
}
|
||||
|
||||
// re-assign new supports back to slice
|
||||
slice.supports = supports;
|
||||
};
|
||||
|
||||
function fillSupportPolys(polys, linewidth, density, z) {
|
||||
// calculate fill density
|
||||
let spacing = linewidth * (1 / density);
|
||||
polys.forEach(function (poly) {
|
||||
// angle based on width/height ratio
|
||||
let angle = (poly.bounds.width() / poly.bounds.height() > 1) ? 90 : 0;
|
||||
// calculate fill density
|
||||
let spacing = linewidth * (1 / density);
|
||||
// inset support poly for fill lines 33% of nozzle width
|
||||
let inset = POLY.offset([poly], -linewidth/3, {flat: true, z: slice.z});
|
||||
let inset = POLY.offset([poly], -linewidth/3, {flat: true, z});
|
||||
// do the fill
|
||||
if (inset && inset.length > 0) {
|
||||
fillArea(inset, angle, spacing, poly.fill = []);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// re-assign new supports back to slice
|
||||
slice.supports = supports;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -1126,14 +1286,16 @@
|
|||
}
|
||||
|
||||
FDM.supports = function(settings, widget) {
|
||||
let isBelt = settings.device.bedBelt;
|
||||
let process = settings.process;
|
||||
let size = process.sliceSupportSize;
|
||||
let min = process.sliceSupportArea || 0.1;
|
||||
let buf = new THREE.BufferGeometry();
|
||||
buf.setAttribute('position', new THREE.BufferAttribute(widget.vertices, 3));
|
||||
let min = process.sliceSupportArea || 1;
|
||||
let geo = new THREE.BufferGeometry();
|
||||
geo.setAttribute('position', new THREE.BufferAttribute(widget.vertices, 3));
|
||||
let mat = new THREE.MeshBasicMaterial();
|
||||
let geo = new THREE.Geometry().fromBufferGeometry(buf);
|
||||
let angle = (Math.PI / 180) * settings.process.sliceSupportAngle;
|
||||
let rad = (Math.PI / 180);
|
||||
let deg = (180 / Math.PI);
|
||||
let angle = rad * settings.process.sliceSupportAngle;
|
||||
let thresh = -Math.sin(angle);
|
||||
let dir = new THREE.Vector3(0,0,-1)
|
||||
let add = [];
|
||||
|
|
@ -1167,6 +1329,13 @@
|
|||
if (point.added) {
|
||||
return;
|
||||
}
|
||||
for (let added of add) {
|
||||
let p2 = new THREE.Vector2(point.x, point.y);
|
||||
let pm = new THREE.Vector2(added.mid.x, added.mid.y);
|
||||
if (p2.distanceTo(pm) < 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let ray = new THREE.Raycaster(point, dir);
|
||||
let int = ray.intersectObjects([ mesh, platform ], false);
|
||||
if (int && int.length && int[0].distance > 0.01) {
|
||||
|
|
@ -1175,20 +1344,33 @@
|
|||
point.added = true;
|
||||
}
|
||||
}
|
||||
geo.faces.filter(f => f.normal.z < thresh).forEach(face => {
|
||||
let a = geo.vertices[face.a];
|
||||
let b = geo.vertices[face.b];
|
||||
let c = geo.vertices[face.c];
|
||||
let filter = isBelt ? (norm) => {
|
||||
return norm.z < thresh && norm.y < -0.001;
|
||||
} : (norm) => {
|
||||
return norm.z < thresh;
|
||||
};
|
||||
let { position } = geo.attributes;
|
||||
let { itemSize, count, array } = position;
|
||||
for (let i = 0; i<count; i += 3) {
|
||||
let ip = i * itemSize;
|
||||
let a = new THREE.Vector3(array[ip++], array[ip++], array[ip++]);
|
||||
let b = new THREE.Vector3(array[ip++], array[ip++], array[ip++]);
|
||||
let c = new THREE.Vector3(array[ip++], array[ip++], array[ip++]);
|
||||
let norm = THREE.computeFaceNormal(a,b,c);
|
||||
// limit to downward faces
|
||||
if (!filter(norm)) {
|
||||
continue;
|
||||
}
|
||||
// skip tiny faces
|
||||
let area = BASE.newPolygon().addPoints([a,b,c]).area();
|
||||
if (BASE.newPolygon().addPoints([a,b,c]).area() < min) {
|
||||
skip++;
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
tp(new THREE.Vector3().add(a).add(b).add(c).divideScalar(3));
|
||||
tl(a,b);
|
||||
tl(b,c);
|
||||
tl(a,c);
|
||||
});
|
||||
}
|
||||
widget.supports = add;
|
||||
return add.length > 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@
|
|||
e = o.point;
|
||||
e.x += p.max.w / 2 - m.fit.x;
|
||||
e.y += p.max.h / 2 - m.fit.y;
|
||||
// e.z = 0;
|
||||
e.z = 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -476,6 +476,8 @@
|
|||
// };
|
||||
// } else
|
||||
// load renderer code in worker context only
|
||||
let wasm;
|
||||
|
||||
fetch('/wasm/kiri-sla.wasm')
|
||||
.then(response => response.arrayBuffer())
|
||||
.then(bytes => WebAssembly.instantiate(bytes, {
|
||||
|
|
@ -488,7 +490,7 @@
|
|||
let {module, instance} = results;
|
||||
let {exports} = instance;
|
||||
let heap = new Uint8Array(exports.memory.buffer);
|
||||
self.wasm = {
|
||||
wasm = {
|
||||
heap,
|
||||
memory: exports.memory,
|
||||
render: exports.render,
|
||||
|
|
@ -502,7 +504,6 @@
|
|||
let width2 = width / 2, height2 = height / 2;
|
||||
let array = [];
|
||||
let count = 0;
|
||||
let wasm = self.wasm;
|
||||
|
||||
function scaleMovePoly(poly) {
|
||||
let points = poly.points;
|
||||
|
|
|
|||
|
|
@ -181,6 +181,15 @@ MOTO.CTRL = function (object, domElement, notify, slider) {
|
|||
}
|
||||
};
|
||||
|
||||
this.getTarget = function() {
|
||||
return this.target;
|
||||
};
|
||||
|
||||
this.setTarget = function(t) {
|
||||
this.target = t;
|
||||
this.target0 = t.clone();
|
||||
}
|
||||
|
||||
function isValue(v) {
|
||||
return v !== null && v !== undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,13 @@
|
|||
PI2 = PI / 2,
|
||||
PI4 = PI / 4,
|
||||
ROUND = Math.round,
|
||||
panX = 0,
|
||||
panY = 0,
|
||||
panZ = 0,
|
||||
home = 0,
|
||||
gridZOff = 0,
|
||||
tweenTime = 500,
|
||||
tweenDelay = 20,
|
||||
platformZOff = 0,
|
||||
perspective = 35,
|
||||
refreshTimeout = null,
|
||||
|
|
@ -92,6 +97,7 @@
|
|||
camera,
|
||||
renderer,
|
||||
container,
|
||||
raycaster,
|
||||
freezeTo,
|
||||
freeze,
|
||||
isRound = false,
|
||||
|
|
@ -139,7 +145,7 @@
|
|||
|
||||
function tweenit() {
|
||||
TWEEN.update();
|
||||
setTimeout(tweenit, 20);
|
||||
setTimeout(tweenit, tweenDelay);
|
||||
}
|
||||
|
||||
tweenit();
|
||||
|
|
@ -170,12 +176,13 @@
|
|||
}
|
||||
}
|
||||
new TWEEN.Tween(from).
|
||||
to(to, 500).
|
||||
to(to, tweenTime).
|
||||
onUpdate(tf).
|
||||
onComplete(() => {
|
||||
viewControl.setPosition(pos);
|
||||
updateLastAction();
|
||||
refresh();
|
||||
if (pos.then) pos.then();
|
||||
}).
|
||||
start();
|
||||
}
|
||||
|
|
@ -195,7 +202,7 @@
|
|||
setGrid();
|
||||
};
|
||||
new TWEEN.Tween(from).
|
||||
to(to, 500).
|
||||
to(to, tweenTime).
|
||||
onStart(start).
|
||||
onUpdate(update).
|
||||
onComplete(complete).
|
||||
|
|
@ -676,14 +683,15 @@
|
|||
if (points.length % 2 != 0) {
|
||||
throw "invalid line : "+points.length;
|
||||
}
|
||||
const geo = new THREE.Geometry();
|
||||
for (let i=0; i < points.length; ) {
|
||||
const p1 = points[i++];
|
||||
const p2 = points[i++];
|
||||
geo.vertices.push(new THREE.Vector3(p1.x, p1.y, p1.z));
|
||||
geo.vertices.push(new THREE.Vector3(p2.x, p2.y, p2.z));
|
||||
const geo = new THREE.BufferGeometry();
|
||||
const vrt = new Float32Array(points.length * 3);
|
||||
let vi = 0;
|
||||
for (let p of points) {
|
||||
vrt[vi++] = p.x;
|
||||
vrt[vi++] = p.y;
|
||||
vrt[vi++] = p.z;
|
||||
}
|
||||
geo.verticesNeedUpdate = true;
|
||||
geo.setAttribute('position', new THREE.BufferAttribute(vrt, 3));
|
||||
return new THREE.LineSegments(geo, new THREE.LineBasicMaterial({
|
||||
color: color,
|
||||
opacity: opacity || 1,
|
||||
|
|
@ -692,9 +700,7 @@
|
|||
}
|
||||
|
||||
function intersect(objects, recurse) {
|
||||
let lookAt = new THREE.Vector3(mouse.x, mouse.y, 0.0).unproject(camera);
|
||||
let ray = new THREE.Raycaster(camera.position, lookAt.sub(camera.position).normalize());
|
||||
return ray.intersectObjects(objects, recurse);
|
||||
return raycaster.intersectObjects(objects, recurse);
|
||||
}
|
||||
|
||||
/** ******************************************************************
|
||||
|
|
@ -802,6 +808,11 @@
|
|||
updateLastAction();
|
||||
let int, vis;
|
||||
|
||||
const mv = new THREE.Vector2();
|
||||
mv.x = ( event.clientX / window.innerWidth ) * 2 - 1;
|
||||
mv.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
|
||||
raycaster.setFromCamera( mv, camera );
|
||||
|
||||
if (viewControl.enabled) {
|
||||
event.preventDefault();
|
||||
let selection = mouseHover ? mouseHover() : null;
|
||||
|
|
@ -847,6 +858,7 @@
|
|||
onEnterKey: onEnterKey,
|
||||
onResize: onResize,
|
||||
update: requestRefresh,
|
||||
raycast: intersect,
|
||||
refresh: refresh,
|
||||
|
||||
showSkyGrid: function(b) {
|
||||
|
|
@ -884,6 +896,7 @@
|
|||
},
|
||||
|
||||
platform: {
|
||||
update: updateDraws,
|
||||
tweenTo: tweenPlatform,
|
||||
setSize: setPlatformSizeUpdateGrid,
|
||||
setColor: setPlatformColor,
|
||||
|
|
@ -896,6 +909,7 @@
|
|||
add: function(o) { WORLD.add(o) },
|
||||
remove: function(o) { WORLD.remove(o) },
|
||||
setMaxZ: function(z) { panY = z / 2 },
|
||||
setCenter: function(x,y,z) { panX = x; panY = z, panZ = y },
|
||||
isHidden: function() { return !showPlatform },
|
||||
setHidden: function(b) { showPlatform = !b; platform.visible = !b },
|
||||
setHiding: function(b) { hidePlatformBelow = b },
|
||||
|
|
@ -935,12 +949,12 @@
|
|||
},
|
||||
|
||||
view: {
|
||||
top: function() { tweenCam({left: 0, up: 0, panX: 0, panY: panY, panZ: 0}) },
|
||||
back: function() { tweenCam({left: PI, up: PI2, panX: 0, panY: panY, panZ: 0}) },
|
||||
home: function() { tweenCam({left: 0, up: PI4, panX: 0, panY: panY, panZ: 0}) },
|
||||
front: function() { tweenCam({left: 0, up: PI2, panX: 0, panY: panY, panZ: 0}) },
|
||||
right: function() { tweenCam({left: PI2, up: PI2, panX: 0, panY: panY, panZ: 0}) },
|
||||
left: function() { tweenCam({left: -PI2, up: PI2, panX: 0, panY: panY, panZ: 0}) },
|
||||
top: function(then) { tweenCam({left: home, up: 0, panX, panY, panZ, then}) },
|
||||
back: function(then) { tweenCam({left: PI, up: PI2, panX, panY, panZ, then}) },
|
||||
home: function(then) { tweenCam({left: home, up: PI4, panX, panY, panZ, then}) },
|
||||
front: function(then) { tweenCam({left: 0, up: PI2, panX, panY, panZ, then}) },
|
||||
right: function(then) { tweenCam({left: PI2, up: PI2, panX, panY, panZ, then}) },
|
||||
left: function(then) { tweenCam({left: -PI2, up: PI2, panX, panY, panZ, then}) },
|
||||
reset: function() { viewControl.reset(); requestRefresh() },
|
||||
load: function(cam) { viewControl.setPosition(cam) },
|
||||
save: function() { return viewControl.getPosition(true) },
|
||||
|
|
@ -953,7 +967,30 @@
|
|||
viewControl.setMouse(viewControl.mouseDefault);
|
||||
}
|
||||
},
|
||||
getFPS: function() { return fps }
|
||||
getFPS: function() { return fps },
|
||||
getFocus: function() { return viewControl.getTarget() },
|
||||
setFocus: function(v) {
|
||||
viewControl.setTarget(v);
|
||||
refresh();
|
||||
},
|
||||
setHome: function(r) {
|
||||
home = r || 0;
|
||||
},
|
||||
spin: function(then, count) {
|
||||
Space.view.front(() => {
|
||||
Space.view.right(() => {
|
||||
Space.view.back(() => {
|
||||
Space.view.left(() => {
|
||||
if (--count > 0) {
|
||||
Space.view.spin(then, count);
|
||||
} else {
|
||||
Space.view.front(then);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
mouse: {
|
||||
|
|
@ -973,6 +1010,14 @@
|
|||
selectRecurse = b;
|
||||
},
|
||||
|
||||
setTweenTime: function(t) {
|
||||
tweenTime = t || 500;
|
||||
},
|
||||
|
||||
setTweenDelay: function(d) {
|
||||
tweenDelay = d || 20;
|
||||
},
|
||||
|
||||
objects: function() {
|
||||
return WC;
|
||||
},
|
||||
|
|
@ -985,7 +1030,7 @@
|
|||
return { renderer, camera, platform };
|
||||
},
|
||||
|
||||
init: function(domelement, slider) {
|
||||
init: function(domelement, slider, ortho) {
|
||||
container = domelement;
|
||||
|
||||
WORLD.rotation.x = -PI2;
|
||||
|
|
@ -998,14 +1043,16 @@
|
|||
antialias: true,
|
||||
preserveDrawingBuffer: true
|
||||
});
|
||||
camera = perspective ?
|
||||
new THREE.PerspectiveCamera(perspective, aspect(), 5, 100000) :
|
||||
new THREE.OrthographicCamera(-100 * aspect(), 100 * aspect(), 100, -100, 0.1, 100000);
|
||||
camera = ortho ?
|
||||
new THREE.OrthographicCamera(-100 * aspect(), 100 * aspect(), 100, -100, 0.1, 100000) :
|
||||
new THREE.PerspectiveCamera(perspective, aspect(), 5, 100000);
|
||||
|
||||
camera.position.set(0, 200, 340);
|
||||
renderer.setSize(width(), height());
|
||||
domelement.appendChild(renderer.domElement);
|
||||
|
||||
raycaster = new THREE.Raycaster();
|
||||
|
||||
viewControl = new MOTO.CTRL(camera, domelement, function (position, moved) {
|
||||
if (platform) {
|
||||
platform.visible = hidePlatformBelow ?
|
||||
|
|
|
|||
|
|
@ -43,12 +43,12 @@
|
|||
#jbody, #gbody {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#jfoot {
|
||||
#jfoot, #dfoot {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
#jfoot button {
|
||||
#jfoot button, #dfoot button {
|
||||
width: 100%;
|
||||
}
|
||||
#gbody {
|
||||
|
|
@ -58,6 +58,7 @@
|
|||
overflow: auto;
|
||||
}
|
||||
#gfoot {
|
||||
display: none;
|
||||
background-color: rgba(61,133,198,0.25);
|
||||
border-top: 1px solid #aaa;
|
||||
padding: 3px;
|
||||
|
|
@ -66,6 +67,9 @@
|
|||
#api {
|
||||
width: 812px;
|
||||
}
|
||||
#download {
|
||||
display: none;
|
||||
}
|
||||
li {
|
||||
list-style: circle;
|
||||
}
|
||||
|
|
@ -77,7 +81,7 @@
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
|
||||
<script src="/code/engine.js"></script>
|
||||
<script>
|
||||
let edit;
|
||||
let edit, saveit = "";
|
||||
function $(id) { return document.getElementById(id) }
|
||||
function onload() {
|
||||
let fnstr = demo.toString().split("\n");
|
||||
|
|
@ -97,10 +101,14 @@
|
|||
$('gfoot').innerText = msg ? Object.keys(msg).join(' - ') : '';
|
||||
}
|
||||
function display_gcode(gcode) {
|
||||
$('gbody').innerText = gcode;
|
||||
$('gbody').innerText = saveit = gcode;
|
||||
display_message();
|
||||
$('dfoot').style.display = 'block';
|
||||
$('gfoot').style.display = '';
|
||||
}
|
||||
function run_code() {
|
||||
$('dfoot').style.display = 'none';
|
||||
$('gfoot').style.display = 'block';
|
||||
let code = edit.session.getValue();
|
||||
eval(`(function(){${code}})()`);
|
||||
}
|
||||
|
|
@ -108,11 +116,28 @@
|
|||
kiri.newEngine()
|
||||
.setListener(display_message)
|
||||
.load("/obj/cube.stl")
|
||||
.then(eng => eng.setProcess({
|
||||
sliceShells: 1,
|
||||
sliceFillSparse: 0.25,
|
||||
sliceTopLayers: 2,
|
||||
sliceSolidLayers: 2,
|
||||
sliceBottomLayers: 2
|
||||
}))
|
||||
.then(eng => eng.setDevice({
|
||||
gcodePre: [ "M82", "M104 S220" ],
|
||||
gcodePost: [ "M107" ]
|
||||
}))
|
||||
.then(eng => eng.slice())
|
||||
.then(eng => eng.prepare())
|
||||
.then(eng => eng.export())
|
||||
.then(display_gcode);
|
||||
}
|
||||
function download() {
|
||||
let blob = new Blob([saveit], {type: "octet/stream"});
|
||||
let url = window.URL.createObjectURL(blob);
|
||||
$('download').innerHTML = `<a id="xo" href="${url}" download="sample.gcode"></a>`;
|
||||
$('xo').click();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="onload()">
|
||||
|
|
@ -127,6 +152,7 @@
|
|||
<div id="ghead">gcode output</div>
|
||||
<div id="gbody"></div>
|
||||
<div id="gfoot"></div>
|
||||
<div id="dfoot"><button onclick="download()">download</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="api">
|
||||
|
|
@ -145,5 +171,6 @@
|
|||
<li><label>prepare()</label> - async path routing of slice data</li>
|
||||
<li><label>export()</label> - async gcode generation from path routing</li>
|
||||
</div>
|
||||
<a id="download"></a>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ th, tr, td, label {
|
|||
#app-mode, #app-acct {
|
||||
width: 125px;
|
||||
}
|
||||
#app-mode:hover #mode-info {
|
||||
#mode-info.hoverpop {
|
||||
display: flex;
|
||||
}
|
||||
#mode-info {
|
||||
|
|
@ -295,7 +295,7 @@ th, tr, td, label {
|
|||
padding-right: 5px;
|
||||
}
|
||||
|
||||
#app-name:hover #app-info {
|
||||
#app-info.hoverpop {
|
||||
display: flex;
|
||||
}
|
||||
#app-info {
|
||||
|
|
@ -317,8 +317,8 @@ th, tr, td, label {
|
|||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
#app-acct:hover #acct-pop {
|
||||
display: flex;
|
||||
#acct-pop.hoverpop {
|
||||
display: flex !important;
|
||||
}
|
||||
#acct-pop {
|
||||
display: none;
|
||||
|
|
@ -441,7 +441,7 @@ th, tr, td, label {
|
|||
background-color: rgba(255,255,255,0.85);
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
border-radius: 3px;
|
||||
width: 60px;
|
||||
min-width: 60px;
|
||||
color: var(--fg-gray);
|
||||
}
|
||||
.pop-lcol > div:hover {
|
||||
|
|
@ -471,10 +471,10 @@ th, tr, td, label {
|
|||
.lt-menu label {
|
||||
font-size: smaller;
|
||||
}
|
||||
.lt-enabled {
|
||||
.lt-enabled, .lt-active {
|
||||
color: var(--fg-gray);
|
||||
}
|
||||
.lt-enabled:hover {
|
||||
.lt-enabled:hover, .lt-active:hover {
|
||||
background-color: #eee;
|
||||
border: 1px solid #aaa;
|
||||
color: #000;
|
||||
|
|
@ -482,6 +482,9 @@ th, tr, td, label {
|
|||
.lt-enabled:hover .pop-lcol {
|
||||
display: flex;
|
||||
}
|
||||
.lt-active .hoverpop {
|
||||
display: flex;
|
||||
}
|
||||
@media only screen and (max-height : 800px) {
|
||||
.lt-menu, .pop-lcol {
|
||||
font-size: 16px !important;
|
||||
|
|
@ -524,7 +527,7 @@ th, tr, td, label {
|
|||
.txt-sel button, .btn-sel {
|
||||
background-color: #ccc;
|
||||
}
|
||||
#pop-rotate .value, #pop-scale .value {
|
||||
#pop-rotate input.value, #pop-scale input.value {
|
||||
width: 90%;
|
||||
}
|
||||
#pop-rotate label {
|
||||
|
|
@ -870,8 +873,8 @@ th, tr, td, label {
|
|||
min-height: 4em !important;
|
||||
}
|
||||
#code-preview-textarea {
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
width: 40em;
|
||||
height: 12em;
|
||||
font-size: 10px;
|
||||
}
|
||||
.mod-end {
|
||||
|
|
@ -962,6 +965,8 @@ th, tr, td, label {
|
|||
}
|
||||
#help .content li {
|
||||
line-height: 1.75em;
|
||||
padding-left: 22px ;
|
||||
text-indent: -22px ;
|
||||
}
|
||||
#help .footer {
|
||||
font-family: monospace;
|
||||
|
|
@ -1239,6 +1244,17 @@ th, tr, td, label {
|
|||
width: 20px;
|
||||
}
|
||||
|
||||
#top-slider {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 60px;
|
||||
left: 50px;
|
||||
right: 50px;
|
||||
}
|
||||
#anim-slider {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#alert-area {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
|
|
@ -1500,3 +1516,43 @@ th, tr, td, label {
|
|||
border-top: 1px solid #ddd;
|
||||
margin: 5px 0 5px 0;
|
||||
}
|
||||
|
||||
#lab-axis, #lab-scale {
|
||||
padding: 0 6px 0 6px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
#lab-axis:hover, #lab-scale:hover {
|
||||
background-color: rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.range-info {
|
||||
position: relative;
|
||||
}
|
||||
.range-info:hover .range-detail {
|
||||
display: flex;
|
||||
}
|
||||
.range-detail {
|
||||
position: absolute;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
bottom: 50%;
|
||||
right: 100%;
|
||||
padding: 5px;
|
||||
margin: 0 10px 0 10px;
|
||||
font-size: smaller;
|
||||
font-family: monospace;
|
||||
transform: translateY(50%);
|
||||
background-color: rgba(255,255,255,0.8);
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.range-detail label.pad {
|
||||
padding-right: 8px;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
.range-detail label.val {
|
||||
font-weight: bold;
|
||||
}
|
||||
.range-detail span {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="author" content="Stewart Allen">
|
||||
<meta name="keywords" content="3d slicer,slicer,3d slicing,cnc,cam,toolpaths,toolpath generation,kiri,kirimoto,kiri:moto,gcode,cura,simplify 3d,prusaslicer,fdm,sla" />
|
||||
<meta name="keywords" content="3d slicer,chromebook,slicer,3d slicing,cnc,cam,toolpaths,toolpath generation,kiri,kirimoto,kiri:moto,gcode,cura,simplify 3d,prusaslicer,fdm,sla" />
|
||||
<meta name="copyright" content="stewart allen [sa@grid.space]">
|
||||
<meta name="description" content="Browser-based 3D slicer, gcode and CNC toolpath generator">
|
||||
<meta property="og:description" content="Kiri:Moto is a unique 3D slicer that runs entirely in browser and creates output for your favorite maker tools: 3D Printers, CNC Mills and Laser Cutters.">
|
||||
|
|
@ -45,17 +45,20 @@
|
|||
<div id="acct-pop" class="f-col">
|
||||
<div id="acct-menu" class="f-col">
|
||||
<div id="acct-lang">
|
||||
<label><i class="fas fa-caret-left"></i> language</label>
|
||||
<label><i class="fas fa-caret-left"></i> <span lk="language">language</span></label>
|
||||
<div id="lang-pop" class="f-col">
|
||||
<div id="lset-en">english</div>
|
||||
<div id="lset-da">danish</div>
|
||||
<div id="lset-en">english</div>
|
||||
<div id="lset-fr">french</div>
|
||||
<div id="lset-de">german</div>
|
||||
<div id="lset-pl">polish</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="acct-export" class="f-col a-end">
|
||||
<label>export</label>
|
||||
<label lk="export">export</label>
|
||||
</div>
|
||||
<div id="acct-help" class="f-col a-end">
|
||||
<label>help</label>
|
||||
<label lk="help">help</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -72,104 +75,104 @@
|
|||
<i class="fas fa-times-circle"></i>
|
||||
</div>
|
||||
<div id="lt-top"></div>
|
||||
<div id="lt-setup" class="lt-menu lt-enabled">
|
||||
<div id="lt-setup" class="lt-menu lt-active">
|
||||
<i class="fas fa-cogs"></i>
|
||||
<label>setup</label>
|
||||
<label lk="setup">setup</label>
|
||||
<div id="set-pop" class="pop-lcol f-row">
|
||||
<div id="set-device">
|
||||
<i class="fas fa-cube"></i>
|
||||
<label>machine</label>
|
||||
<label lk="machine">machine</label>
|
||||
</div>
|
||||
<div id="set-tools">
|
||||
<i class="fas fa-tools"></i>
|
||||
<label>tools<label>
|
||||
<label lk="tools">tools<label>
|
||||
</div>
|
||||
<div id="set-prefs">
|
||||
<i class="fas fa-sliders-h"></i>
|
||||
<label>prefs<label>
|
||||
<label lk="prefs">prefs<label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="lt-file" class="lt-menu lt-enabled">
|
||||
<div id="lt-file" class="lt-menu lt-active">
|
||||
<i class="fas fa-folder"></i>
|
||||
<label>files</label>
|
||||
<label lk="files">files</label>
|
||||
<div id="file-pop" class="pop-lcol f-row">
|
||||
<div id="file-recent">
|
||||
<i class="fas fa-list"></i>
|
||||
<label>recent</label>
|
||||
<label lk="recent">recent</label>
|
||||
</div>
|
||||
<div id="file-import">
|
||||
<i class="fas fa-file-upload"></i>
|
||||
<label>import<label>
|
||||
<label lk="import">import<label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="act-sep"></div>
|
||||
<div id="lt-view" class="lt-menu lt-enabled">
|
||||
<div id="lt-view" class="lt-menu lt-active">
|
||||
<i class="fas fa-eye"></i>
|
||||
<label>view</label>
|
||||
<label lk="view">view</label>
|
||||
<div id="pop-view" class="pop-lcol f-row">
|
||||
<div id="view-arrange">
|
||||
<i class="fas fa-th"></i>
|
||||
<label>arrange</label>
|
||||
<label lk="arrange">arrange</label>
|
||||
</div>
|
||||
<div id="view-top">
|
||||
<i class="fas fa-square"></i>
|
||||
<label>top</label>
|
||||
<label lk="top">top</label>
|
||||
</div>
|
||||
<div id="view-home">
|
||||
<i class="fas fa-home"></i>
|
||||
<label>home</label>
|
||||
<label lk="home">home</label>
|
||||
</div>
|
||||
<div id="view-clear">
|
||||
<i class="far fa-square"></i>
|
||||
<label>clear</label>
|
||||
<label lk="clear">clear</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="act-slice" class="lt-menu lt-enabled">
|
||||
<div id="act-slice" class="lt-menu lt-active">
|
||||
<i class="fas fa-bars"></i>
|
||||
<label id="label-slice" title="analyze parts">slice</label>
|
||||
<label id="label-slice" title="analyze parts" lk="slice">slice</label>
|
||||
<div id="pop-slice" class="pop-lcol f-row">
|
||||
<div id="act-preview">
|
||||
<i class="fas fa-cubes"></i>
|
||||
<label id="label-preview" title="show routing and paths">preview</label>
|
||||
<label id="label-preview" title="show routing and paths" lk="preview">preview</label>
|
||||
</div>
|
||||
<div id="act-animate">
|
||||
<i class="fas fa-running"></i>
|
||||
<label id="label-animate" title="render routing on a mesh">animate</label>
|
||||
<label id="label-animate" title="render routing on a mesh" lk="animate">animate</label>
|
||||
</div>
|
||||
<div id="act-export">
|
||||
<i class="fas fa-file-download"></i>
|
||||
<label id="label-export" title="generate downloadable files">export</label>
|
||||
<label id="label-export" title="generate downloadable files" lk="export">export</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="lt-sep"></div>
|
||||
<div id="lt-render" class="lt-menu lt-enabled">
|
||||
<div id="lt-render" class="lt-menu lt-active">
|
||||
<i class="fas fa-border-style"></i>
|
||||
<label>render</label>
|
||||
<label lk="render">render</label>
|
||||
<div id="pop-render" class="pop-lcol f-row">
|
||||
<div id="render-solid" class="grow a-center">
|
||||
<i class="fas fa-th-large"></i>
|
||||
<label>solid</label>
|
||||
<label lk="solid">solid</label>
|
||||
</div>
|
||||
<div id="render-wire" class="grow a-center">
|
||||
<i class="fas fa-border-all"></i>
|
||||
<label>wire</label>
|
||||
<label lk="wire">wire</label>
|
||||
</div>
|
||||
<div id="render-ghost" class="grow a-center">
|
||||
<i class="fas fa-border-none"></i>
|
||||
<label>ghost</label>
|
||||
<label lk="ghost">ghost</label>
|
||||
</div>
|
||||
<div id="render-hide" class="grow a-center">
|
||||
<label>hide</label>
|
||||
<label lk="hide">hide</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="lt-rotate" class="lt-menu">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
<label>rotate</label>
|
||||
<label lk="rotate">rotate</label>
|
||||
<div id="pop-rotate" class="pop-lcol f-row russo">
|
||||
<div>
|
||||
<div class="grow a-center">
|
||||
|
|
@ -196,12 +199,12 @@
|
|||
<input id="rot_z" class="value center" size="5"/ value="0">
|
||||
</div>
|
||||
<!-- <div id="lay-flat" class="f-col j-center center">lay flat</div> -->
|
||||
<div id="unrotate" class="f-col j-center">reset</div>
|
||||
<div id="unrotate" class="f-col j-center" lk="reset">reset</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="lt-scale" class="lt-menu">
|
||||
<i class="fas fa-expand"></i>
|
||||
<label>scale</label>
|
||||
<label lk="scale">scale</label>
|
||||
<div id="pop-scale" class="pop-lcol f-row russo">
|
||||
<div>
|
||||
<input id="lock_x" type="checkbox" checked/>
|
||||
|
|
@ -222,9 +225,9 @@
|
|||
<div><input id="scale_z" xsize="8" class="value" value="1"/></div>
|
||||
</div>
|
||||
<div class="f-col j-center">
|
||||
<div><label>axis</label></div>
|
||||
<div><label>size</label></div>
|
||||
<div><label>scale</label></div>
|
||||
<div><label id="lab-axis" lk="axis">axis</label></div>
|
||||
<div><label id="lab-size" lk="size">size</label></div>
|
||||
<div><label id="lab-scale" lk="scale">scale</label></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -249,7 +252,7 @@
|
|||
</div>
|
||||
<div id="mod-setup" class="mdialog f-row">
|
||||
<div class="f-col left a-stretch">
|
||||
<label class="header">select a device type</label>
|
||||
<label class="header" lk="dm_sldt">select a device type</label>
|
||||
<div class="f-col">
|
||||
<table><tr>
|
||||
<th><button id="mode-fdm" class="dev-type"><label>FDM</label></button></th>
|
||||
|
|
@ -260,7 +263,7 @@
|
|||
</tr></table>
|
||||
</div>
|
||||
<div class="header sub f-col j-center">
|
||||
<label>standard devices</label>
|
||||
<label lk="dm_stdd">standard devices</label>
|
||||
<div id="dev-search">
|
||||
<i class="fas fa-search"></i>
|
||||
<input id="dev-filter" />
|
||||
|
|
@ -269,20 +272,20 @@
|
|||
<div class="f-col mh0 mh35 j-center a-stretch">
|
||||
<div id="device-list" class="devlist f-col overy"></div>
|
||||
</div>
|
||||
<label class="header sub">my devices</label>
|
||||
<label class="header sub" lk="dm_mydd">my devices</label>
|
||||
<div class="f-col grow">
|
||||
<div id="device-my" class="devlist f-col grow overy"></div>
|
||||
<div class="f-row footer">
|
||||
<div class="grow"></div>
|
||||
<button id="device-add">copy</button>
|
||||
<button id="device-del">delete</button>
|
||||
<button id="device-exp">export</button>
|
||||
<button id="device-add" lk="copy">copy</button>
|
||||
<button id="device-del" lk="delete">delete</button>
|
||||
<button id="device-exp" lk="export">export</button>
|
||||
<div class="grow"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="f-col grow a-stretch">
|
||||
<label class="header">selected device</label>
|
||||
<label class="header" lk="dm_seld">selected device</label>
|
||||
<div class="f-row">
|
||||
<div id="device1" class="f-col t-body t-inset overy grow"></div>
|
||||
<div class="t-pad"></div>
|
||||
|
|
@ -296,27 +299,27 @@
|
|||
</div>
|
||||
<div id="device-action" class="f-row footer">
|
||||
<div class="grow"></div>
|
||||
<button id="device-save">save</button>
|
||||
<button id="device-save" lk="save">save</button>
|
||||
<div class="grow"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mod-files" class="mdialog f-col">
|
||||
<label class="set-header">recent files</label>
|
||||
<label class="set-header" lk="dm_rcnt">recent files</label>
|
||||
<div id="catalogList" class="f-col"></div>
|
||||
</div>
|
||||
<div id="mod-saves" class="mdialog f-col">
|
||||
<label class="set-header">saved settings</label>
|
||||
<label class="set-header" lk="dm_savs">saved settings</label>
|
||||
<div id="settingsList" class="f-col"></div>
|
||||
</div>
|
||||
<div id="mod-tools" class="mdialog">
|
||||
<div class="f-col">
|
||||
<div class="f-row t-head">
|
||||
<label class="t-33">tool</label>
|
||||
<label class="t-33" lk="tool">tool</label>
|
||||
<div class="t-pad"></div>
|
||||
<label class="t-33">detail</label>
|
||||
<label class="t-33" lk="detail">detail</label>
|
||||
<div class="t-pad"></div>
|
||||
<label class="t-33">view</label>
|
||||
<label class="t-33" lk="view">view</label>
|
||||
</div>
|
||||
<div class="f-row">
|
||||
<div class="f-col t-33">
|
||||
|
|
@ -324,23 +327,23 @@
|
|||
</div>
|
||||
<div class="t-pad"></div>
|
||||
<div class="f-col t-33 t-body t-inset">
|
||||
<div class="f-row var-row"><label>name</label><input id="tool-name" size="15"></input></div>
|
||||
<div class="f-row var-row"><label>type</label>
|
||||
<div class="f-row var-row"><label lk="name">name</label><input id="tool-name" size="15"></input></div>
|
||||
<div class="f-row var-row"><label lk="type">type</label>
|
||||
<select id="tool-type">
|
||||
<option value="endmill" selected>end</option>
|
||||
<option value="ballmill">ball</option>
|
||||
<option value="tapermill">taper</option>
|
||||
<option value="endmill" lk="td_tyem" selected>end</option>
|
||||
<option value="ballmill" lk="td_tybm">ball</option>
|
||||
<option value="tapermill" lk="td_tytm">taper</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="f-row var-row" title="tool number to use
in gcode commands"><label>tool #</label><input id="tool-num" size="7"></input></div>
|
||||
<div class="f-row var-row"><label>metric</label><input id="tool-metric" type="checkbox"></input></div>
|
||||
<div class="set-header f-col">shaft</div>
|
||||
<div class="f-row var-row" title="tool number to use
in gcode commands"><label lk="td_tonm">tool #</label><input id="tool-num" size="7"></input></div>
|
||||
<div class="f-row var-row"><label lk="metric">metric</label><input id="tool-metric" type="checkbox"></input></div>
|
||||
<div class="set-header f-col" lk="td_shft">shaft</div>
|
||||
<div class="f-row var-row" title="shaft diameter in inches
unless metric is checked
then in millimeters"><label>diameter</label><input id="tool-sdiam" size="7"></input></div>
|
||||
<div class="f-row var-row" title="shaft length in inches
unless metric is checked
then in millimeters"><label>length</label><input id="tool-slen" size="7"></input></div>
|
||||
<div class="set-header f-col">flute</div>
|
||||
<div class="set-header f-col" lk="td_flut">flute</div>
|
||||
<div class="f-row var-row" title="flute diameter in inches
unless metric is checked
then in millimeters"><label>diameter</label><input id="tool-fdiam" size="7"></input></div>
|
||||
<div class="f-row var-row" title="flute length in inches
unless metric is checked
then in millimeters"><label>length</label><input id="tool-flen" size="7"></input></div>
|
||||
<div class="set-header f-col">taper</div>
|
||||
<div class="set-header f-col" ln="td_tapr">taper</div>
|
||||
<!-- <div class="flow-row" title="taper angle"><label>angle</label><input id="tool-tangle" size=5></input></div> -->
|
||||
<div class="f-row var-row" title="tip width in inches
unless metric is checked
then in millimeters"><label>tip</label><input id="tool-ttip" size="7"></input></div>
|
||||
</div>
|
||||
|
|
@ -351,13 +354,13 @@
|
|||
<button id="tool-add"><i class="fas fa-plus"></i></button>
|
||||
<button id="tool-del"><i class="fas fa-minus"></i></button>
|
||||
<div class="t-pad2"></div>
|
||||
<button id="tools-save">save</button>
|
||||
<button id="tools-close">done</button>
|
||||
<button id="tools-save" lk="save">save</button>
|
||||
<button id="tools-close" lk="done">done</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mod-prefs" class="mdialog f-col a-center">
|
||||
<b>Application Preferences</b>
|
||||
<b lk="dm_appp">Application Preferences</b>
|
||||
<hr width="80%">
|
||||
<div class="f-row">
|
||||
<div id="prefs-gen1" class="f-col"></div>
|
||||
|
|
@ -378,7 +381,7 @@
|
|||
<div id="mod-print" class="mdialog f-col"></div>
|
||||
<div id="mod-any" class="mdialog f-col"></div>
|
||||
<!-- hidden file input loader -->
|
||||
<input id="load-file" type="file" name="loadme" style="display:none" accept=".stl,.gcode,.nc,.km,.b64,.png"/>
|
||||
<input id="load-file" type="file" name="loadme" style="display:none"/>
|
||||
<div class="mod-end"></div></div>
|
||||
</div>
|
||||
<div id="layer-slider" class="f-col a-stretch">
|
||||
|
|
@ -440,13 +443,14 @@
|
|||
</div>
|
||||
<div id="tool-info" class="noshow"></div>
|
||||
<div id="context-menu">
|
||||
<button id="context-clear-workspace">clear workspace</button>
|
||||
<button id="context-export-workspace">export workspace</button>
|
||||
<button id="context-clear-workspace" lk="rc_clws">clear workspace</button>
|
||||
<button id="context-export-workspace" lk="rc_xpws">export workspace</button>
|
||||
<div class="sep"></div>
|
||||
<button id="context-mirror">mirror</button>
|
||||
<button id="context-duplicate">duplicate</button>
|
||||
<button id="context-layflat" lk="rc_lafl">lay flat</button>
|
||||
<button id="context-mirror" lk="rc_mirr">mirror</button>
|
||||
<button id="context-duplicate" lk="rc_dupl">duplicate</button>
|
||||
<div class="sep"></div>
|
||||
<button id="context-export-stl">export as STL</button>
|
||||
<button id="context-export-stl" lk="rc_xstl">export as STL</button>
|
||||
</div>
|
||||
<div id="fps" class="noshow"></div>
|
||||
<div id="layer-animate" class="f-col a-center"></div>
|
||||
|
|
@ -457,6 +461,9 @@
|
|||
<div id="alert-text">alerts<br>alerts<br>alerts</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="top-slider" class="f-col grow">
|
||||
<input id="anim-slider" type="range" min="0" max="1000" value="0"></input>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -67,8 +67,7 @@
|
|||
<tr><td>mouse-wheel</td><td>Zoom</td></tr>
|
||||
<tr><td>middle-drag</td><td>Zoom</td></tr>
|
||||
<tr><td>2-touch-pinch</td><td>Zoom</td></tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr><td><br><br></td></tr>
|
||||
<tr><th colspan=2 class="header">Konfiguration</th></tr>
|
||||
<tr><td><label>?</label></td><td>Dette Hjælpe Vindue</td></tr>
|
||||
<tr><td><label>e</label></td><td>Enhed Udvælger</td></tr>
|
||||
|
|
|
|||
1109
web/kiri/lang/da.js
1109
web/kiri/lang/da.js
File diff suppressed because it is too large
Load diff
1
web/kiri/lang/de-de-help.html
Symbolic link
1
web/kiri/lang/de-de-help.html
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
de-help.html
|
||||
640
web/kiri/lang/de-de.js
Normal file
640
web/kiri/lang/de-de.js
Normal file
|
|
@ -0,0 +1,640 @@
|
|||
// english. other language maps will defer to english
|
||||
// map for any missing key/value pairs
|
||||
kiri.lang['de'] =
|
||||
kiri.lang['de-de'] = {
|
||||
// common keys and menus
|
||||
animate: "Animieren", // CAM animate button
|
||||
arrange: "Anordnen", // layout workspace objects
|
||||
axis: "Achse", // left object scale pop menu
|
||||
clear: "alles entfernen", // clear workspace (remove all objects)
|
||||
copy: "Kopieren",
|
||||
delete: "Löschen",
|
||||
detail: "Details",
|
||||
done: "Fertig",
|
||||
enable: "Aktivieren",
|
||||
export: "Export",
|
||||
files: "Dateien",
|
||||
help: "Hilfe",
|
||||
ghost: "Geist", // left render pop menu (wireframe)
|
||||
hide: "Verbergen", // left render pop menu (invisible)
|
||||
home: "home",
|
||||
import: "Import",
|
||||
language: "Sprache",
|
||||
machine: "Maschine", // device or machine
|
||||
metric: "Metrisch",
|
||||
name: "Name",
|
||||
prefs: "Einstellungen", // left menu "preferences"
|
||||
preview: "Vorschau",
|
||||
recent: "Letzte Objekte",
|
||||
render: "Rendern", // left render pop menu
|
||||
reset: "Zurücksetzen",
|
||||
rotate: "Rotieren", // left rotate pop menu
|
||||
save: "Speichern",
|
||||
scale: "Skalieren", // left object scale pop menu
|
||||
setup: "Einrichtung",
|
||||
settings: "Einstellungen",
|
||||
size: "Größe",
|
||||
solid: "Undurchsichtig", // view type pop menu
|
||||
tool: "Werkzeug",
|
||||
tools: "Werkzeuge", // CAM tool menu button
|
||||
top: "Oben",
|
||||
type: "Typ", // CAM tool type
|
||||
version: "Version",
|
||||
view: "Ansicht", // left view pop menu
|
||||
wire: "Drahtansicht", // left render pop menu
|
||||
|
||||
acct_xpo: ["Lege ein Backup Deiner Geräte","und Geräte-Profile an, mit der","Option, den Arbeitsbereich und","mit Objekten und Anordnung zu speichern"],
|
||||
|
||||
// RIGHT-CLICK CONTEXT MENU
|
||||
rc_clws: "Arbeitsbereich freiräumen",
|
||||
rc_xpws: "Arbeitsbereich exportieren",
|
||||
rc_lafl: "Auf das Bett",
|
||||
rc_mirr: "Spiegeln",
|
||||
rc_dupl: "Duplizieren",
|
||||
rc_xstl: "Als STL exportieren",
|
||||
|
||||
// DEVICE MENU and related dialogs
|
||||
dm_sldt: "Wähle einen Geräte-Typ aus",
|
||||
dm_stdd: "Vordefinierte Geräte",
|
||||
dm_mydd: "Meine Geräte",
|
||||
dm_seld: "Ausgweähltes Gerät",
|
||||
dm_rcnt: "Letzte Dateien",
|
||||
dm_savs: "Gespeicherte Voreinstellungen",
|
||||
dm_appp: "Anwendungseinsetllungen",
|
||||
|
||||
// CAM Tool Dialog
|
||||
td_tyem: "end", // end mill
|
||||
td_tybm: "ball", // ball mill
|
||||
td_tytm: "taper", // taper mill
|
||||
td_tonm: "tool #",
|
||||
td_shft: "shaft", // endmill shaft specs
|
||||
td_flut: "flute", // endmill flute specs
|
||||
td_tapr: "taper", // endmill taper specs
|
||||
|
||||
// DEVICE dialog groups
|
||||
dv_gr_dev: "Gerät",
|
||||
dv_gr_ext: "Extruder",
|
||||
dv_gr_out: "Output",
|
||||
dv_gr_gco: "GCode Macros",
|
||||
|
||||
// DEVICE dialog (_s = label, _l = hover help)
|
||||
dv_name_s: "Name",
|
||||
dv_name_l: "Geräte-Name",
|
||||
dv_fila_s: "Filament",
|
||||
dv_fila_l: "Durchmesser in mm",
|
||||
dv_nozl_s: "Düse",
|
||||
dv_nozl_l: "Durchmesser in mm",
|
||||
dv_bedw_s: "Breite",
|
||||
dv_bedw_l: "Maßeinheiten des Arbeitsbereichs",
|
||||
dv_bedd_s: "Tiefe",
|
||||
dv_bedd_l: "Maßeinheiten der Arbeitsfläche",
|
||||
dv_bedh_s: "Höhe",
|
||||
dv_bedh_l: ["Maximale Objekthöhe","in Maßeinheiten der Arbeitsfläche"],
|
||||
dv_spmx_s: "Spindel-Maximum",
|
||||
dv_spmx_l: ["Maximale Umdrehungen pro Minute der Spindel","0 zum deaktivieren"],
|
||||
dv_xtab_s: "Absolute Positionierung",
|
||||
dv_xtab_l: "Filament wird mit absoluter Positionierung extrudiert",
|
||||
dv_orgc_s: "Nullpunkt in der Mitte",
|
||||
dv_orgc_l: "Nullpunkt des Druckbetts in der Mitte",
|
||||
// dv_orgt_s: "origin top",
|
||||
// dv_orgt_l: "part z origin top",
|
||||
dv_bedc_s: "Rundes Druckbett",
|
||||
dv_bedc_l: "Der Druckbereich des Gerätes ist rund",
|
||||
dv_belt_s: "Riemen-Druckbett",
|
||||
dv_belt_l: "Für bewegliche Druckbetten",
|
||||
dv_fanp_s: "Lüfter-Einstellung",
|
||||
dv_fanp_l: "Wie stark der Lüfter eingestellt sein soll",
|
||||
dv_prog_s: "Fortschrittsanzeige",
|
||||
dv_prog_l: "Wenn für jedes % der Fertigstellung eine Nachicht angezeigt werden soll",
|
||||
dv_layr_s: "Ebene",
|
||||
dv_layr_l: ["Ausgabe bei jeder","neuen Ebene"],
|
||||
dv_tksp_s: "Befehls-Trenner",
|
||||
dv_tksp_l: ["Füge ein Leerzeichen ein bei","GCode-Achsen-Befehlen","G0X0Y0X0","oder","G0 X0 Y0 Z0"],
|
||||
dv_strc_s: "Kommentare entfernen",
|
||||
dv_strc_l: ["Kommentare aus GCode entfernen","Kommentare beginnen mit ;"],
|
||||
dv_fext_s: "Datei-Erweiterung",
|
||||
dv_fext_l: "Datei-Erweiterung",
|
||||
dv_dwll_s: "dwell",
|
||||
dv_dwll_l: "gcode dwell script",
|
||||
dv_tool_s: "Werkzeg-Wechel",
|
||||
dv_tool_l: "Skript zum Werkzegwechsel",
|
||||
dv_sspd_s: "Spindelgeschwindigkeit",
|
||||
dv_sspd_l: "Einstellung der Spindelgeschwindigkeit",
|
||||
dv_paus_s: "Pause",
|
||||
dv_paus_l: "Skript zum Ausführen bei einer Pause",
|
||||
dv_head_s: "Anfang",
|
||||
dv_head_l: "Skript für den Anfang einer GCode-Datei",
|
||||
dv_foot_s: "Ende",
|
||||
dv_foot_l: "Skript für das Ende einer GCode-Datei",
|
||||
dv_lzon_s: "Laser an",
|
||||
dv_lzon_l: "Skript, um den Laser einzuschalten",
|
||||
dv_lzof_s: "Laser aus",
|
||||
dv_lzof_l: "Skript, um den Laser auszuschalten",
|
||||
dv_exts_s: "Auswhälen",
|
||||
dv_exts_l: "GCode, um diesen Extruder auszuwählen",
|
||||
dv_dext_s: "Abwählen",
|
||||
dv_dext_l: "GCode, bevor ein anderer Extruder ausgewählt wird",
|
||||
dv_extd_s: "Deaktivieren",
|
||||
dv_extd_l: "GCode, um diesen Extruder zu deaktivieren",
|
||||
dv_exox_s: "X-Offset",
|
||||
dv_exox_l: "X-Offset der Düse",
|
||||
dv_exoy_s: "Y-Offset",
|
||||
dv_exoy_l: "Y-Offset der Düse",
|
||||
|
||||
// MODE
|
||||
mo_menu: "Arbeits-Modus",
|
||||
mo_fdmp: "FDM-Druck",
|
||||
mo_slap: "SLA-Druck",
|
||||
mo_lazr: "Laser-Cutting",
|
||||
mo_cncm: "CNC-Fräsen",
|
||||
|
||||
// SETUP
|
||||
su_menu: "setup",
|
||||
su_devi: "Geräte",
|
||||
su_tool: "Werkzeuge",
|
||||
su_locl: "Lokal",
|
||||
su_xprt: "Export",
|
||||
su_help: "Hilfe",
|
||||
|
||||
// LOAD
|
||||
fe_menu: "Datei",
|
||||
fn_recn: "Letzte",
|
||||
fn_impo: "Import",
|
||||
|
||||
// FUNCTION
|
||||
fn_menu: "Modus",
|
||||
fn_arra: "Anordnen",
|
||||
fn_slic: "Slice",
|
||||
fn_prev: "Vorschau",
|
||||
fn_expo: "Export",
|
||||
|
||||
// VIEW
|
||||
vu_menu: "Ansicht",
|
||||
vu_home: "Standard",
|
||||
vu_rset: "Zurücksetzen",
|
||||
vu_sptp: "Oben",
|
||||
vu_spfr: "Vorn",
|
||||
vu_splt: "Links",
|
||||
vu_sprt: "Ansicht",
|
||||
|
||||
// WORKSPACE
|
||||
ws_menu: "Ansicht",
|
||||
ws_save: "Speichern",
|
||||
ws_cler: "Leeren",
|
||||
|
||||
// OPTIONS
|
||||
op_menu: "interface",
|
||||
op_disp: "Anzeige",
|
||||
op_xprt_s: "Fortgeschritten",
|
||||
op_xprt_l: "weitere Einstellungen",
|
||||
op_decl_s: "decals",
|
||||
op_decl_l: "show device decals and logos",
|
||||
op_dang_s: "Experimentell",
|
||||
op_dang_l: "Zeige experimentelle Parameter",
|
||||
op_hopo_s: "hover pop",
|
||||
op_hopo_l: ["enable menu hover","to activate"],
|
||||
op_dark_s: "Dunkler Modus",
|
||||
op_dark_l: "Dunkles Interface",
|
||||
op_comp_s: "Kompakt",
|
||||
op_comp_l: ["Kompakte Ansicht","Besser für kleine Bildschirme","und Tablets"],
|
||||
op_shor_s: "Nullpunkt anzeigen",
|
||||
op_shor_l: "Zeige den Nullpunkt des Gerätes oder des Prozesses",
|
||||
op_shru_s: "Lineal einblenden",
|
||||
op_shru_l: ["Zeige Lineale mit Maßen","auf den Hauptachsen"],
|
||||
op_sped_s: "Geschwindigkeiten einblenden",
|
||||
op_sped_l: ["Zeige Legende für Farben und Geschwindigkeiten","in der Vorschau"],
|
||||
op_auto_s: "Automatische Anordnung",
|
||||
op_auto_l: ["Ordne automatisch an","wenn neue Objekte hinzugefügt werden"],
|
||||
op_free_s: "Freie Anordnung",
|
||||
op_free_l: ["Erlaube Freie Anordnung von Objekten","Keine Auswirkung im Laser-Cutting Arbeitsmodus"],
|
||||
op_spcr_s: "Abstand",
|
||||
op_spcr_l: ["Abstand zwischen Objekten","bei automatischer Anordnung","in Maßeinheiten der Arbeitsfläche"],
|
||||
op_invr_s: "Zoom Umkehren",
|
||||
op_invr_l: ["Kehre die Richtung beim Mausrad-","Zoomen um"],
|
||||
op_save_s: "Automatisch speichern",
|
||||
op_save_l: ["Behalte Objekte im Arbeitsbereich","wenn die Anwendung neu geladen wird"],
|
||||
op_line_s: "Darstellungs-Typ",
|
||||
op_line_l: ["Wie Linien bei der Darstellung der Pfade gezeichnet werden","Beeinflußt 3D-Performance","Pfad: 3D (beste)","Flach: 2d (gut)","Linie = 1d (schnell)"],
|
||||
op_unit_s: "Maßeinheiten",
|
||||
op_unit_l: ["die Maßeinheit des Arbeitsbereich wirkt sich auf die Darstellung von ","Geschwindigkeiten und Entfernungen aus"],
|
||||
op_anim_s: "Animieren",
|
||||
op_anim_l: ["Dichte des Netzgitters beim Animieren","Je höher, desto dichter","benötigt mehr Speicher","und ist langsamer"],
|
||||
|
||||
lo_menu: "Anordnung",
|
||||
|
||||
pt_menu: "Objekte",
|
||||
pt_deci_s: "Deizimierung",
|
||||
pt_deci_l: ["Punktdezimierung","während des Imports. Für schnelleres Slicen","und weniger Speicherverbrauch"],
|
||||
pt_qual_s: "Qualität",
|
||||
pt_qual_l: ["Detailstufe beim","Slicen","geringer ist schneller"],
|
||||
pt_heal_s: "Mesh reparieren",
|
||||
pt_heal_l: ["Versuche","defekte Meshes zu reparieren","wirkt sich auf die Verarbeitungszeit us"],
|
||||
|
||||
xp_menu: "Export",
|
||||
|
||||
// SETTINGS
|
||||
se_menu: "Profil",
|
||||
se_load: "Laden",
|
||||
se_save: "Speichern",
|
||||
|
||||
// FDM SLICING
|
||||
sl_menu: "Schichten",
|
||||
sl_lahi_s: "Höhe",
|
||||
sl_lahi_l: ["Höhe jeder Schicht","Schichthöhe in mm"],
|
||||
ad_minl_s: "Mindesthöhe",
|
||||
ad_minl_l: ["Mindesthöhe für adaptive Schichthöhe","in mm","Darf nicht null sein"],
|
||||
sl_ltop_s: "top layers",
|
||||
sl_ltop_l: ["number of solid layers","to enforce at the","top of the print"],
|
||||
sl_lsld_s: "solid layers",
|
||||
sl_lsld_l: ["solid fill areas computed","from layer deltas. see","layer pop menu"],
|
||||
sl_lbot_s: "base layers",
|
||||
sl_lbot_l: ["Anzahl der soliden Schichten","um die Unterseite des","Drucks zu verstärken"],
|
||||
ad_adap_s: "Adaptive Höhe",
|
||||
ad_adap_l: ["Verwende adaptive Schichthöhe","mit 'Maximale Höhe' als Maximum","und 'Mindesthöhe' als Minimum"],
|
||||
|
||||
// FDM SHELLS
|
||||
sl_shel_s: "Anzahl Außenwände",
|
||||
sl_shel_l: ["Anzahl der äußeren","Wände, die erzeugt werden sollen"],
|
||||
sl_ordr_s: "Druckreihenfolge der Wände",
|
||||
sl_ordr_l: ["In welcher Reihenfolge die Wände gedruckt werden","innen nach aussen","oder aussen nach innen","wirkt sich auf die Oberflächenqualität aus"],
|
||||
sl_strt_s: "Start der Ebene",
|
||||
sl_strt_l: ["Startpunkt der Ebene","Letzte = Ende der letzten Ebene ","Mitte = Zur Mitte des Objekts","Nullpunkt = Zum Nullpunkt des Gerätes"],
|
||||
ad_thin_s: "Dünne Wände",
|
||||
ad_thin_l: ["Finde und fülle schmale Lücken","zwischen Außenwänden"],
|
||||
|
||||
// FDM FILL
|
||||
fi_menu: "Füllmaterial",
|
||||
fi_type: "Typ",
|
||||
fi_pcnt_s: "Füll-Dichte",
|
||||
fi_pcnt_l: ["Füll-Dichte ","0.0 - 1.0"],
|
||||
fi_angl_s: "Startwinkel für volle Füllung",
|
||||
fi_angl_l: ["Startwinkel in Grad","90 Grad werden ","bei jeder folgender Schicht dazugerechnet","Wirkt sich nur auf vollgefüllte Schichten aus."],
|
||||
fi_over_s: "Schicht-Überlappung",
|
||||
fi_over_l: ["Überlappung von Schichten und Füllung","als Anteil des Düsen-Durchmessers","0.0 - 1.0"],
|
||||
// fi_rate_s: "print speed",
|
||||
fi_rate_l: ["Druckgeschwindigkeit für Füllmaterial","Auf 0 setzen, um die Standard-","Druckgeschwindigkeit zu verwenden"],
|
||||
|
||||
// FDM FIRST LAYER
|
||||
fl_menu: "Erste Schicht",
|
||||
fl_lahi_s: "Schichthöhe",
|
||||
fl_lahi_l: ["Höhe der ersten Schicht","in in mm","sollte >= der Standard-Schichthöhe sein"],
|
||||
fl_rate_s: "Wand-Geschwindigkeit",
|
||||
fl_rate_l: ["Maximalgeschwindigkeit beim Drucken von Wänden","in mm / min"],
|
||||
fl_frat_s: "Füll-Geschwindikeit",
|
||||
fl_frat_l: ["Maximalgeschwindikeit beim Drucken von Füllung","in mm / min"],
|
||||
fl_mult_s: "Extrusions-Faktor",
|
||||
fl_mult_l: ["Exktrusions-Faktor","0.0 - 2.0"],
|
||||
fl_sfac_s: "Breiten-Faktor",
|
||||
fl_sfac_l: ["Multipliziert mit dem Düsenfaktor","beeinflußt die Breite der Drucklinien"],
|
||||
fl_skrt_s: "Anzahl der Skirt-Linien",
|
||||
fl_skrt_l: ["Wieviele Linien um die erste Schicht","herum generiert werden sollen"],
|
||||
fl_skro_s: "Skirt-Abstand",
|
||||
fl_skro_l: ["Abstand des Skirts vom Objekt","in mm"],
|
||||
fl_nozl_s: "Drucktemperatur",
|
||||
fl_nozl_l: ["in Grad Celsius","Standard-Einstellung wird verwendet","wenn auf 0 gestellt"],
|
||||
fl_bedd_s: "Betttemperatur",
|
||||
fl_bedd_l: ["in Grad Celsius","Standard-Einstellung wird verwendet","when auf 0 gestellt"],
|
||||
fr_spac_s: "Raft Abstand",
|
||||
fr_spac_l: ["Zusätzlicher Abstand","zwischen erster Schicht und Raft","in mm"],
|
||||
fr_nabl_s: "Raft verwenden",
|
||||
fr_nabl_l: ["Erzeuge ein Raft unter dem","Objekt für bessere Betthaftung","verwendet Skirt-Abstand und","Deaktiviert die Erzeugung eines Skirt"],
|
||||
|
||||
// FDM BELT ONLY
|
||||
fl_zoff_s: "belt offset",
|
||||
fl_zoff_l: ["height offset from belt","of lowest extrusion","in millimeters"],
|
||||
fl_brim_s: "Größe des Brim",
|
||||
fl_brim_l: ["Brim am Fuß des Objekts erzeugen","Größe in mm","0 um zu deaktivieren"],
|
||||
fl_brmn_s: "Brim-Auslöser",
|
||||
fl_brmn_l: ["Erzeuge nur Brim, wenn die Fläche","auf dem Gurt kürzer ist als dieser Wert","Angegeben in mm","0 = Immer"],
|
||||
fl_bled_s: "Objekt verankern",
|
||||
fl_bled_l: ["Objekt mit dem Gurt verankern","zu Beginn des Drucks","in mm"],
|
||||
|
||||
// FDM SUPPORT
|
||||
sp_menu: "Stützstrukturen",
|
||||
sp_detect: "Analysieren",
|
||||
sp_dens_s: "Dichte",
|
||||
sp_dens_l: ["Anteil 0.0 - 1.0","empfohlen 0.15","0 zum deaktivieren"],
|
||||
sp_size_s: "Breite der Säule",
|
||||
sp_size_l: ["Breite der Säule","in mm"],
|
||||
sp_offs_s: "Abstand",
|
||||
sp_offs_l: ["Abstand vom Objekt","in mm"],
|
||||
sp_gaps_s: "Schicht-Abstand",
|
||||
sp_gaps_l: ["Anzahl der Schichten","zwischen Stützstruktur und Objekt"],
|
||||
sp_span_s: "Maximale Spannbreite",
|
||||
sp_span_l: ["Für Spannen über dieser Breite","werden Stützstrukturen erzeugt","in mm"],
|
||||
sp_angl_s: "Maximaler Winkel",
|
||||
sp_angl_l: ["Für Überhänge über diesem Winkel","werden Stützstrukturen erzeugt"],
|
||||
sp_area_s: "Mindestfläche",
|
||||
sp_area_l: ["Mindestfläche für","Eine Stützsäule","in mm"],
|
||||
sp_xpnd_s: "Ausdehung",
|
||||
sp_xpnd_l: ["Dehne die Stützstruktur","über die Objekt-Grenzen aus","in mm"],
|
||||
sp_nozl_s: "Extruder",
|
||||
sp_nozl_l: ["In Geräten mit mehreren Extrudern","welcher Extruder wird für","Stützmaterial verwendet"],
|
||||
sp_auto_s: "Automatisch",
|
||||
sp_auto_l: ["Erzeuge Stützstrukturen automatisch","beim Slicen","Stützstruktuen werden erst","Nach dem Slicen angezeigt"],
|
||||
|
||||
// LASER SLICING
|
||||
ls_offs_s: "Abstand",
|
||||
ls_offs_l: ["Anpassung for Strahlbreite","in millimeters"],
|
||||
ls_lahi_s: "Höhe",
|
||||
ls_lahi_l: ["Schichthöhe","in mm","0 = auto/erkennen"],
|
||||
ls_lahm_s: "min",
|
||||
ls_lahm_l: ["Minimale Schichthöhe","Autoslices unter dieser Höhe","werden zusammengeführt","in millimeters"],
|
||||
ls_sngl_s: "Einfach",
|
||||
ls_sngl_l: ["Nur einen Slice bei","angegebener Schichthöhe ausführen"],
|
||||
|
||||
// CNC COMMON terms
|
||||
cc_tool: "Werkzeug",
|
||||
cc_offs_s: "offset",
|
||||
cc_offs_l: ["offset tool center","from chosen path"],
|
||||
cc_spnd_s: "spindle rpm",
|
||||
cc_spnd_l: ["spindle speed in","revolutions / minute"],
|
||||
cc_sovr_s: "step over",
|
||||
cc_sovr_l: ["as a fraction of","tool diameter"],
|
||||
cc_sdwn_s: "step down",
|
||||
cc_sdwn_l: ["step down depth","for each pass","in workspace units","0 to disable"],
|
||||
cc_feed_s: "feed rate",
|
||||
cc_feed_l: ["max cutting speed in","workspace units / minute"],
|
||||
cc_plng_s: "plunge rate",
|
||||
cc_plng_l: ["max z axis speed in","workspace units / minute"],
|
||||
cc_sngl_s: "select lines only",
|
||||
cc_sngl_l: ["select only single edges","instead of connected polylines"],
|
||||
|
||||
// CNC COMMON
|
||||
cc_menu: "limits",
|
||||
cc_flip: "flip",
|
||||
cc_rapd_s: "xy feed",
|
||||
cc_rapd_l: ["max xy moves feedrate","in workspace units / minute"],
|
||||
cc_rzpd_s: "z feed",
|
||||
cc_rzpd_l: ["max z moves feedrate","in workspace units / minute"],
|
||||
|
||||
cc_loff_s: "offset",
|
||||
cc_loff_l: ["distance from stock face","for leveling pass","in workspace units"],
|
||||
|
||||
// CNC ROUGHING
|
||||
cr_menu: "rough",
|
||||
cr_lsto_s: "leave stock",
|
||||
cr_lsto_l: ["horizontal offset from vertical faces","stock to leave for finishing pass","in workspace units"],
|
||||
cr_ease_s: "ease down",
|
||||
cr_ease_l: ["plunge cuts will","spiral down or ease","along a linear path"],
|
||||
cr_clrt_s: "clear top",
|
||||
cr_clrt_l: ["run a clearing pass over","the bounding area of the part","at z = 0"],
|
||||
cr_clrp_s: "clear voids",
|
||||
cr_clrp_l: ["mill out through pockets","instead of just the outline"],
|
||||
cr_clrf_s: "clear faces",
|
||||
cr_clrf_l: ["interpolate step down to","clear any detected flat areas"],
|
||||
cr_olin_s: "inside only",
|
||||
cr_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
|
||||
// CNC OUTLINE
|
||||
co_menu: "outline",
|
||||
co_dogb_s: "dogbones",
|
||||
co_dogb_l: ["insert dogbone cuts","into inside corners"],
|
||||
co_wide_s: "wide cutout",
|
||||
co_wide_l: ["widen outside cutout paths","for deep cuts in hard material"],
|
||||
co_olin_s: "inside only",
|
||||
co_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
co_olot_s: "outside only",
|
||||
co_olot_l: ["limit cutting to","exterior part boundaries","which can be thought of","as the shadow outline"],
|
||||
co_omit_s: "omit through",
|
||||
co_omit_l: "eliminate thru holes",
|
||||
co_olen_s: "enable",
|
||||
co_olen_l: "enabled outline cutting",
|
||||
|
||||
// CNC CONTOUR
|
||||
cn_menu: "contour",
|
||||
cf_angl_s: "max angle",
|
||||
cf_angl_l: ["angles greater than this","are considered vertical"],
|
||||
cf_curv_s: "curves only",
|
||||
cf_curv_l: ["limit linear cleanup","to curved surfaces"],
|
||||
cf_olin_s: "inside only",
|
||||
cf_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
cf_linx_s: "enable y pass",
|
||||
cf_linx_l: "linear y-axis finishing",
|
||||
cf_liny_s: "enable x pass",
|
||||
cf_liny_l: "linear x-axis finishing",
|
||||
|
||||
// CNC TRACE
|
||||
cu_menu: "trace",
|
||||
cu_type_s: "type",
|
||||
cu_type_l: ["follow = tool tip follows line","right or left = tool tip","follows line offset by tool radius"],
|
||||
|
||||
// CNC DRILLING
|
||||
cd_menu: "drill",
|
||||
cd_axis: "axis",
|
||||
cd_points: "points",
|
||||
cd_plpr_s: "plunge per",
|
||||
cd_plpr_l: ["max plunge between","dwell periods","in workspace units","0 to disable"],
|
||||
cd_dwll_s: "dwell time",
|
||||
cd_dwll_l: ["dwell time","between plunges in","in milliseconds"],
|
||||
cd_lift_s: "drill lift",
|
||||
cd_lift_l: ["lift between plunges","after dwell period","in workspace units","0 to disable"],
|
||||
cd_regi_s: "register",
|
||||
cd_regi_l: ["drill registration holes","for double-sided parts","independent of enable","drilling but uses same","tool and settings"],
|
||||
|
||||
// CNC CUTOUT TABS
|
||||
ct_menu: "tabs",
|
||||
ct_angl_s: "angle",
|
||||
ct_angl_l: ["starting angle for tab spacing","in degrees (0-360)"],
|
||||
ct_numb_s: "count",
|
||||
ct_numb_l: ["number of tabs to use","will be spaced evenly","around the part"],
|
||||
ct_wdth_s: "width",
|
||||
ct_wdth_l: "width in workspace units",
|
||||
ct_hght_s: "height",
|
||||
ct_hght_l: "height in workspace units",
|
||||
ct_dpth_s: "depth",
|
||||
ct_dpth_l: ["distance in workspace units","that the tab projects from","the part surface"],
|
||||
ct_midl_s: "midline",
|
||||
ct_midl_l: ["use midline of tab","instead of z bottom","for double-sided work"],
|
||||
ct_nabl_s: "auto",
|
||||
ct_nabl_l: ["auto generate radial tabs","projected from part center","using count and angle offset"],
|
||||
|
||||
// OUTPUT
|
||||
ou_menu: "output",
|
||||
|
||||
// LASER KNIFE
|
||||
dk_menu: "knife",
|
||||
dk_dpth_s: "cut depth",
|
||||
dk_dpth_l: ["final cut depth","in millimeters"],
|
||||
dk_pass_s: "cut passes",
|
||||
dk_pass_l: ["number of passes","down to cut depth"],
|
||||
dk_offs_s: "tip offset",
|
||||
dk_offs_l: ["distance from blade tip","to center of tool","in millimeters"],
|
||||
|
||||
// OUTPUT LASER
|
||||
ou_spac_s: "spacing",
|
||||
ou_spac_l: ["distance between layer output","in millimeters"],
|
||||
ou_scal_s: "scaling",
|
||||
ou_scal_l: "multiplier (0.1 to 100)",
|
||||
ou_powr_s: "power",
|
||||
ou_powr_l: ["0 - 100","represents %"],
|
||||
ou_sped_s: "speed",
|
||||
ou_sped_l: "millimeters / minute",
|
||||
ou_mrgd_s: "merged",
|
||||
ou_mrgd_l: ["merge all layers using","color coding to denote","stacking depth"],
|
||||
ou_grpd_s: "grouped",
|
||||
ou_grpd_l: ["retain each layer as","a unified grouping","instead of separated","polygons"],
|
||||
ou_layr_s: "layer order",
|
||||
ou_layr_l: ["output layer order","from top right to","bottom left"],
|
||||
ou_layo_s: "layer color",
|
||||
ou_layo_l: ["output layer colors","for each z index","overridden by merged"],
|
||||
ou_drkn_s: "drag knife",
|
||||
ou_drkn_l: ["enable drag knife","output in gcode","cut radii are added","to corners with","cut down passes"],
|
||||
|
||||
// OUTPUT FDM
|
||||
ou_nozl_s: "Drucktemperatur",
|
||||
ou_nozl_l: "In Grad Celsius",
|
||||
ou_bedd_s: "Betttemperatur",
|
||||
ou_bedd_l: "In Grad Celsius",
|
||||
ou_feed_s: "Druckgewschwindigkeit",
|
||||
ou_feed_l: ["Maximale Druckgeschwindigkeit","mm / min"],
|
||||
ou_fini_s: "Außengeschwindigkeit",
|
||||
ou_fini_l: ["Geschwindigkeit für Außenwände","mm / min"],
|
||||
ou_move_s: "Bewegungsgeschwnidgkeit",
|
||||
ou_move_l: ["Geschwndigkeit, wenn nicht gedruckt wird ","mm / min","0 = aktiviere G0 Befehle"],
|
||||
ou_shml_s: "Wand-Faktor",
|
||||
ou_flml_s: "Voll-Füll-Faktor",
|
||||
ou_spml_s: "Füll-Material-Faktor",
|
||||
ou_exml_l: ["Extrusions-Multiplikator","0.0 - 2.0"],
|
||||
ou_fans_s: "Geschwindigkeit der Bauteilkühlung",
|
||||
ou_fans_l: "0 - 255",
|
||||
|
||||
// OUTPUT CAM
|
||||
ou_toll_s: "tolerance",
|
||||
ou_toll_l: ["surface precision","in workspace units","lower is slower and","uses more memory","0 = automatic based","on animate preference"],
|
||||
ou_zanc_s: "z anchor",
|
||||
ou_zanc_l: ["controls the position of the part","when stock Z exceeds part Z"],
|
||||
ou_ztof_s: "z offset",
|
||||
ou_ztof_l: ["offset z anchor","in workspace units","has no effect when","anchor is middle"],
|
||||
ou_zbot_s: "z bottom",
|
||||
ou_zbot_l: ["offset from part bottom","to limit cutting depth","in workspace units"],
|
||||
ou_zclr_s: "z clearance",
|
||||
ou_zclr_l: ["safe travel offset","from top of part","in workspace units"],
|
||||
ou_ztru_s: "z thru",
|
||||
ou_ztru_l: ["extend cutout pass down","in workspace units"],
|
||||
ou_conv_s: "conventional",
|
||||
ou_conv_l: ["milling direction","uncheck for 'climb'"],
|
||||
ou_depf_s: "depth first",
|
||||
ou_depf_l: ["optimize pocket cuts","with depth priority"],
|
||||
|
||||
// CAM STOCK
|
||||
cs_menu: "stock",
|
||||
cs_wdth_s: "width",
|
||||
cs_wdth_l: ["width (x) in workspace units","0 defaults to part size"],
|
||||
cs_dpth_s: "depth",
|
||||
cs_dpth_l: ["depth (y) in workspace units","0 defaults to part size"],
|
||||
cs_hght_s: "height",
|
||||
cs_hght_l: ["height (z) in workspace units","0 defaults to part size"],
|
||||
cs_offs_s: "offset",
|
||||
cs_offs_l: ["use width, depth, height","as offsets from max","part size on platform"],
|
||||
cs_clip_s: "clip to",
|
||||
cs_clip_l: ["rough and outline","clip cutting paths","to defined stock"],
|
||||
cs_offe_s: "enable",
|
||||
cs_offe_l: "enable milling stock",
|
||||
|
||||
// ORIGIN (CAM & LASER)
|
||||
or_bnds_s: "origin bounds",
|
||||
or_bnds_l: ["origin is relative to","boundary of all objects"],
|
||||
or_cntr_s: "origin center",
|
||||
or_cntr_l: "origin is referenced from the center",
|
||||
or_topp_s: "origin top",
|
||||
or_topp_l: "origin is references from the top of objects",
|
||||
|
||||
// FDM ADVANCED
|
||||
ad_menu: "Fortgeschritten",
|
||||
ad_rdst_s: "Einzugslänge",
|
||||
ad_rdst_l: ["Wie weit das Filament eingezogen werden soll","bei langen Bewegungen (in mm)"],
|
||||
ad_rrat_s: "Einzugsgeschwindigkeit",
|
||||
ad_rrat_l: ["Geschwindigkeit des Filamenteinzugs","in mm/s"],
|
||||
ad_rdwl_s: "Vorschub-Pause",
|
||||
ad_wpln_s: "Einzugs-Bewegung",
|
||||
ad_wpln_l: ["Bewegung ohne Druck","nach Einzug","in millimeters"],
|
||||
ad_rdwl_l: ["Zeitabstand zwischen","Bewegung und Vorschub nach Einzug ","in msec"],
|
||||
ad_scst_s: "Außenwand-Coasting",
|
||||
ad_scst_l: ["Welche Strecke am Ende einer","Außenwand nicht extrudiert wird","in mm"],
|
||||
ad_msol_s: "Mindestfläche für vollständige Füllung",
|
||||
ad_msol_l: ["Mindestfläche in mm^2 ","für vollständige Füllung","muß > 0.1 sein"],
|
||||
ad_mins_s: "Mindestgeschwindigkeit",
|
||||
ad_mins_l: ["Mindestgeschwindigkeit","für kurze Segmente"],
|
||||
ad_spol_s: "Kurze Segmente",
|
||||
ad_spol_l: ["Segmente die kürzer sind","werden mit","Mindestgeschwindigkeit gedruckt","in mm"],
|
||||
ad_arct_s: "arc tolerance",
|
||||
ad_arct_l: ["convert faceted lines to arcs","center point drift tolerance","when matching arc points","consider values around 0.15","in millimeters","0 to disable"],
|
||||
ad_zhop_s: "Z Hop",
|
||||
ad_zhop_l: ["Hebe Düse bei Einzug an","in mm","0 zum deaaktivieren"],
|
||||
ad_abkl_s: "anti-backlash",
|
||||
ad_abkl_l: ["Für schöneres Aussehen Flacher Oberflächen","verwende Micro-Bewegungen","um Backlash auszugleichen","in mm","0 zum deaktivieren","Wenn Deine Firmware M425 unterstützt","verwende das im Start-GCode und setze hier auf 0"],
|
||||
ad_lret_s: "Einzug bei Ebenenwechsel",
|
||||
ad_lret_l: ["Erzwinge Einzug","bei Ebenen wechseln"],
|
||||
ad_play_s: "Ebenen glätten",
|
||||
ad_play_l: ["glätte bis zu","dieser Anzahl Ebenen"],
|
||||
ad_pspd_s: "Glätt-Geschwindigkeit",
|
||||
ad_pspd_l: ["Glätt-Geschwindigkeit","in mm / min"],
|
||||
|
||||
// CAM EXPERT
|
||||
cx_fast_s: "skip shadow",
|
||||
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"],
|
||||
|
||||
// FDM GCODE
|
||||
ag_menu: "GCode",
|
||||
ag_nozl_s: "Düse",
|
||||
ag_nozl_l: "Wählt Düse oder Druckkopf aus",
|
||||
ag_paws_s: "Pause bei Ebenen",
|
||||
ag_paws_l: ["Liste von Ebenen (kommasepariert","vor denen pausiert werden soll"],
|
||||
ag_loop_s: "Schichten wiederholen",
|
||||
ag_loop_l: ["Schichten die wiederholt werden sollen, im Format ","erste-letzte-anzahl,erste-letzte-anzahl,...","omitted count = 1"],
|
||||
|
||||
// SLA MENU
|
||||
sa_menu: "Slicen",
|
||||
sa_lahe_s: "Schichthöhe",
|
||||
sa_lahe_l: ["Schichthöhe","in mm"],
|
||||
sa_shel_s: "Aushöhlen",
|
||||
sa_shel_l: ["Wanddick mm","verwene Mehrfaches der Schichthöhe","setze 0 zum deaktivieren"],
|
||||
sa_otop_s: "oben offen",
|
||||
sa_otop_l: ["Wenn Aushöhlen aktiviert ist","bleibt das Objekt oben offen"],
|
||||
sa_obas_s: "unten offen",
|
||||
sa_obas_l: ["Wenn Aushöhlen aktiviert ist","bleibt das Objekt unten offen","deaktiviert, wenn Stützstrukturen verwendet werden"],
|
||||
|
||||
sa_layr_m: "layers",
|
||||
sa_lton_s: "light on time",
|
||||
sa_lton_l: ["layer light on","time in seconds"],
|
||||
sa_ltof_s: "light off time",
|
||||
sa_ltof_l: ["layer light off","time in seconds"],
|
||||
sa_pldi_s: "peel distance",
|
||||
sa_pldi_l: ["peel distance","in millimeters"],
|
||||
sa_pllr_s: "peel lift rate",
|
||||
sa_pllr_l: ["peel lift speed","in mm/sec"],
|
||||
sa_pldr_s: "peel drop rate",
|
||||
sa_pldr_l: ["peel drop speed","in mm/sec"],
|
||||
|
||||
sa_base_m: "base",
|
||||
sa_balc_s: "layer count",
|
||||
sa_balc_l: ["number of","base layers"],
|
||||
sa_bltn_l: ["base layer light on","time in seconds"],
|
||||
sa_bltf_l: ["base layer light off","time in seconds"],
|
||||
|
||||
sa_infl_m: "Füllstrukturen",
|
||||
sa_ifdn_s: "Dichte",
|
||||
sa_ifdn_l: ["percent infill","requires shell","0 = disabled","valid 0.0 - 1.0"],
|
||||
sa_iflw_s: "line width",
|
||||
sa_iflw_l: ["hatch line width","in millimeters"],
|
||||
|
||||
sa_supp_m: "support",
|
||||
sa_slyr_s: "base layers",
|
||||
sa_slyr_l: ["base support layers","value range 0-10"],
|
||||
sa_slgp_s: "gap layers",
|
||||
sa_slgp_l: ["number of layers between","raft and bottom of object"],
|
||||
sa_sldn_s: "density",
|
||||
sa_sldn_l: ["used to compute the","number of support pillars","0.0-1.0 (0 = disable)"],
|
||||
sa_slsz_s: "size",
|
||||
sa_slsz_l: ["max size of a","support pillar","in millimeters"],
|
||||
sa_slpt_s: "points",
|
||||
sa_slpt_l: ["number of points in","each support pillar","in millimeters"],
|
||||
sl_slen_l: "enable supports",
|
||||
|
||||
sa_outp_m: "output",
|
||||
sa_opzo_s: "z offset",
|
||||
sa_opzo_l: ["z layer offset","almost always 0.0","0.0-1.0 in millimeters"],
|
||||
sa_opaa_s: "anti alias",
|
||||
sa_opaa_l: ["enable anti-aliasing","produces larger files","can blur details"]
|
||||
};
|
||||
177
web/kiri/lang/de-help.html
Normal file
177
web/kiri/lang/de-help.html
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
<div id="help" class="f-col a-stretch">
|
||||
|
||||
<div class="title f-row j-center">
|
||||
<label>Kiri:Moto Slicer Help</label>
|
||||
<label id="kiri-version"></label>
|
||||
</div>
|
||||
|
||||
<div class="f-row">
|
||||
|
||||
<div id="help-sel" class="f-col">
|
||||
<div class="help-label" tab="about">Über</div>
|
||||
<div class="help-label" tab="start">starting</div>
|
||||
<div class="help-label" tab="controls">Steuerung</div>
|
||||
<div class="help-label" tab="support">Unterstützung</div>
|
||||
<div class="help-label" tab="project">Das Projekt</div>
|
||||
</div>
|
||||
|
||||
<div id="help-tabs" class="f-grow">
|
||||
<div id="help-tab-about" class="help-tab f-col a-center">
|
||||
<div class="content">
|
||||
<p>
|
||||
<b>Kiri:Moto</b> ist ein einzigartiger browser-basierter, komplett quelloffener slicer,
|
||||
mit dem Du 3D-Modelle in Steuerbefehle für <u>3D-Drucker</u>, <u>CNC-Fräsen</u>,
|
||||
uns <u>Laser Cutter</u> umwandeln kannst.
|
||||
</p><br><p>
|
||||
Browser-basiert bedeutet, dass <i>alle</i> Verarbeitung in Deinem Browser stattfindet,
|
||||
und nicht in der Cloud. Deine Modelle und Daten bleiben <i>privat</i> auf Deinem Rechner.
|
||||
</p><br><p>
|
||||
Das heisst, das Kiri wie eine lokale Anwendung auf Deinem Computer läuft, aber zusätzlich
|
||||
so sicher ist, wie Dein Browser.
|
||||
</p><br><p>
|
||||
Ein weiterer Vorteil von Kiri als Web-Anwendung ist, dass Du immer die aktuelle Version
|
||||
verwendest. Neue Funktionen, Fehlerbehebungen, und andere Updates kommen regelmäßig und automatisch
|
||||
bei Dir an. Wenn Du eine ältere, oder eine Entwicklungsversion von Kiri verwenden willst, kannst
|
||||
Du diese im Nutzer-Menü oben rechts auswählen.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grow"></div>
|
||||
<i>Kiri leitet sich von Kiri-e ab, der Japanischen Scherenschnitt-Kunst.</i>
|
||||
<i>Moto ist ein Kürzel für "Modeling Tool" (Modellierungs-Werkzeug)</i>
|
||||
</div>
|
||||
|
||||
<div id="help-tab-start" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Schnell-Anleitung</b>
|
||||
<div class="content">
|
||||
<p>
|
||||
<li id="help-start">Schau Dir <a href="https://youtu.be/08795Sj22QE" target="youtube">The Definitive Video Guide to Kiri:Moto 2.5</a> an (auf Englisch)</li>
|
||||
<li><button><i class="fas fa-cogs"></i></button> Im Einrichtungs-Menü wählst Du <button><i class="fas fa-cube"></i></button> Geräte und Arbeitsmodus</li>
|
||||
<li><button><i class="fas fa-sliders-h"></i></button> preferences allow interface and mode-specific settings</li>
|
||||
<li><button><i class="fas fa-plus"></i></button> Du kannst Geräte-Konfigurationen anpassen, wenn Du die Standard-Einstellungen verändern willst</li>
|
||||
<li><button><i class="fas fa-folder"></i></button> Öffne Dateien <button><i class="fas fa-file-upload"></i></button> importiere Teile in den Arbeitsbereich</li>
|
||||
<li>use the right-side profile menus to customize slicing parameters</li>
|
||||
<li><button><i class="fas fa-bars"></i></button> Mit Slice siehst du, wie die Parameter sich auf Objekte auswirken</li>
|
||||
<li><button><i class="fas fa-cubes"></i></button> Vorschau berechnet Pfade (Maschinen-Anweisungen) aus den gesliceten Objekten</li>
|
||||
<li><button><i class="fas fa-file-download"></i></button> Export speichert diese Pfade in GCode- oder SVG-Dateien</li>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<b class="header">Arbeits-Modi</b>
|
||||
<p>Jeder Modus (FDM, CAM, Laser, SLA) hat unterschiedliche Funktionen und Einstellungsmöglichkeiten.
|
||||
Schau Dir die Youtube-Videos an, um mehr zu erfahren.</p>
|
||||
</div>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-print" class="help-tab f-col">Über 3d-Druck</div>
|
||||
<div id="help-tab-mill" class="help-tab f-col">Über CNC-Fräsen</div>
|
||||
<div id="help-tab-laser" class="help-tab f-col">Über Laser-Cutting</div>
|
||||
|
||||
<div id="help-tab-controls" class="help-tab f-col a-center"><div class="content">
|
||||
<div class="f-row">
|
||||
<table>
|
||||
<tr><td colspan="2" class="header">Tastatur-Befehle</td><tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><th>Taste</th><th>Befehl</th></tr>
|
||||
<tr><td colspan=2 class="header2">Konfiguration</td></tr>
|
||||
<tr><td><label>e</label></td><td>Geräte Auswahl</td></tr>
|
||||
<tr><td><label>o</label></td><td>Auswahl des Fräswerkzeugs</td></tr>
|
||||
<tr><td><label>c</label></td><td>Grid-Geräte im Netzwerk</td></tr>
|
||||
<tr><td><label>q</label></td><td>Voreinstellungen</td></tr>
|
||||
<tr><td><label>l</label></td><td>Arbeits-Profile</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Modus</td></tr>
|
||||
<tr><td><label>a</label></td><td>Platzieren</td></tr>
|
||||
<tr><td><label>s</label></td><td>Slice</td></tr>
|
||||
<tr><td><label>p</label></td><td>Vorschau</td></tr>
|
||||
<tr><td><label>g</label></td><td>Animieren</td></tr>
|
||||
<tr><td><label>x</label></td><td>Export</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Datei</td></tr>
|
||||
<tr><td><label>i</label></td><td>Importieren</td></tr>
|
||||
<tr><td><label>r</label></td><td>Letzte Dateien</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Ansicht</td></tr>
|
||||
<tr><td><label>h</label></td><td>Standard</td></tr>
|
||||
<tr><td><label>t</label></td><td>Oben</td></tr>
|
||||
<tr><td><label>f</label></td><td>Vorn</td></tr>
|
||||
<tr><td><label>b</label></td><td>Hinten</td></tr>
|
||||
<tr><td><label>z</label></td><td>Ansicht zurüksetzen</td></tr>
|
||||
<tr><td><label>< ></label></td><td>Durch die Seitenansichten wechseln</td></tr>
|
||||
<tr><td><label>v</label></td><td>Fokus (Platzieren)</td></tr>
|
||||
<tr><td><label>v</label></td><td>Ebene (Slice/Vorschau)</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Objekte</td></tr>
|
||||
<tr><td><label>d</label></td><td>Duplizieren</td></tr>
|
||||
<tr><td><label>m</label></td><td>Spiegeln</td></tr>
|
||||
<tr><td><label>o</label></td><td>Rotieren (Dialog)</td></tr>
|
||||
<tr><td><label>delete</label></td><td>Löschen</td></tr>
|
||||
<tr><td><label>arrow</label></td><td>Um 90° rotieren</td></tr>
|
||||
<tr><td><label>shift-arrow</label></td><td>Um 5° rotieren</td></tr>
|
||||
<tr><td><label>option-arrow</label></td><td>5mm bewegen</td></tr>
|
||||
<tr><td><label>ctrl-a</label></td><td>Alle Objekte auswählen</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Hilfe</td></tr>
|
||||
<tr><td><label>?</label></td><td>Dieses Fenster</td></tr>
|
||||
<tr><td><br><br></td></tr>
|
||||
<tr><td colspan="2" class="header">Maus-Kontrollen</td><tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><th>Tastenkombination</th><th>Befehl</th></tr>
|
||||
<tr><td colspan=2 class="header2">Ansicht</td></tr>
|
||||
<tr><td><label>shift</label> wheel</td><td>Schicht wechseln</td></tr>
|
||||
<tr><td><label>meta</label> verschieben</td><td>Ansicht schwenken</td></tr>
|
||||
<tr><td><label>right-drag</label></td><td>Ansicht schwenken</td></tr>
|
||||
<tr><td><label>left-drag</label></td><td>Ansicht rotieren</td></tr>
|
||||
<tr><td><label>mouse-wheel</label></td><td>Ausschnitt verändern</td></tr>
|
||||
<tr><td><label>middle-drag</label></td><td>Ausschnitt verändern</td></tr>
|
||||
<tr><td><label>meta</label> drag</td><td>Ansicht schwenkden</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Objekte</td></tr>
|
||||
<tr><td><label>ctrl-click</label></td><td>Seite aufs Bett ausrichten</td></tr>
|
||||
<tr><td><label>meta-click</label></td><td>Seite aufs Bett ausrichten</td></tr>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-support" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Weitere Informationen</b>
|
||||
<div class="content nounderline">
|
||||
<a target="_rsc" href="https://docs.grid.space/projects/kiri-moto"><i class="fas fa-question-circle"></i>Weitereführende Dokumentation</a>
|
||||
<a target="_rsc" href="https://forum.grid.space"><i class="fab fa-discourse"></i> Grid.Space forums</a>
|
||||
<a target="_rsc" href="https://discord.gg/suyCCgr"><i class="fab fa-discord"></i> Discord live chat server</a>
|
||||
<a target="_rsc" href="https://www.youtube.com/playlist?list=PLRoVgyRoWZpumQIKWm7oldx3bjDivqP24"><i class="fab fa-youtube"></i> Youtube videos und Tutorials</a>
|
||||
<a target="_rsc" href="https://twitter.com/grid_space_3d"><i class="fab fa-twitter"></i>Grid.Space auf Twitter</a>
|
||||
<a target="_rsc" href="https://facebook.com/groups/kirimoto"><i class="fab fa-facebook"></i> Kiri:Moto Gruppe aufn Facebook</a>
|
||||
</div>
|
||||
<b class="header">Weitere Optionen</b>
|
||||
<p>
|
||||
Im button><i class="fas fa-user-cog"></i></button> NutzerMenü open rechts, kannst Du die Funktion
|
||||
<span class="mono">Export</span> verwenden, um eine Kopie Deiner Geräte Profile und (optional) Deines Arbeitsbereichs
|
||||
herunterzuladen. Mit dieser Datei kannst Du jederzeit Deine komplette Arbeitsumgebung bei Kiri:Moto wieder herstellen.
|
||||
Du kannst sie auch mit anderen Teilen, zum Beispiel um die Entwickler oder andere Nutzer bei der Fehlersuche zu unterstützen.
|
||||
</p>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-project" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Open Source</b>
|
||||
<p>
|
||||
Kiri:Moto ist komplett <a href="https://github.com/GridSpace/grid-apps" target="_github">quelloffen</a>.
|
||||
Mehr kannst Du auf der Github-Seite zum Projekt erfahten. Es gibt verwandte Projekte, sowohl Software als auch
|
||||
Hardware. Neue Entwickler und Code-Erweiterungen werden gerne entgegen genommen. Der Quellcode ist unter der
|
||||
MIT-Lizenz veröffentlicht.
|
||||
</p><br><p>
|
||||
<a target="_paypal" href="https://paypal.me/gridspace3d?locale.x=en_US">Spenden</a> sind natürlich auch willkommen.
|
||||
</p>
|
||||
<br><b class="header">Integrationen</b>
|
||||
<p>Kiri:Moto ist auch in anderen Applikationen integriert.</p>
|
||||
<li><a target="app" href="https://appstore.onshape.com/apps/CAM/EAAEWYIOMQKBENEMYW2N7MF253CT4WYL6SUJGEY=/description"><b>Onshape</b></a> im App store</li>
|
||||
<li><a target="app" href="http://www.thingiverse.com/apps/kirimoto/"><b>Thingiverse</b></a> als Thing Apps</li>
|
||||
<li><a target="app" href="https://simplyprint.io">SimplyPrint.io</a> verwendet Kiri:Moto als primären Slicer</li>
|
||||
<li><a target="app" href="https://sienci.com/camlab-help/">CAMLab</a> ist eine Variante einer früheren Version von Kiri:Moto</li>
|
||||
</div></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
1
web/kiri/lang/de.js
Symbolic link
1
web/kiri/lang/de.js
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
de-de.js
|
||||
|
|
@ -11,13 +11,6 @@
|
|||
<div class="help-label" tab="about">about</div>
|
||||
<div class="help-label" tab="start">starting</div>
|
||||
<div class="help-label" tab="controls">controls</div>
|
||||
<!--
|
||||
<hr width=75%>
|
||||
<div class="help-label" tab="print">3d print</div>
|
||||
<div class="help-label" tab="mill">cnc mill</div>
|
||||
<div class="help-label" tab="laser">laser cut</div>
|
||||
<hr width=75%>
|
||||
-->
|
||||
<div class="help-label" tab="support">support</div>
|
||||
<div class="help-label" tab="project">project</div>
|
||||
</div>
|
||||
|
|
@ -83,6 +76,7 @@
|
|||
<tr><td><label>o</label></td><td>CAM Tool Selection</td></tr>
|
||||
<tr><td><label>c</label></td><td>Grid Local Devices</td></tr>
|
||||
<tr><td><label>q</label></td><td>Preference panel</td></tr>
|
||||
<tr><td><label>l</label></td><td>Work Profiles</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Mode</td></tr>
|
||||
<tr><td><label>a</label></td><td>Arrange</td></tr>
|
||||
|
|
@ -96,11 +90,14 @@
|
|||
<tr><td><label>r</label></td><td>Recent</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">View</td></tr>
|
||||
<tr><td><label>t</label></td><td>Top</td></tr>
|
||||
<tr><td><label>h</label></td><td>Home</td></tr>
|
||||
<tr><td><label>v</label></td><td>Layer</td></tr>
|
||||
<tr><td><label>t</label></td><td>Top</td></tr>
|
||||
<tr><td><label>f</label></td><td>Front</td></tr>
|
||||
<tr><td><label>b</label></td><td>Back</td></tr>
|
||||
<tr><td><label>z</label></td><td>Reset View</td></tr>
|
||||
<tr><td><label>meta</label> drag</td><td>Pan</td></tr>
|
||||
<tr><td><label>< ></label></td><td>Cycle Side Views</td></tr>
|
||||
<tr><td><label>v</label></td><td>Focus (arrange)</td></tr>
|
||||
<tr><td><label>v</label></td><td>Layer (slice/preview)</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Objects</td></tr>
|
||||
<tr><td><label>d</label></td><td>Duplicate</td></tr>
|
||||
|
|
@ -114,10 +111,7 @@
|
|||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Help</td></tr>
|
||||
<tr><td><label>?</label></td><td>This Window</td></tr>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
<div class="t-pad"></div>
|
||||
<table>
|
||||
<tr><td><br><br></td></tr>
|
||||
<tr><td colspan="2" class="header">Mouse Controls</td><tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><th>Combo</th><th>Action</th></tr>
|
||||
|
|
@ -128,6 +122,7 @@
|
|||
<tr><td><label>left-drag</label></td><td>Rotate</td></tr>
|
||||
<tr><td><label>mouse-wheel</label></td><td>Zoom</td></tr>
|
||||
<tr><td><label>middle-drag</label></td><td>Zoom</td></tr>
|
||||
<tr><td><label>meta</label> drag</td><td>Pan</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Objects</td></tr>
|
||||
<tr><td><label>ctrl-click</label></td><td>Align face to bed</td></tr>
|
||||
|
|
@ -140,12 +135,12 @@
|
|||
<div id="help-tab-support" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Resources</b>
|
||||
<div class="content nounderline">
|
||||
<a target="_rsc" href="https://docs.grid.space/projects/kiri-moto"><i class="fas fa-question-circle"></i> Extended Documentation</a>
|
||||
<a target="_rsc" href="https://forum.grid.space"><i class="fab fa-discourse"></i> Grid.Space forums</a>
|
||||
<a target="_rsc" href="https://discord.gg/suyCCgr"><i class="fab fa-discord"></i> Discord live chat server</a>
|
||||
<a target="_rsc" href="https://www.youtube.com/playlist?list=PLRoVgyRoWZpumQIKWm7oldx3bjDivqP24"><i class="fab fa-youtube"></i> Youtube videos and tutorials</a>
|
||||
<a target="_rsc" href="https://twitter.com/grid_space_3d"><i class="fab fa-twitter"></i> Follow Grid.Space on Twitter</a>
|
||||
<a target="_rsc" href="https://facebook.com/groups/kirimoto"><i class="fab fa-facebook"></i> Kiri:Moto Users group on Facebook</a>
|
||||
<a target="_rsc" href="https://wiki.grid.space/"><i class="fab fa-github"></i> Grid.Space Wiki</a>
|
||||
</div>
|
||||
<b class="header">In-App Options</b>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -2,11 +2,76 @@
|
|||
// map for any missing key/value pairs
|
||||
kiri.lang['en'] =
|
||||
kiri.lang['en-us'] = {
|
||||
version: "version",
|
||||
// common keys and menus
|
||||
animate: "animate", // CAM animate button
|
||||
arrange: "arrange", // layout workspace objects
|
||||
axis: "axis", // left object scale pop menu
|
||||
clear: "clear", // clear workspace (remove all objects)
|
||||
copy: "copy",
|
||||
delete: "delete",
|
||||
detail: "detail",
|
||||
done: "done",
|
||||
enable: "enable",
|
||||
export: "export",
|
||||
files: "files",
|
||||
help: "help",
|
||||
ghost: "ghost", // left render pop menu (wireframe)
|
||||
hide: "hide", // left render pop menu (invisible)
|
||||
home: "home",
|
||||
import: "import",
|
||||
language: "language",
|
||||
machine: "machine", // device or machine
|
||||
metric: "metric",
|
||||
name: "name",
|
||||
prefs: "prefs", // left menu "preferences"
|
||||
preview: "preview",
|
||||
recent: "recent",
|
||||
render: "render", // left render pop menu
|
||||
reset: "reset",
|
||||
rotate: "rotate", // left rotate pop menu
|
||||
save: "save",
|
||||
scale: "scale", // left object scale pop menu
|
||||
setup: "setup",
|
||||
settings: "settings",
|
||||
size: "size",
|
||||
slice: "slice",
|
||||
solid: "solid", // view type pop menu
|
||||
start: "start",
|
||||
tool: "tool",
|
||||
tools: "tools", // CAM tool menu button
|
||||
top: "top",
|
||||
type: "type", // CAM tool type
|
||||
version: "version",
|
||||
view: "view", // left view pop menu
|
||||
wire: "wire", // left render pop menu
|
||||
|
||||
acct_xpo: "make a backup of your device\nand device profiles with the\noption to include workspace\nobjects and positions",
|
||||
acct_xpo: ["make a backup of your device","and device profiles with the","option to include workspace","objects and positions"],
|
||||
|
||||
// RIGHT-CLICK CONTEXT MENU
|
||||
rc_clws: "clear workspace",
|
||||
rc_xpws: "export workspace",
|
||||
rc_lafl: "lay flat",
|
||||
rc_mirr: "mirror",
|
||||
rc_dupl: "duplicate",
|
||||
rc_xstl: "export as STL",
|
||||
|
||||
// DEVICE MENU and related dialogs
|
||||
dm_sldt: "select a device type",
|
||||
dm_stdd: "standard devices",
|
||||
dm_mydd: "my devices",
|
||||
dm_seld: "selected device",
|
||||
dm_rcnt: "recent files",
|
||||
dm_savs: "saved settings",
|
||||
dm_appp: "Application Preferences",
|
||||
|
||||
// CAM Tool Dialog
|
||||
td_tyem: "end", // end mill
|
||||
td_tybm: "ball", // ball mill
|
||||
td_tytm: "taper", // taper mill
|
||||
td_tonm: "tool #",
|
||||
td_shft: "shaft", // endmill shaft specs
|
||||
td_flut: "flute", // endmill flute specs
|
||||
td_tapr: "taper", // endmill taper specs
|
||||
|
||||
// DEVICE dialog groups
|
||||
dv_gr_dev: "device",
|
||||
|
|
@ -26,9 +91,9 @@ kiri.lang['en-us'] = {
|
|||
dv_bedd_s: "depth",
|
||||
dv_bedd_l: "workspace units",
|
||||
dv_bedh_s: "height",
|
||||
dv_bedh_l: "max build height\nin workspace units",
|
||||
dv_bedh_l: ["max build height","in workspace units"],
|
||||
dv_spmx_s: "max spindle",
|
||||
dv_spmx_l: "max spindle rpm speed\n0 to disable",
|
||||
dv_spmx_l: ["max spindle rpm speed","0 to disable"],
|
||||
dv_xtab_s: "absolute positioning",
|
||||
dv_xtab_l: "extrusion moves absolute",
|
||||
dv_orgc_s: "origin center",
|
||||
|
|
@ -39,16 +104,18 @@ kiri.lang['en-us'] = {
|
|||
dv_bedc_l: "device bed is circular",
|
||||
dv_belt_s: "belt bed",
|
||||
dv_belt_l: "continuous printing bed",
|
||||
dv_retr_s: "firmware retract",
|
||||
dv_retr_l: ["device fimware supports G10/G11"],
|
||||
dv_fanp_s: "fan power",
|
||||
dv_fanp_l: "set cooling fan power",
|
||||
dv_prog_s: "progress",
|
||||
dv_prog_l: "output on each % progress",
|
||||
dv_layr_s: "layer",
|
||||
dv_layr_l: "output at each\nlayer change",
|
||||
dv_layr_l: ["output at each","layer change"],
|
||||
dv_tksp_s: "token spacer",
|
||||
dv_tksp_l: "add a space between\ngcode axis parameters\nG0X0Y0X0\nvs\nG0 X0 Y0 Z0",
|
||||
dv_tksp_l: ["add a space between","gcode axis parameters","G0X0Y0X0","vs","G0 X0 Y0 Z0"],
|
||||
dv_strc_s: "strip comments",
|
||||
dv_strc_l: "strip gcode comments\ncomments begin with ;",
|
||||
dv_strc_l: ["strip gcode comments","comments begin with ;"],
|
||||
dv_fext_s: "file extension",
|
||||
dv_fext_l: "file name extension",
|
||||
dv_dwll_s: "dwell",
|
||||
|
|
@ -68,7 +135,9 @@ kiri.lang['en-us'] = {
|
|||
dv_lzof_s: "laser off",
|
||||
dv_lzof_l: "gcode laser off script",
|
||||
dv_exts_s: "select",
|
||||
dv_exts_l: "gcode to select this extruder",
|
||||
dv_exts_l: "gcode run to enable this extruder",
|
||||
dv_dext_s: "deselect",
|
||||
dv_dext_l: "gcode run before enabling another extruder",
|
||||
dv_extd_s: "deselect",
|
||||
dv_extd_l: "gcode to deselect this extruder",
|
||||
dv_exox_s: "offset x",
|
||||
|
|
@ -124,40 +193,48 @@ kiri.lang['en-us'] = {
|
|||
op_xprt_l: "show more settings options",
|
||||
op_decl_s: "decals",
|
||||
op_decl_l: "show device decals and logos",
|
||||
op_dang_s: "experimental",
|
||||
op_dang_l: "show experimental parameters",
|
||||
op_hopo_s: "hover pop",
|
||||
op_hopo_l: "enable menu hover\nto activate",
|
||||
op_hopo_l: ["enable menu hover","to activate"],
|
||||
op_dark_s: "dark mode",
|
||||
op_dark_l: "dark mode interface",
|
||||
op_comp_s: "compact ui",
|
||||
op_comp_l: "compact user interface\nbetter for small screens\nand tablets",
|
||||
op_comp_l: ["compact user interface","better for small screens","and tablets"],
|
||||
op_shor_s: "show origin",
|
||||
op_shor_l: "show device or process origin",
|
||||
op_shru_s: "show rulers",
|
||||
op_shru_l: "show axes rulers\non major gridlines",
|
||||
op_shru_l: ["show axes rulers","on major gridlines"],
|
||||
op_sped_s: "show speeds",
|
||||
op_sped_l: "show speed to color bar\nin preview mode",
|
||||
op_sped_l: ["show speed to color bar","in preview mode"],
|
||||
op_auto_s: "auto layout",
|
||||
op_auto_l: "automatically layout platform\nwhen new items added",
|
||||
op_auto_l: ["automatically layout platform","when new items added"],
|
||||
op_free_s: "free layout",
|
||||
op_free_l: "permit dragable layout\nno effect in laser mode",
|
||||
op_free_l: ["permit dragable layout","no effect in laser mode"],
|
||||
op_spcr_s: "spacing",
|
||||
op_spcr_l: ["spacing between objects","during auto layout","in workspace units"],
|
||||
op_orth_s: "orthographic",
|
||||
op_orth_l: ["orthographic display","requires page refresh"],
|
||||
op_invr_s: "invert zoom",
|
||||
op_invr_l: "invert mouse wheel\nscroll zoom",
|
||||
op_invr_l: ["invert mouse wheel","scroll zoom"],
|
||||
op_save_s: "auto save",
|
||||
op_save_l: "preserve objects in workspace\nbetween application reloads",
|
||||
op_save_l: ["preserve objects in workspace","between application reloads"],
|
||||
op_line_s: "line type",
|
||||
op_line_l: "line style for path rendering\nimpacts 3d performance\npath: 3d best\nflat: 2d good\nline = 1d fast",
|
||||
op_line_l: ["line style for path rendering","impacts 3d performance","path: 3d best","flat: 2d good","line = 1d fast"],
|
||||
op_unit_s: "units",
|
||||
op_unit_l: "workspace units affects\nspeeds and distances",
|
||||
op_unit_l: ["workspace units affects","speeds and distances"],
|
||||
op_anim_s: "animate",
|
||||
op_anim_l: "animation mesh density\nhigher is more dense\ntakes more memory\nand is slower",
|
||||
op_anim_l: ["animation mesh density","higher is more dense","takes more memory","and is slower"],
|
||||
|
||||
lo_menu: "layout",
|
||||
|
||||
pt_menu: "parts",
|
||||
pt_deci_s: "decimate",
|
||||
pt_deci_l: "enable or disable point decimation\nduring port import. for faster slicing\nand lower memory usage",
|
||||
pt_deci_l: ["enable or disable point decimation","during port import. for faster slicing","and lower memory usage"],
|
||||
pt_qual_s: "quality",
|
||||
pt_qual_l: "level of detail to retain\nduring slicing operations\nlower is faster",
|
||||
pt_qual_l: ["level of detail to retain","during slicing operations","lower is faster"],
|
||||
pt_heal_s: "heal mesh",
|
||||
pt_heal_l: ["attempt to heal","non-manifold meshes","adds to slicing time"],
|
||||
|
||||
xp_menu: "exports",
|
||||
|
||||
|
|
@ -169,156 +246,164 @@ kiri.lang['en-us'] = {
|
|||
// FDM SLICING
|
||||
sl_menu: "layers",
|
||||
sl_lahi_s: "height",
|
||||
sl_lahi_l: "height of each slice\nlayer in millimeters",
|
||||
sl_lahi_l: ["height of each slice","layer in millimeters"],
|
||||
ad_minl_s: "height min",
|
||||
ad_minl_l: "adaptive min layer height\nin millimeters\nmust be non-zero",
|
||||
ad_minl_l: ["adaptive min layer height","in millimeters","must be non-zero"],
|
||||
sl_ltop_s: "top layers",
|
||||
sl_ltop_l: "number of solid layers\nto enforce at the\ntop of the print",
|
||||
sl_ltop_l: ["number of solid layers","to enforce at the","top of the print"],
|
||||
sl_lsld_s: "solid layers",
|
||||
sl_lsld_l: "solid fill areas computed\nfrom layer deltas. see\nlayer pop menu",
|
||||
sl_lsld_l: ["solid fill areas computed","from layer deltas. see","layer pop menu"],
|
||||
sl_lbot_s: "base layers",
|
||||
sl_lbot_l: "number of solid layers\nto enforce at the\nbottom of the print",
|
||||
sl_lbot_l: ["number of solid layers","to enforce at the","bottom of the print"],
|
||||
ad_adap_s: "adaptive",
|
||||
ad_adap_l: "use adaptive layer heights\nwith 'layer height' as max\nand 'layer min' as the min",
|
||||
ad_adap_l: ["use adaptive layer heights","with 'layer height' as max","and 'layer min' as the min"],
|
||||
|
||||
// FDM SHELLS
|
||||
sl_shel_s: "shell count",
|
||||
sl_shel_l: "number of perimeter\nwalls to generate",
|
||||
sl_shel_l: ["number of perimeter","walls to generate"],
|
||||
sl_ordr_s: "shell order",
|
||||
sl_ordr_l: "output shell order\ninside to outside\nor outside to inside\naffects surface quality",
|
||||
sl_ordr_l: ["output shell order","inside to outside","or outside to inside","affects surface quality"],
|
||||
sl_strt_s: "layer start",
|
||||
sl_strt_l: "layer starting point\nlast = last layer end\ncenter = part center\norigin = device origin",
|
||||
sl_strt_l: ["layer starting point","last = last layer end","center = part center","origin = device origin"],
|
||||
ad_thin_s: "thin walls",
|
||||
ad_thin_l: "detect and fill gaps\nbetween shell walls",
|
||||
ad_thin_l: ["detect and fill gaps","between shell walls"],
|
||||
|
||||
// FDM FILL
|
||||
fi_menu: "infill",
|
||||
fi_type: "type",
|
||||
fi_pcnt_s: "fraction",
|
||||
fi_pcnt_l: "fill density values\n0.0 - 1.0",
|
||||
fi_angl_s: "start angle",
|
||||
fi_angl_l: "base angle in degrees",
|
||||
fi_over_s: "overlap",
|
||||
fi_over_l: "overlap with shell and fill\nas % of nozzle width\nhigher bonds better\n0.0 - 1.0",
|
||||
fi_type: "fill type",
|
||||
fi_pcnt_s: "fill fraction",
|
||||
fi_pcnt_l: ["fill density values","0.0 - 1.0"],
|
||||
fi_angl_s: "solid start",
|
||||
fi_angl_l: ["starting angle in degrees","90 degrees added to ","each following layer","applies only to solid layers"],
|
||||
fi_wdth_s: "solid width",
|
||||
fi_wdth_l: ["line width for solid fill","as a fraction of nozzle width","values < 1 are more dense","good for surface finishes","0.0 - 1.0"],
|
||||
fi_over_s: "shell overlap",
|
||||
fi_over_l: ["overlap with shell and other fill","as fraction of nozzle diameter","0.0 - 2.0"],
|
||||
// fi_rate_s: "print speed",
|
||||
fi_rate_l: ["extrusion speed for infill","set to 0 to use default","output print speeds"],
|
||||
|
||||
// FDM FIRST LAYER
|
||||
fl_menu: "base",
|
||||
fl_lahi_s: "layer height",
|
||||
fl_lahi_l: "height of each slice\nin millimeters\nshould be >= slice height",
|
||||
fl_lahi_l: ["height of each slice","in millimeters","should be >= slice height"],
|
||||
fl_rate_s: "shell speed",
|
||||
fl_rate_l: "shell printing max speed\nin millimeters / minute",
|
||||
fl_rate_l: ["shell printing max speed","in millimeters / minute"],
|
||||
fl_frat_s: "fill speed",
|
||||
fl_frat_l: "fill printing max speed\nin millimeters / minute",
|
||||
fl_frat_l: ["fill printing max speed","in millimeters / minute"],
|
||||
fl_mult_s: "flow factor",
|
||||
fl_mult_l: "extrusion multiplier\n0.0 - 2.0",
|
||||
fl_mult_l: ["extrusion multiplier","0.0 - 2.0"],
|
||||
fl_sfac_s: "width factor",
|
||||
fl_sfac_l: "multiplier on nozzle size\nchanges line spacing",
|
||||
fl_sfac_l: ["multiplier on nozzle size","changes line spacing"],
|
||||
fl_skrt_s: "skirt count",
|
||||
fl_skrt_l: "number of first-layer offset\nbrims to generate",
|
||||
fl_skrt_l: ["number of first-layer offset","brims to generate"],
|
||||
fl_skro_s: "skirt offset",
|
||||
fl_skro_l: "skirt offset from part\nin millimeters",
|
||||
fl_skro_l: ["skirt offset from part","in millimeters"],
|
||||
fl_nozl_s: "nozzle temp",
|
||||
fl_nozl_l: "degrees in celsius\noutput setting used\nwhen this is zero",
|
||||
fl_nozl_l: ["degrees in celsius","output setting used","when this is zero"],
|
||||
fl_bedd_s: "bed temp",
|
||||
fl_bedd_l: "degrees in celsius\noutput setting used\nwhen this is zero",
|
||||
fl_bedd_l: ["degrees in celsius","output setting used","when this is zero"],
|
||||
fr_spac_s: "raft gap",
|
||||
fr_spac_l: "additional layer spacing\nbetween 1st layer and raft\nin millimeters",
|
||||
fr_spac_l: ["additional layer spacing","between 1st layer and raft","in millimeters"],
|
||||
fr_nabl_s: "raft enable",
|
||||
fr_nabl_l: "create a raft under the\nmodel for better adhesion\nuses skirt offset and\ndisables skirt output",
|
||||
fr_nabl_l: ["create a raft under the","model for better adhesion","uses skirt offset and","disables skirt output"],
|
||||
|
||||
// FDM BELT ONLY
|
||||
fl_zoff_s: "layer offset",
|
||||
fl_zoff_l: "height offset from belt\nof lowest extrusion\nin millimeters",
|
||||
fl_zoff_s: "belt offset",
|
||||
fl_zoff_l: ["height offset from belt","of lowest extrusion","in millimeters"],
|
||||
fl_brim_s: "brim size",
|
||||
fl_brim_l: "add brim to part bottom\nsize is width in millimeters\n0 to disable",
|
||||
fl_brim_l: ["add brim to part bottom","size is width in millimeters","0 to disable"],
|
||||
fl_brmn_s: "brim trigger",
|
||||
fl_brmn_l: "add brims only when segment\nfacing belt is shorter than this\nvalue in millimeters\n0 = Infinity",
|
||||
fl_brmn_l: ["add brims only when segment","facing belt is shorter than this","value in millimeters","0 = Infinity"],
|
||||
fl_bled_s: "part anchor",
|
||||
fl_bled_l: ["belt part anchor","at start of print","in millimeters"],
|
||||
|
||||
// FDM SUPPORT
|
||||
sp_menu: "support",
|
||||
sp_detect: "detect",
|
||||
sp_dens_s: "density",
|
||||
sp_dens_l: "fraction 0.0 - 1.0\nrecommended 0.15\n0 to disable",
|
||||
sp_dens_l: ["fraction 0.0 - 1.0","recommended 0.15","0 to disable"],
|
||||
sp_size_s: "pillar size",
|
||||
sp_size_l: "pillar width\nin millimeters",
|
||||
sp_size_l: ["pillar width","in millimeters"],
|
||||
sp_offs_s: "part offset",
|
||||
sp_offs_l: "offset from part\nin millimeters",
|
||||
sp_offs_l: ["offset from part","in millimeters"],
|
||||
sp_gaps_s: "gap layers",
|
||||
sp_gaps_l: "number of layers\noffset from part",
|
||||
sp_gaps_l: ["number of layers","offset from part"],
|
||||
sp_span_s: "max span",
|
||||
sp_span_l: "unsupported span that causes\na new support to be generated\nin millimeters",
|
||||
sp_span_l: ["unsupported span that causes","a new support to be generated","in millimeters"],
|
||||
sp_angl_s: "max angle",
|
||||
sp_angl_l: "max overhang angle before\nsupporting pillar is generated",
|
||||
sp_angl_l: ["max overhang angle before","supporting pillar is generated"],
|
||||
sp_area_s: "min area",
|
||||
sp_area_l: "minimum area for\na support column\nin millimeters",
|
||||
sp_area_l: ["minimum area for","a support column","in millimeters"],
|
||||
sp_xpnd_s: "expand",
|
||||
sp_xpnd_l: "expand support area\nbeyond part boundary\nin millimeters",
|
||||
sp_xpnd_l: ["expand support area","beyond part boundary","in millimeters"],
|
||||
sp_nozl_s: "extruder",
|
||||
sp_nozl_l: "in multi-extruder systems\nthe extruder to use for\nsupport material",
|
||||
sp_nozl_l: ["in multi-extruder systems","the extruder to use for","support material"],
|
||||
sp_auto_s: "automatic",
|
||||
sp_auto_l: "enable generated supports\nusing at-slice-time geometry\nsupports will only appear\nafter slicing completes",
|
||||
sp_auto_l: ["enable generated supports","using at-slice-time geometry","supports will only appear","after slicing completes"],
|
||||
|
||||
// LASER SLICING
|
||||
ls_offs_s: "offset",
|
||||
ls_offs_l: "adjust for beam width\nin millimeters",
|
||||
ls_offs_l: ["adjust for beam width","in millimeters"],
|
||||
ls_lahi_s: "height",
|
||||
ls_lahi_l: "layer height\nin millimeters\n0 = auto/detect",
|
||||
ls_lahi_l: ["layer height","in millimeters","0 = auto/detect"],
|
||||
ls_lahm_s: "min",
|
||||
ls_lahm_l: "layer height minimum\nwill merge auto slices\nunder this thickness\nin millimeters",
|
||||
ls_lahm_l: ["layer height minimum","will merge auto slices","under this thickness","in millimeters"],
|
||||
ls_sngl_s: "single",
|
||||
ls_sngl_l: "perform only one slice\nat specified layer height",
|
||||
ls_sngl_l: ["perform only one slice","at specified layer height"],
|
||||
|
||||
// CNC COMMON terms
|
||||
cc_tool: "tool",
|
||||
cc_offs_s: "offset",
|
||||
cc_offs_l: "offset tool center\nfrom chosen path",
|
||||
cc_offs_l: ["offset tool center","from chosen path"],
|
||||
cc_spnd_s: "spindle rpm",
|
||||
cc_spnd_l: "spindle speed in\nrevolutions / minute",
|
||||
cc_spnd_l: ["spindle speed in","revolutions / minute"],
|
||||
cc_sovr_s: "step over",
|
||||
cc_sovr_l: "as a fraction of\ntool diameter",
|
||||
cc_sovr_l: ["as a fraction of","tool diameter"],
|
||||
cc_sdwn_s: "step down",
|
||||
cc_sdwn_l: "step down depth\nfor each pass\nin workspace units\n0 to disable",
|
||||
cc_sdwn_l: ["step down depth","for each pass","in workspace units","0 to disable"],
|
||||
cc_feed_s: "feed rate",
|
||||
cc_feed_l: "max cutting speed in\nworkspace units / minute",
|
||||
cc_feed_l: ["max cutting speed in","workspace units / minute"],
|
||||
cc_plng_s: "plunge rate",
|
||||
cc_plng_l: "max z axis speed in\nworkspace units / minute",
|
||||
cc_plng_l: ["max z axis speed in","workspace units / minute"],
|
||||
cc_sngl_s: "select lines only",
|
||||
cc_sngl_l: ["select only single edges","instead of connected polylines"],
|
||||
|
||||
// CNC COMMON
|
||||
cc_menu: "limits",
|
||||
cc_flip: "flip",
|
||||
cc_rapd_s: "xy feed",
|
||||
cc_rapd_l: "max xy moves feedrate\nin workspace units / minute",
|
||||
cc_rapd_l: ["max xy moves feedrate","in workspace units / minute"],
|
||||
cc_rzpd_s: "z feed",
|
||||
cc_rzpd_l: "max z moves feedrate\nin workspace units / minute",
|
||||
cc_rzpd_l: ["max z moves feedrate","in workspace units / minute"],
|
||||
|
||||
cc_loff_s: "offset",
|
||||
cc_loff_l: "distance from stock face\nfor leveling pass\nin workspace units",
|
||||
cc_loff_l: ["distance from stock face","for leveling pass","in workspace units"],
|
||||
|
||||
// CNC ROUGHING
|
||||
cr_menu: "rough",
|
||||
cr_lsto_s: "leave stock",
|
||||
cr_lsto_l: "horizontal offset from vertical faces\nstock to leave for finishing pass\nin workspace units",
|
||||
cr_lsto_l: ["horizontal offset from vertical faces","stock to leave for finishing pass","in workspace units"],
|
||||
cr_ease_s: "ease down",
|
||||
cr_ease_l: "plunge cuts will\nspiral down or ease\nalong a linear path",
|
||||
cr_ease_l: ["plunge cuts will","spiral down or ease","along a linear path"],
|
||||
cr_clrt_s: "clear top",
|
||||
cr_clrt_l: "run a clearing pass over\nthe bounding area of the part\nat z = 0",
|
||||
cr_clrt_l: ["run a clearing pass over","the bounding area of the part","at z = 0"],
|
||||
cr_clrp_s: "clear voids",
|
||||
cr_clrp_l: "mill out through pockets\ninstead of just the outline",
|
||||
cr_clrp_l: ["mill out through pockets","instead of just the outline"],
|
||||
cr_clrf_s: "clear faces",
|
||||
cr_clrf_l: "interpolate step down to\nclear any detected flat areas",
|
||||
cr_clrf_l: ["interpolate step down to","clear any detected flat areas"],
|
||||
cr_olin_s: "inside only",
|
||||
cr_olin_l: "limit cutting to\ninside part boundaries",
|
||||
cr_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
|
||||
// CNC OUTLINE
|
||||
co_menu: "outline",
|
||||
co_dogb_s: "dogbones",
|
||||
co_dogb_l: "insert dogbone cuts\ninto inside corners",
|
||||
co_dogb_l: ["insert dogbone cuts","into inside corners"],
|
||||
co_wide_s: "wide cutout",
|
||||
co_wide_l: "widen outside cutout paths\nfor deep cuts in hard material",
|
||||
co_wide_l: ["widen outside cutout paths","for deep cuts in hard material"],
|
||||
co_olin_s: "inside only",
|
||||
co_olin_l: "limit cutting to\ninside part boundaries",
|
||||
co_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
co_olot_s: "outside only",
|
||||
co_olot_l: "limit cutting to\nexterior part boundaries\nwhich can be thought of\nas the shadow outline",
|
||||
co_olot_l: ["limit cutting to","exterior part boundaries","which can be thought of","as the shadow outline"],
|
||||
co_omit_s: "omit through",
|
||||
co_omit_l: "eliminate thru holes",
|
||||
co_olen_s: "enable",
|
||||
|
|
@ -327,11 +412,11 @@ kiri.lang['en-us'] = {
|
|||
// CNC CONTOUR
|
||||
cn_menu: "contour",
|
||||
cf_angl_s: "max angle",
|
||||
cf_angl_l: "angles greater than this\nare considered vertical",
|
||||
cf_angl_l: ["angles greater than this","are considered vertical"],
|
||||
cf_curv_s: "curves only",
|
||||
cf_curv_l: "limit linear cleanup\nto curved surfaces",
|
||||
cf_curv_l: ["limit linear cleanup","to curved surfaces"],
|
||||
cf_olin_s: "inside only",
|
||||
cf_olin_l: "limit cutting to\ninside part boundaries",
|
||||
cf_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
cf_linx_s: "enable y pass",
|
||||
cf_linx_l: "linear y-axis finishing",
|
||||
cf_liny_s: "enable x pass",
|
||||
|
|
@ -340,37 +425,37 @@ kiri.lang['en-us'] = {
|
|||
// CNC TRACE
|
||||
cu_menu: "trace",
|
||||
cu_type_s: "type",
|
||||
cu_type_l: "follow = tool tip follows line\nright or left = tool tip\nfollows line offset by tool radius",
|
||||
cu_type_l: ["follow = tool tip follows line","right or left = tool tip","follows line offset by tool radius"],
|
||||
|
||||
// CNC DRILLING
|
||||
cd_menu: "drill",
|
||||
cd_axis: "axis",
|
||||
cd_points: "points",
|
||||
cd_plpr_s: "plunge per",
|
||||
cd_plpr_l: "max plunge between\ndwell periods\nin workspace units\n0 to disable",
|
||||
cd_plpr_l: ["max plunge between","dwell periods","in workspace units","0 to disable"],
|
||||
cd_dwll_s: "dwell time",
|
||||
cd_dwll_l: "dwell time\nbetween plunges in\nin milliseconds",
|
||||
cd_dwll_l: ["dwell time","between plunges in","in milliseconds"],
|
||||
cd_lift_s: "drill lift",
|
||||
cd_lift_l: "lift between plunges\nafter dwell period\nin workspace units\n0 to disable",
|
||||
cd_lift_l: ["lift between plunges","after dwell period","in workspace units","0 to disable"],
|
||||
cd_regi_s: "register",
|
||||
cd_regi_l: "drill registration holes\nfor double-sided parts\nindependent of enable\ndrilling but uses same\ntool and settings",
|
||||
cd_regi_l: ["drill registration holes","for double-sided parts","independent of enable","drilling but uses same","tool and settings"],
|
||||
|
||||
// CNC CUTOUT TABS
|
||||
ct_menu: "tabs",
|
||||
ct_angl_s: "angle",
|
||||
ct_angl_l: "starting angle for tab spacing\nin degrees (0-360)",
|
||||
ct_angl_l: ["starting angle for tab spacing","in degrees (0-360)"],
|
||||
ct_numb_s: "count",
|
||||
ct_numb_l: "number of tabs to use\nwill be spaced evenly\naround the part",
|
||||
ct_numb_l: ["number of tabs to use","will be spaced evenly","around the part"],
|
||||
ct_wdth_s: "width",
|
||||
ct_wdth_l: "width in workspace units",
|
||||
ct_hght_s: "height",
|
||||
ct_hght_l: "height in workspace units",
|
||||
ct_dpth_s: "depth",
|
||||
ct_dpth_l: "distance in workspace units\nthat the tab projects from\nthe part surface",
|
||||
ct_dpth_l: ["distance in workspace units","that the tab projects from","the part surface"],
|
||||
ct_midl_s: "midline",
|
||||
ct_midl_l: "use midline of tab\ninstead of z bottom\nfor double-sided work",
|
||||
ct_midl_l: ["use midline of tab","instead of z bottom","for double-sided work"],
|
||||
ct_nabl_s: "auto",
|
||||
ct_nabl_l: "auto generate radial tabs\nprojected from part center\nusing count and angle offset",
|
||||
ct_nabl_l: ["auto generate radial tabs","projected from part center","using count and angle offset"],
|
||||
|
||||
// OUTPUT
|
||||
ou_menu: "output",
|
||||
|
|
@ -378,31 +463,31 @@ kiri.lang['en-us'] = {
|
|||
// LASER KNIFE
|
||||
dk_menu: "knife",
|
||||
dk_dpth_s: "cut depth",
|
||||
dk_dpth_l: "final cut depth\nin millimeters",
|
||||
dk_dpth_l: ["final cut depth","in millimeters"],
|
||||
dk_pass_s: "cut passes",
|
||||
dk_pass_l: "number of passes\ndown to cut depth",
|
||||
dk_pass_l: ["number of passes","down to cut depth"],
|
||||
dk_offs_s: "tip offset",
|
||||
dk_offs_l: "distance from blade tip\nto center of tool\nin millimeters",
|
||||
dk_offs_l: ["distance from blade tip","to center of tool","in millimeters"],
|
||||
|
||||
// OUTPUT LASER
|
||||
ou_spac_s: "spacing",
|
||||
ou_spac_l: "distance between layer output\nin millimeters",
|
||||
ou_spac_l: ["distance between layer output","in millimeters"],
|
||||
ou_scal_s: "scaling",
|
||||
ou_scal_l: "multiplier (0.1 to 100)",
|
||||
ou_powr_s: "power",
|
||||
ou_powr_l: "0 - 100\nrepresents %",
|
||||
ou_powr_l: ["0 - 100","represents %"],
|
||||
ou_sped_s: "speed",
|
||||
ou_sped_l: "millimeters / minute",
|
||||
ou_mrgd_s: "merged",
|
||||
ou_mrgd_l: "merge all layers using\ncolor coding to denote\nstacking depth",
|
||||
ou_mrgd_l: ["merge all layers using","color coding to denote","stacking depth"],
|
||||
ou_grpd_s: "grouped",
|
||||
ou_grpd_l: "retain each layer as\na unified grouping\ninstead of separated\npolygons",
|
||||
ou_grpd_l: ["retain each layer as","a unified grouping","instead of separated","polygons"],
|
||||
ou_layr_s: "layer order",
|
||||
ou_layr_l: "output layer order\nfrom top right to\nbottom left",
|
||||
ou_layr_l: ["output layer order","from top right to","bottom left"],
|
||||
ou_layo_s: "layer color",
|
||||
ou_layo_l: "output layer colors\nfor each z index\noverridden by merged",
|
||||
ou_layo_l: ["output layer colors","for each z index","overridden by merged"],
|
||||
ou_drkn_s: "drag knife",
|
||||
ou_drkn_l: "enable drag knife\noutput in gcode\ncut radii are added\nto corners with\ncut down passes",
|
||||
ou_drkn_l: ["enable drag knife","output in gcode","cut radii are added","to corners with","cut down passes"],
|
||||
|
||||
// OUTPUT FDM
|
||||
ou_nozl_s: "nozzle temp",
|
||||
|
|
@ -410,54 +495,54 @@ kiri.lang['en-us'] = {
|
|||
ou_bedd_s: "bed temp",
|
||||
ou_bedd_l: "degrees in celsius",
|
||||
ou_feed_s: "print speed",
|
||||
ou_feed_l: "max print speed\nmillimeters / minute",
|
||||
ou_feed_l: ["max print speed","millimeters / minute"],
|
||||
ou_fini_s: "finish speed",
|
||||
ou_fini_l: "outermost shell speed\nmillimeters / minute",
|
||||
ou_fini_l: ["outermost shell speed","millimeters / minute"],
|
||||
ou_move_s: "move speed",
|
||||
ou_move_l: "non-print move speed\nmillimeters / minute\n0 = enable G0 moves",
|
||||
ou_move_l: ["non-print move speed","millimeters / minute","0 = enable G0 moves"],
|
||||
ou_shml_s: "shell factor",
|
||||
ou_flml_s: "solid factor",
|
||||
ou_spml_s: "infill factor",
|
||||
ou_exml_l: "extrusion multiplier\n0.0 - 2.0",
|
||||
ou_fanl_s: "fan layer",
|
||||
ou_fanl_l: "layer to enable fan",
|
||||
ou_exml_l: ["extrusion multiplier","0.0 - 2.0"],
|
||||
ou_fans_s: "fan speed",
|
||||
ou_fans_l: "0 - 255",
|
||||
|
||||
// OUTPUT CAM
|
||||
ou_toll_s: "tolerance",
|
||||
ou_toll_l: "surface precision\nin workspace units\nlower is slower and\nuses more memory\n0 = automatic based\non animate preference",
|
||||
ou_toll_l: ["surface precision","in workspace units","lower is slower and","uses more memory","0 = automatic based","on animate preference"],
|
||||
ou_zanc_s: "z anchor",
|
||||
ou_zanc_l: "controls the position of the part\nwhen stock Z exceeds part Z",
|
||||
ou_zanc_l: ["controls the position of the part","when stock Z exceeds part Z"],
|
||||
ou_ztof_s: "z offset",
|
||||
ou_ztof_l: "offset z anchor\nin workspace units\nhas no effect when\nanchor is middle",
|
||||
ou_ztof_l: ["offset z anchor","in workspace units","has no effect when","anchor is middle"],
|
||||
ou_zbot_s: "z bottom",
|
||||
ou_zbot_l: "offset from part bottom\nto limit cutting depth\nin workspace units",
|
||||
ou_zbot_l: ["offset from part bottom","to limit cutting depth","in workspace units"],
|
||||
ou_zclr_s: "z clearance",
|
||||
ou_zclr_l: "safe travel offset\nfrom top of part\nin workspace units",
|
||||
ou_zclr_l: ["safe travel offset","from top of part","in workspace units"],
|
||||
ou_ztru_s: "z thru",
|
||||
ou_ztru_l: "extend cutout pass down\nin workspace units",
|
||||
ou_ztru_l: ["extend cutout pass down","in workspace units"],
|
||||
ou_conv_s: "conventional",
|
||||
ou_conv_l: "milling direction\nuncheck for 'climb'",
|
||||
ou_conv_l: ["milling direction","uncheck for 'climb'"],
|
||||
ou_depf_s: "depth first",
|
||||
ou_depf_l: "optimize pocket cuts\nwith depth priority",
|
||||
ou_depf_l: ["optimize pocket cuts","with depth priority"],
|
||||
|
||||
// CAM STOCK
|
||||
cs_menu: "stock",
|
||||
cs_wdth_s: "width",
|
||||
cs_wdth_l: "width (x) in workspace units\n0 defaults to part size",
|
||||
cs_wdth_l: ["width (x) in workspace units","0 defaults to part size"],
|
||||
cs_dpth_s: "depth",
|
||||
cs_dpth_l: "depth (y) in workspace units\n0 defaults to part size",
|
||||
cs_dpth_l: ["depth (y) in workspace units","0 defaults to part size"],
|
||||
cs_hght_s: "height",
|
||||
cs_hght_l: "height (z) in workspace units\n0 defaults to part size",
|
||||
cs_hght_l: ["height (z) in workspace units","0 defaults to part size"],
|
||||
cs_offs_s: "offset",
|
||||
cs_offs_l: "use width, depth, height\nas offsets from max\npart size on platform",
|
||||
cs_offs_l: ["use width, depth, height","as offsets from max","part size on platform"],
|
||||
cs_clip_s: "clip to",
|
||||
cs_clip_l: "rough and outline\nclip cutting paths\nto defined stock",
|
||||
cs_clip_l: ["rough and outline","clip cutting paths","to defined stock"],
|
||||
cs_offe_s: "enable",
|
||||
cs_offe_l: "enable milling stock",
|
||||
|
||||
// ORIGIN (CAM & LASER)
|
||||
or_bnds_s: "origin bounds",
|
||||
or_bnds_l: "origin is relative to\nboundary of all objects",
|
||||
or_bnds_l: ["origin is relative to","boundary of all objects"],
|
||||
or_cntr_s: "origin center",
|
||||
or_cntr_l: "origin is referenced from the center",
|
||||
or_topp_s: "origin top",
|
||||
|
|
@ -466,94 +551,100 @@ kiri.lang['en-us'] = {
|
|||
// FDM ADVANCED
|
||||
ad_menu: "expert",
|
||||
ad_rdst_s: "retract dist",
|
||||
ad_rdst_l: "amount to retract filament\nfor long moves. in millimeters",
|
||||
ad_rdst_l: ["amount to retract filament","for long moves. in millimeters"],
|
||||
ad_rrat_s: "retract rate",
|
||||
ad_rrat_l: "speed of filament\nretraction in mm/s",
|
||||
ad_rrat_l: ["speed of filament","retraction in mm/s"],
|
||||
ad_rdwl_s: "engage dwell",
|
||||
ad_rdwl_l: "time between re-engaging\nfilament and movement\nin milliseconds",
|
||||
ad_wpln_s: "retract wipe",
|
||||
ad_wpln_l: ["non-printing move","after retraction","in millimeters"],
|
||||
ad_rdwl_l: ["time between re-engaging","filament and movement","in milliseconds"],
|
||||
ad_scst_s: "shell coast",
|
||||
ad_scst_l: "non-printing end\nof perimeter shells\nin millimeters",
|
||||
ad_scst_l: ["non-printing end","of perimeter shells","in millimeters"],
|
||||
ad_msol_s: "min solid",
|
||||
ad_msol_l: "minimum area (mm^2)\nrequired to keep solid\nmust be > 0.1",
|
||||
ad_msol_l: ["minimum area (mm^2)","required to keep solid","must be > 0.1"],
|
||||
ad_mins_s: "min speed",
|
||||
ad_mins_l: "minimum speed\nfor short segments",
|
||||
ad_spol_s: "slow poly",
|
||||
ad_spol_l: "polygons shorter than this\nwill have their print speed\nscaled down to min speed\nin millimeters",
|
||||
ad_mins_l: ["minimum speed","for short segments"],
|
||||
ad_spol_s: "short path",
|
||||
ad_spol_l: ["polygons shorter than this","will have their print speed","scaled down to min speed","in millimeters"],
|
||||
ad_arct_s: "arc tolerance",
|
||||
ad_arct_l: ["convert faceted lines to arcs","center point drift tolerance","when matching arc points","consider values around 0.15","in millimeters","0 to disable"],
|
||||
ad_zhop_s: "z hop dist",
|
||||
ad_zhop_l: "amount to raise z\non retraction moves\nin millimeters\n0 to disable",
|
||||
ad_zhop_l: ["amount to raise z","on retraction moves","in millimeters","0 to disable"],
|
||||
ad_abkl_s: "anti-backlash",
|
||||
ad_abkl_l: "use micro-movements to cancel\nbacklash during fills\nin millimeters",
|
||||
ad_abkl_l: ["for better flat surface finish","use micro-movements to cancel","backlash in solid layer output","in millimeters","0 to disable","if your firmware has M425","put that in the gcode header","and leave this as 0"],
|
||||
ad_lret_s: "layer retract",
|
||||
ad_lret_l: "force filament retraction\nbetween layers",
|
||||
ad_lret_l: ["force filament retraction","between layers"],
|
||||
ad_play_s: "polish layers",
|
||||
ad_play_l: "polish up to specified\n# of layers at a time",
|
||||
ad_play_l: ["polish up to specified","# of layers at a time"],
|
||||
ad_pspd_s: "polish speed",
|
||||
ad_pspd_l: "polishing speed\nin millimeters / minute",
|
||||
ad_pspd_l: ["polishing speed","in millimeters / minute"],
|
||||
|
||||
// CAM EXPERT
|
||||
cx_fast_s: "skip shadow",
|
||||
cx_fast_l: "disable overhang detection\ncan be faster and use less\nmemory with complex models\nbut fails with overhangs\ntry enabling if slicing\nhangs during shadowing",
|
||||
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"],
|
||||
|
||||
// FDM GCODE
|
||||
ag_menu: "gcode",
|
||||
ag_nozl_s: "nozzle",
|
||||
ag_nozl_l: "select output nozzle or head",
|
||||
ag_peel_s: "peel guard",
|
||||
ag_peel_l: ["starting at this belt z positoin","periodically roll the print off and","back on to the belt to unstick it","and prevent rolling deflection"],
|
||||
ag_paws_s: "pause layers",
|
||||
ag_paws_l: "comma-separated list of layers\nto inject pause commands before",
|
||||
ag_paws_l: ["comma-separated list of layers","to inject pause commands before"],
|
||||
ag_loop_s: "loop layers",
|
||||
ag_loop_l: "layer ranges to repeat in the format\nfirst-last-count,first-last-count,...\nomitted count = 1",
|
||||
ag_loop_l: ["layer ranges to repeat in the format","first-last-count,first-last-count,...","omitted count = 1"],
|
||||
|
||||
// SLA MENU
|
||||
sa_menu: "slicing",
|
||||
sa_lahe_s: "layer height",
|
||||
sa_lahe_l: "layer height\nin millimeters",
|
||||
sa_lahe_l: ["layer height","in millimeters"],
|
||||
sa_shel_s: "hollow shell",
|
||||
sa_shel_l: "shell thickness in mm\nuse multiple of layer height\nuse 0 for solid (disabled)",
|
||||
sa_shel_l: ["shell thickness in mm","use multiple of layer height","use 0 for solid (disabled)"],
|
||||
sa_otop_s: "open top",
|
||||
sa_otop_l: "if shell is enabled\nresults in an open top",
|
||||
sa_otop_l: ["if shell is enabled","results in an open top"],
|
||||
sa_obas_s: "open base",
|
||||
sa_obas_l: "if shell is enabled\nresults in an open base\ndisabled with supports",
|
||||
sa_obas_l: ["if shell is enabled","results in an open base","disabled with supports"],
|
||||
|
||||
sa_layr_m: "layers",
|
||||
sa_lton_s: "light on time",
|
||||
sa_lton_l: "layer light on\ntime in seconds",
|
||||
sa_lton_l: ["layer light on","time in seconds"],
|
||||
sa_ltof_s: "light off time",
|
||||
sa_ltof_l: "layer light off\ntime in seconds",
|
||||
sa_ltof_l: ["layer light off","time in seconds"],
|
||||
sa_pldi_s: "peel distance",
|
||||
sa_pldi_l: "peel distance\nin millimeters",
|
||||
sa_pldi_l: ["peel distance","in millimeters"],
|
||||
sa_pllr_s: "peel lift rate",
|
||||
sa_pllr_l: "peel lift speed\nin mm/sec",
|
||||
sa_pllr_l: ["peel lift speed","in mm/sec"],
|
||||
sa_pldr_s: "peel drop rate",
|
||||
sa_pldr_l: "peel drop speed\nin mm/sec",
|
||||
sa_pldr_l: ["peel drop speed","in mm/sec"],
|
||||
|
||||
sa_base_m: "base",
|
||||
sa_balc_s: "layer count",
|
||||
sa_balc_l: "number of\nbase layers",
|
||||
sa_bltn_l: "base layer light on\ntime in seconds",
|
||||
sa_bltf_l: "base layer light off\ntime in seconds",
|
||||
sa_balc_l: ["number of","base layers"],
|
||||
sa_bltn_l: ["base layer light on","time in seconds"],
|
||||
sa_bltf_l: ["base layer light off","time in seconds"],
|
||||
|
||||
sa_infl_m: "infill",
|
||||
sa_ifdn_s: "density",
|
||||
sa_ifdn_l: "percent infill\nrequires shell\n0 = disabled\nvalid 0.0 - 1.0",
|
||||
sa_ifdn_l: ["percent infill","requires shell","0 = disabled","valid 0.0 - 1.0"],
|
||||
sa_iflw_s: "line width",
|
||||
sa_iflw_l: "hatch line width\nin millimeters",
|
||||
sa_iflw_l: ["hatch line width","in millimeters"],
|
||||
|
||||
sa_supp_m: "support",
|
||||
sa_slyr_s: "base layers",
|
||||
sa_slyr_l: "base support layers\nvalue range 0-10",
|
||||
sa_slyr_l: ["base support layers","value range 0-10"],
|
||||
sa_slgp_s: "gap layers",
|
||||
sa_slgp_l: "number of layers between\nraft and bottom of object",
|
||||
sa_slgp_l: ["number of layers between","raft and bottom of object"],
|
||||
sa_sldn_s: "density",
|
||||
sa_sldn_l: "used to compute the\nnumber of support pillars\n0.0-1.0 (0 = disable)",
|
||||
sa_sldn_l: ["used to compute the","number of support pillars","0.0-1.0 (0 = disable)"],
|
||||
sa_slsz_s: "size",
|
||||
sa_slsz_l: "max size of a\nsupport pillar\nin millimeters",
|
||||
sa_slsz_l: ["max size of a","support pillar","in millimeters"],
|
||||
sa_slpt_s: "points",
|
||||
sa_slpt_l: "number of points in\neach support pillar\nin millimeters",
|
||||
sa_slpt_l: ["number of points in","each support pillar","in millimeters"],
|
||||
sl_slen_l: "enable supports",
|
||||
|
||||
sa_outp_m: "output",
|
||||
sa_opzo_s: "z offset",
|
||||
sa_opzo_l: "z layer offset\nalmost always 0.0\n0.0-1.0 in millimeters",
|
||||
sa_opzo_l: ["z layer offset","almost always 0.0","0.0-1.0 in millimeters"],
|
||||
sa_opaa_s: "anti alias",
|
||||
sa_opaa_l: "enable anti-aliasing\nproduces larger files\ncan blur details"
|
||||
sa_opaa_l: ["enable anti-aliasing","produces larger files","can blur details"]
|
||||
};
|
||||
|
|
|
|||
1
web/kiri/lang/fr-fr-help.html
Symbolic link
1
web/kiri/lang/fr-fr-help.html
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
fr-help.html
|
||||
1
web/kiri/lang/fr-fr.js
Symbolic link
1
web/kiri/lang/fr-fr.js
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
fr.js
|
||||
176
web/kiri/lang/fr-help.html
Normal file
176
web/kiri/lang/fr-help.html
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
<div id="help" class="f-col a-stretch">
|
||||
|
||||
<div class="title f-row j-center">
|
||||
<label>Kiri:Moto Aide</label>
|
||||
<label id="kiri-version"></label>
|
||||
</div>
|
||||
|
||||
<div class="f-row">
|
||||
|
||||
<div id="help-sel" class="f-col">
|
||||
<div class="help-label" tab="about">A propos</div>
|
||||
<div class="help-label" tab="start">débuter</div>
|
||||
<div class="help-label" tab="controls">contrôles</div>
|
||||
<div class="help-label" tab="support">support</div>
|
||||
<div class="help-label" tab="project">projet</div>
|
||||
</div>
|
||||
|
||||
<div id="help-tabs" class="f-grow">
|
||||
<div id="help-tab-about" class="help-tab f-col a-center">
|
||||
<div class="content">
|
||||
<p>
|
||||
<b>Kiri:Moto</b> est un logiciel de découpe unique, fonctionnant dans un navigateur, entièrement open source, qui
|
||||
transforme les modèles 3d en instructions de machine pour <u>des imprimantes 3D</u>, <u>des CNC</u>,
|
||||
et <u>des graveurs laser</u>.
|
||||
</p><br><p>
|
||||
Le fait d'être basé sur un navigateur signifie que <i>tout</i> le processus de découpe a lieu dans le navigateur local,
|
||||
et non dans le nuage. Vos données et modèles restent <i>totalement privés</i>.
|
||||
</p><br><p>
|
||||
Cela signifie que Kiri se comporte comme une application native de votre ordinateur avec en plus
|
||||
la sécurité de l'exécution dans le bac à sable de sécurité du navigateur.
|
||||
</p><br><p>
|
||||
L'autre avantage de fonctionner à partir du web est que Kiri est toujours à jour. Les nouvelles
|
||||
fonctionnalités, les corrections de bogues et les mises à jour sont fréquemment mises en place. Si vous souhaitez exécuter une ancienne
|
||||
ou une version de développement de Kiri, sélectionnez cette version dans le menu utilisateur en haut à droite.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grow"></div>
|
||||
<i>Kiri vient de Kiri-e qui est l'art Japonais du découpage de papiers</i>
|
||||
<i>Moto est un raccourci pour "Modeling Tool" (Outil de modélisation)</i>
|
||||
</div>
|
||||
|
||||
<div id="help-tab-start" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Guide de démarrage rapide</b>
|
||||
<div class="content">
|
||||
<p>
|
||||
<li id="help-start">visionner <a href="https://youtu.be/08795Sj22QE" target="youtube">The Definitive Video Guide to Kiri:Moto 2.5</a></li>
|
||||
<li><button><i class="fas fa-cogs"></i></button> le menu setup sélectionne le <button><i class="fas fa-cube"></i></button> type de matériel et un appareil</li>
|
||||
<li><button><i class="fas fa-sliders-h"></i></button> les préférences permettent de régler l'interface et les caractéristiques de l'appareil</li>
|
||||
<li><button><i class="fas fa-plus"></i></button> personnaliser un appareil si vous souhaitez modifier les paramètres par défaut</li>
|
||||
<li><button><i class="fas fa-folder"></i></button> ouvre un fichier ou <button><i class="fas fa-file-upload"></i></button> importe des pièces dans l'espace de travail</li>
|
||||
<li>utiliser les menus de droite pour personnaliser les paramètres de découpage</li>
|
||||
<li><button><i class="fas fa-bars"></i></button> découper les objets pour voir l'effet des paramètres</li>
|
||||
<li><button><i class="fas fa-cubes"></i></button> la prévisualisation calcule les données de cheminement des objets tranchés</li>
|
||||
<li><button><i class="fas fa-file-download"></i></button> l'exportation convertit les chemins d'accès aux fichiers GCode et SVG</li>
|
||||
</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<b class="header">Modes de fonctionnement</b>
|
||||
<p>Chaque mode (FDM, CAM, Laser, SLA) a des caractéristiques et des paramètres différents.
|
||||
Explorez les vidéos Youtube pour en savoir plus.</p>
|
||||
</div>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-print" class="help-tab f-col">about 3d printing</div>
|
||||
<div id="help-tab-mill" class="help-tab f-col">about cnc milling</div>
|
||||
<div id="help-tab-laser" class="help-tab f-col">about laser cutting</div>
|
||||
|
||||
<div id="help-tab-controls" class="help-tab f-col a-center"><div class="content">
|
||||
<div class="f-row">
|
||||
<table>
|
||||
<tr><td colspan="2" class="header">Contrôles via le clavier</td><tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><th>Touche</th><th>Action</th></tr>
|
||||
<tr><td colspan=2 class="header2">Configuration</td></tr>
|
||||
<tr><td><label>e</label></td><td>Sélection de l'appareil</td></tr>
|
||||
<tr><td><label>o</label></td><td>CAM Sélection des outils</td></tr>
|
||||
<tr><td><label>c</label></td><td>Grid Local Devices</td></tr>
|
||||
<tr><td><label>q</label></td><td>Panneau des préférence</td></tr>
|
||||
<tr><td><label>l</label></td><td>Profils de travail</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Mode</td></tr>
|
||||
<tr><td><label>a</label></td><td>Organiser</td></tr>
|
||||
<tr><td><label>s</label></td><td>Découper</td></tr>
|
||||
<tr><td><label>p</label></td><td>Prévisualiser</td></tr>
|
||||
<tr><td><label>g</label></td><td>Animer</td></tr>
|
||||
<tr><td><label>x</label></td><td>Exporter</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Fichier</td></tr>
|
||||
<tr><td><label>i</label></td><td>Importer</td></tr>
|
||||
<tr><td><label>r</label></td><td>Récent</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Voir</td></tr>
|
||||
<tr><td><label>h</label></td><td>Home</td></tr>
|
||||
<tr><td><label>t</label></td><td>Top</td></tr>
|
||||
<tr><td><label>f</label></td><td>Avant</td></tr>
|
||||
<tr><td><label>b</label></td><td>Arrière</td></tr>
|
||||
<tr><td><label>z</label></td><td>Réinitialiser la vue</td></tr>
|
||||
<tr><td><label>< ></label></td><td>Alterner les vues de côtés</td></tr>
|
||||
<tr><td><label>v</label></td><td>Focus (organiser)</td></tr>
|
||||
<tr><td><label>v</label></td><td>Couche (découper/prévisualiser)</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Objets</td></tr>
|
||||
<tr><td><label>d</label></td><td>Dupliquer</td></tr>
|
||||
<tr><td><label>m</label></td><td>Miroir</td></tr>
|
||||
<tr><td><label>o</label></td><td>Pivoter/tourner</td></tr>
|
||||
<tr><td><label>delete</label></td><td>Supprimer</td></tr>
|
||||
<tr><td><label>arrow</label></td><td>Tounrer de 90°</td></tr>
|
||||
<tr><td><label>shift-arrow</label></td><td>Tourner de 5°</td></tr>
|
||||
<tr><td><label>option-arrow</label></td><td>Déplacer de 5mm</td></tr>
|
||||
<tr><td><label>ctrl-a</label></td><td>Tout sélectionner</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Aide</td></tr>
|
||||
<tr><td><label>?</label></td><td>Cette fenêtre</td></tr>
|
||||
<tr><td><br><br></td></tr>
|
||||
<tr><td colspan="2" class="header">Contrôles via la souris</td><tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><th>Combo</th><th>Action</th></tr>
|
||||
<tr><td colspan=2 class="header2">View</td></tr>
|
||||
<tr><td><label>shift</label> molette</td><td>Changer de couche</td></tr>
|
||||
<tr><td><label>meta</label> déplacer</td><td>Pan</td></tr>
|
||||
<tr><td><label>déplacer-droit</label></td><td>Pan</td></tr>
|
||||
<tr><td><label>déplacer-gauche</label></td><td>Tourner</td></tr>
|
||||
<tr><td><label>molette-souris</label></td><td>Zoom</td></tr>
|
||||
<tr><td><label>déplacer-milieu</label></td><td>Zoom</td></tr>
|
||||
<tr><td><label>meta</label> déplacer</td><td>Pan</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Objets</td></tr>
|
||||
<tr><td><label>ctrl-clic</label></td><td>Aligner la face sur le plateau</td></tr>
|
||||
<tr><td><label>meta-clic</label></td><td>Aligner la face sur le plateau</td></tr>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-support" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Ressources</b>
|
||||
<div class="content nounderline">
|
||||
<a target="_rsc" href="https://docs.grid.space/projects/kiri-moto"><i class="fas fa-question-circle"></i> Documentation étendue</a>
|
||||
<a target="_rsc" href="https://forum.grid.space"><i class="fab fa-discourse"></i> fora Grid.Space</a>
|
||||
<a target="_rsc" href="https://discord.gg/suyCCgr"><i class="fab fa-discord"></i> Discord serveur de chat en direct</a>
|
||||
<a target="_rsc" href="https://www.youtube.com/playlist?list=PLRoVgyRoWZpumQIKWm7oldx3bjDivqP24"><i class="fab fa-youtube"></i> Youtube vidéos et tutoriels</a>
|
||||
<a target="_rsc" href="https://twitter.com/grid_space_3d"><i class="fab fa-twitter"></i> Suivre Grid.Space sur Twitter</a>
|
||||
<a target="_rsc" href="https://facebook.com/groups/kirimoto"><i class="fab fa-facebook"></i> Kiri:Moto Groupe d'usagers sur Facebook</a>
|
||||
</div>
|
||||
<b class="header">Options complémentaires</b>
|
||||
<p>
|
||||
Dans <button><i class="fas fa-user-cog"></i></button> le menu utilsateur en haut à droite,
|
||||
utiliser l'option <span class="mono">export</span> pour créer unecopie téléchargeable des
|
||||
profils du matériel et (optionellement) de l'espace de travail. Ce fichier pourra ensuite
|
||||
être utilisé pour contrôler et rétablir un instantané de votre installation à tout moment.
|
||||
Il peut également être partagé afin que les développeurs et autres utilisateurs puissent
|
||||
reproduire votre environnement pour aider au débogage.
|
||||
</p>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-project" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Open Source</b>
|
||||
<p>
|
||||
Kiri:Moto est totalement <a href="https://github.com/GridSpace/grid-apps" target="_github">open-source</a>.
|
||||
Consultez la page du projet Github. Il existe des projets complémentaires, tant sur le plan matériel que logiciel.
|
||||
Les nouveaux développeurs et les contributions au code sont les bienvenus à tout moment. La licence du code est celle du MIT.
|
||||
</p><br><p>
|
||||
<a target="_paypal" href="https://paypal.me/gridspace3d?locale.x=en_US">Toute donation</a> est également bienvenue.
|
||||
</p>
|
||||
<br><b class="header">Intégrations</b>
|
||||
<p>Kiri:Moto est également intégré dans plusieurs autres applications web</p>
|
||||
<li><a target="app" href="https://appstore.onshape.com/apps/CAM/EAAEWYIOMQKBENEMYW2N7MF253CT4WYL6SUJGEY=/description"><b>Onshape</b></a> via son magasin d'Applications</li>
|
||||
<li><a target="app" href="http://www.thingiverse.com/apps/kirimoto/"><b>Thingiverse</b></a> en tant que native Thing Apps</li>
|
||||
<li><a target="app" href="https://simplyprint.io">SimplyPrint.io</a> as the primary slicer under the covers</li>
|
||||
<li><a target="app" href="https://sienci.com/camlab-help/">CAMLab</a> est une branche d'une version antérieure de Kiri:Moto</li>
|
||||
</div></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
642
web/kiri/lang/fr.js
Normal file
642
web/kiri/lang/fr.js
Normal file
|
|
@ -0,0 +1,642 @@
|
|||
// French localization for Kiri:Moto
|
||||
// Will defer to English map for any missing key/value pairs
|
||||
kiri.lang['fr'] =
|
||||
kiri.lang['fr-fr'] = {
|
||||
// common keys and menus
|
||||
animate: "animer", // CAM animate button
|
||||
arrange: "organiser", // layout workspace objects
|
||||
axis: "axe", // left object scale pop menu
|
||||
clear: "effacer", // clear workspace (remove all objects)
|
||||
copy: "copier",
|
||||
delete: "supprimer",
|
||||
detail: "détail",
|
||||
done: "terminé",
|
||||
enable: "permettre",
|
||||
export: "exporter",
|
||||
files: "fichiers",
|
||||
help: "aide",
|
||||
ghost: "translucide", // left render pop menu (wireframe)
|
||||
hide: "cacher", // left render pop menu (invisible)
|
||||
home: "position d'origine",
|
||||
import: "importer",
|
||||
language: "langue",
|
||||
machine: "machine", // device or machine
|
||||
metric: "métrique",
|
||||
name: "nom",
|
||||
prefs: "préfs", // left menu "preferences"
|
||||
preview: "prévisualiser",
|
||||
recent: "récent",
|
||||
render: "rendu", // left render pop menu
|
||||
reset: "remettre",
|
||||
rotate: "tourner", // left rotate pop menu
|
||||
save: "sauvegarder",
|
||||
scale: "échelle", // left object scale pop menu
|
||||
setup: "setup",
|
||||
settings: "paramètres",
|
||||
size: "taille",
|
||||
solid: "solide", // view type pop menu
|
||||
tool: "outil",
|
||||
tools: "outils", // CAM tool menu button
|
||||
top: "haut",
|
||||
type: "genre", // CAM tool type
|
||||
version: "version",
|
||||
view: "vue", // left view pop menu
|
||||
wire: "filaire", // left render pop menu
|
||||
|
||||
acct_xpo: ["faites une sauvegarde de votre machine","et des profils des machines avec","l'option d'inclure les","objets et positions d'environnement"],
|
||||
|
||||
// RIGHT-CLICK CONTEXT MENU
|
||||
rc_clws: "effacer l'environnement",
|
||||
rc_xpws: "exporter l'environnement",
|
||||
rc_lafl: "poser à plat",
|
||||
rc_mirr: "refléter",
|
||||
rc_dupl: "dupliquer",
|
||||
rc_xstl: "exporter en STL",
|
||||
|
||||
// DEVICE MENU and related dialogs
|
||||
dm_sldt: "sélectionner un genre de machine",
|
||||
dm_stdd: "machines standards",
|
||||
dm_mydd: "mes machines",
|
||||
dm_seld: "machine sélectionnée",
|
||||
dm_rcnt: "fichiers récents",
|
||||
dm_savs: "paramètres sauvegardés",
|
||||
dm_appp: "Préférences d'Application",
|
||||
|
||||
// CAM Tool Dialog
|
||||
td_tyem: "plat", // end mill
|
||||
td_tybm: "boule", // ball mill
|
||||
td_tytm: "v forme", // taper mill
|
||||
td_tonm: "outil #",
|
||||
td_shft: "tige", // endmill shaft specs
|
||||
td_flut: "flûte", // endmill flute specs
|
||||
td_tapr: "cône", // endmill taper specs
|
||||
|
||||
// DEVICE dialog groups
|
||||
dv_gr_dev: "périphérique",
|
||||
dv_gr_ext: "extrudeur",
|
||||
dv_gr_out: "sortie",
|
||||
dv_gr_gco: "macros gcode",
|
||||
|
||||
// DEVICE dialog (_s = label, _l = hover help)
|
||||
dv_name_s: "nom",
|
||||
dv_name_l: "nom du matériel",
|
||||
dv_fila_s: "filament",
|
||||
dv_fila_l: "diamètre en millimètres",
|
||||
dv_nozl_s: "buse",
|
||||
dv_nozl_l: "diamètre en millimètres",
|
||||
dv_bedw_s: "largeur",
|
||||
dv_bedw_l: "unités de l'espace de travail",
|
||||
dv_bedd_s: "profondeur",
|
||||
dv_bedd_l: "unités de l'espace de travail",
|
||||
dv_bedh_s: "hauteur",
|
||||
dv_bedh_l: ["hauteur de construction maximale","en unités de l'espace de travail"],
|
||||
dv_spmx_s: "max spindle",
|
||||
dv_spmx_l: ["max spindle rpm speed","0 to disable"],
|
||||
dv_xtab_s: "positionnement absolu",
|
||||
dv_xtab_l: "déplacements extrusion absolu",
|
||||
dv_orgc_s: "origine au centre",
|
||||
dv_orgc_l: "origin du plateau au centre",
|
||||
// dv_orgt_s: "origin top",
|
||||
// dv_orgt_l: "part z origin top",
|
||||
dv_bedc_s: "plateau circulaire",
|
||||
dv_bedc_l: "le plateau du matériel est circulaire",
|
||||
dv_belt_s: "plateau tapis-roulant",
|
||||
dv_belt_l: "plateau à impression continue",
|
||||
dv_retr_s: "rétraction firmware",
|
||||
dv_retr_l: ["le firmware supporte G10/G11"],
|
||||
dv_fanp_s: "refroidissement",
|
||||
dv_fanp_l: "régler la puissance du ventilateur de refroidissement",
|
||||
dv_prog_s: "progression",
|
||||
dv_prog_l: "résultats de chaque % de progression",
|
||||
dv_layr_s: "couche",
|
||||
dv_layr_l: ["résultats de chaque","changement de couche"],
|
||||
dv_tksp_s: "délimiteur d'instruction",
|
||||
dv_tksp_l: ["ajouter un espace","entre les paramètres des axes","G0X0Y0X0","vs","G0 X0 Y0 Z0"],
|
||||
dv_strc_s: "éliminer les commentaires",
|
||||
dv_strc_l: ["éliminer les commentaires du gcode","les commentaires débutent par ;"],
|
||||
dv_fext_s: "extension du fichier",
|
||||
dv_fext_l: "extension du nom de fichier",
|
||||
dv_dwll_s: "dwell",
|
||||
dv_dwll_l: "script gcode dwell",
|
||||
dv_tool_s: "changement d'outil",
|
||||
dv_tool_l: "script de changement d'outil",
|
||||
dv_sspd_s: "spindle speed",
|
||||
dv_sspd_l: "set spindle speed",
|
||||
dv_paus_s: "pause",
|
||||
dv_paus_l: "script gcode de pause",
|
||||
dv_head_s: "header",
|
||||
dv_head_l: "script gcode de démarrage",
|
||||
dv_foot_s: "footer",
|
||||
dv_foot_l: "script gcode de fin",
|
||||
dv_lzon_s: "laser on",
|
||||
dv_lzon_l: "gcode laser on script",
|
||||
dv_lzof_s: "laser off",
|
||||
dv_lzof_l: "gcode laser off script",
|
||||
dv_exts_s: "sélectionner",
|
||||
dv_exts_l: "gcode pour activer cet extrudeur",
|
||||
dv_dext_s: "désélectionner",
|
||||
dv_dext_l: "gcode à lancer avant d'activer un autre extrudeur",
|
||||
dv_extd_s: "désélectionner",
|
||||
dv_extd_l: "gcode pour désactiver cet extrudeur",
|
||||
dv_exox_s: "décalage x",
|
||||
dv_exox_l: "décalage de buse en x",
|
||||
dv_exoy_s: "décalage y",
|
||||
dv_exoy_l: "décalage de buse en y",
|
||||
|
||||
// MODE
|
||||
mo_menu: "mode",
|
||||
mo_fdmp: "Impression FDM",
|
||||
mo_slap: "Impression SLA",
|
||||
mo_lazr: "Découpe / gravure Laser",
|
||||
mo_cncm: "Routeur CNC",
|
||||
|
||||
// SETUP
|
||||
su_menu: "installation",
|
||||
su_devi: "Matériels",
|
||||
su_tool: "Outils",
|
||||
su_locl: "Local",
|
||||
su_xprt: "Exporter",
|
||||
su_help: "Aide",
|
||||
|
||||
// LOAD
|
||||
fe_menu: "fichier",
|
||||
fn_recn: "Récents",
|
||||
fn_impo: "Importer",
|
||||
|
||||
// FUNCTION
|
||||
fn_menu: "action",
|
||||
fn_arra: "Organiser",
|
||||
fn_slic: "Découper",
|
||||
fn_prev: "Prévisualiser",
|
||||
fn_expo: "Exporter",
|
||||
|
||||
// VIEW
|
||||
vu_menu: "vue",
|
||||
vu_home: "Origine",
|
||||
vu_rset: "RAZ",
|
||||
vu_sptp: "Haut",
|
||||
vu_spfr: "Avant",
|
||||
vu_splt: "Gauche",
|
||||
vu_sprt: "Droite",
|
||||
|
||||
// WORKSPACE
|
||||
ws_menu: "vue",
|
||||
ws_save: "Sauvegarder",
|
||||
ws_cler: "Effacer",
|
||||
|
||||
// OPTIONS
|
||||
op_menu: "interface",
|
||||
op_disp: "affichage",
|
||||
op_xprt_s: "expert",
|
||||
op_xprt_l: "afficher plus d'options de paramétrage",
|
||||
op_decl_s: "logos",
|
||||
op_decl_l: "montrer les logos des appareils",
|
||||
op_dang_s: "expérimental",
|
||||
op_dang_l: "montrer les paramètres expérimentaux",
|
||||
op_hopo_s: "survol du menu",
|
||||
op_hopo_l: ["activer le survol du menu", "pour activer"],
|
||||
op_dark_s: "mode sombre",
|
||||
op_dark_l: "interface en mode sombre",
|
||||
op_comp_s: "ui compacte",
|
||||
op_comp_l: ["interface utilisateur compacte", "plus adapté aux petits écrans", "et tablettes"],
|
||||
op_shor_s: "montrer l'origine",
|
||||
op_shor_l: "indiquer l'origine du dispositif ou du processus",
|
||||
op_shru_s: "afficher les règles",
|
||||
op_shru_l: ["montrer les règles des axes", "sur le quadrillage"],
|
||||
op_sped_s: "afficher les vitesses",
|
||||
op_sped_l: ["afficher la vitesse en barre de couleur","en mode prévisualisation"],
|
||||
op_auto_s: "disposition automatique",
|
||||
op_auto_l: ["disposition automatique sur le plateau", "lorsque de nouveaux éléments sont ajoutés"],
|
||||
op_free_s: "disposition libre",
|
||||
op_free_l: ["autoriser la disposition déplaçable","sans effet en mode laser"],
|
||||
op_spcr_s: "espacement",
|
||||
op_spcr_l: ["espacement entre les objets", "avec la disposition automatique", "en unités d'espace de travail"],
|
||||
op_invr_s: "inverser zoom",
|
||||
op_invr_l: ["inverser la molette de la souris", "faire défiler le zoom"],
|
||||
op_save_s: "auto enregt",
|
||||
op_save_l: ["préserve les objets dans l'espace de travail","entre rechargement de l'application"],
|
||||
op_line_s: "type de ligne",
|
||||
op_line_l: ["style de ligne pour le rendu","impacte les performances 3d","chemin: 3d meilleur","plat: 2d bon","ligne = 1d rapide"],
|
||||
op_unit_s: "unités",
|
||||
op_unit_l: ["les unités d'espace de travail affectent","vitesses et distances"],
|
||||
op_anim_s: "animer",
|
||||
op_anim_l: ["densité du maillage de l'animation","plus haut = plus dense","nécessite plus de mémoire","et est plus lent"],
|
||||
|
||||
lo_menu: "disposition",
|
||||
|
||||
pt_menu: "pièces",
|
||||
pt_deci_s: "compression",
|
||||
pt_deci_l: ["activer / désactiver la compression","durant l'importation. Tranchage plus rapide","et usage réduit de la mémoire"],
|
||||
pt_qual_s: "qualité",
|
||||
pt_qual_l: ["niveau de détail à garder", "lors des opérations de tranchage", "plus bas = plus rapide"],
|
||||
pt_heal_s: "correction de maillage",
|
||||
pt_heal_l: ["tentative de correction", "des mailles non-fermées", "accroit le temps de tranchage"],
|
||||
|
||||
xp_menu: "exports",
|
||||
|
||||
// SETTINGS
|
||||
se_menu: "profil",
|
||||
se_load: "charger",
|
||||
se_save: "sauvegarder",
|
||||
|
||||
// FDM SLICING
|
||||
sl_menu: "couches",
|
||||
sl_lahi_s: "hauteur",
|
||||
sl_lahi_l: ["hauteur de chaque couche", "couche en millimètres"],
|
||||
ad_minl_s: "hauteur min",
|
||||
ad_minl_l: ["hauteur de couche minimale adaptative", "en millimètres", "doit être non nulle"],
|
||||
sl_ltop_s: "couches du haut",
|
||||
sl_ltop_l: ["nombre de couches solides", "à appliquer en", "haut de l'impression"],
|
||||
sl_lsld_s: "couches solides",
|
||||
sl_lsld_l: ["zones de remplissage solide calculées", "à partir des deltas de couches. voir", "menu surgissant des couches"],
|
||||
sl_lbot_s: "couches de base",
|
||||
sl_lbot_l: ["nombre de couches solides", "à appliquer en", "bas de l'impression"],
|
||||
ad_adap_s: "adaptive",
|
||||
ad_adap_l: ["utiliser des hauteurs de couche adaptatives", "avec 'hauteur de couche' en maximum", "et 'hauteur min' en minimum"],
|
||||
|
||||
// FDM SHELLS
|
||||
sl_shel_s: "parois",
|
||||
sl_shel_l: ["nombre de périmètre", "murs à générer"],
|
||||
sl_ordr_s: "ordre des parois",
|
||||
sl_ordr_l: ["ordre d'impression des parois","de l'intérieur vers l'extérieur", "ou de l'extérieur vers l'intérieur","affecte la qualité de surface"],
|
||||
sl_strt_s: "début de couche",
|
||||
sl_strt_l: ["point de départ de la couche", "dernier = fin de la couche", "centre = centre de la pièce", "origine = origine du dispositif"],
|
||||
ad_thin_s: "parois fines",
|
||||
ad_thin_l: ["détecte et comble les vides", "entre les parois de la coque"],
|
||||
|
||||
// FDM FILL
|
||||
fi_menu: "remplissage",
|
||||
fi_type: "type",
|
||||
fi_pcnt_s: "fraction de remplissage",
|
||||
fi_pcnt_l: ["valeurs de densité de remplissage","0.0 - 1.0"],
|
||||
fi_angl_s: "départ solide",
|
||||
fi_angl_l: ["angle de départ en degrés", "90 degrés ajoutés à ", "chaque couche suivante", "s'applique uniquement aux couches solides"],
|
||||
fi_over_s: "chevauchement",
|
||||
fi_over_l: ["chevauchement de l'enveloppe et du remplissage", "en tant que fraction du diamètre de la buse", "0,0 - 1,0"],
|
||||
// fi_rate_s: "vitesse d'impression",
|
||||
fi_rate_l: ["vitesse d'extrusion du remplissage", "régler à 0 pour utiliser par défaut", "la vitesse d'impression"],
|
||||
|
||||
// FDM FIRST LAYER
|
||||
fl_menu: "base",
|
||||
fl_lahi_s: "hauteur de couche",
|
||||
fl_lahi_l: ["hauteur de chaque couche", "en millimètres", "devrait être >= hauteur de la couche"],
|
||||
fl_rate_s: "vitesse périmètres",
|
||||
fl_rate_l: ["vitesse maximale d'impression des coques", "en millimètres / minute"],
|
||||
fl_frat_s: "vitesse remplissage",
|
||||
fl_frat_l: ["vitesse maximale d'impression du remplissage", "en millimètres / minute"],
|
||||
fl_mult_s: "débit",
|
||||
fl_mult_l: ["multiplicateur d'extrusion","0.0 - 2.0"],
|
||||
fl_sfac_s: "largeur",
|
||||
fl_sfac_l: ["multiplicateur de la taille de la buse", "modifie l'espacement des lignes"],
|
||||
fl_skrt_s: "jupe nb",
|
||||
fl_skrt_l: ["nombre de lignes de la jupe", "à générer pour la première couche"],
|
||||
fl_skro_s: "décalage bordure",
|
||||
fl_skro_l: ["jupe décalée de la partie", "en millimètres"],
|
||||
fl_nozl_s: "buse",
|
||||
fl_nozl_l: ["degrés en Celsius", "réglage de sortie utilisé", "lorsque celui-ci est égal à zéro"],
|
||||
fl_bedd_s: "température plateau",
|
||||
fl_bedd_l: ["degrés en Celsius", "réglage de sortie utilisé", "lorsque celui-ci est égal à zéro"],
|
||||
fr_spac_s: "écart radeau",
|
||||
fr_spac_l: ["espacement des couches supplémentaires", "entre la 1ère couche et le radeau", "en millimètres"],
|
||||
fr_nabl_s: "activer un radeau",
|
||||
fr_nabl_l: ["créer un radeau sous le ", "modèle pour une meilleure adhérence", "utilise le décalage des jupes et", "désactive la sortie des jupes"],
|
||||
|
||||
// FDM BELT ONLY
|
||||
fl_zoff_s: "décalage bande",
|
||||
fl_zoff_l: ["décalage de hauteur par rapport à la bande", "de l'extrusion la plus basse", "en millimètres"],
|
||||
fl_brim_s: "taille de bordure",
|
||||
fl_brim_l: ["ajoute une bordure à la partie inférieure","la taille est la largeur en millimètres","0 désactive"],
|
||||
fl_brmn_s: "seuil de bordure",
|
||||
fl_brmn_l: ["ajout de bordures uniquement quand le segment", "face à la bande est plus court que cela", "valeur en millimètres", "0 = infini"],
|
||||
fl_bled_s: "ancrage de pièce",
|
||||
fl_bled_l: ["ancrage de la pièce sur la bande", "au début de l'impression", "en millimètres"],
|
||||
|
||||
// FDM SUPPORT
|
||||
sp_menu: "support",
|
||||
sp_detect: "détecter",
|
||||
sp_dens_s: "densité",
|
||||
sp_dens_l: ["fraction 0.0 - 1.0","recommendé 0.15","0 désactive"],
|
||||
sp_size_s: "taille pilier",
|
||||
sp_size_l: ["largeur du pilier","en millimètres"],
|
||||
sp_offs_s: "décalage du pilier",
|
||||
sp_offs_l: ["décalage par rapport à la pièce","en millimètres"],
|
||||
sp_gaps_s: "écart des couches",
|
||||
sp_gaps_l: ["nombre de couches","de décalage de la pièce"],
|
||||
sp_span_s: "portée maximale",
|
||||
sp_span_l: ["portée non soutenue nécessitant", "un nouveau soutien à générer","en millimètres"],
|
||||
sp_angl_s: "angle max",
|
||||
sp_angl_l: ["angle de surplomb maximum avant", "de générer un pilier de soutien"],
|
||||
sp_area_s: "surface min",
|
||||
sp_area_l: ["surface minimale de","la colonne support","en millimètres"],
|
||||
sp_xpnd_s: "étendre",
|
||||
sp_xpnd_l: ["étendre la zone de soutien", "au-delà des limites d'une pièce","en millimètres"],
|
||||
sp_nozl_s: "extrudeur",
|
||||
sp_nozl_l: ["dans les systèmes multi-extrudeurs", "l'extrudeur à utiliser pour", "le matériau de support"],
|
||||
sp_auto_s: "automatique",
|
||||
sp_auto_l: ["activer les supports générés", "utiliser la géométrie at-slice-time", "les supports n'apparaîtront", "qu'une fois le tranchage terminé"],
|
||||
|
||||
// LASER SLICING
|
||||
ls_offs_s: "offset",
|
||||
ls_offs_l: ["adjust for beam width","en millimètres"],
|
||||
ls_lahi_s: "height",
|
||||
ls_lahi_l: ["layer height","in millimeters","0 = auto/detect"],
|
||||
ls_lahm_s: "min",
|
||||
ls_lahm_l: ["layer height minimum","will merge auto slices","under this thickness","in millimeters"],
|
||||
ls_sngl_s: "single",
|
||||
ls_sngl_l: ["perform only one slice","at specified layer height"],
|
||||
|
||||
// CNC COMMON terms
|
||||
cc_tool: "tool",
|
||||
cc_offs_s: "offset",
|
||||
cc_offs_l: ["offset tool center","from chosen path"],
|
||||
cc_spnd_s: "spindle rpm",
|
||||
cc_spnd_l: ["spindle speed in","revolutions / minute"],
|
||||
cc_sovr_s: "step over",
|
||||
cc_sovr_l: ["as a fraction of","tool diameter"],
|
||||
cc_sdwn_s: "step down",
|
||||
cc_sdwn_l: ["step down depth","for each pass","in workspace units","0 to disable"],
|
||||
cc_feed_s: "feed rate",
|
||||
cc_feed_l: ["max cutting speed in","workspace units / minute"],
|
||||
cc_plng_s: "plunge rate",
|
||||
cc_plng_l: ["max z axis speed in","workspace units / minute"],
|
||||
cc_sngl_s: "select lines only",
|
||||
cc_sngl_l: ["select only single edges","instead of connected polylines"],
|
||||
|
||||
// CNC COMMON
|
||||
cc_menu: "limits",
|
||||
cc_flip: "flip",
|
||||
cc_rapd_s: "xy feed",
|
||||
cc_rapd_l: ["max xy moves feedrate","in workspace units / minute"],
|
||||
cc_rzpd_s: "z feed",
|
||||
cc_rzpd_l: ["max z moves feedrate","in workspace units / minute"],
|
||||
|
||||
cc_loff_s: "offset",
|
||||
cc_loff_l: ["distance from stock face","for leveling pass","in workspace units"],
|
||||
|
||||
// CNC ROUGHING
|
||||
cr_menu: "rough",
|
||||
cr_lsto_s: "leave stock",
|
||||
cr_lsto_l: ["horizontal offset from vertical faces","stock to leave for finishing pass","in workspace units"],
|
||||
cr_ease_s: "ease down",
|
||||
cr_ease_l: ["plunge cuts will","spiral down or ease","along a linear path"],
|
||||
cr_clrt_s: "clear top",
|
||||
cr_clrt_l: ["run a clearing pass over","the bounding area of the part","at z = 0"],
|
||||
cr_clrp_s: "clear voids",
|
||||
cr_clrp_l: ["mill out through pockets","instead of just the outline"],
|
||||
cr_clrf_s: "clear faces",
|
||||
cr_clrf_l: ["interpolate step down to","clear any detected flat areas"],
|
||||
cr_olin_s: "inside only",
|
||||
cr_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
|
||||
// CNC OUTLINE
|
||||
co_menu: "outline",
|
||||
co_dogb_s: "dogbones",
|
||||
co_dogb_l: ["insert dogbone cuts","into inside corners"],
|
||||
co_wide_s: "wide cutout",
|
||||
co_wide_l: ["widen outside cutout paths","for deep cuts in hard material"],
|
||||
co_olin_s: "inside only",
|
||||
co_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
co_olot_s: "outside only",
|
||||
co_olot_l: ["limit cutting to","exterior part boundaries","which can be thought of","as the shadow outline"],
|
||||
co_omit_s: "omit through",
|
||||
co_omit_l: "eliminate thru holes",
|
||||
co_olen_s: "enable",
|
||||
co_olen_l: "enabled outline cutting",
|
||||
|
||||
// CNC CONTOUR
|
||||
cn_menu: "contour",
|
||||
cf_angl_s: "max angle",
|
||||
cf_angl_l: ["angles greater than this","are considered vertical"],
|
||||
cf_curv_s: "curves only",
|
||||
cf_curv_l: ["limit linear cleanup","to curved surfaces"],
|
||||
cf_olin_s: "inside only",
|
||||
cf_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
cf_linx_s: "enable y pass",
|
||||
cf_linx_l: "linear y-axis finishing",
|
||||
cf_liny_s: "enable x pass",
|
||||
cf_liny_l: "linear x-axis finishing",
|
||||
|
||||
// CNC TRACE
|
||||
cu_menu: "trace",
|
||||
cu_type_s: "type",
|
||||
cu_type_l: ["follow = tool tip follows line","right or left = tool tip","follows line offset by tool radius"],
|
||||
|
||||
// CNC DRILLING
|
||||
cd_menu: "drill",
|
||||
cd_axis: "axis",
|
||||
cd_points: "points",
|
||||
cd_plpr_s: "plunge per",
|
||||
cd_plpr_l: ["max plunge between","dwell periods","in workspace units","0 to disable"],
|
||||
cd_dwll_s: "dwell time",
|
||||
cd_dwll_l: ["dwell time","between plunges in","in milliseconds"],
|
||||
cd_lift_s: "drill lift",
|
||||
cd_lift_l: ["lift between plunges","after dwell period","in workspace units","0 to disable"],
|
||||
cd_regi_s: "register",
|
||||
cd_regi_l: ["drill registration holes","for double-sided parts","independent of enable","drilling but uses same","tool and settings"],
|
||||
|
||||
// CNC CUTOUT TABS
|
||||
ct_menu: "tabs",
|
||||
ct_angl_s: "angle",
|
||||
ct_angl_l: ["starting angle for tab spacing","in degrees (0-360)"],
|
||||
ct_numb_s: "count",
|
||||
ct_numb_l: ["number of tabs to use","will be spaced evenly","around the part"],
|
||||
ct_wdth_s: "width",
|
||||
ct_wdth_l: "width in workspace units",
|
||||
ct_hght_s: "height",
|
||||
ct_hght_l: "height in workspace units",
|
||||
ct_dpth_s: "depth",
|
||||
ct_dpth_l: ["distance in workspace units","that the tab projects from","the part surface"],
|
||||
ct_midl_s: "midline",
|
||||
ct_midl_l: ["use midline of tab","instead of z bottom","for double-sided work"],
|
||||
ct_nabl_s: "auto",
|
||||
ct_nabl_l: ["auto generate radial tabs","projected from part center","using count and angle offset"],
|
||||
|
||||
// OUTPUT
|
||||
ou_menu: "sortie",
|
||||
|
||||
// LASER KNIFE
|
||||
dk_menu: "knife",
|
||||
dk_dpth_s: "cut depth",
|
||||
dk_dpth_l: ["final cut depth","in millimeters"],
|
||||
dk_pass_s: "cut passes",
|
||||
dk_pass_l: ["number of passes","down to cut depth"],
|
||||
dk_offs_s: "tip offset",
|
||||
dk_offs_l: ["distance from blade tip","to center of tool","in millimeters"],
|
||||
|
||||
// OUTPUT LASER
|
||||
ou_spac_s: "spacing",
|
||||
ou_spac_l: ["distance between layer output","in millimeters"],
|
||||
ou_scal_s: "scaling",
|
||||
ou_scal_l: "multiplier (0.1 to 100)",
|
||||
ou_powr_s: "power",
|
||||
ou_powr_l: ["0 - 100","represents %"],
|
||||
ou_sped_s: "speed",
|
||||
ou_sped_l: "millimeters / minute",
|
||||
ou_mrgd_s: "merged",
|
||||
ou_mrgd_l: ["merge all layers using","color coding to denote","stacking depth"],
|
||||
ou_grpd_s: "grouped",
|
||||
ou_grpd_l: ["retain each layer as","a unified grouping","instead of separated","polygons"],
|
||||
ou_layr_s: "layer order",
|
||||
ou_layr_l: ["output layer order","from top right to","bottom left"],
|
||||
ou_layo_s: "layer color",
|
||||
ou_layo_l: ["output layer colors","for each z index","overridden by merged"],
|
||||
ou_drkn_s: "drag knife",
|
||||
ou_drkn_l: ["enable drag knife","output in gcode","cut radii are added","to corners with","cut down passes"],
|
||||
|
||||
// OUTPUT FDM
|
||||
ou_nozl_s: "température buse",
|
||||
ou_nozl_l: "degrés en celsius",
|
||||
ou_bedd_s: "température plateau",
|
||||
ou_bedd_l: "degrés en celsius",
|
||||
ou_feed_s: "vitesse impression",
|
||||
ou_feed_l: ["vitesse d'impression maximale","millimètres / minute"],
|
||||
ou_fini_s: "vitesse coque",
|
||||
ou_fini_l: ["vitesse de la coque extérieure","millimètres / minute"],
|
||||
ou_move_s: "vitesse déplacement",
|
||||
ou_move_l: ["vitesse de déplacement sans impression","millimètres / minute","0 = active déplacements G0"],
|
||||
ou_shml_s: "débit de coque",
|
||||
ou_flml_s: "débit de solidité",
|
||||
ou_spml_s: "débit de remplissage",
|
||||
ou_exml_l: ["multiplicateur d'extrusion","0.0 - 2.0"],
|
||||
ou_fans_s: "vitesse ventilateur",
|
||||
ou_fans_l: "0 - 255",
|
||||
|
||||
// OUTPUT CAM
|
||||
ou_toll_s: "tolerance",
|
||||
ou_toll_l: ["surface precision","in workspace units","lower is slower and","uses more memory","0 = automatic based","on animate preference"],
|
||||
ou_zanc_s: "z anchor",
|
||||
ou_zanc_l: ["controls the position of the part","when stock Z exceeds part Z"],
|
||||
ou_ztof_s: "z offset",
|
||||
ou_ztof_l: ["offset z anchor","in workspace units","has no effect when","anchor is middle"],
|
||||
ou_zbot_s: "z bottom",
|
||||
ou_zbot_l: ["offset from part bottom","to limit cutting depth","in workspace units"],
|
||||
ou_zclr_s: "z clearance",
|
||||
ou_zclr_l: ["safe travel offset","from top of part","in workspace units"],
|
||||
ou_ztru_s: "z thru",
|
||||
ou_ztru_l: ["extend cutout pass down","in workspace units"],
|
||||
ou_conv_s: "conventional",
|
||||
ou_conv_l: ["milling direction","uncheck for 'climb'"],
|
||||
ou_depf_s: "depth first",
|
||||
ou_depf_l: ["optimize pocket cuts","with depth priority"],
|
||||
|
||||
// CAM STOCK
|
||||
cs_menu: "stock",
|
||||
cs_wdth_s: "width",
|
||||
cs_wdth_l: ["width (x) in workspace units","0 defaults to part size"],
|
||||
cs_dpth_s: "depth",
|
||||
cs_dpth_l: ["depth (y) in workspace units","0 defaults to part size"],
|
||||
cs_hght_s: "height",
|
||||
cs_hght_l: ["height (z) in workspace units","0 defaults to part size"],
|
||||
cs_offs_s: "offset",
|
||||
cs_offs_l: ["use width, depth, height","as offsets from max","part size on platform"],
|
||||
cs_clip_s: "clip to",
|
||||
cs_clip_l: ["rough and outline","clip cutting paths","to defined stock"],
|
||||
cs_offe_s: "enable",
|
||||
cs_offe_l: "enable milling stock",
|
||||
|
||||
// ORIGIN (CAM & LASER)
|
||||
or_bnds_s: "origin bounds",
|
||||
or_bnds_l: ["origin is relative to","boundary of all objects"],
|
||||
or_cntr_s: "origin center",
|
||||
or_cntr_l: "origin is referenced from the center",
|
||||
or_topp_s: "origin top",
|
||||
or_topp_l: "origin is references from the top of objects",
|
||||
|
||||
// FDM ADVANCED
|
||||
ad_menu: "expert",
|
||||
ad_rdst_s: "distance de rétraction",
|
||||
ad_rdst_l: ["longueur de filament à rétracter", "pour les longs mouvements. en millimètres"],
|
||||
ad_rrat_s: "vitesse de rétraction",
|
||||
ad_rrat_l: ["vitesse de rétraction","du filament en mm/s"],
|
||||
ad_rdwl_s: "réenclencher",
|
||||
ad_wpln_s: "essuyage rétractation",
|
||||
ad_wpln_l: ["mouvement sans impression", "après rétraction", "en millimètres"],
|
||||
ad_rdwl_l: ["durée de réenclenchement", "filament et mouvement", "en millisecondes"],
|
||||
ad_scst_s: "cabotage",
|
||||
ad_scst_l: ["extrémité non imprimée", "des coques du périmètre", "en millimètres"],
|
||||
ad_msol_s: "min solide",
|
||||
ad_msol_l: ["aire minimale (mm^2)","requise pour rester solide","doit être > 0.1"],
|
||||
ad_mins_s: "vitesse minimale",
|
||||
ad_mins_l: ["vitesse minimale","des segments courts"],
|
||||
ad_spol_s: "chemin court",
|
||||
ad_spol_l: ["les polygones plus courts", "auront la vitesse réduite et", "seront ramenés à la vitesse minimale", "en millimètres"],
|
||||
ad_arct_s: "tolérance arc",
|
||||
ad_arct_l: ["convertir les lignes des facettes en arcs", "tolérance de dérive du point central", "lors de la correspondance des points d'arc", "considérer les valeurs autour de 0,15", "en millimètres", "0 désactive"],
|
||||
ad_zhop_s: "décalage en Z",
|
||||
ad_zhop_l: ["levée du z","sur les mouvements de rétraction", "en millimètres", "0 désactive"],
|
||||
ad_abkl_s: "anti-backlash",
|
||||
ad_abkl_l: ["pour une meilleure finition de la surface plane", "utiliser des micro-mouvements pour annuler", "le jeu dans la sortie de la couche solide", "en millimètres", "0 désactive", "si le firmware reconnait le M425", "l'utiliser dans l'en-tête du gcode", "et mettre à 0"],
|
||||
ad_lret_s: "rétraction au changement de couche",
|
||||
ad_lret_l: ["forcer la rétraction du filament", "entre les couches"],
|
||||
ad_play_s: "couches de polissage",
|
||||
ad_play_l: ["polir jusqu'au nombre spécifié", "# de couches à la fois"],
|
||||
ad_pspd_s: "vitesse de polissage",
|
||||
ad_pspd_l: ["vitesse de polissage", "en millimètres / minute"],
|
||||
|
||||
// CAM EXPERT
|
||||
cx_fast_s: "skip shadow",
|
||||
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"],
|
||||
|
||||
// FDM GCODE
|
||||
ag_menu: "gcode",
|
||||
ag_nozl_s: "buse",
|
||||
ag_nozl_l: "sélectionner la buse ou la tête d'impression",
|
||||
ag_paws_s: "couches de pause",
|
||||
ag_paws_l: ["liste de couches séparées par des virgules", "pour injecter des commandes de pause avant"],
|
||||
ag_loop_s: "couches de répétitions",
|
||||
ag_loop_l: ["des plages de couches à répéter dans le format ", "premier-compte dernier,premier-compte dernier,...", "compte omis = 1"],
|
||||
|
||||
// SLA MENU
|
||||
sa_menu: "tranchage",
|
||||
sa_lahe_s: "hauteur de couche",
|
||||
sa_lahe_l: ["hauteur de couche","en millimètres"],
|
||||
sa_shel_s: "hollow shell",
|
||||
sa_shel_l: ["shell thickness in mm","use multiple of layer height","use 0 for solid (disabled)"],
|
||||
sa_otop_s: "open top",
|
||||
sa_otop_l: ["if shell is enabled","results in an open top"],
|
||||
sa_obas_s: "open base",
|
||||
sa_obas_l: ["if shell is enabled","results in an open base","disabled with supports"],
|
||||
|
||||
sa_layr_m: "layers",
|
||||
sa_lton_s: "light on time",
|
||||
sa_lton_l: ["layer light on","time in seconds"],
|
||||
sa_ltof_s: "light off time",
|
||||
sa_ltof_l: ["layer light off","time in seconds"],
|
||||
sa_pldi_s: "peel distance",
|
||||
sa_pldi_l: ["peel distance","in millimeters"],
|
||||
sa_pllr_s: "peel lift rate",
|
||||
sa_pllr_l: ["peel lift speed","in mm/sec"],
|
||||
sa_pldr_s: "peel drop rate",
|
||||
sa_pldr_l: ["peel drop speed","in mm/sec"],
|
||||
|
||||
sa_base_m: "base",
|
||||
sa_balc_s: "layer count",
|
||||
sa_balc_l: ["number of","base layers"],
|
||||
sa_bltn_l: ["base layer light on","time in seconds"],
|
||||
sa_bltf_l: ["base layer light off","time in seconds"],
|
||||
|
||||
sa_infl_m: "infill",
|
||||
sa_ifdn_s: "density",
|
||||
sa_ifdn_l: ["percent infill","requires shell","0 = disabled","valid 0.0 - 1.0"],
|
||||
sa_iflw_s: "line width",
|
||||
sa_iflw_l: ["hatch line width","in millimeters"],
|
||||
|
||||
sa_supp_m: "support",
|
||||
sa_slyr_s: "base layers",
|
||||
sa_slyr_l: ["base support layers","value range 0-10"],
|
||||
sa_slgp_s: "gap layers",
|
||||
sa_slgp_l: ["number of layers between","raft and bottom of object"],
|
||||
sa_sldn_s: "density",
|
||||
sa_sldn_l: ["used to compute the","number of support pillars","0.0-1.0 (0 = disable)"],
|
||||
sa_slsz_s: "size",
|
||||
sa_slsz_l: ["max size of a","support pillar","in millimeters"],
|
||||
sa_slpt_s: "points",
|
||||
sa_slpt_l: ["number of points in","each support pillar","in millimeters"],
|
||||
sl_slen_l: "enable supports",
|
||||
|
||||
sa_outp_m: "output",
|
||||
sa_opzo_s: "z offset",
|
||||
sa_opzo_l: ["z layer offset","almost always 0.0","0.0-1.0 in millimeters"],
|
||||
sa_opaa_s: "anti alias",
|
||||
sa_opaa_l: ["enable anti-aliasing","produces larger files","can blur details"]
|
||||
};
|
||||
1
web/kiri/lang/pl-help.html
Symbolic link
1
web/kiri/lang/pl-help.html
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
pl-pl-help.html
|
||||
180
web/kiri/lang/pl-pl-help.html
Normal file
180
web/kiri/lang/pl-pl-help.html
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
<div id="help" class="f-col a-stretch">
|
||||
<!-- tłumaczenie jako własność publiczna (bez licencji) -->
|
||||
<div class="title f-row j-center">
|
||||
<label>Kiri:Moto Pomoc dla programu do cięcia modeli trójwymiarowych</label>
|
||||
<label id="kiri-version"></label>
|
||||
</div>
|
||||
|
||||
<div class="f-row">
|
||||
|
||||
<div id="help-sel" class="f-col">
|
||||
<div class="help-label" tab="about">o programie</div>
|
||||
<div class="help-label" tab="start">początki</div>
|
||||
<div class="help-label" tab="controls">sterowanie</div>
|
||||
<div class="help-label" tab="support">wsparcie</div>
|
||||
<div class="help-label" tab="project">projekt</div>
|
||||
</div>
|
||||
|
||||
<div id="help-tabs" class="f-grow">
|
||||
<div id="help-tab-about" class="help-tab f-col a-center">
|
||||
<div class="content">
|
||||
<p>
|
||||
<b>Kiri:Moto</b> jest unikalnym, opartym na przeglądarce, w pełni otwartym programem
|
||||
do cięcia modeli, który zamienia modele 3d w instrukcje maszynowe dla <u>drukarek 3D</u>,
|
||||
<u>frezarek CNC</u> i <u>wycinarek laserowych</u>.
|
||||
</p><br>
|
||||
<p>
|
||||
Oparcie na przeglądarce oznacza, że <i>całe</i> przetwarzanie odbywa się w lokalnej
|
||||
przeglądarce, a nie w chmurze. Twoje dane i modele pozostają <i>prywatne</i> tylko dla Ciebie.
|
||||
</p><br>
|
||||
<p>
|
||||
Oznacza to, że Kiri zachowuje się tak samo, jak natywny program na komputerze użytkownika.
|
||||
Bezpieczna tak jak bezpieczna jest piaskownica przeglądarki.
|
||||
</p><br>
|
||||
<p>
|
||||
Kolejną zaletą działania w sieci jest to, że Kiri jest zawsze aktualny. Nowa strona
|
||||
nowe funkcje, poprawki błędów i aktualizacje pojawiają się często. Jeśli chcesz uruchomić
|
||||
starszą wersję Kiri lub wersję rozwojową, należy wybrać ją z menu użytkownika w prawym górnym rogu.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grow"></div>
|
||||
<i>Słowo Kiri pochodzi od kiri-e, która jest japońską sztuką wycinania papieru</i>.
|
||||
<i>Moto to skrót od "Modeling Tool"</i>.
|
||||
</div>
|
||||
|
||||
<div id="help-tab-start" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Skrócona instrukcja obsługi</b>
|
||||
<div class="content">
|
||||
<p>
|
||||
<li id="help-start">obejrzyj (po angielsku) <a href="https://youtu.be/08795Sj22QE" target="youtube">The Definitive Video Guide to Kiri:Moto 2.5</a></li>
|
||||
<li><button><i class="fas fa-cogs"></i></button> menu ustawienia <button><i class="fas fa-cube"></i></button> urządzenia i tryby</li>
|
||||
<li><button><i class="fas fa-sliders-h"></i></button> ustawienia interfejsu użytkownika i trybów</li>
|
||||
<li><button><i class="fas fa-plus"></i></button> dopasowanie parametrów urządzenia, jeśli chcesz zmienić ustawienia domyślne</li>
|
||||
<li><button><i class="fas fa-folder"></i></button> otwórz plik lub <button><i class="fas fa-file-upload"></i></button> zaimportuj element do przestrzeni roboczej</li>
|
||||
<li>uzyj menu po prawej stronie by dopasować parametry krojenia obiektów</li>
|
||||
<li><button><i class="fas fa-bars"></i></button> aby zobaczyć jak działają parametry, pokrój obiekty</li>
|
||||
<li><button><i class="fas fa-cubes"></i></button> podgląd ścieżki z pokrojonych obiektów</li>
|
||||
<li><button><i class="fas fa-file-download"></i></button> eksportuj ścieżki zmian do g-kodu lub pliku svg</li>
|
||||
</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<b class="header">Tryby pracy</b>
|
||||
<p>Każdy tryb (FDM, CAM, Laser, SLA) ma inne funkcje i ustawienia.
|
||||
Obejrzyj filmy na Youtube, aby dowiedzieć się więcej.
|
||||
</p>
|
||||
</div>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-print" class="help-tab f-col">o druku 3d</div>
|
||||
<div id="help-tab-mill" class="help-tab f-col">o frezowaniu cnc</div>
|
||||
<div id="help-tab-laser" class="help-tab f-col">o cięciu laserem</div>
|
||||
|
||||
<div id="help-tab-controls" class="help-tab f-col a-center"><div class="content">
|
||||
<div class="f-row">
|
||||
<table>
|
||||
<tr><td colspan="2" class="header">Sterowanie klawiaturą</td><tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><th>Klawisz</th><th>Działanie</th></tr>
|
||||
<tr><td colspan=2 class="header2">Konfiguracja</td></tr>
|
||||
<tr><td><label>e</label></td><td>Wybór urządzenia</td></tr>
|
||||
<tr><td><label>o</label></td><td>Wybór narzędzi CAM</td></tr>
|
||||
<tr><td><label>c</label></td><td>Lokalna siatka odniesienia urządzeń</td></tr>
|
||||
<tr><td><label>q</label></td><td>Panel sterowania</td></tr>
|
||||
<tr><td><label>l</label></td><td>Profile prac</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Tryb</td></tr>
|
||||
<tr><td><label>a</label></td><td>Wyrównanie</td></tr>
|
||||
<tr><td><label>s</label></td><td>Krojenie</td></tr>
|
||||
<tr><td><label>p</label></td><td>Podgląd</td></tr>
|
||||
<tr><td><label>g</label></td><td>Animacja</td></tr>
|
||||
<tr><td><label>x</label></td><td>Eksport</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Plik</td></tr>
|
||||
<tr><td><label>i</label></td><td>Import</td></tr>
|
||||
<tr><td><label>r</label></td><td>Ostatnie</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Widok</td></tr>
|
||||
<tr><td><label>h</label></td><td>Początek</td></tr>
|
||||
<tr><td><label>t</label></td><td>Góra</td></tr>
|
||||
<tr><td><label>f</label></td><td>Z przodu</td></tr>
|
||||
<tr><td><label>b</label></td><td>Z tyłu</td></tr>
|
||||
<tr><td><label>z</label></td><td>Przywrócenie ustawień widoku</td></tr>
|
||||
<tr><td><label>< ></label></td><td>Widok cykli</td></tr>
|
||||
<tr><td><label>v</label></td><td>Podświetl (wyrównanie)</td></tr>
|
||||
<tr><td><label>v</label></td><td>Warstwa (plastry/podgląd)</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Obiekty</td></tr>
|
||||
<tr><td><label>d</label></td><td>Powiel</td></tr>
|
||||
<tr><td><label>m</label></td><td>Odbij</td></tr>
|
||||
<tr><td><label>o</label></td><td>Ustawienia obrotów</td></tr>
|
||||
<tr><td><label>delete</label></td><td>Kasowanie</td></tr>
|
||||
<tr><td><label>arrow</label></td><td>Obrót o 90°</td></tr>
|
||||
<tr><td><label>shift-arrow</label></td><td>Obrót o 5°</td></tr>
|
||||
<tr><td><label>option-arrow</label></td><td>Przesuń o 5mm</td></tr>
|
||||
<tr><td><label>ctrl-a</label></td><td>Zaznacz wszystko</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Pomoc</td></tr>
|
||||
<tr><td><label>?</label></td><td>To okno</td></tr>
|
||||
<tr><td><br><br></td></tr>
|
||||
<tr><td colspan="2" class="header">Ustawienia myszy</td><tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><th>Combo</th><th>Akcje</th></tr>
|
||||
<tr><td colspan=2 class="header2">Widok</td></tr>
|
||||
<tr><td><label>przesuń</label> koła</td><td>Zmiana warstwy</td></tr>
|
||||
<tr><td><label>meta</label> przemieść</td><td>przemieść obiekty</td></tr>
|
||||
<tr><td><label>prawy-przesuń</label></td><td>przemieść obiekty</td></tr>
|
||||
<tr><td><label>lewy-drag</label></td><td>Obróć</td></tr>
|
||||
<tr><td><label>kółko myszy</label></td><td>Powiększ</td></tr>
|
||||
<tr><td><label>środkowy-przesuń</label></td><td>Powiększ</td></tr>
|
||||
<tr><td><label>meta</label> przesuń</td><td>przemieść obiekty</td></tr>
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan=2 class="header2">Obiekty</td></tr>
|
||||
<tr><td><label>ctrl-click</label></td><td>Dopasowanie ściany do podłoża</td></tr>
|
||||
<tr><td><label>meta-click</label></td><td>Dopasowanie ściany do podłoża</td></tr>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-support" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Zasoby</b>
|
||||
<div class="content nounderline">
|
||||
<a target="_rsc" href="https://docs.grid.space/projects/kiri-moto"><i class="fas fa-question-circle"></i> Rozszerzona dokumentacja</a>
|
||||
<a target="_rsc" href="https://forum.grid.space"><i class="fab fa-discourse"></i> Forum Grid.Space</a>
|
||||
<a target="_rsc" href="https://discord.gg/suyCCgr"><i class="fab fa-discord"></i> czat na Discord</a>
|
||||
<a target="_rsc" href="https://www.youtube.com/playlist?list=PLRoVgyRoWZpumQIKWm7oldx3bjDivqP24"><i class="fab fa-youtube"></i> Filmy i poradniki na Youtube</a>
|
||||
<a target="_rsc" href="https://twitter.com/grid_space_3d"><i class="fab fa-twitter"></i> Śledź Grid.Space na Twitterze</a>
|
||||
<a target="_rsc" href="https://facebook.com/groups/kirimoto"><i class="fab fa-facebook"></i> Kiri:Moto Grupa uzytkowników na feceboku (mordoksiążce)</a>
|
||||
</div>
|
||||
<b class="header">Opcje w programie</b>
|
||||
<p>
|
||||
Pod przyciskiem <button><i class="fas fa-user-cog"></i></button> menu użytkownika w prawym górnym rogu,
|
||||
jest opcja <span class="mono">eksport</span>, tworzy on kopię do pobrania profili urządzenia
|
||||
(opcjonalnie również obszaru roboczego). Plik ten może być użyty do tworzenia kolejnych wersji i
|
||||
przywracania pełnej migawki konfiguracji w dowolnym momencie. Można go również udostępnić programistom
|
||||
lub innym użytkownikom, aby mogli odtworzyć środowisko użytkownika. Może to pomóc w usuwaniu błędów.
|
||||
</p>
|
||||
</div></div>
|
||||
|
||||
<div id="help-tab-project" class="help-tab f-col"><div class="content">
|
||||
<b class="header">Otwarte Oprogramowanie</b>
|
||||
<p>
|
||||
Kiri:Moto jest w całości <a href="https://github.com/GridSpace/grid-apps" target="_github">wolnym oprogramowaniem</a>.
|
||||
Sprawdź stronę projektu na Githubie. Istnieją projekty towarzyszące, zarówno sprzętowe jak i programowe.
|
||||
Nowi programiści i wkłady w kod źródłowy są oczywiście mile widziane. Kod źródłowy na licencji MIT.
|
||||
</p><br>
|
||||
<p>
|
||||
<a target="_paypal" href="https://paypal.me/gridspace3d?locale.x=en_US">Dotacje</a> mile widziane.
|
||||
</p>
|
||||
<br><b class="header">Integrations</b>
|
||||
<p>Kiri:Moto współdziała z różnymi innymi aplikacjami jako strona internetowa</p>
|
||||
<li><a target="app" href="https://appstore.onshape.com/apps/CAM/EAAEWYIOMQKBENEMYW2N7MF253CT4WYL6SUJGEY=/description"><b>Onshape</b></a> w sklepie App Store</li>
|
||||
<li><a target="app" href="http://www.thingiverse.com/apps/kirimoto/"><b>Thingiverse</b></a> jako natywne 'Thing Apps'</li>
|
||||
<li>Jako główny program do cięcia uzywany przez <a target="app" href="https://simplyprint.io">SimplyPrint.io</a></li>
|
||||
<li><a target="app" href="https://sienci.com/camlab-help/">CAMLab</a> jest programem pochodnym poprzedniej wersji Kiri:Moto</li>
|
||||
</div></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
645
web/kiri/lang/pl-pl.js
Normal file
645
web/kiri/lang/pl-pl.js
Normal file
|
|
@ -0,0 +1,645 @@
|
|||
// Polish. Język polski tłumaczony na zasadach własności publicznej
|
||||
kiri.lang['pl'] =
|
||||
kiri.lang['pl-pl'] = {
|
||||
// hasło i tłumaczenie
|
||||
animate: "animacja", // CAM animate button
|
||||
arrange: "rozmieść", // layout workspace objects
|
||||
axis: "osie", // left object scale pop menu
|
||||
clear: "wyczyść", //"czyszczenie z obiektów", // clear workspace (remove all objects)
|
||||
copy: "kopiowanie",
|
||||
delete: "kasowanie",
|
||||
detail: "szczegóły",
|
||||
done: "wykonaj",
|
||||
enable: "włącz",
|
||||
export: "eksport",
|
||||
files: "pliki",
|
||||
help: "pomoc",
|
||||
ghost: "druciak", // left render pop menu (wireframe)
|
||||
hide: "ukryj", // left render pop menu (invisible)
|
||||
home: "początek",
|
||||
import: "import",
|
||||
language: "język",
|
||||
machine: "maszyna", // device or machine
|
||||
metric: "metryka",
|
||||
name: "nazwa",
|
||||
prefs: "ustawienia", // left menu "preferences"
|
||||
preview: "podgląd",
|
||||
recent: "recent",
|
||||
render: "render", // left render pop menu
|
||||
reset: "reset",
|
||||
rotate: "obróć", // left rotate pop menu
|
||||
save: "zapisz",
|
||||
scale: "skala", // left object scale pop menu
|
||||
setup: "ustaw",
|
||||
settings: "ustawienia",
|
||||
size: "wielkość",
|
||||
slice: "plaserki",
|
||||
solid: "wypełniony", // view type pop menu
|
||||
start: "start",
|
||||
tool: "narzędzie",
|
||||
tools: "narzędzia", // CAM tool menu button
|
||||
top: "góra",
|
||||
type: "typ", // CAM tool type
|
||||
version: "wersja",
|
||||
view: "widok", // left view pop menu
|
||||
wire: "druciak", // left render pop menu "wire"
|
||||
|
||||
acct_xpo: ["zrób backup swojego urządzenia","i profil urządzenia z","opcja by zapisać przestrzeń roboczą","obiekty i pozycje"],
|
||||
|
||||
// RIGHT-CLICK CONTEXT MENU
|
||||
rc_clws: "wyczyść przestrzeń roboczą",
|
||||
rc_xpws: "wyeksportuj przestrzeń roboczą",
|
||||
rc_lafl: "ułóż płasko",
|
||||
rc_mirr: "odbicie", // lustro
|
||||
rc_dupl: "skopiuj",
|
||||
rc_xstl: "zapisz w formacie STL",
|
||||
|
||||
// DEVICE MENU and related dialogs
|
||||
dm_sldt: "wybierz rodzaj swojego urządzenia",
|
||||
dm_stdd: "zwykłe urządzenia",
|
||||
dm_mydd: "moje urządzenia",
|
||||
dm_seld: "wybierz urządzenie",
|
||||
dm_rcnt: "ostatnio uzywane pliki",
|
||||
dm_savs: "zachowane ustawienia",
|
||||
dm_appp: "Ustawienia programu",
|
||||
|
||||
// CAM Tool Dialog
|
||||
td_tyem: "tępo zakończone", // end mill
|
||||
td_tybm: "kula na końcu", // ball mill
|
||||
td_tytm: "zwężający się", // taper mill
|
||||
td_tonm: "narzędzie #",
|
||||
td_shft: "wał (pionowy)", // endmill shaft specs
|
||||
td_flut: "czołowy", // endmill flute specs
|
||||
td_tapr: "zwężający się", // endmill taper specs
|
||||
|
||||
// DEVICE dialog groups
|
||||
dv_gr_dev: "urządzenie",
|
||||
dv_gr_ext: "ekstruder",
|
||||
dv_gr_out: "wynik",
|
||||
dv_gr_gco: "makra gkodu",
|
||||
|
||||
// DEVICE dialog (_s = label, _l = hover help)
|
||||
dv_name_s: "nazwa",
|
||||
dv_name_l: "nazwa urządzenia",
|
||||
dv_fila_s: "filament",
|
||||
dv_fila_l: "średnica w milimetrach",
|
||||
dv_nozl_s: "dysza",
|
||||
dv_nozl_l: "średnica w milimetrach",
|
||||
dv_bedw_s: "szerokość",
|
||||
dv_bedw_l: "pole robocze w jednostkach",
|
||||
dv_bedd_s: "głębokość",
|
||||
dv_bedd_l: "pole robocze w jednostkach",
|
||||
dv_bedh_s: "wysokość",
|
||||
dv_bedh_l: ["maksymalna wysokość budowania","w jednostkach pola roboczego"],
|
||||
dv_spmx_s: "maksymalna prędkość wrzeciona",
|
||||
dv_spmx_l: ["maksymalna prędkość wrzeciona w obrotach na minutę","0 wyłączone"],
|
||||
dv_xtab_s: "ustawienie pozycji absolutnie",
|
||||
dv_xtab_l: "absolutna wartość wypchnięcia",
|
||||
dv_orgc_s: "środek odniesienia",
|
||||
dv_orgc_l: "środek odniesienia na platformie",
|
||||
// dv_orgt_s: "odniesienie u góry",
|
||||
// dv_orgt_l: "oś z odniesienie u góry",
|
||||
dv_bedc_s: "okrądła platforma drukowania",
|
||||
dv_bedc_l: "platforma druku jest okrągła",
|
||||
dv_belt_s: "pas na platformie",
|
||||
dv_belt_l: "kontynuacja drukowania platformy",
|
||||
dv_retr_s: "domyślne cofnięcie (retrakcja)",
|
||||
dv_retr_l: ["firmware urządzenia wspiera kody G10/G11"],
|
||||
dv_fanp_s: "zasilanie wiatraczków",
|
||||
dv_fanp_l: "ustawienia zasilania wiatraczków",
|
||||
dv_prog_s: "postęp",
|
||||
dv_prog_l: "wynik w czasie każdego % postępu",
|
||||
dv_layr_s: "warstwa",
|
||||
dv_layr_l: ["output at each","layer change"],
|
||||
dv_tksp_s: "token spacer",
|
||||
dv_tksp_l: ["add a space between","gcode axis parameters","G0X0Y0X0","vs","G0 X0 Y0 Z0"],
|
||||
dv_strc_s: "strip comments",
|
||||
dv_strc_l: ["strip gcode comments","comments begin with ;"],
|
||||
dv_fext_s: "rozszerzenie pliku",
|
||||
dv_fext_l: "rozszerzenie pliku",
|
||||
dv_dwll_s: "dwell",
|
||||
dv_dwll_l: "gcode dwell script",
|
||||
dv_tool_s: "zmiana narzędzia",
|
||||
dv_tool_l: "skrypt zmiany narzędzia",
|
||||
dv_sspd_s: "prędkość wrzeciona",
|
||||
dv_sspd_l: "ustaw prędkość wrzeciona",
|
||||
dv_paus_s: "pauza",
|
||||
dv_paus_l: "gkod skryptu pauzy",
|
||||
dv_head_s: "nagłówek (początek)",
|
||||
dv_head_l: "skrypt gkod nagłówka",
|
||||
dv_foot_s: "stopka (zakończenie)",
|
||||
dv_foot_l: "skrypt gkod stopki",
|
||||
dv_lzon_s: "laser włączony",
|
||||
dv_lzon_l: "gcode laser on script",
|
||||
dv_lzof_s: "laser wyłączony",
|
||||
dv_lzof_l: "gcode laser off script",
|
||||
dv_exts_s: "zaznacz",
|
||||
dv_exts_l: "gcode run to enable this extruder",
|
||||
dv_dext_s: "odznacz",
|
||||
dv_dext_l: "gcode run before enabling another extruder",
|
||||
dv_extd_s: "deselect",
|
||||
dv_extd_l: "gcode to deselect this extruder",
|
||||
dv_exox_s: "offset x",
|
||||
dv_exox_l: "nozzle offset x",
|
||||
dv_exoy_s: "offset y",
|
||||
dv_exoy_l: "nozzle offset y",
|
||||
|
||||
// MODE
|
||||
mo_menu: "tryb",
|
||||
mo_fdmp: "FDM Druk przyrostowy",
|
||||
mo_slap: "SLA Druk przyrostowy",
|
||||
mo_lazr: "Ciecie laserem",
|
||||
mo_cncm: "Frezowanie CNC",
|
||||
|
||||
// SETUP
|
||||
su_menu: "ustawienia",
|
||||
su_devi: "Urządzenia",
|
||||
su_tool: "Narzędzia",
|
||||
su_locl: "Lokalnie",
|
||||
su_xprt: "Eksport",
|
||||
su_help: "Pomoc",
|
||||
|
||||
// LOAD
|
||||
fe_menu: "plik",
|
||||
fn_recn: "ostatnie pliki",
|
||||
fn_impo: "Importowanie",
|
||||
|
||||
// FUNCTION
|
||||
fn_menu: "action",
|
||||
fn_arra: "Arrange",
|
||||
fn_slic: "Slice",
|
||||
fn_prev: "Preview",
|
||||
fn_expo: "Export",
|
||||
|
||||
// VIEW
|
||||
vu_menu: "view",
|
||||
vu_home: "Home",
|
||||
vu_rset: "Reset",
|
||||
vu_sptp: "Top",
|
||||
vu_spfr: "Front",
|
||||
vu_splt: "Left",
|
||||
vu_sprt: "Right",
|
||||
|
||||
// WORKSPACE
|
||||
ws_menu: "view",
|
||||
ws_save: "Save",
|
||||
ws_cler: "Clear",
|
||||
|
||||
// OPTIONS
|
||||
op_menu: "interface",
|
||||
op_disp: "display",
|
||||
op_xprt_s: "expert",
|
||||
op_xprt_l: "show more settings options",
|
||||
op_decl_s: "decals",
|
||||
op_decl_l: "show device decals and logos",
|
||||
op_dang_s: "experimental",
|
||||
op_dang_l: "show experimental parameters",
|
||||
op_hopo_s: "hover pop",
|
||||
op_hopo_l: ["enable menu hover","to activate"],
|
||||
op_dark_s: "dark mode",
|
||||
op_dark_l: "dark mode interface",
|
||||
op_comp_s: "compact ui",
|
||||
op_comp_l: ["compact user interface","better for small screens","and tablets"],
|
||||
op_shor_s: "show origin",
|
||||
op_shor_l: "show device or process origin",
|
||||
op_shru_s: "show rulers",
|
||||
op_shru_l: ["show axes rulers","on major gridlines"],
|
||||
op_sped_s: "show speeds",
|
||||
op_sped_l: ["show speed to color bar","in preview mode"],
|
||||
op_auto_s: "auto layout",
|
||||
op_auto_l: ["automatically layout platform","when new items added"],
|
||||
op_free_s: "free layout",
|
||||
op_free_l: ["permit dragable layout","no effect in laser mode"],
|
||||
op_spcr_s: "spacing",
|
||||
op_spcr_l: ["spacing between objects","during auto layout","in workspace units"],
|
||||
op_orth_s: "orthographic",
|
||||
op_orth_l: ["orthographic display","requires page refresh"],
|
||||
op_invr_s: "invert zoom",
|
||||
op_invr_l: ["invert mouse wheel","scroll zoom"],
|
||||
op_save_s: "auto save",
|
||||
op_save_l: ["preserve objects in workspace","between application reloads"],
|
||||
op_line_s: "line type",
|
||||
op_line_l: ["line style for path rendering","impacts 3d performance","path: 3d best","flat: 2d good","line = 1d fast"],
|
||||
op_unit_s: "units",
|
||||
op_unit_l: ["workspace units affects","speeds and distances"],
|
||||
op_anim_s: "animate",
|
||||
op_anim_l: ["animation mesh density","higher is more dense","takes more memory","and is slower"],
|
||||
|
||||
lo_menu: "layout",
|
||||
|
||||
pt_menu: "parts",
|
||||
pt_deci_s: "decimate",
|
||||
pt_deci_l: ["enable or disable point decimation","during port import. for faster slicing","and lower memory usage"],
|
||||
pt_qual_s: "quality",
|
||||
pt_qual_l: ["level of detail to retain","during slicing operations","lower is faster"],
|
||||
pt_heal_s: "heal mesh",
|
||||
pt_heal_l: ["attempt to heal","non-manifold meshes","adds to slicing time"],
|
||||
|
||||
xp_menu: "exports",
|
||||
|
||||
// SETTINGS
|
||||
se_menu: "profile",
|
||||
se_load: "load",
|
||||
se_save: "save",
|
||||
|
||||
// FDM SLICING
|
||||
sl_menu: "layers",
|
||||
sl_lahi_s: "height",
|
||||
sl_lahi_l: ["height of each slice","layer in millimeters"],
|
||||
ad_minl_s: "height min",
|
||||
ad_minl_l: ["adaptive min layer height","in millimeters","must be non-zero"],
|
||||
sl_ltop_s: "top layers",
|
||||
sl_ltop_l: ["number of solid layers","to enforce at the","top of the print"],
|
||||
sl_lsld_s: "solid layers",
|
||||
sl_lsld_l: ["solid fill areas computed","from layer deltas. see","layer pop menu"],
|
||||
sl_lbot_s: "base layers",
|
||||
sl_lbot_l: ["number of solid layers","to enforce at the","bottom of the print"],
|
||||
ad_adap_s: "adaptive",
|
||||
ad_adap_l: ["use adaptive layer heights","with 'layer height' as max","and 'layer min' as the min"],
|
||||
|
||||
// FDM SHELLS
|
||||
sl_shel_s: "shell count",
|
||||
sl_shel_l: ["number of perimeter","walls to generate"],
|
||||
sl_ordr_s: "shell order",
|
||||
sl_ordr_l: ["output shell order","inside to outside","or outside to inside","affects surface quality"],
|
||||
sl_strt_s: "layer start",
|
||||
sl_strt_l: ["layer starting point","last = last layer end","center = part center","origin = device origin"],
|
||||
ad_thin_s: "thin walls",
|
||||
ad_thin_l: ["detect and fill gaps","between shell walls"],
|
||||
|
||||
// FDM FILL
|
||||
fi_menu: "infill",
|
||||
fi_type: "type",
|
||||
fi_pcnt_s: "fill fraction",
|
||||
fi_pcnt_l: ["fill density values","0.0 - 1.0"],
|
||||
fi_angl_s: "solid start",
|
||||
fi_angl_l: ["starting angle in degrees","90 degrees added to ","each following layer","applies only to solid layers"],
|
||||
fi_over_s: "overlap",
|
||||
fi_over_l: ["overlap with shell and other fill","as fraction of nozzle diameter","0.0 - 1.0"],
|
||||
// fi_rate_s: "print speed",
|
||||
fi_rate_l: ["extrusion speed for infill","set to 0 to use default","output print speeds"],
|
||||
|
||||
// FDM FIRST LAYER
|
||||
fl_menu: "base",
|
||||
fl_lahi_s: "layer height",
|
||||
fl_lahi_l: ["height of each slice","in millimeters","should be >= slice height"],
|
||||
fl_rate_s: "shell speed",
|
||||
fl_rate_l: ["shell printing max speed","in millimeters / minute"],
|
||||
fl_frat_s: "fill speed",
|
||||
fl_frat_l: ["fill printing max speed","in millimeters / minute"],
|
||||
fl_mult_s: "flow factor",
|
||||
fl_mult_l: ["extrusion multiplier","0.0 - 2.0"],
|
||||
fl_sfac_s: "width factor",
|
||||
fl_sfac_l: ["multiplier on nozzle size","changes line spacing"],
|
||||
fl_skrt_s: "skirt count",
|
||||
fl_skrt_l: ["number of first-layer offset","brims to generate"],
|
||||
fl_skro_s: "skirt offset",
|
||||
fl_skro_l: ["skirt offset from part","in millimeters"],
|
||||
fl_nozl_s: "nozzle temp",
|
||||
fl_nozl_l: ["degrees in celsius","output setting used","when this is zero"],
|
||||
fl_bedd_s: "bed temp",
|
||||
fl_bedd_l: ["degrees in celsius","output setting used","when this is zero"],
|
||||
fr_spac_s: "raft gap",
|
||||
fr_spac_l: ["additional layer spacing","between 1st layer and raft","in millimeters"],
|
||||
fr_nabl_s: "raft enable",
|
||||
fr_nabl_l: ["create a raft under the","model for better adhesion","uses skirt offset and","disables skirt output"],
|
||||
|
||||
// FDM BELT ONLY
|
||||
fl_zoff_s: "belt offset",
|
||||
fl_zoff_l: ["height offset from belt","of lowest extrusion","in millimeters"],
|
||||
fl_brim_s: "brim size",
|
||||
fl_brim_l: ["add brim to part bottom","size is width in millimeters","0 to disable"],
|
||||
fl_brmn_s: "brim trigger",
|
||||
fl_brmn_l: ["add brims only when segment","facing belt is shorter than this","value in millimeters","0 = Infinity"],
|
||||
fl_bled_s: "part anchor",
|
||||
fl_bled_l: ["belt part anchor","at start of print","in millimeters"],
|
||||
|
||||
// FDM SUPPORT
|
||||
sp_menu: "support",
|
||||
sp_detect: "detect",
|
||||
sp_dens_s: "density",
|
||||
sp_dens_l: ["fraction 0.0 - 1.0","recommended 0.15","0 to disable"],
|
||||
sp_size_s: "pillar size",
|
||||
sp_size_l: ["pillar width","in millimeters"],
|
||||
sp_offs_s: "part offset",
|
||||
sp_offs_l: ["offset from part","in millimeters"],
|
||||
sp_gaps_s: "gap layers",
|
||||
sp_gaps_l: ["number of layers","offset from part"],
|
||||
sp_span_s: "max span",
|
||||
sp_span_l: ["unsupported span that causes","a new support to be generated","in millimeters"],
|
||||
sp_angl_s: "max angle",
|
||||
sp_angl_l: ["max overhang angle before","supporting pillar is generated"],
|
||||
sp_area_s: "min area",
|
||||
sp_area_l: ["minimum area for","a support column","in millimeters"],
|
||||
sp_xpnd_s: "expand",
|
||||
sp_xpnd_l: ["expand support area","beyond part boundary","in millimeters"],
|
||||
sp_nozl_s: "extruder",
|
||||
sp_nozl_l: ["in multi-extruder systems","the extruder to use for","support material"],
|
||||
sp_auto_s: "automatic",
|
||||
sp_auto_l: ["enable generated supports","using at-slice-time geometry","supports will only appear","after slicing completes"],
|
||||
|
||||
// LASER SLICING
|
||||
ls_offs_s: "offset",
|
||||
ls_offs_l: ["adjust for beam width","in millimeters"],
|
||||
ls_lahi_s: "height",
|
||||
ls_lahi_l: ["layer height","in millimeters","0 = auto/detect"],
|
||||
ls_lahm_s: "min",
|
||||
ls_lahm_l: ["layer height minimum","will merge auto slices","under this thickness","in millimeters"],
|
||||
ls_sngl_s: "single",
|
||||
ls_sngl_l: ["perform only one slice","at specified layer height"],
|
||||
|
||||
// CNC COMMON terms
|
||||
cc_tool: "tool",
|
||||
cc_offs_s: "offset",
|
||||
cc_offs_l: ["offset tool center","from chosen path"],
|
||||
cc_spnd_s: "spindle rpm",
|
||||
cc_spnd_l: ["spindle speed in","revolutions / minute"],
|
||||
cc_sovr_s: "step over",
|
||||
cc_sovr_l: ["as a fraction of","tool diameter"],
|
||||
cc_sdwn_s: "step down",
|
||||
cc_sdwn_l: ["step down depth","for each pass","in workspace units","0 to disable"],
|
||||
cc_feed_s: "feed rate",
|
||||
cc_feed_l: ["max cutting speed in","workspace units / minute"],
|
||||
cc_plng_s: "plunge rate",
|
||||
cc_plng_l: ["max z axis speed in","workspace units / minute"],
|
||||
cc_sngl_s: "select lines only",
|
||||
cc_sngl_l: ["select only single edges","instead of connected polylines"],
|
||||
|
||||
// CNC COMMON
|
||||
cc_menu: "limits",
|
||||
cc_flip: "flip",
|
||||
cc_rapd_s: "xy feed",
|
||||
cc_rapd_l: ["max xy moves feedrate","in workspace units / minute"],
|
||||
cc_rzpd_s: "z feed",
|
||||
cc_rzpd_l: ["max z moves feedrate","in workspace units / minute"],
|
||||
|
||||
cc_loff_s: "offset",
|
||||
cc_loff_l: ["distance from stock face","for leveling pass","in workspace units"],
|
||||
|
||||
// CNC ROUGHING
|
||||
cr_menu: "rough",
|
||||
cr_lsto_s: "leave stock",
|
||||
cr_lsto_l: ["horizontal offset from vertical faces","stock to leave for finishing pass","in workspace units"],
|
||||
cr_ease_s: "ease down",
|
||||
cr_ease_l: ["plunge cuts will","spiral down or ease","along a linear path"],
|
||||
cr_clrt_s: "clear top",
|
||||
cr_clrt_l: ["run a clearing pass over","the bounding area of the part","at z = 0"],
|
||||
cr_clrp_s: "clear voids",
|
||||
cr_clrp_l: ["mill out through pockets","instead of just the outline"],
|
||||
cr_clrf_s: "clear faces",
|
||||
cr_clrf_l: ["interpolate step down to","clear any detected flat areas"],
|
||||
cr_olin_s: "inside only",
|
||||
cr_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
|
||||
// CNC OUTLINE
|
||||
co_menu: "outline",
|
||||
co_dogb_s: "dogbones",
|
||||
co_dogb_l: ["insert dogbone cuts","into inside corners"],
|
||||
co_wide_s: "wide cutout",
|
||||
co_wide_l: ["widen outside cutout paths","for deep cuts in hard material"],
|
||||
co_olin_s: "inside only",
|
||||
co_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
co_olot_s: "outside only",
|
||||
co_olot_l: ["limit cutting to","exterior part boundaries","which can be thought of","as the shadow outline"],
|
||||
co_omit_s: "omit through",
|
||||
co_omit_l: "eliminate thru holes",
|
||||
co_olen_s: "enable",
|
||||
co_olen_l: "enabled outline cutting",
|
||||
|
||||
// CNC CONTOUR
|
||||
cn_menu: "contour",
|
||||
cf_angl_s: "max angle",
|
||||
cf_angl_l: ["angles greater than this","are considered vertical"],
|
||||
cf_curv_s: "curves only",
|
||||
cf_curv_l: ["limit linear cleanup","to curved surfaces"],
|
||||
cf_olin_s: "inside only",
|
||||
cf_olin_l: ["limit cutting to","inside part boundaries"],
|
||||
cf_linx_s: "enable y pass",
|
||||
cf_linx_l: "linear y-axis finishing",
|
||||
cf_liny_s: "enable x pass",
|
||||
cf_liny_l: "linear x-axis finishing",
|
||||
|
||||
// CNC TRACE
|
||||
cu_menu: "trace",
|
||||
cu_type_s: "type",
|
||||
cu_type_l: ["follow = tool tip follows line","right or left = tool tip","follows line offset by tool radius"],
|
||||
|
||||
// CNC DRILLING
|
||||
cd_menu: "drill",
|
||||
cd_axis: "axis",
|
||||
cd_points: "points",
|
||||
cd_plpr_s: "plunge per",
|
||||
cd_plpr_l: ["max plunge between","dwell periods","in workspace units","0 to disable"],
|
||||
cd_dwll_s: "dwell time",
|
||||
cd_dwll_l: ["dwell time","between plunges in","in milliseconds"],
|
||||
cd_lift_s: "drill lift",
|
||||
cd_lift_l: ["lift between plunges","after dwell period","in workspace units","0 to disable"],
|
||||
cd_regi_s: "register",
|
||||
cd_regi_l: ["drill registration holes","for double-sided parts","independent of enable","drilling but uses same","tool and settings"],
|
||||
|
||||
// CNC CUTOUT TABS
|
||||
ct_menu: "tabs",
|
||||
ct_angl_s: "angle",
|
||||
ct_angl_l: ["starting angle for tab spacing","in degrees (0-360)"],
|
||||
ct_numb_s: "count",
|
||||
ct_numb_l: ["number of tabs to use","will be spaced evenly","around the part"],
|
||||
ct_wdth_s: "width",
|
||||
ct_wdth_l: "width in workspace units",
|
||||
ct_hght_s: "height",
|
||||
ct_hght_l: "height in workspace units",
|
||||
ct_dpth_s: "depth",
|
||||
ct_dpth_l: ["distance in workspace units","that the tab projects from","the part surface"],
|
||||
ct_midl_s: "midline",
|
||||
ct_midl_l: ["use midline of tab","instead of z bottom","for double-sided work"],
|
||||
ct_nabl_s: "auto",
|
||||
ct_nabl_l: ["auto generate radial tabs","projected from part center","using count and angle offset"],
|
||||
|
||||
// OUTPUT
|
||||
ou_menu: "output",
|
||||
|
||||
// LASER KNIFE
|
||||
dk_menu: "knife",
|
||||
dk_dpth_s: "cut depth",
|
||||
dk_dpth_l: ["final cut depth","in millimeters"],
|
||||
dk_pass_s: "cut passes",
|
||||
dk_pass_l: ["number of passes","down to cut depth"],
|
||||
dk_offs_s: "tip offset",
|
||||
dk_offs_l: ["distance from blade tip","to center of tool","in millimeters"],
|
||||
|
||||
// OUTPUT LASER
|
||||
ou_spac_s: "spacing",
|
||||
ou_spac_l: ["distance between layer output","in millimeters"],
|
||||
ou_scal_s: "scaling",
|
||||
ou_scal_l: "multiplier (0.1 to 100)",
|
||||
ou_powr_s: "power",
|
||||
ou_powr_l: ["0 - 100","represents %"],
|
||||
ou_sped_s: "speed",
|
||||
ou_sped_l: "millimeters / minute",
|
||||
ou_mrgd_s: "merged",
|
||||
ou_mrgd_l: ["merge all layers using","color coding to denote","stacking depth"],
|
||||
ou_grpd_s: "grouped",
|
||||
ou_grpd_l: ["retain each layer as","a unified grouping","instead of separated","polygons"],
|
||||
ou_layr_s: "layer order",
|
||||
ou_layr_l: ["output layer order","from top right to","bottom left"],
|
||||
ou_layo_s: "layer color",
|
||||
ou_layo_l: ["output layer colors","for each z index","overridden by merged"],
|
||||
ou_drkn_s: "drag knife",
|
||||
ou_drkn_l: ["enable drag knife","output in gcode","cut radii are added","to corners with","cut down passes"],
|
||||
|
||||
// OUTPUT FDM
|
||||
ou_nozl_s: "nozzle temp",
|
||||
ou_nozl_l: "degrees in celsius",
|
||||
ou_bedd_s: "bed temp",
|
||||
ou_bedd_l: "degrees in celsius",
|
||||
ou_feed_s: "print speed",
|
||||
ou_feed_l: ["max print speed","millimeters / minute"],
|
||||
ou_fini_s: "finish speed",
|
||||
ou_fini_l: ["outermost shell speed","millimeters / minute"],
|
||||
ou_move_s: "move speed",
|
||||
ou_move_l: ["non-print move speed","millimeters / minute","0 = enable G0 moves"],
|
||||
ou_shml_s: "shell factor",
|
||||
ou_flml_s: "solid factor",
|
||||
ou_spml_s: "infill factor",
|
||||
ou_exml_l: ["extrusion multiplier","0.0 - 2.0"],
|
||||
ou_fans_s: "fan speed",
|
||||
ou_fans_l: "0 - 255",
|
||||
|
||||
// OUTPUT CAM
|
||||
ou_toll_s: "tolerance",
|
||||
ou_toll_l: ["surface precision","in workspace units","lower is slower and","uses more memory","0 = automatic based","on animate preference"],
|
||||
ou_zanc_s: "z anchor",
|
||||
ou_zanc_l: ["controls the position of the part","when stock Z exceeds part Z"],
|
||||
ou_ztof_s: "z offset",
|
||||
ou_ztof_l: ["offset z anchor","in workspace units","has no effect when","anchor is middle"],
|
||||
ou_zbot_s: "z bottom",
|
||||
ou_zbot_l: ["offset from part bottom","to limit cutting depth","in workspace units"],
|
||||
ou_zclr_s: "z clearance",
|
||||
ou_zclr_l: ["safe travel offset","from top of part","in workspace units"],
|
||||
ou_ztru_s: "z thru",
|
||||
ou_ztru_l: ["extend cutout pass down","in workspace units"],
|
||||
ou_conv_s: "conventional",
|
||||
ou_conv_l: ["milling direction","uncheck for 'climb'"],
|
||||
ou_depf_s: "depth first",
|
||||
ou_depf_l: ["optimize pocket cuts","with depth priority"],
|
||||
|
||||
// CAM STOCK
|
||||
cs_menu: "stock",
|
||||
cs_wdth_s: "width",
|
||||
cs_wdth_l: ["width (x) in workspace units","0 defaults to part size"],
|
||||
cs_dpth_s: "depth",
|
||||
cs_dpth_l: ["depth (y) in workspace units","0 defaults to part size"],
|
||||
cs_hght_s: "height",
|
||||
cs_hght_l: ["height (z) in workspace units","0 defaults to part size"],
|
||||
cs_offs_s: "offset",
|
||||
cs_offs_l: ["use width, depth, height","as offsets from max","part size on platform"],
|
||||
cs_clip_s: "clip to",
|
||||
cs_clip_l: ["rough and outline","clip cutting paths","to defined stock"],
|
||||
cs_offe_s: "enable",
|
||||
cs_offe_l: "enable milling stock",
|
||||
|
||||
// ORIGIN (CAM & LASER)
|
||||
or_bnds_s: "origin bounds",
|
||||
or_bnds_l: ["origin is relative to","boundary of all objects"],
|
||||
or_cntr_s: "origin center",
|
||||
or_cntr_l: "origin is referenced from the center",
|
||||
or_topp_s: "origin top",
|
||||
or_topp_l: "origin is references from the top of objects",
|
||||
|
||||
// FDM ADVANCED
|
||||
ad_menu: "expert",
|
||||
ad_rdst_s: "retract dist",
|
||||
ad_rdst_l: ["amount to retract filament","for long moves. in millimeters"],
|
||||
ad_rrat_s: "retract rate",
|
||||
ad_rrat_l: ["speed of filament","retraction in mm/s"],
|
||||
ad_rdwl_s: "engage dwell",
|
||||
ad_wpln_s: "retract wipe",
|
||||
ad_wpln_l: ["non-printing move","after retraction","in millimeters"],
|
||||
ad_rdwl_l: ["time between re-engaging","filament and movement","in milliseconds"],
|
||||
ad_scst_s: "shell coast",
|
||||
ad_scst_l: ["non-printing end","of perimeter shells","in millimeters"],
|
||||
ad_msol_s: "min solid",
|
||||
ad_msol_l: ["minimum area (mm^2)","required to keep solid","must be > 0.1"],
|
||||
ad_mins_s: "min speed",
|
||||
ad_mins_l: ["minimum speed","for short segments"],
|
||||
ad_spol_s: "short path",
|
||||
ad_spol_l: ["polygons shorter than this","will have their print speed","scaled down to min speed","in millimeters"],
|
||||
ad_arct_s: "arc tolerance",
|
||||
ad_arct_l: ["convert faceted lines to arcs","center point drift tolerance","when matching arc points","consider values around 0.15","in millimeters","0 to disable"],
|
||||
ad_zhop_s: "z hop dist",
|
||||
ad_zhop_l: ["amount to raise z","on retraction moves","in millimeters","0 to disable"],
|
||||
ad_abkl_s: "anti-backlash",
|
||||
ad_abkl_l: ["for better flat surface finish","use micro-movements to cancel","backlash in solid layer output","in millimeters","0 to disable","if your firmware has M425","put that in the gcode header","and leave this as 0"],
|
||||
ad_lret_s: "layer retract",
|
||||
ad_lret_l: ["force filament retraction","between layers"],
|
||||
ad_play_s: "polish layers",
|
||||
ad_play_l: ["polish up to specified","# of layers at a time"],
|
||||
ad_pspd_s: "polish speed",
|
||||
ad_pspd_l: ["polishing speed","in millimeters / minute"],
|
||||
|
||||
// CAM EXPERT
|
||||
cx_fast_s: "skip shadow",
|
||||
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"],
|
||||
|
||||
// FDM GCODE
|
||||
ag_menu: "gcode",
|
||||
ag_nozl_s: "nozzle",
|
||||
ag_nozl_l: "select output nozzle or head",
|
||||
ag_paws_s: "pause layers",
|
||||
ag_paws_l: ["comma-separated list of layers","to inject pause commands before"],
|
||||
ag_loop_s: "loop layers",
|
||||
ag_loop_l: ["layer ranges to repeat in the format","first-last-count,first-last-count,...","omitted count = 1"],
|
||||
|
||||
// SLA MENU
|
||||
sa_menu: "slicing",
|
||||
sa_lahe_s: "layer height",
|
||||
sa_lahe_l: ["layer height","in millimeters"],
|
||||
sa_shel_s: "hollow shell",
|
||||
sa_shel_l: ["shell thickness in mm","use multiple of layer height","use 0 for solid (disabled)"],
|
||||
sa_otop_s: "open top",
|
||||
sa_otop_l: ["if shell is enabled","results in an open top"],
|
||||
sa_obas_s: "open base",
|
||||
sa_obas_l: ["if shell is enabled","results in an open base","disabled with supports"],
|
||||
|
||||
sa_layr_m: "layers",
|
||||
sa_lton_s: "light on time",
|
||||
sa_lton_l: ["layer light on","time in seconds"],
|
||||
sa_ltof_s: "light off time",
|
||||
sa_ltof_l: ["layer light off","time in seconds"],
|
||||
sa_pldi_s: "peel distance",
|
||||
sa_pldi_l: ["peel distance","in millimeters"],
|
||||
sa_pllr_s: "peel lift rate",
|
||||
sa_pllr_l: ["peel lift speed","in mm/sec"],
|
||||
sa_pldr_s: "peel drop rate",
|
||||
sa_pldr_l: ["peel drop speed","in mm/sec"],
|
||||
|
||||
sa_base_m: "base",
|
||||
sa_balc_s: "layer count",
|
||||
sa_balc_l: ["number of","base layers"],
|
||||
sa_bltn_l: ["base layer light on","time in seconds"],
|
||||
sa_bltf_l: ["base layer light off","time in seconds"],
|
||||
|
||||
sa_infl_m: "infill",
|
||||
sa_ifdn_s: "density",
|
||||
sa_ifdn_l: ["percent infill","requires shell","0 = disabled","valid 0.0 - 1.0"],
|
||||
sa_iflw_s: "line width",
|
||||
sa_iflw_l: ["hatch line width","in millimeters"],
|
||||
|
||||
sa_supp_m: "support",
|
||||
sa_slyr_s: "base layers",
|
||||
sa_slyr_l: ["base support layers","value range 0-10"],
|
||||
sa_slgp_s: "gap layers",
|
||||
sa_slgp_l: ["number of layers between","raft and bottom of object"],
|
||||
sa_sldn_s: "density",
|
||||
sa_sldn_l: ["used to compute the","number of support pillars","0.0-1.0 (0 = disable)"],
|
||||
sa_slsz_s: "size",
|
||||
sa_slsz_l: ["max size of a","support pillar","in millimeters"],
|
||||
sa_slpt_s: "points",
|
||||
sa_slpt_l: ["number of points in","each support pillar","in millimeters"],
|
||||
sl_slen_l: "enable supports",
|
||||
|
||||
sa_outp_m: "output",
|
||||
sa_opzo_s: "przesunięcie osi Z",
|
||||
sa_opzo_l: ["z layer offset","almost always 0.0","0.0-1.0 in millimeters"],
|
||||
sa_opaa_s: "antyaliasing",
|
||||
sa_opaa_l: ["włączenie tej opcji","tworzy większe pliki","ale pokazuje przejścia tonalne"]
|
||||
};
|
||||
1
web/kiri/lang/pl.js
Symbolic link
1
web/kiri/lang/pl.js
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
pl-pl.js
|
||||
Loading…
Reference in a new issue