67 lines
1.8 KiB
Python
67 lines
1.8 KiB
Python
from typing import Tuple
|
|
|
|
from flickerstrip_py.models.pattern import Pattern, PatternData
|
|
|
|
RGBColor = Tuple[int, int, int]
|
|
|
|
|
|
class PatternBuilder:
|
|
def __init__(self, name: str, fps=1, pixels_per_frame=1):
|
|
self.data: list[RGBColor] = []
|
|
self.name = name
|
|
self.fps = fps
|
|
self.fps: int = fps
|
|
self.frame_count: int = 1
|
|
self.pixels_per_frame: int = pixels_per_frame
|
|
|
|
def set_pixel(self, f: int, i: int, color: RGBColor):
|
|
offset = f * self.pixels_per_frame + i
|
|
|
|
self.data[offset] = color
|
|
|
|
def append_pixel(self, color: RGBColor):
|
|
self.data.append(color)
|
|
|
|
def get_frame(self, f: int) -> list[RGBColor]:
|
|
start = f * self.pixels_per_frame
|
|
end = start + self.pixels_per_frame
|
|
return self.data[start:end]
|
|
|
|
def next_frame(self):
|
|
if not self.is_valid():
|
|
raise Exception("Not enough pixels for next frame")
|
|
|
|
self.frame_count += 1
|
|
|
|
def is_valid(self):
|
|
if self.frame_count == 0:
|
|
return False
|
|
|
|
if len(self.data) != self.frame_count * self.pixels_per_frame:
|
|
return False
|
|
|
|
return True
|
|
|
|
def to_pattern_data(self) -> PatternData:
|
|
data = bytes(y for x in self.data for y in x)
|
|
return PatternData(data=data)
|
|
|
|
def to_pattern(self) -> Pattern:
|
|
return Pattern(
|
|
id=0,
|
|
flags=0,
|
|
name=self.name,
|
|
fps=self.fps,
|
|
frames=self.frame_count,
|
|
pixels=self.pixels_per_frame,
|
|
)
|
|
|
|
@classmethod
|
|
def from_data(cls, meta: Pattern, data: PatternData):
|
|
builder = PatternBuilder(meta.name, meta.fps, meta.pixels)
|
|
builder.data = [
|
|
tuple(data.data[x : x + 3]) for x in range(0, len(data.data), 3)
|
|
]
|
|
builder.frame_count = meta.frames
|
|
return builder
|