##// END OF EJS Templates
Factorized glut code into glut_support.py
Nicolas Rougier -
Show More
@@ -0,0 +1,124 b''
1 # coding: utf-8
2 """
3 GLUT Inputhook support functions
4 """
5
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
12
13 # GLUT is quite an old library and it is difficult to ensure proper
14 # integration within IPython since original GLUT does not allow to handle
15 # events one by one. Instead, it requires for the mainloop to be entered
16 # and never returned (there is not even a function to exit he
17 # mainloop). Fortunately, there are alternatives such as freeglut
18 # (available for linux and windows) and the OSX implementation gives
19 # access to a glutCheckLoop() function that blocks itself until a new
20 # event is received. This means we have to setup a default timer to
21 # ensure we got at least one event that will unblock the function. We set
22 # a default timer of 60fps.
23 #
24 # Furthermore, it is not possible to install these handlers without a
25 # window being first created. We choose to make this window invisible and
26 # the user is supposed to make it visible when needed (see gui-glut.py in
27 # the docs/examples/lib directory). This means that display mode options
28 # are set at this level and user won't be able to change them later
29 # without modifying the code. This should probably be made available via
30 # IPython options system.
31
32 #-----------------------------------------------------------------------------
33 # Imports
34 #-----------------------------------------------------------------------------
35
36 import sys
37 import time
38 import signal
39 import OpenGL
40 OpenGL.ERROR_CHECKING = False
41 import OpenGL.GLUT as glut
42 import OpenGL.platform as platform
43
44 #-----------------------------------------------------------------------------
45 # Constants
46 #-----------------------------------------------------------------------------
47
48 # Frame per second : 60
49 # Should probably be an IPython option
50 glut_fps = 60
51
52
53 # Display mode : double buffeed + rgba + depth
54 # Should probably be an IPython option
55 glut_display_mode = (glut.GLUT_DOUBLE |
56 glut.GLUT_RGBA |
57 glut.GLUT_DEPTH)
58
59 glutMainLoopEvent = None
60 if sys.platform == 'darwin':
61 try:
62 glutCheckLoop = platform.createBaseFunction(
63 'glutCheckLoop', dll=platform.GLUT, resultType=None,
64 argTypes=[],
65 doc='glutCheckLoop( ) -> None',
66 argNames=(),
67 )
68 except AttributeError:
69 raise RuntimeError(
70 '''Your glut implementation does not allow interactive sessions'''
71 '''Consider installing freeglut.''')
72 glutMainLoopEvent = glutCheckLoop
73 elif glut.HAVE_FREEGLUT:
74 glutMainLoopEvent = glut.glutMainLoopEvent
75 else:
76 raise RuntimeError(
77 '''Your glut implementation does not allow interactive sessions. '''
78 '''Consider installing freeglut.''')
79
80
81 #-----------------------------------------------------------------------------
82 # Callback functions
83 #-----------------------------------------------------------------------------
84
85 def glut_display():
86 # Dummy display function
87 pass
88
89 def glut_timer(fps):
90 # We should normally set the active window to 1 and post a
91 # redisplay for each window. The problem is that we do not know
92 # how much active windows we have and there is no function in glut
93 # to get that number.
94 # glut.glutSetWindow(1)
95 glut.glutTimerFunc( int(1000.0/fps), glut_timer, fps)
96 glut.glutPostRedisplay()
97
98 def glut_close():
99 glut.glutHideWindow()
100
101
102 def glut_int_handler(signum, frame):
103 signal.signal(signal.SIGINT, signal.default_int_handler)
104 print '\nKeyboardInterrupt'
105 # Need to reprint the prompt at this stage
106
107
108
109 def inputhook_glut():
110 """ Process pending GLUT events only. """
111
112 # We need to protect against a user pressing Control-C when IPython
113 # is idle and this is running. We should trap KeyboardInterrupt and
114 # pass but it does not seem to work with glutMainLoopEvent.
115 # Instead, we setup a signal handler on SIGINT and returns after
116 # having restored the default python SIGINT handler.
117 signal.signal(signal.SIGINT, glut_int_handler)
118 try:
119 glutMainLoopEvent()
120 except KeyboardInterrupt: # this catch doesn't work for some reasons...
121 pass
122 return 0
123
124
@@ -285,15 +285,17 b' class InputHookManager(object):'
285 285 """
286 286 self.clear_inputhook()
287 287
288
288 289 def enable_glut(self, app=None):
289 """Enable event loop integration with GLUT.
290 """ Enable event loop integration with GLUT.
290 291
291 292 Parameters
292 293 ----------
294
293 295 app : ignored
294 Ignored, it's only a placeholder to keep the call signature of all
295 gui activation methods consistent, which simplifies the logic of
296 supporting magics.
296 Ignored, it's only a placeholder to keep the call signature of all
297 gui activation methods consistent, which simplifies the logic of
298 supporting magics.
297 299
298 300 Notes
299 301 -----
@@ -306,143 +308,28 b' class InputHookManager(object):'
306 308 docs/examples/lib directory.
307 309
308 310 The default screen mode is set to:
309
310 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
311
312 Script integration
313 ------------------
314
315 if glut.glutGetWindow() > 0:
316 interactive = True
317 glut.glutShowWindow()
318 else:
319 interactive = False
320 glut.glutInit(sys.argv)
321 glut.glutInitDisplayMode( glut.GLUT_DOUBLE |
322 glut.GLUT_RGBA |
323 glut.GLUT_DEPTH )
324 ...
325 if not interactive:
326 glut.glutMainLoop()
311 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
327 312 """
328 # GLUT is quite an old library and it is difficult to ensure proper
329 # integration within IPython since original GLUT does not allow to handle
330 # events one by one. Instead, it requires for the mainloop to be entered
331 # and never returned (there is not even a function to exit he
332 # mainloop). Fortunately, there are alternatives such as freeglut
333 # (available for linux and windows) and the OSX implementation gives
334 # access to a glutCheckLoop() function that blocks itself until a new
335 # event is received. This means we have to setup a default timer to
336 # ensure we got at least one event that will unblock the function. We set
337 # a default timer of 60fps.
338 #
339 # Furthermore, it is not possible to install these handlers without a
340 # window being first created. We choose to make this window invisible and
341 # the user is supposed to make it visible when needed (see gui-glut.py in
342 # the docs/examples/lib directory). This means that display mode options
343 # are set at this level and user won't be able to change them later
344 # without modifying the code. This should probably be made available via
345 # IPython options system.
346
347 import OpenGL
348 OpenGL.ERROR_CHECKING = False
349 import OpenGL.GLUT as glut
350 import OpenGL.platform as platform
351 import time
352
353
354 # Frame per second : 60
355 # Should probably be an IPython option
356 glut_fps = 60
357
358
359 # Display mode : double buffeed + rgba + depth
360 # Should probably be an IPython option
361 glut_display_mode = (glut.GLUT_DOUBLE |
362 glut.GLUT_RGBA |
363 glut.GLUT_DEPTH)
364 313
365 glut_interrupted = False
366
367 def display():
368 ''' Dummy display function '''
369 pass
314 from glut_support import *
370 315
371 def timer(fps):
372 # We should normally set the active window to 1 and post a
373 # redisplay for each window. The problem is that we do not know
374 # how much active windows we have and there is no function in glut
375 # to get that number.
376 # glut.glutSetWindow(1)
377 glut.glutTimerFunc( int(1000.0/fps), timer, fps)
378 glut.glutPostRedisplay()
379
380 def close():
381 glut.glutHideWindow()
382
383 glutMainLoopEvent = None
384 if sys.platform == 'darwin':
385 try:
386 glutCheckLoop = platform.createBaseFunction(
387 'glutCheckLoop', dll=platform.GLUT, resultType=None,
388 argTypes=[],
389 doc='glutCheckLoop( ) -> None',
390 argNames=(),
391 )
392 except AttributeError:
393 raise RuntimeError(
394 '''Your glut implementation does not allow interactive sessions'''
395 '''Consider installing freeglut.''')
396 glutMainLoopEvent = glutCheckLoop
397 elif glut.HAVE_FREEGLUT:
398 glutMainLoopEvent = glut.glutMainLoopEvent
399 else:
400 raise RuntimeError(
401 '''Your glut implementation does not allow interactive sessions. '''
402 '''Consider installing freeglut.''')
403
404 def inputhook_glut():
405 """ Process pending GLUT events only. """
406
407 # We need to protect against a user pressing Control-C when IPython
408 # is idle and this is running. We should trap KeyboardInterrupt and
409 # pass but it does not seem to work with glutMainLoopEvent.
410 # Instead, we setup a signal handler on SIGINT and returns after
411 # having restored the default python SIGINT handler.
412 import signal
413 def handler(signum, frame):
414 signal.signal(signal.SIGINT, signal.default_int_handler)
415 print '\nKeyboardInterrupt'
416 # Need to reprint the prompt at this stage
417
418 signal.signal(signal.SIGINT, handler)
419
420 try:
421 glutMainLoopEvent()
422 except KeyboardInterrupt: # this catch doesn't work for some reasons...
423 pass
424
425 return 0
426
427 316 if not self._apps.has_key(GUI_GLUT):
428 317 glut.glutInit(sys.argv)
429 # Display mode should be also an Ipython option since user won't be able
430 # to change it later
431 318 glut.glutInitDisplayMode(glut_display_mode)
432 319 glut.glutCreateWindow(sys.argv[0])
433 320 glut.glutHideWindow()
434 glut.glutWMCloseFunc(close)
435 glut.glutDisplayFunc(display)
436 glut.glutTimerFunc( int(1000.0/glut_fps), timer, glut_fps)
321 glut.glutWMCloseFunc(glut_close)
322 glut.glutDisplayFunc(glut_display)
323 glut.glutTimerFunc( int(1000.0/glut_fps), glut_timer, glut_fps)
437 324 else:
438 glut.glutWMCloseFunc(close)
439 glut.glutDisplayFunc(display)
440 glut.glutTimerFunc( int(1000.0/glut_fps), timer, glut_fps)
441
325 glut.glutWMCloseFunc(glut_close)
326 glut.glutDisplayFunc(glut_display)
327 glut.glutTimerFunc( int(1000.0/glut_fps), glut_timer, glut_fps)
442 328 self.set_inputhook(inputhook_glut)
443 329 self._current_gui = GUI_GLUT
444 330 self._apps[GUI_GLUT] = True
445 331
332
446 333 def disable_glut(self):
447 334 """Disable event loop integration with glut.
448 335
@@ -450,42 +337,11 b' class InputHookManager(object):'
450 337 dummy one and set the timer to a dummy timer that will be triggered
451 338 very far in the future.
452 339 """
453 import signal
454 import OpenGL
455 OpenGL.ERROR_CHECKING = False
456 import OpenGL.GLUT as glut
457 import OpenGL.platform as platform
458
459 def timer_none(fps):
460 ''' Dummy timer function '''
461 pass
462
463 glutMainLoopEvent = None
464 if sys.platform == 'darwin':
465 try:
466 glutCheckLoop = platform.createBaseFunction(
467 'glutCheckLoop', dll=platform.GLUT, resultType=None,
468 argTypes=[],
469 doc='glutCheckLoop( ) -> None',
470 argNames=(),
471 )
472 except AttributeError:
473 raise RuntimeError(
474 '''Your glut implementation does not allow interactive sessions'''
475 '''Consider installing freeglut.''')
476 glutMainLoopEvent = glutCheckLoop
477 elif glut.HAVE_FREEGLUT:
478 glutMainLoopEvent = glut.glutMainLoopEvent
479 else:
480 raise RuntimeError(
481 '''Your glut implementation does not allow interactive sessions. '''
482 '''Consider installing freeglut.''')
340 from glut_support import *
483 341
484 342 glut.glutHideWindow() # This is an event to be processed below
485 343 glutMainLoopEvent()
486 #glut.glutTimerFunc( sys.maxint-1, timer_none, 0)
487 344 self.clear_inputhook()
488 #signal.signal(signal.SIGINT, signal.default_int_handler)
489 345
490 346 def enable_pyglet(self, app=None):
491 347 """Enable event loop integration with pyglet.
General Comments 0
You need to be logged in to leave comments. Login now