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