import json import os # Bibliothèque de sprites animaux CraftPix — RÉSERVÉE au rôle admin (voir # routes/screens/screen_edit.py, routes/scenes/scene_edit_view.py, et les # routes d'écriture screens/scene-objects "personnage"/"add"). Licence # CraftPix : interdiction de rendre ces sprites utilisables par un compte # "user" via l'application (voir le plan "Bibliothèque de sprites animaux # CraftPix"). Générée une fois par scripts/generate_animal_sprite_manifest.py # depuis assets/characters/animal_sprite/ (pack source, non versionné) vers # static/characters/animals///.png, avec un manifest # JSON décrivant le compte RÉEL de frames par pose/variante (variable selon # les packs — pas de table figée comme _SEQUENCE_ANIMATIONS pour Kenney). _MANIFEST_PATH = os.path.join( os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "static", "characters", "animals", "manifest.json", ) def _load_manifest(): try: with open(_MANIFEST_PATH, encoding="utf-8") as f: return json.load(f) except FileNotFoundError: # Poste de dev sans les assets animaux copiés (script pas encore # lancé), ou paquet exporté pour un jeu qui n'utilise aucun # personnage animal (voir publish/build_scorm_package.py, copie # sélective) : aucun personnage animal disponible, pas une erreur. return {} def _slug(animal, nn): return f"animal-{animal}-{nn}" def _label(family_label, nn): n = int(nn) return f"{family_label} (variante {n})" if n > 1 else f"{family_label} (de base)" def _animations_for(animal, nn, poses): return { pose: [f"/static/characters/animals/{animal}/{nn}/{pose}{i}.png" for i in range(count)] for pose, count in poses.items() } def _build_library(): manifest = _load_manifest() library = {} for animal, pack in manifest.items(): family_label = pack["label"] for nn, poses in pack["variants"].items(): library[_slug(animal, nn)] = { "label": _label(family_label, nn), "animations": _animations_for(animal, nn, poses), "family": animal, "family_label": family_label, } return library ADMIN_SPRITE_LIBRARY = _build_library()