RealtimeStyleTransferRuntime/Source/LyraGame/Cosmetics/LyraPawnComponent_Character...

186 lines
6.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Components/PawnComponent.h"
#include "Containers/Array.h"
#include "Containers/ArrayView.h"
#include "Containers/Map.h"
#include "Containers/Set.h"
#include "Containers/SparseArray.h"
#include "Containers/UnrealString.h"
#include "CoreTypes.h"
#include "Cosmetics/LyraCosmeticAnimationTypes.h"
#include "Delegates/Delegate.h"
#include "Engine/EngineTypes.h"
#include "GameplayTagContainer.h"
#include "LyraCharacterPartTypes.h"
#include "Net/Serialization/FastArraySerializer.h"
#include "Templates/UnrealTemplate.h"
#include "UObject/Class.h"
#include "UObject/ObjectPtr.h"
#include "UObject/UObjectGlobals.h"
#include "LyraPawnComponent_CharacterParts.generated.h"
class AActor;
class UChildActorComponent;
class UObject;
class USceneComponent;
class USkeletalMeshComponent;
struct FFrame;
struct FNetDeltaSerializeInfo;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLyraSpawnedCharacterPartsChanged, ULyraPawnComponent_CharacterParts*, ComponentWithChangedParts);
//////////////////////////////////////////////////////////////////////
// A single applied character part
USTRUCT()
struct FLyraAppliedCharacterPartEntry : public FFastArraySerializerItem
{
GENERATED_BODY()
FLyraAppliedCharacterPartEntry()
{}
FString GetDebugString() const;
private:
friend FLyraCharacterPartList;
friend ULyraPawnComponent_CharacterParts;
private:
// The character part being represented
UPROPERTY()
FLyraCharacterPart Part;
// Handle index we returned to the user (server only)
UPROPERTY(NotReplicated)
int32 PartHandle = INDEX_NONE;
// The spawned actor instance (client only)
UPROPERTY(NotReplicated)
TObjectPtr<UChildActorComponent> SpawnedComponent = nullptr;
};
//////////////////////////////////////////////////////////////////////
// Replicated list of applied character parts
USTRUCT(BlueprintType)
struct FLyraCharacterPartList : public FFastArraySerializer
{
GENERATED_BODY()
FLyraCharacterPartList()
: OwnerComponent(nullptr)
{
}
FLyraCharacterPartList(ULyraPawnComponent_CharacterParts* InOwnerComponent)
: OwnerComponent(InOwnerComponent)
{
}
public:
//~FFastArraySerializer contract
void PreReplicatedRemove(const TArrayView<int32> RemovedIndices, int32 FinalSize);
void PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize);
void PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize);
//~End of FFastArraySerializer contract
bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms)
{
return FFastArraySerializer::FastArrayDeltaSerialize<FLyraAppliedCharacterPartEntry, FLyraCharacterPartList>(Entries, DeltaParms, *this);
}
FLyraCharacterPartHandle AddEntry(FLyraCharacterPart NewPart);
void RemoveEntry(FLyraCharacterPartHandle Handle);
void ClearAllEntries(bool bBroadcastChangeDelegate);
FGameplayTagContainer CollectCombinedTags() const;
private:
friend ULyraPawnComponent_CharacterParts;
bool SpawnActorForEntry(FLyraAppliedCharacterPartEntry& Entry);
bool DestroyActorForEntry(FLyraAppliedCharacterPartEntry& Entry);
private:
// Replicated list of equipment entries
UPROPERTY()
TArray<FLyraAppliedCharacterPartEntry> Entries;
// The component that contains this list
UPROPERTY(NotReplicated)
TObjectPtr<ULyraPawnComponent_CharacterParts> OwnerComponent;
// Upcounter for handles
int32 PartHandleCounter = 0;
};
template<>
struct TStructOpsTypeTraits<FLyraCharacterPartList> : public TStructOpsTypeTraitsBase2<FLyraCharacterPartList>
{
enum { WithNetDeltaSerializer = true };
};
//////////////////////////////////////////////////////////////////////
// A component that handles spawning cosmetic actors attached to the owner pawn on all clients
UCLASS(meta=(BlueprintSpawnableComponent))
class ULyraPawnComponent_CharacterParts : public UPawnComponent
{
GENERATED_BODY()
public:
ULyraPawnComponent_CharacterParts(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
//~UActorComponent interface
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
//~End of UActorComponent interface
// Adds a character part to the actor that owns this customization component, should be called on the authority only
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Cosmetics)
FLyraCharacterPartHandle AddCharacterPart(const FLyraCharacterPart& NewPart);
// Removes a previously added character part from the actor that owns this customization component, should be called on the authority only
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Cosmetics)
void RemoveCharacterPart(FLyraCharacterPartHandle Handle);
// Removes all added character parts, should be called on the authority only
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Cosmetics)
void RemoveAllCharacterParts();
// Gets the list of all spawned character parts from this component
UFUNCTION(BlueprintCallable, BlueprintPure=false, BlueprintCosmetic, Category=Cosmetics)
TArray<AActor*> GetCharacterPartActors() const;
// If the parent actor is derived from ACharacter, returns the Mesh component, otherwise nullptr
USkeletalMeshComponent* GetParentMeshComponent() const;
// Returns the scene component to attach the spawned actors to
// If the parent actor is derived from ACharacter, we'll use the Mesh component, otherwise the root component
USceneComponent* GetSceneComponentToAttachTo() const;
// Returns the set of combined gameplay tags from attached character parts, optionally filtered to only tags that start with the specified root
UFUNCTION(BlueprintCallable, BlueprintPure=false, BlueprintCosmetic, Category=Cosmetics)
FGameplayTagContainer GetCombinedTags(FGameplayTag RequiredPrefix) const;
void BroadcastChanged();
public:
// Delegate that will be called when the list of spawned character parts has changed
UPROPERTY(BlueprintAssignable, Category=Cosmetics, BlueprintCallable)
FLyraSpawnedCharacterPartsChanged OnCharacterPartsChanged;
private:
// List of character parts
UPROPERTY(Replicated)
FLyraCharacterPartList CharacterPartList;
// Rules for how to pick a body style mesh for animation to play on, based on character part cosmetics tags
UPROPERTY(EditAnywhere, Category=Cosmetics)
FLyraAnimBodyStyleSelectionSet BodyMeshes;
};