Select Git revision
postprocessing_new.ipynb
VHFacialExpressions.h 3.54 KiB
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Animation/PoseAsset.h"
#include "Misc/DefaultValueHelper.h"
#include "VHFacialExpressions.generated.h"
class UAnimInstance;
class AVirtualHuman;
UENUM()
enum Emotions
{
Neutral = 0 UMETA(DisplayName = "Neutral"),
Happiness = 1 UMETA(DisplayName = "Happiness"),
Sadness = 2 UMETA(DisplayName = "Sadness"),
Surprise = 3 UMETA(DisplayName = "Surprise"),
Fear = 4 UMETA(DisplayName = "Fear"),
Anger = 5 UMETA(DisplayName = "Anger"),
Disgust = 6 UMETA(DisplayName = "Disgust"),
Contempt = 7 UMETA(DisplayName = "Contempt"),
Custom = 9 UMETA(DisplayName = "Custom")
};
UENUM()
enum FACSSidedness
{
AU_Both = 0 UMETA(DisplayName = "Both"),
AU_Left = 1 UMETA(DisplayName = "Left"),
AU_Right = 2 UMETA(DisplayName = "Right")
};
// Action Units (from FACS) and their associated CharacterCreator 3 blendshapes
// AUs that are bSided, use the names BlendShapeName + "_L" and + "_R"
USTRUCT()
struct FAUBlendshape
{
GENERATED_BODY()
int ActionUnitNumber;
FString BlendShapeName;
float BlendShapeValue;
};
USTRUCT()
struct FAUPose
{
GENERATED_BODY()
int ActionUnitNumber;
bool bSided = false;
//if not sided, Blendshapes has one element
//if sided, Blendshapes has two elements: 0: left, 1: right
TArray<TArray<FAUBlendshape>> Blendshapes;
};
USTRUCT(BlueprintType, Blueprintable)
struct FACSValue
{
GENERATED_BODY()
int AUNumber;
float Value;
FACSSidedness Side;
};
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class CHARACTERPLUGIN_API UVHFacialExpressions : public UActorComponent
{
GENERATED_BODY()
public:
UVHFacialExpressions();
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
// returns true if AU is mapped, so if false is returned, nothing is set
// or if interpolation is in progress
// if an unsided FACS unit is given, Side is ignored
UFUNCTION(BlueprintCallable)
bool SetFACSActionUnit(int AUNumber, float Value, FACSSidedness Side = AU_Both);
UFUNCTION(BlueprintCallable)
void VHSetFACSValues(TArray<FACSValue> FACSValues);
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TEnumAsByte<Emotions> SelectedEmotion = Neutral;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
UPoseAsset* Mapping = nullptr;
// Blendshapes interpolation speed factor
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float InterpSpeed = 1.0;
// Controls the influence of LipSync Component
UPROPERTY(BlueprintReadWrite,EditAnywhere)
float LipSyncWeight = 1.0f;
// Used to "call" an update of already selected pose on demand
UPROPERTY(BlueprintReadWrite,EditAnywhere)
bool isPoseDirty = false;
TMap<FName, float>& GetCurrentAnimationValues();
protected:
virtual void BeginPlay() override;
void SetupAUMapping();
private:
bool UpdateFACS(Emotions Emotion, float DeltaTime);
bool ResetFACS(float DeltaTime);
void VHSetMorphTarget(FString Name, float Value);
bool VHSetMorphTarget(FString Name, float Value, float DeltaTime);
bool SetFACSActionUnit(int AUNumber, float Value, float DeltaTime, FACSSidedness Side = AU_Both);
UAnimInstance* AnimInstance = nullptr;
AVirtualHuman* owner = nullptr;
TEnumAsByte<Emotions> CurrentEmotion = Neutral;
TEnumAsByte<Emotions> LastSelectedEmotion;
TMap<FName, TMap<Emotions, float>> FacialExpressionsLibrary;
TMap<Emotions, TArray<FACSValue>> FACSExpressionsLibrary;
TMap<int, FAUPose> AUPoses;
TMap<FName, float> CurrentAnimationValues;
private:
TSet<FString> EvaluatedNames;
};