interactable activator documentation

This commit is contained in:
Oleg Petruny 2024-12-03 18:29:28 +01:00
parent 644083344e
commit 33cbfe1a18
7 changed files with 70 additions and 48 deletions

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "InCameraInteractableActivator.h" #include "InCameraInteractableActivator.h"
#include "CommonFunctions.h" #include "CommonFunctions.h"
@ -20,10 +19,10 @@ UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInit
activatorType = EActivatorType::Saw; activatorType = EActivatorType::Saw;
scanDistance = 7000; scanDistance = 7000;
_capturer = CreateDefaultSubobject<UInteractableScreenCapturer>(TEXT("UInCameraInteractableActivator_UInteractableScreenCapturer")); capturer = CreateDefaultSubobject<UInteractableScreenCapturer>(TEXT("UInCameraInteractableActivator_UInteractableScreenCapturer"));
_capturer->interactableInScreenDelegate.BindUObject(this, &UInCameraInteractableActivator::NewSeenInteractable_Implementation); capturer->interactableInScreenDelegate.BindUObject(this, &UInCameraInteractableActivator::NewSeenInteractable);
_capturer->SetupAttachment(this); capturer->SetupAttachment(this);
_capturer->scanDistance = scanDistance; capturer->scanDistance = scanDistance;
PrimaryComponentTick.bCanEverTick = true; PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = false; PrimaryComponentTick.bStartWithTickEnabled = false;
@ -32,26 +31,27 @@ UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInit
void UInCameraInteractableActivator::OnRegister() void UInCameraInteractableActivator::OnRegister()
{ {
UInteractableActivator::OnRegister(); UInteractableActivator::OnRegister();
_capturer->RegisterComponent(); capturer->RegisterComponent();
_capturer->Activate(); capturer->Activate();
} }
void UInCameraInteractableActivator::NewSeenInteractable_Implementation(AInteractable* interactable) void UInCameraInteractableActivator::NewSeenInteractable(AInteractable* interactable)
{ {
_interactablesToActivate.Enqueue(interactable); interactablesToActivate.Enqueue(interactable);
SetComponentTickEnabled(true); SetComponentTickEnabled(true);
} }
void UInCameraInteractableActivator::Scan_Implementation() void UInCameraInteractableActivator::Scan_Implementation()
{ {
SetComponentTickEnabled(false); SetComponentTickEnabled(false);
while(!_interactablesToActivate.IsEmpty()) while(!interactablesToActivate.IsEmpty())
{ {
AInteractable* interactable; AInteractable* interactable;
_interactablesToActivate.Dequeue(interactable); interactablesToActivate.Dequeue(interactable);
if(interactableActivatedDelegate.IsBound()) if(interactableActivatedDelegate.IsBound())
{ {
interactableActivatedDelegate.Execute(interactable, activatorType); interactableActivatedDelegate.Execute(interactable, activatorType);
OnNewSeenInteractable(interactable);
} }
} }
} }

View File

@ -2,13 +2,14 @@
#pragma once #pragma once
#include "CoreMinimal.h"
#include "InteractableActivator.h" #include "InteractableActivator.h"
#include "InCameraInteractableActivator.generated.h" #include "InCameraInteractableActivator.generated.h"
UCLASS(Blueprintable, BlueprintType) /**
* 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)
class UInCameraInteractableActivator : public UInteractableActivator class UInCameraInteractableActivator : public UInteractableActivator
{ {
GENERATED_BODY() GENERATED_BODY()
@ -19,14 +20,28 @@ public:
protected: protected:
virtual void OnRegister() override; virtual void OnRegister() override;
/**
* Scan is performed independently by _capturer member object.
* This implementation just activates interactables in the game thread.
*/
virtual void Scan_Implementation() override; virtual void Scan_Implementation() override;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) /**
LOST_EDGE_API void NewSeenInteractable(class AInteractable* interactable); * Thread safe enques interactable for activation in the next game tick
virtual void NewSeenInteractable_Implementation(class AInteractable* interactable); * @param interactable .. interactable to activate
*/
UFUNCTION(BlueprintCallable)
void NewSeenInteractable(class AInteractable* interactable);
/**
* Called after interactable activation
* @param interactable .. interactable activated
*/
UFUNCTION(BlueprintImplementableEvent)
virtual void OnNewSeenInteractable(class AInteractable* interactable);
private: private:
UPROPERTY() UPROPERTY()
class UInteractableScreenCapturer* _capturer; class UInteractableScreenCapturer* capturer;
TQueue<class AInteractable*> _interactablesToActivate; TQueue<class AInteractable*> interactablesToActivate;
}; };

