From 143e29643bab785f0a7139dc2e827e75f13429bf Mon Sep 17 00:00:00 2001 From: edujiro5972 <336072401+edujiro5972@users.noreply.github.com> Date: Wed, 7 Oct 2026 15:49:31 +0200 Subject: [PATCH] =?UTF-8?q?AP6=20(restes)=20:=20catalogue=20des=20animatio?= =?UTF-8?q?ns=20(Catalogue.py,=20pack.json,=20catalogue.html/json)=20et=20?= =?UTF-8?q?planches=20anim=C3=A9es=20du=20mod=20Quaternius?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase AP6 (CHG-210, 211). Co-Authored-By: Claude Opus 5.5 --- AnimSources/quaternius/pack.json | 607 ++++ .../Module/Animations/catalogue.html | 106 + .../Module/Animations/catalogue.json | 3187 +++++++++++++++++ Tools/anim/Catalogue.py | 461 +++ Tools/anim/DeliverAnims.ps1 | 28 +- 5 files changed, 4388 insertions(+), 1 deletion(-) create mode 100644 AnimSources/quaternius/pack.json create mode 100644 ModSources/lpr_anim_quaternius/Module/Animations/catalogue.html create mode 100644 ModSources/lpr_anim_quaternius/Module/Animations/catalogue.json create mode 100644 Tools/anim/Catalogue.py diff --git a/AnimSources/quaternius/pack.json b/AnimSources/quaternius/pack.json new file mode 100644 index 0000000..9ed1a9e --- /dev/null +++ b/AnimSources/quaternius/pack.json @@ -0,0 +1,607 @@ +{ + "pack": "quaternius", + "prefixe": "qua", + "source": "Quaternius Universal Animation Library (Standard)", + "auteur": "Quaternius", + "licence": "CC0 1.0", + "url": "https://quaternius.com", + "fichiers": [ + "D:/Game/Universal Animation Library[Standard]/Unreal-Godot/UAL1_Standard.glb" + ], + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "exclus": [ + "A_TPose" + ], + "animations": { + "qua_crouch_fwd_loop": { + "clip": "Crouch_Fwd_Loop", + "nom": { + "fr": "Marche accroupie", + "en": "Crouch walk" + }, + "categorie": "locomotion", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de marche accroupie sur place ; à combiner avec un déplacement pour une scène furtive.", + "en": "Looping crouched walk in place; combine with a character movement for a sneaking scene." + } + }, + "qua_crouch_idle_loop": { + "clip": "Crouch_Idle_Loop", + "nom": { + "fr": "Attente accroupie", + "en": "Crouch idle" + }, + "categorie": "attente", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle d'attente accroupie, pour se cacher ou observer discrètement.", + "en": "Looping crouched idle, for hiding or watching discreetly." + } + }, + "qua_dance_loop": { + "clip": "Dance_Loop", + "nom": { + "fr": "Danse", + "en": "Dance" + }, + "categorie": "danse", + "accessoire": "", + "style": "détendu", + "usage": { + "fr": "Boucle de danse libre, pour une scène de fête ou de club.", + "en": "Looping free dance, for a party or club scene." + } + }, + "qua_death01": { + "clip": "Death01", + "nom": { + "fr": "Mort", + "en": "Death" + }, + "categorie": "chute", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : le personnage s'effondre et reste au sol ; à utiliser pour une mort ou un évanouissement.", + "en": "Played once: the character collapses and stays down; use for a death or a faint." + } + }, + "qua_driving_loop": { + "clip": "Driving_Loop", + "nom": { + "fr": "Conduite", + "en": "Driving" + }, + "categorie": "conduite", + "accessoire": "volant", + "style": "neutre", + "usage": { + "fr": "Boucle de conduite, mains sur le volant ; pour un personnage assis dans un véhicule.", + "en": "Looping driving pose, hands on the wheel; for a character seated in a vehicle." + } + }, + "qua_fixing_kneeling": { + "clip": "Fixing_Kneeling", + "nom": { + "fr": "Réparer à genoux", + "en": "Fix kneeling" + }, + "categorie": "interaction", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de bricolage à genoux, pour une réparation ou un travail au sol.", + "en": "Looping kneeling repair work, for fixing something or working at ground level." + } + }, + "qua_hit_chest": { + "clip": "Hit_Chest", + "nom": { + "fr": "Coup à la poitrine", + "en": "Hit in chest" + }, + "categorie": "combat", + "accessoire": "", + "style": "agressif", + "usage": { + "fr": "Joué une fois : réaction à un coup reçu au torse ; à placer après une attaque.", + "en": "Played once: reaction to a blow to the chest; place it after an attack." + } + }, + "qua_hit_head": { + "clip": "Hit_Head", + "nom": { + "fr": "Coup à la tête", + "en": "Hit in head" + }, + "categorie": "combat", + "accessoire": "", + "style": "agressif", + "usage": { + "fr": "Joué une fois : réaction à un coup reçu à la tête ; à placer après une attaque.", + "en": "Played once: reaction to a blow to the head; place it after an attack." + } + }, + "qua_idle_loop": { + "clip": "Idle_Loop", + "nom": { + "fr": "Attente", + "en": "Idle" + }, + "categorie": "attente", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle d'attente debout par défaut, pour un personnage qui patiente.", + "en": "Default standing idle loop, for a waiting character." + } + }, + "qua_idle_talking_loop": { + "clip": "Idle_Talking_Loop", + "nom": { + "fr": "Attente en parlant", + "en": "Idle talking" + }, + "categorie": "conversation", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle debout avec gestes de la main, pour un personnage qui parle dans un dialogue.", + "en": "Standing loop with hand gestures, for a character speaking in a dialogue." + } + }, + "qua_idle_torch_loop": { + "clip": "Idle_Torch_Loop", + "nom": { + "fr": "Attente avec torche", + "en": "Idle with torch" + }, + "categorie": "attente", + "accessoire": "torche", + "style": "neutre", + "usage": { + "fr": "Boucle d'attente debout en tenant une torche ; pour une scène de nuit ou d'exploration.", + "en": "Standing idle loop holding a torch; for a night or exploration scene." + } + }, + "qua_interact": { + "clip": "Interact", + "nom": { + "fr": "Interagir", + "en": "Interact" + }, + "categorie": "interaction", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : geste pour actionner un objet (bouton, porte, levier).", + "en": "Played once: gesture to operate an object (button, door, lever)." + } + }, + "qua_jog_fwd_loop": { + "clip": "Jog_Fwd_Loop", + "nom": { + "fr": "Jogging", + "en": "Jog" + }, + "categorie": "locomotion", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de course légère sur place ; à combiner avec un déplacement du personnage.", + "en": "Looping light jog in place; combine with a character movement." + } + }, + "qua_jump_land": { + "clip": "Jump_Land", + "nom": { + "fr": "Réception de saut", + "en": "Jump landing" + }, + "categorie": "chute", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : réception au sol ; dernière phase d'un saut (après la boucle en l'air).", + "en": "Played once: landing on the ground; last phase of a jump (after the airborne loop)." + } + }, + "qua_jump_loop": { + "clip": "Jump_Loop", + "nom": { + "fr": "Saut en l'air", + "en": "Jump airborne" + }, + "categorie": "chute", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de la phase en l'air d'un saut, entre le départ et la réception.", + "en": "Looping airborne phase of a jump, between the start and the landing." + } + }, + "qua_jump_start": { + "clip": "Jump_Start", + "nom": { + "fr": "Départ de saut", + "en": "Jump start" + }, + "categorie": "chute", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : impulsion au départ d'un saut ; première phase avant la boucle en l'air.", + "en": "Played once: take-off impulse; first phase before the airborne loop." + } + }, + "qua_pickup_table": { + "clip": "PickUp_Table", + "nom": { + "fr": "Ramasser sur une table", + "en": "Pick up from table" + }, + "categorie": "interaction", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : le personnage prend un objet posé sur une table.", + "en": "Played once: the character picks up an object lying on a table." + } + }, + "qua_pistol_aim_down": { + "clip": "Pistol_Aim_Down", + "nom": { + "fr": "Viser vers le bas", + "en": "Aim down" + }, + "categorie": "combat", + "accessoire": "pistolet", + "style": "agressif", + "usage": { + "fr": "Pose de visée pistolet vers le bas ; à enchaîner avec les autres visées ou le tir.", + "en": "Pistol aiming pose pointing down; chain with the other aims or the shot." + } + }, + "qua_pistol_aim_neutral": { + "clip": "Pistol_Aim_Neutral", + "nom": { + "fr": "Viser droit", + "en": "Aim straight" + }, + "categorie": "combat", + "accessoire": "pistolet", + "style": "agressif", + "usage": { + "fr": "Pose de visée pistolet à l'horizontale ; pose de base avant un tir.", + "en": "Pistol aiming pose at level; base pose before a shot." + } + }, + "qua_pistol_aim_up": { + "clip": "Pistol_Aim_Up", + "nom": { + "fr": "Viser vers le haut", + "en": "Aim up" + }, + "categorie": "combat", + "accessoire": "pistolet", + "style": "agressif", + "usage": { + "fr": "Pose de visée pistolet vers le haut ; à enchaîner avec les autres visées ou le tir.", + "en": "Pistol aiming pose pointing up; chain with the other aims or the shot." + } + }, + "qua_pistol_idle_loop": { + "clip": "Pistol_Idle_Loop", + "nom": { + "fr": "Attente au pistolet", + "en": "Pistol idle" + }, + "categorie": "combat", + "accessoire": "pistolet", + "style": "agressif", + "usage": { + "fr": "Boucle d'attente debout, pistolet en main ; pour un personnage armé qui guette.", + "en": "Standing idle loop with a pistol in hand; for an armed character on guard." + } + }, + "qua_pistol_reload": { + "clip": "Pistol_Reload", + "nom": { + "fr": "Recharger le pistolet", + "en": "Pistol reload" + }, + "categorie": "combat", + "accessoire": "pistolet", + "style": "agressif", + "usage": { + "fr": "Joué une fois : rechargement du pistolet ; à placer entre deux tirs.", + "en": "Played once: pistol reload; place it between two shots." + } + }, + "qua_pistol_shoot": { + "clip": "Pistol_Shoot", + "nom": { + "fr": "Tir au pistolet", + "en": "Pistol shot" + }, + "categorie": "combat", + "accessoire": "pistolet", + "style": "agressif", + "usage": { + "fr": "Joué une fois : un tir de pistolet avec recul.", + "en": "Played once: one pistol shot with recoil." + } + }, + "qua_punch_cross": { + "clip": "Punch_Cross", + "nom": { + "fr": "Direct", + "en": "Cross punch" + }, + "categorie": "combat", + "accessoire": "", + "style": "agressif", + "usage": { + "fr": "Joué une fois : coup de poing direct ; pour une bagarre.", + "en": "Played once: cross punch; for a fight." + } + }, + "qua_punch_jab": { + "clip": "Punch_Jab", + "nom": { + "fr": "Jab", + "en": "Jab" + }, + "categorie": "combat", + "accessoire": "", + "style": "agressif", + "usage": { + "fr": "Joué une fois : coup de poing rapide ; pour une bagarre.", + "en": "Played once: quick jab punch; for a fight." + } + }, + "qua_push_loop": { + "clip": "Push_Loop", + "nom": { + "fr": "Pousser", + "en": "Push" + }, + "categorie": "interaction", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de poussée à deux mains sur place ; pour pousser un meuble ou une porte lourde.", + "en": "Looping two-handed push in place; for pushing furniture or a heavy door." + } + }, + "qua_roll": { + "clip": "Roll", + "nom": { + "fr": "Roulade", + "en": "Roll" + }, + "categorie": "sport", + "accessoire": "", + "style": "agressif", + "usage": { + "fr": "Joué une fois : roulade au sol ; pour esquiver ou plonger.", + "en": "Played once: ground roll; for dodging or diving." + } + }, + "qua_sitting_enter": { + "clip": "Sitting_Enter", + "nom": { + "fr": "S'asseoir", + "en": "Sit down" + }, + "categorie": "assis", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : entrée, le personnage passe de debout à assis ; à suivre d'une boucle assise.", + "en": "Played once: entry, the character goes from standing to seated; follow with a seated loop." + } + }, + "qua_sitting_exit": { + "clip": "Sitting_Exit", + "nom": { + "fr": "Se lever", + "en": "Stand up" + }, + "categorie": "assis", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : sortie, le personnage passe d'assis à debout ; à placer après une boucle assise.", + "en": "Played once: exit, the character goes from seated to standing; place after a seated loop." + } + }, + "qua_sitting_idle_loop": { + "clip": "Sitting_Idle_Loop", + "nom": { + "fr": "Assis, attente", + "en": "Seated idle" + }, + "categorie": "assis", + "accessoire": "", + "style": "détendu", + "usage": { + "fr": "Boucle d'attente assise, après « s'asseoir » ; pour un personnage installé sur une chaise.", + "en": "Seated idle loop, after the sit-down clip; for a character settled on a chair." + } + }, + "qua_sitting_talking_loop": { + "clip": "Sitting_Talking_Loop", + "nom": { + "fr": "Assis, en parlant", + "en": "Seated talking" + }, + "categorie": "assis", + "accessoire": "", + "style": "détendu", + "usage": { + "fr": "Boucle assise avec gestes de la main, pour un dialogue entre personnages assis.", + "en": "Seated loop with hand gestures, for a dialogue between seated characters." + } + }, + "qua_spell_simple_enter": { + "clip": "Spell_Simple_Enter", + "nom": { + "fr": "Début d'incantation", + "en": "Spell start" + }, + "categorie": "magie", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : mise en position pour lancer un sort ; à suivre de la boucle d'incantation.", + "en": "Played once: stance to begin casting a spell; follow with the spell idle loop." + } + }, + "qua_spell_simple_exit": { + "clip": "Spell_Simple_Exit", + "nom": { + "fr": "Fin d'incantation", + "en": "Spell end" + }, + "categorie": "magie", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Joué une fois : retour à la posture normale après un sort.", + "en": "Played once: return to normal stance after a spell." + } + }, + "qua_spell_simple_idle_loop": { + "clip": "Spell_Simple_Idle_Loop", + "nom": { + "fr": "Incantation", + "en": "Spell idle" + }, + "categorie": "magie", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de concentration, mains levées, entre l'entrée et le lancer du sort.", + "en": "Looping concentration pose, hands raised, between the entry and the cast." + } + }, + "qua_spell_simple_shoot": { + "clip": "Spell_Simple_Shoot", + "nom": { + "fr": "Lancer un sort", + "en": "Cast spell" + }, + "categorie": "magie", + "accessoire": "", + "style": "agressif", + "usage": { + "fr": "Joué une fois : le geste qui lance le sort ; à placer après la boucle d'incantation.", + "en": "Played once: the gesture that casts the spell; place after the spell idle loop." + } + }, + "qua_sprint_loop": { + "clip": "Sprint_Loop", + "nom": { + "fr": "Sprint", + "en": "Sprint" + }, + "categorie": "locomotion", + "accessoire": "", + "style": "agressif", + "usage": { + "fr": "Boucle de course rapide sur place ; à combiner avec un déplacement pour une fuite ou une poursuite.", + "en": "Looping fast run in place; combine with a movement for an escape or chase." + } + }, + "qua_swim_fwd_loop": { + "clip": "Swim_Fwd_Loop", + "nom": { + "fr": "Nage", + "en": "Swim" + }, + "categorie": "nage", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de nage en avant ; à combiner avec un déplacement dans l'eau.", + "en": "Looping forward swim; combine with a movement in water." + }, + "posture": "dans l'eau" + }, + "qua_swim_idle_loop": { + "clip": "Swim_Idle_Loop", + "nom": { + "fr": "Surplace dans l'eau", + "en": "Treading water" + }, + "categorie": "nage", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de flottaison sur place dans l'eau.", + "en": "Looping treading water in place." + }, + "posture": "dans l'eau" + }, + "qua_sword_attack": { + "clip": "Sword_Attack", + "nom": { + "fr": "Attaque à l'épée", + "en": "Sword attack" + }, + "categorie": "combat", + "accessoire": "épée", + "style": "agressif", + "usage": { + "fr": "Joué une fois : un coup d'épée ; à enchaîner après l'attente à l'épée.", + "en": "Played once: a sword strike; chain after the sword idle." + } + }, + "qua_sword_idle": { + "clip": "Sword_Idle", + "nom": { + "fr": "Attente à l'épée", + "en": "Sword idle" + }, + "categorie": "combat", + "accessoire": "épée", + "style": "agressif", + "usage": { + "fr": "Boucle d'attente debout, épée en main, en garde.", + "en": "Standing idle loop, sword in hand, on guard." + } + }, + "qua_walk_formal_loop": { + "clip": "Walk_Formal_Loop", + "nom": { + "fr": "Marche formelle", + "en": "Formal walk" + }, + "categorie": "locomotion", + "accessoire": "", + "style": "formel", + "usage": { + "fr": "Boucle de marche tenue et digne sur place ; à combiner avec un déplacement (cérémonie, travail).", + "en": "Looping upright, dignified walk in place; combine with a movement (ceremony, office)." + } + }, + "qua_walk_loop": { + "clip": "Walk_Loop", + "nom": { + "fr": "Marche", + "en": "Walk" + }, + "categorie": "locomotion", + "accessoire": "", + "style": "neutre", + "usage": { + "fr": "Boucle de marche sur place ; à combiner avec un déplacement du personnage.", + "en": "Looping walk in place; combine with a character movement." + } + } + } +} diff --git a/ModSources/lpr_anim_quaternius/Module/Animations/catalogue.html b/ModSources/lpr_anim_quaternius/Module/Animations/catalogue.html new file mode 100644 index 0000000..2b93620 --- /dev/null +++ b/ModSources/lpr_anim_quaternius/Module/Animations/catalogue.html @@ -0,0 +1,106 @@ + + + + + +Animations — lpr_anim_quaternius + + + +
+

Animations — lpr_anim_quaternius

+
Version 1.0 — 42 animations — généré le 2026-10-06. Copiez la clé puis écrivez Actor.animate(clé) dans une scène ou ANIMATION: clé dans une action. Survolez une vignette pour voir le mouvement.
+
+ + + + +
+
+
+
Aucune animation ne correspond aux filtres.
+
+ + + + + diff --git a/ModSources/lpr_anim_quaternius/Module/Animations/catalogue.json b/ModSources/lpr_anim_quaternius/Module/Animations/catalogue.json new file mode 100644 index 0000000..8d092d3 --- /dev/null +++ b/ModSources/lpr_anim_quaternius/Module/Animations/catalogue.json @@ -0,0 +1,3187 @@ +{ + "pack": "quaternius", + "mod": "lpr_anim_quaternius", + "version": "1.0", + "genere": "2026-10-06T16:30:06", + "nombre_animations": 42, + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "animations": [ + { + "cle": "qua_crouch_fwd_loop", + "appel": { + "script": "Actor.animate(qua_crouch_fwd_loop)", + "action": "ANIMATION: qua_crouch_fwd_loop" + }, + "nom": { + "fr": "Marche accroupie", + "en": "Crouch walk" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_crouch_fwd_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_crouch_fwd_loop_M" + }, + "duree_s": 2.0, + "images": 61, + "planche": { + "fichier": "planches/qua_crouch_fwd_loop.jpg", + "images": 24, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 531, + "masculin": 521, + "total": 1052 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "variable", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 79, + "droite": 74 + }, + "mains": { + "gauche": "repos", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "locomotion", + "style": "neutre", + "usage": { + "fr": "Boucle de marche accroupie sur place ; à combiner avec un déplacement pour une scène furtive.", + "en": "Looping crouched walk in place; combine with a character movement for a sneaking scene." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "9B579DF07915651F7F712B108C24E86C4626A41056D91B77AC4FA7D0B6A0C35F" + }, + { + "cle": "qua_crouch_idle_loop", + "appel": { + "script": "Actor.animate(qua_crouch_idle_loop)", + "action": "ANIMATION: qua_crouch_idle_loop" + }, + "nom": { + "fr": "Attente accroupie", + "en": "Crouch idle" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_crouch_idle_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_crouch_idle_loop_M" + }, + "duree_s": 2.93, + "images": 89, + "planche": { + "fichier": "planches/qua_crouch_idle_loop.jpg", + "images": 24, + "taille": 256, + "ips": 8.2 + }, + "cadence": 30, + "taille_ko": { + "feminin": 817, + "masculin": 808, + "total": 1625 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "accroupi", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "attente", + "style": "neutre", + "usage": { + "fr": "Boucle d'attente accroupie, pour se cacher ou observer discrètement.", + "en": "Looping crouched idle, for hiding or watching discreetly." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "0DABE423B515ABB6335D03BF58640351F9978B6C1798E69B0DE3E99BBF139821" + }, + { + "cle": "qua_dance_loop", + "appel": { + "script": "Actor.animate(qua_dance_loop)", + "action": "ANIMATION: qua_dance_loop" + }, + "nom": { + "fr": "Danse", + "en": "Dance" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_dance_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_dance_loop_M" + }, + "duree_s": 1.0, + "images": 31, + "planche": { + "fichier": "planches/qua_dance_loop.jpg", + "images": 12, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 500, + "masculin": 492, + "total": 992 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "danse", + "style": "détendu", + "usage": { + "fr": "Boucle de danse libre, pour une scène de fête ou de club.", + "en": "Looping free dance, for a party or club scene." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "51A7F64FB68A91BE68D2CE8FEDFA635DF66556529605E65D5E9C5DA5E71A987E" + }, + { + "cle": "qua_death01", + "appel": { + "script": "Actor.animate(qua_death01)", + "action": "ANIMATION: qua_death01" + }, + "nom": { + "fr": "Mort", + "en": "Death" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_death01_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_death01_M" + }, + "duree_s": 2.4, + "images": 73, + "planche": { + "fichier": "planches/qua_death01.jpg", + "images": 24, + "taille": 256, + "ips": 10.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 786, + "masculin": 777, + "total": 1563 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 95.63 + }, + "deplacement": { + "cm": 53, + "cm_s": 22, + "sens": "arriere" + }, + "posture": { + "principale": "variable", + "posture_origine": "calculee", + "debut": "debout", + "fin": "allonge" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 86, + "droite": 81 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "chute", + "style": "neutre", + "usage": { + "fr": "Joué une fois : le personnage s'effondre et reste au sol ; à utiliser pour une mort ou un évanouissement.", + "en": "Played once: the character collapses and stays down; use for a death or a faint." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "à revoir", + "motifs": [ + "Bridget : sol cm 5.6 (lFoot)", + "Michael : sol cm 5.6 (lFoot)" + ], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "5C5C89D9FB3304A71CC3B2CB3018EF2781EACA968CDA0A7F2B6358AEE4CC48D7" + }, + { + "cle": "qua_driving_loop", + "appel": { + "script": "Actor.animate(qua_driving_loop)", + "action": "ANIMATION: qua_driving_loop" + }, + "nom": { + "fr": "Conduite", + "en": "Driving" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_driving_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_driving_loop_M" + }, + "duree_s": 1.67, + "images": 51, + "planche": { + "fichier": "planches/qua_driving_loop.jpg", + "images": 20, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 470, + "masculin": 460, + "total": 930 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "assis", + "posture_origine": "calculee", + "hauteur_assise_cm": 45 + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "volant", + "categorie": "conduite", + "style": "neutre", + "usage": { + "fr": "Boucle de conduite, mains sur le volant ; pour un personnage assis dans un véhicule.", + "en": "Looping driving pose, hands on the wheel; for a character seated in a vehicle." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "3992745D7BAFD326EBC7150447823724D78E1BC48DCABFA21435BCF3DCD4D2B5" + }, + { + "cle": "qua_fixing_kneeling", + "appel": { + "script": "Actor.animate(qua_fixing_kneeling)", + "action": "ANIMATION: qua_fixing_kneeling" + }, + "nom": { + "fr": "Réparer à genoux", + "en": "Fix kneeling" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_fixing_kneeling_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_fixing_kneeling_M" + }, + "duree_s": 5.2, + "images": 157, + "planche": { + "fichier": "planches/qua_fixing_kneeling.jpg", + "images": 24, + "taille": 256, + "ips": 4.6 + }, + "cadence": 30, + "taille_ko": { + "feminin": 1231, + "masculin": 1221, + "total": 2452 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.03 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "a genoux", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 94 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "interaction", + "style": "neutre", + "usage": { + "fr": "Boucle de bricolage à genoux, pour une réparation ou un travail au sol.", + "en": "Looping kneeling repair work, for fixing something or working at ground level." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "à revoir", + "motifs": [ + "Bridget : sol cm 5.2 (rFoot)", + "Michael : sol cm 4.4 (rFoot)" + ], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "0DE675BC7314E651A21431333C791649AAED186DECC116E022F3BEC2D111FF1F" + }, + { + "cle": "qua_hit_chest", + "appel": { + "script": "Actor.animate(qua_hit_chest)", + "action": "ANIMATION: qua_hit_chest" + }, + "nom": { + "fr": "Coup à la poitrine", + "en": "Hit in chest" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_hit_chest_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_hit_chest_M" + }, + "duree_s": 0.33, + "images": 11, + "planche": { + "fichier": "planches/qua_hit_chest.jpg", + "images": 4, + "taille": 256, + "ips": 12.1 + }, + "cadence": 30, + "taille_ko": { + "feminin": 445, + "masculin": 436, + "total": 881 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 15.27 + }, + "deplacement": { + "cm": 3, + "cm_s": 9, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Joué une fois : réaction à un coup reçu au torse ; à placer après une attaque.", + "en": "Played once: reaction to a blow to the chest; place it after an attack." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.01, + "pire_torsion_deg": 0.02 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "413F5B0E2BAAD564C4BD39659C8D93378CDC9F70E0C0C29DC8A2EC66026A55E5" + }, + { + "cle": "qua_hit_head", + "appel": { + "script": "Actor.animate(qua_hit_head)", + "action": "ANIMATION: qua_hit_head" + }, + "nom": { + "fr": "Coup à la tête", + "en": "Hit in head" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_hit_head_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_hit_head_M" + }, + "duree_s": 0.43, + "images": 14, + "planche": { + "fichier": "planches/qua_hit_head.jpg", + "images": 5, + "taille": 256, + "ips": 11.6 + }, + "cadence": 30, + "taille_ko": { + "feminin": 459, + "masculin": 449, + "total": 908 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 5.01 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Joué une fois : réaction à un coup reçu à la tête ; à placer après une attaque.", + "en": "Played once: reaction to a blow to the head; place it after an attack." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "45F001A3E71833E01151647FF8A7D9EB3ACE6FF6B5D478B3F7ED77F0EAC1FA1A" + }, + { + "cle": "qua_idle_loop", + "appel": { + "script": "Actor.animate(qua_idle_loop)", + "action": "ANIMATION: qua_idle_loop" + }, + "nom": { + "fr": "Attente", + "en": "Idle" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_idle_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_idle_loop_M" + }, + "duree_s": 2.5, + "images": 76, + "planche": { + "fichier": "planches/qua_idle_loop.jpg", + "images": 24, + "taille": 256, + "ips": 9.6 + }, + "cadence": 30, + "taille_ko": { + "feminin": 570, + "masculin": 560, + "total": 1130 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.19 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "attente", + "style": "neutre", + "usage": { + "fr": "Boucle d'attente debout par défaut, pour un personnage qui patiente.", + "en": "Default standing idle loop, for a waiting character." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "CDF1F85493A49722295790E16CE55F85535389CBC8F31E38C994FB3D02B0E36B" + }, + { + "cle": "qua_idle_talking_loop", + "appel": { + "script": "Actor.animate(qua_idle_talking_loop)", + "action": "ANIMATION: qua_idle_talking_loop" + }, + "nom": { + "fr": "Attente en parlant", + "en": "Idle talking" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_idle_talking_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_idle_talking_loop_M" + }, + "duree_s": 2.93, + "images": 89, + "planche": { + "fichier": "planches/qua_idle_talking_loop.jpg", + "images": 24, + "taille": 256, + "ips": 8.2 + }, + "cadence": 30, + "taille_ko": { + "feminin": 792, + "masculin": 780, + "total": 1573 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "conversation", + "style": "neutre", + "usage": { + "fr": "Boucle debout avec gestes de la main, pour un personnage qui parle dans un dialogue.", + "en": "Standing loop with hand gestures, for a character speaking in a dialogue." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "2E481B14FFB95D4205B451A75218ECB6932F7E11E7412195BB599C6234839CD8" + }, + { + "cle": "qua_idle_torch_loop", + "appel": { + "script": "Actor.animate(qua_idle_torch_loop)", + "action": "ANIMATION: qua_idle_torch_loop" + }, + "nom": { + "fr": "Attente avec torche", + "en": "Idle with torch" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_idle_torch_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_idle_torch_loop_M" + }, + "duree_s": 1.27, + "images": 39, + "planche": { + "fichier": "planches/qua_idle_torch_loop.jpg", + "images": 15, + "taille": 256, + "ips": 11.8 + }, + "cadence": 30, + "taille_ko": { + "feminin": 526, + "masculin": 516, + "total": 1042 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "torche", + "categorie": "attente", + "style": "neutre", + "usage": { + "fr": "Boucle d'attente debout en tenant une torche ; pour une scène de nuit ou d'exploration.", + "en": "Standing idle loop holding a torch; for a night or exploration scene." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "202DF6A92CF7638F8BD8380C6683F7E6E286C030E831E4D4A43EA06359EFC5B5" + }, + { + "cle": "qua_interact", + "appel": { + "script": "Actor.animate(qua_interact)", + "action": "ANIMATION: qua_interact" + }, + "nom": { + "fr": "Interagir", + "en": "Interact" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_interact_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_interact_M" + }, + "duree_s": 2.0, + "images": 61, + "planche": { + "fichier": "planches/qua_interact.jpg", + "images": 24, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 544, + "masculin": 531, + "total": 1075 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "interaction", + "style": "neutre", + "usage": { + "fr": "Joué une fois : geste pour actionner un objet (bouton, porte, levier).", + "en": "Played once: gesture to operate an object (button, door, lever)." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "6787AD53457B4527F8B8E30B487CCF43524D4DF2DA7C9CBADB5E1102B73AC306" + }, + { + "cle": "qua_jog_fwd_loop", + "appel": { + "script": "Actor.animate(qua_jog_fwd_loop)", + "action": "ANIMATION: qua_jog_fwd_loop" + }, + "nom": { + "fr": "Jogging", + "en": "Jog" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_jog_fwd_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_jog_fwd_loop_M" + }, + "duree_s": 0.93, + "images": 29, + "planche": { + "fichier": "planches/qua_jog_fwd_loop.jpg", + "images": 11, + "taille": 256, + "ips": 11.8 + }, + "cadence": 30, + "taille_ko": { + "feminin": 488, + "masculin": 477, + "total": 965 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.26 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 17, + "droite": 17 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "locomotion", + "style": "neutre", + "usage": { + "fr": "Boucle de course légère sur place ; à combiner avec un déplacement du personnage.", + "en": "Looping light jog in place; combine with a character movement." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.06, + "pire_torsion_deg": 0.11 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "2BF6C3A9BCA1BFE725F30895126F78AD0700411E76198B132F11524E0176A29A" + }, + { + "cle": "qua_jump_land", + "appel": { + "script": "Actor.animate(qua_jump_land)", + "action": "ANIMATION: qua_jump_land" + }, + "nom": { + "fr": "Réception de saut", + "en": "Jump landing" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_jump_land_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_jump_land_M" + }, + "duree_s": 1.27, + "images": 39, + "planche": { + "fichier": "planches/qua_jump_land.jpg", + "images": 15, + "taille": 256, + "ips": 11.8 + }, + "cadence": 30, + "taille_ko": { + "feminin": 598, + "masculin": 588, + "total": 1186 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 31.62 + }, + "deplacement": { + "cm": 3, + "cm_s": 3, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "chute", + "style": "neutre", + "usage": { + "fr": "Joué une fois : réception au sol ; dernière phase d'un saut (après la boucle en l'air).", + "en": "Played once: landing on the ground; last phase of a jump (after the airborne loop)." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.02, + "pire_torsion_deg": 0.03 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "C847CE338880ED7A506CA2CFD6ADC04567D735E061F211D23881A8BF826C99A1" + }, + { + "cle": "qua_jump_loop", + "appel": { + "script": "Actor.animate(qua_jump_loop)", + "action": "ANIMATION: qua_jump_loop" + }, + "nom": { + "fr": "Saut en l'air", + "en": "Jump airborne" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_jump_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_jump_loop_M" + }, + "duree_s": 2.5, + "images": 76, + "planche": { + "fichier": "planches/qua_jump_loop.jpg", + "images": 24, + "taille": 256, + "ips": 9.6 + }, + "cadence": 30, + "taille_ko": { + "feminin": 606, + "masculin": 594, + "total": 1199 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 0, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "chute", + "style": "neutre", + "usage": { + "fr": "Boucle de la phase en l'air d'un saut, entre le départ et la réception.", + "en": "Looping airborne phase of a jump, between the start and the landing." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "E74A50B4A340C003209EBB1131EA7369D77D03C7A9A2016A2DA190C16F672674" + }, + { + "cle": "qua_jump_start", + "appel": { + "script": "Actor.animate(qua_jump_start)", + "action": "ANIMATION: qua_jump_start" + }, + "nom": { + "fr": "Départ de saut", + "en": "Jump start" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_jump_start_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_jump_start_M" + }, + "duree_s": 1.33, + "images": 41, + "planche": { + "fichier": "planches/qua_jump_start.jpg", + "images": 16, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 599, + "masculin": 591, + "total": 1191 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 37.45 + }, + "deplacement": { + "cm": 10, + "cm_s": 7, + "sens": "avant" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee", + "debut": "accroupi", + "fin": "debout" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 12, + "droite": 56 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "chute", + "style": "neutre", + "usage": { + "fr": "Joué une fois : impulsion au départ d'un saut ; première phase avant la boucle en l'air.", + "en": "Played once: take-off impulse; first phase before the airborne loop." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "à revoir", + "motifs": [ + "Bridget : saut deg 23.1 (lForearmBend)", + "Michael : saut deg 23.1 (lForearmBend)" + ], + "pire_brut_pct": 0.01, + "pire_torsion_deg": 0.02 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "5EB89CFEC6D1329CA7AF815224B653BB7CBFC910EFD27C3817F46E73B4492E57" + }, + { + "cle": "qua_pickup_table", + "appel": { + "script": "Actor.animate(qua_pickup_table)", + "action": "ANIMATION: qua_pickup_table" + }, + "nom": { + "fr": "Ramasser sur une table", + "en": "Pick up from table" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_pickup_table_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_pickup_table_M" + }, + "duree_s": 0.83, + "images": 26, + "planche": { + "fichier": "planches/qua_pickup_table.jpg", + "images": 10, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 481, + "masculin": 471, + "total": 951 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "interaction", + "style": "neutre", + "usage": { + "fr": "Joué une fois : le personnage prend un objet posé sur une table.", + "en": "Played once: the character picks up an object lying on a table." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.02, + "pire_torsion_deg": 0.05 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "A128DEBD8A93E4C2654160F6CD6F53D53C01B72C1D19B50B0406873A3F05D650" + }, + { + "cle": "qua_pistol_aim_down", + "appel": { + "script": "Actor.animate(qua_pistol_aim_down)", + "action": "ANIMATION: qua_pistol_aim_down" + }, + "nom": { + "fr": "Viser vers le bas", + "en": "Aim down" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_pistol_aim_down_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_pistol_aim_down_M" + }, + "duree_s": 0.17, + "images": 6, + "planche": { + "fichier": "planches/qua_pistol_aim_down.jpg", + "images": 4, + "taille": 256, + "ips": 23.5 + }, + "cadence": 30, + "taille_ko": { + "feminin": 392, + "masculin": 382, + "total": 774 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "pistolet", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Pose de visée pistolet vers le bas ; à enchaîner avec les autres visées ou le tir.", + "en": "Pistol aiming pose pointing down; chain with the other aims or the shot." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "9E23F1BCCDDC168D8DAB59C22E593285A51CDC2962BDF83B03C28A447DA0BECE" + }, + { + "cle": "qua_pistol_aim_neutral", + "appel": { + "script": "Actor.animate(qua_pistol_aim_neutral)", + "action": "ANIMATION: qua_pistol_aim_neutral" + }, + "nom": { + "fr": "Viser droit", + "en": "Aim straight" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_pistol_aim_neutral_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_pistol_aim_neutral_M" + }, + "duree_s": 0.17, + "images": 6, + "planche": { + "fichier": "planches/qua_pistol_aim_neutral.jpg", + "images": 4, + "taille": 256, + "ips": 23.5 + }, + "cadence": 30, + "taille_ko": { + "feminin": 392, + "masculin": 382, + "total": 774 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "pistolet", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Pose de visée pistolet à l'horizontale ; pose de base avant un tir.", + "en": "Pistol aiming pose at level; base pose before a shot." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "984A55AF0B4AB7B5456D237F9F28BE24624C5C8AF8672514045460B1D9FDDA7F" + }, + { + "cle": "qua_pistol_aim_up", + "appel": { + "script": "Actor.animate(qua_pistol_aim_up)", + "action": "ANIMATION: qua_pistol_aim_up" + }, + "nom": { + "fr": "Viser vers le haut", + "en": "Aim up" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_pistol_aim_up_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_pistol_aim_up_M" + }, + "duree_s": 0.17, + "images": 6, + "planche": { + "fichier": "planches/qua_pistol_aim_up.jpg", + "images": 4, + "taille": 256, + "ips": 23.5 + }, + "cadence": 30, + "taille_ko": { + "feminin": 392, + "masculin": 382, + "total": 774 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "levee", + "droite": "levee" + } + }, + "accessoire": "pistolet", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Pose de visée pistolet vers le haut ; à enchaîner avec les autres visées ou le tir.", + "en": "Pistol aiming pose pointing up; chain with the other aims or the shot." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "47FDF5F57483E4831F45C7E8C75BFC5794002B18EC71F35615E0535267964356" + }, + { + "cle": "qua_pistol_idle_loop", + "appel": { + "script": "Actor.animate(qua_pistol_idle_loop)", + "action": "ANIMATION: qua_pistol_idle_loop" + }, + "nom": { + "fr": "Attente au pistolet", + "en": "Pistol idle" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_pistol_idle_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_pistol_idle_loop_M" + }, + "duree_s": 1.67, + "images": 51, + "planche": { + "fichier": "planches/qua_pistol_idle_loop.jpg", + "images": 20, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 473, + "masculin": 464, + "total": 937 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "pistolet", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Boucle d'attente debout, pistolet en main ; pour un personnage armé qui guette.", + "en": "Standing idle loop with a pistol in hand; for an armed character on guard." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "25AC610F52C00AEF05B6379BF801A004A002B1C1897E2B5E91A2FAAE5BAC6B56" + }, + { + "cle": "qua_pistol_reload", + "appel": { + "script": "Actor.animate(qua_pistol_reload)", + "action": "ANIMATION: qua_pistol_reload" + }, + "nom": { + "fr": "Recharger le pistolet", + "en": "Pistol reload" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_pistol_reload_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_pistol_reload_M" + }, + "duree_s": 1.67, + "images": 51, + "planche": { + "fichier": "planches/qua_pistol_reload.jpg", + "images": 20, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 633, + "masculin": 621, + "total": 1254 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "pistolet", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Joué une fois : rechargement du pistolet ; à placer entre deux tirs.", + "en": "Played once: pistol reload; place it between two shots." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.16, + "pire_torsion_deg": 0.3 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "24AEE8EB7849A51A2FC222845C7847896F5EE48F5F2364FF9BEF05355B39AB47" + }, + { + "cle": "qua_pistol_shoot", + "appel": { + "script": "Actor.animate(qua_pistol_shoot)", + "action": "ANIMATION: qua_pistol_shoot" + }, + "nom": { + "fr": "Tir au pistolet", + "en": "Pistol shot" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_pistol_shoot_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_pistol_shoot_M" + }, + "duree_s": 0.63, + "images": 20, + "planche": { + "fichier": "planches/qua_pistol_shoot.jpg", + "images": 8, + "taille": 256, + "ips": 12.7 + }, + "cadence": 30, + "taille_ko": { + "feminin": 439, + "masculin": 430, + "total": 869 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "pistolet", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Joué une fois : un tir de pistolet avec recul.", + "en": "Played once: one pistol shot with recoil." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.01 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "A5EF75F6DDBC1CBAD89869DC0D022761993EBF88D49E4193421F42CF4991CAC4" + }, + { + "cle": "qua_punch_cross", + "appel": { + "script": "Actor.animate(qua_punch_cross)", + "action": "ANIMATION: qua_punch_cross" + }, + "nom": { + "fr": "Direct", + "en": "Cross punch" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_punch_cross_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_punch_cross_M" + }, + "duree_s": 1.0, + "images": 31, + "planche": { + "fichier": "planches/qua_punch_cross.jpg", + "images": 12, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 498, + "masculin": 489, + "total": 987 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Joué une fois : coup de poing direct ; pour une bagarre.", + "en": "Played once: cross punch; for a fight." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "727894040989E2BEF757B2DC50E57447886F5C6CEC90004C4EF5D1F72A5F468E" + }, + { + "cle": "qua_punch_jab", + "appel": { + "script": "Actor.animate(qua_punch_jab)", + "action": "ANIMATION: qua_punch_jab" + }, + "nom": { + "fr": "Jab", + "en": "Jab" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_punch_jab_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_punch_jab_M" + }, + "duree_s": 0.87, + "images": 27, + "planche": { + "fichier": "planches/qua_punch_jab.jpg", + "images": 10, + "taille": 256, + "ips": 11.5 + }, + "cadence": 30, + "taille_ko": { + "feminin": 472, + "masculin": 462, + "total": 934 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Joué une fois : coup de poing rapide ; pour une bagarre.", + "en": "Played once: quick jab punch; for a fight." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.01 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "0286B49557A3CF43FE37DE88E892E3BF43DDF36157A43049AEB514630F6E3279" + }, + { + "cle": "qua_push_loop", + "appel": { + "script": "Actor.animate(qua_push_loop)", + "action": "ANIMATION: qua_push_loop" + }, + "nom": { + "fr": "Pousser", + "en": "Push" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_push_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_push_loop_M" + }, + "duree_s": 2.67, + "images": 81, + "planche": { + "fichier": "planches/qua_push_loop.jpg", + "images": 24, + "taille": 256, + "ips": 9.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 584, + "masculin": 577, + "total": 1161 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 78, + "droite": 80 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "interaction", + "style": "neutre", + "usage": { + "fr": "Boucle de poussée à deux mains sur place ; pour pousser un meuble ou une porte lourde.", + "en": "Looping two-handed push in place; for pushing furniture or a heavy door." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "49D7186234EC47E66A9993FDEA064F4EC4D6A515B2AFA70B7A0E3083B9B87DE2" + }, + { + "cle": "qua_roll", + "appel": { + "script": "Actor.animate(qua_roll)", + "action": "ANIMATION: qua_roll" + }, + "nom": { + "fr": "Roulade", + "en": "Roll" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_roll_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_roll_M" + }, + "duree_s": 1.47, + "images": 45, + "planche": { + "fichier": "planches/qua_roll.jpg", + "images": 18, + "taille": 256, + "ips": 12.2 + }, + "cadence": 30, + "taille_ko": { + "feminin": 631, + "masculin": 621, + "total": 1252 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 29.75 + }, + "deplacement": { + "cm": 11, + "cm_s": 8, + "sens": "avant" + }, + "posture": { + "principale": "variable", + "posture_origine": "calculee", + "debut": "accroupi", + "fin": "debout" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 53, + "droite": 53 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "sport", + "style": "agressif", + "usage": { + "fr": "Joué une fois : roulade au sol ; pour esquiver ou plonger.", + "en": "Played once: ground roll; for dodging or diving." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "à revoir", + "motifs": [ + "Bridget : sol cm 4.8 (rFoot)", + "Michael : sol cm 5.0 (rFoot)" + ], + "pire_brut_pct": 0.19, + "pire_torsion_deg": 0.49 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "C86A5D1A1728CB05A99461B1DF39691D07C5011F01C53DDFE7C2E44C9B97733E" + }, + { + "cle": "qua_sitting_enter", + "appel": { + "script": "Actor.animate(qua_sitting_enter)", + "action": "ANIMATION: qua_sitting_enter" + }, + "nom": { + "fr": "S'asseoir", + "en": "Sit down" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_sitting_enter_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_sitting_enter_M" + }, + "duree_s": 1.3, + "images": 40, + "planche": { + "fichier": "planches/qua_sitting_enter.jpg", + "images": 16, + "taille": 256, + "ips": 12.3 + }, + "cadence": 30, + "taille_ko": { + "feminin": 597, + "masculin": 587, + "total": 1184 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 52.14 + }, + "deplacement": { + "cm": 28, + "cm_s": 22, + "sens": "arriere" + }, + "posture": { + "principale": "variable", + "posture_origine": "calculee", + "debut": "debout", + "fin": "assis" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 90 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "assis", + "style": "neutre", + "usage": { + "fr": "Joué une fois : entrée, le personnage passe de debout à assis ; à suivre d'une boucle assise.", + "en": "Played once: entry, the character goes from standing to seated; follow with a seated loop." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "F71563458C2AE60FECDBEFD8203FEBD96D7318E607FF4B0E6038D4D258E7A98D" + }, + { + "cle": "qua_sitting_exit", + "appel": { + "script": "Actor.animate(qua_sitting_exit)", + "action": "ANIMATION: qua_sitting_exit" + }, + "nom": { + "fr": "Se lever", + "en": "Stand up" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_sitting_exit_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_sitting_exit_M" + }, + "duree_s": 1.03, + "images": 32, + "planche": { + "fichier": "planches/qua_sitting_exit.jpg", + "images": 12, + "taille": 256, + "ips": 11.7 + }, + "cadence": 30, + "taille_ko": { + "feminin": 556, + "masculin": 546, + "total": 1102 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 52.14 + }, + "deplacement": { + "cm": 28, + "cm_s": 27, + "sens": "avant" + }, + "posture": { + "principale": "variable", + "posture_origine": "calculee", + "debut": "assis", + "fin": "debout" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 94 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "assis", + "style": "neutre", + "usage": { + "fr": "Joué une fois : sortie, le personnage passe d'assis à debout ; à placer après une boucle assise.", + "en": "Played once: exit, the character goes from seated to standing; place after a seated loop." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.01 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "6639D68DBFB5833681D25EAFFD8D9043AFBCDA5B75098B100187C4E1FD0BB744" + }, + { + "cle": "qua_sitting_idle_loop", + "appel": { + "script": "Actor.animate(qua_sitting_idle_loop)", + "action": "ANIMATION: qua_sitting_idle_loop" + }, + "nom": { + "fr": "Assis, attente", + "en": "Seated idle" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_sitting_idle_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_sitting_idle_loop_M" + }, + "duree_s": 1.67, + "images": 51, + "planche": { + "fichier": "planches/qua_sitting_idle_loop.jpg", + "images": 20, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 558, + "masculin": 548, + "total": 1106 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "assis", + "posture_origine": "calculee", + "hauteur_assise_cm": 45 + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "assis", + "style": "détendu", + "usage": { + "fr": "Boucle d'attente assise, après « s'asseoir » ; pour un personnage installé sur une chaise.", + "en": "Seated idle loop, after the sit-down clip; for a character settled on a chair." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "5B70EDA8CEA21B2B83DD66B311149600F248EE9F8243340D70F4AABF26E62FC5" + }, + { + "cle": "qua_sitting_talking_loop", + "appel": { + "script": "Actor.animate(qua_sitting_talking_loop)", + "action": "ANIMATION: qua_sitting_talking_loop" + }, + "nom": { + "fr": "Assis, en parlant", + "en": "Seated talking" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_sitting_talking_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_sitting_talking_loop_M" + }, + "duree_s": 2.93, + "images": 89, + "planche": { + "fichier": "planches/qua_sitting_talking_loop.jpg", + "images": 24, + "taille": 256, + "ips": 8.2 + }, + "cadence": 30, + "taille_ko": { + "feminin": 770, + "masculin": 761, + "total": 1531 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "assis", + "posture_origine": "calculee", + "hauteur_assise_cm": 45 + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "assis", + "style": "détendu", + "usage": { + "fr": "Boucle assise avec gestes de la main, pour un dialogue entre personnages assis.", + "en": "Seated loop with hand gestures, for a dialogue between seated characters." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "F0A4091AE1A72C4ACB9466DFC39D74E5EFACE0BABAC06C12BE428120F69495B8" + }, + { + "cle": "qua_spell_simple_enter", + "appel": { + "script": "Actor.animate(qua_spell_simple_enter)", + "action": "ANIMATION: qua_spell_simple_enter" + }, + "nom": { + "fr": "Début d'incantation", + "en": "Spell start" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_spell_simple_enter_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_spell_simple_enter_M" + }, + "duree_s": 0.53, + "images": 17, + "planche": { + "fichier": "planches/qua_spell_simple_enter.jpg", + "images": 6, + "taille": 256, + "ips": 11.3 + }, + "cadence": 30, + "taille_ko": { + "feminin": 478, + "masculin": 468, + "total": 946 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 52.78 + }, + "deplacement": { + "cm": 3, + "cm_s": 5, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "magie", + "style": "neutre", + "usage": { + "fr": "Joué une fois : mise en position pour lancer un sort ; à suivre de la boucle d'incantation.", + "en": "Played once: stance to begin casting a spell; follow with the spell idle loop." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.01, + "pire_torsion_deg": 0.02 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "B3965AAE6955B739C33AA88DC46BE1C8DE44DEB81A2EC5B01C15AA1AF700E680" + }, + { + "cle": "qua_spell_simple_exit", + "appel": { + "script": "Actor.animate(qua_spell_simple_exit)", + "action": "ANIMATION: qua_spell_simple_exit" + }, + "nom": { + "fr": "Fin d'incantation", + "en": "Spell end" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_spell_simple_exit_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_spell_simple_exit_M" + }, + "duree_s": 0.43, + "images": 14, + "planche": { + "fichier": "planches/qua_spell_simple_exit.jpg", + "images": 5, + "taille": 256, + "ips": 11.6 + }, + "cadence": 30, + "taille_ko": { + "feminin": 463, + "masculin": 453, + "total": 916 + }, + "taille_cuite": false, + "boucle": { + "oui": false, + "ecart_pct": 52.78 + }, + "deplacement": { + "cm": 3, + "cm_s": 7, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "magie", + "style": "neutre", + "usage": { + "fr": "Joué une fois : retour à la posture normale après un sort.", + "en": "Played once: return to normal stance after a spell." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.02, + "pire_torsion_deg": 0.04 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "45F84F02B7A818D42F18CC0CA4B52EC182A423C8C60CA036AF02092A04F675C2" + }, + { + "cle": "qua_spell_simple_idle_loop", + "appel": { + "script": "Actor.animate(qua_spell_simple_idle_loop)", + "action": "ANIMATION: qua_spell_simple_idle_loop" + }, + "nom": { + "fr": "Incantation", + "en": "Spell idle" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_spell_simple_idle_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_spell_simple_idle_loop_M" + }, + "duree_s": 2.1, + "images": 64, + "planche": { + "fichier": "planches/qua_spell_simple_idle_loop.jpg", + "images": 24, + "taille": 256, + "ips": 11.4 + }, + "cadence": 30, + "taille_ko": { + "feminin": 574, + "masculin": 566, + "total": 1140 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "magie", + "style": "neutre", + "usage": { + "fr": "Boucle de concentration, mains levées, entre l'entrée et le lancer du sort.", + "en": "Looping concentration pose, hands raised, between the entry and the cast." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "07BAC68BF07A9A6E0E007DEFE06ACF73D3F2245D7D0733EAF0EC321989A5175D" + }, + { + "cle": "qua_spell_simple_shoot", + "appel": { + "script": "Actor.animate(qua_spell_simple_shoot)", + "action": "ANIMATION: qua_spell_simple_shoot" + }, + "nom": { + "fr": "Lancer un sort", + "en": "Cast spell" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_spell_simple_shoot_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_spell_simple_shoot_M" + }, + "duree_s": 0.5, + "images": 16, + "planche": { + "fichier": "planches/qua_spell_simple_shoot.jpg", + "images": 6, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 462, + "masculin": 452, + "total": 914 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "", + "categorie": "magie", + "style": "agressif", + "usage": { + "fr": "Joué une fois : le geste qui lance le sort ; à placer après la boucle d'incantation.", + "en": "Played once: the gesture that casts the spell; place after the spell idle loop." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "76FB42C31F2C6B3A01C986DE1C2CE6A887A1E0D6BD1E5E9A8CA6E91FFB7FFE6F" + }, + { + "cle": "qua_sprint_loop", + "appel": { + "script": "Actor.animate(qua_sprint_loop)", + "action": "ANIMATION: qua_sprint_loop" + }, + "nom": { + "fr": "Sprint", + "en": "Sprint" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_sprint_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_sprint_loop_M" + }, + "duree_s": 0.67, + "images": 21, + "planche": { + "fichier": "planches/qua_sprint_loop.jpg", + "images": 8, + "taille": 256, + "ips": 11.9 + }, + "cadence": 30, + "taille_ko": { + "feminin": 452, + "masculin": 443, + "total": 895 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.26 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 29, + "droite": 14 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "locomotion", + "style": "agressif", + "usage": { + "fr": "Boucle de course rapide sur place ; à combiner avec un déplacement pour une fuite ou une poursuite.", + "en": "Looping fast run in place; combine with a movement for an escape or chase." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.08, + "pire_torsion_deg": 0.14 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "9A341C0B31F5EAF0B93E5F9001AB1246D339EF83B4AB3BEB3F17A4A0916F1CDE" + }, + { + "cle": "qua_swim_fwd_loop", + "appel": { + "script": "Actor.animate(qua_swim_fwd_loop)", + "action": "ANIMATION: qua_swim_fwd_loop" + }, + "nom": { + "fr": "Nage", + "en": "Swim" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_swim_fwd_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_swim_fwd_loop_M" + }, + "duree_s": 1.33, + "images": 41, + "planche": { + "fichier": "planches/qua_swim_fwd_loop.jpg", + "images": 16, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 498, + "masculin": 489, + "total": 987 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "dans l'eau", + "posture_origine": "declaree", + "posture_calculee": "allonge" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "nage", + "style": "neutre", + "usage": { + "fr": "Boucle de nage en avant ; à combiner avec un déplacement dans l'eau.", + "en": "Looping forward swim; combine with a movement in water." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.02, + "pire_torsion_deg": 0.04 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "260E19E1A794EFDE2A8AE788482FE22F03EC3EEC7BE7EE74BC1BDFE01CFCCD65" + }, + { + "cle": "qua_swim_idle_loop", + "appel": { + "script": "Actor.animate(qua_swim_idle_loop)", + "action": "ANIMATION: qua_swim_idle_loop" + }, + "nom": { + "fr": "Surplace dans l'eau", + "en": "Treading water" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_swim_idle_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_swim_idle_loop_M" + }, + "duree_s": 3.33, + "images": 101, + "planche": { + "fichier": "planches/qua_swim_idle_loop.jpg", + "images": 24, + "taille": 256, + "ips": 7.2 + }, + "cadence": 30, + "taille_ko": { + "feminin": 865, + "masculin": 856, + "total": 1721 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "dans l'eau", + "posture_origine": "declaree", + "posture_calculee": "a genoux" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "nage", + "style": "neutre", + "usage": { + "fr": "Boucle de flottaison sur place dans l'eau.", + "en": "Looping treading water in place." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "181DE0C7C89DE68256F6F592DF1E0BC91765207D7460946715CF8DE385CDD277" + }, + { + "cle": "qua_sword_attack", + "appel": { + "script": "Actor.animate(qua_sword_attack)", + "action": "ANIMATION: qua_sword_attack" + }, + "nom": { + "fr": "Attaque à l'épée", + "en": "Sword attack" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_sword_attack_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_sword_attack_M" + }, + "duree_s": 1.53, + "images": 47, + "planche": { + "fichier": "planches/qua_sword_attack.jpg", + "images": 18, + "taille": 256, + "ips": 11.8 + }, + "cadence": 30, + "taille_ko": { + "feminin": 549, + "masculin": 539, + "total": 1089 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 89, + "droite": 100 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "épée", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Joué une fois : un coup d'épée ; à enchaîner après l'attente à l'épée.", + "en": "Played once: a sword strike; chain after the sword idle." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.05, + "pire_torsion_deg": 0.1 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "412F8748FC0F434155C1312F601C68BACBF025BF20450BE7DBF70524C0BA21D6" + }, + { + "cle": "qua_sword_idle", + "appel": { + "script": "Actor.animate(qua_sword_idle)", + "action": "ANIMATION: qua_sword_idle" + }, + "nom": { + "fr": "Attente à l'épée", + "en": "Sword idle" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_sword_idle_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_sword_idle_M" + }, + "duree_s": 1.67, + "images": 51, + "planche": { + "fichier": "planches/qua_sword_idle.jpg", + "images": 20, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 569, + "masculin": 558, + "total": 1126 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 100, + "droite": 100 + }, + "mains": { + "gauche": "repos", + "droite": "repos" + } + }, + "accessoire": "épée", + "categorie": "combat", + "style": "agressif", + "usage": { + "fr": "Boucle d'attente debout, épée en main, en garde.", + "en": "Standing idle loop, sword in hand, on guard." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "60227B1417B16DFE5D64C01AF23CFC3731A39B49737FC7B8A6F92AA664F1D18C" + }, + { + "cle": "qua_walk_formal_loop", + "appel": { + "script": "Actor.animate(qua_walk_formal_loop)", + "action": "ANIMATION: qua_walk_formal_loop" + }, + "nom": { + "fr": "Marche formelle", + "en": "Formal walk" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_walk_formal_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_walk_formal_loop_M" + }, + "duree_s": 1.33, + "images": 41, + "planche": { + "fichier": "planches/qua_walk_formal_loop.jpg", + "images": 16, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 500, + "masculin": 490, + "total": 990 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.36 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 68, + "droite": 68 + }, + "mains": { + "gauche": "repos", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "locomotion", + "style": "formel", + "usage": { + "fr": "Boucle de marche tenue et digne sur place ; à combiner avec un déplacement (cérémonie, travail).", + "en": "Looping upright, dignified walk in place; combine with a movement (ceremony, office)." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.0 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "B6F21793C592498783A5A4FA7BE20889307484B8A86660DBE2537EF3201F13F1" + }, + { + "cle": "qua_walk_loop", + "appel": { + "script": "Actor.animate(qua_walk_loop)", + "action": "ANIMATION: qua_walk_loop" + }, + "nom": { + "fr": "Marche", + "en": "Walk" + }, + "assets": { + "feminin": "/lpr_anim_quaternius/Anims/Female/qua_walk_loop_F", + "masculin": "/lpr_anim_quaternius/Anims/Male/qua_walk_loop_M" + }, + "duree_s": 1.33, + "images": 41, + "planche": { + "fichier": "planches/qua_walk_loop.jpg", + "images": 16, + "taille": 256, + "ips": 12.0 + }, + "cadence": 30, + "taille_ko": { + "feminin": 506, + "masculin": 496, + "total": 1002 + }, + "taille_cuite": false, + "boucle": { + "oui": true, + "ecart_pct": 0.0 + }, + "deplacement": { + "cm": 0, + "cm_s": 0, + "sens": "sur place" + }, + "posture": { + "principale": "debout", + "posture_origine": "calculee" + }, + "contacts": { + "pieds_au_sol_pct": { + "gauche": 68, + "droite": 68 + }, + "mains": { + "gauche": "mouvement", + "droite": "mouvement" + } + }, + "accessoire": "", + "categorie": "locomotion", + "style": "neutre", + "usage": { + "fr": "Boucle de marche sur place ; à combiner avec un déplacement du personnage.", + "en": "Looping walk in place; combine with a character movement." + }, + "corps": [ + "feminin", + "masculin" + ], + "qualite": { + "verdict": "accepté", + "motifs": [], + "pire_brut_pct": 0.0, + "pire_torsion_deg": 0.01 + }, + "source": "Quaternius Universal Animation Library (Standard)", + "licence": "CC0 1.0", + "credit": "Animations : Universal Animation Library (Standard) par Quaternius, licence CC0 1.0, https://quaternius.com", + "version": "1.0", + "empreinte": "2C83B802CC2E1CE528DACCED02E8DBD6C19D37575694D309DE3615A68E5F2A0B" + } + ] +} diff --git a/Tools/anim/Catalogue.py b/Tools/anim/Catalogue.py new file mode 100644 index 0000000..81c4e45 --- /dev/null +++ b/Tools/anim/Catalogue.py @@ -0,0 +1,461 @@ +#!/usr/bin/env python3 +"""Catalogue des animations d'un mod (lot AP6) : catalogue.json, catalogue.html, vignettes. + +Entrees : pack.json (declare), livraison.json + fiches_calculees.json + rapport.json + csv de qualite (calcule), +vignettes Saved/Measurement/vignettes/.png (carres 512 px), planches Saved/Measurement/planches/.jpg + .json +(bande de N images carrees de 256 px, animee au survol), clips du mod ModSources//Content/Anims. +Controles bloquants : code de sortie 1 et liste des causes ; rien n'est ecrit dans --out en cas d'echec. +Python 3 standard, sans dependance. +""" +import argparse +import csv +import datetime +import hashlib +import html +import json +import os +import re +import shutil +import sys + +BASE_KEYS = ["martialart", "sneak", "dance", "smoke", "write", "drinkbottle", "drinkglass", "drinktea", + "camera", "call", "browse", "makeup", "eat", "sweep", "fightlost", "gun", "knockedout"] +TRIAL_MODULE = "lpr_anim_essai" +SENS_FR = {"sur place": "sur place", "avant": "avance", "arriere": "recule", "cote": "de côté"} + + +def read_json(path): + with open(path, encoding="utf-8-sig") as f: + return json.load(f) + + +def sha256_of(paths): + h = hashlib.sha256() + for p in paths: + with open(p, "rb") as f: + for chunk in iter(lambda: f.read(1 << 20), b""): + h.update(chunk) + return h.hexdigest().upper() + + +def read_csv_rows(path): + if not os.path.isfile(path): + return [] + with open(path, encoding="utf-8-sig", newline="") as f: + return list(csv.DictReader(f)) + + +def num(v): + try: + return float(v) + except (TypeError, ValueError): + return 0.0 + + +def game_keys(root): + """Cles deja utilisees par le jeu (hors module d'essai) : ANIMATION: et animate().""" + keys = set() + mods = os.path.join(root, "Content", "Modules") + pat = re.compile(r"ANIMATION:\s*([A-Za-z0-9_]+)|animate\(\s*([A-Za-z0-9_]+)\s*\)") + for dp, dn, fn in os.walk(mods): + rel = os.path.relpath(dp, mods).replace("\\", "/") + if rel.split("/")[0] == TRIAL_MODULE: + dn[:] = [] + continue + for name in fn: + if name.lower().endswith((".lpaction", ".lpscene")): + try: + with open(os.path.join(dp, name), encoding="utf-8-sig", errors="replace") as f: + text = f.read() + except OSError: + continue + for m in pat.finditer(text): + keys.add((m.group(1) or m.group(2)).lower()) + return keys + + +def other_catalogue_keys(root, mod, out_dir): + keys = {} + base = os.path.join(root, "ModSources") + if not os.path.isdir(base): + return keys + own = os.path.normcase(os.path.abspath(os.path.join(out_dir, "catalogue.json"))) + for d in sorted(os.listdir(base)): + p = os.path.join(base, d, "Module", "Animations", "catalogue.json") + if d == mod or not os.path.isfile(p) or os.path.normcase(os.path.abspath(p)) == own: + continue + try: + for a in read_json(p).get("animations", []): + keys[str(a.get("cle", "")).lower()] = d + except (ValueError, OSError): + pass + return keys + + +def build(args, errors): + root = os.path.abspath(args.root) + pipe = os.path.abspath(args.pipeline) + pack_path = os.path.abspath(args.pack) + out = os.path.abspath(args.out) + mod_dir = os.path.abspath(args.mod_dir) if args.mod_dir else os.path.join(root, "ModSources", args.mod) + vign = os.path.abspath(args.vignettes) if args.vignettes else os.path.join(root, "Saved", "Measurement", "vignettes") + plan = os.path.abspath(args.planches) if args.planches else os.path.join(root, "Saved", "Measurement", "planches") + + def load(path, what): + if not os.path.isfile(path): + errors.append("%s introuvable : %s" % (what, path)) + return None + try: + return read_json(path) + except ValueError as e: + errors.append("%s illisible : %s (%s)" % (what, path, e)) + return None + + pack = load(pack_path, "pack.json") + liv_path = os.path.join(pipe, "livraison.json") + fic_path = os.path.join(pipe, "fiches_calculees.json") + liv = load(liv_path, "livraison.json") + fic = load(fic_path, "fiches_calculees.json") + rap = load(os.path.join(pipe, "rapport.json"), "rapport.json") + if None in (pack, liv, fic, rap): + return None + + # Rapport et fiches calculees. + if rap.get("valide") is not True: + errors.append("rapport.json non valide : %s" % "; ".join(map(str, rap.get("echecs") or []))) + if fic.get("echecs"): + errors.append("fiches_calculees.json contient des echecs : %s" % "; ".join(map(str, fic["echecs"]))) + if os.path.getmtime(fic_path) <= os.path.getmtime(liv_path): + errors.append("fiches_calculees.json (%s) n'est pas plus recent que livraison.json (%s) : " + "le catalogue ne decrit pas les clips livres" + % (datetime.datetime.fromtimestamp(os.path.getmtime(fic_path)).isoformat(" ", "seconds"), + datetime.datetime.fromtimestamp(os.path.getmtime(liv_path)).isoformat(" ", "seconds"))) + fiches = fic.get("fiches", {}) + declared = pack.get("animations", {}) + + # Cles : uniques, sans collision. + keys = [str(e.get("cle", "")) for e in liv] + seen = set() + for k in keys: + if k in seen: + errors.append("cle en double dans livraison.json : %s" % k) + seen.add(k) + taken = {k: "jeu de base" for k in BASE_KEYS} + for k in game_keys(root): + taken.setdefault(k, "scenario du jeu") + for k, d in other_catalogue_keys(root, args.mod, out).items(): + taken.setdefault(k, "catalogue de %s" % d) + for k in keys: + if k.lower() in taken: + errors.append("collision de cle : %s deja utilisee (%s)" % (k, taken[k.lower()])) + + # Qualite. + a_revoir = {} + for line in rap.get("a_revoir") or []: + parts = [p.strip() for p in str(line).split(" : ", 2)] + if len(parts) == 3: + a_revoir.setdefault(parts[1], []).append("%s : %s" % (parts[0], parts[2])) + qual = {} + for corps in ("Bridget", "Michael"): + for r in read_csv_rows(os.path.join(pipe, "eval_%s.csv" % corps)): + q = qual.setdefault(r["clip"], {"brut": 0.0, "torsion": 0.0}) + q["brut"] = max(q["brut"], num(r.get("brut_pire"))) + q["torsion"] = max(q["torsion"], num(r.get("torsion_deg"))) + + animations = [] + thumbs = [] + for e in liv: + k = str(e.get("cle", "")) + d = declared.get(k) + f = fiches.get(k) + if d is None: + errors.append("%s : absente de pack.json" % k) + if f is None: + errors.append("%s : fiche calculee absente" % k) + if d is None or f is None: + continue + clip = d.get("clip", "") + miss = [] + for name, val in (("clip", clip), ("nom.fr", (d.get("nom") or {}).get("fr")), ("nom.en", (d.get("nom") or {}).get("en")), + ("categorie", d.get("categorie")), ("style", d.get("style")), + ("usage.fr", (d.get("usage") or {}).get("fr")), ("usage.en", (d.get("usage") or {}).get("en"))): + if not val: + miss.append(name) + for name in ("images", "cadence", "duree_s", "boucle", "deplacement_cm", "vitesse_cm_s", "deplacement_sens", + "posture", "pieds_au_sol_pct", "mains"): + if f.get(name) in (None, "", {}): + miss.append("fiche." + name) + for name in ("source", "licence", "credit"): + if not pack.get({"source": "source", "licence": "licence", "credit": "credit"}[name]): + miss.append("pack." + name) + for name in ("asset_F", "asset_M"): + if not e.get(name): + miss.append("livraison." + name) + if miss: + errors.append("%s : champs obligatoires vides : %s" % (k, ", ".join(miss))) + thumb = os.path.join(vign, "%s.png" % clip) + if not clip or not os.path.isfile(thumb): + errors.append("%s : vignette absente (%s)" % (k, thumb)) + pj = os.path.join(plan, "%s.jpg" % clip) + pm = os.path.join(plan, "%s.json" % clip) + pinfo = None + if not clip or not os.path.isfile(pj): + errors.append("%s : planche absente (%s)" % (k, pj)) + elif not os.path.isfile(pm): + errors.append("%s : description de planche absente (%s)" % (k, pm)) + else: + try: + pinfo = read_json(pm) + n_img = pinfo["images"] + if isinstance(n_img, bool) or not isinstance(n_img, int) or n_img < 2: + errors.append("%s : planche invalide, images = %r (au moins 2 attendues) : %s" % (k, n_img, pm)) + pinfo = None + elif pinfo.get("taille") != 256: + errors.append("%s : planche invalide, taille = %r (256 attendu) : %s" % (k, pinfo.get("taille"), pm)) + pinfo = None + except (ValueError, KeyError, TypeError, AttributeError) as e: + errors.append("%s : description de planche illisible : %s (%r)" % (k, pm, e)) + pinfo = None + files = [os.path.join(mod_dir, "Content", "Anims", "Female", k + "_F.uasset"), + os.path.join(mod_dir, "Content", "Anims", "Male", k + "_M.uasset")] + for p in files: + if not os.path.isfile(p): + errors.append("%s : clip du mod absent : %s" % (k, p)) + if miss or not os.path.isfile(files[0]) or not os.path.isfile(files[1]) or not os.path.isfile(thumb) or pinfo is None: + continue # causes deja listees ci-dessus + + tf, tm = os.path.getsize(files[0]), os.path.getsize(files[1]) + motifs = a_revoir.get(clip, []) + q = qual.get(clip, {"brut": 0.0, "torsion": 0.0}) + decl = d.get("posture") + if decl is not None and (not isinstance(decl, str) or not decl.strip()): + errors.append("%s : posture declaree invalide dans pack.json" % k) + continue + posture = {"principale": decl if decl else f["posture"], + "posture_origine": "declaree" if decl else "calculee"} + if decl: + posture["posture_calculee"] = f["posture"] + if f.get("posture_debut") != f.get("posture_fin"): + posture["debut"], posture["fin"] = f.get("posture_debut"), f.get("posture_fin") + # Hauteur d'assise seulement pour une posture assise (une chute traverse des images "assis"). + if f.get("hauteur_assise_cm") is not None and posture["principale"] == "assis": + posture["hauteur_assise_cm"] = f["hauteur_assise_cm"] + dur_p = float(f["duree_s"]) or num(pinfo.get("duree_s")) + if dur_p <= 0: + errors.append("%s : duree nulle, cadence de planche incalculable" % k) + continue + animations.append({ + "cle": k, + "appel": {"script": "Actor.animate(%s)" % k, "action": "ANIMATION: %s" % k}, + "nom": {"fr": d["nom"]["fr"], "en": d["nom"]["en"]}, + "assets": {"feminin": e["asset_F"], "masculin": e["asset_M"]}, + "duree_s": round(float(f["duree_s"]), 2), + "images": f["images"], + "planche": {"fichier": "planches/%s.jpg" % k, "images": pinfo["images"], "taille": 256, + "ips": round(pinfo["images"] / dur_p, 1)}, + "cadence": f["cadence"], + "taille_ko": {"feminin": round(tf / 1024), "masculin": round(tm / 1024), "total": round((tf + tm) / 1024)}, + "taille_cuite": False, + "boucle": {"oui": bool(f["boucle"]), "ecart_pct": round(f.get("boucle_ecart_pct") or 0.0, 2)}, + "deplacement": {"cm": f["deplacement_cm"], "cm_s": f["vitesse_cm_s"], "sens": f["deplacement_sens"]}, + "posture": posture, + "contacts": {"pieds_au_sol_pct": f["pieds_au_sol_pct"], "mains": f["mains"]}, + "accessoire": d.get("accessoire", ""), + "categorie": d["categorie"], + "style": d["style"], + "usage": {"fr": d["usage"]["fr"], "en": d["usage"]["en"]}, + "corps": ["feminin", "masculin"], + "qualite": {"verdict": "à revoir" if motifs else "accepté", "motifs": motifs, + "pire_brut_pct": round(q["brut"], 2), "pire_torsion_deg": round(q["torsion"], 2)}, + "source": pack.get("source", ""), + "licence": pack.get("licence", ""), + "credit": pack.get("credit", ""), + "version": args.version, + "empreinte": sha256_of(files), + }) + thumbs.append((k, thumb, pj)) + if errors: + return None + header = { + "pack": pack.get("pack", ""), "mod": args.mod, "version": args.version, + "genere": datetime.datetime.now().isoformat(timespec="seconds"), + "nombre_animations": len(animations), "credit": pack.get("credit", ""), + "animations": animations, + } + return header, thumbs, out + + +# ---------------------------------------------------------------------------- HTML + +CSS = """ +:root{--bg:#f6f7f9;--fg:#1d2330;--mut:#5d6677;--card:#fff;--bd:#d9dde5;--acc:#2057c9;--ok:#1d7a3f;--warn:#a85b00;--chip:#eef1f6} +@media (prefers-color-scheme:dark){:root{--bg:#14171d;--fg:#e6e9ef;--mut:#9aa3b4;--card:#1d222b;--bd:#323a48;--acc:#7aa7ff;--ok:#5fcf8a;--warn:#f0a850;--chip:#262c37}} +*{box-sizing:border-box} +body{margin:0;background:var(--bg);color:var(--fg);font:15px/1.45 system-ui,Segoe UI,sans-serif;overflow-wrap:anywhere} +header{padding:16px;max-width:1200px;margin:0 auto} +h1{margin:0 0 4px;font-size:1.4rem} +.sub{color:var(--mut);font-size:.9rem} +.bar{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px} +.bar input,.bar select{font:inherit;padding:6px 8px;border:1px solid var(--bd);border-radius:6px;background:var(--card);color:var(--fg);min-width:0;max-width:100%} +.bar input{flex:1 1 220px} +main{max-width:1200px;margin:0 auto;padding:0 16px 24px;display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,300px),1fr));gap:12px} +.card{background:var(--card);border:1px solid var(--bd);border-radius:10px;overflow:hidden;display:flex;flex-direction:column} +.card[hidden],.card img[hidden],.card .anim[hidden]{display:none} +.card img{width:100%;aspect-ratio:1/1;object-fit:contain;background:var(--chip);display:block} +.card .anim{width:100%;aspect-ratio:1/1;background-color:var(--chip);background-repeat:no-repeat} +.in{padding:10px 12px;display:flex;flex-direction:column;gap:6px} +.in h2{margin:0;font-size:1.05rem} +.key{font-family:Consolas,monospace;background:var(--chip);border:1px solid var(--bd);border-radius:6px;padding:3px 6px;cursor:pointer;text-align:left;color:var(--fg);font-size:.85rem} +.call{font-family:Consolas,monospace;font-size:.8rem;color:var(--mut)} +.tags{display:flex;flex-wrap:wrap;gap:4px} +.tags span{background:var(--chip);border-radius:10px;padding:1px 8px;font-size:.78rem} +.use{font-size:.88rem} +.q-ok{color:var(--ok)}.q-rev{color:var(--warn);font-weight:600} +footer{max-width:1200px;margin:0 auto;padding:0 16px 24px;color:var(--mut);font-size:.8rem} +#none{display:none;padding:16px;max-width:1200px;margin:0 auto} +""" + +JS = """ +const A=JSON.parse(document.getElementById('data').textContent).animations; +const $=id=>document.getElementById(id); +const cap=s=>s.charAt(0).toUpperCase()+s.slice(1); +function dur(a){return a.duree_s<2?'courte':(a.duree_s>5?'longue':'moyenne')} +function fill(sel,vals){[...new Set(vals)].sort().forEach(v=>{const o=document.createElement('option');o.value=v;o.textContent=v;sel.appendChild(o)})} +fill($('fcat'),A.map(a=>a.categorie));fill($('fpos'),A.map(a=>a.posture.principale)); +const SENS={'sur place':'sur place','avant':'avance','arriere':'recule','cote':'de côté'}; +function esc(s){return String(s).replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c]))} +function card(a){ + const dp=a.deplacement,p=a.posture; + let pos=p.principale;if(p.debut)pos+=' ('+p.debut+' → '+p.fin+')';if(p.hauteur_assise_cm!=null)pos+=', assise '+p.hauteur_assise_cm+' cm'; + const mv=dp.sens==='sur place'?'sur place':(SENS[dp.sens]||dp.sens)+' '+Math.round(dp.cm)+' cm ('+Math.round(dp.cm_s)+' cm/s)'; + const q=a.qualite,qc=q.verdict==='accepté'?'q-ok':'q-rev'; + const el=document.createElement('article');el.className='card'; + el.innerHTML=''+esc(a.nom.fr)+'' + +'

'+esc(a.nom.fr)+' / '+esc(a.nom.en)+'

' + +'' + +'
'+esc(a.appel.script)+'
'+esc(a.appel.action)+'
' + +'
'+esc(a.categorie)+''+esc(pos)+''+a.duree_s.toString().replace('.',',')+' s ('+dur(a)+')' + +''+(a.boucle.oui?'boucle':'une fois')+''+esc(mv)+''+(a.accessoire?''+esc(a.accessoire)+'':'')+'
' + +'
'+esc(a.usage.fr)+'
' + +'
Qualité : '+esc(q.verdict)+(q.motifs.length?' ('+esc(q.motifs.join(' ; '))+')':'')+'
'; + hover(el,a); + const b=el.querySelector('.key'); + b.onclick=()=>{const done=()=>{b.textContent='copié';setTimeout(()=>b.textContent=a.cle,900)}; + if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(a.cle).then(done,()=>sel(b))}else sel(b)}; + return el} +const reduce=matchMedia('(prefers-reduced-motion: reduce)'); +function hover(el,a){ + const pl=a.planche,img=el.querySelector('img');let div=null,timer=null,ready=false,want=false,last='mouse'; + function show(){if(!want||!ready)return;img.hidden=true;div.hidden=false;let i=0;div.style.backgroundPosition='0% 0%'; + clearInterval(timer);timer=setInterval(()=>{i=(i+1)%pl.images;div.style.backgroundPosition=(i*100/(pl.images-1))+'% 0%'},1000/pl.ips)} + function start(){want=true; + if(!div){div=document.createElement('div');div.className='anim';div.hidden=true;div.setAttribute('role','img');div.setAttribute('aria-label',a.nom.fr); + div.style.backgroundSize=(pl.images*100)+'% 100%';img.parentNode.insertBefore(div,img); + const im=new Image();im.onload=()=>{div.style.backgroundImage='url("'+pl.fichier+'")';ready=true;show()};im.src=pl.fichier} + else show()} + function stop(){want=false;clearInterval(timer);timer=null;if(div)div.hidden=true;img.hidden=false} + el.addEventListener('pointerenter',e=>{if(e.pointerType!=='touch'&&!reduce.matches)start()}); + el.addEventListener('pointerleave',e=>{if(e.pointerType!=='touch')stop()}); + el.addEventListener('pointerdown',e=>{last=e.pointerType}); + el.addEventListener('click',e=>{if(!e.target.closest('img,.anim'))return;if(last==='touch'||reduce.matches){want?stop():start()}})} +function sel(b){const r=document.createRange();r.selectNodeContents(b);const s=getSelection();s.removeAllRanges();s.addRange(r)} +const main=$('list'),cards=A.map(a=>({a,el:card(a)}));cards.forEach(c=>main.appendChild(c.el)); +function apply(){ + const t=$('q').value.trim().toLowerCase(),c=$('fcat').value,p=$('fpos').value,d=$('fdur').value;let n=0; + cards.forEach(x=>{const a=x.a; + const hay=(a.cle+' '+a.nom.fr+' '+a.nom.en+' '+a.usage.fr+' '+a.usage.en+' '+a.accessoire+' '+a.style).toLowerCase(); + const ok=(!t||hay.includes(t))&&(!c||a.categorie===c)&&(!p||a.posture.principale===p)&&(!d||dur(a)===d); + x.el.hidden=!ok;if(ok)n++}); + $('count').textContent=n+' / '+A.length+' animation(s)';$('none').style.display=n?'none':'block'} +['q','fcat','fpos','fdur'].forEach(i=>$(i).addEventListener('input',apply));apply(); +""" + + +def render_html(cat): + data = json.dumps(cat, ensure_ascii=False).replace(" + + + + +%(title)s + + + +
+

%(title)s

+
Version %(version)s — %(n)d animations — généré le %(date)s. Copiez la clé puis écrivez Actor.animate(clé) dans une scène ou ANIMATION: clé dans une action. Survolez une vignette pour voir le mouvement.
+
+ + + + +
+
+
+
Aucune animation ne correspond aux filtres.
+
+
%(credit)s
+ + + + +""" % {"title": html.escape(title), "css": CSS, "js": JS, "data": data, "version": html.escape(cat["version"]), + "n": cat["nombre_animations"], "date": html.escape(cat["genere"][:10]), "credit": html.escape(cat["credit"])} + + +def main(): + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument("--pack", required=True) + ap.add_argument("--pipeline", required=True) + ap.add_argument("--mod", required=True) + ap.add_argument("--version", required=True) + ap.add_argument("--out", required=True) + here = os.path.dirname(os.path.abspath(__file__)) + ap.add_argument("--root", default=os.path.dirname(os.path.dirname(here)), help="racine du projet") + ap.add_argument("--mod-dir", default="", help="dossier du mod (defaut : /ModSources/)") + ap.add_argument("--planches", default="", help="dossier des planches .jpg/.json (defaut : /Saved/Measurement/planches)") + ap.add_argument("--vignettes", default="", help="dossier des vignettes .png (defaut : /Saved/Measurement/vignettes)") + args = ap.parse_args() + + errors = [] + result = None + try: + result = build(args, errors) + except Exception as e: # noqa: BLE001 + errors.append("erreur inattendue : %r" % (e,)) + rapport = os.path.join(os.path.abspath(args.pipeline), "catalogue_rapport.json") + info = {"date": datetime.datetime.now().isoformat(timespec="seconds"), "mod": args.mod, "version": args.version, + "ok": result is not None and not errors, "fiches": len(result[0]["animations"]) if result else 0, + "echecs": errors} + if result is None or errors: + try: + os.makedirs(os.path.dirname(rapport), exist_ok=True) + with open(rapport, "w", encoding="utf-8", newline="\n") as f: + json.dump(info, f, ensure_ascii=False, indent=2) + except OSError: + pass + print("CATALOGUE ECHEC : %d cause(s)" % len(errors), file=sys.stderr) + for e in errors: + print(" - " + e, file=sys.stderr) + return 1 + cat, thumbs, out = result + os.makedirs(os.path.join(out, "vignettes"), exist_ok=True) + os.makedirs(os.path.join(out, "planches"), exist_ok=True) + for k, src, psrc in thumbs: + shutil.copyfile(src, os.path.join(out, "vignettes", k + ".png")) + shutil.copyfile(psrc, os.path.join(out, "planches", k + ".jpg")) + with open(os.path.join(out, "catalogue.json"), "w", encoding="utf-8", newline="\n") as f: + json.dump(cat, f, ensure_ascii=False, indent=2) + f.write("\n") + with open(os.path.join(out, "catalogue.html"), "w", encoding="utf-8", newline="\n") as f: + f.write(render_html(cat)) + with open(rapport, "w", encoding="utf-8", newline="\n") as f: + json.dump(info, f, ensure_ascii=False, indent=2) + print("CATALOGUE OK : %d fiche(s) -> %s" % (len(cat["animations"]), out)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/Tools/anim/DeliverAnims.ps1 b/Tools/anim/DeliverAnims.ps1 index 3d83a8c..0f2be07 100644 --- a/Tools/anim/DeliverAnims.ps1 +++ b/Tools/anim/DeliverAnims.ps1 @@ -13,6 +13,9 @@ dans UnrealEditor-Cmd (journal Saved\Logs\portage\AP5_DeliverAnims_.log), remet le mod en place, controle la sortie (LIVRAISON copies 2n erreurs 0, n fichiers .uasset par sexe). Code de sortie 1 au moindre ecart. + -Catalogue : apres une livraison reussie, lance Tools\anim\Catalogue.py (lot AP6). + -CatalogueOnly : saute la copie et ne produit que le catalogue (rapport valide exige), sans lancer Unreal. + .EXAMPLE .\Tools\anim\DeliverAnims.ps1 -DryRun .\Tools\anim\DeliverAnims.ps1 @@ -23,7 +26,9 @@ param( [string] $Prefix = 'qua', [string] $Exclude = 'A_TPose', [string] $Report = '', - [switch] $DryRun + [switch] $DryRun, + [switch] $Catalogue, + [switch] $CatalogueOnly ) $ErrorActionPreference = 'Stop' @@ -39,6 +44,21 @@ function New-IfMissing([string] $Path, [string] $Text) { Write-Host " cree : $Path" } +# Lot AP6 : catalogue du mod (Tools\anim\Catalogue.py), version lue dans le .lpmod. +function Invoke-Catalogue { + $lpmodPath = Join-Path $Root "ModSources\$Name\Module\$Name.lpmod" + if (-not (Test-Path $lpmodPath)) { throw "lpmod introuvable : $lpmodPath" } + $line = Select-String -Path $lpmodPath -Pattern '^MODULE_VERSION:\s*(\S+)' | Select-Object -First 1 + if (-not $line) { throw "MODULE_VERSION absente de $lpmodPath" } + $version = $line.Matches[0].Groups[1].Value + $pipeline = Split-Path $Report -Parent + $out = Join-Path $Root "ModSources\$Name\Module\Animations" + Write-Host "Catalogue : version $version -> $out" + & python (Join-Path $Root 'Tools\anim\Catalogue.py') --pack (Join-Path $Root 'AnimSources\quaternius\pack.json') ` + --pipeline $pipeline --mod $Name --version $version --out $out + if ($LASTEXITCODE -ne 0) { throw "Catalogue.py a echoue (code $LASTEXITCODE)" } +} + try { # 1. Verdict des controles qualite. if (-not (Test-Path $Report)) { throw "rapport.json introuvable : $Report" } @@ -49,6 +69,11 @@ try { } foreach ($r in @($rapport.a_revoir)) { Write-Warning "a revoir : $r" } + if ($CatalogueOnly -and -not $DryRun) { + Invoke-Catalogue + exit 0 + } + # 2. Controles d'environnement. $running = @(Get-Process UnrealEditor, UnrealEditor-Cmd -ErrorAction SilentlyContinue) if ($running) { throw "UnrealEditor est ouvert (pid $($running[0].Id)) : le fermer avant la livraison" } @@ -140,6 +165,7 @@ try { if ($count -ne $n) { throw "$dir : $count fichier(s) .uasset pour $n cle(s)" } } Write-Host "Livraison terminee : $n cle(s), $($n * 2) copies" + if ($Catalogue) { Invoke-Catalogue } exit 0 } catch {