diff --git a/steps/index.html b/steps/index.html index 69c7c4b..69449e8 100644 --- a/steps/index.html +++ b/steps/index.html @@ -160,12 +160,12 @@ FULLSCREEN - (F11) + (F11) - Data-Explorer(MATLAB-style) + Data-Explorer(MATLAB) (i) diff --git a/steps/src/dom.js b/steps/src/dom.js index 8901f53..2efba25 100644 --- a/steps/src/dom.js +++ b/steps/src/dom.js @@ -155,14 +155,14 @@ export function updateFrame(frame, forceVideoSeek) { updatePersistentOverlays(timeForUpdates); } // --- End of fix --- - - if (appState.p5_instance) appState.p5_instance.redraw(); // Redraw radar sketch + // --- START: Conditional Redraw Logic --- + // Only force a redraw from here if the animation loop is NOT running. + // When playing, the animationLoop is responsible for redrawing. + if (!appState.isPlaying && appState.p5_instance) appState.p5_instance.redraw(); + if (!appState.isPlaying && appState.speedGraphInstance) appState.speedGraphInstance.redraw(); // --- NEW: Centralized Explorer Update --- throttledUpdateExplorer(); // --- END: Centralized Explorer Update --- - if (appState.speedGraphInstance && !appState.isPlaying) - // Redraw speed graph if not playing. - appState.speedGraphInstance.redraw(); const endTime = performance.now(); appState.lastFrameRenderTime = endTime - startTime; // <-- End timer and update state @@ -358,12 +358,15 @@ export function updatePersistentOverlays(currentMediaTime) { const targetRadarTimeMs = currentRadarFrame.timestampMs; const offsetMs = parseFloat(offsetInput.value) || 0; const driftMs = currentMediaTime * 1000 + offsetMs - targetRadarTimeMs; - const driftColor = Math.abs(driftMs) > 50 ? "#FF6347" : "#98FB98"; // Tomato red or Pale green - const colorMode = getCurrentColorMode(); + const driftColor = Math.abs(driftMs) > 50 ? "#FF6347" : "#98FB98"; // Tomato or Pale Green + const colorMode = getCurrentColorMode(); + const fps = appState.fps; + const fpsColor = fps >= 58 && fps <= 62 ? "#98FB98" : "#FF6347"; // Pale Green or Tomato radarInfoOverlay.innerHTML = ` Frame: ${appState.currentFrame + 1} Motion State: ${motionState} + | FPS: ${fps.toFixed(1)} | Abs Time: ${formatUTCTime(absRadarTime)} | Color Mode: ${colorMode} | Drift: ${driftMs.toFixed( diff --git a/steps/src/drawUtils.js b/steps/src/drawUtils.js index 93741a3..b949572 100644 --- a/steps/src/drawUtils.js +++ b/steps/src/drawUtils.js @@ -414,8 +414,7 @@ export function drawTrajectories(p, plotScales) { // --- END: New Dynamic Coloring Logic --- } - p.drawingContext.setLineDash([]); - p.pop(); + p.pop(); // This was the missing pop call for each trajectory loop } } diff --git a/steps/src/p5/radarSketch.js b/steps/src/p5/radarSketch.js index ad10bf4..8fa85ae 100644 --- a/steps/src/p5/radarSketch.js +++ b/steps/src/p5/radarSketch.js @@ -45,6 +45,10 @@ export const radarSketch = function (p) { let isFirstFrame = true; // Flag to initialize smoothed position // --- END: Mouse Smoothing Variables --- + // --- START: FPS Calculation Variables --- + let lastFrameTime = 0; + // --- END: FPS Calculation Variables --- + // Helper function to allow other sketches to access the static background p.getStaticBackground = function () { return staticBackgroundBuffer; @@ -120,6 +124,21 @@ export const radarSketch = function (p) { }; p.draw = function () { + // --- START: FPS Calculation & Display --- + const currentTime = p.millis(); + if (lastFrameTime > 0) { + const delta = currentTime - lastFrameTime; + if (delta > 0) { + const currentFps = 1000 / delta; + // Use exponential moving average for smoothing + const smoothingFactor = 0.95; + appState.fps = + appState.fps * smoothingFactor + currentFps * (1 - smoothingFactor); + } + } + lastFrameTime = currentTime; + // --- END: FPS Calculation & Display --- + // Set background color based on current theme (dark/light) p.background( document.documentElement.classList.contains("dark") diff --git a/steps/src/state.js b/steps/src/state.js index 18f9e96..b232891 100644 --- a/steps/src/state.js +++ b/steps/src/state.js @@ -2,6 +2,7 @@ export const appState = { zoomHideDelayTimeout: null, // Timeout before the hide countdown begins zoomCountdown: null, // Holds the number of seconds left before zoom hides zoomCountdownInterval: null, // The interval timer for the countdown + fps: 0, // To store the calculated FPS for performance monitoring isRawOnlyMode: false, // <-- ADD THIS LINE // Stores the parsed visualization data (radar frames, tracks, etc.) diff --git a/steps/src/sync.js b/steps/src/sync.js index 40ce955..1e707b0 100644 --- a/steps/src/sync.js +++ b/steps/src/sync.js @@ -71,8 +71,11 @@ export function animationLoop() { updatePersistentOverlays(currentMediaTime); updateDebugOverlay(currentMediaTime); - // Redraw the speed graph if an instance exists + // --- START: Centralized Redraw Logic --- + // Explicitly redraw all active sketches in sync with the animation frame. + if (appState.p5_instance) appState.p5_instance.redraw(); if (appState.speedGraphInstance) appState.speedGraphInstance.redraw(); + // --- END: Centralized Redraw Logic --- // Request the next frame requestAnimationFrame(animationLoop);