changeset 425:1104dc2553ee

Make the anmviewer use the new architecture.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 16 Jul 2013 21:07:15 +0200
parents f4d76d3d6f2a
children 5d7bb2fd74f7
files README anmviewer pytouhou/ui/anmrenderer.py pytouhou/ui/anmrenderer.pyx pytouhou/ui/anmrenderer.pyxbld
diffstat 4 files changed, 77 insertions(+), 108 deletions(-) [+]
line wrap: on
line diff
--- a/README
+++ b/README
@@ -14,7 +14,7 @@ Dependencies:
 Running:
     * Python2 (>= 2.6)
     * Cython
-    * Pyglet
+    * A working OpenGL driver
     * SDL2
     * SDL2_image, SDL2_mixer
 
--- a/anmviewer
+++ b/anmviewer
@@ -19,9 +19,8 @@ import os
 import pyximport
 pyximport.install()
 
+from pytouhou.ui.window import Window
 from pytouhou.resource.loader import Loader
-from pytouhou.game.sprite import Sprite
-from pytouhou.vm.anmrunner import ANMRunner
 from pytouhou.ui.anmrenderer import ANMRenderer
 
 
@@ -29,10 +28,13 @@ def main(path, data, name, script, sprit
     resource_loader = Loader()
     resource_loader.scan_archives(os.path.join(path, name) for name in data)
 
+    window = Window((384, 448), fixed_pipeline=fixed_pipeline, sound=False)
+
     # Get out animation
     anm_wrapper = resource_loader.get_anm_wrapper(name.split(','))
-    anm = ANMRenderer(resource_loader, anm_wrapper, script, sprites, fixed_pipeline)
-    anm.start()
+    anm = ANMRenderer(window, resource_loader, anm_wrapper, script, sprites)
+    window.set_runner(anm)
+    window.run()
 
 
 parser = argparse.ArgumentParser(description='Viewer of ANM files, archives containing animations used in Touhou games.')
rename from pytouhou/ui/anmrenderer.py
rename to pytouhou/ui/anmrenderer.pyx
--- a/pytouhou/ui/anmrenderer.py
+++ b/pytouhou/ui/anmrenderer.pyx
@@ -12,44 +12,32 @@
 ## GNU General Public License for more details.
 ##
 
-import pyglet
-import traceback
-
-from pyglet.gl import (glMatrixMode, glEnable,
-                       glHint, glEnableClientState, glViewport,
-                       glLoadMatrixf, GL_PROJECTION, GL_MODELVIEW,
-                       GL_TEXTURE_2D, GL_BLEND,
-                       GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST,
-                       GL_COLOR_ARRAY, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY,
-                       glClearColor, glClear, GL_COLOR_BUFFER_BIT,
-                       glGenBuffers)
+from pytouhou.lib.opengl cimport \
+         (glClearColor, glClear, GL_COLOR_BUFFER_BIT)
 
 from pytouhou.game.sprite import Sprite
 from pytouhou.vm.anmrunner import ANMRunner
 
 from pytouhou.utils.helpers import get_logger
-from pytouhou.utils.maths import perspective, setup_camera
+from pytouhou.utils.maths cimport perspective, setup_camera
 
 from .renderer import Renderer
 from .shaders.eosd import GameShader
 
-from ctypes import c_uint
+from pytouhou.lib import sdl
 
 
 logger = get_logger(__name__)
 
 
-class ANMRenderer(pyglet.window.Window, Renderer):
-    def __init__(self, resource_loader, anm_wrapper, index=0, sprites=False,
-                 fixed_pipeline=False):
-        Renderer.__init__(self, resource_loader)
-        self.texture_manager.preload(resource_loader.instanced_anms.values())
+class ANMRenderer(Renderer):
+    def __init__(self, window, resource_loader, anm_wrapper, index=0, sprites=False):
+        self.use_fixed_pipeline = window.use_fixed_pipeline #XXX
 
-        width, height = 384, 448
-        pyglet.window.Window.__init__(self, width=width, height=height,
-                                      caption='PyTouhou', resizable=False)
+        Renderer.__init__(self, resource_loader)
 
-        self.use_fixed_pipeline = fixed_pipeline
+        self.window = window
+        self.texture_manager.preload(resource_loader.instanced_anms.values())
 
         self._anm_wrapper = anm_wrapper
         self.sprites = sprites
@@ -59,94 +47,26 @@ class ANMRenderer(pyglet.window.Window, 
         self.load(index)
         self.objects = [self]
 
-        self.x = width / 2
-        self.y = height / 2
+        self.width = 384
+        self.height = 448
+
+        self.x = self.width / 2
+        self.y = self.height / 2
 
 
     def start(self, width=384, height=448):
-        if (width, height) != (self.width, self.height):
-            self.set_size(width, height)
-
-        # Initialize OpenGL
-        glEnable(GL_BLEND)
-        if self.use_fixed_pipeline:
-            glEnable(GL_TEXTURE_2D)
-            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
-            glEnableClientState(GL_COLOR_ARRAY)
-            glEnableClientState(GL_VERTEX_ARRAY)
-            glEnableClientState(GL_TEXTURE_COORD_ARRAY)
+        self.window.set_size(width, height)
 
         # Switch to game projection
-        proj = perspective(30, float(self.width) / float(self.height),
+        proj = perspective(30, float(width) / float(height),
                            101010101./2010101., 101010101./10101.)
         view = setup_camera(0, 0, 1)
 
-        if not self.use_fixed_pipeline:
-            shader = GameShader()
-
-            vbo_array = (c_uint * 1)()
-            glGenBuffers(1, vbo_array)
-            self.vbo, = vbo_array
-
-            mvp = view * proj
-            shader.bind()
-            shader.uniform_matrixf('mvp', mvp.get_c_data())
-        else:
-            glMatrixMode(GL_PROJECTION)
-            glLoadMatrixf(proj.get_c_data())
-
-            glMatrixMode(GL_MODELVIEW)
-            glLoadMatrixf(view.get_c_data())
-
-        # Use our own loop to ensure 60 fps
-        pyglet.clock.set_fps_limit(60)
-        while not self.has_exit:
-            pyglet.clock.tick()
-            self.dispatch_events()
-            self.update()
-            self.flip()
-
-
-    def on_resize(self, width, height):
-        glViewport(0, 0, width, height)
-
+        shader = GameShader()
 
-    def _event_text_symbol(self, ev):
-        # XXX: Ugly workaround to a pyglet bug on X11
-        #TODO: fix that bug in pyglet
-        try:
-            return pyglet.window.Window._event_text_symbol(self, ev)
-        except Exception as exc:
-            logger.warn('Pyglet error: %s', traceback.format_exc(exc))
-            return None, None
-
-
-    def on_key_press(self, symbol, modifiers):
-        if symbol == pyglet.window.key.ESCAPE:
-            self.has_exit = True
-        elif symbol == pyglet.window.key.W:
-            self.load()
-        elif symbol == pyglet.window.key.X:
-            self.x, self.y = {(192, 224): (0, 0),
-                              (0, 0): (-224, 0),
-                              (-224, 0): (192, 224)}[(self.x, self.y)]
-        elif symbol == pyglet.window.key.C:
-            self.force_allow_dest_offset = not self.force_allow_dest_offset
-            self.load()
-        elif symbol == pyglet.window.key.LEFT:
-            self.change(-1)
-        elif symbol == pyglet.window.key.RIGHT:
-            self.change(+1)
-        elif symbol == pyglet.window.key.TAB:
-            self.toggle_sprites()
-        elif symbol == pyglet.window.key.SPACE:
-            self.toggle_clear_color()
-        elif symbol >= pyglet.window.key.F1 and symbol <= pyglet.window.key.F12:
-            interrupt = symbol - pyglet.window.key.F1 + 1
-            if modifiers & pyglet.window.key.MOD_SHIFT:
-                interrupt += 12
-            if not self.sprites:
-                self.anmrunner.interrupt(interrupt)
+        mvp = view * proj
+        shader.bind()
+        shader.uniform_matrix('mvp', mvp)
 
 
     def load(self, index=None):
@@ -192,14 +112,60 @@ class ANMRenderer(pyglet.window.Window, 
 
 
     def update(self):
+        sdl.SCANCODE_C = 6
+        sdl.SCANCODE_TAB = 43
+        sdl.SCANCODE_SPACE = 44
+        sdl.SCANCODE_F1 = 58
+        sdl.SCANCODE_F12 = 69
+        for event in sdl.poll_events():
+            type_ = event[0]
+            if type_ == sdl.KEYDOWN:
+                scancode = event[1]
+                if scancode == sdl.SCANCODE_Z:
+                    self.load()
+                elif scancode == sdl.SCANCODE_X:
+                    self.x, self.y = {(192, 224): (0, 0),
+                                      (0, 0): (-224, 0),
+                                      (-224, 0): (192, 224)}[(self.x, self.y)]
+                elif scancode == sdl.SCANCODE_C:
+                    self.force_allow_dest_offset = not self.force_allow_dest_offset
+                    self.load()
+                elif scancode == sdl.SCANCODE_LEFT:
+                    self.change(-1)
+                elif scancode == sdl.SCANCODE_RIGHT:
+                    self.change(+1)
+                elif scancode == sdl.SCANCODE_TAB:
+                    self.toggle_sprites()
+                elif scancode == sdl.SCANCODE_SPACE:
+                    self.toggle_clear_color()
+                elif sdl.SCANCODE_F1 <= scancode <= sdl.SCANCODE_F12:
+                    interrupt = scancode - sdl.SCANCODE_F1 + 1
+                    keys = sdl.get_keyboard_state()
+                    if keys[sdl.SCANCODE_LSHIFT]:
+                        interrupt += 12
+                    if not self.sprites:
+                        self.anmrunner.interrupt(interrupt)
+                elif scancode == sdl.SCANCODE_ESCAPE:
+                    return False
+            elif type_ == sdl.QUIT:
+                return False
+            elif type_ == sdl.WINDOWEVENT:
+                event_ = event[1]
+                if event_ == sdl.WINDOWEVENT_RESIZED:
+                    self.window.set_size(event[2], event[3])
+
         if not self.sprites:
-             self.anmrunner.run_frame()
+            self.anmrunner.run_frame()
 
         if self.force_allow_dest_offset:
             self.sprite.allow_dest_offset = True
 
-        glClearColor(*self.clear_color)
+        glClearColor(self.clear_color[0], self.clear_color[1], self.clear_color[2], self.clear_color[3])
         glClear(GL_COLOR_BUFFER_BIT)
         if not self.sprite.removed:
             self.render_elements([self])
+        return True
 
+
+    def finish(self):
+        pass
new file mode 120000
--- /dev/null
+++ b/pytouhou/ui/anmrenderer.pyxbld
@@ -0,0 +1,1 @@
+../lib/opengl.pyxbld
\ No newline at end of file