128 lines
4.1 KiB
JavaScript
128 lines
4.1 KiB
JavaScript
// Options picker
|
|
import {
|
|
DISPLAY_ACCELERATION_VECTORS,
|
|
DISPLAY_VELOCITY_VECTORS,
|
|
GRAVITATIONAL_CONSTANT,
|
|
MERGE_ON_COLLIDE,
|
|
PATH_TRACES_DASHED,
|
|
PAUSE_DURING_CREATION,
|
|
PAUSE_DURING_SELECTION,
|
|
TOOL_INFO_CLASSNAME,
|
|
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},
|
|
]
|
|
}, {
|
|
type: 'group', name: 'param', title: 'Parameters',
|
|
items: [
|
|
{type: 'number', name: 'gravity', title: 'Gravity', default: GRAVITATIONAL_CONSTANT},
|
|
]
|
|
}];
|
|
|
|
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;
|
|
}
|
|
case 'number': {
|
|
const div = document.createElement('div');
|
|
const title = document.createElement('button');
|
|
const input = document.createElement('input');
|
|
const maxLength = item.maxLength || 8;
|
|
div.appendChild(title);
|
|
div.appendChild(input);
|
|
div.classList.add(WIDE_CLASSNAME);
|
|
title.classList.add(TOOL_INFO_CLASSNAME);
|
|
if (item.wide) {
|
|
// title.classList.add(WIDE_CLASSNAME);
|
|
input.classList.add(WIDE_CLASSNAME);
|
|
}
|
|
title.innerHTML = item.title;
|
|
input.value = item.default;
|
|
this.setOption(path, item.default);
|
|
|
|
input.addEventListener('input', () => {
|
|
input.value = input.value.slice(0, maxLength);
|
|
});
|
|
|
|
input.addEventListener('change', () => {
|
|
this.setOption(path, input.value);
|
|
});
|
|
return div;
|
|
}
|
|
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
|
|
}
|
|
}
|