gravity/tool/options.js
2025-12-28 15:19:58 -06:00

95 lines
3.0 KiB
JavaScript

// Options picker
import {
DISPLAY_ACCELERATION_VECTORS,
DISPLAY_VELOCITY_VECTORS,
MERGE_ON_COLLIDE,
PATH_TRACES_DASHED,
PAUSE_DURING_CREATION,
PAUSE_DURING_SELECTION,
WIDE_CLASSNAME,
} from '../config.js';
import {Tool} from '../tool.js';
export class Options extends Tool {
options = [{
type: 'group', name: 'pauseDuring', title: 'Pause During',
items: [
{type: 'boolean', name: 'creation', title: 'Create', default: PAUSE_DURING_CREATION},
{type: 'boolean', name: 'selection', title: 'Select', default: PAUSE_DURING_SELECTION},
]
}, {
type: 'group', name: 'display', title: 'Display',
items: [
{type: 'boolean', name: 'velocity', title: 'Velocity', default: DISPLAY_VELOCITY_VECTORS},
{type: 'boolean', name: 'acceleration', title: 'Accel', default: DISPLAY_ACCELERATION_VECTORS},
{type: 'boolean', name: 'traces', title: 'Traces', default: DISPLAY_ACCELERATION_VECTORS},
{type: 'boolean', name: 'dashedTraces', title: 'Dashed', default: PATH_TRACES_DASHED},
]
}, {
type: 'group', name: 'collision', title: 'Collision',
items: [
{type: 'boolean', name: 'merge', title: 'Merge Masses', default: MERGE_ON_COLLIDE, wide: true},
]
}];
values = {};
visitItem(item, path) {
path = [path, item.name].filter(x => !!x).join('.');
switch (item.type) {
case 'group': {
const group = document.createElement('div');
const heading = document.createElement('h3');
heading.innerHTML = item.title;
group.appendChild(heading);
for (const next of item.items) {
const child = this.visitItem(next, path);
group.appendChild(child);
}
return group;
}
case 'boolean': {
const button = document.createElement('button');
button.innerHTML = item.title;
if (item.wide === true) {
button.classList.add(WIDE_CLASSNAME);
}
this.setOption(path, item.default);
button.style.opacity = this.values[path] ? '100%' : '50%';
button.addEventListener('click', () => {
this.setOption(path, !this.getOption(path));
button.style.opacity = this.values[path] ? '100%' : '50%';
});
return button;
}
default:
throw new Error('unknown option type');
}
}
constructor(toolbar) {
super(toolbar);
const heading = document.createElement('h2');
heading.innerHTML = 'Options';
// this.div.appendChild(heading);
for (const item of this.options) {
const child = this.visitItem(item);
this.div.appendChild(child);
}
// Global methods to get/set current option values
this.sim.getOption = (path) => this.getOption(path);
this.sim.setOption = (path, value) => this.setOption(path, value);
}
getOption(path) {
const val = this.values[path];
return val;
}
setOption(path, value) {
this.values[path] = value;
// TODO Update button opacity in case this is called from elsewhere
}
}