197 lines
16 KiB
Markdown
197 lines
16 KiB
Markdown
|
|
# VQ0-CART — Cartographie des réglages classés Video dans Settings
|
||
|
|
|
||
|
|
**Fiche :** VQ0-T1
|
||
|
|
**Rôle :** A-CART
|
||
|
|
**Date :** 07 octobre 2026
|
||
|
|
**Workspace :** `d:\Game\LifePlay-master 5.5`
|
||
|
|
**Statut :** Validé — cartographie complète
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. Contexte et Objectifs
|
||
|
|
|
||
|
|
Dans le cadre du chantier **VQ0** (Refonte et rationalisation des réglages Vidéo / Graphismes), l'objectif de cette cartographie est d'auditer et répertorier l'ensemble des éléments d'interface qui se retrouvent classés sous l'onglet **Video** du panneau des réglages (`MainMenu.SettingsScrollBox`).
|
||
|
|
|
||
|
|
Le système actuel repose sur deux mécanismes complémentaires :
|
||
|
|
1. `ULPSettingsSubsystem` (introduit en **CHG-158**, ajusté en **CHG-160**) : organise les widgets existants du Blueprint `MainMenu` en onglets dynamiques (`General`, `Audio`, `Video`, `Keyboard`, `Lewd`, `Misc`) sans modifier les Blueprints.
|
||
|
|
2. `ULPColorGradeSubsystem` (introduit en **CHG-161**, stylisé en **CHG-163**) : injecte dynamiquement des curseurs de colorimétrie post-traitement (`LPColor*`) au bas de la liste `SettingsScrollBox`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. Analyse de `LPSettingsSubsystem.cpp`
|
||
|
|
|
||
|
|
### 2.1 Méthode de classification : `CategoryOf`
|
||
|
|
|
||
|
|
La fonction `LPSettingsUi::CategoryOf(const UWidget* Widget)` inspecte chaque enfant de `SettingsScrollBox` pour déterminer son onglet de destination.
|
||
|
|
|
||
|
|
L'aiguillage vers l'onglet **Video** (`TabVideo = 2`) s'opère selon deux règles successives :
|
||
|
|
|
||
|
|
1. **Règle explicite par préfixe :**
|
||
|
|
```cpp
|
||
|
|
if (Widget && Widget->GetName().StartsWith(TEXT("LPColor")))
|
||
|
|
{
|
||
|
|
return TabVideo;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
Tout widget dont le nom C++/UMG commence par `LPColor` est immédiatement dirigé vers `TabVideo`.
|
||
|
|
|
||
|
|
2. **Règle textuelle par mots-clés (`RowText`) :**
|
||
|
|
Si le widget ne commence pas par `LPColor` et n'a pas été capturé par les mots-clés Audio (`volume`, `audio`, `sound`, `music`), `CategoryOf` convertit le texte extrait en minuscules et teste les motifs suivants :
|
||
|
|
```cpp
|
||
|
|
if (Text.Contains(TEXT("fps")) || Text.Contains(TEXT("screen")) || Text.Contains(TEXT("shadow")) || Text.Contains(TEXT("quality"))
|
||
|
|
|| Text.Contains(TEXT("fullscreen")) || Text.Contains(TEXT("window")) || Text.Contains(TEXT("toon")) || Text.Contains(TEXT("depth of field"))
|
||
|
|
|| Text.Contains(TEXT("censor")) || Text.Contains(TEXT("morph")) || Text.Contains(TEXT("dog")) || Text.Contains(TEXT("jiggle"))
|
||
|
|
|| Text.Contains(TEXT("resolution")) || Text.Contains(TEXT("vsync")) || Text.Contains(TEXT("brightness")))
|
||
|
|
{
|
||
|
|
return TabVideo;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2.2 Extraction du texte : `RowText`
|
||
|
|
|
||
|
|
La fonction `RowText(const UWidget* Widget)` cumule tout le texte associé à la ligne :
|
||
|
|
- La propriété réflexive `SettingText` (`FTextProperty`), utilisée par les UserWidgets `SettingSlider` et `SettingCheckbox`.
|
||
|
|
- L'infobulle native (`Widget->GetToolTipText()`).
|
||
|
|
- Une exploration récursive en profondeur de tous les sous-widgets (`UTextBlock::GetText()`, `UUserWidget::GetRootWidget()`, `UPanelWidget::GetChildAt()`).
|
||
|
|
|
||
|
|
### 2.3 Mécanisme `EnsureTabs` et `ApplyRows`
|
||
|
|
|
||
|
|
- **`EnsureTabs(UScrollBox* Scroll)`** :
|
||
|
|
- Identifie le parent `UCanvasPanel` de `SettingsScrollBox`.
|
||
|
|
- Crée la barre d'onglets `LPSettingsTabs` (`UHorizontalBox`) au-dessus de la boîte de défilement (décalage Y de -46 px).
|
||
|
|
- Crée les boutons d'onglets : `General`, `Audio`, `Video`, `Keyboard`, `Lewd`, `Misc`.
|
||
|
|
- Instancie `LPSettingsKeyboard` (`UNativeWidgetHost`) pour héberger la page dédiée au remappage clavier (`ULPKeyboardSubsystem`).
|
||
|
|
- Active l'onglet initial `TabGeneral` (0) et exécute `ApplyRows()`.
|
||
|
|
|
||
|
|
- **`ApplyRows()`** :
|
||
|
|
- Met à jour la couleur du texte des onglets (doré `(1.0, 0.92, 0.45)` pour l'onglet actif, gris clair `(0.75, 0.75, 0.75)` pour les inactifs).
|
||
|
|
- Parcourt tous les enfants directs de `SettingsScrollBox` :
|
||
|
|
- Masque le widget legacy `LPKeyboardRow` (`Visibility = Collapsed`).
|
||
|
|
- Applique `RenameVolumes` (renomme `Volume - Sex` en `Volume - Dialogue` et `Volume - Sex Moans` en `Volume - SFX`).
|
||
|
|
- Évalue `Category = CategoryOf(Child)`.
|
||
|
|
- Si `Category < 0` (ex. bouton `BackButton`), le widget reste visible en permanence.
|
||
|
|
- Si `Category == ActiveTab` (et que l'on n'est pas sur l'onglet Keyboard), le widget est rendu **Visible**, sinon **Collapsed**.
|
||
|
|
- Si l'onglet actif est `TabKeyboard`, la liste `SettingsScrollBox` n'affiche aucune ligne métier et l'hôte `KeyboardHost` affiche l'arbre Slate natif de `ULPKeyboardSubsystem`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. Analyse de `LPColorGradeSubsystem`
|
||
|
|
|
||
|
|
`ULPColorGradeSubsystem` est un `UGameInstanceSubsystem` qui gère un volume de post-traitement global non borné (`APostProcessVolume`, `bUnbound = true`, priorité 100.0).
|
||
|
|
|
||
|
|
Dans `EnsureControls()`, il vérifie la présence de `LPColorBrightness` dans `SettingsScrollBox`. S'il est absent, il injecte 5 lignes créées dynamiquement en C++ via `AddRow` :
|
||
|
|
|
||
|
|
| Nom widget | Libellé | Type | Min | Max | Pas | Défaut | Handler C++ | Info-bulle / Rôle | Propriété FPostProcessSettings |
|
||
|
|
|---|---|---|---|---|---|---|---|---|---|
|
||
|
|
| `LPColorBrightness` | Brightness | Slider + Readout | -2.0 | 2.0 | 0.05 | 0.0 | `OnBrightnessChanged` | Exposure compensation. -1 is twice as dark, +1 is twice as bright. | `AutoExposureBias` |
|
||
|
|
| `LPColorSaturation` | Saturation | Slider + Readout | 0.0 | 2.0 | 0.05 | 1.0 | `OnSaturationChanged` | Color intensity. 1 is unchanged, 0 is gray. | `ColorSaturation` (XYZ) |
|
||
|
|
| `LPColorContrast` | Contrast | Slider + Readout | 0.0 | 2.0 | 0.05 | 1.0 | `OnContrastChanged` | Range between light and dark. 1 is unchanged. | `ColorContrast` (XYZ) |
|
||
|
|
| `LPColorWhiteBalance` | White Balance | Slider + Readout | 1500 | 15000 | 50.0 | 6500.0 | `OnWhiteBalanceChanged` | Color temperature in kelvin. 6500 is daylight. | `WhiteTemp` (`TEMP_WhiteBalance`) |
|
||
|
|
| `LPColorTint` | Tint | Slider + Readout | -1.0 | 1.0 | 0.01 | 0.0 | `OnTintChanged` | Magenta to green. 0 is unchanged. | `WhiteTint` |
|
||
|
|
|
||
|
|
### Caractéristiques d'injection :
|
||
|
|
- **Insertion :** `Scroll->AddChild(Row)` — les widgets sont systématiquement ajoutés **à la fin** de la liste d'enfants de `SettingsScrollBox`.
|
||
|
|
- **Héritage du style :** `LPColorGrade::FindLook` inspecte les lignes existantes pour copier la police (`Regular 20` avec contour noir de 2 px) et le style Slate du curseur (`FSliderStyle` copié depuis `SettingSlider`).
|
||
|
|
- **Persistance :** Écrit et relit `Saved/Config/Windows/LPColorGrade.ini` (section `[LPColorGrade]`), sans aucune dépendance envers `GameSettings.sav`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. Relevé historique et analyse des modifications (Docs / Journal)
|
||
|
|
|
||
|
|
L'analyse de `Docs/Migration/Journal_Modifications.md` et des historiques de commits montre la genèse des réglages :
|
||
|
|
- **CHG-156 (2026-10-05) :** Ajout initial d'un bouton Clavier directement dans `SettingsScrollBox`.
|
||
|
|
- **CHG-158 (2026-10-05) :** Séparation en 6 onglets au-dessus de `SettingsScrollBox` via `LPSettingsSubsystem` ; les lignes existantes du Blueprint sont classées selon leur texte par `CategoryOf`.
|
||
|
|
- **CHG-159 (2026-10-05) :** Bouton `Settings` réintégré au menu titre sous `Mod Manager` via `LPSettingsTitleButton`.
|
||
|
|
- **CHG-160 (2026-10-05) :** Ordre final des onglets (`General`, `Audio`, `Video`, `Keyboard`, `Lewd`, `Misc`), renommage des libellés audio crus.
|
||
|
|
- **CHG-161 (2026-10-05) :** `LPColorGradeSubsystem` : correction de l'image brûlée/trop blanche via Color Grading natif Unreal (exposition et balance des blancs) plutôt qu'un pipeline externe.
|
||
|
|
- **CHG-163 (2026-10-05) :** Harmonisation graphique des curseurs et polices sur `SettingSlider`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. Cartographie exhaustive des lignes classées "Video"
|
||
|
|
|
||
|
|
L'inspection directe des binaires d'assets (`MainMenu.uasset`, `SettingSlider.uasset`, `SettingCheckbox.uasset`, `GameSettings.uasset`) permet d'établir la liste complète des widgets dirigés vers l'onglet Video :
|
||
|
|
|
||
|
|
| Nom widget UMG | Libellé affiché (`SettingText` / Text) | Type UMG | Source | Mot-clé `CategoryOf` | Rôle technique / Variable sous-jacente |
|
||
|
|
|---|---|---|---|---|---|
|
||
|
|
| `FullscreenButton` (avec `FullscreenText`) | `Fullscreen` (bascule `Borderless Window` / `Windowed`) | `UButton` + `UTextBlock` | BP (`MainMenu`) | `fullscreen`, `window` | Bascule le mode fenêtré (`EWindowMode`, `GameUserSettings`) |
|
||
|
|
| `PostProcessAAQuality` | `AA Quality` | `SettingSlider_C` | BP (`MainMenu`) | `quality` | Qualité de l'anti-aliasing (`r.PostProcessAAQuality`) |
|
||
|
|
| `PostProcessQuality` | `PP Quality (FPS intensive)` | `SettingSlider_C` | BP (`MainMenu`) | `quality`, `fps`, `depth of field` (tooltip) | Évolutivité post-traitement globale (`sg.PostProcessQuality`) |
|
||
|
|
| `ScreenPercentage` | `Screen Percentage` | `SettingSlider_C` | BP (`MainMenu`) | `screen`, `resolution` (tooltip) | Échelle de résolution 3D interne (`r.ScreenPercentage`) |
|
||
|
|
| `ShadowQuality` | `Shadow Quality` | `SettingSlider_C` | BP (`MainMenu`) | `shadow`, `quality`, `resolution` (tooltip) | Évolutivité des ombres (`sg.ShadowQuality`) |
|
||
|
|
| `ShowFPS` | `Show FPS` (`Show Frame Per Second`) | `SettingCheckbox_C` | BP (`MainMenu`) | `fps` | Affichage du compteur d'images/sec (`stat FPS`) |
|
||
|
|
| `ToonShading` | `Toon Shading` | `SettingCheckbox_C` | BP (`MainMenu`) | `toon` | Matériau de post-traitement Cel-Shading 2D |
|
||
|
|
| `Censore` | `YouTube Censore` | `SettingCheckbox_C` | BP (`MainMenu`) | `censor` | Pixellisation mosaïque de censure vidéo/SFW |
|
||
|
|
| `CPUSkinning` | `Tick If Morphs Don't Work` | `SettingCheckbox_C` | BP (`MainMenu`) | `morph` | Force le calcul des morph targets sur CPU (`r.MorphTarget.Mode`) |
|
||
|
|
| `DisableFurEffect` | `Invisible Dog Fix` | `SettingCheckbox_C` | BP (`MainMenu`) | `dog` | Contournement de rendu du pelage des chiens (cartes graphiques instables) |
|
||
|
|
| `SpinBoxPhysicsMult` (avec `TextBlock_13`) | `Boob Jiggle Strength` | `UHorizontalBox` + `USpinBox` | BP (`MainMenu`) | `jiggle` | Multiplicateur physique pour la dynamique secondaire de poitrine |
|
||
|
|
| `SpinBox_0` (avec `TextBlock_14`) | `Depth of Field Strength` | `UHorizontalBox` + `USpinBox` | BP (`MainMenu`) | `depth of field` | Intensité du flou de profondeur de champ dans les chambres |
|
||
|
|
| `ShadeDepth` (avec `TextBlock_16`) | `Toon Shade Depth` | `UHorizontalBox` + `USpinBox` | BP (`MainMenu`) | `toon` | Seuil de profondeur pour le rendu Toon Shading |
|
||
|
|
| *`NewAnimationsOnly` (Cas litigieux)* | `New Animations Only` | `SettingCheckbox_C` | BP (`MainMenu`) | `quality` (involontaire via tooltip) | **Conflit :** Filtrage d'animations capturé par Video à cause de l'infobulle |
|
||
|
|
| `LPColorBrightness` | `Brightness` | `UHorizontalBox` + `USlider` | `LPColor` | `LPColor*` (et `brightness`) | Compensation d'exposition globale (`AutoExposureBias`) |
|
||
|
|
| `LPColorSaturation` | `Saturation` | `UHorizontalBox` + `USlider` | `LPColor` | `LPColor*` | Saturation colorimétrique (`ColorSaturation`) |
|
||
|
|
| `LPColorContrast` | `Contrast` | `UHorizontalBox` + `USlider` | `LPColor` | `LPColor*` | Contraste de l'image (`ColorContrast`) |
|
||
|
|
| `LPColorWhiteBalance` | `White Balance` | `UHorizontalBox` + `USlider` | `LPColor` | `LPColor*` | Température des blancs (`WhiteTemp`, Kelvin) |
|
||
|
|
| `LPColorTint` | `Tint` | `UHorizontalBox` + `USlider` | `LPColor` | `LPColor*` | Teinte magenta/vert (`WhiteTint`) |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 6. Analyse des conflits potentiels
|
||
|
|
|
||
|
|
### 6.1 Conflit `quality`
|
||
|
|
1. **Faux-positif `NewAnimationsOnly` :**
|
||
|
|
- Le widget `NewAnimationsOnly` est une option de gameplay/animation (« Avoid using the old converted animations... »).
|
||
|
|
- Son infobulle se termine par : *« For those that prefer quality to quantity. »*
|
||
|
|
- Comme `RowText` agrège l'infobulle et que `quality` est testé dans `TabVideo` **avant** le mot-clé `animation` de `TabGeneral`, cette case se retrouve classée à tort dans l'onglet **Video** !
|
||
|
|
2. **Ambiguïté sur les paramètres d'évolutivité (Scalability) :**
|
||
|
|
- Les réglages BP existants utilisent `PP Quality` (`sg.PostProcessQuality`) et `AA Quality` (`r.PostProcessAAQuality`).
|
||
|
|
- L'introduction de nouveaux réglages `LPVideo*` gérant la qualité globale (`Overall Quality`) ou d'autres sous-groupes (`Texture Quality`, `Effects Quality`, `View Distance Quality`) risque de créer une confusion ou une double commande avec les curseurs BP actuels.
|
||
|
|
|
||
|
|
### 6.2 Conflit `shadow`
|
||
|
|
1. **Redondance directe sur la qualité des ombres :**
|
||
|
|
- Le Blueprint fournit déjà `ShadowQuality` (`sg.ShadowQuality` via `SettingSlider`).
|
||
|
|
- Si `LPVideo*` injecte un curseur ou sélecteur d'ombres sans masquer ou synchroniser le widget BP existant, les deux widgets entreront en concurrence directe.
|
||
|
|
2. **Homonymie `ShadeDepth` :**
|
||
|
|
- Le widget `ShadeDepth` porte le libellé `Toon Shade Depth`. Bien qu'il contienne la racine *shade*, il est actuellement capté par le mot-clé `toon`. Il ne règle pas les ombres géométriques mais le seuil de découpe du cel-shading.
|
||
|
|
|
||
|
|
### 6.3 Conflit `brightness`
|
||
|
|
1. **Concurrence sur la luminosité et la luminance d'affichage :**
|
||
|
|
- `LPColorBrightness` agit sur `AutoExposureBias` (valeur neutre 0.0, plage [-2.0, 2.0]) dans un volume de post-traitement non borné.
|
||
|
|
- Si `LPVideo*` introduit un réglage standard de luminosité d'écran (ex. Gamma `r.Color.Mid`, courbe de gamma d'affichage ou compensation d'exposition), il y aura un conflit de superposition avec `LPColorBrightness`.
|
||
|
|
- Il conviendra soit de fusionner la notion d'exposition/luminosité sous une bannière unique, soit de clairement distinguer `Brightness (Exposition 3D)` de `Gamma d'affichage`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 7. Proposition d'emplacement d'injection pour `LPVideo*`
|
||
|
|
|
||
|
|
### 7.1 Recommandation : Injection AVANT `LPColor*`
|
||
|
|
|
||
|
|
L'injection des futurs composants `LPVideo*` doit se positionner **AVANT les lignes `LPColor*`**, pour les raisons suivantes :
|
||
|
|
|
||
|
|
1. **Hiérarchie ergonomique standard de l'industrie :**
|
||
|
|
- Dans tous les jeux vidéo modernes sous Unreal Engine, la structure conventionnelle du menu Vidéo / Affichage est :
|
||
|
|
1. **Affichage / Écran :** Mode fenêtré, Résolution d'écran, VSync, Limite FPS.
|
||
|
|
2. **Qualité graphique / Évolutivité :** Préréglage global, Échelle de rendu, Ombres, Post-traitement, Anti-Aliasing, Textures.
|
||
|
|
3. **Effets visuels spécifiques :** Cel-Shading, Profondeur de champ, Flou de mouvement.
|
||
|
|
4. **Étalonnage / Colorimétrie (Calibration) :** Luminosité/Exposition, Contraste, Saturation, Balance des blancs.
|
||
|
|
- Placer `LPColor*` en queue de menu respecte cette logique naturelle où l'étalonnage colorimétrique constitue la section finale de réglage fin de l'image.
|
||
|
|
|
||
|
|
2. **Cohérence d'implémentation technique :**
|
||
|
|
- `LPColorGradeSubsystem` s'exécute déjà en ajoutant ses lignes à la fin (`Scroll->AddChild(Row)`).
|
||
|
|
- En faisant injecter `LPVideo*` en amont (soit au-dessus de `LPColor*`, soit à l'emplacement des curseurs BP que `LPVideo` viendra remplacer ou compléter), `LPColor*` conservera son statut naturel de bloc de calibration terminal.
|
||
|
|
- Si des options BP existantes (`ShadowQuality`, `PostProcessQuality`, `PostProcessAAQuality`, `ScreenPercentage`) sont retirées ou remplacées par `LPVideo*`, celles-ci doivent être masquées (`SetVisibility(ESlateVisibility::Collapsed)`) par le sous-système au moment de l'injection de `LPVideo*`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 8. Synthèse récapitulative
|
||
|
|
|
||
|
|
| Périmètre | Nombre de lignes | Origine | Statut |
|
||
|
|
|---|---|---|---|
|
||
|
|
| Réglages d'affichage BP | 1 (`FullscreenButton`) | Blueprint `MainMenu` | Valide, à conserver en tête de menu |
|
||
|
|
| Curseurs Scalability BP | 4 (`ScreenPercentage`, `PostProcessQuality`, `PostProcessAAQuality`, `ShadowQuality`) | Blueprint `MainMenu` | Fonctionnels mais redondants avec un futur menu vidéo complet |
|
||
|
|
| Cases à cocher / Effets BP | 4 (`ShowFPS`, `ToonShading`, `Censore`, `CPUSkinning`, `DisableFurEffect`) | Blueprint `MainMenu` | Spécifiques LifePlay, à conserver |
|
||
|
|
| SpinBoxes secondaires BP | 3 (`Boob Jiggle Strength`, `Depth of Field Strength`, `Toon Shade Depth`) | Blueprint `MainMenu` | Réglages visuels spécifiques |
|
||
|
|
| Faux-positif à corriger | 1 (`NewAnimationsOnly`) | Blueprint `MainMenu` | À reclasser dans `TabGeneral` (conflit mot-clé `quality`) |
|
||
|
|
| Lignes Color Grading C++ | 5 (`LPColorBrightness`, `Saturation`, `Contrast`, `WhiteBalance`, `Tint`) | `LPColorGradeSubsystem` | Valides, stables, à maintenir en bloc terminal |
|
||
|
|
| **Emplacement `LPVideo*`** | **Nouveau bloc** | `LPVideo*` (C++) | **À intercaler entre les réglages BP et le bloc `LPColor*`** |
|