LifePlay-Revival/Docs/Migration/etat/ST/STE/STE-P1-SPEC.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

316 lines
24 KiB
Markdown

Fiche STE-P1 — Niveau N3 — Modèle prévu (modèle de l'agent lp-impl) | utilisé claude-opus-5-5 — Agent lp-impl (A-IMPL-H) — Skills sk-protocol, ue-cpp-build, lp-build, lp-ue-compat, lp-mcp, lp-doc (gabarits)
# STE-P1-SPEC : poser le style d'une Text Box sans laisser Slate pointer sur une temporaire (ERR-088) (2026-10-10)
Cette SPEC est écrite en lecture seule. Sources lues : le moteur installé
`D:\Game\Launcher\Engine\UE_5.8\Engine\Source` (abrégé `UE58\`), le moteur 5.5 pour la garde (`UE55\`),
`Source\LifePlay` et le relevé `Saved\Logs\portage\U5_assets_apres.txt` (abrégé `relevé`). Livrable amont :
`STE-TXT-DIAG.md`. Les lignes de `ScriptCore.cpp` viennent de ce DIAG et n'ont pas été relues ici.
**Décision.** Je retiens le corps **(D)**, une variante de (B) :
`TextBox->WidgetStyle = Style; TextBox->SetWidgetStyle(TextBox->GetWidgetStyle());` en 5.8.
- En 5.5, sous la garde `UE_VERSION_OLDER_THAN(5, 8, 0)`, la fonction écrit seulement le membre, comme le faisait le
nœud Set.
- (A) est écarté : `SynchronizeProperties` réapplique tout le widget (§ 2.1, § 6.3).
- La fonction va dans une nouvelle bibliothèque, `ULPWidgetStyleLibrary`. `Build.cs` ne change pas.
- Les 4 nœuds sont situés dans un relevé 5.8 valable pour l'état courant : aucun dump ne manque (§ 2.4).
- **Aucune question bloquante.**
## 1. Objectif mesurable
- Ajouter une fonction C++ `BlueprintCallable` :
`ULPWidgetStyleLibrary::SetEditableTextBoxStyle(UEditableTextBox* TextBox, const FEditableTextBoxStyle& Style)`.
- Après l'appel, `SEditableTextBox::Style` vise `UEditableTextBox::WidgetStyle`. Ce membre vit autant que le widget
UMG.
- Slate ne reçoit jamais l'adresse du paramètre, même un instant.
- Rien d'autre n'est réappliqué : texte, liaisons, infobulle, visibilité restent tels quels.
- Remplacer les 4 nœuds `Set WidgetStyle` par un appel à cette fonction : CharGen `K2Node_VariableSet_1146` et `_1147`,
StatMenu `K2Node_VariableSet_1146` et `_1147`. Mêmes entrées, même enchaînement d'exécution.
- Mesures :
- build LifePlayEditor 5.8 : code 0, 0 erreur, 0 avertissement nouveau ;
- `compile_blueprint` sans avertissement sur CharGen et StatMenu ;
- 0 nœud Set `WidgetStyle` restant dans les deux EventGraph ;
- `CompileAllBlueprints` 0/0 ;
- en PIE : 10 refus de nom de suite sans plantage, flash rouge visible, texte noir lisible (critère 8 de la fiche).
## 2. Fichiers touchés, ordre
Ordre : (1) `Source\LifePlay\LPWidgetStyleLibrary.h` et (2) `.cpp`, créés par lp-impl. Puis (3) BUILD par
lp-builder. Puis (4) `Content\UI\StatMenu.uasset` et (5) `Content\UI\CharGen.uasset`, modifiés par l'orchestrateur
par MCP, sous BUILD-GO, une fois le module compilé et l'éditeur relancé. `LifePlay.Build.cs` ne change pas.
### 2.1 Choix du corps : (A), (B) ou (D)
| Critère | (A) membre + `SynchronizeProperties` | (B) `SetWidgetStyle(InStyle)` puis `SetWidgetStyle(GetWidgetStyle())` | **(D) retenu** : membre, puis `SetWidgetStyle(GetWidgetStyle())` |
|---|---|---|---|
| Pointeur gardé par Slate à la fin | `&WidgetStyle` (`EditableTextBox.cpp:133`) | `&WidgetStyle` (`:397`, `InStyle` = le membre) | `&WidgetStyle` (idem) |
| Slate vise le paramètre un instant | non | oui, entre les deux appels | **non** |
| Ce qui est réappliqué | tout le widget (§ 6.3) | `SetStyle` seul, deux fois (`:392-399`) | `SetStyle` seul, une fois |
| Auto-affectation `WidgetStyle = WidgetStyle` | non | oui | oui (sûre, § 6.2) |
| Compile en 5.5 | oui, sans garde | non : `SetWidgetStyle` et `GetWidgetStyle` n'existent pas en 5.5 | non, d'où la garde (§ 2.3) |
| Proximité du nœud Set actuel | faible (texte et liaisons réappliqués) | setter 5.8 sans le défaut | setter 5.8 sans le défaut : c'est le correctif P3 de `STE-TXT-DIAG.md` |
Raisons du choix :
- **(D) fait exactement ce que ferait le setter du moteur s'il passait `&WidgetStyle`** au lieu de `&InStyle`
(`EditableTextBox.cpp:394`, `:397`) :
- il copie le style dans le membre ;
- puis il appelle `SEditableTextBox::SetStyle` sur le membre (`SEditableTextBox.cpp:113-132`). Cet appel recalcule
les pointeurs de bordure, recopie le style de texte (`SEditableText.cpp:161-167`) et invalide la mise en page.
- C'est le traitement que le nœud Set reçoit aujourd'hui, défaut en moins.
- **(A) écarté.** `SynchronizeProperties` réapplique tout (§ 6.3). Les valeurs sont en principe identiques, mais deux
effets sont réels :
- **le texte est relu de force** (`SlateEditableTextLayout.cpp:273-284`). Avec le focus et une liaison `Text`, le
texte saisi peut être remplacé (`:4343`, `:4361`), le curseur peut sauter en fin (`:4364-4367`) et `OnTextChanged`
peut être émis (`:4370-4373`) ;
- **l'infobulle est recréée** (`Widget.cpp:1506-1526`).
- lp-mcp § 4 (ERR-057) donne la même leçon : les liaisons et les `OnValueChanged` se déclenchent pendant
`SynchronizeProperties`.
- **(D) plutôt que (B).** L'effet final est le même. (D) ne donne pas à Slate l'adresse du paramètre et fait un
`SetStyle` de moins. L'adresse du paramètre est une référence valable le temps de l'appel seulement
(`P_GET_STRUCT_REF` → `PARAM_PASSED_BY_REF`, `ScriptMacros.h:73`).
- **Aliasing, demandé par la fiche pour (B), qui vaut aussi pour (D).** `SetWidgetStyle(GetWidgetStyle())` passe à
`WidgetStyle = InStyle` une référence au membre lui-même (`EditableTextBox.h:263`, `.cpp:401-404`).
- L'opérateur de copie est celui par défaut (`SlateTypes.h:1024`, `SlateTypes.cpp:310`). Il copie membre à membre ;
détail au § 6.2.
### 2.2 Emplacement
Nouvelle bibliothèque `Source\LifePlay\LPWidgetStyleLibrary.h/.cpp`, `ULPWidgetStyleLibrary : UBlueprintFunctionLibrary`.
- `ULPModSettingsLibrary` ne convient pas : elle porte la sélection de mods de l'écran titre (lot UI15,
`LPModSettingsLibrary.h:1-8`, catégorie `LifePlay|Mods`, `:23`). C'est un autre domaine.
- Le modèle suivi est `ULPMeshCompat` (`LPMeshCompat.h:1-32`) : une fonction de bibliothèque qui contourne, pour les
Blueprints, un comportement du moteur.
- Les dépendances sont déjà là : `Slate`, `SlateCore`, `UMG` en privé (`LifePlay.Build.cs:38`). L'en-tête n'est
inclus par aucun autre module. `LifePlayEditorTools` n'inclut que `LPAssetRegistryHelpers.h`
(`LifePlay.Build.cs:11-15`). Les dépendances privées suffisent donc, et `Build.cs` ne change pas.
- Statut : contournement d'un défaut du moteur, à garder comme les correctifs de compatibilité (lp-ue-compat § 4) tant
que le moteur installé garde `SetStyle(&InStyle)` (`EditableTextBox.cpp:397`).
### 2.3 Code à écrire (IMPL lp-impl)
En-tête : il inclut `Styling/SlateTypes.h` (SlateCore). Le thunk généré par UHT construit un
`FEditableTextBoxStyle` local et a donc besoin du type complet. `UEditableTextBox` est seulement prédéclaré.
```cpp
UFUNCTION(BlueprintCallable, Category = "LifePlay|UI", meta = (DisplayName = "Set Widget Style (Text Box, LP)"))
static void SetEditableTextBoxStyle(UEditableTextBox* TextBox, const FEditableTextBoxStyle& Style);
```
Corps :
```cpp
if (!IsValid(TextBox)) { UE_LOG(LogLifePlay, Verbose, ...); return; }
TextBox->WidgetStyle = Style; // membre public, non déprécié (EditableTextBox.h:50-52)
#if !UE_VERSION_OLDER_THAN(5, 8, 0)
TextBox->SetWidgetStyle(TextBox->GetWidgetStyle()); // auto-affectation, puis SetStyle(&WidgetStyle)
#endif
// UE 5.5 : pas de setter natif ; le nœud Set écrivait le membre seul, et Slate visait déjà &WidgetStyle.
```
- Includes du `.cpp` : `LPWidgetStyleLibrary.h` d'abord, puis `Components/EditableTextBox.h`,
`Misc/EngineVersionComparison.h` et `LifePlay.h` (pour `LogLifePlay`, comme `LPMeshCompat.cpp:3-7`).
- Fichiers en ASCII et fins de ligne LF, comme les voisins (`file LPMeshCompat.* LPModSettingsLibrary.*` : « ASCII
text », sans CRLF). Commentaires en français sans accents.
- Branche 5.5, choisie pour rester fidèle à 5.5 :
- en 5.5, la propriété n'a pas de `Setter` (`UE55\…\EditableTextBox.h:48`). Le nœud Set écrivait donc le membre ;
- Slate gardait l'adresse du membre, donnée par `SynchronizeProperties` (`UE55\…\EditableTextBox.cpp:129`) ;
- la couleur de fond est relue à chaque image (`DetermineBackgroundColor`, `SEditableTextBox.cpp:348-352` en 5.8 ;
même mécanisme estimé en 5.5) ;
- la branche 5.5 ne fait donc rien de plus que le nœud d'origine.
### 2.4 Graphe : les 4 substitutions (orchestrateur, MCP, BUILD-GO)
**Source : le relevé.** CharGen `:1195439-1195460`, StatMenu `:1415089-1415112`.
**Le relevé vaut pour l'état courant (établi) :**
- CharGen : les nœuds `_1146`, `_1147`, `MakeStruct_62` et `_64`, `IfThenElse_366` et `VariableGet_2400` sont
identiques octet pour octet entre HEAD et l'état STE-TXT (`STE-TXT-DIAG.md:81-85`).
- StatMenu : `md5sum` = `4fa5d803b35bcaa47aab3c0a854b1ad8`, identique à `git show HEAD:Content/UI/StatMenu.uasset`.
Le fichier date du 2026-10-08 20:28:43, le relevé du 20:31:01. Dernier commit sur StatMenu : `809102a` (U5).
`git status` : StatMenu n'est pas modifié.
- **Aucun dump ne manque.** Confirmation facultative, sous BUILD-GO, éditeur fermé :
`.\Tools\RunCommandlet.ps1 -Lot STE-D -Commandlet LPDumpFunction -Args '-BP=StatMenu -Fn=EventGraph -Pins -Exec'`
(même commande avec `-BP=CharGen`).
| Asset | Nœud à supprimer | Position (X, Y) | `execute` ← | `then` → | Cible `TextBox` ← | `Style` ← | `Output_Get` |
|---|---|---|---|---|---|---|---|
| CharGen | `K2Node_VariableSet_1147` (rouge) | (-2400, 13024) | `K2Node_IfThenElse_366.else` | `K2Node_CallFunction_5310.execute` (Delay) | `K2Node_VariableGet_2400.FilenameEntry` | `K2Node_MakeStruct_62.EditableTextBoxStyle` | non relié |
| CharGen | `K2Node_VariableSet_1146` (blanc) | (-1808, 13024) | `K2Node_CallFunction_5310.then` | aucun (fin de chaîne) | `K2Node_VariableGet_2400.FilenameEntry` | `K2Node_MakeStruct_64.EditableTextBoxStyle` | non relié |
| StatMenu | `K2Node_VariableSet_1147` (rouge) | (496, 2592) | `K2Node_IfThenElse_366.else` | `K2Node_CallFunction_5310.execute` | `K2Node_VariableGet_204.FilenameEntry` | `K2Node_MakeStruct_62.EditableTextBoxStyle` | non relié |
| StatMenu | `K2Node_VariableSet_1146` (blanc) | (1088, 2592) | `K2Node_CallFunction_5310.then` | aucun | `K2Node_VariableGet_204.FilenameEntry` | `K2Node_MakeStruct_64.EditableTextBoxStyle` | non relié |
Sources du tableau : relevé `:1195442-1195449`, `:1195453-1195460`, `:1415092-1415100`, `:1415104-1415112`. Aucune
broche `Output_Get` n'est reliée : rien en aval ne lit la valeur du Set.
Procédure, pour chaque asset (lp-mcp § 1 règle 3 et § 3) :
1. `git status --short -- Content/UI/StatMenu.uasset` doit être vide. Puis
`.\Tools\Snapshot.ps1 -Lot STE-P1 -Path Content\UI\StatMenu.uasset` (fiche, rubrique 4). Pour CharGen, voir R8 et Q2.
2. `load_asset` (`/Game/UI/<Asset>`). Puis `find_node_types {graph, type_id_filter:"SetEditableTextBoxStyle"}` ; à
défaut, filtrer sur `Set Widget Style (Text Box, LP)`. Noter le `type_id` (catégorie `LifePlay|UI`).
3. `get_node_infos` du nœud Set : vérifier que ses liens sont ceux du tableau. Écart = arrêt et rapport (fiche,
rubrique 9).
4. `create_node` à la position du nœud Set. Lire ensuite les indices des broches par `get_node_infos` : `execute`,
`then`, `TextBox`, `Style`. La broche `self` de la bibliothèque est cachée.
5. Relier d'abord les broches qui acceptent plusieurs liens :
- `FilenameEntry` → `TextBox` et `MakeStruct_xx.EditableTextBoxStyle` → `Style` (sorties de données) ;
- pour `_1147` seulement : `then` → `K2Node_CallFunction_5310.execute` (entrée d'exécution).
6. `delete_node` de l'ancien Set. Cela libère `IfThenElse_366.else` ou `CallFunction_5310.then`, des sorties
d'exécution à lien unique.
7. Relier `execute` ← `K2Node_IfThenElse_366.else` (pour `_1147`) ou ← `K2Node_CallFunction_5310.then` (pour `_1146`).
8. Relire le nœud par `get_node_infos` : 4 liens pour la copie de `_1147`, 3 pour celle de `_1146`. Puis
`find_nodes {graph, title}` sur le titre du nœud Set : 0 dans l'EventGraph.
9. `compile_blueprint`, avertissements traités comme des erreurs, puis `hyper_blueprint_debug_inspect` : 0 diagnostic.
Puis `save_assets {asset_paths:["/Game/UI/CharGen","/Game/UI/StatMenu"]}`, ces deux assets seuls.
## 3. Repli
- C++ : `.\Tools\Restore.ps1 -Lot STE-P1`. Les deux fichiers sont notés `Existed=False` et seront déplacés, pas
supprimés. Le graphe doit être restauré en même temps, sinon les nœuds d'appel deviennent orphelins.
- StatMenu : l'instantané STE-P1 de l'étape 1, ou git (`HEAD` = `4fa5d803…`), éditeur fermé.
- CharGen : l'instantané STE-TXT est l'état **d'avant** STE-TXT (HEAD, `21ab367c…`). Le restaurer défait aussi
STE-TXT. Voir R8 et Q2.
- Si la VAL montre un défaut d'affichage avec (D) : le corps (A) s'écrit dans le même fichier, sans toucher au graphe.
Ses risques sont au § 2.1.
- Si le module ne compile pas : lp-builder rapporte, sans rien corriger (boucle U3, lp-build § 5).
## 4. Risques R#, questions Q#
- **R1 (estimé, faible) : auto-affectation.**
- Les types qui portent de la mémoire sont sûrs, et c'est établi : `TArray` et `FString` (`Array.h:1012-1020`, test
`this != &Other`), `TSharedPtr` (`SharedPointer.h:966-971`, copie puis échange).
- Aucun `operator=` n'est déclaré dans `SlateBrush.h`, `SlateFontInfo.h`, `SlateColor.h`, `SlateWidgetStyle.h`, ni
dans `SlateTypes.h` en dehors de `:1024` (Grep `operator=\s*\(`). Les autres membres utilisent donc la copie
implicite.
- Conséquence si c'était faux : un style abîmé, visible en VAL. Repli (A).
- **R2 (établi, sans effet nouveau) : `SetStyle` recopie le style de texte et relance la mise en page**
(`SEditableTextBox.cpp:130-131`, `SEditableText.cpp:161-167`). Le nœud Set le fait déjà aujourd'hui.
- **R3 (incertain) : d'autres appelants du setter existent peut-être.**
- C++ du jeu : Grep `UEditableTextBox|SetWidgetStyle` sur `Source\LifePlay` donne 5 lignes, toutes sur d'autres
widgets, toutes sûres :
- `USlider` : `LPColorGradeSubsystem.cpp:201`, `LPVideoQualitySubsystem.cpp:395`, `LPSettingsSubsystem.cpp:415` ;
- `UCheckBox` : `LPSettingsSubsystem.cpp:371` ;
- `USpinBox` : `LPSettingsSubsystem.cpp:390`.
Leurs setters 5.8 passent `&WidgetStyle` (`Slider.cpp:215`, `CheckBox.cpp:244`) ou invalident le style
(`SpinBox.cpp:154`). Seul `UEditableTextBox` passe `&InStyle`. Aucun `UEditableTextBox` dans `Source`.
- Blueprints du relevé : 4 nœuds en tout (`STE-TXT-DIAG.md:121-123`).
- Les mods (`Content\Modules`) n'ont pas été cherchés : un mod qui pose `WidgetStyle` sur une Text Box garde le
défaut. Ce point sort du périmètre et va aux Constats.
- **R4 (établi) : la branche 5.5 ne sera pas compilée dans ce lot**, faute de build 5.5 dans la fiche. Elle se limite à
une affectation de membre public : `UE55\…\EditableTextBox.h:45-49`, section `public` ouverte à `:45`.
- **R5 (constaté) : les deux nœuds Set de StatMenu portent `ErrorType = 1`** (relevé `:1415094`, `:1415106`).
- `1` vaut `EMessageSeverity::Error` (`TokenizedMessage.h:23`).
- `ClearCompilerMessage` ne remet pas `ErrorType` à zéro (`EdGraphNode.h:398`, `:667-670`) : c'est probablement un
drapeau ancien (estimé).
- Les nœuds sont supprimés, mais l'orchestrateur relit les diagnostics de StatMenu à l'étape 9.
- **R6 (établi par la fiche) : le plantage n'arrive pas à chaque fois.** Seule la répétition le prouve absent (T3 :
10 refus de suite).
- **R7 (incertain) : `type_id` localisé.** Trouver le nœud par `find_node_types`, ne pas le deviner (lp-mcp § 3).
- **R8 (établi) : retour arrière de CharGen.** Aucun instantané ne garde l'état STE-TXT (`9669B103…`) : seul
l'instantané STE-TXT existe, et il garde HEAD. Pour défaire STE-P1 seul, il faut prendre
`.\Tools\Snapshot.ps1 -Lot STE-P1 -Path Content\UI\CharGen.uasset` avant l'écriture MCP. Voir Q2.
- **R9 (estimé) : `UEditableTextBox` est `MinimalAPI`** (`EditableTextBox.h:26`).
- Le code généré du jeu référence ses informations de type. MinimalAPI exporte précisément ces informations, et les
membres utilisés sont exportés (`UMG_API`, `:261`, `:263`).
- L'accès direct à `WidgetStyle` ne demande aucun export.
- Le build le confirmera, à l'édition de liens.
- **R10 (estimé) : si Epic corrige la ligne `:397` dans une version future, (D) reste correct** : l'appel donnerait le
même résultat.
- **Q1 (non bloquante) : faut-il garder la branche 5.5 ?** La règle lp-ue-compat § 1 vaut pour U0-U8. Si la copie 5.5
ne reçoit plus de code, la garde peut être retirée plus tard. Je la garde par défaut.
- **Q2 (non bloquante, pour l'orchestrateur) : prendre l'instantané de CharGen sous STE-P1 (R8) ?** Cela s'écarte de la
rubrique 4 de la fiche, qui dit « CharGen : instantané STE-TXT déjà pris ».
## 5. Interdits
- Ne pas modifier le moteur. Ne pas modifier `Build.cs`. Ne rien écrire hors des deux fichiers C++ et des livrables
(lp-impl). Ne rien écrire hors de CharGen et StatMenu (orchestrateur).
- Pas de `SynchronizeProperties` dans la branche 5.8 (§ 2.1). Pas de `PRAGMA_DISABLE_DEPRECATION_WARNINGS`.
- Pas de « modernisation » des fichiers de compatibilité (`LPStringCompat`, `LPMeshCompat`, `LPNavigationHelpers`…).
- Graphe : ne toucher ni aux `MakeStruct_62` à `_65`, ni au Delay `CallFunction_5310`, ni à `IfThenElse_366`. Aucun
nœud ajouté hors des 4 appels.
- Pas de compilation ni d'éditeur par lp-impl. Aucune commande git qui écrit (sk-protocol § 2).
## 6. Valeurs moteur lues dans le moteur installé
### 6.1 Le défaut et le correctif (5.8)
- `UE58\Runtime\UMG\Public\Components\EditableTextBox.h` :
- `:26` : `UCLASS(..., MinimalAPI)` ;
- `:39` et `:54` : `Text` et `HintText` sont sous `UE_DEPRECATED(5.1, ...)` ;
- `:50-52` : `WidgetStyle`, `UPROPERTY(..., Getter, Setter, ...)`, **sans `UE_DEPRECATED`**. L'accès direct ne
produit donc pas de C4996 ;
- `:261` : `UMG_API void SetWidgetStyle(const FEditableTextBoxStyle&)`, sans `UFUNCTION` ;
- `:263` : `UMG_API const FEditableTextBoxStyle& GetWidgetStyle() const` ;
- `:270` : `UMG_API virtual void SynchronizeProperties()`, public.
- `UE58\Runtime\UMG\Private\Components\EditableTextBox.cpp` :
- `:97` : `RebuildWidget` → `.Style(&WidgetStyle)` ;
- `:121-151` : `SynchronizeProperties`, avec `:133` `SetStyle(&WidgetStyle)` ;
- `:392-399` : `SetWidgetStyle` : `:394` `WidgetStyle = InStyle`, `:397` `MyEditableTextBlock->SetStyle(&InStyle)`
(le défaut) ;
- `:401-404` : `GetWidgetStyle` renvoie le membre.
- `UE58\Runtime\Slate\Private\Widgets\Input\SEditableTextBox.cpp` :
- `:45-47` : bordure, fond et avant-plan sont liés à `Determine*` ;
- `:65` : la police est liée à `DetermineFont` ;
- `:113-132` : `SetStyle` : `Style = InStyle` (`:115`), pointeurs `BorderImage*` dans le style (`:125-128`),
`SetTextBlockStyle(&Style->TextStyle)` (`:130`), `Invalidate(Layout)` (`:131`). Pas de sortie anticipée si le
pointeur ne change pas ;
- `:342-346` : `DetermineFont` lit `Style->TextStyle.Font` ;
- `:348-352` : `DetermineBackgroundColor` lit `Style->BackgroundColor`.
- `UE58\Runtime\Slate\Private\Widgets\Input\SEditableText.cpp:161-167` : `SetTextBlockStyle` **copie** le style
(`SetTextStyle(*InTextStyle)`) et ne garde pas de pointeur.
- `UE58\Runtime\CoreUObject\Public\UObject\ScriptMacros.h:73` :
`P_GET_STRUCT_REF` = `PARAM_PASSED_BY_REF`. Le paramètre `const&` est une référence à durée d'appel.
- Repris de `STE-TXT-DIAG.md` § 3.4, non relu ici : `ScriptCore.cpp:2906-2929`. La VM appelle le setter avec une
temporaire, puis la détruit.
### 6.2 Copie et auto-affectation
- `UE58\Runtime\SlateCore\Public\Styling\SlateTypes.h:1018-1025` : `FEditableTextBoxStyle` déclare un constructeur de
copie, un `operator=` et un destructeur, tous `SLATECORE_API`.
- `UE58\Runtime\SlateCore\Private\Styling\SlateTypes.cpp:309-312` : ils sont `= default`, placés entre
`PRAGMA_DISABLE/ENABLE_DEPRECATION_WARNINGS`.
- Ils sont définis hors ligne. Le membre `Font_DEPRECATED` n'est donc pas touché dans l'unité du jeu : pas de C4996.
- `UE58\Runtime\Core\Public\Containers\Array.h:1012-1020` : `TArray::operator=` teste `this != &Other`.
- `UE58\Runtime\Core\Public\Templates\SharedPointer.h:966-971` : `TSharedPtr::operator=` copie, puis échange.
### 6.3 Ce que (A) réapplique (raison de l'écarter)
- `UE58\Runtime\UMG\Private\Components\Widget.cpp:1444-1541` (`UWidget::SynchronizeProperties`) :
- données d'accessibilité (`:1451`) ;
- curseur (`:1477-1480`) ;
- `SetEnabled` et `SetVisibility` par liaison (`:1482-1483`) ;
- découpe (`:1493`), aimantation au pixel (`:1496`), direction (`:1497`), `ForceVolatile` (`:1499`) ;
- opacité (`:1501`), transformée (`:1503-1504`) ;
- **infobulle recréée** (`:1506-1526`) ;
- accessibilité (`:1528-1539`).
- `EditableTextBox.cpp:130-150` : `SetStyle`, **`SetText(liaison)`**, `SetHintText(liaison)`, `IsReadOnly`,
`IsPassword`, largeur minimale, comportements de focus et de validation, menu contextuel, clavier virtuel,
justification, débordement, chargement des polices, `ShapedTextOptions`.
- `UE58\Runtime\Slate\Private\Widgets\Text\SlateEditableTextLayout.cpp` :
- `:273-284` : `SetText` force la relecture (`bForceBoundTextReview = true`) ;
- `:4337-4377` : `OnBoundTextChanged`. Une relecture forcée passe outre le focus (`:4343`). Si le texte lié diffère
du texte affiché, il le remplace (`:4354`, `:4361`). Avec le focus, le curseur saute en fin (`:4364-4367`), et
`OnTextChanged` est émis si le texte a changé (`:4370-4373`).
- Conclusion : sans liaison `Text`, l'effet est nul (le membre `Text` suit la saisie, `EditableTextBox.cpp:406-413`).
Avec une liaison, le texte saisi peut être remplacé. Cette surface est inutile ici.
### 6.4 Garde de version
- `UE_VERSION_OLDER_THAN` : `UE58\Runtime\Core\Public\Misc\EngineVersionComparison.h:24` et `UE55\…:18`.
- 5.5 :
- `UE55\Runtime\UMG\Public\Components\EditableTextBox.h:45-49` : section `public`, `WidgetStyle` sans `Setter`
(`:48`) ;
- `:256` : `SynchronizeProperties` public (section `public` de `:148` à `:268`) ;
- Grep `WidgetStyle` sur cet en-tête : 1 ligne (`:49`), donc ni `SetWidgetStyle` ni `GetWidgetStyle` ;
- `UE55\…\EditableTextBox.cpp:117-129` : `SynchronizeProperties` → `SetStyle(&WidgetStyle)` ;
- Grep `void UEditableTextBox::SetWidgetStyle` : 0.
## 7. Critères de VAL (commande → attendu)
1. `.\Tools\Build.ps1 -Lot STE-P1` (lp-builder, éditeur fermé) :
- code 0 ;
- ligne `Using Visual Studio 14.50.35739 toolchain (…\MSVC\14.50.35717)` ;
- unités `LPWidgetStyleLibrary.cpp` et `LPWidgetStyleLibrary.gen.cpp`, ou leur unité unity, compilées ;
`UnrealEditor-LifePlay.dll` liée ;
- 0 `error`, 0 `warning C4996` ;
- « autres lignes » = 20 (HyperAIStudio, lp-build § 7).
2. Diff (`git status --short -- Source`) : exactement 2 fichiers nouveaux (`??`), ASCII, fins de ligne LF
(`file Source/LifePlay/LPWidgetStyleLibrary.*`), aucun autre fichier de `Source` touché.
3. Graphe, après MCP :
- `find_nodes` du titre du nœud Set `WidgetStyle` dans `CharGen:EventGraph` et `StatMenu:EventGraph` → 0 ;
- `get_node_infos` des 4 nouveaux nœuds → liens du § 2.4 ;
- `compile_blueprint` → 0 avertissement ; `hyper_blueprint_debug_inspect` → 0 diagnostic.
4. `CompileAllBlueprints` (commandlet, éditeur fermé) → 0 erreur, 0 avertissement.
5. PIE avec l'utilisateur, dans CharGen, panneau Save Preset, nom vidé :
- 10 refus de suite sans plantage ;
- flash rouge puis retour au blanc ;
- texte noir lisible avant, pendant et après, avec et sans focus dans le champ.
Même essai dans StatMenu si un refus y est accessible.
6. Contrôle de non-régression du texte : pendant le Delay, cliquer dans le champ et taper. Le texte saisi est conservé
et le curseur ne saute pas, comme avant.
7. Contrôle optionnel : `Saved\Crashes` ne contient aucun nouveau rapport `FCachedTypefaceData` après l'essai
(Grep `FCachedTypefaceData::FCachedTypefaceData`, 1 fichier attendu, l'ancien).
Fichiers à commiter (dépôt du jeu, branche `ue5.8`, par le gardien) : `A Docs/Migration/etat/ST/STE/STE-P1-SPEC.md`.
Tours : 14 / 60 (partie SPEC ; total SPEC et IMPL dans `STE-P1-IMPL.md`)