from __future__ import annotations from pathlib import Path from PIL import Image from engine.defs import DefRegistry TEXTURE_SIZE = 32 BORDER_SHADE = 0.75 DEPTH_SHADOW_TEXTURE = "tiles/depth_shadow.png" DEPTH_SHADOW_ALPHA = 90 # out of 255 per stacked copy - see Renderer._draw_depth_shadow def _checker_image(color: tuple[int, int, int], size: int = TEXTURE_SIZE) -> Image.Image: img = Image.new("RGBA", (size, size), (*color, 255)) pixels = img.load() border = max(1, size // 16) shaded = tuple(int(c * BORDER_SHADE) for c in color) for y in range(size): for x in range(size): if x < border or y < border or x >= size - border or y >= size - border: pixels[x, y] = (*shaded, 255) return img def _ensure_texture(textures_dir: Path, relative_path: str, color: tuple[int, int, int]) -> None: path = textures_dir / relative_path if path.exists(): return path.parent.mkdir(parents=True, exist_ok=True) _checker_image(color).save(path) def generate_placeholder_textures(registry: DefRegistry, textures_dir: Path) -> None: """Writes a flat-color/checker PNG for every def with a texture path, if missing.""" for layer_def in registry.tile_layer_defs.values(): if layer_def.texture: _ensure_texture(textures_dir, layer_def.texture, layer_def.color) for item_def in registry.item_defs.values(): if item_def.texture: _ensure_texture(textures_dir, item_def.texture, item_def.color) for part_def in registry.body_part_defs.values(): if part_def.texture: _ensure_texture(textures_dir, part_def.texture, part_def.color) def generate_depth_shadow_texture(textures_dir: Path) -> None: """A flat black, partially-transparent overlay - Renderer stacks 1+ copies of it on a tile to darken it proportionally to how far below the camera's reference z-level it sits (see Renderer._draw_depth_shadow), Dwarf-Fortress-style depth shading. Not keyed to any def (it's a rendering-only overlay, not game data) but generated the same "only if missing" way as generate_placeholder_textures. """ path = textures_dir / DEPTH_SHADOW_TEXTURE if path.exists(): return path.parent.mkdir(parents=True, exist_ok=True) Image.new("RGBA", (TEXTURE_SIZE, TEXTURE_SIZE), (0, 0, 0, DEPTH_SHADOW_ALPHA)).save(path)