"""Script à usage unique (PAS exécuté au runtime du moteur) : copie les sprites CraftPix depuis assets/characters/animal_sprite/ (pack source, non versionné dans static/) vers static/characters/animals/// .png, et écrit static/characters/animals/manifest.json (compte réel de frames par pose/variante — variable selon les packs, voir le plan "Bibliothèque de sprites animaux CraftPix"). Réutilisé une fois par moi via `python scripts/generate_animal_sprite_manifest.py`, jamais importé par le moteur. Accès réservé au rôle admin (voir screens/labels/animal_sprite_library.py, routes/screens/screen_edit.py, routes/scenes/scene_edit_view.py) : licence CraftPix, ne redistribue pas ces sprites à des comptes "user".""" import json import os import shutil from typing import Any _BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) _SRC_ROOT = os.path.join(_BASE_DIR, "assets", "characters", "animal_sprite") _DST_ROOT = os.path.join(_BASE_DIR, "static", "characters", "animals") # Nom de dossier source -> (slug interne court, libellé FR). _PACKS = { "craftpix-net-125818-cute-monsters-game-character-sprites-pack": ("monster", "Monstre"), "craftpix-net-131088-cartoon-bunny-characters-asset-pack": ("bunny", "Lapin"), "craftpix-net-145571-cartoon-penguins-game-character-sprites-pack": ("penguin", "Pingouin"), "craftpix-net-340410-cute-chick-game-character-sprites": ("chick", "Poussin"), "craftpix-net-410327-cute-bear-character-sprites-pack": ("bear", "Ours"), "craftpix-net-454427-cute-duckling-game-character-sprites": ("duckling", "Caneton"), "craftpix-net-532103-cute-cats-game-character-sprites": ("cat", "Chat"), "craftpix-net-534018-cute-koala-game-character-sprite": ("koala", "Koala"), "craftpix-net-634797-cute-panda-game-person-sprites": ("panda", "Panda"), "craftpix-net-654141-cute-mushroom-character-game-sprites": ("mushroom", "Champignon"), "craftpix-net-746105-capybara-cartoon-characters-asset-pack": ("capybara", "Capybara"), "craftpix-net-784100-cute-pigs-game-character-sprite-pack": ("pig", "Cochon"), "craftpix-net-877867-cute-raccoon-game-character-sprites": ("raccoon", "Raton laveur"), "craftpix-net-950875-cute-beaver-character-game-sprites": ("beaver", "Castor"), } # Nom de pose source (dossier Png/CharacterNN/) -> nom exposé (clé # d'animation). "Stuned" est une coquille du pack source, corrigée ici. _POSE_NAMES = { "Idle": "idle", "Walk": "walk", "Jump": "jump", "Fly": "fly", "Roll": "roll", "Hit": "hit", "Stuned": "stunned", "Throwing": "throwing", "Dead": "dead", } def _copy_variant(pack_dir: str, animal: str, nn: str) -> dict[str, int] | None: char_dir = os.path.join(pack_dir, "Png", f"Character{nn}") if not os.path.isdir(char_dir): return None poses: dict[str, int] = {} for pose_folder in sorted(os.listdir(char_dir)): exposed = _POSE_NAMES.get(pose_folder) if not exposed: continue src_pose_dir = os.path.join(char_dir, pose_folder) frames = sorted(f for f in os.listdir(src_pose_dir) if f.lower().endswith(".png")) if not frames: continue dst_dir = os.path.join(_DST_ROOT, animal, nn) os.makedirs(dst_dir, exist_ok=True) for i, fname in enumerate(frames): shutil.copy2(os.path.join(src_pose_dir, fname), os.path.join(dst_dir, f"{exposed}{i}.png")) poses[exposed] = len(frames) return poses or None def main() -> None: manifest: dict[str, Any] = {} for pack_folder, (animal, label) in sorted(_PACKS.items()): pack_dir = os.path.join(_SRC_ROOT, pack_folder) if not os.path.isdir(pack_dir): print(f"SKIP (introuvable) : {pack_folder}") continue variants: dict[str, Any] = {} for n in range(1, 16): nn = f"{n:02d}" poses = _copy_variant(pack_dir, animal, nn) if poses: variants[nn] = poses if variants: manifest[animal] = {"label": label, "variants": variants} print(f"{animal} ({label}) : {len(variants)} variantes copiées") else: print(f"SKIP (aucune variante) : {pack_folder}") os.makedirs(_DST_ROOT, exist_ok=True) manifest_path = os.path.join(_DST_ROOT, "manifest.json") with open(manifest_path, "w", encoding="utf-8") as f: json.dump(manifest, f, ensure_ascii=False, indent=2, sort_keys=True) print(f"\nManifest écrit : {manifest_path}") if __name__ == "__main__": main()