changeset 459:6e733ed817bd

Move every rendering function from gamerunner to gamerenderer.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 06 Sep 2013 22:35:54 +0200
parents 1b56d62250ab
children ec327e58b477
files pytouhou/ui/background.pxd pytouhou/ui/background.pyx pytouhou/ui/gamerenderer.pxd pytouhou/ui/gamerenderer.pyx pytouhou/ui/gamerunner.pyx
diffstat 5 files changed, 144 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/ui/background.pxd
+++ b/pytouhou/ui/background.pxd
@@ -11,6 +11,7 @@ cdef class BackgroundRenderer:
     cdef unsigned short blendfunc, nb_vertices
     cdef Vertex *vertex_buffer
     cdef unsigned int use_fixed_pipeline, vbo
+    cdef object background
 
-    cpdef render_background(self)
-    cpdef prerender(self, background)
+    cdef void render_background(self)
+    cdef void load(self, background)
--- a/pytouhou/ui/background.pyx
+++ b/pytouhou/ui/background.pyx
@@ -42,7 +42,7 @@ cdef class BackgroundRenderer:
             glGenBuffers(1, &self.vbo)
 
 
-    cpdef render_background(self):
+    cdef void render_background(self):
         if self.use_fixed_pipeline:
             glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].x)
             glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].u)
@@ -68,11 +68,13 @@ cdef class BackgroundRenderer:
             glBindBuffer(GL_ARRAY_BUFFER, 0)
 
 
-    cpdef prerender(self, background):
+    cdef void load(self, background):
         cdef float ox, oy, oz, ox2, oy2, oz2
         cdef unsigned short nb_vertices = 0
         cdef Vertex* vertex_buffer
 
+        self.background = background
+
         vertex_buffer = self.vertex_buffer
 
         for ox, oy, oz, model_id, model in background.object_instances:
--- a/pytouhou/ui/gamerenderer.pxd
+++ b/pytouhou/ui/gamerenderer.pxd
@@ -1,9 +1,16 @@
 from pytouhou.utils.matrix cimport Matrix
+from .background cimport BackgroundRenderer
 from .renderer cimport Renderer
 from .shader cimport Shader
 
 cdef class GameRenderer(Renderer):
     cdef Matrix game_mvp, interface_mvp, proj
     cdef Shader game_shader, background_shader, interface_shader
+    cdef BackgroundRenderer background_renderer
 
-    cdef object game, background, background_renderer #XXX
+    cdef void load_background(self, background)
+    cdef void start(self, game)
+    cdef void render(self, game)
+    cdef void render_game(self, game)
+    cdef void render_text(self, texts)
+    cdef void render_interface(self, interface, game_boss)
--- a/pytouhou/ui/gamerenderer.pyx
+++ b/pytouhou/ui/gamerenderer.pyx
@@ -16,25 +16,64 @@ from itertools import chain
 
 from pytouhou.lib.opengl cimport \
          (glClear, glMatrixMode, glLoadIdentity, glLoadMatrixf, glDisable,
-          glEnable, glFogi, glFogf, glFogfv,
-          GL_PROJECTION, GL_MODELVIEW, GL_FOG, GL_FOG_MODE, GL_LINEAR,
-          GL_FOG_START, GL_FOG_END, GL_FOG_COLOR, GL_COLOR_BUFFER_BIT, GLfloat)
+          glEnable, glFogi, glFogf, glFogfv, GL_PROJECTION, GL_MODELVIEW,
+          GL_FOG, GL_FOG_MODE, GL_LINEAR, GL_FOG_START, GL_FOG_END,
+          GL_FOG_COLOR, GL_COLOR_BUFFER_BIT, GLfloat, glViewport, glScissor,
+          GL_SCISSOR_TEST, GL_DEPTH_BUFFER_BIT)
 
-from pytouhou.utils.maths cimport setup_camera
+from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d
+from .shaders.eosd import GameShader, BackgroundShader
+
+from collections import namedtuple
+Rect = namedtuple('Rect', 'x y w h')
+Color = namedtuple('Color', 'r g b a')
 
 
 cdef class GameRenderer(Renderer):
