make cli a more fully featured command line utility refs #199

This commit is contained in:
Stewart Allen 2022-02-11 11:50:34 -05:00
commit 90cf2b038e
5 changed files with 338 additions and 245 deletions

View file

@ -0,0 +1,64 @@
{
"noclone":false,
"mode":"FDM",
"internal":0,
"imageURL":"",
"imageScale":0.75,
"imageAnchor":0,
"bedHeight":2.5,
"bedWidth":220,
"bedDepth":220,
"bedRound":false,
"bedBelt":false,
"maxHeight":300,
"originCenter":false,
"extrudeAbs":true,
"spindleMax":0,
"gcodeFan":[ "M106 S{fan_speed}" ],
"gcodeTrack":[],
"gcodeLayer":[],
"gcodePre":[
"M107 ; turn off filament cooling fan",
"G90 ; set absolute positioning mode",
"M82 ; set absolute positioning for extruder",
"M104 S{temp} T{tool} ; set extruder temperature",
"M140 S{bed_temp} T{tool} ; set bed temperature",
"G28 ; home axes",
"G92 X0 Y0 Z0 E0 ; reset all axes positions",
"G1 X0 Y0 Z0.25 F180 ; move XY to 0,0 and Z 0.25mm over bed",
"G92 E0 ; zero the extruded",
"M190 S{bed_temp} T{tool} ; wait for bed to reach target temp",
"M109 S{temp} T{tool} ; wait for extruder to reach target temp",
"G92 E0 ; zero the extruded",
"G1 F225 ; set feed speed"
],
"gcodePost":[
"M107 ; turn off filament cooling fan",
"M104 S0 T{tool} ; turn off right extruder",
"M140 S0 T{tool} ; turn off bed",
"G1 X0 Y300 F1200 ; end move",
"M84 ; disable stepper motors"
],
"gcodeProc":"",
"gcodePause":[],
"gcodeDwell":[],
"gcodeSpindle":[],
"gcodeChange":[],
"gcodeFExt":"gcode",
"gcodeSpace":true,
"gcodeStrip":false,
"gcodeLaserOn":[],
"gcodeLaserOff":[],
"extruders":[
{
"extFilament":1.75,
"extNozzle":0.4,
"extSelect":[ "T0" ],
"extDeselect":[],
"extOffsetX":0,
"extOffsetY":0
}
],
"new":false,
"deviceName":"Creality.Ender.3"
}

View file

@ -0,0 +1,70 @@
{
"sName":"Ender3_test",
"sliceHeight":0.25,
"sliceShells":3,
"sliceShellOrder":"in-out",
"sliceLayerStart":"last",
"sliceFillAngle":45,
"sliceFillOverlap":0.3,
"sliceFillSparse":0.2,
"sliceFillType":"gyroid",
"sliceAdaptive":false,
"sliceMinHeight":0,
"sliceSupportDensity":0.25,
"sliceSupportOffset":0.4,
"sliceSupportGap":1,
"sliceSupportSize":6,
"sliceSupportArea":1,
"sliceSupportExtra":0,
"sliceSupportAngle":50,
"sliceSupportNozzle":0,
"sliceSolidMinArea":1,
"sliceSolidLayers":3,
"sliceBottomLayers":3,
"sliceTopLayers":3,
"firstLayerRate":10,
"firstLayerPrintMult":1.15,
"firstLayerYOffset":0,
"firstLayerBrim":0,
"firstLayerBeltLead":3,
"outputTemp":210,
"outputBedTemp":60,
"outputFeedrate":50,
"outputFinishrate":50,
"outputSeekrate":80,
"outputShellMult":1.25,
"outputFillMult":1.25,
"outputSparseMult":1.25,
"outputRetractDist":4,
"outputRetractSpeed":30,
"outputRetractDwell":30,
"outputShortPoly":100,
"outputMinSpeed":10,
"outputCoastDist":0.1,
"outputLayerRetract":true,
"detectThinWalls":true,
"zHopDistance":0,
"antiBacklash":0,
"outputOriginCenter":false,
"sliceFillRate":0,
"sliceSupportEnable":false,
"firstSliceHeight":0.25,
"firstLayerFillRate":35,
"firstLayerLineMult":1,
"firstLayerNozzleTemp":0,
"firstLayerBedTemp":0,
"firstLayerBrimTrig":0,
"outputRaft":false,
"outputRaftSpacing":0.2,
"outputRetractWipe":0,
"outputBrimCount":2,
"outputBrimOffset":2,
"outputLoopLayers":null,
"outputInvertX":false,
"outputInvertY":false,
"arcTolerance":0,
"gcodePause":"",
"ranges":[],
"firstLayerFanSpeed":0,
"outputFanSpeed":255
}

