Migration

This commit is contained in:
2024-03-20 16:21:19 +01:00
commit 4d87f6e4ab
1847 changed files with 19406 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "0.1",
"FriendlyName": "CompositeEquipmentSystem",
"Description": "Equipment system to attach elements to a character skeletal mesh",
"Category": "Gameplay",
"CreatedBy": "Amasson",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": true,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "CompositeEquipmentSystem",
"Type": "Runtime",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "Niagara",
"Enabled": true
}
]
}

Binary file not shown.

View File

@@ -0,0 +1,54 @@
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class CompositeEquipmentSystem : ModuleRules
{
public CompositeEquipmentSystem(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"Niagara",
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}

View File

@@ -0,0 +1,237 @@
// Amasson
#include "Components/CompositeEquipmentComponent.h"
#include "Kismet/GameplayStatics.h"
#include "NiagaraFunctionLibrary.h"
#include "NiagaraComponent.h"
UCompositeEquipmentComponent::UCompositeEquipmentComponent()
{
PrimaryComponentTick.bCanEverTick = false;
}
void UCompositeEquipmentComponent::InitializeWithLeaderPose(USkeletalMeshComponent* NewLeaderPose)
{
LeaderPoseComponent = NewLeaderPose;
PoseOwner = IsValid(LeaderPoseComponent) ? LeaderPoseComponent->GetOwner() : nullptr;
UpdateCompositesObjects();
}
void UCompositeEquipmentComponent::AddCompositeName(FName CompositeName)
{
CompositeNames.Add(CompositeName);
UpdateCompositesObjects();
}
void UCompositeEquipmentComponent::RemoveCompositeName(FName CompositeName)
{
CompositeNames.Remove(CompositeName);
UpdateCompositesObjects();
}
void UCompositeEquipmentComponent::SetCompositeNames(const TSet<FName>& NewCompositeNames)
{
CompositeNames = NewCompositeNames;
UpdateCompositesObjects();
}
void UCompositeEquipmentComponent::AddCompositeCustom(const FEquipmentComposite& Composite, FName KeyName)
{
if (CompositeNames.Remove(KeyName))
DestroyRemovedComposites();
CompositeNames.Add(KeyName);
CreateCompositeWithKey(Composite, KeyName);
UpdateCompositesObjects();
}
/** Private */
void UCompositeEquipmentComponent::UpdateCompositesObjects()
{
DestroyRemovedComposites();
CreateAddedComposites();
OnEquipedCompositesUpdated.Broadcast(this);
}
void UCompositeEquipmentComponent::DestroyRemovedComposites()
{
TArray<FName> KeysToRemove;
for (TPair<FName, FEquipmentCompositeGeneratedObjects>& NameAndGeneratedObjects : GeneratedObjectsForCompositeNames)
{
const FName& CompositeName(NameAndGeneratedObjects.Key);
FEquipmentCompositeGeneratedObjects& GeneratedObjects(NameAndGeneratedObjects.Value);
bool bShouldRemoveKey = !CompositeNames.Contains(CompositeName);
if (bShouldRemoveKey)
{
GeneratedObjects.Destroy();
KeysToRemove.Add(CompositeName);
}
}
for (const FName& Key : KeysToRemove)
{
GeneratedObjectsForCompositeNames.Remove(Key);
}
}
void UCompositeEquipmentComponent::CreateAddedComposites()
{
for (const FName& CompositeName : CompositeNames)
{
if (!GeneratedObjectsForCompositeNames.Contains(CompositeName))
CreateCompositeFromTable(CompositeName);
}
}
void UCompositeEquipmentComponent::CreateCompositeFromTable(const FName& CompositeName)
{
if (IsValid(EquipmentTable))
{
FEquipmentComposite* CompositeRow = EquipmentTable->FindRow<FEquipmentComposite>(CompositeName, "Fetch Equipment Data");
if (CompositeRow)
{
CreateCompositeWithKey(*CompositeRow, CompositeName);
return;
}
}
/**
* In case of invalid name, we still create an empty object in our
* GeneratedObjectsForCompositeNames array to prevent future lookup
* that would waste performances
*/
CreateCompositeWithKey(FEquipmentComposite(), CompositeName);
}
void UCompositeEquipmentComponent::CreateCompositeWithKey(const FEquipmentComposite& Composite, const FName& CompositeKey)
{
FEquipmentCompositeGeneratedObjects ComponentsArray;
CreateCompositeObjects(Composite, ComponentsArray);
GeneratedObjectsForCompositeNames.Add(CompositeKey, ComponentsArray);
}
void UCompositeEquipmentComponent::CreateCompositeObjects(const FEquipmentComposite& Composite, FEquipmentCompositeGeneratedObjects& GeneratedObjects)
{
if (!(IsValid(LeaderPoseComponent) && PoseOwner.IsValid()))
return;
CreateStaticMeshes(Composite.StaticMeshes, GeneratedObjects);
CreateSkeletalMeshes(Composite.SkeletalMeshes, GeneratedObjects);
CreateSpecialEffects(Composite.SpecialEffects, GeneratedObjects);
CreateChildActors(Composite.ChildActors, GeneratedObjects);
}
void UCompositeEquipmentComponent::CreateStaticMeshes(const TArray<FEquipableStaticMesh>& EquipableMeshes, FEquipmentCompositeGeneratedObjects& GeneratedObjects)
{
for (const FEquipableStaticMesh& Equipable : EquipableMeshes)
{
UStaticMeshComponent* MeshComponent = CreateAttachedComponent_Unsafe<UStaticMeshComponent>(Equipable);
if (IsValid(MeshComponent))
{
MeshComponent->SetStaticMesh(Equipable.StaticMesh);
for (int32 i = 0; i < Equipable.OverrideMaterials.Num(); i++)
MeshComponent->SetMaterial(i, Equipable.OverrideMaterials[i]);
GeneratedObjects.AddComponent(MeshComponent);
}
}
}
void UCompositeEquipmentComponent::CreateSkeletalMeshes(const TArray<FEquipableSkeletalMesh>& EquipableMeshes, FEquipmentCompositeGeneratedObjects& GeneratedObjects)
{
AActor* Owner = LeaderPoseComponent->GetOwner();
if (!IsValid(Owner)) return;
for (const FEquipableSkeletalMesh& Equipable : EquipableMeshes)
{
USkeletalMeshComponent* SkeletalComponent = CreateAttachedComponent_Unsafe<USkeletalMeshComponent>(Equipable);
if (IsValid(SkeletalComponent))
{
SkeletalComponent->SetSkeletalMesh(Equipable.SkeletalMesh);
for (int32 i = 0; i < Equipable.OverrideMaterials.Num(); i++)
SkeletalComponent->SetMaterial(i, Equipable.OverrideMaterials[i]);
for (const FName& BoneName : Equipable.HiddenBones)
SkeletalComponent->HideBoneByName(BoneName, EPhysBodyOp::PBO_None);
if (Equipable.bUseLeaderPose)
SkeletalComponent->SetLeaderPoseComponent(LeaderPoseComponent);
if (IsValid(Equipable.AnimInstanceClass))
SkeletalComponent->SetAnimInstanceClass(Equipable.AnimInstanceClass);
GeneratedObjects.AddComponent(SkeletalComponent);
}
}
}
void UCompositeEquipmentComponent::CreateSpecialEffects(const TArray<FEquipableSpecialEffect>& EquipableEffects, FEquipmentCompositeGeneratedObjects& GeneratedObjects)
{
for (const FEquipableSpecialEffect& Equipable : EquipableEffects)
{
if (IsValid(Equipable.CascadeEffect))
{
UParticleSystemComponent* ParticleComponent = UGameplayStatics::SpawnEmitterAttached(
Equipable.CascadeEffect,
LeaderPoseComponent,
Equipable.SocketName,
Equipable.RelativeTransform.GetLocation(),
Equipable.RelativeTransform.GetRotation().Rotator(),
EAttachLocation::Type::KeepRelativeOffset
);
GeneratedObjects.AddComponent(ParticleComponent);
}
if (IsValid(Equipable.NiagaraEffect))
{
UNiagaraComponent* NiagaraComponent = UNiagaraFunctionLibrary::SpawnSystemAttached(
Equipable.NiagaraEffect,
LeaderPoseComponent,
Equipable.SocketName,
Equipable.RelativeTransform.GetLocation(),
Equipable.RelativeTransform.GetRotation().Rotator(),
EAttachLocation::Type::KeepRelativeOffset,
true
);
GeneratedObjects.AddComponent(NiagaraComponent);
}
}
}
void UCompositeEquipmentComponent::CreateChildActors(const TArray<FEquipableChildActor>& EquipableActors, FEquipmentCompositeGeneratedObjects& GeneratedObjects)
{
AActor* Owner = LeaderPoseComponent->GetOwner();
if (!IsValid(Owner)) return;
for (const FEquipableChildActor& Equipable : EquipableActors)
{
UChildActorComponent* ChildActorComponent = CreateAttachedComponent_Unsafe<UChildActorComponent>(Equipable);
if (IsValid(ChildActorComponent))
{
ChildActorComponent->SetChildActorClass(Equipable.ActorClass);
GeneratedObjects.AddComponent(ChildActorComponent);
}
}
}

View File

@@ -0,0 +1,20 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "CompositeEquipmentSystem.h"
#define LOCTEXT_NAMESPACE "FCompositeEquipmentSystemModule"
void FCompositeEquipmentSystemModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FCompositeEquipmentSystemModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FCompositeEquipmentSystemModule, CompositeEquipmentSystem)

