186 lines
6.4 KiB
C++
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;
|
|
};
|