Files
led2/lightsync/animations/__init__.py
Claude f4da9564d4 feat(03-02): implement animation library — 7 types with registry and factory
- AnimationBase ABC with render(t, led_count) and from_params() contract
- SolidColorAnimation: time-independent uniform fill
- ChaseAnimation: moving lit segment with forward/reverse support
- PulseAnimation: sine-wave breathing effect (speed maps to period)
- RainbowAnimation: HSV hue cycle across strip via colorsys.hsv_to_rgb
- StrobeAnimation: on/off flashing at 1-20 Hz with configurable duty cycle
- ColorWipeAnimation: progressive fill from start or end
- FireAnimation: Fire2012 algorithm with cooling/sparking/heat-to-color mapping
- ANIMATION_REGISTRY + create_animation() factory function
- All 24 tests passing
2026-04-06 21:47:39 +00:00

49 lines
1.5 KiB
Python

"""Animation library — 7 built-in animation types with a factory registry."""
from lightsync.animations.base import AnimationBase
from lightsync.animations.solid_color import SolidColorAnimation
from lightsync.animations.chase import ChaseAnimation
from lightsync.animations.pulse import PulseAnimation
from lightsync.animations.rainbow import RainbowAnimation
from lightsync.animations.strobe import StrobeAnimation
from lightsync.animations.color_wipe import ColorWipeAnimation
from lightsync.animations.fire import FireAnimation
__all__ = [
"AnimationBase",
"SolidColorAnimation",
"ChaseAnimation",
"PulseAnimation",
"RainbowAnimation",
"StrobeAnimation",
"ColorWipeAnimation",
"FireAnimation",
"ANIMATION_REGISTRY",
"create_animation",
]
ANIMATION_REGISTRY: dict[str, type[AnimationBase]] = {
"solid_color": SolidColorAnimation,
"chase": ChaseAnimation,
"pulse": PulseAnimation,
"rainbow": RainbowAnimation,
"strobe": StrobeAnimation,
"color_wipe": ColorWipeAnimation,
"fire": FireAnimation,
}
def create_animation(name: str, params: dict) -> AnimationBase:
"""Create an animation by registry name.
Args:
name: Animation type name (e.g. "chase", "fire").
params: CueModel.params dict passed to from_params().
Raises:
ValueError: If name is not in ANIMATION_REGISTRY.
"""
cls = ANIMATION_REGISTRY.get(name)
if cls is None:
raise ValueError(f"Unknown animation: {name!r}. Available: {sorted(ANIMATION_REGISTRY)}")
return cls.from_params(params)