Files
gta6/tools/extract/leonida/coords.py
T

56 lines
2.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Umrechnung zwischen gtadb-Weltkoordinaten, Kacheln und Mosaikpixeln.
Spiegelt src/world/coords.js. Beide Seiten müssen dieselben Werte liefern.
"""
import re
TILE_PX = 256
WORLD_HALF = 16384
CHUNK_SIZE = 250
SLICE = {"x0": -1000, "x1": 2000, "y0": -500, "y1": 2500}
def tile_for_world(x: float, y: float) -> tuple[int, int]:
return (int((WORLD_HALF - y) // TILE_PX), int((x + WORLD_HALF) // TILE_PX))
def slice_tiles() -> list[tuple[int, int]]:
r0, c0 = tile_for_world(SLICE["x0"], SLICE["y1"])
r1, c1 = tile_for_world(SLICE["x1"] - 1, SLICE["y0"] + 1)
return [(r, c) for r in range(r0, r1 + 1) for c in range(c0, c1 + 1)]
def mosaic_origin_px() -> tuple[int, int]:
"""Pixelversatz der Ausschnittsecke innerhalb des ungeschnittenen Kachelrasters."""
r0, c0 = tile_for_world(SLICE["x0"], SLICE["y1"])
return (SLICE["x0"] + WORLD_HALF - c0 * TILE_PX, (WORLD_HALF - SLICE["y1"]) - r0 * TILE_PX)
def pixel_to_world(px: int, py: int) -> tuple[float, float]:
return (SLICE["x0"] + px, SLICE["y1"] - py)
CHUNKS_PER_SIDE = (SLICE["x1"] - SLICE["x0"]) // CHUNK_SIZE # 12
CHUNK_COLUMNS = "ABCDEFGHIJKL"
# [0-9] statt \d: in Python passt \d auch auf andere Ziffernzeichen wie ١ oder 1, in JavaScript nicht.
_CHUNK_NAME = re.compile(r"([A-La-l])([1-9][0-9]?)")
def _is_index(k) -> bool:
return isinstance(k, int) and not isinstance(k, bool) and 0 <= k < CHUNKS_PER_SIDE
def chunk_name(i: int, j: int) -> str | None:
"""Planquadrat-Name wie src/world/coords.js: Spalte A–L aus i, Zeile 1–12 aus j. A1 = Nordwest."""
if not (_is_index(i) and _is_index(j)):
return None
return f"{CHUNK_COLUMNS[i]}{j + 1}"
def parse_chunk_name(name: str) -> tuple[int, int] | None:
"""Umkehrung von chunk_name. Akzeptiert Kleinschreibung, None außerhalb A1–L12."""
match = _CHUNK_NAME.fullmatch(str(name))
if not match or int(match.group(2)) > CHUNKS_PER_SIDE:
return None
return CHUNK_COLUMNS.index(match.group(1).upper()), int(match.group(2)) - 1