|
3 | 3 | To render a console you need a tileset and a window to render to.
|
4 | 4 | See :ref:`getting-started` for info on how to set those up.
|
5 | 5 | """
|
6 |
| - |
| 6 | +import os |
| 7 | +import pathlib |
7 | 8 | import warnings
|
8 |
| -from typing import Any, Optional, Tuple, Union # noqa: F401 |
| 9 | +from typing import Any, Iterable, Optional, Tuple, Union |
9 | 10 |
|
10 | 11 | import numpy as np
|
11 | 12 | from typing_extensions import Literal
|
@@ -1229,3 +1230,102 @@ def recommended_size() -> Tuple[int, int]:
|
1229 | 1230 | w = max(1, xy[0] // lib.TCOD_ctx.tileset.tile_width)
|
1230 | 1231 | h = max(1, xy[1] // lib.TCOD_ctx.tileset.tile_height)
|
1231 | 1232 | return w, h
|
| 1233 | + |
| 1234 | + |
| 1235 | +def load_xp( |
| 1236 | + path: Union[str, pathlib.Path], order: Literal["C", "F"] = "C" |
| 1237 | +) -> Tuple[Console, ...]: |
| 1238 | + """Load a REXPaint file as a tuple of consoles. |
| 1239 | +
|
| 1240 | + `path` is the name of the REXPaint file to load. |
| 1241 | + Usually ending with `.xp`. |
| 1242 | +
|
| 1243 | + `order` is the memory order of the Console's array buffer, |
| 1244 | + see :any:`tcod.console.Console`. |
| 1245 | +
|
| 1246 | + .. versionadded:: 12.4 |
| 1247 | +
|
| 1248 | + Example:: |
| 1249 | + import tcod |
| 1250 | + from numpy import np |
| 1251 | +
|
| 1252 | + path = "example.xp" # REXPaint file with one layer. |
| 1253 | +
|
| 1254 | + # Load a REXPaint file with a single layer. |
| 1255 | + # The comma after console is used to unpack a single item tuple. |
| 1256 | + console, = tcod.console.load_xp(path, order="F") |
| 1257 | +
|
| 1258 | + # Convert from REXPaint's encoding to Unicode. |
| 1259 | + CP437_TO_UNICODE = np.asarray(tcod.tileset.CHARMAP_CP437) |
| 1260 | + console.ch[:] = CP437_TO_UNICODE[console.ch] |
| 1261 | +
|
| 1262 | + # Apply REXPaint's alpha key color. |
| 1263 | + KEY_COLOR = (255, 0, 255) |
| 1264 | + is_transparent = console.rgb["bg"] == KEY_COLOR |
| 1265 | + console.rgba[is_transparent] = (ord(" "), (0,), (0,)) |
| 1266 | + """ |
| 1267 | + if not os.path.exists(path): |
| 1268 | + raise FileNotFoundError(f"File not found:\n\t{os.path.abspath(path)}") |
| 1269 | + layers = _check( |
| 1270 | + tcod.lib.TCOD_load_xp(str(path).encode("utf-8"), 0, ffi.NULL) |
| 1271 | + ) |
| 1272 | + consoles = ffi.new("TCOD_Console*[]", layers) |
| 1273 | + _check(tcod.lib.TCOD_load_xp(str(path).encode("utf-8"), layers, consoles)) |
| 1274 | + return tuple( |
| 1275 | + Console._from_cdata(console_p, order=order) for console_p in consoles |
| 1276 | + ) |
| 1277 | + |
| 1278 | + |
| 1279 | +def save_xp( |
| 1280 | + path: Union[str, pathlib.Path], |
| 1281 | + consoles: Iterable[Console], |
| 1282 | + compress_level: int = 9, |
| 1283 | +) -> None: |
| 1284 | + """Save tcod Consoles to a REXPaint file. |
| 1285 | +
|
| 1286 | + `path` is where to save the file. |
| 1287 | +
|
| 1288 | + `consoles` are the :any:`tcod.console.Console` objects to be saved. |
| 1289 | +
|
| 1290 | + `compress_level` is the zlib compression level to be used. |
| 1291 | +
|
| 1292 | + Color alpha will be lost during saving. |
| 1293 | +
|
| 1294 | + Consoles will be saved as-is as much as possible. You may need to convert |
| 1295 | + characters from Unicode to CP437 if you want to load the file in REXPaint. |
| 1296 | +
|
| 1297 | + .. versionadded:: 12.4 |
| 1298 | +
|
| 1299 | + Example:: |
| 1300 | + import tcod |
| 1301 | + from numpy import np |
| 1302 | +
|
| 1303 | + console = tcod.Console(80, 24) # Example console. |
| 1304 | +
|
| 1305 | + # Load a REXPaint file with a single layer. |
| 1306 | + # The comma after console is used to unpack a single item tuple. |
| 1307 | + console, = tcod.console.load_xp(path, order="F") |
| 1308 | +
|
| 1309 | + # Convert from Unicode to REXPaint's encoding. |
| 1310 | + # Required to load this console correctly in the REXPaint tool. |
| 1311 | + CP437_TO_UNICODE = np.asarray(tcod.tileset.CHARMAP_CP437) |
| 1312 | + UNICODE_TO_CP437 = np.full(0x1FFFF, fill_value=ord("?")) |
| 1313 | + UNICODE_TO_CP437[CP437_TO_UNICODE] = np.arange(len(CP437_TO_UNICODE)) |
| 1314 | + console.ch[:] = UNICODE_TO_CP437[console.ch] |
| 1315 | +
|
| 1316 | + # Convert console alpha into REXPaint's alpha key color. |
| 1317 | + KEY_COLOR = (255, 0, 255) |
| 1318 | + is_transparent = console.rgba["bg"][:, :, 3] == 0 |
| 1319 | + console.rgb["bg"][is_transparent] = KEY_COLOR |
| 1320 | +
|
| 1321 | + tcod.console.save_xp("example.xp", [console]) |
| 1322 | + """ |
| 1323 | + consoles_c = ffi.new("TCOD_Console*[]", [c.console_c for c in consoles]) |
| 1324 | + _check( |
| 1325 | + tcod.lib.TCOD_save_xp( |
| 1326 | + len(consoles_c), |
| 1327 | + consoles_c, |
| 1328 | + str(path).encode("utf-8"), |
| 1329 | + compress_level, |
| 1330 | + ) |
| 1331 | + ) |
0 commit comments