/* dev:start */
import { makeDiv, removeAllChildren } from "../../../core/utils";
import { Vector } from "../../../core/vector";
import { Entity } from "../../entity";
import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach";
/**
* Allows to inspect entities by pressing F8 while hovering them
*/
export class HUDEntityDebugger extends BaseHUDPart {
createElements(parent) {
this.element = makeDiv(
parent,
"ingame_HUD_EntityDebugger",
[],
`
Use F8 to toggle this overlay
`
);
this.componentsElem = this.element.querySelector(".entityComponents");
}
initialize() {
this.root.gameState.inputReciever.keydown.add(key => {
if (key.keyCode === 119) {
// F8
this.pickEntity();
}
});
/**
* The currently selected entity
* @type {Entity}
*/
this.selectedEntity = null;
this.lastUpdate = 0;
this.domAttach = new DynamicDomAttach(this.root, this.element);
}
pickEntity() {
const mousePos = this.root.app.mousePosition;
if (!mousePos) {
return;
}
const worldPos = this.root.camera.screenToWorld(mousePos);
const worldTile = worldPos.toTileSpace();
const entity = this.root.map.getTileContent(worldTile, this.root.currentLayer);
this.selectedEntity = entity;
if (entity) {
this.rerenderFull(entity);
}
}
/**
*
* @param {string} name
* @param {any} val
* @param {number} indent
* @param {Array} recursion
*/
propertyToHTML(name, val, indent = 0, recursion = []) {
if (indent > 20) {
return;
}
if (val !== null && typeof val === "object") {
// Array is displayed like object, with indexes
recursion.push(val);
// Get type class name (like Array, Object, Vector...)
let typeName = `(${val.constructor ? val.constructor.name : "unknown"})`;
if (Array.isArray(val)) {
typeName = `(Array[${val.length}])`;
}
if (val instanceof Vector) {
typeName = `(Vector[${val.x}, ${val.y}])`;
}
const colorStyle = `color: hsl(${30 * indent}, 100%, 80%)`;
let html = `${name} ${typeName}
`;
for (const property in val) {
let hiddenValue = null;
if (val[property] == this.root) {
hiddenValue = "";
} else if (val[property] instanceof Node) {
hiddenValue = `<${val[property].constructor.name}>`;
} else if (recursion.includes(val[property])) {
// Avoid recursion by not "expanding" object more than once
hiddenValue = "";
}
html += this.propertyToHTML(
property,
hiddenValue ? hiddenValue : val[property],
indent + 1,
[...recursion] // still expand same value in other "branches"
);
}
html += "
";
return html;
}
const displayValue = (val + "")
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">");
return ` ${displayValue}`;
}
/**
* Rerenders the whole container
* @param {Entity} entity
*/
rerenderFull(entity) {
removeAllChildren(this.componentsElem);
let html = "";
const property = (strings, val) => ` ${val}`;
html += property`registered ${!!entity.registered}`;
html += property`uid ${entity.uid}`;
html += property`destroyed ${!!entity.destroyed}`;
for (const componentId in entity.components) {
const data = entity.components[componentId];
html += "";
html += "" + componentId + "
";
for (const property in data) {
// Put entity into recursion list, so it won't get "expanded"
html += this.propertyToHTML(property, data[property], 0, [entity]);
}
html += "