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();
};

View File

@@ -0,0 +1,24 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "0.1",
"FriendlyName": "InteractionSystem",
"Description": "Triggerable interaction system",
"Category": "Gameplay",
"CreatedBy": "Amasson",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": true,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "InteractionSystem",
"Type": "Runtime",
"LoadingPhase": "Default"
}
]
}

Binary file not shown.

View File

@@ -0,0 +1,53 @@
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class InteractionSystem : ModuleRules
{
public InteractionSystem(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",
// ... 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,137 @@
// Amasson
#include "Components/InteractionControllerComponent.h"
#include "GameFramework/PlayerController.h"
UInteractionControllerComponent::UInteractionControllerComponent()
{
PrimaryComponentTick.bCanEverTick = true;
}
void UInteractionControllerComponent::BeginPlay()
{
Super::BeginPlay();
OwningPlayerController = Cast<APlayerController>(GetOwner());
if (!IsValid(OwningPlayerController))
{
UE_LOG(LogTemp, Error, TEXT("UInteractionControllerComponent is not owned by a valid APlayerController"));
}
}
void UInteractionControllerComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
UpdateHover();
}
void UInteractionControllerComponent::TriggerHoveredObject()
{
if (IsValid(HoveredObject))
{
bHoveredObjectPressed = true;
APawn* TriggeringPawn = nullptr;
if (IsValid(OwningPlayerController))
TriggeringPawn = OwningPlayerController->GetPawn();
Super::ExecuteTrigger(HoveredObject, OwningPlayerController, TriggeringPawn, FName("PlayerInteraction"), this);
}
}
void UInteractionControllerComponent::ReleaseTriggerHoveredObject()
{
bHoveredObjectPressed = false;
if (IsValid(HoveredObject))
{
APawn* TriggeringPawn = nullptr;
if (IsValid(OwningPlayerController))
TriggeringPawn = OwningPlayerController->GetPawn();
Super::ExecuteReleaseTrigger(HoveredObject, OwningPlayerController, TriggeringPawn, FName("PlayerInteraction"), this);
}
}
void UInteractionControllerComponent::Activate(bool bReset)
{
Super::Activate(bReset);
if (bReset)
CursorHit = FHitResult();
SetComponentTickEnabled(true);
}
void UInteractionControllerComponent::Deactivate()
{
Super::Deactivate();
if (IsValid(HoveredObject))
UnhoverObject_Unsafe();
SetComponentTickEnabled(false);
}
void UInteractionControllerComponent::UpdateHover()
{
if (!IsValid(OwningPlayerController))
return;
OwningPlayerController->GetHitResultUnderCursor(CursorChannel, false, CursorHit);
UObject* NewHitObject = GetHoverableObjectFromCursorHit();
if (IsValid(HoveredObject))
{
bool bCurrentHoverIsStillValid = IWorldHoverable::Execute_CanBeHovered(HoveredObject, OwningPlayerController, CursorHit);
bool bShouldUnhover = (!bCurrentHoverIsStillValid) || (NewHitObject != HoveredObject);
if (bShouldUnhover)
UnhoverObject_Unsafe();
}
if (!HoveredObject && IsValid(NewHitObject))
{
HoverObject(NewHitObject);
}
}
UObject* UInteractionControllerComponent::GetHoverableObjectFromCursorHit()
{
UPrimitiveComponent* HitComponent = CursorHit.GetComponent();
if (IsValid(HitComponent) && HitComponent->Implements<UWorldHoverable>())
{
if (IWorldHoverable::Execute_CanBeHovered(HitComponent, OwningPlayerController, CursorHit))
return HitComponent;
}
AActor* HitActor = CursorHit.GetActor();
if (IsValid(HitActor) && HitActor->Implements<UWorldHoverable>())
{
if (IWorldHoverable::Execute_CanBeHovered(HitActor, OwningPlayerController, CursorHit))
return HitActor;
}
return nullptr;
}
void UInteractionControllerComponent::UnhoverObject_Unsafe()
{
if (bHoveredObjectPressed)
ReleaseTriggerHoveredObject();
IWorldHoverable::Execute_HoveredEnd(HoveredObject, OwningPlayerController);
OnHoverObjectEnd.Broadcast(this, HoveredObject);
HoveredObject = nullptr;
}
void UInteractionControllerComponent::HoverObject(UObject* NewHoverObject)
{
HoveredObject = NewHoverObject;
IWorldHoverable::Execute_HoveredBegin(HoveredObject, OwningPlayerController, CursorHit);
OnHoverObjectBegin.Broadcast(this, HoveredObject);
}

View File

@@ -0,0 +1,119 @@
// Amasson
#include "Components/ObjectTriggererComponent.h"
#include "Interfaces/Triggerable.h"
#include "GameFramework/GameStateBase.h"
UObjectTriggererComponent::UObjectTriggererComponent()
{
PrimaryComponentTick.bCanEverTick = false;
SetIsReplicatedByDefault(true);
}
void UObjectTriggererComponent::BeginPlay()
{
Super::BeginPlay();
GlobalObjectTriggerer = GetGlobalObjectTriggererComponent();
}
void UObjectTriggererComponent::ExecuteTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
if (IsValid(TriggerableObject) && TriggerableObject->Implements<UTriggerable>())
{
ETriggerMode TriggerMode = ITriggerable::Execute_GetTriggerMode(TriggerableObject);
switch (TriggerMode)
{
case ETriggerMode::TM_Server:
Server_ExecuteTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
break;
case ETriggerMode::TM_Client:
Client_ExecuteTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
break;
case ETriggerMode::TM_Multicast:
Server_MulticastExecuteTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
break;
}
}
}
void UObjectTriggererComponent::ExecuteReleaseTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
if (IsValid(TriggerableObject) && TriggerableObject->Implements<UTriggerable>())
{
ETriggerMode TriggerMode = ITriggerable::Execute_GetTriggerMode(TriggerableObject);
switch (TriggerMode)
{
case ETriggerMode::TM_Server:
Server_ExecuteReleaseTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
break;
case ETriggerMode::TM_Client:
Client_ExecuteReleaseTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
break;
case ETriggerMode::TM_Multicast:
Server_MulticastExecuteReleaseTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
break;
}
}
}
void UObjectTriggererComponent::Server_ExecuteTrigger_Implementation(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
ITriggerable::Execute_Trigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
}
void UObjectTriggererComponent::Client_ExecuteTrigger_Implementation(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
ITriggerable::Execute_Trigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
}
void UObjectTriggererComponent::Server_MulticastExecuteTrigger_Implementation(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
UObjectTriggererComponent* Triggerer = GlobalObjectTriggerer;
if (!IsValid(Triggerer))
Triggerer = this;
Triggerer->NetMulticast_ExecuteTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
}
void UObjectTriggererComponent::NetMulticast_ExecuteTrigger_Implementation(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
ITriggerable::Execute_Trigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
}
void UObjectTriggererComponent::Server_ExecuteReleaseTrigger_Implementation(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
ITriggerable::Execute_ReleaseTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
}
void UObjectTriggererComponent::Client_ExecuteReleaseTrigger_Implementation(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
ITriggerable::Execute_ReleaseTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
}
void UObjectTriggererComponent::Server_MulticastExecuteReleaseTrigger_Implementation(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
UObjectTriggererComponent* Triggerer = GlobalObjectTriggerer;
if (!IsValid(Triggerer))
Triggerer = this;
Triggerer->NetMulticast_ExecuteReleaseTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
}
void UObjectTriggererComponent::NetMulticast_ExecuteReleaseTrigger_Implementation(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
ITriggerable::Execute_ReleaseTrigger(TriggerableObject, TriggeringController, TriggeringPawn, Tag, Payload);
}
UObjectTriggererComponent* UObjectTriggererComponent::GetGlobalObjectTriggererComponent() const
{
AGameStateBase* GameState = GetWorld()->GetGameState();
UObjectTriggererComponent *GlobalTrigger = GameState->GetComponentByClass<UObjectTriggererComponent>();
if (!IsValid(GlobalTrigger))
UE_LOG(LogTemp, Warning, TEXT("No UObjectTriggererComponent in GameState... Multicast triggers won't be executed by everyone"));
return GlobalTrigger;
}

