LifePlay-Revival/Docs/Migration/21_Sandbox_Addon.md
2026-10-08 08:56:02 +02:00

24 KiB
Raw Blame History

21. Migration sandbox → addon éditeur (ébauche, 2026-10-06)

Objectif : extraire le code de sandbox Pair / Interaction / Mesure (aujourd'hui dans Source/LifePlay/ et Source/LifePlayEditorTools/, en grande partie non suivi par git) vers un plugin éditeur dédié, sans casser le jeu empaqueté ni la chaîne d'animations (20_Chaine_Animations.md). Le module LifePlay ne garde que le contrat minimal vers le jeu (dont LPShowCoupleSubsystem).

Amont : lot S0 validé (S0-VAL.md : PASS). Inventaire gelé : Docs/Migration/etat/sandbox/S0/S0-CART.md.


Périmètre S0 (fichiers gelés)

Liste figée au 2026-10-06 ; toute évolution ultérieure passe par une fiche de lot et une entrée CHG.

Runtime (Source/LifePlay/)

Chemin LOC approx. Notes
LPPairSandbox.h 322 Stage / Character / GameMode Pair
LPPairSandbox.cpp 4261 Monolith Pair, interaction, mesure
LPInteractionSandbox.* — Retiré S4-T3 (addon) ; Interaction via menu LPPairSandbox
LPPoseMeasure.h 100 API mesure
LPPoseMeasure.cpp 1558 Sample / Transfer / T-fit
LPSkeletonProfile.h 38 Profils JSON
LPSkeletonProfile.cpp 157
LPPoseOrchestrator.h 30
LPPoseOrchestrator.cpp 487
LPAnimRedirect.h 15 Cible sandbox | game
LPAnimRedirect.cpp 24
LPShowCoupleSubsystem.h 77 Reste dans LifePlay (sync lot S5)
LPShowCoupleSubsystem.cpp 1048

Éditeur (Source/LifePlayEditorTools/)

Chemin LOC approx. Notes
LPPairCollisionTestCommandlet.* ~546 PairCol headless
LPAnimEvalCommandlet.* ~489 Mesure headless
LPAnimCatalogCommandlet.* ~388
LPAnimChecks.* ~435
LPAnimTwistCommandlet.* ~384

Lanceurs (Tools/debug/)

Chemin Notes
LifePlay_pair_sandbox.bat Pair
LifePlay_interaction_sandbox.bat Interaction
LifePlay_measure_sandbox.bat Mesure

Synthèse S0-CART : ~7,5 k LOC runtime sandbox + mesure ; trois lanceurs désormais versionnables (motif .gitignore : /Debug/).


Contrat (S1 : configuration des chemins)

Le lot S1 fixe le premier contrat jeu ↔ addon : tous les chemins d'assets et de fichiers du sandbox Pair passent par Config/LPSandbox.ini, lu par un point d'accès unique. Détail : etat/sandbox/S1/S1-SPEC.md ; implémentation S1-IMPL.md ; audit S1-CART.md ; validation S1-VAL.md (PASS statique ; compilation et runtime à confirmer).

  • Fichier : Config/LPSandbox.ini (versionné, pas dans Saved/ ; depuis DC3 il vit dans l'addon, avec sa section [Workshop] GameRoot), lecture directe non hiérarchique (FConfigFile::Read).
  • API : struct LIFEPLAY_API FLPSandboxConfig (Source/LifePlay/LPSandboxConfig.h/.cpp), static const FLPSandboxConfig& Get(), chargé une fois. LPPairSandbox.cpp et LPAnimRedirect::ClipPath n'utilisent plus de littéral /Game/....
  • Repli : fichier, clé ou valeur vide absents => default = littéral historique (comportement identique sans ini). Un asset introuvable garde le journal LogLifePlay d'origine, sans repli silencieux.
  • 19 clés, 6 sections : Sandbox.Mode (Mode = Pair | Interaction | Mesure, Saved/sandbox_mode.txt reste prioritaire) ; Sandbox.Assets (PersonBP, BridgetMesh, MichaelMesh, QuaterniusMannequinMesh, DazIdleFemale, DazIdleMale, FurnitureWallMaterial) ; Sandbox.Roots (FurnitureRoot, DazAnimRoot, QuaterniusRoot, QuaterniusUALRoot) ; Sandbox.Content, chemins relatifs à Content/ (ModuleRoot, WorldFile, ChatAction, QuaterniusUALDisk) ; Sandbox.Sky (SkyCubemap, SkyIntensity) ; Sandbox.Output, relatif à Saved/ (MeasureOutputRoot).
  • Conventions : asset = chemin UE complet /Game/...Nom.Nom (LoadObject) ; racine = package sans nom d'asset ; disque = relatif à ProjectContentDir() (ou ProjectSavedDir() pour Output).
  • Hors contrat (volontaire) : LPKeyboard.ini, Saved/sandbox_mode.txt / sandbox_tour.txt, littéraux /Engine/..., noms de clips et poses (Idle_Loop, Walk_Loop, A_TPose, B_/M_), liste Names[].
  • Reste ouvert (lots suivants) : points d'accroche ShowCouple (S5) ; staging de LPSandbox.ini si le sandbox doit tourner empaqueté. (Dépendances Build.cs et répartition des exports : traitées en S2, section suivante.)

Module LPAnimMeasure (S2 : extraction de la chaîne de mesure)

Le lot S2 sort la chaîne de mesure de LifePlay vers un module Runtime dédié, Source/LPAnimMeasure/ (structure plate, comme LifePlay). Détail : etat/sandbox/S2/S2-CART.md (cartographie), S2-IMPL-H.md (implémentation), S2-VAL.md (validation : PASS statique et runtime Mesure).

  • Contenu : LPPoseMeasure, LPSkeletonProfile, LPPoseOrchestrator, LPAnimRedirect (8 fichiers déplacés) + LPAnimMeasure.Build.cs, LPAnimMeasure.h/.cpp (catégorie de journal LogLPAnimMeasure, ex-LogLifePlay pour les lignes POSET / PROFIL / ORCH / MESURE).
  • Exports : LPANIMMEASURE_API remplace LIFEPLAY_API ; 6 symboles ajoutés pour LPPairSandbox.cpp (KeyBones, LogReport, TFitReport, Run, Restore, SampleAt) ; les structs de données restent header-only.
  • Rupture du couplage : LPAnimRedirect ne lit plus LPSandboxConfig. l'addon (LPSandbox.cpp:17) appelle LPAnimRedirect::SetUALRoot(FLPSandboxConfig::Get().QuaterniusUALRoot) (FLifePlayModule::StartupModule() ne l'appelle plus) ; depuis DC1, LPAnimRedirect et LPCoupleSim sont dans le plugin du jeu Plugins/LPAnimCore ; défaut interne /Game/Quaternius/UAL (identique à celui de la config).
  • Déclaration : entrée Runtime / Default dans LifePlay.uproject, placée avant LifePlay ; ExtraModuleNames des deux *.Target.cs.

Graphe de dépendances des modules

flowchart LR
    LPET["LifePlayEditorTools<br/>(Editor)"] -->|Public| LP["LifePlay<br/>(Runtime, module primaire)"]
    MT["LPModTools<br/>(Editor, addon, DC2)"] -->|Public| AM["LPAnimMeasure<br/>(Runtime, nouveau S2)"]
    LP -->|Public<br/>LPPairSandbox, LPDirectControl| AM
    LP -->|Public DC1| AC["LPAnimCore<br/>(plugin du jeu : LPAnimRedirect, LPCoupleSim)"]
    AM -->|Private DC1| AC
    SB["LPSandbox<br/>(addon)"] -->|DC1| AM
    SB -->|DC1| AC
    SB -.->|"LPSandbox.cpp:17 : SetUALRoot(QuaterniusUALRoot)"| AC
    AM -->|Public| ENG["Core, CoreUObject, Engine"]
    AM -->|Private| JSON["Json"]

Règles : LPAnimMeasure ne dépend ni de LifePlay ni de LifePlayEditorTools (graphe acyclique) ; LPSandboxConfig reste dans LifePlay et pousse la configuration vers LPAnimMeasure par un setter, jamais l'inverse. Ordre de chargement LPAnimMeasure avant LifePlay : dépendance Build.cs et ordre du .uproject.

De Vers Type Motif
LifePlay LPAnimMeasure Public LPPairSandbox.h/.cpp, LPDirectControlSubsystem.cpp, LifePlay.cpp
LifePlay LPAnimCore Public DC1 : LPAnimRedirect, LPCoupleSim (plugin du jeu Plugins/LPAnimCore)
LPAnimMeasure LPAnimCore Private DC1 : la mesure utilise LPAnimRedirect
LPSandbox LPAnimMeasure, LPAnimCore Public DC1 : mesure et redirection / géométrie du couple
LifePlayEditorTools LifePlay Public existant
LPModTools (Editor, addon) LPAnimMeasure Public DC2 : LPAnimChecks.h expose FLPPose ; commandlets LPAnimEval, LPAnimCatalog, LPAnimTwist, LPAnimIdentify, LPHairFromStaticMesh (ex-LifePlayEditorTools, qui ne dépend plus de LPAnimMeasure)
LPAnimMeasure Core, CoreUObject, Engine / Json Public / Privé animations, squelettes ; lecture de Tools/anim/profiles/*.json
LPAnimMeasure LifePlay, LifePlayEditorTools aucune évite un cycle de modules

Stratégie git et liaison jeu ↔ addon (S3)

Le lot S3 déplace le code sandbox dans un dépôt séparé, LifePlay-Sandbox (https://github.com/edujiro5972/LifePlay-Sandbox.git, branche main). Détail : etat/sandbox/S3/S3-INT.md ; validation : etat/sandbox/S3/S3-VAL.md (PASS).

Décision : deux dépôts siblings + AdditionalPluginDirectories. Pas de submodule imbriqué.

D:\Game\
  LifePlay-master 5.5\     <- jeu (repo LifePlay)
  LifePlay-Sandbox\        <- addon (repo LifePlay-Sandbox)
  • Liaison : LifePlay.uproject déclare "AdditionalPluginDirectories": ["../LifePlay-Sandbox/Plugins"] (chemin relatif au .uproject) et active LPSandbox dans Plugins. UBT et l'éditeur y trouvent LPSandbox.uplugin (modules LPSandbox et LPAnimMeasure) ; les DLL du plugin sont compilées avec le jeu (Build.bat LifePlayEditor Win64 Development).
  • Pourquoi pas un submodule : l'addon est un uproject mince qui contient le plugin sous Plugins/LPSandbox/. Un submodule monté sur Plugins/LPSandbox du jeu donnerait Plugins/LPSandbox/Plugins/LPSandbox/ (plugin imbriqué, non scanné au bon niveau) ; un submodule External/LifePlay-Sandbox dupliquerait l'addon à côté du sibling et rendrait ambigu l'exemplaire chargé. Un clone sibling évite les deux problèmes.
  • Pin : le jeu consomme un commit précis de l'addon, consigné à la main dans S3-INT.md (aujourd'hui 79f0205b7281152dde7cd088086d8c813e0b20f5, lot/DC3-atelier, DC3 atelier de mods (scripts, ModSources, AnimSources) dans l'addon ; précédents : 97c0d134cd1388c3735add79d77ea98817e89fbe DC2 module éditeur LPModTools et chemins propres à l'addon, 3e9c32f1f27b1abdaf7731dc90496c27ee061718 DC1 LPAnimRedirect et LPCoupleSim rapatriés dans le plugin LPAnimCore du jeu, 16905c68070992f5139dab907b41b461fb765957 SB4 ouverture par déclencheur éphémère non mémorisée, 3d858527fccfdddd8711c7c7448fa001442e0b8a SB2-O1 correction de ShowRoom, fece7e9a0e63b3058b5d24d96d669a3c9c0e9add SB2 bibliothèques de scène et de personnages, caméra du socle, état des modes sorti vers les mods, 82dae58380b76c45f60541fd7cb5a0a409700e10 SB1 registre de mods et barre latérale, 3b21fd180c04f0fa49a1b5c9ef1b517ade1cb362 SB0 conception de la sandbox modulaire, f09c42e5a2bc613cf269cce76c878461ca41c8b7 S7-T2 uplugin, c1fdd29e2c1036c7d6365ba6389eff5d2f8c8c96 S5-T2 LPCoupleSim, f8102647ccdebad37e4977ccbf2c51e583823a80, S4-T3). Le pin est mis à jour (hash dans S3-INT.md et README de l'addon) à chaque évolution de l'addon que le jeu doit prendre. Reproduire :
cd D:\Game
git clone https://github.com/edujiro5972/LifePlay-Sandbox.git
git -C LifePlay-Sandbox checkout 79f0205b7281152dde7cd088086d8c813e0b20f5
# le jeu doit être cloné à côté : D:\Game\LifePlay-master 5.5
  • Content : le jeu n'a rien à monter. L'addon utilisé seul (LPSandbox.uproject) a besoin du Content du jeu : junction NTFS LifePlay-Sandbox\Content → LifePlay-master 5.5\Content (/Game ne peut pointer que vers <projet>/Content ; la clé AdditionalAssetDirectories n'existe pas en UE 5.5). Voir le README de l'addon.
  • Contenu du jeu après S3-T3 : Source/LPAnimMeasure/ et les fichiers LPPairSandbox*, LPInteractionSandbox*, LPSandboxConfig* ne sont plus dans le jeu. Le bat Pair lance toujours LifePlay.uproject avec game=/Script/LPSandbox.LPPairSandboxGameMode. Source/LifePlay/LifePlay.Build.cs dépend toujours de LPAnimMeasure (module désormais fourni par le plugin).
  • Validation S3-VAL : bat Pair depuis le jeu, plugin monté et GameMode résolu sans erreur de module ; addon mince lancé avec le même GameMode (réserve : son .uproject n'active pas StreetMap, d'où des erreurs de chargement de Blueprints du jeu sans effet sur le sandbox).

CoupleBox : LPCoupleSim partagé (S5)

Le lot S5 ferme la dérive de fork entre la sandbox (LPSandbox/LPCoupleSim.cpp, méthodes de ALPPairSandboxStage) et le jeu (LPShowCoupleSubsystem) : les deux gardaient une copie de la géométrie du couple (mesure de pose, boîte, balayage, soudure) qui divergeait (plancher −90 / −88, itérations 2 / 3, os exclus). Détail : etat/sandbox/S5/S5-CART.md (écarts), S5-IMPL-H.md (implémentation), S5-VAL.md (validation : PASS runtime Pair, PASS-STATIC ShowCouple). Addon pinné sur c1fdd29.

  • Où : header Plugins/LPSandbox/Source/LPAnimMeasure/LPCoupleSim.h (215 l.) et LPCoupleSimCore.cpp (474 l.), module LPAnimMeasure, namespace LPCoupleSim, exports LPANIMMEASURE_API. Une seule copie : le jeu la voit par LifePlay.Build.cs (dépendance publique existante), sans recopie ni changement de .Build.cs. Le nom LPCoupleSimCore.cpp évite la collision avec LPSandbox/LPCoupleSim.cpp.
  • Trois niveaux d'API :
    • pur (sans UObject ni UWorld, testable sans monde) : MeshToActor, ComposeComponentSpace, AccumulatePoints, IsExcludedLiveBone, FitFromAnimBounds, FitFromLiveBounds, SlideWish ;
    • lecture : CapsuleHalfOf, AccumulateAnimBounds (8 pas, os animés, GetBoneTransform(raw=false)), AccumulateLiveBody ;
    • effets de bord : EnsureBox, ApplyBoxFit, PlaceBodyMesh, SaveAndFreeze / RestoreMove (FSavedMove), AttachPartner, Unweld, ResolveCoupleMove.
  • Paramètres : FBoxFitParams (demi-capsule 88, pad anime 12/12/6 plafond 800, pad vivant 4/4/4 min 8 plafond 400, ancre pelvis 140, FloorLocalZ, MinExtentZ 20) ; FSweepOptions::Show() (3 itérations, SweepMulti, dépénétration, PNJ + coque Wall* ignorés) et FSweepOptions::Sandbox() (2 itérations, SweepSingle, arrêt net, marches, Z à plat). ResolveCoupleMove ne déplace rien : elle rend la position retenue (FSweepResult), chaque appelant l'applique.
  • Appelants : sandbox FitCoupleBox / Weld / MoveCouple ; jeu FitBox / FitToBodies / Weld / Engage / Release / KeepTogether. Les copies AddPose (jeu), Accumulate (sandbox), les deux créations de UBoxComponent et les deux boucles de balayage n'existent plus (−336 lignes dupliquées, +689 dans le module partagé).
  • Écarts conservés volontairement (options, pas de copies) : plancher sandbox −90 contre jeu −88 (FloorLocalZ), balayage simple 2 itérations contre multi 3 itérations, nom de composant CoupleBox contre LPShowCoupleBox. L'alignement du plancher est une ligne dans FitCoupleBox, à décider après capture en jeu.
  • Reste dans LifePlay : sélection du couple (SexPersons, AP1/AP2, ShowReach), réflexion GI / Room, IsBedMesh (injecté via IsWalkableSupport), IsUseFurniture, OpenUseFurniture, PairSibling / IsIdleClip, FlipResponse / RestoreResponses (non partagés, hors S5-T2), CVar lp.ShowCouple.
  • Contrat de modification : tout changement de géométrie du couple se fait dans LPCoupleSim (addon), puis bump du pin ; le jeu ne doit pas réintroduire de copie locale.

Acceptation

État au 2026-10-06 (lot S8). Case cochée = prouvée par la fiche citée ; case vide = non faite.

  • S0 : hygiène dépôt, inventaire gelé (S0-VAL.md PASS).
  • S1 : tous les chemins du sandbox via Config/LPSandbox.ini (S1-VAL.md PASS statique).
  • S2 : module LPAnimMeasure extrait, sans dépendance vers LifePlay (S2-VAL.md PASS).
  • S3 : addon dans le dépôt LifePlay-Sandbox, liaison sibling + AdditionalPluginDirectories, pin manuel (S3-VAL.md PASS).
  • S4 : sandbox Pair découpé, GameMode Interaction legacy retiré (S4-VAL.md PASS).
  • S5 : géométrie du couple partagée via LPCoupleSim, une seule copie (S5-VAL.md PASS runtime Pair, PASS-STATIC ShowCouple).
  • S6 : stack Mesure sur la liaison addon, LPAnimEval court (S6-VAL.md PASS).
  • S7 / isolation : plugin sans include / LIFEPLAY_API / module LifePlay ; Person = CDO seul, aucun GI / Room ; chemins par config (S7-SPEC.md, S7-CART.md : 0 écart).
  • S7 / configurations : LPSandbox hors Shipping (TargetConfigurationDenyList), LPAnimMeasure conservé, plugin Optional dans LifePlay.uproject (S7-IMPL-L.md).
  • Smoke Pair (bat court, plugin monté, boîte du couple identique à S5-VAL, 0 crash) (S7-VAL.md).
  • Commandlets anim restants (LPAnimCatalog, LPAnimChecks, LPAnimTwist) déplacés dans un module éditeur de l'addon : fait au lot DC2 (module LPModTools, avec LPAnimEval, LPAnimIdentify, LPAnimMethodSelect, LPHairFromStaticMesh).
  • S8 : bilan du mode multi-agents (22_Eval_Agents_Sandbox.md : GO conditionnel) ; code sandbox absent du module jeu depuis S3 ; smoke Pair par le .bat réel, boîte du couple identique à S5 / S7, 0 crash (S8-VAL.md PASS).
  • BuildMod.ps1 -Target sandbox -Open rejoué sur la liaison addon : non fait.
  • Compilation / packaging Shipping complets avec le plugin (seul le plan UBT est vérifié).
  • Parcours Show complet en jeu et décision d'alignement du plancher (-90 / -88).
  • Commit addon f09c42e poussé vers origin/main (constaté en S8 : origin/main = dae6206, qui le contient).
  • Migration commitée côté jeu (LifePlay.uproject, Config/LPSandbox.ini, Build.cs, LPShowCoupleSubsystem.*, docs 21 / 22, etat/sandbox/) : non fait (22 § 6).
  • SB0 : conception de la sandbox modulaire (addon, pin 3b21fd1, tag lot-SB0-valide).
  • SB1 : registre de mods, barre latérale, 7 descripteurs .lpmod, modes Pair / Interaction / Mesure enveloppés en lps_couple / lps_interaction / lps_asset_integration (etat/sandbox/SB1/SB1-VAL.md PASS, contrôle visuel utilisateur 2026-10-07 ; tag lot-SB1-valide).
  • SB2 : bibliothèques lps_lib_scene / lps_lib_actors, caméra du socle, état des modes sorti vers les mods lps_couple / lps_interaction / lps_asset_integration (etat/sandbox/SB2/SB2-VAL.md PASS, contrôle visuel utilisateur 2026-10-07 ; tag lot-SB2-valide).
  • Reports SB1 (registre unique, lot propriétaire SB2) : (traité) images de la tournée Mesure non déterministes : SB2-T5 compare les JSON/CSV (identiques) et les images visuellement ; (traité, SB4-T0, prouvé SB4-VAL F2) « Open réécrit » : chaque ouverture de mod réécrit Open dans Saved/sandbox_mods.ini (une tournée automatique laisse donc Open=lps_asset_integration). Corrigé : Open(Id, Context, bRemember), une ouverture par Saved/sandbox_mode.txt n'est plus mémorisée.
  • SB4 : validation finale (SB4-VAL PASS : démarrage, tournées Quaternius et FreeAnimationsPack identiques à SB2-REF, LPAnimEval identique, Open intact), doc 23 § 7 ; commit 16905c6 et tag lot-SB4-valide ; évaluation etat/sandbox/SB4/SB4-EVAL.md : GO transposition.
  • G-SB3 : SB3 abandonné (décision utilisateur 2026-10-07). Motif : les mods du jeu sont du contenu (.lpmod + pak), leurs dépendances sont vérifiées par le registre (prouvé en SB1/SB2) ; coût ≈ 1 à 1,5 lot, et LPAnimMeasure est utilisé par le jeu en Shipping ; on passe à SB4.
  • SB2-O1 : correction du défaut O1 (etat/sandbox/SB2/SB2-O1-BUILD.md PASS, contrôle visuel utilisateur 2026-10-07 ; tag lot-SB2-O1-valide).
  • Reports SB2 : (O1) traité (SB2-O1, 3d858527fccfdddd8711c7c7448fa001442e0b8a : ShowRoom symétrique de HideRoom, contrôle visuel utilisateur 2026-10-07 « c'est bon ») ; (E3) sans lps_lib_scene, la pièce est construite quand même : non traité, séparation physique abandonnée à la porte G-SB3 (décision utilisateur 2026-10-07).
  • DC0 : cartographie et SPEC du découplage jeu / sandbox (etat/sandbox/DC0/DC0-SPEC.md, approuvée par l'utilisateur 2026-10-07) ; plan 24_Plan_Decouplage_Sandbox.md.
  • DC1 : Plugin LPAnimCore dans le jeu, LPAnimMeasure réduit à la mesure (DC1-T1..T5) (DC1-VAL PASS, contrôle visuel utilisateur 2026-10-07 ; tag addon lot-DC1-valide).
  • DC2 : Commandlets de mods vers un module éditeur de la sandbox (DC2-T1..T5) (DC2-VAL PASS ; tag addon lot-DC2-valide ; le jeu compile et démarre sans l'addon).
  • DC3 : Scripts, données et sources de mods vers la sandbox (DC3-T1..T5) (DC3-VAL PASS ; tag addon lot-DC3-valide ; atelier de mods dans l'addon).
  • DC4 : Preuve « jeu seul », docs, évaluation (DC4-T1..T4) (DC4-VAL PASS, test en jeu utilisateur 2026-10-07 ; évaluation DC4-EVAL : le jeu public compile et tourne sans l'addon).
  • Intégration des déplacements dans le jeu à améliorer (remarque utilisateur au contrôle visuel DC1, 2026-10-07) ; lot propriétaire : à définir, hors DC.
  • Reports DC0 (lot propriétaire DC1, traité : texte corrigé en § Rupture du couplage) : § Rupture du couplage : la mention d'un appel à SetUALRoot par FLifePlayModule::StartupModule() est périmée ; seul l'addon l'appelle (LPSandbox.cpp:17, LPSandboxMeasure.cpp:39) — voir DC0-CART b2.
  • Report DC2 (traité en DC3 : -Livraison= obligatoire) : LPAnimCatalog ignore -DryRun et a des valeurs par défaut (pack quaternius) : lancé sans arguments, il réécrit Saved/AnimPipeline/quaternius/fiches_calculees.json (DC2-VAL anomalie 1) — lot propriétaire DC3.
  • Report DC2 (traité en DC4, fbbcee1) : LifePlay.Build.cs garde Json avec un commentaire AP1 périmé (plus aucun usage dans LifePlay) — lot propriétaire DC4.
  • Report DC2 (traité : documenté dans 09/18) : sans addon, l'absence est silencieuse au runtime ; l'éditeur/UBT affiche AdditionalPluginDirectory … not found (avertissement, non bloquant) — pour information, DC4 docs.
  • Report DC3 (traité : documenté dans 09/18) : après un test sans addon, UBT réutilise un Makefile.bin sans les modules de l'addon : le déplacer avant de recompiler (DC3-BUILD) — à écrire dans 09/18 — lot propriétaire DC4.
  • Numéros de docs en double : traité (DOCNUM, CHG-246) — 23_Video_Quality.md → 25_Video_Quality.md, 24_Eval_Agents_VideoQuality.md → 26_Eval_Agents_VideoQuality.md (ordre de création ; 23 et 24 inchangés).

Lots (S0 … S8)

Lot Objet (une ligne)
S0 Hygiène dépôt : /Debug/ dans .gitignore, lanceurs Tools/debug suivis, inventaire et preuves etat/sandbox/S0/*.
S1 Contrat jeu ↔ addon : API minimale, dépendances modules, règles de linking (placeholder ci-dessus).
S2 Extraction du module LPAnimMeasure (mesure, profils, orchestrateur, redirection) hors de LifePlay ; dépendances Build.cs et exports. Fait : S2-VAL.md PASS (voir section « Module LPAnimMeasure »). Le plugin éditeur (uplugin) reste à faire.
S3 Création du dépôt addon LifePlay-Sandbox (scaffold, transfert du code, retrait côté jeu) et liaison par clone sibling + AdditionalPluginDirectories, pin manuel. Fait : S3-VAL.md PASS (voir section « Stratégie git »). Rejeu stack Mesure : lot S6 (S6-VAL.md).
S4 Sandbox Pair : découpage LPPairSandbox, retrait GM Interaction legacy (S4-T3 fait), commandlet LPPairCollisionTest, bat Pair. Validation : S4-VAL.md (PASS).
S5 ShowCouple : LPShowCoupleSubsystem reste dans LifePlay ; géométrie du couple partagée via LPCoupleSim (module LPAnimMeasure de l'addon, pin c1fdd29). Fait : S5-VAL.md PASS (runtime Pair, PASS-STATIC ShowCouple ; voir section « CoupleBox »). Show complet en jeu et alignement du plancher restent à valider.
S6 Stack Mesure sur la liaison addon : LifePlayEditorTools → LPAnimMeasure (plugin), lanceurs Tools/debug, sorties Saved/Measurement, commandlet -run=LPAnimEval. Fait : S6-VAL.md PASS (doc 20 / 09, essai court LPAnimEval).
S7 Isolation du plugin (sans lien vers LifePlay, Person en CDO seul, config seulement), LPSandbox hors Shipping, Optional dans LifePlay.uproject. Fait : S7-VAL.md PASS (smoke Pair ; Shipping vérifié par plan UBT). Le déplacement des commandlets Catalog / Checks / Twist reste à planifier (voir § Acceptation).
S8 Bilan et clôture : évaluation du mode multi-agents + multi-modèles (22_Eval_Agents_Sandbox.md, GO conditionnel, 3 recommandations), smoke Pair final. Fait : S8-VAL.md PASS. BuildMod -Target et commit côté jeu restent ouverts (§ Acceptation).

Chaque lot suit 10_Protocole_Operations.md : instantané, entrée CHG, retour arrière documenté.