Interactables

This commit is contained in:
Oleg Petruny 2024-12-10 22:34:23 +01:00
parent 33cbfe1a18
commit 0226afe5ae
20 changed files with 90 additions and 57 deletions

View File

@ -9,7 +9,7 @@
/** /**
* Activates interactable only once if is in a camera view * Activates interactable only once if is in a camera view
*/ */
UCLASS(Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent, ShortTooltip = "Activates interactable only once if is in a camera view"), MinimalAPI) UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableActivator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Activates interactable only once if is in a camera view"), MinimalAPI)
class UInCameraInteractableActivator : public UInteractableActivator class UInCameraInteractableActivator : public UInteractableActivator
{ {
GENERATED_BODY() GENERATED_BODY()
@ -38,7 +38,7 @@ protected:
* @param interactable .. interactable activated * @param interactable .. interactable activated
*/ */
UFUNCTION(BlueprintImplementableEvent) UFUNCTION(BlueprintImplementableEvent)
virtual void OnNewSeenInteractable(class AInteractable* interactable); void OnNewSeenInteractable(class AInteractable* interactable);
private: private:
UPROPERTY() UPROPERTY()

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "InteractableActivator.h" #include "InteractableActivator.h"
#include "Engine/CollisionProfile.h" #include "Engine/CollisionProfile.h"

View File

@ -11,7 +11,10 @@
DECLARE_DELEGATE_TwoParams(FInteractableActivated, AInteractable*, EActivatorType); DECLARE_DELEGATE_TwoParams(FInteractableActivated, AInteractable*, EActivatorType);
DECLARE_DELEGATE_TwoParams(FInteractableDeactivated, AInteractable*, EActivatorType); DECLARE_DELEGATE_TwoParams(FInteractableDeactivated, AInteractable*, EActivatorType);
UCLASS(Abstract, Blueprintable, BlueprintType) /**
* Activates interactable based on type
*/
UCLASS(Abstract, Blueprintable, BlueprintType, ClassGroup = InteractableActivator, meta = (ShortTooltip = "Activates interactable based on type"), MinimalAPI)
class UInteractableActivator : public USceneComponent class UInteractableActivator : public USceneComponent
{ {
GENERATED_BODY() GENERATED_BODY()
@ -20,14 +23,16 @@ public:
UInteractableActivator(const FObjectInitializer& ObjectInitializer); UInteractableActivator(const FObjectInitializer& ObjectInitializer);
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
/** Resets activator state forcing to rescan */
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
LOST_EDGE_API void Rescan(); LOST_EDGE_API void Rescan();
virtual void Rescan_Implementation() {} virtual void Rescan_Implementation() PURE_VIRTUAL(UInteractableActivator::Scan_Implementation, );
FInteractableActivated interactableActivatedDelegate; FInteractableActivated interactableActivatedDelegate;
FInteractableActivated interactableDeactivatedDelegate; FInteractableActivated interactableDeactivatedDelegate;
protected: protected:
/** Activator scan function in game thread tick */
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
LOST_EDGE_API void Scan(); LOST_EDGE_API void Scan();
virtual void Scan_Implementation() PURE_VIRTUAL(UInteractableActivator::Scan_Implementation, ); virtual void Scan_Implementation() PURE_VIRTUAL(UInteractableActivator::Scan_Implementation, );

View File

@ -9,7 +9,9 @@
DECLARE_DELEGATE_OneParam(FInteractableInScreen, class AInteractable*); DECLARE_DELEGATE_OneParam(FInteractableInScreen, class AInteractable*);
/**
* Notifies only once about interactable is in a camera view
*/
UCLASS(BlueprintType, hidecategories = (Collision, Object, Physics, SceneComponent), ClassGroup = Rendering, editinlinenew, meta = (BlueprintSpawnableComponent, ShortTooltip = "Notifies only once about interactable is in a camera view"), MinimalAPI) UCLASS(BlueprintType, hidecategories = (Collision, Object, Physics, SceneComponent), ClassGroup = Rendering, editinlinenew, meta = (BlueprintSpawnableComponent, ShortTooltip = "Notifies only once about interactable is in a camera view"), MinimalAPI)
class UInteractableScreenCapturer : public USceneCaptureComponent2D class UInteractableScreenCapturer : public USceneCaptureComponent2D
{ {

View File

@ -9,7 +9,7 @@
/** /**
* Activates interactable with a single raycast from a camera center * Activates interactable with a single raycast from a camera center
*/ */
UCLASS(Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent, ShortTooltip = "Activates interactable with a single raycast from a camera center"), MinimalAPI) UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableActivator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Activates interactable with a single raycast from a camera center"), MinimalAPI)
class URaycastInteractableActivator : public UInteractableActivator class URaycastInteractableActivator : public UInteractableActivator
{ {
GENERATED_BODY() GENERATED_BODY()

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "Interactable.h" #include "Interactable.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
@ -86,13 +85,13 @@ void AInteractable::EndPlay(const EEndPlayReason::Type EndPlayReason)
if(activated) if(activated)
{ {
activationLockers.Empty(); activationLockers.Empty();
_Deactivate(static_cast<EActivatorType>(activated)); Deactivate(static_cast<EActivatorType>(activated));
} }
Super::EndPlay(EndPlayReason); Super::EndPlay(EndPlayReason);
} }
void AInteractable::_Activate(EActivatorType type) void AInteractable::Activate(EActivatorType type)
{ {
#ifdef INTERACTABLE_DEBUG #ifdef INTERACTABLE_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Cyan, TEXT("Player activate: ") + this->GetName() GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Cyan, TEXT("Player activate: ") + this->GetName()
@ -127,7 +126,7 @@ void AInteractable::_Activate(EActivatorType type)
Activate(type); Activate(type);
} }
void AInteractable::_Deactivate(EActivatorType type) void AInteractable::Deactivate(EActivatorType type)
{ {
#ifdef INTERACTABLE_DEBUG #ifdef INTERACTABLE_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Magenta, TEXT("Player deactivate: ") + this->GetName() GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Magenta, TEXT("Player deactivate: ") + this->GetName()

View File

@ -2,15 +2,18 @@
#pragma once #pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "Interactable.generated.h" #include "Interactable.generated.h"
/** Turns on debug of interactable objects */
//#define INTERACTABLE_DEBUG //#define INTERACTABLE_DEBUG
/** Turns on debug of interactable activator components */
//#define INTERACTABLE_ACTIVATOR_DEBUG //#define INTERACTABLE_ACTIVATOR_DEBUG
/** Turns on debug of interactable modificator components */
//#define INTERACTABLE_MODIFICATOR_DEBUG //#define INTERACTABLE_MODIFICATOR_DEBUG
/** Defines activation types */
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true")) UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
enum class EActivatorType : uint8 enum class EActivatorType : uint8
{ {
@ -27,38 +30,52 @@ enum class EActivatorType : uint8
}; };
ENUM_CLASS_FLAGS(EActivatorType); ENUM_CLASS_FLAGS(EActivatorType);
/**
* Object capable of reacting to activators and execute modificators.
* Sets all needed settings as collision layers on begin play.
*/
UCLASS(Blueprintable, BlueprintType, MinimalAPI) UCLASS(Blueprintable, BlueprintType, MinimalAPI)
class AInteractable : public AActor class AInteractable : public AActor
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
/** Returns flags mask of activated types */
int32 GetActivatedFlags(); int32 GetActivatedFlags();
void _Activate(EActivatorType type); /** Receives activate signal from activator of specific type and activates all modificators of that type */
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) UFUNCTION(BlueprintCallable)
void Activate(EActivatorType type); void Activate(EActivatorType type);
virtual void Activate_Implementation(EActivatorType type) {}
void _Deactivate(EActivatorType type); /** Receives deactivate signal from activator of specific type and deactivates all modificators of that type */
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) UFUNCTION(BlueprintCallable)
void Deactivate(EActivatorType type); void Deactivate(EActivatorType type);
virtual void Deactivate_Implementation(EActivatorType type) {}
/**
* All modificators that requires (de)activation lock for current interactable.
* Used manually by modificators to handle operations which can be continued after physical deactivation.
* Eg. MoveModificator movement while mouse buttons are down even if player don't activating interactable anymore.
*/
TSet<class UInteractableModificator*> activationLockers; TSet<class UInteractableModificator*> activationLockers;
protected: protected:
virtual void BeginPlay() override; virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFUNCTION(BlueprintImplementableEvent)
void OnActivate(EActivatorType type);
UFUNCTION(BlueprintImplementableEvent)
void OnDeactivate(EActivatorType type);
/** Mask of active activator types */
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Bitmask, BitmaskEnum = "EActivatorType")) UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
int32 activated = 0; int32 activated = 0;
/** Map of modificators to activator types initialized on BeginPlay */
UPROPERTY() UPROPERTY()
TMap<EActivatorType, class UInteractableModificator*> modificators; TMap<EActivatorType, class UInteractableModificator*> modificators;
class APlayerBase* player = nullptr;
TArray<UPrimitiveComponent*> collisions; TArray<UPrimitiveComponent*> collisions;
class APlayerBase* player = nullptr;
}; };

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "ActivateInteractableModificator.h" #include "ActivateInteractableModificator.h"
#include "EnhancedInputComponent.h" #include "EnhancedInputComponent.h"

View File

@ -2,14 +2,16 @@
#pragma once #pragma once
#include "CoreMinimal.h"
#include "InteractableModificator.h" #include "InteractableModificator.h"
#include "ActivateInteractableModificator.generated.h" #include "ActivateInteractableModificator.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FActivateInteractableModificatorActivatedDelegate); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FActivateInteractableModificatorActivatedDelegate);
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) /**
* Basic modificator for type Use
*/
UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Basic modificator for type Use"), MinimalAPI)
class UActivateInteractableModificator : public UInteractableModificator class UActivateInteractableModificator : public UInteractableModificator
{ {
GENERATED_BODY() GENERATED_BODY()

View File

@ -1,14 +1,11 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "EditInteractableModificator.h" #include "EditInteractableModificator.h"
#include "Interactable/Interactable.h" #include "Interactable/Interactable.h"
UEditInteractableModificator::UEditInteractableModificator(const FObjectInitializer& ObjectInitializer) //UEditInteractableModificator::UEditInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer) // : UInteractableModificator(ObjectInitializer)
{ //{
activatorTypes |= static_cast<uint8>(EActivatorType::Collide); // activatorTypes |= static_cast<uint8>(EActivatorType::Collide);
//}
}

View File

@ -2,17 +2,20 @@
#pragma once #pragma once
#include "CoreMinimal.h"
#include "InteractableModificator.h" #include "InteractableModificator.h"
#include "EditInteractableModificator.generated.h" //#include "EditInteractableModificator.generated.h"
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) /**
class UEditInteractableModificator : public UInteractableModificator * <WIP>
{ * Edits object topology on collision
GENERATED_BODY() */
//UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Edits object topology on collision"), MinimalAPI)
public: //class UEditInteractableModificator : public UInteractableModificator
UEditInteractableModificator(const FObjectInitializer& ObjectInitializer); //{
// GENERATED_BODY()
}; //
//public:
// UEditInteractableModificator(const FObjectInitializer& ObjectInitializer);
//
//};

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "InteractableModificator.h" #include "InteractableModificator.h"
#include "InputMappingContext.h" #include "InputMappingContext.h"

