UNPKG

@spearwolf/twopoint5d

Version:

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

164 lines 5.25 kB
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