View File

@@ -0,0 +1,58 @@
// Amasson
#include "Components/Shapes/BoxInteractionComponent.h"
/** Trigger */
void UBoxInteractionComponent::Trigger_Implementation(AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
if (IsValid(TriggeringActor) && TriggeringActor->Implements<UTriggerable>())
{
ITriggerable::Execute_Trigger(TriggeringActor, TriggeringController, TriggeringPawn, this->TriggeringTag, this->TriggeringPayload);
}
}
void UBoxInteractionComponent::ReleaseTrigger_Implementation(AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload)
{
if (IsValid(TriggeringActor) && TriggeringActor->Implements<UTriggerable>())
{
ITriggerable::Execute_ReleaseTrigger(TriggeringActor, TriggeringController, TriggeringPawn, this->TriggeringTag, this->TriggeringPayload);
}
}
ETriggerMode UBoxInteractionComponent::GetTriggerMode_Implementation() const
{
if (IsValid(TriggeringActor) && TriggeringActor->Implements<UTriggerable>())
{
return ITriggerable::Execute_GetTriggerMode(TriggeringActor);
}
return ETriggerMode::TM_Client;
}
/** Hovering */
void UBoxInteractionComponent::GetWorldHoverableInfos_Implementation(FWorldHoverableInfos& Infos)
{
Infos.Location = GetComponentTransform().TransformPosition(InfoLocationOffset);
Infos.Text = InfoText;
Infos.bScreenSpace = false;
}
bool UBoxInteractionComponent::CanBeHovered_Implementation(AController* Controller, const FHitResult& TraceHit)
{
if (MaxRange >= 0)
return TraceHit.Distance < MaxRange;
return true;
}
void UBoxInteractionComponent::HoveredBegin_Implementation(AController* Controller, const FHitResult& TraceHit)
{
OnHoverBegin.Broadcast(this, TraceHit);
}
void UBoxInteractionComponent::HoveredEnd_Implementation(AController* Controller)
{
OnHoverEnd.Broadcast(this);
}

View File

@@ -0,0 +1,20 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "InteractionSystem.h"
#define LOCTEXT_NAMESPACE "FInteractionSystemModule"
void FInteractionSystemModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FInteractionSystemModule::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(FInteractionSystemModule, InteractionSystem)

View File

@@ -0,0 +1,11 @@
// Amasson
#include "InteractionSystemLibrary.h"
void UInteractionSystemLibrary::DefaultsActorWorldHoverableInfos(AActor* Actor, FText TooltipText, FWorldHoverableInfos& Infos)
{
Infos.Location = IsValid(Actor) ? Actor->GetActorLocation() : FVector();
Infos.Text = TooltipText;
Infos.bScreenSpace = false;
}

View File

@@ -0,0 +1,5 @@
// Amasson
#include "Interfaces/Triggerable.h"

View File

@@ -0,0 +1,5 @@
// Amasson
#include "Interfaces/WorldHoverable.h"

View File

@@ -0,0 +1,81 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Components/ObjectTriggererComponent.h"
#include "Interfaces/WorldHoverable.h"
#include "Interfaces/Triggerable.h"
#include "InteractionControllerComponent.generated.h"
class APlayerController;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHoverObjectChangedSignature, UInteractionControllerComponent*, InteractionComponent, UObject*, WorldHoverable);
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class INTERACTIONSYSTEM_API UInteractionControllerComponent : public UObjectTriggererComponent
{
GENERATED_BODY()
public:
UInteractionControllerComponent();
virtual void BeginPlay() override;
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
UPROPERTY(BlueprintAssignable, Category = "Hover")
FOnHoverObjectChangedSignature OnHoverObjectBegin;
UPROPERTY(BlueprintAssignable, Category = "Hover")
FOnHoverObjectChangedSignature OnHoverObjectEnd;
UFUNCTION(BlueprintCallable, Category = "Hover")
FORCEINLINE UObject* GetHoveredObject() const { return HoveredObject; }
UFUNCTION(BlueprintCallable, Category = "Hover")
FORCEINLINE AActor* GetHoveredActor() const { return IsValid(HoveredObject) ? Cast<AActor>(HoveredObject) : nullptr; }
UFUNCTION(BlueprintCallable, Category = "Hover")
FORCEINLINE UActorComponent* GetHoveredComponent() const { return IsValid(HoveredObject) ? Cast<UActorComponent>(HoveredObject) : nullptr; }
UFUNCTION(BlueprintCallable, Category = "Cursor")
const FHitResult& GetCursorHit() const { return CursorHit; }
UFUNCTION(BlueprintCallable, Category = "Trigger")
void TriggerHoveredObject();
UFUNCTION(BlueprintCallable, Category = "Trigger")
void ReleaseTriggerHoveredObject();
virtual void Activate(bool bReset = false) override;
virtual void Deactivate() override;
protected:
void UpdateHover();
UObject* GetHoverableObjectFromCursorHit();
void UnhoverObject_Unsafe();
void HoverObject(UObject* NewHoverObject);
UPROPERTY()
TObjectPtr<APlayerController> OwningPlayerController;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cursor", meta = (AllowPrivateAccess = true))
TEnumAsByte<ECollisionChannel> CursorChannel;
UPROPERTY()
FHitResult CursorHit;
UPROPERTY()
TObjectPtr<UObject> HoveredObject;
// UPROPERTY(EditAnywhere, Category = "Cursor", meta = (AllowPrivateAccess = true))
// TObjectPtr<UInputAction> InteractionInput;
bool bHoveredObjectPressed = false;
};

View File

