add prefs dialog, dark mode
This commit is contained in:
parent
853816e921
commit
536da7acbf
6 changed files with 87 additions and 23 deletions
|
|
@ -112,7 +112,7 @@ function restore_space() {
|
|||
store_matrices();
|
||||
}).then(() => {
|
||||
// restore preferences after models are restored
|
||||
api.prefs.load().then(() => {
|
||||
return api.prefs.load().then(() => {
|
||||
let { map } = api.prefs;
|
||||
let { space, mode } = map;
|
||||
api.grid(space.grid);
|
||||
|
|
@ -123,10 +123,13 @@ function restore_space() {
|
|||
api.selection.set([...smodel, ...sgroup]);
|
||||
// restore edit mode
|
||||
api.mode.set(mode);
|
||||
// restore dark mode
|
||||
set_darkmode(map.space.dark);
|
||||
});
|
||||
});
|
||||
}).finally(() => {
|
||||
// hide loading curtain
|
||||
$d('curtain','none');
|
||||
});
|
||||
}
|
||||
|
||||
// toggle edit/split temporary mode (present plane on hover)
|
||||
|
|
@ -254,8 +257,13 @@ function space_init(data) {
|
|||
if (api.modal.showing) {
|
||||
return;
|
||||
}
|
||||
if (evt.key === '?') {
|
||||
return api.help();
|
||||
}
|
||||
let { shiftKey, metaKey, ctrlKey, code } = evt;
|
||||
switch (code) {
|
||||
case 'KeyQ':
|
||||
return api.settings();
|
||||
case 'KeyI':
|
||||
return api.file.import();
|
||||
case 'KeyX':
|
||||
|
|
@ -454,6 +462,29 @@ function object_destroy(id) {
|
|||
store_matrices();
|
||||
}
|
||||
|
||||
// listen for changes like dark mode toggle
|
||||
function set_darkmode(dark) {
|
||||
let { prefs } = mesh.api;
|
||||
let { sky, platform } = moto.Space;
|
||||
if (dark) {
|
||||
mesh.material.wireframe.color.set(0xeeeeee);
|
||||
} else {
|
||||
mesh.material.wireframe.color.set(0,0,0);
|
||||
}
|
||||
sky.set({ color: dark ? 0 : 0xffffff });
|
||||
platform.set({
|
||||
grid: dark ? {
|
||||
colorMajor: 0x666666,
|
||||
colorMinor: 0x333333,
|
||||
} : {
|
||||
colorMajor: 0xcccccc,
|
||||
colorMinor: 0xeeeeee,
|
||||
},
|
||||
});
|
||||
prefs.map.space.dark = dark;
|
||||
prefs.save();
|
||||
}
|
||||
|
||||
// bind functions to topics
|
||||
broker.listeners({
|
||||
load_files,
|
||||
|
|
@ -461,6 +492,7 @@ broker.listeners({
|
|||
space_load,
|
||||
object_matrix,
|
||||
object_destroy,
|
||||
set_darkmode,
|
||||
edit_split
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -420,6 +420,10 @@ let mode = {
|
|||
},
|
||||
};
|
||||
|
||||
// cache pref signature so we know when it changes
|
||||
let prefsig;
|
||||
let prefsignew;
|
||||
|
||||
// persisted preference map
|
||||
let prefs = {
|
||||
map: {
|
||||
|
|
@ -433,14 +437,18 @@ let prefs = {
|
|||
},
|
||||
},
|
||||
|
||||
put(key, val) {
|
||||
prefs.map[key] = val;
|
||||
prefs.update();
|
||||
// look for changes in pref signature
|
||||
changed() {
|
||||
prefsignew = JSON.stringify(prefs.map);
|
||||
return prefsignew !== prefsig;
|
||||
},
|
||||
|
||||
// persist to data store
|
||||
save() {
|
||||
if (prefs.changed()) {
|
||||
mesh.db.admin.put("prefs", prefs.map);
|
||||
prefsig = prefsignew;
|
||||
}
|
||||
},
|
||||
|
||||
// reload from data store
|
||||
|
|
@ -546,6 +554,6 @@ broker.wrapObject(model, 'model');
|
|||
broker.wrapObject(group, 'group');
|
||||
|
||||
// optimize db writes by merging updates
|
||||
prefs.save = util.deferWrap(prefs.save);
|
||||
prefs.save = util.deferWrap(prefs.save, 100);
|
||||
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -169,6 +169,18 @@ let log = api.log = {
|
|||
// bind endpoint for worker to log in the ui
|
||||
gapp.broker.subscribe("mesh.log", log.emit);
|
||||
|
||||
// bind settings endpoint to api
|
||||
api.settings = function() {
|
||||
modal.show('settings', h.div([
|
||||
h.label('dark mode'),
|
||||
h.input({
|
||||
type: "checkbox",
|
||||
onchange: ev => call.set_darkmode(ev.target.checked),
|
||||
[ api.prefs.map.space.dark ? 'checked' : 'unchecked' ] : 1
|
||||
})
|
||||
]));
|
||||
}
|
||||
|
||||
// create html elements
|
||||
function ui_build() {
|
||||
// set app version
|
||||
|
|
@ -177,8 +189,12 @@ function ui_build() {
|
|||
|
||||
// add a help button
|
||||
h.bind($('top-right'), [
|
||||
h.div({ id: "help", onclick: api.help },
|
||||
[ h.div({ class: "far fa-question-circle" }) ])
|
||||
h.div({ id: "top-settings", onclick: api.settings }, [
|
||||
h.div({ class: "fas fa-sliders-h" }),
|
||||
]),
|
||||
h.div({ id: "top-help", onclick: api.help }, [
|
||||
h.div({ class: "far fa-question-circle" }),
|
||||
]),
|
||||
]);
|
||||
|
||||
// create top level app areas
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ let util = mesh.util = {
|
|||
rec.timer = setTimeout(() => {
|
||||
deferFn.remove(rec);
|
||||
fn();
|
||||
});
|
||||
}, time);
|
||||
deferFn.push(rec);
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -458,8 +458,8 @@
|
|||
}
|
||||
|
||||
function setGridColor(opt = {}) {
|
||||
grid.colorMajor = valueOr(opt.major, grid.colorMajor);
|
||||
grid.colorMinor = valueOr(opt.minor, grid.colorMinor);
|
||||
grid.colorMajor = valueOr(opt.major || opt.colorMajor, grid.colorMajor);
|
||||
grid.colorMinor = valueOr(opt.minor || opt.colorMinor, grid.colorMinor);
|
||||
grid.colorX = valueOr(opt.colorX, grid.colorX);
|
||||
grid.colorY = valueOr(opt.colorY, grid.colorY);
|
||||
updateGrid();
|
||||
|
|
@ -921,8 +921,8 @@
|
|||
function setSky(opt = {}) {
|
||||
let { grid, color, gridColor } = opt;
|
||||
if (grid) Space.sky.showGrid(grid);
|
||||
if (color) Space.sky.setColor(color);
|
||||
if (gridColor) Space.sky.setGridColor(gridColor);
|
||||
if (color !== undefined) Space.sky.setColor(color);
|
||||
if (gridColor !== undefined) Space.sky.setGridColor(gridColor);
|
||||
}
|
||||
|
||||
function setPlatform(opt = {}) {
|
||||
|
|
@ -945,7 +945,7 @@
|
|||
let { colorX, colorY, colorMajor, colorMinor } = grid;
|
||||
platform.setGrid(major, minor);
|
||||
platform.setGridColor({ colorX, colorY, colorMajor, colorMinor });
|
||||
platform.setGridZOff(zOffset);
|
||||
if (zOffset !== undefined) platform.setGridZOff(zOffset);
|
||||
}
|
||||
if (origin) {
|
||||
let { x, y, z, show } = origin;
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ body, div {
|
|||
padding: 3px 0 3px 0;
|
||||
flex-direction: row;
|
||||
font-family: 'Russo One', sans-serif;
|
||||
background-color: rgba(255,255,255,0.75);
|
||||
background-color: rgba(255,255,255,0.55);
|
||||
}
|
||||
|
||||
#top-sep {
|
||||
|
|
@ -168,20 +168,26 @@ button:hover {
|
|||
position: absolute;
|
||||
padding: 3px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
right: 3px;
|
||||
top: 0;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
#help {
|
||||
#top-right > div {
|
||||
flex-direction: row;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#top-right > div:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#top-settings, #top-help {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
#help:hover {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.export {
|
||||
flex-direction: column;
|
||||
font-family: monospace;
|
||||
|
|
@ -236,6 +242,8 @@ button:hover {
|
|||
border-top-right-radius: 4px;
|
||||
border-bottom: 1px solid gray;
|
||||
background-color: rgba(0,0,0,0.2);
|
||||
font-family: 'Russo One', monospace;
|
||||
font-size: smaller;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue