vtt-mapper/src/renderer/renderer.class.ts

118 lines
2.9 KiB
TypeScript

import * as Three from 'three';
import { RESOLUTION_X, RESOLUTION_Y } from '../consts';
import Stats from 'stats.js';
import { Point } from '../physics/common';
import Selector from './selector.class';
import Asset from '../assets/asset.class';
export enum CursorType
{
default = "default",
pointer = "pointer",
move = "move",
updown = "ns-resize",
leftright = "ew-resize",
nesw = "nesw-resize",
nwse = "nwse-resize",
//rotate = "url(public/rotate.png)"
rotate = "crosshair" //tmp
}
export default class Renderer
{
static scene: Three.Scene;
static aspect: number;
static renderer: Three.WebGLRenderer;
static camera: Three.OrthographicCamera;
static #zoom: number;
static #pos: Point = { x: 0, y: 0 };
static #stats: Stats;
static init(): Boolean
{
try {
this.renderer = new Three.WebGLRenderer({ antialias: true });
this.renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild(this.renderer.domElement);
this.scene = new Three.Scene();
this.camera = new Three.OrthographicCamera();
this.camera.position.z = 500;
this.#zoom = 5;
const stats = this.#stats = new Stats();
stats.showPanel(0);
document.body.appendChild(stats.dom);
this.#resize();
window.addEventListener("resize", this.#resize.bind(this));
return true;
}
catch(e)
{
console.error(e);
return false;
}
}
static get canvas(): HTMLCanvasElement
{
return this.renderer.domElement;
}
static get zoom(): number
{
return this.#zoom;
}
static set zoom(v: number)
{
this.#zoom = v;
this.#resize();
}
static move(x: number, y: number): void
{
this.#pos.x += x;
this.#pos.y += y;
this.camera.position.x += x;
this.camera.position.y += y;
}
static screenSpaceToCameraSpace(x: number, y: number, omit: boolean = false): Point {
return { x: ((x / window.innerWidth - 0.5) * RESOLUTION_X * this.aspect) / this.#zoom + (omit ? 0 : this.#pos.x), y: (- (y / window.innerHeight - 0.5) * RESOLUTION_Y) / this.zoom + (omit ? 0 : this.#pos.y) };
}
static #resize(): void
{
const aspect = this.aspect = window.innerWidth / window.innerHeight;
this.renderer.setSize( window.innerWidth, window.innerHeight );
this.camera.left = RESOLUTION_X * aspect / - 2 / this.#zoom;
this.camera.right = RESOLUTION_X * aspect / 2 / this.#zoom;
this.camera.top = RESOLUTION_Y / 2 / this.#zoom;
this.camera.bottom = RESOLUTION_Y / - 2 / this.#zoom;
this.camera.updateProjectionMatrix();
this.render();
}
static render(delta?: number): void
{
this.#stats.begin();
Selector.update();
this.renderer.render(this.scene, this.camera);
Asset.quadtree.cleanup();
this.#stats.end();
}
static startRendering(): void
{
this.renderer.setAnimationLoop(Renderer.render.bind(Renderer));
}
static stopRendering(): void
{
this.renderer.setAnimationLoop(null);
}
static cursor(type?: CursorType): void
{
Renderer.canvas.style.setProperty("cursor", type ?? CursorType.default);
}
}