Skip to content

Commit 4de3606

Browse files
committed
Update libtcod to 1.16.0-alpha.13.
New context and Context.present logic.
1 parent 625a570 commit 4de3606

6 files changed

Lines changed: 169 additions & 71 deletions

File tree

CHANGELOG.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,28 @@ v2.0.0
88

99
Unreleased
1010
------------------
11+
Added
12+
- Added `tcod.context.new` function.
13+
- Contexts now have CLI support.
14+
- You can now provide the window x,y position when making contexts.
15+
16+
Changed
17+
- Using `libtcod 1.16.0-alpha.13`.
18+
- The OpenGL 2 renderer can now use `SDL_HINT_RENDER_SCALE_QUALITY` to
19+
determine the tileset upscaling filter.
20+
- Improved performance of the FOV_BASIC algorithm.
21+
22+
Deprecated
23+
- `tcod.context.new_window` and `tcod.context.new_terminal` have been replaced
24+
by `tcod.context.new`.
25+
1126
Fixed
1227
- Pathfinders will now work with boolean arrays.
28+
- Console blits now ignore alpha compositing which would result in division by
29+
zero.
30+
- `tcod.console_is_key_pressed` should work even if libtcod events are ignored.
31+
- The `TCOD_RENDERER` and `TCOD_VSYNC` environment variables should work now.
32+
- `FOV_PERMISSIVE` algorithm is now reentrant.
1333

1434
11.15.3 - 2020-07-30
1535
--------------------

build_libtcod.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,9 @@ def fix_header(filepath: str) -> None:
356356
for i, line in enumerate(include.header.split("\n"), 1):
357357
print("%03i %s" % (i, line))
358358
raise
359+
ffi.cdef("""
360+
#define TCOD_COMPILEDVERSION ...
361+
""")
359362
ffi.set_source(
360363
module_name,
361364
"#include <tcod/cffi.h>\n#include <SDL.h>",

libtcod

Submodule libtcod updated 245 files

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ def check_sdl_version():
166166
"Programming Language :: Python :: 3.6",
167167
"Programming Language :: Python :: 3.7",
168168
"Programming Language :: Python :: 3.8",
169+
"Programming Language :: Python :: 3.9",
169170
"Programming Language :: Python :: Implementation :: CPython",
170171
"Programming Language :: Python :: Implementation :: PyPy",
171172
"Topic :: Games/Entertainment",

tcod/cdef.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ float _pycall_path_dest_only(int x1, int y1, int x2, int y2, void* user_data);
1919
void _pycall_sdl_hook(struct SDL_Surface*);
2020

2121
int _pycall_event_watch(void* userdata, union SDL_Event* event);
22+
23+
void _pycall_cli_output(void* userdata, const char* output);
2224
}

tcod/context.py

Lines changed: 142 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
hidden global objects within libtcod. If you begin using contexts then
99
most of these functions will no longer work properly.
1010
11-
Instead of calling :any:`tcod.console_init_root` you can call either
12-
:any:`tcod.context.new_window` or :any:`tcod.context.new_terminal` depending
13-
on how you plan to setup the size of the console. You should use
11+
Instead of calling :any:`tcod.console_init_root` you can call
12+
:any:`tcod.context.new` with different keywords depending on how you plan
13+
to setup the size of the console. You should use
1414
:any:`tcod.tileset` to load the font for a context.
1515
1616
.. note::
@@ -50,10 +50,10 @@
5050
import sys
5151
import os
5252

53-
from typing import Any, Optional, Tuple
53+
from typing import Any, Iterable, List, Optional, Tuple
5454

5555
import tcod
56-
from tcod._internal import _check, _check_warn
56+
from tcod._internal import _check, _check_warn, deprecate
5757
from tcod.loader import ffi, lib
5858
import tcod.event
5959
import tcod.tileset
@@ -129,11 +129,14 @@ def _handle_tileset(tileset: Optional[tcod.tileset.Tileset]) -> Any:
129129
return tileset._tileset_p if tileset else ffi.NULL
130130

131131

132-
def _handle_title(title: Optional[str]) -> str:
133-
"""Return title, or if title is None then return a decent default title."""
132+
def _handle_title(title: Optional[str]) -> Any:
133+
"""Return title as a CFFI string.
134+
135+
If title is None then return a decent default title is returned.
136+
"""
134137
if title is None:
135138
title = os.path.basename(sys.argv[0])
136-
return title
139+
return ffi.new("char[]", title.encode("utf-8"))
137140

138141

