move src2 -> src, web2 -> web, remove old module system, fix deps

This commit is contained in:
Stewart Allen 2025-07-06 23:44:33 -04:00
commit ce4f5d6e78
488 changed files with 26179 additions and 26609 deletions

View file

@ -1,12 +1,6 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: kiri.api
gapp.register("kiri.alerts", [], (root, exports) => {
const { kiri } = root;
const { api } = kiri;
import { api } from './api.js';
let alerts = [];
@ -68,11 +62,14 @@ function update(clear) {
}
}
// extend API
Object.assign(api.alerts, {
export {
hide,
show,
update
});
};
});
export default {
hide,
show,
update
};

View file

@ -1,17 +1,30 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
import alerts from './alerts.js';
import settings from './settings.js'
import STACKS from './stacks.js';
// dep: moto.broker
// dep: data.local
// dep: kiri.utils
// dep: kiri.consts
gapp.register("kiri.api", (root, exports) => {
import { broker } from '../moto/broker.js';
import { client as work } from './client.js';
import { consts, COLOR as color, LISTS as lists, MODES, VIEWS } from './consts.js';
import { device, devices } from './devices.js';
import { catalog, dialog, event, group, help, hide, image } from './main.js';
import { modal, mode, probe, process, show, space, util, view } from './main.js';
import { local as dataLocal } from '../data/local.js';
import { noop, ajax, o2js, js2o } from './utils.js';
import { functions } from './function.js';
import { platform } from './platform.js';
import { selection } from './selection.js';
import { stats } from '../kiri/stats.js';
import { widgets } from './widgets.js';
import { updateTool } from '../kiri-mode/cam/tools.js';
let { data, kiri, moto, noop } = root,
{ consts, utils } = kiri,
{ ajax, o2js, js2o } = utils,
lists = consts.LISTS,
import { LANG } from './lang.js';
import { LOCAL, SETUP, SECURE } from './main.js';
import { UI } from './ui.js';
let UC = UI.prefix('kiri').inputAction(settings.conf.update),
und = undefined,
clone = Object.clone,
isHover = false,
feature = {
@ -20,27 +33,33 @@ let { data, kiri, moto, noop } = root,
frame: true, // receive frame events
alert_event: false, // emit alerts as events instead of display
controls: true, // show or not side menus
device_filter: undefined, // function to limit devices shown
drop_group: undefined, // optional array to group multi drop
device_filter: und, // function to limit devices shown
drop_group: und, // optional array to group multi drop
drop_layout: true, // layout on new drop
hoverAdds: false, // when true only searches widget additions
on_key: undefined, // function override default key handlers
on_key: und, // function override default key handlers
on_key2: [], // allows for multiple key handlers
on_load: undefined, // function override file drop loads
on_add_stl: undefined, // legacy override stl drop loads
on_mouse_up: undefined, // function intercepts mouse up select
on_mouse_down: undefined, // function intercepts mouse down
on_load: und, // function override file drop loads
on_add_stl: und, // legacy override stl drop loads
on_mouse_up: und, // function intercepts mouse up select
on_mouse_down: und, // function intercepts mouse down
work_alerts: true, // allow disabling work progress alerts
pmode: consts.PMODES.SPEED, // preview modes
pmode: consts.PMODES.SPEED, // preview modes
// hover: false, // when true fires mouse hover events
get hover() {
return isHover;
},
set hover(b) {
isHover = b;
moto.broker.publish("feature.hover", b);
broker.publish("feature.hover", b);
}
},
busyVal = 0,
busy = {
val() { return busy },
inc() { api.event.emit("busy", ++busyVal) },
dec() { api.event.emit("busy", --busyVal) }
},
onkey = (fn) => {
api.feature.on_key2.push(fn);
},
@ -53,7 +72,7 @@ let { data, kiri, moto, noop } = root,
let proc = api.conf.get().process,
size = proc.sliceHeight || proc.slaSlice || 1,
base = (proc.firstSliceHeight || size);
layers = Array.isArray(layers) ? layers : [ layers ];
layers = Array.isArray(layers) ? layers : [layers];
proc.xray = layers.map(l => raw ? l : base + l * size - size / 2);
proc.xrayi = layers.slice();
api.function.slice();
@ -72,62 +91,9 @@ let { data, kiri, moto, noop } = root,
set: (key, val) => localSet(key, val),
},
tweak = {
line_precision(v) { api.work.config({base:{clipperClean: v}}) },
gcode_decimals(v) { api.work.config({base:{gcode_decimals: v}}) }
},
und = undefined,
api = exports({
ajax, // via utils
alerts: {}, // alerts.js
busy: {}, // main.js
catalog: und, // main.js
clip, // <--
clone, // <--
color: und, // main.js
conf: {}, // settings.js
const: {}, // main.js
devel, // <--
device: {}, // devices.js
devices: {}, // devices.js
dialog: {}, // main.js
doit, // <--
event: {}, // main.js
feature, // <--
function: {}, // function.js
group: {}, // main.js
help: {}, // main.js
hide: {}, // main.js
image: {}, // main.js
js2o, // via utils
language: und, // main.js
lists, // <--
local, // <--
modal: {}, // main.js
mode: {}, // main.js
o2js, // via utils
onkey, // <--
platform: {}, // platform.js
probe: {}, // main.js
process: {}, // main.js
sdb: data.local,
selection: {}, // selection.js
settings: {}, // settings.js
show: {}, // main.js
space: {}, // main.js
tool: {}, // kiri-mode/cam/tools.js
tweak, // <--
uc: {}, // main.js
ui: {}, // main.js
util: {}, // main.js
var: {
layer_lo: 0,
layer_hi: 0,
layer_max: 0
},
view: {}, // main.js
widgets: {}, // widgets.js
work: und, // main.js
});
line_precision(v) { api.work.config({ base: { clipperClean: v } }) },
gcode_decimals(v) { api.work.config({ base: { gcode_decimals: v } }) }
};
function clip(text) {
navigator.clipboard
@ -146,4 +112,64 @@ function localSet(key, val) {
return val;
}
});
export const api = {
ajax,
alerts,
busy,
catalog,
client: work,
clip,
clone,
color,
conf: settings.conf,
const: { LANG, LISTS: lists, LOCAL, MODES, SETUP, SECURE, STACKS, VIEWS },
devel,
device,
devices,
dialog,
doit,
event,
feature,
function: functions,
group,
help,
hide,
image,
js2o,
language: LANG,
lists,
local,
modal,
mode,
noop,
o2js,
onkey,
platform,
probe,
process,
sdb: dataLocal,
selection,
settings,
show,
space,
stacks: STACKS,
stats,
tool: {
update: updateTool
},
tweak,
uc: UC,
ui: {},
util,
var: {
layer_lo: 0,
layer_hi: 0,
layer_max: 0
},
view,
widgets,
work,
};
// allow widget to straddle client / worker FOR NOW
self.kiri_api = api;

52
src/kiri/boxes.js Normal file
View file

@ -0,0 +1,52 @@
import { space } from '../moto/space.js';
const { BoxGeometry, Matrix4, MeshPhongMaterial, Quaternion, Vector3, Mesh } = THREE;
const boxes = [];
let lastBox;
export function getlastbox() {
return lastBox;
}
export function delbox(name) {
const old = boxes[name];
if (old) {
old.groupTo.remove(old);
}
}
export function addbox(point, color, name, dim = {x:1,y:1,z:1,rz:0}, opt = {}) {
delbox(name);
const box = boxes[name] = new Mesh(
new BoxGeometry(dim.x, dim.y, dim.z),
new MeshPhongMaterial({
transparent: true,
opacity: opt.opacity || 0.5,
color
})
);
box.position.x = point.x;
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 Quaternion().setFromAxisAngle(new Vector3(0,0,1), dim.rz);
}
if (opt.rotate) {
opt.matrix = new Matrix4().makeRotationFromQuaternion(opt.rotate);
}
if (opt.matrix) {
box.geometry.applyMatrix4(opt.matrix);
}
return box;
}

View file

