import colorsys from time import time class Animation: def __init__(self): pass def __str__(self): return f"{type(self).__name__}" def update(self, index, count): return (0, 0 ,0) def name(self): return "None" class Off(Animation): def __init__(self): super(Off, self).__init__() def name(self): return "off" class Steady(Animation): def __init__(self, color): super(Steady, self).__init__() (r, g, b) = color self.r = r self.g = g self.b = b def update(self, index, count): return (self.r, self.g, self.b) def __str__(self): return f"{type(self).__name__}({self.r}, {self.g}, {self.b})" def name(self): return "steady" class FadeTo(Steady): def __init__(self, color, t=2.0): super(FadeTo, self).__init__(color) self.t = t self.start = time() def update(self, index, count): h = (time() - self.start) / self.t h = min(h, 1.0) return (int(self.r * h), int(self.g * h), int(self.b * h)) def __str__(self): return f"{type(self).__name__}({self.r}, {self.g}, {self.b}, {self.t:.2f})" def name(self): return "fadeTo" class RotatingRainbow(Animation): def __init__(self, looptime=10.0): super(RotatingRainbow, self).__init__() self.looptime = looptime pass def update(self, index, count): """ One full round takes self.looptime seconds, each RGB is offset in a circle :param index: :param count: :return: """ hue = (time() / self.looptime + (index + 0.0) / count) % 1.0 rgb = hsv_to_rgb(hue, 1, 1) return rgb def __str__(self): return f"{type(self).__name__}" def name(self): return "rainbow" class Chase(Steady): def __init__(self, color, looptime=1.0): super(Chase, self).__init__(color) self.looptime = looptime def update(self, index, count): angle = (time() / self.looptime + (index + 0.0) / count) % 1.0 l = 1 - min(abs(angle - 1 / count) * .9, 1.0 / count) * count # print(f"f({index}, {angle:.2f}) -> {l:.2f}") return (int(self.r * l), int(self.g * l), int(self.b * l)) def __str__(self): return f"{type(self).__name__}({self.r}, {self.g}, {self.b}, {self.looptime:.2f})" def name(self): return "chase" def hsv_to_rgb(h, s, v): (r, g, b) = colorsys.hsv_to_rgb(h, s, v) return [int(r * 255), int(g * 255), int(b * 255)]