draw.py 4.1 KB

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