View File

@@ -0,0 +1,18 @@
// Amasson
#include "Structures/CompositeEquipmentSystemStructs.h"
void FEquipmentCompositeGeneratedObjects::AddComponent(UActorComponent* NewComponent)
{
Components.Add(NewComponent);
}
void FEquipmentCompositeGeneratedObjects::Destroy()
{
for (UActorComponent* Component : Components)
{
Component->DestroyComponent();
}
}

View File

@@ -0,0 +1,107 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Structures/CompositeEquipmentSystemStructs.h"
#include "CompositeEquipmentComponent.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEquipedCompositesUpdatedSignature, UCompositeEquipmentComponent*, MeshEquipmentComponent);
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class COMPOSITEEQUIPMENTSYSTEM_API UCompositeEquipmentComponent : public UActorComponent
{
GENERATED_BODY()
public:
UCompositeEquipmentComponent();
UPROPERTY(BlueprintAssignable)
FOnEquipedCompositesUpdatedSignature OnEquipedCompositesUpdated;
UFUNCTION(BlueprintCallable, Category="Leader Pose")
void InitializeWithLeaderPose(USkeletalMeshComponent* NewLeaderPose);
FORCEINLINE USkeletalMeshComponent* GetLeaderPoseComponent() const { return LeaderPoseComponent; }
UFUNCTION(BlueprintCallable, Category="Equiped Composites")
void AddCompositeName(FName CompositeName);
UFUNCTION(BlueprintCallable, Category="Equiped Composites")
void RemoveCompositeName(FName CompositeName);
UFUNCTION(BlueprintCallable, Category="Equiped Composites")
void SetCompositeNames(const TSet<FName>& NewCompositeNames);
UFUNCTION(BlueprintCallable, Category="Equiped Composites")
void AddCompositeCustom(const FEquipmentComposite& Composite, FName KeyName);
protected:
/** Table of EquipmentComposite */
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Equipment Data", meta = (RequiredAssetDataTags = "RowStructure=/Script/CompositeEquipmentSystem.EquipmentComposite"))
TObjectPtr<UDataTable> EquipmentTable;
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Equiped Composites", meta = (AllowPrivateAccess = true))
TSet<FName> CompositeNames;
private:
UPROPERTY(BlueprintReadOnly, Category = "Leader Pose", meta = (AllowPrivateAccess = true))
TObjectPtr<USkeletalMeshComponent> LeaderPoseComponent;
UPROPERTY()
TWeakObjectPtr<AActor> PoseOwner;
UPROPERTY()
TMap<FName, FEquipmentCompositeGeneratedObjects> GeneratedObjectsForCompositeNames;
protected:
void UpdateCompositesObjects();
void DestroyRemovedComposites();
void CreateAddedComposites();
void CreateCompositeFromTable(const FName& CompositeName);
void CreateCompositeWithKey(const FEquipmentComposite& Composite, const FName& CompositeKey);
void CreateCompositeObjects(const FEquipmentComposite& Composite, FEquipmentCompositeGeneratedObjects& GeneratedObjects);
void CreateStaticMeshes(const TArray<FEquipableStaticMesh>& EquipableMeshes, FEquipmentCompositeGeneratedObjects& GeneratedObjects);
void CreateSkeletalMeshes(const TArray<FEquipableSkeletalMesh>& EquipableMeshes, FEquipmentCompositeGeneratedObjects& GeneratedObjects);
void CreateSpecialEffects(const TArray<FEquipableSpecialEffect>& EquipableEffects, FEquipmentCompositeGeneratedObjects& GeneratedObjects);
void CreateChildActors(const TArray<FEquipableChildActor>& EquipableActors, FEquipmentCompositeGeneratedObjects& GeneratedObjects);
template<class TComponent>
TComponent* CreateAttachedComponent_Unsafe(const FEquipableAttached& Equipable)
{
static_assert(std::is_base_of<USceneComponent, TComponent>::value, "TComponent must be a subclass of USceneComponent.");
UActorComponent* CreatedComponent = PoseOwner->AddComponentByClass(
TComponent::StaticClass(),
true,
Equipable.RelativeTransform,
false
);
if (!IsValid(CreatedComponent))
return nullptr;
if (TComponent* SceneComponent = Cast<TComponent>(CreatedComponent))
{
SceneComponent->AttachToComponent(
LeaderPoseComponent,
FAttachmentTransformRules::KeepRelativeTransform,
Equipable.SocketName
);
return SceneComponent;
}
return nullptr;
}
};