@@ -0,0 +1,59 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "ObjectTriggererComponent.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class INTERACTIONSYSTEM_API UObjectTriggererComponent : public UActorComponent
{
GENERATED_BODY()
public:
UObjectTriggererComponent();
virtual void BeginPlay() override;
UFUNCTION(BlueprintCallable, Category = "Trigger")
void ExecuteTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(BlueprintCallable, Category = "Trigger")
void ExecuteReleaseTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
protected:
UFUNCTION(Server, Reliable)
void Server_ExecuteTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(Client, Reliable)
void Client_ExecuteTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(Server, Reliable)
void Server_MulticastExecuteTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(NetMulticast, Reliable)
void NetMulticast_ExecuteTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(Server, Reliable)
void Server_ExecuteReleaseTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(Client, Reliable)
void Client_ExecuteReleaseTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(Server, Reliable)
void Server_MulticastExecuteReleaseTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(NetMulticast, Reliable)
void NetMulticast_ExecuteReleaseTrigger(UObject* TriggerableObject, AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UObjectTriggererComponent* GetGlobalObjectTriggererComponent() const;
UPROPERTY()
TObjectPtr<UObjectTriggererComponent> GlobalObjectTriggerer;
};

View File

@@ -0,0 +1,71 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Components/BoxComponent.h"
#include "Interfaces/WorldHoverable.h"
#include "Interfaces/Triggerable.h"
#include "BoxInteractionComponent.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInteractionHoverBeginSignature, UBoxInteractionComponent*, BoxInteraction, FHitResult, CursorHit);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnInteractionHoverEndSignature, UBoxInteractionComponent*, BoxInteraction);
/**
*
*/
UCLASS( Blueprintable, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class INTERACTIONSYSTEM_API UBoxInteractionComponent : public UBoxComponent, public IWorldHoverable, public ITriggerable
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintAssignable)
FOnInteractionHoverBeginSignature OnHoverBegin;
UPROPERTY(BlueprintAssignable)
FOnInteractionHoverEndSignature OnHoverEnd;
/** Trigger */
virtual void Trigger_Implementation(AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload) override;
virtual void ReleaseTrigger_Implementation(AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload) override;
virtual ETriggerMode GetTriggerMode_Implementation() const override;
/** Hovering */
virtual void GetWorldHoverableInfos_Implementation(FWorldHoverableInfos& Infos) override;
virtual bool CanBeHovered_Implementation(AController* Controller, const FHitResult& TraceHit) override;
virtual void HoveredBegin_Implementation(AController* Controller, const FHitResult& TraceHit) override;
virtual void HoveredEnd_Implementation(AController* Controller) override;
/** Trigger Properties */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Interaction")
TObjectPtr<AActor> TriggeringActor;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Interaction")
FName TriggeringTag;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Interaction")
TObjectPtr<UObject> TriggeringPayload;
/** Hovering Properties */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Interaction")
float MaxRange = -1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Interaction")
FVector InfoLocationOffset;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Interaction")
FText InfoText;
};

View File

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

View File

@@ -0,0 +1,23 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Interfaces/WorldHoverable.h"
#include "InteractionSystemLibrary.generated.h"
/**
*
*/
UCLASS()
class INTERACTIONSYSTEM_API UInteractionSystemLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "WorldTooltip", meta = (DefaultToSelf = "Actor"))
static void DefaultsActorWorldHoverableInfos(AActor* Actor, FText TooltipText, FWorldHoverableInfos& Infos);
};

View File

@@ -0,0 +1,45 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Triggerable.generated.h"
UENUM(BlueprintType)
enum class ETriggerMode : uint8
{
TM_Multicast UMETA(DisplayName="Multicast"),
TM_Server UMETA(DisplayName="Server"),
TM_Client UMETA(DisplayName="Client"),
};
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UTriggerable : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class INTERACTIONSYSTEM_API ITriggerable
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Triggerable")
void Trigger(AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Triggerable")
void ReleaseTrigger(AController* TriggeringController, APawn* TriggeringPawn, FName Tag, UObject* Payload);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Triggerable")
ETriggerMode GetTriggerMode() const;
};

View File

@@ -0,0 +1,59 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "WorldHoverable.generated.h"
USTRUCT(BlueprintType)
struct INTERACTIONSYSTEM_API FWorldHoverableInfos
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FVector Location = FVector::ZeroVector;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FText Text;
/** Is Location in Screen Space or World Space */
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool bScreenSpace = false;
};
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UWorldHoverable : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class INTERACTIONSYSTEM_API IWorldHoverable
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "WorldTooltip")
void GetWorldHoverableInfos(FWorldHoverableInfos& Infos);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "WorldTooltip")
bool CanBeHovered(AController* Controller, const FHitResult& TraceHit);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "WorldTooltip")
void HoveredBegin(AController* Controller, const FHitResult& TraceHit);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "WorldTooltip")
void HoveredEnd(AController* Controller);
};

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,30 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "LibAmasson",
"Description": "My plugin of frequently implemented functions",
"Category": "Blueprints",
"CreatedBy": "Amasson",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "LibAmasson",
"Type": "Runtime",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "OnlineSubsystemUtils",
"Enabled": true
}
]
}

Binary file not shown.

View File

