From 6d79e9c91aa61d2b1c61777baad9f2cfa06769d9 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sat, 15 Jan 2022 13:47:03 -0500 Subject: [PATCH] wire up split plane visualization and selection --- src/main/mesh.js | 73 +++++++++++++++++++++++++++++++++++++++++++++- src/mesh/api.js | 4 --- src/mesh/build.js | 3 +- web/mesh/index.css | 27 +++++++---------- 4 files changed, 84 insertions(+), 23 deletions(-) diff --git a/src/main/mesh.js b/src/main/mesh.js index 4d2edd41..a588d451 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -8,7 +8,7 @@ let broker = gapp.broker; let call = broker.send; let dbindex = [ "admin", "space" ]; let worker = moto.client.fn; -let { Quaternion, Vector3 } = THREE; +let { Quaternion, Vector3, Mesh, MeshPhongMaterial, PlaneGeometry, DoubleSide } = THREE; // set below. called once the DOM readyState = complete // this is the main() entrypoint called after all dependents load @@ -129,6 +129,72 @@ function restore_space() { $d('curtain','none'); } +// toggle edit/split temporary mode (present plane on hover) +let temp_mode; + +// split functions +let split = { + start() { + let space = moto.Space; + let { api, util } = mesh; + // highlight button + let button = event.target; + button.classList.add('selected'); + // create split plane visual + let geo, mat, obj = new Mesh( + geo = new PlaneGeometry(1,1), + mat = new MeshPhongMaterial({ + side: DoubleSide, + color: 0x999999, + transparent: false, + opacity: 0.1 + }) + ); + space.scene.add(obj); + // enable temp mode + let state = split.state = { button, obj }; + // for split and lay flat modes + space.mouse.onHover((int, event, ints) => { + if (!event) { + return api.objects(); + } + let { button, buttons } = event; + if (buttons) { + return; + } + let { dim, mid } = util.bounds(int.object); + let { x, y, z } = int.point; + state.point = { x, y, z }; + obj.scale.set(dim.x, dim.y, 1); + obj.position.set(mid.x, y, mid.y); + }); + temp_mode = split; + }, + + select() { + // select plane (also exec) + console.log({select_plane: split.state}); + split.end(); + }, + + end() { + let space = moto.Space; + let { button, obj } = split.state; + button.classList.remove('selected'); + space.scene.remove(obj); + space.mouse.onHover(undefined); + temp_mode = split.state = undefined; + } +} + +function edit_split(event) { + if (temp_mode) { + temp_mode.end(); + } else { + split.start(); + } +} + // add space event bindings function space_init(data) { let { space, platform } = data; @@ -219,6 +285,7 @@ function space_init(data) { break; case 'Escape': selection.clear(); + temp_mode && temp_mode.end(); estop(evt); break; case 'Backspace': @@ -273,6 +340,9 @@ function space_init(data) { space.mouse.upSelect((int, event) => { if (event && event.target.nodeName === "CANVAS") { let model = int && int.object.model ? int.object.model : undefined; + if (temp_mode) { + return temp_mode.select(model); + } if (model) { let group = model.group; let { ctrlKey, metaKey, shiftKey } = event; @@ -360,6 +430,7 @@ broker.listeners({ space_load, object_matrix, object_destroy, + edit_split }); // remove version cache bust from url diff --git a/src/mesh/api.js b/src/mesh/api.js index 71008ab9..6c9b2bd9 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -307,10 +307,6 @@ let tool = { }); }, - split(models) { - models = fallback(models); - }, - duplicate() { for (let m of selection.models()) { m.duplicate(); diff --git a/src/mesh/build.js b/src/mesh/build.js index fd6ec96b..e895d85a 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -14,6 +14,7 @@ let mesh = self.mesh = self.mesh || {}; if (mesh.build) return; let broker = gapp.broker; +let call = broker.send; let { api, util } = mesh; broker.listeners({ @@ -250,7 +251,7 @@ function ui_build() { // h.div({ class: "vsep" }), h.button({ _: 'duplicate', onclick: tool.duplicate }), h.button({ _: 'merge', onclick: tool.merge }), - h.button({ _: 'split', onclick: tool.split }), + h.button({ _: 'split', onclick: call.edit_split }), h.button({ _: 'invert', onclick: tool.invert }), ]), h.div([ diff --git a/web/mesh/index.css b/web/mesh/index.css index a63324cd..e7bf291c 100644 --- a/web/mesh/index.css +++ b/web/mesh/index.css @@ -140,6 +140,7 @@ button { padding: 2px 3px 2px 3px; border: 1px solid rgba(150,150,150,0.5); background-color: rgba(220,220,220,0.75); + user-select: none; outline: none; } @@ -276,7 +277,7 @@ button:hover { will-change: transform; } -/** common child look & feel */ +/** common look & feel */ #logger, #modal_frame, #actions > div, #grouplist > div { border: 1px solid gray; @@ -291,6 +292,14 @@ button:hover { border-bottom: 1px dashed gray; } +button.selected { + background-color: rgba(0,255,0,0.5); +} + +button.selected:hover { + background-color: rgba(0,255,0,1); +} + /** modes menu top/center **/ #modes { @@ -307,14 +316,6 @@ button:hover { gap: 2px; } -#modes button.selected { - background-color: rgba(0,255,0,0.5); -} - -#modes button.selected:hover { - background-color: rgba(0,255,0,1); -} - #mode-line, #mode-vertex { display: none; } @@ -416,14 +417,6 @@ button:hover { text-align: left; } -#grouplist .selected { - background-color: rgba(0,255,0,0.5) -} - -#grouplist .selected:hover { - background-color: rgba(0,255,0,1) -} - #grouplist .hidden { background-color: rgba(0,0,255,0.2); }