@spearwolf/twopoint5d
Version:
a library to create 2.5d realtime graphics and pixelart with three.js
158 lines • 5.45 kB
JavaScript
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