#!/usr/bin/env python from __future__ import division import pygame import sys import time from threading import Thread from math import degrees, cos, sin from src.server import GestureServer from src.window import FullscreenWindow from src.trackers.transform import TransformationTracker from src.trackers.tap import TapTracker from src.screen import screen_size import tests.parse_arguments pygame.init() FULLSCREEN = '-f' in sys.argv[1:] # Config FINGER_RADIUS = 20 CENTROID_RADIUS = 15 W, H = screen_size if 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 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 = [] 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.centroid: c = coord(*transform.centroid.xy) for p in server.points.itervalues(): xy = coord(p.x, p.y) # Draw line to centroid if 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.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() # Create server and fullscreen window server = GestureServer() win = FullscreenWindow(server=server) # Bind trackers def rotate(gesture): global angle angle += gesture.get_angle() def pinch(gesture): global scale scale = min(scale * gesture.get_scale(), MAX_SCALE) transform = TransformationTracker(win) transform.bind('rotate', rotate) transform.bind('pinch', pinch) tap = TapTracker(win) tap.bind('tap', lambda g: taps.append([coord(*g.xy), FINGER_RADIUS])) tap.bind('single_tap', lambda g: dtaps.append(list(coord(*g.xy)) + [1])) tap.bind('double_tap', lambda g: dtaps.append(list(coord(*g.xy)) + [0])) try: # Start touch gesture server in separate thread thread = Thread(target=server.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: server.stop()