Mercurial > sypikslang
annotate gamelib/gui_base.py @ 130:8f717b2b3378
Advance milestone
author | Neil Muller <drnlmuller@gmail.com> |
---|---|
date | Thu, 10 May 2012 16:46:18 +0200 |
parents | 9a30162f2a9c |
children | 821ecb98e888 |
rev | line source |
---|---|
37 | 1 import pygame |
70 | 2 from pygame.locals import SRCALPHA |
39
d82d3e54a4ef
fixed more pep8 issues
Rizmari Versfeld <rizziepit@gmail.com>
parents:
38
diff
changeset
|
3 from pygame import Surface, Rect |
37 | 4 from pygame.font import Font |
5 | |
6 from gamelib import data | |
7 | |
8 | |
9 # different font sizes | |
10 pygame.font.init() | |
11 font_small = Font(data.filepath('fonts/DejaVuSans.ttf'), 10) | |
12 font_medium = Font(data.filepath('fonts/DejaVuSans.ttf'), 14) | |
13 font_large = Font(data.filepath('fonts/DejaVuSans.ttf'), 18) | |
110
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
14 font_auto = None |
37 | 15 |
16 | |
17 class Drawable(object): | |
38 | 18 |
19 def __init__(self, rect): | |
20 if isinstance(rect, Rect): | |
21 self.rect = rect | |
22 else: | |
23 self.rect = Rect(rect[0], rect[1], rect[2], rect[3]) | |
24 | |
25 def draw(self, surface): | |
26 pass | |
27 | |
28 | |
37 | 29 class Clickable(object): |
38 | 30 |
31 def on_mouse_down(self, pos): | |
32 pass | |
33 | |
34 def on_mouse_up(self, pos): | |
35 pass | |
36 | |
37 def on_mouse_move(self, pos): | |
38 pass | |
39 | |
40 def on_mouse_cancel(self): | |
41 pass | |
42 | |
43 def on_click(self): | |
44 pass | |
45 | |
37 | 46 |
47 class ContainerView(Drawable): | |
38 | 48 |
49 def __init__(self): | |
50 self.children = [] | |
51 | |
52 def add_child(self, child): | |
53 self.children.append(child) | |
54 | |
55 def remove_child(self, child): | |
56 self.children.remove(child) | |
57 | |
58 def get_child_by_pos(self, pos): | |
59 for child in self.children: | |
60 if child.rect.collidepoint(pos): | |
61 if isinstance(child, ContainerView): | |
62 # calculates position relative to child | |
63 x = pos[0] - child.rect[0] | |
64 y = pos[1] - child.rect[1] | |
65 return child.get_child_by_pos((x, y)) | |
66 else: | |
67 return child | |
68 | |
69 def draw_children(self, surface): | |
70 for child in self.children: | |
71 child.draw(surface) | |
72 | |
73 | |
37 | 74 class Window(Clickable, ContainerView): |
38 | 75 |
76 def __init__(self, screen): | |
77 super(Window, self).__init__() | |
78 self.surface = Surface((screen.get_width(), screen.get_height())) | |
79 self.background_colour = None | |
80 self.background_image = None | |
81 self.pressed_child = None | |
82 | |
83 def on_mouse_down(self, pos): | |
84 child = self.get_child_by_pos(pos) | |
85 if isinstance(child, Clickable): | |
86 # calculates position relative to child | |
87 x = pos[0] - child.rect[0] | |
88 y = pos[1] - child.rect[1] | |
89 child.on_mouse_down((x, y)) | |
90 self.pressed_child = child | |
91 | |
92 def on_mouse_up(self, pos): | |
93 if self.pressed_child: | |
94 child = self.pressed_child | |
95 x = pos[0] - child.rect[0] | |
96 y = pos[1] - child.rect[1] | |
97 child.on_mouse_up((x, y)) | |
98 self.pressed_child = None | |
99 | |
100 def on_mouse_move(self, pos): | |
101 if self.pressed_child: | |
102 if self.pressed_child != self.get_child_by_pos(pos): | |
103 self.pressed_child.on_mouse_cancel() | |
104 self.pressed_child = None | |
105 | |
106 def draw(self, screen): | |
107 if self.background_colour: | |
108 self.surface.fill(self.background_colour) | |
68
7309392d9ca9
fixed widget drawing bugs
Rizmari Versfeld <rizziepit@gmail.com>
parents:
64
diff
changeset
|
109 else: |
7309392d9ca9
fixed widget drawing bugs
Rizmari Versfeld <rizziepit@gmail.com>
parents:
64
diff
changeset
|
110 self.surface.fill((0, 0, 0, 255)) |
38 | 111 if self.background_image: |
112 self.surface.blit(self.background_image, (0, 0)) | |
113 self.draw_children(self.surface) | |
114 screen.blit(self.surface, (0, 0)) | |
115 | |
37 | 116 |
117 class StateDrawable(Drawable): | |
38 | 118 |
119 def __init__(self, rect): | |
120 super(StateDrawable, self).__init__(rect) | |
121 self.state = -1 | |
122 self.states = {} | |
123 self.drawables = [] | |
124 self.surface = Surface((self.rect[2], self.rect[3])) | |
125 | |
126 def draw(self, surface): | |
127 if self.state != -1 and self.drawables[self.state]: | |
128 self.drawables[self.state].draw(surface) | |
129 | |
130 def add_state(self, state_name, drawable): | |
131 self.states[state_name] = len(self.drawables) | |
132 self.drawables.append(drawable) | |
133 | |
134 def set_state(self, state_name): | |
135 self.state = self.states[state_name] | |
136 | |
137 | |
37 | 138 class Button(Clickable, StateDrawable): |
38 | 139 |
140 def __init__(self, rect, normal_drawable, down_drawable): | |
141 super(Button, self).__init__(rect) | |
142 self.add_state('NORMAL', normal_drawable) | |
143 self.add_state('DOWN', down_drawable) | |
144 self.set_state('NORMAL') | |
145 | |
146 def on_mouse_down(self, pos): | |
147 self.set_state('DOWN') | |
148 | |
149 def on_mouse_up(self, pos): | |
150 self.set_state('NORMAL') | |
151 self.on_click() | |
152 | |
153 def on_mouse_cancel(self): | |
154 self.set_state('NORMAL') | |
155 | |
156 | |
37 | 157 class TextButton(Button): |
158 | |
62
38f41d046c6f
Make button font a parameter. Tweak indication of points to be spent
Neil Muller <drnlmuller@gmail.com>
parents:
55
diff
changeset
|
159 def __init__(self, rect, normal_drawable, down_drawable, text, font, |
38f41d046c6f
Make button font a parameter. Tweak indication of points to be spent
Neil Muller <drnlmuller@gmail.com>
parents:
55
diff
changeset
|
160 shadow): |
38 | 161 super(TextButton, self).__init__(rect, normal_drawable, down_drawable) |
70 | 162 self.surface = Surface((rect[2], rect[3]), SRCALPHA) |
38 | 163 self.text = text |
110
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
164 if font is font_auto: |
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
165 font = self._auto_font() |
62
38f41d046c6f
Make button font a parameter. Tweak indication of points to be spent
Neil Muller <drnlmuller@gmail.com>
parents:
55
diff
changeset
|
166 self.font = font |
38f41d046c6f
Make button font a parameter. Tweak indication of points to be spent
Neil Muller <drnlmuller@gmail.com>
parents:
55
diff
changeset
|
167 self.shadow = shadow |
55
86d83dcb7d42
Make text drawing easier to poke at for subclasses
Neil Muller <drnlmuller@gmail.com>
parents:
39
diff
changeset
|
168 self._draw_text() |
86d83dcb7d42
Make text drawing easier to poke at for subclasses
Neil Muller <drnlmuller@gmail.com>
parents:
39
diff
changeset
|
169 |
110
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
170 def _auto_font(self): |
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
171 for font in (font_large, font_medium): |
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
172 h, w = font.size(self.text) |
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
173 if w < self.rect.width and h < self.rect.height: |
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
174 return font |
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
175 return font_small |
ff7c953502d5
Auto-downsize fonts on BigButtons that are too large.
Simon Cross <hodgestar@gmail.com>
parents:
74
diff
changeset
|
176 |
55
86d83dcb7d42
Make text drawing easier to poke at for subclasses
Neil Muller <drnlmuller@gmail.com>
parents:
39
diff
changeset
|
177 def _draw_text(self): |
62
38f41d046c6f
Make button font a parameter. Tweak indication of points to be spent
Neil Muller <drnlmuller@gmail.com>
parents:
55
diff
changeset
|
178 self.font.set_bold(True) |
68
7309392d9ca9
fixed widget drawing bugs
Rizmari Versfeld <rizziepit@gmail.com>
parents:
64
diff
changeset
|
179 self.text_surface = self.font.render(self.text, True, (0, 0, 0)) |
69 | 180 size = self.font.size(self.text) |
62
38f41d046c6f
Make button font a parameter. Tweak indication of points to be spent
Neil Muller <drnlmuller@gmail.com>
parents:
55
diff
changeset
|
181 if self.shadow: |
69 | 182 s = self.font.render(self.text, True, (128, 128, 128)) |
74
22b65c943712
prettified main menu - temp background
Rizmari Versfeld <rizziepit@gmail.com>
parents:
71
diff
changeset
|
183 temp = Surface((s.get_width() + 1, s.get_width() + 1), SRCALPHA) |
71 | 184 temp.fill((255, 255, 255, 0)) |
74
22b65c943712
prettified main menu - temp background
Rizmari Versfeld <rizziepit@gmail.com>
parents:
71
diff
changeset
|
185 temp.blit(s, (1, 1)) |
71 | 186 temp.blit(self.text_surface, (0, 0)) |
187 self.text_surface = temp | |
68
7309392d9ca9
fixed widget drawing bugs
Rizmari Versfeld <rizziepit@gmail.com>
parents:
64
diff
changeset
|
188 size = [s + 2 for s in size] |
55
86d83dcb7d42
Make text drawing easier to poke at for subclasses
Neil Muller <drnlmuller@gmail.com>
parents:
39
diff
changeset
|
189 self.text_offset = ((self.rect[2] - size[0]) / 2, |
86d83dcb7d42
Make text drawing easier to poke at for subclasses
Neil Muller <drnlmuller@gmail.com>
parents:
39
diff
changeset
|
190 (self.rect[3] - size[1]) / 2) |
68
7309392d9ca9
fixed widget drawing bugs
Rizmari Versfeld <rizziepit@gmail.com>
parents:
64
diff
changeset
|
191 self.font.set_bold(False) |
37 | 192 |
38 | 193 def draw(self, surface): |
194 self.surface.fill((0, 0, 0, 0)) | |
195 super(TextButton, self).draw(self.surface) | |
196 self.surface.blit(self.text_surface, self.text_offset) | |
197 surface.blit(self.surface, self.rect) | |
64 | 198 |
199 | |
200 class TextLabel(Drawable): | |
201 | |
202 def __init__(self, rect, text, font, color): | |
203 super(TextLabel, self).__init__(rect) | |
68
7309392d9ca9
fixed widget drawing bugs
Rizmari Versfeld <rizziepit@gmail.com>
parents:
64
diff
changeset
|
204 self.surface = Surface((rect[2], rect[3]), pygame.SRCALPHA) |
64 | 205 self.text = text |
206 self.font = font | |
207 self.color = color | |
208 self._draw_text() | |
209 | |
210 def _draw_text(self): | |
211 self.text_surface = self.font.render(self.text, True, self.color) | |
212 size = self.font.size(self.text) | |
213 # We centre vertically, but start at left edge | |
214 self.text_offset = (0, (self.rect[3] - size[1]) / 2) | |
215 | |
216 def draw(self, surface): | |
217 self.surface.fill((0, 0, 0, 0)) | |
218 super(TextLabel, self).draw(self.surface) | |
219 self.surface.blit(self.text_surface, self.text_offset) | |
220 surface.blit(self.surface, self.rect) | |
113 | 221 |
222 | |
223 class TextBox(TextLabel): | |
224 | |
225 def _draw_text(self): | |
226 self.text_surface = Surface((self.rect[2], self.rect[3]), | |
227 pygame.SRCALPHA) | |
228 current_height = 0 | |
229 current_str = '' | |
230 size = None | |
231 for word in self.text.split(' '): | |
232 size = self.font.size(current_str + word) | |
233 if size[0] < self.rect.width: | |
234 current_str += word + ' ' | |
235 else: | |
236 s = self.font.render(current_str[0:-1], True, self.color) | |
119
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
237 self._resize_text_surface(current_height + size[1]) |
113 | 238 self.text_surface.blit(s, (0, current_height)) |
239 current_height += size[1] | |
240 current_str = word + ' ' | |
241 if current_str[-1] == ' ': | |
242 current_str = current_str[0:-1] | |
243 s = self.font.render(current_str, True, self.color) | |
119
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
244 self._resize_text_surface(current_height + size[1]) |
113 | 245 self.text_surface.blit(s, (0, current_height)) |
246 self.text_offset = (0, 0) | |
247 self.rect.height = current_height + size[1] | |
248 self.surface = Surface((self.rect.width, self.rect.height), | |
249 pygame.SRCALPHA) | |
119
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
250 |
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
251 def _resize_text_surface(self, new_height): |
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
252 """Resize the text surface if needed""" |
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
253 if new_height > self.text_surface.get_rect().height: |
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
254 old_text = self.text_surface |
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
255 self.text_surface = Surface((self.rect[2], new_height), |
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
256 pygame.SRCALPHA) |
9a30162f2a9c
Add more logic around resizing surfaces
Neil Muller <drnlmuller@gmail.com>
parents:
114
diff
changeset
|
257 self.text_surface.blit(old_text, (0, 0)) |