diff --git a/app.js b/app.js index 1cf42c37..6e704409 100644 --- a/app.js +++ b/app.js @@ -289,7 +289,7 @@ const script = { "kiri/tools", "@devices", "@icons" - ].map(p => p.charAt(0) !== '@' ? `src/${p}.js` : p), + ], worker : [ "main/kiri", "ext/three", @@ -341,7 +341,7 @@ const script = { "kiri/print", "kiri/codec", "kiri/worker" - ].map(p => `src/${p}.js`), + ], minion : [ "main/kiri", "add/license", @@ -367,7 +367,7 @@ const script = { "kiri/widget", "kiri/codec", "kiri/minion" - ].map(p => `src/${p}.js`), + ], engine : [ "main/kiri", "add/license", @@ -394,10 +394,10 @@ const script = { "kiri/widget", "kiri/codec", "kiri/engine" - ].map(p => `src/${p}.js`), + ], frame : [ "kiri/frame" - ].map(p => `src/${p}.js`), + ], meta : [ "ext/three", "add/license", @@ -425,32 +425,19 @@ const script = { "moto/ui", "kiri/catalog", "main/meta" - ].map(p => `src/${p}.js`), + ], mesh : [ "main/mesh", + "moto/client", "ext/three", "ext/three-bgu", "ext/three-svg", - "ext/jszip", "add/license", - "ext/clip2", "ext/tween", "ext/fsave", - "ext/earcut", - "ext/base64", "add/array", "add/three", - "geo/base", - "geo/point", - "geo/points", - "geo/slope", - "geo/line", - "geo/bounds", - "geo/polygon", - "geo/polygons", "geo/mesh", - // "moto/kv", - // "moto/ajax", "moto/ctrl", "moto/space", "moto/load-3mf", @@ -460,28 +447,35 @@ const script = { "moto/load-url", "moto/load-file", "moto/broker", - "moto/db", - // "kiri/ui", - // "kiri/do", - // "kiri/lang", - // "kiri/lang-en", - // "kiri/catalog", - // "kiri/slice", - // "kiri/layers", - // "kiri/client", - // "kiri/stack", - // "kiri/stacks", - // "kiri/widget", - // "kiri/print", - // "kiri/codec", - // "kiri/conf", - // "kiri/main", - // "kiri/init", - // "kiri/export", - // "kiri/tools", - ].map(p => `src/${p}.js`), + "moto/db" + ], + mesh_work : [ + "moto/worker", + "add/license", + "ext/jszip", + "ext/clip2", + "ext/earcut", + "ext/base64", + "ext/three", + "add/three", + "ext/three-bgu", + "geo/base", + "geo/point", + "geo/points", + "geo/slope", + "geo/line", + "geo/bounds", + "geo/polygon", + "geo/polygons", + "geo/mesh", + ] }; +// process script dependencies, expand paths +for (let [key,val] of Object.entries(script)) { + script[key] = val.map(p => p.charAt(0) !== '@' ? `src/${p}.js` : p); +} + // prevent caching of specified modules const cachever = {}; @@ -644,13 +638,9 @@ function generateDevices() { function prepareScripts() { generateIcons(); generateDevices(); - code.meta = concatCode(script.meta); - code.mesh = concatCode(script.mesh); - code.kiri = concatCode(script.kiri); - code.worker = concatCode(script.worker); - code.minion = concatCode(script.minion); - code.engine = concatCode(script.engine); - code.frame = concatCode(script.frame); + for (let key of Object.keys(script)) { + code[key] = concatCode(script[key]); + } } function concatCode(array) { diff --git a/notes.md b/notes.md index da05bec0..abdd93af 100644 --- a/notes.md +++ b/notes.md @@ -1,4 +1,4 @@ -# Kiri:Moto todo and notes +# Kiri:Moto / Grid:Apps notes ## `C` cosmetic, `F` functional, `P` performance, `B` bug fix @@ -108,20 +108,3 @@ # Laser * `F` add PLT / HP-GL output format (https://en.wikipedia.org/wiki/HP-GL) - -# References - -* https://www.canva.com/colors/color-wheel/ -* http://lcamtuf.coredump.cx/gcnc/full/ -* http://wiki.imal.org/howto/cnc-milling-introduction-cutting-tools -* http://www.twak.co.uk/2011/01/degeneracy-in-weighted-straight.html -* http://photon.chrisgraf.de/ -* https://github.com/Jack000/SVGnest - -# More CNC - -* https://www.researchgate.net/publication/250328721_Toolpath_Optimization_on_Automatic_Removal_Uncut_and_Application - -# Meta - -* free-space tetrahedron modeler with vertex mating diff --git a/readme.md b/readme.md index 532aa97a..5aaec83b 100644 --- a/readme.md +++ b/readme.md @@ -48,8 +48,8 @@ if installing the app-server fails or gives you permissions errors, then your no sudo npm install -g @gridspace/app-server ``` -to start a local instance of the apps. then open -[localhost:8080/kiri](http://localhost:8080/kiri) on your local host +to start a local instance of the apps. then use a browser to open +[localhost:8080/kiri](http://localhost:8080/kiri) Alternatively, if you are using a packaged version of npm that ships with a Linux distribution, but still want to install in your home directory, you @@ -73,7 +73,7 @@ cd grid-apps docker-compose -f src/dock/compose.yml up ``` -You can now access your environment of grid-apps by going to: +You can now access your environment of grid-apps by going to [localhost:8080/kiri](http://127.0.0.1:8080/kiri) ### Windows Developers diff --git a/src/main/mesh.js b/src/main/mesh.js index 6ecfcb86..c30a696c 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -1,10 +1,14 @@ // required for license and other grid app dependencies -self.gapp = {}; +self.gapp = self.gapp || {}; function $(id) { return document.getElementById(id); } +function $d(id, v) { + $(id).style.display = v; +} + function init() { let container = $('container'), moto = self.moto, @@ -28,10 +32,13 @@ function init() { Space.useDefaultKeys(true); // hide loading curtain - $('curtain').style.display = 'none'; + $d('curtain','none'); // remove version cache bust from url window.history.replaceState({},'','/mesh/'); + + // start worker + moto.client.start(`/code/mesh_work?${gapp.version}`); } document.onreadystatechange = function() { diff --git a/src/moto/client.js b/src/moto/client.js new file mode 100644 index 00000000..2376967a --- /dev/null +++ b/src/moto/client.js @@ -0,0 +1,124 @@ +/** Copyright Stewart Allen -- All Rights Reserved */ + +"use strict"; + +(function() { + +let MOTO = self.moto = self.moto || {}, + time = function() { return new Date().getTime() }, + restarting = false, + running = {}, + workurl = null, + worker = null, + seqid = 1; + +/** + * @param {Function} fn name of function in MOTO.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) { + // establish listener and track replies + running[seq] = { fn:onreply }; + } + let msg = { + seq: seq, + task: fn, + time: time(), + data: data + }; + try { + worker.postMessage(msg, zerocopy); + } catch (error) { + console.trace('work send error', {data, error}); + } +} + +// code is running in the browser / client context +let CLIENT = MOTO.client = { + send: send, + + // factory can be overridden + newWorker: function(url = workurl) { + if (self.createWorker) { + return self.createWorker(); + } else { + return new Worker(workurl = url); + } + }, + + // return number of running requests + current: function() { + let current = 0; + for (let rec of Object.values(running)) { + if (rec.fn) current++; + } + return current; + }, + + stop: function() { + if (worker) { + worker.terminate(); + worker = null; + } + }, + + // same as restart + start: function(url) { + CLIENT.restart(url); + }, + + restart: function(url) { + // prevent re-entry from cancel callback + if (restarting) { + return; + } + + CLIENT.stop(); + + restarting = true; + + for (let key in running) { + let rec = running[key]; + if (rec.fn) { + rec.fn({error: "cancelled operation"}); + } + } + + running = {}; + worker = CLIENT.newWorker(url); + + // bind to CLIENT to enable synth injections + CLIENT.onmessage = worker.onmessage = function(e) { + let now = time(), + reply = e.data, + record = running[reply.seq], + onreply = record ? record.fn : undefined; + + 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({drop_reply: reply}); + } + }; + + // signal worker client is ready + worker.postMessage("--init--"); + + restarting = false; + } + +}; + +})(); diff --git a/src/moto/worker.js b/src/moto/worker.js new file mode 100644 index 00000000..9a9635f3 --- /dev/null +++ b/src/moto/worker.js @@ -0,0 +1,80 @@ +/** Copyright Stewart Allen -- All Rights Reserved */ + +"use strict"; + +(function() { + +let MOTO = self.moto = self.moto || {}, + time = Date.now; + +// allow license to inject module +self.gapp = self.gapp || MOTO; + +// code is running in the worker / server context +const dispatch = MOTO.worker = { + + send: (msg) => { + self.postMessage(msg); + }, + + onmessage: (e) => { + + if (e.data === '--init--') { + console.log('worker got init'); + return; + } + + let time_recv = time(), + msg = e.data || {}, + run = dispatch[msg.task], + send = { + data : function(data,direct) { + dispatch.send({ + seq: msg.seq, + task: msg.task, + done: false, + data: data + }, direct); + }, + done : function(data,direct) { + dispatch.send({ + seq: msg.seq, + task: msg.task, + done: true, + data: data + }, direct); + } + }; + + if (run) { + try { + let time_xfer = (time_recv - msg.time), + output = run(msg.data, send), + time_send = time(), + time_proc = time_send - time_recv; + + if (output) dispatch.send({ + seq: msg.seq, + task: msg.task, + time_send: time_xfer, + time_proc: time_proc, + // replaced on reply side + time_recv: time(), + data: output + }); + } catch (wrkerr) { + // console.log(wrkerr); + console.trace(wrkerr.stack); + send.done({error: wrkerr.toString()}); + } + } else { + console.log({worker_unhandled: e, msg, fn: dispatch[msg.task]}); + } + } + +}; + +// attach onmessage hanler +self.onmessage = dispatch.onmessage; + +})(); diff --git a/web/mesh/index.css b/web/mesh/index.css index 2b818769..ffe82635 100644 --- a/web/mesh/index.css +++ b/web/mesh/index.css @@ -9,7 +9,7 @@ } @font-face { font-family: 'Russo One'; - src: url('ext/russo-one.ttf'); + src: url('/kiri/ext/russo-one.ttf'); } a, a:hover, a:visited { border: none; @@ -28,17 +28,33 @@ a, a:hover, a:visited { bottom: 0; } #app-name { - position: absolute; + xposition: absolute; top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%); z-index: 50; } -#app-name, #app-mode-name, #app-acct { - cursor: pointer; +#app-name:hover #app-info { + display: flex; } -#app-mode-name { - border-bottom: 2px dotted grey; +#app-info { + display: none; + position: absolute; + white-space: nowrap; + font-size: smaller; + font-family: sans-serif; + margin-top: 5px; + padding: 5px; + transform: translateX(-50%); + left: 50%; + top: 100%; + color: var(--fg-gray); + border-radius: 3px; + border: 1px solid #ddd; + background-color: white; +} +#app-name, #app-acct { + cursor: pointer; } #app,div { display: flex; @@ -46,6 +62,11 @@ a, a:hover, a:visited { border: 0; margin: 0; } +#top-sep, #mid-sep { + z-index: 14; + height: 1px; + background-image: var(--gradbar); +} #gsbox { width: 40px; height: 40px; diff --git a/web/mesh/index.html b/web/mesh/index.html index 6c23b54a..0d442bf5 100644 --- a/web/mesh/index.html +++ b/web/mesh/index.html @@ -14,7 +14,7 @@ Mesh:Tool - + @@ -24,23 +24,18 @@
loading...
-
+
+
Mesh:Tool
version
+
+

this site uses cookies to preserve application preferences

-
-
-
alerts
alerts
alerts
-
-
-
- -