""" Pipeline parameters - Runtime configuration layer for animation control. PipelineParams is the target for AnimationController - animation events modify these params, which the pipeline then applies to its stages. """ from dataclasses import dataclass, field from typing import Any try: from engine.display import BorderMode except ImportError: BorderMode = object # Fallback for type checking @dataclass class PipelineParams: """Runtime configuration for the pipeline. This is the canonical config object that AnimationController modifies. Stages read from these params to adjust their behavior. """ # Source config source: str = "headlines" source_refresh_interval: float = 60.0 # Display config display: str = "terminal" border: bool | BorderMode = False positioning: str = "mixed" # Positioning mode: "absolute", "relative", "mixed" # Camera config camera_mode: str = "vertical" camera_speed: float = 1.0 # Default speed camera_x: int = 0 # For horizontal scrolling # Effect config effect_order: list[str] = field( default_factory=lambda: ["noise", "fade", "glitch", "firehose"] ) effect_enabled: dict[str, bool] = field(default_factory=dict) effect_intensity: dict[str, float] = field(default_factory=dict) # Animation-driven state (set by AnimationController) pulse: float = 0.0 current_effect: str | None = None path_progress: float = 0.0 # Viewport viewport_width: int = 80 viewport_height: int = 24 # Firehose firehose_enabled: bool = False # Runtime state frame_number: int = 0 fps: float = 60.0 def get_effect_config(self, name: str) -> tuple[bool, float]: """Get (enabled, intensity) for an effect.""" enabled = self.effect_enabled.get(name, True) intensity = self.effect_intensity.get(name, 1.0) return enabled, intensity def set_effect_config(self, name: str, enabled: bool, intensity: float) -> None: """Set effect configuration.""" self.effect_enabled[name] = enabled self.effect_intensity[name] = intensity def is_effect_enabled(self, name: str) -> bool: """Check if an effect is enabled.""" if name not in self.effect_enabled: return True # Default to enabled return self.effect_enabled.get(name, True) def get_effect_intensity(self, name: str) -> float: """Get effect intensity (0.0 to 1.0).""" return self.effect_intensity.get(name, 1.0) def to_dict(self) -> dict[str, Any]: """Convert to dictionary for serialization.""" return { "source": self.source, "display": self.display, "positioning": self.positioning, "camera_mode": self.camera_mode, "camera_speed": self.camera_speed, "effect_order": self.effect_order, "effect_enabled": self.effect_enabled.copy(), "effect_intensity": self.effect_intensity.copy(), "pulse": self.pulse, "current_effect": self.current_effect, "viewport_width": self.viewport_width, "viewport_height": self.viewport_height, "firehose_enabled": self.firehose_enabled, } @classmethod def from_dict(cls, data: dict[str, Any]) -> "PipelineParams": """Create from dictionary.""" params = cls() for key, value in data.items(): if hasattr(params, key): setattr(params, key, value) return params def copy(self) -> "PipelineParams": """Create a copy of this params object.""" params = PipelineParams() params.source = self.source params.display = self.display params.camera_mode = self.camera_mode params.camera_speed = self.camera_speed params.camera_x = self.camera_x params.effect_order = self.effect_order.copy() params.effect_enabled = self.effect_enabled.copy() params.effect_intensity = self.effect_intensity.copy() params.pulse = self.pulse params.current_effect = self.current_effect params.path_progress = self.path_progress params.viewport_width = self.viewport_width params.viewport_height = self.viewport_height params.firehose_enabled = self.firehose_enabled params.frame_number = self.frame_number params.fps = self.fps return params # Default params for different modes DEFAULT_HEADLINE_PARAMS = PipelineParams( source="headlines", display="terminal", camera_mode="vertical", effect_order=["noise", "fade", "glitch", "firehose"], ) DEFAULT_PYGAME_PARAMS = PipelineParams( source="headlines", display="pygame", camera_mode="vertical", effect_order=["noise", "fade", "glitch", "firehose"], ) DEFAULT_PIPELINE_PARAMS = PipelineParams( source="pipeline", display="pygame", camera_mode="trace", effect_order=[], # No effects for pipeline viz )