(Feat) Add Animation Fps Charater
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "PlayerNameplateComponent.h"
|
||||
|
||||
#include "Engine/Engine.h"
|
||||
#include "Engine/World.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "GameFramework/PlayerState.h"
|
||||
#include "PlayerNameplateWidget.h"
|
||||
|
||||
UPlayerNameplateComponent::UPlayerNameplateComponent()
|
||||
{
|
||||
// Espace ecran : l'etiquette fait toujours face a la camera, par
|
||||
// construction, et n'est jamais occultee par le decor.
|
||||
SetWidgetSpace(EWidgetSpace::Screen);
|
||||
|
||||
// Le widget se dimensionne sur son contenu : un pseudo court n'a pas a
|
||||
// trainer une boite de la largeur du plus long.
|
||||
SetDrawAtDesiredSize(true);
|
||||
|
||||
// Une etiquette ne se vise pas et n'arrete pas un trace : sans ca, elle
|
||||
// bloquerait le canal Visibility et masquerait l'interaction du joueur
|
||||
// qu'elle surmonte.
|
||||
SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
SetGenerateOverlapEvents(false);
|
||||
|
||||
// Au-dessus de la tete. Reglable dans le Blueprint, la capsule et la taille
|
||||
// du personnage pouvant changer.
|
||||
SetRelativeLocation(FVector(0.f, 0.f, 100.f));
|
||||
|
||||
// Cachee au depart : la premiere passe decidera. Sans ca, une etiquette
|
||||
// sans nom clignote pendant la frame qui precede l'arrivee du PlayerState.
|
||||
SetVisibility(false);
|
||||
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void UPlayerNameplateComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
// Un serveur dedie ne rend rien : lui faire calculer des distances pour des
|
||||
// etiquettes que personne ne verra serait du gaspillage pur. Sans effet sur
|
||||
// notre serveur d'ecoute, qui n'est pas dans ce mode.
|
||||
if (GetNetMode() == NM_DedicatedServer)
|
||||
{
|
||||
SetComponentTickEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const APawn* OwnerPawn = Cast<APawn>(GetOwner());
|
||||
|
||||
// Son propre pseudo : on eteint definitivement, tick compris. Ce n'est pas
|
||||
// un cas a reevaluer -- un pawn ne change pas de proprietaire en cours de
|
||||
// vie, et apres un respawn c'est un NOUVEL acteur qui repassera par ici.
|
||||
if (bHideOnOwningPlayer && OwnerPawn && OwnerPawn->IsLocallyControlled())
|
||||
{
|
||||
SetVisibility(false);
|
||||
SetComponentTickEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
APlayerState* UPlayerNameplateComponent::GetOwnerPlayerState() const
|
||||
{
|
||||
const APawn* OwnerPawn = Cast<APawn>(GetOwner());
|
||||
return OwnerPawn ? OwnerPawn->GetPlayerState() : nullptr;
|
||||
}
|
||||
|
||||
void UPlayerNameplateComponent::RefreshName()
|
||||
{
|
||||
// Le PlayerState arrive APRES le pawn chez un client : la premiere passe
|
||||
// trouve donc un nom vide, et il faut continuer a regarder.
|
||||
const APlayerState* State = GetOwnerPlayerState();
|
||||
if (!State)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const FString CurrentName = State->GetPlayerName();
|
||||
if (CurrentName.IsEmpty() || CurrentName == LastShownName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (UPlayerNameplateWidget* Nameplate = Cast<UPlayerNameplateWidget>(GetUserWidgetObject()))
|
||||
{
|
||||
Nameplate->SetPlayerName(FText::FromString(CurrentName));
|
||||
LastShownName = CurrentName;
|
||||
}
|
||||
}
|
||||
|
||||
void UPlayerNameplateComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
// Le point de vue du joueur LOCAL, et non celui du pawn porteur : c'est de
|
||||
// notre ecran qu'on parle. GetFirstLocalPlayerController et non
|
||||
// GetFirstPlayerController -- en PIE a deux fenetres, le second rendrait le
|
||||
// controller de l'autre instance et l'etiquette clignoterait.
|
||||
const APlayerController* Viewer = GEngine ? GEngine->GetFirstLocalPlayerController(GetWorld()) : nullptr;
|
||||
if (!Viewer || !Viewer->PlayerCameraManager)
|
||||
{
|
||||
SetVisibility(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const float Distance = FVector::Dist(
|
||||
Viewer->PlayerCameraManager->GetCameraLocation(),
|
||||
GetComponentLocation());
|
||||
|
||||
// Au-dela de la portee on eteint le composant lui-meme, pas seulement son
|
||||
// opacite : un widget transparent continue d'etre projete et dessine.
|
||||
if (Distance > MaxDrawDistance)
|
||||
{
|
||||
SetVisibility(false);
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshName();
|
||||
|
||||
// Sans nom a montrer, rien a montrer du tout.
|
||||
if (LastShownName.IsEmpty())
|
||||
{
|
||||
SetVisibility(false);
|
||||
return;
|
||||
}
|
||||
|
||||
UPlayerNameplateWidget* Nameplate = Cast<UPlayerNameplateWidget>(GetUserWidgetObject());
|
||||
if (!Nameplate)
|
||||
{
|
||||
SetVisibility(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Echelle en 1/d : c'est la loi de la perspective, et c'est ce que l'oeil
|
||||
// attend. A ReferenceDistance l'etiquette vaut exactement ce qui est dessine
|
||||
// dans le WBP ; deux fois plus pres elle double, deux fois plus loin elle
|
||||
// est de moitie -- borne des deux cotes.
|
||||
const float SafeDistance = FMath::Max(Distance, 1.f);
|
||||
const float Scale = FMath::Clamp(ReferenceDistance / SafeDistance, MinScale, MaxScale);
|
||||
Nameplate->SetRenderScale(FVector2D(Scale, Scale));
|
||||
|
||||
// Fondu sur la derniere bande avant la portee maximale. FadeLength est
|
||||
// borne a MaxDrawDistance : un fondu plus long que la portee elle-meme
|
||||
// donnerait une etiquette jamais totalement opaque.
|
||||
const float EffectiveFade = FMath::Clamp(FadeLength, 0.f, MaxDrawDistance);
|
||||
float Opacity = 1.f;
|
||||
if (EffectiveFade > KINDA_SMALL_NUMBER)
|
||||
{
|
||||
const float FadeStart = MaxDrawDistance - EffectiveFade;
|
||||
Opacity = FMath::Clamp(1.f - (Distance - FadeStart) / EffectiveFade, 0.f, 1.f);
|
||||
}
|
||||
Nameplate->SetRenderOpacity(Opacity);
|
||||
|
||||
SetVisibility(true);
|
||||
}
|
||||
Reference in New Issue
Block a user