147 lines
5.2 KiB
C++
147 lines
5.2 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "GameFramework/Actor.h"
|
|
#include "CharacterAppearanceTypes.h"
|
|
#include "CharacterPreviewActor.generated.h"
|
|
|
|
class UCameraComponent;
|
|
class UCharacterAppearanceComponent;
|
|
class USkeletalMeshComponent;
|
|
|
|
/**
|
|
* Les deux cadrages de l'ecran de customisation.
|
|
*
|
|
* Deux et pas un par categorie : ce qu'on veut, c'est voir le visage quand on
|
|
* choisit une barbe et la silhouette entiere quand on choisit un corps. Un
|
|
* cadrage par categorie donnerait onze reglages a poser a la main pour onze
|
|
* fois le meme resultat.
|
|
*/
|
|
UENUM(BlueprintType)
|
|
enum class ECharacterPreviewFraming : uint8
|
|
{
|
|
FullBody,
|
|
Face,
|
|
|
|
Count UMETA(Hidden)
|
|
};
|
|
|
|
/**
|
|
* Le mannequin de l'ecran de customisation : un personnage pose dans la map de
|
|
* menu, qu'on fait tourner a la souris et que la camera cadre selon ce que le
|
|
* joueur est en train de regler.
|
|
*
|
|
* Il porte le MEME UCharacterAppearanceComponent que le pawn de jeu, et c'est
|
|
* tout l'interet : le personnage qu'on regarde ici est monte par exactement le
|
|
* code qui montera celui que les autres joueurs verront. Deux chemins de
|
|
* montage finiraient par diverger, et le joueur s'en apercevrait au pire
|
|
* moment -- une fois en partie.
|
|
*/
|
|
UCLASS()
|
|
class EMBERWILD_API ACharacterPreviewActor : public AActor
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
ACharacterPreviewActor();
|
|
|
|
virtual void Tick(float DeltaSeconds) override;
|
|
|
|
/** Monte l'apparence sur le mannequin. */
|
|
UFUNCTION(BlueprintCallable, Category = "Preview")
|
|
void ApplyAppearance(const FCharacterAppearance& InAppearance);
|
|
|
|
/** La camera glisse vers le cadrage demande. Sans effet s'il y est deja. */
|
|
UFUNCTION(BlueprintCallable, Category = "Preview")
|
|
void SetFraming(ECharacterPreviewFraming NewFraming);
|
|
|
|
/** Fait pivoter le personnage. Appelee pendant un clic-glisser. */
|
|
UFUNCTION(BlueprintCallable, Category = "Preview")
|
|
void AddPreviewYaw(float DeltaDegrees);
|
|
|
|
/** Remet le personnage face a la camera. */
|
|
UFUNCTION(BlueprintCallable, Category = "Preview")
|
|
void ResetPreviewYaw();
|
|
|
|
UFUNCTION(BlueprintPure, Category = "Preview")
|
|
UCameraComponent* GetPreviewCamera() const { return PreviewCamera; }
|
|
|
|
UFUNCTION(BlueprintPure, Category = "Preview")
|
|
UCharacterAppearanceComponent* GetAppearanceComponent() const { return AppearanceComponent; }
|
|
|
|
/** Le reglage vit ici et pas sur le widget : c'est une sensibilite de camera. */
|
|
UFUNCTION(BlueprintPure, Category = "Preview")
|
|
float GetYawPerPixel() const { return YawPerPixel; }
|
|
|
|
protected:
|
|
virtual void BeginPlay() override;
|
|
|
|
/** Le porteur d'animation et de pose ; les pieces s'y accrochent. */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Preview")
|
|
TObjectPtr<USkeletalMeshComponent> BodyMesh;
|
|
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Preview")
|
|
TObjectPtr<UCharacterAppearanceComponent> AppearanceComponent;
|
|
|
|
/**
|
|
* Pivot de rotation, entre la racine et le mesh.
|
|
*
|
|
* Le personnage tourne en faisant pivoter CE composant et jamais l'acteur :
|
|
* la camera est fille de l'acteur, la faire tourner avec lui donnerait un
|
|
* decor qui defile pendant qu'on regarde un personnage immobile.
|
|
*/
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Preview")
|
|
TObjectPtr<USceneComponent> TurntablePivot;
|
|
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Preview")
|
|
TObjectPtr<UCameraComponent> PreviewCamera;
|
|
|
|
/**
|
|
* Les deux positions de camera, a placer A LA SOURIS dans le viewport du
|
|
* Blueprint plutot qu'a taper en coordonnees.
|
|
*
|
|
* Ce sont des reperes vides : la camera n'y est pas accrochee, elle glisse
|
|
* vers eux. Sans quoi changer de categorie la ferait sauter d'un cadrage a
|
|
* l'autre, ce qui se lit comme une coupure de montage.
|
|
*/
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Preview|Framing")
|
|
TObjectPtr<USceneComponent> FullBodyViewSpot;
|
|
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Preview|Framing")
|
|
TObjectPtr<USceneComponent> FaceViewSpot;
|
|
|
|
/**
|
|
* Vitesse de glissement de la camera entre deux cadrages.
|
|
*
|
|
* Une vitesse d'interpolation et pas une duree : le mouvement freine en
|
|
* arrivant au lieu de s'arreter net, et deux changements de categorie
|
|
* coup sur coup s'enchainent sans a-coup -- la camera repart d'ou elle est.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Preview|Framing", meta = (ClampMin = "0.5"))
|
|
float FramingInterpSpeed = 6.f;
|
|
|
|
/** Degres de rotation par pixel de deplacement horizontal de la souris. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Preview|Turntable")
|
|
float YawPerPixel = 0.35f;
|
|
|
|
private:
|
|
/** Le repere vise par la camera, selon le cadrage courant. */
|
|
USceneComponent* GetSpotForFraming(ECharacterPreviewFraming InFraming) const;
|
|
|
|
/**
|
|
* Coupe le Tick quand la camera est arrivee.
|
|
*
|
|
* Meme principe que le couvercle d'AStorageContainer : cet acteur ne tick
|
|
* que pendant qu'il bouge. Un mannequin immobile dans un menu n'a aucune
|
|
* raison de couter une frame.
|
|
*/
|
|
void UpdateFramingInterpolation(float DeltaSeconds);
|
|
|
|
ECharacterPreviewFraming CurrentFraming = ECharacterPreviewFraming::FullBody;
|
|
|
|
/** Rotation accumulee par le clic-glisser, en degres. */
|
|
float TurntableYaw = 0.f;
|
|
};
|