@spearwolf/twopoint5d
Version:
a library to create 2.5d realtime graphics and pixelart with three.js
164 lines • 5.25 kB
JavaScript
import { emit, eventize, on, once } from '@spearwolf/eventize';
import { Display } from '../display/Display.js';
import { RemoveFromParent, StageAdded, StageRemoved } from '../events.js';
export class StageRenderer {
#parent;
#renderOrder;
#orderedStages;
set renderOrder(order) {
order = order || '*';
if (this.#renderOrder !== order) {
this.#renderOrder = order;
this.#renderOrderArray = undefined;
this.#orderedStages = undefined;
this.onRenderOrderChanged();
}
}
onRenderOrderChanged() {
}
get renderOrder() {
return this.#renderOrder;
}
#renderOrderArray;
get renderOrderArray() {
if (!this.#renderOrderArray) {
this.#renderOrderArray = this.renderOrder
.split(',')
.map((item) => item.trim())
.filter(Boolean);
}
return this.#renderOrderArray;
}
get parent() {
return this.#parent;
}
set parent(parent) {
if (this.#parent !== parent) {
if (this.#parent) {
this.#removeFromParent();
}
this.#parent = parent;
if (this.#parent) {
this.#addToParent();
}
}
}
#removeFromParent() {
emit(this, RemoveFromParent);
if (!(this.#parent instanceof Display)) {
this.#parent.removeStage(this);
}
}
#addToParent() {
if (this.#parent instanceof Display) {
this.#addToDisplay(this.#parent);
}
else {
this.#parent.addStage(this);
}
}
#addToDisplay(display) {
once(this, RemoveFromParent, on(display, 'resize', ({ width, height }) => {
this.resize(width, height, display.pixelRatio);
}));
once(this, RemoveFromParent, on(display, 'frame', ({ renderer, now, deltaTime, frameNo }) => {
this.renderFrame(renderer, now, deltaTime, frameNo);
}));
}
constructor() {
this.isStageRenderer = true;
this.name = 'StageRenderer';
this.width = 0;
this.height = 0;
this.pixelRatio = 1;
this.stages = [];
this.#renderOrder = '*';
this.#renderOrderArray = [];
eventize(this);
}
attach(parent) {
this.parent = parent;
}
detach() {
this.parent = undefined;
}
resize(width, height, pixelRatio = 1) {
this.width = width;
this.height = height;
this.pixelRatio = pixelRatio;
this.stages.forEach((stage) => this.resizeStage(stage, width, height));
this.onResizeRenderer(width, height, pixelRatio);
}
onResizeRenderer(_width, _height, _pixelRatio) {
}
resizeStage(stage, width, height) {
if (stage.width !== width || stage.height !== height) {
stage.width = width;
stage.height = height;
stage.stage.resize(width, height);
}
}
renderFrame(renderer, now, deltaTime, frameNo) {
this.getOrderedStages().forEach((stage) => {
this.resizeStage(stage, this.width, this.height);
stage.stage.renderFrame(renderer, now, deltaTime, frameNo);
});
}
getOrderedStages() {
if (this.#orderedStages)
return this.#orderedStages;
const renderOrder = this.renderOrderArray;
if (renderOrder.length === 0 || (renderOrder.length === 1 && (renderOrder[0] === '' || renderOrder[0] === '*'))) {
return this.stages;
}
const explicitlyNamedStages = new Map();
const otherStages = this.stages.slice();
renderOrder.forEach((name) => {
if (name !== '*') {
const index = otherStages.findIndex((stage) => stage.stage.name === name);
if (index !== -1) {
const stage = otherStages.splice(index, 1)[0];
explicitlyNamedStages.set(name, stage);
}
}
});
const orderedStages = renderOrder
.map((name) => {
if (name === '*') {
return otherStages;
}
return explicitlyNamedStages.get(name);
})
.flat()
.filter(Boolean);
explicitlyNamedStages.clear();
this.#orderedStages = orderedStages;
return orderedStages;
}
#getIndex(stage) {
return this.stages.findIndex((item) => item.stage === stage);
}
hasStage(stage) {
return this.#getIndex(stage) !== -1;
}
addStage(stage) {
if (!this.hasStage(stage)) {
this.stages.push({
stage,
width: 0,
height: 0,
});
this.#orderedStages = undefined;
emit(this, StageAdded, { stage, renderer: this });
}
}
removeStage(stage) {
const index = this.#getIndex(stage);
if (index !== -1) {
this.stages.splice(index, 1);
this.#orderedStages = undefined;
emit(this, StageRemoved, { stage, renderer: this });
}
}
}
//# sourceMappingURL=StageRenderer.js.map