add missing src2/kiri
This commit is contained in:
parent
7d22cc1029
commit
c9667476ee
34 changed files with 15187 additions and 0 deletions
344
src2/kiri/client.js
Normal file
344
src2/kiri/client.js
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from './api.js';
|
||||
import { noop } from './utils.js';
|
||||
import { version } from '../moto/license.js';
|
||||
|
||||
// this code runs in kiri's main loop
|
||||
let debug = self.debug === true,
|
||||
time = Date.now,
|
||||
seqid = 1,
|
||||
syncd = {},
|
||||
running = {},
|
||||
worker = null,
|
||||
minions = false,
|
||||
restarting = false;
|
||||
|
||||
/**
|
||||
* @param {Function} fn name of function in kiri.worker
|
||||
* @param {Object} data to send to server
|
||||
* @param {Function} onreply function to call on reply messages
|
||||
* @param {Object[]} zerocopy array of objects to pass using zerocopy
|
||||
*/
|
||||
function send(fn, data, onreply, zerocopy) {
|
||||
let seq = seqid++;
|
||||
|
||||
if (onreply) {
|
||||
// track it only when we expect and can handle a reply
|
||||
running[seq] = { fn:onreply };
|
||||
}
|
||||
let msg = {
|
||||
seq: seq,
|
||||
task: fn,
|
||||
time: time(),
|
||||
data: data
|
||||
};
|
||||
// console.log('client send', msg);
|
||||
// if (!fn) { console.trace({empty_fn: data}) };
|
||||
try {
|
||||
worker.postMessage(msg, zerocopy);
|
||||
} catch (error) {
|
||||
console.trace('work send error', {data, error});
|
||||
}
|
||||
}
|
||||
|
||||
// code is running in the browser / client context
|
||||
export const client = {
|
||||
send: send,
|
||||
|
||||
pool: {
|
||||
start() {
|
||||
minions = true;
|
||||
send("pool_start", {}, noop);
|
||||
},
|
||||
|
||||
stop() {
|
||||
minions = false;
|
||||
send("pool_stop", {}, noop);
|
||||
}
|
||||
},
|
||||
|
||||
newWorker() {
|
||||
if (self.createWorker) {
|
||||
return self.createWorker();
|
||||
} else if (self.kiri_work) {
|
||||
const work = atob(self.kiri_work);
|
||||
const blob = new Blob([ work ], { type: 'application/javascript' });
|
||||
return new Worker(URL.createObjectURL(blob));
|
||||
} else {
|
||||
let worker = new Worker(`/v2/lib/kiri-run/worker.js`, { type: 'module' });
|
||||
worker.onerror = (error) => {
|
||||
console.log({ worker_error: error });
|
||||
error.preventDefault();
|
||||
};
|
||||
worker.onmessageerror = (error) => {
|
||||
console.log({ worker_message_error: error });
|
||||
};
|
||||
console.log({ worker });
|
||||
return worker;
|
||||
}
|
||||
},
|
||||
|
||||
isBusy() {
|
||||
let current = 0;
|
||||
|
||||
for (let rec of Object.values(running)) {
|
||||
if (rec.fn) current++;
|
||||
}
|
||||
return current > 0;
|
||||
},
|
||||
|
||||
restart() {
|
||||
// prevent re-entry from cancel callback
|
||||
if (restarting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (worker) {
|
||||
worker.terminate();
|
||||
}
|
||||
|
||||
restarting = true;
|
||||
|
||||
for (let key in running) {
|
||||
let rec = running[key];
|
||||
if (rec.fn) {
|
||||
rec.fn({error: "cancelled operation"});
|
||||
}
|
||||
}
|
||||
|
||||
syncd = {};
|
||||
running = {};
|
||||
worker = client.newWorker();
|
||||
|
||||
client.onmessage = worker.onmessage = function(e) {
|
||||
let now = time(),
|
||||
reply = e.data,
|
||||
record = running[reply.seq],
|
||||
onreply = record ? record.fn : undefined;
|
||||
|
||||
// console.log('client recv', e)
|
||||
if (reply.done) {
|
||||
delete running[reply.seq];
|
||||
}
|
||||
|
||||
// calculate and replace recv time
|
||||
reply.time_recv = now - reply.time_recv;
|
||||
|
||||
if (onreply) {
|
||||
onreply(reply.data, reply);
|
||||
} else {
|
||||
console.log({unexpected_reply: reply});
|
||||
}
|
||||
};
|
||||
|
||||
// restart minions if they were running
|
||||
if (minions) {
|
||||
client.pool.start();
|
||||
}
|
||||
|
||||
restarting = false;
|
||||
},
|
||||
|
||||
config(obj) {
|
||||
send("config", obj, noop);
|
||||
},
|
||||
|
||||
clear() {
|
||||
syncd = {};
|
||||
send("clear", {}, noop);
|
||||
},
|
||||
|
||||
snap(data) {
|
||||
send("snap", data, noop);
|
||||
},
|
||||
|
||||
png(data, ondone) {
|
||||
send("png", data, ondone);
|
||||
},
|
||||
|
||||
// widget sync
|
||||
sync(widgets) {
|
||||
if (!widgets) {
|
||||
widgets = api.widgets.all();
|
||||
}
|
||||
// sync any widget that has changed
|
||||
for (let widget of widgets.filter(w => w.modified || !syncd[w.id])) {
|
||||
syncd[widget.id] = true;
|
||||
let vertices = widget.getGeoVertices();
|
||||
send("sync", {
|
||||
id: widget.id,
|
||||
meta: widget.meta,
|
||||
group: widget.group.id,
|
||||
track: widget.track,
|
||||
vertices,
|
||||
position: widget.mesh.position,
|
||||
}, done => {
|
||||
widget.modified = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// for belt / angled printing
|
||||
rotate(settings, callback) {
|
||||
send("rotate", { settings }, reply => {
|
||||
if (reply.group) {
|
||||
// collect post-rotation data for slice/preview renders
|
||||
for (let widget of kiri.Widget.Groups.forid(reply.group)) {
|
||||
widget.belt = reply.belt;
|
||||
}
|
||||
} else if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// called once for each widget
|
||||
slice(settings, widget, callback) {
|
||||
console.log('CSLICE', { settings, widget, callback });
|
||||
send("slice", {
|
||||
id: widget.id,
|
||||
anno: widget.annotations(),
|
||||
settings: settings
|
||||
}, reply => {
|
||||
callback(reply);
|
||||
if (reply.done || reply.error) {
|
||||
// in belt mode, slicing modifies a widget and requires re-sync
|
||||
if (settings.device.bedBelt) {
|
||||
widget.modified = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// called once after each widget is sliced
|
||||
// performs merged actions that consider all widget slice data
|
||||
sliceAll(settings, callback) {
|
||||
send("sliceAll", { settings }, callback);
|
||||
},
|
||||
|
||||
// turn widget slices into unified path output
|
||||
prepare(settings, update, done) {
|
||||
send("prepare", { settings }, reply => {
|
||||
if (reply.progress) {
|
||||
update(reply.progress, reply.message, reply.layer);
|
||||
}
|
||||
if (reply.done) {
|
||||
done(reply.output, reply.maxSpeed, reply.minSpeed);
|
||||
}
|
||||
if (reply.error) {
|
||||
done(reply);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// convert path output to gcode or other target file output
|
||||
export(settings, online, ondone) {
|
||||
send("export", { settings }, reply => {
|
||||
if (reply.line) {
|
||||
online(reply.line);
|
||||
}
|
||||
if (reply.done) {
|
||||
ondone(reply.output);
|
||||
}
|
||||
if (reply.error) {
|
||||
ondone(null, reply.error);
|
||||
}
|
||||
if (reply.debug) {
|
||||
api.event.emit("export.debug", reply.debug);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
colors(colors, max, done) {
|
||||
send("colors", { colors, max }, reply => {
|
||||
done(reply);
|
||||
});
|
||||
},
|
||||
|
||||
parse(args, progress, done) {
|
||||
// have to do this client side because DOMParser is not in workers
|
||||
if (args.type === 'svg') {
|
||||
const { settings, code, type } = args;
|
||||
const origin = settings.origin;
|
||||
const offset = {
|
||||
x: origin.x,
|
||||
y: -origin.y,
|
||||
z: origin.z
|
||||
};
|
||||
const output = kiri.newPrint().parseSVG(code, offset);
|
||||
send("parse_svg", output, reply => {
|
||||
if (reply.parsed) {
|
||||
done(kiri.codec.decode(reply.parsed));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
send("parse", args, reply => {
|
||||
if (reply.progress) {
|
||||
progress(reply.progress);
|
||||
}
|
||||
if (reply.parsed) {
|
||||
done(kiri.codec.decode(reply.parsed), reply.maxSpeed, reply.minSpeed);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
image2mesh(data, progress, output) {
|
||||
send("image2mesh", data, reply => {
|
||||
if (reply.progress) {
|
||||
progress(reply.progress);
|
||||
}
|
||||
if (reply.vertices) {
|
||||
output(reply.vertices);
|
||||
}
|
||||
}, [ data.png ]);
|
||||
},
|
||||
|
||||
gerber2mesh(data, progress, output) {
|
||||
send('gerber2mesh', data, reply => {
|
||||
if (reply.progress) {
|
||||
progress(reply.progress);
|
||||
}
|
||||
if (reply.vertices) {
|
||||
output(reply.vertices);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
zip(files, progress, output) {
|
||||
send("zip", {files}, reply => {
|
||||
if (reply.percent !== undefined) {
|
||||
progress(reply);
|
||||
} else {
|
||||
output(reply);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
wasm(enable) {
|
||||
send("wasm", {enable}, reply => {
|
||||
// console.log({wasm_worker_said: reply});
|
||||
});
|
||||
},
|
||||
|
||||
putCache(key, data) {
|
||||
console.log({ putCache: key, data });
|
||||
send("putCache", {key, data}, reply => {
|
||||
// console.log({ putCache_reply: reply });
|
||||
});
|
||||
},
|
||||
|
||||
clearCache() {
|
||||
send("clearCache", {}, reply => {
|
||||
// console.log({ clearCache_reply: reply });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// start worker
|
||||
client.restart();
|
||||
|
||||
self.kiri_client = client;
|
||||
|
||||
export default client;
|
||||
Loading…
Reference in a new issue