-    def __init__(self, resource_loader):
+    def __init__(self, resource_loader, use_fixed_pipeline):
+        self.use_fixed_pipeline = use_fixed_pipeline #XXX
+
         Renderer.__init__(self, resource_loader)
 
+        if not self.use_fixed_pipeline:
+            self.game_shader = GameShader()
+            self.background_shader = BackgroundShader()
+            self.interface_shader = self.game_shader
 
-    def render(self):
+
+    cdef void load_background(self, background):
+        if background is not None:
+            self.background_renderer = BackgroundRenderer(self.use_fixed_pipeline)
+            self.background_renderer.load(background)
+        else:
+            self.background_renderer = None
+
+
+    cdef void start(self, game):
+        self.proj = perspective(30, float(game.width) / float(game.height),
+                                101010101./2010101., 101010101./10101.)
+        game_view = setup_camera(0, 0, 1)
+        self.game_mvp = game_view * self.proj
+        self.interface_mvp = ortho_2d(0., float(game.interface.width), float(game.interface.height), 0.)
+
+
+    cdef void render(self, game):
+        self.render_game(game)
+        self.render_text(game.texts + game.native_texts)
+        self.render_interface(game.interface, game.boss)
+
+
+    cdef void render_game(self, game):
+        cdef long game_x, game_y
         cdef float x, y, z, dx, dy, dz, fog_data[4], fog_start, fog_end
         cdef unsigned char fog_r, fog_g, fog_b
         cdef Matrix mvp
 
-        back = self.background
-        game = self.game
+        game_x, game_y = game.interface.game_pos
+        glViewport(game_x, game_y, game.width, game.height)
+        glClear(GL_DEPTH_BUFFER_BIT)
+        glScissor(game_x, game_y, game.width, game.height)
+        glEnable(GL_SCISSOR_TEST)
 
         if self.use_fixed_pipeline:
             glMatrixMode(GL_PROJECTION)
@@ -50,7 +89,8 @@ cdef class GameRenderer(Renderer):
                 self.game_shader.uniform_matrix('mvp', self.game_mvp)
 
             self.render_elements([game.spellcard_effect])
-        elif back is not None:
+        elif self.background_renderer is not None:
+            back = self.background_renderer.background
             x, y, z = back.position_interpolator.values
             dx, dy, dz = back.position2_interpolator.values
             fog_b, fog_g, fog_r, fog_start, fog_end = back.fog_interpolator.values
@@ -106,7 +146,7 @@ cdef class GameRenderer(Renderer):
                 self.game_shader.bind()
                 self.game_shader.uniform_matrix('mvp', self.game_mvp)
 