View File

@ -3,7 +3,6 @@
#pragma once #pragma once
#include "Components/SceneComponent.h" #include "Components/SceneComponent.h"
#include "CoreMinimal.h"
#include "Interactable/Interactable.h" #include "Interactable/Interactable.h"

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "InteractableScreenCapturer.h" #include "InteractableScreenCapturer.h"
#include "Engine/Texture.h" #include "Engine/Texture.h"
@ -16,9 +15,12 @@
#include "Interactable/Interactable.h" #include "Interactable/Interactable.h"
#include "InteractableScreenCapturerBitMapCS.h" #include "InteractableScreenCapturerBitMapCS.h"
constexpr float tickInterval = 1.0f / 5; namespace
constexpr float textureWidth = 1280 / 2; {
constexpr float textureHeight = 720 / 2; constexpr float tickInterval = 1.0f / 5;
constexpr float textureWidth = 1280 / 2;
constexpr float textureHeight = 720 / 2;
}
UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer) UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer)
: USceneCaptureComponent2D(ObjectInitializer) : USceneCaptureComponent2D(ObjectInitializer)
@ -85,7 +87,7 @@ void UInteractableScreenCapturer::TickComponent(float DeltaTime, enum ELevelTick
{ {
USceneCaptureComponent2D::TickComponent(DeltaTime, TickType, ThisTickFunction); USceneCaptureComponent2D::TickComponent(DeltaTime, TickType, ThisTickFunction);
CaptureScene(); CaptureScene();
GetCameraView(DeltaTime, _view); GetCameraView(DeltaTime, view);
Process(); Process();
} }
break; break;
@ -104,7 +106,7 @@ void UInteractableScreenCapturer::Process()
[ [
capture = TextureTarget->GetResource()->TextureRHI, capture = TextureTarget->GetResource()->TextureRHI,
world = GetWorld(), world = GetWorld(),
view = _view, view = view,
//output = _output->GetResource()->TextureRHI, //output = _output->GetResource()->TextureRHI,
this this
] ]
@ -262,6 +264,7 @@ void UInteractableScreenCapturer::Process()
AsyncTask(ENamedThreads::GameThread, [=, this]() AsyncTask(ENamedThreads::GameThread, [=, this]()
{ {
interactableInScreenDelegate.Execute(interactable); interactableInScreenDelegate.Execute(interactable);
OnInteractableInScreen(interactable);
}); });
} }
} }

View File