@ -1,27 +1,17 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// use: kiri.api
gapp.register("kiri.client", [], (root, exports) => {
const { kiri } = root;
import { api } from './api.js';
import { noop } from './utils.js';
// this code runs in kiri's main loop
let loc = self.location,
host = loc.hostname,
port = loc.port,
proto = loc.protocol,
debug = self.debug === true,
let debug = self.debug === true,
time = Date.now,
seqid = 1,
syncd = {},
running = {},
worker = null,
minions = false,
restarting = false
// occ = new Worker("/kiri/ext/occ-worker.js", {type:"module"}),
;
restarting = false;
/**
* @param {Function} fn name of function in kiri.worker
@ -52,7 +42,7 @@ function send(fn, data, onreply, zerocopy) {
}
// code is running in the browser / client context
const client = exports({
export const client = {
send: send,
pool: {
@ -75,8 +65,16 @@ const client = exports({
const blob = new Blob([ work ], { type: 'application/javascript' });
return new Worker(URL.createObjectURL(blob));
} else {
let _ = debug ? '_' : '';
return new Worker(`/code/kiri_work.js?${_}${gapp.version}`);
let worker = new Worker(`/lib/kiri-run/worker.js`, { type: 'module' });
worker.onerror = (error) => {
console.log({ WORKER_ERROR: error });
error.preventDefault();
};
worker.onmessageerror = (error) => {
console.log({ WORKER_MESSAGE_ERROR: error });
error.preventDefault();
};
return worker;
}
},
@ -112,7 +110,7 @@ const client = exports({
running = {};
worker = client.newWorker();
client.onmessage = worker.onmessage = function(e) {
client.onmessage = worker.onmessage = (e) => {
let now = time(),
reply = e.data,
record = running[reply.seq],
@ -161,7 +159,7 @@ const client = exports({
// widget sync
sync(widgets) {
if (!widgets) {
widgets = kiri.api.widgets.all();
widgets = api.widgets.all();
}
// sync any widget that has changed
for (let widget of widgets.filter(w => w.modified || !syncd[w.id])) {
@ -245,7 +243,7 @@ const client = exports({
ondone(null, reply.error);
}
if (reply.debug) {
kiri.api.event.emit("export.debug", reply.debug);
api.event.emit("export.debug", reply.debug);
}
});
},
@ -334,9 +332,11 @@ const client = exports({
// console.log({ clearCache_reply: reply });
});
}
});
};
// start worker
client.restart();
});
self.kiri_client = client;
export default client;

View file

@ -1,32 +1,15 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
import { base } from '../geo/base.js';
import { Layers } from './layers.js';
import { newPoint } from '../geo/point.js';
import { Polygon, newPolygon } from '../geo/polygon.js';
import { Slice, newSlice, Top, newTop } from './slice.js';
import { Widget, newWidget } from './widget.js';
// dep: main.kiri
// dep: geo.base
// dep: geo.polygon
// dep: kiri.widget
// dep: kiri.slice
// dep: kiri.layers
gapp.register("kiri.codec", [], (root, exports) => {
const { base, kiri } = root;
const decoders = {};
const freeMem = true;
const codec = exports({
undef: undefined,
encode: encode,
decode: decode,
registerDecoder: registerDecoder,
allocFloat32Array: allocFloat32Array,
encodePointArray,
decodePointArray,
encodePointArray2D,
decodePointArray2D,
toCodable
});
const TYPE = {
WIDGET: 100,
SLICE: 200,
@ -210,7 +193,7 @@ function decodePointArray(array) {
const points = new Array(length / 3);
for (let vid=0, pid=0; vid < length; ) {
points[pid++] = base.newPoint(array[vid++], array[vid++], array[vid++]);
points[pid++] = newPoint(array[vid++], array[vid++], array[vid++]);
}
return points;
@ -225,7 +208,7 @@ function decodePointArray2D(array, z, fn) {
for (let vid=0, pid=0; vid < length; ) {
points[pid++] = fn ?
fn(array[vid++], array[vid++]) :
base.newPoint(array[vid++], array[vid++], z);
newPoint(array[vid++], array[vid++], z);
}
return points;
@ -233,7 +216,7 @@ function decodePointArray2D(array, z, fn) {
// ----- Widget Codec -----
kiri.Widget.prototype.encode = function(state) {
Widget.prototype.encode = function(state) {
const json = state._json_;
const geo = this.getGeoVertices();
const coded = {
@ -252,7 +235,7 @@ registerDecoder(TYPE.WIDGET, function(v, state) {
const id = v.id,
group = v.group || id,
track = v.track || undefined,
widget = kiri.newWidget(id, kiri.Widget.Groups.forid(group));
widget = newWidget(id, Widget.Groups.forid(group));
widget.loadVertices(v.json ? v.geo.toFloat32() : v.geo);
widget.saved = Date.now();
@ -266,7 +249,7 @@ registerDecoder(TYPE.WIDGET, function(v, state) {
// ----- Slice Codec -----
kiri.Slice.prototype.encode = function(state) {
Slice.prototype.encode = function(state) {
const rv = {
type: TYPE.SLICE,
z: this.z,
@ -279,7 +262,7 @@ kiri.Slice.prototype.encode = function(state) {
};
registerDecoder(TYPE.SLICE, function(v, state) {
let slice = kiri.newSlice(v.z, state.mesh ? state.mesh.newGroup() : null);
let slice = newSlice(v.z, state.mesh ? state.mesh.newGroup() : null);
slice.index = v.index;
slice.layers = decode(v.layers, state)
@ -289,7 +272,7 @@ registerDecoder(TYPE.SLICE, function(v, state) {
// ----- Slice.Top Codec -----
kiri.Top.prototype.encode = function(state) {
Top.prototype.encode = function(state) {
let obj = {
type: TYPE.TOP,
poly: encode(this.poly, state)
@ -307,7 +290,7 @@ kiri.Top.prototype.encode = function(state) {
};
registerDecoder(TYPE.TOP, function(v, state) {
let top = kiri.newTop(decode(v.poly, state));
let top = newTop(decode(v.poly, state));
if (state.full) {
// top.gaps = decode(v.gaps, state);
top.last = decode(v.last, state);
@ -320,7 +303,7 @@ registerDecoder(TYPE.TOP, function(v, state) {
// ----- Polygon Codec -----
base.Polygon.prototype.encode = function(state) {
Polygon.prototype.encode = function(state) {
if (!state.poly) state.poly = {};
let cached = state.poly[this.id];
@ -352,10 +335,10 @@ registerDecoder(TYPE.POLY, function(v, state) {
const array = v.array;
const length = array.length;
const poly = base.newPolygon();
const poly = newPolygon();
for (let vid = 0; vid < length; ) {
poly.push(base.newPoint(array[vid++], array[vid++], array[vid++]));
poly.push(newPoint(array[vid++], array[vid++], array[vid++]));
}
state.poly[v.id] = poly;
@ -382,7 +365,7 @@ function encodeLayerPolys(polys, state) {
});
}
kiri.Layers.prototype.encode = function(state) {
Layers.prototype.encode = function(state) {
let zeros = state.zeros;
let enc = {
type: TYPE.LAYERS,
@ -419,7 +402,7 @@ kiri.Layers.prototype.encode = function(state) {
};
registerDecoder(TYPE.LAYERS, function(v, state) {
const render = new kiri.Layers();
const render = new Layers();
const { layers } = v;
for (let i=0; i<layers.length; i++) {
@ -463,4 +446,28 @@ registerDecoder(TYPE.LAYERS, function(v, state) {
return render;
});
});
export const codec = {
encode,
decode,
registerDecoder,
allocFloat32Array,
encodePointArray,
decodePointArray,
encodePointArray2D,
decodePointArray2D,
toCodable
};
export {
encode,
decode,
registerDecoder,
allocFloat32Array,
encodePointArray,
decodePointArray,
encodePointArray2D,
decodePointArray2D,
toCodable
};
self.kiri_codec = codec;

View file

@ -1,13 +1,5 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: add.array
// dep: data.local
gapp.register("kiri.conf", (root, exports) => {
const { data } = root;
const { local } = data;
const { clone } = Object;
const CVER = 410;
@ -219,7 +211,7 @@ const renamed = {
outputClockwise: "camConventional"
};
const conf = exports({
export const conf = {
// --------------- helper functions
normalize,
device_from_code,
@ -971,7 +963,7 @@ const conf = exports({
id: genID(),
ver: CVER
}
});
};
const settings = conf.template;
@ -990,5 +982,3 @@ settings.cdev.LASER = clone(settings.device);
settings.cdev.DRAG = clone(settings.device);
settings.cdev.WJET = clone(settings.device);
settings.cdev.WEDM = clone(settings.device);
});

View file

@ -1,9 +1,5 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
gapp.register("kiri.consts", (root, exports) => {
const COLOR = {
wireframe: 0x444444,
wireframe_opacity: 0.25,
@ -147,7 +143,7 @@ const PMODES = {
const SEED = 'kiri-seed';
exports({
export let consts = {
PMODES,
COLOR,
LISTS,
@ -155,6 +151,6 @@ exports({
VIEWS,
SEED,
beltfact: Math.cos(Math.PI / 4)
});
};
});
export { COLOR, LISTS, MODES, VIEWS, PMODES, SEED };

View file

@ -1,393 +1,382 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
import { $, h } from '../moto/webui.js';
import { api } from './api.js';
import { conf } from './conf.js';
import { space } from '../moto/space.js';
import { devices as devlist } from '../pack/devices.js';
import { settings, conf as setconf } from './settings.js';
// dep: kiri.api
// dep: kiri.settings
gapp.register("kiri.devices", (root, exports) => {
export const device = {
clone: cloneDevice,
code: currentDeviceCode,
get: currentDeviceName,
set: selectDevice,
isBelt
};
let { kiri } = root,
{ api, conf } = kiri;
export const devices = {
show: showDevices,
select: selectDevice,
refresh: updateDeviceList,
update_laser_state: updateLaserState
};
// extend API
Object.assign(api.show, {
devices: showDevices
});
function isBelt() {
return setconf.get().device.bedBelt;
}
Object.assign(api.device, {
clone: cloneDevice,
code: currentDeviceCode,
get: currentDeviceName,
set: selectDevice,
isBelt
});
function currentDeviceName() {
return setconf.get().filter[api.mode.get()];
}
Object.assign(api.devices, {
show: showDevices,
select: selectDevice,
refresh: updateDeviceList,
update_laser_state: updateLaserState
});
function currentDeviceCode() {
return setconf.get().devices[currentDeviceName()];
}
function isBelt() {
return api.conf.get().device.bedBelt;
}
function getModeDevices() {
return Object.keys(devlist[ api.mode.get_lower() ]).sort();
}
function currentDeviceName() {
return api.conf.get().filter[api.mode.get()];
}
export function showDevices() {
settings.sync.get().then(_showDevices);
}
function currentDeviceCode() {
return api.conf.get().devices[currentDeviceName()];
}
function _showDevices() {
updateDeviceList();
api.modal.show('setup');
}
function getModeDevices() {
// devices are injected into self scope by
// app.js generateDevices()
return Object.keys(devices[api.mode.get_lower()]).sort();
}
function updateDeviceList() {
renderDevices(getModeDevices());
}
function showDevices() {
api.settings.sync.get().then(_showDevices);
}
function _showDevices() {
function updateDeviceName(newname) {
let selected = api.device.get(),
devs = setconf.get().devices;
if (newname !== selected) {
devs[newname] = devs[selected];
delete devs[selected];
selectDevice(newname);
updateDeviceList();
api.modal.show('setup');
}
}
function updateDeviceList() {
renderDevices(getModeDevices());
}
function putLocalDevice(devicename, obj) {
setconf.get().devices[devicename] = obj;
setconf.save();
}
function updateDeviceName(newname) {
let selected = api.device.get(),
devs = api.conf.get().devices;
if (newname !== selected) {
devs[newname] = devs[selected];
delete devs[selected];
selectDevice(newname);
updateDeviceList();
function removeLocalDevice(devicename) {
delete setconf.get().devices[devicename];
setconf.save();
settings.sync.put();
}
function isLocalDevice(devicename) {
return setconf.get().devices[devicename] ? true : false;
}
function getSelectedDevice() {
return api.device.get();
}
function selectDevice(devicename) {
if (isLocalDevice(devicename)) {
setDeviceCode(setconf.get().devices[devicename], devicename);
} else {
let code = devlist[api.mode.get_lower()][devicename];
if (code) {
setDeviceCode(code, devicename);
}
}
}
function putLocalDevice(devicename, obj) {
api.conf.get().devices[devicename] = obj;
api.conf.save();
// only for local filters
function cloneDevice() {
let name = `${getSelectedDevice().replace(/\./g,' ')}`;
let code = api.clone(setconf.get().device);
code.mode = api.mode.get();
if (name.toLowerCase().indexOf('my ') >= 0) {
name = `${name} copy`;
} else {
name = `My ${name}`;
}
putLocalDevice(name, code);
setDeviceCode(code, name);
settings.sync.put();
}
function removeLocalDevice(devicename) {
delete api.conf.get().devices[devicename];
api.conf.save();
api.settings.sync.put();
}
function updateLaserState() {
const dev = setconf.get().device;
$('laser-on').style.display = dev.useLaser ? 'flex' : 'none';
$('laser-off').style.display = dev.useLaser ? 'flex' : 'none';
}
function isLocalDevice(devicename) {
return api.conf.get().devices[devicename] ? true : false;
}
function setDeviceCode(code, devicename) {
api.event.emit('device.select', devicename);
try {
if (typeof(code) === 'string') code = js2o(code) || {};
function getSelectedDevice() {
return api.device.get();
}
let mode = api.mode.get(),
lmode = mode.toLowerCase(),
current = setconf.get(),
local = isLocalDevice(devicename),
dev = current.device = conf.device_from_code(code,mode),
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
function selectDevice(devicename) {
if (isLocalDevice(devicename)) {
setDeviceCode(api.conf.get().devices[devicename], devicename);
} else {
let code = devices[api.mode.get_lower()][devicename];
if (code) {
setDeviceCode(code, devicename);
}
}
}
// fill missing device fields
conf.fill_cull_once(dev, conf.defaults[lmode].d);
// only for local filters
function cloneDevice() {
let name = `${getSelectedDevice().replace(/\./g,' ')}`;
let code = api.clone(api.conf.get().device);
code.mode = api.mode.get();
if (name.toLowerCase().indexOf('my ') >= 0) {
name = `${name} copy`;
} else {
name = `My ${name}`;
}
putLocalDevice(name, code);
setDeviceCode(code, name);
api.settings.sync.put();
}
function updateLaserState() {
const dev = api.conf.get().device;
$('laser-on').style.display = dev.useLaser ? 'flex' : 'none';
$('laser-off').style.display = dev.useLaser ? 'flex' : 'none';
}
function setDeviceCode(code, devicename) {
api.event.emit('device.select', devicename);
try {
if (typeof(code) === 'string') code = js2o(code) || {};
let mode = api.mode.get(),
lmode = mode.toLowerCase(),
current = api.conf.get(),
local = isLocalDevice(devicename),
dev = current.device = conf.device_from_code(code,mode),
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
// fill missing device fields
conf.fill_cull_once(dev, conf.defaults[lmode].d);
// first time device use, add any print profiles and set to default if present
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;
}
// first time device use, add any print profiles and set to default if present
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;
let { platform, ui, uc } = api;
let { space } = kiri;
ui.deviceBelt.checked = dev.bedBelt;
ui.deviceRound.checked = dev.bedRound;
ui.deviceOrigin.checked = dev.ctOriginCenter || dev.originCenter || dev.bedRound;
ui.fwRetract.checked = dev.fwRetract;
// add extruder selection buttons
if (dev.extruders) {
let ext = api.lists.extruders = [];
dev.internal = 0;
for (let i=0; i<dev.extruders.length; i++) {
ext.push({id:i, name:i});
}
}
// disable editing for non-local devices
[
// ui.deviceName,
ui.gcodePre,
ui.gcodePost,
ui.bedDepth,
ui.bedWidth,
ui.maxHeight,
ui.useLaser,
ui.resolutionX,
ui.resolutionY,
ui.deviceOrigin,
ui.deviceRound,
ui.deviceBelt,
ui.fwRetract,
ui.deviceZMax,
ui.gcodeTime,
ui.gcodeFan,
ui.gcodeFeature,
ui.gcodeTrack,
ui.gcodeLayer,
ui.extFilament,
ui.extNozzle,
ui.spindleMax,
ui.gcodeSpindle,
ui.gcodeDwell,
ui.gcodeChange,
ui.gcodeFExt,
ui.gcodeSpace,
ui.gcodeStrip,
ui.gcodeLaserOn,
ui.gcodeLaserOff,
ui.laserMaxPower,
ui.extPrev,
ui.extNext,
ui.extAdd,
ui.extDel,
ui.extOffsetX,
ui.extOffsetY
].forEach(function(e) {
e.disabled = !local;
});
ui.deviceSave.disabled = !local;
ui.deviceDelete.disabled = !local;
ui.deviceRename.disabled = !local;
ui.deviceExport.disabled = !local;
ui.deviceAdd.style.display = mode === 'SLA' ? 'none' : '';
if (local) {
ui.deviceAdd.innerText = "copy";
ui.deviceDelete.style.display = '';
ui.deviceRename.style.display = '';
ui.deviceExport.style.display = '';
} else {
ui.deviceAdd.innerText = "customize";
ui.deviceDelete.style.display = 'none';
ui.deviceRename.style.display = 'none';
ui.deviceExport.style.display = 'none';
}
ui.deviceAdd.disabled = dev.noclone;
api.conf.update_fields();
space.platform.setBelt(isBelt());
platform.update_size();
platform.update_origin();
platform.update();
updateLaserState();
// store current device name for this mode
current.filter[mode] = devicename;
// cache device record for this mode (restored in setMode)
current.cdev[mode] = dev;
if (dproc) {
// restore last process associated with this device
api.conf.load(null, dproc);
} else {
api.conf.update();
}
api.conf.save();
if (isBelt()) {
// space.view.setHome(dev.bedBelt ? Math.PI/2 : 0, Math.PI / 2.5);
space.view.setHome(0, Math.PI / 2.5);
} else {
space.view.setHome(0);
}
// when changing devices, update focus on widgets
if (chgdev) {
setTimeout(api.space.set_focus, 0);
}
uc.refresh(1);
api.event.emit('device.selected', dev);
} catch (e) {
console.log({error:e, device:code, devicename});
api.show.alert(`invalid or deprecated device: "${devicename}"`, 10);
api.show.alert(`please select a new device`, 10);
throw e;
showDevices();
}
api.function.clear();
api.event.settings();
}
function renderDevices(devices) {
let selected = api.device.get() || devices[0],
features = api.feature,
devs = api.conf.get().devices,
dfilter = typeof(features.device_filter) === 'function' ? features.device_filter : undefined;
dev.new = false;
dev.deviceName = devicename;
for (let local in devs) {
if (!(devs.hasOwnProperty(local) && devs[local])) {
continue;
let { platform, ui, uc } = api;
ui.deviceBelt.checked = dev.bedBelt;
ui.deviceRound.checked = dev.bedRound;
ui.deviceOrigin.checked = dev.ctOriginCenter || dev.originCenter || dev.bedRound;
ui.fwRetract.checked = dev.fwRetract;
// add extruder selection buttons
if (dev.extruders) {
let ext = api.lists.extruders = [];
dev.internal = 0;
for (let i=0; i<dev.extruders.length; i++) {
ext.push({id:i, name:i});
}
let dev = devs[local],
fdmCode = dev.cmd,
fdmMode = (api.mode.get() === 'FDM');
if (dev.mode ? (dev.mode === api.mode.get()) : (fdmCode ? fdmMode : !fdmMode)) {
devices.push(local);
}
};
}
devices = devices.sort();
let { event, ui } = api;
event.emit('devices.render', devices);
ui.deviceSave.onclick = function() {
event.emit('device.save');
api.function.clear();
api.conf.save();
api.settings.sync.put();
showDevices();
api.modal.hide();
};
ui.deviceAdd.onclick = function() {
api.function.clear();
cloneDevice();
showDevices();
};
ui.deviceDelete.onclick = function() {
api.function.clear();
removeLocalDevice(getSelectedDevice());
selectDevice(getModeDevices()[0]);
showDevices();
};
ui.deviceRename.onclick = function() {
api.uc.prompt(`Rename "${selected}`, selected).then(newname => {
if (newname) {
updateDeviceName(newname);
api.conf.save();
api.settings.sync.put();
showDevices();
} else {
showDevices();
}
});
};
ui.deviceExport.onclick = function(event) {
const record = {
version: kiri.version,
device: selected,
process: api.process.code(),
profiles: event.altKey ? api.settings.prof() : undefined,
code: devs[selected],
time: Date.now()
};
let exp = api.util.b64enc(record);
api.device.export(exp, selected, { event, record });
};
let dedup = {};
let list_cdev = [];
let list_mdev = [];
devices.forEach(function(device, index) {
// prevent device from appearing twice
// such as local name = standard device name
if (dedup[device]) {
return;
}
dedup[device] = device;
let loc = isLocalDevice(device);
if (dfilter && dfilter(device) === false) {
return;
}
if (loc) {
list_mdev.push(h.option(device));
} else {
list_cdev.push(h.option(device));
}
// disable editing for non-local devices
[
// ui.deviceName,
ui.gcodePre,
ui.gcodePost,
ui.bedDepth,
ui.bedWidth,
ui.maxHeight,
ui.useLaser,
ui.resolutionX,
ui.resolutionY,
ui.deviceOrigin,
ui.deviceRound,
ui.deviceBelt,
ui.fwRetract,
ui.deviceZMax,
ui.gcodeTime,
ui.gcodeFan,
ui.gcodeFeature,
ui.gcodeTrack,
ui.gcodeLayer,
ui.extFilament,
ui.extNozzle,
ui.spindleMax,
ui.gcodeSpindle,
ui.gcodeDwell,
ui.gcodeChange,
ui.gcodeFExt,
ui.gcodeSpace,
ui.gcodeStrip,
ui.gcodeLaserOn,
ui.gcodeLaserOff,
ui.laserMaxPower,
ui.extPrev,
ui.extNext,
ui.extAdd,
ui.extDel,
ui.extOffsetX,
ui.extOffsetY
].forEach(function(e) {
e.disabled = !local;
});
let dev_list = $('dev-list');
h.bind(dev_list, [
h.option({ _: '-- My Devices --', disabled: true }),
...list_mdev,
h.option({ _: '-- Stock Devices --', disabled: true }),
...list_cdev
]);
let dev_opts = [...dev_list.options].map(o => o.innerText);
dev_list.selectedIndex = dev_opts.indexOf(selected);
dev_list.onchange = ev => {
const seldev = dev_list.options[dev_list.selectedIndex];
selectDevice(seldev.innerText);
api.platform.layout();
}
selectDevice(selected);
}
ui.deviceSave.disabled = !local;
ui.deviceDelete.disabled = !local;
ui.deviceRename.disabled = !local;
ui.deviceExport.disabled = !local;
ui.deviceAdd.style.display = mode === 'SLA' ? 'none' : '';
if (local) {
ui.deviceAdd.innerText = "copy";
ui.deviceDelete.style.display = '';
ui.deviceRename.style.display = '';
ui.deviceExport.style.display = '';
} else {
ui.deviceAdd.innerText = "customize";
ui.deviceDelete.style.display = 'none';
ui.deviceRename.style.display = 'none';
ui.deviceExport.style.display = 'none';
}
ui.deviceAdd.disabled = dev.noclone;
setconf.update_fields();
space.platform.setBelt(isBelt());
platform.update_size();
platform.update_origin();
platform.update();
updateLaserState();
// store current device name for this mode
current.filter[mode] = devicename;
// cache device record for this mode (restored in setMode)
current.cdev[mode] = dev;
if (dproc) {
// restore last process associated with this device
setconf.load(null, dproc);
} else {
setconf.update();
}
setconf.save();
if (isBelt()) {
// space.view.setHome(dev.bedBelt ? Math.PI/2 : 0, Math.PI / 2.5);
space.view.setHome(0, Math.PI / 2.5);
} else {
space.view.setHome(0);
}
// when changing devices, update focus on widgets
if (chgdev) {
setTimeout(api.space.set_focus, 0);
}
uc.refresh(1);
api.event.emit('device.selected', dev);
} catch (e) {
console.log({error:e, device:code, devicename});
api.show.alert(`invalid or deprecated device: "${devicename}"`, 10);
api.show.alert(`please select a new device`, 10);
throw e;
showDevices();
}
api.function.clear();
api.event.settings();
}
function renderDevices(devices) {
let selected = api.device.get() || devices[0],
features = api.feature,
devs = setconf.get().devices,
dfilter = typeof(features.device_filter) === 'function' ? features.device_filter : undefined;
for (let local in devs) {
if (!(devs.hasOwnProperty(local) && devs[local])) {
continue;
}
let dev = devs[local],
fdmCode = dev.cmd,
fdmMode = (api.mode.get() === 'FDM');
if (dev.mode ? (dev.mode === api.mode.get()) : (fdmCode ? fdmMode : !fdmMode)) {
devices.push(local);
}
};
devices = devices.sort();
let { event, ui } = api;
event.emit('devices.render', devices);
ui.deviceSave.onclick = function() {
event.emit('device.save');
api.function.clear();
setconf.save();
settings.sync.put();
showDevices();
api.modal.hide();
};
ui.deviceAdd.onclick = function() {
api.function.clear();
cloneDevice();
showDevices();
};
ui.deviceDelete.onclick = function() {
api.function.clear();
removeLocalDevice(getSelectedDevice());
selectDevice(getModeDevices()[0]);
showDevices();
};
ui.deviceRename.onclick = function() {
api.uc.prompt(`Rename "${selected}`, selected).then(newname => {
if (newname) {
updateDeviceName(newname);
setconf.save();
settings.sync.put();
showDevices();
} else {
showDevices();
}
});
};
ui.deviceExport.onclick = function(event) {
const record = {
version: kiri.version,
device: selected,
process: api.process.code(),
profiles: event.altKey ? settings.prof() : undefined,
code: devs[selected],
time: Date.now()
};
let exp = api.util.b64enc(record);
api.device.export(exp, selected, { event, record });
};
let dedup = {};
let list_cdev = [];
let list_mdev = [];
devices.forEach(function(device, index) {
// prevent device from appearing twice
// such as local name = standard device name
if (dedup[device]) {
return;
}
dedup[device] = device;
let loc = isLocalDevice(device);
if (dfilter && dfilter(device) === false) {
return;
}
if (loc) {
list_mdev.push(h.option(device));
} else {
list_cdev.push(h.option(device));
}
});
let dev_list = $('dev-list');
h.bind(dev_list, [
h.option({ _: '-- My Devices --', disabled: true }),
...list_mdev,
h.option({ _: '-- Stock Devices --', disabled: true }),
...list_cdev
]);
let dev_opts = [...dev_list.options].map(o => o.innerText);
dev_list.selectedIndex = dev_opts.indexOf(selected);
dev_list.onchange = ev => {
const seldev = dev_list.options[dev_list.selectedIndex];
selectDevice(seldev.innerText);
api.platform.layout();
}
selectDevice(selected);
}
});

View file

@ -1,13 +1,8 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
// dep: kiri.api
// use: kiri.selection
// use: moto.space
gapp.register("kiri.do", [], (root, events) => {
import { api } from './api.js';
import { space } from '../moto/space.js';
const { kiri, moto } = root;
const { api } = kiri;
const { space } = moto;
const { event } = api;
let stack = [];
@ -44,7 +39,7 @@ let clear = api.doit.clear = function() {
};
function updateButtons() {
let isArrange = api.view.get() === kiri.consts.VIEWS.ARRANGE;
let isArrange = api.view.get() === api.consts.VIEWS.ARRANGE;
$('doit').style.display = isArrange && stack.length ? 'flex' : 'none';
$('undo').disabled = stpos === 0;
$('redo').disabled = stpos == stack.length;
@ -175,5 +170,3 @@ event.on('mouse.drag.done', () => {
});
moved = {x:0, y:0};
});
});

View file

@ -1,23 +1,13 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: ext.md5
// dep: geo.base
// dep: data.local
// dep: kiri.consts
// dep: kiri.api
// dep: kiri.main
gapp.register("kiri.export", [], (root, exports) => {
const { base, data, kiri } = root;
const { api, consts } = kiri;
const { local } = data;
const { util } = base;
const { stats, ui } = api;
const { MODES } = consts;
kiri.export = exportFile;
import { $ } from '../moto/webui.js';
import { api } from './api.js';
import { client } from './client.js';
import { local } from '../data/local.js';
import { util } from '../geo/base.js';
import { MODES } from './consts.js';
import { LASER as laser_driver } from '../kiri-mode/laser/driver.js';
import { SLA as sla_client } from '../kiri-mode/sla/client.js';
let printSeq = parseInt(local['kiri-print-seq'] || local['print-seq'] || "0") + 1;
@ -29,7 +19,7 @@ function localSet(key, val) {
return api.local.set(key, val);
}
function exportFile(options) {
export function exportFile(options) {
let mode = api.mode.get();
let names = api.widgets.all().map(w => w.meta ? w.meta.file : undefined)
.filter(v => v)
@ -53,7 +43,7 @@ function callExport(callback, mode, names) {
let gcode = [];
let section = [];
let sections = { };
kiri.client.export(api.conf.get(), (line) => {
client.export(api.conf.get(), (line) => {
if (typeof line !== 'string') {
if (line.section) {
sections[line.section] = section = [];
@ -75,7 +65,7 @@ function callExport(callback, mode, names) {
}
function callExportLaser(options, names) {
kiri.client.export(api.conf.get(), (line) => {
client.export(api.conf.get(), (line) => {
// engine export uses lines
// console.log({unexpected_line: line});
}, (output, error) => {
@ -89,14 +79,14 @@ function callExportLaser(options, names) {
}
function callExportSLA(options, names) {
kiri.client.export(api.conf.get(), (line) => {
client.export(api.conf.get(), (line) => {
api.show.progress(line.progress, "exporting");
}, (output, error) => {
api.show.progress(0);
if (error) {
api.show.alert(error, 5);
} else {
kiri.driver.SLA.printDownload(output, api, names);
sla_client.printDownload(output, api, names);
}
});
}
@ -107,7 +97,7 @@ function exportLaserDialog(data, names) {
const fileroot = names[0] || "laser";
const filename = `${fileroot}-${(printSeq.toString().padStart(3,"0"))}`;
const settings = api.conf.get();
const driver = kiri.driver.LASER;
const driver = laser_driver;
function download_svg() {
api.util.download(
@ -207,7 +197,7 @@ function exportGCodeDialog(gcode, sections, info, names) {
ajax.onreadystatechange = function() {
if (ajax.readyState === 4) {
let status = ajax.status;
stats.add(`ua_${api.mode.get_lower()}_print_octo_${status}`);
api.stats.add(`ua_${api.mode.get_lower()}_print_octo_${status}`);
if (status >= 200 && status < 300) {
api.modal.hide();
} else {
@ -278,11 +268,11 @@ function exportGCodeDialog(gcode, sections, info, names) {
)
.then(t => t.text())
.then(t => {
stats.add(`ua_${api.mode.get_lower()}_print_local_ok`);
api.stats.add(`ua_${api.mode.get_lower()}_print_local_ok`);
console.log({grid_spool_said: t});
})
.catch(e => {
stats.add(`ua_${api.mode.get_lower()}_print_local_err`);
api.stats.add(`ua_${api.mode.get_lower()}_print_local_err`);
console.log({grid_local_spool_error: e});
})
.finally(() => {
@ -394,7 +384,7 @@ function exportGCodeDialog(gcode, sections, info, names) {
xhtr.onreadystatechange = function() {
if (xhtr.readyState === 4) {
let status = xhtr.status;
stats.add(`ua_${api.mode.get_lower()}_print_grid_${status}`);
api.stats.add(`ua_${api.mode.get_lower()}_print_grid_${status}`);
if (status >= 200 && status < 300) {
let json = js2o(xhtr.responseText);
gridhost_tracker(host,json.key);
@ -511,7 +501,7 @@ function exportGCodeDialog(gcode, sections, info, names) {
})
}
}
kiri.client.zip(files, progress => {
client.zip(files, progress => {
api.show.progress(progress.percent/100, "generating zip files");
}, output => {
api.show.progress(0);
@ -681,7 +671,7 @@ function exportGCodeDialog(gcode, sections, info, names) {
name: `Metadata/top_1.png`,
data: api.view.bambu.s512.png
}];
kiri.client.zip(files, progress => {
client.zip(files, progress => {
api.show.progress(progress.percent/100, "generating 3mf");
}, output => {
api.show.progress(0);
@ -742,5 +732,3 @@ function exportGCodeDialog(gcode, sections, info, names) {
// preview of the generated GCODE (first 64k max)
if (preview && gcode) $('code-preview-textarea').value = gcode.substring(0,65535);
}
});

View file

@ -1,13 +1,5 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: main.kiri
// use: data.index
gapp.register("kiri.files", [], (root, exports) => {
const { kiri } = self;
class Files {
constructor(indexdb) {
let store = this;
@ -176,8 +168,8 @@ function notifyFileListeners(store) {
}
}
kiri.openFiles = function(indexdb) {
export const openFiles = function(indexdb) {
return new Files(indexdb);
};
});
export { saveFileList, notifyFileListeners };

View file

@ -1,14 +1,12 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { load } from '../load.js';
import { kiri } from './kiri.js';
import { moto } from '../moto.js';
import { api } from './api.js';
import { newWidget } from './widget.js';
import { conf, event, feature, platform, settings, show } from './api.js';
import { VIEWS } from './consts.js';
"use strict";
// use: load.stl
// use: load.svg
// use: kiri.api
// use: kiri.platform
// use: kiri.settings
// use: kiri.widget
gapp.register("kiri.frame", [], (root, exports) => {
// add frame message api listener
window.addEventListener('message', msg => {
@ -127,4 +125,5 @@ window.addEventListener('message', msg => {
}
});
});
// No direct exports; sets up message listener

View file

@ -1,30 +1,16 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: kiri.api
// dep: kiri.client
// dep: kiri.export
// dep: moto.space
// use: kiri-mode.cam.client
// dep: kiri-mode.fdm.client
// dep: kiri-mode.sla.client
// dep: kiri-mode.laser.driver
// dep: kiri-mode.drag.driver
// dep: kiri-mode.wjet.driver
// dep: kiri-mode.wedm.driver
gapp.register("kiri.function", (root, exports) => {
const { kiri } = root;
const { api, client, consts, utils } = kiri;
const { space } = moto;
const { COLOR, PMODES } = consts;
import { api } from './api.js';
import { client } from './client.js';
import { codec } from './codec.js';
import { space } from '../moto/space.js';
import { COLOR, PMODES } from './consts.js';
import { exportFile } from './export.js';
let complete = {};
function prepareSlices(callback, scale = 1, offset = 0) {
const { conf, event, feature, hide, mode, view, platform, show } = api;
const { stacks } = kiri;
const { conf, event, feature, hide, mode, view, platform, show, stacks } = api;
if (view.is_arrange()) {
// in arrange mode, create a screenshot at the start slicing
@ -139,10 +125,34 @@ function prepareSlices(callback, scale = 1, offset = 0) {
}
function sliceWidget(widget) {
// weight each widget progress % by their # vertices
let factor = (widget.getVertices().count / defvert);
widget.slice(settings, (sliced, error) => {
function onupdate(update, msg, alert) {
if (alert) {
api.show.alert(alert);
}
if (msg && msg !== lastMsg) {
let mark = Date.now();
if (lastMsg) {
let key = widgets.length > 1 ?
`${widget.id}_${segNumber++}_${lastMsg}` :
`${segNumber++}_${lastMsg}`
segtimes[key] = mark - startTime;
}
lastMsg = msg;
startTime = mark;
}
// on update
if (update >= 0) {
track[widget.id] = (update || 0) * factor;
totalProgress = 0;
for (let w of slicing) {
totalProgress += (track[w.id] || 0);
}
show.progress(offset + (totalProgress / slicing.length) * scale, msg);
}
}
function ondone(sliced, error) {
let mark = Date.now();
// update UI info
if (sliced) {
@ -169,28 +179,55 @@ function prepareSlices(callback, scale = 1, offset = 0) {
// start next widget slice
sliceNext();
}
}, (update, msg, alert) => {
if (alert) {
api.show.alert(alert);
}
// weight each widget progress % by their # vertices
let factor = (widget.getVertices().count / defvert);
widget.settings = settings;
widget.clearSlices();
onupdate(0.0001, "slicing");
// store slicing visuals
widget.stack = api.stacks.create(widget.id, widget.mesh);
// compensate for zcut (widget moved through floor)
widget.stack.obj.view.position.z = widget.track.zcut || 0;
// in case result of slice is nothing, do not preserve previous
widget.slices = []
// executed from kiri.js
client.slice(settings, widget, (reply) => {
if (reply.alert) {
onupdate(null, null, reply.alert);
}
if (msg && msg !== lastMsg) {
let mark = Date.now();
if (lastMsg) {
segtimes[`${widget.id}_${segNumber++}_${lastMsg}`] = mark - startTime;
}
lastMsg = msg;
startTime = mark;
if (reply.update) {
onupdate(reply.update, reply.updateStatus);
}
// on update
if (update >= 0) {
track[widget.id] = (update || 0) * factor;
totalProgress = 0;
for (let w of slicing) {
totalProgress += (track[w.id] || 0);
}
show.progress(offset + (totalProgress / slicing.length) * scale, msg);
if (reply.send_start) {
widget.xfer = {start: reply.send_start};
}
if (reply.stats) {
widget.stats = reply.stats;
}
if (reply.send_end) {
widget.stats.load_time = widget.xfer.start - reply.send_end;
}
if (reply.slice) {
widget.slices.push(codec.decode(reply.slice, {mesh:widget.mesh}));
}
if (reply.done) {
ondone(true);
}
if (reply.error) {
ondone(false, reply.error);
}
});
// discard point cache
widget.points = undefined;
}
function sliceDone() {
@ -247,9 +284,7 @@ function prepareSlices(callback, scale = 1, offset = 0) {
}
function preparePreview(callback, scale = 1, offset = 0) {
const { conf, event, feature, hide, mode, view, platform, show } = api;
const { stacks } = kiri;
const { conf, event, feature, hide, mode, view, platform, show, stacks } = api;
const widgets = api.widgets.all();
const settings = conf.get();
const { device, process, controller } = settings;
@ -305,7 +340,7 @@ function preparePreview(callback, scale = 1, offset = 0) {
client.prepare(settings, (progress, message, layer) => {
if (layer) {
output.push(kiri.codec.decode(layer));
output.push(codec.decode(layer));
}
if (message && message !== lastMsg) {
const mark = Date.now();
@ -407,7 +442,7 @@ function prepareExport() {
}
api.event.emit("function.export", {mode: settings.mode});
complete.export = true;
kiri.export(...argsave);
exportFile(...argsave);
}
function cancelWorker() {
@ -441,8 +476,12 @@ function parseCode(code, type) {
});
}
function clear_progress() {
complete = {};
}
// extend API (api.function)
const functions = Object.assign(api.function, {
export const functions = {
slice: prepareSlices,
print: preparePreview,
prepare: preparePreview,
@ -451,7 +490,16 @@ const functions = Object.assign(api.function, {
cancel: cancelWorker,
parse: parseCode,
clear: client.clear,
clear_progress() { complete = {} }
});
clear_progress,
};
});
export {
prepareSlices as slice,
preparePreview as print,
preparePreview as prepare,
prepareAnimation as animate,
prepareExport as export,
cancelWorker as cancel,
parseCode as parse,
clear_progress,
};

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
../../web/kiri/lang/en.js

932
src/kiri/lang-en.js Normal file
View file

@ -0,0 +1,932 @@
// English language map. Other localization maps will
// defer to English map for any missing key/value pairs
self.lang['en'] =
self.lang['en-us'] = {
// common keys and menus
animate: "animate", // CAM animate button
arrange: "arrange", // layout workspace objects
axis: "axis", // left object scale pop menu
back: "back",
clear: "clear", // clear workspace (remove all objects)
copy: "copy",
clone: "clone", // create duplicate
delete: "delete",
detail: "detail",
done: "done",
edit: "edit",
enable: "enable",
disable: "disable",
donate: "donate",
export: "export",
files: "files",
filter: "filter",
front: "front",
fullscreen: "fullscreen",
help: "help",
ghost: "ghost", // left render pop menu (wireframe)
hide: "hide", // left render pop menu (invisible)
home: "home",
import: "import",
language: "language",
left: "left",
machines: "machines", // device or machine
mesh: "mesh", // mesh editing
metric: "metric",
name: "name",
new: "new", // file new
off: "off", // turn something off (like a lightbulb)
on: "on", // turn something on (like a lightbulb)
profs: "profiles", // right menu "profiles"
prefs: "preferences", // right menu "preferences"
preview: "preview",
recent: "recent",
rename: "rename",
render: "render", // left render pop menu
reset: "reset",
right: "right",
rotate: "rotate", // left rotate pop menu
save: "save",
scale: "scale", // left object scale pop menu
select: "select",
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
volume: "volume", // device build area
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_focs: "set focus",
rc_heal: "heal meshes",
rc_swap: "replace vertices",
rc_xobj: "export OBJ",
rc_xstl: "export STL",
sb_info: ["print speed","in mm/s"],
rc_merg: "merge object meshes",
// 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: "settings",
dm_appp: "Application Preferences",
// CAM Tool Dialog
td_tyem: "end", // end mill
td_tybm: "ball", // ball mill
td_tytm: "taper", // taper mill
td_tydr: "drill", // drill
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",
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: "device name",
dv_fila_s: "filament",
dv_fila_l: "diameter in millimeters",
dv_nozl_s: "nozzle",
dv_nozl_l: "diameter in millimeters",
dv_bedw_s: "width",
dv_bedw_l: "workspace units",
dv_bedd_s: "depth",
dv_bedd_l: "workspace units",
dv_bedh_s: "height",
dv_bedh_l: ["max build height","in workspace units"],
dv_rezx_s: "resolution X",
dv_rezx_l: ["x resolution"],
dv_rezy_s: "resolution Y",
dv_rezy_l: ["y resolution"],
dv_zmax_s: "Z axis speed limit",
dv_zmax_l: ["maximum Z axis speed","in millimeters / second","0 to disable"],
dv_time_s: "output time factor",
dv_time_l: ["modifier to print time estimates","in the gcode export dialog.","raise or lower value based on your","predicted vs observed print times"],
dv_spmx_s: "max spindle",
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",
dv_orgc_l: "bed origin center",
// dv_orgt_s: "origin top",
// dv_orgt_l: "part z origin top",
dv_bedc_s: "circular bed",
dv_bedc_l: "device bed is circular",
dv_belt_s: "belt bed",
dv_belt_l: "continuous printing bed",
dv_fsrc_s: "filament source",
dv_fsrc_l: ["how filament is fed\ninto the extruder"],
dv_retr_s: "firmware retract",
dv_retr_l: ["device fimware supports G10/G11"],
dv_fanp_s: "cooling",
dv_fanp_l: "set cooling fan power",
dv_feat_s: "feature",
dv_feat_l: "inject code for specified features",
dv_prog_s: "progress",
dv_prog_l: "output on each % progress",
dv_layr_s: "layer",
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: "file extension",
dv_fext_l: "file name extension",
dv_lazr_s: "enable laser",
dv_lazr_l: ["enable laser operations"],
dv_dwll_s: "dwell",
dv_dwll_l: "gcode dwell script",
dv_tool_s: "tool",
dv_tool_l: "tool change script",
dv_sspd_s: "spindle",
dv_sspd_l: "set spindle speed",
dv_paus_s: "pause",
dv_paus_l: "gcode pause script",
dv_head_s: "header",
dv_head_l: "gcode header script",
dv_foot_s: "footer",
dv_foot_l: "gcode footer script",
dv_pext_s: "exterior",
dv_pext_l: ["gcode script run before","printing exterior lines"],
dv_pint_s: "interior",
dv_pint_l: ["gcode script run before","printing interior lines"],
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_waon_s: "water on",
dv_waon_l: "gcode water pump on script",
dv_waof_s: "water off",
dv_waof_l: "gcode water pump off script",
dv_dkon_s: "knife down",
dv_dkon_l: "gcode knife down script",
dv_dkof_s: "knife up",
dv_dkof_l: "gcode knife up script",
dv_exts_s: "select",
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",
dv_exox_l: "nozzle offset x",
dv_exoy_s: "offset y",
dv_exoy_l: "nozzle offset y",
dv_paid_s: "printer id",
dv_paid_l: ["unique printer identifier","may be made up"],
dv_paps_s: "ping spacing",
dv_paps_l: ["minimum filament consumption","between pings in millimeters","recommended 500 - 1000","0 = disable pings"],
dv_pafe_s: "feed length",
dv_pafe_l: ["feeder tube length in millimeters","short=570, medium=800, long=1100"],
dv_papl_s: "push length",
dv_papl_l: ["distance between extruder gear","and nozzle tip in millimeters"],
dv_paof_s: "offset length",
dv_paof_l: ["length to add or remove from","the first segment in millimeters","usually 0"],
dv_pahe_s: "heating time",
dv_pahe_l: ["offset from default"],
dv_paco_s: "cooling time",
dv_paco_l: ["offset from default"],
dv_pacm_s: "compression time",
dv_pacm_l: ["offset from default"],
// MODE
mo_menu: "mode",
mo_fdmp: "FDM Print",
mo_slap: "SLA Print",
mo_lazr: "Laser Cut",
mo_cncm: "CNC Mill",
// SETUP
su_menu: "setup",
su_devi: "Devices",
su_tool: "Tools",
su_locl: "Local",
su_xprt: "Export",
su_help: "Help",
// LOAD
fe_menu: "file",
fn_recn: "Recent",
fn_impo: "Import",
// 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: "show decals",
op_decl_l: "show device decals and logos",
op_shny_s: "detail render",
op_shny_l: "choose a slice render method that is slower and uses specular highlighting. this makes it easier to see detail in some models at the expense of render speed",
op_devl_s: "developer",
op_devl_l: ["show developer options","enable developer debugging"],
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","in belt mode, use 0","to auto-space by height"],
op_spoa_s: "edge angle",
op_spoa_l: ["surface angle difference triggering an edge trace"],
op_spcx_s: "random X",
op_spcx_l: ["in belt mode, randomly","layout the part on X","to even belt wear"],
op_orth_s: "orthographic",
op_orth_l: ["orthographic display","requires page refresh"],
op_anta_s: "anti-alias",
op_anta_l: ["smooth display. better but slower","requires a page refresh or reload"],
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"],
op_exgl_l: ["show Grid:Local devices in export dialog","includes Grid:Bots and OctoPrint plugins"],
op_exgh_l: ["legacy Grid:Host local network support"],
op_exop_l: ["legacy OctoPrint local network support","Grid:Space OctoPrint plugin recommended"],
lo_menu: "layout",
pt_menu: "slicer",
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: "detail",
pt_qual_l: ["level of detail to retain during slicing operations. lower is faster and uses less memory. large scale models often do no benefit from higher detail. instead it my only result in memory and processing problems. reduce this value if you are getting out of memory errors."],
pt_heal_s: "heal mesh",
pt_heal_l: ["attempt to heal non-manifold meshes during slicing. may increase slicing time. enables a warning when non-manifold geometries are detected."],
pt_thrd_s: "threaded",
pt_thrd_l: ["use parallel processing when browser supports nested workers. may increase memory pressure on larger models. disable if you are getting out of memory errors"],
pt_assy_s: "assembly",
pt_assy_l: ["use web assembly when supported by browser. if you experience artifacts or memory errors, try disabling this."],
xp_menu: "exports",
// SETTINGS
se_menu: "profile",
se_load: "load",
se_save: "save",
// FDM LAYERS
sl_menu: "paths",
sl_angl_s: "slice angle",
sl_angl_l: ["slice angle bias in degrees"],
sl_lahi_s: "layer height",
sl_lahi_l: ["height of each slice","layer in millimeters"],
ad_minl_s: "layer minimum",
ad_minl_l: ["adaptive min layer height","in millimeters","must be non-zero"],
ad_adap_s: "adaptive",
ad_adap_l: ["use adaptive layer heights","with 'layer height' as max","and 'layer min' as the min"],
sl_ltop_s: "top layers",
sl_ltop_l: ["number of solid layers at the top of the print or on flat areas facing up"],
sl_lsld_s: "solid layers",
sl_lsld_l: ["solid fill areas computed","from bridges and flat areas","detected betwen sliced layers"],
sl_lbot_s: "base layers",
sl_lbot_l: ["number of solid layers at bottom of the print or under bridge spans"],
// FDM WALLS
sw_menu: "shells",
sl_shel_s: "shell count",
sl_shel_l: ["number of perimeter","walls to generate"],
ad_thin_s: "thin walls",
ad_thin_l: ["detect and fill gaps","between shell walls"],
// FDM SHELLS
sl_line_s: "shell width",
sl_line_l: ["extrusion width in millimeters","0 = nozzle diameter"],
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"],
// FDM FILL
fi_menu: "sparse fill",
fi_type: "fill type",
fi_pcnt_s: "fill amount",
fi_pcnt_l: ["fill density values","0.0 - 1.0"],
fi_rept_s: "fill repeat",
fi_rept_l: ["number of times to repeat","unchanged fill layers"],
fi_angl_s: "solid angle",
fi_angl_l: ["starting angle in degrees","90 degrees added to ","each following layer","applies only to solid layers"],
fi_grow_s: "solid expand",
fi_grow_l: ["expand projected solids","can help with solid areas","over sparse infill areas","units in millimeters"],
fi_over_s: "fill overlap",
fi_over_l: ["overlap with shell and other fill","for improved extrusion bonding","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 HEATING
fh_menu: "heating",
// FDM COOLING
fc_menu: "cooling",
// 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 / second"],
fl_frat_s: "fill speed",
fl_frat_l: ["fill printing max speed","in millimeters / second"],
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","when rafts are used","this is the raft offset"],
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"],
fr_draf_s: "draft shield",
fr_draf_l: ["extend skirt to height of part","which acts as a shield against","drafts and traps hot air"],
// FDM BELT ONLY
fl_zoff_s: "belt offset",
fl_zoff_l: ["height offset from belt","of lowest extrusion","in millimeters"],
fl_flat_s: "flatten",
fl_flat_l: ["flatten to the belt any point","height less than this value","in millimeters"],
fl_brim_s: "brim sides",
fl_brim_l: ["add brim to part perimeter","size is width in millimeters","0 to disable"],
fl_brin_s: "brim interior",
fl_brin_l: ["add brim to part interior","when interior voids exist","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_brco_s: "brim comb",
fl_brco_l: ["add brim gaps","every n lines","0 to disable"],
fl_brgp_s: "brim gap",
fl_brgp_l: ["spacing between brim and part","in millimeters"],
fl_bled_s: "part anchor",
fl_bled_l: ["belt part anchor","at start of print","in millimeters"],
fl_blmp_s: "anchor bump",
fl_blmp_l: ["add a bump to the start of","an anchor to help it peel","off at the end of the belt","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","smaller values exponentially","increase detection times"],
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","normal values 45-60","belt values 0-10"],
sp_area_s: "min area",
sp_area_l: ["minimum area for","a support column","in millimeters","smaller values will","slow detection"],
sp_xpnd_s: "expand",
sp_xpnd_l: ["expand support area","beyond part boundary","in millimeters"],
sp_grow_s: "grow",
sp_grow_l: ["grow support column to fill small gaps","in millimeters"],
sp_nozl_s: "extruder",
sp_nozl_l: ["in multi-extruder systems","the extruder to use for","support material"],
sp_outl_s: "enclosed",
sp_outl_l: ["enclose support pattern","inside a perimeter shell"],
sp_auto_s: "automatic",
sp_auto_l: ["enable generated supports","using at-slice-time geometry","supports will only appear","after slicing completes"],
// 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: ["a fraction of tool diameter between 0 and 1. values greater than 0.49 may result in uncut areas or undesirable artifacts."],
cc_sovc_s: "wide steps",
cc_sovc_l: ["number of wide cutout steps"],
cc_sang_s: "step angle",
cc_sang_l: ["rotation in degrees between lathe axial points"],
cc_sdwn_s: "step down",
cc_sdwn_l: ["step down depth","for each pass","in workspace units","0 to disable"],
cc_thru_s: "cut thru",
cc_thru_l: ["additional cut depth below trace bottom"],
cc_offd_s: "offset",
cc_offd_l: ["overrides default offset distance (which is the tool radius) when set to any value but zero"],
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"],
cc_sele_s: "select",
cc_sele_l: ["select lines for follow","select loops for clear","select surface for pocket"],
// CNC COMMON
cc_menu: "limits",
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"],
// CNC LEVELING
cc_loff_s: "z offset",
cc_loff_l: ["distance from stock face","in workspace units"],
cc_lxyo_s: "xy offset",
cc_lxyo_l: ["xy offset from part boundary as a fraction of the tool diameter (0 - 1.0)"],
cc_lsto_s: "stock",
cc_lsto_l: ["use stock area instead of part area"],
// 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_lstz_s: "leave stock z",
cr_lstz_l: ["vertical offset for roughing passes in workspace units. best for roughing curved surfaces."],
cr_ease_s: "ease down",
cr_ease_l: ["plunge cuts will","spiral down or ease","along a linear path"],
cr_clst_s: "clear stock",
cr_clst_l: ["in indexed mode, clear entire stock area, not just to part periemter"],
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_merg_s: "merge overlap",
co_merg_l: ["merge overlapping lines to prevent overcutting into adjacent solids"],
co_dogb_s: "dogbones",
co_dogb_l: ["insert dogbone cuts","into inside corners"],
co_dogr_s: "reverse bones",
co_dogr_l: ["reverse dogbone direction"],
co_clrt_s: "clear top",
co_clrt_l: ["cut starting at the top of stock","when stock is enabled"],
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_omvd_s: "omit pocket",
co_omvd_l: "eliminate interior pockets",
co_olen_s: "enable",
co_olen_l: "enabled outline cutting",
// CNC CONTOUR
cn_menu: "contour",
cf_angl_s: "max angle",
cf_angl_l: ["changes in z that result in angles greater than this are considered vertical and omitted from curves"],
cf_leav_s: "leave stock",
cf_leav_l: ["amount of stock to leave above part surface"],
cf_botm_s: "z bottom",
cf_botm_l: ["obey z bottom limit"],
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: ["clear = clear a closed-line pocket","follow = tool tip follows line","with offset option when closed"],
// CNC POCKET
cp_xpnd_s: "expand",
cp_xpnd_l: ["grow (+) or shrink (-) selected areas","contour uses entire selected area","non-contour defaults to tool radius","in workspace units"],
cp_smoo_s: "smooth",
cp_smoo_l: ["clean up jagged edges caused by angled walls. can speedup and improve pocketing for detailed geometries. recommend starting with values around 1 if slicing takes too long or the contours look jagged"],
cp_foll_s: "selection",
cp_foll_l: ["curvature selection limit in degrees. values closer to 0 will restrict selections to flatter surfaces"],
cp_refi_s: "refine",
cp_refi_l: ["number of refining passes to perform on contoured polylines. meant to address Z delta sawtoothing caused by faced geometries whereas smoothing handles XY. values > 10 work well for gently contoured geometries with significant Z movement."],
cp_cont_s: "contour",
cp_cont_l: ["ignore interior voids and features"],
cp_engr_s: "engrave",
cp_engr_l: ["sets up a single pass around the perimeter of the selected area. also useful for 3D laser marking"],
cp_outl_s: "outline only",
cp_outl_l: ["ignore interior voids and features"],
// 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"],
cd_thru_s: "z extend",
cd_thru_l: ["extend downward cut through stock","in workspace units"],
cd_dtru_s: "drill through",
cd_dtru_l: ["additional drill depth below part bottom","overrides global z thru","0 to disable"],
cd_mark_s: "marking",
cd_mark_l: ["only mark holes, do not drill out","the step down setting is used","to determine how deep to mark"],
cd_ftop_s: "from stock top",
cd_ftop_l: ["drill from stock top","instead of part surface"],
cd_prcn_s: "precision",
cd_prcn_l: ["distance between slices","to search for holes","in workspace units","lower is slower and","uses more memory","0 = only flats"],
cd_seli_l: ["individually select holes","to drill"],
cd_sela_s: "Select Matching Diameter",
cd_sela_l: ["select all holes that", "match selected tool diameter"],
// CNC FLIP
cf_menu: "flip",
cf_nvrt_s: "z bottom",
cf_nvrt_l: "invert z bottom setting to follow stock",
// CNC INDEX AXIS
ci_degr_s: "degrees",
ci_degr_l: "degrees to rotate the A (indexed) axis",
ci_abso_s: "absolute",
ci_abso_l: "degree rotation is absolute",
ci_face_s: "face",
ci_face_l: "select face to rotate facing up",
ci_line_s: "linear",
ci_line_l: "make linear passes along X then rotate Y",
// CNC LASER On/Off Operations (Carvera)
cl_powr_s: "power",
cl_powr_l: "laser power from 0 to 1.0",
cl_adap_s: "adaptive",
cl_adap_l: "use adaptive power based on Z height",
cl_adrp_s: "repeating",
cl_adrp_l: "apply a moduluse of Z height using the given band to make repeating patterns",
cl_flat_s: "flatten",
cl_flat_l: "flatten output to a given Z height",
cl_flaz_s: "flat height",
cl_flaz_l: ["flatten output to this Z height", "in workspace units"],
cl_minp_s: "z min power",
cl_minp_l: ["power setting at the lowest part of the Z band. may be higher or lower than the other end of the Z band."],
cl_maxp_s: "z max power",
cl_maxp_l: ["power setting at the highest part of the Z band. may be higher or lower than the other end of the Z band."],
cl_minz_s: "min z height",
cl_minz_l: ["lowest Z band position"],
cl_maxz_s: "max z height",
cl_maxz_l: ["highest Z band position. when set to 0, uses the highest Z point of the workspace"],
// 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 SLICING
ls_offs_s: "offset / kerf",
ls_offs_l: ["distance between the center of the cutting","path and the edge of remaining material","in millimeters"],
ls_lahi_s: "slice height",
ls_lahi_l: ["layer height","in millimeters","0 = auto/detect"],
ls_lahm_s: "slice minimum",
ls_lahm_l: ["layer height minimum","will merge auto slices","under this thickness","in millimeters"],
ls_sngl_s: "single slice",
ls_sngl_l: ["perform only one slice","at specified layer height"],
// LASER KNIFE
dk_menu: "drag 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"],
// WIRE EDM
we_omit_s: "omit inner",
we_omit_l: "omit inner polygons",
// LASER OUTPUT
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 / second",
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_lays_s: "layer marking",
ou_lays_l: ["mark layers for stacking. the layer above will be output in a different color which the laser can mark with a lower power. turns on layer grouping."],
ou_drkn_s: "drag knife",
ou_drkn_l: ["enable drag knife","output in gcode","cut radii are added","to corners with","cut down passes"],
ou_stak_s: "3d stack",
ou_stak_l: ["output is a 3D stack of 2D paths rather than packing layers flat in 2D"],
ou_maxp_s: "max power",
ou_maxp_l: ["max power value in gcode. power % from settings will scale from 0 to this value"],
ou_inch_s: "imperial",
ou_inch_l: ["output values in inches"],
ou_shap_s: "shaper tool",
ou_shap_l: ["annotate SVG with Shaper Tool custom attributes"],
// 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 printing speed","set to 0 to use default","millimeters / second"],
ou_fini_s: "finish speed",
ou_fini_l: ["outermost shell speed","bridge/flat solid layers","set to 0 to use default","millimeters / second"],
ou_move_s: "move speed",
ou_move_l: ["non-print move speed","millimeters / second","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_fanl_s: "fan on layer",
ou_fanl_l: ["layer # to turn on fan","layers start at 0"],
ou_fans_s: "fan speed",
ou_fans_l: "0 - 255",
// OUTPUT CAM
ou_toll_s: "precision",
ou_toll_l: ["surface precision","in workspace units","lower is slower and","uses more memory","0 = automatic based","on animate preference"],
ou_flat_s: "flatness",
ou_flat_l: ["delta z below which two adjacent points are considered co-linear. 0 = compute using tolerance"],
ou_redu_s: "reduction",
ou_redu_l: ["number of axis steps to skip for each unit of precision. higher precision may require reduction to produce reasonable file sizes. start at 0 and test in increments of 1."],
ou_brdg_s: "bridging",
ou_brdg_l: ["flat distance between curved","areas to bridge with a cut"],
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"],
ou_ztop_s: "z top",
ou_ztop_l: ["offset from stock bottom","to set start of cutting depth","in workspace units","* drill/contour ignore this *"],
ou_zbot_s: "z bottom",
ou_zbot_l: ["offset from stock 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"],
ou_toin_s: "tool init",
ou_toin_l: "add tool change with first operation. when disabled, the gcode assumes the first tool is loaded and offset probed",
ou_forz_s: "force z max",
ou_forz_l: "all moves between pockets will go to z max (above stock). this is usually required if you are not performing a roughing operation before pocketing operations.",
ou_z1st_s: "first z max",
ou_z1st_l: "first move in the job will be to Z max (travel distance above stock)",
ou_feng_s: "engage factor",
ou_feng_l: "speed scale (0.1-1) when endmill is fully engaged on a new cut. stepped over cuts when the endmill is less than fully engaged run at a factor of 1 relative to output speed. typically this relates to roughing or any operation with step over.",
ou_eang_s: "ease angle",
ou_eang_l: "descent angle for ease down in degrees",
// 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_ishg_s: "show grid",
cs_ishg_l: ["show platform grid in indexed mode"],
cs_indx_s: "indexed",
cs_indx_l: ["stock is mounted to a rotatary indexer"],
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",
or_offx_s: "origin offset X",
or_offx_l: "origin offset X",
or_offy_s: "origin offset Y",
or_offy_l: "origin offset Y",
// CAM ORIGIN
co_menu: "origin",
co_offx_s: "offset x",
co_offx_l: ["offset origin along x axis","in workspace units"],
co_offy_s: "offset y",
co_offt_l: ["offset origin along y axis","in workspace units"],
co_offz_s: "offset z",
co_offz_l: ["offset origin along z axis","in workspace units"],
// 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_lbir_s: "belt first",
ad_lbir_l: ["always print shells touching the belt before any other shells. this is no longer a recommended setting based on extensive testing."],
ad_altr_s: "alternating",
ad_altr_l: ["alternate shell winding order","clockwise / counter-clockwise","may reduce warping in thin areas","and help with belt edge adhesion"],
ad_zint_s: "interleave z",
ad_zint_l: ["interleave Z heights with odd number shells"],
ad_lret_s: "layer retract",
ad_lret_l: ["force filament retraction","between layers"],
ad_agap_s: "avoid gaps",
ad_agap_l: ["route around gaps rather","than perform a retract","when possible"],
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 / second"],
ad_purg_s: "purge tower",
ad_purg_l: ["purge tower area in mm^2","for multi extruder setups","0 = disabled"],
// 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"],
cx_true_s: "true shadow",
cx_true_l: ["computationally correct shadow","will be slower but produce","better cuts for complex parts"],
cx_arct_s: "arc tolerance",
cx_arct_l: ["convert cicrular paths to arcs;","center point drift tolerance","when matching arc points","consider values around 0.15","in mm, or 0.006 inches;","High values may cause","unexpected behavior","0 to disable"],
cx_arcr_s: "arc resolution",
cx_arcr_l: ["change in line direction","aceptible in an arc","consider values around 5","High values may cause","unexpected behavior",],
// 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 position","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","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"],
ag_loop_s: "loop count",
ag_loop_l: ["number of times to repeat","the selected range or the","entire print if no range"],
// 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: "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"]
};

View file

@ -1,11 +1,6 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
gapp.register("kiri.lang", [], (root, exports) => {
const { kiri } = root;
const LANG = kiri.lang = { current: {} };
const LANG = self.lang = { current: {} };
const KDFL = 'en-us';
let lset = navigator.language.toLocaleLowerCase();
@ -78,4 +73,6 @@ LANG.set = function() {
return undefined;
}
});
export default { LANG };
export { LANG };

View file

@ -1,25 +1,9 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
import { newPolygon, Polygon } from '../geo/polygon.js';
import { polygons as POLY } from '../geo/polygons.js';
/*
* provides the `output` abstraction for turning poly lines (open and closed)
* into primordial geometries (faces, lines, color ranges). used inside of
* workers as part of slicing and preview output.
*/
// dep: geo.base
// dep: geo.paths
// dep: geo.polygon
// dep: geo.polygons
gapp.register("kiri.layers", [], (root, exports) => {
const { base, kiri } = root;
const { polygons, newPolygon } = base;
const POLY = base.polygons;
class Layers {
export class Layers {
constructor() {
this.init();
}
@ -94,7 +78,7 @@ class Layers {
options.open = true;
const polys = [];
for (let i=0; i<lines.length-1; i += 2) {
polys.push(new base.Polygon()
polys.push(new Polygon()
.append(lines[i])
.append(lines[i+1])
.setOpen());
@ -110,11 +94,14 @@ class Layers {
// an open or closed polygon
addPoly(poly, options) {
return this.addPolys([poly], options);
return this.addPolys([ poly ], options);
}
// a polygon rendered as a webgl line
addPolys(polys, options) {
if (!Array.isArray(polys)) {
throw "polys must be an array";
}
if (polys.length === 0) {
return this;
}
@ -186,8 +173,7 @@ class Layers {
p1.setZ(poly.z);
p2.setZ(poly.z);
}
this.addPolys(p1);
this.addPolys(p2);
this.addPolys([ p1, p2 ]);
}
const color = opts.color ?
(typeof(opts.color) === 'number' ? { line: opts.color, face: opts.color } : opts.color) :
@ -277,7 +263,3 @@ function flat(polys) {
return POLY.flatten([polys.clone(true)], [], true);
}
}
kiri.Layers = Layers;
});

File diff suppressed because it is too large Load diff

View file

@ -1,17 +1,6 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
/**
* adapted from
* http://codeincomplete.com/posts/2011/5/7/bin_packing/
*/
gapp.register("kiri.pack", [], (root, exports) => {
const { kiri } = root;
class Packer {
export class Packer {
constructor(w, h, spacing, opt = {}) {
this.w = w;
this.h = h;
@ -150,7 +139,3 @@ class Packer {
return node;
}
}
kiri.Pack = Packer;
});

View file

@ -1,26 +1,16 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
import { $, h } from '../moto/webui.js';
import { api } from './api.js';
import { ajax, js2o } from './utils.js';
import { base } from '../geo/base.js';
import { load } from '../load/file.js';
import { space } from '../moto/space.js';
import { Widget } from './widget.js';
import { Packer } from './pack.js';
// dep: moto.space
// dep: moto.webui
// dep: kiri.api
// dep: kiri.consts
// dep: kiri.utils
// dep: kiri.widget
// dep: load.stl
// dep: load.obj
// dep: load.3mf
// dep: load.gbr
// use: kiri-mode.cam.tool
gapp.register("kiri.platform", [], (root, exports) => {
const { base, kiri, moto, load } = root;
const { api, consts, driver, utils, newWidget, Widget } = kiri;
const { ajax, js2o } = utils;
const { space } = moto;
const { util } = base;
const { COLOR, MODES } = consts;
import { COLOR, MODES } from './consts.js';
import { THREE } from '../ext/three.js';
const V0 = new THREE.Vector3(0,0,0);
@ -525,7 +515,7 @@ function platformDelete(widget, defer) {
api.event.emit('widget.delete', widget);
return;
}
kiri.client.clear(widget);
api.client.clear(widget);
api.widgets.remove(widget);
api.selection.remove(widget);
Widget.Groups.remove(widget);
@ -719,12 +709,12 @@ function platformLayout() {
mp = [sz.x, sz.y],
ms = [mp[0] / 2, mp[1] / 2],
c = Widget.Groups.blocks().sort(),
p = new kiri.Pack(ms[0], ms[1], gap).fit(c);
p = new Packer(ms[0], ms[1], gap).fit(c);
while (!p.packed) {
ms[0] *= 1.1;
ms[1] *= 1.1;
p = new kiri.Pack(ms[0], ms[1], gap).fit(c);
p = new Packer(ms[0], ms[1], gap).fit(c);
}
for (i = 0; i < c.length; i++) {
@ -809,7 +799,7 @@ function platformLoadFiles(files, group) {
if (api.conf.get().controller.devel) {
api.event.emit('cam.parse.gerber', { data: text });
} else {
kiri.client.gerber2mesh(text, progress => {
api.client.gerber2mesh(text, progress => {
api.show.progress(progress, "converting");
}, vertices => {
api.show.progress(0);
@ -921,7 +911,7 @@ function fitDeviceToWidgets() {
}
// extend API (api.platform)
const platform = Object.assign(api.platform, {
export const platform = {
fit: fitDeviceToWidgets,
add: platformAdd,
changed: platformChanged,
@ -950,6 +940,4 @@ const platform = Object.assign(api.platform, {
show_volume: space.platform.showVolume,
top_z() { return topZ },
clear() { api.space.clear(); api.space.save(true) }
});
});
};

View file

@ -1,19 +1,13 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
import { arcToPath } from '../geo/paths.js';
import { consts } from './consts.js';
import { newPoint } from '../geo/point.js';
import { util } from '../geo/base.js';
// dep: geo.base
// dep: geo.point
// dep: geo.polygon
// dep: geo.paths
// dep: kiri.consts
gapp.register("kiri.print", [], (root, evets) => {
const { base, kiri } = self;
const { paths, util, newPoint } = base;
const { arcToPath } = paths;
const { numOrDefault } = util;
const { beltfact } = kiri.consts;
const { beltfact } = consts;
const XAXIS = new THREE.Vector3(1,0,0);
const DEG2RAD = Math.PI / 180;
@ -463,10 +457,10 @@ class Print {
let arcPoints = arcToPath( prevPoint, point, 64,{ clockwise:g2,center}) ?? []
let emit = g2 ? 2 : 3;
// console.log("clone point",structuredClone({point,prevPoint,center,arcPoints,emit}));
// console.log("pointer point",{point,prevPoint,center,arcPoints,emit});
outputPoint(point,prevPoint,emit,{center,arcPoints});
// scope.addOutput(seq, point, emit, pos.F, tool,{center,arcPoints});
}
@ -680,9 +674,7 @@ function newPrint(settings, widgets, id) {
return new Print(settings, widgets, id);
};
gapp.overlay(kiri, {
export {
Print,
newPrint
});
});
};

View file

@ -1,35 +1,24 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
import { Layers } from './layers.js';
import { newPoint } from '../geo/point.js';
import { newPolygon } from '../geo/polygon.js';
import { newSlopeFromAngle } from '../geo/slope.js';
/*
* uses `layers.js` to convert paths (usually preview) into primordial geometries.
* the input is based on an array (layers) of arrays containing `Output` objects
*/
// dep: geo.base
// dep: geo.point
// dep: geo.polygon
gapp.register("kiri.render", [], (root, exports) => {
const { base, kiri } = root;
const { config, util, newPolygon } = base;
const hsV = 0.9;
const XAXIS = new THREE.Vector3(1,0,0);
const DEG2RAD = Math.PI / 180;
exports({
path,
is_dark,
rate_to_color
});
function worker() {
return self.kiri_worker.current;
}
function is_cam() {
return root.worker.print.settings.mode === 'CAM';
return worker().print.settings.mode === 'CAM';
}
function is_dark() {
return root.worker.print.settings.controller.dark ? true : false;
return worker().print.settings.controller.dark ? true : false;
};
function rate_to_color(rate, max) {
@ -44,17 +33,17 @@ function rate_to_color(rate, max) {
}
};
/**
* Generate visual representation of a gcode program.
* @param {Output[][]} levels - Array of arrays containing `Output` objects.
* @param {function} update - Called with a completion percentage and the rendered layer.
* @param {{tools: Object, flat: Boolean, thin: Boolean, speed: Boolean, lineWidth: Number, toolMode: Boolean, z: Number, action: String, other: String}} [opts] - Optional parameters.
* @returns {Promise.kiri.Layers[]} - Array of layers.
*/
/**
* Generate visual representation of a gcode program.
* @param {Output[][]} levels - Array of arrays containing `Output` objects.
* @param {function} update - Called with a completion percentage and the rendered layer.
* @param {{tools: Object, flat: Boolean, thin: Boolean, speed: Boolean, lineWidth: Number, toolMode: Boolean, z: Number, action: String, other: String}} [opts] - Optional parameters.
* @returns {Promise.kiri.Layers[]} - Array of layers.
*/
async function path(levels, update, opts = {}) {
levels = levels.filter(level => level.length);
if (levels.length === 0) {
self.worker.print.maxSpeed = 0;
worker().print.maxSpeed = 0;
return [];
}
@ -107,10 +96,11 @@ async function path(levels, update, opts = {}) {
// }).reduce((a, v) => Math.max(a, v)) + 1;
// for reporting
self.worker.print.minSpeed = minspd;
self.worker.print.maxSpeed = maxspd;
self.worker.print.thinColor = thin;
self.worker.print.flatColor = flat;
let print = worker().print;
print.minSpeed = minspd;
print.maxSpeed = maxspd;
print.thinColor = thin;
print.flatColor = flat;
let lastTool = null;
let lastEnd = null;
@ -138,7 +128,8 @@ async function path(levels, update, opts = {}) {
const engages = [];
const lasers = [];
const sparks = [];
const output = new kiri.Layers();
const output = new Layers();
layers.push(output);
const pushPrint = (toolid, poly) => {
@ -172,8 +163,8 @@ async function path(levels, update, opts = {}) {
let p2 = new THREE.Vector3(point.x, point.y, point.z)
.applyAxisAngle(XAXIS, point.a * DEG2RAD);
// reconstruct point point for display without A axis
outPoint = base.newPoint(p2.x, p2.y, p2.z);
// let sp = base.newPoint(outPoint.x * 1.1, outPoint.y * 1.1, outPoint.z * 1.1);
outPoint = newPoint(p2.x, p2.y, p2.z);
// let sp = newPoint(outPoint.x * 1.1, outPoint.y * 1.1, outPoint.z * 1.1);
// sparks.push(outPoint, sp);
}
if (out.tool !== lastTool) {
@ -321,8 +312,8 @@ async function path(levels, update, opts = {}) {
.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 s1 = newSlopeFromAngle(slope.angle + 20);
const s2 = newSlopeFromAngle(slope.angle - 20);
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);
@ -543,4 +534,14 @@ function color4(rgb, inc, seg) {
}
}
});
export const render = {
path,
is_dark,
rate_to_color
};
export {
path,
is_dark,
rate_to_color
};

View file

@ -1,16 +1,8 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: moto.space
// dep: kiri.api
// dep: kiri.consts
// dep: kiri.utils
gapp.register("kiri.selection", (root, exports) => {
const { kiri, moto, noop } = self;
const { api, consts, utils } = kiri;
const { space } = moto;
import { api } from './api.js';
import { space } from '../moto/space.js';
import { THREE } from '../ext/three.js';
const selectedMeshes = [];
@ -296,7 +288,7 @@ function setDisabled(bool) {
}
// extend API (api.selection)
const selection = Object.assign(api.selection, {
export const selection = {
move,
merge,
scale,
@ -320,6 +312,4 @@ const selection = Object.assign(api.selection, {
disable() { setDisabled(true) },
opacity() { api.widgets.opacity(...arguments) },
meshes() { return selectedMeshes.slice() },
});
});
};

View file

@ -1,23 +1,19 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
import { $, h } from '../moto/webui.js';
import { api } from './api.js';
import { conf } from './conf.js';
import { codec } from './codec.js';
import { consts } from './consts.js';
import { space } from '../moto/space.js';
import { local } from '../data/local.js';
import { utils } from './utils.js';
import { version } from '../moto/license.js';
// dep: kiri.api
// dep: kiri.conf
// dep: kiri.utils
// dep: moto.space
// dep: data.local
// use: kiri.widgets
// use: ext.base64
gapp.register("kiri.settings", (root, exports) => {
const { data, kiri, moto, noop } = self;
const { api, conf, consts, utils } = kiri;
const { space } = moto;
const { local } = data;
const { clone } = Object;
const { areEqual, ls2o, js2o } = utils;
const { COLOR } = consts;
const { clone } = Object;
const localFilterKey ='kiri-gcode-filters';
const localFilters = js2o(local.getItem(localFilterKey)) || [];
@ -506,7 +502,7 @@ function settingsExport(opts = {}) {
const widgets = api.widgets.all();
const note = opts.node || undefined;
const shot = opts.work || opts.screen ? space.screenshot() : undefined;
const work = opts.work ? kiri.codec.encode(widgets,{_json_:true}) : undefined;
const work = opts.work ? codec.encode(widgets,{_json_:true}) : undefined;
const view = opts.work ? space.view.save() : undefined;
const setn = Object.clone(settings);
// stuff in legacy annotations for re-import
@ -515,7 +511,7 @@ function settingsExport(opts = {}) {
}
const xprt = {
settings: setn,
version: kiri.version,
version: version,
screen: shot,
space: space.info,
note: note,
@ -600,7 +596,7 @@ function settingsImport(data, ask) {
work.type = 100;
}
}
kiri.codec.decode(data.work).forEach(widget => {
codec.decode(data.work).forEach(widget => {
api.platform.add(widget, 0, true, true);
});
if (data.view) {
@ -761,7 +757,7 @@ function setEnableWASM(bool) {
}
// extend API (api.conf)
Object.assign(api.conf, {
const apiConf = {
dbo: () => { return ls2o('ws-settings') },
get: getSettings,
put: putSettings,
@ -777,10 +773,10 @@ Object.assign(api.conf, {
restore: restoreSettings,
export: settingsExport,
import: settingsImport,
});
};
// extend API (api.settings)
Object.assign(api.settings, {
const apiSet = {
get: getSettings,
import: settingsImport,
import_zip: settingsImportZip,
@ -796,6 +792,16 @@ Object.assign(api.settings, {
async put() {},
status: false
}
});
};
});
export default {
conf: apiConf,
set: apiSet,
settings: apiSet
};
export {
apiConf as conf,
apiSet as set,
apiSet as settings
};

View file

@ -1,14 +1,8 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: geo.base
// dep: geo.polygons
gapp.register("kiri.slice", [], (root, exports) => {
const { base, kiri } = root;
const POLY = base.polygons;
import { base } from '../geo/base.js';
import { Layers } from './layers.js';
import { polygons as POLY } from '../geo/polygons.js';
let tracker;
@ -41,7 +35,7 @@ class Slice {
*/
output() {
if (this.layers) return this.layers;
let layers = this.layers = new kiri.Layers();
let layers = this.layers = new Layers();
if (tracker) {
layers.setRotation(-tracker.rotation || 0);
}
@ -251,12 +245,10 @@ function newSlice(z, view) {
return new Slice(z, view);
}
gapp.overlay(kiri, {
export {
Top,
Slice,
newTop,
newSlice,
setSliceTracker
});
});
};

View file

@ -1,15 +1,9 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
gapp.register("kiri.stack", [], (root, exports) => {
const { kiri } = root;
/*
* converts `layers.js` output data structures into three.js meshes for display
*/
class Stack {
export class Stack {
constructor(view, freeMem, shiny) {
this._view = view;
this.view = view.newGroup();
@ -245,8 +239,6 @@ class Stack {
}
}
kiri.Stack = Stack;
let shininess = 15,
specular = 0x444444,
emissive = 0x101010,
@ -301,5 +293,3 @@ function createLambertMaterial(color, flat) {
side: flat ? THREE.DoubleSide : THREE.FrontSide
});
}
});

View file

@ -1,13 +1,8 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: kiri.stack
// use: kiri.api
// use: kiri.ui
gapp.register("kiri.stacks", [], (root, exports) => {
const { kiri } = root;
import { $ } from '../moto/webui.js';
import { api } from './api.js';
import { Stack } from './stack.js';
let freeMem = true,
stacks = {},
@ -18,7 +13,7 @@ let freeMem = true,
function init() {
labels = $("layers");
API = kiri.api,
API = api,
UC = API.uc,
UI = API.ui;
}
@ -80,7 +75,7 @@ function create(name, view) {
}
const stack = stacks[name] = {
layers: [ ],
obj: new kiri.Stack(view, freeMem, kiri.api.conf.get().controller.shiny),
obj: new Stack(view, freeMem, api.conf.get().controller.shiny),
add: function(layers) {
let lmap = layers.layers;
let map = stack.obj.addLayers(layers);
@ -93,9 +88,9 @@ function create(name, view) {
mat.visible = ctrl.toggle.checked;
});
if (ctrl.toggle.checked) {
kiri.api.event.emit("stack.show", label);
api.event.emit("stack.show", label);
} else {
kiri.api.event.emit("stack.hide", label)
api.event.emit("stack.hide", label)
}
})
};
@ -155,7 +150,7 @@ function setFraction(frac) {
});
}
kiri.stacks = {
export default {
clear,
create,
rotate,
@ -170,4 +165,17 @@ kiri.stacks = {
setFreeMem
};
});
export {
clear,
create,
rotate,
remove,
getStack,
getStacks,
getRange,
setRange,
getLabels,
setVisible,
setFraction,
setFreeMem
};

View file

@ -1,20 +1,12 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: moto.broker
// dep: kiri.api
// dep: kiri.utils
gapp.register("kiri.stats", [], (root, exports) => {
const { data, kiri, gapp } = root;
const { broker } = gapp;
const { api, utils } = kiri;
const { js2o, o2js } = utils;
import { local } from '../data/local.js';
import { broker } from '../moto/broker.js';
import { js2o, o2js } from './utils.js';
class Stats {
constructor(db) {
this.db = db || data.local;
this.db = db || local;
this.obj = js2o(this.db['stats'] || '{}');
let o = this.obj, k;
for (k in o) {
@ -56,6 +48,6 @@ class Stats {
}
}
kiri.stats = new Stats();
export const stats = new Stats();
});
export { stats as Stats };

View file

@ -1,12 +1,10 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
// dep: add.three
// dep: kiri.api
gapp.register("kiri.tools", (root, exports) => {
import { api } from './api.js';
import { THREE } from '../ext/three.js';
const { Vector3, Quaternion } = THREE;
const { kiri, moto } = root;
const { api } = kiri;
const XAXIS = new THREE.Vector3(1,0,0);
const ZAXIS = new THREE.Vector3(0,0,1);
@ -164,4 +162,5 @@ api.event.on('mouse.hover.up', (ev) => {
endIt();
});
});
export { onLayFlatSelect, onFaceUpSelect, startIt, endIt, cleanup, scale, onDone };

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,6 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
gapp.register("kiri.utils", [], (root, exports) => {
import { local as dataLocal } from '../data/local.js';
function parseOpt(ov) {
let opt = {}, kv, kva;
@ -46,7 +44,7 @@ function js2o(s,def) {
function ls2o(key,def) {
// defer ref b/c it may run in a worker
return js2o(root.data.local.getItem(key),def);
return js2o(dataLocal.getItem(key),def);
}
// split 24 bit color into [ r, g, b ]
@ -99,11 +97,14 @@ function trackFn(fn, name) {
}
}
exports({
function noop() {}
export {
trackFn,
areEqual,
parseOpt,
encodeOpt,
noop,
ajax,
o2js,
js2o,
@ -111,6 +112,19 @@ exports({
avgc,
rgb,
a2c
});
};
});
export let utils = {
trackFn,
areEqual,
parseOpt,
encodeOpt,
noop,
ajax,
o2js,
js2o,
ls2o,
avgc,
rgb,
a2c
};

View file

@ -1,23 +1,11 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// dep: geo.base
// dep: geo.point
// dep: geo.points
// dep: geo.polygons
// dep: kiri.utils
// use: kiri.codec
// use: mesh.util
gapp.register("kiri.widget", [], (root, exports) => {
const { base, kiri } = root;
const { api, driver, utils } = kiri;
const { util, polygons } = base;
const { Mesh, newPoint, verticesToPoints } = base;
const { inRange, time } = util;
const { avgc, trackFn } = utils;
import { base } from '../geo/base.js';
import { avgc } from './utils.js';
import { verticesToPoints } from '../geo/points.js';
import { util as mesh_util } from '../mesh/util.js';
const { inRange, time } = base.util;
const solid_opacity = 1.0;
const groups = [];
@ -28,12 +16,14 @@ let nextId = 0;
function newWidget(id,group) { return new Widget(id,group) }
function catalog() { return kiri.catalog }
function catalog() { return self.kiri_catalog };
function index() { return catalog().index }
function index() { return self.kiri_catalog.index }
class Widget {
constructor(id, group) {
this.api = self.kiri_api;
this.id = id || Date.now().toString(36)+(nextId++);
this.grouped = group ? true : false;
this.group = group || [];
@ -347,7 +337,7 @@ class Widget {
}
selectFaces(faces) {
let groups = mesh.util.facesToGroups(faces || []);
let groups = mesh_util.facesToGroups(faces || []);
let geo = this.mesh.geometry;
geo.clearGroups();
for (let group of groups) {
@ -503,8 +493,8 @@ class Widget {
w._move(x, y, z, abs);
});
// allow for use in engine / cli
if ((x || y || z) && api && api.event) {
api.event.emit('widget.move', {widget: this, pos: {x, y, z}, abs});
if ((x || y || z) && this.api && this.api.event) {
this.api.event.emit('widget.move', {widget: this, pos: {x, y, z}, abs});
}
}
@ -555,8 +545,8 @@ class Widget {
w._scale(x, y, z);
});
this.center(false);
if (api && api.event) {
api.event.emit('widget.scale', {widget: this, x, y, z});
if (this.api && this.api.event) {
this.api.event.emit('widget.scale', {widget: this, x, y, z});
}
}
@ -586,8 +576,8 @@ class Widget {
if (this.outline) {
this.setEdges(true);
}
if ((x || y || z) && api && api.event) {
api.event.emit('widget.rotate', {widget: this, x, y, z});
if ((x || y || z) && this.api && this.api.event) {
this.api.event.emit('widget.rotate', {widget: this, x, y, z});
}
}
@ -630,8 +620,8 @@ class Widget {
w._mirror();
});
this.center();
if (api && api.event) {
api.event.emit('widget.mirror', {widget: this});
if (this.api && this.api.event) {
this.api.event.emit('widget.mirror', {widget: this});
}
}
@ -758,113 +748,21 @@ class Widget {
return this;
}
/**
* processes points into facets, then into slices
*
* once upon a time there were multiple slicers. this was the fastest in most cases.
* lines are added to all the buckets they cross. then buckets are processed in order.
* buckets are contiguous ranges of z slicers. the advantage of this method is that
* as long as a large percentage of lines do not cross large z distances, this reduces
* the number of lines each slice has to consider thus improving speed.
*
* @params {Object} settings
* @params {Function} [ondone]
* @params {Function} [onupdate]
*/
slice(settings, ondone, onupdate) {
let widget = this;
let startTime = time();
widget.settings = settings;
widget.clearSlices();
onupdate(0.0001, "slicing");
if (kiri.client && !widget.inWorker) {
// store slicing visuals
widget.stack = kiri.stacks.create(widget.id, widget.mesh);
// compensate for zcut (widget moved through floor)
widget.stack.obj.view.position.z = widget.track.zcut || 0;
// in case result of slice is nothing, do not preserve previous
widget.slices = []
// executed from kiri.js
kiri.client.slice(settings, this, function(reply) {
if (reply.alert) {
onupdate(null, null, reply.alert);
}
if (reply.update) {
onupdate(reply.update, reply.updateStatus);
}
if (reply.send_start) {
widget.xfer = {start: reply.send_start};
}
if (reply.stats) {
widget.stats = reply.stats;
}
if (reply.send_end) {
widget.stats.load_time = widget.xfer.start - reply.send_end;
}
if (reply.slice) {
widget.slices.push(kiri.codec.decode(reply.slice, {mesh:widget.mesh}));
}
if (reply.done) {
ondone(true);
}
if (reply.error) {
ondone(false, reply.error);
}
});
}
if (kiri.server) {
// executed from kiri-worker.js
let catchdone = function(error) {
if (error) {
return ondone(error);
}
onupdate(1.0, "transfer");
widget.stats.slice_time = time() - startTime;
ondone();
};
let catchupdate = function(progress, message, alert) {
onupdate(progress, message, alert);
};
let drv = driver[settings.mode.toUpperCase()];
if (drv) {
let promise = drv.slice(settings, widget, catchupdate, catchdone);
if (promise) promise.catch(error => ondone(error));
} else {
console.log('invalid mode: '+settings.mode);
ondone('invalid mode: '+settings.mode);
}
}
// discard point cache
widget.points = undefined;
}
/**
* render to provided stack
*/
render(stack) {
const mark = Date.now();
if (this.slices)
this.slices.forEach(slice => {
for (let slice of this.slices || []) {
if (slice.layers) {
stack.add(slice.layers);
}
});
}
return Date.now() - mark;
}
setEdges(set) {
if (!(api && api.conf)) {
if (!(this.api && this.api.conf)) {
// missing api features in engine mode
return;
}
@ -878,8 +776,8 @@ class Widget {
}
if (set) {
let dark = api.space.is_dark();
let angle = api.conf.get().controller.edgeangle || 20;
let dark = this.api.space.is_dark();
let angle = this.api.conf.get().controller.edgeangle || 20;
let edges = new THREE.EdgesGeometry(mesh.geometry, angle);
let material = new THREE.LineBasicMaterial({ color: 0 });
this.outline = new THREE.LineSegments(edges, material);
@ -889,7 +787,7 @@ class Widget {
}
setWireframe(set, color, opacity) {
if (!(api && api.conf)) {
if (!(this.api && this.api.conf)) {
// missing api features in engine mode
return;
}
@ -901,7 +799,7 @@ class Widget {
this.wire = null;
}
if (set) {
let dark = api.space.is_dark();
let dark = this.api.space.is_dark();
let mat = new THREE.MeshBasicMaterial({
wireframe: true,
color: dark ? 0xaaaaaa : 0,
@ -911,7 +809,7 @@ class Widget {
let wire = widget.wire = new THREE.Mesh(mesh.geometry.shallowClone(), mat);
mesh.add(wire);
}
if (api.view.is_arrange()) {
if (this.api.view.is_arrange()) {
this.setColor(this.color);
} else {
this.setColor(0x888888,undefined,false);
@ -1066,7 +964,4 @@ Widget.deleteFromState = function(id,ondone) {
index().remove('ws-save-'+id, ondone);
};
kiri.Widget = Widget;
kiri.newWidget = newWidget;
});
export { Widget, newWidget };

View file

@ -1,14 +1,9 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
// use: load.file
// use: kiri.selection
// use: kiri.platform
gapp.register("kiri.widgets", (root, exports) => {
const { data, kiri, moto, noop } = root;
const { api, consts, utils, newWidget, Widget } = kiri;
import { $ } from '../moto/webui.js';
import { api } from './api.js';
import { load } from '../load/file.js';
import { Widget, newWidget } from './widget.js';
let WIDGETS = [];
@ -36,7 +31,7 @@ function rename(sel) {
return;
}
let widget = widgets[0];
kiri.ui.prompt("new widget name", widget.meta.file || "no name").then(newname => {
api.uc.prompt("new widget name", widget.meta.file || "no name").then(newname => {
if (newname) {
widget.meta.file = newname;
api.platform.changed();
@ -89,7 +84,7 @@ function meshes() {
function opacity(value) {
api.widgets.each(w => w.setOpacity(value));
moto.space.update();
api.space.update();
}
function setIndexed(value) {
@ -101,7 +96,7 @@ function setAxisIndex(value) {
}
// extend API (api.widgets)
const widgets = Object.assign(api.widgets, {
export const widgets = {
load: Widget.loadFromCatalog,
new: newWidget,
map,
@ -120,6 +115,4 @@ const widgets = Object.assign(api.widgets, {
each(fn) { WIDGETS.slice().forEach(widget => fn(widget)) },
for(fn) { widgets.each(fn) },
forid(id) { return WIDGETS.filter(w => w.id === id)[0] }
});
});
};