302 lines
29 KiB
Markdown
302 lines
29 KiB
Markdown
Fiche KEY2-IMPL-01 — Niveau N3 — Modèle prévu non précisé par la fiche (N3) | utilisé Opus 5.5 (claude-opus-5-5) — Agent A-IMPL-H (lp-impl) — Skills sk-protocol, ue-cpp-build, lp-build, lp-ue-compat (préchargés) ; sk-change-safety demandé par la fiche mais absent du contexte (instantané déjà pris par l'orchestratrice)
|
||
# KEY2-IMPL-01 : panneau de touches K2, K5, K6, migration Version=2 et consommateurs C++ (2026-10-20)
|
||
|
||
Ordre : GO de Big Boss, fiche transmise par l'orchestratrice. Hors copie UE : aucune compilation, aucun éditeur, aucun lancement. SPEC faisant foi : `KEY2-SPEC-01.md` révision 7 (§ 1 décisions 1 à 14 ; § 4, 5, 5b, 7, 8, 8b, 8c, 9, 10) et `KEY2-CART-02.md` § 2 à 5 et § 10.
|
||
Niveaux de preuve : **établi** (fichier:ligne relu ou commande rejouée) ; **estimé** (déduit, à éprouver au build ou en jeu).
|
||
|
||
## 1. Fichiers modifiés
|
||
|
||
### 1.1 Empreintes et fins de ligne
|
||
|
||
Commande : `md5sum` sur les 5 fichiers avant toute écriture, puis après ; référence = `scratchpad\key2_base` (copie de l'orchestratrice, MD5 identiques à la copie de travail au départ, établi). MD5 de départ de `LPCameraModeSubsystem.cpp` attendu par la fiche : `406fbf1d74eeff5b7af95998eaf2accf`, relevé identique (établi) : écriture autorisée.
|
||
|
||
| Fichier | MD5 avant | MD5 après | Lignes avant → après | Fins de ligne (CR comptés par `tr -cd '\r' \| wc -c`) |
|
||
|---|---|---|---|---|
|
||
| `Config/DefaultInput.ini` | `20952b1fe933b283a414975f79a34317` | `1a8e89a1ac4acc462280e654ffe4ffd8` | 171 → 169 | CRLF gardé (169 CR / 169 lignes) |
|
||
| `Source/LifePlay/LPKeyboardSubsystem.h` | `eed95e9860b26c5a7327ce4e3f90d8c8` | `06793e5749102b5a943ee8bbc8a1f625` | 68 → 86 | CRLF gardé (86 / 86) |
|
||
| `Source/LifePlay/LPKeyboardSubsystem.cpp` | `5d60d3f8ffe721698820fe68e55f938c` | `94575a8eef58548484844ea3070a358e` | 958 → 1463 | CRLF gardé (1463 / 1463) |
|
||
| `Source/LifePlay/LPCameraModeSubsystem.h` | `9aee8d04cf35c0c6eedf226e3b0a86c3` | `36feac2a77e13529a8ea689be74c954f` | 206 → 214 | LF gardé (0 CR) |
|
||
| `Source/LifePlay/LPCameraModeSubsystem.cpp` | `406fbf1d74eeff5b7af95998eaf2accf` | `cd6427aa03bc6c530cfe7748eee2a4bb` | 2275 → 2380 | LF gardé (0 CR) |
|
||
|
||
`git diff --no-index --numstat` contre la référence (ajouts, retraits) : DefaultInput.ini 5 / 7 ; LPKeyboardSubsystem.h 19 / 1 ; LPKeyboardSubsystem.cpp 519 / 14 ; LPCameraModeSubsystem.h 8 / 0 ; LPCameraModeSubsystem.cpp 105 / 0 (`105 insertions(+)`, aucun retrait).
|
||
Toutes les écritures par l'outil Edit (aucun script, aucun `sed -i`).
|
||
|
||
### 1.2 `Config/DefaultInput.ini` (SPEC § 9 ; § 4, § 5, § 5b, § 8b)
|
||
|
||
- Retirées (5 + 2) : `SpeedUp NumPadSix`, `SpeedDown NumPadFour` (anciennes l. 113-114), `TestScenes Tilde` (l. 121), `SpeedUp Equals`, `SpeedDown Hyphen` (l. 123-124), `MoveForward Z` (l. 155), `MoveRight Q −1` (l. 158).
|
||
- Ajoutées : `+ActionMappings=(ActionName="ActionPanel",…,Key=Q)` après `Interact` ; `+AxisMappings` `CameraHeight` G (+1) / B (−1) et `CoupleMoveY` V (+1) / X (−1) après `PenisRotation`.
|
||
- Gardées : `SpeedUp Add`, `SpeedDown Subtract`, `Favorite4/6` (Four, Six, NumPadFour, NumPadSix), `TestScenes Insert`, `ConsoleKeys`. Résultat : déplacement W S A D seul (préréglage QWERTY, décision 12).
|
||
|
||
### 1.3 `Source/LifePlay/LPKeyboardSubsystem.h`
|
||
|
||
- Publics ajoutés (l. 40-50) : `ApplyLayout(const FString&)` (§ 4), `RefuseLeftClick()` et `CommitWheel(...)` (§ 7), `IsCoupleDragByKeys()` (accesseur lu par LPCameraModeSubsystem) et `SetCoupleDragByKeys(bool)` (§ 8b), `GetLayout()`.
|
||
- Privés : `LoadSaved()` n'est plus `const` (il lit et migre la section) ; `ApplyPreset(bool, TArray<FString>&)` (l. 64-65) ; `IdleStatus()` ; membres `Layout` (défaut `QWERTY`) et `bCoupleDragKeys` (l. 83-85).
|
||
|
||
### 1.4 `Source/LifePlay/LPKeyboardSubsystem.cpp`
|
||
|
||
| § SPEC | Lieu (lignes après) | Changement |
|
||
|---|---|---|
|
||
| § 4, § 5 | l. 36-74 (espace anonyme) | constantes `Kb*` : section `LPKeyboard`, `QWERTY` / `AZERTY` / `Custom`, `KbVersion = 2`, noms d'actions et d'axes ; `KbIsMoveGroup`, `KbLayoutPreset` (QWERTY : W +1, S −1, A −1, D +1, ActionPanel Q ; AZERTY : Z, S, Q, D, ActionPanel A ; Interact non touché), `KbGameReadKey` (LeftShift, RightShift, LeftControl, RightControl, F12, PageDown, Y, N, LeftMouseButton, RightMouseButton) |
|
||
| § 8 | `ActionLabel`, `AxisLabel` | « Action Panel » ; « Camera Height Up / Down » ; « Couple Right / Left » |
|
||
| § 8 | l. 198-249 `FBindGroup`, `GroupFor` | champs `Sub` et `SubTitle` ; section « Scene » (ordre 8) en 4 blocs : « Camera » (LeftRight, DownUp, ScrollDownUp, RotateCamera, SwitchCamera, CameraHeight), « Characters » (ManualAnimating, l'axe de rotation existant, CoupleMoveY), « Actions » (ActionPanel), « Other » (TestScenes, Recommended) |
|
||
| § 7, 4 | `ChordText` | paramètre `bCmd`, préfixe « Cmd+ » ; appel de la ligne de touche mis à jour |
|
||
| § 8 | l. 284-299 `KbAddMissing` ; l. 479-484 | ligne « (no key) » avec Add pour ActionPanel, CameraHeight ±, CoupleMoveY ± quand le fichier du joueur ne les a pas (écart E1) |
|
||
| § 4 | l. 325-328, l. 352-388, l. 615-620, l. 686-689 | `SComboBox<TSharedPtr<FString>>` (QWERTY, AZERTY), bouton « Apply », texte « Layout: QWERTY / AZERTY / custom » en tête du panneau |
|
||
| § 8, § 8b | l. 505-531 (Rebuild), l. 645-672 | tri par groupe puis bloc ; sous-titres de bloc ; option « Move couple with » (bouton « Mouse and arrows » / « Arrows only ») en tête du bloc « Characters » |
|
||
| § 7, 1-3 | l. 703-804 (`FKeyboardProcessor`) | modificateur seul retenu à l'appui (hors répétition) et enregistré au relâchement (`HandleKeyUpEvent`) si rien d'autre n'a été pressé ; `HandleMouseButtonDownEvent` : droit, milieu, Thumb1, Thumb2 seuls, gauche seulement avec Shift / Ctrl / Alt / Cmd, sinon `RefuseLeftClick` ; `HandleMouseWheelOrGestureEvent` : `CommitWheel` (MouseScrollUp / MouseScrollDown) |
|
||
| § 4, § 7, 5 | l. 1001-1040 (`CommitKey`) | groupe de déplacement touché (axe remplacé ou touche retirée d'un axe de déplacement) → `Layout = Custom` ; avertissement « Also used by the game: <touche>. » sans refus |
|
||
| § 4 | l. 1059 (`RemoveBinding`) | retrait d'une liaison de déplacement → `Custom` |
|
||
| § 4 | l. 1067-1144 | `ApplyPreset` (étapes 1 à 3 du § 4 : retire MoveForward, MoveRight, ActionPanel ; retire la même touche sans modificateur des autres actions et axes, avec annonce ; ajoute les 5 liaisons) ; `ApplyLayout` (+ `Layout`, `ApplyToPlayer` qui enregistre, ligne d'état, ligne `LogLifePlay`) |
|
||
| § 7 | l. 1146-1161 | `RefuseLeftClick` (message, la capture continue) ; `CommitWheel` (refus pour un axe : les axes gardent `MouseWheelAxis`) |
|
||
| § 8b | l. 1163-1172 | `SetCoupleDragByKeys` (enregistre aussitôt) |
|
||
| § 4 | l. 1174-1187, appels dans `TakeEmbeddedPage` / `OpenKeyboardMenu` | `IdleStatus` : « Action Panel has no key: choose a layout and press Apply, or use Add. » si ActionPanel est sans touche |
|
||
| § 4, décision 12 | l. 1252-1263 (`ResetToDefault`) | après DefaultInput, réapplique AZERTY si `Layout=AZERTY` (gardé) ; sinon `Layout = QWERTY` |
|
||
| § 5, § 5b | l. 1306-1366, l. 1394-1398 (`LoadSaved`) | lit `Layout`, `CoupleDrag`, `Version` ; si `Version` < 2 (absente = 0) : retire les 5 liaisons exactes (SpeedUp NumPadSix, SpeedDown NumPadFour, SpeedUp Equals, SpeedDown Hyphen, TestScenes Tilde, modificateurs tous faux), ajoute ActionPanel=Q seulement si Q n'est lié à rien (actions et axes du fichier) et si ActionPanel n'y est pas, `Layout = Custom`, une ligne `LogLifePlay` avec le compte, puis réécrit le fichier |
|
||
| § 4, § 5, § 8b | l. 1430-1433 (`SaveSaved`) | section `[LPKeyboard]` : `Layout`, `Version=2`, `CoupleDrag=Mouse|Keys` |
|
||
|
||
### 1.5 `Source/LifePlay/LPCameraModeSubsystem.h` (gel CAM2 : 8 lignes ajoutées en fin de classe, rien d'autre)
|
||
|
||
Déclaration de `TickSceneKeys(APlayerController*, AActor* View, const UObject* Room, const TArray<AActor*>& Couple, bool bGrabbing, float Step)` et membres `SceneCameraLift`, `bLiftC3Was` (l. 206-213).
|
||
|
||
### 1.6 `Source/LifePlay/LPCameraModeSubsystem.cpp` (gel CAM2 : ajouts seulement, aucun bloc existant modifié ni déplacé)
|
||
|
||
Blocs ajoutés : constantes KEY2 (l. 208-220 : `CameraHeightSpeed = 100` cm/s, borne relative `[-40, 150]`, `ECoupleMoveSpace` + constante unique `CoupleMoveSpace = World`, pas `CoupleMoveYStep = 5`) ; aide `ActionJustPressed` (l. 312-334, modificateurs exacts comme `InteractPressed`) ; un appel dans `TickSexCamera` (l. 1248-1249, en scène, hors menu, après `TickCoupleMouse`) ; fonction `TickSceneKeys` (l. 1344-1400) ; garde « Arrows only » dans `TickCoupleMouse` (l. 1627-1633, clic gauche seulement). Aides existantes réutilisées : `AxisValue`, `ReadObject`, `ReadBool`, `MappedKeys`, `PCLeftMouseSexOn`, `RoomSceneCamera`, `PCSexC3`, `LastSexView` ; garde de menu = le `return` existant de `TickSexCamera` sur `bMenuOnScreen`.
|
||
|
||
Diff unifié complet contre la référence (`diff -u` ; code de sortie 1 = différences ; 0 ligne `-`) :
|
||
|
||
```diff
|
||
--- key2_base/LPCameraModeSubsystem.cpp
|
||
+++ Source/LifePlay/LPCameraModeSubsystem.cpp
|
||
@@ -205,6 +205,20 @@
|
||
const float HelpIconSize = 28.f;
|
||
const int32 HelpZOrder = 60;
|
||
|
||
+ // KEY2 (KEY2-SPEC-01 § 6, § 8b, § 8c) : touche d'action (meme evenement que G-g), hauteur de la camera de scene,
|
||
+ // couple sur Y. Actions et axes de DefaultInput.ini, remappables dans le menu Clavier.
|
||
+ const FName ActionPanelAction(TEXT("ActionPanel"));
|
||
+ const FName AxisCameraHeight(TEXT("CameraHeight"));
|
||
+ const FName AxisCoupleMoveY(TEXT("CoupleMoveY"));
|
||
+ const float CameraHeightSpeed = 100.f; // cm par seconde (a regler a l'essai)
|
||
+ // Hauteur ajoutee bornee comme C2Height de Room ([-40, 150], KEY2-CART-02 § 5), depuis le dernier recadrage.
|
||
+ const float CameraHeightMin = -40.f;
|
||
+ const float CameraHeightMax = 150.f;
|
||
+ // Repere de CoupleMoveY (Q12, decision 14) : World = Y du monde (comme le X de PC), Couple = droite du premier acteur.
|
||
+ enum class ECoupleMoveSpace : uint8 { World, Couple };
|
||
+ const ECoupleMoveSpace CoupleMoveSpace = ECoupleMoveSpace::World;
|
||
+ const float CoupleMoveYStep = 5.f; // par unite d'axe et par image, comme le X de PC (KEY2-CART-02 § 5)
|
||
+
|
||
// Copie de LPDirectControlSubsystem.cpp (MenuClasses) : menus pendant lesquels le texte est masque.
|
||
const TCHAR* const MenuClasses[] = {
|
||
TEXT("Journal_C"), TEXT("MainMenu_C"), TEXT("CityMenu_C"), TEXT("StatMenu_C"),
|
||
@@ -295,6 +309,30 @@
|
||
return FMath::Clamp(Value, -1.f, 1.f);
|
||
}
|
||
|
||
+ // KEY2 : une touche de l'action Name vient d'etre pressee, modificateurs exacts (comme InteractPressed et
|
||
+ // ModifiersMatch de LPDirectControlSubsystem.cpp), mappages et remappages suivis.
|
||
+ bool ActionJustPressed(const APlayerController* PC, FName Action)
|
||
+ {
|
||
+ const UInputSettings* Settings = UInputSettings::GetInputSettings();
|
||
+ if (!PC || !PC->PlayerInput || !Settings)
|
||
+ {
|
||
+ return false;
|
||
+ }
|
||
+ const bool bCtrl = PC->IsInputKeyDown(EKeys::LeftControl) || PC->IsInputKeyDown(EKeys::RightControl);
|
||
+ const bool bShift = PC->IsInputKeyDown(EKeys::LeftShift) || PC->IsInputKeyDown(EKeys::RightShift);
|
||
+ const bool bAlt = PC->IsInputKeyDown(EKeys::LeftAlt) || PC->IsInputKeyDown(EKeys::RightAlt);
|
||
+ const bool bCmd = PC->IsInputKeyDown(EKeys::LeftCommand) || PC->IsInputKeyDown(EKeys::RightCommand);
|
||
+ for (const FInputActionKeyMapping& Map : Settings->GetActionMappings())
|
||
+ {
|
||
+ if (Map.ActionName == Action && Map.bCtrl == bCtrl && Map.bShift == bShift && Map.bAlt == bAlt && Map.bCmd == bCmd
|
||
+ && PC->PlayerInput->WasJustPressed(Map.Key))
|
||
+ {
|
||
+ return true;
|
||
+ }
|
||
+ }
|
||
+ return false;
|
||
+ }
|
||
+
|
||
// Noms des touches du clavier de l'action ou de l'axe Name, mappages en cours (comme AxisValue, remappages suivis) ;
|
||
// Sign : 1 ou -1 = echelle de l'axe de ce signe, 0 = toutes. Souris, manette et axes analogiques exclus.
|
||
FString MappedKeys(FName Name, int32 Sign)
|
||
@@ -1207,6 +1245,8 @@
|
||
// Prise du couple a la souris (B2p-D) ; pendant la prise, la camera est figee et ZQSD ne la deplace pas.
|
||
const bool bGrabbing = TickCoupleMouse(GI, PC, View, Room, Couple, Pivot);
|
||
const AActor* SceneCamera = Cast<AActor>(LPCameraModeLocal::ReadObject(Room, LPCameraModeLocal::RoomSceneCamera));
|
||
+ // KEY2 (KEY2-SPEC-01 § 8c) : touche d'action, hauteur de la camera de scene, couple sur Y.
|
||
+ TickSceneKeys(PC, View, Room, Couple, bGrabbing, Step);
|
||
if (!bGrabbing && bKeys && Couple.Num() > 0 && View == SceneCamera)
|
||
{
|
||
// Mode Scene : la camera tourne autour du couple du meme angle que son lacet (cadrage garde, comme B2n),
|
||
@@ -1301,6 +1341,64 @@
|
||
bMiddleWasDown = bMiddle;
|
||
}
|
||
|
||
+void ULPCameraModeSubsystem::TickSceneKeys(APlayerController* PC, AActor* View, const UObject* Room, const TArray<AActor*>& Couple, bool bGrabbing, float Step)
|
||
+{
|
||
+ // KEY2 (§ 8c, 1) : la touche d'action bascule le panneau d'action, par le meme evenement que TickPanelClick.
|
||
+ if (LPCameraModeLocal::ActionJustPressed(PC, LPCameraModeLocal::ActionPanelAction))
|
||
+ {
|
||
+ UFunction* PanelToggle = PC->FindFunction(LPCameraModeLocal::PCLeftMouseSexOn);
|
||
+ if (PanelToggle && PanelToggle->NumParms == 0)
|
||
+ {
|
||
+ UE_LOG(LogLifePlay, Log, TEXT("Scene : panneau d'action bascule (ActionPanel, touche %s)"), *LPCameraModeLocal::MappedKeys(LPCameraModeLocal::ActionPanelAction, 0));
|
||
+ PC->ProcessEvent(PanelToggle, nullptr);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ UE_LOG(LogLifePlay, Log, TEXT("Scene : panneau d'action non bascule, evenement LeftMouseSexOn absent du PC"));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ // KEY2 (§ 8c, 5) : CameraHeight monte ou baisse SceneCamera ; hauteur ajoutee bornee, rien pendant une prise.
|
||
+ AActor* LiftCamera = Cast<AActor>(LPCameraModeLocal::ReadObject(Room, LPCameraModeLocal::RoomSceneCamera));
|
||
+ const bool bLiftC3 = LPCameraModeLocal::ReadBool(PC, LPCameraModeLocal::PCSexC3);
|
||
+ if (!IsValid(LiftCamera) || View != LiftCamera || LastSexView.Get() != LiftCamera || (bLiftC3 && !bLiftC3Was))
|
||
+ {
|
||
+ // Hors vue Scene, ou recadrage a venir (entree en Scene, passage en C3) : la camera reprend sa hauteur par defaut.
|
||
+ SceneCameraLift = 0.f;
|
||
+ }
|
||
+ else if (!bGrabbing)
|
||
+ {
|
||
+ const float HeightAxis = LPCameraModeLocal::AxisValue(PC, LPCameraModeLocal::AxisCameraHeight);
|
||
+ if (!FMath::IsNearlyZero(HeightAxis))
|
||
+ {
|
||
+ const float NewLift = FMath::Clamp(SceneCameraLift + HeightAxis * LPCameraModeLocal::CameraHeightSpeed * Step,
|
||
+ LPCameraModeLocal::CameraHeightMin, LPCameraModeLocal::CameraHeightMax);
|
||
+ if (!FMath::IsNearlyEqual(NewLift, SceneCameraLift))
|
||
+ {
|
||
+ LiftCamera->AddActorWorldOffset(FVector(0.0, 0.0, static_cast<double>(NewLift - SceneCameraLift)));
|
||
+ SceneCameraLift = NewLift;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ bLiftC3Was = bLiftC3;
|
||
+
|
||
+ // KEY2 (§ 8c, 4) : CoupleMoveY, piece cachee seulement (meme garde que le X de PC), pas fixe par image.
|
||
+ const AActor* MoveRoom = Cast<AActor>(Room);
|
||
+ const float MoveAxis = LPCameraModeLocal::AxisValue(PC, LPCameraModeLocal::AxisCoupleMoveY);
|
||
+ if (bGrabbing || FMath::IsNearlyZero(MoveAxis) || Couple.Num() == 0 || !MoveRoom || !MoveRoom->IsHidden())
|
||
+ {
|
||
+ return;
|
||
+ }
|
||
+ const FVector CoupleRight = Couple[0]->GetActorRightVector();
|
||
+ const FVector Side = LPCameraModeLocal::CoupleMoveSpace == LPCameraModeLocal::ECoupleMoveSpace::World
|
||
+ ? FVector(0.0, 1.0, 0.0) : FVector(CoupleRight.X, CoupleRight.Y, 0.0).GetSafeNormal();
|
||
+ const FVector MoveStep = Side * static_cast<double>(MoveAxis * LPCameraModeLocal::CoupleMoveYStep);
|
||
+ for (AActor* Person : Couple)
|
||
+ {
|
||
+ Person->SetActorLocation(Person->GetActorLocation() + MoveStep);
|
||
+ }
|
||
+}
|
||
+
|
||
void ULPCameraModeSubsystem::KeepMouseFree(APlayerController* PC, float DeltaTime)
|
||
{
|
||
// COMMUN-12 : a la fermeture du panneau, le PC repasse en GameOnly (CapturePermanently, LockOnCapture, mouvement
|
||
@@ -1526,6 +1624,13 @@
|
||
{
|
||
// Maj tenu : la voie d'origine (Maj + bouton + souris, Room) garde la main, aucune prise.
|
||
const bool bShiftHeld = Input && (Input->IsPressed(EKeys::LeftShift) || Input->IsPressed(EKeys::RightShift));
|
||
+ // KEY2 (KEY2-SPEC-01 § 8b, decision 13) : « Arrows only » (CoupleDrag=Keys), le clic gauche ne prend plus le
|
||
+ // couple et reste au jeu ; le clic droit garde la rotation.
|
||
+ const ULPKeyboardSubsystem* DragKeys = GI->GetSubsystem<ULPKeyboardSubsystem>();
|
||
+ if (DragKeys && DragKeys->IsCoupleDragByKeys() && bLeftPressed)
|
||
+ {
|
||
+ return false;
|
||
+ }
|
||
if ((!bLeftPressed && !bRightPressed) || bShiftHeld)
|
||
{
|
||
return false;
|
||
```
|
||
|
||
### 1.7 API moteur relues (UE 5.8, `D:\Game\Launcher\Engine\UE_5.8\Engine\Source`, établi)
|
||
|
||
- `IInputProcessor` : `HandleKeyUpEvent` (`Runtime/Slate/Public/Framework/Application/IInputProcessor.h:29`), `HandleMouseButtonDownEvent` (:38), `HandleMouseWheelOrGestureEvent(FSlateApplication&, const FPointerEvent&, const FPointerEvent*)` (:47). Les préprocesseurs passent avant les widgets et un `true` arrête l'événement : `SlateApplication.cpp:5097`, `:5324`, `:6232`.
|
||
- `FPointerEvent::GetEffectingButton` (`Runtime/SlateCore/Public/Input/Events.h:1078`), `GetWheelDelta` (:1081) ; `FInputEvent::IsRepeat` (:210), `IsShiftDown` (:220), `IsControlDown` (:244), `IsAltDown` (:268), `IsCommandDown` (:292).
|
||
- `SComboBox` : `SLATE_ITEMS_SOURCE_ARGUMENT(OptionType, OptionsSource)` (`Runtime/Slate/Public/Widgets/Input/SComboBox.h:151`, surcharge `const TArray<ArgType>*` dans `Widgets/Views/IItemsSource.h:32`), `OnSelectionChanged` / `OnGenerateWidget` (:152-153 ; signatures `Framework/SlateDelegates.h:157-162` et `:205-210`), `InitiallySelectedItem` (:162), slot de contenu (:137). Styles « ComboBox » et « ComboBox.Row » présents dans le style du jeu (`Runtime/SlateCore/Private/Styling/StarshipCoreStyle.cpp:1595`, `:1646`).
|
||
- `EKeys::MouseScrollUp/Down` (`Runtime/InputCore/Classes/InputCoreTypes.h:352-353`, détails `MouseButton | ButtonAxis` : `InputCoreTypes.cpp:539-540`), `ThumbMouseButton`, `ThumbMouseButton2` (`.h:359-360`) ; touches de modificateur = Shift, Ctrl, Alt, Cmd gauches et droites (`InputCoreTypes.cpp:646-653`).
|
||
- `FConfigFile` (`Runtime/Core/Public/Misc/ConfigCacheIni.h:574`) : `GetString(Section, Key, FString&)` (:815), `GetInt(Section, Key, int32&)` (:833), `AddToSection(Section, FName, const FString&)` (:945).
|
||
- `UPlayerInput::WasJustPressed` lit `EventCounts[IE_Pressed]` (`Runtime/Engine/Private/UserInterface/PlayerInput.cpp:2111-2130`), remis à zéro au début de `ProcessInputStack` (:1285, :1335) : lisible par un ticker du noyau après le tick du monde, comme `InteractPressed` (`LPDirectControlSubsystem.cpp:189-204`, ticker 0 s `:832`) (estimé pour l'ordre exact des ticks).
|
||
|
||
## 2. Écarts à la SPEC (obligatoire)
|
||
|
||
1. **E1, ajout** : lignes « (no key) » avec Add pour ActionPanel, CameraHeight ± et CoupleMoveY ± quand aucune liaison ne les porte (`KbAddMissing`). Motif : le menu ne montre que les liaisons existantes ; la migration § 5 n'ajoute ni CameraHeight ni CoupleMoveY, et ActionPanel reste sans touche si Q est pris : sans ces lignes, ces entrées seraient invisibles et non remappables pour un joueur déjà équipé d'un `LPKeyboard.ini`.
|
||
2. **E2, interprétation** : le bloc caméra quitte le groupe « Camera » (rang 1) pour la section « Scene » (rang 8, place de l'ancien groupe Scene), comme le demande l'ordre du § 8 ; la caméra apparaît donc plus bas dans la liste qu'avant.
|
||
3. **E3, sous-titres** : blocs « Camera », « Characters », « Actions » (ActionPanel seul), « Other » (TestScenes, Recommended, que la SPEC ne place pas). Libellés neutres seulement (décision 10).
|
||
4. **E4, Reset d'un joueur Custom** : après Reset, les touches sont celles de DefaultInput (QWERTY) et `Layout=QWERTY` est écrit. « Layout est gardé » (§ 4) est appliqué au seul cas AZERTY.
|
||
5. **E5, clic gauche seul pendant une capture** : refusé avec message et **consommé** (la capture continue, Escape l'annule). Choix : un clic laissé à l'interface pendant la reconstruction du panneau aurait pu viser un widget détruit.
|
||
6. **E6, option « Move couple with »** : un bouton bascule qui affiche la valeur en cours (« Mouse and arrows » / « Arrows only »), pas une liste ; enregistré aussitôt (`CoupleDrag=Mouse|Keys`).
|
||
7. **E7, CameraHeight** : translation verticale seule de SceneCamera (sans réorientation) ; vitesse 100 cm/s (SPEC : à fixer à l'essai) ; borne `[-40, 150]` sur la hauteur ajoutée depuis le dernier recadrage (remise à zéro hors vue Scene, à l'entrée en Scene et au passage en C3). L'avance ou le recul (MoveForward) met à l'échelle le décalage de la caméra : la hauteur ajoutée réelle peut s'écarter un peu du compteur (estimé).
|
||
8. **E8, CoupleMoveY** : ignoré pendant une prise à la souris (prudence, non demandé) ; aucune borne en Y (le X de PC n'est borné qu'en X).
|
||
9. **E9, CoupleDrag=Keys** : un appui gauche et droit dans la même image ne prend rien (cas limite ; garde ajoutée sans toucher à la ligne `CoupleGrabMode = bLeftPressed ? 1 : 2`).
|
||
10. **E10, migration** : `Version` absente vaut 0 ; ActionPanel n'est ajouté que si le fichier porte des actions (sinon les actions de DefaultInput, Q compris, restent) ; « Q lié à rien » est testé sur toutes les liaisons du fichier, tous modificateurs confondus.
|
||
11. **E11, Custom** : seul le groupe de déplacement (MoveForward, MoveRight) passe la disposition en Custom ; changer ActionPanel à la main ne la change pas (lecture stricte du § 4).
|
||
12. **E12, journal** : une ligne `LogLifePlay` à chaque Apply (« Clavier : disposition … appliquee »), non demandée.
|
||
|
||
## 3. Instantané
|
||
|
||
Pris par l'orchestratrice avant la fiche : `Tools\Snapshot.ps1 -Lot KEY2-IMPL` (manifeste non relu ici) ; copie de référence `scratchpad\key2_base` (5 fichiers, MD5 = colonne « avant » du § 1.1, relevés au départ). Retour arrière proposé seulement : `Tools\Restore.ps1 -Lot KEY2-IMPL`, ou recopie des 5 fichiers de `key2_base` (attention : `LPCameraModeSubsystem.*` portent aussi les modifications non commitées de CAM2).
|
||
|
||
## 4. Ce qui n'a pas été fait
|
||
|
||
- Aucune compilation ni aucun essai (fiche) : tout le code est « proposé, non compilé ».
|
||
- Texte d'aide du jeu `BuildControlsHelp` (`LPCameraModeSubsystem.cpp`) non mis à jour (Arrows only, touche d'action, G / B, V / X) : fichier en gel, hors des blocs demandés.
|
||
- Migration : pas d'ajout de CameraHeight G / B ni de CoupleMoveY V / X aux fichiers existants (non prévu au § 5) ; voir E1. Question pour Big Boss : faut-il les ajouter si les touches sont libres, comme ActionPanel ?
|
||
- ActionPanel hors scène (`UI/Action`) : non (§ 8c, 1). Remappage de Y / N : build 2 (décision 11). `ConsoleKeys` non touchés (§ 5b).
|
||
- Aucun Blueprint modifié ; nom technique de l'axe de rotation dans le C++ (§ 8, signalé) non traité.
|
||
|
||
## 5. Points à confirmer en VAL (un par ligne)
|
||
|
||
- V1 Build `LifePlayEditor` puis Development (`Tools\Build.ps1`) à code 0, aucun avertissement nouveau ; `LPKeyboardSubsystem.cpp` et `LPCameraModeSubsystem.cpp` dans les unités compilées.
|
||
- V2 Compilation de `SComboBox<TSharedPtr<FString>>` : `.OptionsSource(&LayoutOptions)` (choix de surcharge), `OnGenerateWidget_Lambda` et `OnSelectionChanged_Lambda` (paramètres `TSharedPtr<FString>` par valeur).
|
||
- V3 Unity : noms `Kb*` uniques (grep sur `Source/` et `Plugins/` : seul `LPKeyboardSubsystem.cpp`) ; aucun C2374 / C2084.
|
||
- V4 Aucun C4456 / C4458 (ombrage) ni C4702 (constante `CoupleMoveSpace` en ternaire, comme `bSexWheelZoom`) avec les réglages V7 de la copie 5.8.
|
||
- V5 Initialisations d'agrégat `FBindGroup` à 4 champs (`{KbSceneOrder, TEXT("Scene"), 0, TEXT("Camera")}`) et tableau local `FRetiredKey` (FKey copiés d'`EKeys`).
|
||
- V6 Premier lancement sans `LPKeyboard.ini` : `[LPKeyboard]` `Layout=QWERTY`, `Version=2`, `CoupleDrag=Mouse` écrits ; W A S D déplacent ; Z et Q (gauche) n'agissent plus ; « Layout: QWERTY ».
|
||
- V7 Migration (copie d'un ancien `LPKeyboard.ini` avec les 5 liaisons) : les 5 disparaissent, journal « … passe de la version 0 a 2 : 5 liaisons retirees … », `Version=2`, `Layout=Custom`, autres liaisons intactes (diff avant / après).
|
||
- V8 Migration d'un fichier issu de l'ancien DefaultInput (MoveRight Q −1 présent) : Q pris → ActionPanel sans touche, ligne « (no key) » visible, ligne d'état « Action Panel has no key… » ; Apply QWERTY ou AZERTY la pose.
|
||
- V9 Apply QWERTY puis AZERTY : le diff de `LPKeyboard.ini` montre les 5 liaisons du préréglage et `Layout` ; en AZERTY Z Q S D déplacent, W n'agit plus, A ouvre le panneau d'action en scène, E interagit ; en QWERTY W A S D, Z n'agit plus, Q ouvre le panneau.
|
||
- V10 Apply annonce les touches retirées ailleurs (« Removed from: … ») quand une touche du préréglage était liée sans modificateur à une autre action.
|
||
- V11 Modification manuelle de MoveForward ou MoveRight (Change, Add, Remove, ou touche reprise par une autre action) → « Layout: custom » et `Layout=Custom`.
|
||
- V12 Reset : joueur AZERTY → touches de DefaultInput puis AZERTY, « AZERTY layout kept » ; joueur QWERTY ou Custom → QWERTY.
|
||
- V13 K5 : clic droit, bouton du milieu, Thumb1, Thumb2, Ctrl+clic gauche s'enregistrent ; clic gauche seul → message, capture maintenue.
|
||
- V14 K5 : molette haut / bas sur une action → « Mouse Wheel Up / Down » enregistré et affiché (passe `IsRemappable` : à vérifier, `ButtonAxis` non relu au niveau de `FKeyDetails::IsAnalog`) ; molette pendant la capture d'un axe → message.
|
||
- V15 K5 : Ctrl seul (appui puis relâchement sans autre touche) → « Left Ctrl saved » ; Ctrl+E pendant la capture → Ctrl+E, pas Ctrl seul.
|
||
- V16 K5 : avertissement « Also used by the game: Y » (et Shift, Ctrl, F12, PageDown, N, clics gauche et droit) sans refus.
|
||
- V17 K6 : section « Scene » dans l'ordre Camera (LeftRight, DownUp, ScrollDownUp, RotateCamera, SwitchCamera, CameraHeight), Characters (option « Move couple with », CoupleMoveY, ManualAnimating, axe de rotation), Actions (Action Panel), Other ; aucun libellé adulte ajouté au C++ (grep).
|
||
- V18 Liste déroulante en jeu : s'ouvre, se ferme, ne laisse pas le focus clavier bloqué ; fonctionne en page intégrée (réglages) et en fenêtre.
|
||
- V19 ActionPanel en scène : Q (QWERTY) ou A (AZERTY) bascule le panneau d'action (journal « Scene : panneau d'action bascule ») ; Ctrl+Q ne le bascule pas ; rien hors scène ni menu ouvert ; une saisie dans le filtre du panneau ne le rebascule pas.
|
||
- V20 CameraHeight en vue Scene : G monte, B baisse, arrêt à +150 / −40 cm, remise à zéro à l'entrée en Scene et en C3 ; rien pendant une prise à la souris.
|
||
- V21 CoupleMoveY : V / X déplacent le couple sur Y du monde de 5 par image, seulement quand `Room` est cachée (garde reprise du X de PC) ; à vérifier : si la pièce n'est pas cachée dans une scène ordinaire, V / X n'agissent pas (même comportement que DownUp dans PC).
|
||
- V22 « Arrows only » : clic gauche sur le couple → aucune prise, le clic reste au jeu ; clic droit → rotation ; `CoupleDrag=Keys` relu après redémarrage.
|
||
- V23 Aucun `Accessed None` nouveau ; Ctrl+C / Ctrl+E (§ 3) et Add / Subtract, pavé 4 / 6 sur les favoris seulement (§ 10, 4).
|
||
|
||
## 6. Fichiers à commiter (dépôt du jeu, branche `ue5.8`)
|
||
|
||
- M `Config/DefaultInput.ini`
|
||
- M `Source/LifePlay/LPKeyboardSubsystem.h`
|
||
- M `Source/LifePlay/LPKeyboardSubsystem.cpp`
|
||
- M `Source/LifePlay/LPCameraModeSubsystem.h` (porte aussi les changements non commités de CAM2 : ordre des commits à fixer par Big Boss)
|
||
- M `Source/LifePlay/LPCameraModeSubsystem.cpp` (idem)
|
||
- A `Docs/Migration/etat/REL/KEY2/KEY2-IMPL-01.md`
|
||
|
||
Tours : 25 / 30 (estimé par l'agent ; `FicheStats.py` fait foi)
|
||
|
||
## Constats
|
||
|
||
- L'ancien DefaultInput liait Q à MoveRight (−1) : presque tous les fichiers existants ont Q pris, donc la migration laissera ActionPanel sans touche (comportement voulu par le § 4) ; E1 rend l'entrée visible.
|
||
- `LPCameraModeSubsystem.cpp` reste en LF, les fichiers clavier et `DefaultInput.ini` en CRLF : l'outil Edit a gardé chaque convention (comptes du § 1.1).
|
||
- PubCheck du livrable (`pwsh -NoProfile -Command "& 'D:\Game\LifePlay-master 5.8\Tools\PubCheck.ps1' -Fichiers @('…\KEY2-IMPL-01.md')"`, avant l'ajout de cette ligne) : `PubCheck : 0 constat(s)`, code 0 ; livrable en LF (288 lignes, 0 CR).
|
||
|
||
## 7. Complément de l'orchestratrice (2026-10-20, arbitrages de Big Boss)
|
||
|
||
Arbitrages de Big Boss : E1, E4, E5, E6 et E7 **acceptés**. Migration des anciens `LPKeyboard.ini` : ajouter G / B, V / X et ActionPanel quand la touche n'est liée à rien. Texte d'aide `BuildControlsHelp` à faire par KEY2, seul écrivain du fichier jusqu'au commit (gel CAM2).
|
||
Instantané frais avant écriture : `Tools\Snapshot.ps1 -Lot KEY2-IMPL2` (LPKeyboardSubsystem.cpp 94575a8e, LPCameraModeSubsystem.cpp cd6427aa).
|
||
|
||
| Fichier | Changement | MD5 avant → après |
|
||
|---|---|---|
|
||
| `Source/LifePlay/LPKeyboardSubsystem.cpp` (CRLF gardé : 1476 lignes, 1476 CR) | migration Version=2 : une aide `KeyFree` (touche utilisée par aucune action ni aucun axe du fichier du joueur) ; ActionPanel sur Q si libre ; CameraHeight G (+1) / B (−1) et CoupleMoveY V (+1) / X (−1), chaque sens ajouté seulement s'il n'est pas déjà lié et si sa touche est libre ; journal avec le nombre de touches d'axe ajoutées | 94575a8e → 7501ec6a |
|
||
| `Source/LifePlay/LPCameraModeSubsystem.cpp` (LF) | `BuildControlsHelp` : 3 lignes d'aide (hauteur de la caméra, couple sur le côté, panneau d'action) et leurs 5 arguments ; une seule ligne existante remplacée (fin de la liste d'arguments, `);` déplacé) | cd6427aa → f15c2b9b |
|
||
|
||
Diff contre la référence 406fbf1d : `git diff --no-index --numstat` → **112 / 1** (105 / 0 de la première passe, plus 7 / 1 de l'aide). La seule ligne retirée est la dernière ligne d'arguments de `BuildControlsHelp`, prolongée ; aucun bloc de CAM2 (A1, R-B1f, F2) n'est touché.
|
||
Toujours non compilé : la compilation est KEY2-BUILD-01.
|