Bug: Camera update() method never called, scroll position never advances #39

Closed
opened 2026-03-19 05:42:16 +00:00 by david · 1 comment
Owner

Problem

The camera's update(dt) method is never called in the pipeline execution loop, causing the scroll camera position to remain static at 0.

Root Cause

  1. No dt calculation in main loop: The frame loop in engine/app/pipeline_runner.py sleeps for 1/60 second but never calculates delta time
  2. No camera.update() call: The Camera class has update() method for advancing position, but it's never invoked
  3. CameraStage isolation: CameraStage only calls camera.apply() to slice the buffer, never advances camera position

Expected Behavior

With --pipeline-camera scroll, the viewport should smoothly scroll upward at a configured speed, showing different parts of the content over time.

Current Behavior

Viewport remains static at position 0, no scrolling motion occurs.

Code Locations

  • engine/camera.py: Camera class has update(dt) method (line 122) and _update_scroll() (line 171)
  • engine/app/pipeline_runner.py: Main loop (line 643-691) lacks dt tracking and camera.update() call
  • engine/pipeline/adapters/camera.py: CameraStage.process() calls camera.apply() but never camera.update()

Proposed Fix

Following Option 1 (CameraStage self-contained):

  • Calculate dt in CameraStage using frame timing
  • Call camera.update(dt) in CameraStage.process()
  • This keeps camera logic self-contained
  • Issue #38: Already fixed - PIL height estimation performance fix
  • Issue #35: Pipeline Mutation API - camera hot-swap capability

Acceptance Criteria

  • Scroll camera position advances each frame
  • ViewportFilterStage reads correct camera_y from context
  • Smooth vertical scrolling visible in terminal output
## Problem The camera's `update(dt)` method is never called in the pipeline execution loop, causing the scroll camera position to remain static at 0. ## Root Cause 1. **No dt calculation in main loop**: The frame loop in `engine/app/pipeline_runner.py` sleeps for 1/60 second but never calculates delta time 2. **No camera.update() call**: The Camera class has `update()` method for advancing position, but it's never invoked 3. **CameraStage isolation**: CameraStage only calls `camera.apply()` to slice the buffer, never advances camera position ## Expected Behavior With `--pipeline-camera scroll`, the viewport should smoothly scroll upward at a configured speed, showing different parts of the content over time. ## Current Behavior Viewport remains static at position 0, no scrolling motion occurs. ## Code Locations - `engine/camera.py`: Camera class has `update(dt)` method (line 122) and `_update_scroll()` (line 171) - `engine/app/pipeline_runner.py`: Main loop (line 643-691) lacks dt tracking and camera.update() call - `engine/pipeline/adapters/camera.py`: CameraStage.process() calls `camera.apply()` but never `camera.update()` ## Proposed Fix Following Option 1 (CameraStage self-contained): - Calculate dt in CameraStage using frame timing - Call `camera.update(dt)` in CameraStage.process() - This keeps camera logic self-contained ## Related Issues - Issue #38: Already fixed - PIL height estimation performance fix - Issue #35: Pipeline Mutation API - camera hot-swap capability ## Acceptance Criteria - [ ] Scroll camera position advances each frame - [ ] ViewportFilterStage reads correct camera_y from context - [ ] Smooth vertical scrolling visible in terminal output
Author
Owner

Summary

Created two linked bug tickets that together cause scroll camera motion to fail:

#39 - Camera update never called:

  • camera.update(dt) never called in main loop
  • Camera position never advances

#40 - Camera state not propagated:

  • CameraStage doesn't set camera_y in context
  • ViewportFilterStage can't filter based on camera position

Root Cause Analysis

The CameraStage adapter only applies camera slicing to the buffer:

return self._camera.apply(data, viewport_width, viewport_height)

But the Camera class also needs:

  1. update(dt) called each frame to advance position
  2. camera.y propagated to context for dependent stages

Fix Strategy

Following your choice of Option 1 (CameraStage self-contained):

  • Calculate dt in CameraStage.process()
  • Call camera.update(dt)
  • Set ctx.set_state("camera_y", camera.y)

This keeps camera logic self-contained and requires minimal changes to main loop.

## Summary Created two linked bug tickets that together cause scroll camera motion to fail: **#39** - Camera update never called: - `camera.update(dt)` never called in main loop - Camera position never advances **#40** - Camera state not propagated: - `CameraStage` doesn't set `camera_y` in context - `ViewportFilterStage` can't filter based on camera position ## Root Cause Analysis The `CameraStage` adapter only applies camera slicing to the buffer: ```python return self._camera.apply(data, viewport_width, viewport_height) ``` But the Camera class also needs: 1. `update(dt)` called each frame to advance position 2. `camera.y` propagated to context for dependent stages ## Fix Strategy Following your choice of **Option 1 (CameraStage self-contained)**: - Calculate dt in CameraStage.process() - Call camera.update(dt) - Set ctx.set_state("camera_y", camera.y) This keeps camera logic self-contained and requires minimal changes to main loop.
david closed this issue 2026-03-19 05:46:58 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: klubhaus/sideline#39