Skip to content

Commit

Permalink
First pass on some a naive debug tool
Browse files Browse the repository at this point in the history
  • Loading branch information
hubol committed Jan 5, 2024
1 parent 07ebec3 commit 3ca2be3
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 17 deletions.
60 changes: 58 additions & 2 deletions public/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,16 @@ html {

body {
background-color: var(--bg-color);
display: flex;
height: 100%;
}

main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
flex-grow: 1;
}

noscript {
Expand Down Expand Up @@ -350,4 +355,55 @@ noscript {
100% {
background-position: calc(var(--ant-size) * 2) 0;
}
}
}

.debug_panel {
width: calc(100vw - 100vh);
background-color: #1E1E1E;
font-family: "JetBrains Mono", monospace;
font-size: 14px;
padding: 1em;
overflow-y: scroll;
}

.color {
display: inline-block;
width: 1em;
height: 1em;
margin-right: 0.3em;
border: solid 1px #808080;
}

.debug_panel .name {
color: rgb(209, 159, 23);
}

.debug_panel .info {
color: rgb(23, 104, 209);
}

.debug_panel .properties {
color: rgb(135, 23, 209);
font-style: italic;
}

.debug_panel .children {
margin-top: 0.3em;
padding-left: 1em;
border-left: solid 1px #776100;
position: relative;
}

.debug_panel .children > *::before {
content: '';
display: inline-block;
position: absolute;
width: 0.8em;
border-top: solid 1px #776100;
margin-top: 0.5em;
margin-left: -1em;
}

.debug_panel .hidden {
display: none;
}
18 changes: 10 additions & 8 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@
</head>

<body>
<div id="loading">
<button id="user_gesture">
<span>Please Click</span>
</button>
<div id="loading_bar">
<div id="preload"></div>
<div class="front"></div>
<main>
<div id="loading">
<button id="user_gesture">
<span>Please Click</span>
</button>
<div id="loading_bar">
<div id="preload"></div>
<div class="front"></div>
</div>
</div>
</div>
</main>
<noscript>JavaScript&trade; is required to play this game.</noscript>
</body>

Expand Down
3 changes: 3 additions & 0 deletions src/igua/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { IguaScene, IguaSceneStack } from "./igua-scene-stack";
import { Collision } from "../lib/pixi/collision";
import { setDefaultStages } from "../lib/game-engine/default-stages";
import { devAssignDisplayObjectIdentifiers } from "../lib/pixi/dev-assign-displayobject-identifiers";
import { createDebugPanel } from "../lib/game-engine/debug/debug-panel";

export let renderer: PixiRenderer;

Expand All @@ -21,6 +22,8 @@ export let scene: IguaScene;
export const sceneStack = new IguaSceneStack(layers, (_scene) => scene = _scene);

