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 5 files changed, 179 insertions(+), 210 deletions(-) [+]
line wrap: on
line diff
--- a/README	Tue Jul 16 21:07:15 2013 +0200
+++ b/README	Tue Jul 16 21:07:15 2013 +0200
@@ -14,7 +14,7 @@
 Running:
     * Python2 (>= 2.6)
     * Cython
-    * Pyglet
+    * A working OpenGL driver
     * SDL2
     * SDL2_image, SDL2_mixer
 
--- a/anmviewer	Tue Jul 16 21:07:15 2013 +0200
+++ b/anmviewer	Tue Jul 16 21:07:15 2013 +0200
@@ -19,9 +19,8 @@
 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 @@
     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.')
--- a/pytouhou/ui/anmrenderer.py	Tue Jul 16 21:07:15 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-# -*- encoding: utf-8 -*-
-##
-## Copyright (C) 2011 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
-##
-## This program is free software; you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published
-## by the Free Software Foundation; version 3 only.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## 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.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 .renderer import Renderer
-from .shaders.eosd import GameShader
-
-from ctypes import c_uint
-
-
-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())
-
-        width, height = 384, 448
-        pyglet.window.Window.__init__(self, width=width, height=height,
-                                      caption='PyTouhou', resizable=False)
-
-        self.use_fixed_pipeline = fixed_pipeline
-
-        self._anm_wrapper = anm_wrapper
-        self.sprites = sprites
-        self.clear_color = (0., 0., 0., 1.)
-        self.force_allow_dest_offset = False
-        self.index_items()
-        self.load(index)
-        self.objects = [self]
-
-        self.x = width / 2
-        self.y = 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)
-
-        # Switch to game projection
-        proj = perspective(30, float(self.width) / float(self.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)
-
-
-    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)
-
-
-    def load(self, index=None):
-        if index is None:
-            index = self.num
-        self.sprite = Sprite()
-        if self.sprites:
-            self.sprite.anm, self.sprite.texcoords = self._anm_wrapper.get_sprite(index)
-            print('Loaded sprite %d' % index)
-        else:
-            self.anmrunner = ANMRunner(self._anm_wrapper, index, self.sprite)
-            print('Loading anim %d, handled events: %r' % (index, self.anmrunner.script.interrupts.keys()))
-        self.num = index
-
-
-    def change(self, diff):
-        keys = self.items.keys()
-        keys.sort()
-        index = (keys.index(self.num) + diff) % len(keys)
-        item = keys[index]
-        self.load(item)
-
-
-    def index_items(self):
-        self.items = {}
-        if self.sprites:
-            self.items = self._anm_wrapper.sprites
-        else:
-            self.items = self._anm_wrapper.scripts
-
-
-    def toggle_sprites(self):
-        self.sprites = not(self.sprites)
-        self.index_items()
-        self.load(0)
-
-
-    def toggle_clear_color(self):
-        if self.clear_color[0] == 0.:
-            self.clear_color = (1., 1., 1., 1.)
-        else:
-            self.clear_color = (0., 0., 0., 1.)
-
-
-    def update(self):
-        if not self.sprites:
-             self.anmrunner.run_frame()
-
-        if self.force_allow_dest_offset:
-            self.sprite.allow_dest_offset = True
-
-        glClearColor(*self.clear_color)
-        glClear(GL_COLOR_BUFFER_BIT)
-        if not self.sprite.removed:
-            self.render_elements([self])
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pytouhou/ui/anmrenderer.pyx	Tue Jul 16 21:07:15 2013 +0200
@@ -0,0 +1,171 @@
+# -*- encoding: utf-8 -*-
+##
+## Copyright (C) 2011 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published
+## by the Free Software Foundation; version 3 only.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+
+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 cimport perspective, setup_camera
+
+from .renderer import Renderer
+from .shaders.eosd import GameShader
+
+from pytouhou.lib import sdl
+
+
+logger = get_logger(__name__)
+
+
+class ANMRenderer(Renderer):
+    def __init__(self, window, resource_loader, anm_wrapper, index=0, sprites=False):
+        self.use_fixed_pipeline = window.use_fixed_pipeline #XXX
+
+        Renderer.__init__(self, resource_loader)
+
+        self.window = window
+        self.texture_manager.preload(resource_loader.instanced_anms.values())
+
+        self._anm_wrapper = anm_wrapper
+        self.sprites = sprites
+        self.clear_color = (0., 0., 0., 1.)
+        self.force_allow_dest_offset = False
+        self.index_items()
+        self.load(index)
+        self.objects = [self]
+
+        self.width = 384
+        self.height = 448
+
+        self.x = self.width / 2
+        self.y = self.height / 2
+
+
+    def start(self, width=384, height=448):
+        self.window.set_size(width, height)
+
+        # Switch to game projection
+        proj = perspective(30, float(width) / float(height),
+                           101010101./2010101., 101010101./10101.)
+        view = setup_camera(0, 0, 1)
+
+        shader = GameShader()
+
+        mvp = view * proj
+        shader.bind()
+        shader.uniform_matrix('mvp', mvp)
+
+
+    def load(self, index=None):
+        if index is None:
+            index = self.num
+        self.sprite = Sprite()
+        if self.sprites:
+            self.sprite.anm, self.sprite.texcoords = self._anm_wrapper.get_sprite(index)
+            print('Loaded sprite %d' % index)
+        else:
+            self.anmrunner = ANMRunner(self._anm_wrapper, index, self.sprite)
+            print('Loading anim %d, handled events: %r' % (index, self.anmrunner.script.interrupts.keys()))
+        self.num = index
+
+
+    def change(self, diff):
+        keys = self.items.keys()
+        keys.sort()
+        index = (keys.index(self.num) + diff) % len(keys)
+        item = keys[index]
+        self.load(item)
+
+
+    def index_items(self):
+        self.items = {}
+        if self.sprites:
+            self.items = self._anm_wrapper.sprites
+        else:
+            self.items = self._anm_wrapper.scripts
+
+
+    def toggle_sprites(self):
+        self.sprites = not(self.sprites)
+        self.index_items()
+        self.load(0)
+
+
+    def toggle_clear_color(self):
+        if self.clear_color[0] == 0.:
+            self.clear_color = (1., 1., 1., 1.)
+        else:
+            self.clear_color = (0., 0., 0., 1.)
+
+
+    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()
+
+        if self.force_allow_dest_offset:
+            self.sprite.allow_dest_offset = True
+
+        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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pytouhou/ui/anmrenderer.pyxbld	Tue Jul 16 21:07:15 2013 +0200
@@ -0,0 +1,1 @@
+../lib/opengl.pyxbld
\ No newline at end of file