grid-apps-cmms/src/kiri/client.js

293 lines
7.8 KiB
JavaScript
Raw Normal View History

2020-06-03 22:39:30 -04:00
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
2021-01-01 11:14:07 -05:00
(function() {
// this code runs in kiri's main loop
2020-12-31 23:22:39 -05:00
let KIRI = self.kiri = self.kiri || {},
loc = self.location,
host = loc.hostname,
port = loc.port,
proto = loc.protocol,
time = function() { return new Date().getTime() },
seqid = 1,
2020-11-30 22:36:06 -05:00
syncd = {},
running = {},
2021-02-24 11:09:02 -05:00
worker = null,
restarting = false
2021-02-01 16:39:22 -05:00
// occ = new Worker("/kiri/ext/occ-worker.js", {type:"module"}),
;
2020-11-03 11:19:13 -05:00
/**
* @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});
}
}
2017-04-18 17:09:33 -04:00
2020-11-03 11:19:13 -05:00
// code is running in the browser / client context
const CLIENT =
2020-11-03 11:19:13 -05:00
KIRI.client =
KIRI.work = {
2020-11-03 11:19:13 -05:00
send: send,
2020-06-15 22:47:11 -04:00
newWorker: function() {
if (self.createWorker) {
return self.createWorker();
} else {
return new Worker(`/code/worker.js?${self.kiri.version}`);
}
},
2021-02-24 11:09:02 -05:00
isBusy: function() {
let current = 0;
2021-02-24 11:09:02 -05:00
for (let rec of Object.values(running)) {
if (rec.fn) current++;
}
return current > 0;
},
2017-04-18 17:09:33 -04:00
2020-11-26 23:18:28 -05:00
restart: function() {
2021-02-24 11:09:02 -05:00
// prevent re-entry from cancel callback
if (restarting) {
return;
}
if (worker) {
worker.terminate();
}
2017-04-18 17:09:33 -04:00
2021-02-24 11:09:02 -05:00
restarting = true;
for (let key in running) {
let rec = running[key];
if (rec.fn) {
rec.fn({error: "cancelled operation"});
}
}
2017-04-18 17:09:33 -04:00
2021-01-13 14:31:38 -05:00
syncd = {};
running = {};
2020-06-15 22:47:11 -04:00
worker = KIRI.work.newWorker();
CLIENT.onmessage = worker.onmessage = function(e) {
let now = time(),
reply = e.data,
record = running[reply.seq],
onreply = record ? record.fn : undefined;
2020-06-15 22:47:11 -04:00
// 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});
}
};
2021-02-24 11:09:02 -05:00
restarting = false;
},
2020-11-26 23:18:28 -05:00
decimate: function(vertices, options, callback) {
let alert = KIRI.api.show.alert('processing model', 1000);
vertices = vertices.buffer.slice(0);
send("decimate", {vertices, options}, function(output) {
KIRI.api.hide.alert(alert);
callback(output);
});
},
2020-11-26 23:18:28 -05:00
config: function(obj) {
2021-01-29 13:25:41 -05:00
send("config", obj, function(reply) { });
},
clear: function() {
2021-01-29 13:25:41 -05:00
syncd = {};
send("clear", {}, function(reply) { });
},
2020-11-26 23:18:28 -05:00
snap: function(data) {
2021-01-29 13:25:41 -05:00
send("snap", data, function(reply) { });
},
// widget sync
sync: function(widgets) {
if (!widgets) {
widgets = KIRI.api.widgets.all();
}
// send list of currently valid widgets
send("sync", { valid: widgets.map(w => w.id) }, () => {});
// sync any widget that has changed
widgets.forEach(widget => {
2020-11-30 22:36:06 -05:00
if (widget.modified || !syncd[widget.id]) {
syncd[widget.id] = true;
let vertices = widget.getGeoVertices().buffer.slice(0);
send("sync", {
id: widget.id,
2021-01-24 00:13:09 -05:00
group: widget.group.id,
track: widget.track,
vertices: vertices,
position: widget.mesh.position,
}, done => {
widget.modified = false;
}, [vertices]);
}
});
},
2021-01-24 00:13:09 -05:00
rotate: function(settings, callback) {
send("rotate", { settings }, reply => {
if (reply.group) {
for (let widget of KIRI.Widget.Groups.forid(reply.group)) {
widget.belt = reply.belt;
}
} else if (callback) {
callback();
}
});
},
unrotate: function(settings, callback) {
send("unrotate", { settings }, reply => {
if (reply.group) {
for (let widget of KIRI.Widget.Groups.forid(reply.group)) {
widget.rotinfo = reply.rotinfo;
}
} else if (callback) {
callback();
}
});
},
2020-11-26 23:18:28 -05:00
slice: function(settings, widget, callback) {
send("slice", {
id: widget.id,
settings: settings
}, function(reply) {
callback(reply);
2020-11-08 13:04:54 -05:00
if (reply.done || reply.error) {
// in belt mode, slicing modifies a widget and requires re-sync
if (settings.device.bedBelt) {
widget.modified = true;
}
2020-11-08 13:04:54 -05:00
}
});
},
2020-11-26 23:18:28 -05:00
prepare: function(settings, update, done) {
2020-11-09 13:57:18 -05:00
send("prepare", { settings }, function(reply) {
2020-11-08 13:04:54 -05:00
if (reply.progress) {
update(reply.progress, reply.message, reply.layer);
2020-11-08 13:04:54 -05:00
}
if (reply.done) {
2020-11-11 08:07:02 -05:00
done(reply.output, reply.maxSpeed);
2020-11-08 13:04:54 -05:00
}
if (reply.error) {
done(reply);
}
});
},
2020-11-26 23:18:28 -05:00
export: function(settings, online, ondone) {
2020-11-09 13:57:18 -05:00
send("export", { settings }, function(reply) {
2020-04-14 09:26:59 -04:00
if (reply.line) {
online(reply.line);
}
if (reply.done) {
2020-11-08 17:35:40 -05:00
ondone(reply.output);
2020-04-14 09:26:59 -04:00
}
if (reply.error) {
ondone(null, reply.error);
}
2020-04-14 09:26:59 -04:00
});
},
2020-11-26 23:18:28 -05:00
colors: function(colors, max, done) {
2020-11-11 08:07:02 -05:00
send("colors", { colors, max }, function(reply) {
done(reply);
});
},
2020-11-26 23:18:28 -05:00
parse: function(args, progress, done) {
2020-11-09 23:01:41 -05:00
// 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, function(reply) {
if (reply.parsed) {
done(KIRI.codec.decode(reply.parsed));
}
});
return;
}
2020-11-09 13:57:18 -05:00
send("parse", args, function(reply) {
if (reply.progress) {
2021-02-26 09:32:34 -05:00
progress(reply.progress);
2020-11-09 13:57:18 -05:00
}
if (reply.parsed) {
2020-11-13 09:27:42 -05:00
done(KIRI.codec.decode(reply.parsed), reply.maxSpeed);
}
});
2020-11-26 23:18:28 -05:00
},
image2mesh: function(data, progress, output) {
send("image2mesh", data, reply => {
if (reply.progress) {
progress(reply.progress);
}
if (reply.done) {
output(reply.done);
}
}, [ data.png ]);
2021-02-01 16:39:22 -05:00
},
2021-02-01 17:13:55 -05:00
zip: function(files, progress, output) {
2021-02-01 16:39:22 -05:00
send("zip", {files}, reply => {
2021-02-01 17:44:25 -05:00
if (reply.percent !== undefined) {
2021-02-01 17:13:55 -05:00
progress(reply);
} else {
output(reply);
}
2021-02-01 16:39:22 -05:00
});
}
};
2017-04-18 17:09:33 -04:00
// start worker
KIRI.work.restart();
2021-01-01 11:14:07 -05:00
})();