113 lines
3.3 KiB
C++
113 lines
3.3 KiB
C++
|
|
// Portage UE 5.5 - voir LPSecondScreenSubsystem.h
|
||
|
|
|
||
|
|
#include "LPSecondScreenSubsystem.h"
|
||
|
|
|
||
|
|
#include "Components/CapsuleComponent.h"
|
||
|
|
#include "Components/SceneCaptureComponent2D.h"
|
||
|
|
#include "Components/SkeletalMeshComponent.h"
|
||
|
|
#include "Engine/GameInstance.h"
|
||
|
|
#include "Engine/SceneCapture2D.h"
|
||
|
|
#include "Engine/World.h"
|
||
|
|
#include "EngineUtils.h"
|
||
|
|
#include "GameFramework/Character.h"
|
||
|
|
#include "LifePlay.h"
|
||
|
|
#include "UObject/UnrealType.h"
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
// Cadrage du visage : distance camera-tete (cm) et champ horizontal (degres).
|
||
|
|
constexpr float FaceDistance = 80.f;
|
||
|
|
constexpr float FaceFOV = 30.f;
|
||
|
|
const FName CaptureActorName(TEXT("SecondScreen"));
|
||
|
|
const FName PersonPropertyName(TEXT("SecondScreenPerson"));
|
||
|
|
const FName HeadSocket(TEXT("head"));
|
||
|
|
|
||
|
|
/** Position de la tete : os "head" du premier maillage qui le porte, sinon haut de la capsule. */
|
||
|
|
FVector HeadLocation(const AActor* Person)
|
||
|
|
{
|
||
|
|
TInlineComponentArray<USkeletalMeshComponent*> Meshes(Person);
|
||
|
|
for (const USkeletalMeshComponent* Mesh : Meshes)
|
||
|
|
{
|
||
|
|
if (Mesh && Mesh->GetSkinnedAsset() && Mesh->DoesSocketExist(HeadSocket))
|
||
|
|
{
|
||
|
|
return Mesh->GetSocketLocation(HeadSocket);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (const ACharacter* Character = Cast<ACharacter>(Person))
|
||
|
|
{
|
||
|
|
if (const UCapsuleComponent* Capsule = Character->GetCapsuleComponent())
|
||
|
|
{
|
||
|
|
return Capsule->GetComponentLocation() + FVector(0.f, 0.f, Capsule->GetScaledCapsuleHalfHeight() * 0.8f);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return Person->GetActorLocation();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void ULPSecondScreenSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||
|
|
{
|
||
|
|
Super::Initialize(Collection);
|
||
|
|
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &ULPSecondScreenSubsystem::Tick));
|
||
|
|
}
|
||
|
|
|
||
|
|
void ULPSecondScreenSubsystem::Deinitialize()
|
||
|
|
{
|
||
|
|
FTSTicker::GetCoreTicker().RemoveTicker(TickHandle);
|
||
|
|
Super::Deinitialize();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ULPSecondScreenSubsystem::Tick(float DeltaTime)
|
||
|
|
{
|
||
|
|
const UGameInstance* GI = GetGameInstance();
|
||
|
|
UWorld* World = GI ? GI->GetWorld() : nullptr;
|
||
|
|
if (!World)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// La camera est recherchee une fois par monde (par nom d'objet : l'etiquette n'existe pas en Shipping).
|
||
|
|
if (CaptureWorld.Get() != World)
|
||
|
|
{
|
||
|
|
CaptureWorld = World;
|
||
|
|
Capture.Reset();
|
||
|
|
for (TActorIterator<ASceneCapture2D> It(World); It; ++It)
|
||
|
|
{
|
||
|
|
if (It->GetFName() == CaptureActorName)
|
||
|
|
{
|
||
|
|
Capture = *It;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
ASceneCapture2D* CaptureActor = Capture.Get();
|
||
|
|
USceneCaptureComponent2D* CaptureComp = CaptureActor ? CaptureActor->GetCaptureComponent2D() : nullptr;
|
||
|
|
if (!CaptureComp)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
const FObjectPropertyBase* Prop = CastField<FObjectPropertyBase>(GI->GetClass()->FindPropertyByName(PersonPropertyName));
|
||
|
|
const AActor* Person = Prop ? Cast<AActor>(Prop->GetObjectPropertyValue_InContainer(GI)) : nullptr;
|
||
|
|
if (!IsValid(Person))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
const FVector Head = HeadLocation(Person);
|
||
|
|
FVector Forward = Person->GetActorForwardVector();
|
||
|
|
Forward.Z = 0.f;
|
||
|
|
if (!Forward.Normalize())
|
||
|
|
{
|
||
|
|
Forward = FVector::ForwardVector;
|
||
|
|
}
|
||
|
|
const FVector CameraLocation = Head + Forward * FaceDistance;
|
||
|
|
if (CaptureComp->Mobility != EComponentMobility::Movable)
|
||
|
|
{
|
||
|
|
// Composant pose dans la carte : un composant statique refuse d'etre deplace en jeu.
|
||
|
|
CaptureComp->SetMobility(EComponentMobility::Movable);
|
||
|
|
}
|
||
|
|
CaptureComp->SetWorldLocationAndRotation(CameraLocation, (Head - CameraLocation).Rotation());
|
||
|
|
CaptureComp->FOVAngle = FaceFOV;
|
||
|
|
return true;
|
||
|
|
}
|