View File

@ -3,29 +3,37 @@
#pragma once #pragma once
#include "Components/ActorComponent.h" #include "Components/ActorComponent.h"
#include "CoreMinimal.h"
#include "InteractableModificator.generated.h" #include "InteractableModificator.generated.h"
enum class EActivatorType : uint8; enum class EActivatorType : uint8;
UCLASS(Abstract, Blueprintable, BlueprintType) /**
* Do something on activation by specified activator types
*/
UCLASS(Abstract, Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Do something on activation by specified activator types"), MinimalAPI)
class UInteractableModificator : public UActorComponent class UInteractableModificator : public UActorComponent
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
/** Append itself to CustomGameInstance modificators registry */
void OnRegister() override; void OnRegister() override;
/** Returns input mappings assigned in constructor */
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
const class UInputMappingContext* GetMappingContext() const; const class UInputMappingContext* GetMappingContext() const;
/** Filters activation type in interractable */
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
EActivatorType GetActivatorTypes() const; EActivatorType GetActivatorTypes() const;
/** Called from interactable on activation (mostly used to bind input context to internal modificator functions) */
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Bind(class UEnhancedInputComponent* input); void Bind(class UEnhancedInputComponent* input);
virtual void Bind_Implementation(class UEnhancedInputComponent* input) {} virtual void Bind_Implementation(class UEnhancedInputComponent* input) {}
/** Called from interactable on deactivation (mostly used to unbind input context from internal functions) */
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Unbind(); void Unbind();
virtual void Unbind_Implementation() {} virtual void Unbind_Implementation() {}

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "InventoryInteractableModificator.h" #include "InventoryInteractableModificator.h"
#include "EnhancedInputComponent.h" #include "EnhancedInputComponent.h"

View File

@ -2,12 +2,14 @@
#pragma once #pragma once
#include "CoreMinimal.h"
#include "InteractableModificator.h" #include "InteractableModificator.h"
#include "InventoryInteractableModificator.generated.h" #include "InventoryInteractableModificator.generated.h"
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) /**
* Modificator of type Use for storing items in a APlayerBase
*/
UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Modificator of type Use for storing items in a APlayerBase"), MinimalAPI)
class UInventoryInteractableModificator : public UInteractableModificator class UInventoryInteractableModificator : public UInteractableModificator
{ {
GENERATED_BODY() GENERATED_BODY()

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "MoveInteractableModificator.h" #include "MoveInteractableModificator.h"
#include "EnhancedInputComponent.h" #include "EnhancedInputComponent.h"
@ -90,7 +89,7 @@ void UMoveInteractableModificator::Unbind_Implementation()
bindindingHandlers.Empty(); bindindingHandlers.Empty();
SetComponentTickEnabled(false); SetComponentTickEnabled(false);
actor->_Deactivate(GetActivatorTypes()); actor->Deactivate(GetActivatorTypes());
OnMoveDeactivated.Broadcast(); OnMoveDeactivated.Broadcast();
} }

