214 lines
12 KiB
C++
214 lines
12 KiB
C++
// Lot CAM-B2c - indicateur du mode de camera (SPEC : Docs/Migration/etat/CAM/CAM-B2c-SPEC.md).
|
|
//
|
|
// Le joueur ne sait pas toujours quelle camera est active (C1, C2, C3, carte de la ville, studio,
|
|
// constructeur). Toutes les 0,1 s, ce sous-systeme lit la cible de vue du PlayerController et quelques
|
|
// variables de GI et de Room par reflexion, en deduit le mode (table du paragraphe 2 de la SPEC) et
|
|
// l'affiche en petit, en bas a gauche de l'ecran. Le texte est masque quand un menu est ouvert (meme
|
|
// test que LPDirectControlSubsystem). Aucun Blueprint ni asset n'est modifie ; propriete absente ou
|
|
// reference nulle : rien n'est affiche.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Containers/Ticker.h"
|
|
#include "Subsystems/GameInstanceSubsystem.h"
|
|
#include "LPCameraModeSubsystem.generated.h"
|
|
|
|
class AActor;
|
|
class APlayerController;
|
|
class UGameInstance;
|
|
class SWidget;
|
|
class STextBlock;
|
|
class UGameViewportClient;
|
|
class UButton;
|
|
class UTextBlock;
|
|
class UUserWidget;
|
|
|
|
UCLASS()
|
|
class LIFEPLAY_API ULPCameraModeSubsystem : public UGameInstanceSubsystem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
|
virtual void Deinitialize() override;
|
|
|
|
private:
|
|
bool Tick(float DeltaTime);
|
|
/** Libelle du mode courant ; vide si aucun mode n'est reconnu. */
|
|
FString ComputeLabel() const;
|
|
/** Cree le texte et l'ajoute une fois au viewport de ce GameInstance ; faux sans viewport. */
|
|
bool EnsureWidget();
|
|
/** Retire le texte du viewport qui le porte, s'il existe encore. */
|
|
void RemoveWidget();
|
|
void SetShown(bool bShow);
|
|
/** Temoin C2 (CAM-B2f, journal seulement) : camera trop pres de la tete, et ce que la sonde Camera touche. */
|
|
void WitnessC2(float DeltaTime);
|
|
/** Temoin touche C (CAM-B2j, journal seulement) : a chaque image, front montant d'une touche de SwitchCamera. */
|
|
bool TickSwitchKey(float DeltaTime);
|
|
/** Ecrit les drapeaux qui gardent la touche C (PC, GI, Room) et la vue courante. */
|
|
void LogSwitchKey(const APlayerController* PC) const;
|
|
|
|
FTSTicker::FDelegateHandle TickHandle;
|
|
FTSTicker::FDelegateHandle SwitchKeyHandle;
|
|
/** Une touche de SwitchCamera etait enfoncee a l'image precedente. */
|
|
bool bSwitchKeyDown = false;
|
|
/** Vue deja signalee par « Indicateur de camera : aucun » (une ligne par changement de vue). */
|
|
FString LastEmptyView;
|
|
/** Delai avant la prochaine ligne du temoin C2 (au plus une par seconde). */
|
|
float WitnessCooldown = 0.f;
|
|
/** Temoin d'occlusion C2 (CAM-Tocc, journal seulement) : un composant visible entre la camera et la tete. */
|
|
void WitnessOcclusion(float DeltaTime);
|
|
/** Delai avant le prochain trace d'occlusion (0,5 s), ou la prochaine ligne apres un masquage (1 s). */
|
|
float OcclusionCooldown = 0.f;
|
|
/** Sortie de CharGen (CAM-B2r) : remet GI.SpaceOn (et GI.MainMenuOn si le menu principal est ferme) une fois
|
|
* la vue revenue sur une camera de piece ; rien si la vue reste sur la carte de la ville. */
|
|
void RepairAfterCharGen(const FString& Label, bool bMenu, float DeltaTime);
|
|
/** GI.CharGenOn a ete vu vrai ; la reparation reste a faire. */
|
|
bool bCharGenSeen = false;
|
|
/** Delai restant pour trouver une camera de piece apres CharGen (10 s). */
|
|
float CharGenRepairTimeout = 0.f;
|
|
/** Temoin C1 (CAM-B2r, journal seulement) : camera loin des yeux, penchee ou tournee par rapport au controle. */
|
|
void WitnessC1(float DeltaTime);
|
|
/** Delai avant la prochaine mesure du temoin C1 (0,5 s), ou la prochaine ligne (1 s). */
|
|
float C1Cooldown = 0.f;
|
|
/** Camera de scene au clavier (CAM-B2p, P3), a chaque image : pendant le sexe, ZQSD pilote la camera en vue
|
|
* (orbite et distance en mode Scene, regard en POV) ; temoin des touches (au plus une ligne par seconde). */
|
|
void TickSexCamera(float DeltaTime);
|
|
/** Menu a l'ecran au dernier passage de Tick (0,1 s) : le parcours des widgets n'est pas refait a chaque image. */
|
|
bool bMenuOnScreen = false;
|
|
/** Delai avant la prochaine ligne « Sexe : touches ». */
|
|
float SexKeysCooldown = 0.f;
|
|
/** Couple a la souris (CAM-B2p-D), mode Scene : clic gauche maintenu sur le couple = glisser-deposer sur la
|
|
* surface visee (lit ou sol, borne au sol de Room), clic droit maintenu = rotation ; camera figee pendant la
|
|
* prise. Vrai tant qu'une prise est en cours. */
|
|
bool TickCoupleMouse(UGameInstance* GI, APlayerController* PC, AActor* View, const UObject* Room, const TArray<AActor*>& Couple, const FVector& Pivot);
|
|
/** Leve toute prise (hors sexe, menu, vue invalide) : les clics reviennent au jeu tels quels. */
|
|
void ReleaseCoupleGrab();
|
|
/** 0 : aucune prise ; 1 : deplacement (clic gauche) ; 2 : rotation (clic droit). */
|
|
int32 CoupleGrabMode = 0;
|
|
bool bLeftWasDown = false;
|
|
bool bRightWasDown = false;
|
|
/** Le curseur a bouge d'au moins 5 px depuis la prise (le couple ne bouge pas sur un simple clic). */
|
|
bool bGrabMoved = false;
|
|
/** Ecart entre la racine du maillage la plus basse et la surface sous le couple, pris a la selection (journal
|
|
* seulement depuis CAM-B2p-H : la hauteur de pose est la surface visee + 3 cm). */
|
|
bool bGrabHasHeight = false;
|
|
double GrabHeight = 0.0;
|
|
/** Decalage XY entre le pivot et le point vise a la selection. */
|
|
FVector GrabOffset = FVector::ZeroVector;
|
|
FVector2D GrabMouseStart = FVector2D::ZeroVector;
|
|
float GrabLastMouseX = 0.f;
|
|
float GrabTurned = 0.f;
|
|
/** Camera en vue figee pendant la prise, et sa pose au moment du clic. */
|
|
TWeakObjectPtr<AActor> GrabCamera;
|
|
FVector GrabCameraLocation = FVector::ZeroVector;
|
|
FRotator GrabCameraRotation = FRotator::ZeroRotator;
|
|
/** « curseur sans position » deja ecrit pour cette scene. */
|
|
bool bCursorWarned = false;
|
|
/** Borne dure du couple (CAM-B2p-E), a chaque image pendant le sexe, menus compris : pivot dans le sol de Room,
|
|
* racine du maillage entre le dessus du sol et un plafond estime ; temoin des deplacements hors prise. */
|
|
void TickCoupleBounds(float DeltaTime);
|
|
FVector LastCouplePivot = FVector::ZeroVector;
|
|
bool bHasLastPivot = false;
|
|
/** « pas de borne » (piece cachee ou sans sol) deja ecrit pour cette scene. */
|
|
bool bHiddenRoomWarned = false;
|
|
float CoupleBoundsCooldown = 0.f;
|
|
float CoupleMoveCooldown = 0.f;
|
|
/** CAM-B2p-F : une prise vient de finir dans cette image (le temoin hors prise ne compte pas son dernier pas). */
|
|
bool bGrabJustEnded = false;
|
|
/** Bornes retenues deja ecrites pour cette scene (F2). */
|
|
bool bBoundsLogged = false;
|
|
/** Dernier composant qui a refuse une place au glisser (une ligne par changement). */
|
|
FString LastSpotBlocker;
|
|
/** Derniere surface refusee au glisser (CAM-B2p-H, G-f : ni sol ni lit ; une ligne par changement). */
|
|
FString LastSurfaceRefused;
|
|
/** Focus clavier (H1, H2) : premiere image du sexe deja traitee ; bouton de souris tenu a l'image precedente. */
|
|
bool bSceneFocusChecked = false;
|
|
bool bFocusClickWasDown = false;
|
|
/** Place du meneur a la prise : au relacher, s'il a bouge, LPShowCouple reprend sa place sure (G3, STE). */
|
|
FVector GrabLeadStart = FVector::ZeroVector;
|
|
/** Camera de scene (CAM-B2p-G) : recadrage a l'entree en Scene et en C3 (variable SexC3 du PC), suivi du couple
|
|
* hors glisser, distance bornee. Appele par TickCoupleBounds, a chaque image pendant le sexe. */
|
|
void TickSceneCamera(UGameInstance* GI, AActor* Room, const TArray<AActor*>& Couple, const FVector& Pivot, bool bGrabEnded);
|
|
/** Place SceneCamera a distance par defaut du couple, dans la piece, devant le premier obstacle, regard sur le couple. */
|
|
void RecenterSceneCamera(UGameInstance* GI, AActor* Room, AActor* SceneCamera, const TArray<AActor*>& Couple, const FVector& Pivot, const TCHAR* Reason);
|
|
/** Vue a l'image precedente (detection de l'entree en Scene). */
|
|
TWeakObjectPtr<AActor> LastSexView;
|
|
/** PC.SexC3 a l'image precedente (front montant = passage en C3). */
|
|
bool bSexC3Was = false;
|
|
/** Clic molette court pendant le sexe (CAM-B2p-H, G-g) : appui puis relacher en 0,2 s au plus, curseur immobile
|
|
* a 5 px pres = PC.LeftMouseSexOn (bascule du panneau des positions). Appele seulement pendant le sexe, hors menu. */
|
|
void TickPanelClick(APlayerController* PC, float DeltaTime);
|
|
bool bMiddleWasDown = false;
|
|
bool bMiddleHadMouse = false;
|
|
bool bMiddleMoved = false;
|
|
float MiddleHeld = 0.f;
|
|
FVector2D MiddleStart = FVector2D::ZeroVector;
|
|
/** Aide des controles du sexe (CAM-B2p-I), toutes les 0,1 s : icone « i » dans le panneau des actions (Cursor), a cote
|
|
* du filtre SearchAction (survol = info-bulle, clic = boite d'aide), 4 lignes d'origine de SexInterface.TextBlock_1
|
|
* rendues invisibles quand le bloc porte ce texte. Hors du sexe : icone repliee, boite fermee. */
|
|
void TickControlsHelp();
|
|
/** Texte d'aide en anglais (langue du jeu), touches lues dans les mappages en cours. */
|
|
FString BuildControlsHelp() const;
|
|
/** Insere l'icone dans le parent de SearchAction ; nul (et une ligne de temoin) si SearchAction ou son parent manque. */
|
|
UButton* AttachHelpIcon(UUserWidget* ActionCursor);
|
|
UFUNCTION()
|
|
void ToggleControlsHelp();
|
|
bool EnsureHelpBox();
|
|
void RemoveHelpBox();
|
|
/** Instance du panneau deja traitee (insertion tentee une fois, reussie ou non). */
|
|
TWeakObjectPtr<UUserWidget> HelpCursor;
|
|
TWeakObjectPtr<UButton> HelpButton;
|
|
/** Bloc des 4 lignes rendu invisible, et son opacite d'avant. */
|
|
TWeakObjectPtr<UTextBlock> FadedHelpLines;
|
|
float FadedLinesOpacity = 1.f;
|
|
bool bHelpBoxOpen = false;
|
|
/** Dernier texte pose dans l'info-bulle de l'icone. */
|
|
FString HelpTextShown;
|
|
TSharedPtr<SWidget> HelpRoot;
|
|
TSharedPtr<STextBlock> HelpText;
|
|
TWeakObjectPtr<UGameViewportClient> HelpViewport;
|
|
/** Panneau bascule par Alt (et non par le clic molette) a l'appui en cours. */
|
|
bool bPanelByAlt = false;
|
|
/** CAM-B2p-I (COMMUN-12) : pendant le sexe, hors menu et sans bouton tenu, remet la souris libre (GameAndUI,
|
|
* DoNotLock) quand le PC l'a verrouillee (GameOnly) : sinon le curseur est fige et le glisser vaut 0. */
|
|
void KeepMouseFree(APlayerController* PC, float DeltaTime);
|
|
/** Debut et fin de scene : empreinte des touches ; a la fin, chaque etat touche par CAM est rendu, une ligne. */
|
|
void BeginSexScene();
|
|
void EndSexScene();
|
|
bool bSexStateWas = false;
|
|
FString MappingsAtSexStart;
|
|
bool bMouseFreed = false;
|
|
/** Etat de la souris au debut de la scene (EMouseCaptureMode, EMouseLockMode, curseur cache a l'appui), rendu a la fin. */
|
|
bool bSavedMouseState = false;
|
|
uint8 SavedCaptureMode = 0;
|
|
uint8 SavedLockMode = 0;
|
|
bool bSavedHideCursor = false;
|
|
int32 MouseFreeCount = 0;
|
|
float MouseFreeCooldown = 0.f;
|
|
/** Curseur de la prise : position reelle quand elle bouge, sinon deltas bruts de la souris (souris verrouillee). */
|
|
FVector2D GrabCursor = FVector2D::ZeroVector;
|
|
FVector2D GrabLastReal = FVector2D::ZeroVector;
|
|
int32 GrabRawFrames = 0;
|
|
bool bGrabAimWarned = false;
|
|
/** Pivot apres la derniere action de CAM pendant la prise (temoin des deplacements venus d'ailleurs). */
|
|
FVector GrabPivotAfterCam = FVector::ZeroVector;
|
|
double ExternalMoveLogTime = 0.0;
|
|
double SelectMissLogTime = 0.0;
|
|
TSharedPtr<SWidget> Root;
|
|
TSharedPtr<STextBlock> Text;
|
|
/** Viewport auquel Root a ete ajoute. */
|
|
TWeakObjectPtr<UGameViewportClient> Viewport;
|
|
/** Libelle actuellement ecrit dans Text (mis a jour seulement quand il change). */
|
|
FString ShownLabel;
|
|
bool bShown = false;
|
|
/** KEY2 (KEY2-SPEC-01 § 8c), en scene, hors menu, a chaque image : ActionPanel bascule le panneau d'action
|
|
* (PC.LeftMouseSexOn), CameraHeight monte ou baisse SceneCamera (hauteur ajoutee bornee), CoupleMoveY deplace le
|
|
* couple sur Y (piece cachee seulement, comme le X de PC). Rien ne bouge pendant une prise a la souris. */
|
|
void TickSceneKeys(APlayerController* PC, AActor* View, const UObject* Room, const TArray<AActor*>& Couple, bool bGrabbing, float Step);
|
|
/** Hauteur ajoutee a SceneCamera par CameraHeight depuis le dernier recadrage (cm). */
|
|
float SceneCameraLift = 0.f;
|
|
/** PC.SexC3 a l'image precedente, pour CameraHeight (le recadrage de C3 remet la hauteur ajoutee a zero). */
|
|
bool bLiftC3Was = false;
|
|
};
|