gravity/tool/utility.js
2025-12-31 18:41:50 -06:00

95 lines
2.6 KiB
JavaScript

import {Tool} from '../tool.js';
import {
TOOL_INFO_CLASSNAME,
WIDE_CLASSNAME,
} from '../config.js';
export class UtilityTool extends Tool {
currentTimeEl = undefined;
get timeText() {
let time = this.sim.time;
// Time in milliseconds
const ms = Math.floor(time % 1000);
time = (time - ms) / 1000;
const s = Math.floor(time % 60);
time = (time - s) / 60;
const m = Math.floor(time % 60);
time = (time - m) / 60;
const h = Math.floor(time % 24);
time = (time - h) / 24;
const d = Math.floor(time);
return [
d || undefined,
h.toString().padStart(2, '0'),
m.toString().padStart(2, '0'),
[
s.toString().padStart(2, '0'),
ms.toString().padStart(3, '0'),
].join('.')
].filter(x => x !== undefined).join(':');
}
frame() {
if (this.currentTimeEl) {
this.currentTimeEl.innerHTML = this.timeText;
}
}
constructor(container) {
super(container);
const zeroVelocity = document.createElement('button');
const clearTraces = document.createElement('button');
const currentTime = document.createElement('button');
const clearDebug = document.createElement('button');
this.currentTimeEl = currentTime;
this.div.appendChild(currentTime);
this.div.appendChild(zeroVelocity);
this.div.appendChild(clearTraces);
this.div.appendChild(clearDebug);
zeroVelocity.classList.add(WIDE_CLASSNAME);
clearTraces.classList.add(WIDE_CLASSNAME);
currentTime.classList.add(TOOL_INFO_CLASSNAME);
currentTime.classList.add(WIDE_CLASSNAME);
clearDebug.classList.add(WIDE_CLASSNAME);
zeroVelocity.innerHTML = 'Zero Momentum';
clearTraces.innerHTML = 'Clear Traces';
currentTime.innerHTML = this.timeText;
clearDebug.innerHTML = 'Clear Debug';
zeroVelocity.addEventListener('click', () => {
// Determine center of mass and average momentum
const { totalMass, netMomentum } = this.sim.system.computeSystemCenter();
const netVelocity = {
x: netMomentum.x / totalMass,
y: netMomentum.y / totalMass,
};
// Apply offset to all object velocities
this.sim.system.forEachObject(obj => {
obj.velocity.x -= netVelocity.x;
obj.velocity.y -= netVelocity.y;
});
// Cancel panning
this.sim.panning = undefined;
});
clearTraces.addEventListener('click', () => {
// Obliterate object histories
this.sim.system.forEachObject(obj => {
obj.history = [];
}, {alive: null});
});
clearDebug.addEventListener('click', () => {
this.sim.info = {};
});
}
}