85 lines
2.3 KiB
JavaScript
85 lines
2.3 KiB
JavaScript
import { Display } from './display.js';
|
|
import { Overlay } from './overlay.js';
|
|
import { Pointer } from './pointer.js';
|
|
import { Objects } from './objects.js';
|
|
import { Toolbar } from './toolbar.js';
|
|
import { PlayPause } from './tools/play-pause.js';
|
|
import { SCALE_MAX, SCALE_MIN} from './config.js';
|
|
|
|
export class Sim {
|
|
info = {};
|
|
time = undefined;
|
|
nextZoom = undefined;
|
|
playing = true;
|
|
|
|
display = undefined;
|
|
overlay = undefined;
|
|
pointer = undefined;
|
|
objects = undefined;
|
|
|
|
init(divId) {
|
|
this.divId = divId;
|
|
const div = document.getElementById(this.divId);
|
|
this.div = div;
|
|
|
|
this.display = new Display(this);
|
|
this.overlay = new Overlay(this);
|
|
this.pointer = new Pointer(this);
|
|
this.objects = new Objects(this);
|
|
this.toolbar = new Toolbar(this);
|
|
|
|
// Set up toolbar
|
|
this.toolbar.addTool(new PlayPause(this.toolbar));
|
|
|
|
// Initiate main loop
|
|
this.time = document.timeline.currentTime;
|
|
requestAnimationFrame(t => this.loop(t));
|
|
}
|
|
|
|
scheduleZoom({x, y}, factor) {
|
|
this.nextZoom = {x, y, factor};
|
|
}
|
|
|
|
zoom({x, y, factor}) {
|
|
// x, y are the mouse coordinates, which should be the center of the new view frame
|
|
// the new view origin should be x, y minus half the new view width and height
|
|
// compute new scale
|
|
this.display.scale = this.display.scale * factor;
|
|
if (this.display.scale > SCALE_MAX) this.display.scale = SCALE_MAX;
|
|
if (this.display.scale < SCALE_MIN) this.display.scale = SCALE_MIN;
|
|
// compute coordinates of new view frame
|
|
this.display.viewOrigin.x = x - this.display.width / 2;
|
|
this.display.viewOrigin.y = y - this.display.height / 2;
|
|
}
|
|
|
|
// Transform display coordinates to simulator coordinates using scale and viewOrigin
|
|
screenToSim(x, y) {
|
|
return this.display.screenToSim(x, y);
|
|
}
|
|
|
|
play() {
|
|
this.playing = true;
|
|
}
|
|
|
|
pause() {
|
|
this.playing = false;
|
|
}
|
|
|
|
// Main loop
|
|
loop(currentTime) {
|
|
const elapsedTime = currentTime - this.time;
|
|
this.time = currentTime;
|
|
if (this.nextZoom) {
|
|
this.zoom(this.nextZoom);
|
|
this.nextZoom = undefined;
|
|
}
|
|
this.info['scale'] = this.display.scale;
|
|
this.objects.computeFrame(elapsedTime);
|
|
this.display.fillCanvas();
|
|
this.display.drawObjects();
|
|
this.overlay.updateDraggable();
|
|
this.overlay.renderInfo();
|
|
requestAnimationFrame(t => this.loop(t));
|
|
}
|
|
}
|