draw.py 3.6 KB

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