LifePlay-Revival/Docs/Migration/etat/ST/STD/STD-TXT-DIAG.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

16 KiB
Raw Blame History

Fiche STD-TXT — Niveau N3 — Modèle prévu (modèle de l'agent lp-cart) | utilisé claude-opus-5-5 — Agent lp-cart — Skills lp-doc (gabarits), sk-protocol

STD-TXT-DIAG : texte trop clair des champs de saisie du panneau Save Preset de CharGen, 5.5 → 5.8 (2026-10-10)

Lecture seule stricte (gel STC) : aucun UE, éditeur, commandlet ni jeu lancé. Seule écriture : ce fichier. Les fichiers intermédiaires (diffs, chaînes extraites) sont dans le scratchpad de session et ne sont pas des livrables.

1. Symptôme et reproduction

  • Symptôme (capture de l'utilisateur, fiche § 3) : dans le panneau Save Preset de CharGen, le texte saisi « tee » est à peine visible dans la boîte « Content/Modules/.lpcharacter », et la valeur « 0.0 » est estompée dans la SpinBox « Variance +- … % ». Selon l'utilisateur, l'affichage était correct en 5.5.
  • Build concerné : build empaqueté 5.8 Development (D:\Game\LifePlay_Build_5.8_STB-JEU2_Development, STB-JEU-VAL.md:5-8) ; l'écran CharGen n'a pas été touché par STB (STB-JEU-VAL.md:34).
  • Widgets identifiés dans le relevé d'assets U5 (copie 5.8, Saved\Logs\portage\U5_assets_apres.txt) :
    • boîte de saisie = CharGen:WidgetTree.FilenameEntry [EditableTextBox] (:1219144-1219151), précédée du TextBlock TextContentModul (:1219637-1219639) ;
    • SpinBox = CharGen:WidgetTree.VarianceSpinBox [SpinBox] (:1221929-1221940), précédée du TextBlock TextVariance.
  • Distinction demandée par la fiche :
    • pas un HintText : le HintText de FilenameEntry est « MyFirstMod/MyFirstCharacter » (:1219146) ; « tee » est donc du texte saisi ; la SpinBox n'a pas de hint ;
    • pas désactivé, pas en lecture seule : aucun bIsEnabled, IsReadOnly ni Visibility parmi les propriétés sérialisées des deux widgets (:1219145-1219151, :1221930-1221940). Aucun appel SetIsEnabled, SetIsReadOnly ni SetForegroundColor dans le graphe de CharGen (Grep des MemberName= sur tout le relevé : ces appels n'existent que dans d'autres widgets, par exemple MainMenu :1346405).
  • Reproduction : pas encore faite (gel). Test décisif au § 5.

2. Hypothèse testée (une seule)

H1 : un changement entre UE 5.5 et UE 5.8 du style par défaut (couleurs, pinceaux) ou du code d'EditableTextBox, EditableText ou SpinBox (UMG et Slate), ou de la propagation de la couleur de premier plan, rend le texte plus clair en 5.8.

3. Essai et résultat brut

3.1 Recherche web (d'abord, décision utilisateur du 2026-10-09)

3.2 Valeurs de style par défaut, moteurs 5.5 et 5.8 (sources installées)

Commande type : git -c core.autocrlf=false diff --no-index <UE_5.5>/<f> <UE_5.8>/<f> (Bash, depuis D:\Game\Launcher\Engine).

Élément 5.5 5.8 Résultat
FEditableTextBoxStyle() : TextStyle UseForeground, ForegroundColor/ReadOnly…/Focused… = UseForeground, BackgroundColor blanc SlateTypes.cpp:272-291 SlateTypes.cpp:287-306 identique
FSpinBoxStyle() : ForegroundColor UseForeground SlateTypes.cpp:542-549 SlateTypes.cpp:560-567 identique
FUMGColor (dont ForegroundInverted = 0.472885) hunk @@ -30,38 +42,38 @@ idem seul le suffixe f des littéraux change
NormalText UMG : ColorAndOpacity UseForeground — UMGCoreStyle.cpp:238-240 inchangé (diff sans hunk ici)
NormalEditableTextBox UMG (aucune couleur de texte) — UMGCoreStyle.cpp:554-562 inchangé
SpinBox UMG : .SetForegroundColor(InvertedForeground) — UMGCoreStyle.cpp:745-752 (InvertedForeground :217) inchangé
FDefaultStyleCache (styles d'exécution des widgets UMG) — DefaultStyleCache.cpp:40-41, 63-64 diff vide (fichier identique)
StarshipCoreStyle.cpp, CoreStyle.cpp, StyleColors.cpp, SlateTypes.h — — aucune ligne modifiée sur NormalText, EditableTextBox, SpinBox ni leurs couleurs (Grep des lignes +/- des diffs)

3.3 Pinceaux et empaquetage

  • MD5 identiques 5.5/5.8 pour Engine/Content/Slate/Common/{TextBox, TextBox_Hovered, TextBox_ReadOnly, TextBox_Dark, Spinbox, Spinbox_Hovered, Spinbox_Fill, Spinbox_Fill_Hovered}.png (md5sum, 8/8 identiques).
  • Pixel central décodé : TextBox.png = gris 255 avec alpha 204 (blanc à 80 %) ; Spinbox.png = gris 230 opaque.
  • Manifestes UFS : Checkerboard.png et Common/TextBox.png empaquetés dans les deux builds (5.8 STB-JEU2 Manifest_UFSFiles_Win64.txt:26, 121 ; 5.5 DC4 :26, 119) ; Common/Spinbox.png absent des deux manifestes. Liste Engine/Content/Slate/ : 789 entrées (5.8) contre 722 (5.5) ; diff des listes : uniquement des ajouts 5.8 (icônes d'éditeur), aucun retrait.
  • Journal du build 5.8 (…STB-JEU2_Development\Windows\LifePlay\Saved\Logs\LifePlay.log) : 0 ligne FUMGCoreStyle|Unable to find Slate Widget Style|assets not detected et 0 ligne Slate resource (Grep).

3.4 Code UMG et Slate des deux widgets

  • UEditableTextBox : différences 5.5 → 5.8 limitées aux polices asynchrones, au curseur et à un SetWidgetStyle natif (diff EditableTextBox.cpp, EditableTextBox.h). Le style d'exécution vient toujours du cache (EditableTextBox.cpp:41, 5.8). WidgetStyle reçoit Getter, Setter natifs ; le nœud Blueprint Set écrit le champ directement et n'appelle pas ce setter (K2Node_VariableSet.cpp:501-505, 5.8, « todo check … native Setter »).
  • SEditableTextBox : SetStyle est appelé après la construction en 5.8 (SEditableTextBox.cpp:99), avant en 5.5 (diff, hunk @@ -27,7 +28,6 @@). Pas d'effet en UMG : SynchronizeProperties appelle SetStyle(&WidgetStyle) dans les deux versions (EditableTextBox.cpp:129, 5.5). DetermineForegroundColor est inchangé (lecture seule → focus → normal, SEditableTextBox.cpp:354-379, 5.8).
  • SEditableText : la couleur passe par un TSlateAttribute (bIsColorAndOpacityAttrSet) avec la même sémantique que ColorAndOpacity.IsSet() en 5.5 (SEditableText.cpp:553-562, 5.8, et diff). La peinture prend toujours TextStyle.ColorAndOpacity.GetColor(InWidgetStyle) comme premier plan (diff OnPaint, inchangé).
  • Hint : l'opacité 0.35 était codée en dur en 5.5 ; en 5.8 elle devient un paramètre dont la valeur par défaut est 0.35 (SlateEditableTextLayout.h:79, emploi SlateEditableTextLayout.cpp:3683). Seul le hint est concerné, pas le texte saisi.
  • USpinBox : ForegroundColor = WidgetStyle.ForegroundColor, soit InvertedForeground (SpinBox.cpp:52, 5.8), poussé au widget Slate par SetForegroundColor (:98), puis SetWidgetStyle (:111). Diff 5.5/5.8 : seul ajout, VirtualKeyboardDismissAction.
  • SSpinBox : code déplacé de l'en-tête vers SSpinBox.cpp ; même construction : premier plan du style (SSpinBox.cpp:81 ↔ SSpinBox.h:206 en 5.5), STextBlock au style par défaut (:186-191 ↔ :300-305), flèches en UseForeground (:223 ↔ :335).
  • Propagation du premier plan : SBorder.cpp et SlateColor.cpp identiques ; SGameLayerManager.cpp, SObjectWidget.cpp, SWindow.cpp, Border.cpp, SlateColor.h : aucune ligne modifiée touchant Foreground|ColorAndOpacity|WidgetStyle|Tint. UUserWidget::ForegroundColor vaut UseForeground dans les deux versions (UserWidget.cpp:92 en 5.5, :105 en 5.8).
  • Pipeline de rendu : SlateElementPixelShader.usf est fortement modifié (243 ajouts, 132 suppressions : type de shader dynamique, factorisation des polices et SDF). Le Grep des lignes modifiées ne montre aucun changement de gamma ni de contraste, mais l'examen n'a pas été poussé (§ 5).

3.5 Asset CharGen (valeurs sérialisées et graphe)

  • Les relevés U5 d'avant et d'après le resave 5.8 sont identiques pour ces widgets (U5_assets_avant.txt:1220410-1220417, 1223195-1223203, 1222238-1222246 ; U5_assets_apres.txt aux lignes ci-dessous). Chaînes extraites des deux CharGen.uasset (script Python -I en lecture seule) : 25 243 lignes (5.8) et 24 375 (5.5), 6 occurrences de WidgetStyle dans chaque copie, mêmes nœuds K2Node_MakeStruct_EditableTextBoxStyle, K2Node_BreakStruct et K2Node_VariableSet.
  • FilenameEntry : seule surcharge, WidgetStyle = (TextStyle=(Font=(FontObject=None,Size=16.000000))) (:1219145). Aucune couleur sérialisée : ni ForegroundColor, ni TextStyle.ColorAndOpacity.
  • VarianceSpinBox : Font = (TypefaceFontName="Italic",Size=16.000000) (:1221930). Aucun ForegroundColor sérialisé.
  • Parents : HorizontalBox_13 / HorizontalBox_14 → VerticalBox_1 → CanvasPanel_5 → SaveBorder [Border], Background teinté noir à alpha 0.5, aucun ContentColorAndOpacity (:1219633-1219650, :1221957-1221960, :1218888-1218891, :1220972-1220983).
  • Graphe : sur un nom de fichier refusé (K2Node_IfThenElse_366.else, :1191697-1191704), on écrit WidgetStyle avec BackgroundColor rouge (K2Node_MakeStruct_62 / _63, :1192103-1192135), puis Delay 1 s (:1188387-1188397), puis on remet BackgroundColor à blanc (_64 / _65, :1192136-1192168), sur FilenameEntry (K2Node_VariableSet_1147 / _1146, :1195439-1195460). TextStyle, ForegroundColor et ReadOnlyForegroundColor sont recopiés du style courant (K2Node_BreakStruct_62, :1184403-1184415) ; FocusedForegroundColor n'est pas relié : il est remis à UseForeground (:1192122, :1192155).
  • Autre appel touchant l'opacité : SetRenderOpacity sur CharGen lui-même (CharGen:EventGraph.K2Node_CallFunction_240, :1186472-1186473), valeur non lue.

4. Verdict

H1 réfutée pour les valeurs de style par défaut, les pinceaux et leur empaquetage, le code UMG et Slate d'EditableTextBox, EditableText et SpinBox, et la propagation du premier plan : rien de ce qui a été lu ne change la couleur du texte saisi entre 5.5 et 5.8. Indécise pour le pipeline de rendu Slate (shader refactoré, § 3.4), non examiné à fond.

Ce que montrent les sources, sur l'asset (établi pour les valeurs lues, estimé pour le rendu qui en découle) :

  • FilenameEntry : la couleur du texte est entièrement héritée. Style, TextStyle et UserWidget sont tous en UseForeground (§ 3.2, § 3.4), sans surcharge dans l'asset (§ 3.5). Le texte prend donc le premier plan de la racine Slate, blanc par défaut d'après mes connaissances (non relu dans la source), sur un fond TextBox.png blanc à 80 % posé sur un Border noir à 50 %, soit un fond gris clair.
  • VarianceSpinBox : le texte est en InvertedForeground = 0.472885 linéaire (environ 0.72 en sRGB, gris clair), sur un fond gris clair. Spinbox.png est absent des deux builds ; le pinceau de repli n'a pas été vérifié.
  • Selon les sources, ce rendu clair sur clair est le même en 5.5 et en 5.8. L'écart signalé par l'utilisateur n'est pas expliqué par les sources lues.

Causes classées par probabilité :

# Cause Probabilité Preuve
C1 L'asset ne fixe aucune couleur de texte : il dépend des couleurs par défaut du moteur, claires sur fond clair (texte hérité pour FilenameEntry, InvertedForeground pour la SpinBox) probable (cause directe du faible contraste, établie sur l'asset) § 3.5 :1219145, :1221930 ; § 3.2 UMGCoreStyle.cpp:217, 238-240, 745-752 ; SpinBox.cpp:52, 98
C2 Changement du rendu Slate 5.5 → 5.8 (shader refactoré, gamma ou contraste des polices) qui éclaircirait un texte identique possible, non vérifié diffstat SlateElementPixelShader.usf (243 ajouts, 132 suppressions) ; aucune ligne gamma ou contraste trouvée
C3 La référence 5.5 « correcte » n'est pas comparable : autre build, résolution ou DPI, ou souvenir d'un rendu 4.27 où le texte par défaut était noir possible aucune capture 5.5 au dossier ; les sources 5.5 donnent les mêmes couleurs que 5.8
C4 SetRenderOpacity sur CharGen inférieur à 1 au moment de la saisie peu probable (agirait sur tout l'écran) :1186472-1186473, valeur non lue
exclu HintText, widget désactivé ou en lecture seule, nœud Blueprint Set WidgetStyle, style par défaut modifié, pinceaux modifiés — § 1, § 3.2-3.5

5. Hypothèse suivante proposée, et à quel niveau

H2 (N3, éditeur et builds disponibles après le gel STC) : « le même asset s'affiche différemment dans les builds 5.5 et 5.8 » (sépare C1+C3 de C2).

Test qui tranche (T1, lecture seule, sans modifier l'asset) :

  1. Lancer le build 5.5 (D:\Game\LifePlay_Build_5.5_DC4) puis le build 5.8 (…STB-JEU2_Development) dans la même résolution et la même échelle d'interface ; ouvrir CharGen, panneau Save Preset ; saisir « tee » ; capturer.
  2. Relever la couleur d'un pixel plein du texte et du fond, dans les deux captures.
  3. Lecture :
    • les deux clairs : C1 confirmée, C3 explique l'impression d'écart ; on applique le correctif ci-dessous ;
    • 5.5 foncé, 5.8 clair avec des valeurs d'asset identiques (§ 3.5) : C2 ; escalade N4 rendu (diff complet du shader et de FSlateRHIRenderingPolicy, CVar de gamma, et lecture au Widget Reflector, en PIE, du premier plan calculé de SEditableText).

Test du correctif (T2, après instantané Tools/Snapshot.ps1, éditeur ouvert) : appliquer les valeurs ci-dessous à FilenameEntry et à VarianceSpinBox, lancer en PIE, saisir un texte et provoquer un refus du nom (flash rouge) : le texte doit rester foncé avant, pendant et après le flash, avec et sans focus.

Correctif proposé (décision à l'utilisateur ; aucune modification du moteur) :

  • CharGen › FilenameEntry (EditableTextBox) : Style › Text Style › Color and Opacity = couleur spécifiée (R=0,G=0,B=0,A=1). Ce choix survit au graphe, qui recopie TextStyle (:1184408) ; il fixe aussi le premier plan peint par SEditableText et le hint, qui devient noir à 35 %. Alternative déconseillée : Style › Foreground Color. Le graphe remet FocusedForegroundColor à UseForeground après un refus (:1192122, :1192155), et c'est la couleur utilisée avec le focus (SEditableTextBox.cpp:371-374) : texte de nouveau clair pendant la saisie.
  • CharGen › VarianceSpinBox (SpinBox) : propriété Foreground Color (USpinBox::ForegroundColor, poussée par SpinBox.cpp:98) = (R=0,G=0,B=0,A=1).
  • Même paire de widgets dans StatMenu (FilenameEntry U5_assets_apres.txt:1417292, VarianceSpinBox :1417533) : probablement le même symptôme (estimé). À traiter dans le même lot si l'utilisateur le décide.
  • Voie : éditeur UMG ou LPEditWidget (-DryRun d'abord), avec instantané et trace CHG (CLAUDE.md du projet).

Constats

  • Constat annexe (établi sur le code, effet estimé) : UEditableTextBox::SetWidgetStyle en 5.8 passe au widget Slate l'adresse de son paramètre (MyEditableTextBlock->SetStyle(&InStyle), diff EditableTextBox.cpp, hunk @@ -375,4 +390,18 @@), alors que SEditableTextBox conserve ce pointeur (SEditableTextBox.cpp:115). Un appel C++ avec un temporaire laisserait un pointeur pendant. Sans effet ici : le Blueprint écrit le champ sans passer par ce setter (§ 3.4). À éviter dans tout code C++ futur du projet.
  • Budget : environ 60 appels d'outils, plafond de la rubrique 9 atteint. État de reprise : restent non faits la lecture du premier plan par défaut de FWidgetStyle (en-tête non localisé sous SlateCore/Public/Layout), le diff complet du pipeline de rendu Slate (C2), la valeur de SetRenderOpacity (C4), le pinceau de repli de la SpinBox sans Spinbox.png et les valeurs StatMenu. T1 est à faire en premier, après la levée du gel.