diff pytouhou/ui/gamerenderer.pyx @ 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 a71b912b45b7
line wrap: on
line diff
--- 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