Ensure color_pos is always -1 when the lights go out, so behaviour is always consistent
[tabakrolletjie.git] / tabakrolletjie / transforms.py
1 """ Image transformations for use with the image loader. """
2
3 import pygame.surface
4
5 import pygame.locals as pgl
6
7 from .constants import COLOURS
8
9
10 class Transform(object):
11
12     ARGS = []
13
14     def __init__(self, **kw):
15         for k in self.ARGS:
16             setattr(self, k, kw.pop(k))
17         assert not kw
18         self._repr = "%s: <%s>" % (
19             self.__class__.__name__,
20             ", ".join("%s=%s" % (k, getattr(self, k)) for k in self.ARGS))
21         return
22
23     def __repr__(self):
24         return self._repr
25
26     def __hash__(self):
27         return hash(self._repr)
28
29     def __eq__(self, other):
30         if not isinstance(other, Transform):
31             return NotImplemented
32         return self._repr == other._repr
33
34     def apply(self, surface):
35         raise NotImplementedError("Transforms should implement .apply")
36
37
38 class NullTransform(Transform):
39     """ Do nothing. """
40
41     def apply(self, surface):
42         return surface
43
44
45 class Overlay(Transform):
46     """ Apply a colour overlay. """
47
48     ARGS = ["colour"]
49
50     def apply(self, surface):
51         over = pygame.surface.Surface(surface.get_size())
52         over = over.convert_alpha()
53         over.fill(self.colour)
54         surface.blit(over, (0, 0), None)
55         return surface
56
57
58 class Multiply(Transform):
59     """ Apply a colour by multiplying. """
60
61     ARGS = ["colour"]
62
63     def apply(self, surface):
64         mult = pygame.surface.Surface(surface.get_size())
65         mult = mult.convert_alpha()
66         mult.fill(self.colour)
67         surface.blit(mult, (0, 0), None, pgl.BLEND_RGBA_MULT)
68         return surface
69
70
71 class Alpha(Transform):
72     """ Make translucent. """
73
74     ARGS = ["alpha"]
75
76     def apply(self, surface):
77         surface.fill((255, 255, 255, self.alpha), None, pgl.BLEND_RGBA_MULT)
78         return surface
79
80
81 class ColourWedges(Transform):
82     """ Apply colours as wedges. """
83
84     ARGS = ["colours"]
85
86     def apply(self, surface):
87         size = surface.get_width()
88         assert size in (16, 32, 48, 64)
89         fitting_colours = [COLOURS[c] for c in self.colours]
90         ncolour = len(fitting_colours)
91         if ncolour > 3:
92             print "Multicoloured light should not have more than 3 colours"
93             ncolour = 3
94
95         if ncolour == 1:
96             multiply = Multiply(colour=fitting_colours[0])
97             return multiply.apply(surface)
98
99         colour_mult_image = pygame.surface.Surface((size, size))
100         from .loader import loader
101         for i in range(ncolour):
102             sector = loader.load_image(
103                 str(size), "light_mask_%d_%d.png" % (ncolour, i + 1),
104                 transform=Multiply(colour=fitting_colours[i]))
105             colour_mult_image.blit(sector, (0, 0), None, 0)
106
107         surface.blit(colour_mult_image, (0, 0), None, pgl.BLEND_RGBA_MULT)
108         return surface