Source code for pyparadigm.misc

"""Contains code that did not make it into an own module.

"""

import contextlib
with contextlib.redirect_stdout(None):
    import pygame
    import pygame.ftfont
from . import surface_composition as sc

import os
import time
from functools import lru_cache
from threading import Thread

class _PumpThread(Thread):
    """See the documentation for the interactive_mode arg from :ref:`init`"""
    def run(self):
        while self._run:
            pygame.event.pump()
            time.sleep(0.1)

    def stop(self):
        self._run = False
        self.join()

    def __init__(self):
        super().__init__()
        self._run = True
        self.start()


[docs]def init(resolution, pygame_flags=0, display_pos=(0, 0), interactive_mode=False, title='Pygame Window'): """Creates a window of given resolution. :param resolution: the resolution of the windows as (width, height) in pixels :type resolution: tuple :param pygame_flags: modify the creation of the window. For further information see :ref:`creating_a_window` :type pygame_flags: int :param display_pos: determines the position on the desktop where the window is created. In a multi monitor system this can be used to position the window on a different monitor. E.g. the monitor to the right of the main-monitor would be at position (1920, 0) if the main monitor has the width 1920. :type display_pos: tuple :param interactive_mode: Will install a thread, that emptys the event-queue every 100ms. This is neccessary to be able to use the display() function in an interactive console on windows systems. If interactive_mode is set, init() will return a reference to the background thread. This thread has a stop() method which can be used to cancel it. If you use ctrl+d or exit() within ipython, while the thread is still running, ipython will become unusable, but not close. :type interactive_mode: bool :param title: the Title of the Window :type title: str :return: a reference to the display screen, or a reference to the background thread if interactive_mode was set to true. In the second scenario you can obtain a reference to the display surface via pygame.display.get_surface() :rtype: pygame.Surface """ os.environ['SDL_VIDEO_WINDOW_POS'] = "{}, {}".format(*display_pos) pygame.init() pygame.ftfont.init() disp = pygame.display.set_mode(resolution, pygame_flags) pygame.display.set_caption(title) return _PumpThread() if interactive_mode else disp
[docs]def display(surface): """Displays a pygame.Surface in the window. in pygame the window is represented through a surface, on which you can draw as on any other pygame.Surface. A refernce to to the screen can be optained via the :py:func:`pygame.display.get_surface` function. To display the contents of the screen surface in the window :py:func:`pygame.display.flip` needs to be called. :py:func:`display` draws the surface onto the screen surface at the postion (0, 0), and then calls :py:func:`flip`. :param surface: the pygame.Surface to display :type surface: pygame.Surface """ screen = pygame.display.get_surface() screen.blit(surface, (0, 0)) pygame.display.flip()
[docs]def slide_show(slides, continue_handler): """Displays one "slide" after another. After displaying a slide, continue_handler is called without arguments. When continue_handler returns, the next slide is displayed. Usage example :: slide_show(text_screens, partial(event_listener.wait_for_n_keypresses, pygame.K_RETURN)) (partial is imported from the functools module.) :param slides: pygame.Surfaces to be displayed. :type slides: iterable :param continue_handler: function, that returns when the next slide should be displayed. :type continue_handler: callable with arity 0. """ for slide in slides: display(slide) continue_handler()
[docs]def empty_surface(fill_color, size=None, flags=0): """Returns an empty surface filled with fill_color. :param fill_color: color to fill the surface with :type fill_color: pygame.Color :param size: the size of the new surface, if None its created to be the same size as the screen :type size: int-2-tuple """ if size is None: sr = pygame.display.get_surface().get_rect() surf = pygame.Surface((sr.w, sr.h), flags=flags) else: surf = pygame.Surface(size, flags=flags) surf.fill(fill_color) return surf
_char_mappings = { "\r": "\n", "\t": " " }
[docs]def rgba(colorcode, alpha=255): """Returns a pygame rgba color object, with the provided alpha value.""" return pygame.Color(colorcode * 0x100 + alpha)
[docs]def process_char(buffer: str, char: str, mappings=_char_mappings): """This is a convinience method for use with EventListener.wait_for_unicode_char(). In most cases it simply appends char to buffer. Some replacements are done because presing return will produce '\\r' but for most cases '\\n' would be desireable. Also backspace cant just be added to a string either, therefore, if char is "\\u0008" the last character from buffer will be cut off. The replacement from '\\r' to '\\n' is done using the mappings argument, the default value for it also contains a mapping from '\t' to 4 spaces. :param buffer: the string to be updated :type buffer: str :param char: the unicode character to be processed :type char: str :param mappings: a dict containing mappings :type mappings: dict :returns: a new string""" if char in mappings: return buffer + mappings[char] elif char == "\u0008": return buffer[:-1] if len(buffer) > 0 else buffer else: return buffer + char
[docs]def make_transparent_by_mask(surf, mask, copy=True): """Sets all voxels that are 1 in the mask to transparent. if surf has no alpha channel a new image is returned, if it does have one the behavior depends on the copy parameter""" if surf.get_flags() & pygame.SRCALPHA == 0: surf = surf.convert_alpha() elif copy: surf = surf.copy() pix_arr = pygame.surfarray.pixels_alpha(surf) pix_arr[mask.astype(bool)] = 0 return surf
[docs]def make_transparent_by_colorkey(surf, colorkey, copy=True): """Makes image transparent, and sets all pixel of a certain color transparent This is useful if images should be scaled and smoothed, as this will change the colors and make colorkeys useless, if surf has no alpha channel a new image is returned, if it does have one the behavior depends on the copy parameter""" if type(colorkey) != int: colorkey = surf.map_rgb(colorkey) pix_arr = pygame.surfarray.array2d(surf) mask = pix_arr == colorkey return make_transparent_by_mask(surf, mask, copy)