Пример #1
0
    def __init__(self,
                 win,
                 border_thickness=.003,
                 button_text_sz=0.03,
                 buttonPos=(-.5, 0),
                 buttonText="text for button",
                 survey="",
                 thisExp="",
                 type="surveySubmit",
                 **kwargs):

        #local variables
        button_width = len(buttonText) * .025
        button_x_inner_margin = .02
        button_x_outer_margin = button_x_inner_margin + border_thickness
        button_y_inner_margin = button_text_sz
        button_y_outer_margin = button_text_sz + border_thickness
        button_x_range = (0 - button_width / 2 + buttonPos[0],
                          0 + button_width / 2 + buttonPos[0])

        self.thisExp = thisExp
        self._dragging = False
        self.survey = survey
        self.type = type  # this needs to be dynamic
        self.mouse = event.Mouse()
        self.button_selected = False
        self.buttonItems = []
        self.buttonColor = "blue"
        self.button_border = BaseShapeStim(
            win,
            fillColor="blue",
            vertices=((button_x_range[0] - button_x_outer_margin,
                       -button_y_outer_margin + buttonPos[1]),
                      (button_x_range[0] - button_x_outer_margin,
                       button_y_outer_margin + buttonPos[1]),
                      (button_x_range[1] + button_x_outer_margin,
                       button_y_outer_margin + buttonPos[1]),
                      (button_x_range[1] + button_x_outer_margin,
                       -button_y_outer_margin + buttonPos[1])))  #edges=4
        self.button_inner = BaseShapeStim(
            win,
            fillColor="white",
            vertices=((button_x_range[0] - button_x_inner_margin,
                       -button_y_inner_margin + buttonPos[1]),
                      (button_x_range[0] - button_x_inner_margin,
                       button_y_inner_margin + buttonPos[1]),
                      (button_x_range[1] + button_x_inner_margin,
                       button_y_inner_margin + buttonPos[1]),
                      (button_x_range[1] + button_x_inner_margin,
                       -button_y_inner_margin + buttonPos[1])))  #edges=4
        self.button_inner_text = visual.TextStim(win,
                                                 text=buttonText,
                                                 color="blue",
                                                 pos=buttonPos,
                                                 height=button_text_sz)

        self.buttonItems.append(self.button_border)
        self.buttonItems.append(self.button_inner)
        self.buttonItems.append(self.button_inner_text)
Пример #2
0
    def __init__(self,
                 win,
                 borderThickness=.003,
                 labelSize=0.03,
                 pos=(0, 0),
                 labelText="text for button",
                 textColor='blue',
                 borderColor='blue',
                 buttonColor='white',
                 buttonEnabled=False,
                 ):

        # local variables
        super(ButtonStim, self).__init__(win)
        button_width = len(labelText) * .025
        button_x_inner_margin = .02
        button_x_outer_margin = button_x_inner_margin + borderThickness
        button_y_inner_margin = labelSize
        button_y_outer_margin = labelSize + borderThickness
        button_x_range = (0 - button_width / 2 + pos[0], 0 + button_width / 2 + pos[0])

        self.win = win
        self.borderThickness = borderThickness
        self.labelSize = labelSize
        self.pos = pos
        self.labelText = labelText
        self.textColor = textColor
        self.borderColor = borderColor
        self.buttonColor = buttonColor
        self.buttonEnabled = buttonEnabled

        self._dragging = False
        self.mouse = event.Mouse()
        self.buttonSelected = False
        self.buttonItems = []

        self.buttonBorder = BaseShapeStim(self.win, fillColor=self.borderColor, vertices=(
            (button_x_range[0] - button_x_outer_margin, -button_y_outer_margin + self.pos[1]),
            (button_x_range[0] - button_x_outer_margin, button_y_outer_margin + self.pos[1]),
            (button_x_range[1] + button_x_outer_margin, button_y_outer_margin + self.pos[1]),
            (button_x_range[1] + button_x_outer_margin, -button_y_outer_margin + self.pos[1])))
        self.buttonInner = BaseShapeStim(self.win, fillColor=self.buttonColor, vertices=(
            (button_x_range[0] - button_x_inner_margin, -button_y_inner_margin + self.pos[1]),
            (button_x_range[0] - button_x_inner_margin, button_y_inner_margin + self.pos[1]),
            (button_x_range[1] + button_x_inner_margin, button_y_inner_margin + self.pos[1]),
            (button_x_range[1] + button_x_inner_margin, -button_y_inner_margin + self.pos[1])))
        self.buttonInnerText = TextStim(self.win, text=self.labelText, color=self.textColor, pos=self.pos,
                                               height=self.labelSize)
        self.buttonItems.append(self.buttonBorder)
        self.buttonItems.append(self.buttonInner)
        self.buttonItems.append(self.buttonInnerText)