@ -9,7 +9,8 @@
DECLARE_DELEGATE_OneParam(FInteractableInScreen, class AInteractable*); DECLARE_DELEGATE_OneParam(FInteractableInScreen, class AInteractable*);
UCLASS(hidecategories = (Collision, Object, Physics, SceneComponent), ClassGroup = Rendering, editinlinenew, meta = (BlueprintSpawnableComponent), 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
{ {
GENERATED_BODY() GENERATED_BODY()
@ -19,15 +20,18 @@ public:
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
FInteractableInScreen interactableInScreenDelegate; FInteractableInScreen interactableInScreenDelegate;
UFUNCTION(BlueprintImplementableEvent)
void OnInteractableInScreen(class AInteractable* interactable);
UPROPERTY(EditAnywhere) UPROPERTY(EditAnywhere)
float scanDistance = 7000; float scanDistance = 7000;
protected: protected:
/** Enques render thread task to find obect on screen */
void Process(); void Process();
private: private:
FMinimalViewInfo _view; FMinimalViewInfo view; //!< Camera view cache
TSet<class AInteractable*> _sawInteractables; TSet<class AInteractable*> _sawInteractables;
//class UTextureRenderTarget2D* _output; //class UTextureRenderTarget2D* _output;
}; };

View File

@ -1,6 +1,5 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "RaycastInteractableActivator.h" #include "RaycastInteractableActivator.h"
#include "DrawDebugHelpers.h" #include "DrawDebugHelpers.h"
@ -14,12 +13,12 @@ URaycastInteractableActivator::URaycastInteractableActivator(const FObjectInitia
void URaycastInteractableActivator::Rescan_Implementation() void URaycastInteractableActivator::Rescan_Implementation()
{ {
_last = nullptr; lastInteractable = nullptr;
} }
void URaycastInteractableActivator::Scan_Implementation() void URaycastInteractableActivator::Scan_Implementation()
{ {
FHitResult result{}; FHitResult result;
FVector startLocation = GetComponentLocation(); FVector startLocation = GetComponentLocation();
FVector endLocation = startLocation + (GetComponentRotation().Vector() * scanDistance); FVector endLocation = startLocation + (GetComponentRotation().Vector() * scanDistance);
@ -32,17 +31,17 @@ void URaycastInteractableActivator::Scan_Implementation()
if(result.bBlockingHit) if(result.bBlockingHit)
{ {
if(_last != result.GetActor()) if(lastInteractable != result.GetActor())
{ {
if(_last) if(lastInteractable)
{ {
interactableDeactivatedDelegate.Execute(_last, activatorType); interactableDeactivatedDelegate.Execute(lastInteractable, activatorType);
_last = nullptr; lastInteractable = nullptr;
} }
_activated = true; activated = true;
if(auto interactable = Cast<AInteractable>(result.GetActor())) if(auto interactable = Cast<AInteractable>(result.GetActor()))
{ {
_last = interactable; lastInteractable = interactable;
if(interactableActivatedDelegate.IsBound()) if(interactableActivatedDelegate.IsBound())
{ {
interactableActivatedDelegate.Execute(interactable, activatorType); interactableActivatedDelegate.Execute(interactable, activatorType);
@ -56,18 +55,18 @@ void URaycastInteractableActivator::Scan_Implementation()
} }
else else
{ {
if(_activated) if(activated)
{ {
if(interactableDeactivatedDelegate.IsBound()) if(interactableDeactivatedDelegate.IsBound())
{ {
interactableDeactivatedDelegate.Execute(_last, activatorType); interactableDeactivatedDelegate.Execute(lastInteractable, activatorType);
} }
_activated = false; activated = false;
_last = nullptr; lastInteractable = nullptr;
} }
#ifdef INTERACTABLE_ACTIVATOR_DEBUG #ifdef INTERACTABLE_ACTIVATOR_DEBUG
DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, PrimaryComponentTick.TickInterval, 10, 0.1f); DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, PrimaryComponentTick.TickInterval, 10, 0.1f);
#endif // INTERACTABLE_ACTIVATOR_DEBUG #endif // INTERACTABLE_ACTIVATOR_DEBUG
} }
} }

View File

@ -2,12 +2,14 @@
#pragma once #pragma once
#include "CoreMinimal.h"
#include "InteractableActivator.h" #include "InteractableActivator.h"
#include "RaycastInteractableActivator.generated.h" #include "RaycastInteractableActivator.generated.h"
UCLASS(Blueprintable, BlueprintType) /**
* 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)
class URaycastInteractableActivator : public UInteractableActivator class URaycastInteractableActivator : public UInteractableActivator
{ {
GENERATED_BODY() GENERATED_BODY()
@ -21,6 +23,6 @@ protected:
virtual void Scan_Implementation() override; virtual void Scan_Implementation() override;
private: private:
class AInteractable* _last = nullptr; class AInteractable* lastInteractable = nullptr;
bool _activated = false; bool activated = false;
}; };