export function installGlobals(_renderer: PixiRenderer) {
// document.body.appendChild(createDebugPanel(rootStage));

renderer = _renderer;

renderer.view.style.opacity = '0';
Expand Down
3 changes: 3 additions & 0 deletions src/igua/scenes/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { objText } from "../../assets/fonts";
import { sleep } from "../../lib/game-engine/promise/sleep";
import { IguanaLooks } from "../iguana/looks";
import { lerp } from "../../lib/game-engine/promise/lerp";
import { createDebugPanel } from "../../lib/game-engine/debug/debug-panel";

const TailTextures = Tx.Iguana.Tail.split({ width: 28, trimFrame: true });

Expand Down Expand Up @@ -214,4 +215,6 @@ export function SceneTest() {
objText.Small('Hubol was here\nSwag!', { tint: 0xffffff }).at(64, 64).show();
objText.Large('Hubol was here\nSwag!', { tint: 0xff0040 }).at(48, 96).show();
objText.MediumDigits('0123456789', { tint: 0xdd7e95 }).at(64, 128).show();

document.body.appendChild(createDebugPanel(scene.stage));
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ ErrorReporter.announcer = createDomErrorAnnouncer();

function addGameCanvasToDocument(element: HTMLCanvasElement) {
element.id = "game_canvas";
document.body.appendChild(element);
document.getElementsByTagName('main')[0].appendChild(element);

return element;
}
201 changes: 201 additions & 0 deletions src/lib/game-engine/debug/debug-panel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import { BitmapText, Container, DisplayObject, Graphics, Sprite } from "pixi.js";
import { AdjustColor } from "../../pixi/adjust-color";

export function createDebugPanel(root: Container) {
const el = document.createElement('div');
el.className = 'debug_panel';
el.appendChild(new DisplayObjectComponent(root).el);
return el;
}

class DisplayObjectComponent {
expanded = true;
readonly el = document.createElement('div');
private readonly _nameContainerEl = this.div('name_container');
private readonly _colorEl = this.dom('span', 'color', this._nameContainerEl);
private readonly _nameEl = this.dom('span', 'name', this._nameContainerEl);
private readonly _propertiesEl = this.div('properties');
private readonly _infoEl = this.div('info');
private readonly _childrenEl = this.div('children');

constructor(readonly obj: DisplayObject) {
this._nameEl.textContent = getTypeName(obj);
this._propertiesEl.textContent = getExtendedPropertyKeysString(obj);
this.update();
}

private div(className?: string, target = this.el) {
return this.dom("div", className, target);
}

private dom(tag = "div", className?: string, target: HTMLElement = this.el) {
const el = document.createElement(tag);
if (className)
el.className = className;
target.appendChild(el);
return el;
}

private readonly _objectsDisplayed = new Set<DisplayObject>();

update() {
const color = getTintCssColor(this.obj);
this._colorEl.classList[color ? 'remove' : 'add']('hidden');
if (color)
this._colorEl.style.backgroundColor = color;

this._infoEl.textContent = getTypeInformationString(this.obj);

this._childrenEl.classList[this.expanded ? 'remove' : 'add']('hidden');

if (this.expanded && childrenHaveChanged(this.obj, this._objectsDisplayed)) {
this._objectsDisplayed.clear();

for (let i = 0; i < this.obj.children!.length; i++) {
const child = this.obj.children![i] as DisplayObject;
this._childrenEl.appendChild(new DisplayObjectComponent(child).el);
}
}
}
}

function traverseAndUpdate(c: DisplayObjectComponent) {

}

class DisplayObjectStateComponent {
readonly el = document.createElement('el');

constructor() {

}

update() {

}
}

function childrenHaveChanged(obj: DisplayObject, objectsDisplayed: Set<DisplayObject>) {
if (!obj.children)
return false;

if (objectsDisplayed.size !== obj.children.length)
return true;

for (let i = 0; i < obj.children.length; i++) {
const child = obj.children[i] as DisplayObject;
if (!objectsDisplayed.has(child))
return true;
}

return false;
}

function getFriendlyConstructorName(obj: DisplayObject) {
return constructorName.get(obj.constructor) ?? obj.constructor.name;
}

const constructorName = new WeakMap<Function, string>();
constructorName.set(Container, 'Container');
constructorName.set(Sprite, 'Sprite');
constructorName.set(Graphics, 'Graphics');
constructorName.set(BitmapText, 'BitmapText');

function getTypeName(obj: DisplayObject) {
return getFriendlyConstructorName(obj) + ' ' + obj["Name"];
}

const getTypeInformationString = (obj: DisplayObject) => {
let string = '';

if (obj.children) {
const length = obj.children!.length;

if (length > 0 || !(obj instanceof Container)) {
if (length === 1)
string += '1 child';
else
string += length + ' children';
}
}

if (obj['texture']) {
if (string)
string += ', ';

string += (obj as Sprite).texture.getId();
}

if (obj['text']) {
if (string)
string += ', ';

string += obj['text'];
}

return string;
}

const getTintCssColor = (obj: DisplayObject) => {
if ('tint' in obj) {
const tint = obj.tint as number;
if (obj instanceof Sprite || obj instanceof Graphics) {
if (tint === 0xffffff)
return;
}
const { r, g, b } = AdjustColor.pixi(tint).toRgb();
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}

return;
}

const getExtendedPropertyKeysString = (() => {
const keys = new Set([
...Object.keys(new Container()),
...Object.keys(new Graphics()),
...Object.keys(new Sprite()),
"Name", "Stack", "containerUpdateTransform", "getChildByName",
"displayObjectUpdateTransform", "_cacheAsBitmap", "_cacheData",
"_cacheAsBitmapResolution", "_cacheAsBitmapMultisample", "_renderCached",
"_initCachedDisplayObject", "_renderCachedCanvas", "_initCachedDisplayObjectCanvas",
"_calculateCachedBounds", "_getCachedLocalBounds", "_destroyCachedDisplayObject",
"_cacheAsBitmapDestroy", "name", "getGlobalPosition", "onclick", "onmousedown",
"onmouseenter", "onmouseleave", "onmousemove", "onglobalmousemove", "onmouseout",
"onmouseover", "onmouseup", "onmouseupoutside", "onpointercancel", "onpointerdown",
"onpointerenter", "onpointerleave", "onpointermove", "onglobalpointermove",
"onpointerout", "onpointerover", "onpointertap", "onpointerup", "onpointerupoutside",
"onrightclick", "onrightdown", "onrightup", "onrightupoutside", "ontap",
"ontouchcancel", "ontouchend", "ontouchendoutside", "ontouchmove",
"onglobaltouchmove", "ontouchstart", "onwheel", "_internalInteractive", "interactive",
"_internalEventMode", "eventMode", "isInteractive", "interactiveChildren", "hitArea",
"addEventListener", "removeEventListener", "dispatchEvent", "accessible",
"accessibleTitle", "accessibleHint", "tabIndex", "_accessibleActive",
"_accessibleDiv", "accessibleType", "accessiblePointerEvents", "accessibleChildren",
"renderId", "eventNames", "listeners", "listenerCount", "emit", "on", "once",
"removeListener", "removeAllListeners", "off", "addListener",
// BitmapText
"_activePagesMeshData", "_textWidth", "_textHeight", "_align", "_font", "_fontName",
"_fontSize", "_text", "dirty", "_maxWidth", "_maxLineHeight", "_letterSpacing",
"_resolution", "_autoResolution", "_textureCache",
// Asshat
"_ticker", "cancellationToken", "_collisionShape", "_collisionShapeDisplayObjects",
]);

return (obj: DisplayObject) => {
let string = '';
for (const key in obj) {
if (keys.has(key))
continue;
if (string)
string += ', ';
// string += '"' + key + '"';
string += key;
}
return string;
};
})();

export const DebugPanel = {

};
18 changes: 12 additions & 6 deletions src/lib/pixi/dev-assign-displayobject-identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,31 @@ import { DisplayObject } from "pixi.js";

export function devAssignDisplayObjectIdentifiers(constructed: DisplayObject) {
const error = new Error();
constructed['Stack'] = getDisplayObjectStack(error);
const [ name, stack ] = getDisplayObjectStack(error);
constructed['Name'] = name;
constructed['Stack'] = stack;
}

const regex = new RegExp(/(?:Error)?\s+at\s(?:Object\.)?((?:new\s)?[a-zA-Z0-9_\.]*)\s\(.*\)/gm);

function getDisplayObjectStack(e: Error) {
let current: RegExpExecArray;
let result = '';
let stack = '';
let name = '';

while ((current = regex.exec(e.stack!)!) !== null) {
const match = current[1];

if (match === 'devAssignDisplayObjectIdentifiers' || match.startsWith('new _') || match === 'container')
continue;

if (result)
result += ' < ';
result += match;
if (!name && !match.startsWith('new '))
name = match;

if (stack)
stack += ' < ';
stack += match;
}

return result;
return [ name, stack ];
}

0 comments on commit 3ca2be3

Please sign in to comment.