52
src/cli/kiri-source.json Normal file
View file

@ -0,0 +1,52 @@
[
"main/gapp",
"moto/license",
"main/kiri",
"ext/three",
"ext/pngjs",
"ext/jszip",
"ext/clip2",
"ext/earcut",
"add/array",
"add/three",
"add/class",
"geo/base",
"geo/point",
"geo/points",
"geo/slope",
"geo/line",
"geo/bounds",
"geo/polygons",
"geo/polygon",
"geo/gyroid",
"kiri/conf",
"kiri/pack",
"kiri/client",
"kiri/engine",
"kiri/slice",
"kiri/slicer",
"kiri/layers",
"kiri-mode/fdm/fill",
"kiri-mode/fdm/driver",
"kiri-mode/fdm/slice",
"kiri-mode/fdm/prepare",
"kiri-mode/fdm/export",
"kiri-mode/sla/driver",
"kiri-mode/sla/slice",
"kiri-mode/sla/export",
"kiri-mode/cam/driver",
"kiri-mode/cam/slicer",
"kiri-mode/cam/ops",
"kiri-mode/cam/tool",
"kiri-mode/cam/topo",
"kiri-mode/cam/slice",
"kiri-mode/cam/prepare",
"kiri-mode/cam/export",
"kiri-mode/cam/animate",
"kiri-mode/laser/driver",
"kiri/widget",
"kiri/print",
"kiri/codec",
"kiri/worker",
"load/stl"
]

View file

