29 KiB
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èsInteract;+AxisMappingsCameraHeightG (+1) / B (−1) etCoupleMoveYV (+1) / X (−1) aprèsPenisRotation. - 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()etCommitWheel(...)(§ 7),IsCoupleDragByKeys()(accesseur lu par LPCameraModeSubsystem) etSetCoupleDragByKeys(bool)(§ 8b),GetLayout(). - Privés :
LoadSaved()n'est plusconst(il lit et migre la section) ;ApplyPreset(bool, TArray<FString>&)(l. 64-65) ;IdleStatus(); membresLayout(défautQWERTY) etbCoupleDragKeys(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: . » 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 |
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 -) :
--- 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 untruearrê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, surchargeconst TArray<ArgType>*dansWidgets/Views/IItemsSource.h:32),OnSelectionChanged/OnGenerateWidget(:152-153 ; signaturesFramework/SlateDelegates.h:157-162et: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étailsMouseButton | 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::WasJustPressedlitEventCounts[IE_Pressed](Runtime/Engine/Private/UserInterface/PlayerInput.cpp:2111-2130), remis à zéro au début deProcessInputStack(:1285, :1335) : lisible par un ticker du noyau après le tick du monde, commeInteractPressed(LPDirectControlSubsystem.cpp:189-204, ticker 0 s:832) (estimé pour l'ordre exact des ticks).
2. Écarts à la SPEC (obligatoire)
- 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'unLPKeyboard.ini. - 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.
- 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).
- E4, Reset d'un joueur Custom : après Reset, les touches sont celles de DefaultInput (QWERTY) et
Layout=QWERTYest écrit. « Layout est gardé » (§ 4) est appliqué au seul cas AZERTY. - 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.
- 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). - 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é). - 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).
- 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). - E10, migration :
Versionabsente 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. - 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).
- 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).ConsoleKeysnon 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
LifePlayEditorpuis Development (Tools\Build.ps1) à code 0, aucun avertissement nouveau ;LPKeyboardSubsystem.cppetLPCameraModeSubsystem.cppdans les unités compilées. - V2 Compilation de
SComboBox<TSharedPtr<FString>>:.OptionsSource(&LayoutOptions)(choix de surcharge),OnGenerateWidget_LambdaetOnSelectionChanged_Lambda(paramètresTSharedPtr<FString>par valeur). - V3 Unity : noms
Kb*uniques (grep surSource/etPlugins/: seulLPKeyboardSubsystem.cpp) ; aucun C2374 / C2084. - V4 Aucun C4456 / C4458 (ombrage) ni C4702 (constante
CoupleMoveSpaceen ternaire, commebSexWheelZoom) 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 localFRetiredKey(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.iniavec 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.inimontre les 5 liaisons du préréglage etLayout; 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,ButtonAxisnon relu au niveau deFKeyDetails::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
Roomest 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=Keysrelu après redémarrage. - V23 Aucun
Accessed Nonenouveau ; 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.cppreste en LF, les fichiers clavier etDefaultInput.inien 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.