From dff7840e6f2562a4b8bee69030a5ba7daa486a60 Mon Sep 17 00:00:00 2001 From: devfred78 <97401939+devfred78@users.noreply.github.com> Date: Fri, 11 Feb 2022 18:15:32 +0100 Subject: [PATCH 1/5] add test for transparency --- tests/test11_console_Transparency.py | 149 +++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 tests/test11_console_Transparency.py diff --git a/tests/test11_console_Transparency.py b/tests/test11_console_Transparency.py new file mode 100644 index 0000000..ee5b755 --- /dev/null +++ b/tests/test11_console_Transparency.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- + +""" + 'console' test set : tests regarding only the pygconsole.console submodule + Test 11 : Test transparency feature. + ESCAPE Key to exit. +""" + + +# Standard modules +#----------------- +import sys +import os +from collections import namedtuple +import logging + +# Third party modules +#-------------------- +import pygame +from pygame.locals import * +from colorlog import ColoredFormatter + +# Internal modules +#----------------- +if __name__ == '__main__': + sys.path.append(os.path.join(os.path.dirname(__file__),'..')) + import pygconsole +else: + from .. import pygconsole + +# namedtuples +#------------ +Coordinates = namedtuple("Coordinates", "x y") +Colour = namedtuple("Colour", "red green blue alpha") + +# Global constants +#----------------- +RESOURCE_DIR = os.path.join(os.path.dirname(__file__),"resources") # directory where graphical resources are stored +BACKGROUND_IMAGE = os.path.join(RESOURCE_DIR,"background.jpg") # Background image +FONT = None # Font displayed outside of the console (None = default pygame font) + +DISPLAY_SIZE = Coordinates(1920,1080) # screen resolution +CONSOLE_COORDINATES = Coordinates(1000,620) # upper left corner coordinates of the console +FRAMERATE = 50 # Maximum number of displaying loops per second + +FONT_SIZE = 40 # size of the font displayed on the screen, but out of the console +FONT_COLOUR = Colour(255,0,0,255) # Colour of the font displayed outside of the console +TEXT_COORDINATES = Coordinates(50,50) # Coordinates of the first line of the text displayed outside of the console + +TEXT_LIST = [ + "Test 11: Test transparency feature", + "Press '+' to increase opacity of the console", + "Press '-' to decrease opacity.", + "ESCAPE key to exit." + ] + +LONG_TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vitae nunc dictum, sagittis elit venenatis, efficitur justo. Etiam suscipit, ipsum accumsan aliquam elementum, massa tellus pellentesque lacus, ut porttitor ligula tortor at urna. Duis eu felis non tortor bibendum ultrices. Aliquam tortor velit, suscipit faucibus nunc quis, blandit posuere leo. Donec dignissim aliquam lectus, vitae lacinia risus feugiat non. Curabitur dapibus, massa quis eleifend lobortis, nulla sem ullamcorper turpis, vel sodales risus orci non velit. Nam ac neque faucibus, consequat eros eu, viverra neque. Nulla vel blandit lorem. Nam interdum nisl non sem pretium dictum. Phasellus id sapien vitae ipsum efficitur fringilla. Quisque suscipit consequat erat quis commodo. Aenean tristique felis libero, et ultrices justo porttitor eget. Vivamus sit amet urna nibh. Ut ultrices nulla et dui eleifend, ut sagittis ipsum condimentum. Mauris nec dolor eget augue gravida lacinia. " + +# Dataclasses +#------------ + +# Classes +#-------- + + +# Functions +#---------- + + +# Main function +#-------------- +def main(): + """ Main program execution""" + + # Logging initialization + formatter = ColoredFormatter( + '%(log_color)s[%(asctime)s][%(levelname)s][%(name)s]:%(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + reset=True, + log_colors={ + 'DEBUG': 'cyan', + 'INFO': 'green', + 'WARNING': 'yellow', + 'ERROR': 'red', + 'CRITICAL': 'red,bg_white' + }, + secondary_log_colors={}, + style='%' + ) + handler = logging.StreamHandler() + handler.setLevel(logging.DEBUG) + handler.setFormatter(formatter) + log = logging.getLogger('display') + log.setLevel(logging.DEBUG) + log.addHandler(handler) + + + # screen initialization + pygame.init() + clock = pygame.time.Clock() # timer to control framerate + flags = FULLSCREEN|SCALED|DOUBLEBUF + screen_surface = pygame.display.set_mode(size=DISPLAY_SIZE,flags=flags) + background_surface = pygame.image.load(BACKGROUND_IMAGE) + + # Font initialization + font = pygame.font.Font(FONT,FONT_SIZE) + line_space = font.get_linesize() + + # console initialization + console = pygconsole.console.Console.get_console(logger = log) + console.add_char(LONG_TEXT) + + # Displaying loop + while True: + clock.tick(FRAMERATE) + + # Events + for event in pygame.event.get(): + if event.type == QUIT: sys.exit() + if event.type == KEYDOWN: + if event.key == K_ESCAPE: sys.exit() + elif event.key == K_PLUS or event.key == K_KP_PLUS: + console.background_transparency += 1 + elif event.key == K_MINUS or event.key == K_KP_MINUS: + console.background_transparency -= 1 + + # Background display + screen_surface.blit(background_surface,(0,0)) + + # Text display + text_line_coordinates = TEXT_COORDINATES + for text_line in TEXT_LIST: + text_surface = font.render(text_line,True,FONT_COLOUR) + screen_surface.blit(text_surface,text_line_coordinates) + text_line_coordinates = text_line_coordinates._replace(y=text_line_coordinates.y+line_space) + + # Console display + screen_surface.blit(console.surface,CONSOLE_COORDINATES) + + # Screen rendering + pygame.display.flip() + + +# Main program, +# running only if the module is NOT imported (but directly executed) +#------------------------------------------------------------------- +if __name__ == '__main__': + main() + \ No newline at end of file From 7626a7902373b862baeb6b9ef33987665e1327c1 Mon Sep 17 00:00:00 2001 From: devfred78 <97401939+devfred78@users.noreply.github.com> Date: Fri, 11 Feb 2022 18:17:00 +0100 Subject: [PATCH 2/5] add control for transparency values --- pygconsole/console.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pygconsole/console.py b/pygconsole/console.py index 3b04d55..90f9c46 100644 --- a/pygconsole/console.py +++ b/pygconsole/console.py @@ -476,8 +476,11 @@ class Console(): self.log.warning(f"{value} cannot be applied to a transparency value. The default value is kept: {self.Console.DEFAULT_ALPHA}") value_int = Console.DEFAULT_ALPHA finally: + if value_int > 255: value_int = 255 + elif value_int < 0: value_int = 0 self._font_transparency = value_int self.log.debug(f"The font transparency is set to {value_int}.") + self._render_all() @property def background_transparency(self): @@ -494,8 +497,11 @@ class Console(): self.log.warning(f"{value} cannot be applied to a transparency value. The default value is kept: {self.Console.DEFAULT_ALPHA}") value_int = Console.DEFAULT_ALPHA finally: + if value_int > 255: value_int = 255 + elif value_int < 0: value_int = 0 self._background_transparency = value_int self.log.debug(f"The background transparency is set to {value_int}.") + self._render_all() @property def italic(self): From eeba208ea96c511e2f6c62784d3d5dc5cdccfd35 Mon Sep 17 00:00:00 2001 From: devfred78 <97401939+devfred78@users.noreply.github.com> Date: Sat, 12 Feb 2022 21:30:38 +0100 Subject: [PATCH 3/5] display level of opacity on test 11 --- tests/test11_console_Transparency.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test11_console_Transparency.py b/tests/test11_console_Transparency.py index ee5b755..2e91ec2 100644 --- a/tests/test11_console_Transparency.py +++ b/tests/test11_console_Transparency.py @@ -133,6 +133,10 @@ def main(): text_surface = font.render(text_line,True,FONT_COLOUR) screen_surface.blit(text_surface,text_line_coordinates) text_line_coordinates = text_line_coordinates._replace(y=text_line_coordinates.y+line_space) + # Additional line: level of opacity + text_line = f"Level of opacity (0-255): {console.background_transparency}" + text_surface = font.render(text_line,True,FONT_COLOUR) + screen_surface.blit(text_surface,text_line_coordinates) # Console display screen_surface.blit(console.surface,CONSOLE_COORDINATES) From 452a204da7ed5ccbcc09dc59321f9370982892b6 Mon Sep 17 00:00:00 2001 From: devfred78 <97401939+devfred78@users.noreply.github.com> Date: Sat, 12 Feb 2022 21:34:03 +0100 Subject: [PATCH 4/5] the project becomes dependent on NumPy --- README.md | 6 ++++++ setup.cfg | 1 + 2 files changed, 7 insertions(+) diff --git a/README.md b/README.md index 49ff5ec..2e233f8 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,12 @@ pygconsole depends on the following packages. The installation of pygconsole sho pip install colorlog ``` +* numpy: version 1.22.0 or above + + ```sh + pip install numpy + ``` + ### Installation Install from PyPi with: diff --git a/setup.cfg b/setup.cfg index 9b6b6fa..9bd8002 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,6 +29,7 @@ packages = pygconsole install_requires = pygame >= 2.1.0 colorlog >= 6.4.1 + numpy >= 1.22.0 python_requires = >= 3.8 [options.packages.find] From 5083ab2ec9b74c46ae12aa0b5b4ff47535e161d8 Mon Sep 17 00:00:00 2001 From: devfred78 <97401939+devfred78@users.noreply.github.com> Date: Sat, 12 Feb 2022 21:38:30 +0100 Subject: [PATCH 5/5] the 'background_transparency' attribute becomes active, the whole opacity can be modified dynamically using this attribute --- pygconsole/console.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/pygconsole/console.py b/pygconsole/console.py index 90f9c46..709422f 100644 --- a/pygconsole/console.py +++ b/pygconsole/console.py @@ -307,8 +307,13 @@ class Console(): surf_width = char_width * self._width surf_height = char_height * self._height self._current_surface = pygame.Surface((surf_width, surf_height), flags=SRCALPHA) - with pygame.PixelArray(self._current_surface) as currentpxarray: - currentpxarray[:] = pygame.Color(0, 0, 0, 0) # invisible surface by default + self._current_surface = self._current_surface.convert_alpha() + + # set the default transparency + surface_alpha_array = pygame.surfarray.pixels_alpha(self._current_surface) + surface_alpha_array[:] = Console.DEFAULT_ALPHA + del(surface_alpha_array) + self._previous_surface = self._current_surface.copy() # Presentation stream initialization @@ -843,9 +848,15 @@ class Console(): local_font.underline = self._presentation_stream[index].underline font_surf = local_font.render(self._presentation_stream[index].str, True, self._presentation_stream[index].foreground_colour, self._presentation_stream[index].background_colour) + # set transparency + font_surf = font_surf.convert_alpha() + font_alpha_array = pygame.surfarray.pixels_alpha(font_surf) + font_alpha_array[:] = self._background_transparency + del(font_alpha_array) + with self._update_surface_lock: self._current_surface.blit(font_surf,coord_char) - # self._current_surface = self._current_surface.convert_alpha() + self._current_surface = self._current_surface.convert_alpha() self._previous_surface = self._current_surface.copy() @@ -877,11 +888,17 @@ class Console(): local_font.underline = self._presentation_stream[index].underline font_surf = local_font.render(self._presentation_stream[index].str, True, self._presentation_stream[index].foreground_colour, self._presentation_stream[index].background_colour) - surf_to_blit.append((font_surf,coord_char)) + # set transparency + font_surf = font_surf.convert_alpha() + font_alpha_array = pygame.surfarray.pixels_alpha(font_surf) + font_alpha_array[:] = self._background_transparency + del(font_alpha_array) + + surf_to_blit.append((font_surf,coord_char,font_surf.get_rect())) with self._update_surface_lock: self._current_surface.blits(surf_to_blit,doreturn=False) - # self._current_surface = self._current_surface.convert_alpha() + self._current_surface = self._current_surface.convert_alpha() self._previous_surface = self._current_surface.copy() @@ -906,10 +923,14 @@ class Console(): local_font.underline = self._presentation_stream[index].underline font_surf = local_font.render(self._presentation_stream[index].str, True, self._presentation_stream[index].foreground_colour, self._presentation_stream[index].background_colour) - surf_to_blit.append((font_surf,coord_char)) + surf_to_blit.append((font_surf,coord_char,font_surf.get_rect())) with self._update_surface_lock: self._current_surface.blits(surf_to_blit,doreturn=False) - # self._current_surface = self._current_surface.convert_alpha() + # set transparency + self._current_surface = self._current_surface.convert_alpha() + surface_alpha_array = pygame.surfarray.pixels_alpha(self._current_surface) + surface_alpha_array[:] = self._background_transparency + del(surface_alpha_array) self._previous_surface = self._current_surface.copy()