UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

243 lines (166 loc) • 6.09 kB
import { assert } from "../../../../../core/assert.js"; import LabelView from "../../../../../view/common/LabelView.js"; import { CSS_ABSOLUTE_POSITIONING } from "../../../../../view/CSS_ABSOLUTE_POSITIONING.js"; import EmptyView from "../../../../../view/elements/EmptyView.js"; import { decompose_finger_print } from "../tile/decompose_finger_print.js"; import { tile_address_to_finger_print } from "../tile/tile_address_to_finger_print.js"; class TextureLODView extends EmptyView { /** * * @type {View[]} */ #tiles = []; #resolution = [1, 1]; constructor({ resolution = [1, 1], tile_size = 8 }) { super({ css: CSS_ABSOLUTE_POSITIONING }); this.css({ background: "rgba(255,255,255,0.05)" }); this.#resolution = resolution; const width = resolution[0]; const height = resolution[1]; assert.isNonNegativeInteger(width, 'width'); assert.isNonNegativeInteger(height, 'height'); for (let j = 0; j < height; j++) { for (let i = 0; i < width; i++) { const tileView = new EmptyView({ css: CSS_ABSOLUTE_POSITIONING }); // const flipped_y = height - j - 1; tileView.position.set(i * tile_size, j * tile_size); // tileView.position.set(i * tile_size, flipped_y * tile_size); tileView.size.set(tile_size, tile_size); this.clearTile(tileView); this.#tiles.push(tileView) this.addChild(tileView); } } this.size.set(width * tile_size, height * tile_size); const label = new LabelView(`${width} x ${height}`, { css: { ...CSS_ABSOLUTE_POSITIONING, color: '#FFFFFF', textShadow: '0 0 2px black', whiteSpace: "pre" } }); label.position.set(this.size.x + 4, (this.size.y - 20) * 0.5); this.addChild(label); } clear() { const resolution = this.#resolution; const count = resolution[0] * resolution[1]; for (let i = 0; i < count; i++) { const view = this.#tiles[i]; this.clearTile(view); } } /** * * @param {View} view */ clearTile(view) { view.css({ background: "none" }); view.visible = false; } getTile(x, y) { assert.isNonNegativeInteger(x, 'x'); assert.isNonNegativeInteger(y, 'y'); const resolution = this.#resolution; // assert.lessThan(x, resolution[0]); // assert.lessThan(y, resolution[1]); const width = resolution[0]; const view = this.#tiles[x + width * y]; if (view === undefined) { debugger } return view; } } export class UsagePyramidDebugView extends EmptyView { #levels = []; #resolution = [1, 1]; #tile_size = 0; #used_set = []; #used_set_size = 0; #image_url = null setImageURL(url) { this.#image_url = url; this.#applyImageURL(); } #applyImageURL() { const background = { backgroundImage: this.#image_url === null ? "none" : `url(${this.#image_url})`, backgroundSize: "contain" }; this.#levels.forEach(l => { l.css(background); }); } setTextureParameters(resolution, tile_size) { if (this.#resolution[0] === resolution && this.#resolution[1] === resolution && this.#tile_size === tile_size) { return; } this.#tile_size = tile_size; this.#resolution = [resolution, resolution]; this.#levels.splice(0, this.#levels.length); this.removeAllChildren(); let size = resolution / tile_size; assert.isNonNegativeInteger(size, 'size'); while (size > 0) { const lod = new TextureLODView({ resolution: [size, size], }); lod.css({ border: "1px solid rgba(0,0,0,0.7)" }); this.#levels.push(lod); this.addChild(lod); size >>>= 1; } this.#levels.reverse(); let y = 0; for (let i = 0; i < this.#levels.length; i++) { const level = this.#levels[i]; level.position.set(2, y); y += level.size.y + 4; } this.#applyImageURL(); } /** * * @param {VirtualTextureUsage} usage */ set usage(usage) { for (let i = 0; i < this.#used_set_size; i++) { const finger_print = this.#used_set[i]; const { mip, x, y } = decompose_finger_print(finger_print); const mipView = this.#levels[mip]; const tile = mipView.getTile(x, y); mipView.clearTile(tile); } this.#used_set_size = 0; const occupancy = usage.occupancy; const occupancyCount = usage.occupancy_count; for (let i = 0; i < occupancyCount; i++) { const occupancy_index = occupancy[i]; const fingerPrint = tile_address_to_finger_print(occupancy_index); const count = usage.getCountByFingerprint(fingerPrint); if (count <= 0) { continue; } const { mip, x, y } = decompose_finger_print(fingerPrint); const mipView = this.#levels[mip]; const tile = mipView.getTile(x, y); tile.css({ background: "rgba(255,0,0,0.8)" }); tile.visible = true; this.#used_set[this.#used_set_size] = fingerPrint; this.#used_set_size++; } } }