1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
|
"""
A screen.
"""
__author__ = 'Florian Krause <florian@expyriment.org>, \
Oliver Lindemann <oliver@expyriment.org>'
__version__ = '0.7.0'
__revision__ = '55a4e7e'
__date__ = 'Wed Mar 26 14:33:37 2014 +0100'
import pygame
try:
import OpenGL.GL as ogl
except ImportError:
ogl = None
import expyriment
from _input_output import Output
class Screen(Output):
"""A class implementing a screen output.
Each experiment and all stimuli need a screen instance to function.
They are expecting this screen instance to be referenced in
expyriment._active_exp.screen.
Calling expyriment.control.intialize(exp) will automatically create such
a screen instance and will additionally reference it in exp.screen for
easy access.
"""
def __init__(self, colour, open_gl, window_mode, window_size):
"""Create and set up a screen output.
Notes
-----
CAUTION: We discourage from creating a screen instance manually!
Parameters
----------
colour : (int, int, int)
colour of the screen
open_gl : bool
if OpenGL should be used
window_mode : bool
if screen should be a window
window_size : (int, int)
size of the window in window_mode,
full screen mode if size of window_mode[0]<=0
"""
Output.__init__(self)
self._colour = colour
self._open_gl = open_gl
self._fullscreen = not window_mode
self._window_size = window_size
if ogl is None:
warn_message = "PyOpenGL is not installed. \
OpenGL will be deactivated!"
print("Warning: " + warn_message)
expyriment._active_exp._event_file_warn("Screen,warning," + warn_message)
self._open_gl = False
if self._open_gl and not self._fullscreen:
warn_message = "OpenGL does not support window mode. \
OpenGL will be deactivated!"
print("Warning: " + warn_message)
expyriment._active_exp._event_file_warn("Screen,warning," + warn_message)
self._open_gl = False
pygame.display.init()
if self._fullscreen:
self._window_size = (pygame.display.Info().current_w,
pygame.display.Info().current_h)
else:
self._window_size = window_size
if not self._open_gl:
if self._fullscreen:
self._surface = pygame.display.set_mode(self._window_size,
pygame.FULLSCREEN)
else:
self._surface = pygame.display.set_mode(self._window_size)
else:
self._surface = pygame.display.set_mode(
self._window_size,
pygame.DOUBLEBUF | pygame.OPENGL | pygame.FULLSCREEN)
ogl_version = ogl.glGetString(ogl.GL_VERSION)
if float(ogl_version[0:3]) < 2.0:
ogl_extensions = ogl.glGetString(ogl.GL_EXTENSIONS)
if "ARB_texture_non_power_of_two" not in ogl_extensions:
raise RuntimeError("OpenGL mode is not supported on this \
machine!")
pygame.mouse.set_visible(False)
pygame.event.set_blocked(pygame.MOUSEMOTION)
pygame.event.set_blocked(pygame.MOUSEBUTTONDOWN)
pygame.event.set_blocked(pygame.MOUSEBUTTONUP)
@property
def colour(self):
"""Getter for colour."""
return self._colour
@colour.setter
def colour(self, value):
"""Setter for colour."""
self._colour = value
@property
def surface(self):
"""Getter for surface."""
return self._surface
@property
def open_gl(self):
"""Getter for open_gl."""
return self._open_gl
@property
def window_mode(self):
"""Getter for window_mode."""
return not self._fullscreen
@property
def window_size(self):
"""Getter for window_size."""
return self._window_size
def update(self):
"""Update the screen.
This will flip the display double buffer.
"""
pygame.event.pump()
pygame.display.flip()
if self._open_gl:
ogl.glFinish()
if self._logging:
expyriment._active_exp._event_file_log("Screen,updated", 2)
def update_stimuli(self, stimuli):
"""Update only some stimuli on the screen.
Notes
-----
This does only work for non OpenGL screens.
Parameters
----------
stimuli : list
stimulus or a list of stimuli to update
"""
if type(stimuli) is not list:
stimuli = [stimuli]
if not self._open_gl:
rectangles = []
half_screen_size = (self.size[0] / 2, self.size[1] / 2)
for stim in stimuli:
pos = stim.absolute_position
stim_size = stim.surface_size
rect_pos = (pos[0] + half_screen_size[0] - stim_size[0] / 2,
- pos[1] + half_screen_size[1] - stim_size[1] / 2)
rectangles.append(pygame.Rect(rect_pos, stim_size))
pygame.display.update(rectangles)
if self._logging:
expyriment._active_exp._event_file_log("Screen,stimuli updated,{0}"\
.format([stim.id for stim in stimuli]), 2)
pygame.event.pump()
@property
def center_x(self):
"""Getter for X-coordinate of the screen center.
Notes
-----
Each initialized experiment has its one screen (exp.screen). Please use always the
screen of your current experiment.
"""
return self._window_size[0] / 2
@property
def center_y(self):
"""Getter for the Y-coordinate of the screen center.
Notes
-----
Each initialized experiment has its one screen (exp.screen). Please use always the
screen of your current experiment.
"""
return self._window_size[1] / 2
@property
def size(self):
"""Getter for the size of the screen.
Notes
-----
Each initialized experiment has its one screen (exp.screen). Please use always the
screen of your current experiment.
"""
return self._window_size
def clear(self):
"""Clear the screen.
This will reset the default experimental background colour.
"""
if self._open_gl:
ogl.glClearColor(float(self._colour[0]) / 255,
float(self._colour[1]) / 255,
float(self._colour[2]) / 255, 0)
ogl.glClear(ogl.GL_COLOR_BUFFER_BIT | ogl.GL_DEPTH_BUFFER_BIT)
else:
self._surface.fill(self._colour)
if self._logging:
expyriment._active_exp._event_file_log("Screen,cleared", 2)
def save(self, filename):
"""Save the content of the screen as a picture.
Parameters
----------
filename : str
name of the file to write (possible extensions are BMP,
TGA, PNG, or JPEG, with the default being TGA)
"""
pygame.image.save(self._surface, filename)
|