@@ -0,0 +1,55 @@
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class LibAmasson : ModuleRules
{
public LibAmasson(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",
"UMG",
"OnlineSubsystemUtils",
// ... 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,55 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Animation/CharacterMovementAnimInstance.h"
#include "Kismet/KismetMathLibrary.h"
#include "GameFramework/CharacterMovementComponent.h"
void UCharacterMovementAnimInstance::NativeInitializeAnimation()
{
Super::NativeInitializeAnimation();
if (APawn* Owner = TryGetPawnOwner()) {
CharacterMovementComponent = Owner->GetComponentByClass<UCharacterMovementComponent>();
_PreviousYaw = Owner->GetActorRotation().Yaw;
}
}
void UCharacterMovementAnimInstance::NativeUpdateAnimation(float DeltaTime)
{
Super::NativeUpdateAnimation(DeltaTime);
if (APawn* Owner = TryGetPawnOwner())
{
FRotator Rotation = Owner->GetActorRotation();
TurnVelocity = (Rotation.Yaw - _PreviousYaw) / DeltaTime;
if (CharacterMovementComponent)
{
bFalling = CharacterMovementComponent->IsFalling();
bCrouching = CharacterMovementComponent->IsCrouching();
bSwimming = CharacterMovementComponent->IsSwimming();
LocalVelocity = Rotation.UnrotateVector(CharacterMovementComponent->Velocity);
LocalVelocityAngle = LocalVelocity.IsNearlyZero() ? 0 : FMath::RadiansToDegrees(FMath::Atan2(LocalVelocity.Y, LocalVelocity.X));
}
_PreviousYaw = Rotation.Yaw;
}
}
bool UCharacterMovementAnimInstance::IsPawnMoving() const
{
return LocalVelocity.SquaredLength() > 10;
}
bool UCharacterMovementAnimInstance::IsJumpingUp() const
{
return LocalVelocity.Z > 0 && bFalling;
}
bool UCharacterMovementAnimInstance::IsFallingDown() const
{
return LocalVelocity.Z <= 0 && bFalling;
}

View File

@@ -0,0 +1,54 @@
// Amasson
#include "Components/NetInterpToMovementComponent.h"
UNetInterpToMovementComponent::UNetInterpToMovementComponent()
{
SetIsReplicatedByDefault(true);
}
UNetInterpToMovementComponent::~UNetInterpToMovementComponent()
{
if (GetOwner() && GetOwner()->GetWorld())
GetOwner()->GetWorldTimerManager().ClearTimer(TimerHandle_BroadcastMovement);
}
void UNetInterpToMovementComponent::BeginPlay()
{
Super::BeginPlay();
if (AActor* Owner = GetOwner())
{
if (Owner->HasAuthority())
{
if (Owner->GetWorld())
{
Owner->GetWorldTimerManager().SetTimer(TimerHandle_BroadcastMovement, this, &ThisClass::BroadcastMovement, 5.0f, true);
}
}
}
}
void UNetInterpToMovementComponent::BroadcastMovement()
{
if (GetOwner())
NetMulticast_UpdateMovement(GetOwner()->GetActorLocation(), CurrentTime, CurrentDirection, bIsWaiting, bStopped);
}
void UNetInterpToMovementComponent::NetMulticast_UpdateMovement_Implementation(const FVector& Location, float InCurrentTime, float InCurrentDirection, bool bInIsWaiting, bool bInStopped)
{
FVector Diff = GetOwner()->GetActorLocation() - Location;
UE_LOG(LogTemp, Warning, TEXT("Location Difference: %s"), *Diff.ToString());
if (!Diff.IsNearlyZero())
UE_LOG(LogTemp, Warning, TEXT("Location Difference: %s"), *Diff.ToString());
if (GetOwner())
GetOwner()->SetActorLocation(Location);
CurrentTime = InCurrentTime;
CurrentDirection = InCurrentDirection;
bIsWaiting = bInIsWaiting;
bStopped = bInStopped;
}

View File

@@ -0,0 +1,20 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "LibAmasson.h"
#define LOCTEXT_NAMESPACE "FLibAmassonModule"
void FLibAmassonModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FLibAmassonModule::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(FLibAmassonModule, LibAmasson)

View File

@@ -0,0 +1,105 @@
// Amasson
#include "MathLibrary.h"
#include "Kismet/KismetMathLibrary.h"
void UMathLibrary::GetTraceForward(USceneComponent* Component, double Distance, FVector& StartPoint, FVector& EndPoint)
{
FVector Location = Component->GetComponentLocation();
FVector Forward = Component->GetForwardVector();
StartPoint = Location;
EndPoint = Location + Forward * Distance;
}
void UMathLibrary::TraceClampDistance(const FVector& StartPoint, const FVector& EndPoint,
double MinDistance, double MaxDistance,
FVector& NewStartPoint, FVector& NewEndPoint)
{
FVector StartToEnd = EndPoint - StartPoint;
StartToEnd = UKismetMathLibrary::ClampVectorSize(StartToEnd, MinDistance, MaxDistance);
NewStartPoint = StartPoint;
NewEndPoint = StartPoint + StartToEnd;
}
FVector UMathLibrary::AddLengthToVector(FVector Vector, double Length)
{
FVector NewVector = Vector;
NewVector.Normalize();
return Vector + NewVector * Length;
}
FVector UMathLibrary::SetLengthToVector(FVector Vector, double Length)
{
FVector NewVector = Vector;
NewVector.Normalize();
return NewVector * Length;
}
TArray<FVector> UMathLibrary::TransformPoints(const TArray<FVector>& Points, const FTransform& Transform)
{
TArray<FVector> NewPoints = Points;
for (FVector& NewPoint : NewPoints)
{
NewPoint = Transform.TransformPosition(NewPoint);
}
return NewPoints;
}
TArray<FTransform> UMathLibrary::TransformTransforms(const TArray<FTransform>& Transforms, const FTransform& Transform)
{
TArray<FTransform> NewTransforms = Transforms;
for (FTransform& NewTransform : NewTransforms)
{
NewTransform = NewTransform * Transform;
}
return NewTransforms;
}
void UMathLibrary::ArcPoints(float ArcAngle, int32 Count, float Distance, TArray<FVector>& Points)
{
if (Count <= 0)
return;
const float StepAngle = ArcAngle / (Count - 1);
FVector Direction = Count == 1 ?
FVector(1, 0, 0) :
FVector(1, 0, 0).RotateAngleAxis(-ArcAngle / 2.0f, FVector::UpVector);
for (int32 i = 0; i < Count; i++)
{
const FVector Location = Direction * Distance;
Points.Add(Location);
Direction = Direction.RotateAngleAxis(StepAngle, FVector::UpVector);
}
}
void UMathLibrary::ArcTransforms(float ArcAngle, int32 Count, float Distance, TArray<FTransform>& Transforms)
{
if (Count <= 0)
return;
if (Count == 1)
{
Transforms.Add(FTransform(FVector(Distance, 0.0f, 0.0f)));
return;
}
float StepAngle = ArcAngle / static_cast<float>(Count - 1);
FRotator DirectionRotator;
for (int32 i = 0; i < Count; i++)
{
const FRotator Rotation(0.0f, -(ArcAngle / 2.0f) + i * StepAngle, 0.0f);
const FQuat QuatRotation = Rotation.Quaternion();
const FVector Location = QuatRotation.GetForwardVector() * Distance;
const FTransform Transform = FTransform(QuatRotation, Location);
Transforms.Add(Transform);
}
}

View File

@@ -0,0 +1,34 @@
// Amasson
#include "Sorting/ObjectSortPredicate.h"
bool UObjectSortPredicate::Compare(UObject* Left, UObject* Right) const
{
if (CanScorify())
return ScorifyElement(Left) < ScorifyElement(Right);
return BP_Compare(Left, Right);
}
float UObjectSortPredicate::ScorifyElement(UObject* Element) const
{
return BP_ScorifyElement(Element);
}
TArray<TPair<UObject*, float>> UObjectSortPredicate::ScorifyArray(const TArray<UObject*>& Array) const
{
checkf(CanScorify(), TEXT("ScorifyArray used on predicate that cannot scorify"));
TArray<TPair<UObject*, float>> ScorifiedElements;
for (UObject* Element : Array)
{
TPair<UObject*, float> ScorifiedElement;
ScorifiedElement.Key = Element;
ScorifiedElement.Value = ScorifyElement(Element);
ScorifiedElements.Add(ScorifiedElement);
}
return ScorifiedElements;
}

View File

@@ -0,0 +1,27 @@
// Amasson
#include "Sorting/Predicates/DistanceSortPredicate.h"
UDistanceSortPredicate::UDistanceSortPredicate()
{
bCanScorify = true;
}
float UDistanceSortPredicate::ScorifyElement(UObject* Element) const
{
FVector Location;
if (IsValid(Element))
{
if (AActor* AsActor = Cast<AActor>(Element))
Location = AsActor->GetActorLocation();
else if (USceneComponent* AsSceneComponent = Cast<USceneComponent>(Element))
Location = AsSceneComponent->GetComponentLocation();
}
else
Location = FVector::ZeroVector;
return (Location - ComparisonPoint).SquaredLength();
}

View File

@@ -0,0 +1,19 @@
// Amasson
#include "Sorting/Predicates/NameSortPredicate.h"
#include "Kismet/KismetSystemLibrary.h"
UNameSortPredicate::UNameSortPredicate()
{
bCanScorify = false;
}
bool UNameSortPredicate::Compare(UObject* Left, UObject* Right) const
{
const FString LeftName = UKismetSystemLibrary::GetDisplayName(Left);
const FString RightName = UKismetSystemLibrary::GetDisplayName(Right);
return LeftName <= RightName;
}

View File

@@ -0,0 +1,148 @@
// Amasson
#include "Sorting/SortingFunctionLibrary.h"
void USortingFunctionLibrary::SortInPlace(TArray<UObject*>& Array, TSubclassOf<UObjectSortPredicate> PredicateClass)
{
if (!IsValid(PredicateClass))
return;
UObjectSortPredicate *Predicate = NewObject<UObjectSortPredicate>(GetTransientPackage(), PredicateClass);
SortInPlaceUsingPredicate(Array, Predicate);
}
void USortingFunctionLibrary::SortInPlaceUsingPredicate(TArray<UObject*>& Array, UObjectSortPredicate* Predicate)
{
if (!IsValid(Predicate))
return;
const bool bAscending = Predicate->bSortAscending;
if (Predicate->CanScorify())
{
TArray<TPair<UObject*, float>> ScorifiedArray = Predicate->ScorifyArray(Array);
ScorifiedArray.Sort([bAscending](TPair<UObject*, float> Left, TPair<UObject*, float> Right) {
return bAscending ? Left.Value <= Right.Value : Right.Value <= Left.Value;
});
for (int i = 0; i < ScorifiedArray.Num(); i++)
{
Array[i] = ScorifiedArray[i].Key;
}
}
else
{
Array.Sort([Predicate, bAscending](UObject& Left, UObject& Right) {
return bAscending ? Predicate->Compare(&Left, &Right) : Predicate->Compare(&Right, &Left);
});
}
}
bool USortingFunctionLibrary::IsArraySorted(const TArray<UObject*>& Array, TSubclassOf<UObjectSortPredicate> PredicateClass)
{
UObjectSortPredicate *Predicate = NewObject<UObjectSortPredicate>(GetTransientPackage(), PredicateClass);
return IsArraySortedUsingPredicate(Array, Predicate);
}
bool USortingFunctionLibrary::IsArraySortedUsingPredicate(const TArray<UObject*>& Array, UObjectSortPredicate* Predicate)
{
// Array of 0 or 1 element is always sorted
if (Array.Num() <= 1)
return true;
if (Predicate->CanScorify())
{
float PreviousElementScore = Predicate->ScorifyElement(Array[0]);
for (int32 i = 1; i < Array.Num(); i++)
{
const float ElementScore = Predicate->ScorifyElement(Array[i]);
const bool bSorted = Predicate->bSortAscending ?
PreviousElementScore <= ElementScore :
ElementScore <= PreviousElementScore;
if (!bSorted)
return false;
PreviousElementScore = ElementScore;
}
return true;
}
else
{
for (int32 i = 1; i < Array.Num(); i++)
{
const bool bSorted = Predicate->bSortAscending ?
Predicate->Compare(Array[i - 1], Array[i]) :
Predicate->Compare(Array[i], Array[i - 1]);
if (!bSorted)
return false;
}
return true;
}
}
/** Sort range */
TArray<UObject*> USortingFunctionLibrary::GetNMin(const TArray<UObject*>& Array, int32 N, TSubclassOf<UObjectSortPredicate> PredicateClass)
{
UObjectSortPredicate *Predicate = NewObject<UObjectSortPredicate>(GetTransientPackage(), PredicateClass);
return GetNMinUsingPredicate(Array, N, Predicate);
}
TArray<UObject*> USortingFunctionLibrary::GetNMinUsingPredicate(const TArray<UObject*>& Array, int32 N, UObjectSortPredicate* Predicate)
{
TArray<UObject*> SortedArray(Array);
SortInPlaceUsingPredicate(SortedArray, Predicate);
if (SortedArray.Num() > N)
SortedArray.SetNum(N, true);
return SortedArray;
}
TArray<UObject*> USortingFunctionLibrary::GetNMax(const TArray<UObject*>& Array, int32 N, TSubclassOf<UObjectSortPredicate> PredicateClass)
{
UObjectSortPredicate *Predicate = NewObject<UObjectSortPredicate>(GetTransientPackage(), PredicateClass);
return GetNMaxUsingPredicate(Array, N, Predicate);
}
TArray<UObject*> USortingFunctionLibrary::GetNMaxUsingPredicate(const TArray<UObject*>& Array, int32 N, UObjectSortPredicate* Predicate)
{
TArray<UObject*> SortedArray(Array);
SortInPlaceUsingPredicate(SortedArray, Predicate);
for (int32 i = 0; N + i - 1 < SortedArray.Num(); i++)
{
SortedArray[i] = SortedArray[N + i - 1];
}
if (SortedArray.Num() > N)
SortedArray.SetNum(N, true);
return SortedArray;
}
/** Cast */
TArray<UObject*>& USortingFunctionLibrary::CastArray(TArray<UObject*>& ObjectArray, TSubclassOf<UObject> NewClass, bool bSafe)
{
if (!bSafe)
return ObjectArray;
for (UObject*& ElementPtr : ObjectArray)
{
if (IsValid(ElementPtr) && !ElementPtr->IsA(NewClass))
ElementPtr = nullptr;
}
return ObjectArray;
}

View File

@@ -0,0 +1,82 @@
// Amasson
#include "UI/ControllableUserWidget.h"
#include "Blueprint/WidgetTree.h"
#include "UI/WidgetControllerComponent.h"
#include "UI/WidgetController.h"
UWidgetControllerComponent* UControllableUserWidget::GetComponentFromControllerByClass(TSubclassOf<UWidgetControllerComponent> ComponentClass) const
{
if (!WidgetController) return nullptr;
return WidgetController->GetComponentByClass(ComponentClass);
}
void UControllableUserWidget::SetWidgetController(UWidgetController* NewWidgetController)
{
WidgetController = NewWidgetController;
WidgetControllerSet(WidgetController);
PropagateWidgetController(this);
}
bool UControllableUserWidget::AcceptWidgetController(UWidgetController* InWidgetController) const
{
// We accept invalid objects as widget controllers
if (!InWidgetController || !InWidgetController->GetClass())
return true;
// If we have no required class, we accept any of them
if (AcceptedControllerClasses.IsEmpty())
return true;
if (AcceptedControllerClasses.Contains(InWidgetController->GetClass()))
return true;
for (TSubclassOf<UWidgetController> AcceptedControllerClass : AcceptedControllerClasses)
{
if (InWidgetController->GetClass()->IsChildOf(AcceptedControllerClass))
return true;
}
return false;
}
void UControllableUserWidget::PropagateWidgetController(UWidget* Parent)
{
TArray<UWidget*> AllWidgets;
WidgetTree->GetAllWidgets(AllWidgets);
for (UWidget* Widget : AllWidgets)
{
if (!IsValid(Widget)) continue;
if (UControllableUserWidget* ControlledWidget = Cast<UControllableUserWidget>(Widget))
{
if (ControlledWidget->TakeControllerFromParent && ControlledWidget->AcceptWidgetController(WidgetController))
{
ControlledWidget->SetWidgetController(WidgetController);
}
}
}
// TArray<UWidget*> ChildWidgets;
// UWidgetTree::GetChildWidgets(Parent, ChildWidgets);
// for (UWidget* ChildWidget : ChildWidgets)
// {
// if (UControllableUserWidget* ControlledWidget = Cast<UControllableUserWidget>(ChildWidget))
// {
// if (ControlledWidget->TakeControllerFromParent)
// {
// ControlledWidget->SetWidgetController(WidgetController);
// PropagateWidgetController(ChildWidget);
// }
// }
// else
// {
// PropagateWidgetController(ChildWidget);
// }
// }
}

View File

@@ -0,0 +1,174 @@
// Amasson
#include "UI/WidgetController.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/PlayerState.h"
#include "GameFramework/Pawn.h"
#include "GameFramework/Character.h"
#include "UI/WidgetControllerComponent.h"
UWidgetController::UWidgetController()
{
}
UWidgetController* UWidgetController::MakeWidgetController(UObject* Outer, TSubclassOf<UWidgetController> WidgetControllerClass, AActor* ObservedActor)
{
if (!IsValid(WidgetControllerClass))
return nullptr;
UWidgetController* NewWidgetController = NewObject<UWidgetController>(Outer, WidgetControllerClass);
if (!IsValid(NewWidgetController))
return nullptr;
NewWidgetController->Construct();
NewWidgetController->BP_Construct();
if (IsValid(ObservedActor))
NewWidgetController->SetObservedActor(ObservedActor, true);
return NewWidgetController;
}
void UWidgetController::SetObservedController(AController* InController)
{
if (!IsValid(InController)) return;
Controller = InController;
if (APlayerController* AsPC = Cast<APlayerController>(InController))
PlayerState = AsPC->GetPlayerState<APlayerState>();
else
PlayerState = nullptr;
Pawn = InController->GetPawn();
Actor = InController;
FinishSetObserved();
}
void UWidgetController::SetObservedPlayerState(APlayerState* InPlayerState)
{
if (!IsValid(InPlayerState)) return;
Controller = InPlayerState->GetPlayerController();
PlayerState = InPlayerState;
Pawn = InPlayerState->GetPawn();
Actor = InPlayerState;
FinishSetObserved();
}
void UWidgetController::SetObservedPawn(APawn* InPawn)
{
if (!IsValid(InPawn)) return;
Controller = InPawn->GetController();
if (APlayerController* AsPC = Cast<APlayerController>(Controller))
PlayerState = AsPC->GetPlayerState<APlayerState>();
else
PlayerState = nullptr;
Pawn = InPawn;
Actor = InPawn;
FinishSetObserved();
}
void UWidgetController::SetObservedActor(AActor* InActor, bool bTryCast)
{
if (!IsValid(InActor)) return;
if (bTryCast)
{
if (AController* AsPC = Cast<AController>(InActor))
{
return SetObservedController(AsPC);
}
else if (APlayerState* AsPS = Cast<APlayerState>(InActor))
{
return SetObservedPlayerState(AsPS);
}
else if (APawn* AsPawn = Cast<APawn>(InActor))
{
return SetObservedPawn(AsPawn);
}
}
Controller = nullptr;
PlayerState = nullptr;
Pawn = nullptr;
Actor = InActor;
FinishSetObserved();
}
void UWidgetController::BroadcastValues()
{
for (UWidgetControllerComponent* Component : Components)
{
Component->BroadcastValues();
}
BP_BroadcastValues();
}
void UWidgetController::BindCallbacksToDependencies()
{
for (UWidgetControllerComponent* Component : Components)
{
Component->BindCallbacksToDependencies();
}
}
UWidgetControllerComponent* UWidgetController::GetComponentByClass(TSubclassOf<UWidgetControllerComponent> ComponentClass) const
{
for (UWidgetControllerComponent* Component : Components)
{
if (Component->IsA(ComponentClass))
{
return Component;
}
}
return nullptr;
}
UWidgetControllerComponent* UWidgetController::GetComponentByClassAndName(TSubclassOf<UWidgetControllerComponent> ComponentClass, FName ComponentName) const
{
for (UWidgetControllerComponent* Component : Components)
{
if (Component->IsA(ComponentClass) && Component->GetFName() == ComponentName)
{
return Component;
}
}
return nullptr;
}
TArray<UWidgetControllerComponent*> UWidgetController::GetComponentsByClass(TSubclassOf<UWidgetControllerComponent> ComponentClass) const
{
TArray<UWidgetControllerComponent*> ComponentsList;
for (UWidgetControllerComponent* Component : Components)
{
if (Component->IsA(ComponentClass))
{
ComponentsList.Add(Component);
}
}
return ComponentsList;
}
UWidgetControllerComponent* UWidgetController::AddComponentByClass(TSubclassOf<UWidgetControllerComponent> ComponentClass, FName ComponentName)
{
UWidgetControllerComponent* NewComponent = NewObject<UWidgetControllerComponent>(this, ComponentClass, ComponentName);
Components.Add(NewComponent);
return NewComponent;
}
void UWidgetController::FinishSetObserved()
{
ObservedActorSet();
BP_ObservedActorSet();
BindCallbacksToDependencies();
BP_BindCallbacksToDependencies();
}

View File

@@ -0,0 +1,14 @@
// Amasson
#include "UI/WidgetControllerComponent.h"
void UWidgetControllerComponent::BroadcastValues()
{
BP_BroadcastValues();
}
void UWidgetControllerComponent::BindCallbacksToDependencies()
{
BP_BindCallbacksToDependencies();
}

View File

@@ -0,0 +1,24 @@
// Amasson
#include "UI/WidgetControllerComponents/GameManagementWcc.h"
#include "Kismet/GameplayStatics.h"
void UGameManagementWcc::Initialize(UObject* InWorldContextObject)
{
WorldContextObject = InWorldContextObject;
}
/** GameplayStatics */
void UGameManagementWcc::OpenLevel(FName LevelName, bool bAbsolute, FString Options)
{
UGameplayStatics::OpenLevel(WorldContextObject, LevelName, bAbsolute, Options);
}
void UGameManagementWcc::OpenLevelBySoftObjectPtr(const TSoftObjectPtr<UWorld> Level, bool bAbsolute, FString Options)
{
UGameplayStatics::OpenLevelBySoftObjectPtr(WorldContextObject, Level, bAbsolute, Options);
}

View File

@@ -0,0 +1,55 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "CharacterMovementAnimInstance.generated.h"
/**
*
*/
UCLASS()
class LIBAMASSON_API UCharacterMovementAnimInstance : public UAnimInstance
{
GENERATED_BODY()
public:
virtual void NativeInitializeAnimation() override;
virtual void NativeUpdateAnimation(float DeltaTime) override;
UPROPERTY(BlueprintReadOnly, Category = Movement)
class UCharacterMovementComponent* CharacterMovementComponent;
UPROPERTY(BlueprintReadWrite, Category = Movement)
FVector LocalVelocity;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = Movement)
bool IsPawnMoving() const;
UPROPERTY(BlueprintReadWrite, Category = Movement)
float LocalVelocityAngle = 0;
UPROPERTY(BlueprintReadWrite, Category = Movement)
float TurnVelocity = 0;
UPROPERTY(BlueprintReadWrite, Category = Movement)
bool bFalling = false;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = Movement)
bool IsJumpingUp() const;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = Movement)
bool IsFallingDown() const;
UPROPERTY(BlueprintReadWrite, Category = Movement)
bool bCrouching = false;
UPROPERTY(BlueprintReadWrite, Category = Movement)
bool bSwimming = false;
private:
float _PreviousYaw = 0;
};

