add selection modes to left menu
This commit is contained in:
parent
12d8607f3c
commit
6ca4551fb5
4 changed files with 98 additions and 33 deletions
|
|
@ -114,13 +114,15 @@ function restore_space() {
|
|||
// restore preferences after models are restored
|
||||
api.prefs.load().then(() => {
|
||||
let { map } = api.prefs;
|
||||
let { space } = map;
|
||||
let { space, mode } = map;
|
||||
api.grid(space.grid);
|
||||
// restore selected state
|
||||
let selist = space.select;
|
||||
let smodel = api.model.list().filter(m => selist.contains(m.id));
|
||||
let sgroup = api.group.list().filter(m => selist.contains(m.id));
|
||||
api.selection.set([...smodel, ...sgroup]);
|
||||
// restore edit mode
|
||||
api.mode.set(mode);
|
||||
});
|
||||
});
|
||||
// hide loading curtain
|
||||
|
|
@ -264,11 +266,7 @@ function space_init(data) {
|
|||
if (model) {
|
||||
let group = model.group;
|
||||
let { ctrlKey, metaKey, shiftKey } = event;
|
||||
if (shiftKey && metaKey) {
|
||||
// find faces adjacent to point/line clicked
|
||||
model.find(int.point, int.face);
|
||||
// console.log(int);
|
||||
} else if (metaKey) {
|
||||
if (metaKey) {
|
||||
// set focus on intersected face
|
||||
let { x, y, z } = int.point;
|
||||
// y,z swap due to world rotation for orbit controls
|
||||
|
|
@ -277,7 +275,18 @@ function space_init(data) {
|
|||
// rotate selected face towawrd z "floor"
|
||||
group.faceDown(int.face.normal);
|
||||
} else {
|
||||
selection.toggle(shiftKey ? model : model.group);
|
||||
let modes = api.mode.modes;
|
||||
switch(api.mode.get()) {
|
||||
case modes.object:
|
||||
selection.toggle(shiftKey ? model : model.group);
|
||||
break;
|
||||
case modes.face:
|
||||
case modes.line:
|
||||
case modes.vertex:
|
||||
// find faces adjacent to point/line clicked
|
||||
model.find(int.point, int.face);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -121,12 +121,6 @@ let selection = {
|
|||
util.defer(selection.update);
|
||||
},
|
||||
|
||||
duplicate() {
|
||||
for (let m of selection.models()) {
|
||||
m.duplicate();
|
||||
}
|
||||
},
|
||||
|
||||
// update selection and wireframe for all objects
|
||||
update() {
|
||||
for (let group of groups) {
|
||||
|
|
@ -309,6 +303,12 @@ let tool = {
|
|||
});
|
||||
},
|
||||
|
||||
duplicate() {
|
||||
for (let m of selection.models()) {
|
||||
m.duplicate();
|
||||
}
|
||||
},
|
||||
|
||||
analyze(models) {
|
||||
models = fallback(models);
|
||||
api.log.emit('analyzing mesh(es)...').pin();
|
||||
|
|
@ -377,10 +377,46 @@ let tool = {
|
|||
}
|
||||
};
|
||||
|
||||
let modes = { object: "object", face: "face", line: "line", vertex: "vertex" };
|
||||
|
||||
// edit mode
|
||||
let mode = {
|
||||
set(mode) {
|
||||
prefs.save(prefs.map.mode = mode);
|
||||
for (let key of Object.values(modes)) {
|
||||
$(`mode-${key}`).classList.remove('selected');
|
||||
}
|
||||
$(`mode-${mode}`).classList.add('selected');
|
||||
},
|
||||
|
||||
get() {
|
||||
return prefs.map.mode;
|
||||
},
|
||||
|
||||
object() {
|
||||
mode.set(modes.object);
|
||||
},
|
||||
|
||||
face() {
|
||||
mode.set(modes.face);
|
||||
},
|
||||
|
||||
line() {
|
||||
mode.set(modes.line);
|
||||
},
|
||||
|
||||
vertex() {
|
||||
mode.set(modes.vertex);
|
||||
},
|
||||
|
||||
modes
|
||||
};
|
||||
|
||||
// persisted preference map
|
||||
let prefs = {
|
||||
map: {
|
||||
info: {},
|
||||
mode: modes.object,
|
||||
space: {
|
||||
wire: false,
|
||||
grid: true,
|
||||
|
|
@ -460,6 +496,8 @@ let api = mesh.api = {
|
|||
prefs.save( prefs.map.space.wire = wire );
|
||||
},
|
||||
|
||||
mode,
|
||||
|
||||
selection,
|
||||
|
||||
group,
|
||||
|
|
|
|||
|
|
@ -210,29 +210,37 @@ function ui_build() {
|
|||
// create slid in/out logging window
|
||||
h.bind(logger, [ h.div({ id: 'logtext' }) ]);
|
||||
|
||||
// a few shortcuts to api calls
|
||||
let { file, selection, mode, tool, prefs } = api;
|
||||
|
||||
// create hotkey/action menu (top/left)
|
||||
h.bind(actions, [
|
||||
h.div([
|
||||
// create and bind file loading elements
|
||||
h.button({ _: 'import', onclick: api.file.import }, [
|
||||
h.button({ _: 'import', onclick: file.import }, [
|
||||
h.input({
|
||||
id: "import", type: "file", class: ["hide"], multiple: true,
|
||||
onchange(evt) { broker.send.load_files(evt.target.files) }
|
||||
})
|
||||
]),
|
||||
h.button({ _: 'export', onclick: api.file.export }),
|
||||
h.button({ _: 'export', onclick: file.export }),
|
||||
h.div({ class: "vsep" }),
|
||||
h.button({ _: 'visible', onclick() { api.selection.visible({ toggle: true }) } }),
|
||||
h.button({ _: 'bounds', onclick() { api.selection.boundsBox({ toggle: true }) } }),
|
||||
h.button({ _: 'visible', onclick() { selection.visible({ toggle: true }) } }),
|
||||
h.button({ _: 'bounds', onclick() { selection.boundsBox({ toggle: true }) } }),
|
||||
h.button({ _: 'gridlines', onclick() { api.grid() } }),
|
||||
h.button({ _: 'wireframe', onclick() { api.wireframe() } }),
|
||||
h.div({ class: "vsep" }),
|
||||
h.button({ _: 'duplicate', onclick: api.selection.duplicate }),
|
||||
h.button({ _: 'merge', onclick: api.tool.merge }),
|
||||
h.button({ _: 'duplicate', onclick: tool.duplicate }),
|
||||
h.button({ _: 'merge', onclick: tool.merge }),
|
||||
h.div({ class: "vsep" }),
|
||||
h.button({ _: 'analyze', onclick: api.tool.analyze }),
|
||||
h.button({ _: 'repair', onclick: api.tool.repair }),
|
||||
h.button({ _: 'clean', onclick: api.tool.clean }),
|
||||
h.button({ _: 'analyze', onclick: tool.analyze }),
|
||||
h.button({ _: 'repair', onclick: tool.repair }),
|
||||
h.button({ _: 'clean', onclick: tool.clean }),
|
||||
h.div({ class: "vsep" }),
|
||||
h.button({ _: 'object', id: "mode-object", onclick() { mode.object() } }),
|
||||
h.button({ _: 'face', id: "mode-face", onclick() { mode.face() } }),
|
||||
h.button({ _: 'line', id: "mode-line", onclick() { mode.line() } }),
|
||||
h.button({ _: 'vertex', id: "mode-vertex", onclick() { mode.vertex() } }),
|
||||
]),
|
||||
]);
|
||||
|
||||
|
|
@ -261,14 +269,14 @@ function ui_build() {
|
|||
|
||||
// update model selector list (top/right)
|
||||
function update_selector() {
|
||||
let selHas = api.selection.contains;
|
||||
let selHas = selection.contains;
|
||||
// map groups to divs
|
||||
let groups = api.group.list()
|
||||
.map(g => h.div([
|
||||
h.button({ _: g.name || `group`, title: g.id,
|
||||
class: [ "group", selHas(g) ? 'selected' : undefined ],
|
||||
onclick(e) {
|
||||
e.shiftKey ? api.selection.toggle(g) : api.selection.set([g])
|
||||
e.shiftKey ? selection.toggle(g) : selection.set([g])
|
||||
}
|
||||
}),
|
||||
h.div({ class: "vsep" }),
|
||||
|
|
@ -280,10 +288,10 @@ function ui_build() {
|
|||
m.visible() ? undefined : 'hidden'
|
||||
],
|
||||
onclick(e) {
|
||||
let sel = api.selection.list();
|
||||
let sel = selection.list();
|
||||
e.shiftKey || (sel.length === 1 && m === sel[0]) ?
|
||||
api.selection.toggle(m) :
|
||||
api.selection.set([m])
|
||||
selection.toggle(m) :
|
||||
selection.set([m])
|
||||
}
|
||||
}))
|
||||
)
|
||||
|
|
@ -294,8 +302,8 @@ function ui_build() {
|
|||
// update model information dashboard (bottom)
|
||||
function update_selection() {
|
||||
let map = { fixed: 2 };
|
||||
let s_grp = api.selection.groups();
|
||||
let s_mdl = api.selection.models();
|
||||
let s_grp = selection.groups();
|
||||
let s_mdl = selection.models();
|
||||
if (s_mdl.length === 0) {
|
||||
return h.bind(selectlist, []);
|
||||
}
|
||||
|
|
@ -359,20 +367,20 @@ function ui_build() {
|
|||
...h_ara,
|
||||
...h_msh
|
||||
]);
|
||||
let prefs = api.prefs.map.info;
|
||||
let pmap = prefs.map.info;
|
||||
// map buttons to show/hide selection info
|
||||
function toggle(label, h, s, d) {
|
||||
s.onclick = () => {
|
||||
s.style.display = 'none';
|
||||
d.style.display = 'flex';
|
||||
api.prefs.save( prefs[label] = 'show' ); // <- :)
|
||||
prefs.save( pmap[label] = 'show' ); // <- :)
|
||||
};
|
||||
h.onclick = () => {
|
||||
d.style.display = 'none';
|
||||
s.style.display = 'flex';
|
||||
api.prefs.save( prefs[label] = 'hide' );
|
||||
prefs.save( pmap[label] = 'hide' );
|
||||
};
|
||||
if (prefs[label] === 'show') {
|
||||
if (pmap[label] === 'show') {
|
||||
s.onclick();
|
||||
} else {
|
||||
h.onclick();
|
||||
|
|
|
|||
|
|
@ -280,6 +280,16 @@ button:hover {
|
|||
border-bottom: 1px dashed gray;
|
||||
}
|
||||
|
||||
/** actions menu top/left **/
|
||||
|
||||
#actions button.selected {
|
||||
background-color: rgba(0,255,0,0.5);
|
||||
}
|
||||
|
||||
#actions button.selected:hover {
|
||||
background-color: rgba(0,255,0,1);
|
||||
}
|
||||
|
||||
/** slide in/out logging window **/
|
||||
|
||||
#logger {
|
||||
|
|
|
|||
Loading…
Reference in a new issue