172 lines
14 KiB
Markdown
172 lines
14 KiB
Markdown
|
|
# SB2-CART — Carte de découpe (SB2-T1)
|
|||
|
|
|
|||
|
|
- **Fiche** : SB2-T1 — **Agent** : A-CART — **Modèle** : prévu opus (M3) | utilisé opus (session principale)
|
|||
|
|
- **Dépôt** : addon `D:\Game\LifePlay-Sandbox`, branche `lot/SB2-bibliotheques`, tag d'entrée `lot-SB2-avant` = `b8fe6b3`
|
|||
|
|
- **Entrée** : `Docs/SB0-conception.md` § 2, 3 et 5 (addon) ; `SB1-SPEC.md`, `SB1-IMPL.md` ; sources lues en entier :
|
|||
|
|
`LPPairSandbox.h/.cpp`, `LPCoupleSim.cpp`, `LPSandboxInteraction.cpp`, `LPSandboxRoomBuilder.cpp`, début de
|
|||
|
|
`LPSandboxMeasure.cpp` ; relevés par recherche : `LPSandboxMeasure.cpp`, `LPSandboxMeasureTour.cpp`, `LPSandboxActionVM.cpp`.
|
|||
|
|
|
|||
|
|
## 1. Principe
|
|||
|
|
|
|||
|
|
Comportement inchangé : le code des méthodes est **déplacé**, pas réécrit. Seuls changent le propriétaire (classe) et
|
|||
|
|
les accès à l'état partagé, qui passent par des services du contexte. Les écarts inévitables sont listés en § 7.
|
|||
|
|
|
|||
|
|
## 2. Classes cibles
|
|||
|
|
|
|||
|
|
| Classe (fichier) | Module | Nature | Rôle |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| `ALPSandboxScene` (`LPSandboxScene.h/.cpp`, ex-`LPSandboxRoomBuilder.cpp`) | `lps_lib_scene` | `AActor` (ex-`ALPPairSandboxStage`) | pièce, mobilier, coque, sol, lumières, ciel ; points de départ ; **hôte des composants** des mods (outer et racine d'attache, comme la scène aujourd'hui) |
|
|||
|
|
| `FLPSandboxActors` (`LPSandboxActors.h/.cpp`) | `lps_lib_actors` | C++ (instance unique par session, possédée par le GameMode) | joueur et partenaire, capsule copiée de Person, scan Quaternius, corps, lecture de clips, masquage des personnages |
|
|||
|
|
| `FLPSandboxCamera` (`LPSandboxCamera.h/.cpp`) | `lps_system_core` | C++, enveloppe du bras et de la caméra du pion | longueur et décalage du bras, focale, rotation de contrôle, bornes de tangage, `ResetView` |
|
|||
|
|
| `ALPPairSandboxCharacter` (`LPPairSandbox.h/.cpp`) | core (pion) + actors (corps) | `ACharacter`, garde son nom (GameMode, config) | composants `Arm`/`Camera` ; menu (barre des mods, rangée Corps, emplacement du panneau du mod ouvert) ; `Tick` réduit à l'aiguillage |
|
|||
|
|
| `ALPPairSandboxGameMode` | core | inchangé de nom | crée scène, acteurs, contexte |
|
|||
|
|
| `ULPSandboxCoupleMod` (`LPSandboxCoupleMod.h/.cpp`, ex-partie de `LPCoupleSim.cpp`) | `lps_couple` | `UObject` (outer : la scène) | couple : soudure, boîte, déplacement, animations de paire, interrupteurs 1/2, messages du mode Pair |
|
|||
|
|
| `ULPSandboxInteractionMod` (`LPSandboxInteractionMod.h/.cpp`, ex-`LPSandboxInteraction.cpp`) | `lps_interaction` | `UObject` | filtres, chat, pastille de touche, vues, marche |
|
|||
|
|
| `ULPSandboxMeasureMod` (`LPSandboxMeasure.cpp`, `LPSandboxMeasureTour.cpp`, nouveau `LPSandboxMeasureMod.h`) | `lps_asset_integration` | `UObject` | tout l'état Mesure (≈ 70 membres) ; `AddUObject` des captures conservé |
|
|||
|
|
|
|||
|
|
Les enveloppes `ILPSandboxMod` (`LPSandboxModWrappers.cpp`) tiennent chacune un `TStrongObjectPtr` vers l'objet du mod,
|
|||
|
|
créé à la première ouverture (outer = scène). `UObject` plutôt que C++ pur : `OnScreenshotCaptured().AddUObject` et
|
|||
|
|
les `TObjectPtr` (composants, caméras) gardent leur sémantique actuelle.
|
|||
|
|
|
|||
|
|
### 2.1 Contexte et interface (révision de `LPSandboxMod.h`)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
struct FLPSandboxContext
|
|||
|
|
{
|
|||
|
|
UWorld* World = nullptr;
|
|||
|
|
ALPPairSandboxCharacter* Player = nullptr; // pion (lecture des touches, menu)
|
|||
|
|
FLPSandboxCamera* Camera = nullptr; // core
|
|||
|
|
ALPSandboxScene* Scene = nullptr; // lps_lib_scene, nul si non requis
|
|||
|
|
FLPSandboxActors* Actors = nullptr; // lps_lib_actors, nul si non requis
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
struct FLPSandboxInput // rempli par le Tick du pion, une fois par image
|
|||
|
|
{
|
|||
|
|
APlayerController* PC = nullptr;
|
|||
|
|
float DeltaSeconds = 0.f;
|
|||
|
|
float MouseX = 0.f, MouseY = 0.f; // clic droit tenu, sinon 0
|
|||
|
|
FVector Direction = FVector::ZeroVector; // ZQSD/WASD dans le repère de la caméra (non normalisé)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class ILPSandboxMod
|
|||
|
|
{
|
|||
|
|
// existants : GetId, Activate, Deactivate
|
|||
|
|
virtual TSharedPtr<SWidget> BuildPanel(); // construit une fois, mis en cache par l'enveloppe
|
|||
|
|
virtual void TickInput(const FLPSandboxInput& Input); // remplace l'aiguillage du Tick du pion
|
|||
|
|
virtual void OnFellOff(); // pion sous z = -50
|
|||
|
|
virtual void OnBodyChanged(ACharacter* Who); // choix MC / PNJ dans la rangée Corps
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Remplissage selon `MODULE_REQUIREMENTS` : `lps_asset_integration` ne requiert pas `lps_lib_scene` dans son descripteur
|
|||
|
|
actuel mais **utilise la scène comme hôte de ses composants** et masque la pièce → ajouter `lps_lib_scene` à ses
|
|||
|
|
prérequis (décision D2, § 6). Pas d'accès de mod à mod : les seuls points de contact sont scène, acteurs, caméra.
|
|||
|
|
|
|||
|
|
## 3. Destination de chaque membre
|
|||
|
|
|
|||
|
|
### 3.1 `ALPPairSandboxStage` → `ALPSandboxScene`, `FLPSandboxActors`, mods
|
|||
|
|
|
|||
|
|
| Membre / méthode (lignes `LPPairSandbox.h`) | Destination |
|
|||
|
|
|---|---|
|
|||
|
|
| `Build` (RoomBuilder 105–316), `LoadWorldFile`, `Token`, `FProp` | Scene ; la lecture de la capsule Person (119–127) part dans Actors (`ReadPersonCapsule`) ; `Build(World, Radius, Half, bCopied)` reçoit la capsule pour la recherche du départ et le journal (texte inchangé) ; l'appel final `LoadChat()` + `PairSandbox::LoadActions()` (314–315) part dans le mod interaction |
|
|||
|
|
| `Furniture`, `RoomShell` (124–125), `bFurnitureBlocks` (104) | Scene ; services `SetFurnitureBlocksPawn(bool)` (boucle de `Apply` 74–77), `HideRoom()` / `ShowRoom()` (copies exactes des boucles de `BeginMeasure` 172–187 et `EndMeasure` 85–98) |
|
|||
|
|
| `PlayerSpot`, `PartnerSpot` (205–206) | Scene (`GetPlayerSpot`, `GetPartnerSpot`) |
|
|||
|
|
| `Possess` (cpp 43–72) | GameMode / Actors : `Actors.Spawn(Scene, PlayerPawn)` ; l'appel `Apply()` (67) devient « ouvrir le mod initial » ; `ShowAnimMenu` reste appelé |
|
|||
|
|
| `Player`, `Partner` (201–202), `GetPartner` | Actors (`GetPlayer`, `GetPartner`) |
|
|||
|
|
| `CapsuleRadius`, `CapsuleHalf`, `bCopiedPerson` (207–209), `ConfigureCapsule` | Actors |
|
|||
|
|
| `PlayIdle` | aucun appelant : supprimé (vérifié par recherche) |
|
|||
|
|
| `bCapsulesOn` (105), `CoupleBox` (129), `CurrentPair` (203), `Apply`, `Weld`, `FitCoupleBox`, `MoveCouple`, `PlayPair`, `ToggleFurniture`, `ToggleCapsules` | `ULPSandboxCoupleMod` ; `Apply` appelle `Scene->SetFurnitureBlocksPawn(bFurnitureBlocks)` où `bFurnitureBlocks` reste lu dans la scène (l'interrupteur 1 bascule l'état de la scène) |
|
|||
|
|
| `BeginInteraction`, `LoadChat`, `ChatLabel` | `ULPSandboxInteractionMod` |
|
|||
|
|
| `BeginMeasure` … `WritePlanche`, `MeasureBodies` … `AutoStatus`, `FTourStep`, `FLPMeasureFigure`, `bShowMannequin` (106) | `ULPSandboxMeasureMod` (substitutions § 4) |
|
|||
|
|
|
|||
|
|
### 3.2 `ALPPairSandboxCharacter`
|
|||
|
|
|
|||
|
|
| Membre / méthode | Destination |
|
|||
|
|
|---|---|
|
|||
|
|
| `Arm`, `Camera`, `ResetView`, `SavedArmLength` | composants : pion ; manipulation : `FLPSandboxCamera` ; `SavedArmLength` → mod Mesure |
|
|||
|
|
| `SetStage`, `Stage` | remplacés par le contexte ; réglage souris/caméra de `SetStage` (109–121) → `FLPSandboxCamera::Init` |
|
|||
|
|
| `ApplyBody`, `BodyLabel`, `SelectBody`, `QuaterniusMesh`, `QuaterniusClips`, `LoadQuaternius` | Actors (scan unique par session ; `ApplyBody(Who, Label)`) ; `SelectBody` reste dans le menu du pion puis appelle `OpenMod->OnBodyChanged(Who)` |
|
|||
|
|
| `RefreshPose` | coupé en deux services Actors : `PlayClip(Who, Clip)` (branche Quaternius B_/M_, 315–349) et `PlayPairClip(Who, Pair)` (branche paire 352–371) ; la logique de choix part dans couple (paire / Idle_Loop) et interaction (marche / Idle_Loop) |
|
|||
|
|
| `PlayWalk`, `WalkLabel`, `SelectWalk`, `bWasMoving`, `EyesIdle`, `bResumeEyes`, `CurrentView`, `SelectView`, `ApplyInteractionView`, `ApplyFilters`, `ShowChat`, `HideChat`, `ChatLine`, `bChatOpen`, `RefreshInteractKey`, `ShowKeyMark`, `HideKeyMark`, `PlaceKeyMark`, `KeyMark`, `bKeyVisible`, `InteractKey`, `InteractLetter`, `bInteract*`, `bPrevE`, `Who1Name` … `bSpouses`, `ListedActions`, `BuildFilterPanel` | `ULPSandboxInteractionMod` (pointeurs sur membre de `Flag` : `bool ULPSandboxInteractionMod::*`) |
|
|||
|
|
| `SelectAnim`, `CurrentAnim`, liste des 38 noms (`ShowAnimMenu` 290–313), `bPrevOne`, `bPrevTwo` | `ULPSandboxCoupleMod` (panneau : liste des paires) |
|
|||
|
|
| `BuildMeasurePanel`, `TickMeasureInput` | `ULPSandboxMeasureMod` (`BuildPanel`, `TickInput`) |
|
|||
|
|
| `SelectMode`, `ModeLabel`, `bMeasure`, `bInteraction`, `IsInteraction`, `IsMeasure`, `GetModeLabel`, `ModeCombo`, `Menu->Modes/Mode/AnimRow/ViewRow/FilterRow/MeasureRow` | **supprimés** : le registre et `Activate`/`Deactivate` les remplacent ; `OpenModeLabel` / `IdForModeLabel` gardés pour `sandbox_mode.txt` et `[Sandbox.Mode]` |
|
|||
|
|
| `OpenNeutral` | scène neutre = aucun mod : personnages à l'arrêt, pas de `TickInput` (D3) |
|
|||
|
|
| `Menu` (`FPairSandboxMenu`) | réduit à `Widget`, `BodyRow`, `ModPanel` (emplacement), `Bodies` ; `Views`, `Walks`, `Who1/2`, `Places`, `Whens`, `Races` → interaction ; `Options/Selected` → couple |
|
|||
|
|
| `Tick` (638–855) | pion : chute (653–668) → `OnFellOff`, souris (676–682), direction (684–703), Échap (818–821) ; le reste → `TickInput` du mod ouvert (tableau 3.3) |
|
|||
|
|
|
|||
|
|
### 3.3 Découpe du `Tick` du pion
|
|||
|
|
|
|||
|
|
| Lignes | Condition actuelle | Destination |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 645–652 boîte de débogage | Pair | couple `TickInput` |
|
|||
|
|
| 653–668 chute | interaction / sinon | `OnFellOff` : interaction (`BeginInteraction` + `PlayWalk`), couple (`Apply`), Mesure : rien (D4) |
|
|||
|
|
| 704–714 déplacement | Pair : `MoveCouple` ; Interaction : `AddMovementInput` | couple / interaction |
|
|||
|
|
| 715–749 marche, yeux | Interaction | interaction |
|
|||
|
|
| 750–764 touches 1, 2 | Pair | couple |
|
|||
|
|
| 765–817 pastille, chat | Interaction | interaction |
|
|||
|
|
| 823–835 touches Mesure, étiquettes | Mesure | Mesure |
|
|||
|
|
| 836–854 messages à l'écran | Pair | couple |
|
|||
|
|
|
|||
|
|
### 3.4 Transitions (`SelectMode` 175–257) → `Activate` / `Deactivate`
|
|||
|
|
|
|||
|
|
| Bloc actuel | Destination |
|
|||
|
|
|---|---|
|
|||
|
|
| `HideChat`, `HideKeyMark`, `SetOwnerNoSee(false)` (189–191) | interaction `Deactivate` + `Camera`/Actors au besoin (`SetOwnerNoSee(false)` dans chaque `Activate`, comme aujourd'hui à chaque changement) |
|
|||
|
|
| sortie de Mesure (216–223) | Mesure `Deactivate` |
|
|||
|
|
| entrée Mesure (224–239) | Mesure `Activate` |
|
|||
|
|
| entrée Interaction (241–251) | interaction `Activate` |
|
|||
|
|
| entrée Pair (252–256) | couple `Activate` (`PlayPair(CurrentAnim)` + `ResetView`) |
|
|||
|
|
| `BeginInteraction` 97–100 et `BeginMeasure` 188–192 (boîte du couple coupée) | couple `Deactivate` (collision coupée et boîte masquée) : un mod ne touche plus l'état d'un autre |
|
|||
|
|
|
|||
|
|
## 4. Substitutions mécaniques dans les fichiers Mesure
|
|||
|
|
|
|||
|
|
| Avant (membre de la scène) | Après (dans `ULPSandboxMeasureMod`) |
|
|||
|
|
|---|---|
|
|||
|
|
| `ALPPairSandboxStage::` | `ULPSandboxMeasureMod::` |
|
|||
|
|
| `Player.Get()` / `Partner.Get()` | `Actors->GetPlayer()` / `Actors->GetPartner()` |
|
|||
|
|
| `PlayerSpot`, `CapsuleHalf` | `Scene->GetPlayerSpot()`, `Actors->GetCapsuleHalf()` |
|
|||
|
|
| boucles `Furniture` / `RoomShell` | `Scene->HideRoom()` / `Scene->ShowRoom()` |
|
|||
|
|
| `CoupleBox` (188–192) | supprimé (couple `Deactivate`) |
|
|||
|
|
| `NewObject<T>(this…)`, `GetRootComponent()`, `GetWorld()`, `GetActorLocation()` | `NewObject<T>(Scene…)`, `Scene->GetRootComponent()`, `Scene->GetWorld()`, `Scene->GetActorLocation()` |
|
|||
|
|
| `AddUObject(this, &ALPPairSandboxStage::…)` | `AddUObject(this, &ULPSandboxMeasureMod::…)` |
|
|||
|
|
| `Room->…` dans `TickMeasureInput`, `Who->Stage` dans `BuildMeasurePanel` | `this->…` ; `Arm`/`GetMesh()` du pion via `Camera` / `Player` |
|
|||
|
|
|
|||
|
|
Mêmes substitutions pour couple (`LPCoupleSim.cpp`) et interaction (`Player`/`Partner`, `PlayerSpot`, `Arm`, `Camera`, `GetController`).
|
|||
|
|
|
|||
|
|
## 5. Ordre de déplacement (fiches IMPL)
|
|||
|
|
|
|||
|
|
1. **SB2-T2** (socle et bibliothèques) : `LPSandboxMod.h` (contexte, entrée, 3 crochets), `ALPSandboxScene`,
|
|||
|
|
`FLPSandboxActors`, `FLPSandboxCamera`, GameMode, pion (menu réduit, aiguillage) ; enveloppes adaptées.
|
|||
|
|
2. **SB2-T3a** couple, **T3b** interaction, **T3c** Mesure (≈ 1 600 lignes, substitutions § 4).
|
|||
|
|
3. Une compilation (SB2-T4) après T3c : le code intermédiaire ne compile pas seul (la scène perd ses membres en T2).
|
|||
|
|
|
|||
|
|
Points d'appel croisés à casser : `Build → LoadChat/LoadActions` ; `BeginInteraction → CoupleBox` ;
|
|||
|
|
`BeginMeasure → CoupleBox` ; `Possess → Apply` ; `RefreshPose → Stage->CurrentPair / Stage->Player->WalkLabel` ;
|
|||
|
|
`SelectBody → bInteraction, bWasMoving, CurrentView` ; `ShowAnimMenu → PairSandbox::PlaceChoices/WhenChoices` ;
|
|||
|
|
`Tick → Stage->CoupleBox, bCapsulesOn, bFurnitureBlocks`.
|
|||
|
|
|
|||
|
|
## 6. Décisions proposées
|
|||
|
|
|
|||
|
|
| # | Décision | Motif |
|
|||
|
|
|---|---|---|
|
|||
|
|
| D1 | Les mods sont des `UObject` (outer = scène) tenus par l'enveloppe | captures d'écran par `AddUObject`, composants en `TObjectPtr` |
|
|||
|
|
| D2 | `lps_asset_integration` requiert `lps_lib_scene` (descripteur) et `lps_lib_actors` | il masque la pièce et les personnages et accroche ses composants à la scène ; sinon contexte nul |
|
|||
|
|
| D3 | Scène neutre (aucun mod) : pas de comportement de couple | l'état neutre de SB1 (« Pair sans liste ») dépendait du couple ; un mod ne peut plus servir de défaut |
|
|||
|
|
| D4 | Chute du pion en Mesure : rien | aujourd'hui `Apply()` du couple ; le pion est figé et à l'intérieur de la pièce pendant la Mesure, cas non atteint |
|
|||
|
|
| D5 | Panneau du mod ouvert placé sous la rangée Corps (MC, PNJ) | aujourd'hui le panneau Mesure est au-dessus de MC/PNJ et les autres en dessous ; un seul emplacement |
|
|||
|
|
| D6 | `EndSession` vide aussi les instances de mods | l'état des mods vit dans le monde (outer = scène), comme celui de la scène aujourd'hui |
|
|||
|
|
| D7 | Les instances persistent entre deux ouvertures dans la session | l'état actuel (clip Mesure, filtres, paire choisie) survit aux changements de mode |
|
|||
|
|
|
|||
|
|
## 7. Écarts visibles attendus
|
|||
|
|
|
|||
|
|
- Ordre du panneau (D5) ; scène neutre sans couple (D3) ; chargement de `chat.lpaction` et des actions à la première
|
|||
|
|
ouverture d'interaction, plus au démarrage (journal déplacé) ; un seul scan Quaternius par session au lieu de trois
|
|||
|
|
(lignes « Sandbox Quaternius » moins nombreuses).
|
|||
|
|
|
|||
|
|
## 8. Observation hors périmètre (comportement actuel, non corrigé en SB2)
|
|||
|
|
|
|||
|
|
- **O1** : `EndMeasure` (`LPSandboxMeasure.cpp` 85–98) remet `SetVisibility(true)` sur meubles et murs sans
|
|||
|
|
`SetHiddenInGame(false)`, alors que `BeginMeasure` a mis `SetHiddenInGame(true)` : après Mesure, la pièce devrait
|
|||
|
|
rester invisible en Couple et Interaction. À confirmer à l'écran ; correction proposée hors SB2 (registre des reports).
|