LifePlay-Revival/Docs/Migration/20_Chaine_Animations.md
edujiro5972 e46093c81c DC3 : atelier de mods hors du jeu, dans l'addon LifePlay-Sandbox (CHG-236)
Retrait de BuildMod, NewMod, EditMod, ModSource, HairPipeline et leurs .py, Tools/anim,
Tools/hairs, Tools/mods, ModSources, AnimSources, Config/LPSandbox.ini, lanceurs sandbox et
guide des moddeurs (57 fichiers suivis ; contenu disque deplace vers la sauvegarde DC3).
References et docs mises a jour. Pin addon 79f0205. Validation : DC3-VAL PASS (cuisson
lpr_anim_freeanims depuis l'addon identique au mod publie, tournee identique a SB2-REF).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 19:53:13 +02:00

20 KiB
Raw Blame History

20. Chaîne des animations : de l'achat du pack au mod livré (étude, 2026-10-06)

Depuis le lot DC3 (2026-10-07), ces scripts, ModSources/ et AnimSources/ sont dans le dépôt addon LifePlay-Sandbox (même disposition relative ; lancer depuis l'addon, D:\Game\LifePlay-Sandbox).

Objectif : qu'un pack d'animations, quel que soit son squelette d'origine, soit converti pour les corps du jeu (Genesis 8 : Bridget, Michael), évalué et livré en mod sans intervention manuelle, avec un contrôle bloquant à chaque étape. Base technique : la méthode validée dans la sandbox Mesure (CHG-188 à 204, mémoire « transfert de pose ») et le mécanisme des mods d'assets (16_H3_Mods_Paquets.md).


1. État actuel de la chaîne

Question Situation aujourd'hui Source
Comment les animations entrent Un seul pack, importé à la main : Tools/ImportQuaternius.py lit un .glb à un chemin fixe (D:/Game/Universal Animation Library[Standard]/…) et écrit dans /Game/Quaternius/UAL. Un second pack (Content/FreeAnimationsPack, mannequin UE5) est présent mais n'est pas traité. ImportQuaternius.py
Comment le modèle est identifié Levé (AP7) : -run=LPAnimIdentify (et LPAnimMeasure::Identify) compare les os du squelette aux profils Tools/anim/profiles/*.json (score par profil, os manquants, méthode associée) ; à égalité, le profil le plus complet l'emporte (le mannequin UE5 contient tous les noms UE4). Les tables ne sont plus en dur. CHG-221
Le pack contient-il un modèle de référence Quaternius : oui, UAL1_Standard (maillage, squelette, repos en pose T). FreeAnimationsPack : oui, SKM_Manny / SKM_Quinn, plus un clip MM_T_Pose et son propre RTG_Mannequin. Content/Quaternius/UAL, Content/FreeAnimationsPack/Demo
Calques Le calque de pose (CHG-203) est le squelette cible posé par la formule, à partir du squelette source du pack : il utilise déjà le modèle de référence du pack (son squelette au repos), pas un modèle à nous. mode Mesure du plugin LPSandbox (LPSandboxMeasure*.cpp, ex-LPPairSandbox.cpp)
Conversion Retargeter généré par Tools/anim/RetargetPack.py (ex-RetargetQuaternius.py), piloté par Saved/anim_retarget.json ; la méthode (ue4 pose T, ue5 pose A, genesis_direct) est choisie par -Methode=<id ou auto> ; pose de retarget écrite par -run=LPAnimEval (-PoseDir, Saved/Measurement par défaut) ou la sandbox Mesure ; os Twist répartis après cuisson (-run=LPAnimTwist). Module de mesure : LPAnimMeasure (addon LifePlay-Sandbox, 21_Sandbox_Addon.md). CHG-204, CHG-221, CHG-222
Évaluation Interactive : tournée sandbox Mesure (tour.csv, captures, vignettes, planches ; CHG-202, AP6). Headless : -run=LPAnimEval — rapports sous Saved/AnimPipeline/<run>/, contrôles AP4 (controles_*.csv, rapport.json). Enchaînée (AP7) : Tools/anim/AnimPipeline.ps1 (BuildMod.ps1 -Anim <pack>) exécute identification, calque, conversion, évaluation, livraison et catalogue ; passé sur Quaternius et FreeAnimationsPack. CHG-206 à CHG-208, CHG-223
Livraison Les clips convertis sont dans le contenu du jeu (/Game/Quaternius/UAL/B_*, M_*), adressés par un chemin en dur (LPAnimRedirect::ClipPath). Ils ne passent pas par un mod. BuildMod.ps1 -Retarget ne vérifie que la présence d'une ligne de journal. LPAnimRedirect.cpp, BuildMod.ps1
Appel depuis un scénario Un scénario désigne une animation par une clé courte : ANIMATION: write (.lpaction), Actor.animate(martialart) (.lpscene). Le jeu lui associe les assets <clé>_F (corps féminin) et <clé>_M (corps masculin), par exemple Content/Heavy/New3/Anims/Daily/martialart_F / _M ; la même convention sert aux paires de couple (LPShowCoupleSubsystem). Les clips convertis, nommés B_<clip> / M_<clip>, ne sont donc pas appelables par un scénario. Le jeu résout la clé par Person::PlayDaily, qui cherche dans Room.Dailies (tableau fixe de clips, sans registre d'assets) ; les clips des mods y sont ajoutés par ULPModDailiesSubsystem (CHG-209). vin_Base/Actions, vin_Base/Scenes
Information pour le moddeur Aucune : pour connaître la durée, la posture ou l'usage d'un clip, il faut l'ouvrir dans l'éditeur.

Écarts à combler

  1. Pas d'identification du squelette : un pack Mixamo, UE5, CC4 ou Genesis 9 serait converti avec une table fausse. Levé (AP7) : LPAnimIdentify et profils (CHG-221).
  2. Correspondance dupliquée (C++ et Python) : une modification oubliée d'un côté fausse le résultat sans erreur. Levé (AP1, CHG-205) : profils JSON lus par le C++ et le Python.
  3. La pose de retarget dépend d'une ouverture manuelle de la sandbox. Levé (AP2 / S6, confirmé AP7) : -run=LPAnimEval écrit les mêmes fichiers sans fenêtre ; la sandbox reste utile pour le contrôle visuel.
  4. Torsion des membres non répartie entre Bend et Twist (peau de l'avant-bras).
  5. Michael converti mais jamais mesuré.
  6. Livraison hors mod : impossible de distribuer un pack sans recuire le jeu.
  7. Aucun contrôle bloquant entre les étapes.
  8. Clips nommés hors de la convention <clé>_F / <clé>_M : inutilisables depuis un scénario.
  9. Aucun catalogue : un moddeur doit ouvrir chaque clip pour savoir ce qu'il fait.

2. Réponses de fond

Le modèle de référence du pack doit-il servir aux calques ? Oui, et c'est même nécessaire. Le calque est le squelette cible posé par la transformation ; la transformation part de la pose T du squelette source. Chaque pack apporte donc sa référence : son squelette au repos suffit (un USkeleton a toujours une pose de référence, même sans maillage) ; son maillage ne sert qu'à l'affichage (touche M). Notre mannequin UAL1_Standard ne convient que pour les packs au squelette mannequin UE4.

Condition : le repos du squelette source doit être une pose T connue. Un pack livré en pose A (comme Genesis) doit déclarer sa conversion A → T dans son profil (comme les réglages Daz). Un contrôle le vérifie (étape 3).

Conversion d'un modèle vers un autre : la méthode validée est générale :

  • pose T commune, ajustée segment par segment (phase A) ;
  • rotation de chaque os depuis la pose T, passée dans le repère du corps cible (phase B) ;
  • chaînes de longueurs différentes réparties par interpolation (colonne, cou) ;
  • torsion séparée entre os Bend et Twist ;
  • report dans le retargeter Unreal (phase C), qui applique la même formule quand sa pose de retarget est la pose T ajustée (0,00 % d'écart sur 129 instants, CHG-204).

Seule la table de correspondance change d'un squelette à l'autre : elle devient une donnée (profil), plus du code.

Méthodes de transformation (AP7). Le convertisseur choisit un profil de transformation (Tools/anim/methodes/*.json, -Methode=<id ou auto>) en quatre parties : 1) la pose du mannequin source, A ou T, est le calque d'origine ; 2) Bridget et Michael sont placés dans la même pose, le calque étant ajusté à leur morphologie ; 3) la méthode est choisie d'après le profil identifié ; 4) la transformation est appliquée. Méthodes : ue4 (pose T, mannequin UE4 / Quaternius), ue5 (pose A : calques = repos du mannequin UE5 et de Genesis, ajusté à la morphologie), genesis_direct (copie Daz, déclarée factice). Règle d'égalité : à score égal entre profils, le plus complet l'emporte (le mannequin UE5 contient tous les noms UE4 et était pris pour UE4 à 100 %). Pour UE5 la conversion se fait A → A : aucun angle A → T n'est inventé, les deux calques sont dans la même pose de repos. Borne des réglages : 30° pour le corps, 45° pour les doigts (-SeuilReglageDoigts), la main du mannequin UE5 étant au repos légèrement fermée (ajustement des doigts ≈ 31°). Voir CHG-221.


3. Chaîne cible

Un pilote unique, Tools/AnimPipeline.ps1, sur le modèle de HairPipeline.ps1, appelé par BuildMod.ps1 -Anim <pack>. Chaque étape écrit un rapport JSON dans Saved/AnimPipeline/<pack>/ et s'arrête au premier contrôle en échec, avec la liste des causes. Une étape réussie n'est pas refaite (reprise par -From <étape>). Rien n'est supprimé : un résultat précédent est déplacé dans precedent_<date>.

# Étape Contenu Contrôle bloquant
0 Inventaire Pack déclaré dans AnimSources/<pack>/pack.json : origine, licence, fichiers (.fbx, .glb, ou dossier .uasset). Licence présente et compatible (règle existante de BuildMod pour les mods payants) ; fichiers trouvés ; empreintes SHA-256 consignées.
1 Import Import automatisé (généralisation d'ImportQuaternius.py) dans /AnimSources/<pack>/. Nombre de clips importés = nombre attendu ; durée et cadence lues ; aucun clip vide ; un squelette unique.
2 Identification Empreinte du squelette (noms d'os, hiérarchie) comparée aux profils Tools/anim/profiles/*.json : mannequin UE4, mannequin UE5, Mixamo, Genesis 8, Genesis 9, CC4… Un seul profil reconnu, avec au moins 95 % de ses os obligatoires présents ; sinon arrêt « squelette inconnu » et liste des os manquants.
3 Référence et pose T Pose T source = repos du squelette (ou conversion déclarée par le profil) ; ajustement de la pose T de chaque corps cible (phase A, sans la sandbox : commandlet). Repos source vérifié en T (bras à l'horizontale, jambes droites, tolérance fixée) ; après ajustement : tous les segments ≤ 1 %, réglages symétriques gauche / droite (écart ≤ 0,5°), aucun réglage hors bornes ; fichier retarget_pose_<Corps>.txt écrit.
4 Conversion Rigs et retargeters générés depuis le profil (chaînes, Interpolated pour colonne et cou, doigts, orteils, bassin) ; cuisson des copies dans /<Mod>/Anims/<Corps>/. Puis répartition de la torsion Bend / Twist sur les clips produits (post-traitement). Autant de clips produits que de clips source, par corps ; durées et nombres d'images identiques ; aucune valeur non numérique.
5 Évaluation Tournée sans intervention (fenêtre de jeu automatisée) sur chaque corps cible : écart à la formule, plus des contrôles indépendants (voir § 4). Planches de captures face / profil / dos et rapport HTML. Chaque clip est classé « accepté », « à revoir » ou « rejeté » selon des seuils fixés ; un clip rejeté bloque la livraison sauf exclusion explicite dans pack.json.
6 Catalogue Une fiche par animation (§ 5), calculée sur les clips produits et complétée par pack.json. Une fiche par clé et par clip ; clés uniques dans le mod et sans collision avec les clés du jeu ni des mods connus ; champs obligatoires remplis ; vignettes présentes.
7 Livraison Mod d'assets (H3) : clips renommés à la convention du jeu, <clé>_F / <clé>_M, sous /<Mod>/Anims/… ; module texte .lpmod ; catalogue joint ; cuisson DLC, contrôle du conteneur et archive .zip (étapes existantes de BuildMod). La clé peut contenir _ (coupure au dernier _, CHG-209) ; outil : Tools\anim\DeliverAnims.ps1. Conteneur sans asset du jeu ; archive testée ; essai de chargement : jeu de test lancé avec le mod, chaque clé du catalogue appelée par animate() sur un personnage féminin et un masculin (journal).

Réalisé par Tools/anim/AnimPipeline.ps1 (CHG-223) ; ordre réel des étapes 6 et 7 : la livraison dans le mod précède les fiches et le catalogue, puis vient la cuisson DLC.

Le jeu résout les clés par Room.Dailies ; les clips des mods y sont ajoutés par ULPModDailiesSubsystem (CHG-209). LPAnimRedirect ne sert plus qu'à la sandbox et au personnage piloté. Depuis le lot DC1, LPAnimRedirect et LPCoupleSim sont dans le plugin LPAnimCore du jeu (Plugins/LPAnimCore) ; la mesure reste dans le module LPAnimMeasure de l'addon. Depuis le lot DC2, les commandlets LPAnimEval, LPAnimTwist, LPAnimCatalog et LPAnimIdentify sont dans le module éditeur LPModTools de l'addon ; profils et méthodes sont lus via LPAnimMeasurePaths (addon, repli sur le jeu jusqu'à DC3).


4. Évaluation : ce qui est mesuré

L'écart à la formule (0,00 % aujourd'hui) prouve que la conversion reproduit la transformation ; il ne prouve pas que le résultat est beau. Des contrôles indépendants s'ajoutent, tous calculés sur la pose et sans rendu :

Contrôle Défaut visé Seuil « à revoir » (rejet : 3 × le seuil)
Écart à la formule (direction des segments, rotation du tronc) conversion fausse ≤ 1 %
Torsion locale des os Bend / Twist peau de l'avant-bras ou de la cuisse vrillée relevée ; bloquante sur option -SeuilTorsion
Main ou coude dans le volume du tronc (capsules) « le bras passe à travers le corps » pénétration ≤ 1 cm
Pied sous le sol, glissement au contact jambes plus longues ou plus courtes que la source sol ≤ 3 cm, glissement ≤ 3 cm/image
Limites articulaires (coude, genou) hyperextension genou ≤ 1 cm, flexion ≤ 5°
Continuité d'une image à l'autre saut, tremblement ≤ 10°, au-delà de 1,5 × la source + 2°
Symétrie des réglages de pose T ajustement aberrant d'un côté ≤ 0,5°

Faute d'actif physique sur les corps, les capsules du tronc sont construites depuis la peau du maillage.

Les planches de captures restent la validation finale à l'œil, mais seulement pour les clips classés « à revoir ».


5. Catalogue des animations (livré avec le mod)

But : qu'un moddeur choisisse une animation et l'écrive dans un scénario sans ouvrir l'éditeur ni le jeu.

Formats :

  • Content/Modules/<Mod>/Animations/catalogue.json : pour les outils (lecture par script, éditeur de scénarios) ;
  • Content/Modules/<Mod>/Animations/catalogue.html : pour le moddeur, une ligne par animation avec sa vignette, filtrable par posture, usage et durée ; lisible hors ligne ;
  • Content/Modules/<Mod>/Animations/vignettes/<clé>.png : profil droit à 1/3 de la durée, mode vignettes de la tournée.

Fiche d'une animation : calculé = mesuré sur le clip produit, sans saisie ; déclaré = repris de pack.json (ou déduit du nom, puis corrigeable).

Champ Exemple Origine
cle (identifiant) qua_walk_loop calculé : préfixe du pack + nom source normalisé ; unique et stable d'une version à l'autre
appel Actor.animate(qua_walk_loop) / ANIMATION: qua_walk_loop calculé
nom « Marche » / « Walk » déclaré (nom source par défaut)
assets /<Mod>/Anims/Female/qua_walk_loop_F, …/Male/qua_walk_loop_M calculé
duree_s, images, cadence 1,07 s, 32 images, 30 i/s calculé
taille_ko 186 Ko (_F) + 190 Ko (_M), cuits calculé (après cuisson)
boucle oui (première et dernière pose identiques à 1 % près) calculé
deplacement avance 1,2 m par cycle (1,1 m/s), sans root motion : le personnage marche sur place calculé (trajet du bassin)
posture debout / assis / accroupi / à genoux / allongé calculé (hauteur du bassin et inclinaison du tronc)
hauteur_assise_cm 46 cm (pour placer un siège) calculé, postures assises
contacts pieds au sol ; mains libres / main droite occupée calculé (hauteur des pieds, vitesse et position des mains)
accessoire pistolet, épée, torche, volant déclaré, proposé d'après le nom (Pistol, Sword, Torch, Driving)
categorie locomotion, attente, conversation, combat, assis, interaction, sport, danse déclaré, proposé d'après le nom
style neutre, formel, détendu, agressif déclaré
usage « attente en conversation, debout » déclaré
corps féminin, masculin calculé (clips produits)
qualite accepté ; pire écart 0,00 % ; contrôles verts calculé (étape 5)
source, licence, credit Quaternius UAL, CC0 déclaré (pack.json)
version, empreinte version du mod, SHA-256 des clips calculé

Réalisation (AP6, CHG-210) : les champs calculés viennent de LPAnimCatalogCommandlet (-run=LPAnimCatalog, mesure image par image du clip féminin source, contrôle que F et M ont même durée et même nombre d'images) ; les champs déclarés viennent de AnimSources/quaternius/pack.json ; la qualité vient du rapport AP4 ; la taille, l'empreinte et les chemins viennent des fichiers livrés. Tools/anim/Catalogue.py assemble le tout. Définitions : boucle si la dernière image diffère de la première de 1 % de la taille ou moins (extrémités relatives à la hanche) ; déplacement : trajet horizontal de la hanche, « sur place » sous 5 cm ; posture par image (allongé : tronc > 60° ; à genoux : genou < 12 cm et hanche < 72 % ; assis : hanche < 72 % et plus de 20 cm en arrière des chevilles ; accroupi : hanche < 72 % ; debout sinon), posture du clip si elle couvre au moins 60 % des images, sinon « variable ». Les vignettes font 512 px, de profil. taille_ko est la taille des .uasset non cuits (taille_cuite: false) en attendant AP7. La posture peut être déclarée dans pack.json (champ posture), ce qui remplace la posture calculée. Planches (CHG-211) : chaque fiche porte aussi une planche JPEG de 256 px (12 images par seconde de clip, de 4 à 24, côte à côte) que la page fait défiler au survol de la vignette (au toucher : lance / arrête ; la planche n'est chargée qu'au premier survol) ; un GIF a été écarté (256 couleurs, lourd, aucun encodeur disponible).

Le catalogue est régénéré à chaque passage de la chaîne : il ne peut pas décrire un état antérieur des clips. Le pilote refuse de livrer un mod dont le catalogue n'a pas été produit dans le même passage.


6. Découpage en lots proposé

Lot Objet Contrôle de sortie
AP1 ✔ Profils de squelettes en JSON, lus par le C++ et le Python ; suppression des tables en dur sandbox et retarget identiques à CHG-204 (tournée : 0,00 %) — fait, CHG-205
AP2 ✔ Commandlet de pose T et d'évaluation sans fenêtre (étapes 3 et 5, mesures) mêmes fichiers de pose et même tour.csv que la sandbox — fait, CHG-206 (-run=LPAnimEval)
AP3 ✔ Répartition de la torsion Bend / Twist sur les clips produits contrôle de torsion vert, comparaison visuelle — fait, CHG-207 (-run=LPAnimTwist) ; comparaison visuelle à faire
AP4 ✔ Contrôles indépendants (§ 4) et rapport HTML seuils étalonnés sur les 43 clips — fait, CHG-208 (-run=LPAnimEval, Tools/anim/RapportControles.py) ; 0 rejeté, 8 clips à revoir (4 par corps : Death01, Fixing_Kneeling, Roll au sol, Jump_Start au saut)
AP5 ✔ Livraison en mod : clips renommés <clé>_F / <clé>_M sous /<Mod>/Anims, ajout à Room.Dailies et correctif de Person::PlayDaily, essai de chargement par animate() jeu de test avec le mod Quaternius, clés appelées depuis un scénario d'essai — fait, CHG-209 ; essai empaqueté reporté (nouvelle version de référence nécessaire)
AP6 ✔ Catalogue (§ 5) : fiches calculées, pack.json, vignettes, catalogue.json et catalogue.html une fiche par clip, champs calculés relus sur 5 clips témoins (marche, assis, pistolet, danse, chute) — fait, CHG-210 ; taille cuite en AP7
AP7 ✔ Pilote AnimPipeline.ps1 + BuildMod -Anim, identification, méthodes ue4 / ue5, deuxième pack (FreeAnimationsPack, mannequin UE5) pack UE5 converti, évalué, catalogué et livré de bout en bout sans intervention — fait, CHG-221 à 224 ; cuisson DLC contre la version d'essai 2026.10.1.6 et essai en jeu empaqueté validés (CHG-224)

Chaque lot suit 10_Protocole_Operations.md : instantané, journal CHG, retour arrière par Restore.ps1.