Skip to content

Commit

Permalink
ENH: start on emulating pyglet mouse events
Browse files Browse the repository at this point in the history
Uses: testing PsychoPy mouse code & experiments, maybe use in actual experiments

Current description:
- fully backwards compatible
- want an emulation mode that sets mouse RT as a side effect
- very fast (< 10^-5s), effectively as fast as before; profiling revealed a 250ms delay
   for the first mention of pyglet.window.mouse.LEFT MIDDLE RIGHT
- move import pyglet.window.mouse.LEFT etc earlier to avoid 250ms first-mention
   delay; don't want that to happen during an experiment trial
- RF to allow for multiple buttons at once via a single integer code

Still to-do:
- add a proper API in psychopy.hardware.emulator?
- emulation of click coordinates x, y; they can be given here but no effect (merely logged)
  • Loading branch information
jeremygray committed Feb 27, 2015
1 parent df68d43 commit f78a9b3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 18 deletions.
43 changes: 27 additions & 16 deletions psychopy/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
else: usePygame=False

if havePyglet:
from pyglet.window.mouse import LEFT, MIDDLE, RIGHT # takes ~250ms, so do it now
global _keyBuffer
_keyBuffer = []
global mouseButtons
Expand Down Expand Up @@ -110,34 +111,44 @@ def _onPygletKey(symbol, modifiers, emulated=False):
_keyBuffer.append( (thisKey,keyTime) ) # tuple
logging.data("%s: %s" % (keySource, thisKey))

def _onPygletMousePress(x,y, button, modifiers):

def _onPygletMousePress(x,y, button, modifiers, emulated=False):
"""button left=1, middle=2, right=4;
"""
global mouseButtons, mouseClick, mouseTimes
if button == pyglet.window.mouse.LEFT:
if emulated:
label = 'Emulated'
else:
label = ''
if button & LEFT:
mouseButtons[0]=1
mouseTimes[0]= psychopy.clock.getTime()-mouseClick[0].getLastResetTime()
label='Left'
if button == pyglet.window.mouse.MIDDLE:
label += ' Left'
if button & MIDDLE:
mouseButtons[1]=1
mouseTimes[1]= psychopy.clock.getTime()-mouseClick[1].getLastResetTime()
label='Middle'
if button == pyglet.window.mouse.RIGHT:
label += ' Middle'
if button & RIGHT:
mouseButtons[2]=1
mouseTimes[2]= psychopy.clock.getTime()-mouseClick[2].getLastResetTime()
label='Right'
logging.data("Mouse: %s button down, pos=(%i,%i)" %(label, x,y))
label += ' Right'
logging.data("Mouse: %s button down, pos=(%i,%i)" %(label.strip(), x,y))

def _onPygletMouseRelease(x,y, button, modifiers):
def _onPygletMouseRelease(x,y, button, modifiers, emulated=False):
global mouseButtons
label = 'unknownButton'
if button == pyglet.window.mouse.LEFT:
if emulated:
label = 'Emulated'
else:
label = ''
if button & LEFT:
mouseButtons[0]=0
label='Left'
if button == pyglet.window.mouse.MIDDLE:
label += ' Left'
if button & MIDDLE:
mouseButtons[1]=0
label='Middle'
if button == pyglet.window.mouse.RIGHT:
label += ' Middle'
if button & RIGHT:
mouseButtons[2]=0
label='Right'
label += ' Right'
logging.data("Mouse: %s button up, pos=(%i,%i)" %(label, x,y))

def _onPygletMouseWheel(x,y,scroll_x, scroll_y):
Expand Down
27 changes: 25 additions & 2 deletions psychopy/tests/test_misc/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
from psychopy.visual import Window, ShapeStim
from psychopy import event, core
from psychopy.constants import NOT_STARTED
import pyglet, pygame
import pyglet
from pyglet.window.mouse import LEFT, MIDDLE, RIGHT
try:
import pygame
havePygame = True
except:
havePygame = False
import pytest
import copy
import threading
Expand Down Expand Up @@ -50,6 +56,22 @@ def test_mouse_pos(self):
m.setPos((0,0))
m.getPos()

def test_emulated_mouse(self):
mouse = event.Mouse() # real mouse
event.mouseButtons = [0,0,0]
[c.reset() for c in event.mouseClick] # mouse click RT clocks
assert not any(event.mouseButtons)
assert not any(event.mouseTimes)

# fake clicks on all buttons:
event._onPygletMousePress(0, 0, LEFT | MIDDLE | RIGHT, None, emulated=True)
assert all(mouse.getPressed())
assert all([RT < 0.01 for RT in event.mouseTimes]) # should be < .0001

# fake release all buttons:
event._onPygletMouseRelease(0, 0, LEFT | MIDDLE | RIGHT, None, emulated=True)
assert not any(event.mouseButtons)

def test_mouse_clock(self):
x, y = 0, 0
scroll_x, scroll_y = 1, 1
Expand Down Expand Up @@ -198,7 +220,8 @@ class TestPygletNorm(_baseTest):
@classmethod
def setup_class(self):
self.win = Window([128,128], winType='pyglet', pos=[50,50], autoLog=False)
assert pygame.display.get_init() == 0
if havePygame:
assert pygame.display.get_init() == 0

class xxxTestPygameNorm(_baseTest):
@classmethod
Expand Down

0 comments on commit f78a9b3

Please sign in to comment.