Skip to content

Commit a72211b

Browse files
committed
Merge remote-tracking branch 'origin/master' into removelibs
2 parents c74df63 + b796680 commit a72211b

16 files changed

+2108
-668
lines changed

.gitignore

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,26 @@
66
*.egg-info
77
*.wpr
88
*.wpu
9-
.DS_Store
10-
.gitignore~
11-
.gitignore
9+
*~
1210

1311
#files
1412
Leap.py
1513

16-
1714
#directories
1815
.idea
19-
20-
#other
21-
dist
16+
bin
2217
build
18+
develop-eggs
19+
dist
2320
eggs
21+
lib
22+
lib64
2423
parts
25-
bin
26-
var
2724
sdist
28-
develop-eggs
25+
var
26+
27+
#other
28+
.DS_Store
29+
.cleanup.sh
2930
.installed.cfg
30-
lib
31-
lib64
3231
pip-log.txt

FingerControl.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,18 @@
44

55

66
import math
7-
import sys
8-
if sys.platform == "darwin":
9-
import OSX.Leap as Leap
10-
else:
11-
import Windows.Leap as Leap
12-
import Geometry
7+
from leap import Leap, Mouse
138
from MiscFunctions import *
149

1510

1611
class Finger_Control_Listener(Leap.Listener): #The Listener that we attach to the controller. This listener is for pointer finger movement
17-
def __init__(self, cursor):
12+
def __init__(self, mouse, smooth_aggressiveness=8, smooth_falloff=1.3):
1813
super(Finger_Control_Listener, self).__init__() #Initialize like a normal listener
1914
#Initialize a bunch of stuff specific to this implementation
2015
self.screen = None
2116
self.screen_resolution = (0,0)
22-
self.cursor = cursor #The cursor object that lets us control mice cross-platform
17+
self.cursor = mouse.absolute_cursor() #The cursor object that lets us control mice cross-platform
18+
self.mouse_position_smoother = mouse_position_smoother(smooth_aggressiveness, smooth_falloff) #Keeps the cursor from fidgeting
2319
self.mouse_button_debouncer = debouncer(5) #A signal debouncer that ensures a reliable, non-jumpy click
2420
self.most_recent_pointer_finger_id = None #This holds the ID of the most recently used pointing finger, to prevent annoying switching
2521

@@ -77,6 +73,7 @@ def do_mouse_stuff(self, hand): #Take a hand and use it as a mouse
7773
if not math.isnan(intersection.x) and not math.isnan(intersection.y): #If the finger intersects with the screen
7874
x_coord = intersection.x * self.screen_resolution[0] #x pixel of intersection
7975
y_coord = (1.0 - intersection.y) * self.screen_resolution[1] #y pixel of intersection
76+
x_coord,y_coord = self.mouse_position_smoother.update((x_coord,y_coord)) #Smooth movement
8077
self.cursor.move(x_coord,y_coord) #Move the cursor
8178
if has_thumb(hand): #We've found a thumb!
8279
self.mouse_button_debouncer.signal(True) #We have detected a possible click. The debouncer ensures that we don't have click jitter

Geometry.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@
33

44

55
import math
6-
import sys
7-
if sys.platform == "darwin":
8-
import OSX.Leap as Leap
9-
else:
10-
import Windows.Leap as Leap
6+
from leap import Leap
117

128

139
def to_vector(leap_vector):

LICENSE.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Copyright (c) 2012, William Yager
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5+
6+
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7+
Redistribution of this software in binary form or as source code as part of a software package that is non-free or closed-source is forbidden without express written consent of the author.
8+
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Linux/Leap.py

Lines changed: 1074 additions & 0 deletions
Large diffs are not rendered by default.