View File

@@ -0,0 +1,15 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class FCompositeEquipmentSystemModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};

View File

@@ -0,0 +1,131 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "CompositeEquipmentSystemStructs.generated.h"
USTRUCT(BlueprintType)
struct COMPOSITEEQUIPMENTSYSTEM_API FEquipableAttached
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Position")
FTransform RelativeTransform;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Position")
FName SocketName;
};
USTRUCT(BlueprintType)
struct COMPOSITEEQUIPMENTSYSTEM_API FEquipableStaticMesh : public FEquipableAttached
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Mesh")
TObjectPtr<UStaticMesh> StaticMesh;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Mesh")
TArray<UMaterialInterface*> OverrideMaterials;
};
USTRUCT(BlueprintType)
struct COMPOSITEEQUIPMENTSYSTEM_API FEquipableSkeletalMesh : public FEquipableAttached
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Mesh")
TObjectPtr<USkeletalMesh> SkeletalMesh;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Mesh")
TArray<UMaterialInterface*> OverrideMaterials;
/** Incompatible with UseLeaderPose */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Mesh")
TArray<FName> HiddenBones;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Animation")
bool bUseLeaderPose = true;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Animation")
TSubclassOf<UAnimInstance> AnimInstanceClass;
};
class UNiagaraSystem;
class UParticleSystem;
USTRUCT(BlueprintType)
struct COMPOSITEEQUIPMENTSYSTEM_API FEquipableSpecialEffect : public FEquipableAttached
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VFX")
TObjectPtr<UNiagaraSystem> NiagaraEffect;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VFX")
TObjectPtr<UParticleSystem> CascadeEffect;
};
USTRUCT(BlueprintType)
struct COMPOSITEEQUIPMENTSYSTEM_API FEquipableChildActor : public FEquipableAttached
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Actor")
TSubclassOf<AActor> ActorClass;
};
USTRUCT(BlueprintType, Blueprintable)
struct COMPOSITEEQUIPMENTSYSTEM_API FEquipmentComposite : public FTableRowBase
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Composites")
TArray<FEquipableStaticMesh> StaticMeshes;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Composites")
TArray<FEquipableSkeletalMesh> SkeletalMeshes;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Composites")
TArray<FEquipableSpecialEffect> SpecialEffects;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Composites")
TArray<FEquipableChildActor> ChildActors;
};
USTRUCT(BlueprintType)
struct FEquipmentCompositeGeneratedObjects
{
GENERATED_USTRUCT_BODY()
UPROPERTY()
TArray<UActorComponent*> Components;
void AddComponent(UActorComponent* NewComponent);
void Destroy();
};