View File

@@ -0,0 +1,39 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Components/InterpToMovementComponent.h"
#include "NetInterpToMovementComponent.generated.h"
/**
*
*/
UCLASS(ClassGroup=Movement, meta=(BlueprintSpawnableComponent),HideCategories=Velocity)
class LIBAMASSON_API UNetInterpToMovementComponent : public UInterpToMovementComponent
{
GENERATED_BODY()
public:
UNetInterpToMovementComponent();
virtual ~UNetInterpToMovementComponent();
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Network")
float MovementUpdatePeriod = 5.0f;
protected:
virtual void BeginPlay();
UPROPERTY()
FTimerHandle TimerHandle_BroadcastMovement;
UFUNCTION()
void BroadcastMovement();
UFUNCTION(NetMulticast, Reliable, Category = "Network")
void NetMulticast_UpdateMovement(const FVector& Location, float InCurrentTime, float InCurrentDirection, bool bInIsWaiting, bool bInStopped);
};

View File

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

View File

@@ -0,0 +1,43 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MathLibrary.generated.h"
/**
*
*/
UCLASS()
class LIBAMASSON_API UMathLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Math|Trace")
static void GetTraceForward(USceneComponent* Component, double Distance, FVector& StartPoint, FVector& EndPoint);
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Math|Trace")
static void TraceClampDistance(const FVector& StartPoint, const FVector& EndPoint, double MinDistance, double MaxDistance, FVector& NewStartPoint, FVector& NewEndPoint);
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Math|Vector")
static FVector AddLengthToVector(FVector Vector, double Length);
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Math|Vector")
static FVector SetLengthToVector(FVector Vector, double Length);
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Math|Vector")
static TArray<FVector> TransformPoints(const TArray<FVector>& Points, const FTransform& Transform);
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Math|Vector")
static TArray<FTransform> TransformTransforms(const TArray<FTransform>& Transforms, const FTransform& Transform);
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Math|Vector")
static void ArcPoints(float ArcAngle, int32 Count, float Distance, TArray<FVector>& Points);
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Math|Vector")
static void ArcTransforms(float ArcAngle, int32 Count, float Distance, TArray<FTransform>& Transforms);
};

