diff --git a/src/main/mesh.js b/src/main/mesh.js index 3c5dddaf..364b35e3 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -127,33 +127,33 @@ function space_init(data) { } let { shiftKey, metaKey, ctrlKey, code } = evt; switch (code) { + case 'KeyD': + if (shiftKey) { + for (let m of selection.models()) { + m.debug(); + } + } + break; case 'KeyC': - selection.centerXY().focus(); - break; + return selection.centerXY().focus(); + case 'KeyX': + return api.file.export(); case 'KeyV': - selection.focus(); - break; + return selection.focus(); case 'KeyW': - api.wireframe(); - break; + return api.wireframe(); case 'KeyG': - api.grid(); - break; + return api.grid(); case 'KeyB': - selection.boundsBox({toggle:true}); - break; + return selection.boundsBox({toggle:true}); case 'KeyH': - space.view.home(); - break; + return space.view.home(); case 'KeyR': - api.tool.repair(); - break; + return api.tool.repair(); case 'KeyT': - space.view.top(); - break; + return space.view.top(); case 'KeyZ': - space.view.reset(); - break; + return space.view.reset(); } }, 'keydown', evt => { @@ -172,13 +172,6 @@ function space_init(data) { estop(evt); } break; - case 'KeyD': - if (shiftKey) { - for (let m of selection.models()) { - m.debug(); - } - } - break; case 'Escape': selection.clear(); estop(evt); diff --git a/src/mesh/api.js b/src/mesh/api.js index 0d69c0b8..4061d35d 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -218,7 +218,16 @@ let file = { }, export() { - console.log('...export todo'); + let recs = selection.models().map(m => { return { + id: m.id, matrix: m.matrix, file: m.file + } }); + api.log.emit(`exporting ${recs.length} model(s)`); + moto.client.fn.file_export({ + recs, format: "obj" + }).then(data => { + console.log({work_export: data}); + util.download(data, "export.obj"); + }); }, }; @@ -244,7 +253,7 @@ let tool = { } }; -// api is augmented in mesh.build +// api is augmented in mesh.build (log, modal, download) let api = mesh.api = { clear() { for (let group of group.list()) { @@ -300,8 +309,8 @@ let api = mesh.api = { let deferFn = []; let boundsCache = {}; +// util functions augmented in build (download) let util = mesh.util = { - uuid(segs = 1) { let uid = []; while (segs-- > 0) { diff --git a/src/mesh/build.js b/src/mesh/build.js index 1cb92035..62b6008a 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -20,6 +20,13 @@ broker.listeners({ let spin_timer; +// add download / blob export to util +let download = mesh.util.download = (data, filename = "mesh-data") => { + let url = window.URL.createObjectURL(new Blob([data], {type: "octet/stream"})); + $('download').innerHTML = `x`; + $('_data_export_').click(); +}; + // add modal dialog functions to api let modal = mesh.api.modal = { show(title, contents) { @@ -155,7 +162,8 @@ function ui_build() { h.div({ id: 'actions' }), h.div({ id: 'grouplist'}), h.div({ id: 'selectlist'}), - h.div({ id: 'logger', onmouseover() { log.show() } }) + h.div({ id: 'logger', onmouseover() { log.show() } }), + h.div({ id: 'download', class: "hide" }) ]); let { actions, grouplist, selectlist, logger } = bound; @@ -174,7 +182,7 @@ function ui_build() { onchange(evt) { broker.send.load_files(evt.target.files) } }) ]), - h.button({ _: 'export', onclick: api.file.export, disabled: true }), + h.button({ _: 'export', onclick: api.file.export }), h.div({ class: "vsep" }), h.button({ _: 'analyze', disabled: true }), h.button({ _: 'repair', onclick: api.tool.repair }), @@ -215,7 +223,9 @@ function ui_build() { .map(g => h.div([ h.button({ _: `group`, title: g.id, class: [ "group", selHas(g) ? 'selected' : undefined ], - onclick() { api.selection.toggle(g) } + onclick(e) { + e.shiftKey ? api.selection.toggle(g) : api.selection.set([g]) + } }), h.div({ class: "vsep" }), h.div({ class: "models"}, diff --git a/src/mesh/model.js b/src/mesh/model.js index a23cafee..f02b46f1 100644 --- a/src/mesh/model.js +++ b/src/mesh/model.js @@ -76,9 +76,13 @@ mesh.model = class MeshModel extends mesh.object { return this.mesh; } + get matrix() { + return this.mesh.matrixWorld.elements; + } + debug() { worker.model_debug({ - matrix: this.mesh.matrixWorld.elements, + matrix: this.matrix, id: this.id }).then(data => { // for debugging matrix ops diff --git a/src/mesh/work.js b/src/mesh/work.js index b648d1f4..6386ca43 100644 --- a/src/mesh/work.js +++ b/src/mesh/work.js @@ -31,6 +31,13 @@ function cacheUpdate(id, data) { Object.assign(cache[id], data); } +function translate_encode(id, matrix) { + let rec = cache[id]; + let geo = rec.geo.clone(); + geo.applyMatrix4(core_matrix.clone().multiply( new THREE.Matrix4().fromArray(matrix) )); + return geo.attributes.position.array; +} + let model = { load(data) { let { vertices, indices, name, id } = data; @@ -41,7 +48,9 @@ let model = { }, debug(data) { - let { matrix, id } = data; + let { id, matrix } = data; + return translate_encode(id, matrix); + throw "should not here"; let rec = cache[id]; let geo = rec.geo.clone(); let m4 = core_matrix.clone().multiply( new THREE.Matrix4().fromArray(matrix) ); @@ -108,14 +117,41 @@ let object = { } }; -worker.bind("debug", (data, send) => { +let file = { + export(data, send) { + let { format, recs } = data; + switch (format) { + case "obj": + let p = 1; + let obj = []; + for (let rec of recs) { + let { id, matrix, file } = rec; + let verts = translate_encode(id, matrix); + obj.push(`g ${file}`); + for (let i=0; i