From d750aa693dd97fdbe4d48dcf1a267cc83435f880 Mon Sep 17 00:00:00 2001 From: Jonah <47046556+jwbonner@users.noreply.github.com> Date: Sat, 5 Oct 2024 17:24:00 -0400 Subject: [PATCH] Add on-demand rendering for more tabs (#204) --- src/shared/renderers/JoysticksRenderer.ts | 14 +++++++++++++- src/shared/renderers/LineGraphRenderer.ts | 11 +++++++++++ src/shared/renderers/OdometryRenderer.ts | 16 ++++++++++++++-- src/shared/renderers/SwerveRenderer.ts | 16 ++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/shared/renderers/JoysticksRenderer.ts b/src/shared/renderers/JoysticksRenderer.ts index 36090717..8fe70832 100644 --- a/src/shared/renderers/JoysticksRenderer.ts +++ b/src/shared/renderers/JoysticksRenderer.ts @@ -10,6 +10,8 @@ export default class JoysticksRenderer implements TabRenderer { private BLACK_COLOR = "#222222"; private WHITE_COLOR = "#eeeeee"; + private lastRenderState = ""; + constructor(root: HTMLElement) { this.CANVAS = root.getElementsByTagName("canvas")[0] as HTMLCanvasElement; for (let i = 0; i < 6; i++) { @@ -33,11 +35,21 @@ export default class JoysticksRenderer implements TabRenderer { let context = this.CANVAS.getContext("2d") as CanvasRenderingContext2D; let canvasWidth = this.CANVAS.clientWidth; let canvasHeight = this.CANVAS.clientHeight; + let isLight = !window.matchMedia("(prefers-color-scheme: dark)").matches; + + // Exit if render state unchanged + let renderState: any[] = [canvasWidth, canvasHeight, isLight, window.devicePixelRatio, command]; + let renderStateString = JSON.stringify(renderState); + if (renderStateString === this.lastRenderState) { + return; + } + this.lastRenderState = renderStateString; + + // Apply setup and scaling this.CANVAS.width = canvasWidth * window.devicePixelRatio; this.CANVAS.height = canvasHeight * window.devicePixelRatio; context.scale(window.devicePixelRatio, window.devicePixelRatio); context.clearRect(0, 0, canvasWidth, canvasHeight); - let isLight = !window.matchMedia("(prefers-color-scheme: dark)").matches; // Iterate over joysticks command.forEach((joystick, index) => { diff --git a/src/shared/renderers/LineGraphRenderer.ts b/src/shared/renderers/LineGraphRenderer.ts index 8621cc1a..e46cdd8b 100644 --- a/src/shared/renderers/LineGraphRenderer.ts +++ b/src/shared/renderers/LineGraphRenderer.ts @@ -14,6 +14,7 @@ export default class LineGraphRenderer implements TabRenderer { private hasController: boolean; private scrollSensor: ScrollSensor; + private lastRenderState = ""; private mouseDownX = 0; private grabZoomActive = false; private grabZoomStartTime = 0; @@ -94,6 +95,16 @@ export default class LineGraphRenderer implements TabRenderer { let width = this.CANVAS.clientWidth; let height = this.CANVAS.clientHeight; let light = !window.matchMedia("(prefers-color-scheme: dark)").matches; + + // Exit if render state unchanged + let renderState: any[] = [width, height, light, devicePixelRatio, command, this.lastCursorX]; + let renderStateString = JSON.stringify(renderState); + if (renderStateString === this.lastRenderState) { + return; + } + this.lastRenderState = renderStateString; + + // Apply setup and scaling this.CANVAS.width = width * devicePixelRatio; this.CANVAS.height = height * devicePixelRatio; context.scale(devicePixelRatio, devicePixelRatio); diff --git a/src/shared/renderers/OdometryRenderer.ts b/src/shared/renderers/OdometryRenderer.ts index e5022faa..ad90191a 100644 --- a/src/shared/renderers/OdometryRenderer.ts +++ b/src/shared/renderers/OdometryRenderer.ts @@ -13,6 +13,8 @@ export default class OdometryRenderer implements TabRenderer { private heatmap: Heatmap; private lastImageSource = ""; private aspectRatio = 1; + private lastRenderState = ""; + private imageLoadCount = 0; constructor(root: HTMLElement) { this.CONTAINER = root.getElementsByClassName("odometry-canvas-container")[0] as HTMLElement; @@ -20,6 +22,7 @@ export default class OdometryRenderer implements TabRenderer { this.IMAGE = document.createElement("img"); this.HEATMAP_CONTAINER = root.getElementsByClassName("odometry-heatmap-container")[0] as HTMLElement; this.heatmap = new Heatmap(this.HEATMAP_CONTAINER); + this.IMAGE.addEventListener("load", () => this.imageLoadCount++); } saveState(): unknown { @@ -33,11 +36,21 @@ export default class OdometryRenderer implements TabRenderer { } render(command: OdometryRendererCommand): void { - // Set up canvas + // Get setup let context = this.CANVAS.getContext("2d") as CanvasRenderingContext2D; let isVertical = command.orientation === Orientation.DEG_90 || command.orientation === Orientation.DEG_270; let width = isVertical ? this.CONTAINER.clientHeight : this.CONTAINER.clientWidth; let height = isVertical ? this.CONTAINER.clientWidth : this.CONTAINER.clientHeight; + + // Exit if render state unchanged + let renderState: any[] = [width, height, window.devicePixelRatio, command, this.imageLoadCount]; + let renderStateString = JSON.stringify(renderState); + if (renderStateString === this.lastRenderState) { + return; + } + this.lastRenderState = renderStateString; + + // Set up canvas this.CANVAS.style.width = width.toString() + "px"; this.CANVAS.style.height = height.toString() + "px"; this.CANVAS.width = width * window.devicePixelRatio; @@ -70,7 +83,6 @@ export default class OdometryRenderer implements TabRenderer { this.lastImageSource = gameData.path; this.IMAGE.src = gameData.path; } - if (!(this.IMAGE.width > 0 && this.IMAGE.height > 0)) return; // Determine if objects are flipped let objectsFlipped = command.origin === "red"; diff --git a/src/shared/renderers/SwerveRenderer.ts b/src/shared/renderers/SwerveRenderer.ts index 2733432c..5888c871 100644 --- a/src/shared/renderers/SwerveRenderer.ts +++ b/src/shared/renderers/SwerveRenderer.ts @@ -9,6 +9,8 @@ export default class SwerveRenderer implements TabRenderer { private BLACK_COLOR = "#222222"; private WHITE_COLOR = "#eeeeee"; + private lastRenderState = ""; + constructor(root: HTMLElement) { this.CONTAINER = root.firstElementChild as HTMLElement; this.CANVAS = this.CONTAINER.firstElementChild as HTMLCanvasElement; @@ -25,6 +27,20 @@ export default class SwerveRenderer implements TabRenderer { } render(command: SwerveRendererCommand): void { + // Exit if render state unchanged + let renderState: any[] = [ + this.CONTAINER.clientWidth, + this.CONTAINER.clientHeight, + window.matchMedia("(prefers-color-scheme: dark)").matches, + window.devicePixelRatio, + command + ]; + let renderStateString = JSON.stringify(renderState); + if (renderStateString === this.lastRenderState) { + return; + } + this.lastRenderState = renderStateString; + // Update canvas size let context = this.CANVAS.getContext("2d") as CanvasRenderingContext2D; let size = Math.min(this.CONTAINER.clientWidth, this.CONTAINER.clientHeight);