From 499f4ff2c253a42cf6a0b00430e9174f9de14cb1 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Thu, 9 Apr 2020 14:52:43 -0400 Subject: [PATCH] checkpoint settings work --- js/kiri-conf.js | 249 ++++++++++++++++++++----- js/kiri-init.js | 227 ++++++++-------------- js/kiri.js | 218 ++++++++-------------- js/license.js | 2 +- js/moto-space.js | 6 +- notes.md | 1 + web/kiri/filter/FDM/Any.Generic.Marlin | 12 +- web/kiri/style.css | 5 + web/moto/style.css | 20 +- 9 files changed, 392 insertions(+), 348 deletions(-) diff --git a/js/kiri-conf.js b/js/kiri-conf.js index fb05897e..3fb25cd9 100644 --- a/js/kiri-conf.js +++ b/js/kiri-conf.js @@ -2,23 +2,187 @@ "use strict"; -var gs_kiri_conf = exports; +let gs_kiri_conf = exports; (function() { if (!self.kiri) self.kiri = { }; if (self.kiri.conf) return; - let KIRI = self.kiri; + let KIRI = self.kiri, + CVER = 2; function genID() { while (true) { - var k = Math.round(Math.random() * 9999999999).toString(36); + let k = Math.round(Math.random() * 9999999999).toString(36); if (k.length >= 4 && k.length <= 8) return k; } } - KIRI.conf = { + // add fields to o(bject) from t(arget) that are missing + // remove fields from o(bject) that don't exist in f(ilter) + function fill_cull(o, t, f) { + // add missing + for (let k in t) { + if (!t.hasOwnProperty(k)) { + continue; + } + let okv = o[k]; + if (f[k] !== undefined && (okv === undefined || okv === null)) { + // console.log({fill: k}); + o[k] = t[k]; + } + } + // remove invalid + for (let k in o) { + if (!o.hasOwnProperty(k)) { + continue; + } + if (!f.hasOwnProperty(k)) { + // console.log({cull: k}); + delete o[k]; + } + } + } + + function valueOf(val, dv) { + return typeof(val) !== 'undefined' ? val : dv; + } + + function device_v1_to_v2(device) { + if (device && device.filamentSize) { + device.extruders = [{ + extFilament: device.filamentSize, + extNozzle: device.nozzleSize, + extSelect: ["T0"], + extDeselect: [], + extOffsetX: 0, + extOffsetY: 0 + }]; + delete device.filamentSize; + delete device.nozzleSize; + } + } + + // convert default filter (from server) into device structure + function device_from_code(code,mode) { + // presence of internal field indicates already converted + if (code.internal >= 0) return code; + + let API = KIRI.api, + cmd = code.cmd || {}, + set = code.settings || {}, + ext = code.extruders; + + let device = { + mode: mode || '', + internal: 0, + bedHeight: 2.5, + bedWidth: valueOf(set.bed_width, 300), + bedDepth: valueOf(set.bed_depth, 175), + bedRound: valueOf(set.bed_circle, false), + maxHeight: valueOf(set.build_height, 150), + originCenter: valueOf(set.origin_center, false), + extrudeAbs: valueOf(set.extrude_abs, false), + spindleMax: valueOf(set.spindle_max, 0), + gcodeFan: valueOf(cmd.fan_power, ''), + gcodeTrack: valueOf(cmd.progress, ''), + gcodeLayer: valueOf(cmd.layer, []), + gcodePre: valueOf(code.pre, []), + gcodePost: valueOf(code.post, []), + gcodeProc: valueOf(code.proc, ''), + gcodePause: valueOf(code.pause, []), + gcodeDwell: valueOf(code.dwell, []), + gcodeSpindle: valueOf(cmd.spindle, []), + gcodeChange: valueOf(code['tool-change'], []), + gcodeFExt: valueOf(code['file-ext'], 'gcode'), + gcodeSpace: valueOf(code['token-space'], ''), + gcodeStrip: valueOf(code['strip-comments'], false), + gcodeLaserOn: valueOf(code['laser-on'], []), + gcodeLaserOff: valueOf(code['laser-off'], []), + extruders: [] + }; + + if (ext) { + // synthesize extruders from new style settings + ext.forEach(rec => { + let e = API.clone(CONF.template.device.extruders[0]); + if (rec.nozzle) e.extNozzle = rec.nozzle; + if (rec.filament) e.extFilament = rec.filament; + if (rec.offset_x) e.extOffsetX = rec.offset_x; + if (rec.offset_y) e.extOffsetY = rec.offset_y; + if (rec.select) e.extSelect = rec.select; + if (rec.deselect) e.extDeselect= rec.deselect; + device.extruders.push(e); + }); + } else { + // synthesize extruders from old style settings + device.extruders = [API.clone(CONF.template.device.extruders[0])]; + device.extruders[0].extNozzle = valueOf(set.nozzle_size, 0.4); + device.extruders[0].extFilament = valueOf(set.filament_diameter, 1.75); + } + + return device; + } + + function forValues(o, fn) { + Object.values(o).forEach(v => fn(v)); + } + + // ensure settings structure is up-to-date + function normalize(settings) { + let API = KIRI.api, + filter = CONF.filter, + defaults = CONF.template, + filter_dev = filter.fdm.d, + filter_pro = filter.fdm.p; + + switch (settings.mode) { + case 'FDM': + break; + case 'CAM': + filter_dev = filter.cam.d; + filter_pro = filter.cam.p; + break; + case 'LASER': + filter_dev = filter.laser.d; + filter_pro = filter.laser.p; + break; + } + + // v1 to v2 changed FDM extruder / nozzle / filament structure + if (settings.ver === 1) { + // backup settings before upgrade + API.sdb.setItem(`ws-settings-${Date.now()}`, JSON.stringify(settings)); + device_v1_to_v2(settings.device); + device_v1_to_v2(settings.cdev.FDM); + settings.ver = 2; + } + + fill_cull(settings, defaults, defaults); + fill_cull(settings.device, defaults.device, filter_dev); + fill_cull(settings.process, defaults.process, filter_pro); + fill_cull(settings.cdev.FDM, defaults.device, filter.fdm.d); + forValues(settings.sproc.FDM, proc => { + fill_cull(proc, defaults.process, filter.fdm.p); + }); + fill_cull(settings.cdev.CAM, defaults.device, filter.cam.d); + forValues(settings.sproc.CAM, proc => { + fill_cull(proc, defaults.process, filter.cam.p); + }); + fill_cull(settings.cdev.LASER, defaults.device, filter.laser.d); + forValues(settings.sproc.LASER, proc => { + fill_cull(proc, defaults.process, filter.laser.p); + }); + fill_cull(settings.controller, defaults.controller, defaults.controller); + + return settings; + } + + let CONF = KIRI.conf = { + // --------------- helper functions + normalize: normalize, + device_from_code: device_from_code, // --------------- MODES: { FDM: 1, // fused deposition modeling (also FFF) @@ -30,11 +194,13 @@ var gs_kiri_conf = exports; SLICE: 2, PREVIEW: 3 }, - // --------------- settings filters (for loading/saving) + // --------------- settings field filters filter: { fdm:{ // fields permitted in FDM:Device d:{ + mode: 1, + internal: 1, bedWidth: 1, bedDepth: 1, bedHeight: 1, @@ -42,8 +208,6 @@ var gs_kiri_conf = exports; maxHeight: 1, extrudeAbs: 1, originCenter: 1, - filamentSize: 1, - nozzleSize: 1, gcodePre: 1, gcodePost: 1, gcodeProc: 1, @@ -120,6 +284,8 @@ var gs_kiri_conf = exports; cam:{ // fields permitted in CAM:Device d:{ + mode: 1, + internal: 1, bedWidth: 1, bedDepth: 1, bedHeight: 1, @@ -192,8 +358,11 @@ var gs_kiri_conf = exports; laser: { // fields permitted in Laser:Device d:{ + mode: 1, + internal: 1, bedWidth: 1, bedDepth: 1, + bedHeight: 1, gcodePre: 1, gcodePost: 1, gcodeFExt: 1, @@ -220,8 +389,9 @@ var gs_kiri_conf = exports; } } }, - // --------------- (default) + // --------------- default settings template: { + // use by UI for populating selectors infill:[ { name: "vase" }, { name: "hex" }, @@ -278,24 +448,24 @@ var gs_kiri_conf = exports; taper_tip: 0, } ], - // FDM/CAM/Laser + // FDM/CAM/Laser merged device:{ + mode: "", // device local + internal: 0, // device edit state bedWidth: 300, // FDM/CAM/Laser bedDepth: 175, // FDM/CAM/Laser bedHeight: 2.5, // display only (deprecate) bedRound: false, // FDM originCenter: false,// FDM/CAM maxHeight: 150, // FDM - filamentSize: 1.75, // FDM - nozzleSize: 0.4, // FDM spindleMax: 0, // CAM gcodePre: [], // FDM/CAM header script gcodePost: [], // FDM/CAM footer script - gcodeProc: "", // FDM post processor script (encoding, etc) gcodePause: [], // FDM pause script + gcodeProc: "", // FDM post processor script (encoding, etc) gcodeFan: "", // FDM fan command gcodeTrack: "", // FDM progress command - gcodeLayer: "", // FDM layer output + gcodeLayer: [], // FDM layer output gcodeFExt: "", // CAM file extension gcodeSpace: "", // CAM token spacing gcodeStrip: true, // CAM strip comments @@ -305,27 +475,30 @@ var gs_kiri_conf = exports; gcodeLaserOn: ["M106 S{power}"],// LASER turn on gcodeLaserOff: ["M107"], // LASER turn off extruders:[{ // FDM extruders structure - filament: 1.75, - nozzle: 0.4, - select: [], - deselect: [], - offsetX: 0, - offsetY: 0 + extFilament: 1.75, + extNozzle: 0.4, + extSelect: ["T0"], + extDeselect: [], + extOffsetX: 0, + extOffsetY: 0 }] }, - // FDM/CAM/Laser + // FDM/CAM/Laser merged process:{ + // --- shared --- processName: "default", + outputOriginBounds: true, + outputOriginCenter: true, + outputInvertX: false, + outputInvertY: false, // --- FDM --- - sliceHeight: 0.25, sliceShells: 3, sliceFillAngle: 45, sliceFillOverlap: 0.3, sliceFillSparse: 0.5, sliceFillType: "hex", - sliceSupportEnable: false, sliceSupportDensity: 0.25, sliceSupportOffset: 1.0, @@ -334,21 +507,18 @@ var gs_kiri_conf = exports; sliceSupportArea: 1, sliceSupportExtra: 0, sliceSupportSpan: 6, - sliceSolidMinArea: 1, sliceSolidLayers: 3, sliceBottomLayers: 3, sliceTopLayers: 3, - firstSliceHeight: 0.25, firstLayerRate: 30, firstLayerFillRate: 40, firstLayerPrintMult: 1.0, - outputRaft: false, - outputRaftSpacing: 0.2, firstLayerNozzleTemp: 0, firstLayerBedTemp: 0, - + outputRaft: false, + outputRaftSpacing: 0.2, outputTemp: 200, outputFanMax: 255, outputBedTemp: 0, @@ -379,11 +549,9 @@ var gs_kiri_conf = exports; gcodePauseLayers: "", // --- LASER --- - laserOffset: 0.25, laserSliceHeight: 1, laserSliceSingle: false, - outputTileSpacing: 1, outputTileScaling: 1, outputLaserPower: 100, @@ -392,9 +560,7 @@ var gs_kiri_conf = exports; outputLaserMerged: false, // --- CAM --- - camFastFeed: 6000, - roughingTool: 1000, roughingSpindle: 1000, roughingDown: 2, @@ -404,7 +570,6 @@ var gs_kiri_conf = exports; roughingStock: 0, camPocketOnlyRough: false, roughingOn: true, - finishingTool: 1000, finishingSpindle: 1000, finishingDown: 3, @@ -417,7 +582,6 @@ var gs_kiri_conf = exports; finishingYOn: true, finishCurvesOnly: false, camPocketOnlyFinish: false, - drillTool: 1000, drillSpindle: 1000, drillDownSpeed: 250, @@ -425,13 +589,11 @@ var gs_kiri_conf = exports; drillDwell: 250, drillLift: 2, drillingOn: false, - camTabsAngle: 0, camTabsCount: 4, camTabsWidth: 5, camTabsHeight: 5, camTabsOn: false, - camPocketOnly: false, camDepthFirst: false, camEaseDown: false, @@ -440,20 +602,11 @@ var gs_kiri_conf = exports; camZTopOffset: 0, camZBottom: 0, camZClearance: 1, - camStockX: 0, camStockY: 0, camStockZ: 0, camStockOffset: true, - outputClockwise: false, - - // --- shared FDM/Laser/CAM --- - - outputOriginBounds: true, - outputOriginCenter: true, - outputInvertX: false, - outputInvertY: false }, // current process name cproc:{ @@ -470,12 +623,14 @@ var gs_kiri_conf = exports; // cached device settings by mode cdev: { FDM: null, - CAM: null + CAM: null, + LASER: null }, // now they're called devices instead of gcode filters filter:{ FDM: "Any.Generic.Marlin", - CAM: "Any.Generic.Grbl" + CAM: "Any.Generic.Grbl", + LASER: "Any.Generic.Laser" }, // custom devices by name devices:{ @@ -522,7 +677,7 @@ var gs_kiri_conf = exports; }, mode: 'FDM', id: genID(), - ver: 1 + ver: CVER } }; diff --git a/js/kiri-init.js b/js/kiri-init.js index b5031dc8..c9107fe6 100644 --- a/js/kiri-init.js +++ b/js/kiri-init.js @@ -11,6 +11,7 @@ var gs_kiri_init = exports; let KIRI = self.kiri, MOTO = self.moto, + CONF = KIRI.conf, WIN = self.window, DOC = self.document, LOC = self.location, @@ -478,8 +479,8 @@ var gs_kiri_init = exports; API.conf.show(); } - function putLocalDevice(devicename, code) { - settings().devices[devicename] = code; + function putLocalDevice(devicename, obj) { + settings().devices[devicename] = obj; API.conf.save(); } @@ -490,7 +491,6 @@ var gs_kiri_init = exports; function isLocalDevice(devicename) { return settings().devices[devicename] ? true : false; - // return localFilters.contains(devicename); } function isFavoriteDevice(devicename) { @@ -514,50 +514,13 @@ var gs_kiri_init = exports; $('selected-device').innerHTML = devicename; } - function valueOf(val, dv) { - return typeof(val) !== 'undefined' ? val : dv; - } - // only for local filters - function updateDeviceCode(override) { - let oldname = getSelectedDevice(), - newname = override || UI.deviceName.value, - code = { - mode: API.mode.get(), - settings: { - bed_width: parseInt(UI.deviceWidth.value) || 300, - bed_depth: parseInt(UI.deviceDepth.value) || 175, - bed_circle: UI.deviceRound.checked, - build_height: parseInt(UI.deviceHeight.value) || 150, - nozzle_size: parseFloat(UI.extruderNozzle.value) || 0.4, - filament_diameter: parseFloat(UI.extruderFilament.value) || 1.75, - origin_center: UI.deviceOrigin.checked, - origin_top: UI.deviceOriginTop.checked, - extrude_abs: UI.extrudeAbsolute.checked, - spindle_max: parseInt(UI.deviceMaxSpindle.value) || 0 - }, - cmd: { - fan_power: UI.gcodeFan.value, - progress: UI.gcodeProgress.value, - spindle: UI.gcodeSpindle.value.split('\n'), - layer: UI.gcodeLayer.value.split('\n') - }, - pre: UI.gcodeHeader.value.split('\n'), - post: UI.gcodeFooter.value.split('\n'), - pause: UI.gcodePause.value.split('\n'), - dwell: UI.gcodeDwell.value.split('\n'), - 'laser-on': UI.gcodeLaserOn.value.split('\n'), - 'laser-off': UI.gcodeLaserOff.value.split('\n'), - 'tool-change': UI.gcodeToolChange.value.split('\n'), - 'file-ext': UI.gcodeExtension.value, - 'token-space': UI.gcodeToken.checked ? ' ' : '', - 'strip-comments': UI.gcodeStrip.checked - }; - - if (oldname !== newname && isLocalDevice(oldname)) removeLocalDevice(oldname); - - putLocalDevice(newname, code); - setDeviceCode(code, newname); + function cloneDevice() { + let name = `${getSelectedDevice()}.copy`; + let code = API.clone(settings().device); + code.mode = API.mode.get(); + putLocalDevice(name, code); + setDeviceCode(code, name); } function setDeviceCode(code, devicename) { @@ -566,49 +529,15 @@ var gs_kiri_init = exports; if (typeof(code) === 'string') code = js2o(code) || {}; - let cmd = code.cmd || {}, - set = code.settings || {}, - local = isLocalDevice(devicename), + let mode = API.mode.get(), current = settings(), + local = isLocalDevice(devicename), dproc = current.devproc[devicename], - mode = API.mode.get(); - - current.device = { - bedHeight: 2.5, - bedWidth: valueOf(set.bed_width, 300), - bedDepth: valueOf(set.bed_depth, 175), - bedRound: valueOf(set.bed_circle, false), - maxHeight: valueOf(set.build_height, 150), - nozzleSize: valueOf(set.nozzle_size, 0.4), - filamentSize: valueOf(set.filament_diameter, 1.75), - originCenter: valueOf(set.origin_center, false), - extrudeAbs: valueOf(set.extrude_abs, false), - spindleMax: valueOf(set.spindle_max, 0), - gcodeFan: valueOf(cmd.fan_power, ''), - gcodeTrack: valueOf(cmd.progress, ''), - gcodeLayer: valueOf(cmd.layer, []), - gcodePre: valueOf(code.pre, []), - gcodePost: valueOf(code.post, []), - gcodeProc: valueOf(code.proc, ''), - gcodePause: valueOf(code.pause, []), - gcodeDwell: valueOf(code.dwell, []), - gcodeSpindle: valueOf(cmd.spindle, []), - gcodeChange: valueOf(code['tool-change'], []), - gcodeFExt: valueOf(code['file-ext'], 'gcode'), - gcodeSpace: valueOf(code['token-space'], ''), - gcodeStrip: valueOf(code['strip-comments'], false), - gcodeLaserOn: valueOf(code['laser-on'], []), - gcodeLaserOff: valueOf(code['laser-off'], []) - }; - - let dev = current.device, + dev = current.device = CONF.device_from_code(code,mode), proc = current.process; - proc.outputOriginCenter = valueOf(set.origin_center, true); - proc.camOriginTop = valueOf(set.origin_top, true); - + proc.outputOriginCenter = dev.outputOriginCenter; UI.deviceName.value = devicename; - // common UI.gcodeHeader.value = dev.gcodePre.join('\n'); UI.gcodeFooter.value = dev.gcodePost.join('\n'); UI.gcodePause.value = dev.gcodePause.join('\n'); @@ -617,65 +546,69 @@ var gs_kiri_init = exports; UI.deviceHeight.value = dev.maxHeight; UI.deviceRound.checked = dev.bedRound; UI.deviceOrigin.checked = proc.outputOriginCenter; - // FDM - UI.gcodeFan.value = dev.gcodeFan; - UI.gcodeProgress.value = dev.gcodeTrack; - UI.gcodeLayer.value = dev.gcodeLayer.join('\n'); - UI.extruderFilament.value = dev.filamentSize; - UI.extruderNozzle.value = dev.nozzleSize; - UI.extrudeAbsolute.checked = dev.extrudeAbs; - // CAM - UI.deviceMaxSpindle.value = dev.spindleMax; - UI.gcodeSpindle.value = dev.gcodeSpindle.join('\n'); - UI.gcodeDwell.value = dev.gcodeDwell.join('\n'); - UI.gcodeToolChange.value = dev.gcodeChange.join('\n'); UI.gcodeExtension.value = dev.gcodeFExt; - UI.gcodeToken.checked = dev.gcodeSpace ? true : false; - UI.gcodeStrip.checked = dev.gcodeStrip; - // LASER - UI.gcodeLaserOn.value = dev.gcodeLaserOn.join('\n'); - UI.gcodeLaserOff.value = dev.gcodeLaserOff.join('\n'); + + if (mode === 'FDM') { + UI.gcodeFan.value = dev.gcodeFan; + UI.gcodeProgress.value = dev.gcodeTrack; + UI.gcodeLayer.value = dev.gcodeLayer.join('\n'); + UI.extrudeAbsolute.checked = dev.extrudeAbs; + } + + if (mode === 'CAM') { + proc.camOriginTop = dev.outputOriginTop; + UI.deviceMaxSpindle.value = dev.spindleMax; + UI.gcodeSpindle.value = dev.gcodeSpindle.join('\n'); + UI.gcodeDwell.value = dev.gcodeDwell.join('\n'); + UI.gcodeToolChange.value = dev.gcodeChange.join('\n'); + UI.gcodeToken.checked = dev.gcodeSpace ? true : false; + UI.gcodeStrip.checked = dev.gcodeStrip; + } + + if (mode === 'LASER') { + UI.gcodeLaserOn.value = dev.gcodeLaserOn.join('\n'); + UI.gcodeLaserOff.value = dev.gcodeLaserOff.join('\n'); + } // disable editing for non-local devices [ - UI.deviceName, - UI.gcodeHeader, - UI.gcodeFooter, - UI.gcodePause, - UI.deviceDepth, - UI.deviceWidth, - UI.deviceHeight, - UI.extrudeAbsolute, - UI.deviceOrigin, - UI.deviceOriginTop, - UI.deviceRound, - UI.gcodeFan, - UI.gcodeProgress, - UI.gcodeLayer, - UI.extruderFilament, - UI.extruderNozzle, - UI.deviceMaxSpindle, - UI.gcodeSpindle, - UI.gcodeDwell, - UI.gcodeToolChange, - UI.gcodeExtension, - UI.gcodeToken, - UI.gcodeStrip, - UI.gcodeLaserOn, - UI.gcodeLaserOff + UI.deviceName, + UI.gcodeHeader, + UI.gcodeFooter, + UI.gcodePause, + UI.deviceDepth, + UI.deviceWidth, + UI.deviceHeight, + UI.extrudeAbsolute, + UI.deviceOrigin, + UI.deviceOriginTop, + UI.deviceRound, + UI.gcodeFan, + UI.gcodeProgress, + UI.gcodeLayer, + UI.extFilament, + UI.extNozzle, + UI.deviceMaxSpindle, + UI.gcodeSpindle, + UI.gcodeDwell, + UI.gcodeToolChange, + UI.gcodeExtension, + UI.gcodeToken, + UI.gcodeStrip, + UI.gcodeLaserOn, + UI.gcodeLaserOff ].forEach(function(e) { e.disabled = !local; }); // hide spindle fields when device doens't support it - if (mode === 'CAM') - [ - UI.extrudeAbsolute, - UI.roughingSpindle, - UI.finishingSpindle, - UI.drillSpindle + if (mode === 'CAM') [ + UI.extrudeAbsolute, + UI.roughingSpindle, + UI.finishingSpindle, + UI.drillSpindle ].forEach(function(e) { - e.parentNode.style.display = dev.spindleMax >= 0 ? 'none' : 'block'; + e.parentNode.style.display = dev.spindleMax >= 0 ? 'none' : 'block'; }); UI.deviceSave.disabled = !local; @@ -693,9 +626,10 @@ var gs_kiri_init = exports; API.conf.save(); } catch (e) { console.log({error:e, device:code, devicename}); + throw e; API.show.alert(`invalid or deprecated device: "${devicename}"`, 10); API.show.alert(`please select a new device`, 10); - showDevices(); + // showDevices(); } API.function.clear(); API.event.settings(); @@ -727,13 +661,12 @@ var gs_kiri_init = exports; UI.deviceClose.onclick = API.dialog.hide; UI.deviceSave.onclick = function() { API.function.clear(); - updateDeviceCode(); API.conf.save(); showDevices(); }; UI.deviceAdd.onclick = function() { API.function.clear(); - updateDeviceCode(getSelectedDevice()+".copy"); + cloneDevice(); showDevices(); }; UI.deviceDelete.onclick = function() { @@ -787,11 +720,11 @@ var gs_kiri_init = exports; } showDevices(); }; - if (API.show.favorites()) { + // if (API.show.favorites()) { if (loc) opt.setAttribute("local", 1); - } else { - if (fav) opt.setAttribute("favorite", 1); - } + // } else { + if (loc || fav) opt.setAttribute("favorite", 1); + // } UI.deviceSelect.appendChild(opt); if (device === selected) { selectedIndex = incr; @@ -1200,14 +1133,14 @@ var gs_kiri_init = exports; deviceRound: UC.newBoolean(LANG.dv_bedc_s, onBooleanClick, {title:LANG.dv_bedc_l, modes:FDM}), extruder: UC.newGroup(LANG.dv_gr_ext, $('device'), {group:"dext", nocompact:true, modes:FDM}), - extruderFilament: UC.newInput(LANG.dv_fila_s, {title:LANG.dv_fila_l, convert:UC.toFloat, modes:FDM}), - extruderNozzle: UC.newInput(LANG.dv_nozl_s, {title:LANG.dv_nozl_l, convert:UC.toFloat, modes:FDM}), - extruderOffX: UC.newInput(LANG.dv_exox_s, {title:LANG.dv_exox_l, convert:UC.toFloat, modes:FDM, expert:true}), - extruderOffY: UC.newInput(LANG.dv_exoy_s, {title:LANG.dv_exoy_l, convert:UC.toFloat, modes:FDM, expert:true}), - extruderSelect: UC.newText(LANG.dv_exts_s, {title:LANG.dv_exts_l, modes:FDM, size:14, height:3, modes:FDM, expert:true}), - extruderDeselect: UC.newText(LANG.dv_extd_s, {title:LANG.dv_extd_l, modes:FDM, size:14, height:3, modes:FDM, expert:true}), + extFilament: UC.newInput(LANG.dv_fila_s, {title:LANG.dv_fila_l, convert:UC.toFloat, modes:FDM}), + extNozzle: UC.newInput(LANG.dv_nozl_s, {title:LANG.dv_nozl_l, convert:UC.toFloat, modes:FDM}), + extOffsetX: UC.newInput(LANG.dv_exox_s, {title:LANG.dv_exox_l, convert:UC.toFloat, modes:FDM, expert:true}), + extOffsetY: UC.newInput(LANG.dv_exoy_s, {title:LANG.dv_exoy_l, convert:UC.toFloat, modes:FDM, expert:true}), + extSelect: UC.newText(LANG.dv_exts_s, {title:LANG.dv_exts_l, modes:FDM, size:14, height:3, modes:FDM, expert:true}), + extDeselect: UC.newText(LANG.dv_extd_s, {title:LANG.dv_extd_l, modes:FDM, size:14, height:3, modes:FDM, expert:true}), extrudeAbsolute: UC.newBoolean(LANG.dv_xtab_s, onBooleanClick, {title:LANG.dv_xtab_l, modes:FDM}), - extruders: UC.newTableRow([[ + extActions: UC.newTableRow([[ UC.newButton("<", undefined), UC.newButton("+", undefined), UC.newButton("-", undefined), diff --git a/js/kiri.js b/js/kiri.js index 0a68b6d7..3cdd15c9 100644 --- a/js/kiri.js +++ b/js/kiri.js @@ -32,11 +32,11 @@ self.kiri.copyright = exports.COPYRIGHT; STATS = new Stats(SDB), SEED = 'kiri-seed', // --------------- - MODES = KIRI.conf.MODES, - VIEWS = KIRI.conf.VIEWS, - filter = KIRI.conf.filter, - settings = KIRI.conf.template, - settingsDefault = settings, + CONF = KIRI.conf, + MODES = CONF.MODES, + VIEWS = CONF.VIEWS, + settings = clone(CONF.template), + settingsDefault = clone(settings), // --------------- Widget = kiri.Widget, newWidget = kiri.newWidget, @@ -133,6 +133,7 @@ self.kiri.copyright = exports.COPYRIGHT; o2js: o2js, js2o: js2o, ajax: ajax, + clone: clone, focus: setFocus, stats: STATS, catalog: CATALOG, @@ -255,7 +256,7 @@ self.kiri.copyright = exports.COPYRIGHT; function Stats(db) { this.db = db; this.obj = js2o(this.db['stats'] || '{}'); - var o = this.obj, k; + let o = this.obj, k; for (k in o) { if (!o.hasOwnProperty(k)) continue; if (k === 'dn' || k.indexOf('-') > 0 || k.indexOf('_') > 0) { @@ -376,7 +377,7 @@ self.kiri.copyright = exports.COPYRIGHT; } function parseOpt(ov) { - var opt = {}, kv, kva; + let opt = {}, kv, kva; // handle kiri legacy and proper url encoding better ov.replace(/&/g,',').split(',').forEach(function(el) { kv = decodeURIComponent(el).split(':'); @@ -409,17 +410,6 @@ self.kiri.copyright = exports.COPYRIGHT; return js2o(SDB.getItem(key),def); } - function cull(o, f) { - for (var k in o) { - if (!o.hasOwnProperty(k)) { - continue; - } - if (!f.hasOwnProperty(k)) { - delete o[k]; - } - } - } - function setProgress(value, msg) { if (value) { value = UTIL.round(value*100,4); @@ -440,7 +430,7 @@ self.kiri.copyright = exports.COPYRIGHT; } function meshArray() { - var out = []; + let out = []; forAllWidgets(function(widget) { out.push(widget.mesh); }); @@ -479,7 +469,7 @@ self.kiri.copyright = exports.COPYRIGHT; } function updateSliderMax(set) { - var max = 0; + let max = 0; if (viewMode === VIEWS.PREVIEW && currentPrint) { max = currentPrint.getLayerCount(); } else { @@ -503,7 +493,7 @@ self.kiri.copyright = exports.COPYRIGHT; } function hideSlices() { - var showing = false; + let showing = false; setOpacity(color.model_opacity); forAllWidgets(function(widget) { widget.setWireframe(false); @@ -538,7 +528,7 @@ self.kiri.copyright = exports.COPYRIGHT; UI.layerID.value = layer; UI.layerSlider.value = layer; - var j, + let j, slice, slices, layers, @@ -640,7 +630,7 @@ self.kiri.copyright = exports.COPYRIGHT; function preparePrint(callback) { // kick off slicing it hasn't been done already - for (var i=0; i < WIDGETS.length; i++) { + for (let i=0; i < WIDGETS.length; i++) { if (!WIDGETS[i].slices || WIDGETS[i].isModified()) { prepareSlices(function() { if (!WIDGETS[i].slices || WIDGETS[i].isModified()) { @@ -725,7 +715,7 @@ self.kiri.copyright = exports.COPYRIGHT; setViewMode(VIEWS.SLICE); API.conf.save(); - var firstMesh = true, + let firstMesh = true, countdown = WIDGETS.length, preserveMax = API.var.layer_max, preserveLayer = API.var.layer_at, @@ -739,7 +729,7 @@ self.kiri.copyright = exports.COPYRIGHT; // for each widget, slice forAllWidgets(function(widget) { - var segtimes = {}, + let segtimes = {}, segNumber = 0, errored = false, startTime, @@ -748,7 +738,7 @@ self.kiri.copyright = exports.COPYRIGHT; widget.stats.progress = 0; widget.setColor(color.slicing); widget.slice(settings, function(sliced, error) { - var mark = UTIL.time(); + let mark = UTIL.time(); // on done widget.render(renderMode, MODE === MODES.CAM); // clear wireframe @@ -788,7 +778,7 @@ self.kiri.copyright = exports.COPYRIGHT; } }, function(update, msg) { if (msg !== lastMsg) { - var mark = UTIL.time(); + let mark = UTIL.time(); if (lastMsg) segtimes[segNumber+"_"+lastMsg] = mark - startTime; lastMsg = msg; startTime = mark; @@ -858,13 +848,13 @@ self.kiri.copyright = exports.COPYRIGHT; } function scaleSelection(ev) { - var dv = parseFloat(ev.target.value || 1); + let dv = parseFloat(ev.target.value || 1); if (UI.scaleUniform.checked) { UI.scaleX.value = dv; UI.scaleY.value = dv; UI.scaleZ.value = dv; } - var x = parseFloat(UI.scaleX.value || dv), + let x = parseFloat(UI.scaleX.value || dv), y = parseFloat(UI.scaleY.value || dv), z = parseFloat(UI.scaleZ.value || dv); forSelectedGroups(function (w) { @@ -941,7 +931,7 @@ self.kiri.copyright = exports.COPYRIGHT; } function platformUpdateSize() { - var dev = settings.device, + let dev = settings.device, width, depth, height = Math.round(Math.max(dev.bedHeight, dev.bedWidth/100, dev.bedDepth/100)); SPACE.platform.setRound(dev.bedRound); @@ -956,7 +946,7 @@ self.kiri.copyright = exports.COPYRIGHT; } function platformUpdateBounds() { - var bounds = new THREE.Box3(); + let bounds = new THREE.Box3(); forAllWidgets(function(widget) { let wp = widget.track.pos; let wb = widget.mesh.getBoundingBox().clone(); @@ -968,7 +958,7 @@ self.kiri.copyright = exports.COPYRIGHT; function platformSelect(widget, shift) { if (viewMode !== VIEWS.ARRANGE) return; - var mesh = widget.mesh, + let mesh = widget.mesh, sel = (selectedMeshes.indexOf(mesh) >= 0); if (sel) { if (shift) { @@ -1010,7 +1000,7 @@ self.kiri.copyright = exports.COPYRIGHT; }); return; } - var mesh = widget.mesh, + let mesh = widget.mesh, si = selectedMeshes.indexOf(mesh), sel = (si >= 0); if (sel) { @@ -1079,7 +1069,7 @@ self.kiri.copyright = exports.COPYRIGHT; return; } if (Array.isArray(widget)) { - var mc = widget.slice(), i; + let mc = widget.slice(), i; for (i=0; i1 widget, force layout with spacing @ 1.5x largest tool diameter if (MODE === MODES.CAM && WIDGETS.length > 1) { - var spacing = space || 1, CAM = KIRI.driver.CAM; + let spacing = space || 1, CAM = KIRI.driver.CAM; if (proc.roughingOn) spacing = Math.max(spacing, CAM.getToolDiameter(settings, proc.roughingTool)); if (proc.finishingOn || proc.finishingXOn || proc.finishingYOn) spacing = Math.max(spacing, CAM.getToolDiameter(settings, proc.finishingTool)); gap = spacing * 1.5; } - var i, m, sz = SPACE.platform.size(), + let i, m, sz = SPACE.platform.size(), mp = [sz.x, sz.y], ms = [mp[0] / 2, mp[1] / 2], mi = mp[0] > mp[1] ? [(mp[0] / mp[1]) * 10, 10] : [10, (mp[1] / mp[1]) * 10], @@ -1213,9 +1203,9 @@ self.kiri.copyright = exports.COPYRIGHT; $('stock-height').innerText = (csz/scale).toFixed(2); } if (!camStock) { - var geo = new THREE.BoxGeometry(1, 1, 1); - var mat = new THREE.MeshBasicMaterial({ color: 0x777777, opacity: 0.2, transparent: true, side:THREE.DoubleSide }); - var cube = new THREE.Mesh(geo, mat); + let geo = new THREE.BoxGeometry(1, 1, 1); + let mat = new THREE.MeshBasicMaterial({ color: 0x777777, opacity: 0.2, transparent: true, side:THREE.DoubleSide }); + let cube = new THREE.Mesh(geo, mat); SPACE.platform.add(cube); camStock = cube; } @@ -1247,66 +1237,32 @@ self.kiri.copyright = exports.COPYRIGHT; * Settings Functions ******************************************************************* */ - function resetSettings(force) { - if (force || confirm('reset all values to system defaults?')) { - settings = settingsDefault; - updateFields(); - }; - } - - /** - * fill in missing settings from default template to pick up new fields - * that may have been recently added and expected in the code - * - * @param {Object} osrc - * @param {Object} odst - */ - function fillMissingSettings(osrc, odst) { - var key, val; - for (key in osrc) { - if (!osrc.hasOwnProperty(key)) continue; - val = odst[key]; - if (typeof val === 'undefined' || val === null || val === '') { - odst[key] = osrc[key]; - } else if (typeof osrc[key] === 'object') { - fillMissingSettings(osrc[key], odst[key]); - } - } - } - - /** - * @returns {Object} - */ + // given a settings region, update values of matching bound UI fields function updateFieldsFromSettings(scope) { if (!scope) return console.trace("missing scope"); - var key, val; + // CONF.normalize(settings); - fillMissingSettings(settingsDefault, settings); - settings.infill = settingsDefault.infill; - settings.units = settingsDefault.units; - - for (key in scope) { + for (let key in scope) { if (!scope.hasOwnProperty(key)) continue; - val = scope[key]; + let val = scope[key]; if (UI.hasOwnProperty(key)) { - var uie = UI[key], - typ = uie ? uie.type : null; + let uie = UI[key], typ = uie ? uie.type : null; if (typ === 'text') { uie.value = val; } else if (typ === 'checkbox') { uie.checked = val; } else if (typ === 'select-one') { uie.innerHTML = ''; - var chosen = null; - var source = uie.parentNode.getAttribute('source'); - var list = settings[source]; + let source = uie.parentNode.getAttribute('source'), + list = settings[source], + chosen = null; list.forEach(function(tool, index) { let id = tool.id || tool.name; if (val === id) { chosen = index + 1; } - var opt = DOC.createElement('option'); + let opt = DOC.createElement('option'); opt.appendChild(DOC.createTextNode(tool.name)); opt.setAttribute('value', id); uie.appendChild(opt); @@ -1315,8 +1271,6 @@ self.kiri.copyright = exports.COPYRIGHT; } } } - - return settings; } /** @@ -1325,17 +1279,19 @@ self.kiri.copyright = exports.COPYRIGHT; function updateSettingsFromFields(scope) { if (!scope) return console.trace("missing scope"); - var key, - changed = false; + let key, changed = false; // for each key in scope object for (key in scope) { - if (!scope.hasOwnProperty(key)) continue; + if (!scope.hasOwnProperty(key)) { + continue; + } if (UI.hasOwnProperty(key)) { - var nval = null, - uie = UI[key]; + let nval = null, uie = UI[key]; // skip empty UI values - if (!uie || uie === '') continue; + if (!uie || uie === '') { + continue; + } if (uie.type === 'text') { nval = UI[key].convert(); } else if (uie.type === 'checkbox') { @@ -1348,6 +1304,8 @@ self.kiri.copyright = exports.COPYRIGHT; nval = parseInt(nval); } } + } else { + continue; } if (scope[key] != nval) { scope[key] = nval; @@ -1366,6 +1324,10 @@ self.kiri.copyright = exports.COPYRIGHT; updateFieldsFromSettings(settings.process); updateFieldsFromSettings(settings.layers); updateFieldsFromSettings(settings.controller); + let device = settings.device; + if (device.extruders && device.extruders[device.internal]) { + updateFieldsFromSettings(device.extruders[device.internal]); + } } function updateSettings() { @@ -1373,33 +1335,19 @@ self.kiri.copyright = exports.COPYRIGHT; updateSettingsFromFields(settings.process); updateSettingsFromFields(settings.layers); updateSettingsFromFields(settings.controller); + let device = settings.device; + if (device.extruders && device.extruders[device.internal]) { + updateSettingsFromFields(device.extruders[device.internal]); + } API.conf.save(); platform.update_stock(); } function saveSettings() { - // remove settings invalid for a given mode (cleanup) - cull(settings, settingsDefault); - switch (settings.mode) { - case 'FDM': - cull(settings.device, filter.fdm.d); - cull(settings.process, filter.fdm.p); - break; - case 'CAM': - cull(settings.device, filter.cam.d); - cull(settings.process, filter.cam.p); - break; - case 'LASER': - cull(settings.device, filter.laser.d); - cull(settings.process, filter.laser.p); - settings.cdev.LASER = clone(settings.device); - break; - } - cull(settings.cdev.FDM, filter.fdm.d); - cull(settings.cdev.CAM, filter.cam.d); // store camera view let view = SPACE.view.save(); if (view.left || view.up) settings.controller.view = view; + // CONF.normalize(settings); SDB.setItem('ws-settings', JSON.stringify(settings)); } @@ -1408,19 +1356,20 @@ self.kiri.copyright = exports.COPYRIGHT; try { data = JSON.parse(atob(data)); } catch (e) { - console.log({data}) alert('invalid settings format'); + console.log('data',data); return; } } - if (!(data.settings && data.moto && data.time)) { + if (!(data.settings && data.version && data.time)) { alert('invalid settings format'); + console.log('data',data); return; } if (ask && !confirm(`Import settings made on ${new Date(data.time)} from Kiri:Moto version ${data.version}?`)) { return; } - settings = data.settings; + settings = CONF.normalize(data.settings); // MOTO.restore(data.moto); // SDB.setItem('kiri-init', data.init || 2); API.conf.save(); @@ -1479,7 +1428,7 @@ self.kiri.copyright = exports.COPYRIGHT; function saveWorkspace() { API.conf.save(); - var newWidgets = [], + let newWidgets = [], oldWidgets = js2o(SDB.getItem('ws-widgets'), []); forAllWidgets(function(widget) { newWidgets.push(widget.id); @@ -1494,12 +1443,11 @@ self.kiri.copyright = exports.COPYRIGHT; } function restoreSettings(save) { - var newset = ls2o('ws-settings'), + let newset = ls2o('ws-settings'), camera = ls2o('ws-camera'); if (newset) { - fillMissingSettings(settingsDefault, newset); - settings = newset; + settings = CONF.normalize(newset); // override camera from settings if (settings.controller.view) { camera = settings.controller.view; @@ -1508,7 +1456,7 @@ self.kiri.copyright = exports.COPYRIGHT; } // merge custom filters from localstorage into settings localFilters.forEach(function(fname) { - var fkey = "gcode-filter-"+fname, ov = ls2o(fkey); + let fkey = "gcode-filter-"+fname, ov = ls2o(fkey); if (ov) settings.devices[fname] = ov; SDB.removeItem(fkey) }); @@ -1573,7 +1521,7 @@ self.kiri.copyright = exports.COPYRIGHT; } function modalShowing() { - var showing = $('modal').style.display !== 'none'; + let showing = $('modal').style.display !== 'none'; return showing || UC.isPopped(); } @@ -1594,7 +1542,7 @@ self.kiri.copyright = exports.COPYRIGHT; return; } ["catalog","devices","tools","settings"].forEach(function(dialog) { - var style = UI[dialog].style; + let style = UI[dialog].style; style.display = (dialog === which && (force || style.display !== 'flex') ? 'flex' : 'none'); }); } @@ -1608,13 +1556,13 @@ self.kiri.copyright = exports.COPYRIGHT; } function putSettings(newset) { - settings = newset; + settings = CONF.normalize(newset); API.conf.save() API.space.restore(null, true); } function editSettings(e) { - var mode = getMode(), + let mode = getMode(), name = e.target.getAttribute("name"), load = settings.sproc[mode][name], edit = prompt(`settings for "${name}"`, JSON.stringify(load)); @@ -1633,19 +1581,12 @@ self.kiri.copyright = exports.COPYRIGHT; } function loadSettings(e, named) { - var mode = getMode(), + let mode = getMode(), name = e ? e.target.getAttribute("load") : named || settings.cproc[mode], load = settings.sproc[mode][name]; if (!load) return; - for (var k in load) { - if (!load.hasOwnProperty(k)) continue; - // prevent stored process from overwriting device defaults - //if (k === "outputOriginCenter" && mode == "FDM") continue; - settings.process[k] = load[k]; - } - settings.process.processName = name; settings.cproc[mode] = name; @@ -1662,16 +1603,17 @@ self.kiri.copyright = exports.COPYRIGHT; settings.process.outputOriginCenter = (settings.device.originCenter || false); } - updateFields(); if (!named) { hideDialog(); } + + updateFields(); API.conf.update(); if (e) triggerSettingsEvent(); } function deleteSettings(e) { - var name = e.target.getAttribute("del"); + let name = e.target.getAttribute("del"); delete settings.sproc[getMode()][name]; updateSettingsList(); API.conf.save(); @@ -1679,13 +1621,13 @@ self.kiri.copyright = exports.COPYRIGHT; } function updateSettingsList() { - var list = [], s = settings, sp = s.sproc[getMode()] || {}, table = UI.settingsList; + let list = [], s = settings, sp = s.sproc[getMode()] || {}, table = UI.settingsList; table.innerHTML = ''; - for (var k in sp) { + for (let k in sp) { if (sp.hasOwnProperty(k)) list.push(k); } list.sort().forEach(function(sk) { - var row = DOC.createElement('div'), + let row = DOC.createElement('div'), load = DOC.createElement('button'), edit = DOC.createElement('button'), del = DOC.createElement('button'), @@ -1788,7 +1730,7 @@ self.kiri.copyright = exports.COPYRIGHT; function setFocus(el) { el = [ el || UI.load, UI.import, UI.ctrlLeft, UI.container, UI.assets, UI.control, UI.modeFDM, UI.reverseZoom, UI.modelOpacity, DOC.body ]; - for (var es, i=0; i - All Rights Reserved", LICENSE:"See the license.md file included with the source distribution", - VERSION:"1.8.2" + VERSION:"1.8.3" }; if (!module) var module = {}; module.exports = exports; diff --git a/js/moto-space.js b/js/moto-space.js index 36769811..bf491afc 100644 --- a/js/moto-space.js +++ b/js/moto-space.js @@ -567,7 +567,6 @@ var MOTO = window.moto = window.moto || {}; setColor: setPlatformColor, setOrigin: setOrigin, setGrid: setGrid, - add: function(o) { WORLD.add(o) }, remove: function(o) { WORLD.remove(o) }, setMaxZ: function(z) { panY = z / 2 }, @@ -577,16 +576,13 @@ var MOTO = window.moto = window.moto || {}; setZOff: function(z) { platformZOff = z; updatePlatformPosition() }, setGZOff: function(z) { gridZOff = z; updatePlatformPosition() }, opacity: function(o) { platform.material.opacity = o }, - onMove: function(f) { platformOnMove = f }, onHover: function(f) { platformHover = f }, onClick: function(f) { platformClick = f}, - size: function() { return platform.scale }, isVisible: function() { return platform.visible }, showGrid: function(b) { gridView.visible = b }, - - setRound: function(bool) { + setRound: function(bool) { let current = platform; isRound = bool; if (bool) { diff --git a/notes.md b/notes.md index 10c632a6..283c4e9e 100644 --- a/notes.md +++ b/notes.md @@ -38,6 +38,7 @@ * `B` fails in pancaking (clone) when there are no sliced layers (like z bottom too high) * `B` linear finishing should extend beyond part boundaries by tool radius * `B` outside cutting direction in roughing mode inverted +* `F` use arcs to connect hard angles * `F` do not rough areas that go all the way through the part https://github.com/GridSpace/grid-apps/issues/20 * `F` send gcode to cncjs diff --git a/web/kiri/filter/FDM/Any.Generic.Marlin b/web/kiri/filter/FDM/Any.Generic.Marlin index a9628c60..fa5ffe79 100644 --- a/web/kiri/filter/FDM/Any.Generic.Marlin +++ b/web/kiri/filter/FDM/Any.Generic.Marlin @@ -24,24 +24,20 @@ "G28 X0 Y0 ; home XY axes", "M84 ; disable stepper motors" ], - "extruder":[ + "extruders":[ { "nozzle": 0.4, "filament": 1.75, "offset_x": 0, "offset_y": 0, - "select": [ - "T0" - ], + "select": [ "T0" ], "deselect": [] - }, + },{ "nozzle": 0.4, "filament": 1.75, "offset_x": 30, "offset_y": 0, - "select": [ - "T1" - ], + "select": [ "T1" ], "deselect": [] } ], diff --git a/web/kiri/style.css b/web/kiri/style.css index 3fd32296..e7a7ad14 100644 --- a/web/kiri/style.css +++ b/web/kiri/style.css @@ -473,6 +473,11 @@ button.selected { #devices-body { height: 100%; } +#device .tablerow button { + margin: 5px 3px 5px 3px; + padding-top: 0; + padding-bottom: 2px; +} #device-labels span { width: 200px; padding: 2px 5px 2px 5px; diff --git a/web/moto/style.css b/web/moto/style.css index 02529017..8e76efc8 100644 --- a/web/moto/style.css +++ b/web/moto/style.css @@ -237,6 +237,23 @@ th, tr, td, span, div, label, button { * ID ******************************************************************* */ +.dark #appid span { + border-color: #555; + background-color: rgba(100,120,150,0.75); + color: #eee; +} +.dark #appid a { + color: #eee; +} +.dark #appid a:hover { + color: #eee; +} +.dark #appid span:hover { + background-color: rgba(80,100,230,0.75); +} +.dark #langpop { + color: black; +} #appid { text-align: center; position: fixed; @@ -335,10 +352,9 @@ th, tr, td, span, div, label, button { background-color: rgba(100,120,150,0.75); border: 1px solid #555; color: #eee; - xfont-weight: normal; } .dark .compact .grouphead:hover { - background-color: rgba(80,100,180,0.75); + background-color: rgba(80,100,230,0.75); } .dark .compact.control { background-color: rgba(128,128,128,0.2) !important;