move devices and export into ui
This commit is contained in:
parent
a752c18855
commit
a0091b8abb
5 changed files with 9 additions and 9 deletions
|
|
@ -7,7 +7,7 @@ import STACKS from '../ui/stacks.js';
|
|||
import { broker } from '../../moto/broker.js';
|
||||
import { client as work } from './client.js';
|
||||
import { consts, COLOR as color, LISTS as lists } from './consts.js';
|
||||
import { device, devices } from './devices.js';
|
||||
import { device, devices } from '../ui/devices.js';
|
||||
import { catalog, dialog, event, group, help, hide, image } from './main.js';
|
||||
import { modal, mode, process, show, space, util, view } from './main.js';
|
||||
import { local as dataLocal } from '../../data/local.js';
|
||||
|
|
|
|||
|
|
@ -1,385 +0,0 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
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/kiri-devs.js';
|
||||
import { settings, conf as setconf } from './settings.js';
|
||||
|
||||
export const device = {
|
||||
clone: cloneDevice,
|
||||
code: currentDeviceCode,
|
||||
get: currentDeviceName,
|
||||
set: selectDevice,
|
||||
isBelt
|
||||
};
|
||||
|
||||
export const devices = {
|
||||
show: showDevices,
|
||||
select: selectDevice,
|
||||
refresh: updateDeviceList,
|
||||
update_laser_state: updateLaserState
|
||||
};
|
||||
|
||||
function isBelt() {
|
||||
return setconf.get().device.bedBelt;
|
||||
}
|
||||
|
||||
function currentDeviceName() {
|
||||
return setconf.get().filter[api.mode.get()];
|
||||
}
|
||||
|
||||
function currentDeviceCode() {
|
||||
return setconf.get().devices[currentDeviceName()];
|
||||
}
|
||||
|
||||
function getModeDevices() {
|
||||
return Object.keys(devlist[ api.mode.get_lower() ]).sort();
|
||||
}
|
||||
|
||||
export function showDevices() {
|
||||
settings.sync.get().then(_showDevices);
|
||||
}
|
||||
|
||||
function _showDevices() {
|
||||
updateDeviceList();
|
||||
api.modal.show('setup');
|
||||
}
|
||||
|
||||
function updateDeviceList() {
|
||||
renderDevices(getModeDevices());
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
function putLocalDevice(devicename, obj) {
|
||||
setconf.get().devices[devicename] = obj;
|
||||
setconf.save();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 updateLaserState() {
|
||||
const dev = setconf.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) || {};
|
||||
if (code.code) code = code.code;
|
||||
|
||||
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
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev.new = false;
|
||||
dev.deviceName = devicename;
|
||||
|
||||
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;
|
||||
ui.useIndexed.checked = dev.useIndexed;
|
||||
|
||||
// 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.useIndexed,
|
||||
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;
|
||||
|
||||
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: api.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);
|
||||
}
|
||||
|
||||
|
|
@ -1,518 +0,0 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
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 '../mode/laser/driver.js';
|
||||
import { SLA as sla_client } from '../mode/sla/init-ui.js';
|
||||
import { hash } from '../../ext/md5.js';
|
||||
|
||||
let printSeq = parseInt(local['kiri-print-seq'] || local['print-seq'] || "0") + 1;
|
||||
|
||||
function localGet(key) {
|
||||
return api.local.get(key);
|
||||
}
|
||||
|
||||
function localSet(key, val) {
|
||||
return api.local.set(key, val);
|
||||
}
|
||||
|
||||
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)
|
||||
.map(v => v.replace(/ /g,'-'))
|
||||
.map(v => v.substring(0,20))
|
||||
.map(v => v.split('.')[0]);
|
||||
api.event.emit('export', mode);
|
||||
switch (mode) {
|
||||
case 'WEDM':
|
||||
case 'WJET':
|
||||
case 'DRAG':
|
||||
case 'LASER': return callExportLaser(options, names);
|
||||
case 'FDM': return callExport(options, mode, names);
|
||||
case 'CAM': return callExport(options, mode, names);
|
||||
case 'SLA': return callExportSLA(options, names);
|
||||
}
|
||||
}
|
||||
|
||||
function callExport(callback, mode, names) {
|
||||
let alert = api.feature.work_alerts ? api.show.alert("Exporting") : null;
|
||||
let gcode = [];
|
||||
let section = [];
|
||||
let sections = { };
|
||||
client.export(api.conf.get(), (line) => {
|
||||
if (typeof line !== 'string') {
|
||||
if (line.section) {
|
||||
sections[line.section] = section = [];
|
||||
}
|
||||
return;
|
||||
}
|
||||
gcode.push(line);
|
||||
section.push(line);
|
||||
}, (output, error) => {
|
||||
api.hide.alert(alert);
|
||||
if (error) {
|
||||
api.show.alert(error, 5);
|
||||
} else if (callback) {
|
||||
callback(gcode.join('\r\n'), output);
|
||||
} else {
|
||||
exportGCodeDialog(gcode, mode === 'CAM' ? sections : undefined, output, names);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function callExportLaser(options, names) {
|
||||
client.export(api.conf.get(), (line) => {
|
||||
// engine export uses lines
|
||||
// console.log({unexpected_line: line});
|
||||
}, (output, error) => {
|
||||
// UI export uses output
|
||||
if (error) {
|
||||
api.show.alert(error, 5);
|
||||
} else {
|
||||
exportLaserDialog(output, names);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function callExportSLA(options, names) {
|
||||
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 {
|
||||
sla_client.printDownload(output, api, names);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function exportLaserDialog(data, names) {
|
||||
localSet('kiri-print-seq', printSeq++);
|
||||
|
||||
const fileroot = names[0] || "laser";
|
||||
const filename = `${fileroot}-${(printSeq.toString().padStart(3,"0"))}`;
|
||||
const settings = api.conf.get();
|
||||
const driver = laser_driver;
|
||||
const { process } = settings;
|
||||
if (process.ctOutStack) {
|
||||
$('print-stl').classList.remove('hide');
|
||||
} else {
|
||||
$('print-stl').classList.add('hide');
|
||||
}
|
||||
|
||||
function download_svg() {
|
||||
api.util.download(
|
||||
driver.exportSVG(settings, data),
|
||||
$('print-filename-laser').value + ".svg"
|
||||
);
|
||||
}
|
||||
|
||||
function download_dxf() {
|
||||
api.util.download(
|
||||
driver.exportDXF(settings, data),
|
||||
$('print-filename-laser').value + ".dxf"
|
||||
);
|
||||
}
|
||||
|
||||
function download_stl() {
|
||||
api.util.download(
|
||||
driver.exportSTL(settings, data),
|
||||
$('print-filename-laser').value + ".stl"
|
||||
);
|
||||
}
|
||||
|
||||
function download_gcode() {
|
||||
api.util.download(
|
||||
driver.exportGCode(settings, data),
|
||||
$('print-filename-laser').value + ".gcode"
|
||||
);
|
||||
}
|
||||
|
||||
api.modal.show('xlaser');
|
||||
|
||||
let segments = 0;
|
||||
data.forEach(layer => { segments += layer.length });
|
||||
|
||||
$('print-filename-laser').value = filename;
|
||||
$('print-lines').value = util.comma(segments);
|
||||
$('print-svg').onclick = download_svg;
|
||||
$('print-dxf').onclick = download_dxf;
|
||||
$('print-stl').onclick = download_stl;
|
||||
$('print-lg').onclick = download_gcode;
|
||||
}
|
||||
|
||||
function bindField(field, varname) {
|
||||
$(field).onblur = function() {
|
||||
console.log('save', field, 'to', varname);
|
||||
localSet(varname, $(field).value.trim());
|
||||
};
|
||||
}
|
||||
|
||||
function exportGCodeDialog(gcode, sections, info, names) {
|
||||
localSet('kiri-print-seq', printSeq++);
|
||||
|
||||
let settings = api.conf.get(),
|
||||
MODE = api.mode.get_id(),
|
||||
name = names[0] || (MODE === MODES.CAM ? "cnc" : "print"),
|
||||
pre = `${name}-${(printSeq.toString().padStart(3,"0"))}`,
|
||||
filename = pre,// + (new Date().getTime().toString(36)),
|
||||
fileext = settings.device.gcodeFExt || "gcode",
|
||||
codeproc = settings.device.gcodeProc,
|
||||
octo_host,
|
||||
octo_apik,
|
||||
grid_host,
|
||||
grid_apik,
|
||||
grid_target,
|
||||
grid_targets = {},
|
||||
grid_local,
|
||||
grid_uuid;
|
||||
|
||||
// join gcode array into a string
|
||||
gcode = gcode.join('\r\n') + '\r\n';
|
||||
|
||||
// run gcode post processor function (when supplied and valid)
|
||||
if (codeproc && self[codeproc]) {
|
||||
gcode = self[codeproc](gcode);
|
||||
}
|
||||
|
||||
function getBlob() {
|
||||
return new Blob(
|
||||
[gcode],
|
||||
{type:"application/octet-stream"});
|
||||
}
|
||||
|
||||
function sendto_octoprint() {
|
||||
if (!(octo_host && octo_apik)) return;
|
||||
|
||||
let form = new FormData(),
|
||||
ajax = new XMLHttpRequest(),
|
||||
host = octo_host.value.toLowerCase(),
|
||||
apik = octo_apik.value;
|
||||
|
||||
if (host.indexOf("http") !== 0) {
|
||||
api.show.alert("host missing protocol (http:// or https://)");
|
||||
return;
|
||||
}
|
||||
if (api.const.SECURE && !api.util.isSecure(host)) {
|
||||
api.show.alert("host must begin with 'https' on a secure site");
|
||||
return;
|
||||
}
|
||||
|
||||
localSet('octo-host', host.trim());
|
||||
localSet('octo-apik', apik.trim());
|
||||
|
||||
filename = $('print-filename').value;
|
||||
form.append("file", getBlob(), filename+"."+fileext);
|
||||
ajax.onreadystatechange = function() {
|
||||
if (ajax.readyState === 4) {
|
||||
let status = ajax.status;
|
||||
api.stats.add(`ua_${api.mode.get_lower()}_print_octo_${status}`);
|
||||
if (status >= 200 && status < 300) {
|
||||
api.modal.hide();
|
||||
} else {
|
||||
api.show.alert("octoprint error\nstatus: "+status+"\nmessage: "+ajax.responseText);
|
||||
}
|
||||
api.show.progress(0);
|
||||
}
|
||||
api.show.progress(0);
|
||||
};
|
||||
ajax.upload.addEventListener('progress', function(evt) {
|
||||
api.show.progress(evt.loaded/evt.total, "sending");
|
||||
});
|
||||
ajax.open("POST", host+"/api/files/local");
|
||||
if (apik) {
|
||||
ajax.setRequestHeader("X-Api-Key", apik);
|
||||
}
|
||||
ajax.send(form);
|
||||
}
|
||||
|
||||
function download() {
|
||||
filename = $('print-filename').value;
|
||||
api.util.download(gcode, filename + "." + fileext);
|
||||
// saveAs(getBlob(), filename + "." + fileext);
|
||||
}
|
||||
|
||||
function pad(v) {
|
||||
v = v.toString();
|
||||
return v.length < 2 ? '0' + v : v;
|
||||
}
|
||||
|
||||
function calcWeight() {
|
||||
try {
|
||||
let density = $('print-density');
|
||||
info.weight = (
|
||||
(Math.PI * util.sqr(
|
||||
info.settings.device.extruders[0].extFilament / 2
|
||||
)) *
|
||||
info.distance *
|
||||
(parseFloat(density.value) || 1.25) /
|
||||
1000
|
||||
).round(2);
|
||||
$('print-weight').value = info.weight.toFixed(2);
|
||||
density.onkeyup = (ev) => {
|
||||
if (ev.key === 'Enter') calcWeight();
|
||||
};
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
function calcTime() {
|
||||
let floor = Math.floor,
|
||||
time = floor(info.time),
|
||||
hours = floor(time / 3600),
|
||||
newtime = time - hours * 3600,
|
||||
mins = floor(newtime / 60),
|
||||
secs = newtime - mins * 60;
|
||||
|
||||
$('output-time').value = [pad(hours),pad(mins),pad(secs)].join(':');
|
||||
}
|
||||
|
||||
api.modal.show('xany');
|
||||
let set = api.conf.get();
|
||||
let fdm = MODE === MODES.FDM;
|
||||
let octo = set.controller.exportOcto && MODE !== MODES.CAM;
|
||||
let preview = set.controller.exportPreview;
|
||||
$('code-preview-head').style.display = preview ? '' : 'none';
|
||||
$('code-preview').style.display = preview ? '' : 'none';
|
||||
$('print-download').onclick = download;
|
||||
$('print-filament').style.display = fdm ? '' : 'none';
|
||||
$('print-filename').value = filename;
|
||||
$('print-filesize').value = util.comma(info.bytes);
|
||||
$('print-length').value = Math.round(info.distance);
|
||||
if (set.controller.devel) {
|
||||
$('code-preview-textarea').style.height = "30em";
|
||||
}
|
||||
calcTime();
|
||||
if (fdm) {
|
||||
calcWeight();
|
||||
}
|
||||
|
||||
// persist fields when changed
|
||||
bindField('octo-host', 'octo-host');
|
||||
bindField('octo-apik', 'octo-apik');
|
||||
|
||||
// in cam mode, show zip file option
|
||||
let downloadZip = $('print-zip');
|
||||
downloadZip.style.display = sections ? 'flex' : 'none';
|
||||
downloadZip.onclick = function() {
|
||||
let files = [];
|
||||
for (let [ name, data ] of Object.entries(sections)) {
|
||||
if (name.indexOf('op-') === 0) {
|
||||
let head = sections.header || [];
|
||||
let foot = sections.footer || [];
|
||||
files.push({
|
||||
name: `${name}.${fileext}`,
|
||||
data: [ ...head, ...data, ...foot ].join('\r\n')
|
||||
})
|
||||
}
|
||||
}
|
||||
client.zip(files, progress => {
|
||||
api.show.progress(progress.percent/100, "generating zip files");
|
||||
}, output => {
|
||||
api.show.progress(0);
|
||||
api.util.download(output, `${$('print-filename').value}.zip`);
|
||||
})
|
||||
};
|
||||
|
||||
// in fdm mode, show 3mf file option
|
||||
let nozzle0 = set.device?.extruders?.[0]?.extNozzle || 0.4;
|
||||
let download3MF = $('print-3mf');
|
||||
download3MF.style.display = fdm ? 'flex' : 'none';
|
||||
download3MF.onclick = function() {
|
||||
gen3mf(zip => api.util.download(zip, `${$('print-filename').value}.3mf`));
|
||||
};
|
||||
|
||||
// present bambu print options when selected device is bambu
|
||||
if (api.bambu) {
|
||||
api.bambu.prep_export(gen3mf, gcode, info, settings);
|
||||
}
|
||||
|
||||
// let wids = api.widgets.all();
|
||||
// let bnds = settings.bounds;
|
||||
// console.log({ wids, bnds });
|
||||
|
||||
function gen3mf(then, ptype = 'unknown', ams = [0]) {
|
||||
let now = new Date();
|
||||
let ymd = [
|
||||
now.getFullYear(),
|
||||
(now.getMonth() + 1).toString().padStart(2,0),
|
||||
now.getDate().toString().padStart(2,0),
|
||||
].join('-');
|
||||
let files = [{
|
||||
name: `[Content_Types].xml`,
|
||||
data: [
|
||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||
'<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">',
|
||||
' <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>',
|
||||
' <Default Extension="model" ContentType="application/vnd.ms-package.3dmanufacturing-3dmodel+xml"/>',
|
||||
' <Default Extension="gcode" ContentType="application/octet-stream"/>',
|
||||
'</Types>'
|
||||
].join('\n')
|
||||
},{
|
||||
name: `_rels/.rels`,
|
||||
data: [
|
||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">',
|
||||
' <Relationship Target="/3D/3dmodel.model" Id="rel-1" Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel"/>',
|
||||
'</Relationships>'
|
||||
].join('\n')
|
||||
},{
|
||||
name: `3D/3dmodel.model`,
|
||||
data: [
|
||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||
'<model unit="millimeter" xml:lang="en-US" xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02" xmlns:BambuStudio="http://schemas.bambulab.com/package/2021">',
|
||||
' <metadata name="Application">Kiri:Moto</metadata>',
|
||||
' <metadata name="Copyright"></metadata>',
|
||||
` <metadata name="CreationDate">${ymd}</metadata>`,
|
||||
' <metadata name="Description"></metadata>',
|
||||
' <metadata name="Designer"></metadata>',
|
||||
' <metadata name="DesignerCover"></metadata>',
|
||||
' <metadata name="License"></metadata>',
|
||||
` <metadata name="ModificationDate">${ymd}</metadata>`,
|
||||
' <metadata name="Origin"></metadata>',
|
||||
' <metadata name="Title"></metadata>',
|
||||
' <resources>',
|
||||
' </resources>',
|
||||
' <build/>',
|
||||
'</model>'
|
||||
].join('\n')
|
||||
},{
|
||||
name: `Metadata/_rels/model_settings.config.rels`,
|
||||
data: [
|
||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">',
|
||||
' <Relationship Target="/Metadata/plate_1.gcode" Id="rel-1" Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/gcode"/>',
|
||||
'</Relationships>'
|
||||
].join('\n')
|
||||
// },{
|
||||
// name: `Metadata/plate_1.json`,
|
||||
// data: JSON.stringify({
|
||||
// "bbox_all": [ 100, 100, 200, 200 ],
|
||||
// "bbox_objects": (info.labels || []).map(label => {
|
||||
// return {
|
||||
// area: 600,
|
||||
// bbox: [ 100, 100, 200, 200 ],
|
||||
// id: label,
|
||||
// layer_height: 0.2,
|
||||
// name: "Object"
|
||||
// }
|
||||
// }),
|
||||
// "bed_type": "textured_plate",
|
||||
// "filament_colors": ["#FFFFFF"],
|
||||
// "filament_ids": ams,
|
||||
// "first_extruder": ams[0],
|
||||
// "is_seq_print": false,
|
||||
// "nozzle_diameter": 0.6,
|
||||
// "version": 2
|
||||
// })
|
||||
},{
|
||||
name: `Metadata/model_settings.config`,
|
||||
data: [
|
||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||
'<config>',
|
||||
' <plate>',
|
||||
' <metadata key="plater_id" value="1"/>',
|
||||
' <metadata key="plater_name" value=""/>',
|
||||
' <metadata key="locked" value="false"/>',
|
||||
' <metadata key="gcode_file" value="Metadata/plate_1.gcode"/>',
|
||||
' <metadata key="thumbnail_file" value="Metadata/plate_1.png"/>',
|
||||
' <metadata key="thumbnail_no_light_file" value="Metadata/plate_no_light_1.png"/>',
|
||||
' <metadata key="top_file" value="Metadata/top_1.png"/>',
|
||||
' <metadata key="pick_file" value="Metadata/pick_1.png"/>',
|
||||
' </plate>',
|
||||
'</config>'
|
||||
].join('\n')
|
||||
},{
|
||||
name: `Metadata/slice_info.config`,
|
||||
data: [
|
||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||
'<config>',
|
||||
' <header>',
|
||||
' <header_item key="X-BBL-Client-Type" value="slicer"/>',
|
||||
' <header_item key="X-BBL-Client-Version" value="01.10.01.50"/>',
|
||||
' </header>',
|
||||
' <plate>',
|
||||
' <metadata key="index" value="1"/>',
|
||||
// setting this value allows for the printer to error out if
|
||||
// the gcode / 3mf was intended for a different target type.
|
||||
// leaving it blank bypasses the check
|
||||
// ` <metadata key="printer_model_id" value="${ptype}"/>`,
|
||||
` <metadata key="nozzle_diameters" value="${nozzle0}"/>`,
|
||||
' <metadata key="timelapse_type" value="0"/>',
|
||||
` <metadata key="prediction" value="${Math.round(info.time)}"/>`,
|
||||
` <metadata key="weight" value="${info.weight}"/>`,
|
||||
' <metadata key="outside" value="false"/>',
|
||||
' <metadata key="support_used" value="false"/>',
|
||||
' <metadata key="label_object_enabled" value="false"/>',
|
||||
// (info.labels || []).map(label =>
|
||||
// ` <object identify_id="${label}" name="Object" skipped="false" />`),
|
||||
// ' <filament id="1" tray_info_idx="GFL96" type="PLA" color="#FFFFFF" used_m="0.17" used_g="0.50" />',
|
||||
// ' <warning msg="bed_temperature_too_high_than_filament" level="1" error_code ="1000C001" />',
|
||||
' </plate>',
|
||||
'</config>'
|
||||
].filter(v => v).flat().join('\n')
|
||||
},{
|
||||
name: `Metadata/project_settings.config`,
|
||||
data: JSON.stringify({},undefined,4)
|
||||
},{
|
||||
name: `Metadata/plate_1.gcode`,
|
||||
data: gcode
|
||||
},{
|
||||
name: `Metadata/plate_1.gcode.md5`,
|
||||
data: hash(gcode)
|
||||
},{
|
||||
name: `Metadata/plate_1_small.png`,
|
||||
data: api.view.bambu.s128.png
|
||||
},{
|
||||
name: `Metadata/plate_no_light_1.png`,
|
||||
data: api.view.bambu.s512.png
|
||||
},{
|
||||
name: `Metadata/plate_1.png`,
|
||||
data: api.view.bambu.s512.png
|
||||
},{
|
||||
name: `Metadata/pick_1.png`,
|
||||
data: api.view.bambu.s512.png
|
||||
},{
|
||||
name: `Metadata/top_1.png`,
|
||||
data: api.view.bambu.s512.png
|
||||
}];
|
||||
client.zip(files, progress => {
|
||||
api.show.progress(progress.percent/100, "generating 3mf");
|
||||
}, output => {
|
||||
api.show.progress(0);
|
||||
then(output);
|
||||
})
|
||||
};
|
||||
|
||||
// octoprint setup
|
||||
$('send-to-octohead').style.display = octo ? '' : 'none';
|
||||
$('send-to-octoprint').style.display = octo ? '' : 'none';
|
||||
if (octo) try {
|
||||
$('print-octoprint').onclick = sendto_octoprint;
|
||||
octo_host = $('octo-host');
|
||||
octo_apik = $('octo-apik');
|
||||
if (MODE === MODES.CAM) {
|
||||
$('send-to-octohead').style.display = 'none';
|
||||
$('send-to-octoprint').style.display = 'none';
|
||||
} else {
|
||||
$('send-to-octohead').style.display = '';
|
||||
$('send-to-octoprint').style.display = '';
|
||||
}
|
||||
// hide octoprint when hard-coded in the url
|
||||
if (api.const.OCTO) {
|
||||
$('ophost').style.display = 'none';
|
||||
$('opapik').style.display = 'none';
|
||||
$('oph1nt').style.display = 'none';
|
||||
}
|
||||
octo_host.value = localGet('octo-host') || '';
|
||||
octo_apik.value = localGet('octo-apik') || '';
|
||||
} catch (e) { console.log(e) }
|
||||
|
||||
// preview of the generated GCODE (first 64k max)
|
||||
if (preview && gcode) $('code-preview-textarea').value = gcode.substring(0,65535);
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ 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';
|
||||
import { exportFile } from '../ui/export.js';
|
||||
|
||||
let complete = {};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { openFiles } from '../ui/files.js';
|
|||
import { platform } from './platform.js';
|
||||
import { selection } from './selection.js';
|
||||
import { settings } from './settings.js';
|
||||
import { showDevices } from './devices.js';
|
||||
import { showDevices } from '../ui/devices.js';
|
||||
import { space as SPACE } from '../../moto/space.js';
|
||||
import { stats } from '../ui/stats.js';
|
||||
import { noop, utils } from './utils.js';
|
||||
|
|
|
|||
Loading…
Reference in a new issue