(Feat) Add footsteps
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "CharacterPreviewActor.h"
|
||||
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "CharacterAppearanceComponent.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
|
||||
ACharacterPreviewActor::ACharacterPreviewActor()
|
||||
{
|
||||
// Allume par SetFraming et eteint des que la camera est arrivee. Un
|
||||
// mannequin immobile dans un menu n'a aucune raison de couter une frame.
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
PrimaryActorTick.bStartWithTickEnabled = false;
|
||||
|
||||
USceneComponent* SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
|
||||
SetRootComponent(SceneRoot);
|
||||
|
||||
TurntablePivot = CreateDefaultSubobject<USceneComponent>(TEXT("TurntablePivot"));
|
||||
TurntablePivot->SetupAttachment(SceneRoot);
|
||||
|
||||
BodyMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("BodyMesh"));
|
||||
BodyMesh->SetupAttachment(TurntablePivot);
|
||||
// Aucune collision : c'est un decor de menu, rien ne doit le heurter ni le
|
||||
// tracer.
|
||||
BodyMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
|
||||
// Les reperes de cadrage sont filles de la RACINE et pas du pivot : ils ne
|
||||
// doivent surtout pas tourner avec le personnage, sinon la camera suivrait
|
||||
// le clic-glisser au lieu de le montrer.
|
||||
FullBodyViewSpot = CreateDefaultSubobject<USceneComponent>(TEXT("FullBodyViewSpot"));
|
||||
FullBodyViewSpot->SetupAttachment(SceneRoot);
|
||||
FullBodyViewSpot->SetRelativeLocation(FVector(260.f, 60.f, 95.f));
|
||||
FullBodyViewSpot->SetRelativeRotation(FRotator(0.f, 180.f, 0.f));
|
||||
|
||||
FaceViewSpot = CreateDefaultSubobject<USceneComponent>(TEXT("FaceViewSpot"));
|
||||
FaceViewSpot->SetupAttachment(SceneRoot);
|
||||
FaceViewSpot->SetRelativeLocation(FVector(90.f, 25.f, 165.f));
|
||||
FaceViewSpot->SetRelativeRotation(FRotator(0.f, 180.f, 0.f));
|
||||
|
||||
PreviewCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("PreviewCamera"));
|
||||
PreviewCamera->SetupAttachment(SceneRoot);
|
||||
|
||||
AppearanceComponent = CreateDefaultSubobject<UCharacterAppearanceComponent>(TEXT("AppearanceComponent"));
|
||||
}
|
||||
|
||||
void ACharacterPreviewActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
// Le composant cherche le mesh d'un ACharacter par defaut ; ici il n'y en a
|
||||
// pas, on lui designe le notre.
|
||||
if (AppearanceComponent)
|
||||
{
|
||||
AppearanceComponent->SetTargetMesh(BodyMesh);
|
||||
}
|
||||
|
||||
// Pose la camera sur le cadrage de depart sans interpolation : glisser
|
||||
// depuis l'origine de l'acteur au premier affichage montrerait un travelling
|
||||
// que personne n'a demande.
|
||||
if (const USceneComponent* Spot = GetSpotForFraming(CurrentFraming))
|
||||
{
|
||||
PreviewCamera->SetRelativeLocationAndRotation(Spot->GetRelativeLocation(), Spot->GetRelativeRotation());
|
||||
}
|
||||
}
|
||||
|
||||
void ACharacterPreviewActor::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
|
||||
UpdateFramingInterpolation(DeltaSeconds);
|
||||
}
|
||||
|
||||
void ACharacterPreviewActor::ApplyAppearance(const FCharacterAppearance& InAppearance)
|
||||
{
|
||||
if (AppearanceComponent)
|
||||
{
|
||||
AppearanceComponent->ApplyAppearance(InAppearance);
|
||||
}
|
||||
}
|
||||
|
||||
void ACharacterPreviewActor::SetFraming(ECharacterPreviewFraming NewFraming)
|
||||
{
|
||||
if (CurrentFraming == NewFraming)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentFraming = NewFraming;
|
||||
SetActorTickEnabled(true);
|
||||
}
|
||||
|
||||
void ACharacterPreviewActor::AddPreviewYaw(float DeltaDegrees)
|
||||
{
|
||||
TurntableYaw = FRotator::NormalizeAxis(TurntableYaw + DeltaDegrees);
|
||||
|
||||
if (TurntablePivot)
|
||||
{
|
||||
TurntablePivot->SetRelativeRotation(FRotator(0.f, TurntableYaw, 0.f));
|
||||
}
|
||||
}
|
||||
|
||||
void ACharacterPreviewActor::ResetPreviewYaw()
|
||||
{
|
||||
TurntableYaw = 0.f;
|
||||
|
||||
if (TurntablePivot)
|
||||
{
|
||||
TurntablePivot->SetRelativeRotation(FRotator::ZeroRotator);
|
||||
}
|
||||
}
|
||||
|
||||
USceneComponent* ACharacterPreviewActor::GetSpotForFraming(ECharacterPreviewFraming InFraming) const
|
||||
{
|
||||
return (InFraming == ECharacterPreviewFraming::Face) ? FaceViewSpot : FullBodyViewSpot;
|
||||
}
|
||||
|
||||
void ACharacterPreviewActor::UpdateFramingInterpolation(float DeltaSeconds)
|
||||
{
|
||||
const USceneComponent* Spot = GetSpotForFraming(CurrentFraming);
|
||||
if (!Spot || !PreviewCamera)
|
||||
{
|
||||
SetActorTickEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const FVector TargetLocation = Spot->GetRelativeLocation();
|
||||
const FRotator TargetRotation = Spot->GetRelativeRotation();
|
||||
|
||||
const FVector NewLocation = FMath::VInterpTo(
|
||||
PreviewCamera->GetRelativeLocation(), TargetLocation, DeltaSeconds, FramingInterpSpeed);
|
||||
const FRotator NewRotation = FMath::RInterpTo(
|
||||
PreviewCamera->GetRelativeRotation(), TargetRotation, DeltaSeconds, FramingInterpSpeed);
|
||||
|
||||
PreviewCamera->SetRelativeLocationAndRotation(NewLocation, NewRotation);
|
||||
|
||||
// Un interpolateur exponentiel n'atteint jamais sa cible exactement : sans
|
||||
// ce seuil, le Tick ne s'eteindrait plus jamais. On termine le dernier
|
||||
// millimetre d'un coup, il ne se voit pas.
|
||||
const bool bLocationReached = NewLocation.Equals(TargetLocation, 0.5f);
|
||||
const bool bRotationReached = NewRotation.Equals(TargetRotation, 0.5f);
|
||||
|
||||
if (bLocationReached && bRotationReached)
|
||||
{
|
||||
PreviewCamera->SetRelativeLocationAndRotation(TargetLocation, TargetRotation);
|
||||
SetActorTickEnabled(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user