comparison pyntnclick/tools/rect_drawer.py @ 854:79b5c1be9a5e default tip

Remove pyntnclick, it's its own library, now
author Stefano Rivera <stefano@rivera.za.net>
date Sat, 21 Jun 2014 22:06:09 +0200
parents f95830b58336
children
comparison
equal deleted inserted replaced
852:f95830b58336 854:79b5c1be9a5e
1 # Quickly hacked together helper for working out
2 # interactive regions in Suspended Sentence
3
4 from pygame.locals import (K_LEFT, K_RIGHT, K_UP, K_DOWN,
5 K_a, K_t, K_d, K_i, K_r, K_o, K_b, K_z,
6 QUIT, MOUSEBUTTONDOWN, MOUSEMOTION,
7 MOUSEBUTTONUP, KEYDOWN)
8 import pygame
9 import os
10
11 import pyntnclick.constants
12 from pyntnclick.i18n import _
13 from pyntnclick.widgets.text import LabelWidget, TextButton
14 from pyntnclick.widgets.base import Container, Button, TranslucentImage
15 from pyntnclick.widgets.filechooser import FileChooser
16 from pyntnclick.utils import draw_rect_image
17
18 DRAW, CYCLE, DELETE, IMAGE = range(4)
19
20
21 class RectDrawerError(Exception):
22 """Raised when initilaization failed"""
23
24
25 class RectDrawerConstants(pyntnclick.constants.GameConstants):
26 debug = True
27 menu_width = 200
28 menu_button_height = 25
29 zoom = 4
30 zoom_step = 100
31
32 constants = RectDrawerConstants()
33
34
35 class ColourButton(Button):
36 """Button for selecting a colour"""
37
38 sel_colour = pygame.color.Color(255, 255, 255)
39 unsel_colour = pygame.color.Color(128, 128, 128)
40
41 padding = 2
42 border = 3
43
44 def __init__(self, rect, gd, colour, palette, size=None):
45 super(ColourButton, self).__init__(rect, gd, size=size)
46 self._colour = pygame.color.Color(colour)
47 self._button_rect = self.rect.inflate(-self.padding, -self.padding)
48 self._colour_rect = self._button_rect.inflate(-self.border,
49 -self.border)
50 self.selected = False
51 self._palette = palette
52 self.add_callback('clicked', self.fix_selection)
53
54 def fix_selection(self, ev, widget):
55 self._palette.cur_selection.selected = False
56 self.selected = True
57 self._palette.cur_selection = self
58
59 def draw(self, surface):
60 if self.visible:
61 self.do_prepare()
62 surface.fill(pygame.color.Color(0, 0, 0), self.rect)
63 if self.selected:
64 surface.fill(self.sel_colour, self._button_rect)
65 else:
66 surface.fill(self.unsel_colour, self._button_rect)
67 surface.fill(self._colour, self._colour_rect)
68
69
70 class AppPalette(Container):
71
72 but_size = 35
73
74 colors = [
75 'red', 'maroon1', 'palevioletred1', 'moccasin', 'orange',
76 'honeydew', 'yellow', 'gold', 'goldenrod', 'brown',
77 'blue', 'purple', 'darkorchid4', 'thistle', 'skyblue1',
78 'green', 'palegreen1', 'darkgreen', 'aquamarine', 'darkolivegreen',
79 ]
80
81 def __init__(self, pos, gd, app_image, size=None):
82 self.image = app_image
83 super(AppPalette, self).__init__(pos, gd, size=size)
84 self.selection = 0
85 self.image.rect_color = pygame.color.Color(self.colors[self.selection])
86
87 x, y = pos
88 for num, col in enumerate(self.colors):
89 if (x - self.rect.left + self.but_size) >= self.rect.width:
90 x = self.rect.left
91 y += self.but_size
92 button = ColourButton((x, y),
93 gd, col, self, size=(self.but_size, self.but_size))
94 x += self.but_size
95 if num == 0:
96 self.cur_selection = button
97 button.fix_selection(None, None)
98 button.add_callback('clicked', self.click_item, num)
99 self.add(button)
100 # Fix height
101 self.rect.height = y + self.but_size - self.rect.top
102
103 def click_item(self, ev, widget, number):
104 self.selection = number
105 self.image.rect_color = pygame.color.Color(self.colors[number])
106
107
108 class AppImage(Container):
109
110 rect_thick = 3
111 draw_thick = 1
112
113 def __init__(self, parent, gd, state, scene, detail):
114 self.state = state
115 super(AppImage, self).__init__((0, 0), gd, size=constants.screen)
116 self.mode = DRAW
117 self._scene = scene
118 self._parent = parent
119 self._detail = detail
120 self.rects = []
121 self.images = []
122 self.start_pos = None
123 self.end_pos = None
124 self.rect_color = pygame.color.Color('white')
125 self.current_image = None
126 self.place_image_menu = None
127 self.close_button = LabelWidget((0, 0), gd, _('Close'))
128 self.close_button.fg_color = (0, 0, 0)
129 self.close_button.bg_color = (0, 0, 0)
130 self.draw_rects = True
131 self.draw_things = True
132 self.draw_thing_rects = True
133 self.draw_images = True
134 self.trans_images = False
135 self.draw_toolbar = True
136 self.old_mouse_pos = None
137 self.zoom_display = False
138 self.draw_anim = False
139 self.zoom_offset = (600, 600)
140 self.clear_display = False
141 self.filechooser = None
142 if self._detail:
143 w, h = self._scene.get_detail_size()
144 rect = pygame.rect.Rect(0, 0, w, h)
145 self.close_button.rect.midbottom = rect.midbottom
146 self.offset = (0, 0)
147 else:
148 self.offset = (-self._scene.OFFSET[0],
149 -self._scene.OFFSET[1])
150 self.find_existing_intersects()
151 self.add_callback(MOUSEBUTTONDOWN, self.mouse_down)
152 self.add_callback(MOUSEBUTTONUP, self.mouse_up)
153 self.add_callback(MOUSEMOTION, self.mouse_move)
154 self.add_callback(KEYDOWN, self.key_down)
155
156 def get_mode_name(self):
157 """Return the translated mode name"""
158 # We do things this way to avoid defining translated strings
159 # at import time
160 if self.mode == DRAW:
161 return _("draw")
162 elif self.mode == CYCLE:
163 return _("cycle")
164 elif self.mode == DELETE:
165 return _("delete")
166 elif self.mode == IMAGE:
167 return _("image")
168 else:
169 raise RuntimeError("Invalid mode")
170
171 def _print_thing(self, thing, interact_name):
172 """Helper to avoid repeated translations"""
173 print (_("Thing %(thing)s Interact %(interact)s") %
174 {'thing': thing.name, 'interact': interact_name})
175
176 def _print_rects(self, rect1, rect2):
177 """Helper to avoid repeated translations"""
178 print _(" Rects"), rect1, rect2
179
180 def find_existing_intersects(self):
181 """Parse the things in the scene for overlaps"""
182 scene = self._scene
183 # Pylint hates this function
184 for thing in scene.things.itervalues():
185 for interact_name in thing.interacts:
186 thing._set_interact(interact_name)
187 if hasattr(thing.rect, 'collidepoint'):
188 thing_rects = [thing.rect]
189 else:
190 thing_rects = thing.rect
191 for thing2 in scene.things.itervalues():
192 if thing is thing2:
193 continue
194 for interact2_name in thing2.interacts:
195 thing2._set_interact(interact2_name)
196 if hasattr(thing2.rect, 'collidepoint'):
197 thing2_rects = [thing2.rect]
198 else:
199 thing2_rects = thing2.rect
200 for my_rect in thing_rects:
201 for other_rect in thing2_rects:
202 if my_rect.colliderect(other_rect):
203 print _('Existing Intersecting rects')
204 self._print_thing(thing, interact_name)
205 self._print_thing(thing2, interact2_name)
206 self._print_rects(my_rect, other_rect)
207 print
208
209 def find_intersecting_rects(self, d):
210 """Find if any rect collections intersect"""
211 # I loath N^X brute search algorithms, but whatever, hey
212 scene = self._scene
213 for (num, col) in enumerate(d):
214 rect_list = d[col]
215 for thing in scene.things.itervalues():
216 for interact_name in thing.interacts:
217 thing._set_interact(interact_name)
218 if hasattr(thing.rect, 'collidepoint'):
219 thing_rects = [thing.rect]
220 else:
221 thing_rects = thing.rect
222 for other_rect in thing_rects:
223 for my_rect in rect_list:
224 if my_rect.colliderect(other_rect):
225 print _('Intersecting rects')
226 print _(" Object %s") % num
227 self._print_thing(thing, interact_name)
228 self._print_rects(my_rect, other_rect)
229 if thing.INITIAL:
230 thing._set_interact(thing.INITIAL)
231 print
232 for (num2, col2) in enumerate(d):
233 if num2 == num:
234 continue
235 other_list = d[col2]
236 for my_rect in rect_list:
237 for other_rect in other_list:
238 if my_rect.colliderect(other_rect):
239 print _('Intersecting rects'),
240 print (_(' Object %(object1)s and %(object2)s') %
241 {'object1': num, 'object2': num2})
242 self._print_rects(my_rect, other_rect)
243 print
244 print
245
246 def toggle_things(self, ev, widget):
247 self.draw_things = not self.draw_things
248
249 def toggle_thing_rects(self, ev, widget):
250 self.draw_thing_rects = not self.draw_thing_rects
251 scene = self._scene
252 for thing in scene.things.itervalues():
253 if not self.draw_thing_rects:
254 if not hasattr(thing, 'old_colour'):
255 thing.old_colour = thing._interact_hilight_color
256 thing._interact_hilight_color = None
257 else:
258 thing._interact_hilight_color = thing.old_colour
259
260 def toggle_images(self, ev, widget):
261 self.draw_images = not self.draw_images
262 for image in self.images:
263 image.set_visible(self.draw_images)
264 if self.current_image:
265 self.current_image.set_visible(self.draw_images)
266 self.invalidate()
267
268 def toggle_trans_images(self, ev, widget):
269 self.trans_images = not self.trans_images
270 for image in self.images:
271 image.translucent = self.trans_images
272 if self.current_image:
273 self.current_image.translucent = self.trans_images
274 self.invalidate()
275
276 def toggle_rects(self, ev, widget):
277 self.draw_rects = not self.draw_rects
278
279 def toggle_toolbar(self, ev, widget):
280 self.draw_toolbar = not self.draw_toolbar
281
282 def toggle_zoom(self, ev, widget):
283 self.zoom_display = not self.zoom_display
284 self.invalidate()
285
286 def toggle_anim(self, ev, widget):
287 self.draw_anim = not self.draw_anim
288
289 def draw_mode(self, ev, widget):
290 self.mode = DRAW
291
292 def del_mode(self, ev, widget):
293 self.mode = DELETE
294 self.start_pos = None
295 self.end_pos = None
296
297 def invalidate(self):
298 self.clear_display = True
299
300 def draw(self, surface):
301 if not self.visible:
302 return
303 self.do_prepare()
304 if self.clear_display:
305 surface.fill(pygame.color.Color(0, 0, 0),
306 pygame.Rect(0, 0, constants.screen[0],
307 constants.screen[1]))
308 self.clear_display = False
309
310 if self.zoom_display:
311 base_surface = surface.copy()
312 self.do_unzoomed_draw(base_surface)
313 zoomed = pygame.transform.scale(base_surface,
314 (constants.zoom * base_surface.get_width(),
315 constants.zoom * base_surface.get_height()))
316 area = pygame.rect.Rect(self.zoom_offset[0], self.zoom_offset[1],
317 constants.screen[0], constants.screen[1])
318 surface.blit(zoomed, (0, 0), area)
319 else:
320 self.do_unzoomed_draw(surface)
321
322 def do_unzoomed_draw(self, surface):
323 if self.draw_things:
324 self._scene.draw(surface)
325 else:
326 self._scene.draw_background(surface)
327 if self._detail:
328 # We duplicate draw logic here, so we zoom the close
329 # button correctly
330 self.close_button.draw(surface)
331 if self.mode == DRAW and self.start_pos and self.draw_rects:
332 rect = pygame.rect.Rect(self.start_pos[0], self.start_pos[1],
333 self.end_pos[0] - self.start_pos[0],
334 self.end_pos[1] - self.start_pos[1])
335 rect.normalize()
336 draw_rect_image(surface, self.rect_color, rect, self.draw_thick)
337 if self.draw_rects:
338 for (col, rect) in self.rects:
339 draw_rect_image(surface, col, rect, self.rect_thick)
340 for image in self.images:
341 image.draw(surface)
342 if self.current_image and self.mode == IMAGE:
343 self.current_image.draw(surface)
344 if self.draw_toolbar:
345 tb_surf = surface.subsurface(0, constants.screen[1]
346 - constants.button_size,
347 constants.screen[0],
348 constants.button_size).convert_alpha()
349 tb_surf.fill(pygame.color.Color(127, 0, 0, 191))
350 surface.blit(tb_surf, (0, constants.screen[1]
351 - constants.button_size))
352
353 def _make_dict(self):
354 d = {}
355 for col, rect in self.rects:
356 col = (col.r, col.g, col.b)
357 d.setdefault(col, [])
358 d[col].append(rect)
359 return d
360
361 def print_objs(self, ev, widget):
362 d = self._make_dict()
363 self.find_intersecting_rects(d)
364 for (num, col) in enumerate(d):
365 print _('Rect %d : ') % num
366 for rect in d[col]:
367 r = rect.move(self.offset)
368 print ' (%d, %d, %d, %d),' % (r.x, r.y, r.w, r.h)
369 print
370 for i, image in enumerate(self.images):
371 print _('Image %d') % i
372 rect = image.rect
373 r = rect.move(self.offset)
374 print ' (%d, %d, %d, %d),' % (r.x, r.y, r.w, r.h)
375 print
376 print
377
378 def image_load(self, ev, widget):
379 if self.filechooser is None:
380 self.filechooser = FileChooser((0, 0), self.gd, None, os.curdir,
381 self.do_load_image)
382 else:
383 self.filechooser.refresh()
384 self.invalidate()
385 self._parent.paused = True
386 self._parent.add(self.filechooser)
387
388 def do_load_image(self, filename):
389 try:
390 self.current_image = TranslucentImage((0, 0), self.gd,
391 pygame.image.load(filename))
392 if not self.draw_images:
393 # Selecting an image makes image visible
394 self.toggle_images(None, None)
395 self.current_image.translucent = self.trans_images
396 self.place_image_menu.enabled = True
397 self.current_image.rect = self.current_image.rect.move(
398 constants.screen[0] + constants.menu_width,
399 constants.screen[1])
400 self.image_mode(None, None)
401 except pygame.error, e:
402 print 'Unable to load image %s (reason %s)' % (filename, e)
403
404 def image_mode(self, ev, widget):
405 self.mode = IMAGE
406 self.start_pos = None
407 self.end_pos = None
408 # So we do the right thing for off screen images
409 self.old_mouse_pos = None
410
411 def cycle_mode(self, ev, widget):
412 self.mode = CYCLE
413
414 def _conv_pos(self, mouse_pos):
415 if self.zoom_display:
416 pos = ((mouse_pos[0] + self.zoom_offset[0]) / constants.zoom,
417 (mouse_pos[1] + self.zoom_offset[1]) / constants.zoom)
418 else:
419 pos = mouse_pos
420 return pos
421
422 def _check_limits(self, offset):
423 if offset[0] < 0:
424 offset[0] = 0
425 if offset[1] < 0:
426 offset[1] = 0
427 width, height = constants.screen
428 if offset[0] > constants.zoom * width - width:
429 offset[0] = constants.zoom * width - width
430 if offset[1] > constants.zoom * height - height:
431 offset[1] = constants.zoom * height - height
432
433 def _make_zoom_offset(self, pos):
434 zoom_pos = (pos[0] * constants.zoom, pos[1] * constants.zoom)
435 offset = [zoom_pos[0] - constants.screen[0] / 2,
436 zoom_pos[1] - constants.screen[1] / 2]
437 self._check_limits(offset)
438 self.zoom_offset = tuple(offset)
439
440 def _move_zoom(self, x, y):
441 offset = list(self.zoom_offset)
442 offset[0] += constants.zoom_step * x
443 offset[1] += constants.zoom_step * y
444 self._check_limits(offset)
445 self.zoom_offset = tuple(offset)
446
447 def key_down(self, ev, widget):
448 if self.mode == IMAGE and self.current_image:
449 # Move the image by 1 pixel
450 cur_pos = self.current_image.rect.center
451 if ev.key == K_LEFT:
452 self.current_image.rect.center = (cur_pos[0] - 1, cur_pos[1])
453 elif ev.key == K_RIGHT:
454 self.current_image.rect.center = (cur_pos[0] + 1, cur_pos[1])
455 elif ev.key == K_UP:
456 self.current_image.rect.center = (cur_pos[0], cur_pos[1] - 1)
457 elif ev.key == K_DOWN:
458 self.current_image.rect.center = (cur_pos[0], cur_pos[1] + 1)
459 elif self.zoom_display:
460 if ev.key == K_LEFT:
461 self._move_zoom(-1, 0)
462 elif ev.key == K_RIGHT:
463 self._move_zoom(1, 0)
464 elif ev.key == K_UP:
465 self._move_zoom(0, -1)
466 elif ev.key == K_DOWN:
467 self._move_zoom(0, 1)
468
469 if ev.key == K_o:
470 self.toggle_trans_images(None, None)
471 elif ev.key == K_t:
472 self.toggle_things(None, None)
473 elif ev.key == K_r:
474 self.toggle_thing_rects(None, None)
475 elif ev.key == K_i:
476 self.toggle_images(None, None)
477 elif ev.key == K_d:
478 self.toggle_rects(None, None)
479 elif ev.key == K_b:
480 self.toggle_toolbar(None, None)
481 elif ev.key == K_z:
482 self.toggle_zoom(None, None)
483 elif ev.key == K_a:
484 self.toggle_anim(None, None)
485
486 def mouse_down(self, ev, widget):
487 pos = self._conv_pos(ev.pos)
488 if self._parent.paused:
489 # Ignore this if the filechooser is active
490 return False
491 if self.mode == DELETE:
492 cand = None
493 # Images are drawn above rectangles, so search those first
494 for image in self.images:
495 if image.rect.collidepoint(pos):
496 cand = image
497 break
498 if cand:
499 self.images.remove(cand)
500 self.invalidate()
501 return
502 for (col, rect) in self.rects:
503 if rect.collidepoint(pos):
504 cand = (col, rect)
505 break
506 if cand:
507 self.rects.remove(cand)
508 self.invalidate()
509 elif self.mode == CYCLE:
510 scene = self._scene
511 cand = None
512 for thing in scene.things.itervalues():
513 if thing.contains(pos):
514 cand = thing
515 break
516 if cand:
517 # Find current interacts in this thing
518 cur_interact = cand.current_interact
519 j = cand.interacts.values().index(cur_interact)
520 if j + 1 < len(cand.interacts):
521 next_name = cand.interacts.keys()[j + 1]
522 else:
523 next_name = cand.interacts.keys()[0]
524 if cand.interacts[next_name] != cur_interact:
525 cand._set_interact(next_name)
526 elif self.mode == DRAW:
527 self.start_pos = pos
528 self.end_pos = pos
529 elif self.mode == IMAGE:
530 if self.current_image:
531 self.images.append(self.current_image)
532 self.current_image = None
533 self.old_mouse_pos = None
534 self.invalidate()
535 else:
536 cand = None
537 for image in self.images:
538 if image.rect.collidepoint(pos):
539 cand = image
540 break
541 if cand:
542 self.images.remove(cand)
543 self.current_image = cand
544 # We want to move relative to the current mouse pos, so
545 self.old_mouse_pos = pos
546 self.invalidate()
547
548 def mouse_up(self, ev, widget):
549 if self._parent.paused:
550 return False
551 if self.mode == DRAW:
552 if self.start_pos is None:
553 # We've come here not via a drawing situation, so bail
554 return False
555 rect = pygame.rect.Rect(self.start_pos[0], self.start_pos[1],
556 self.end_pos[0] - self.start_pos[0],
557 self.end_pos[1] - self.start_pos[1])
558 rect.normalize()
559 self.rects.append((self.rect_color, rect))
560 self.start_pos = self.end_pos = None
561
562 def mouse_move(self, ev, widget):
563 # We're only interested in this if left mouse button is down or we've
564 # got and image
565 if self.mode == IMAGE and self.current_image:
566 pos = self._conv_pos(ev.pos)
567 if self.old_mouse_pos:
568 delta = (pos[0] - self.old_mouse_pos[0],
569 pos[1] - self.old_mouse_pos[1])
570 self.current_image.rect.center = (
571 self.current_image.rect.center[0] + delta[0],
572 self.current_image.rect.center[1] + delta[1])
573 else:
574 self.current_image.rect.center = pos
575 self.invalidate()
576 self.old_mouse_pos = pos
577 return True
578 elif ev.buttons[0] == 1 and self.mode == DRAW:
579 self.end_pos = self._conv_pos(ev.pos)
580 return True
581 return False
582
583 def animate(self):
584 if self.draw_anim:
585 self._scene.animate()
586
587
588 class ModeLabel(LabelWidget):
589
590 def __init__(self, pos, gd, app_image, size=None):
591 self.app_image = app_image
592 super(ModeLabel, self).__init__(pos,
593 gd, _('Mode : '), fontname=constants.bold_font,
594 fontsize=15, color=pygame.color.Color(128, 0, 255),
595 size=size)
596 self.start_rect = self.rect.copy()
597
598 def draw(self, surface):
599 self.do_prepare()
600 text = _('Mode : %s') % self.app_image.get_mode_name()
601 if self.text != text:
602 self.text = text
603 self.is_prepared = False
604 self.rect = self.start_rect.copy()
605 self.do_prepare()
606 super(ModeLabel, self).draw(surface)
607
608
609 def make_button(text, gd, action, ypos):
610 rect = pygame.rect.Rect(0, 0, constants.menu_width,
611 constants.menu_button_height)
612 rect.move_ip(805, ypos)
613 button = TextButton(rect.topleft, gd, text, size=(constants.menu_width,
614 constants.menu_button_height),
615 fontname=constants.font, fontsize=12,
616 color=pygame.color.Color(255, 255, 0), border=1, padding=3)
617 button.add_callback('clicked', action)
618 return button
619
620
621 class RectApp(Container):
622 """The actual rect drawer main app"""
623 def __init__(self, rect, gd, detail):
624 super(RectApp, self).__init__(rect, gd)
625
626 try:
627 state = gd.initial_state()
628 scene = state.scenes[gd._initial_scene]
629 except KeyError:
630 raise RectDrawerError(_('Invalid scene: %s') % gd._initial_scene)
631 gd.sound.disable_sound() # No sound here
632
633 if detail:
634 try:
635 scene = state.detail_views[detail]
636 except KeyError:
637 raise RectDrawerError(_('Invalid detail: %s') % detail)
638
639 self.paused = False
640
641 self.image = AppImage(self, gd, state, scene, detail is not None)
642 self.add(self.image)
643 mode_label = ModeLabel((805, 0), self.gd, self.image, size=(200, 50))
644 self.add(mode_label)
645 y = mode_label.rect.height
646 draw = make_button(_('Draw Rect'), gd, self.image.draw_mode, y)
647 self.add(draw)
648 y += draw.rect.height
649 load_image = make_button(_("Load image"), gd, self.image.image_load, y)
650 self.add(load_image)
651 y += load_image.rect.height
652 add_image = make_button(_("Place/Move images"), gd,
653 self.image.image_mode, y)
654 add_image.enabled = False
655 self.add(add_image)
656 self.image.place_image_menu = add_image
657 y += add_image.rect.height
658 cycle = make_button(_("Cycle interacts"), gd, self.image.cycle_mode, y)
659 self.add(cycle)
660 y += cycle.rect.height
661 delete = make_button(_("Delete Objects"), gd, self.image.del_mode, y)
662 self.add(delete)
663 y += delete.rect.height
664 palette = AppPalette((810, y), gd, self.image, size=(200, 0))
665 self.add(palette)
666 y += palette.rect.height
667 print_rects = make_button(_("Print objects"), gd,
668 self.image.print_objs, y)
669 self.add(print_rects)
670 y += print_rects.rect.height
671 toggle_things = make_button(_("Show Things (t)"), gd,
672 self.image.toggle_things, y)
673 self.add(toggle_things)
674 y += toggle_things.rect.height
675 toggle_thing_rects = make_button(_("Show Thing Rects (r)"), gd,
676 self.image.toggle_thing_rects, y)
677 self.add(toggle_thing_rects)
678 y += toggle_thing_rects.rect.height
679 toggle_images = make_button(_("Show Images (i)"), gd,
680 self.image.toggle_images, y)
681 self.add(toggle_images)
682 y += toggle_images.rect.height
683 trans_images = make_button(_("Opaque Images (o)"), gd,
684 self.image.toggle_trans_images, y)
685 self.add(trans_images)
686 y += trans_images.rect.height
687 toggle_rects = make_button(_("Show Drawn Rects (d)"), gd,
688 self.image.toggle_rects, y)
689 self.add(toggle_rects)
690 y += toggle_rects.rect.height
691 toggle_toolbar = make_button(_("Show Toolbar (b)"), gd,
692 self.image.toggle_toolbar, y)
693 self.add(toggle_toolbar)
694 y += toggle_toolbar.rect.height
695 toggle_anim = make_button(_("Show Animations (a)"), gd,
696 self.image.toggle_anim, y)
697 self.add(toggle_anim)
698 y += toggle_anim.rect.height
699 toggle_zoom = make_button(_("Zoom (z)"), gd,
700 self.image.toggle_zoom, y)
701 self.add(toggle_zoom)
702 y += toggle_zoom.rect.height
703 quit_but = make_button(_("Quit"), gd, self.quit, 570)
704 self.add(quit_but)
705
706 def quit(self, ev, widget):
707 pygame.event.post(pygame.event.Event(QUIT))
708
709 def animate(self):
710 self.image.animate()
711
712
713 class RectEngine(object):
714 """Engine for the rect drawer."""
715
716 def __init__(self, gd, detail):
717 self.state = None
718 self._gd = gd
719 rect = pygame.display.get_surface().get_rect()
720 self.app = RectApp(rect.topleft, self._gd, detail)
721
722 def run(self):
723 """App loop"""
724 clock = pygame.time.Clock()
725 while True:
726 events = pygame.event.get()
727 for ev in events:
728 if ev.type == QUIT:
729 return
730 else:
731 self.app.event(ev)
732 self.app.animate()
733 surface = pygame.display.get_surface()
734 self.app.draw(surface)
735 pygame.display.flip()
736 clock.tick(self._gd.constants.frame_rate)
737
738
739 def make_rect_display():
740 pygame.display.init()
741 pygame.font.init()
742 pygame.display.set_mode((constants.screen[0]
743 + constants.menu_width, constants.screen[1]))