def __init__(self, text="", fg_color=None, bg_color=None, style=""): self.text = text """The text attribute. It needs to be a str.""" self.fg_color = None """The fg_color attribute sets the foreground color. It needs to be a :class:`~pyagemlib.gfx.core.Color`.""" if fg_color is None or pgl_isinstance(fg_color, "pygamelib.gfx.core.Color"): self.fg_color = fg_color else: raise PglInvalidTypeException( "Text(text, bg_color, fg_color, style): fg_color needs to be a " "pygamelib.gfx.core.Color object.") self.bg_color = None """The bg_color attribute sets the background color. It needs to be a :class:`~pyagemlib.gfx.core.Color`.""" if bg_color is None or pgl_isinstance(bg_color, "pygamelib.gfx.core.Color"): self.bg_color = bg_color else: raise PglInvalidTypeException( "Text(text, bg_color, fg_color, style): bg_color needs to be a " "pygamelib.gfx.core.Color object.") self.style = style """The style attribute sets the style of the text. It needs to be a str.""" self.parent = None """This object's parent. It needs to be a :class:`~pygamelib.board_items.BoardItem`.""" self._sprite = None self._item = None
def __init__(self, text="", fg_color=None, bg_color=None, style=""): super().__init__() self.__text = "" self.__bg_color = None self.__fg_color = None self.__fgcc = "" self.__bgcc = "" if type(text) is str: self.__text = text if fg_color is None or pgl_isinstance(fg_color, "pygamelib.gfx.core.Color"): self.__fg_color = fg_color else: raise PglInvalidTypeException( "Text(text, bg_color, fg_color, style): fg_color needs to be a " "pygamelib.gfx.core.Color object." ) if bg_color is None or pgl_isinstance(bg_color, "pygamelib.gfx.core.Color"): self.__bg_color = bg_color else: raise PglInvalidTypeException( "Text(text, bg_color, fg_color, style): bg_color needs to be a " "pygamelib.gfx.core.Color object." ) self.__build_color_cache() self.style = style """The style attribute sets the style of the text. It needs to be a str.""" self.parent = None """This object's parent. It needs to be a :class:`~pygamelib.board_items.BoardItem`.""" self._sprite_data = None self._item = None
def __build_color_cache(self): t = Console.instance() if self.bg_color is not None and pgl_isinstance( self.bg_color, "pygamelib.gfx.core.Color"): self.__bgcc = t.on_color_rgb(self.bg_color.r, self.bg_color.g, self.bg_color.b) if self.fg_color is not None and pgl_isinstance( self.fg_color, "pygamelib.gfx.core.Color"): self.__fgcc = t.color_rgb(self.fg_color.r, self.fg_color.g, self.fg_color.b)
def __repr__(self): t = Console.instance() bgc = fgc = "" if self.bg_color is not None and pgl_isinstance( self.bg_color, "pygamelib.gfx.core.Color"): bgc = t.on_color_rgb(self.bg_color.r, self.bg_color.g, self.bg_color.b) if self.fg_color is not None and pgl_isinstance( self.fg_color, "pygamelib.gfx.core.Color"): fgc = t.color_rgb(self.fg_color.r, self.fg_color.g, self.fg_color.b) return "".join([bgc, fgc, self.style, self.text, "\x1b[0m"])
def fg_color(self, value): if pgl_isinstance(value, "pygamelib.gfx.core.Color"): self.__fg_color = value else: raise PglInvalidTypeException( "Text.fg_color can only be a pygamelib.gfx.core.Color object." ) self.__build_color_cache()
def bg_color(self, value): if pgl_isinstance(value, "pygamelib.gfx.core.Color"): if self.__bg_color is not None: self.__bg_color.detach(self) self.__bg_color = value self.__bg_color.attach(self) elif value is None: if self.__bg_color is not None: self.__bg_color.detach(self) self.__bg_color = value self.__bgcc = Back.RESET else: raise PglInvalidTypeException( "Text.bg_color can only be a pygamelib.gfx.core.Color object.") self.__build_color_cache()
def fg_color(self, value): if pgl_isinstance(value, "pygamelib.gfx.core.Color"): if self.__fg_color is not None: self.__fg_color.detach(self) self.__fg_color = value self.__fg_color.attach(self) self.notify(self, "base.Text.fg_color:changed", value) elif value is None: if self.__fg_color is not None: self.__fg_color.detach(self) self.__fg_color = value self.notify(self, "base.Text.fg_color:changed", value) self.__fgcc = Fore.RESET else: raise PglInvalidTypeException( "Text.fg_color can only be a pygamelib.gfx.core.Color object.") self.__build_color_cache()
def test_screen_buffer(self): sprites_panda = SpriteCollection.load_json_file("tests/panda.spr") b = engine.Board(size=[20, 20]) s = engine.Screen() # This is a dirty hack for CircleCI as it returns a 0x0 screen size. if s.width <= 0 or s.height <= 0: s._display_buffer = np.array( [[Sprixel(" ") for i in range(0, 50, 1)] for j in range(0, 50, 1)] ) s._screen_buffer = np.array( [[Sprixel(" ") for i in range(0, 50, 1)] for j in range(0, 50, 1)] ) # Because CircleCI return a console with no size (most probably because we are # not attached to any terminal), we need to make sure that the partial display # tests work in that environment too screen_width = 0 screen_height = 0 if s.width <= 0: screen_width = 50 else: screen_width = s.width if s.height <= 0: screen_height = 50 else: screen_height = s.height self.assertEqual(s.vcenter, int(s.height / 2)) self.assertEqual(s.hcenter, int(s.width / 2)) b.place_item(board_items.Tile(sprite=sprites_panda["panda"]), 0, 0) self.assertIsInstance(b.render_cell(1, 1), Sprixel) b.item(19, 19).model = "@" b.item(19, 19).sprixel = None self.assertIsInstance(b.render_cell(19, 19), Sprixel) self.assertEqual(b.render_cell(19, 19), Sprixel()) with self.assertRaises(base.PglOutOfBoardBoundException): b.render_cell(50, 50) self.assertIsNone(s.clear_buffers()) self.assertIsNone(s.clear_screen_buffer()) # And again after clear buffers. if s.width <= 0 or s.height <= 0: s._display_buffer = np.array( [[Sprixel(" ") for i in range(0, 50, 1)] for j in range(0, 50, 1)] ) s._screen_buffer = np.array( [[Sprixel(" ") for i in range(0, 50, 1)] for j in range(0, 50, 1)] ) self.assertTrue(s._is_dirty) self.assertTrue(functions.pgl_isinstance(s.buffer, "numpy.ndarray")) self.assertIsNone(s.update()) b = engine.Board(size=[1, 1]) b.place_item(board_items.Wall(model="##"), 0, 0) self.assertIsNone(s.place("test", 0, 0)) self.assertIsNone(s.place(b, 1, 0)) t = base.Text("test 2") self.assertIsNone(s.place(t, 2, 0)) self.assertIsNone(s.place(sprites_panda["panda"], 0, 5)) self.assertIsNone(s.place(TB(), 3, 0)) self.assertIsNone(s.place(board_items.BoardItem(model="##"), 10, 0)) self.assertIsNone( s.place( board_items.Tile( sprixels=[ [Sprixel("##"), Sprixel("##")], [Sprixel("##"), Sprixel("##")], ] ), 4, 0, ) ) with self.assertRaises(base.PglInvalidTypeException): s.place(None, 0, 0) with self.assertRaises(base.PglInvalidTypeException): s.place(1, 0, 0) s.update() t.text = "update" self.assertIsNone( s.place(sprites_panda["panda"], screen_height - 2, screen_width - 2) ) self.assertIsNone(s.place("test", 1, screen_width - 2)) s.update() self.assertIsNone(s.render()) # Should not render self.assertFalse(s.need_rendering) s.trigger_rendering() self.assertTrue(s.need_rendering) # Now testing partial display camera = board_items.Camera() camera.row = 0 camera.column = 0 b = engine.Board( size=[screen_width * 2, screen_height * 2], enable_partial_display=True, partial_display_viewport=[ int(screen_height / 2) - 1, int(screen_width / 2) - 1, ], partial_display_focus=camera, DISPLAY_SIZE_WARNINGS=False, ) for row in range(0, b.height): for col in range(0, b.width): b.place_item( board_items.Wall( sprixel=Sprixel(" ", Color(row * 4, col, int((row + col) / 2))), ), row, col, ) self.assertIsNone(s.place(b, 0, 0, 2)) s.trigger_rendering() self.assertIsNone(s.update()) b.partial_display_viewport = [ int(screen_height * 3) - 1, int(screen_width * 3) - 1, ] camera.row += 1 with self.assertRaises(IndexError): s.force_render() s.update() b.partial_display_viewport = [ int(screen_height / 2) - 1, int(screen_width / 2) - 1, ] camera.row = b.height - 1 camera.column = b.width - 1 self.assertIsNone(s.trigger_rendering()) self.assertIsNone(s.update()) camera = board_items.Tile( sprite=Sprite( sprixels=[[Sprixel("+"), Sprixel("+")], [Sprixel("+"), Sprixel("+")]] ) ) b.partial_display_focus = camera # Please never do that in real life... camera.pos = [1, 1] self.assertIsNone(s.trigger_rendering()) self.assertIsNone(s.render()) self.assertIsNone(s.update()) # This will succeed but the str type cannot benefit from deferred rendering. self.assertIsNone(s.place("test delete", 0, 0, 2)) self.assertIsNone(s.update()) self.assertIsNone(s.delete(0, 0)) self.assertIsNone(s.update())
def __init__(self, text="", fg_color=None, bg_color=None, style="", font=None): """ :param text: The text to manipulate :type text: str :param fg_color: The foreground color for the text. :type fg_color: :class:`~pygamelib.gfx.core.Color` :param bg_color: The background color for the text. :type bg_color: :class:`~pygamelib.gfx.core.Color` :param style: The style for the text. :type style: str :param font: The font in which the text is going to be displayed (only works when using Screen.place() and Screen.update()) :type font: `~pygamelib.gfx.core.Font` """ super().__init__() self.__text = "" self.__bg_color = None self.__fg_color = None self.__fgcc = "" self.__bgcc = "" self.__length = 0 self.__font = None if type(text) is str: self.__text = text self.__length = self.__length = Console.instance().length( self.__text) if fg_color is None or pgl_isinstance(fg_color, "pygamelib.gfx.core.Color"): self.__fg_color = fg_color if fg_color is not None: fg_color.attach(self) else: raise PglInvalidTypeException( "Text(text, bg_color, fg_color, style): fg_color needs to be a " "pygamelib.gfx.core.Color object.") if bg_color is None or pgl_isinstance(bg_color, "pygamelib.gfx.core.Color"): self.__bg_color = bg_color if bg_color is not None: bg_color.attach(self) else: raise PglInvalidTypeException( "Text(text, bg_color, fg_color, style): bg_color needs to be a " "pygamelib.gfx.core.Color object.") self.__build_color_cache() self.style = style """The style attribute sets the style of the text. It needs to be a str.""" self.parent = None """This object's parent. It needs to be a :class:`~pygamelib.board_items.BoardItem`.""" self._sprite_data = None self._item = None if font is not None: if pgl_isinstance(font, "pygamelib.gfx.core.Font"): self.__font = font else: raise PglInvalidTypeException( "Text(): the font parameter needs to be a Font object.")
def test_screen_buffer(self): sprites_panda = SpriteCollection.load_json_file("tests/panda.spr") b = engine.Board(size=[20, 20]) s = engine.Screen(50, 50) # Because CircleCI return a console with no size (most probably because we are # not attached to any terminal), we need to make sure that the partial display # tests work in that environment too screen_width = 0 screen_height = 0 if s.width <= 0: screen_width = 50 else: screen_width = s.width if s.height <= 0: screen_height = 50 else: screen_height = s.height self.assertEqual(s.vcenter, int(s.height / 2)) self.assertEqual(s.hcenter, int(s.width / 2)) b.place_item(board_items.Tile(sprite=sprites_panda["panda"]), 0, 0) self.assertIsInstance(b.render_cell(1, 1), Sprixel) b.item(19, 19).model = "@" b.item(19, 19).sprixel = None self.assertIsInstance(b.render_cell(19, 19), Sprixel) self.assertEqual(b.render_cell(19, 19), Sprixel()) b.place_item(board_items.Door(), 19, 19) b.place_item( board_items.Door(sprixel=Sprixel( "*", Color(125, 125, 0), is_bg_transparent=False)), 19, 19, ) b.place_item( board_items.Door(sprixel=Sprixel("#", is_bg_transparent=True)), 19, 19) b.place_item( board_items.NPC(sprixel=Sprixel("$", is_bg_transparent=True)), 19, 19) self.assertEqual(b.layers(19, 19), 4) b.place_item( board_items.BoardItemVoid(sprixel=Sprixel(is_bg_transparent=True)), 19, 19) b.place_item( board_items.BoardItemVoid(sprixel=Sprixel(is_bg_transparent=True)), 19, 19) self.assertIsInstance(b.render_cell(19, 19), Sprixel) b._clean_layers(19, 19) self.assertEqual(b.layers(19, 19), 3) b._clean_layers(18, 19) self.assertEqual(b.layers(18, 19), 1) with self.assertRaises(base.PglOutOfBoardBoundException): b.render_cell(50, 50) self.assertIsNone(s.clear_buffers()) self.assertIsNone(s.clear_screen_buffer()) self.assertTrue(s._is_dirty) self.assertTrue(functions.pgl_isinstance(s.buffer, "numpy.ndarray")) self.assertIsNone(s.update()) b = engine.Board(size=[1, 1]) b.place_item(board_items.Wall(model="##"), 0, 0) self.assertIsNone(s.place("test", 0, 0)) self.assertIsNone(s.place(b, 1, 0)) self.assertIsInstance(s.get(1, 0), engine.Board) t = base.Text("test 2") self.assertIsNone(s.place(t, 2, 0)) self.assertIsNone(s.place(sprites_panda["panda"], 0, 5)) self.assertIsNone(s.place(TB(), 3, 0)) self.assertIsNone(s.place(board_items.BoardItem(model="##"), 10, 0)) self.assertIsNone( s.place( board_items.Tile(sprite=Sprite(sprixels=[ [Sprixel("##"), Sprixel("##")], [Sprixel("##"), Sprixel("##")], ])), 4, 0, )) self.assertIsNone( s.place( Sprite(sprixels=[ [Sprixel("##"), Sprixel("##")], [Sprixel("###"), Sprixel("##")], ]), 8, 0, )) s.force_render() with self.assertRaises(base.PglInvalidTypeException): s.place(None, 0, 0) with self.assertRaises(base.PglInvalidTypeException): s.place(1, 0, 0) with self.assertRaises(base.PglException): s.place(TB(), 400, 0) with self.assertRaises(base.PglException): s.place(TB(), 0, 400) s.force_update() t.text = "update" self.assertIsNone( s.place(sprites_panda["panda"], screen_height - 2, screen_width - 2)) self.assertIsNone(s.place("test", 1, screen_width - 2)) s.update() self.assertIsNone(s.render()) # Should not render self.assertFalse(s.need_rendering) s.trigger_rendering() self.assertTrue(s.need_rendering) # Now testing partial display camera = board_items.Camera() camera.row = 0 camera.column = 0 b = engine.Board( size=[screen_width * 2, screen_height * 2], enable_partial_display=True, partial_display_viewport=[ int(screen_height / 2) - 1, int(screen_width / 2) - 1, ], partial_display_focus=camera, DISPLAY_SIZE_WARNINGS=False, ) for row in range(0, b.height): for col in range(0, b.width): b.place_item( board_items.Wall(sprixel=Sprixel( " ", Color(row * 4, col, int((row + col) / 2))), ), row, col, ) self.assertIsNone(s.place(b, 0, 0, 2)) s.trigger_rendering() self.assertIsNone(s.update()) b.partial_display_viewport = [ int(screen_height / 2) - 1, int(screen_width / 2) - 1, ] camera.row = b.height - 1 camera.column = b.width - 1 self.assertIsNone(s.trigger_rendering()) self.assertIsNone(s.update()) camera = board_items.Tile( sprite=Sprite(sprixels=[[Sprixel("+"), Sprixel("+")], [Sprixel("+"), Sprixel("+")]])) b.partial_display_focus = camera # Please never do that in real life... camera.pos = [1, 1] self.assertIsNone(s.trigger_rendering()) self.assertIsNone(s.render()) self.assertIsNone(s.update()) # This will succeed but the str type cannot benefit from deferred rendering. self.assertIsNone(s.place("test delete", 0, 0, 2)) self.assertIsNone(s.update()) self.assertIsNone(s.delete(0, 0)) self.assertIsNone(s.update()) self.assertIsNone( functions.render_string_to_buffer( "hello", s._display_buffer, 0, 0, s._display_buffer.shape[0], s._display_buffer.shape[1], )) # This test has nothing to do here... but I'm lazy. self.assertEqual(5, functions.clamp(5, 0, 10)) self.assertEqual(0, functions.clamp(-5, 0, 10)) self.assertEqual(10, functions.clamp(15, 0, 10)) # This one either and it's even worst: it's going to disappear! t = base.Text("this is a text\non multiple lines") t.render_to_buffer( s._display_buffer, s._display_buffer.shape[0] - 1, s._display_buffer.shape[1] - 5, s._display_buffer.shape[0], s._display_buffer.shape[1], ) s.update() t = base.Text( "this is a text", Color(0, 0, 0), Color(255, 255, 255), font=Font("8bits"), ) t.render_to_buffer( s._display_buffer, s._display_buffer.shape[0] - 1, s._display_buffer.shape[1] - 5, s._display_buffer.shape[0], s._display_buffer.shape[1], ) s.update()