source: rgbkbd/trunk/rgbkbd/animation.py @ 71

Last change on this file since 71 was 71, checked in by retracile, 9 years ago

Initial import of source code

  • Property svn:executable set to *
File size: 5.0 KB
Line 
1#!/usr/bin/python
2
3import time
4import random
5import math
6
7from core import ColorPattern, MotionPattern, EventHandler
8from color import Color, Colors
9from geometry import key_positions, KeyMatrix, Keys
10
11
12class AlternatingColorPattern(ColorPattern):
13    """Steps through a cycle of colors"""
14    def color(self, t):
15        index = int(round(len(self.colors)*self.phase(t))) - 1
16        return self.colors[index]
17
18
19class BeatColorPattern(ColorPattern):
20    """Linearly fades through a cycle of colors"""
21    def color(self, t):
22        index = int(len(self.colors)*self.phase(t)) % len(self.colors)
23        foreground = self.colors[index]
24        background = self.colors[(index+1)%len(self.colors)]
25        phase = (self.phase(t) * len(self.colors)) % 1
26        return Color.blend(foreground, background, transparency=phase)
27
28
29class ThrobColorPattern(ColorPattern):
30    """Non-linearly (sin wave) fades through a cycle of colors"""
31    def color(self, t):
32        index = (2*int(len(self.colors)*self.phase(t))) % len(self.colors)
33        foreground = self.colors[index]
34        background = self.colors[(index+1)%len(self.colors)]
35        phase = (self.phase(t) * len(self.colors)) % 1
36        intensity = (1 + math.sin(2 * math.pi * phase)) / 2
37        return Color.blend(foreground, background, transparency=1-intensity)
38
39
40class PulseColorPattern(ColorPattern):
41    """Pulses a color on, then fades to the next color, through a cycle of
42    colors
43    """
44    def color(self, t):
45        index = (2 * int(len(self.colors)*self.phase(t))) % len(self.colors)
46        foreground = self.colors[index]
47        background = self.colors[(index+1)%len(self.colors)]
48        phase = (self.phase(t) * len(self.colors)) % 1
49        return Color.blend(foreground, background,
50            transparency=phase)
51
52
53class AngleMotionPattern(MotionPattern):
54    """Applies a phase offset across the keyboard at a specified angle and
55    stretched a specified distance.  (Makes for something of a wave effect.)
56    """
57    def __init__(self, angle=0.0, size=50, *args, **kwargs):
58        super(AngleMotionPattern, self).__init__(*args, **kwargs)
59        self.angle = angle
60        self.size = size
61
62    def phase_offset(self, x, y):
63        # The pixels for the keyboard geometry are not square; so account for
64        # their shape by doubling the Y value.
65        return (- x * math.cos(self.angle) - 2 * y * math.sin(self.angle)) / self.size
66
67
68# Lighting animations
69class RandomAnimation(EventHandler):
70    """Light up a randomly selected subset of keys"""
71    tick_rate = 0.1
72
73    def __init__(self, foreground=Colors.WHITE, background=Colors.BLACK,
74            quantity=40, *args, **kwargs):
75        super(RandomAnimation, self).__init__(*args, **kwargs)
76        self.foreground = foreground
77        self.background = background
78        self.quantity = quantity
79        self.lit_keys = []
80
81    def tick(self):
82        """Handler for the periodic events"""
83        # We don't enforce a strict rate here.  If you are typing, the random
84        # updating of keys will occur more frequently.  If this is getting
85        # called as part of a group of event handlers where another event
86        # handler has a lower value for tick_rate, this animation will toggle
87        # keys faster.  Given the intent of this animation, that isn't a
88        # problem.
89        if len(self.lit_keys) > self.quantity:
90            key = self.lit_keys.pop(0)
91            self.keyboard.set_keys(key, self.background)
92        key = random.choice(list(set(Keys.ALL.split(',')) - set(self.lit_keys)))
93        self.lit_keys.append(key)
94        self.keyboard.set_keys(key, self.foreground)
95
96
97class ColorAnimation(EventHandler):
98    """Given a color pattern, apply that pattern to the keyboard"""
99    def __init__(self, color_pattern=None, keys=Keys.ALL, *args, **kwargs):
100        super(ColorAnimation, self).__init__(*args, **kwargs)
101        self.keys = keys
102        self.color_pattern = color_pattern
103
104    def tick(self):
105        color = self.color_pattern.color(time.time())
106        self.keyboard.set_keys(self.keys, color)
107
108
109class MotionAnimation(EventHandler):
110    def __init__(self, color_pattern=None, motion_pattern=None, keys=Keys.ALL,
111            *args, **kwargs):
112        super(MotionAnimation, self).__init__(*args, **kwargs)
113        self.keys = keys.split(',')
114        self.color_pattern = color_pattern
115        self.motion_pattern = motion_pattern
116
117        # pre-calculate the points we will have to color
118        self.points = []
119        for key in self.keys:
120            self.points.extend(key_positions[key])
121
122    def tick(self):
123        matrix = KeyMatrix()
124        for x,y in self.points:
125            color = self.color_pattern.color(time.time() + self.motion_pattern.t_offset(x, y))
126            matrix.set_pixel(x, y, color)
127        colors = {}
128        for key in self.keys:
129            color = matrix.get_key(key)
130            colors.setdefault(color, []).append(key)
131        key_colors = []
132        for color, keys in colors.items():
133            key_colors.append((','.join(keys), color))
134        self.keyboard.set_many_keys(key_colors)
Note: See TracBrowser for help on using the repository browser.