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

173 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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).