UNPKG

@spearwolf/twopoint5d

Version:

a library to create 2.5d realtime graphics and pixelart with three.js

158 lines 5.45 kB
import { emit, eventize, retain } from '@spearwolf/eventize'; import { Camera, Color, Scene, WebGLRenderer } from 'three'; import { FirstFrame, StageAfterCameraChanged, StageRenderFrame, StageResize, } from '../events.js'; const _oldClearColor = new Color(); export class Stage2D { get name() { return this.scene.name; } set name(name) { this.scene.name = name; } #containerWidth; #containerHeight; get containerWidth() { return this.#containerWidth; } get containerHeight() { return this.#containerHeight; } #width; #height; get width() { return this.#width; } get height() { return this.#height; } #projection; get projection() { return this.#projection; } set projection(projection) { if (this.#projection !== projection) { this.#projection = projection; this.#cameraFromProjection = undefined; this.update(true); } } #cameraFromProjection; #cameraUserOverride; get camera() { return this.#cameraUserOverride ?? this.#cameraFromProjection; } set camera(camera) { this.#updateCamera(() => void (this.#cameraUserOverride = camera)); } #updateCamera; constructor(projection, scene) { this.isStage2D = true; this.autoClear = true; this.clearColor = new Color(0x000000); this.clearAlpha = 0; this.needsUpdate = false; this.#containerWidth = 0; this.#containerHeight = 0; this.#width = 0; this.#height = 0; this.#updateCamera = (updateCallback) => { const prevCamera = this.camera; updateCallback(); if (prevCamera !== this.camera) { const args = [this, prevCamera]; emit(this, StageAfterCameraChanged, ...args); } }; this.#updateProjection = (width, height) => { this.needsUpdate = false; this.projection.updateViewRect(width, height); const [w, h] = this.projection.getViewRect(); const prevWidth = this.#width; const prevHeight = this.#height; this.#width = w; this.#height = h; if (this.camera != null) { this.projection.updateCamera(this.camera); } else { this.#updateCamera(() => { this.#cameraFromProjection = this.projection.createCamera(); }); } if (prevWidth !== w || prevHeight !== h) { emit(this, StageResize, { stage: this, width: w, height: h }); } }; this.isFirstFrame = true; this.#noCameraErrorCount = 0; eventize(this); retain(this, FirstFrame); this.projection = projection; this.scene = scene ?? new Scene(); } resize(width, height) { if (width !== this.#containerWidth || height !== this.#containerHeight) { this.#containerWidth = width; this.#containerHeight = height; if (this.projection) { this.#updateProjection(width, height); } } } update(forceUpdate = false) { if ((forceUpdate || this.needsUpdate) && this.projection) { this.#updateProjection(this.#containerWidth, this.#containerHeight); } } #updateProjection; #firstFrameProps; #noCameraErrorCount; renderFrame(renderer, now, deltaTime, frameNo, skipRenderCall = false) { const { scene, camera } = this; if (scene == null || camera == null) { if (!camera && ++this.#noCameraErrorCount === 100) { this.#noCameraErrorCount = -1000; console.warn('Stage2D has no camera and therefore cannot be rendered! normally this only happens if you forget to call the resize() method ..'); } return; } const renderFrameProps = { renderer, now, deltaTime, frameNo, stage: this, width: this.width, height: this.height, }; if (this.isFirstFrame) { this.#firstFrameProps = { ...renderFrameProps, scene: this.scene }; emit(this, FirstFrame, this.#firstFrameProps); this.isFirstFrame = false; } else if (this.#firstFrameProps != null) { Object.assign(this.#firstFrameProps, renderFrameProps); this.#firstFrameProps.scene = this.scene; } emit(this, StageRenderFrame, renderFrameProps); if (skipRenderCall) return; const previousAutoClearValue = renderer.autoClear; const oldClearAlpha = renderer.getClearAlpha(); if (this.autoClear) { renderer.getClearColor(_oldClearColor); } renderer.autoClear = this.autoClear; if (this.autoClear) { renderer.setClearColor(this.clearColor, this.clearAlpha); renderer.setClearAlpha(this.clearAlpha); } renderer.render(scene, camera); renderer.autoClear = previousAutoClearValue; if (this.autoClear) { renderer.setClearColor(_oldClearColor, oldClearAlpha); renderer.setClearAlpha(oldClearAlpha); } } } //# sourceMappingURL=Stage2D.js.map