gravity/select.js
2026-01-04 16:45:40 -06:00

91 lines
2.5 KiB
JavaScript

import {EVENT_SELECT} from './config.js';
import {add, copy, mult} from './vector.js';
export class Select {
sim = undefined;
box = {
start: undefined,
end: undefined,
};
selectedSingle = undefined;
selectedGroup = [];
constructor(sim) {
this.sim = sim;
// TODO: Move this to a new Keyboard class singleton
window.addEventListener('keydown', (e) => {
switch (e.key) {
case 'Tab': {
e.preventDefault();
if (!this.selectedGroup.length) return;
const currentIdx = this.selectedGroup.indexOf(this.selectedSingle);
const newIdx = (currentIdx + 1) % this.selectedGroup.length;
this.selectedSingle = this.selectedGroup[newIdx];
break;
}
}
});
}
handlePointerDown({x: clientX, y: clientY}) {
this.box.start = this.sim.screenToSim(clientX, clientY);
this.box.end = this.box.start;
// this.getSelectedObjects();
}
handlePointerMove({x: clientX, y: clientY}) {
if (!this.box.start) return;
this.box.end = this.sim.screenToSim(clientX, clientY);
}
handlePointerUp() {
if (!this.box.start) return;
const start = copy(this.box.start);
const end = copy(this.box.end);
this.box.start = {
x: Math.min(start.x, end.x),
y: Math.min(start.y, end.y),
};
this.box.end = {
x: Math.max(start.x, end.x),
y: Math.max(start.y, end.y),
};
this.getSelectedObjects();
this.sim.div.dispatchEvent(new CustomEvent(EVENT_SELECT));
this.box = {
start: undefined,
end: undefined,
};
}
frame(elapsedTime) {
if (!this.box.start) return;
// If panning, let's update the position of our box so it doesn't drift away
const {velocity} = this.sim.panning;
const delta = mult(velocity, elapsedTime);
this.box.start = add(this.box.start, delta);
this.box.end = add(this.box.end, delta);
// Display the box
this.sim.display.drawBox(this.box.start, this.box.end);
}
getSelectedObjects() {
const {start, end} = this.box;
if (!start) return;
this.selectedGroup = this.sim.system.filter(({position: {x, y}}) => {
return x >= start.x && x <= end.x && y >= start.y && y <= end.y;
});
// For now, first object in group is selected single
this.selectedSingle = this.selectedGroup[0] ?? undefined;
}
// cb: ({selectedGroup, selectedSingle}) => undefined
onSelect(cb) {
this.sim.div.addEventListener(EVENT_SELECT, () => {
const {selectedGroup, selectedSingle} = this;
cb({selectedGroup, selectedSingle});
});
}
}