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) - Trois recherches (EditableTextBox/SpinBox, couleur du texte, régression 5.6/5.7/5.8, gamma Slate) : **aucune source** ne signale de changement du style par défaut ni de régression de couleur du texte entre 5.6 et 5.8. Ce qui a été trouvé : - fils anciens (UE4) sur `ForegroundColor` et la reconstruction du style : https://forums.unrealengine.com/t/374507, https://forums.unrealengine.com/t/379386 ; - UE-297198 (coloration des lots Slate, 5.5/5.6, corrigé en 5.7, déclenché par une commande de débogage), page https://issues.unrealengine.com/issue/UE-297198 inaccessible (HTTP 403) : non retenu ; - UE-366670 (double encodage gamma avec nDisplay, 5.6/5.7) : https://issues.unrealengine.com/issue/UE-366670 : sans objet ici (pas de nDisplay). - Conclusion : rien d'établi par le web. Passage à la vérification locale ciblée. ### 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 / /` (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.