# 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*`** |