Linux/Mouse.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
from pymouse import PyMouse
2+
mouse = PyMouse()
3+
4+
def AbsoluteMouseMove(posx,posy):
5+
print 'move to', posx, posy
6+
mouse.move(int(posx), int(posy))
7+
8+
def AbsoluteMouseClick(posx,posy):
9+
print 'click on ', posx, posy
10+
mouse.click(posx, posy)
11+
12+
def AbsoluteMouseClickDown(posx, posy):
13+
print 'left button down'
14+
mouse.press(posx, posy)
15+
16+
def AbsoluteMouseClickUp(posx, posy):
17+
print 'left button up'
18+
mouse.release(posx, posy)
19+
20+
def AbsoluteMouseDrag(posx, posy): #Only relevant in OS X(?)
21+
mouse.move(posx, posy)
22+
23+
def AbsoluteMouseRightClick(posx,posy):
24+
mouse.click(posx, posy, button=2)
25+
26+
def AbsoluteMouseScroll(posx, posy, up=True): #PyUserInput doesn't appear to support relative scrolling
27+
if up is True:
28+
mouse.click(posx, posy, button=4)
29+
elif up is False:
30+
mouse.click(posx, posy, button=5)
31+
#When PyUserInput > 0.1.5 is released, the following will work:
32+
#mouse.scroll(posx, posy, up)
33+
34+
def GetDisplayWidth():
35+
return mouse.screen_size()[0]
36+
37+
def GetDisplayHeight():
38+
return mouse.screen_size()[1]
39+
40+
41+
#A cursor that does commands based on absolute position (good for finger pointing)
42+
class absolute_cursor(object):
43+
def __init__(self):
44+
self.x_max = GetDisplayWidth() - 1
45+
self.y_max = GetDisplayHeight() - 1
46+
self.left_button_pressed = False
47+
self.x = 0
48+
self.y = 0
49+
50+
def move(self, posx, posy): #Move to coordinates
51+
self.x = posx
52+
self.y = posy
53+
if self.x > self.x_max:
54+
self.x = self.x_max
55+
if self.y > self.y_max:
56+
self.y = self.y_max
57+
if self.x < 0.0:
58+
self.x = 0.0
59+
if self.y < 0.0:
60+
self.y = 0.0
61+
if self.left_button_pressed: #We are dragging
62+
AbsoluteMouseDrag(self.x, self.y)
63+
else: #We are not dragging
64+
AbsoluteMouseMove(self.x, self.y)
65+
66+
def click(self, posx=None, posy=None): #Click at coordinates (current coordinates by default)
67+
if posx == None:
68+
posx = self.x
69+
if posy == None:
70+
posy = self.y
71+
AbsoluteMouseClick(posx, posy)
72+
73+
def set_left_button_pressed(self, boolean_button): #Set the state of the left button
74+
if boolean_button == True: #Pressed
75+
self.click_down()
76+
else: #Not pressed
77+
self.click_up()
78+
79+
def click_down(self, posx=None, posy=None):
80+
if posx == None:
81+
posx = self.x
82+
if posy == None:
83+
posy = self.y
84+
AbsoluteMouseClickDown(posx, posy)
85+
self.left_button_pressed = True
86+
87+
def click_up(self, posx=None, posy=None):
88+
if posx == None:
89+
posx = self.x
90+
if posy == None:
91+
posy = self.y
92+
AbsoluteMouseClickUp(posx, posy)
93+
self.left_button_pressed = False
94+
95+
def rightClick(self, posx=None, posy=None):
96+
if posx == None:
97+
posx = self.x
98+
if posy == None:
99+
posy = self.y
100+
AbsoluteMouseRightClick(posx, posy)
101+
102+
def scroll(self, x_movement, y_movement):
103+
posx = self.x
104+
posy = self.y
105+
up = False
106+
if y_movement < 0:
107+
up = True
108+
AbsoluteMouseScroll(posx, posy, up)
109+
110+
111+
#Allows for relative movement instead of absolute movement. This implementation is not a "true" relative mouse,
112+
#but is really just a relative wrapper for an absolute mouse. Not the best way to do it, but I need to
113+
#figure out how to send raw "mouse moved _this amount_" events. This class is (as of writing) untested.
114+
#It's only here in case someone else wants to figure out how to do this properly on OS X.
115+
#I will be "actually" implementing this on Windows shortly. OSX TBD.
116+
class relative_cursor(absolute_cursor):
117+
def __init__(self):
118+
absolute_cursor.__init__(self)
119+
120+
def move(self, x_amt, y_amt):
121+
self.x = self.x + x_amt
122+
self.y = self.y + y_amt
123+
if self.x > self.x_max:
124+
self.x = self.x_max
125+
if self.y > self.y_max:
126+
self.y = self.y_max
127+
if self.x < 0.0:
128+
self.x = 0.0
129+
if self.y < 0.0:
130+
self.y = 0.0
131+
if self.left_button_pressed: #We are dragging
132+
AbsoluteMouseDrag(self.x, self.y)
133+
else: #We are not dragging
134+
AbsoluteMouseMove(self.x, self.y)

