# HG changeset patch # User Emmanuel Gil Peyrot # Date 1378907719 -7200 # Node ID 36bc577b23925c378818098bbae0e97770286956 # Parent 11708a1d0a1adaf22805761c3f7546f9214a4d11 Make the window resizable, and scale its content correctly. diff --git a/pytouhou/lib/_sdl.pxd b/pytouhou/lib/_sdl.pxd --- a/pytouhou/lib/_sdl.pxd +++ b/pytouhou/lib/_sdl.pxd @@ -43,6 +43,7 @@ cdef extern from "SDL_video.h" nogil: SDL_WINDOWPOS_CENTERED SDL_WINDOW_OPENGL SDL_WINDOW_SHOWN + SDL_WINDOW_RESIZABLE ctypedef struct SDL_Window: pass @@ -76,6 +77,7 @@ cdef extern from "SDL_events.h" nogil: ctypedef enum SDL_EventType: SDL_KEYDOWN SDL_QUIT + SDL_WINDOWEVENT ctypedef struct SDL_Keysym: SDL_Scancode scancode @@ -84,9 +86,19 @@ cdef extern from "SDL_events.h" nogil: Uint32 type SDL_Keysym keysym + ctypedef enum SDL_WindowEventID: + SDL_WINDOWEVENT_RESIZED + + ctypedef struct SDL_WindowEvent: + Uint32 type + SDL_WindowEventID event + int data1 + int data2 + ctypedef union SDL_Event: Uint32 type SDL_KeyboardEvent key + SDL_WindowEvent window int SDL_PollEvent(SDL_Event *event) diff --git a/pytouhou/lib/sdl.pxd b/pytouhou/lib/sdl.pxd --- a/pytouhou/lib/sdl.pxd +++ b/pytouhou/lib/sdl.pxd @@ -23,6 +23,7 @@ cdef SDL_GLattr GL_DEPTH_SIZE cdef SDL_WindowFlags WINDOWPOS_CENTERED cdef SDL_WindowFlags WINDOW_OPENGL cdef SDL_WindowFlags WINDOW_SHOWN +cdef SDL_WindowFlags WINDOW_RESIZABLE #TODO: should be SDL_Scancode, but Cython doesn’t allow enum for array indexing. cdef long SCANCODE_Z @@ -35,8 +36,11 @@ cdef long SCANCODE_RIGHT cdef long SCANCODE_LCTRL cdef long SCANCODE_ESCAPE +cdef SDL_WindowEventID WINDOWEVENT_RESIZED + cdef SDL_EventType KEYDOWN cdef SDL_EventType QUIT +cdef SDL_EventType WINDOWEVENT cdef class Window: diff --git a/pytouhou/lib/sdl.pyx b/pytouhou/lib/sdl.pyx --- a/pytouhou/lib/sdl.pyx +++ b/pytouhou/lib/sdl.pyx @@ -20,6 +20,7 @@ GL_DEPTH_SIZE = SDL_GL_DEPTH_SIZE WINDOWPOS_CENTERED = SDL_WINDOWPOS_CENTERED WINDOW_OPENGL = SDL_WINDOW_OPENGL WINDOW_SHOWN = SDL_WINDOW_SHOWN +WINDOW_RESIZABLE = SDL_WINDOW_RESIZABLE SCANCODE_Z = SDL_SCANCODE_Z SCANCODE_X = SDL_SCANCODE_X @@ -31,8 +32,11 @@ SCANCODE_RIGHT = SDL_SCANCODE_RIGHT SCANCODE_LCTRL = SDL_SCANCODE_LCTRL SCANCODE_ESCAPE = SDL_SCANCODE_ESCAPE +WINDOWEVENT_RESIZED = SDL_WINDOWEVENT_RESIZED + KEYDOWN = SDL_KEYDOWN QUIT = SDL_QUIT +WINDOWEVENT = SDL_WINDOWEVENT class SDLError(Exception): @@ -207,6 +211,8 @@ cdef list poll_events(): ret.append((event.type, event.key.keysym.scancode)) elif event.type == SDL_QUIT: ret.append((event.type,)) + elif event.type == SDL_WINDOWEVENT: + ret.append((event.type, event.window.event, event.window.data1, event.window.data2)) return ret diff --git a/pytouhou/ui/gamerenderer.pxd b/pytouhou/ui/gamerenderer.pxd --- a/pytouhou/ui/gamerenderer.pxd +++ b/pytouhou/ui/gamerenderer.pxd @@ -11,7 +11,7 @@ cdef class GameRenderer(Renderer): cdef void load_background(self, background) cdef void start(self, game) - cdef void render(self, game) + cdef void render(self, game, window) cdef void render_game(self, game) cdef void render_text(self, texts) cdef void render_interface(self, interface, game_boss) diff --git a/pytouhou/ui/gamerenderer.pyx b/pytouhou/ui/gamerenderer.pyx --- a/pytouhou/ui/gamerenderer.pyx +++ b/pytouhou/ui/gamerenderer.pyx @@ -60,7 +60,7 @@ cdef class GameRenderer(Renderer): self.interface_mvp = ortho_2d(0., float(game.interface.width), float(game.interface.height), 0.) - cdef void render(self, game): + cdef void render(self, game, window): if not self.use_fixed_pipeline: self.framebuffer.bind() @@ -71,7 +71,7 @@ cdef class GameRenderer(Renderer): if not self.use_fixed_pipeline: self.passthrough_shader.bind() self.passthrough_shader.uniform_matrix('mvp', self.interface_mvp) - self.render_framebuffer(self.framebuffer) + self.render_framebuffer(self.framebuffer, window) cdef void render_game(self, game): diff --git a/pytouhou/ui/gamerunner.pyx b/pytouhou/ui/gamerunner.pyx --- a/pytouhou/ui/gamerunner.pyx +++ b/pytouhou/ui/gamerunner.pyx @@ -25,12 +25,10 @@ cdef class GameRunner(Runner): cdef Window window cdef object replay_level, save_keystates cdef long keystate - cdef bint skip, use_fixed_pipeline + cdef bint skip - def __init__(self, window, resource_loader, bint skip=False): - self.use_fixed_pipeline = window.use_fixed_pipeline #XXX - - self.renderer = GameRenderer(resource_loader, self.use_fixed_pipeline) + def __init__(self, Window window, resource_loader, bint skip=False): + self.renderer = GameRenderer(resource_loader, window.use_fixed_pipeline) self.window = window self.replay_level = None @@ -98,6 +96,10 @@ cdef class GameRunner(Runner): return False #TODO: implement the pause. 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 self.game: if self.replay_level is None: #TODO: allow user settings @@ -135,5 +137,5 @@ cdef class GameRunner(Runner): self.game.run_iter(keystate) self.game.interface.labels['framerate'].set_text('%.2ffps' % self.window.get_fps()) if not self.skip: - self.renderer.render(self.game) + self.renderer.render(self.game, self.window) return True diff --git a/pytouhou/ui/renderer.pxd b/pytouhou/ui/renderer.pxd --- a/pytouhou/ui/renderer.pxd +++ b/pytouhou/ui/renderer.pxd @@ -1,4 +1,5 @@ from cpython cimport PyObject +from .window cimport Window from pytouhou.lib.opengl cimport GLuint cdef struct Vertex: @@ -25,7 +26,7 @@ cdef class Renderer: cpdef render_elements(self, elements) cpdef render_quads(self, rects, colors, texture) - cpdef render_framebuffer(self, Framebuffer fb) + cpdef render_framebuffer(self, Framebuffer fb, Window window) cdef class Framebuffer: diff --git a/pytouhou/ui/renderer.pyx b/pytouhou/ui/renderer.pyx --- a/pytouhou/ui/renderer.pyx +++ b/pytouhou/ui/renderer.pyx @@ -217,7 +217,7 @@ cdef class Renderer: glBindBuffer(GL_ARRAY_BUFFER, 0) - cpdef render_framebuffer(self, Framebuffer fb): + cpdef render_framebuffer(self, Framebuffer fb, Window window): cdef PassthroughVertex[4] buf cdef unsigned short indices[6] indices[:] = [0, 1, 2, 2, 3, 0] @@ -225,7 +225,7 @@ cdef class Renderer: assert not self.use_fixed_pipeline glBindFramebuffer(GL_FRAMEBUFFER, 0) - glViewport(0, 0, 640, 480) + glViewport(window.x, window.y, window.width, window.height) glBlendFunc(GL_ONE, GL_ZERO) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) diff --git a/pytouhou/ui/window.pxd b/pytouhou/ui/window.pxd --- a/pytouhou/ui/window.pxd +++ b/pytouhou/ui/window.pxd @@ -21,7 +21,7 @@ cdef class Runner: cdef class Window: cdef sdl.Window win cdef long fps_limit - cdef public long width, height + cdef public long x, y, width, height cdef public bint use_fixed_pipeline cdef Runner runner cdef Clock clock diff --git a/pytouhou/ui/window.pyx b/pytouhou/ui/window.pyx --- a/pytouhou/ui/window.pyx +++ b/pytouhou/ui/window.pyx @@ -12,6 +12,7 @@ ## GNU General Public License for more details. ## +cimport cython from pytouhou.lib.opengl cimport \ (glEnable, glHint, glEnableClientState, GL_TEXTURE_2D, GL_BLEND, @@ -100,10 +101,14 @@ cdef class Window: self.width, self.height = size if size is not None else (640, 480) + flags = sdl.WINDOW_OPENGL | sdl.WINDOW_SHOWN + if not self.use_fixed_pipeline: + flags |= sdl.WINDOW_RESIZABLE + self.win = sdl.Window('PyTouhou', sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, self.width, self.height, - sdl.WINDOW_OPENGL | sdl.WINDOW_SHOWN) + flags) self.win.gl_create_context() IF USE_GLEW: @@ -123,9 +128,22 @@ cdef class Window: self.clock = Clock(self.fps_limit) + @cython.cdivision(True) cdef void set_size(self, int width, int height) nogil: self.win.set_window_size(width, height) + runner_width = float(self.runner.width) + runner_height = float(self.runner.height) + + scale = min(width / runner_width, + height / runner_height) + + self.width = int(runner_width * scale) + self.height = int(runner_height * scale) + + self.x = (width - self.width) // 2 + self.y = (height - self.height) // 2 + cpdef set_runner(self, Runner runner=None): self.runner = runner