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.gesture_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()