2021-09-21 12:23:36 -04:00
|
|
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-06-03 22:39:30 -04:00
|
|
|
"use strict";
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
(function () {
|
2018-01-10 20:04:51 -05:00
|
|
|
|
2022-02-18 13:27:26 -05:00
|
|
|
const { base, data, load, kiri, moto, noop } = self;
|
2022-02-18 10:52:49 -05:00
|
|
|
const { api, consts, lang, Widget, newWidget, utils } = kiri;
|
2022-02-18 18:42:08 -05:00
|
|
|
const { areEqual, parseOpt, encodeOpt, ajax, o2js, js2o, ls2o } = utils;
|
|
|
|
|
const { feature, platform, selection, settings } = api;
|
2022-02-18 10:52:49 -05:00
|
|
|
const { COLOR, MODES, PMODES, VIEWS } = consts;
|
2022-02-17 14:40:51 -05:00
|
|
|
|
|
|
|
|
const LANG = lang.current,
|
2020-03-08 20:58:26 -04:00
|
|
|
WIN = self.window,
|
|
|
|
|
DOC = self.document,
|
|
|
|
|
LOC = self.location,
|
|
|
|
|
HOST = LOC.host.split(':'),
|
|
|
|
|
SETUP = parseOpt(LOC.search.substring(1)),
|
|
|
|
|
SECURE = isSecure(LOC.protocol),
|
2020-04-17 09:43:25 -04:00
|
|
|
LOCAL = self.debug && !SETUP.remote,
|
2022-02-17 14:40:51 -05:00
|
|
|
EVENT = kiri.broker = gapp.broker,
|
2022-02-18 10:52:49 -05:00
|
|
|
SDB = data.local,
|
2022-02-17 14:40:51 -05:00
|
|
|
SPACE = kiri.space = moto.Space,
|
2022-02-18 11:30:00 -05:00
|
|
|
FILES = kiri.catalog = kiri.openFiles(new data.Index(SETUP.d ? SETUP.d[0] : 'kiri')),
|
2017-04-18 17:09:33 -04:00
|
|
|
STATS = new Stats(SDB),
|
2022-02-17 14:40:51 -05:00
|
|
|
CONF = kiri.conf,
|
|
|
|
|
clone = Object.clone;
|
|
|
|
|
|
2022-02-18 18:42:08 -05:00
|
|
|
let UI = {},
|
|
|
|
|
UC = kiri.ui.prefix('kiri').inputAction(api.conf.update),
|
2017-04-18 17:09:33 -04:00
|
|
|
MODE = MODES.FDM,
|
2022-02-17 14:40:51 -05:00
|
|
|
STACKS = kiri.stacks,
|
2020-06-11 22:11:19 -04:00
|
|
|
DRIVER = undefined,
|
2017-04-18 17:09:33 -04:00
|
|
|
viewMode = VIEWS.ARRANGE,
|
|
|
|
|
local = SETUP.local,
|
2020-10-11 21:09:37 -04:00
|
|
|
busy = 0,
|
2020-03-17 10:44:42 -04:00
|
|
|
showFavorites = SDB.getItem('dev-favorites') === 'true',
|
2020-04-07 19:56:30 -04:00
|
|
|
alerts = [],
|
2020-12-02 10:00:41 -05:00
|
|
|
saveTimer = null,
|
2022-02-17 17:55:26 -05:00
|
|
|
version = kiri.version = gapp.version;
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-03-10 14:23:42 -04:00
|
|
|
// add show() to catalog for API
|
2022-02-18 11:30:00 -05:00
|
|
|
FILES.show = showCatalog;
|
2020-03-10 14:23:42 -04:00
|
|
|
|
2021-12-26 13:09:07 -05:00
|
|
|
// patch broker for api backward compatibility
|
|
|
|
|
EVENT.on = (topic, listener) => {
|
|
|
|
|
EVENT.subscribe(topic, listener);
|
|
|
|
|
return EVENT;
|
|
|
|
|
};
|
|
|
|
|
|
2022-02-17 14:40:51 -05:00
|
|
|
// augment api
|
|
|
|
|
Object.assign(api, {
|
2020-03-09 11:02:09 -04:00
|
|
|
ui: UI,
|
|
|
|
|
uc: UC,
|
2022-02-17 14:40:51 -05:00
|
|
|
focus: noop,
|
2020-03-09 11:02:09 -04:00
|
|
|
stats: STATS,
|
2022-02-18 11:30:00 -05:00
|
|
|
catalog: FILES,
|
2020-10-11 21:09:37 -04:00
|
|
|
busy: {
|
2022-02-17 14:40:51 -05:00
|
|
|
val() { return busy },
|
|
|
|
|
inc() { kiri.api.event.emit("busy", ++busy) },
|
|
|
|
|
dec() { kiri.api.event.emit("busy", --busy) }
|
2020-10-11 21:09:37 -04:00
|
|
|
},
|
2020-03-09 11:02:09 -04:00
|
|
|
const: {
|
|
|
|
|
LANG,
|
|
|
|
|
LOCAL,
|
2020-06-10 18:56:55 -04:00
|
|
|
SETUP,
|
2020-11-09 01:42:17 -05:00
|
|
|
SECURE,
|
|
|
|
|
STACKS,
|
2020-03-09 11:02:09 -04:00
|
|
|
},
|
|
|
|
|
device: {
|
2021-02-15 11:05:47 -05:00
|
|
|
code: currentDeviceCode,
|
2020-03-17 16:32:43 -04:00
|
|
|
get: currentDeviceName,
|
2020-12-02 10:00:41 -05:00
|
|
|
set: noop, // set during init
|
|
|
|
|
clone: noop // set during init
|
2020-03-09 11:02:09 -04:00
|
|
|
},
|
|
|
|
|
dialog: {
|
2020-06-06 11:17:04 -04:00
|
|
|
show: showModal,
|
2022-02-18 18:42:08 -05:00
|
|
|
hide: hideModal,
|
|
|
|
|
update_process_list: updateProcessList
|
2020-03-09 11:02:09 -04:00
|
|
|
},
|
|
|
|
|
help: {
|
|
|
|
|
show: showHelp,
|
|
|
|
|
file: showHelpFile
|
|
|
|
|
},
|
|
|
|
|
event: {
|
2022-02-17 14:40:51 -05:00
|
|
|
on(t,l) { return EVENT.on(t,l) },
|
|
|
|
|
emit(t,m,o) { return EVENT.publish(t,m,o) },
|
|
|
|
|
bind(t,m,o) { return EVENT.bind(t,m,o) },
|
2020-03-09 11:02:09 -04:00
|
|
|
import: loadFile,
|
|
|
|
|
alerts: updateAlerts,
|
|
|
|
|
settings: triggerSettingsEvent
|
|
|
|
|
},
|
2021-03-01 00:22:07 -05:00
|
|
|
group: {
|
|
|
|
|
merge: groupMerge,
|
|
|
|
|
split: groupSplit,
|
|
|
|
|
},
|
2020-03-09 11:12:11 -04:00
|
|
|
hide: {
|
2022-02-17 14:40:51 -05:00
|
|
|
alert(rec,recs) { alert2cancel(rec,recs) },
|
|
|
|
|
import: noop,
|
2020-11-24 00:48:45 -05:00
|
|
|
slider: hideSlider
|
2020-03-09 11:12:11 -04:00
|
|
|
},
|
2022-02-17 21:52:54 -05:00
|
|
|
image: {
|
|
|
|
|
dialog: loadImageDialog,
|
|
|
|
|
convert: loadImageConvert
|
|
|
|
|
},
|
2022-02-17 14:40:51 -05:00
|
|
|
language: kiri.lang,
|
2020-03-09 11:02:09 -04:00
|
|
|
modal: {
|
|
|
|
|
show: showModal,
|
|
|
|
|
hide: hideModal,
|
|
|
|
|
visible: modalShowing
|
|
|
|
|
},
|
|
|
|
|
mode: {
|
2022-02-17 14:40:51 -05:00
|
|
|
get_id() { return MODE },
|
2020-03-09 11:02:09 -04:00
|
|
|
get_lower: getModeLower,
|
|
|
|
|
get: getMode,
|
|
|
|
|
set: setMode,
|
2020-04-17 09:43:25 -04:00
|
|
|
switch: switchMode,
|
2022-02-18 14:56:59 -05:00
|
|
|
set_expert: noop,
|
|
|
|
|
is_fdm() { return MODE === MODES.FDM },
|
|
|
|
|
is_cam() { return MODE === MODES.CAM },
|
|
|
|
|
is_sla() { return MODE === MODES.SLA },
|
|
|
|
|
is_laser() { return MODE === MODES.LASER },
|
2020-03-09 11:02:09 -04:00
|
|
|
},
|
|
|
|
|
probe: {
|
2022-02-17 14:40:51 -05:00
|
|
|
live: "https://live.grid.space",
|
|
|
|
|
grid: noop,
|
|
|
|
|
local: noop
|
2020-03-09 11:02:09 -04:00
|
|
|
},
|
2021-02-15 11:05:47 -05:00
|
|
|
process: {
|
|
|
|
|
code: currentProcessCode,
|
|
|
|
|
get: currentProcessName
|
|
|
|
|
},
|
2020-03-09 11:02:09 -04:00
|
|
|
show: {
|
|
|
|
|
alert: alert2,
|
2020-12-02 10:00:41 -05:00
|
|
|
devices: noop, // set during init
|
2020-03-09 11:02:09 -04:00
|
|
|
progress: setProgress,
|
|
|
|
|
controls: setControlsVisible,
|
|
|
|
|
favorites: getShowFavorites,
|
|
|
|
|
slices: showSlices,
|
2020-03-09 18:08:08 -04:00
|
|
|
layer: setVisibleLayer,
|
2020-03-09 11:12:11 -04:00
|
|
|
local: showLocal,
|
|
|
|
|
import: function() { UI.import.style.display = '' }
|
2020-03-09 11:02:09 -04:00
|
|
|
},
|
|
|
|
|
space: {
|
2022-02-17 21:52:54 -05:00
|
|
|
reload,
|
|
|
|
|
auto_save,
|
2020-03-09 11:02:09 -04:00
|
|
|
restore: restoreWorkspace,
|
|
|
|
|
clear: clearWorkspace,
|
2021-01-22 10:41:04 -05:00
|
|
|
save: saveWorkspace,
|
2021-10-19 21:58:06 -04:00
|
|
|
set_focus: setFocus,
|
2022-01-23 17:21:20 -05:00
|
|
|
update: SPACE.update,
|
2022-02-18 18:42:08 -05:00
|
|
|
is_dark() { return settings.ctrl().dark }
|
2020-03-09 11:02:09 -04:00
|
|
|
},
|
2020-06-10 18:56:55 -04:00
|
|
|
util: {
|
2020-12-23 14:27:18 -05:00
|
|
|
isSecure,
|
2022-02-18 18:42:08 -05:00
|
|
|
ui2rec() { api.conf.update_from(...arguments) },
|
2021-02-15 12:37:54 -05:00
|
|
|
rec2ui: updateFieldsFromSettings,
|
|
|
|
|
download: downloadBlob,
|
2022-02-17 14:40:51 -05:00
|
|
|
b64enc(obj) { return base64js.fromByteArray(new TextEncoder().encode(JSON.stringify(obj))) },
|
|
|
|
|
b64dec(obj) { return JSON.parse(new TextDecoder().decode(base64js.toByteArray(obj))) }
|
2020-06-10 18:56:55 -04:00
|
|
|
},
|
2020-03-09 11:02:09 -04:00
|
|
|
view: {
|
2022-01-23 17:21:20 -05:00
|
|
|
get() { return viewMode },
|
2022-02-17 14:40:51 -05:00
|
|
|
set() { setViewMode(...arguments) },
|
|
|
|
|
set_arrange() { api.view.set(VIEWS.ARRANGE) },
|
|
|
|
|
set_slice() { api.view.set(VIEWS.SLICE) },
|
|
|
|
|
set_preview() { api.view.set(VIEWS.PREVIEW) },
|
|
|
|
|
is_arrange() { return viewMode === VIEWS.ARRANGE },
|
|
|
|
|
is_slice() { return viewMode === VIEWS.SLICE },
|
|
|
|
|
is_preview() { return viewMode === VIEWS.PREVIEW },
|
2022-02-17 21:52:54 -05:00
|
|
|
hide_slices: hideSlices,
|
|
|
|
|
update_speeds: updateSpeeds,
|
2020-03-09 18:28:58 -04:00
|
|
|
update_fields: updateFields,
|
2022-02-17 21:52:54 -05:00
|
|
|
update_slider: updateSlider,
|
|
|
|
|
update_slider_max: updateSliderMax,
|
2020-11-14 11:12:12 -05:00
|
|
|
snapshot: null,
|
2020-12-06 21:25:31 -05:00
|
|
|
unit_scale: unitScale,
|
2022-02-17 21:52:54 -05:00
|
|
|
wireframe: setWireframe,
|
2020-03-09 11:02:09 -04:00
|
|
|
},
|
2022-02-17 14:40:51 -05:00
|
|
|
work: kiri.work
|
|
|
|
|
});
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2022-02-18 13:53:41 -05:00
|
|
|
function setFocus(sel, point) {
|
2021-04-21 22:30:42 -04:00
|
|
|
if (point) {
|
|
|
|
|
SPACE.platform.setCenter(point.x, point.z, point.y);
|
|
|
|
|
SPACE.view.setFocus(new THREE.Vector3(point.x, point.y, point.z));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-02-18 13:53:41 -05:00
|
|
|
if (sel === undefined) {
|
|
|
|
|
sel = api.widgets.all();
|
2021-01-22 10:41:04 -05:00
|
|
|
} else if (!Array.isArray) {
|
2022-02-18 13:53:41 -05:00
|
|
|
sel = [ sel ];
|
|
|
|
|
} else if (sel.length === 0) {
|
|
|
|
|
sel = api.widgets.all();
|
2021-01-22 10:41:04 -05:00
|
|
|
}
|
|
|
|
|
let pos = { x:0, y:0, z:0 };
|
2022-02-18 13:53:41 -05:00
|
|
|
for (let widget of sel) {
|
2021-01-22 10:41:04 -05:00
|
|
|
pos.x += widget.track.pos.x;
|
|
|
|
|
pos.y += widget.track.pos.y;
|
|
|
|
|
pos.z += widget.track.pos.z;
|
|
|
|
|
}
|
2022-02-18 13:53:41 -05:00
|
|
|
if (sel.length) {
|
|
|
|
|
pos.x /= sel.length;
|
|
|
|
|
pos.y /= sel.length;
|
|
|
|
|
pos.z /= sel.length;
|
2021-01-23 10:20:31 -05:00
|
|
|
}
|
2022-02-17 21:52:54 -05:00
|
|
|
SPACE.platform.setCenter(pos.x, -pos.y, platform.top_z() / 2);
|
|
|
|
|
SPACE.view.setFocus(new THREE.Vector3(pos.x, platform.top_z() / 2, -pos.y));
|
2021-01-22 10:41:04 -05:00
|
|
|
}
|
|
|
|
|
|
2020-05-09 18:19:02 -04:00
|
|
|
function reload() {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('reload');
|
2020-10-11 21:09:37 -04:00
|
|
|
do_reload(100);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function do_reload(time) {
|
|
|
|
|
// allow time for async saves to complete and busy to to to zero
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (busy === 0) {
|
|
|
|
|
LOC.reload();
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`reload deferred on busy=${busy}`);
|
|
|
|
|
do_reload(250);
|
|
|
|
|
}
|
|
|
|
|
}, time || 100);
|
2020-05-09 18:19:02 -04:00
|
|
|
}
|
|
|
|
|
|
2020-11-18 09:11:29 -05:00
|
|
|
function auto_save() {
|
2022-02-18 18:42:08 -05:00
|
|
|
if (!settings.ctrl().autoSave) {
|
2020-11-18 09:11:29 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
clearTimeout(saveTimer);
|
|
|
|
|
saveTimer = setTimeout(() => {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.space.save(true);
|
2020-11-18 09:11:29 -05:00
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-04 17:19:13 -05:00
|
|
|
// frame message api
|
|
|
|
|
WIN.addEventListener('message', msg => {
|
2022-02-02 20:19:28 -05:00
|
|
|
if (!feature.frame) return;
|
2021-01-04 17:19:13 -05:00
|
|
|
let { origin, source, target, data } = msg;
|
|
|
|
|
if (source.window === target.window) return;
|
|
|
|
|
let send = source.window.postMessage;
|
2022-02-17 14:40:51 -05:00
|
|
|
if (data.mode) { api.mode.set(data.mode.toUpperCase()) }
|
|
|
|
|
if (data.view) { api.view.set(VIEWS[data.view.toUpperCase()]) }
|
2022-02-08 21:10:05 -05:00
|
|
|
if (data.function) {
|
|
|
|
|
let cb = data.callback ? (output) => {
|
|
|
|
|
send({event:`${data.function}.done`, data: output});
|
|
|
|
|
} : undefined;
|
2022-02-17 14:40:51 -05:00
|
|
|
api.function[data.function.toLowerCase()](cb);
|
2022-02-08 21:10:05 -05:00
|
|
|
}
|
2021-01-04 17:19:13 -05:00
|
|
|
if (data.event) {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.on(data.event, (evd) => {
|
2021-01-04 17:19:13 -05:00
|
|
|
send({event: data.event, data: evd});
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-02-17 14:40:51 -05:00
|
|
|
if (data.emit) api.event.emit(data.emit, data.message)
|
2021-01-04 20:36:35 -05:00
|
|
|
if (data.get) switch (data.get) {
|
2022-02-18 18:42:08 -05:00
|
|
|
case "mode": send({mode: settings.mode()}); break;
|
|
|
|
|
case "device": send({device: settings.dev()}); break;
|
|
|
|
|
case "process": send({process: settings.proc()}); break;
|
2021-01-04 20:36:35 -05:00
|
|
|
default: send({all: settings}); break;
|
|
|
|
|
|
2021-01-04 17:19:13 -05:00
|
|
|
}
|
2021-01-04 20:36:35 -05:00
|
|
|
if (data.set) switch (data.set) {
|
2021-01-04 17:19:13 -05:00
|
|
|
case "features":
|
|
|
|
|
Object.assign(feature, data.features);
|
|
|
|
|
break;
|
|
|
|
|
case "device":
|
2022-02-18 18:42:08 -05:00
|
|
|
Object.assign(settings.dev(), data.options);
|
|
|
|
|
api.conf.save();
|
2021-01-04 17:19:13 -05:00
|
|
|
break;
|
|
|
|
|
case "process":
|
2022-02-18 18:42:08 -05:00
|
|
|
Object.assign(settings.proc(), data.options);
|
|
|
|
|
api.conf.save();
|
2021-01-04 17:19:13 -05:00
|
|
|
break;
|
|
|
|
|
}
|
2021-01-04 20:36:35 -05:00
|
|
|
if (data.parse) {
|
2022-02-08 21:10:05 -05:00
|
|
|
let type = (data.type || 'stl').toLowerCase();
|
|
|
|
|
let bin = data.parse;
|
|
|
|
|
let widget;
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'stl':
|
|
|
|
|
if (!bin.buffer) bin = new Float32Array(bin).buffer;
|
|
|
|
|
new load.STL().parse(bin, vertices => {
|
|
|
|
|
platform.add(widget = newWidget().loadVertices(vertices));
|
|
|
|
|
send({event: "parsed", data: [ widget.id ]});
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
|
case 'obj':
|
|
|
|
|
// todo
|
|
|
|
|
break;
|
|
|
|
|
case '3mf':
|
|
|
|
|
// todo
|
|
|
|
|
break;
|
|
|
|
|
case 'svg':
|
|
|
|
|
let wid = [];
|
2022-02-17 14:40:51 -05:00
|
|
|
for (let svg of load.SVG.parse(bin)) {
|
2022-02-08 21:10:05 -05:00
|
|
|
if (!(svg && svg.length)) continue;
|
|
|
|
|
platform.add(widget = newWidget().loadVertices(svg.toFloat32()));
|
|
|
|
|
wid.push(widget.id);
|
|
|
|
|
}
|
|
|
|
|
send({event: "parsed", data: wid});
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-01-04 20:36:35 -05:00
|
|
|
}
|
2022-02-08 21:10:05 -05:00
|
|
|
if (data.load) {
|
2022-02-18 12:08:08 -05:00
|
|
|
api.platform.load(data.load, (verts, widget) => {
|
2022-02-08 21:10:05 -05:00
|
|
|
send({event: "loaded", data: [ widget.id ]});
|
|
|
|
|
})
|
|
|
|
|
};
|
2021-01-04 20:36:35 -05:00
|
|
|
if (data.clear) platform.clear();
|
2021-01-04 17:19:13 -05:00
|
|
|
if (data.alert) alert2(data.alert, data.time);
|
|
|
|
|
if (data.progress >= 0) setProgress(data.progress, data.message);
|
|
|
|
|
});
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
/** ******************************************************************
|
|
|
|
|
* Stats accumulator
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
|
|
|
|
function Stats(db) {
|
|
|
|
|
this.db = db;
|
2020-03-07 13:14:22 -05:00
|
|
|
this.obj = js2o(this.db['stats'] || '{}');
|
2020-04-09 14:52:43 -04:00
|
|
|
let o = this.obj, k;
|
2017-04-18 17:09:33 -04:00
|
|
|
for (k in o) {
|
|
|
|
|
if (!o.hasOwnProperty(k)) continue;
|
2020-07-08 12:54:49 -04:00
|
|
|
if (['dn','lo','re'].indexOf(k) >= 0 || k.indexOf('-') > 0 || k.indexOf('_') > 0) {
|
2020-03-07 13:14:22 -05:00
|
|
|
delete o[k];
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
2020-03-07 12:33:26 -05:00
|
|
|
|
|
|
|
|
Stats.prototype.save = function(quiet) {
|
2017-04-18 17:09:33 -04:00
|
|
|
this.db['stats'] = o2js(this.obj);
|
2020-03-07 12:33:26 -05:00
|
|
|
if (!quiet) {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('stats', this.obj);
|
2020-03-07 12:33:26 -05:00
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
return this;
|
|
|
|
|
};
|
2020-03-07 12:33:26 -05:00
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
Stats.prototype.get = function(k) {
|
|
|
|
|
return this.obj[k];
|
2020-03-07 12:33:26 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Stats.prototype.set = function(k,v,quiet) {
|
2017-04-18 17:09:33 -04:00
|
|
|
this.obj[k] = v;
|
2020-03-07 12:33:26 -05:00
|
|
|
this.save(quiet);
|
2017-04-18 17:09:33 -04:00
|
|
|
return this;
|
|
|
|
|
};
|
2020-03-07 12:33:26 -05:00
|
|
|
|
|
|
|
|
Stats.prototype.add = function(k,v,quiet) {
|
2017-04-18 17:09:33 -04:00
|
|
|
this.obj[k] = (this.obj[k] || 0) + (v || 1);
|
2020-03-07 12:33:26 -05:00
|
|
|
this.save(quiet);
|
2017-04-18 17:09:33 -04:00
|
|
|
return this;
|
|
|
|
|
};
|
2020-03-07 12:33:26 -05:00
|
|
|
|
|
|
|
|
Stats.prototype.del = function(k, quiet) {
|
2017-04-18 17:09:33 -04:00
|
|
|
delete this.obj[k];
|
2020-03-07 12:33:26 -05:00
|
|
|
this.save(quiet);
|
2017-04-18 17:09:33 -04:00
|
|
|
return this;
|
2020-03-07 12:33:26 -05:00
|
|
|
};
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-03-07 15:57:45 -05:00
|
|
|
let inits = parseInt(SDB.getItem('kiri-init') || STATS.get('init') || 0) + 1;
|
2020-03-07 14:00:41 -05:00
|
|
|
SDB.setItem('kiri-init', inits);
|
|
|
|
|
|
|
|
|
|
STATS.set('init', inits);
|
2017-04-18 17:09:33 -04:00
|
|
|
STATS.set('kiri', kiri.version);
|
|
|
|
|
|
2020-12-31 23:22:39 -05:00
|
|
|
// remove version from url, preserve other settings
|
|
|
|
|
WIN.history.replaceState({},'','/kiri/' + encodeOpt(SETUP) + LOC.hash);
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
/** ******************************************************************
|
|
|
|
|
* Utility Functions
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
2021-12-09 23:12:35 -05:00
|
|
|
function unitScale() {
|
2022-02-18 18:42:08 -05:00
|
|
|
return MODE === MODES.CAM && settings.ctrl().units === 'in' ? 25.4 : 1;
|
2021-12-09 23:12:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function alert2(message, time) {
|
|
|
|
|
if (message === undefined || message === null) {
|
|
|
|
|
return updateAlerts(true);
|
|
|
|
|
}
|
|
|
|
|
let rec = [message, Date.now(), time, true];
|
|
|
|
|
if (feature.alert_event) {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('alert', rec);
|
2021-12-09 23:12:35 -05:00
|
|
|
} else {
|
|
|
|
|
alerts.push(rec);
|
|
|
|
|
updateAlerts();
|
|
|
|
|
}
|
|
|
|
|
return rec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function alert2cancel(rec,recs) {
|
|
|
|
|
if (Array.isArray(recs)) {
|
|
|
|
|
for (let r of recs) {
|
|
|
|
|
alert2cancel(r);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (feature.alert_event) {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('alert.cancel', rec);
|
2021-12-09 23:12:35 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (Array.isArray(rec)) {
|
|
|
|
|
rec[3] = false;
|
|
|
|
|
updateAlerts();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateAlerts(clear) {
|
|
|
|
|
if (clear) {
|
|
|
|
|
alerts = [];
|
|
|
|
|
}
|
|
|
|
|
let now = Date.now();
|
|
|
|
|
// filter out by age and active flag
|
|
|
|
|
alerts = alerts.filter(alert => {
|
|
|
|
|
return alert[3] && (now - alert[1]) < ((alert[2] || 5) * 1000);
|
|
|
|
|
});
|
|
|
|
|
// limit to 5 showing
|
|
|
|
|
while (alerts.length > 5) {
|
|
|
|
|
alerts.shift();
|
|
|
|
|
}
|
|
|
|
|
// return if called before UI configured
|
|
|
|
|
if (!UI.alert) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (alerts.length > 0) {
|
|
|
|
|
UI.alert.text.innerHTML = alerts.map(v => ['<p>',v[0],'</p>'].join('')).join('');
|
|
|
|
|
UI.alert.dialog.style.display = 'flex';
|
|
|
|
|
} else {
|
|
|
|
|
UI.alert.dialog.style.display = 'none';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getShowFavorites(bool) {
|
|
|
|
|
if (bool !== undefined) {
|
|
|
|
|
SDB.setItem('dev-favorites', bool);
|
|
|
|
|
showFavorites = bool;
|
|
|
|
|
return bool;
|
|
|
|
|
}
|
|
|
|
|
return showFavorites;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function triggerSettingsEvent() {
|
2022-02-18 21:25:25 -05:00
|
|
|
api.event.emit('settings', settings.get());
|
2021-12-09 23:12:35 -05:00
|
|
|
}
|
2020-03-07 12:33:26 -05:00
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
function isSecure(proto) {
|
|
|
|
|
return proto.toLowerCase().indexOf("https") === 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setProgress(value, msg) {
|
|
|
|
|
if (value) {
|
2022-02-17 14:40:51 -05:00
|
|
|
value = (value * 100).round(4);
|
2017-04-18 17:09:33 -04:00
|
|
|
UI.loading.display = 'block';
|
|
|
|
|
UI.progress.width = value+'%';
|
|
|
|
|
if (msg) UI.prostatus.innerHTML = msg;
|
|
|
|
|
} else {
|
|
|
|
|
UI.loading.display = 'none';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function bound(v,min,max) {
|
|
|
|
|
return Math.max(min,Math.min(max,v));
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-10 01:02:18 -05:00
|
|
|
function getOverlappingRanges(lo, hi) {
|
|
|
|
|
let ranges = [];
|
2022-02-18 18:42:08 -05:00
|
|
|
for (let range of settings.proc().ranges || []) {
|
2021-02-10 01:02:18 -05:00
|
|
|
let in_lo = range.lo >= lo && range.lo <= hi;
|
|
|
|
|
let in_hi = range.hi >= lo && range.hi <= hi;
|
|
|
|
|
if (in_lo || in_hi) {
|
|
|
|
|
ranges.push(range);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ranges;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-10 11:45:42 -05:00
|
|
|
// set process override values for a range
|
2021-02-10 16:10:18 -05:00
|
|
|
function updateRange(lo, hi, values, add) {
|
2022-02-18 18:42:08 -05:00
|
|
|
let ranges = settings.proc().ranges;
|
2021-02-10 16:10:18 -05:00
|
|
|
let slices = {};
|
|
|
|
|
let min = lo;
|
|
|
|
|
let max = hi;
|
|
|
|
|
|
2021-10-09 11:35:57 -04:00
|
|
|
// special case for belt loops which should not be flattened
|
|
|
|
|
if (values.outputLoops) {
|
|
|
|
|
ranges.push({
|
|
|
|
|
lo, hi, fields: values
|
|
|
|
|
});
|
2022-02-18 18:42:08 -05:00
|
|
|
updateFieldsFromSettings(settings.proc());
|
2022-02-17 14:40:51 -05:00
|
|
|
api.show.alert("update ranges", 2);
|
|
|
|
|
api.event.emit("range.updates", ranges);
|
2021-10-09 11:35:57 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-10 16:10:18 -05:00
|
|
|
// just remove values from matching ranges
|
|
|
|
|
if (!add) {
|
|
|
|
|
for (let range of getOverlappingRanges(lo, hi)) {
|
|
|
|
|
for (let key of Object.keys(values)) {
|
|
|
|
|
delete range.fields[key];
|
|
|
|
|
}
|
|
|
|
|
if (Object.keys(range.fields).length === 0) {
|
|
|
|
|
let pos = ranges.indexOf(range);
|
|
|
|
|
if (pos >= 0) {
|
|
|
|
|
ranges.splice(pos,1);
|
|
|
|
|
}
|
2021-02-10 11:45:42 -05:00
|
|
|
}
|
|
|
|
|
}
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit("range.updates", ranges);
|
2021-02-10 11:45:42 -05:00
|
|
|
return;
|
2021-02-10 01:02:18 -05:00
|
|
|
}
|
2021-02-10 16:10:18 -05:00
|
|
|
|
2021-10-09 14:55:28 -04:00
|
|
|
// set aside belt loops and re-append later
|
|
|
|
|
// since we do not want to collapse/merge loops
|
|
|
|
|
let exclude = ranges.filter(r => r.fields.outputLoops);
|
|
|
|
|
ranges = ranges.filter(r => !r.fields.outputLoops);
|
|
|
|
|
|
2021-02-10 16:10:18 -05:00
|
|
|
// flatten ranges
|
|
|
|
|
ranges.push({lo, hi, fields: values});
|
|
|
|
|
for (let range of ranges) {
|
|
|
|
|
min = Math.min(range.lo, min);
|
|
|
|
|
max = Math.max(range.hi, max);
|
|
|
|
|
for (let i=range.lo; i<=range.hi; i++) {
|
|
|
|
|
let slice = slices[i];
|
|
|
|
|
if (!slice) {
|
|
|
|
|
slice = slices[i] = {};
|
|
|
|
|
}
|
|
|
|
|
for (let [key,val] of Object.entries(range.fields)) {
|
|
|
|
|
slice[key] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-10 01:02:18 -05:00
|
|
|
}
|
2021-02-10 16:10:18 -05:00
|
|
|
|
|
|
|
|
// merge contiguous matching ranges
|
2022-02-18 18:42:08 -05:00
|
|
|
ranges = settings.proc().ranges = [];
|
2021-02-10 16:10:18 -05:00
|
|
|
let range;
|
|
|
|
|
for (let i=min; i<=max; i++) {
|
|
|
|
|
let slice = slices[i];
|
|
|
|
|
if (slice && !range) {
|
|
|
|
|
range = {lo: i, hi: i, fields: slice};
|
2022-02-18 10:52:49 -05:00
|
|
|
} else if (slice && range && areEqual(range.fields, slice)) {
|
2021-02-10 16:10:18 -05:00
|
|
|
range.hi = i;
|
|
|
|
|
} else if (range) {
|
|
|
|
|
ranges.push(range);
|
|
|
|
|
if (slice) {
|
|
|
|
|
range = {lo: i, hi: i, fields: slice};
|
|
|
|
|
} else {
|
|
|
|
|
range = undefined;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-10 01:02:18 -05:00
|
|
|
}
|
2021-02-10 16:10:18 -05:00
|
|
|
|
|
|
|
|
ranges.push(range);
|
2021-10-09 14:55:28 -04:00
|
|
|
ranges.appendAll(exclude);
|
|
|
|
|
|
2022-02-18 18:42:08 -05:00
|
|
|
updateFieldsFromSettings(settings.proc());
|
2022-02-17 14:40:51 -05:00
|
|
|
api.show.alert("update ranges", 2);
|
|
|
|
|
api.event.emit("range.updates", ranges);
|
2021-02-10 01:02:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let overrides = {};
|
|
|
|
|
|
2021-02-10 11:45:42 -05:00
|
|
|
// updates editable fields that are range dependent
|
2021-02-10 01:02:18 -05:00
|
|
|
function updateFieldsFromRange() {
|
2021-02-10 16:10:18 -05:00
|
|
|
return;
|
2022-02-18 18:42:08 -05:00
|
|
|
if (settings.mode !== 'FDM' || viewMode !== VIEWS.SLICE || !settings.proc().ranges) {
|
2021-02-10 11:45:42 -05:00
|
|
|
let okeys = Object.keys(overrides);
|
|
|
|
|
if (okeys.length) {
|
|
|
|
|
updateFieldsFromSettings(overrides);
|
|
|
|
|
overrides = {};
|
|
|
|
|
}
|
2021-02-10 01:02:18 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let match = 0;
|
|
|
|
|
let values = {};
|
|
|
|
|
let restores = Object.clone(overrides);
|
2022-02-17 14:40:51 -05:00
|
|
|
let { layer_lo, layer_hi } = api.var;
|
|
|
|
|
for (let range of getOverlappingRanges(api.var.layer_lo, api.var.layer_hi)) {
|
2021-02-10 01:02:18 -05:00
|
|
|
for (let key of Object.keys(range.fields)) {
|
|
|
|
|
values[key] = range.fields[key];
|
2022-02-18 18:42:08 -05:00
|
|
|
overrides[key] = settings.proc()[key];
|
2021-02-10 01:02:18 -05:00
|
|
|
delete restores[key];
|
|
|
|
|
match++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (match) {
|
|
|
|
|
updateFieldsFromSettings(values);
|
|
|
|
|
}
|
|
|
|
|
let rkeys = Object.keys(restores);
|
|
|
|
|
if (rkeys.length) {
|
|
|
|
|
updateFieldsFromSettings(restores);
|
|
|
|
|
for (let key of rkeys) {
|
|
|
|
|
delete overrides[key];
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-10 11:45:42 -05:00
|
|
|
UC.refresh();
|
2021-02-10 01:02:18 -05:00
|
|
|
}
|
|
|
|
|
|
2022-02-17 21:52:54 -05:00
|
|
|
function updateSpeeds(maxSpeed, minSpeed) {
|
|
|
|
|
const { ui } = api;
|
|
|
|
|
ui.speeds.style.display =
|
|
|
|
|
maxSpeed &&
|
|
|
|
|
settings.mode !== 'SLA' &&
|
|
|
|
|
settings.mode !== 'LASER' &&
|
|
|
|
|
viewMode === VIEWS.PREVIEW &&
|
|
|
|
|
ui.showSpeeds.checked ? 'block' : '';
|
|
|
|
|
if (maxSpeed) {
|
|
|
|
|
const colors = [];
|
|
|
|
|
for (let i = 0; i <= maxSpeed; i += maxSpeed / 20) {
|
|
|
|
|
colors.push(Math.round(Math.max(i, 1)));
|
|
|
|
|
}
|
|
|
|
|
kiri.client.colors(colors, maxSpeed, speedColors => {
|
|
|
|
|
const list = [];
|
|
|
|
|
Object.keys(speedColors).map(v => parseInt(v)).sort((a, b) => b - a).forEach(speed => {
|
|
|
|
|
const color = speedColors[speed];
|
|
|
|
|
const hex = color.toString(16).padStart(6, 0);
|
|
|
|
|
const r = (color >> 16) & 0xff;
|
|
|
|
|
const g = (color >> 8) & 0xff;
|
|
|
|
|
const b = (color >> 0) & 0xff;
|
|
|
|
|
const style = `background-color:#${hex}`;
|
|
|
|
|
list.push(`<label style="${style}">${speed}</label>`);
|
|
|
|
|
});
|
|
|
|
|
ui.speedbar.innerHTML = list.join('');
|
|
|
|
|
});
|
|
|
|
|
api.event.emit('preview.speeds', {
|
|
|
|
|
min: minSpeed,
|
|
|
|
|
max: maxSpeed
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-07 23:02:05 -04:00
|
|
|
function updateSlider() {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit("slider.set", {
|
|
|
|
|
start: (api.var.layer_lo / api.var.layer_max),
|
|
|
|
|
end: (api.var.layer_hi / api.var.layer_max)
|
2020-06-07 23:02:05 -04:00
|
|
|
});
|
2021-02-10 01:02:18 -05:00
|
|
|
updateFieldsFromRange();
|
2020-06-07 23:02:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setVisibleLayer(h, l) {
|
2022-02-17 14:40:51 -05:00
|
|
|
h = h >= 0 ? h : api.var.layer_hi;
|
|
|
|
|
l = l >= 0 ? l : api.var.layer_lo;
|
|
|
|
|
api.var.layer_hi = bound(h, 0, api.var.layer_max);
|
|
|
|
|
api.var.layer_lo = bound(l, 0, h);
|
|
|
|
|
api.event.emit("slider.label");
|
2020-06-07 23:02:05 -04:00
|
|
|
updateSlider();
|
|
|
|
|
showSlices();
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-11-08 16:44:32 -05:00
|
|
|
function setWireframe(bool, color, opacity) {
|
2022-02-18 13:53:41 -05:00
|
|
|
api.widgets.each(function(w) { w.setWireframe(bool, color, opacity) });
|
2020-11-08 16:44:32 -05:00
|
|
|
SPACE.update();
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
function updateSliderMax(set) {
|
2020-11-08 16:44:32 -05:00
|
|
|
let max = STACKS.getRange().tallest - 1;
|
2022-02-17 14:40:51 -05:00
|
|
|
api.var.layer_max = UI.sliderMax.innerText = max;
|
|
|
|
|
if (set || max < api.var.layer_hi) {
|
|
|
|
|
api.var.layer_hi = api.var.layer_max;
|
|
|
|
|
api.event.emit("slider.label");
|
2020-06-07 23:02:05 -04:00
|
|
|
updateSlider();
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hideSlices() {
|
2020-11-08 10:55:36 -05:00
|
|
|
STACKS.clear();
|
2022-02-18 13:53:41 -05:00
|
|
|
api.widgets.opacity(COLOR.model_opacity);
|
|
|
|
|
api.widgets.each(function(widget) {
|
2017-04-18 17:09:33 -04:00
|
|
|
widget.setWireframe(false);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-30 17:36:27 -04:00
|
|
|
function setWidgetVisibility(bool) {
|
2022-02-18 13:53:41 -05:00
|
|
|
api.widgets.each(w => {
|
2020-10-30 17:36:27 -04:00
|
|
|
if (bool) {
|
|
|
|
|
w.show();
|
|
|
|
|
} else {
|
|
|
|
|
w.hide();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
/**
|
|
|
|
|
* hide or show slice-layers and their sub-elements
|
|
|
|
|
*
|
|
|
|
|
* @param {number} [layer]
|
|
|
|
|
*/
|
|
|
|
|
function showSlices(layer) {
|
2020-06-08 12:23:35 -04:00
|
|
|
if (viewMode === VIEWS.ARRANGE) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-07 23:02:05 -04:00
|
|
|
showSlider();
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
if (typeof(layer) === 'string' || typeof(layer) === 'number') {
|
|
|
|
|
layer = parseInt(layer);
|
|
|
|
|
} else {
|
2022-02-17 14:40:51 -05:00
|
|
|
layer = api.var.layer_hi;
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2022-02-17 14:40:51 -05:00
|
|
|
layer = bound(layer, 0, api.var.layer_max);
|
|
|
|
|
if (layer < api.var.layer_lo) api.var.layer_lo = layer;
|
|
|
|
|
api.var.layer_hi = layer;
|
|
|
|
|
api.event.emit("slider.label");
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-11-07 14:55:15 -05:00
|
|
|
let cam = MODE === MODES.CAM,
|
2020-07-15 10:47:40 -04:00
|
|
|
sla = MODE === MODES.SLA,
|
2022-02-17 14:40:51 -05:00
|
|
|
hi = cam ? api.var.layer_max - api.var.layer_lo : api.var.layer_hi,
|
|
|
|
|
lo = cam ? api.var.layer_max - api.var.layer_hi : api.var.layer_lo;
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-06-07 23:02:05 -04:00
|
|
|
updateSlider();
|
2022-02-17 14:40:51 -05:00
|
|
|
STACKS.setRange(api.var.layer_lo, api.var.layer_hi);
|
2020-06-07 23:02:05 -04:00
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
SPACE.update();
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-07 23:02:05 -04:00
|
|
|
function showSlider() {
|
|
|
|
|
UI.layers.style.display = 'flex';
|
|
|
|
|
UI.slider.style.display = 'flex';
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-18 14:56:59 -05:00
|
|
|
function hideSlider() {
|
2020-06-07 23:02:05 -04:00
|
|
|
UI.layers.style.display = 'none';
|
|
|
|
|
UI.slider.style.display = 'none';
|
2020-11-24 00:48:45 -05:00
|
|
|
UI.speeds.style.display = 'none';
|
2020-06-07 23:02:05 -04:00
|
|
|
}
|
|
|
|
|
|
2021-01-18 15:11:18 -05:00
|
|
|
function loadImageDialog(image, name, force) {
|
|
|
|
|
if (!force && image.byteLength > 2500000) {
|
|
|
|
|
return UC.confirm("Large images may fail to import<br>Consider resizing under 1000 x 1000<br>Proceed with import?").then(ok => {
|
|
|
|
|
if (ok) {
|
|
|
|
|
loadImageDialog(image, name, true);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-11-27 13:06:56 -05:00
|
|
|
const opt = {pre: [
|
|
|
|
|
"<div class='f-col a-center'>",
|
|
|
|
|
" <h3>Image Conversion</h3>",
|
|
|
|
|
" <p class='t-just' style='width:300px;line-height:1.5em'>",
|
|
|
|
|
" This will create a 3D model from a 2D PNG image. Photos must",
|
|
|
|
|
" be blurred to be usable. Values from 0=off to 50=high are suggested.",
|
|
|
|
|
" Higher values incur more processing time.",
|
|
|
|
|
" </p>",
|
2020-11-27 14:42:55 -05:00
|
|
|
" <div class='f-row t-right'><table>",
|
|
|
|
|
" <tr><th>blur value</th><td><input id='png-blur' value='0' size='3'></td>",
|
|
|
|
|
" <th> invert image</th><td><input id='png-inv' type='checkbox'></td></tr>",
|
|
|
|
|
" <tr><th>base size</th><td><input id='png-base' value='0' size='3'></td>",
|
|
|
|
|
" <th> invert alpha</th><td><input id='alpha-inv' type='checkbox'></td></tr>",
|
2020-11-27 15:03:25 -05:00
|
|
|
" <tr><th>border size</th><td><input id='png-border' value='0' size='3'></td>",
|
|
|
|
|
" <th></th><td></td></tr>",
|
2020-11-27 14:42:55 -05:00
|
|
|
" </table></div>",
|
2020-11-27 13:06:56 -05:00
|
|
|
"</div>"
|
|
|
|
|
]};
|
|
|
|
|
UC.confirm(undefined, {convert:true, cancel:false}, undefined, opt).then((ok) => {
|
|
|
|
|
if (ok) {
|
2020-11-27 14:42:55 -05:00
|
|
|
loadImage(image, {
|
2020-11-27 15:50:22 -05:00
|
|
|
file: name,
|
2020-11-27 14:42:55 -05:00
|
|
|
blur: parseInt($('png-blur').value) || 0,
|
|
|
|
|
base: parseInt($('png-base').value) || 0,
|
2020-11-27 15:03:25 -05:00
|
|
|
border: parseInt($('png-border').value) || 0,
|
2020-11-27 14:42:55 -05:00
|
|
|
inv_image: $('png-inv').checked,
|
2020-11-27 15:50:22 -05:00
|
|
|
inv_alpha: $('alpha-inv').checked
|
2020-11-27 14:42:55 -05:00
|
|
|
});
|
2020-11-27 13:06:56 -05:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function loadImage(image, opt = {}) {
|
2022-02-18 14:56:59 -05:00
|
|
|
const info = Object.assign({settings, png:image}, opt);
|
2022-02-17 14:40:51 -05:00
|
|
|
kiri.client.image2mesh(info, progress => {
|
|
|
|
|
api.show.progress(progress, "converting");
|
2020-11-26 23:18:28 -05:00
|
|
|
}, output => {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.show.progress(0);
|
2022-02-18 14:56:59 -05:00
|
|
|
const { bigv, verts, index } = output;
|
|
|
|
|
const widget = newWidget().loadVertices(bigv)
|
2020-11-27 15:50:22 -05:00
|
|
|
widget.meta.file = opt.file;
|
|
|
|
|
platform.add(widget);
|
2020-11-26 23:18:28 -05:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-08 20:58:26 -04:00
|
|
|
/** ******************************************************************
|
|
|
|
|
* Selection Functions
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
2021-03-01 00:22:07 -05:00
|
|
|
function groupMerge() {
|
2022-02-18 13:27:26 -05:00
|
|
|
Widget.Groups.merge(selection.widgets(true));
|
2021-03-01 00:22:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function groupSplit() {
|
2022-02-18 13:27:26 -05:00
|
|
|
Widget.Groups.split(selection.widgets(false));
|
2020-12-06 21:25:31 -05:00
|
|
|
}
|
|
|
|
|
|
2020-03-08 20:58:26 -04:00
|
|
|
/** ******************************************************************
|
|
|
|
|
* Settings Functions
|
|
|
|
|
******************************************************************* */
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-04-09 14:52:43 -04:00
|
|
|
// given a settings region, update values of matching bound UI fields
|
2020-12-27 22:51:32 -05:00
|
|
|
function updateFieldsFromSettings(setrec, uirec = UI, trace) {
|
2020-12-23 14:27:18 -05:00
|
|
|
if (!setrec) {
|
|
|
|
|
return console.trace("missing scope");
|
|
|
|
|
}
|
|
|
|
|
for (let key in setrec) {
|
|
|
|
|
if (!setrec.hasOwnProperty(key)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
let val = setrec[key];
|
|
|
|
|
if (!uirec.hasOwnProperty(key)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
let uie = uirec[key], typ = uie ? uie.type : null;
|
|
|
|
|
if (typ === 'text') {
|
|
|
|
|
if (uie.setv) {
|
|
|
|
|
uie.setv(val);
|
|
|
|
|
} else {
|
|
|
|
|
uie.value = val;
|
|
|
|
|
}
|
|
|
|
|
} else if (typ === 'checkbox') {
|
|
|
|
|
uie.checked = val;
|
|
|
|
|
} else if (typ === 'select-one') {
|
|
|
|
|
uie.innerHTML = '';
|
|
|
|
|
let source = uie.parentNode.getAttribute('source'),
|
2022-02-17 14:40:51 -05:00
|
|
|
list = uie._source || settings[source] || api.lists[source],
|
2020-12-23 14:27:18 -05:00
|
|
|
chosen = null;
|
|
|
|
|
if (list) list.forEach(function(el, index) {
|
|
|
|
|
let id = el.id || el.name;
|
|
|
|
|
let ev = el.value || id;
|
|
|
|
|
if (val == id) {
|
|
|
|
|
chosen = index;
|
2020-04-09 15:29:34 -04:00
|
|
|
}
|
2020-12-23 14:27:18 -05:00
|
|
|
let opt = DOC.createElement('option');
|
|
|
|
|
opt.appendChild(DOC.createTextNode(el.name));
|
|
|
|
|
opt.setAttribute('value', ev);
|
|
|
|
|
uie.appendChild(opt);
|
|
|
|
|
});
|
|
|
|
|
if (chosen) {
|
|
|
|
|
uie.selectedIndex = chosen;
|
|
|
|
|
}
|
|
|
|
|
} else if (typ === 'textarea') {
|
|
|
|
|
if (Array.isArray(val)) {
|
|
|
|
|
uie.value = val.join('\n');
|
|
|
|
|
} else {
|
|
|
|
|
uie.value = '';
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateFields() {
|
2022-02-18 18:42:08 -05:00
|
|
|
updateFieldsFromSettings(settings.dev());
|
|
|
|
|
updateFieldsFromSettings(settings.proc());
|
|
|
|
|
updateFieldsFromSettings(settings.ctrl());
|
|
|
|
|
updateExtruderFields(settings.dev());
|
2020-04-10 12:27:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateExtruderFields(device) {
|
2020-04-09 14:52:43 -04:00
|
|
|
if (device.extruders && device.extruders[device.internal]) {
|
|
|
|
|
updateFieldsFromSettings(device.extruders[device.internal]);
|
2020-04-09 15:29:34 -04:00
|
|
|
UI.extruder.firstChild.innerText = `${LANG.dv_gr_ext} [${device.internal+1}/${device.extruders.length}]`;
|
2020-04-10 12:27:08 -04:00
|
|
|
UI.extPrev.disabled = device.internal === 0;
|
|
|
|
|
UI.extPrev.onclick = function() {
|
|
|
|
|
device.internal--;
|
|
|
|
|
updateExtruderFields(device);
|
|
|
|
|
};
|
|
|
|
|
UI.extNext.disabled = device.internal === device.extruders.length - 1;
|
|
|
|
|
UI.extNext.onclick = function() {
|
|
|
|
|
device.internal++;
|
|
|
|
|
updateExtruderFields(device);
|
|
|
|
|
};
|
2021-02-11 10:10:48 -05:00
|
|
|
UI.extDel.disabled = UI.extDel.disabled || device.extruders.length < 2;
|
2020-04-10 13:12:13 -04:00
|
|
|
UI.extDel.onclick = function() {
|
|
|
|
|
device.extruders.splice(device.internal,1);
|
2020-04-10 13:24:45 -04:00
|
|
|
device.internal = Math.min(device.internal, device.extruders.length-1);
|
2020-04-10 13:12:13 -04:00
|
|
|
updateExtruderFields(device);
|
|
|
|
|
};
|
|
|
|
|
UI.extAdd.onclick = function() {
|
2020-04-12 22:25:00 -04:00
|
|
|
let copy = clone(device.extruders[device.internal]);
|
|
|
|
|
copy.extSelect = [`T${device.extruders.length}`];
|
2021-02-09 10:25:23 -05:00
|
|
|
copy.extDeselect = [];
|
2020-04-12 22:25:00 -04:00
|
|
|
device.extruders.push(copy);
|
2020-04-10 13:12:13 -04:00
|
|
|
device.internal = device.extruders.length - 1;
|
|
|
|
|
updateExtruderFields(device);
|
|
|
|
|
};
|
2020-04-09 14:52:43 -04:00
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2021-02-23 10:08:04 -05:00
|
|
|
function loadImageConvert(res, name) {
|
|
|
|
|
let url = URL.createObjectURL(new Blob([res]));
|
|
|
|
|
|
|
|
|
|
$('mod-any').innerHTML = `<img id="xsrc" src="${url}"><canvas id="xdst"></canvas>`;
|
|
|
|
|
|
|
|
|
|
let img = $('xsrc');
|
|
|
|
|
let can = $('xdst');
|
|
|
|
|
|
|
|
|
|
img.onload = () => {
|
|
|
|
|
can.width = img.width;
|
|
|
|
|
can.height = img.height;
|
|
|
|
|
let ctx = can.getContext('2d');
|
|
|
|
|
ctx.drawImage(img, 0, 0);
|
|
|
|
|
fetch(can.toDataURL()).then(r => r.arrayBuffer()).then(data => {
|
|
|
|
|
loadImageDialog(data, name);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
function loadFile() {
|
|
|
|
|
$('load-file').onchange = function(event) {
|
2021-07-04 21:05:46 -04:00
|
|
|
console.log(event);
|
2022-02-18 12:08:08 -05:00
|
|
|
api.platform.load_files(event.target.files);
|
2017-04-18 17:09:33 -04:00
|
|
|
};
|
|
|
|
|
$('load-file').click();
|
2019-01-18 16:46:17 -05:00
|
|
|
// alert2("drag/drop STL files onto platform to import\nreload page to return to last saved state");
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-11-18 09:11:29 -05:00
|
|
|
function saveWorkspace(quiet) {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.conf.save();
|
2022-02-18 11:30:00 -05:00
|
|
|
const newWidgets = [];
|
|
|
|
|
const oldWidgets = js2o(SDB.getItem('ws-widgets'), []);
|
2022-02-18 13:53:41 -05:00
|
|
|
api.widgets.each(function(widget) {
|
2021-01-24 00:13:09 -05:00
|
|
|
if (widget.synth) return;
|
2020-03-10 10:40:57 -04:00
|
|
|
newWidgets.push(widget.id);
|
|
|
|
|
oldWidgets.remove(widget.id);
|
|
|
|
|
widget.saveState();
|
2022-02-17 14:40:51 -05:00
|
|
|
let ann = api.widgets.annotate(widget.id);
|
2020-11-25 09:35:28 -05:00
|
|
|
ann.file = widget.meta.file;
|
|
|
|
|
ann.url = widget.meta.url;
|
2020-03-10 10:40:57 -04:00
|
|
|
});
|
|
|
|
|
SDB.setItem('ws-widgets', o2js(newWidgets));
|
|
|
|
|
oldWidgets.forEach(function(wid) {
|
|
|
|
|
Widget.deleteFromState(wid);
|
|
|
|
|
});
|
2020-05-26 11:05:21 -04:00
|
|
|
// eliminate dangling saved widgets
|
2022-02-18 11:30:00 -05:00
|
|
|
FILES.deleteFilter(key => newWidgets.indexOf(key.substring(8)) < 0, "ws-save-", "ws-savf");
|
2020-11-18 09:11:29 -05:00
|
|
|
if (!quiet) {
|
|
|
|
|
alert2("workspace saved", 1);
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-03-29 20:23:48 -04:00
|
|
|
function restoreWorkspace(ondone, skip_widget_load) {
|
2022-02-18 18:42:08 -05:00
|
|
|
let newset = api.conf.restore(false),
|
2020-04-13 17:42:40 -04:00
|
|
|
camera = newset.controller.view,
|
2020-03-29 20:23:48 -04:00
|
|
|
toload = ls2o('ws-widgets',[]),
|
2020-04-13 17:42:40 -04:00
|
|
|
loaded = 0,
|
2020-03-29 20:23:48 -04:00
|
|
|
position = true;
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
updateFields();
|
2020-03-08 20:58:26 -04:00
|
|
|
platform.update_size();
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
SPACE.view.reset();
|
2020-04-15 15:20:02 -04:00
|
|
|
if (camera) {
|
|
|
|
|
SPACE.view.load(camera);
|
|
|
|
|
} else {
|
|
|
|
|
SPACE.view.home();
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-11-15 22:12:45 -05:00
|
|
|
if (skip_widget_load) {
|
|
|
|
|
if (ondone) {
|
|
|
|
|
ondone();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-03-17 16:32:43 -04:00
|
|
|
// remove any widgets from platform
|
2022-02-18 13:53:41 -05:00
|
|
|
api.widgets.each(function(widget) {
|
2020-03-08 20:58:26 -04:00
|
|
|
platform.delete(widget);
|
2017-04-18 17:09:33 -04:00
|
|
|
});
|
2020-03-17 16:32:43 -04:00
|
|
|
|
|
|
|
|
// load any widget by name that was saved to the workspace
|
2017-04-18 17:09:33 -04:00
|
|
|
toload.forEach(function(widgetid) {
|
|
|
|
|
Widget.loadFromState(widgetid, function(widget) {
|
2020-03-03 20:06:10 -05:00
|
|
|
if (widget) {
|
2020-03-08 20:58:26 -04:00
|
|
|
platform.add(widget, 0, position);
|
2022-02-17 14:40:51 -05:00
|
|
|
let ann = api.widgets.annotate(widgetid);
|
2020-11-25 23:28:41 -05:00
|
|
|
widget.meta.file = ann.file;
|
|
|
|
|
widget.meta.url = ann.url;
|
2020-03-03 20:06:10 -05:00
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
if (++loaded === toload.length) {
|
2020-03-08 20:58:26 -04:00
|
|
|
platform.deselect();
|
2020-03-03 20:06:10 -05:00
|
|
|
if (ondone) {
|
|
|
|
|
ondone();
|
2020-03-17 16:32:43 -04:00
|
|
|
setTimeout(() => {
|
|
|
|
|
platform.update_top_z();
|
|
|
|
|
SPACE.update();
|
|
|
|
|
}, 1);
|
2020-03-03 20:06:10 -05:00
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
2020-03-03 20:06:10 -05:00
|
|
|
}, position);
|
2017-04-18 17:09:33 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return toload.length > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearWorkspace() {
|
|
|
|
|
// free up worker cache/mem
|
2022-02-17 14:40:51 -05:00
|
|
|
kiri.work.clear();
|
2020-03-09 11:02:09 -04:00
|
|
|
platform.select_all();
|
2022-02-18 13:27:26 -05:00
|
|
|
platform.delete(selection.meshes());
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function modalShowing() {
|
2020-06-06 11:17:04 -04:00
|
|
|
return UI.modal.style.display === 'flex';
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function showModal(which) {
|
2020-06-06 11:17:04 -04:00
|
|
|
let mod = UI.modal,
|
|
|
|
|
style = mod.style,
|
|
|
|
|
visible = modalShowing(),
|
|
|
|
|
info = { pct: 0 };
|
|
|
|
|
|
2020-06-12 20:39:59 -04:00
|
|
|
["help","setup","tools","prefs","saves","files","print","local","any"].forEach(function(name) {
|
2020-06-06 11:17:04 -04:00
|
|
|
UI[name].style.display = name === which ? 'flex' : '';
|
2017-04-18 17:09:33 -04:00
|
|
|
});
|
|
|
|
|
|
2020-06-06 11:17:04 -04:00
|
|
|
function ondone() {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('modal.show', which);
|
2020-06-06 11:17:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (visible) {
|
|
|
|
|
return ondone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
style.height = '0';
|
|
|
|
|
style.display = 'flex';
|
|
|
|
|
|
|
|
|
|
new TWEEN.Tween(info).
|
|
|
|
|
easing(TWEEN.Easing.Quadratic.InOut).
|
|
|
|
|
to({ pct: 100 }, 100).
|
|
|
|
|
onUpdate(() => { style.height = `${info.pct}%` }).
|
|
|
|
|
onComplete(ondone).
|
|
|
|
|
start();
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 11:17:04 -04:00
|
|
|
function hideModal() {
|
|
|
|
|
if (!modalShowing()) {
|
2018-02-02 09:02:07 -05:00
|
|
|
return;
|
|
|
|
|
}
|
2020-06-06 11:17:04 -04:00
|
|
|
let mod = UI.modal, style = mod.style, info={pct:100};
|
|
|
|
|
new TWEEN.Tween(info).
|
|
|
|
|
easing(TWEEN.Easing.Quadratic.InOut).
|
|
|
|
|
to({pct:0}, 100).
|
|
|
|
|
onUpdate(() => { style.height = `${info.pct}%` }).
|
|
|
|
|
onComplete(() => { style.display = '' }).
|
|
|
|
|
start();
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
function showCatalog() {
|
2020-06-06 16:02:04 -04:00
|
|
|
showModal("files");
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-03-29 20:23:48 -04:00
|
|
|
function editSettings(e) {
|
2022-02-18 18:42:08 -05:00
|
|
|
let current = settings.get(),
|
|
|
|
|
mode = getMode(),
|
2019-07-23 12:54:26 -04:00
|
|
|
name = e.target.getAttribute("name"),
|
2022-02-18 18:42:08 -05:00
|
|
|
load = current.sproc[mode][name],
|
2019-07-23 12:54:26 -04:00
|
|
|
edit = prompt(`settings for "${name}"`, JSON.stringify(load));
|
|
|
|
|
if (edit) {
|
|
|
|
|
try {
|
2022-02-18 18:42:08 -05:00
|
|
|
current.sproc[mode][name] = JSON.parse(edit);
|
|
|
|
|
if (name === current.proc().processName) {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.conf.load(null, name);
|
2019-07-23 21:12:40 -04:00
|
|
|
}
|
2022-02-17 14:40:51 -05:00
|
|
|
api.conf.save();
|
2019-07-23 12:54:26 -04:00
|
|
|
} catch (e) {
|
2020-06-19 19:23:09 -04:00
|
|
|
UC.alert('malformed settings object');
|
2019-07-23 12:54:26 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-15 12:37:54 -05:00
|
|
|
function exportSettings(e) {
|
2022-02-18 18:42:08 -05:00
|
|
|
let current = settings.get(),
|
|
|
|
|
mode = getMode(),
|
2021-02-15 12:37:54 -05:00
|
|
|
name = e.target.getAttribute("name"),
|
2022-02-17 14:40:51 -05:00
|
|
|
data = api.util.b64enc({
|
2022-02-18 18:42:08 -05:00
|
|
|
process: current.sproc[mode][name],
|
2022-02-17 14:40:51 -05:00
|
|
|
version: kiri.version,
|
|
|
|
|
moto: moto.id,
|
2021-02-15 12:37:54 -05:00
|
|
|
time: Date.now(),
|
|
|
|
|
mode,
|
|
|
|
|
name
|
|
|
|
|
});
|
|
|
|
|
UC.prompt("Export Process Filename", name).then(name => {
|
|
|
|
|
if (name) {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.util.download(data, `${name}.km`);
|
2021-02-15 12:37:54 -05:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-29 20:23:48 -04:00
|
|
|
function deleteSettings(e) {
|
2022-02-18 18:42:08 -05:00
|
|
|
let current = settings.get();
|
2020-04-09 14:52:43 -04:00
|
|
|
let name = e.target.getAttribute("del");
|
2022-02-18 18:42:08 -05:00
|
|
|
delete current.sproc[getMode()][name];
|
|
|
|
|
updateProcessList();
|
2022-02-17 14:40:51 -05:00
|
|
|
api.conf.save();
|
2017-04-18 17:09:33 -04:00
|
|
|
triggerSettingsEvent();
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-18 18:42:08 -05:00
|
|
|
function updateProcessList() {
|
|
|
|
|
let current = settings.get();
|
|
|
|
|
let list = [], s = current, sp = s.sproc[getMode()] || {}, table = UI.settingsList;
|
2017-04-18 17:09:33 -04:00
|
|
|
table.innerHTML = '';
|
2020-04-09 14:52:43 -04:00
|
|
|
for (let k in sp) {
|
2017-04-18 17:09:33 -04:00
|
|
|
if (sp.hasOwnProperty(k)) list.push(k);
|
|
|
|
|
}
|
2020-11-20 09:46:10 -05:00
|
|
|
list.filter(n => n !=='default').sort().forEach(function(sk) {
|
2020-04-09 14:52:43 -04:00
|
|
|
let row = DOC.createElement('div'),
|
2017-04-18 17:09:33 -04:00
|
|
|
load = DOC.createElement('button'),
|
2019-07-23 12:54:26 -04:00
|
|
|
edit = DOC.createElement('button'),
|
2021-02-15 12:37:54 -05:00
|
|
|
xprt = DOC.createElement('button'),
|
2017-04-18 17:09:33 -04:00
|
|
|
del = DOC.createElement('button'),
|
|
|
|
|
name = sk;
|
|
|
|
|
|
|
|
|
|
load.setAttribute('load', sk);
|
2020-06-09 23:19:51 -04:00
|
|
|
load.onclick = (ev) => {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.conf.load(undefined, sk);
|
2022-02-18 18:42:08 -05:00
|
|
|
updateProcessList();
|
2020-11-20 09:46:10 -05:00
|
|
|
hideModal();
|
2020-06-09 23:19:51 -04:00
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
load.appendChild(DOC.createTextNode(sk));
|
2022-02-18 18:42:08 -05:00
|
|
|
if (sk == settings.proc().processName) {
|
2017-12-14 20:41:19 -05:00
|
|
|
load.setAttribute('class', 'selected')
|
|
|
|
|
}
|
2022-02-18 18:42:08 -05:00
|
|
|
UI.settingsName.value = settings.proc().processName;
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
del.setAttribute('del', sk);
|
|
|
|
|
del.setAttribute('title', "remove '"+sk+"'");
|
2020-11-20 09:46:10 -05:00
|
|
|
del.innerHTML = '<i class="far fa-trash-alt"></i>';
|
2020-03-29 20:23:48 -04:00
|
|
|
del.onclick = deleteSettings;
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2019-07-23 12:54:26 -04:00
|
|
|
edit.setAttribute('name', sk);
|
|
|
|
|
edit.setAttribute('title', 'edit');
|
2020-11-20 09:46:10 -05:00
|
|
|
edit.innerHTML = '<i class="far fa-edit"></i>';
|
2020-03-29 20:23:48 -04:00
|
|
|
edit.onclick = editSettings;
|
2019-07-23 12:54:26 -04:00
|
|
|
|
2021-02-15 12:37:54 -05:00
|
|
|
xprt.setAttribute('name', sk);
|
|
|
|
|
xprt.setAttribute('title', 'export');
|
|
|
|
|
xprt.innerHTML = '<i class="fas fa-download"></i>';
|
|
|
|
|
xprt.onclick = exportSettings;
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
row.setAttribute("class", "flow-row");
|
2019-07-23 12:54:26 -04:00
|
|
|
row.appendChild(edit);
|
2017-04-18 17:09:33 -04:00
|
|
|
row.appendChild(load);
|
2021-02-15 12:37:54 -05:00
|
|
|
row.appendChild(xprt);
|
2017-04-18 17:09:33 -04:00
|
|
|
row.appendChild(del);
|
|
|
|
|
table.appendChild(row);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-09 11:02:09 -04:00
|
|
|
function showHelp() {
|
2021-10-26 19:35:57 -04:00
|
|
|
showHelpFile(`local`,() => {});
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-11-16 15:04:58 -05:00
|
|
|
function showHelpFile(local,then) {
|
2017-04-18 17:09:33 -04:00
|
|
|
if (!local) {
|
2021-10-26 19:35:57 -04:00
|
|
|
WIN.open("//docs.grid.space/", "_help");
|
2017-04-18 17:09:33 -04:00
|
|
|
return;
|
|
|
|
|
}
|
2022-02-17 14:40:51 -05:00
|
|
|
$('kiri-version').innerHTML = `${LANG.version} ${kiri.version}`;
|
2021-10-26 19:35:57 -04:00
|
|
|
showModal('help');
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('help.show', local);
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-02-06 16:22:43 -05:00
|
|
|
function showLocal() {
|
|
|
|
|
showModal('local');
|
2022-02-17 14:40:51 -05:00
|
|
|
api.probe.local((err,data) => {
|
2020-07-11 21:22:52 -04:00
|
|
|
let devc = 0;
|
|
|
|
|
let bind = [];
|
|
|
|
|
let html = ['<table>'];
|
|
|
|
|
html.push(`<thead><tr><th>device</th><th>type</th><th>status</th><th></th></tr></thead>`);
|
|
|
|
|
html.push(`<tbody>`);
|
2021-06-02 17:14:07 -04:00
|
|
|
let recs = [];
|
2020-07-11 21:22:52 -04:00
|
|
|
for (let k in data) {
|
2021-06-02 17:14:07 -04:00
|
|
|
recs.push(data[k].stat);
|
|
|
|
|
}
|
|
|
|
|
recs.sort((a,b) => {
|
|
|
|
|
return a.device.name < b.device.name ? -1 : 1;
|
|
|
|
|
});
|
|
|
|
|
for (let r of recs) {
|
2020-07-11 21:22:52 -04:00
|
|
|
bind.push({uuid: r.device.uuid, host: r.device.addr[0], port: r.device.port});
|
|
|
|
|
html.push(`<tr>`);
|
|
|
|
|
html.push(`<td>${r.device.name}</td>`);
|
|
|
|
|
html.push(`<td>${r.device.mode}</td>`);
|
|
|
|
|
html.push(`<td>${r.state}</td>`);
|
|
|
|
|
html.push(`<td><button id="${r.device.uuid}">admin</button></td>`);
|
|
|
|
|
html.push(`</tr>`);
|
|
|
|
|
devc++;
|
|
|
|
|
}
|
|
|
|
|
html.push(`</tbody>`);
|
|
|
|
|
html.push(`</table>`);
|
|
|
|
|
if (devc) {
|
|
|
|
|
$('mod-local').innerHTML = html.join('');
|
|
|
|
|
} else {
|
|
|
|
|
$('mod-local').innerHTML = `<br><b>no local devices</b>`;
|
|
|
|
|
}
|
|
|
|
|
bind.forEach(rec => {
|
|
|
|
|
$(rec.uuid).onclick = () => {
|
|
|
|
|
window.open(`http://${rec.host}:${rec.port||4080}/`);
|
|
|
|
|
};
|
2020-02-06 16:22:43 -05:00
|
|
|
});
|
2020-07-11 21:22:52 -04:00
|
|
|
});
|
2020-02-06 16:22:43 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
function setViewMode(mode) {
|
2020-11-11 08:13:40 -05:00
|
|
|
const oldMode = viewMode;
|
2022-02-18 18:42:08 -05:00
|
|
|
const isCAM = settings.mode() === 'CAM';
|
2017-04-18 17:09:33 -04:00
|
|
|
viewMode = mode;
|
2020-03-08 20:58:26 -04:00
|
|
|
platform.deselect();
|
2022-02-18 13:27:26 -05:00
|
|
|
selection.update_info();
|
2020-11-19 13:54:55 -05:00
|
|
|
// disable clear in non-arrange modes
|
|
|
|
|
$('view-clear').style.display = mode === VIEWS.ARRANGE ? '' : 'none';
|
2017-04-18 17:09:33 -04:00
|
|
|
switch (mode) {
|
|
|
|
|
case VIEWS.ARRANGE:
|
2022-02-18 14:56:59 -05:00
|
|
|
api.function.clear_progress();
|
2020-11-11 08:13:40 -05:00
|
|
|
UI.back.style.display = '';
|
|
|
|
|
UI.render.style.display = '';
|
2022-02-17 14:40:51 -05:00
|
|
|
kiri.client.clear();
|
2020-11-08 17:35:40 -05:00
|
|
|
STACKS.clear();
|
2020-06-07 23:02:05 -04:00
|
|
|
hideSlider();
|
2020-11-10 21:48:04 -05:00
|
|
|
updateSpeeds();
|
2020-11-09 00:21:35 -05:00
|
|
|
setVisibleLayer();
|
2020-10-30 17:36:27 -04:00
|
|
|
setWidgetVisibility(true);
|
2022-02-18 13:53:41 -05:00
|
|
|
api.widgets.opacity(1);
|
2017-04-18 17:09:33 -04:00
|
|
|
break;
|
|
|
|
|
case VIEWS.SLICE:
|
2020-11-11 08:13:40 -05:00
|
|
|
UI.back.style.display = 'flex';
|
|
|
|
|
if (!isCAM) UI.render.classList.remove('lt-enabled');
|
2020-11-10 21:48:04 -05:00
|
|
|
updateSpeeds();
|
2017-04-18 17:09:33 -04:00
|
|
|
updateSliderMax();
|
2020-10-30 17:36:27 -04:00
|
|
|
setWidgetVisibility(true);
|
2017-04-18 17:09:33 -04:00
|
|
|
break;
|
|
|
|
|
case VIEWS.PREVIEW:
|
2020-11-11 08:13:40 -05:00
|
|
|
UI.back.style.display = 'flex';
|
|
|
|
|
if (!isCAM) UI.render.classList.remove('lt-enabled');
|
2020-10-30 17:36:27 -04:00
|
|
|
setWidgetVisibility(true);
|
2017-04-18 17:09:33 -04:00
|
|
|
break;
|
|
|
|
|
default:
|
2021-07-04 21:05:46 -04:00
|
|
|
console.log("invalid view mode: "+mode);
|
2017-04-18 17:09:33 -04:00
|
|
|
return;
|
|
|
|
|
}
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('view.set', mode);
|
2019-03-30 13:45:57 -04:00
|
|
|
DOC.activeElement.blur();
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getMode() {
|
2022-02-18 18:42:08 -05:00
|
|
|
return settings.mode();
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2020-03-07 13:14:22 -05:00
|
|
|
function getModeLower() {
|
|
|
|
|
return getMode().toLowerCase();
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 21:01:00 -05:00
|
|
|
function switchMode(mode) {
|
2020-03-08 20:58:26 -04:00
|
|
|
setMode(mode, platform.update_size);
|
2020-02-08 21:01:00 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
function setMode(mode, lock, then) {
|
|
|
|
|
if (!MODES[mode]) {
|
2021-07-04 21:05:46 -04:00
|
|
|
console.log("invalid mode: "+mode);
|
2017-04-18 17:09:33 -04:00
|
|
|
mode = 'FDM';
|
|
|
|
|
}
|
2022-02-18 18:42:08 -05:00
|
|
|
const current = settings.get();
|
2020-06-11 22:11:19 -04:00
|
|
|
// change mode constants
|
2022-02-18 18:42:08 -05:00
|
|
|
current.mode = mode;
|
2020-06-09 18:12:59 -04:00
|
|
|
MODE = MODES[mode];
|
2022-02-17 14:40:51 -05:00
|
|
|
DRIVER = kiri.driver[mode];
|
2020-06-11 22:11:19 -04:00
|
|
|
// update mode display
|
2021-01-12 19:04:56 -05:00
|
|
|
$('app-mode-name').innerHTML = mode === 'CAM' ? 'CNC' : mode;
|
2020-06-11 22:11:19 -04:00
|
|
|
// highlight relevant device mode button
|
|
|
|
|
["fdm","sla","cam","laser"].forEach(dev => {
|
|
|
|
|
let cl = $(`mode-${dev}`).classList;
|
|
|
|
|
if (dev === mode.toLowerCase()) {
|
|
|
|
|
cl.add("dev-sel");
|
|
|
|
|
} else {
|
|
|
|
|
cl.remove("dev-sel");
|
|
|
|
|
}
|
|
|
|
|
});
|
2017-04-18 17:09:33 -04:00
|
|
|
// restore cached device profile for this mode
|
2022-02-18 18:42:08 -05:00
|
|
|
if (current.cdev[mode]) {
|
|
|
|
|
current.device = clone(current.cdev[mode]);
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('device.set', currentDeviceName());
|
2020-02-10 17:41:59 -05:00
|
|
|
}
|
2020-06-11 22:11:19 -04:00
|
|
|
// really belongs in CAM driver (lots of work / abstraction needed)
|
2020-11-14 11:12:12 -05:00
|
|
|
// updateStockVisibility();
|
2020-03-17 16:32:43 -04:00
|
|
|
// updates right-hand menu by enabling/disabling fields
|
2020-04-25 21:08:13 -04:00
|
|
|
setViewMode(VIEWS.ARRANGE);
|
2017-04-18 17:09:33 -04:00
|
|
|
UC.setMode(MODE);
|
2020-06-11 22:11:19 -04:00
|
|
|
// sanitize and persist settings
|
2022-02-17 14:40:51 -05:00
|
|
|
api.conf.load();
|
|
|
|
|
api.conf.save();
|
2020-06-11 22:11:19 -04:00
|
|
|
// other housekeeping
|
2017-04-18 17:09:33 -04:00
|
|
|
triggerSettingsEvent();
|
2022-02-17 21:52:54 -05:00
|
|
|
platform.update_selected();
|
2022-02-18 13:53:41 -05:00
|
|
|
selection.update_bounds(api.widgets.all());
|
2020-04-11 16:33:10 -04:00
|
|
|
updateFields();
|
2020-06-11 22:11:19 -04:00
|
|
|
// because device dialog, if showing, needs to be updated
|
2020-06-06 20:05:21 -04:00
|
|
|
if (modalShowing()) {
|
2022-02-17 14:40:51 -05:00
|
|
|
api.show.devices();
|
2020-04-16 22:33:09 -04:00
|
|
|
}
|
2022-02-17 14:40:51 -05:00
|
|
|
api.space.restore(null, true);
|
|
|
|
|
api.event.emit("mode.set", mode);
|
2020-06-11 22:11:19 -04:00
|
|
|
if (then) {
|
|
|
|
|
then();
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2018-01-31 10:42:55 -05:00
|
|
|
function currentDeviceName() {
|
2022-02-18 18:42:08 -05:00
|
|
|
return settings.get().filter[getMode()];
|
2018-01-31 10:42:55 -05:00
|
|
|
}
|
|
|
|
|
|
2021-02-15 11:05:47 -05:00
|
|
|
function currentDeviceCode() {
|
2022-02-18 18:42:08 -05:00
|
|
|
return settings.get().devices[currentDeviceName()];
|
2021-02-15 11:05:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function currentProcessName() {
|
2022-02-18 18:42:08 -05:00
|
|
|
return settings.get().cproc[getMode()];
|
2021-02-15 11:05:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function currentProcessCode() {
|
2022-02-18 18:42:08 -05:00
|
|
|
return settings.get().sproc[getMode()][currentProcessName()];
|
2021-02-15 11:05:47 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
function setControlsVisible(show) {
|
2020-06-07 23:02:05 -04:00
|
|
|
$('mid-lcol').style.display = show ? 'flex' : 'none';
|
|
|
|
|
$('mid-rcol').style.display = show ? 'flex' : 'none';
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
2021-02-15 12:37:54 -05:00
|
|
|
function downloadBlob(data, filename) {
|
|
|
|
|
let url = WIN.URL.createObjectURL(new Blob([data], {type: "octet/stream"}));
|
|
|
|
|
$('mod-any').innerHTML = `<a id="_dexport_" href="${url}" download="${filename}">x</a>`;
|
|
|
|
|
$('_dexport_').click();
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
// prevent safari from exiting full screen mode
|
2020-03-09 11:02:09 -04:00
|
|
|
DOC.onkeydown = function (evt) { if (evt.keyCode == 27) evt.preventDefault() }
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2022-02-17 15:04:36 -05:00
|
|
|
// complete module loading
|
|
|
|
|
kiri.load_exec();
|
2020-03-16 23:57:14 -04:00
|
|
|
|
2021-02-27 17:26:24 -05:00
|
|
|
// upon restore, seed presets
|
2022-02-17 14:40:51 -05:00
|
|
|
api.event.emit('preset', api.conf.dbo());
|
2017-04-18 17:09:33 -04:00
|
|
|
})();
|