managed_window.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. from pyglet.window import Window
  2. from pyglet.clock import Clock
  3. from threading import Thread, Lock
  4. gl_lock = Lock()
  5. class ManagedWindow(Window):
  6. """
  7. A pyglet window with an event loop which executes automatically
  8. in a separate thread. Behavior is added by creating a subclass
  9. which overrides setup, update, and/or draw.
  10. """
  11. fps_limit = 30
  12. default_win_args = {"width": 600,
  13. "height": 500,
  14. "vsync": False,
  15. "resizable": True}
  16. def __init__(self, **win_args):
  17. """
  18. It is best not to override this function in the child
  19. class, unless you need to take additional arguments.
  20. Do any OpenGL initialization calls in setup().
  21. """
  22. # check if this is run from the doctester
  23. if win_args.get('runfromdoctester', False):
  24. return
  25. self.win_args = dict(self.default_win_args, **win_args)
  26. self.Thread = Thread(target=self.__event_loop__)
  27. self.Thread.start()
  28. def __event_loop__(self, **win_args):
  29. """
  30. The event loop thread function. Do not override or call
  31. directly (it is called by __init__).
  32. """
  33. gl_lock.acquire()
  34. try:
  35. try:
  36. super().__init__(**self.win_args)
  37. self.switch_to()
  38. self.setup()
  39. except Exception as e:
  40. print("Window initialization failed: %s" % (str(e)))
  41. self.has_exit = True
  42. finally:
  43. gl_lock.release()
  44. clock = Clock()
  45. clock.fps_limit = self.fps_limit
  46. while not self.has_exit:
  47. dt = clock.tick()
  48. gl_lock.acquire()
  49. try:
  50. try:
  51. self.switch_to()
  52. self.dispatch_events()
  53. self.clear()
  54. self.update(dt)
  55. self.draw()
  56. self.flip()
  57. except Exception as e:
  58. print("Uncaught exception in event loop: %s" % str(e))
  59. self.has_exit = True
  60. finally:
  61. gl_lock.release()
  62. super().close()
  63. def close(self):
  64. """
  65. Closes the window.
  66. """
  67. self.has_exit = True
  68. def setup(self):
  69. """
  70. Called once before the event loop begins.
  71. Override this method in a child class. This
  72. is the best place to put things like OpenGL
  73. initialization calls.
  74. """
  75. pass
  76. def update(self, dt):
  77. """
  78. Called before draw during each iteration of
  79. the event loop. dt is the elapsed time in
  80. seconds since the last update. OpenGL rendering
  81. calls are best put in draw() rather than here.
  82. """
  83. pass
  84. def draw(self):
  85. """
  86. Called after update during each iteration of
  87. the event loop. Put OpenGL rendering calls
  88. here.
  89. """
  90. pass
  91. if __name__ == '__main__':
  92. ManagedWindow()