@ -1,60 +1,54 @@
/** example of how to use Kiri:Moto's slicer engine from the command-line */ /** example of how to use Kiri:Moto's slicer engine from the command-line */
let fs = require('fs'); let fs = require('fs');
let args = process.argv.slice(2); let args = process.argv.slice(2);
let dir = args[0] || "."; let opts = {
let files = [ dir: ".",
"main/gapp", output: "-",
"moto/license", model: "/web/obj/cube.stl",
"main/kiri", source: "/src/cli/kiri-source.json",
"ext/three", process: "/src/cli/kiri-fdm-process.json",
"ext/pngjs", device: "/src/cli/kiri-fdm-device.json",
"ext/jszip", };
"ext/clip2", for (let i=0; i<args.length; i++) {
"ext/earcut", let arg = args[i].split('=');
"add/array", let [ key, val ] = arg;
"add/three", if (arg.length === 2) {
"add/class", key = arg[0];
"geo/base", val = arg[1];
"geo/point", } else if (key.indexOf('--') === 0) {
"geo/points", val = true;
"geo/slope", } else if (key.indexOf('-') === 0) {
"geo/line", val = args[++i];
"geo/bounds", } else {
"geo/polygons", val = undefined;
"geo/polygon", }
"geo/gyroid", if (key && val) {
"kiri/conf", key = key.replace(/-/g,'');
"kiri/pack", opts[key.trim()] = val;
"kiri/client", } else {
"kiri/engine", key = "model";
"kiri/slice", val = arg;
"kiri/slicer", }
"kiri/layers", }
"kiri-mode/fdm/fill", if (opts.help) {
"kiri-mode/fdm/driver", console.log([
"kiri-mode/fdm/slice", "cli <options> <file>",
"kiri-mode/fdm/prepare", " --verbose | enable verbose logging",
"kiri-mode/fdm/export", " --dir=[dir] | root directory for file paths (default: '.')",
"kiri-mode/sla/driver", " --model=[file] | model file to load (or last parameter)",
"kiri-mode/sla/slice", " --source=[file] | source file list (defaults to kiri engine)",
"kiri-mode/sla/export", " --device=[file] | device definition file (json)",
"kiri-mode/cam/driver", " --process=[file] | process definition file (json)",
"kiri-mode/cam/slicer", " --output=[file] | gcode output to file or '-' for stdout",
"kiri-mode/cam/ops", " --position=x,y,z | move loaded model to position x,y,z",
"kiri-mode/cam/tool", " --rotate=x,y,z | rotate loaded model x,y,z radians",
"kiri-mode/cam/topo", " --scale=x,y,z | scale loaded model in x,y,z",
"kiri-mode/cam/slice", " --move=x,y,z | move loaded model x,y,z millimeters"
"kiri-mode/cam/prepare", ].join("\r\n"));
"kiri-mode/cam/export", return;
"kiri-mode/cam/animate", }
"kiri-mode/laser/driver",
"kiri/widget",
"kiri/print",
"kiri/codec",
"kiri/worker",
"load/stl"
].map(p => `${dir}/src/${p}.js`);
let { dir, verbose, model, output, position, move, scale, rotate } = opts;
let exports_save = exports, let exports_save = exports,
navigator = { userAgent: "" }, navigator = { userAgent: "" },
module_save = module, module_save = module,
@ -72,11 +66,20 @@ let exports_save = exports,
}; };
// fake fetch for worker to get wasm, if needed // fake fetch for worker to get wasm, if needed
let fetch = function(url) { let fetch = function(url, opts = {}) {
console.log({fake_fetch: url}); if (verbose) console.log({fetch: url});
let buf = fs.readFileSync(dir + url); let buf = fs.readFileSync(dir + url);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => { resolve(new Promise((resolve, reject) => {
if (opts.format === 'string') {
return resolve(buf.toString());
}
if (opts.format === 'buffer') {
return resolve(buf);
}
if (opts.format === 'eval') {
return resolve(eval('(' + buf + ')'));
}
resolve({ resolve({
arrayBuffer: function() { arrayBuffer: function() {
return buf; return buf;
@ -89,7 +92,7 @@ let fetch = function(url) {
// imitate worker process // imitate worker process
class Worker { class Worker {
constructor(url) { constructor(url) {
console.log({fake_worker: url}); if (verbose) console.log({worker: url});
} }
postMessage(msg) { postMessage(msg) {
@ -118,197 +121,97 @@ function btoa(b) {
return Buffer.from(b, 'base64').toString(); return Buffer.from(b, 'base64').toString();
} }
for (let file of files) { async function run() {
let isPNG = file.indexOf("/pngjs") > 0; let files = await fetch(opts.source, { format: "eval" } );
let isClip = file.indexOf("/clip") > 0; let device = await fetch(opts.device, { format: "eval" } );
let isEarcut = file.indexOf("/earcut") > 0; let process = await fetch(opts.process, { format: "eval" } );
let isTHREE = file.indexOf("/three") > 0;
if (isTHREE) { for (let file of files.map(p => `${dir}/src/${p}.js`)) {
// THREE.js kung-fu fake-out let isPNG = file.indexOf("/pngjs") > 0;
exports = {}; let isClip = file.indexOf("/clip") > 0;
} let isEarcut = file.indexOf("/earcut") > 0;
let swapMod = isEarcut; let isTHREE = file.indexOf("/three") > 0;
if (swapMod) { if (isTHREE) {
module = { exports: {} }; // THREE.js kung-fu fake-out
} exports = {};
let clearMod = isPNG || isClip; }
if (clearMod) { let swapMod = isEarcut;
module = undefined; if (swapMod) {
} module = { exports: {} };
try { }
console.log(`loading ... ${dir}/${file}`); let clearMod = isPNG || isClip;
eval(fs.readFileSync(dir + "/" + file).toString()); if (clearMod) {
} catch (e) { module = undefined;
throw e; }
} try {
if (isClip) { if (verbose) console.log(`loading ... ${dir}/${file}`);
ClipperLib = self.ClipperLib; eval(fs.readFileSync(dir + "/" + file).toString());
} } catch (e) {
if (isTHREE) { throw e;
Object.assign(THREE, exports); }
// restore exports after faking out THREE.js if (isClip) {
exports = exports_save; ClipperLib = self.ClipperLib;
} }
if (isEarcut) { if (isTHREE) {
self.earcut = module.exports; Object.assign(THREE, exports);
} // restore exports after faking out THREE.js
if (clearMod || swapMod) { exports = exports_save;
module = module_save; }
if (isEarcut) {
self.earcut = module.exports;
}
if (clearMod || swapMod) {
module = module_save;
}
} }
let { kiri, moto, load } = self;
console.log({version: kiri.version});
let engine = kiri.newEngine();
let data = await fetch(model)
let buf = data.arrayBuffer().buffer;
return engine.parse(buf)
.then(data => { if (verbose) console.log({loaded: data}) })
.then(() => {
if (position) {
let [ x, y, z ] = position.split(',').map(v => parseFloat(v || 0));
if (verbose) console.log('moveTo', {x, y, z});
engine.moveTo(x,y,z);
}
if (move) {
let [ x, y, z ] = move.split(',').map(v => parseFloat(v || 0));
if (verbose) console.log('move', {x, y, z});
engine.move(x,y,z);
}
if (scale) {
let [ x, y, z ] = scale.split(',').map(v => parseFloat(v || 0));
if (verbose) console.log('scale', {x, y, z});
engine.scale(x,y,z);
}
if (rotate) {
let [ x, y, z ] = rotate.split(',').map(v => parseFloat(v || 0));
if (verbose) console.log('rotate', {x, y, z});
engine.rotate(x,y,z);
}
})
.then(() => engine.setProcess(process))
.then(() => engine.setDevice(device))
.then(eng => eng.slice())
.then(eng => eng.prepare())
.then(eng => engine.export())
.then(gcode => {
if (output === '-') {
console.log({gcode});
} else {
fs.writeFileSync(output, gcode);
}
})
.catch(error => {
console.log({error});
});
} }
let { kiri, moto, load } = self; run();
let engine = kiri.newEngine();
fetch('/web/obj/cube.stl').then(data => {
console.log({version: kiri.version});
let buf = data.arrayBuffer().buffer;
engine.parse(buf)
.then(data => {
console.log({loaded: data});
})
.then(() => engine.moveTo(1,1,1))
.then(() => engine.setProcess({
"sName":"Ender3_test",
"sliceHeight":0.25,
"sliceShells":3,
"sliceShellOrder":"in-out",
"sliceLayerStart":"last",
"sliceFillAngle":45,
"sliceFillOverlap":0.3,
"sliceFillSparse":0.2,
"sliceFillType":"gyroid",
"sliceAdaptive":false,
"sliceMinHeight":0,
"sliceSupportDensity":0.25,
"sliceSupportOffset":0.4,
"sliceSupportGap":1,
"sliceSupportSize":6,
"sliceSupportArea":1,
"sliceSupportExtra":0,
"sliceSupportAngle":50,
"sliceSupportNozzle":0,
"sliceSolidMinArea":1,
"sliceSolidLayers":3,
"sliceBottomLayers":3,
"sliceTopLayers":3,
"firstLayerRate":10,
"firstLayerPrintMult":1.15,
"firstLayerYOffset":0,
"firstLayerBrim":0,
"firstLayerBeltLead":3,
"outputTemp":210,
"outputBedTemp":60,
"outputFeedrate":50,
"outputFinishrate":50,
"outputSeekrate":80,
"outputShellMult":1.25,
"outputFillMult":1.25,
"outputSparseMult":1.25,
"outputRetractDist":4,
"outputRetractSpeed":30,
"outputRetractDwell":30,
"outputShortPoly":100,
"outputMinSpeed":10,
"outputCoastDist":0.1,
"outputLayerRetract":true,
"detectThinWalls":true,
"zHopDistance":0,
"antiBacklash":0,
"outputOriginCenter":false,
"sliceFillRate":0,
"sliceSupportEnable":false,
"firstSliceHeight":0.25,
"firstLayerFillRate":35,
"firstLayerLineMult":1,
"firstLayerNozzleTemp":0,
"firstLayerBedTemp":0,
"firstLayerBrimTrig":0,
"outputRaft":false,
"outputRaftSpacing":0.2,
"outputRetractWipe":0,
"outputBrimCount":2,
"outputBrimOffset":2,
"outputLoopLayers":null,
"outputInvertX":false,
"outputInvertY":false,
"arcTolerance":0,
"gcodePause":"",
"ranges":[],
"firstLayerFanSpeed":0,
"outputFanSpeed":255
}))
.then(() => engine.setDevice({
"noclone":false,
"mode":"FDM",
"internal":0,
"imageURL":"",
"imageScale":0.75,
"imageAnchor":0,
"bedHeight":2.5,
"bedWidth":220,
"bedDepth":220,
"bedRound":false,
"bedBelt":false,
"maxHeight":300,
"originCenter":false,
"extrudeAbs":true,
"spindleMax":0,
"gcodeFan":[ "M106 S{fan_speed}" ],
"gcodeTrack":[],
"gcodeLayer":[],
"gcodePre":[
"M107 ; turn off filament cooling fan",
"G90 ; set absolute positioning mode",
"M82 ; set absolute positioning for extruder",
"M104 S{temp} T{tool} ; set extruder temperature",
"M140 S{bed_temp} T{tool} ; set bed temperature",
"G28 ; home axes",
"G92 X0 Y0 Z0 E0 ; reset all axes positions",
"G1 X0 Y0 Z0.25 F180 ; move XY to 0,0 and Z 0.25mm over bed",
"G92 E0 ; zero the extruded",
"M190 S{bed_temp} T{tool} ; wait for bed to reach target temp",
"M109 S{temp} T{tool} ; wait for extruder to reach target temp",
"G92 E0 ; zero the extruded",
"G1 F225 ; set feed speed"
],
"gcodePost":[
"M107 ; turn off filament cooling fan",
"M104 S0 T{tool} ; turn off right extruder",
"M140 S0 T{tool} ; turn off bed",
"G1 X0 Y300 F1200 ; end move",
"M84 ; disable stepper motors"
],
"gcodeProc":"",
"gcodePause":[],
"gcodeDwell":[],
"gcodeSpindle":[],
"gcodeChange":[],
"gcodeFExt":"gcode",
"gcodeSpace":true,
"gcodeStrip":false,
"gcodeLaserOn":[],
"gcodeLaserOff":[],
"extruders":[
{
"extFilament":1.75,
"extNozzle":0.4,
"extSelect":[ "T0" ],
"extDeselect":[],
"extOffsetX":0,
"extOffsetY":0
}
],
"new":false,
"deviceName":"Creality.Ender.3"
}))
.then(eng => eng.slice())
.then(eng => eng.prepare())
.then(eng => engine.export())
.then(gcode => {
console.log({gcode});
})
.catch(error => {
console.log({error});
});
});

View file

@ -954,6 +954,10 @@ console.log/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
}; };
PRO.setWireframe = function(set, color, opacity) { PRO.setWireframe = function(set, color, opacity) {
if (!(KIRI.api && KIRI.api.conf)) {
// missing api features in engine mode
return;
}
let mesh = this.mesh, let mesh = this.mesh,
widget = this; widget = this;
if (this.wire) { if (this.wire) {