draw.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/env python
  2. from __future__ import division
  3. import pygame
  4. from threading import Thread
  5. from math import degrees
  6. from src.server import GestureServer
  7. from src.window import FullscreenWindow
  8. from src.trackers.transform import TransformationTracker
  9. from src.trackers.tap import TapTracker
  10. from src.screen import screen_size
  11. from tests.parse_arguments import create_parser, parse_args
  12. parser = create_parser()
  13. parser.add_argument('-f', '--fullscreen', action='store_true', default=False,
  14. help='run in fullscreen')
  15. args = parse_args(parser)
  16. pygame.init()
  17. # Config
  18. FINGER_RADIUS = 20
  19. CENTROID_RADIUS = 15
  20. W, H = screen_size if args.fullscreen else (640, 480)
  21. BG_COLOR = 0, 0, 0
  22. LINE_COLOR = 128, 128, 128
  23. CIRCLE_COLOR = 255, 255, 255
  24. RECT_COLOR = 0, 200, 0
  25. RECT_POS = W / 2, H / 2
  26. RECT_SIZE = W / 6., H / 6.
  27. TAP_RADIUS = 65
  28. TAP_INCREMENT = .3
  29. BEAM_COLOR = 255, 50, 50
  30. BEAM_LENGTH = 50
  31. BEAM_WIDTH = 3
  32. BEAM_INCREMENT = .8
  33. MAX_SCALE = 10
  34. # Create canvas GUI
  35. flags = pygame.FULLSCREEN if args.fullscreen else 0
  36. screen = pygame.display.set_mode((W, H), flags)
  37. def coord(x, y):
  38. w, h = screen_size
  39. return int(round(W / w * x)), int(round(H / h * y))
  40. # Global state
  41. angle = 0
  42. scale = 1
  43. taps = []
  44. dtaps = []
  45. def update():
  46. global taps, dtaps
  47. # Clear previous frame
  48. screen.fill(BG_COLOR)
  49. # Apply scale and rotation to a fixed-size rectangle canvas
  50. canvas = pygame.Surface(RECT_SIZE)
  51. canvas.fill(RECT_COLOR)
  52. transformed = pygame.transform.rotozoom(canvas, degrees(angle), scale)
  53. rect = transformed.get_rect()
  54. rect.center = W / 2, H / 2
  55. screen.blit(transformed, rect)
  56. # Draw touch points
  57. if transform.centroid:
  58. c = coord(*transform.centroid.xy)
  59. for p in server.points.itervalues():
  60. xy = coord(p.x, p.y)
  61. # Draw line to centroid
  62. if transform.centroid:
  63. pygame.draw.line(screen, LINE_COLOR, xy, c, 1)
  64. # Draw outlined circle around touch point
  65. pygame.draw.circle(screen, CIRCLE_COLOR, xy, FINGER_RADIUS, 1)
  66. # Fill filled circle with background color within the outline
  67. pygame.draw.circle(screen, BG_COLOR, xy, FINGER_RADIUS - 1, 0)
  68. # Draw filled circle around centroid
  69. if transform.centroid:
  70. pygame.draw.circle(screen, CIRCLE_COLOR, c, CENTROID_RADIUS)
  71. # Draw an expanding circle around each tap event
  72. taps = filter(lambda (xy, r): r <= TAP_RADIUS, taps)
  73. for tap in taps:
  74. xy, radius = tap
  75. pygame.draw.circle(screen, CIRCLE_COLOR, xy, int(radius), 2)
  76. # Increment radius
  77. tap[1] += TAP_INCREMENT
  78. # Shoot a beam from each double tap event to the left
  79. dtaps = filter(lambda (x, y, s): 0 <= x <= W, dtaps)
  80. for dtap in dtaps:
  81. x, y, single = dtap
  82. if single:
  83. start_x = x
  84. end_x = x + BEAM_LENGTH
  85. dtap[0] += BEAM_INCREMENT
  86. else:
  87. start_x = x - BEAM_LENGTH
  88. end_x = x
  89. dtap[0] -= BEAM_INCREMENT
  90. pygame.draw.line(screen, BEAM_COLOR, (start_x, y), (end_x, y), BEAM_WIDTH)
  91. # Update canvas
  92. pygame.display.flip()
  93. # Create server and fullscreen window
  94. server = GestureServer()
  95. win = FullscreenWindow(server=server)
  96. # Bind trackers
  97. def rotate(gesture):
  98. global angle
  99. angle += gesture.get_angle()
  100. def pinch(gesture):
  101. global scale
  102. scale = min(scale * gesture.get_scale(), MAX_SCALE)
  103. transform = TransformationTracker(win)
  104. transform.rotate(rotate)
  105. transform.pinch(pinch)
  106. tap = TapTracker(win)
  107. tap.tap(lambda g: taps.append([coord(*g.xy), FINGER_RADIUS]))
  108. tap.single_tap(lambda g: dtaps.append(list(coord(*g.xy)) + [1]))
  109. tap.double_tap(lambda g: dtaps.append(list(coord(*g.xy)) + [0]))
  110. try:
  111. # Start touch gesture server in separate thread
  112. thread = Thread(target=server.start)
  113. thread.daemon = True
  114. thread.start()
  115. # Start GUI event loop
  116. def is_quit_event(e):
  117. return e.type == pygame.QUIT \
  118. or (e.type == pygame.KEYDOWN and e.key == ord('q'))
  119. while not any(filter(is_quit_event, pygame.event.get())):
  120. update()
  121. except KeyboardInterrupt:
  122. pass
  123. finally:
  124. server.stop()