| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- import time
- from threading import Thread
- from ..tracker import GestureTracker
- from ..geometry import Positionable
- from utils import PointGesture
- class TapTracker(GestureTracker):
- __gesture_types__ = ['tap', 'single_tap', 'double_tap']
- __configurable__ = ['tap_distance', 'tap_time', 'double_tap_time',
- 'double_tap_distance', 'update_rate']
- def __init__(self, window=None):
- super(TapTracker, self).__init__(window)
- # Map of TUIO session id to tuple (timestamp, position) of point down
- self.reg = {}
- # Maximum radius in which a touch point can move in order to be a tap
- # event in pixels
- self.tap_distance = 20
- # Maximum time between 'down' and 'up' of a tap event in seconds
- self.tap_time = .2
- # Maximum time in seconds and distance in pixels between two taps to
- # count as double tap
- self.double_tap_time = .3
- self.double_tap_distance = 30
- # Times per second to detect single taps
- self.update_rate = 30
- self.reset_last_tap()
- self.single_tap_thread = Thread(target=self.detect_single_tap)
- self.single_tap_thread.daemon = True
- self.single_tap_thread.start()
- def detect_single_tap(self):
- """
- Iteration function for single-tap detection thread.
- """
- while True:
- time_diff = time.time() - self.last_tap_time
- if self.last_tap and time_diff > self.double_tap_time:
- # Last tap is too long ago to be a double tap, so trigger a
- # single tap
- self.trigger(SingleTapGesture(self.last_tap))
- self.reset_last_tap()
- time.sleep(1. / self.update_rate)
- def reset_last_tap(self):
- self.last_tap_time = 0
- self.last_tap = None
- def on_point_down(self, point):
- x, y = point.get_position()
- self.reg[point.sid] = time.time(), Positionable(x, y)
- def on_point_move(self, point):
- if point.sid not in self.reg:
- return
- # If a stationary point moves beyond a threshold, delete it so that the
- # 'up' event will not trigger a 'tap'
- t, initial_position = self.reg[point.sid]
- if point.distance_to(initial_position) > self.tap_distance:
- del self.reg[point.sid]
- def on_point_up(self, point):
- # Assert that the point has not been deleted by a 'move' event yet
- if point.sid not in self.reg:
- return
- down_time = self.reg[point.sid][0]
- del self.reg[point.sid]
- # Only trigger a tap event if the 'up' is triggered within a certain
- # time afer the 'down'
- current_time = time.time()
- if current_time - down_time > self.tap_time:
- return
- tap = TapGesture(point)
- self.trigger(tap)
- # Trigger double tap if the threshold has not not expired yet
- if self.last_tap:
- if self.last_tap.distance_to(tap) <= self.double_tap_distance:
- # Close enough to be a double tap
- self.trigger(DoubleTapGesture(self.last_tap))
- self.reset_last_tap()
- return
- # Generate a seperate single tap gesture for the last tap,
- # because the lat tap variable is overwritten now
- self.trigger(SingleTapGesture(self.last_tap))
- self.last_tap_time = current_time
- self.last_tap = tap
- class TapGesture(PointGesture):
- """
- A tap gesture is triggered
- """
- __type__ = 'tap'
- class SingleTapGesture(TapGesture):
- """
- A single tap gesture is triggered after a regular tap gesture, if no double
- tap is triggered for that gesture.
- """
- __type__ = 'single_tap'
- class DoubleTapGesture(TapGesture):
- """
- A double tap gesture is triggered if two sequential taps are triggered
- within a certain time and distance of eachother.
- """
- __type__ = 'double_tap'
|