aboutsummaryrefslogtreecommitdiffstats
path: root/hex33board/rgb.py
blob: 2a3bdf804674080e3f9799b2874d6dfbf36cfc8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from __future__ import annotations

from adafruit_ticks import ticks_diff

from .util import hsv_to_rgb


class RGBEffect:
    keyboard: Keyboard
    prepared: list[Any]

    def __init__(self, keyboard: Keyboard):
        self.keyboard = keyboard

    def prepare(self):
        base = self.keyboard.modes["base"]
        self.prepared = [self.prepare_key(key) for key in base.keys]

    def prepare_key(self, key: Key) -> Any:
        pass

    def tick(self, ticks_ms: int):
        pass

    def get_color(self, i: int, key: Key):
        pass


class ColorScale(RGBEffect):
    def prepare_key(self, key: Key):
        in_scale = self.keyboard.scale.is_in_scale(key.pitch)

        if in_scale:
            return (0.1, 0.9, 0.65)
        else:
            return (0.3, 0.8, 0.0)

    def get_color(self, i: int, key: Key):
        if key.pitch < 0 or key.pitch > 127:
            return 0

        hue, sat, key_val = self.prepared[i]

        base = self.keyboard.modes["base"]
        extra = base.extra_notes.get(key.pitch)
        note_for_pitch = base.notes.get(key.pitch)
        note_for_pitch = note_for_pitch or base.notes_expiring.get(key.pitch)

        if extra:
            return hsv_to_rgb(hue, 1.0, 1.0)

        if key.note:
            value = 1.0
        elif note_for_pitch:
            value = note_for_pitch.expiry * 0.3
        else:
            hue = 0.7
            value = 0.0

        rest = 1.0 - key_val
        value = key_val + value * rest
        return hsv_to_rgb(hue, sat, value)


class Rainbow(RGBEffect):
    hue_shift: float = 0.0
    last_ticks_ms: int

    def tick(self, ticks_ms: int):
        if hasattr(self, "last_ticks_ms"):
            delta = ticks_diff(ticks_ms, self.last_ticks_ms)
            self.hue_shift = (self.hue_shift + delta / 1000 / 6) % 1

        self.last_ticks_ms = ticks_ms

    def prepare(self):
        self.hue_shift = 0.0
        super().prepare()

    def prepare_key(self, key: Key):
        return (0, 0.9, 1.0)

    def get_color(self, i: int, key: Key):
        if key.pitch < 0 or key.pitch > 127:
            return 0

        x, y = key.pos
        hue, sat, val = self.prepared[i]
        hue += x / 50 + y / 40 + self.hue_shift

        return hsv_to_rgb(hue, sat, val)


class RainbowScale(Rainbow):
    def prepare_key(self, key: Key):
        if self.keyboard.scale.is_in_scale(key.pitch):
            return (0, 0.9, 1)
        else:
            return (0, 0.75, 0.1)


class RainbowScaleAlt(Rainbow):
    def prepare_key(self, key: Key):
        if self.keyboard.scale.is_in_scale(key.pitch):
            return (0, 0.9, 1)
        else:
            return (0.2, 0.9, 0.5)


RGB_EFFECTS = {
    "scale": ColorScale,
    "rainbow": Rainbow,
    "rainbow scale": RainbowScale,
    "rainbow scale alt": RainbowScaleAlt,
}