libtcod / python-tcod

A high-performance Python port of libtcod. Includes the libtcodpy module for backwards compatibility with older projects.
BSD 2-Clause "Simplified" License
413 stars 36 forks source link

Colored spaces are not cleared by black spaces with the older renderers. #80

Closed FractalWire closed 4 years ago

FractalWire commented 5 years ago

Hi,

It's been a while. I'm currently retrying some of my previous tcod projects and I spot some weird behaviours with the last tcod version. I updated from tcod 9.3.0 to the last version (11.1.0)

When using console.clear and console.print_box the space character do not print properly if bg value for clear is (0,0,0)

Here is a small gist to illustrate what I mean : https://gist.github.com/FractalWire/3e40543a332d16cd147bd1cf0ff943b6

6 test cases : 1) blitting a console with bg=(0,0,0) does not print the console properly 2) blitting a console with bg=(0,0,0) and ch=ord('.') print the console properly with the good color 3) blitting a console with bg=(60,60,60) print the console properly 4) blitting a console with bg=(0,0,0) and a print_box does not print the console properly. Print_box shows space characters with parent console bg color 5) blitting a console with bg=(0,0,0) and ch=ord('.') and a print_box does not print the print_box properly. Print_box shows space characters with parent console bg color 6) blitting a console with bg=(60,60,60) and ch=ord('.') and a print_box print everything as expected.

The behaviour of print_box changes if you give a non-default bg color. It's similar to what's happening with clear.

HexDecimal commented 5 years ago

The triggering example can be shortened down to:

root_console = tcod.console_init_root(..., renderer=<deprecated renderer>)
root_console.clear(bg=(80, 80, 80))  # Any color.
tcod.console_flush()
root_console.clear(bg=(0, 0, 0))  # Black.
tcod.console_flush()  # Old background color is still displayed here.

There are no issues with the print, clear, or blit functions. Examining the console data shows that these values are correct even though they are not displayed correctly.

The problem is that the deprecated renderers are optimizing out drawing space characters when the background color is black. The new renderers don't do this and will display them correctly, but all deprecated renderers show this issue. This was possibly more noticeable after a change to clear where before clear would always force a full redraw of the console but that has since been removed.

I've noticed this issue long ago when the particle effects from the libtcod C/C++ samples would leave behind artifacts, but I never knew what caused them until now.

For now you can use either the SDL2 or OPENGL2 renderer to avoid this issue.

FractalWire commented 5 years ago

Ah, yes, this seems to work fine with newer renderer.

Although, I feel I need to explain why I was using the Opengl renderer. I'm using i3, a tiled window manager and for some reason, the opengl renderer was the only one to automatically make the window floating and not tiled. Which is actually what I want when I try my tcod program, otherwise, when it's tiled, the aspect ratio is weird. You can still manually make the tiled window floating but this is more convenient when it's done automatically.

Do you have an idea why that difference happened between opengl renderer and the other renderers ? I'm just curious here. Looking at the windows properties with xprop, I don't notice significant differences, so not sure why i3 chooses to make the window floating when using opengl renderer.

Thanks for the support.

HexDecimal commented 5 years ago

I've never used i3 before, but I suspect that it needs to resize windows to fit them into its tiles and the difference in renderers is that the newer ones create resizable windows and the old ones don't. If the window can't be resized then i3 can't accept it and the window falls back to being a floating window.

At the moment custrender.py is the only option for starting the SDL2 renderer with a non-resizable window. It's also a good option for keeping aspect ratios correct after the window is resized.

FractalWire commented 5 years ago

It seems you guessed right. I tried custrenderer.py without the resizable sdl flag, and it yields a floating windows.

The ability to have more control on the window properties is useful. For example being able to define if a window is a utility/tooltip/Popup might be useful for the WM. This is actually the normal way how i3 determine if it should make the window floating or not, and so by adding the corresponding flag that's another way to make the window automatically floating in i3.

Even if the use case for a roguelike with multiple utility windows seems pretty slim to me, it might be useful.

HexDecimal commented 5 years ago

Window categories are technically supported with custrender.py. Multiple windows are not supported yet but they should happen as the renderers are refactored.

HexDecimal commented 4 years ago

This ended up getting fixed for the older renderers, and then the old renderers were also removed.

This issue should be resolved in the recent versions of python-tcod.