lambda g: #!/usr/bin/env python from __future__ import division import pygame from threading import Thread from math import degrees from src import FullscreenArea, create_driver from src.screen import screen_size from parse_arguments import create_parser, parse_args # Parse arguments parser = create_parser() parser.add_argument('-f', '--fullscreen', action='store_true', default=False, help='run in fullscreen') args = parse_args(parser) pygame.init() # Config FINGER_RADIUS = 20 CENTROID_RADIUS = 15 W, H = screen_size if args.fullscreen else (640, 480) BG_COLOR = 0, 0, 0 LINE_COLOR = 128, 128, 128 CIRCLE_COLOR = 255, 255, 255 RECT_COLOR = 0, 200, 0 RECT_POS = W / 2, H / 2 RECT_SIZE = W / 6., H / 6. TAP_RADIUS = 65 TAP_INCREMENT = .3 BEAM_COLOR = 255, 50, 50 BEAM_LENGTH = 50 BEAM_WIDTH = 3 BEAM_INCREMENT = .8 MAX_SCALE = 10 # Create canvas GUI flags = pygame.FULLSCREEN if args.fullscreen else 0 screen = pygame.display.set_mode((W, H), flags) def coord(x, y): w, h = screen_size return int(round(W / w * x)), int(round(H / h * y)) # Global state angle = 0 scale = 1 taps = [] dtaps = [] points = [] def update(): global taps, dtaps # Clear previous frame screen.fill(BG_COLOR) # Apply scale and rotation to a fixed-size rectangle canvas canvas = pygame.Surface(RECT_SIZE) canvas.fill(RECT_COLOR) transformed = pygame.transform.rotozoom(canvas, degrees(angle), scale) rect = transformed.get_rect() rect.center = W / 2, H / 2 screen.blit(transformed, rect) # Draw touch points if transform and transform.centroid: c = coord(*transform.centroid) for p in points: xy = coord(p.x, p.y) # Draw line to centroid if transform and transform.centroid: pygame.draw.line(screen, LINE_COLOR, xy, c, 1) # Draw outlined circle around touch point pygame.draw.circle(screen, CIRCLE_COLOR, xy, FINGER_RADIUS, 1) # Fill filled circle with background color within the outline pygame.draw.circle(screen, BG_COLOR, xy, FINGER_RADIUS - 1, 0) # Draw filled circle around centroid if transform and transform.centroid: pygame.draw.circle(screen, CIRCLE_COLOR, c, CENTROID_RADIUS) # Draw an expanding circle around each tap event taps = filter(lambda (xy, r): r <= TAP_RADIUS, taps) for tap in taps: xy, radius = tap pygame.draw.circle(screen, CIRCLE_COLOR, xy, int(radius), 2) # Increment radius tap[1] += TAP_INCREMENT # Shoot a beam from each double tap event to the left dtaps = filter(lambda (x, y, s): 0 <= x <= W, dtaps) for dtap in dtaps: x, y, single = dtap if single: start_x = x end_x = x + BEAM_LENGTH dtap[0] += BEAM_INCREMENT else: start_x = x - BEAM_LENGTH end_x = x dtap[0] -= BEAM_INCREMENT pygame.draw.line(screen, BEAM_COLOR, (start_x, y), (end_x, y), BEAM_WIDTH) # Update canvas pygame.display.flip() transform = None def save_tracker(gesture): global transform if not transform: transform = gesture.get_tracker() def rotate(gesture): global angle angle += gesture.get_angle() save_tracker(gesture) def pinch(gesture): global scale scale = min(scale * gesture.get_scale(), MAX_SCALE) save_tracker(gesture) area = FullscreenArea() driver = create_driver(area) area.on_rotate(rotate) area.on_pinch(pinch) area.on_tap(lambda g: taps.append([coord(*g), FINGER_RADIUS])) area.on_single_tap(lambda g: dtaps.append(list(coord(*g)) + [1])) area.on_double_tap(lambda g: dtaps.append(list(coord(*g)) + [0])) area.on_point_down(lambda g: points.append(g.get_event().point)) area.on_point_up(lambda g: points.remove(g.get_event().point)) try: # Start touch gesture server in separate thread thread = Thread(target=driver.start) thread.daemon = True thread.start() # Start GUI event loop def is_quit_event(e): return e.type == pygame.QUIT \ or (e.type == pygame.KEYDOWN and e.key == ord('q')) while not any(filter(is_quit_event, pygame.event.get())): update() except KeyboardInterrupt: pass finally: driver.stop()