Skip to content

Commit

Permalink
Move the spector stuff from GraphicsSystem to UiSpector
Browse files Browse the repository at this point in the history
This also avoids initializing Spector until we actually toggle on the UI.
Before, it was adding some instrumentation to requestAnimationFrame and spying
the canvas even when we weren't using Spector.
  • Loading branch information
bhousel committed Oct 24, 2024
1 parent b0114fb commit 1e3ec1e
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 62 deletions.
9 changes: 0 additions & 9 deletions modules/core/GraphicsSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ export class GraphicsSystem extends AbstractSystem {
this.events = null;
this.textures = null;

// Spector.js is a WebGL debugging tool, only available in the dev build.
this.spector = null;

// Properties used to manage the scene transform
this.pixiViewport = new Viewport();
this._prevTransform = { x: 0, y: 0, k: 256 / Math.PI, r: 0 }; // transform at time of last draw
Expand Down Expand Up @@ -184,12 +181,6 @@ export class GraphicsSystem extends AbstractSystem {
pixi: PIXI,
app: this.pixi
};

const renderer = this.pixi.renderer;
if (window.SPECTOR && renderer.type === PIXI.RendererType.WEBGL) {
this.spector = new window.SPECTOR.Spector();
this.spector.spyCanvas(renderer.context.canvas);
}
}

// Setup the stage
Expand Down
108 changes: 55 additions & 53 deletions modules/ui/UiSpector.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as PIXI from 'pixi.js';
import { selection } from 'd3-selection';


Expand All @@ -16,8 +17,12 @@ export class UiSpector {
constructor(context) {
this.context = context;

this._isHidden = true; // start out hidden
this._didInit = false;
this._isHidden = true; // start out hidden

// Child components, we will defer creating these until `_initSpectorUI()`
this.Spector = null;
this.CaptureMenu = null;
this.ResultView = null;

// D3 selections
this.$parent = null;
Expand All @@ -43,11 +48,7 @@ export class UiSpector {
return; // no parent - called too early?
}

const context = this.context;
const gfx = context.systems.gfx;
if (!gfx.spector) return;

// add .spector
// add .spector wrapper
let $wrap = $parent.selectAll('.spector')
.data([0]);

Expand All @@ -70,16 +71,16 @@ export class UiSpector {
this._initSpectorUI();

const $wrap = this.$wrap;
const captureMenu = this.captureMenu;
if (!$wrap || !captureMenu) return; // called too early?
const CaptureMenu = this.CaptureMenu;
if (!$wrap || !CaptureMenu) return; // called too early / couldn't init spector?

if (this._isHidden) {
this._isHidden = false;
captureMenu.display();
CaptureMenu.display();

// Hide fps meter (it is inaccurate?)
$wrap.selectAll('.fpsCounterComponent')
.style('display', 'none');
// Hide fps meter (it is inaccurate?)
$wrap.selectAll('.fpsCounterComponent')
.style('display', 'none');

$wrap
.style('display', 'block')
Expand All @@ -96,73 +97,74 @@ $wrap.selectAll('.fpsCounterComponent')
.style('opacity', '0')
.on('end', () => {
$wrap.style('display', 'none');
captureMenu.hide();
CaptureMenu.hide();
});
}
}


/**
*
* _initSpectorUI
* This creates the Spector components and starts spying on the rendering canvas.
* (We avoid doing this until something calls `toggle()` to try to show the UI)
*/
_initSpectorUI() {
if (this._didInit) return; // do once
if (!this.$wrap) return; // called too early?
if (this.Spector) return; // already done
if (!window.SPECTOR) return; // no spector - production build?

const context = this.context;
const gfx = context.systems.gfx;
const spector = gfx.spector;
if (!spector) return;
const renderer = gfx.pixi.renderer;

// Spector will only work with the WebGL renderer
if (renderer.type !== PIXI.RendererType.WEBGL) return; // webgpu?
const spector = new window.SPECTOR.Spector();
this.Spector = spector;

// The default behavior of the CaptureMenu is to search the document for canvases to spy.
// This doesn't work in our situation because Pixi is setup with `multiView: true`
// and will render to an offscreen canvas.
// The GraphicsSystem should be already spying the canvas we are interested in.
const canvas = spector.canvasSpy?.canvas;
if (!canvas) return;
// and will render to an offscreen canvas - instead we will tell it what canvas to spy on.
const canvas = renderer.context.canvas;
spector.spyCanvas(canvas);

// override of spector.getCaptureUI()
if (!this.captureMenu) {
const options = {
rootPlaceHolder: this.$wrap.node(),
canvas: canvas,
hideLog: true
};

const cm = new window.SPECTOR.EmbeddedFrontend.CaptureMenu(options);
cm.trackPageCanvases = () => {}; // replace with no-op to avoid doing this
cm.updateCanvasesList([canvas]); // only the one we are spying

cm.onPauseRequested.add(spector.pause, spector);
cm.onPlayRequested.add(spector.play, spector);
cm.onPlayNextFrameRequested.add(spector.playNextFrame, spector);
cm.onCaptureRequested.add(info => {
if (info) {
spector.captureCanvas(info.ref);
}
}, spector);
const options = {
rootPlaceHolder: this.$wrap.node(),
canvas: canvas,
hideLog: true
};

const cm = new window.SPECTOR.EmbeddedFrontend.CaptureMenu(options);
cm.trackPageCanvases = () => {}; // replace with no-op to avoid doing this
cm.updateCanvasesList([canvas]); // only the one we are spying

cm.onPauseRequested.add(spector.pause, spector);
cm.onPlayRequested.add(spector.play, spector);
cm.onPlayNextFrameRequested.add(spector.playNextFrame, spector);
cm.onCaptureRequested.add(info => {
if (info) {
spector.captureCanvas(info.ref);
}
}, spector);

// hide fps meter (it is inaccurate?)
// window.setInterval(() => {
// if (this._isHidden) return;
// cm.setFPS(spector.getFps());
// }, 1000);

this.captureMenu = spector.captureMenu = cm;
}
this.CaptureMenu = spector.captureMenu = cm;

// override of spector.getResultUI()
if (!this.resultView) {
const rv = new window.SPECTOR.EmbeddedFrontend.ResultView();
const rv = new window.SPECTOR.EmbeddedFrontend.ResultView();

spector.onCapture.add(capture => {
rv.display();
rv.addCapture(capture);
});

this.resultView = spector.resultView = rv;
}
spector.onCapture.add(capture => {
rv.display();
rv.addCapture(capture);
});

this._didInit = true;
this.ResultView = spector.resultView = rv;
}

}

0 comments on commit 1e3ec1e

Please sign in to comment.