wire up split plane visualization and selection
This commit is contained in:
parent
0466d36f4d
commit
6d79e9c91a
4 changed files with 84 additions and 23 deletions
|
|
@ -8,7 +8,7 @@ let broker = gapp.broker;
|
||||||
let call = broker.send;
|
let call = broker.send;
|
||||||
let dbindex = [ "admin", "space" ];
|
let dbindex = [ "admin", "space" ];
|
||||||
let worker = moto.client.fn;
|
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
|
// set below. called once the DOM readyState = complete
|
||||||
// this is the main() entrypoint called after all dependents load
|
// this is the main() entrypoint called after all dependents load
|
||||||
|
|
@ -129,6 +129,72 @@ function restore_space() {
|
||||||
$d('curtain','none');
|
$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
|
// add space event bindings
|
||||||
function space_init(data) {
|
function space_init(data) {
|
||||||
let { space, platform } = data;
|
let { space, platform } = data;
|
||||||
|
|
@ -219,6 +285,7 @@ function space_init(data) {
|
||||||
break;
|
break;
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
selection.clear();
|
selection.clear();
|
||||||
|
temp_mode && temp_mode.end();
|
||||||
estop(evt);
|
estop(evt);
|
||||||
break;
|
break;
|
||||||
case 'Backspace':
|
case 'Backspace':
|
||||||
|
|
@ -273,6 +340,9 @@ function space_init(data) {
|
||||||
space.mouse.upSelect((int, event) => {
|
space.mouse.upSelect((int, event) => {
|
||||||
if (event && event.target.nodeName === "CANVAS") {
|
if (event && event.target.nodeName === "CANVAS") {
|
||||||
let model = int && int.object.model ? int.object.model : undefined;
|
let model = int && int.object.model ? int.object.model : undefined;
|
||||||
|
if (temp_mode) {
|
||||||
|
return temp_mode.select(model);
|
||||||
|
}
|
||||||
if (model) {
|
if (model) {
|
||||||
let group = model.group;
|
let group = model.group;
|
||||||
let { ctrlKey, metaKey, shiftKey } = event;
|
let { ctrlKey, metaKey, shiftKey } = event;
|
||||||
|
|
@ -360,6 +430,7 @@ broker.listeners({
|
||||||
space_load,
|
space_load,
|
||||||
object_matrix,
|
object_matrix,
|
||||||
object_destroy,
|
object_destroy,
|
||||||
|
edit_split
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove version cache bust from url
|
// remove version cache bust from url
|
||||||
|
|
|
||||||
|
|
@ -307,10 +307,6 @@ let tool = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
split(models) {
|
|
||||||
models = fallback(models);
|
|
||||||
},
|
|
||||||
|
|
||||||
duplicate() {
|
duplicate() {
|
||||||
for (let m of selection.models()) {
|
for (let m of selection.models()) {
|
||||||
m.duplicate();
|
m.duplicate();
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ let mesh = self.mesh = self.mesh || {};
|
||||||
if (mesh.build) return;
|
if (mesh.build) return;
|
||||||
|
|
||||||
let broker = gapp.broker;
|
let broker = gapp.broker;
|
||||||
|
let call = broker.send;
|
||||||
let { api, util } = mesh;
|
let { api, util } = mesh;
|
||||||
|
|
||||||
broker.listeners({
|
broker.listeners({
|
||||||
|
|
@ -250,7 +251,7 @@ function ui_build() {
|
||||||
// h.div({ class: "vsep" }),
|
// h.div({ class: "vsep" }),
|
||||||
h.button({ _: 'duplicate', onclick: tool.duplicate }),
|
h.button({ _: 'duplicate', onclick: tool.duplicate }),
|
||||||
h.button({ _: 'merge', onclick: tool.merge }),
|
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.button({ _: 'invert', onclick: tool.invert }),
|
||||||
]),
|
]),
|
||||||
h.div([
|
h.div([
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ button {
|
||||||
padding: 2px 3px 2px 3px;
|
padding: 2px 3px 2px 3px;
|
||||||
border: 1px solid rgba(150,150,150,0.5);
|
border: 1px solid rgba(150,150,150,0.5);
|
||||||
background-color: rgba(220,220,220,0.75);
|
background-color: rgba(220,220,220,0.75);
|
||||||
|
user-select: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,7 +277,7 @@ button:hover {
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** common child look & feel */
|
/** common look & feel */
|
||||||
|
|
||||||
#logger, #modal_frame, #actions > div, #grouplist > div {
|
#logger, #modal_frame, #actions > div, #grouplist > div {
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
|
|
@ -291,6 +292,14 @@ button:hover {
|
||||||
border-bottom: 1px dashed gray;
|
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 menu top/center **/
|
||||||
|
|
||||||
#modes {
|
#modes {
|
||||||
|
|
@ -307,14 +316,6 @@ button:hover {
|
||||||
gap: 2px;
|
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 {
|
#mode-line, #mode-vertex {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -416,14 +417,6 @@ button:hover {
|
||||||
text-align: left;
|
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 {
|
#grouplist .hidden {
|
||||||
background-color: rgba(0,0,255,0.2);
|
background-color: rgba(0,0,255,0.2);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue