LifePlay-Revival/Docs/Migration/etat/CAM/CAM-B2j-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

140 lines
12 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-B2j-VAL — Niveau N1 — Modèle prévu sonnet | utilisé Sonnet 5.5 (claude-sonnet-5-5) — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate
# CAM-B2j-VAL : témoin « touche C », validation statique (2026-10-13)
Copie `D:\Game\LifePlay-master 5.8`, branche `ue5.8` (`git branch --show-current` : `ue5.8`). Sans UE, sans compilation, sans
build : lecture et diff seulement. Seul fichier écrit : ce livrable.
## 1. Fiches amont relues
- Spécification : `Docs\Migration\etat\CAM\CAM-COMMUN4-DIAG.md` § 5 point 2 (l. 164-174) et complément (l. 180-198).
- Aucune fiche `CAM-B2j-*` ni IMPL B2j dans `Docs\` (Glob `**/*B2j*` : 0 résultat). Il n'y a donc pas de « point à
confirmer » d'IMPL à reprendre (voir § 2). `CAM-B2i-IMPL.md` et `CAM-B2i-VAL.md` existent (hors périmètre du diff B2j,
non relus en détail).
- Avant : `D:\Game\LifePlay_Backup_5.5\CAM-B2j\Source\LifePlay\` (2 fichiers) ; après : `Source\LifePlay\`.
- État git : `git status --short` donne `??` pour les deux fichiers (non suivis dans la copie 5.8, donc pas de
`<lot>-avant` exploitable) ; la comparaison se fait par `git diff --no-index` sur la sauvegarde.
## 2. Points à confirmer des IMPL
| Point | Verdict |
|---|---|
| Aucune IMPL B2j écrite, donc aucun point listé | sans objet : aucun livrable IMPL (Glob 0 résultat) ; les points de compilation et de comportement sont traités en § 3 |
| Compilation réelle (C2xxx, C4996) | reporté (BLOCKED-pas-de-build : non demandé) : à confirmer par la fiche BUILD de B2j |
| Ligne `Touche C` effectivement émise en jeu | reporté : exige un essai en jeu (passage CharGen en C1, appui sur C) |
## 3. Critères rejoués
### 3.1 Empreintes
Commande : `md5sum` des 4 fichiers.
```
d8981529e3773fbf50bb7fc1c91bc91f *Source/LifePlay/LPCameraModeSubsystem.cpp
2e1e245883960c2affc667a9a48fd96d *Source/LifePlay/LPCameraModeSubsystem.h
61fb558202e9bb3f567bceaa4bf241d3 *…/CAM-B2j/Source/LifePlay/LPCameraModeSubsystem.cpp
84f9ba303e1abd171c506dfbb4ed9f63 *…/CAM-B2j/Source/LifePlay/LPCameraModeSubsystem.h
```
Attendus : `D8981529…`, `2E1E2458…`, `61FB5582…`, `84F9BA30…`. Verdict : **PASS** (4 sur 4).
### 3.2 Diff lu en entier
`git diff --no-index --stat` : `.cpp` 72 lignes (71 ajouts, 1 suppression), `.h` 10 ajouts. Diff complet lu (2 fichiers).
La seule ligne supprimée est la condition de tête de `Tick` (`if (Label.IsEmpty() || MenuOnScreen(...))`), remplacée par
une version à `bMenu` calculé en amont (`.cpp:196` : même condition). Aucun Blueprint ni asset dans le diff.
Verdict : **PASS-STATIC**.
### 3.3 Conformité à la spécification (§ 5 point 2)
| Exigence | Preuve | Verdict |
|---|---|---|
| Second FTSTicker à intervalle 0, ajouté dans `Initialize` | `.cpp:163` `AddTicker(... TickSwitchKey), 0.f)` dans `SwitchKeyHandle` | PASS-STATIC |
| Retiré dans `Deinitialize` | `.cpp:167` `RemoveTicker(SwitchKeyHandle)` avant `TickHandle` | PASS-STATIC |
| Lecture des `ActionMappings` d'`UInputSettings`, action `SwitchCamera` | `.cpp:224-228` (`GetInputSettings()`, boucle `GetActionMappings()`), `.cpp:230` `Map.ActionName == SwitchCameraAction` (`FName("SwitchCamera")`, `.cpp:45`) | PASS-STATIC |
| `PlayerInput->IsPressed` | `.cpp:230` | PASS-STATIC |
| Front montant uniquement | `.cpp:237` `bDown && !bSwitchKeyDown`, puis `.cpp:241` `bSwitchKeyDown = bDown` | PASS-STATIC |
| Champs de la ligne `Touche C` : BuilderOn, SpaceOn, SexOn, CamC1On, CamC3On, C1Hidden, entree PC, regard ignore, viewport ignore, vue (classe), Room, PC, indicateur | `.cpp:254-258` ; variables : `GIBuilderOn`, `GISpaceOn` (nouveau, `.cpp:43`), `GISexOn`, `RoomCamC1On`, `RoomCamC3On`, `RoomC1Hidden` (nouveau, `.cpp:44`) | PASS-STATIC |
| Ligne `Indicateur de camera : aucun (vue …, classe …)` hors menu quand le libellé est vide | `.cpp:182-195` : branche `else if (!bMenu)` ; texte `"%s, classe %s"` inséré dans `(vue %s)` | PASS-STATIC |
| Une seule ligne par changement de vue | `.cpp:189` `ViewText != LastEmptyView` ; `LastEmptyView` remis à zéro dès qu'un libellé non vide existe (`.cpp:178-181`) | PASS-STATIC |
| `ShownLabel` remis à zéro au changement de vue vide, donc libellé suivant journalisé de nouveau | `.cpp:192` `ShownLabel.Reset()` ; test `.cpp:205` `Label != ShownLabel` puis log `.cpp:209` | PASS-STATIC |
| Aucun changement de comportement de l'indicateur affiché | remarques R1, R2 ci-dessous | PASS-STATIC |
| Aucun Blueprint touché | le diff ne porte que sur 2 fichiers C++ | PASS-STATIC |
Remarques (non bloquantes) :
- R1. `MenuOnScreen` est désormais évalué à chaque tick de 0,1 s même quand le libellé est vide (avant : court-circuit par
`Label.IsEmpty() ||`). La fonction est sans effet de bord (lecture, `TObjectIterator<UUserWidget>`) et déjà exécutée à la
même cadence quand le libellé est non vide ; l'effet (`SetShown(false)` puis retour) est le même. Estimé : surcoût
négligeable à 10 Hz.
- R2. `ShownLabel.Reset()` au changement de vue vide force seulement la réécriture du même texte à la reprise d'un libellé
non vide, sans effet visible. Estimé.
- R3 (limite du témoin, estimé). `UGameViewportClient::InputKey` rend la main avant `PlayerInput` si `IgnoreInput()` est
vrai (`Engine\Private\GameViewportClient.cpp:767-770`). Avec `viewport ignore=1`, la touche n'atteint donc pas
`PlayerInput->IsPressed` et aucune ligne `Touche C` ne sortira : l'absence de ligne est alors elle-même un indice (H4 côté
viewport). Les cas `entree PC=0` et `regard ignore=1` restent journalisés.
### 3.4 Compilation probable (en-têtes `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Engine\Classes\…`)
| Élément | Source | Verdict |
|---|---|---|
| Includes `GameFramework/InputSettings.h` (`.cpp:13`) et `GameFramework/PlayerInput.h` (`.cpp:15`) | ajoutés en ordre alphabétique autour de `PlayerController.h` | PASS-STATIC |
| `UInputSettings::GetInputSettings()` statique ; `GetActionMappings() const` | `GameFramework/InputSettings.h:248`, `:316` | PASS-STATIC |
| `UPlayerInput::IsPressed(FKey) const` | `GameFramework/PlayerInput.h:745` | PASS-STATIC |
| `PC->PlayerInput` est un `TObjectPtr<UPlayerInput>` : via `const APlayerController*` le pointé reste non const, `IsPressed const` appelable de toute façon | `GameFramework/PlayerController.h:370` | PASS-STATIC |
| `APlayerController::InputEnabled() const` | `PlayerController.h:2142` | PASS-STATIC |
| `AController::IsLookInputIgnored() const` (virtuelle) | `GameFramework/Controller.h:383` | PASS-STATIC |
| `GetViewTarget() const` | `Controller.h:253`, `PlayerController.h:1911` | PASS-STATIC |
| `UGameViewportClient::IgnoreInput()` non const | `Engine/GameViewportClient.h:773` (`virtual bool IgnoreInput() override`, sans `const`) | PASS-STATIC |
| `UGameInstance::GetGameViewportClient() const` rend un pointeur non const, d'où `UGameViewportClient* ViewportClient` | `Engine/GameInstance.h:295` ; `.cpp:252` | PASS-STATIC |
| `UWorld::GetFirstPlayerController()` rend `APlayerController*`, converti en `const APlayerController*` | `Engine/World.h:2781` | PASS-STATIC |
| `GetNameSafe(const UObjectBaseUtility*)` accepte `const AActor*`, `const UObject*`, `const APlayerController*` | `Runtime\CoreUObject\Public\UObject\UObjectBaseUtility.h:893` | PASS-STATIC |
| `LogSwitchKey(...) const` n'appelle que du const : `GetGameInstance()`, `ReadObject` / `ReadBool` (fonctions libres), `IsValid`, `GetViewTarget`, `InputEnabled`, `IsLookInputIgnored`, `GetClass`, `GetGameViewportClient` ; `IgnoreInput` passe par un pointeur non const local | `.cpp:245-259` | PASS-STATIC |
| `TickSwitchKey` (non const) appelle `LogSwitchKey` (const) | `.cpp:239` | PASS-STATIC |
| `UE_LOG` « Touche C » : 14 spécificateurs (9 `%d` puis 5 `%s`) pour 14 arguments (3 + 3 `Flag` en `int`, 3 ternaires `? 1 : 0`, puis `*GetNameSafe(View)`, `View ? *…GetName() : TEXT("-")` (`const TCHAR*`), `*GetNameSafe(Room)`, `*GetNameSafe(PC)`, `*ShownLabel`) | `.cpp:254-258` | PASS-STATIC |
| `UE_LOG` « aucun » : 1 `%s` pour `*ViewText` ; `Printf("%s, classe %s")` : `*GetNameSafe(View)` et `const TCHAR*` | `.cpp:188`, `.cpp:193` | PASS-STATIC |
| Lambda `Flag` : `[](const UObject* Container, FName Name) { return ReadBool(...) ? 1 : 0; }`, sans capture ; `ReadBool` qualifiée, accepte un conteneur nul ; reçoit `const UGameInstance*` (conversion vers `const UObject*`) ; définie hors de la macro `UE_LOG` | `.cpp:253` ; `ReadBool` `.cpp:77-81` | PASS-STATIC |
| `class APlayerController;` avant usage en signature | `.h:17`, usage `.h:45` | PASS-STATIC |
| `.h` : `FTSTicker` (`Containers/Ticker.h` déjà inclus), `FString` via `CoreMinimal.h` | `.h:12-13` | PASS-STATIC |
| `LogLifePlay` déclaré (`LifePlay.h` inclus `.cpp:17`) | `LifePlay.h:9` | PASS-STATIC |
| Espace nommé `LPCameraModeLocal` (pas anonyme) ; nouvelles constantes dans cet espace ; appels qualifiés ; commentaire de tête de l'espace | `.cpp:24-45` | PASS-STATIC |
| `DeltaTime` non utilisé : `(void)DeltaTime;` | `.cpp:242` | PASS-STATIC |
| Membres initialisés : `SwitchKeyHandle`, `bSwitchKeyDown = false`, `LastEmptyView` | `.h:48-52` | PASS-STATIC |
Verdict du bloc : **PASS-STATIC** (aucune erreur de compilation décelée par lecture ; compilation non rejouée).
Incertain : avertissement d'ombre de nom éventuel (`PC`, `World` locaux dans `Tick` ou `LogSwitchKey`) ; aucun membre
homonyme dans le `.h`, estimé sans risque.
### 3.5 Coût
Le ticker à intervalle 0 exécute, à chaque image : `GetFirstPlayerController`, `GetInputSettings` (CDO), une boucle sur
`GetActionMappings()` (une centaine d'entrées au plus, comparaison d'`FName` = comparaison d'entiers) et `IsPressed`
seulement pour les entrées nommées `SwitchCamera`. Pas d'allocation en régime normal (le `FString` de `LogSwitchKey`
n'existe que sur front montant). Estimé : de l'ordre de la microseconde par image, **acceptable** pour un témoin de
diagnostic. Verdict : **PASS-STATIC** (non mesuré). Le témoin est à retirer après le diagnostic.
### 3.6 Fins de ligne, BOM
Commande : `pwsh -NoProfile -Command '& "D:\Game\LifePlay-master 5.8\Tools\FileCheck.ps1" -Path "Source\LifePlay\LPCameraModeSubsystem.cpp","Source\LifePlay\LPCameraModeSubsystem.h"'`, code 0 :
```
LF 0 456 0 - D8981529E3773FBF50BB7FC1C91BC91F Source\LifePlay\LPCameraModeSubsystem.cpp
LF 0 62 0 - 2E1E245883960C2AFFC667A9A48FD96D Source\LifePlay\LPCameraModeSubsystem.h
fichiers=2 LF=2 alertes=0 introuvables=0
```
Recoupé par `tr -cd '\r' | wc -c` : CR = 0 pour les deux fichiers (et 0 pour le `.cpp` d'avant) ; `head -c3 | xxd -p` :
`2f2f20` (« // »), donc sans BOM. Piège noté : `-Path 'a','b'` passé par `pwsh -File` est lu comme un seul chemin
(« introuvable ») ; passer par `-Command`. Verdict : **PASS**.
### 3.7 Chemins de profil Windows
Grep `C:\\Users|AppData|<nom du compte>` sur `LPCameraModeSubsystem.*` : 0 occurrence. Le présent livrable n'en contient pas
(chemins du moteur et de la copie seulement). Verdict : **PASS**.
## 4. Diff lu en entier
- Fichiers : `Source\LifePlay\LPCameraModeSubsystem.cpp` (+71 −1), `Source\LifePlay\LPCameraModeSubsystem.h` (+10).
- Recompté : `git diff --no-index --stat` donne `72 …+++++++++++++++++++++-` et `10 ++++++++++`. Toutes les lignes
ajoutées relèvent de la spécification (constantes, includes, ticker, `Tick`, `TickSwitchKey`, `LogSwitchKey`, membres) :
aucun ajout non demandé.
## 5. Verdict
**PASS-STATIC** : conforme à la spécification et compilable à la lecture, empreintes attendues, LF sans BOM, aucun chemin
de profil. Non rejoué : compilation, émission de la ligne en jeu (§ 6). Aucun écart bloquant ; 3 remarques (R1 à R3).
## 6. Points à confirmer par l'utilisateur (cases)
- [ ] Compilation `LifePlayEditor` 5.8 sans erreur nouvelle (fiche BUILD B2j, puis `Build.ps1 -FromLog`).
- [ ] Essai en jeu : passage CharGen en C1, appui sur C, lecture de la ligne `Touche C : …` dans `Saved\Logs\LifePlay.log`.
- [ ] Lecture de R3 : si aucune ligne `Touche C` n'apparaît après l'appui, la touche n'atteint pas `PlayerInput`
(viewport ignore ou coupure en amont) ; ce n'est pas un défaut du témoin.
- [ ] Retrait du témoin (ticker image par image) après le diagnostic.
Fichiers à commiter : aucun par cette VAL (livrable `Docs\Migration\etat\CAM\CAM-B2j-VAL.md` à verser par le gardien avec le
lot ; les deux fichiers C++ sont `??` dans la copie 5.8 et relèvent du ticket du lot).
Tours : 12 / 40