-            self.render_elements(enemy for enemy in game.enemies if enemy.visible)
+            self.render_elements([enemy for enemy in game.enemies if enemy.visible])
             self.render_elements(game.effects)
             self.render_elements(chain(game.players_bullets,
                                        game.lasers_sprites(),
@@ -115,3 +155,68 @@ cdef class GameRenderer(Renderer):
             self.render_elements(chain(game.bullets, game.lasers,
                                        game.cancelled_bullets, game.items,
                                        game.labels))
+
+        if game.msg_runner:
+            rect = Rect(48, 368, 288, 48)
+            color1 = Color(0, 0, 0, 192)
+            color2 = Color(0, 0, 0, 128)
+            self.render_quads([rect], [(color1, color1, color2, color2)], 0)
+
+        glDisable(GL_SCISSOR_TEST)
+
+
+    cdef void render_text(self, texts):
+        if self.font_manager is None:
+            return
+
+        labels = [label for label in texts if label is not None]
+        self.font_manager.load(labels)
+
+        black = Color(0, 0, 0, 255)
+
+        for label in labels:
+            if label is None:
+                continue
+
+            rect = Rect(label.x, label.y, label.width, label.height)
+            gradient = [Color(*color, a=label.alpha) for color in label.gradient]
+
+            if label.shadow:
+                shadow_rect = Rect(label.x + 1, label.y + 1, label.width, label.height)
+                shadow = [black._replace(a=label.alpha)] * 4
+                self.render_quads([shadow_rect, rect], [shadow, gradient], label.texture)
+            else:
+                self.render_quads([rect], [gradient], label.texture)
+
+
+    cdef void render_interface(self, interface, game_boss):
+        elements = []
+
+        if self.use_fixed_pipeline:
+            glMatrixMode(GL_MODELVIEW)
+            glLoadMatrixf(self.interface_mvp.data)
+            glDisable(GL_FOG)
+        else:
+            self.interface_shader.bind()
+            self.interface_shader.uniform_matrix('mvp', self.interface_mvp)
+        glViewport(0, 0, interface.width, interface.height)
+
+        items = [item for item in interface.items if item.anmrunner and item.anmrunner.running]
+        labels = interface.labels.values()
+
+        if items:
+            # Redraw all the interface
+            elements.extend(items)
+        else:
+            # Redraw only changed labels
+            labels = [label for label in labels if label.changed]
+
+        elements.extend(interface.level_start)
+
+        if game_boss is not None:
+            elements.extend(interface.boss_items)
+
+        elements.extend(labels)
+        self.render_elements(elements)
+        for label in labels:
+            label.changed = False
--- a/pytouhou/ui/gamerunner.pyx
+++ b/pytouhou/ui/gamerunner.pyx
@@ -14,37 +14,23 @@
 
 from pytouhou.lib cimport sdl
 
-from pytouhou.lib.opengl cimport \
-         (glMatrixMode, glEnable, glDisable, glViewport, glScissor,
-          glLoadMatrixf, glGenBuffers, glDeleteBuffers, GL_MODELVIEW,
-          GL_FOG, GL_SCISSOR_TEST, glClear, GL_DEPTH_BUFFER_BIT)
-
-from pytouhou.utils.helpers import get_logger
-from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d
-
 from .window cimport Window
 from .gamerenderer cimport GameRenderer
-from .background import BackgroundRenderer
 from .music import MusicPlayer, SFXPlayer, NullPlayer
-from .shaders.eosd import GameShader, BackgroundShader
-
-from collections import namedtuple
-Rect = namedtuple('Rect', 'x y w h')
-Color = namedtuple('Color', 'r g b a')
-
-logger = get_logger(__name__)
 
 
-cdef class GameRunner(GameRenderer):
+cdef class GameRunner:
+    cdef object game, background
+    cdef GameRenderer renderer
     cdef Window window
     cdef object replay_level, save_keystates
     cdef long width, height, keystate
-    cdef bint skip
+    cdef bint skip, use_fixed_pipeline
 
     def __init__(self, window, resource_loader, bint skip=False):
         self.use_fixed_pipeline = window.use_fixed_pipeline #XXX
 
-        GameRenderer.__init__(self, resource_loader)
+        self.renderer = GameRenderer(resource_loader, self.use_fixed_pipeline)
 
         self.window = window
         self.replay_level = None
@@ -54,21 +40,13 @@ cdef class GameRunner(GameRenderer):
         self.width = window.width #XXX
         self.height = window.height #XXX
 
-        if not self.use_fixed_pipeline:
-            self.game_shader = GameShader()
-            self.background_shader = BackgroundShader()
-            self.interface_shader = self.game_shader
-
 
     def load_game(self, game=None, background=None, bgms=None, replay=None, save_keystates=None):
         self.game = game
         self.background = background
 
-        self.texture_manager.load(game.resource_loader.instanced_anms.values())
-
-        if background:
-            self.background_renderer = BackgroundRenderer(self.use_fixed_pipeline)
-            self.background_renderer.prerender(background)
+        self.renderer.texture_manager.load(game.resource_loader.instanced_anms.values())
+        self.renderer.load_background(background)
 
         self.set_input(replay)
         if replay and replay.levels[game.stage - 1]:
@@ -98,16 +76,13 @@ cdef class GameRunner(GameRenderer):
 
 
     def start(self):
-        width = self.game.interface.width if self.game else 640
-        height = self.game.interface.height if self.game else 480
-        if (width, height) != (self.width, self.height):
+        cdef long width, height
+        width = self.game.interface.width if self.game is not None else 640
+        height = self.game.interface.height if self.game is not None else 480
+        if width != self.width or height != self.height:
             self.window.set_size(width, height)
 
-        self.proj = perspective(30, float(self.game.width) / float(self.game.height),
-                                101010101./2010101., 101010101./10101.)
-        game_view = setup_camera(0, 0, 1)
-        self.game_mvp = game_view * self.proj
-        self.interface_mvp = ortho_2d(0., float(self.width), float(self.height), 0.)
+        self.renderer.start(self.game)
 
 
     def finish(self):
@@ -166,88 +141,7 @@ cdef class GameRunner(GameRenderer):
                 self.save_keystates.append(keystate)
 
             self.game.run_iter(keystate)
+            self.game.interface.labels['framerate'].set_text('%.2ffps' % self.window.get_fps())
         if not self.skip:
-            self.render_game()
-            self.render_text()
-            self.render_interface()
+            self.renderer.render(self.game)
         return True
-
-
-    def render_game(self):
-        # Switch to game projection
-        #TODO: move that to GameRenderer?
-        x, y = self.game.interface.game_pos
-        glViewport(x, y, self.game.width, self.game.height)
-        glClear(GL_DEPTH_BUFFER_BIT)
-        glScissor(x, y, self.game.width, self.game.height)
-        glEnable(GL_SCISSOR_TEST)
-
-        GameRenderer.render(self)
-
-        glDisable(GL_SCISSOR_TEST)
-
-        if self.game.msg_runner:
-            rect = Rect(48, 368, 288, 48)
-            color1 = Color(0, 0, 0, 192)
-            color2 = Color(0, 0, 0, 128)
-            self.render_quads([rect], [(color1, color1, color2, color2)], 0)
-
-
-    def render_text(self):
-        if self.font_manager is None:
-            return
-
-        labels = [label for label in self.game.texts + self.game.native_texts if label is not None]
-        self.font_manager.load(labels)
-
-        black = Color(0, 0, 0, 255)
-
-        for label in labels:
-            if label is None:
-                continue
-
-            rect = Rect(label.x, label.y, label.width, label.height)
-            gradient = [Color(*color, a=label.alpha) for color in label.gradient]
-
-            if label.shadow:
-                shadow_rect = Rect(label.x + 1, label.y + 1, label.width, label.height)
-                shadow = [black._replace(a=label.alpha)] * 4
-                self.render_quads([shadow_rect, rect], [shadow, gradient], label.texture)
-            else:
-                self.render_quads([rect], [gradient], label.texture)
-
-
-    def render_interface(self):
-        elements = []
-        interface = self.game.interface
-        interface.labels['framerate'].set_text('%.2ffps' % self.window.get_fps())
-
-        if self.use_fixed_pipeline:
-            glMatrixMode(GL_MODELVIEW)
-            glLoadMatrixf(self.interface_mvp.data)
-            glDisable(GL_FOG)
-        else:
-            self.interface_shader.bind()
-            self.interface_shader.uniform_matrix('mvp', self.interface_mvp)
-        glViewport(0, 0, self.width, self.height)
-
-        items = [item for item in interface.items if item.anmrunner and item.anmrunner.running]
-        labels = interface.labels.values()
-
-        if items:
-            # Redraw all the interface
-            elements.extend(items)
-        else:
-            # Redraw only changed labels
-            labels = [label for label in labels if label.changed]
-
-        elements.extend(interface.level_start)
-
-        if self.game.boss:
-            elements.extend(interface.boss_items)
-
-        elements.extend(labels)
-        self.render_elements(elements)
-        for label in labels:
-            label.changed = False
-