diff --git a/src/main/mesh.js b/src/main/mesh.js index eeac19a4..21ee2ba8 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -276,6 +276,7 @@ function space_init(data) { case 'KeyF': return selection.floor().focus(); case 'KeyM': + if (shiftKey) return api.tool.mirror(); return api.tool.merge(); case 'KeyA': return api.tool.analyze(); diff --git a/src/mesh/api.js b/src/mesh/api.js index 8d988ba8..38a13eca 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -140,6 +140,8 @@ let selection = { } // update saved selection id list prefs.save( prefs.map.space.select = selected.map(s => s.id) ); + // force repaint in case of idle + space.update(); return selection; }, @@ -293,6 +295,9 @@ function fallback(models, strict) { let tool = { merge(models) { models = fallback(models); + if (models.length <= 1) { + return api.log.emit('nothing to merge'); + } api.log.emit(`merging ${models.length} models`).pin(); worker.model_merge(models.map(m => { return { id: m.id, matrix: m.matrix } @@ -313,6 +318,12 @@ let tool = { } }, + mirror() { + for (let m of selection.models()) { + m.mirror(); + } + }, + invert() { for (let m of selection.models()) { m.invert(api.mode.get()); diff --git a/src/mesh/build.js b/src/mesh/build.js index 704f2378..6502fb71 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -267,6 +267,7 @@ function ui_build() { // h.div({ class: "vsep" }), h.button({ _: 'duplicate', onclick: tool.duplicate }), h.button({ _: 'merge', onclick: tool.merge }), + h.button({ _: 'mirror', onclick: tool.mirror }), h.button({ _: 'split', onclick: call.edit_split }), h.button({ _: 'invert', onclick: tool.invert }), ]), diff --git a/src/mesh/group.js b/src/mesh/group.js index 5e4fbb99..f8a851c9 100644 --- a/src/mesh/group.js +++ b/src/mesh/group.js @@ -108,6 +108,13 @@ mesh.group = class MeshGroup extends mesh.object { return this.centerXY().floor(); } + scale(x = 1, y = 1, z = 1) { + for (let m of this.models) { + m.scale(x, y, z); + } + return this; + } + // center objects to group bounds // dependent on first being added to world/scene centerModels() { @@ -141,6 +148,11 @@ mesh.group = class MeshGroup extends mesh.object { model.select(...arguments); } } + + // ok, this is confusing, but necessary for now :/ + setSelected() { + super.select(); + } }; })(); diff --git a/src/mesh/model.js b/src/mesh/model.js index f81dfc3f..080192a2 100644 --- a/src/mesh/model.js +++ b/src/mesh/model.js @@ -108,16 +108,45 @@ mesh.model = class MeshModel extends mesh.object { return this.mesh.matrixWorld.elements; } + // override and translate mesh + move(x = 0, y = 0, z = 0) { + let arr = this.attributes.position.array; + for (let i=0, l=arr.length; i { mesh.api.group.new([new mesh.model({ - file: `${this.file}-dup`, + file: `${this.file}`, mesh: data - })]).select(); + })]).setSelected(); }); } @@ -357,7 +386,7 @@ mesh.model = class MeshModel extends mesh.object { this.group.add(model = new mesh.model({ file: `${this.file}`, mesh: o2 - }).applyMatrix4(m4)).select(); + }).applyMatrix4(m4)).setSelected(); if (o1.length) { // this becomes bottom this.reload(o1); diff --git a/src/mesh/util.js b/src/mesh/util.js index 177097a3..9403f197 100644 --- a/src/mesh/util.js +++ b/src/mesh/util.js @@ -103,6 +103,10 @@ let util = mesh.util = { // https://discourse.threejs.org/t/bounding-box-bigger-than-concave-object-extrudegeometry/26073/2 // https://discourse.threejs.org/t/invalid-bounds-generated-for-some-orientations/33205 box3expand(box3, object) { + if (object._no_bounds) { + return; + } + let geometry = object.geometry; object.updateWorldMatrix(geometry ? true : false, false); @@ -183,6 +187,7 @@ let util = mesh.util = { this.size = size; this.type = 'FaceNormalsHelper'; this.matrixAutoUpdate = false; + this._no_bounds = true; this.update(); } diff --git a/src/mesh/work.js b/src/mesh/work.js index 97601f69..8158f332 100644 --- a/src/mesh/work.js +++ b/src/mesh/work.js @@ -72,8 +72,30 @@ let model = { // return new vertices in world coordinates duplicate(data) { - let { id, matrix } = data; - return translate_encode(id, matrix); + let { id, matrix, opt } = data; + let array = translate_encode(id, matrix); + if (opt.mirror) { + // find max z and invert z + let maxz = -Infinity; + for (let i=2, l=array.length; i