From 8b283a40b43fbbcec4308057767dfb0ed554b942 Mon Sep 17 00:00:00 2001 From: scamiv <6170744+scamiv@users.noreply.github.com> Date: Sun, 22 Feb 2026 18:26:10 +0100 Subject: [PATCH] feat: implement resize --- .../graphics/layers/PerformanceOverlay.ts | 121 +++++++++++++++++- 1 file changed, 116 insertions(+), 5 deletions(-) diff --git a/src/client/graphics/layers/PerformanceOverlay.ts b/src/client/graphics/layers/PerformanceOverlay.ts index 7dfdf575e..bf6f64272 100644 --- a/src/client/graphics/layers/PerformanceOverlay.ts +++ b/src/client/graphics/layers/PerformanceOverlay.ts @@ -63,6 +63,9 @@ export class PerformanceOverlay extends LitElement implements Layer { @state() private tickLayersExpanded: boolean = false; + @state() + private overlayWidthPx: number | null = null; + private frameCount: number = 0; private lastTime: number = 0; private frameTimes: number[] = []; @@ -78,6 +81,13 @@ export class PerformanceOverlay extends LitElement implements Layer { private copyStatusTimeoutId: ReturnType | null = null; + private resizeState: { + pointerId: number; + startClientX: number; + startWidthPx: number; + pendingWidthPx: number; + } | null = null; + // Smoothed per-layer render timings (EMA over recent frames) private layerStats: Map< string, @@ -147,7 +157,7 @@ export class PerformanceOverlay extends LitElement implements Layer { cursor: move; transition: none; box-sizing: border-box; - width: min(460px, calc(100vw - 16px)); + width: var(--overlay-width, min(460px, calc(100vw - 16px))); max-width: calc(100vw - 16px); max-height: calc(100vh - 16px); overflow: auto; @@ -186,6 +196,28 @@ export class PerformanceOverlay extends LitElement implements Layer { pointer-events: auto; } + .resize-handle { + position: absolute; + top: 0; + right: 0; + height: 100%; + width: 12px; + cursor: ew-resize; + touch-action: none; + pointer-events: auto; + } + + .resize-handle::after { + content: ""; + position: absolute; + top: 6px; + bottom: 6px; + right: 4px; + width: 2px; + border-radius: 2px; + background: rgba(255, 255, 255, 0.25); + } + .performance-good { color: #4ade80; /* green-400 */ } @@ -337,6 +369,14 @@ export class PerformanceOverlay extends LitElement implements Layer { setVisible(visible: boolean) { this.isVisible = visible; FrameProfiler.setEnabled(visible); + + if (!visible && this.resizeState) { + globalThis.removeEventListener("pointermove", this.onResizePointerMove); + globalThis.removeEventListener("pointerup", this.onResizePointerUp); + globalThis.removeEventListener("pointercancel", this.onResizePointerUp); + this.resizeState = null; + } + this.requestUpdate(); } @@ -353,7 +393,8 @@ export class PerformanceOverlay extends LitElement implements Layer { target.classList.contains("close-button") || target.classList.contains("reset-button") || target.classList.contains("copy-json-button") || - target.classList.contains("collapse-button") + target.classList.contains("collapse-button") || + target.classList.contains("resize-handle") ) { return; } @@ -378,7 +419,11 @@ export class PerformanceOverlay extends LitElement implements Layer { const margin = 8; const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; - const overlayWidth = Math.min(420, Math.max(0, viewportWidth - margin * 2)); + const defaultWidth = Math.min(460, Math.max(0, viewportWidth - margin * 2)); + const overlayWidth = Math.min( + this.overlayWidthPx ?? defaultWidth, + viewportWidth - margin * 2, + ); this.position = { x: Math.max( @@ -397,6 +442,59 @@ export class PerformanceOverlay extends LitElement implements Layer { document.removeEventListener("mouseup", this.handleMouseUp); }; + private onResizePointerMove = (e: PointerEvent) => { + if (!this.resizeState || e.pointerId !== this.resizeState.pointerId) return; + + const margin = 8; + const minWidthPx = 260; + const viewportWidth = window.innerWidth; + const left = Math.max(margin, Math.min(this.position.x, viewportWidth)); + const maxWidthPx = Math.max(minWidthPx, viewportWidth - left - margin); + + const delta = e.clientX - this.resizeState.startClientX; + const nextWidth = this.resizeState.startWidthPx + delta; + const clamped = Math.max(minWidthPx, Math.min(maxWidthPx, nextWidth)); + this.resizeState.pendingWidthPx = clamped; + + const overlay = this.renderRoot.querySelector( + ".performance-overlay", + ); + overlay?.style.setProperty("--overlay-width", `${clamped}px`); + }; + + private onResizePointerUp = (e: PointerEvent) => { + if (!this.resizeState || e.pointerId !== this.resizeState.pointerId) return; + + globalThis.removeEventListener("pointermove", this.onResizePointerMove); + globalThis.removeEventListener("pointerup", this.onResizePointerUp); + globalThis.removeEventListener("pointercancel", this.onResizePointerUp); + + this.overlayWidthPx = this.resizeState.pendingWidthPx; + this.resizeState = null; + this.requestUpdate(); + }; + + private handleResizePointerDown = (e: PointerEvent) => { + e.preventDefault(); + e.stopPropagation(); + + const overlay = this.renderRoot.querySelector( + ".performance-overlay", + ); + const startWidth = overlay?.getBoundingClientRect().width ?? 460; + + this.resizeState = { + pointerId: e.pointerId, + startClientX: e.clientX, + startWidthPx: startWidth, + pendingWidthPx: startWidth, + }; + + globalThis.addEventListener("pointermove", this.onResizePointerMove); + globalThis.addEventListener("pointerup", this.onResizePointerUp); + globalThis.addEventListener("pointercancel", this.onResizePointerUp); + }; + private handleReset = () => { // reset FPS / frame stats this.frameCount = 0; @@ -798,7 +896,11 @@ export class PerformanceOverlay extends LitElement implements Layer { const margin = 8; const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; - const overlayWidth = Math.min(420, Math.max(0, viewportWidth - margin * 2)); + const defaultWidth = Math.min(460, Math.max(0, viewportWidth - margin * 2)); + const overlayWidth = Math.min( + this.overlayWidthPx ?? defaultWidth, + viewportWidth - margin * 2, + ); const maxLeft = Math.max(margin, viewportWidth - overlayWidth - margin); const clampedX = Math.max(margin, Math.min(this.position.x, maxLeft)); const clampedY = Math.max( @@ -826,10 +928,15 @@ export class PerformanceOverlay extends LitElement implements Layer { ? Math.max(...tickLayersToShow.map((l) => l.avg)) : 1; + const overlayWidthStyle = + this.overlayWidthPx === null + ? "" + : `--overlay-width: ${this.overlayWidthPx}px;`; + return html`
+
${translateText("performance_overlay.fps")}