View File

@@ -0,0 +1,51 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "ObjectSortPredicate.generated.h"
/**
*
*/
UCLASS(Abstract, Blueprintable, BlueprintType)
class LIBAMASSON_API UObjectSortPredicate : public UObject
{
GENERATED_BODY()
public:
virtual bool Compare(UObject* Left, UObject* Right) const;
UFUNCTION(BlueprintImplementableEvent, DisplayName = "Compare", Category = "Sorting")
bool BP_Compare(UObject* Left, UObject* Right) const;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Sort", meta = (ExposeOnSpawn = true))
bool bSortAscending = true;
/** Scorify */
FORCEINLINE float CanScorify() const { return bCanScorify; }
virtual float ScorifyElement(UObject* Element) const;
/** CanScorify must be activated for this function to be used */
UFUNCTION(BlueprintImplementableEvent, DisplayName = "ScorifyElement", Category = "Score")
float BP_ScorifyElement(UObject* Element) const;
TArray<TPair<UObject*, float>> ScorifyArray(const TArray<UObject*>& Array) const;
protected:
/** When activated, the sort algorithm will not use the Compare function,
* but Instead, will attribute a float value to each elements using the
* ScorifyElement function and sort them with this value.
* Allowing us to do performance intensive calculations only once per
* elements like calculating a distance from a point.
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Score")
bool bCanScorify = false;
};

View File

@@ -0,0 +1,26 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Sorting/ObjectSortPredicate.h"
#include "DistanceSortPredicate.generated.h"
/**
*
*/
UCLASS(BlueprintType)
class LIBAMASSON_API UDistanceSortPredicate : public UObjectSortPredicate
{
GENERATED_BODY()
public:
UDistanceSortPredicate();
virtual float ScorifyElement(UObject* Element) const override;
UPROPERTY(BlueprintReadWrite, Category = "Distance", meta = (ExposeOnSpawn = true))
FVector ComparisonPoint;
};

View File

@@ -0,0 +1,23 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Sorting/ObjectSortPredicate.h"
#include "NameSortPredicate.generated.h"
/**
*
*/
UCLASS(BlueprintType)
class LIBAMASSON_API UNameSortPredicate : public UObjectSortPredicate
{
GENERATED_BODY()
public:
UNameSortPredicate();
virtual bool Compare(UObject* Left, UObject* Right) const override;
};

View File

@@ -0,0 +1,53 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Sorting/ObjectSortPredicate.h"
#include "SortingFunctionLibrary.generated.h"
/**
*
*/
UCLASS()
class LIBAMASSON_API USortingFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Sort")
static void SortInPlace(UPARAM(Ref) TArray<UObject*>& Array, TSubclassOf<UObjectSortPredicate> PredicateClass);
UFUNCTION(BlueprintCallable, Category = "Sort")
static void SortInPlaceUsingPredicate(UPARAM(Ref) TArray<UObject*>& Array, UObjectSortPredicate* Predicate);
UFUNCTION(BlueprintCallable, Category = "Sort")
static bool IsArraySorted(const TArray<UObject*>& Array, TSubclassOf<UObjectSortPredicate> PredicateClass);
UFUNCTION(BlueprintCallable, Category = "Sort")
static bool IsArraySortedUsingPredicate(const TArray<UObject*>& Array, UObjectSortPredicate* Predicate);
/** Sort range */
UFUNCTION(BlueprintCallable, Category = "Sort")
static TArray<UObject*> GetNMin(const TArray<UObject*>& Array, int32 N, TSubclassOf<UObjectSortPredicate> PredicateClass);
UFUNCTION(BlueprintCallable, Category = "Sort")
static TArray<UObject*> GetNMinUsingPredicate(const TArray<UObject*>& Array, int32 N, UObjectSortPredicate* Predicate);
UFUNCTION(BlueprintCallable, Category = "Sort")
static TArray<UObject*> GetNMax(const TArray<UObject*>& Array, int32 N, TSubclassOf<UObjectSortPredicate> PredicateClass);
UFUNCTION(BlueprintCallable, Category = "Sort")
static TArray<UObject*> GetNMaxUsingPredicate(const TArray<UObject*>& Array, int32 N, UObjectSortPredicate* Predicate);
/** Cast */
UFUNCTION(BlueprintCallable, Category = "Array", meta = (DeterminesOutputType = "NewClass"))
static TArray<UObject*>& CastArray(UPARAM(Ref) TArray<UObject*>& ObjectArray, TSubclassOf<UObject> NewClass, bool bSafe = false);
};

