##// 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 self.clear_inputhook()
286 self.clear_inputhook()
287
287
288
288 def enable_glut(self, app=None):
289 def enable_glut(self, app=None):
289 """Enable event loop integration with GLUT.
290 """ Enable event loop integration with GLUT.
290
291
291 Parameters
292 Parameters
292 ----------
293 ----------
294
293 app : ignored
295 app : ignored
294 Ignored, it's only a placeholder to keep the call signature of all
296 Ignored, it's only a placeholder to keep the call signature of all
295 gui activation methods consistent, which simplifies the logic of
297 gui activation methods consistent, which simplifies the logic of
296 supporting magics.
298 supporting magics.
297
299
298 Notes
300 Notes
299 -----
301 -----
@@ -306,143 +308,28 b' class InputHookManager(object):'
306 docs/examples/lib directory.
308 docs/examples/lib directory.
307
309
308 The default screen mode is set to:
310 The default screen mode is set to:
309
311 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
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()
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
314 from glut_support import *
366
367 def display():
368 ''' Dummy display function '''
369 pass
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 if not self._apps.has_key(GUI_GLUT):
316 if not self._apps.has_key(GUI_GLUT):
428 glut.glutInit(sys.argv)
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 glut.glutInitDisplayMode(glut_display_mode)
318 glut.glutInitDisplayMode(glut_display_mode)
432 glut.glutCreateWindow(sys.argv[0])
319 glut.glutCreateWindow(sys.argv[0])
433 glut.glutHideWindow()
320 glut.glutHideWindow()
434 glut.glutWMCloseFunc(close)
321 glut.glutWMCloseFunc(glut_close)
435 glut.glutDisplayFunc(display)
322 glut.glutDisplayFunc(glut_display)
436 glut.glutTimerFunc( int(1000.0/glut_fps), timer, glut_fps)
323 glut.glutTimerFunc( int(1000.0/glut_fps), glut_timer, glut_fps)
437 else:
324 else:
438 glut.glutWMCloseFunc(close)
325 glut.glutWMCloseFunc(glut_close)
439 glut.glutDisplayFunc(display)
326 glut.glutDisplayFunc(glut_display)
440 glut.glutTimerFunc( int(1000.0/glut_fps), timer, glut_fps)
327 glut.glutTimerFunc( int(1000.0/glut_fps), glut_timer, glut_fps)
441
442 self.set_inputhook(inputhook_glut)
328 self.set_inputhook(inputhook_glut)
443 self._current_gui = GUI_GLUT
329 self._current_gui = GUI_GLUT
444 self._apps[GUI_GLUT] = True
330 self._apps[GUI_GLUT] = True
445
331
332
446 def disable_glut(self):
333 def disable_glut(self):
447 """Disable event loop integration with glut.
334 """Disable event loop integration with glut.
448
335
@@ -450,42 +337,11 b' class InputHookManager(object):'
450 dummy one and set the timer to a dummy timer that will be triggered
337 dummy one and set the timer to a dummy timer that will be triggered
451 very far in the future.
338 very far in the future.
452 """
339 """
453 import signal
340 from glut_support import *
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.''')
483
341
484 glut.glutHideWindow() # This is an event to be processed below
342 glut.glutHideWindow() # This is an event to be processed below
485 glutMainLoopEvent()
343 glutMainLoopEvent()
486 #glut.glutTimerFunc( sys.maxint-1, timer_none, 0)
487 self.clear_inputhook()
344 self.clear_inputhook()
488 #signal.signal(signal.SIGINT, signal.default_int_handler)
489
345
490 def enable_pyglet(self, app=None):
346 def enable_pyglet(self, app=None):
491 """Enable event loop integration with pyglet.
347 """Enable event loop integration with pyglet.
General Comments 0
You need to be logged in to leave comments. Login now