Пример #3
0
    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))
Пример #4
0
class Aperture(MinimalStim, ContainerMixin):
    """Restrict a stimulus visibility area to a basic shape or
    list of vertices.

    When enabled, any drawing commands will only operate on pixels within
    the Aperture. Once disabled, subsequent draw operations affect the whole
    screen as usual.

    If shape is 'square' or 'triangle' then that is what will be used
    If shape is 'circle' or `None` then a polygon with nVerts will be used (120 for a rough circle)
    If shape is a list or numpy array (Nx2) then it will be used directly
        as the vertices to a :class:`~psychopy.visual.ShapeStim`
    If shape is a filename then it will be used to load and image as a
        :class:`~psychopy.visual.ImageStim`. Note that transparent parts
        in the image (e.g. in a PNG file) will not be included in the mask
        shape. The color of the image will be ignored.

    See demos/stimuli/aperture.py for example usage

    :Author:
        2011, Yuri Spitsyn
        2011, Jon Peirce added units options, Jeremy Gray added shape & orientation
        2014, Jeremy Gray added .contains() option
        2015, Thomas Emmerling added ImageStim option
    """
    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))

    def _reset(self):
        """Internal method to rebuild the shape - shouldn't be called by
        the user. You have to explicitly turn resetting off by setting
        self._needReset = False
        """
        if not self._needReset:
            self._needReset = True
        else:
            self.enabled = True  # attributeSetter, turns on.
            GL.glClearStencil(0)
            GL.glClear(GL.GL_STENCIL_BUFFER_BIT)

            GL.glPushMatrix()
            if self.__dict__['filename'] == False:
                self.win.setScale('pix')

            GL.glDisable(GL.GL_LIGHTING)
            self.win.depthTest = False
            self.win.depthMask = False
            GL.glStencilFunc(GL.GL_NEVER, 0, 0)
            GL.glStencilOp(GL.GL_INCR, GL.GL_INCR, GL.GL_INCR)

            if self.__dict__['filename']:
                GL.glEnable(GL.GL_ALPHA_TEST)
                GL.glAlphaFunc(GL.GL_GREATER, 0)
                self._shape.draw()
                GL.glDisable(GL.GL_ALPHA_TEST)
            else:
                # draw without push/pop matrix
                self._shape.draw(keepMatrix=True)

            if self.inverted:
                GL.glStencilFunc(GL.GL_EQUAL, 0, 1)
            else:
                GL.glStencilFunc(GL.GL_EQUAL, 1, 1)
            GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP)

            GL.glPopMatrix()

    @attributeSetter
    def size(self, size):
        """Set the size (diameter) of the Aperture.

        This essentially controls a :class:`.ShapeStim` so see
        documentation for ShapeStim.size.

        :ref:`Operations <attrib-operations>` supported here as
        well as ShapeStim.

        Use setSize() if you want to control logging and resetting.
        """
        self.__dict__['size'] = size
        self._shape.size = size  # _shape is a ShapeStim
        self._reset()

    def setSize(self, size, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message
        """
        self._needReset = needReset
        setAttribute(self, 'size', size, log)

    @attributeSetter
    def ori(self, ori):
        """Set the orientation of the Aperture.

        This essentially controls a :class:`.ShapeStim` so see
        documentation for ShapeStim.ori.

        :ref:`Operations <attrib-operations>` supported here as
        well as ShapeStim.

        Use setOri() if you want to control logging and resetting.
        """
        self.__dict__['ori'] = ori
        self._shape.ori = ori  # a ShapeStim
        self._reset()

    def setOri(self, ori, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message.
        """
        self._needReset = needReset
        setAttribute(self, 'ori', ori, log)

    @attributeSetter
    def pos(self, pos):
        """Set the pos (centre) of the Aperture.
        :ref:`Operations <attrib-operations>` supported.

        This essentially controls a :class:`.ShapeStim` so see
        documentation for ShapeStim.pos.

        :ref:`Operations <attrib-operations>` supported here as
        well as ShapeStim.

        Use setPos() if you want to control logging and resetting.
        """
        self.__dict__['pos'] = numpy.array(pos)
        self._shape.pos = self.pos  # a ShapeStim
        self._reset()

    def setPos(self, pos, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message
        """
        self._needReset = needReset
        setAttribute(self, 'pos', pos, log)

    @attributeSetter
    def inverted(self, value):
        """True / False. Set to true to invert the aperture.
        A non-inverted aperture masks everything BUT the selected shape.
        An inverted aperture masks the selected shape.

        NB. The Aperture is not inverted by default, when created.
        """
        self.__dict__['inverted'] = value
        self._reset()

    def invert(self):
        """Use Aperture.inverted = True instead.
        """
        self.inverted = True

    @property
    def posPix(self):
        """The position of the aperture in pixels
        """
        return self._shape.posPix

    @property
    def sizePix(self):
        """The size of the aperture in pixels
        """
        return self._shape.sizePix

    @attributeSetter
    def enabled(self, value):
        """True / False. Enable or disable the aperture.
        Determines whether it is used in future drawing operations.

        NB. The Aperture is enabled by default, when created.
        """
        if value:
            if self._shape._needVertexUpdate:
                self._shape._updateVertices()
            self.win.stencilTest = True
            self.status = STARTED
        else:
            self.win.stencilTest = False
            self.status = STOPPED

        self.__dict__['enabled'] = value

    def enable(self):
        """Use Aperture.enabled = True instead.
        """
        self.enabled = True

    def disable(self):
        """Use Aperture.enabled = False instead.
        """
        self.enabled = False

    def __del__(self):
        try:
            self.enabled = False
        except (ImportError, ModuleNotFoundError, TypeError):
            pass  # trying to avoid 'Exception ignored in: ....' error from pyglet when experiment exits
Пример #5
0
    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)
        else:
            self._shape = BaseShapeStim(
                win=self.win, vertices=vertices, fillColor=1, lineColor=None,
                interpolate=False, pos=pos, size=size, autoLog=False)
            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))
Пример #6
0
class Aperture(MinimalStim, ContainerMixin):
    """Restrict a stimulus visibility area to a basic shape or
    list of vertices.

    When enabled, any drawing commands will only operate on pixels within
    the Aperture. Once disabled, subsequent draw operations affect the whole
    screen as usual.

    If shape is 'square' or 'triangle' then that is what will be used
    If shape is 'circle' or `None` then a polygon with nVerts will be used
        (120 for a rough circle)
    If shape is a list or numpy array (Nx2) then it will be used directly
        as the vertices to a :class:`~psychopy.visual.ShapeStim`
    If shape is a filename then it will be used to load and image as a
        :class:`~psychopy.visual.ImageStim`. Note that transparent parts
        in the image (e.g. in a PNG file) will not be included in the mask
        shape. The color of the image will be ignored.

    See demos/stimuli/aperture.py for example usage

    :Author:
        2011, Yuri Spitsyn
        2011, Jon Peirce added units options,
              Jeremy Gray added shape & orientation
        2014, Jeremy Gray added .contains() option
        2015, Thomas Emmerling added ImageStim option
    """

    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)
        else:
            self._shape = BaseShapeStim(
                win=self.win, vertices=vertices, fillColor=1, lineColor=None,
                interpolate=False, pos=pos, size=size, autoLog=False)
            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))

    def _reset(self):
        """Internal method to rebuild the shape - shouldn't be called by
        the user. You have to explicitly turn resetting off by setting
        self._needReset = False
        """
        if not self._needReset:
            self._needReset = True
        else:
            self.enabled = True  # attributeSetter, turns on.
            GL.glClearStencil(0)
            GL.glClear(GL.GL_STENCIL_BUFFER_BIT)

            GL.glPushMatrix()
            if self.__dict__['filename'] == False:
                self.win.setScale('pix')

            GL.glDisable(GL.GL_LIGHTING)
            GL.glDisable(GL.GL_DEPTH_TEST)
            GL.glDepthMask(GL.GL_FALSE)
            GL.glStencilFunc(GL.GL_NEVER, 0, 0)
            GL.glStencilOp(GL.GL_INCR, GL.GL_INCR, GL.GL_INCR)

            if self.__dict__['filename']:
                GL.glEnable(GL.GL_ALPHA_TEST)
                GL.glAlphaFunc(GL.GL_GREATER, 0)
                self._shape.draw()
                GL.glDisable(GL.GL_ALPHA_TEST)
            else:
                # draw without push/pop matrix
                self._shape.draw(keepMatrix=True)

            if self.inverted:
                GL.glStencilFunc(GL.GL_EQUAL, 0, 1)
            else:
                GL.glStencilFunc(GL.GL_EQUAL, 1, 1)
            GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP)

            GL.glPopMatrix()

    @attributeSetter
    def size(self, size):
        """Set the size (diameter) of the Aperture.

        This essentially controls a :class:`.ShapeStim` so see
        documentation for ShapeStim.size.

        :ref:`Operations <attrib-operations>` supported here as
        well as ShapeStim.

        Use setSize() if you want to control 0logging and resetting.
        """
        self.__dict__['size'] = size
        self._shape.size = size  # _shape is a ShapeStim
        self._reset()

    def setSize(self, size, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message
        """
        self._needReset = needReset
        setAttribute(self, 'size', size, log)

    @attributeSetter
    def ori(self, ori):
        """Set the orientation of the Aperture.

        This essentially controls a :class:`.ShapeStim` so see
        documentation for ShapeStim.ori.

        :ref:`Operations <attrib-operations>` supported here as
        well as ShapeStim.

        Use setOri() if you want to control logging and resetting.
        """
        self.__dict__['ori'] = ori
        self._shape.ori = ori  # a ShapeStim
        self._reset()

    def setOri(self, ori, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message.
        """
        self._needReset = needReset
        setAttribute(self, 'ori', ori, log)

    @attributeSetter
    def pos(self, pos):
        """Set the pos (centre) of the Aperture.
        :ref:`Operations <attrib-operations>` supported.

        This essentially controls a :class:`.ShapeStim` so see
        documentation for ShapeStim.pos.

        :ref:`Operations <attrib-operations>` supported here as
        well as ShapeStim.

        Use setPos() if you want to control logging and resetting.
        """
        self.__dict__['pos'] = numpy.array(pos)
        self._shape.pos = self.pos  # a ShapeStim
        self._reset()

    def setPos(self, pos, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message
        """
        self._needReset = needReset
        setAttribute(self, 'pos', pos, log)

    @attributeSetter
    def inverted(self, value):
        """True / False. Set to true to invert the aperture.
        A non-inverted aperture masks everything BUT the selected shape.
        An inverted aperture masks the selected shape.

        NB. The Aperture is not inverted by default, when created.
        """
        self.__dict__['inverted'] = value
        self._reset()

    def invert(self):
        """Use Aperture.inverted = True instead.
        """
        self.inverted = True

    @property
    def posPix(self):
        """The position of the aperture in pixels
        """
        return self._shape.posPix

    @property
    def sizePix(self):
        """The size of the aperture in pixels
        """
        return self._shape.sizePix

    @attributeSetter
    def enabled(self, value):
        """True / False. Enable or disable the aperture.
        Determines whether it is used in future drawing operations.

        NB. The Aperture is enabled by default, when created.
        """
        if value:
            if self._shape._needVertexUpdate:
                self._shape._updateVertices()
            GL.glEnable(GL.GL_STENCIL_TEST)
            self.status = STARTED
        else:
            GL.glDisable(GL.GL_STENCIL_TEST)
            self.status = STOPPED

        self.__dict__['enabled'] = value

    def enable(self):
        """Use Aperture.enabled = True instead.
        """
        self.enabled = True

    def disable(self):
        """Use Aperture.enabled = False instead.
        """
        self.enabled = False

    def __del__(self):
        self.enabled = False
Пример #7
0
class ButtonStim(BaseShapeStim):
    """A class for putting a button into your experiment.

    """

    def __init__(self,
                 win,
                 borderThickness=.003,
                 labelSize=0.03,
                 pos=(0, 0),
                 labelText="text for button",
                 textColor='blue',
                 borderColor='blue',
                 buttonColor='white',
                 buttonEnabled=False,
                 ):

        # local variables
        super(ButtonStim, self).__init__(win)
        button_width = len(labelText) * .025
        button_x_inner_margin = .02
        button_x_outer_margin = button_x_inner_margin + borderThickness
        button_y_inner_margin = labelSize
        button_y_outer_margin = labelSize + borderThickness
        button_x_range = (0 - button_width / 2 + pos[0], 0 + button_width / 2 + pos[0])

        self.win = win
        self.borderThickness = borderThickness
        self.labelSize = labelSize
        self.pos = pos
        self.labelText = labelText
        self.textColor = textColor
        self.borderColor = borderColor
        self.buttonColor = buttonColor
        self.buttonEnabled = buttonEnabled

        self._dragging = False
        self.mouse = event.Mouse()
        self.buttonSelected = False
        self.buttonItems = []

        self.buttonBorder = BaseShapeStim(self.win, fillColor=self.borderColor, vertices=(
            (button_x_range[0] - button_x_outer_margin, -button_y_outer_margin + self.pos[1]),
            (button_x_range[0] - button_x_outer_margin, button_y_outer_margin + self.pos[1]),
            (button_x_range[1] + button_x_outer_margin, button_y_outer_margin + self.pos[1]),
            (button_x_range[1] + button_x_outer_margin, -button_y_outer_margin + self.pos[1])))
        self.buttonInner = BaseShapeStim(self.win, fillColor=self.buttonColor, vertices=(
            (button_x_range[0] - button_x_inner_margin, -button_y_inner_margin + self.pos[1]),
            (button_x_range[0] - button_x_inner_margin, button_y_inner_margin + self.pos[1]),
            (button_x_range[1] + button_x_inner_margin, button_y_inner_margin + self.pos[1]),
            (button_x_range[1] + button_x_inner_margin, -button_y_inner_margin + self.pos[1])))
        self.buttonInnerText = TextStim(self.win, text=self.labelText, color=self.textColor, pos=self.pos,
                                               height=self.labelSize)
        self.buttonItems.append(self.buttonBorder)
        self.buttonItems.append(self.buttonInner)
        self.buttonItems.append(self.buttonInnerText)

    def draw(self):
        self.getMouseResponses()
        for item in self.buttonItems:
            item.draw()

    def buttonSwitch(self, switch):
        if switch:
            self.buttonBorder.color = self.buttonColor
            self.buttonInner.color = self.borderColor
            self.buttonInnerText.color = self.buttonColor
        else:
            self.buttonBorder.color = self.borderColor
            self.buttonInner.color = self.buttonColor
            self.buttonInnerText.color = self.borderColor

    def buttonContains(self, mouse):
        return self.buttonBorder.contains(mouse)

    def buttonClicked(self, mouse):
        self.buttonSelected = bool(self.buttonContains(mouse)
                                   and mouse.getPressed()[0])
        return self.buttonSelected

    def buttonGuard(self, condition):
        if not self.buttonEnabled:
            self.buttonBorder.color = 'dimgrey'
            self.buttonInner.color = 'darkgrey'
            self.buttonInnerText.color = 'dimgrey'
        else:
            self.buttonBorder.color = self.buttonColor
            self.buttonInner.color = self.borderColor
            self.buttonInnerText.color = self.buttonColor

    def getMouseResponses(self):
        self.buttonGuard(self.buttonEnabled)
        if not self.buttonEnabled:
            return

        if not self.buttonClicked(self.mouse):  # hovering
            self.buttonSwitch(self.buttonContains(self.mouse))

        if self.buttonClicked(self.mouse):
            self._dragging = True
            # Update current but don't set Rating (mouse is still down)
            # Dragging has to start inside a "valid" area (i.e., on the
            # slider), but may continue even if the mouse moves away from
            # the slider, as long as the mouse button is not released.
        else:  # mouse is up - check if it *just* came up
            if self._dragging:
                if self.buttonContains(self.mouse):
                    self.buttonSelected = True
                self._dragging = False
            else:
                # is up and was already up - move along
                return None
Пример #8
0
class Button(BaseShapeStim):
    """A class for putting a button into your experiment.

        As of 18/9/2018 the only type of button available is "surveySubmit"
            See Coder Demos -> surveys -> aq_form.py for an example of a button used like this

        :Authors:
            - 2018: Anthony Haffey
    """
    def __init__(self,
                 win,
                 border_thickness=.003,
                 button_text_sz=0.03,
                 buttonPos=(-.5, 0),
                 buttonText="text for button",
                 survey="",
                 thisExp="",
                 type="surveySubmit",
                 **kwargs):

        #local variables
        button_width = len(buttonText) * .025
        button_x_inner_margin = .02
        button_x_outer_margin = button_x_inner_margin + border_thickness
        button_y_inner_margin = button_text_sz
        button_y_outer_margin = button_text_sz + border_thickness
        button_x_range = (0 - button_width / 2 + buttonPos[0],
                          0 + button_width / 2 + buttonPos[0])

        self.thisExp = thisExp
        self._dragging = False
        self.survey = survey
        self.type = type  # this needs to be dynamic
        self.mouse = event.Mouse()
        self.button_selected = False
        self.buttonItems = []
        self.buttonColor = "blue"
        self.button_border = BaseShapeStim(
            win,
            fillColor="blue",
            vertices=((button_x_range[0] - button_x_outer_margin,
                       -button_y_outer_margin + buttonPos[1]),
                      (button_x_range[0] - button_x_outer_margin,
                       button_y_outer_margin + buttonPos[1]),
                      (button_x_range[1] + button_x_outer_margin,
                       button_y_outer_margin + buttonPos[1]),
                      (button_x_range[1] + button_x_outer_margin,
                       -button_y_outer_margin + buttonPos[1])))  #edges=4
        self.button_inner = BaseShapeStim(
            win,
            fillColor="white",
            vertices=((button_x_range[0] - button_x_inner_margin,
                       -button_y_inner_margin + buttonPos[1]),
                      (button_x_range[0] - button_x_inner_margin,
                       button_y_inner_margin + buttonPos[1]),
                      (button_x_range[1] + button_x_inner_margin,
                       button_y_inner_margin + buttonPos[1]),
                      (button_x_range[1] + button_x_inner_margin,
                       -button_y_inner_margin + buttonPos[1])))  #edges=4
        self.button_inner_text = visual.TextStim(win,
                                                 text=buttonText,
                                                 color="blue",
                                                 pos=buttonPos,
                                                 height=button_text_sz)

        self.buttonItems.append(self.button_border)
        self.buttonItems.append(self.button_inner)
        self.buttonItems.append(self.button_inner_text)

    def draw(self):
        self.getMouseResponses()

        for item in self.buttonItems:
            item.draw()
        ### This code has been used to change the color when a button is clicked on or hovered over. Been unable to implement without disrupting the form

    def getMouseResponses(self):
        click = bool(self.mouse.getPressed()[0])

        #hover = bool(self.button_border.contains(self.mouse))

        #if hover:
        if (self.button_selected == False):
            if self.button_border.contains(self.mouse):
                self.button_border.color = self.buttonColor
                self.button_inner.color = self.buttonColor
                self.button_inner_text.color = "white"
            else:
                self.button_border.color = self.buttonColor
                self.button_inner.color = "white"
                self.button_inner_text.color = self.buttonColor
        else:
            if self.button_border.contains(self.mouse):
                self.button_border.color = self.buttonColor
                self.button_inner.color = "white"
                self.button_inner_text.color = self.buttonColor
            else:
                self.button_border.color = self.buttonColor
                self.button_inner.color = self.buttonColor
                self.button_inner_text.color = "white"

        if click:
            self._dragging = True
            # Update current but don't set Rating (mouse is still down)
            # Dragging has to start inside a "valid" area (i.e., on the
            # slider), but may continue even if the mouse moves away from
            # the slider, as long as the mouse button is not released.

        else:  # mouse is up - check if it *just* came up
            if self._dragging:
                if self.type == "surveySubmit":
                    if self.button_border.contains(self.mouse):
                        itemsFailed = surveys.saveScores(
                            self.survey, self.thisExp)
                        if len(itemsFailed) > 0:

                            self.buttonColor = "red"

                elif self.type == "surveyItem":
                    print("Will code what to do with you later")

                if self.button_border.contains(self.mouse):
                    if (self.button_selected == True):
                        self.button_selected = False
                    else:
                        self.button_selected = True
                self._dragging = False

            else:

                # is up and was already up - move along
                return None