import pygame from pygame.locals import * from OpenGL.GL import * from queue import Queue from .renderer import ImageRenderer, TransitionMix from .manager import PixMan class PixDisplay: def __init__(self, textures): self.screen = None self.last_time = 0 self.start_time = 0 self.image_time = 0 self.paused = False self.textures = textures self.current_texture_index = 0 self.renderer = None self.win_w = 0 self.win_h = 0 self.transition_reverse = False self.text_prev = None self.tex = None self._force_redraw = False self.queue = Queue() self.update_config() def update_config(self): config = PixMan().config self.max_framerate = config.max_framerate self.image_duration = config.image_duration self.transition_duration = config.transition_duration self.auto_transition = config.auto_transition def update_textures(self, textures): self.textures = textures self.current_texture_index = 0 def increment_texture_index(self, increment): self.transition_reverse = increment < 0 self.tex_prev = self.textures[self.current_texture_index] self.current_texture_index = (self.current_texture_index + increment) % len(self.textures) self.tex = self.textures[self.current_texture_index] if not self.tex.initialized or not self.tex_prev.initialized: return # Ensure textures are initialized for opengl self.tex_prev.gl_init() self.tex.gl_init() # Main display function def display(self): # Calculate timings alive_time = pygame.time.get_ticks() / 1000 delta_time = alive_time - self.last_time self.last_time = alive_time if not self.tex or not self.tex.initialized or not self.tex.id: if self.textures.asset_count > 0: self.increment_texture_index(0) # Draw black window if no textures are available if not self.tex or not self.tex.id: glClearColor(0.0, 0.0, 0.0, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) pygame.display.flip() return # Run queue events while not self.queue.empty(): f = self.queue.get() # Get the task and its data f() # Progress image time if not self.paused: self.image_time += delta_time # Get window size old_win_w, old_win_h = self.win_w, self.win_h self.win_w, self.win_h = self.screen.get_size() # Draw static image except during a transition if self.image_time < self.image_duration: # Avoid unforced-redraw unless window size has changed if self._force_redraw or self.win_w != old_win_w or self.win_h != old_win_h: self.renderer.draw_static(self.tex, self.win_w, self.win_h, 1.0) self._force_redraw = False return # Start drawing transition once image_time >= image_duration if self.auto_transition: self.increment_texture_index(1) self.auto_transition = False transition_time = self.image_time - self.image_duration self.renderer.draw_transition(self.tex_prev, self.tex, self.win_w, self.win_h, delta_time, transition_time, self.transition_duration, self.transition_reverse) if transition_time >= self.transition_duration: self.image_time = 0 self.auto_transition = True def seek(self, increment): self.auto_transition = False self.increment_texture_index(increment) self.image_time = self.image_duration # Initialization and main loop def main(self, fullscreen=False): # Initialize the window pygame.init() self.screen = pygame.display.set_mode((0, 0), DOUBLEBUF | OPENGL | (FULLSCREEN if fullscreen else 0)) pygame.mouse.set_visible(False) # Set up the OpenGL viewport and projection glEnable(GL_TEXTURE_2D) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(-1, 1, -1, 1, -1, 1) glMatrixMode(GL_MODELVIEW) # Enable alpha blending glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # Setup renderer and slide timing self.renderer = ImageRenderer() self.renderer.set_transition(TransitionMix) self.image_time = 0 self.last_time = 0 # Run display clock = pygame.time.Clock() while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() return elif event.type == KEYDOWN: # Quit with escape or ctrl+q if event.key == pygame.K_ESCAPE or event.key == pygame.K_q and event.mod & pygame.KMOD_CTRL: pygame.quit() return # Seek with left/right arrow elif event.key == pygame.K_LEFT: self.seek(-1) elif event.key == pygame.K_RIGHT: self.seek(+1) self.display() clock.tick(self.max_framerate)