165 lines
14 KiB
Markdown
165 lines
14 KiB
Markdown
Fiche CAM-B2c-IMPL — Niveau N3 — Modèle prévu opus | utilisé claude-opus-5-5 — Agent lp-impl — Skills sk-protocol, sk-change-safety, ue-cpp-build, lp-ue-compat (préchargés : sk-protocol, ue-cpp-build, lp-build, lp-ue-compat ; sk-change-safety absent du contexte, règle de la fiche appliquée : fichiers neufs)
|
|
# CAM-B2c-IMPL : indicateur du mode de caméra, ULPCameraModeSubsystem (2026-10-13)
|
|
|
|
SPEC : `Docs/Migration/etat/CAM/CAM-B2c-SPEC.md` (lue en entier). Copie `D:\Game\LifePlay-master 5.8`, branche `ue5.8`.
|
|
Aucune compilation, aucun éditeur, aucun MCP, aucune écriture git (fiche, rubriques 2 et 5).
|
|
|
|
## 1. Fichiers modifiés (chemins, lignes)
|
|
Deux fichiers neufs, aucun fichier existant modifié par cette fiche.
|
|
|
|
| Fichier | Taille | MD5 | Lignes | Fins de ligne | Codage |
|
|
|---|---|---|---|---|---|
|
|
| `Source/LifePlay/LPCameraModeSubsystem.h` | 1790 o | `bf3412c1857a06ba1626a477eea5ef62` | 48 | LF (CR = 0) | ASCII pur (0 octet non ASCII), sans BOM |
|
|
| `Source/LifePlay/LPCameraModeSubsystem.cpp` | 8879 o | `8253ff12534e2933d16ccb997f967982` | 273 | LF (CR = 0) | ASCII pur, sans BOM |
|
|
|
|
Mesure (commande rejouée après écriture) :
|
|
```
|
|
for f in …LPCameraModeSubsystem.h …cpp; do wc -c ; tr -cd '\r' | wc -c ; tr -cd '\n' | wc -c ; head -c 3 | od -An -tx1 ; LC_ALL=C tr -d '\000-\177' | wc -c ; done ; md5sum …
|
|
Source/LifePlay/LPCameraModeSubsystem.h taille=1790 CR=0 LF=48 debut= 2f 2f 20 non-ASCII=0
|
|
Source/LifePlay/LPCameraModeSubsystem.cpp taille=8879 CR=0 LF=273 debut= 2f 2f 20 non-ASCII=0
|
|
bf3412c1857a06ba1626a477eea5ef62 *Source/LifePlay/LPCameraModeSubsystem.h
|
|
8253ff12534e2933d16ccb997f967982 *Source/LifePlay/LPCameraModeSubsystem.cpp
|
|
```
|
|
Référence des fins de ligne : `git ls-files --eol Source/LifePlay/LPOutdoorRoomSubsystem.cpp` → `i/lf w/lf attr/-text`
|
|
(modèle désigné par la fiche) ; dossier `Source/LifePlay` : 40 fichiers `i/lf`, 18 `i/crlf` ; `.gitattributes` = `* -text`.
|
|
Voisins sans BOM (`2f 2f 20` en tête de LPOutdoorRoomSubsystem.*, LPDirectControlSubsystem.cpp, LPKeyboardSubsystem.h).
|
|
|
|
Contenu :
|
|
- `.h` : `ULPCameraModeSubsystem : UGameInstanceSubsystem` (enregistrement automatique) ; `Initialize`, `Deinitialize` ;
|
|
privés `Tick`, `ComputeLabel`, `EnsureWidget`, `RemoveWidget`, `SetShown` ; membres `TickHandle`, `Root`
|
|
(`TSharedPtr<SWidget>`), `Text` (`TSharedPtr<STextBlock>`), `Viewport` (`TWeakObjectPtr<UGameViewportClient>`),
|
|
`ShownLabel`, `bShown`. En-tête de fichier en français (lot, rôle, aucun asset modifié), style de LPOutdoorRoomSubsystem.h.
|
|
- `.cpp` : espace de noms **nommé** `LPCameraModeLocal` (lectures par réflexion `ReadObject`, `ReadBool`,
|
|
`ArrayContains` ; copie de `MenuClasses` et `MenuOnScreen`) ; ticker `FTSTicker` toutes les 0,1 s ; classement ; texte
|
|
Slate.
|
|
|
|
Classement (`ComputeLabel`, ordre du § 2 de la SPEC, premier vrai gagne) :
|
|
| # | Condition (C++) | Libellé |
|
|
|---|---|---|
|
|
| 0 | pas de PC, ou cible de vue nulle | rien |
|
|
| 1 | vue == `GI.Birdview` (non nul) **ou** nom de classe de la vue contient `Birdview` | `Camera: Overview` |
|
|
| 2 | `GI.SexOn` et `GI.POVOn` | `Camera: POV` |
|
|
| 3 | `GI.SexOn` | `Camera: Scene` |
|
|
| 4 | vue == `GI.PlayerCharacter` (non nul) et `Room.CamC1On` | `Camera: C1 First person` |
|
|
| 5 | vue == `Room.CamRoom` (non nul) et `Room.CamC3On` | `Camera: C3 Ceiling` |
|
|
| 6 | vue == `Room.CamRoom` (non nul) | `Camera: C2 Follow` |
|
|
| 7 | `Room.CamC3On` | `Camera: C3 Room (old)` |
|
|
| 8 | vue ∈ `GI.ChargenCameras` (tableau d'objets, parcouru par `FScriptArrayHelper`) | `Camera: Studio` |
|
|
| 9 | vue == `Room.SceneCamera` (non nul) | `Camera: Builder` |
|
|
| — | sinon | rien |
|
|
PC : `GetGameInstance()->GetWorld()->GetFirstPlayerController()`, à défaut `GI.PC` ; vue : `PC->GetViewTarget()`. Room :
|
|
`GI.Room` si `IsValid`, sinon nul (les lectures sur un conteneur nul rendent nul / faux). Propriété absente, d'un autre
|
|
type, ou référence nulle : la ligne ne s'applique pas ; aucune lecture Blueprint, donc pas d'`Accessed None`.
|
|
|
|
Affichage : `SOverlay` racine, slot `HAlign_Left` / `VAlign_Bottom`, marge `FMargin(16.f)` ; `STextBlock` police
|
|
`FCoreStyle::GetDefaultFontStyle("Regular", 12)`, couleur `FLinearColor(1, 1, 1, 0.7)`, ombre décalée (1, 1) noire à
|
|
70 %. Racine `EVisibility::HitTestInvisible` quand visible, `Collapsed` sinon (changement seulement quand l'état
|
|
change). Ajout unique par `AddViewportWidgetContent(Root, 50)` sur le viewport du GameInstance, refait seulement si ce
|
|
viewport a changé. `SetText` seulement quand le libellé change (+ une ligne `LogLifePlay: Indicateur de camera : <libellé>`).
|
|
Masqué si libellé vide ou menu ouvert (copie de `MenuOnScreen` : `ULPKeyboardSubsystem::IsMenuOpen`, classes
|
|
`MenuClasses`, champ focalisé `Editable`) ; le test de menu n'est fait que si un libellé est à afficher.
|
|
Deinitialize : `RemoveTicker(TickHandle)`, puis `RemoveViewportWidgetContent(Root)` si le viewport porteur est encore
|
|
valide (pointeur faible), puis remise à zéro des pointeurs.
|
|
|
|
Noms de propriétés relus (établi) : GI `Birdview` (`ST/STE/dumps/GI__EventGraph_V5.txt:625`), `ChargenCameras` (:4442),
|
|
`PlayerCharacter` (:918), `PC` (:569), `Room` (:20904), `SexOn` (:6896), `POVOn` (:20528) ; Room `CamC1On`
|
|
(`CAM/CAM-B2b-VAL_LPDumpFunction_20261013-161237.txt:9699`), `CamC3On` (:9712), `CamRoom` (:9970), `SceneCamera` (:2312).
|
|
Types : `Birdview` = acteur `Birdview_C` (`CAM-AUDIT.md:15`), `CamRoom` = `CameraActor` (`CAM-B0-IMPL.md:25`),
|
|
`CamC1On` / `CamC3On` = bool (`CAM-B1-IMPL.md:20`), `ChargenCameras` = tableau de `CameraActor` (`CAM-AUDIT.md:16-18`).
|
|
|
|
API moteur lues dans `D:/Game/Launcher/Engine/UE_5.8/Engine/Source` (5.8.3, `Engine/Build/Build.version`) :
|
|
- `UGameViewportClient::AddViewportWidgetContent` `Runtime/Engine/Classes/Engine/GameViewportClient.h:258`,
|
|
`RemoveViewportWidgetContent` :265 (corps `Private/GameViewportClient.cpp:3376`, :3387 : `RemoveSlot` si l'overlay
|
|
existe) ; `RemoveAllViewportWidgets` n'est appelé qu'en `BeginDestroy` / `DetachViewportClient` (`GameViewportClient.cpp:472`, :480).
|
|
- `UGameInstance::GetWorld` `Runtime/Engine/Classes/Engine/GameInstance.h:211`, `GetGameViewportClient` :295 ;
|
|
`UGameInstanceSubsystem::GetGameInstance` `Runtime/Engine/Public/Subsystems/GameInstanceSubsystem.h:25`.
|
|
- `UWorld::GetFirstPlayerController` `Runtime/Engine/Classes/Engine/World.h:2781` ; `APlayerController::GetViewTarget`
|
|
`Runtime/Engine/Classes/GameFramework/PlayerController.h:1911`.
|
|
- `FTSTicker::AddTicker(const FTickerDelegate&, float InDelay)` `Runtime/Core/Public/Containers/Ticker.h:45` (InDelay :43),
|
|
`RemoveTicker` :66.
|
|
- `EVisibility::HitTestInvisible` `Runtime/SlateCore/Public/Layout/Visibility.h:23` ; `SWidget::SetVisibility`
|
|
`Runtime/SlateCore/Public/Widgets/SWidget.h:1068` ; `STextBlock` `Font` / `ColorAndOpacity` / `ShadowOffset` /
|
|
`ShadowColorAndOpacity` `Runtime/Slate/Public/Widgets/Text/STextBlock.h:89, 95, 98, 101`, `SetText` :200 ;
|
|
`FCoreStyle::GetDefaultFontStyle` `Runtime/SlateCore/Public/Styling/CoreStyle.h:51`.
|
|
- `UWidget::IsInViewport` `Runtime/UMG/Public/Components/Widget.h:549`, `GetVisibility` :586, `GetGameInstance` :871 ;
|
|
`FSlateApplication::GetKeyboardFocusedWidget` `Runtime/Slate/Public/Framework/Application/SlateApplication.h:1653` ;
|
|
`TObjectIterator` `Runtime/CoreUObject/Public/UObject/UObjectIterator.h:251`.
|
|
- `Runtime/CoreUObject/Public/UObject/UnrealType.h` : `FBoolProperty` :2589, `GetPropertyValue_InContainer` :2688 ;
|
|
`FObjectPropertyBase` :2773, `GetObjectPropertyValue` :2894, `GetObjectPropertyValue_InContainer` :2896 ;
|
|
`FArrayProperty` :3776, `Inner` :3782 ; `FScriptArrayHelper` :4262, constructeur `(const FArrayProperty*, const void*)`
|
|
:4285, `Num` :4303, `GetRawPtr` :4324 ; `ContainerPtrToValuePtr` (conteneur `const UObject*`) :811.
|
|
- Précédents compilés dans le module : même lecture de tableau (`LPModDailies.cpp:114-137`), espace de noms nommé
|
|
(`LPModDailiesImpl`, `LPUserSettingsGi`), `TWeakObjectPtr` d'un type déclaré en avant (`LPOutdoorRoomSubsystem.h`).
|
|
|
|
## 2. Écarts à la SPEC
|
|
- E1 (interprétation) Ligne 1 : « vue = `GI.Birdview` (classe contenant `Birdview`) » est codée en **ou** : égalité avec
|
|
`GI.Birdview`, ou nom de classe de la vue contenant `Birdview` (`Birdview_C`, `CAM-AUDIT.md:15`). Conséquence : la carte
|
|
est reconnue même si `GI.Birdview` est nul. Pour l'égalité seule : retirer le second terme (`LPCameraModeSubsystem.cpp`,
|
|
ligne `if ((Birdview && View == Birdview) || …)`).
|
|
- E2 PC : premier PlayerController du monde du GameInstance (fiche), `GI.PC` seulement en repli. Pas de PC ou pas de cible
|
|
de vue : rien n'est affiché, y compris pour les lignes 2-3 (`SexOn`, `POVOn`) qui ne dépendent pas de la vue.
|
|
- E3 Viewport : `GetGameInstance()->GetGameViewportClient()` au lieu de `GEngine->GameViewport` (modèle
|
|
LPDirectControlSubsystem) : viewport propre à ce GameInstance (PIE à plusieurs instances) ; ajout refait si le
|
|
viewport change (pointeur faible), sinon une seule fois.
|
|
- E4 Ajout : une ligne `LogLifePlay` (niveau Log) à chaque changement du libellé affiché, preuve de chargement pour la
|
|
VAL et l'essai (`lp-build` § 9 (8)). Non demandée par la SPEC.
|
|
- E5 Valeurs choisies (SPEC : « petite taille », « ombre ») : police Regular 12, ombre (1, 1) noire à 70 %, ordre Z 50
|
|
(celui du modèle, sans recouvrement : les invites de LPDirectControl sont centrées en bas).
|
|
- E6 Menu : partage « par copie » (option du § 3 de la SPEC), LPDirectControlSubsystem non modifié ; le test n'est fait
|
|
que lorsqu'un libellé est à afficher (coût du `TObjectIterator<UUserWidget>` évité sinon).
|
|
- E7 Espace de noms nommé `LPCameraModeLocal` au lieu d'un espace anonyme : `MenuClasses` et `MenuOnScreen` existent déjà
|
|
dans l'espace anonyme de LPDirectControlSubsystem.cpp ; en unity build ce serait une redéfinition (`lp-build` § 8).
|
|
- Constat sur la SPEC, **non corrigé** (aucune correction d'initiative) : la ligne 9 (`Camera: Builder`) est
|
|
inatteignable, car `Room.SceneCamera` = `GI.ChargenCameras[0]` (`CAM-AUDIT.md:16`, `CAM-T2-CART.md:95`) et la ligne 8
|
|
(`Camera: Studio`) est évaluée avant. Le constructeur affichera donc `Camera: Studio` (estimé). Correctif possible, à
|
|
décider : tester un indicateur du constructeur (`BuilderOn`, `CAM-T2-CART.md:66, 182`) avant la ligne 8, ou placer la
|
|
ligne 9 avant la ligne 8.
|
|
- Constat lié (estimé) : la ligne 7 ne dépend que de `CamC3On` ; si `CamC3On` reste vrai quand la vue passe à une caméra
|
|
du CharGen, des contacts ou du constructeur, le libellé sera `Camera: C3 Room (old)` (les menus CharGen_C et
|
|
ContactMenu_C masquent déjà le texte dans deux de ces cas).
|
|
|
|
## 3. Instantané (lot, manifeste)
|
|
sans objet : fichiers neufs, rien à sauvegarder (fiche, rubrique 2b) ; `Existed=False` pour
|
|
`Source/LifePlay/LPCameraModeSubsystem.h` et `Source/LifePlay/LPCameraModeSubsystem.cpp` (absents avant écriture :
|
|
`Grep "LPCameraMode|CameraMode"` sur `Source` → `No files found`, puis création par Write).
|
|
|
|
## 4. Ce qui n'a pas été fait
|
|
- Aucune compilation (confiée à lp-builder), aucun essai en jeu, aucune vérification en 5.5 (développement 5.5 arrêté).
|
|
- Pas de libellés français (SPEC : anglais proposés ; français « si l'utilisateur le préfère »).
|
|
- Pas de fonction partagée avec LPDirectControlSubsystem (copie, fiche rubrique 4 et 5).
|
|
- Pas d'entrée CHG ni de ticket (orchestrateur, gardien).
|
|
- Ligne 9 de la SPEC non réordonnée (§ 2 ci-dessus).
|
|
|
|
## 5. Points à confirmer en VAL
|
|
- V1 Build LifePlayEditor 5.8 (`Tools/Build.ps1`) : code 0, `LPCameraModeSubsystem.cpp` et `.gen.cpp` compilés, `UnrealEditor-LifePlay.dll` lié.
|
|
- V2 Aucun avertissement nouveau, en particulier C4456/C4458/C4459 (masquage de noms) et C4996.
|
|
- V3 Unity build complet (pas seulement adaptive) : pas de C2374/C2084/C2995 entre LPCameraModeSubsystem.cpp, LPDirectControlSubsystem.cpp et LPOutdoorRoomSubsystem.cpp.
|
|
- V4 Fichiers : LF, sans BOM, ASCII ; MD5 du § 1 inchangés avant commit.
|
|
- V5 `git status --short -- Source` : les 2 fichiers en `??` ; aucun fichier existant modifié par cette fiche (voir Constats : LPOutdoorRoomSubsystem.* modifiés par STG).
|
|
- V6 En jeu, journal : lignes `LogLifePlay: Indicateur de camera : Camera: …` aux changements de mode.
|
|
- V7 En jeu : texte en bas à gauche, marge 16 px, blanc translucide avec ombre, non cliquable (clics de la souris de pièce inchangés).
|
|
- V8 En jeu : texte masqué avec MainMenu, Journal, CityMenu, StatMenu, ContactMenu, Inventory, CharGen, ModManager, BodyShapeMenu, menu Clavier, champ de saisie focalisé.
|
|
- V9 En jeu : C (C1 → C2 → C3) donne `C1 First person`, `C2 Follow`, `C3 Room (old)` ; sortie de pièce `Overview` ; sexe `Scene`, POV `POV`.
|
|
- V10 En jeu : constructeur affiche `Camera: Studio` (ligne 9 inatteignable, § 2) : décision de l'orchestrateur.
|
|
- V11 Fermeture du jeu et arrêt / relance de PIE : pas de crash, pas d'`Accessed None`, texte présent une seule fois après relance.
|
|
|
|
## 6. Fichiers à commiter
|
|
Dépôt du jeu `D:\Game\LifePlay-master 5.8`, branche `ue5.8` :
|
|
- A `Source/LifePlay/LPCameraModeSubsystem.h`
|
|
- A `Source/LifePlay/LPCameraModeSubsystem.cpp`
|
|
- A `Docs/Migration/etat/CAM/CAM-B2c-IMPL.md`
|
|
|
|
Tours : 22 / 40
|
|
|
|
## Constats
|
|
- Écriture concurrente pendant la fiche (établi) : `git status --short -- Source` montrait au début
|
|
`M LPDebugSubsystem.cpp`, `M LPDebugSubsystem.h` seulement ; après mes écritures il montre aussi
|
|
`M Source/LifePlay/LPOutdoorRoomSubsystem.cpp` et `.h`. Horodatages : LPOutdoorRoomSubsystem.cpp 17:12:31,
|
|
`.h` 17:12:38 ; mes fichiers 17:13:42 (`.h`) et 17:14:14 (`.cpp`) ; le diff (+92 / -2) porte l'en-tête « Lot STG (S-F4,
|
|
B-SOL / B-DEPL) » (plancher `Room.Box`). Ce n'est pas cette fiche (lecture seule de ces fichiers). Le critère 6 de la
|
|
fiche (« exactement ces 2 fichiers en ?? en plus de l'existant ») se lit donc avec 4 `M` (STG) + 2 `??` (CAM-B2c).
|
|
Les nouveaux noms de l'espace anonyme de LPOutdoorRoomSubsystem.cpp (`FloorPropertyName`, `IndoorScaleZ`) ne
|
|
rencontrent aucun nom de LPCameraModeSubsystem.cpp (relu, lignes 12-28).
|
|
- Recherche de noms globaux qui masqueraient mes variables locales en unity build (C4459) : `Grep` des déclarations de
|
|
niveau 0-1 tabulation sur `Source/LifePlay/*.cpp` : seules des variables locales de fonctions membres, aucune
|
|
globale homonyme (estimé sans compilation).
|