LifePlay-Revival/Docs/Migration/etat/CAM/CAM-B2r-VAL.md
edujiro5972 8084622450 LifePlay UE 5.8 : état de développement au 2026-10-19
Tickets : REP1-T4

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 22:57:42 +02:00

15 KiB
Raw Blame History

Fiche CAM-B2r-VAL — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate

CAM-B2r-VAL : remise de SpaceOn / MainMenuOn après CharGen et témoins C1, VAL statique sans compilation (2026-10-14)

Date : 2026-10-14. Copie D:\Game\LifePlay-master 5.8, branche ue5.8, UE 5.8 (D:\Game\Launcher\Engine\UE_5.8). Portée : VAL statique (lecture et commandes de lecture seule). Aucune compilation, aucun éditeur, aucun commandlet, aucun MCP, aucun git en écriture. Seul fichier écrit : ce livrable.

1. Fiches amont relues

Fichier Lu Remarque
Docs/Migration/etat/CAM/CAM-B2r-FICHE.md (81 lignes) oui, en entier R1, R2, R3, essais CAM-50 à CAM-53, retour arrière
Docs/Migration/etat/CAM/CAM-B2r-IMPL.md (47 lignes) oui, en entier voir écart de gabarit en Constats C-7
D:\Game\LifePlay_Backup_5.5\CAM-B2r\manifest.csv + copies Source\LifePlay\LPCameraModeSubsystem.{cpp,h} oui instantané d'avant, date 2026-10-14 07:46
Source/LifePlay/LPCameraModeSubsystem.cpp (662 lignes) et .h (77 lignes) actuels oui, en entier
lp-doc/gabarits.md (gabarit VAL) oui sections 1 à 6 ci-dessous

2. Points à confirmer des IMPL

L'IMPL ne contient pas de section « points à confirmer » (écart de gabarit, C-7). Je reprends à la place ses deux écarts déclarés et son seul « non fait ».

Identifiant Point Résultat
IMPL-E1 Critère « vue = caméra de pièce » par le libellé de ComputeLabel (C1, C2, C3 plafond, C3 ancienne), Birdview exclu, pas d'écriture pendant un menu PASS-STATIC : libellés de RoomCameraLabels (cpp 79-81) égaux, caractère par caractère, aux retours de ComputeLabel (cpp 564, 576, 582, 594) ; Birdview rend « Camera: Overview » (cpp 564), absent de la table. Plus strict que la fiche pour le cas Builder (voir 6.R1) : acceptable
IMPL-E2 R3 : si l'axe de visée de FirstPerson_C n'est pas son X local, une ligne par seconde en C1 (bruit sans effet) PASS-STATIC pour le risque (journal seulement, aucune écriture dans WitnessC1) ; l'axe lui-même : reporté à l'essai CAM-53 (BLOCKED sans jeu)
IMPL-N1 Compilation (COMMUN-7, jeton UE) reporté : critère « Build.ps1 : 0 erreur, aucun avertissement nouveau » de la fiche non vérifié ici (BLOCKED-jeton-UE, voulu)
IMPL-N2 Essais CAM-50 à CAM-53 reporté (V7, build suivant)

3. Critères rejoués (commande → résultat)