139142
class Context:
@@ -197,20 +200,22 @@ def present(
197200
upper-left corner. Values of 0.5 will center the console.
198201
"""
199202
clear_rgba = (clear_color[0], clear_color[1], clear_color[2], 255)
200-
options = {
201-
"keep_aspect": keep_aspect,
202-
"integer_scaling": integer_scaling,
203-
"clear_color": clear_rgba,
204-
"align_x": align[0],
205-
"align_y": align[1],
206-
}
207-
console_p = console.console_c
208-
with ffi.new("struct TCOD_ViewportOptions*", options) as viewport_opts:
209-
_check(
210-
lib.TCOD_context_present(
211-
self._context_p, console_p, viewport_opts
212-
)
203+
viewport_args = ffi.new(
204+
"TCOD_ViewportOptions*",
205+
{
206+
"tcod_version": lib.TCOD_COMPILEDVERSION,
207+
"keep_aspect": keep_aspect,
208+
"integer_scaling": integer_scaling,
209+
"clear_color": clear_rgba,
210+
"align_x": align[0],
211+
"align_y": align[1],
212+
},
213+
)
214+
_check(
215+
lib.TCOD_context_present(
216+
self._context_p, console.console_c, viewport_args
213217
)
218+
)
214219

215220
def pixel_to_tile(self, x: int, y: int) -> Tuple[int, int]:
216221
"""Convert window pixel coordinates to tile coordinates."""
@@ -316,19 +321,39 @@ def toggle_fullscreen(context: tcod.context.Context) -> None:
316321
return lib.TCOD_context_get_sdl_window(self._context_p)
317322

318323

319-
def new_window(
320-
width: int,
321-
height: int,
324+
@ffi.def_extern() # type: ignore
325+
def _pycall_cli_output(catch_reference: Any, output: Any) -> None:
326+
"""Callback for the libtcod context CLI. Catches the CLI output."""
327+
catch = ffi.from_handle(catch_reference) # type: List[str]
328+
catch.append(ffi.string(output).decode("utf-8"))
329+
330+
331+
def new(
322332
*,
333+
x: Optional[int] = None,
334+
y: Optional[int] = None,
335+
width: Optional[int] = None,
336+
height: Optional[int] = None,
337+
columns: Optional[int] = None,
338+
rows: Optional[int] = None,
323339
renderer: Optional[int] = None,
324340
tileset: Optional[tcod.tileset.Tileset] = None,
325341
vsync: bool = True,
326342
sdl_window_flags: Optional[int] = None,
327-
title: Optional[str] = None
343+
title: Optional[str] = None,
344+
argv: Optional[Iterable[str]] = None
328345
) -> Context:
329346
"""Create a new context with the desired pixel size.
330347
331-
`width` and `height` is the desired pixel resolution of the window.
348+
`x`, `y`, `width`, and `height` are the desired position and size of the
349+
window. If these are None then they will be derived from `columns` and
350+
`rows`. So if you plan on having a console of a fixed size then you should
351+
set `columns` and `rows` instead of the window keywords.
352+
353+
`columns` and `rows` is the desired size of the console. Can be left as
354+
`None` when you're setting a context by a window size instead of a console.
355+
356+
Providing no size information at all is also acceptable.
332357
333358
`renderer` is the desired libtcod renderer to use.
334359
Typical options are :any:`tcod.context.RENDERER_OPENGL2` for a faster
@@ -348,32 +373,95 @@ def new_window(
348373
349374
`title` is the desired title of the window.
350375
351-
After the context is created you can use
352-
:any:`Context.recommended_console_size` to figure out the size of the
353-
console for the context.
376+
`argv` these arguments are passed to libtcod and allow an end-user to make
377+
last second changes such as forcing fullscreen or windowed mode, or
378+
changing the libtcod renderer.
379+
By default this will pass in `sys.argv` but you can disable this feature
380+
by providing an empty list instead.
381+
Certain commands such as ``-help`` will raise a SystemExit exception from
382+
this function with the output message.
383+
384+
When a window size is given instead of a console size then you can use
385+
:any:`Context.recommended_console_size` to automatically find the size of
386+
the console which should be used.
387+
388+
.. versionadded:: 11.16
354389
"""
355-
context_pp = ffi.new("TCOD_Context**")
356390
if renderer is None:
357-
renderer = RENDERER_SDL2
391+
renderer = RENDERER_OPENGL2
358392
if sdl_window_flags is None:
359393
sdl_window_flags = SDL_WINDOW_RESIZABLE
360-
tileset_p = _handle_tileset(tileset)
361-
title = _handle_title(title)
362-
_check_warn(
363-
lib.TCOD_context_new_window(
364-
width,
365-
height,
366-
renderer,
367-
tileset_p,
368-
vsync,
369-
sdl_window_flags,
370-
title.encode("utf-8"),
371-
context_pp,
372-
)
394+
if argv is None:
395+
argv = sys.argv
396+
argv_encoded = [ # Needs to be kept alive for argv_c.
397+
ffi.new("char[]", arg.encode("utf-8")) for arg in argv
398+
]
399+
argv_c = ffi.new("char*[]", argv_encoded)
400+
401+
catch_msg = [] # type: List[str]
402+
catch_handle = ffi.new_handle(catch_msg) # Keep alive.
403+
404+
params = ffi.new(
405+
"struct TCOD_ContextParams*",
406+
{
407+
"tcod_version": lib.TCOD_COMPILEDVERSION,
408+
"x": x if x is not None else lib.SDL_WINDOWPOS_UNDEFINED,
409+
"y": y if y is not None else lib.SDL_WINDOWPOS_UNDEFINED,
410+
"pixel_width": width or 0,
411+
"pixel_height": height or 0,
412+
"columns": columns or 0,
413+
"rows": rows or 0,
414+
"renderer_type": renderer,
415+
"tileset": _handle_tileset(tileset),
416+
"vsync": vsync,
417+
"sdl_window_flags": sdl_window_flags,
418+
"window_title": _handle_title(title),
419+
"argc": len(argv_c),
420+
"argv": argv_c,
421+
"cli_output": ffi.addressof(lib, "_pycall_cli_output"),
422+
"cli_userdata": catch_handle,
423+
},
373424
)
425+
context_pp = ffi.new("TCOD_Context**")
426+
error = lib.TCOD_context_new(params, context_pp)
427+
if error == lib.TCOD_E_REQUIRES_ATTENTION:
428+
raise SystemExit(catch_msg[0])
429+
_check_warn(error)
374430
return Context._claim(context_pp[0])
375431

376432

433+
@deprecate(
434+
"Call tcod.context.new with width and height as keyword parameters."
435+
)
436+
def new_window(
437+
width: int,
438+
height: int,
439+
*,
440+
renderer: Optional[int] = None,
441+
tileset: Optional[tcod.tileset.Tileset] = None,
442+
vsync: bool = True,
443+
sdl_window_flags: Optional[int] = None,
444+
title: Optional[str] = None
445+
) -> Context:
446+
"""Create a new context with the desired pixel size.
447+
448+
.. deprecated:: 11.16
449+
:any:`tcod.context.new` provides more options, such as window position.
450+
"""
451+
return new(
452+
width=width,
453+
height=height,
454+
renderer=renderer,
455+
tileset=tileset,
456+
vsync=vsync,
457+
sdl_window_flags=sdl_window_flags,
458+
title=title,
459+
)
460+
461+
462+
@deprecate(
463+
"Call tcod.context.new with columns and rows as keyword parameters."
464+
)
377465
def new_terminal(
378466
columns: int,
379467
rows: int,
@@ -386,31 +474,15 @@ def new_terminal(
386474
) -> Context:
387475
"""Create a new context with the desired console size.
388476
389-
`columns` and `rows` are the desired size of the console.
390-
391-
The remaining parameters are the same as :any:`new_window`.
392-
393-
You can use this instead of :any:`new_window` if you plan on using a
394-
:any:`tcod.Console` of a fixed size. This function is the most similar to
395-
:any:`tcod.console_init_root`.
477+
.. deprecated:: 11.16
478+
:any:`tcod.context.new` provides more options.
396479
"""
397-
context_pp = ffi.new("TCOD_Context**")
398-
if renderer is None:
399-
renderer = RENDERER_SDL2
400-
if sdl_window_flags is None:
401-
sdl_window_flags = SDL_WINDOW_RESIZABLE
402-
tileset_p = _handle_tileset(tileset)
403-
title = _handle_title(title)
404-
_check_warn(
405-
lib.TCOD_context_new_terminal(
406-
columns,
407-
rows,
408-
renderer,
409-
tileset_p,
410-
vsync,
411-
sdl_window_flags,
412-
title.encode("utf-8"),
413-
context_pp,
414-
)
480+
return new(
481+
columns=columns,
482+
rows=rows,
483+
renderer=renderer,
484+
tileset=tileset,
485+
vsync=vsync,
486+
sdl_window_flags=sdl_window_flags,
487+
title=title,
415488
)
416-
return Context._claim(context_pp[0])

0 commit comments

Comments
 (0)