Source code for bruhanimate.demos.image_demo

"""Six resizable panels: transitions, image masks, and a public animation sequence.

Run python -m bruhanimate.demos.image_demo; q quits. An 80x40 terminal gives each
panel enough room for its small pyfiglet image. Tiny viewports clip safely.
"""

from collections.abc import Callable

from bruhanimate import (
    Animation,
    Buffer,
    Column,
    DissolveImageEffect,
    Fixed,
    FocusImageEffect,
    GlitchImageEffect,
    ImageMask,
    Label,
    Layer,
    Panel,
    PlasmaEffect,
    PlasmaSettings,
    ResizePolicy,
    Row,
    Scene,
    Slot,
    TextStyle,
    WipeImageEffect,
    play,
    text_to_image,
)

from ._image_cycle import ImageCycle


[docs] def build_scene(buffer: Buffer) -> Animation: """Build independently owned panels using public Layer mask/style options.""" rows = text_to_image("bruh", font="small") def tile( name: str, make: Callable[[], Animation] | None ) -> Callable[[Buffer], Animation]: def build(local: Buffer) -> Animation: def content(canvas: Buffer) -> Animation: plasma = PlasmaEffect( Buffer(canvas.height(), canvas.width()), " ", PlasmaSettings(color=True, characters=False, seed=7), ) if make is None: return Scene( Layer(plasma, mask=ImageMask(rows), updates_per_second=30) ) return Scene( Layer(plasma, updates_per_second=30), Layer( make(), style=TextStyle(foreground=231, bold=True), preserve_background=True, ), ) return Panel( effect_factory=content, size=(max(1, local.width() - 2), max(1, local.height() - 2)), title=name, fit=True, border_color=117, ) return build return Column( Slot( Label("IMAGE EFFECTS | resize freely | q quit", align="center"), size=Fixed(1), ), Slot( Row( Slot( effect_factory=tile( "Glitch", lambda: GlitchImageEffect( rows, seed=42, repeat=True, reverse=True ), ) ), Slot( effect_factory=tile( "Focus", lambda: FocusImageEffect( rows, seed=42, repeat=True, reverse=True ), ) ), gap=1, ) ), Slot( Row( Slot( effect_factory=tile( "Dissolve", lambda: DissolveImageEffect( rows, seed=42, repeat=True, reverse=True ), ) ), Slot(effect_factory=tile("ImageMask | plasma-filled glyphs", None)), gap=1, ) ), Slot( Row( Slot( effect_factory=tile( "Wipe right / reverse", lambda: WipeImageEffect(rows, repeat=True, reverse=True), ) ), Slot( effect_factory=tile("AnimationSequence", lambda: ImageCycle(rows)) ), gap=1, ) ), gap=1, ).build(buffer)
[docs] def run( *, frames: int | None = None, fps: float = 60, on_resize: ResizePolicy = "resize" ) -> int: """Present at fps; transitions use simulation seconds and preserve resize state.""" return play( effect_factory=build_scene, frames=frames, fps=fps, updates_per_second=60, on_complete="hold", on_resize=on_resize, )
if __name__ == "__main__": run()