Fiche SET1-V1b — Niveau N2 — Modèle prévu Sonnet (fiche) | utilisé claude-sonnet-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build (préchargés en plus : lp-build, lp-ue-compat) # SET1-V1b-IMPL : les lignes Couleur, Video et Mods se posent sur l'instance de MainMenu qui est à l'écran (2026-10-20) Hors gabarit : la fiche demande, après les rubriques IMPL 1 à 6, la compilation, le diff, les MD5, les journaux et la preuve attendue en jeu (sections 7 à 12). Suite directe de `SET1-V1-IMPL.md` (§ 0 et § 8). Contenu adulte (doc 27) : noms techniques de widgets seulement. Résultat : **réussi à la compilation** (éditeur et jeu : code 0, 0 erreur, 0 avertissement) ; **non éprouvé en jeu** (la preuve en jeu revient à la VAL, § 10). Les trois sous-systèmes choisissent maintenant la même liste que les onglets ; aucun état par instance à remettre à zéro n'a été trouvé chez eux (§ 2, constat C1). ## 1. Fichiers modifiés | Fichier | Lignes (après modification) | Contenu | |---|---|---| | `Source/LifePlay/LPSettingsSubsystem.h` | 17 | `class UGameInstance;` (déclaration avancée) | | idem | 50-55 | `static UScrollBox* FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current = nullptr);` publique, avec son commentaire | | `Source/LifePlay/LPSettingsSubsystem.cpp` | 592-596 | `ULPSettingsSubsystem::FindOnScreenSettingsList` : une ligne, renvoie `LPSettingsUi::FindOnScreenSettingsList(GI, Current)` (la fonction du `namespace LPSettingsUi`, `:122-146`, n'est pas touchée ; le `Tick` des onglets l'appelle comme avant) | | `Source/LifePlay/LPColorGradeSubsystem.cpp` | 18 | `#include "LPSettingsSubsystem.h"` | | idem | 260-264 | `EnsureControls` (commence l. 258) : la boucle « première `SettingsScrollBox` + `break` » (ancien 259-274) est remplacée par `ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance())` | | idem | 313-314 | nouvelle ligne de journal `Couleur : reglages de couleur ajoutes sur ` (fin d'`EnsureControls`) | | `Source/LifePlay/LPVideoQualitySubsystem.cpp` | 20 | `#include "LPSettingsSubsystem.h"` | | idem | 463-467 | `EnsureControls` (commence l. 461) : même remplacement (ancien 462-477) | | idem | 594-595 | journal `Video : controles ajoutes avant les reglages de couleur (sur )` | | `Source/LifePlay/LPModInfoSubsystem.cpp` | 21 | `#include "LPSettingsSubsystem.h"` | | idem | 243-246 | `EnsureSettingsRows` (commence l. 241) : même remplacement (ancien 242-257) | | idem | 302-305 | journal `Modules : cases de controle des mods ajoutees a Settings > Misc (moteur …, version min …, version max …) sur ` | Les numéros de ligne « après » ont été relevés par `grep -n` sur les fichiers actuels (après les builds). Total (`diff -u --strip-trailing-cr` contre l'instantané, lignes `+` / `-` hors en-têtes ; § 11) : 5 fichiers, +38 / −51. Par fichier : `LPSettingsSubsystem.h` +8 / −0, `LPSettingsSubsystem.cpp` +6 / −0, `LPColorGradeSubsystem.cpp` +8 / −16, `LPVideoQualitySubsystem.cpp` +8 / −17, `LPModInfoSubsystem.cpp` +8 / −18. Fins de ligne conservées (§ 9) : CRLF pour quatre fichiers, LF pour `LPModInfoSubsystem.cpp` (le fichier est LF dans l'index, `git ls-files --eol`). `LPKeyboardSubsystem.cpp` : non touché (consigne), MD5 `611c21489d80374a4817f70e408cf4db` avant et après. API moteur utilisée, lue dans `D:\Game\Launcher\Engine\UE_5.8\Engine\Source` (5.8.3). Le lot n'ajoute aucune API moteur nouvelle par rapport à SET1-V1 (§ 1 de `SET1-V1-IMPL.md`) ; les seules lignes neuves s'appuient sur : | API | Source | |---|---| | `UGameInstanceSubsystem::GetGameInstance() const` renvoie `UGameInstance*` (paramètre `const UGameInstance*` de la nouvelle fonction : conversion vers `const`) | `Runtime/Engine/Public/Subsystems/GameInstanceSubsystem.h:25` | | `class UGameInstance;` déjà déclarée par `GameInstanceSubsystem.h` (la redéclaration dans notre `.h` est sans effet) | `GameInstanceSubsystem.h:9` | | `UObject::GetTypedOuter() const` (pour le nom du `MainMenu` dans les journaux) | `Runtime/CoreUObject/Public/UObject/UObjectBaseUtility.h:551-553` | ## 2. Écarts à la SPEC / à la fiche | # | Écart | Motif | |---|---|---| | E1 | Le journal de Video et celui de Mods changent de texte (suffixe `(sur )` / `sur `), et le Color reçoit une ligne neuve. La fiche demande que « les lignes de journal de chaque sous-système visent l'instance à l'écran ». | Sans nom d'instance, aucune ligne ne prouve sur quelle liste les lignes ont été posées. Le début du texte est conservé, donc une recherche par préfixe trouve toujours les lignes : `VQ2-VAL.md:62` et `VQ2-SPEC.md:302` citent `Video : controles ajoutes avant les reglages de couleur` ; `U7-T7-IMPL.md:221` cite la ligne Mods **entière**, qui se terminait par `)` : une comparaison exacte avec cette trace ancienne échouerait. | | E2 | `Tick` des onglets inchangé : il appelle toujours la fonction du `namespace LPSettingsUi`, pas la fonction statique. | « Sans changer son comportement » : la statique est un renvoi d'une ligne vers la même fonction, aucun risque de divergence. | | E3 | Les trois appelants passent `Current` = nul (valeur par défaut) ; `Tick` des onglets passe `SettingsList`. | Ils ne suivent aucune liste. Conséquence : à égalité de score (deux instances à l'écran, aucune liste ouverte) ils prennent la première trouvée, les onglets la liste déjà suivie. Cas non rencontré (une seule instance à l'écran à la fois d'après `SET1-V1-IMPL.md` § 0), sans effet visible : dès qu'une liste est ouverte (score 2), les quatre sous-systèmes la choisissent. | | E4 | `LPSettingsSubsystem.h` est modifié (V1 : « `.h` non modifié »). | Exigé par la fiche (fonction statique publique déclarée dans le `.h`). | | E5 | Aucune remise à zéro d'état par instance n'a été ajoutée dans Color, Video et Mods (la fiche : « corrige au minimum »). | Constat C1 ci-dessous : leur « état » est lu sur les enfants de la liste choisie, donc par instance de fait. | | E6 | `CopieEtat.ps1 -Lot SET1` rend `ALERTE GIT` (code 1), 7 fichiers. | Deux sont **antérieurs** à ce travail (`LPCameraModeSubsystem.cpp`, `LPDirectControlSubsystem.cpp`, statut git de départ de la session) ; `LPSettingsSubsystem.cpp` porte aussi les changements de SET1-V1, non commités ; les quatre autres sont les fichiers de ce lot, non déclarés par `-Assets` (aucun asset). | **Constat C1 — état par instance (lecture, non observé en jeu).** Pour chacun des trois sous-systèmes, ce qui décide « les lignes sont-elles déjà là ? » est lu sur la liste choisie, jamais mémorisé dans un indicateur : - Color : présence d'un enfant `LPColorBrightness` (`LPColorGradeSubsystem.cpp:273`, boucle sur `Scroll->GetChildrenCount()`). Les cinq afficheurs de valeur `BrightnessValue`…`TintValue` sont des `TWeakObjectPtr` (`LPColorGradeSubsystem.h:53-57`) réaffectés par `AddRow` (`LPColorGradeSubsystem.cpp:235-254`, test sur le nom de la ligne) puis remplis (`:293-312`). Aucun indicateur booléen. - Video : présence d'un enfant `LPVideoOverall` (`LPVideoQualitySubsystem.cpp:477`). `Rows[]` (`.h:104`) et `RecommendedButton` (`.h:105`) sont réaffectés par `AddRow` (`:426-427`) et `MakeRecommendedRow` (`:457`) ; `RefreshWidgets()` (`:591`) et `ApplyToScalability()` (`:593`) rejouent les valeurs sur les curseurs neufs. `Levels` et `bConfigured` sont globaux par conception (choix du joueur), pas par instance. - Mods : présence d'un enfant `LPModCheckEngine` (`LPModInfoSubsystem.cpp:254`, `RowNames[0]`) ; aucune variable membre liée à la liste des réglages (`ManagerList` et `bManagerListLogged`, `.h:75-76`, concernent le gestionnaire de mods, autre widget, déjà filtré par `IsInViewport` à `TickModManager`). Avec la bonne liste, une nouvelle instance n'a pas ces enfants : les lignes sont recréées à la première image où l'instance est à l'écran ; l'ancienne instance n'est plus regardée. Les noms `LPColor*` / `LPVideo*` / `LPModCheck*` sont classés par `LPSettingsUi::CategoryOf` (`LPSettingsSubsystem.cpp:267-275` : Video, Video, Misc) et `ApplyRows` est rejoué à chaque image où la liste est ouverte, donc une ligne ajoutée plus tard entre dans son onglet à l'image suivante. **Constat C2 — délai.** Les lignes sont posées par des tickers à 0,5 s (`LPColorGradeSubsystem.cpp:77`, `LPVideoQualitySubsystem.cpp:160`, `LPModInfoSubsystem.cpp:150`), alors que `LPSettingsSubsystem` tourne à chaque image (`:583`, période 0). Entre l'apparition d'une instance à l'écran et ses lignes, il peut s'écouler jusqu'à ≈ 0,5 s ; un clic sur Settings dans cet intervalle montrerait les onglets Video et Misc incomplets quelques images (puis complétés). Estimé, non mesuré ; périodes non modifiées (hors fiche). **Constat C3 — le défaut de V1 §8 est bien celui-ci.** Les trois boucles supprimées étaient les mêmes (`TObjectIterator`, nom `SettingsScrollBox`, même `GameInstance`, `break` à la première) : `git diff`/`diff -u` du § 11, lignes `-`. ## 3. Instantané `D:\Game\LifePlay_Backup_5.5\SET1-V1b\` (fait par l'orchestrateur), `manifest.csv` relu : 5 fichiers, MD5 de départ **tous égaux** au manifeste avant écriture (relevé de session, § 9). | Fichier (dans `Source\LifePlay\`) | Octets | MD5 du manifeste | |---|---|---| | `LPSettingsSubsystem.cpp` | 33904 | `3591F579D88C4CA3A44468C750C9A24E` | | `LPSettingsSubsystem.h` | 1792 | `0F98C05568AE789C5C0B78F6EC580503` | | `LPColorGradeSubsystem.cpp` | 12464 | `F818C7F56DA018ED97683F01717A9AFB` | | `LPVideoQualitySubsystem.cpp` | 19408 | `DFF29F3F1B976979E556501CEBBF2613` | | `LPModInfoSubsystem.cpp` | 16572 | `1D0FFF7D4327C493903F180868D00BDE` | Retour arrière (proposé, non lancé) : `Tools\Restore.ps1 -Lot SET1-V1b`. Attention : `LPSettingsSubsystem.cpp` y revient à l'état **de fin de SET1-V1** (qui contient le travail de V1, non commité), pas à HEAD. ## 4. Ce qui n'a pas été fait - Aucun essai en jeu (la fiche n'en confie pas) ; aucun éditeur ni jeu lancé. - `LPKeyboardSubsystem.cpp` non touché (consigne). `LPReadableTextSubsystem.cpp`, `LPCameraModeSubsystem.cpp`, `LPDirectControlSubsystem.cpp` non ouverts. - Pas de changement des périodes des tickers (C2), du `Tick` des onglets, de `PlaceSettingsButton`, d'un Blueprint ni du GI. - Pas de test automatique (aucun existant pour ces sous-systèmes). Pas de build empaqueté. - Aucune autre boucle `SettingsScrollBox` à reprendre : `Grep "SettingsScrollBox"` sur `Source` ne trouve plus que `LPSettingsSubsystem.cpp:129` (la fonction partagée), `LPKeyboardSubsystem.cpp:854` (hors consigne, indicateur de journal sans `break`), `LPReadableTextSubsystem.cpp:125` (remontée de parents) et des commentaires. ## 5. Points à confirmer en VAL (un par ligne) 1. W1 : en partie (Échap, Settings), première ouverture : l'onglet Video montre Overall Quality, Shadows, Textures, Effects, Anti-Aliasing, Recommended (`LPVideo*`) puis Brightness, Saturation, Contrast, White Balance, Tint (`LPColor*`) ; l'onglet Misc montre les trois cases de contrôle des mods (`LPModCheck*`) ; le tout dès l'ouverture, sans attendre la collecte d'une ancienne instance (≈ 30 s). 2. W2 : deuxième et troisième ouverture en partie (nouvelle instance à chaque fois) : mêmes contenus Video et Misc dès l'ouverture ; pour chaque instance trois lignes de journal portant le **même** `MainMenu_C_` que `Reglages : onglets poses sur MainMenu_C_ (partie)` : `Couleur : reglages de couleur ajoutes sur …`, `Video : controles ajoutes avant les reglages de couleur (sur …)`, `Modules : cases de controle des mods ajoutees a Settings > Misc (…) sur …`. 3. W3 : écran titre, premier lancement, ouvrir Settings : mêmes contenus et mêmes trois lignes, `` identique à celui de `onglets poses sur … (ecran titre)`. Symptôme du risque V6 de SET1-V1 (`IsInViewport()` faux pour l'instance du titre) : aucune des trois lignes et aucun `onglets poses` au titre ; ce lot l'aggraverait pour Video/Mods/Couleur, qui l'avaient avant (première liste trouvée, sans filtre d'écran). 4. W4 : retour au titre puis réouverture : mêmes contenus et trois lignes avec un `` différent de celui du premier titre. 5. W5 : valeurs sur l'instance neuve : le curseur Overall et les quatre curseurs de Video affichent le niveau en cours (`RefreshWidgets`, pas la valeur par défaut) ; les cinq afficheurs de Couleur affichent les valeurs en cours (réaffectation des `TWeakObjectPtr`) ; un curseur déplacé sur l'instance neuve met bien à jour son afficheur (pas l'ancien). 6. W6 : pas de doublon : une seule ligne de journal par sous-système et par instance ; les noms `LPColorBrightness`, `LPVideoOverall`, `LPModCheckEngine` présents une fois dans la liste de l'instance à l'écran. 7. W7 : délai (C2) : mesurer, dans `LifePlay.log`, l'écart entre `Reglages : onglets poses sur …` et les trois lignes de la même instance ; attendu ≤ ≈ 0,5 s ; une ouverture de Settings dans cet intervalle ne doit rien casser. 8. W8 : ouverture répétée sur la même instance (ouvrir, Back, rouvrir) : aucune nouvelle ligne `Couleur`/`Video`/`Modules` (présence déjà vue), onglet Video inchangé. 9. W9 : reprise de V8 de `SET1-V1-IMPL.md` § 5 (onglets Video et Misc de l'instance de partie complets) : à juger sur W1 à W3 ; V1 à V10 de SET1-V1 restent à rejouer comme prévu. ## 6. Fichiers à commiter Dépôt du jeu, branche `ue5.8` : M `Source/LifePlay/LPSettingsSubsystem.h` M `Source/LifePlay/LPSettingsSubsystem.cpp` (contient aussi le travail de SET1-V1, non commité à la date de cette fiche) M `Source/LifePlay/LPColorGradeSubsystem.cpp` M `Source/LifePlay/LPVideoQualitySubsystem.cpp` M `Source/LifePlay/LPModInfoSubsystem.cpp` A `Docs/Migration/etat/REL/SET1/SET1-V1b-IMPL.md` A `Docs/Migration/etat/REL/SET1/SET1_Build_20261020-213520.txt` (résumé `Build.ps1` éditeur) A `Docs/Migration/etat/REL/SET1/SET1_Build_20261020-213620.txt` (résumé `Build.ps1` jeu) A `Docs/Migration/etat/REL/SET1/SET1-V1b_CopieEtat_avant_build.json`, `SET1-V1b_CopieEtat_apres_build.json` (traces `CopieEtat.ps1`) Hors lot, déjà modifiés avant ce travail, **à ne pas embarquer** : `Source/LifePlay/LPCameraModeSubsystem.cpp`, `Source/LifePlay/LPDirectControlSubsystem.cpp`. ## 7. Compilation Éditeur fermé et rien ne tournait avant (`UeState` : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0). Les deux builds ont été lancés à la suite, l'éditeur d'abord, le jeu seulement après un code 0. | | LifePlayEditor Win64 Development | LifePlay Win64 Development `-NoUBA` | |---|---|---| | Commande | `pwsh -NoProfile -Command "& 'D:/Game/LifePlay-master 5.8/Tools/Build.ps1' -Lot SET1 -EtatDir 'D:/Game/LifePlay-master 5.8/Docs/Migration/etat/REL/SET1'"` | idem + `-Target LifePlay -Config Development -ExtraArgs '-NoUBA'` | | Code de sortie | 0 | 0 | | Durée | 59 s | 59 s | | Erreurs / avertissements du compilateur | 0 / 0 | 0 / 0 | | Autres lignes (UBT, UHT, liens) | 20 (les 20 lignes `Plugin 'HyperAIStudio' does not list plugin …` connues, `lp-build` § 7 : attendu 20 pour l'éditeur) | 0 (attendu 0 pour la cible jeu) | | Unités compilées | 5 : `LPColorGradeSubsystem.cpp`, `LPModInfoSubsystem.cpp`, `LPSettingsSubsystem.cpp`, `LPVideoQualitySubsystem.cpp`, `Module.LifePlay.cpp` | les mêmes 5, marquées `[NoUba]` | | Liaison | `[6/8] Link [x64] UnrealEditor-LifePlay.dll` (DLL liées : 1) | `[6/7] Link [x64] LifePlay.exe [NoUba]`, `Output binary: D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.exe`, `Result: Succeeded` (journal `:26, :31, :33`) ; le résumé compte « DLL liées : 0 » car le jeu lie un `.exe` | | Toolchain | `Using Visual Studio 14.50.35739 toolchain (C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.50.35717)` = MSVC épinglé de la 5.8 | idem | | Résumé | `Docs\Migration\etat\REL\SET1\SET1_Build_20261020-213520.txt` | `Docs\Migration\etat\REL\SET1\SET1_Build_20261020-213620.txt` | | Journal | `Saved\Logs\portage\SET1_Build_20261020-213520.log` | `Saved\Logs\portage\SET1_Build_20261020-213620.log` | Sorties brutes de `Build.ps1` (dernières lignes de chaque build) : ``` code=0 duree=59s erreurs=0 avertissements=0 autres=20 unites=5 code=0 duree=59s erreurs=0 avertissements=0 autres=0 unites=5 ``` Dates des binaires (`ls -l --time-style=full-iso`) : `UnrealEditor-LifePlay.dll` 2026-10-20 21:36:18, `LifePlay.exe` 2026-10-20 21:37:17 (postérieurs aux écritures du § 11). Limites : la ligne `Makefile` des deux résumés est vide (comme en V1) ; le module modifié figure bien dans les unités compilées. Aucune ligne de journal propre au nouveau code n'existe avant un lancement du jeu (§ 10). ## 8. Les quatre autres sous-systèmes (point 3 de la fiche) `LPKeyboardSubsystem.cpp` : non modifié, MD5 `611c21489d80374a4817f70e408cf4db` identique avant et après (`md5sum`, § 9). Aucun défaut de choix d'instance d'après `SET1-V1-IMPL.md` § 8 (boucle sans `break`, ne sert qu'à un indicateur pour un journal). Trois sous-systèmes corrigés : Color, Video, Mods (§ 1). `LPReadableTextSubsystem` : sans objet (aucun choix d'instance). ## 9. MD5 et fins de ligne Commande : `md5sum Source/LifePlay/LPSettingsSubsystem.cpp Source/LifePlay/LPSettingsSubsystem.h Source/LifePlay/LPColorGradeSubsystem.cpp Source/LifePlay/LPVideoQualitySubsystem.cpp Source/LifePlay/LPModInfoSubsystem.cpp Source/LifePlay/LPKeyboardSubsystem.cpp` (après modification et après les builds, identique aux deux relevés) : ``` 6277a8fc139c05dc10e302f88de0f8d9 *Source/LifePlay/LPSettingsSubsystem.cpp 138350efe8473c430db984db63c8feac *Source/LifePlay/LPSettingsSubsystem.h 5be400543166b6de7a4a88f6097a9d93 *Source/LifePlay/LPColorGradeSubsystem.cpp c3055197030bdbbce813df4cc6d7cd63 *Source/LifePlay/LPVideoQualitySubsystem.cpp 98206e688308e908b04ae15cf408e1bb *Source/LifePlay/LPModInfoSubsystem.cpp 611c21489d80374a4817f70e408cf4db *Source/LifePlay/LPKeyboardSubsystem.cpp ``` | Fichier | MD5 avant (relu avant d'écrire, = manifeste) | MD5 après | |---|---|---| | `LPSettingsSubsystem.cpp` | `3591f579d88c4ca3a44468c750c9a24e` | `6277a8fc139c05dc10e302f88de0f8d9` | | `LPSettingsSubsystem.h` | `0f98c05568ae789c5c0b78f6ec580503` | `138350efe8473c430db984db63c8feac` | | `LPColorGradeSubsystem.cpp` | `f818c7f56da018ed97683f01717a9afb` | `5be400543166b6de7a4a88f6097a9d93` | | `LPVideoQualitySubsystem.cpp` | `dff29f3f1b976979e556501cebbf2613` | `c3055197030bdbbce813df4cc6d7cd63` | | `LPModInfoSubsystem.cpp` | `1d0fff7d4327c493903f180868d00bde` | `98206e688308e908b04ae15cf408e1bb` | | `LPKeyboardSubsystem.cpp` (non touché) | `611c21489d80374a4817f70e408cf4db` | idem | `git ls-files --eol` sur les cinq fichiers modifiés, puis comptes `tr -cd '\r' | wc -c` et `tr -cd '\n' | wc -c` : ``` i/crlf w/crlf attr/-text Source/LifePlay/LPColorGradeSubsystem.cpp (CR=370 LF=370) i/lf w/lf attr/-text Source/LifePlay/LPModInfoSubsystem.cpp (CR=0 LF=432) i/crlf w/crlf attr/-text Source/LifePlay/LPSettingsSubsystem.cpp (CR=1002 LF=1002) i/crlf w/crlf attr/-text Source/LifePlay/LPSettingsSubsystem.h (CR=76 LF=76) i/crlf w/crlf attr/-text Source/LifePlay/LPVideoQualitySubsystem.cpp (CR=596 LF=596) ``` `pwsh -NoProfile -File Tools/FileCheck.ps1 -Lot SET1-V1b` (le lot de l'instantané donne le manifeste des 5 fichiers) : ``` Fichiers CRLF LF CR BOM : fichiers=5 CRLF=4 LF=1 alertes=0 introuvables=0 contenu : modifie=5 ``` (détail par fichier : CRLF 370 / LF 432 / CRLF 1002 / CRLF 76 / CRLF 596, `Sauv` = fins de ligne de l'instantané identiques, aucune alerte.) `pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers -Depot "D:/Game/LifePlay-master 5.8"` (stdin sur `/dev/null`, un fichier par appel) : `PubCheck : 0 constat(s)`, code 0, pour chacun des cinq fichiers source. Pour ce livrable : voir la fin de la section 12. `pwsh -NoProfile -File Tools/CopieEtat.ps1 -Lot SET1 -Sortie …` avant et après les builds : `COPIE ALERTE lot=SET1 … proc=0 assets=0 absents=0 modifies=0 git=7/0/0 hors_declares=7 parasites=0 … alertes=GIT`, code 1 dans les deux cas (voir E6). Traces : `SET1-V1b_CopieEtat_avant_build.json`, `SET1-V1b_CopieEtat_apres_build.json`. Fin de lot : `pwsh -NoProfile -File Tools/UeState.ps1 < /dev/null` → `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0. **Jeton UE rendu.** ## 10. Journaux et preuve attendue en jeu Lignes de journal (préfixe `LogLifePlay: ` dans `LifePlay.log`) : | Ligne | Origine | Quand | |---|---|---| | `Reglages : onglets poses sur (ecran titre|partie)` | SET1-V1 (`LPSettingsSubsystem.cpp`, fin d'`EnsureTabs`) | création d'une barre sur une instance | | `Couleur : reglages de couleur ajoutes sur ` | **nouvelle** (`LPColorGradeSubsystem.cpp:313-314`, texte à la ligne 314) | les 5 lignes `LPColor*` viennent d'être ajoutées à la liste de cette instance | | `Video : controles ajoutes avant les reglages de couleur (sur )` | existante, suffixe **nouveau** (`LPVideoQualitySubsystem.cpp:594-595`) | les lignes `LPVideo*` et Recommended viennent d'être ajoutées | | `Modules : cases de controle des mods ajoutees a Settings > Misc (moteur a, version min b, version max c) sur ` | existante, suffixe **nouveau** (`LPModInfoSubsystem.cpp:302-305`) | les 3 cases `LPModCheck*` viennent d'être ajoutées | Recette de lecture pour la VAL : `pwsh -NoProfile -File Tools/LogStats.ps1 -Log -Pattern 'onglets (poses|retires)|reglages de couleur ajoutes sur|controles ajoutes avant|cases de controle des mods' -Max 60` (un seul motif à alternatives : `pwsh -File` refuse une liste ; journal de la session, pas de compte refait de mémoire). Rapprocher ensuite les noms `MainMenu_C_` des quatre familles de lignes. Preuve attendue, à rejouer par la VAL sur un build Development : | Scénario | Attendu à l'écran | Attendu au journal | |---|---|---| | Partie : Échap, Settings, première ouverture | onglets Video et Misc complets dès l'ouverture (W1) | `onglets poses sur MainMenu_C_n (partie)` puis, avec le même `n`, les trois lignes Couleur, Video, Modules (ordre libre) | | Partie : deuxième, troisième ouverture | idem, sans attendre ≈ 30 s (W2) | `onglets retires de ` si une barre existait ; un `n` nouveau à chaque ouverture, repris par les quatre lignes | | Écran titre, puis retour au titre | idem (W3, W4) | `(ecran titre)` ; un `n` différent au second titre, repris par les trois lignes | | Même instance rouverte | aucun changement (W8) | aucune nouvelle ligne Couleur, Video, Modules | Limite : la présence d'une ligne `sur ` ne prouve que la liste choisie ; ce que le joueur voit (contenu des onglets) se juge à l'écran. Ni `IsInViewport()` sur l'instance du titre, ni l'ordre réel d'itération de `TObjectIterator`, ni le délai du ticker à 0,5 s ne sont observés ; établis par lecture seulement. ## 11. Diff (`diff -u --strip-trailing-cr` entre l'instantané `D:/Game/LifePlay_Backup_5.5/SET1-V1b/Source/LifePlay/` et `Source/LifePlay/`) ```diff === LPSettingsSubsystem.h @@ -14,6 +14,7 @@ class UButton; class UCanvasPanel; +class UGameInstance; class UHorizontalBox; class UNativeWidgetHost; class UScrollBox; @@ -46,6 +47,13 @@ UFUNCTION() void OpenSettings(); + // Lot SET1-V1b. Liste des reglages (MainMenu.SettingsScrollBox) de l'instance de MainMenu qui est a l'ecran, nulle s'il + // n'y en a aucune. Partagee avec les sous-systemes qui ajoutent des lignes a cette liste (couleur, video, controle des + // mods) : une ancienne instance, retiree du viewport et pas encore collectee, garde sa liste en memoire et ne doit pas + // recevoir leurs lignes a la place de l'instance affichee. Current : liste deja suivie par l'appelant, elle departage + // deux listes a l'ecran ; peut etre nulle. + static UScrollBox* FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current = nullptr); + private: bool Tick(float DeltaTime); void PlaceSettingsButton(); === LPSettingsSubsystem.cpp @@ -589,6 +589,12 @@ Super::Deinitialize(); } +UScrollBox* ULPSettingsSubsystem::FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current) +{ + // SET1-V1b : meme choix que le Tick des onglets (LPSettingsUi::FindOnScreenSettingsList), expose aux autres sous-systemes. + return LPSettingsUi::FindOnScreenSettingsList(GI, Current); +} + bool ULPSettingsSubsystem::Tick(float DeltaTime) { (void)DeltaTime; === LPColorGradeSubsystem.cpp @@ -15,6 +15,7 @@ #include "Engine/PostProcessVolume.h" #include "Engine/World.h" #include "LifePlay.h" +#include "LPSettingsSubsystem.h" #include "Misc/ConfigCacheIni.h" #include "Misc/Paths.h" #include "Styling/CoreStyle.h" @@ -256,22 +257,11 @@ void ULPColorGradeSubsystem::EnsureControls() { - UScrollBox* Scroll = nullptr; - for (TObjectIterator It; It; ++It) - { - UScrollBox* Candidate = *It; - if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) - { - continue; - } - const UUserWidget* Owner = Candidate->GetTypedOuter(); - if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance()) - { - continue; - } - Scroll = Candidate; - break; - } + // SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance, + // retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par + // instance a remettre a zero : la presence de LPColorBrightness se lit sur les enfants de la liste choisie, et AddRow + // rebranche les afficheurs de valeur (BrightnessValue...) sur les lignes de cette liste. + UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance()); if (!Scroll) { return; @@ -320,6 +310,8 @@ { Readout->SetText(FText::FromString(LPColorGrade::FormatValue(Tint, 2))); } + const UUserWidget* Menu = Scroll->GetTypedOuter(); + UE_LOG(LogLifePlay, Display, TEXT("Couleur : reglages de couleur ajoutes sur %s"), Menu ? *Menu->GetName() : TEXT("?")); } void ULPColorGradeSubsystem::OnBrightnessChanged(float Value) === LPVideoQualitySubsystem.cpp @@ -17,6 +17,7 @@ #include "Engine/World.h" #include "HAL/IConsoleManager.h" #include "LifePlay.h" +#include "LPSettingsSubsystem.h" #include "Misc/ConfigCacheIni.h" #include "Misc/Paths.h" #include "DynamicRHI.h" @@ -459,22 +460,11 @@ void ULPVideoQualitySubsystem::EnsureControls() { - UScrollBox* Scroll = nullptr; - for (TObjectIterator It; It; ++It) - { - UScrollBox* Candidate = *It; - if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) - { - continue; - } - const UUserWidget* Owner = Candidate->GetTypedOuter(); - if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance()) - { - continue; - } - Scroll = Candidate; - break; - } + // SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance, + // retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par + // instance a remettre a zero : la presence de LPVideoOverall se lit sur les enfants de la liste choisie, et AddRow / + // MakeRecommendedRow rebranchent Rows et RecommendedButton sur les lignes de cette liste. + UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance()); if (!Scroll) { return; @@ -601,5 +591,6 @@ RefreshWidgets(); // Nouvelle instance du menu : le Blueprint a pu reappliquer ses propres valeurs. ApplyToScalability(); - UE_LOG(LogLifePlay, Display, TEXT("Video : controles ajoutes avant les reglages de couleur")); + const UUserWidget* Menu = Scroll->GetTypedOuter(); + UE_LOG(LogLifePlay, Display, TEXT("Video : controles ajoutes avant les reglages de couleur (sur %s)"), Menu ? *Menu->GetName() : TEXT("?")); } === LPModInfoSubsystem.cpp @@ -18,6 +18,7 @@ #include "LifePlay.h" #include "LPDataCompat.h" #include "LPModGuard.h" +#include "LPSettingsSubsystem.h" #include "Misc/EngineVersion.h" #include "Misc/FileHelper.h" #include "Misc/Paths.h" @@ -239,22 +240,10 @@ void ULPModInfoSubsystem::EnsureSettingsRows() { - UScrollBox* Scroll = nullptr; - for (TObjectIterator It; It; ++It) - { - UScrollBox* Candidate = *It; - if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) - { - continue; - } - const UUserWidget* Owner = Candidate->GetTypedOuter(); - if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance()) - { - continue; - } - Scroll = Candidate; - break; - } + // SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance, + // retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par + // instance a remettre a zero : la presence de LPModCheckEngine se lit sur les enfants de la liste choisie. + UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance()); if (!Scroll) { return; @@ -310,9 +299,10 @@ Slot->SetPadding(FMargin(0.f, 0.f, 0.f, 10.f)); } } - UE_LOG(LogLifePlay, Display, TEXT("Modules : cases de controle des mods ajoutees a Settings > Misc (moteur %d, version min %d, version max %d)"), + const UUserWidget* Menu = Scroll->GetTypedOuter(); + UE_LOG(LogLifePlay, Display, TEXT("Modules : cases de controle des mods ajoutees a Settings > Misc (moteur %d, version min %d, version max %d) sur %s"), FLPModGuard::GetSavedCheck(ELPModCheck::Engine) ? 1 : 0, FLPModGuard::GetSavedCheck(ELPModCheck::MinVersion) ? 1 : 0, - FLPModGuard::GetSavedCheck(ELPModCheck::MaxVersion) ? 1 : 0); + FLPModGuard::GetSavedCheck(ELPModCheck::MaxVersion) ? 1 : 0, Menu ? *Menu->GetName() : TEXT("?")); } ``` ## 12. Établi / estimé / incertain - **Établi** : les trois boucles remplacées étaient identiques (`SettingsScrollBox`, même `GameInstance`, `break` à la première, § 11 lignes `-`) ; aucun autre site ne les reprend (`Grep "SettingsScrollBox"` sur `Source`, § 4) ; l'état de Color, Video et Mods se lit sur les enfants de la liste choisie (C1, avec lignes) ; la fonction statique renvoie la même valeur que celle des onglets (renvoi d'une ligne, `LPSettingsSubsystem.cpp:592-596`) ; MD5 de départ égaux au manifeste, MD5 d'arrivée et fins de ligne relevés (§ 9) ; `LPKeyboardSubsystem.cpp` inchangé ; compilation éditeur et jeu : code 0, 0 erreur, 0 avertissement, 5 unités compilées dans chaque (§ 7). - **Estimé** : une ancienne instance précède la nouvelle dans `TObjectIterator` (déjà estimé en V1) ; les lignes arrivent au plus ≈ 0,5 s après l'apparition de l'instance (tickers à 0,5 s, C2) ; `ApplyRows` classe sans autre changement les lignes ajoutées plus tard (rejoué à chaque image, `Tick` des onglets). - **Incertain** (essai qui trancherait : W1 à W9, § 5) : contenu réel des onglets Video et Misc aux trois scénarios ; `IsInViewport()` vrai pour l'instance du titre (V6 de V1) ; absence de régression de Video/Mods/Couleur au titre si ce filtre était faux ; mesure du délai de 0,5 s. - **Livrable** : 0 CR (fins de ligne LF, `tr -cd '\r' | wc -c` = 0) ; `PubCheck` sur ce fichier : `PubCheck : 0 constat(s)`, code 0 ; `UeState` final : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0 ; **jeton UE rendu**. Tours : 36 / 40 (déclaré par l'agent ; `Tools/FicheStats.py` fait foi) ## Constats - `Tools\FileCheck.ps1 -Lot SET1-V1b` (lot de l'instantané, sans `-Path`) compare bien les cinq fichiers au manifeste (`Sauv` = fins de ligne d'origine, `Contenu` = modifié). C'est le contournement du piège relevé en V1 (`Contenu = pas sauvegarde` avec un chemin relatif à barres obliques). - Les builds ont été enchaînés dans une commande d'arrière-plan (`CopieEtat` avant, `Build` éditeur, `Build` jeu seulement si l'éditeur rend 0, `CopieEtat` après, `UeState`), l'attente se faisant par `UeState.ps1 -Kind Compilation -WaitExit` (`lp-build` § 2) ; le jeu est lancé par `pwsh -Command "& '…/Build.ps1' … -ExtraArgs '-NoUBA'"` : la forme `-File … -ExtraArgs '-NoUBA'` risquerait de lire `-NoUBA` comme un nom de paramètre. - La ligne exacte `U7-T7-IMPL.md:221` (trace ancienne de la ligne Mods) ne correspond plus à la ligne produite par le code actuel (suffixe ` sur `) : voir E1.