Changes on Console attributes memory_size, width and height do not imply console reset anymore

This commit is contained in:
devfred78
2022-02-15 18:59:22 +01:00
parent e8afb3a271
commit ffcba706d4
2 changed files with 242 additions and 15 deletions

View File

@@ -128,7 +128,11 @@ class Console():
DEFAULT_ALPHA = 255 # Default console transparency (0=invisible, 255=opaque)
DEFAULT_FOREGROUND_COLOUR = Colour(255,255,255,DEFAULT_ALPHA) # Default font colour
DEFAULT_BACKGROUND_COLOUR = Colour(0,0,0,DEFAULT_ALPHA) # Default background colour
DEFAULT_CHAR_MEMORY_SIZE = 80*24*10 # Default amount of memorized characters
DEFAULT_WIDTH = 80
DEFAULT_HEIGHT = 24
DEFAULT_MEMORY_SCREENS = 10
DEFAULT_CHAR_MEMORY_SIZE = DEFAULT_WIDTH*DEFAULT_HEIGHT*DEFAULT_MEMORY_SCREENS # Default amount of memorized characters
STANDARD_COLOURS = {
'black': Colour(0,0,0,DEFAULT_ALPHA),
@@ -155,7 +159,7 @@ class Console():
# Static methods
@staticmethod
def get_console(name = __name__, width = 80, height = 24, font_size = 10, font_transparency = DEFAULT_ALPHA, background_transparency = DEFAULT_ALPHA, logger = None):
def get_console(name = __name__, width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT, font_size = 10, font_transparency = DEFAULT_ALPHA, background_transparency = DEFAULT_ALPHA, logger = None):
"""
Return a Console instance.
@@ -255,7 +259,7 @@ class Console():
#############################################################
# Initialization
def __init__(self, name = __name__, width = 80, height = 24, font_size = 10, font_transparency = DEFAULT_ALPHA, background_transparency = DEFAULT_ALPHA, logger = None):
def __init__(self, name = __name__, width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT, font_size = 10, font_transparency = DEFAULT_ALPHA, background_transparency = DEFAULT_ALPHA, logger = None):
"""
Parameters
----------
@@ -558,7 +562,7 @@ class Console():
"""
Amount of memorized characters.
If modified, the console is re-initialized, and all memorized characters are lost. Its value must be higher or equal to the amount of displayable characters on the console surface. If not, the set value is ignored, and the attribute remains unchanged.
Its value must be higher or equal to the amount of displayable characters on the console surface. If not, the set value is ignored, and the attribute remains unchanged.
"""
return self._char_memory_size
@@ -566,11 +570,10 @@ class Console():
def memory_size(self, value):
if value >= self._width * self._height:
self._char_memory_size = value
# Console re-init
self._presentation_stream = deque([None] * self._width * self._height, self._char_memory_size)
self._cursor = 0
self._start_window = 0
self._end_window = self._width * self._height - 1
# Presentation stream update
self._temp_presentation_stream = deque([], self._char_memory_size)
self._temp_presentation_stream.extend(self._presentation_stream)
self._presentation_stream = self._temp_presentation_stream.copy()
else: self.log.warning(f"Memory cannot be less than {self._width * self._height}. The previous value is kept: {self._char_memory_size}")
@property
@@ -578,7 +581,7 @@ class Console():
"""
Console width, in characters.
If modified, the console is re-initialized, and all memorized characters are lost. If the set value is negative or null, it is ignored, and the attribute remains unchanged.
If the set value is negative or null, it is ignored, and the attribute remains unchanged.
"""
return self._width
@@ -586,8 +589,22 @@ class Console():
def width(self, value):
if value > 0:
self._width = value
# Console re-init
self._init_console()
self.log.info(f"Width console update. New value = {self._width}")
# Memory size update
self.memory_size = self._width * self._height * Console.DEFAULT_MEMORY_SCREENS
# Presentation stream padding if necessary
self._end_window = self._start_window + self._width * self._height - 1
if len(self._presentation_stream) < self._end_window + 1:
padding = [None] * (self._end_window + 1 - len(self._presentation_stream))
self._presentation_stream.extend(padding)
# Surface render update
with self._update_surface_lock:
char_width, char_height = self._normal_font.size(" ") # Works only with fixed-width fonts !
surf_width = char_width * self._width
surf_height = char_height * self._height
self._current_surface = pygame.Surface((surf_width, surf_height), flags=SRCALPHA)
self._current_surface = self._current_surface.convert_alpha()
self._render_all()
else: self.log.warning(f"Console width cannot be negative. The previous value is kept: {self._width}")
@property
@@ -595,7 +612,7 @@ class Console():
"""
Console height, in characters.
If modified, the console is re-initialized, and all memorized characters are lost. If the set value is negative or null, it is ignored, and the attribute remains unchanged.
If the set value is negative or null, it is ignored, and the attribute remains unchanged.
"""
return self._height
@@ -603,8 +620,22 @@ class Console():
def height(self, value):
if value > 0:
self._height = value
# Console re-init
self._init_console()
self.log.info(f"Height console update. New value = {self._height}")
# Memory size update
self.memory_size = self._width * self._height * Console.DEFAULT_MEMORY_SCREENS
# Presentation stream padding if necessary
self._end_window = self._start_window + self._width * self._height - 1
if len(self._presentation_stream) < self._end_window + 1:
padding = [None] * (self._end_window + 1 - len(self._presentation_stream))
self._presentation_stream.extend(padding)
# Surface render update
with self._update_surface_lock:
char_width, char_height = self._normal_font.size(" ") # Works only with fixed-width fonts !
surf_width = char_width * self._width
surf_height = char_height * self._height
self._current_surface = pygame.Surface((surf_width, surf_height), flags=SRCALPHA)
self._current_surface = self._current_surface.convert_alpha()
self._render_all()
else: self.log.warning(f"Console height cannot be negative. The previous value is kept: {self._height}")
#############################################################

View File

@@ -0,0 +1,196 @@
# -*- coding: utf-8 -*-
"""
'console' test set : tests regarding only the pygconsole.console submodule
Test 12_1 : Test console sizes, with no clearance when changing dimensions.
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(700,100) # 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
CONSOLE_DEFAULT_FONT_SIZE = 10 # Default font size displayed on the console
CONSOLE_DEFAULT_WIDTH = 80 # Default width of the console, in characters
CONSOLE_DEFAULT_HEIGHT = 24 # Default height of the console, in characters
TEXT_LIST = [
"Test 12_1: Test console sizes with no clearance when changing dimensions",
"Press '+' to increase font size",
"Press '-' to decrease size",
"Press 'UP or DOWN arrow' to change height",
"Press 'LEFT or RIGHT arrow' to change width",
"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_font_size = CONSOLE_DEFAULT_FONT_SIZE
console_width = CONSOLE_DEFAULT_WIDTH
console_height = CONSOLE_DEFAULT_HEIGHT
console = pygconsole.console.Console.get_console(name = f"console{console_font_size}", width = console_width, height = console_height, font_size = console_font_size, 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_font_size += 1
console = pygconsole.console.Console.get_console(name = f"console{console_font_size}", width = console_width, height = console_height, font_size = console_font_size, logger = log)
# set dimensions again for consoles already initialized
console.height = console_height
console.width = console_width
console.clear()
console.add_char(LONG_TEXT)
elif event.key == K_MINUS or event.key == K_KP_MINUS:
console_font_size -= 1
if console_font_size <= 0: console_font_size = 1
console = pygconsole.console.Console.get_console(name = f"console{console_font_size}", width = console_width, height = console_height, font_size = console_font_size, logger = log)
# set dimensions again for consoles already initialized
console.height = console_height
console.width = console_width
console.clear()
console.add_char(LONG_TEXT)
elif event.key == K_UP:
console_height += 1
console.height = console_height
# No text added
# console.add_char(LONG_TEXT)
elif event.key == K_DOWN:
console_height -= 1
if console_height <= 0: console_height = 1
console.height = console_height
# No text added
# console.add_char(LONG_TEXT)
elif event.key == K_RIGHT:
console_width += 1
console.width = console_width
# No text added
# console.add_char(LONG_TEXT)
elif event.key == K_LEFT:
console_width -= 1
if console_width <= 0: console_width = 1
console.width = console_width
# No text added
# console.add_char(LONG_TEXT)
# 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)
# Additional line: level of opacity
text_line = f"Font size: {console_font_size}"
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)
# Screen rendering
pygame.display.flip()
# Main program,
# running only if the module is NOT imported (but directly executed)
#-------------------------------------------------------------------
if __name__ == '__main__':
main()