pybeamshow/effects/presets.py
2023-02-24 18:21:40 +01:00

452 lines
14 KiB
Python

import pygame as pg
from typing import Iterator, List
from random import choice, randint, randrange
from effects.effect import Effect
from effects.line import Lines
from util.color import (
color_darken,
color_randomize,
color_static,
color_strobe,
color_wheel,
Colors,
)
# from effects.crazypolys import CrazyPolys
from effects.drops import Drops
from effects.bouncingspot import BouncingSpot
from effects.doublespot import DoubleSpot
from effects.moonflower import Moonflower
from effects.rainbowwave import RainbowWave
from effects.rotatingpoly import RotatingPoly
from effects.scanreticle import ScanReticle
# from effects.spiro import Spiro
from effects.starfield import Starfield
from util.transform import (
transform_bounce,
transform_falling,
transform_oscillate,
transform_static,
)
class Presets:
def __init__(self, bounds: pg.Rect, beat_reactive: bool = False) -> None:
self.bounds = bounds
self.beat_reactive = beat_reactive
def default(self) -> List[Effect]:
return self.SpotRow()
def __getitem__(self, idx: str) -> List[Effect]:
return getattr(self, idx)()
def __contains__(self, idx: str) -> bool:
return hasattr(self, idx)
def __iter__(self) -> Iterator[str]:
return (
func
for func in dir(self)
if callable(getattr(self, func)) and not func.startswith("__")
)
def randomize(self) -> str:
return choice(
[
func
for func in dir(self)
if callable(getattr(self, func))
and not (func.startswith("__") or func == "randomize")
]
)
def DoubleSpotRandomColor(self) -> List[Effect]:
return [
DoubleSpot(
bounds=self.bounds,
color=color_wheel(increase=30),
beat_adapt=self.beat_reactive,
radius=100,
fade_out=True,
fade_in=True,
hold=60,
)
]
def DoubleBouncingSpotsColorWheel(self) -> List[Effect]:
return [
BouncingSpot(
bounds=self.bounds,
color=color_wheel(),
sizes=(self.bounds.height / 8, self.bounds.height / 6),
mover=transform_bounce(
bounds=self.bounds,
velocity=(1, 1),
x_factor=(1, 1),
y_factor=(2.2, 2.2),
on_beat_phase=90,
),
),
BouncingSpot(
bounds=self.bounds,
color=color_wheel(hue=180),
sizes=(self.bounds.height / 8, self.bounds.height / 6),
mover=transform_bounce(
bounds=self.bounds,
velocity=(1, 1),
x_factor=(1, 1),
y_factor=(2.2, 2.2),
on_beat_phase=180,
),
),
]
def CollidingWaves(self) -> List[Effect]:
return [
RainbowWave(
bounds=pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height),
wave_count=5,
wave_height=self.bounds.height // 6,
thickness=30,
mover=transform_oscillate(self.bounds, 60, (0, 0)),
),
RainbowWave(
bounds=pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height),
# hue=180,
wave_count=5,
wave_height=self.bounds.height // 6,
start_phase=120,
thickness=20,
mover=transform_oscillate(
self.bounds, 60, (0, self.bounds.height * 5 // 6)
),
),
]
def RainbowWave(self) -> List[Effect]:
return [
RainbowWave(
bounds=pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height),
wave_count=1,
color_inc=2,
wave_height=self.bounds.height // 3,
thickness=30,
mover=transform_static(position=(0, 0)),
),
]
def FallingWave(self) -> List[Effect]:
bounds = pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height // 2)
return [
RainbowWave(
bounds=bounds,
wave_count=8,
wave_height=self.bounds.height // 8,
thickness=25,
hue=30 * randrange(0, 12),
color_inc=0,
scroll_speed=0,
mover=transform_falling(
bounds,
acceleration=0.8,
initial_pos=(0, 0),
initial_velocity=0.01,
on_beat_reset=True,
),
),
]
def BouncingSpotWhite(self) -> List[Effect]:
return [
BouncingSpot(
bounds=self.bounds,
color=color_static(Colors.White),
sizes=(self.bounds.height / 3, self.bounds.height / 3),
velocity=(1, 1),
mover=transform_bounce(
bounds=self.bounds,
velocity=(1, 1),
x_factor=(1, 1),
y_factor=(2.2, 2.2),
on_beat_phase=180,
),
),
]
def RotatingPoly(self) -> List[Effect]:
return [
RotatingPoly(
bounds=self.bounds,
color=color_wheel(increase=(75 if self.beat_reactive else 0)),
beat_color=self.beat_reactive,
size=int(self.bounds.height * 0.8),
outer=randint(3, 8),
rot_speed=1,
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 0.5),
x_factor=(0.5, 1.5),
y_factor=(0.5, 3),
),
)
]
def Moonflower(self) -> List[Effect]:
return [
Moonflower(
bounds=self.bounds,
colors=(
color_wheel(increase=(75 if self.beat_reactive else 0)),
color_wheel(hue=180, increase=(75 if self.beat_reactive else 0)),
),
beat_color=self.beat_reactive,
size=self.bounds.height // 2,
outer=5,
inner_factor=0.3,
rot_speed=1.5,
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 1.5),
x_factor=(0.5, 1.5),
y_factor=(0.5, 1.5),
),
)
]
def DoubleMoonflower(self) -> List[Effect]:
hue_left = randrange(0, 360)
hue_right = randrange(0, 360)
size = int(self.bounds.height * 0.75)
return [
Moonflower(
bounds=self.bounds,
colors=(
color_wheel(
hue=hue_left, increase=(75 if self.beat_reactive else 0)
),
color_wheel(
hue=180 + hue_left, increase=(75 if self.beat_reactive else 0)
),
),
beat_color=self.beat_reactive,
size=size,
outer=7,
inner_factor=0.5,
rot_speed=-1.5,
mover=transform_static(position=(size // 2, self.bounds.height // 2)),
),
Moonflower(
bounds=self.bounds,
colors=(
color_wheel(
hue=hue_right, increase=(75 if self.beat_reactive else 0)
),
color_wheel(
hue=180 + hue_right, increase=(75 if self.beat_reactive else 0)
),
),
beat_color=self.beat_reactive,
size=size,
outer=7,
inner_factor=0.5,
rot_speed=1.7,
mover=transform_static(
position=(self.bounds.width - size // 2, self.bounds.height // 2)
),
),
]
def NestedMoonflower(self) -> List[Effect]:
hue_left = randrange(0, 12) * 30
hue_right = (hue_left + 180) % 360
# hue_right = randrange(0, 360)
size = int(self.bounds.height * 0.8)
return [
Moonflower(
bounds=self.bounds,
colors=(
color_wheel(
hue=hue_left, increase=(15 if self.beat_reactive else 0)
),
color_wheel(
hue=180 + hue_left, increase=(15 if self.beat_reactive else 0)
),
),
beat_color=self.beat_reactive,
size=size,
outer=7,
inner_factor=0.5,
rot_speed=-1.5,
mover=transform_static(
position=(self.bounds.width // 2, self.bounds.height // 2)
),
),
Moonflower(
bounds=self.bounds,
colors=(
color_wheel(
hue=hue_right, increase=(15 if self.beat_reactive else 0)
),
color_wheel(
hue=180 + hue_right, increase=(15 if self.beat_reactive else 0)
),
),
beat_color=self.beat_reactive,
size=int(size * 0.6),
outer=7,
inner_factor=0.3,
rot_speed=1,
mover=transform_static(
position=(self.bounds.width // 2, self.bounds.height // 2)
),
),
]
def WhiteStarfield(self) -> List[Effect]:
return [
Starfield(
bounds=self.bounds,
color=color_static(Colors.White),
# color=color_randomize(),
fade_in=True,
fade_out=True,
# radius=30,
star_factor=1,
hold=60 * 2,
# beat_adapt=True,
)
]
def ColorStarfield(self) -> List[Effect]:
return [
Starfield(
bounds=self.bounds,
color=color_randomize(),
fade_in=True,
fade_out=True,
# radius=30,
star_factor=1,
hold=60 * 2,
beat_adapt=True,
)
]
def GreenBlueDrops(self) -> List[Effect]:
return [
Drops(
bounds=self.bounds,
colors=(
color_static(Colors.Green),
color_static(color_darken(Colors.Blue, 0.2)),
),
sizes=(self.bounds.width // 40, self.bounds.width // 35),
drop_rate=0.1,
drop_acceleration=0.3,
)
]
def ScanReticle(self) -> List[Effect]:
return [
ScanReticle(
self.bounds,
(color_static(Colors.Red), color_static(Colors.White)),
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 1),
x_factor=(3, 3),
y_factor=(0.5, 1),
),
)
]
def FallingLine(self) -> List[Effect]:
bounds = pg.rect.Rect(0, 0, self.bounds.width, 30)
return [
Lines(
bounds=bounds,
vectors=(((0, 15), (self.bounds.width, 15), color_wheel()),),
thickness=30,
mover=transform_falling(
bounds,
acceleration=0.8,
initial_pos=(0, 0),
initial_velocity=0.01,
on_beat_reset=True,
),
),
]
def StrobeLine(self) -> List[Effect]:
bounds = pg.rect.Rect(0, 0, self.bounds.width, 30)
return [
Lines(
bounds=bounds,
vectors=(
(
(0, 15),
(self.bounds.width, 15),
color_strobe(color=color_wheel(), rate=(2, 8)),
),
),
thickness=30,
mover=transform_falling(
bounds,
acceleration=0.8,
initial_pos=(0, 0),
initial_velocity=0.01,
on_beat_reset=True,
),
),
]
# def Spiro(self) -> List[Effect]:
# return [
# Spiro(
# bounds=self.bounds,
# color=color_wheel(increase=2),
# sizes=(self.bounds.height, self.bounds.height),
# velocity=(0.1, 0.4),
# mover=transform_bounce(
# self.bounds,
# velocity=(0.1, 0.4),
# x_factor=(1, 1),
# y_factor=(0.5, 1.5),
# ),
# ),
# ]
# def CrazyPolys(self) -> List[Effect]:
# return [
# CrazyPolys(
# bounds=self.bounds,
# color=color_wheel(increase=2),
# sizes=(self.bounds.height, self.bounds.height),
# velocity=(0.1, 0.4),
# y_factor=(0.5, 1.5),
# ),
# ]
def SpotRow(self) -> List[Effect]:
count = 8
size = self.bounds.width // (count * 2)
return [
BouncingSpot(
bounds=self.bounds,
color=color_wheel(hue=3 * 360 // count * i, increase=60),
sizes=(size, size),
velocity=(1, 1),
on_beat_color=True,
mover=transform_static(
(
size + size * 2 * i,
size,
)
),
)
for i in range(count)
]