LifePlay-Revival/Docs/Migration/etat/CAM/CAM-B2c-IMPL.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

14 KiB

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