def __init__(self, win, newPos=None, visible=True, leftLimit=None, topLimit=None, rightLimit=None, bottomLimit=None, showLimitBox=False, clickOnUp=False, pointer=None, name=None, autoLog=None): """Class for customizing the appearance and behavior of the mouse. Use a custom mouse for extra control over the pointer appearance and function. Its probably slower to render than the regular system mouse. Create your `visual.Window` before creating a CustomMouse. :Parameters: win : required, `visual.Window` the window to which this mouse is attached visible : **True** or False makes the mouse invisbile if necessary newPos : **None** or [x,y] gives the mouse a particular starting position (pygame or pyglet) leftLimit : left edge of a virtual box within which the mouse can move topLimit : top edge of virtual box rightLimit : right edge of virtual box bottomLimit : lower edge of virtual box showLimitBox : default is False display the boundary of the area within which the mouse can move. pointer : The visual display item to use as the pointer; must have .draw() and setPos() methods. If your item has .setOpacity(), you can alter the mouse's opacity. clickOnUp : when to count a mouse click as having occured default is False, record a click when the mouse is first pressed down. True means record a click when the mouse button is released. :Note: CustomMouse is a new feature, and subject to change. `setPos()` does not work yet. `getRel()` returns `[0,0]` and `mouseMoved()` always returns `False`. `clickReset()` may not be working. """ #what local vars are defined (these are the init params) for use by __repr__ self._initParams = dir() self._initParams.remove('self') super(CustomMouse, self).__init__(name=name, autoLog=False) self.autoLog = False # set properly at end of init self.win = win self.mouse = event.Mouse(win=self.win) # maybe inheriting from Mouse would be easier? its not that simple self.getRel = self.mouse.getRel self.getWheelRel = self.mouse.getWheelRel self.mouseMoved = self.mouse.mouseMoved # FAILS self.mouseMoveTime = self.mouse.mouseMoveTime self.getPressed = self.mouse.getPressed self.clickReset = self.mouse.clickReset # ??? self._pix2windowUnits = self.mouse._pix2windowUnits self._windowUnits2pix = self.mouse._windowUnits2pix # the graphic to use as the 'mouse' icon (pointer) if pointer: self.setPointer(pointer) else: #self.pointer = TextStim(win, text='+') self.pointer = ImageStim(win, image=os.path.join(os.path.split(__file__)[0], 'pointer.png'), autoLog=False) self.mouse.setVisible(False) # hide the actual (system) mouse self.visible = visible # the custom (virtual) mouse self.leftLimit = self.rightLimit = None self.topLimit = self.bottomLimit = None self.setLimit(leftLimit=leftLimit, topLimit=topLimit, rightLimit=rightLimit, bottomLimit=bottomLimit) self.showLimitBox = showLimitBox self.lastPos = None self.prevPos = None if newPos is not None: self.lastPos = newPos else: self.lastPos = self.mouse.getPos() # for counting clicks: self.clickOnUp = clickOnUp self.wasDown = False # state of mouse 1 frame prior to current frame, look for changes self.clicks = 0 # how many mouse clicks since last reset self.clickButton = 0 # which button to count clicks for; 0 = left # set autoLog now that params have been initialised self.__dict__['autoLog'] = autoLog or autoLog is None and self.win.autoLog if self.autoLog: logging.exp("Created %s = %s" %(self.name, str(self)))
def __init__(self, win, size=1, pos=(0, 0), ori=0, nVert=120, shape='circle', inverted=False, units=None, name=None, autoLog=None): # what local vars are defined (these are the init params) for use by # __repr__ self._initParams = dir() self._initParams.remove('self') super(Aperture, self).__init__(name=name, autoLog=False) # set self params self.autoLog = False # change after attribs are set self.win = win if not win.allowStencil: logging.error('Aperture has no effect in a window created ' 'without allowStencil=True') core.quit() self.__dict__['size'] = size self.__dict__['pos'] = pos self.__dict__['ori'] = ori self.__dict__['inverted'] = inverted self.__dict__['filename'] = False # unit conversions if units != None and len(units): self.units = units else: self.units = win.units # set vertices using shape, or default to a circle with nVerts edges if hasattr(shape, 'lower') and not os.path.isfile(shape): shape = shape.lower() if shape is None or shape == 'circle': # NB: pentagon etc point upwards by setting x,y to be y,x # (sin,cos): vertices = [(0.5 * sin(radians(theta)), 0.5 * cos(radians(theta))) for theta in numpy.linspace(0, 360, nVert, False)] elif shape == 'square': vertices = [[0.5, -0.5], [-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5]] elif shape == 'triangle': vertices = [[0.5, -0.5], [0, 0.5], [-0.5, -0.5]] elif type(shape) in [tuple, list, numpy.ndarray] and len(shape) > 2: vertices = shape elif isinstance(shape, basestring): # is a string - see if it points to a file if os.path.isfile(shape): self.__dict__['filename'] = shape else: msg = ("Unrecognized shape for aperture. Expected 'circle'," " 'square', 'triangle', vertices, filename, or None;" " got %s") logging.error(msg % repr(shape)) if self.__dict__['filename']: self._shape = ImageStim(win=self.win, image=self.__dict__['filename'], pos=pos, size=size, autoLog=False, units=self.units) else: self._shape = BaseShapeStim(win=self.win, vertices=vertices, fillColor=1, lineColor=None, colorSpace='rgb', interpolate=False, pos=pos, size=size, autoLog=False, units=self.units) self.vertices = self._shape.vertices self._needVertexUpdate = True self._needReset = True # Default when setting attributes # implicitly runs a self.enabled = True. Also sets # self._needReset = True on every call self._reset() # set autoLog now that params have been initialised wantLog = autoLog is None and self.win.autoLog self.__dict__['autoLog'] = autoLog or wantLog if self.autoLog: logging.exp("Created {} = {}".format(self.name, self))
class CustomMouse(MinimalStim): """Class for more control over the mouse, including the pointer graphic and bounding box. Seems to work with pyglet or pygame. Not completely tested. Known limitations: - only norm units are working - getRel() always returns [0,0] - mouseMoved() is always False; maybe due to self.mouse.visible == False -> held at [0,0] - no idea if clickReset() works Author: Jeremy Gray, 2011 """ def __init__(self, win, newPos=None, visible=True, leftLimit=None, topLimit=None, rightLimit=None, bottomLimit=None, showLimitBox=False, clickOnUp=False, pointer=None, name=None, autoLog=None): """Class for customizing the appearance and behavior of the mouse. Use a custom mouse for extra control over the pointer appearance and function. Its probably slower to render than the regular system mouse. Create your `visual.Window` before creating a CustomMouse. :Parameters: win : required, `visual.Window` the window to which this mouse is attached visible : **True** or False makes the mouse invisbile if necessary newPos : **None** or [x,y] gives the mouse a particular starting position (pygame or pyglet) leftLimit : left edge of a virtual box within which the mouse can move topLimit : top edge of virtual box rightLimit : right edge of virtual box bottomLimit : lower edge of virtual box showLimitBox : default is False display the boundary of the area within which the mouse can move. pointer : The visual display item to use as the pointer; must have .draw() and setPos() methods. If your item has .setOpacity(), you can alter the mouse's opacity. clickOnUp : when to count a mouse click as having occured default is False, record a click when the mouse is first pressed down. True means record a click when the mouse button is released. :Note: CustomMouse is a new feature, and subject to change. `setPos()` does not work yet. `getRel()` returns `[0,0]` and `mouseMoved()` always returns `False`. `clickReset()` may not be working. """ #what local vars are defined (these are the init params) for use by __repr__ self._initParams = dir() self._initParams.remove('self') super(CustomMouse, self).__init__(name=name, autoLog=False) self.autoLog = False # set properly at end of init self.win = win self.mouse = event.Mouse(win=self.win) # maybe inheriting from Mouse would be easier? its not that simple self.getRel = self.mouse.getRel self.getWheelRel = self.mouse.getWheelRel self.mouseMoved = self.mouse.mouseMoved # FAILS self.mouseMoveTime = self.mouse.mouseMoveTime self.getPressed = self.mouse.getPressed self.clickReset = self.mouse.clickReset # ??? self._pix2windowUnits = self.mouse._pix2windowUnits self._windowUnits2pix = self.mouse._windowUnits2pix # the graphic to use as the 'mouse' icon (pointer) if pointer: self.setPointer(pointer) else: #self.pointer = TextStim(win, text='+') self.pointer = ImageStim(win, image=os.path.join(os.path.split(__file__)[0], 'pointer.png'), autoLog=False) self.mouse.setVisible(False) # hide the actual (system) mouse self.visible = visible # the custom (virtual) mouse self.leftLimit = self.rightLimit = None self.topLimit = self.bottomLimit = None self.setLimit(leftLimit=leftLimit, topLimit=topLimit, rightLimit=rightLimit, bottomLimit=bottomLimit) self.showLimitBox = showLimitBox self.lastPos = None self.prevPos = None if newPos is not None: self.lastPos = newPos else: self.lastPos = self.mouse.getPos() # for counting clicks: self.clickOnUp = clickOnUp self.wasDown = False # state of mouse 1 frame prior to current frame, look for changes self.clicks = 0 # how many mouse clicks since last reset self.clickButton = 0 # which button to count clicks for; 0 = left # set autoLog now that params have been initialised self.__dict__['autoLog'] = autoLog or autoLog is None and self.win.autoLog if self.autoLog: logging.exp("Created %s = %s" %(self.name, str(self))) def _setPos(self, pos=None): # not implemented hence: # pragma: no cover """internal mouse position management. setting a position here leads to the virtual mouse being out of alignment with the hardware mouse, which leads to an 'invisible wall' effect for the mouse. """ if pos is None: pos = self.getPos() else: self.lastPos = pos self.pointer.setPos(pos) def setPos(self, pos): """Not implemented yet. Place the mouse at a specific position. """ raise NotImplementedError('setPos is not available for custom mouse') def getPos(self): """Returns the mouse's current position. Influenced by changes in .getRel(), constrained to be in its virtual box. """ dx, dy = self.getRel() x = min(max(self.lastPos[0] + dx, self.leftLimit), self.rightLimit) y = min(max(self.lastPos[1] + dy, self.bottomLimit), self.topLimit) self.lastPos = numpy.array([x,y]) return self.lastPos def draw(self): """Draw mouse (if its visible), show the limit box, update the click count. """ self._setPos() if self.showLimitBox: self.box.draw() if self.visible: self.pointer.draw() isDownNow = self.getPressed()[self.clickButton] if self.clickOnUp: if self.wasDown and not isDownNow: # newly up self.clicks += 1 else: if not self.wasDown and isDownNow: # newly down self.clicks += 1 self.wasDown = isDownNow def getClicks(self): """Return the number of clicks since the last reset""" return self.clicks def resetClicks(self): """Set click count to zero""" self.clicks = 0 def getVisible(self): """Return the mouse's visibility state""" return self.visible def setVisible(self, visible): """Make the mouse visible or not (pyglet or pygame).""" self.visible = visible def setPointer(self, pointer): """Set the visual item to be drawn as the mouse pointer.""" if hasattr(pointer, 'draw') and hasattr(pointer, 'setPos'): self.pointer = pointer else: raise AttributeError, "need .draw() and .setPos() methods in pointer" def setLimit(self, leftLimit=None, topLimit=None, rightLimit=None, bottomLimit=None): """Set the mouse's bounding box by specifying the edges.""" if type(leftLimit) in [int,float]: self.leftLimit = leftLimit elif self.leftLimit is None: self.leftLimit = -1 if self.win.units == 'pix': self.leftLimit = self.win.size[0]/-2. if type(rightLimit) in [int,float]: self.rightLimit = rightLimit elif self.rightLimit is None: self.rightLimit = .99 if self.win.units == 'pix': self.rightLimit = self.win.size[0]/2. - 5 if type(topLimit) in [int,float]: self.topLimit = topLimit elif self.topLimit is None: self.topLimit = 1 if self.win.units == 'pix': self.topLimit = self.win.size[1]/2. if type(bottomLimit) in [int,float]: self.bottomLimit = bottomLimit elif self.bottomLimit is None: self.bottomLimit = -0.98 if self.win.units == 'pix': self.bottomLimit = self.win.size[1]/-2. + 10 self.box = psychopy.visual.ShapeStim(self.win, vertices=[[self.leftLimit,self.topLimit],[self.rightLimit,self.topLimit], [self.rightLimit,self.bottomLimit], [self.leftLimit,self.bottomLimit],[self.leftLimit,self.topLimit]], opacity=0.35, autoLog=False) # avoid accumulated relative-offsets producing a different effective limit: self.mouse.setVisible(True) self.lastPos = self.mouse.getPos() # hardware mouse's position self.mouse.setVisible(False)