Add debug overlay

This commit is contained in:
Sean Boult 2021-09-27 12:25:20 +00:00 committed by GitHub
parent 4355d13c0b
commit 08b79ae312
5 changed files with 173 additions and 4382 deletions

9
.prettierrc Normal file
View File

@ -0,0 +1,9 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": true,
"printWidth": 100,
"singleQuote": false,
"quoteProps": "preserve",
"arrowParens": "avoid"
}

View File

@ -99,17 +99,40 @@
.hidden {
display: none;
}
.skin_wrap {
position: relative;
}
#debug_canvas {
position: absolute;
background: rgba(0, 0, 0, 0.5);
padding: 6px;
color: #fff;
top: 0px;
left: 0px;
width: 100px;
height: 150px;
}
</style>
</head>
<body>
<canvas id="skin_container"></canvas>
<div class="skin_wrap">
<canvas id="skin_container"></canvas>
</div>
<div class="controls">
<button id="reset_all" type="button" class="control">Reset All</button>
<div class="control-section">
<h1>Debug Mode</h1>
<label class="control"><input id="debug_mode_checkbox" type="checkbox"> Enable</label>
</div>
<div class="control-section">
<h1>Viewport</h1>
<div>
@ -381,6 +404,14 @@
rotateAnimation.speed = e.target.value;
}
});
document.getElementById("debug_mode_checkbox").addEventListener("change", e => {
const value = e.target.checked;
skinViewer.debugInfo = value
// toggle it
skinViewer.debugCanvas.setState(value);
});
for (const el of document.querySelectorAll('input[type="radio"][name="primary_animation"]')) {
el.addEventListener("change", e => {
if (primaryAnimation !== null) {

4403
package-lock.json generated

File diff suppressed because it is too large Load Diff

100
src/debug.ts Normal file
View File

@ -0,0 +1,100 @@
import { SkinViewer } from "./viewer";
export class DebugCanvas {
private wrapperElement: HTMLElement | null;
private canvas: HTMLCanvasElement | null;
private ctx: CanvasRenderingContext2D | null;
private _skinViewer: SkinViewer;
public enabled: boolean = false;
constructor(skinViewer: SkinViewer) {
this.canvas = null;
this.ctx = null;
this.wrapperElement = null;
this._skinViewer = skinViewer;
}
createCanvas(): void {
// create the canvas
this.canvas = document.createElement("canvas");
const width = 100;
const height = 92;
this.ctx = this.canvas.getContext("2d");
// attempt dpi correction
const ratio = Math.ceil(window.devicePixelRatio);
this.canvas.width = width * ratio;
this.canvas.height = height * ratio;
this.canvas.style.width = `${width}px`;
this.canvas.style.height = `${height}px`;
// create a wrapper node
const wrapper = document.createElement("div");
wrapper.style.position = "absolute";
wrapper.style.top = "0";
wrapper.style.left = "0";
wrapper.style.background = "rgba(0,0,0,0.5)";
wrapper.appendChild(this.canvas);
this.wrapperElement = wrapper;
// add it to the dom and overlay it aboslute
const parent = this._skinViewer.canvas.parentNode;
if (parent) {
parent.appendChild(wrapper);
}
}
destroyCanvas(): void {
// attempt to remove canvas
this.wrapperElement?.remove();
this.canvas = null;
this.wrapperElement = null;
}
setState(state: boolean): void {
// set the new state
this.enabled = state;
// call the create/destroy method based on prior
this.enabled ? this.createCanvas() : this.destroyCanvas();
// debug log
console.info("[Debug canvas]", this.enabled ? "enabled": "disabled");
}
render(): void {
const { ctx, canvas, _skinViewer } = this;
if (!ctx || !canvas) {
return;
}
const { x, y, z } = _skinViewer.camera.position;
const { x: rotX, y: rotY, z: rotZ } = _skinViewer.camera.rotation;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.font = '14px serif';
ctx.fillStyle = 'white';
const items = [
`x: ${x.toFixed(2)}`,
`y: ${y.toFixed(2)}`,
`z: ${z.toFixed(2)}`,
`rotX: ${rotX.toFixed(2)}`,
`rotY: ${rotY.toFixed(2)}`,
`rotZ: ${rotZ.toFixed(2)}`,
]
const spacing = 15;
const offsetX = 15;
const offsetY = 6;
items.forEach((s, index) => ctx.fillText(s, offsetY, offsetX + spacing * index));
}
}

View File

@ -2,6 +2,7 @@ import { inferModelType, isTextureSource, loadCapeToCanvas, loadImage, loadSkinT
import { Color, ColorRepresentation, EquirectangularReflectionMapping, Group, NearestFilter, PerspectiveCamera, Scene, Texture, Vector2, WebGLRenderer } from "three";
import { RootAnimation } from "./animation.js";
import { BackEquipment, PlayerObject } from "./model.js";
import { DebugCanvas } from "./debug.js";
export interface LoadOptions {
/**
@ -87,6 +88,8 @@ export class SkinViewer {
private onContextLost: (event: Event) => void;
private onContextRestored: () => void;
public debugCanvas: DebugCanvas;
constructor(options: SkinViewerOptions = {}) {
this.canvas = options.canvas === undefined ? document.createElement("canvas") : options.canvas;
@ -101,6 +104,9 @@ export class SkinViewer {
this.capeTexture.magFilter = NearestFilter;
this.capeTexture.minFilter = NearestFilter;
// setup debug canvas class
this.debugCanvas = new DebugCanvas(this);
this.scene = new Scene();
this.camera = new PerspectiveCamera();
@ -251,6 +257,10 @@ export class SkinViewer {
this.animations.runAnimationLoop(this.playerObject);
this.render();
this.animationID = window.requestAnimationFrame(() => this.draw());
// render the debug canvas
this.debugCanvas.render();
}
/**