View File

@@ -0,0 +1,52 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "ControllableUserWidget.generated.h"
class UWidgetController;
class UWidgetControllerComponent;
/**
*
*/
UCLASS()
class LIBAMASSON_API UControllableUserWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Controller|Component", meta = (DeterminesOutputType = "ComponentClass"))
UWidgetControllerComponent* GetComponentFromControllerByClass(TSubclassOf<UWidgetControllerComponent> ComponentClass) const;
UFUNCTION(BlueprintCallable, Category = "Controller")
void SetWidgetController(UWidgetController* NewWidgetController);
protected:
UFUNCTION(BlueprintImplementableEvent, Category = "Controller")
void WidgetControllerSet(UWidgetController* NewWidgetController);
UFUNCTION(Category = "Controller|Propagation")
virtual bool AcceptWidgetController(UWidgetController* InWidgetController) const;
private:
UFUNCTION()
void PropagateWidgetController(UWidget* Parent);
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Controller", meta = (AllowPrivateAccess = true))
TObjectPtr<UWidgetController> WidgetController;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Controller|Propagation")
bool TakeControllerFromParent = true;
UPROPERTY(EditDefaultsOnly, Category = "Controller|Propagation")
TSet<TSubclassOf<UWidgetController>> AcceptedControllerClasses;
};

