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

View File

@ -2,13 +2,14 @@
#pragma once
#include "CoreMinimal.h"
#include "InteractableActivator.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
{
GENERATED_BODY()
@ -19,14 +20,28 @@ public:
protected:
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;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
LOST_EDGE_API void NewSeenInteractable(class AInteractable* interactable);
virtual void NewSeenInteractable_Implementation(class AInteractable* interactable);
/**
* Thread safe enques interactable for activation in the next game tick
* @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:
UPROPERTY()
class UInteractableScreenCapturer* _capturer;
TQueue<class AInteractable*> _interactablesToActivate;
class UInteractableScreenCapturer* capturer;
TQueue<class AInteractable*> interactablesToActivate;
};

View File

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

View File

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

View File

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

View File

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

View File

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