View File

@ -2,7 +2,6 @@
#pragma once #pragma once
#include "CoreMinimal.h"
#include "InputActionValue.h" #include "InputActionValue.h"
#include "InteractableModificator.h" #include "InteractableModificator.h"
@ -13,7 +12,10 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDeactivateMoveInteractableModificatorActivat
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FHoldingMoveInteractableModificatorActivatedDelegate); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FHoldingMoveInteractableModificatorActivatedDelegate);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRotatingMoveInteractableModificatorActivatedDelegate); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRotatingMoveInteractableModificatorActivatedDelegate);
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) /**
* Basic modificator for Move type activator
*/
UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Basic modificator for Move type activator"), MinimalAPI)
class UMoveInteractableModificator : public UInteractableModificator class UMoveInteractableModificator : public UInteractableModificator
{ {
GENERATED_BODY() GENERATED_BODY()

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "SawInteractableModificator.h" #include "SawInteractableModificator.h"
#include "Interactable/Interactable.h" #include "Interactable/Interactable.h"

View File

@ -2,14 +2,16 @@
#pragma once #pragma once
#include "CoreMinimal.h"
#include "InteractableModificator.h" #include "InteractableModificator.h"
#include "SawInteractableModificator.generated.h" #include "SawInteractableModificator.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FSawInteractableModificatorActivatedDelegate); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FSawInteractableModificatorActivatedDelegate);
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) /**
* Basic modificator for Saw type activator
*/
UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Basic modificator for Saw type activator"), MinimalAPI)
class USawInteractableModificator : public UInteractableModificator class USawInteractableModificator : public UInteractableModificator
{ {
GENERATED_BODY() GENERATED_BODY()

View File

@ -284,7 +284,7 @@ void APlayerBase::InteractableActivated(AInteractable* interactable, EActivatorT
if(interactionLocked || interactable->IsHidden()) if(interactionLocked || interactable->IsHidden())
return; return;
interactable->_Activate(type); interactable->Activate(type);
if(interactable != lastInteractable) if(interactable != lastInteractable)
lastInteractable = interactable; lastInteractable = interactable;
@ -295,7 +295,7 @@ void APlayerBase::InteractableDeactivated(AInteractable* interactable, EActivato
if(!interactable) if(!interactable)
return; return;
interactable->_Deactivate(type); interactable->Deactivate(type);
if(interactable->GetActivatedFlags() == 0) if(interactable->GetActivatedFlags() == 0)
lastInteractable = nullptr; lastInteractable = nullptr;