N° Contrôle Commande Sortie brute (courte) Verdict
1 MD5 avant (instantané) md5sum <Backup>/CAM-B2r/Source/LifePlay/LPCameraModeSubsystem.* fe9236bd138a46bbc2b63027977b3cd9 (.cpp), 7da111cb65b267a9e2f7482cba368be9 (.h) ; manifest.csv : FE9236BD…, 7DA111CB… PASS : égaux aux valeurs annoncées
1 MD5 après (fichiers actuels) md5sum "<copie>/Source/LifePlay/LPCameraModeSubsystem.*" 124336d3293ef06befcf076d10956234 (.cpp), 61a3e06280bf7226adb52ecfdd9173de (.h) PASS : égaux à 124336D3… et 61A3E062… annoncés
2 Diff complet diff -u <instantané> <actuel> pour les deux fichiers, lu en entier .h : 1 hunk, +11 −0 ; .cpp : 7 hunks, +154 non vides (+7 lignes vides), −2 ; 503→662 lignes, 66→77 PASS-STATIC : tout dans le périmètre (section 4)
3 Fins de ligne tr -cd '\r' < f | wc -c avant : .cpp 0, .h 0 ; après : .cpp 0, .h 0 ; espaces en fin de ligne : 0 et 0 (grep -c "[[:space:]]$") PASS : LF avant et après
4 Compilation « à l'œil » relecture ligne à ligne + lecture des en-têtes UE 5.8 voir détail 3.a PASS-STATIC, aucun bloquant
5 Sûreté lecture + Grep WriteBool\( WriteBool : définition cpp 116, appels cpp 336 et 341 seulement, tous deux dans RepairAfterCharGen (cpp 297-344) PASS-STATIC (détail 3.b)
6 Cohérence fiche / IMPL comparaison R1, R2, R3 voir section 6 PASS-STATIC avec 3 écarts non déclarés non bloquants (C-1, C-2, C-3)

3.a Détail du contrôle 4 (types, signatures, const, format)

  • FBoolProperty::SetPropertyValue_InContainer(void*, bool, int32) const : UnrealType.h:2710 (UE 5.8). WriteBool prend UObject* (non const) et une const FBoolProperty* : correct (cpp 116-123).
  • FTimerHandle::StaticStruct() : USTRUCT (Engine/TimerHandle.h:10-13) ; la fonction est inline dans TimerHandle.generated.h:26 et appelle ENGINE_API Z_Construct_UScriptStruct_FTimerHandle (ligne 22) : pas de risque d'édition de liens depuis le module LifePlay. TimerManager.h:13 inclut Engine/TimerHandle.h.
  • FTimerManager::IsTimerActive(FTimerHandle) const : TimerManager.h:331 ; UWorld::GetTimerManager() const : World.h:4289. TimerActive prend const UWorld* : correct (cpp 126-134). ContainerPtrToValuePtr<FTimerHandle> sur const UObject* : même motif que ReadVector existant (cpp 143).
  • FRotator::NormalizeAxis : static, Rotator.h:432 (modèle T, double en LWC). YawGap et Distance sont des double ; CameraRotation.Pitch/Yaw sont des double (FRotator UE5). FVector::Dist rend un double.
  • UWidget::IsInViewport() const (Widget.h:549), GetVisibility() const (Widget.h:586), GetGameInstance() const (Widget.h:871) : WidgetOnScreen (cpp 211-227) travaille sur const UUserWidget* sans appel non const. TObjectIterator::operator bool est explicit (UObjectIterator.h:286), accepté dans It && GI (conversion contextuelle).
  • Const-correctness : aucune fonction const nouvelle. LogSwitchKey (const) n'appelle que ReadBool, GetNameSafe, GetGameViewportClient (déjà présents) ; la lambda Flag prend const UObject* et reçoit GI / PC / Room const. RepairAfterCharGen et WitnessC1 sont non const dans le .h (61, 67) et le cpp (297, 346) : déclarations égales aux définitions (types const FString&, bool, float / float).
  • Format UE_LOG, spécificateurs contre arguments :
    • cpp 328 : %s, %s ← *GetNameSafe(View), *Label (2/2) ;
    • cpp 337 : %s, %s ← idem (2/2) ;
    • cpp 342 : aucun spécificateur, aucun argument ;
    • cpp 375-378 : %.0f %+.0f %+.0f %d %d ← Distance (double), Pitch (double), YawGap (double), deux ? 1 : 0 int (5/5) ;
    • cpp 417-423 (R2) : 19 spécificateurs (14 d'origine + 5 nouveaux %d), 19 arguments : 3+3+3 int, 5 %s en TCHAR* (*GetNameSafe, View ? *… : TEXT("-"), *ShownLabel), puis 5 Flag(...) int. Comptés à la main, un par un.
  • Unité de compilation unitaire : Grep de tous les noms nouveaux (WriteBool, TimerActive, WidgetOnScreen, MainMenuClass, LabelC1, RoomCameraLabels, GICharGenOn, GIMainMenuOn, GIJournalOn, GIContactsOn, PCMoveCamera, PlayerFirstPersonSM, PlayerOccupyingFnt, RoomCamTimer, LeftEyeSocket, RightEyeSocket, C1Interval, C1LogInterval, C1MaxEyeDistance, C1MaxPitch, C1MaxYawGap, CharGenRepairDelay) dans tout Source/ : LPCameraModeSubsystem.cpp:39 et aucun autre fichier. LPCameraModeLocal n'apparaît que dans ce fichier (61 occurrences). Tous les appels sont qualifiés LPCameraModeLocal:: (cpp 250-378, 417-423 ; les seuls appels non qualifiés sont à l'intérieur de l'espace nommé, il n'y en a aucun de nouveau).
  • Ombrage (C4458) : les locaux nouveaux (GI, World, PC, View, Camera, Mesh, Player, Eyes, Distance, Label) ne portent le nom d'aucun membre de classe (membres : Text, Root, Viewport, ShownLabel, bShown, …).
  • Pas de variable inutilisée : View (cpp 316) sert aux deux journaux ; RoomObject (cpp 373) sert à TimerActive.

3.b Détail du contrôle 5 (sûreté)

  • Pointeurs : GI testé nul (cpp 300) ; World, PC, View chaînés par ? : (cpp 314-316) ; GetNameSafe accepte nul ; ReadBool / ReadObject / WriteBool / TimerActive testent Container (cpp 105, 111, 118, 128). WitnessC1 : Player par IsValid, Mesh et Camera par test, PC par test, Room par IsValid avant TimerActive, World testé dans TimerActive (cpp 354-363, 373, 378). Aucune déréférence nue.
  • WriteBool : seulement dans RepairAfterCharGen (cpp 336, 341).
  • Une seule réparation : bCharGenSeen = false est posé en cpp 333, avant les écritures ; le seul autre chemin qui le remet à faux est le délai (cpp 327). bCharGenSeen ne repasse à vrai que par CharGenOn vrai (cpp 306).
  • Jamais hors caméra de pièce ou avec un menu : la sortie if (!bRoomCamera || bMenu) (cpp 322-331) précède toute écriture et rend la main. Birdview donne « Camera: Overview », absent de RoomCameraLabels : jamais réparé. bMenu vient de MenuOnScreen (inchangé), qui inclut MainMenu_C (cpp 98) : le contrôle WidgetOnScreen du cpp 339 est une double garde (voir C-5).
  • Seules écritures du correctif : deux booléens de GI (SpaceOn à vrai, MainMenuOn à faux), chacun seulement s'il vaut l'inverse (cpp 334, 339). WitnessC1 et LogSwitchKey ne font que lire.

4. Diff lu en entier

Commande : diff -u entre la copie d'instantané et le fichier actuel, deux fichiers, lu intégralement. Comptes : .h +11 −0 (1 hunk) ; .cpp +161 (dont 7 lignes vides) −2 (7 hunks). Les −2 sont la ligne UE_LOG de LogSwitchKey (format) et sa dernière ligne d'arguments, réécrites pour R2 ; aucune autre ligne d'origine n'est modifiée.

Hunk Contenu Dans le périmètre de la fiche ?
.h RepairAfterCharGen, bCharGenSeen, CharGenRepairTimeout, WitnessC1, C1Cooldown oui (membres du .h de R1 et R3)
.cpp 21 #include "TimerManager.h" oui
.cpp 67-95 constantes R1 et R3 (GICharGenOn, GIMainMenuOn, GIJournalOn, GIContactsOn, PCMoveCamera, MainMenuClass, CharGenRepairDelay, RoomCameraLabels, LabelC1, PlayerFirstPersonSM, PlayerOccupyingFnt, RoomCamTimer, LeftEyeSocket, RightEyeSocket, C1*) oui. MainMenuClass, RoomCameraLabels, LabelC1 sont des aides de R1/R3, non nommées dans la fiche mais demandées par le contrôle 2 (constantes)
.cpp 115-134 WriteBool, TimerActive oui
.cpp 210-227 WidgetOnScreen oui
.cpp 250, 290-293 appel de RepairAfterCharGen dans Tick ; branche else if (Label == LabelC1) oui
.cpp 297-379 corps de RepairAfterCharGen (R1) et de WitnessC1 (R3) oui
.cpp 416-423 extension de LogSwitchKey (R2) oui, texte égal à la fiche : ; MainMenuOn=%d JournalOn=%d ContactsOn=%d CharGenOn=%d MoveCamera=%d

Ajouts non demandés : aucun fonctionnel. Ajouts mineurs hors lettre de la fiche : mot « indicateur » dans les journaux (C-1), IsInViewport-et-visibilité dans WidgetOnScreen (calqué sur MenuOnScreen, cohérent). Le .cpp est non suivi par git (??, git ls-files --error-unmatch : « did not match any file(s) known to git »), donc git diff <lot>-avant est inutilisable ; la référence est l'instantané. git status --short -- Source ne montre pas d'autre fichier source nouveau lié au lot (les M de LPDebugSubsystem, LPDirectControlSubsystem, LPOutdoorRoomSubsystem, LifePlay.cpp préexistent et ne relèvent pas de ce lot : non lus ici).

5. Verdict

PASS-STATIC avec réserves (réserves non bloquantes, section Constats). Aucun défaut bloquant. Non rejoué : compilation (Build.ps1), LPTestStringCompat, essais CAM-50 à CAM-53 (BLOCKED-jeton-UE, voulu par la fiche et l'IMPL). Le fichier n'est pas encore prouvé compilable : seule la lecture des en-têtes UE 5.8 (section 3.a) le soutient.

6. Points à confirmer par l'utilisateur (cases)

  • R1 (cohérence fiche) : la fiche définit « caméra de pièce » par CamC1On / CamRoom / SceneCamera + CamC3On ; l'IMPL utilise les libellés. Différences : le libellé exclut Camera: Scene / POV (SexOn) et Camera: Builder (scène Builder avec SceneCamera et CamC3On). Plus sûr ; accepter ? Avis du validateur : acceptable.
  • R1/R2/R3 sont écrits conformément à la fiche pour le texte de R2 et les seuils de R3 (8 cm, ±25°, 30°, 0,5 s, 1 s, 10 s) : confirmé par relecture (cpp 78, 90-94, 417).
  • Libellés des journaux de R1 : la fiche dit (vue %s), le code écrit (vue %s, indicateur '%s') (C-1). Accepter ? La sous-chaîne attendue par CAM-50 (« CharGen : SpaceOn remis a vrai ») reste présente.
  • K2_IsTimerActiveHandle (fiche) remplacé par FTimerManager::IsTimerActive (C-2) : accepter ?
  • Compilation sous jeton UE (COMMUN-7) puis essais CAM-50 à CAM-53 : à faire ; le verdict ci-dessus ne les couvre pas.

Tours : 12 / 40

Constats

Bloquants : aucun.

Non bloquants (ligne exacte dans Source/LifePlay/LPCameraModeSubsystem.cpp) :

  • C-1 (cpp 328 et 337) : les deux journaux ajoutent indicateur '%s' au texte de la fiche (vue %s). Écart non déclaré dans l'IMPL ; sans effet fonctionnel ; le préfixe testé par CAM-50 est conservé.
  • C-2 (cpp 133) : la fiche R3 prescrit UKismetSystemLibrary::K2_IsTimerActiveHandle ; l'IMPL appelle World->GetTimerManager().IsTimerActive(Handle) après vérification de Prop->Struct == FTimerHandle::StaticStruct(). Écart non listé dans « Écart à la fiche » de l'IMPL (il figure seulement dans la liste des écritures). Équivalent attendu (estimé : la fonction Kismet délègue au gestionnaire de minuteries du monde ; non relu dans le moteur) et plus simple (pas d'objet de contexte).
  • C-3 (cpp 322-329) : quand la vue est une caméra de pièce mais qu'un menu est à l'écran, le délai de 10 s s'écoule quand même ; à l'échéance le journal dit « sortie sans camera de piece » alors que la cause est le menu, et la réparation est abandonnée. Si un menu reste ouvert plus de 10 s juste après CharGen, SpaceOn n'est pas remis. Cas rare, conforme à « jamais pendant un menu » ; message trompeur seulement.
  • C-4 (cpp 364) : si les douilles lEye / rEye n'existent pas, GetSocketLocation rend la position du composant et le témoin C1 peut écrire une ligne par seconde (bruit, journal seulement). Cousin du risque déclaré IMPL-E2.
  • C-5 (cpp 339) : WidgetOnScreen(MainMenu_C) est redondant avec bMenu (qui contient MainMenu_C) : quand on arrive à cette ligne, bMenu est déjà faux. Inoffensif (double garde) ; à garder pour la lisibilité ou à retirer plus tard, sur décision de l'orchestrateur.
  • C-6 (cpp 1) : l'en-tête du .cpp porte toujours « Lot CAM-B2c » (inchangé, pré-existant) ; rien de B2r n'y est mentionné. Cosmétique.
  • C-7 (gabarit) : CAM-B2r-IMPL.md ne suit pas le gabarit IMPL de lp-doc/gabarits.md : pas de tête « Fiche … Niveau … Modèle … Agent … Skills », sections 1 à 6 absentes ou non numérotées (pas de « Points à confirmer en VAL », pas de « Fichiers à commiter », pas de ligne « Tours »). Les informations utiles (MD5, écarts, non fait) y sont. Le présent livrable déduit donc ses « points à confirmer » de la section « Écart à la fiche » et de « Non fait ».
  • C-8 (dépôt) : LPCameraModeSubsystem.cpp et .h sont non suivis par git (??) : pour le gardien, ils seront A (nouveaux pour git), pas M. Le retour arrière du lot passe par l'instantané (Restore.ps1 -Lot CAM-B2r).

Fichiers à commiter (par le gardien, sur ticket ; non suivis par git donc A) :

  • A Source/LifePlay/LPCameraModeSubsystem.cpp
  • A Source/LifePlay/LPCameraModeSubsystem.h
  • A Docs/Migration/etat/CAM/CAM-B2r-VAL.md (ce livrable)

Fichier écrit par le validateur : D:\Game\LifePlay-master 5.8\Docs\Migration\etat\CAM\CAM-B2r-VAL.md (seul).