Linux/__init__.py

Whitespace-only changes.

MiscFunctions.py

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,38 @@
44

55

66
import math
7-
import sys
8-
if sys.platform == "darwin":
9-
import OSX.Leap as Leap
10-
else:
11-
import Windows.Leap as Leap
7+
from leap import Leap
128
import Geometry
139

10+
#Smooths the mouse's position
11+
class mouse_position_smoother(object):
12+
def __init__(self, smooth_aggressiveness, smooth_falloff):
13+
#Input validation
14+
if smooth_aggressiveness < 1:
15+
raise Exception("Smooth aggressiveness must be greater than 1.")
16+
if smooth_falloff < 1:
17+
raise Exception("Smooth falloff must be greater than 1.0.")
18+
self.previous_positions = []
19+
self.smooth_falloff = smooth_falloff
20+
self.smooth_aggressiveness = int(smooth_aggressiveness)
21+
def update(self, (x,y)):
22+
self.previous_positions.append((x,y))
23+
if len(self.previous_positions) > self.smooth_aggressiveness:
24+
del self.previous_positions[0]
25+
return self.get_current_smooth_value()
26+
def get_current_smooth_value(self):
27+
smooth_x = 0
28+
smooth_y = 0
29+
total_weight = 0
30+
num_positions = len(self.previous_positions)
31+
for position in range(0, num_positions):
32+
weight = 1 / (self.smooth_falloff ** (num_positions - position))
33+
total_weight += weight
34+
smooth_x += self.previous_positions[position][0] * weight
35+
smooth_y += self.previous_positions[position][1] * weight
36+
smooth_x /= total_weight
37+
smooth_y /= total_weight
38+
return smooth_x, smooth_y
1439

1540
class debouncer(object): #Takes a binary "signal" and debounces it.
1641
def __init__(self, debounce_time): #Takes as an argument the number of opposite samples it needs to debounce.
@@ -51,30 +76,12 @@ def signal(self, signal_value):
5176
if self.state_counters[i] < 0: self.state_counters[i] = 0
5277
if self.state_counters[i] >= self.debounce_time: #Confirmed new state at index i
5378
self.state_counters[i] = self.debounce_time
54-
for x in range(0,len(self.state_counters)):
79+
for x in range(0,len(self.state_counters)):
5580
if x is not i: self.state_counters[x] = 0 #Zero out all other state counters
5681
self.state = i #Save the new state
5782
return self.state
5883

5984

60-
class mouse_manager(object): #The original intent of this object was to allow for smoother mouse movements. However, I hope to eliminate it soon.
61-
def __init__(self):
62-
self.xcounter = 0.0
63-
self.ycounter = 0.0
64-
65-
#Returns the integer part of the mouse movement, stores the leftover float part for later
66-
def add(self, (x, y)):
67-
self.xcounter = self.xcounter + x
68-
self.ycounter = self.ycounter + y
69-
split_x = math.modf(self.xcounter) #Saves the float part (remainder) into the counter
70-
split_y = math.modf(self.ycounter) #And the int part into the movement
71-
self.xcounter = split_x[0]
72-
xmovement = int(split_x[1])
73-
self.ycounter = split_y[0]
74-
ymovement = int(split_y[1])
75-
return xmovement, ymovement
76-
77-
7885
def sort_fingers_by_distance_from_screen(fingers):
7986
new_finger_list = [finger for finger in fingers] #Copy the list of fingers
8087
new_finger_list.sort(key=lambda x: x.tip_position.z) #Sort by increasing z

0 commit comments

Comments
 (0)