View File

@@ -0,0 +1,139 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "UI/WidgetControllerComponent.h"
#include "WidgetController.generated.h"
class AController;
class APlayerState;
class APawn;
class ACharacter;
/**
*
*/
UCLASS(BlueprintType, Blueprintable)
class LIBAMASSON_API UWidgetController : public UObject
{
GENERATED_BODY()
public:
UWidgetController();
/** Make and construct a widget controller from the specific class.
* If there is an observed actor given, it will cast it to the correct type and
* call SetObserved_X with it.
*/
UFUNCTION(BlueprintCallable, Category = "WidgetController|Construct", meta = (HidePin = "Outer", DefaultToSelf = "Outer"), meta = (DeterminesOutputType = "WidgetControllerClass"))
static UWidgetController* MakeWidgetController(UObject* Outer, TSubclassOf<UWidgetController> WidgetControllerClass, AActor* ObservedActor);
UFUNCTION(BlueprintCallable, Category = "Observed")
virtual void SetObservedController(AController* InController);
UFUNCTION(BlueprintCallable, Category = "Observed")
virtual void SetObservedPlayerState(APlayerState* InPlayerState);
UFUNCTION(BlueprintCallable, Category = "Observed")
virtual void SetObservedPawn(APawn* InPawn);
UFUNCTION(BlueprintCallable, Category = "Observed")
virtual void SetObservedActor(AActor* InActor, bool bTryCast = false);
UFUNCTION(BlueprintCallable, Category = "Broadcast")
virtual void BroadcastValues();
UFUNCTION(BlueprintCallable, Category = "Observed")
FORCEINLINE AController* GetController() const { return Controller; }
UFUNCTION(BlueprintCallable, Category = "Observed")
FORCEINLINE APlayerState* GetPlayerState() const { return PlayerState; }
UFUNCTION(BlueprintCallable, Category = "Observed")
FORCEINLINE APawn* GetPawn() const { return Pawn; }
UFUNCTION(BlueprintCallable, Category = "Observed")
AActor* GetObservedActor() const { return Actor; }
template<class TComponentType>
TComponentType* GetComponent()
{
static_assert(std::is_base_of<UWidgetControllerComponent, TComponentType>::value, "TComponentType must be a subclass of UWidgetControllerComponent.");
for (UWidgetControllerComponent* Component : Components)
{
if (TComponentType* CastComponent = Cast<TComponentType>(Component))
{
return CastComponent;
}
}
return nullptr;
}
UFUNCTION(BlueprintCallable, Category = "Component", meta = (DeterminesOutputType = "ComponentClass"))
UWidgetControllerComponent* GetComponentByClass(TSubclassOf<UWidgetControllerComponent> ComponentClass) const;
UFUNCTION(BlueprintCallable, Category = "Component", meta = (DeterminesOutputType = "ComponentClass"))
UWidgetControllerComponent* GetComponentByClassAndName(TSubclassOf<UWidgetControllerComponent> ComponentClass, FName ComponentName) const;
UFUNCTION(BlueprintCallable, Category = "Component", meta = (DeterminesOutputType = "ComponentClass"))
TArray<UWidgetControllerComponent*> GetComponentsByClass(TSubclassOf<UWidgetControllerComponent> ComponentClass) const;
template<class TComponentType>
TComponentType* AddComponent(FName ComponentName)
{
static_assert(std::is_base_of<UWidgetControllerComponent, TComponentType>::value, "TComponentType must be a subclass of UWidgetControllerComponent.");
TComponentType* NewComponent = NewObject<TComponentType>(this, TComponentType::StaticClass(), ComponentName);
Components.Add(NewComponent);
return NewComponent;
}
UFUNCTION(BlueprintCallable, Category = "Component", meta = (DeterminesOutputType = "ComponentClass"))
UWidgetControllerComponent* AddComponentByClass(TSubclassOf<UWidgetControllerComponent> ComponentClass, FName ComponentName);
protected:
UFUNCTION()
virtual void Construct() {}
UFUNCTION(BlueprintImplementableEvent, Category = "Construction", DisplayName = "Construct")
void BP_Construct();
UFUNCTION()
virtual void ObservedActorSet() {}
UFUNCTION(BlueprintImplementableEvent, Category = "Observed", DisplayName = "ObservedActorSet")
void BP_ObservedActorSet();
UFUNCTION()
virtual void BindCallbacksToDependencies();
UFUNCTION(BlueprintImplementableEvent, Category = "Broadcast", DisplayName = "BindCallbacksToDependencies")
void BP_BindCallbacksToDependencies();
/** Called at the end of controller SetObserved_X */
UFUNCTION(BlueprintCallable, Category = "Observed")
void FinishSetObserved();
UFUNCTION(BlueprintImplementableEvent, Category = "Broadcast", DisplayName = "BroadcastValues")
void BP_BroadcastValues();
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "WidgetController")
TObjectPtr<AController> Controller;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "WidgetController")
TObjectPtr<APlayerState> PlayerState;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "WidgetController")
TObjectPtr<APawn> Pawn;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "WidgetController")
TObjectPtr<AActor> Actor;
UPROPERTY()
TArray<TObjectPtr<UWidgetControllerComponent>> Components;
};

View File

@@ -0,0 +1,36 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "WidgetControllerComponent.generated.h"
/**
*
*/
UCLASS(Abstract, Blueprintable)
class LIBAMASSON_API UWidgetControllerComponent : public UObject
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Broadcast")
virtual void BroadcastValues();
UFUNCTION(BlueprintImplementableEvent, Category = "Broadcast", DisplayName = "BroadcastValues")
void BP_BroadcastValues();
protected:
UFUNCTION()
virtual void BindCallbacksToDependencies();
UFUNCTION(BlueprintImplementableEvent, Category = "Bind", DisplayName = "BindCallbacksToDependencies")
void BP_BindCallbacksToDependencies();
friend class UWidgetController;
};

View File

@@ -0,0 +1,40 @@
// Amasson
#pragma once
#include "CoreMinimal.h"
#include "UI/WidgetControllerComponent.h"
#include "GameManagementWcc.generated.h"
class APlayerController;
/**
*
*/
UCLASS()
class LIBAMASSON_API UGameManagementWcc : public UWidgetControllerComponent
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Initialize")
void Initialize(UObject* WorldContextObject);
/** GameplayStatics */
UFUNCTION(BlueprintCallable, meta=(AdvancedDisplay = "2", DisplayName = "Open Level (by Name)"), Category="Game")
void OpenLevel(FName LevelName, bool bAbsolute = true, FString Options = FString(TEXT("")));
UFUNCTION(BlueprintCallable, meta=(AdvancedDisplay = "2", DisplayName = "Open Level (by Object Reference)"), Category="Game")
void OpenLevelBySoftObjectPtr(const TSoftObjectPtr<UWorld> Level, bool bAbsolute = true, FString Options = FString(TEXT("")));
protected:
UPROPERTY()
TObjectPtr<UObject> WorldContextObject;
};

Some files were not shown because too many files have changed in this diff Show More