forked from genewildish/Mainline
feat(core): add Camera abstraction for viewport scrolling
- Add Camera class with modes: vertical, horizontal, omni, floating - Refactor scroll.py and demo to use Camera abstraction - Add vis_offset for horizontal scrolling support - Add camera_x to EffectContext for effects - Add pygame window resize handling - Add HUD effect plugin for demo mode - Add --demo flag to run demo mode - Add tests for Camera and vis_offset
This commit is contained in:
@@ -7,6 +7,7 @@ import random
|
||||
import time
|
||||
|
||||
from engine import config
|
||||
from engine.camera import Camera
|
||||
from engine.display import (
|
||||
Display,
|
||||
TerminalDisplay,
|
||||
@@ -27,10 +28,19 @@ from engine.viewport import th, tw
|
||||
USE_EFFECT_CHAIN = True
|
||||
|
||||
|
||||
def stream(items, ntfy_poller, mic_monitor, display: Display | None = None):
|
||||
def stream(
|
||||
items,
|
||||
ntfy_poller,
|
||||
mic_monitor,
|
||||
display: Display | None = None,
|
||||
camera: Camera | None = None,
|
||||
):
|
||||
"""Main render loop with four layers: message, ticker, scroll motion, firehose."""
|
||||
if display is None:
|
||||
display = TerminalDisplay()
|
||||
if camera is None:
|
||||
camera = Camera.vertical()
|
||||
|
||||
random.shuffle(items)
|
||||
pool = list(items)
|
||||
seen = set()
|
||||
@@ -46,7 +56,6 @@ def stream(items, ntfy_poller, mic_monitor, display: Display | None = None):
|
||||
scroll_step_interval = calculate_scroll_step(config.SCROLL_DUR, ticker_view_h)
|
||||
|
||||
active = []
|
||||
scroll_cam = 0
|
||||
ticker_next_y = ticker_view_h
|
||||
noise_cache = {}
|
||||
scroll_motion_accum = 0.0
|
||||
@@ -72,10 +81,10 @@ def stream(items, ntfy_poller, mic_monitor, display: Display | None = None):
|
||||
scroll_motion_accum += config.FRAME_DT
|
||||
while scroll_motion_accum >= scroll_step_interval:
|
||||
scroll_motion_accum -= scroll_step_interval
|
||||
scroll_cam += 1
|
||||
camera.update(config.FRAME_DT)
|
||||
|
||||
while (
|
||||
ticker_next_y < scroll_cam + ticker_view_h + 10
|
||||
ticker_next_y < camera.y + ticker_view_h + 10
|
||||
and queued < config.HEADLINE_LIMIT
|
||||
):
|
||||
from engine.effects import next_headline
|
||||
@@ -88,17 +97,17 @@ def stream(items, ntfy_poller, mic_monitor, display: Display | None = None):
|
||||
queued += 1
|
||||
|
||||
active = [
|
||||
(c, hc, by, mi) for c, hc, by, mi in active if by + len(c) > scroll_cam
|
||||
(c, hc, by, mi) for c, hc, by, mi in active if by + len(c) > camera.y
|
||||
]
|
||||
for k in list(noise_cache):
|
||||
if k < scroll_cam:
|
||||
if k < camera.y:
|
||||
del noise_cache[k]
|
||||
|
||||
grad_offset = (time.monotonic() * config.GRAD_SPEED) % 1.0
|
||||
ticker_buf_start = len(buf)
|
||||
|
||||
ticker_buf, noise_cache = render_ticker_zone(
|
||||
active, scroll_cam, ticker_h, w, noise_cache, grad_offset
|
||||
active, camera.y, camera.x, ticker_h, w, noise_cache, grad_offset
|
||||
)
|
||||
buf.extend(ticker_buf)
|
||||
|
||||
@@ -110,8 +119,9 @@ def stream(items, ntfy_poller, mic_monitor, display: Display | None = None):
|
||||
buf,
|
||||
w,
|
||||
h,
|
||||
scroll_cam,
|
||||
camera.y,
|
||||
ticker_h,
|
||||
camera.x,
|
||||
mic_excess,
|
||||
grad_offset,
|
||||
frame_number,
|
||||
|
||||
Reference in New Issue
Block a user