diff --git a/src/main/mesh.js b/src/main/mesh.js index 2d654e8c..32fae044 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -337,11 +337,9 @@ function space_init(data) { // without args to return a list of selectable targets // with args when a selection is made space.mouse.downSelect((int, event, ints) => { - if (int?.object?.sketch) { - int.object.sketch.drag({ start: int.object }); - } else if (int?.object?.sketch_item) { - int.object.sketch_item.sketch.drag({ start: int.object }); - } + let obj = int?.object; + if (obj) api.selection.drag({ start: int.object }); + if (obj) obj.sketch_item?.sketch.drag({ start: int.object }); if (event?.shiftKey) { return api.objects(); } else { @@ -435,7 +433,7 @@ function space_init(data) { let { mode, modes } = api; if (delta) { if (delta.event?.shiftKey && selection.count()) { - selection.move(delta.x, delta.y, 0); + selection.drag({ delta, offset }); } } else if (up) { if (selection.count()) { diff --git a/src/mesh/api.js b/src/mesh/api.js index 6971bdf6..7b247b08 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -213,9 +213,7 @@ const selection = { }, drag(opt = {}) { - for (let s of selection.sketches()) { - s.drag(opt); - } + selected.forEach(s => s.drag(opt)); return selection; }, diff --git a/src/mesh/build.js b/src/mesh/build.js index 882de41d..ad564945 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -284,18 +284,18 @@ api.settings = function() { }), ]); - // const set5 = h.div([ - // h.label({ class: "header", _: 'snap'}), - // h.label('value'), - // h.input({ type: "text", size: 5, value: parseFloat(space.snap || 1), - // onchange: ev => call.set_snap_value(ev.target.value) - // }), - // h.label('enabled'), - // h.input({ type: "checkbox", - // onchange: ev => prefs.save( space.snapon = !space.snapon ), - // [ space.snapon === true ? 'checked' : 'unchecked' ] : 1 - // }), - // ]); + const set5 = h.div([ + h.label({ class: "header", _: 'snap'}), + h.label('value'), + h.input({ type: "text", size: 5, value: parseFloat(space.snap || 1), + onchange: ev => call.set_snap_value(ev.target.value) + }), + h.label('enabled'), + h.input({ type: "checkbox", + onchange: ev => prefs.save( space.snapon = !space.snapon ), + [ space.snapon === true ? 'checked' : 'unchecked' ] : 1 + }), + ]); modal.show('settings', h.div({ class: "settings" }, [ set1, set2, set3, set4, set5 ] )); } diff --git a/src/mesh/group.js b/src/mesh/group.js index aec80092..686f313c 100644 --- a/src/mesh/group.js +++ b/src/mesh/group.js @@ -156,8 +156,9 @@ mesh.group = class MeshGroup extends mesh.object { } // ok, this is confusing, but necessary for now :/ + // todo: obsolete? setSelected() { - super.select(); + // super.select(); return this; } }; diff --git a/src/mesh/model.js b/src/mesh/model.js index c0c71288..706d4749 100644 --- a/src/mesh/model.js +++ b/src/mesh/model.js @@ -16,6 +16,7 @@ const { MeshPhongMaterial, MeshBasicMaterial, LineBasicMaterial } = THREE; const { BufferGeometry, BufferAttribute, DoubleSide, Mesh } = THREE; const { mesh, moto } = root; const { space } = moto; +const { api } = mesh; const mapp = mesh; const worker = moto.client.fn; @@ -129,6 +130,43 @@ mesh.model = class MeshModel extends mesh.object { return this.mesh.matrixWorld; } + drag(opt = {}) { + let { start, delta, offset, end } = opt; + let { snap, snapon } = api.prefs.map.space; + if (start) { + let mid = this.bounds.mid; + this._save = { + pos: Object.assign({},mid), + start: Object.assign({},mid), + } + } else if (end) { + delete this._save; + } else if (offset) { + let { pos, start } = this._save; + let target = { + x: start.x + offset.x, + y: start.y + offset.y, + z: start.z + offset.z + }; + if (snapon && snap) { + target.x = Math.round(target.x / snap) * snap; + target.y = Math.round(target.y / snap) * snap; + target.z = Math.round(target.z / snap) * snap; + } + delta = { + x: target.x - pos.x, + y: target.y - pos.y, + z: target.z - pos.z + }; + pos.x += delta.x; + pos.y += delta.y; + pos.z += delta.z; + } + if (delta) { + this.move(delta.x, delta.y, delta.z); + } + } + // override and translate mesh move(x = 0, y = 0, z = 0) { let attr = this.attributes; diff --git a/src/mesh/sketch.js b/src/mesh/sketch.js index 7c9684eb..6e99ed16 100644 --- a/src/mesh/sketch.js +++ b/src/mesh/sketch.js @@ -352,10 +352,14 @@ mesh.sketch = class MeshSketch extends mesh.object { drag(opt = {}) { let { items } = this; - if (opt.start) { + let { start, delta, end } = opt; + if (start) { let selected = items.filter(i => i.selected); - this.dragging = opt.start.sketch_item ? selected : opt.start; - } else if (opt.end) { + this.dragging = start.sketch_item ? selected : start; + // } else if (offset) { + } else if (delta) { + this.move(delta.x, delta.y, delta.z); + } else if (end) { this.dragging = undefined; } else { console.log({ invalid_sketch_drag: opt }); diff --git a/src/moto/space.js b/src/moto/space.js index 6cc6d6b0..f4979987 100644 --- a/src/moto/space.js +++ b/src/moto/space.js @@ -53,7 +53,6 @@ gapp.register("moto.space", [], (root, exports) => { debug: false }, cameraLight = addLight(0, 0, 0, lightInfo.intensity), - trackDelta = {x:0, y:0, z:0}, origin = {x:0, y:0, z: 0}, mouse = {x: 0, y: 0}, mouseStart = null, @@ -772,19 +771,6 @@ gapp.register("moto.space", [], (root, exports) => { requestRefresh(); } - // function alignTracking(point, rot, out) { - // if (point && rot) { - // alignedTracking = true; - // trackPlane.position.set(point.x, point.y, point.z); - // trackPlane.rotation.set(rot.x, rot.y, rot.z); - // trackDelta = out; - // } else { - // alignedTracking = false; - // trackPlane.position.set(0, 0, 0); - // trackPlane.rotation.set(PI2, 0, 0); - // } - // } - function cca(c) { return c.charCodeAt(0); } @@ -1007,8 +993,13 @@ gapp.register("moto.space", [], (root, exports) => { mouseDrag({ x: -delta.x, y: delta.z, + z: 0, event - }, offset.multiplyVectors(offset, trackDelta)); + }, { + x: -offset.x, + y: offset.z, + z: 0 + }); requestRefresh(); } } @@ -1100,7 +1091,6 @@ gapp.register("moto.space", [], (root, exports) => { update: requestRefresh, setAntiAlias(b) { antiAlias = b ? true : false }, - // alignTracking: alignTracking, raycast: intersect, event: {