pybeamshow/effects/presets.py

598 lines
19 KiB
Python
Raw Normal View History

2023-02-19 22:54:40 +01:00
import pygame as pg
2023-02-23 01:56:05 +01:00
from typing import Iterator, List
2023-02-19 22:54:40 +01:00
2023-02-23 01:56:05 +01:00
from random import choice, randint, randrange
2023-03-05 01:46:59 +01:00
from effects.chase_circle import ChaseCircle
2023-02-22 22:55:11 +01:00
from effects.effect import Effect
2023-02-24 17:23:22 +01:00
from effects.line import Lines
2023-03-05 01:46:59 +01:00
from effects.rectangle import Rectangle
2023-02-24 18:21:21 +01:00
from util.color import (
color_darken,
color_randomize,
color_static,
color_strobe,
color_wheel,
Colors,
)
2023-02-22 22:55:11 +01:00
2023-02-24 17:23:22 +01:00
# from effects.crazypolys import CrazyPolys
2023-02-20 02:01:16 +01:00
from effects.drops import Drops
2023-02-17 02:08:21 +01:00
from effects.bouncingspot import BouncingSpot
from effects.doublespot import DoubleSpot
2023-02-20 02:01:16 +01:00
from effects.moonflower import Moonflower
2023-02-23 02:02:57 +01:00
from effects.rainbowwave import RainbowWave
2023-02-20 02:01:16 +01:00
from effects.rotatingpoly import RotatingPoly
from effects.scanreticle import ScanReticle
2023-02-24 17:23:22 +01:00
# from effects.spiro import Spiro
2023-02-20 02:01:16 +01:00
from effects.starfield import Starfield
2023-02-23 01:56:05 +01:00
from util.transform import (
transform_bounce,
transform_falling,
transform_oscillate,
transform_static,
)
2023-02-17 02:08:21 +01:00
class Presets:
2023-02-20 02:01:16 +01:00
def __init__(self, bounds: pg.Rect, beat_reactive: bool = False) -> None:
2023-02-17 02:08:21 +01:00
self.bounds = bounds
2023-02-20 02:01:16 +01:00
self.beat_reactive = beat_reactive
2023-03-05 01:46:59 +01:00
self.shuffles = list(iter(self)) * 2
2023-02-20 02:01:16 +01:00
def default(self) -> List[Effect]:
2023-03-05 02:37:18 +01:00
return self.DoubleBouncingSpotsColorWheel()
2023-02-23 01:56:05 +01:00
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)
2023-03-05 01:46:59 +01:00
if callable(getattr(self, func))
and not (func.startswith("__") or func == "randomize")
2023-02-23 01:56:05 +01:00
)
def randomize(self) -> str:
2023-03-05 01:46:59 +01:00
selected = choice(self.shuffles)
self.shuffles.remove(selected)
if not self.shuffles:
self.shuffles = list(iter(self)) * 2
return selected
# return choice(
# [
# func
# for func in dir(self)
# if callable(getattr(self, func))
# and not (func.startswith("__") or func == "randomize")
# ]
# )
2023-02-17 02:08:21 +01:00
def DoubleSpotRandomColor(self) -> List[Effect]:
return [
DoubleSpot(
bounds=self.bounds,
color=color_wheel(increase=30),
2023-02-20 02:01:16 +01:00
beat_adapt=self.beat_reactive,
2023-02-17 02:08:21 +01:00
radius=100,
fade_out=True,
fade_in=True,
hold=60,
)
]
def DoubleBouncingSpotsColorWheel(self) -> List[Effect]:
return [
2023-02-20 02:01:16 +01:00
BouncingSpot(
bounds=self.bounds,
color=color_wheel(),
2023-02-24 17:23:22 +01:00
sizes=(self.bounds.height / 8, self.bounds.height / 6),
2023-02-23 01:56:05 +01:00
mover=transform_bounce(
bounds=self.bounds,
velocity=(1, 1),
x_factor=(1, 1),
y_factor=(2.2, 2.2),
on_beat_phase=90,
),
2023-02-20 02:01:16 +01:00
),
BouncingSpot(
bounds=self.bounds,
color=color_wheel(hue=180),
2023-02-24 17:23:22 +01:00
sizes=(self.bounds.height / 8, self.bounds.height / 6),
2023-02-23 01:56:05 +01:00
mover=transform_bounce(
bounds=self.bounds,
velocity=(1, 1),
x_factor=(1, 1),
y_factor=(2.2, 2.2),
on_beat_phase=180,
),
2023-02-20 02:01:16 +01:00
),
2023-02-17 02:08:21 +01:00
]
2023-02-19 22:54:40 +01:00
def CollidingWaves(self) -> List[Effect]:
return [
2023-02-23 02:02:57 +01:00
RainbowWave(
2023-02-19 22:54:40 +01:00
bounds=pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height),
wave_count=5,
wave_height=self.bounds.height // 6,
2023-02-24 17:23:22 +01:00
thickness=30,
2023-02-23 01:56:05 +01:00
mover=transform_oscillate(self.bounds, 60, (0, 0)),
2023-02-19 22:54:40 +01:00
),
2023-02-23 02:02:57 +01:00
RainbowWave(
2023-02-19 22:54:40 +01:00
bounds=pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height),
2023-02-24 17:23:22 +01:00
# hue=180,
2023-02-19 22:54:40 +01:00
wave_count=5,
wave_height=self.bounds.height // 6,
start_phase=120,
thickness=20,
2023-02-23 01:56:05 +01:00
mover=transform_oscillate(
self.bounds, 60, (0, self.bounds.height * 5 // 6)
),
),
]
2023-02-24 17:23:22 +01:00
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)),
),
]
2023-02-23 01:56:05 +01:00
def FallingWave(self) -> List[Effect]:
2023-02-24 17:23:22 +01:00
bounds = pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height // 2)
2023-02-23 01:56:05 +01:00
return [
2023-02-23 02:02:57 +01:00
RainbowWave(
2023-02-23 01:56:05 +01:00
bounds=bounds,
wave_count=8,
wave_height=self.bounds.height // 8,
2023-02-24 17:23:22 +01:00
thickness=25,
2023-02-23 01:56:05 +01:00
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,
),
2023-02-19 22:54:40 +01:00
),
]
2023-02-17 02:08:21 +01:00
def BouncingSpotWhite(self) -> List[Effect]:
return [
BouncingSpot(
bounds=self.bounds,
2023-02-24 18:21:21 +01:00
color=color_static(Colors.White),
2023-02-24 17:23:22 +01:00
sizes=(self.bounds.height / 3, self.bounds.height / 3),
2023-02-17 02:08:21 +01:00
velocity=(1, 1),
2023-02-23 01:56:05 +01:00
mover=transform_bounce(
bounds=self.bounds,
velocity=(1, 1),
x_factor=(1, 1),
y_factor=(2.2, 2.2),
2023-02-24 17:23:22 +01:00
on_beat_phase=180,
2023-02-23 01:56:05 +01:00
),
2023-02-17 02:08:21 +01:00
),
]
2023-02-20 02:01:16 +01:00
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,
2023-02-24 18:21:21 +01:00
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 0.5),
x_factor=(0.5, 1.5),
y_factor=(0.5, 3),
),
2023-02-20 02:01:16 +01:00
)
]
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,
2023-02-24 17:23:22 +01:00
size=self.bounds.height // 2,
2023-02-20 02:01:16 +01:00
outer=5,
2023-02-24 17:23:22 +01:00
inner_factor=0.3,
2023-02-20 02:01:16 +01:00
rot_speed=1.5,
2023-02-23 00:19:20 +01:00
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 1.5),
x_factor=(0.5, 1.5),
y_factor=(0.5, 1.5),
),
2023-02-20 02:01:16 +01:00
)
]
2023-02-23 01:56:05 +01:00
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]:
2023-02-24 17:23:22 +01:00
hue_left = randrange(0, 12) * 30
hue_right = (hue_left + 180) % 360
# hue_right = randrange(0, 360)
2023-02-23 01:56:05 +01:00
size = int(self.bounds.height * 0.8)
return [
Moonflower(
bounds=self.bounds,
colors=(
color_wheel(
2023-02-24 17:23:22 +01:00
hue=hue_left, increase=(15 if self.beat_reactive else 0)
2023-02-23 01:56:05 +01:00
),
color_wheel(
2023-02-24 17:23:22 +01:00
hue=180 + hue_left, increase=(15 if self.beat_reactive else 0)
2023-02-23 01:56:05 +01:00
),
),
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(
2023-02-24 17:23:22 +01:00
hue=hue_right, increase=(15 if self.beat_reactive else 0)
2023-02-23 01:56:05 +01:00
),
color_wheel(
2023-02-24 17:23:22 +01:00
hue=180 + hue_right, increase=(15 if self.beat_reactive else 0)
2023-02-23 01:56:05 +01:00
),
),
beat_color=self.beat_reactive,
2023-02-24 17:23:22 +01:00
size=int(size * 0.6),
2023-02-23 01:56:05 +01:00
outer=7,
2023-02-24 17:23:22 +01:00
inner_factor=0.3,
2023-02-23 01:56:05 +01:00
rot_speed=1,
mover=transform_static(
position=(self.bounds.width // 2, self.bounds.height // 2)
),
),
]
2023-02-20 02:01:16 +01:00
def WhiteStarfield(self) -> List[Effect]:
return [
Starfield(
bounds=self.bounds,
2023-02-24 18:21:21 +01:00
color=color_static(Colors.White),
2023-02-20 02:01:16 +01:00
# 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,
2023-02-24 18:21:21 +01:00
colors=(
color_static(Colors.Green),
color_static(color_darken(Colors.Blue, 0.2)),
),
2023-02-20 02:01:16 +01:00
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,
2023-02-24 18:21:21 +01:00
(color_static(Colors.Red), color_static(Colors.White)),
2023-02-23 01:56:05 +01:00
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 1),
2023-03-05 01:46:59 +01:00
x_factor=(2, 2),
2023-02-23 01:56:05 +01:00
y_factor=(0.5, 1),
),
2023-02-20 02:01:16 +01:00
)
]
2023-02-22 03:43:50 +01:00
2023-03-05 01:46:59 +01:00
# 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,
# ),
# ),
# ]
2023-02-22 03:43:50 +01:00
2023-02-24 18:21:21 +01:00
def StrobeLine(self) -> List[Effect]:
2023-02-24 18:59:24 +01:00
thickness = 50
bounds = pg.rect.Rect(0, 0, self.bounds.width, thickness)
2023-02-22 03:43:50 +01:00
return [
2023-02-24 18:21:21 +01:00
Lines(
bounds=bounds,
vectors=(
(
2023-02-24 18:59:24 +01:00
(0, thickness // 2),
(self.bounds.width, thickness // 2),
color_strobe(color=color_wheel(), rate=(4, 60)),
2023-02-24 18:21:21 +01:00
),
),
2023-02-24 18:59:24 +01:00
thickness=thickness,
mover=transform_static((0, 0)),
),
Lines(
bounds=bounds,
vectors=(
(
(0, thickness // 2),
(self.bounds.width, thickness // 2),
color_strobe(color=color_wheel(), rate=(4, 10)),
),
2023-02-24 18:21:21 +01:00
),
2023-02-24 18:59:24 +01:00
thickness=thickness,
mover=transform_static((0, self.bounds.height - thickness)),
2023-02-22 03:43:50 +01:00
),
]
2023-02-24 18:21:21 +01:00
# 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)
]
2023-02-24 18:59:24 +01:00
def OscillateSpotRow(self) -> List[Effect]:
count = 4
size = self.bounds.width // (count * 2)
return [
BouncingSpot(
bounds=self.bounds,
color=color_wheel(hue=180 * i, increase=120),
sizes=(size * 1.5, size * 1.5),
velocity=(1, 1),
on_beat_color=True,
mover=transform_oscillate(
bounds=pg.Rect(
size + size * 2 * i,
size * 1.5 // 2,
size * 1.5,
self.bounds.height,
),
period=120,
auto_period=4,
),
)
for i in range(count)
]
2023-03-05 01:46:59 +01:00
def StrobeRect(self) -> List[Effect]:
thickness = 50
color_lr = color_wheel(hue=0, increase=1, repeat=4)
color_ud = color_wheel(hue=180, increase=1, repeat=4)
color_lr_s = color_strobe(color=color_lr, rate=(30, 120), flash_color=color_ud)
color_ud_s = color_strobe(color=color_ud, rate=(30, 120), flash_color=color_lr)
return [
Lines(
bounds=self.bounds,
vectors=(
(
(0, thickness // 2),
(self.bounds.width, thickness // 2),
color_ud_s,
),
(
(0, self.bounds.height - thickness // 2),
(self.bounds.width, self.bounds.height - thickness // 2),
color_ud_s,
),
),
thickness=thickness,
mover=transform_static((0, 0)),
),
Lines(
bounds=self.bounds,
vectors=(
(
(thickness // 2, 0),
(thickness // 2, self.bounds.height),
color_lr_s,
),
(
(self.bounds.width - thickness // 2, 0),
(self.bounds.width - thickness // 2, self.bounds.height),
color_lr_s,
),
),
thickness=thickness,
mover=transform_static((0, 0)),
),
]
def ChaseCircle(self) -> List[Effect]:
return [
ChaseCircle(
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)),
),
on_beat_color=self.beat_reactive,
size=int(self.bounds.height * 0.7),
rot_speed=5,
thickness=80,
size_factor=1,
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.1, 0.5),
x_factor=(0.5, 1),
y_factor=(0.1, 0.3),
),
)
]
def ChaseCircleLine(self) -> List[Effect]:
return [
ChaseCircle(
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)),
),
on_beat_color=self.beat_reactive,
size=int(self.bounds.height * 0.7),
rot_speed=-20,
thickness=80,
size_factor=0.2,
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.1, 0.5),
x_factor=(0.5, 1),
y_factor=(0.1, 0.3),
),
)
]
2023-03-05 02:37:18 +01:00
# def Rectangle(self) -> List[Effect]:
# return [
# Rectangle(
# bounds=self.bounds,
# color=color_wheel(increase=(75 if self.beat_reactive else 1)),
# size=int(self.bounds.height*0.9),
# aspect=1.0,
# rot_speed=0.5,
# thickness=80,
# mover=transform_bounce(
# bounds=self.bounds,
# velocity=(0.1, 0.5),
# x_factor=(0.5, 1),
# y_factor=(0.1, 0.3),
# ),
# )
# ]