Interactable code cleanup, complete activators

This commit is contained in:
Oleg Petruny 2024-06-02 11:39:07 +02:00
parent 2a5677656c
commit 15244e3936
54 changed files with 447 additions and 253 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,6 @@
{ {
"FileVersion": 3, "FileVersion": 3,
"EngineAssociation": "{0DD41C75-443A-77B1-7C02-5F9B73D04B7B}", "EngineAssociation": "5.4",
"Category": "", "Category": "",
"Description": "", "Description": "",
"Modules": [ "Modules": [

View File

@ -10,14 +10,14 @@ RWBuffer<unsigned int> Output;
void InteractableScreenCapturerBitMapCS( void InteractableScreenCapturerBitMapCS(
uint3 dti : SV_DispatchThreadID) uint3 dti : SV_DispatchThreadID)
{ {
switch (Input[dti.x]) Output[dti.x] = Input[dti.x];
{ //switch (Input[dti.x])
case 0xFF00FFFF: //{
//Output[dti.x / 4] = Output[dti.x / 4] | (0xFF << 8 * (3 - (dti.x % 4))); // sets n-th byte to 0xFF // case 0xFF00FFFF:
break; // Output[dti.x / 4] = Output[dti.x / 4] | (0xFF << 8 * (3 - (dti.x % 4))); // sets n-th byte to 0xFF
default: // break;
//Output[dti.x / 4] = Output[dti.x / 4] & ~(0xFF << 8 * (3 - (dti.x % 4))); // sets n-th byte to 0x00 // default:
break; // Output[dti.x / 4] = Output[dti.x / 4] & ~(0xFF << 8 * (3 - (dti.x % 4))); // sets n-th byte to 0x00
} // break;
//Output[0] = 1; //}
} }

View File

@ -7,13 +7,14 @@
#include "InputMappingContext.h" #include "InputMappingContext.h"
#include "CustomGameUserSettings.h" #include "CustomGameUserSettings.h"
#include "Interactable/SawInteractable.h" #include "Interactable/Activators/InCameraInteractableActivator.h"
#include "Interactable/UsableInteractable.h" #include "Interactable/Activators/RaycastInteractableActivator.h"
void UCustomGameInstanceBase::Init() void UCustomGameInstanceBase::Init()
{ {
// IN FUTURE ASSIGN FROM CONTENT LOADER MEMBER // IN FUTURE ASSIGN FROM CONTENT LOADER MEMBER
interactionsActivators = { {UUsableInteractable::StaticClass()}, {USawInteractable::StaticClass()} }; interactionsActivators.Add(URaycastInteractableActivator::StaticClass());
interactionsActivators.Add(UInCameraInteractableActivator::StaticClass());
UGameInstance::Init(); UGameInstance::Init();

View File

@ -19,7 +19,7 @@ public:
void ApplyMouseSettings(); void ApplyMouseSettings();
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
TArray<TSubclassOf<class UInteractableComponent>> interactionsActivators; TArray<TSubclassOf<class UInteractableActivator>> interactionsActivators;
protected: protected:
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)

View File

@ -1,9 +1,8 @@
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#include "Interactable/InCameraInteractableActivator.h" #include "InCameraInteractableActivator.h"
#include "Interactable.h"
#include "InteractableScreenCapturer.h" #include "InteractableScreenCapturer.h"
UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInitializer& ObjectInitializer) UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInitializer& ObjectInitializer)
@ -14,9 +13,13 @@ UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInit
return; return;
} }
activatorType = EActivatorType::Saw;
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_Implementation);
_capturer->SetupAttachment(this); _capturer->SetupAttachment(this);
_capturer->scanDistance = scanDistance;
PrimaryComponentTick.bCanEverTick = true; PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = false; PrimaryComponentTick.bStartWithTickEnabled = false;
@ -44,7 +47,7 @@ void UInCameraInteractableActivator::Scan_Implementation()
_interactablesToActivate.Dequeue(interactable); _interactablesToActivate.Dequeue(interactable);
if(interactableActivatedDelegate.IsBound()) if(interactableActivatedDelegate.IsBound())
{ {
interactableActivatedDelegate.Execute(interactable); interactableActivatedDelegate.Execute(interactable, activatorType);
} }
} }
} }

View File

@ -5,10 +5,12 @@
#include "Components/SceneComponent.h" #include "Components/SceneComponent.h"
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "../Interactable.h"
#include "InteractableActivator.generated.h" #include "InteractableActivator.generated.h"
DECLARE_DELEGATE_OneParam(FInteractableActivated, class AInteractable*); DECLARE_DELEGATE_TwoParams(FInteractableActivated, AInteractable*, EActivatorType);
DECLARE_DELEGATE_OneParam(FInteractableDeactivated, class AInteractable*); DECLARE_DELEGATE_TwoParams(FInteractableDeactivated, AInteractable*, EActivatorType);
UCLASS(Abstract, Blueprintable, BlueprintType) UCLASS(Abstract, Blueprintable, BlueprintType)
class UInteractableActivator : public USceneComponent class UInteractableActivator : public USceneComponent
@ -27,10 +29,13 @@ protected:
inline void Scan(); inline void Scan();
inline virtual void Scan_Implementation() PURE_VIRTUAL(UInteractableActivator::Scan_Implementation, ); inline virtual void Scan_Implementation() PURE_VIRTUAL(UInteractableActivator::Scan_Implementation, );
UPROPERTY(EditDefaultsOnly)
EActivatorType activatorType;
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
float scanDistance = 200; float scanDistance = 200;
class UWorld* world; class UWorld* world;
class APlayerBase* player; class APlayerBase* player;
enum ECollisionChannel collisionChannel; ECollisionChannel collisionChannel;
}; };

View File

@ -7,16 +7,18 @@
#include "Engine/TextureRenderTarget2D.h" #include "Engine/TextureRenderTarget2D.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#include "RenderGraphUtils.h"
#include "RHIGPUReadback.h"
#include "RHIResources.h" #include "RHIResources.h"
#include "SceneView.h" #include "SceneView.h"
#include "TextureCompressorModule.h" #include "TextureCompressorModule.h"
#include "Interactable.h" #include "../Interactable.h"
#include "InteractableScreenCapturerBitMapCS.h"
constexpr float tickInterval = 1.0f / 5; constexpr float tickInterval = 1.0f / 5;
constexpr float textureWidth = 1280 / 2; constexpr float textureWidth = 1280 / 2;
constexpr float textureHeight = 720 / 2; constexpr float textureHeight = 720 / 2;
constexpr float rayDistance = 7000;
UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer) UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer)
: USceneCaptureComponent2D(ObjectInitializer) : USceneCaptureComponent2D(ObjectInitializer)
@ -24,7 +26,8 @@ UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitialize
PrimaryComponentTick.bCanEverTick = false; PrimaryComponentTick.bCanEverTick = false;
PrimaryComponentTick.bStartWithTickEnabled = false; PrimaryComponentTick.bStartWithTickEnabled = false;
TextureTarget = LoadObject<UTextureRenderTarget2D>(this, TEXT("/Game/tempStaff/Input")); TextureTarget = LoadObject<UTextureRenderTarget2D>(this, TEXT("/Game/Misc/Interactables/T_InteractableScreencapturerDebugInput"));
//_output = LoadObject<UTextureRenderTarget2D>(this, TEXT("/Game/Misc/Interactables/T_InteractableScreencapturerDebugOutput"));
//TextureTarget = ObjectInitializer.CreateDefaultSubobject<UTextureRenderTarget2D>(this, TEXT("UInteractableScreenCapturer_TextureRenderTarget")); //TextureTarget = ObjectInitializer.CreateDefaultSubobject<UTextureRenderTarget2D>(this, TEXT("UInteractableScreenCapturer_TextureRenderTarget"));
//TextureTarget->RenderTargetFormat = ETextureRenderTargetFormat::RTF_RGBA8; //TextureTarget->RenderTargetFormat = ETextureRenderTargetFormat::RTF_RGBA8;
//TextureTarget->ClearColor = FLinearColor::Black; //TextureTarget->ClearColor = FLinearColor::Black;
@ -36,12 +39,14 @@ UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitialize
PrimitiveRenderMode = ESceneCapturePrimitiveRenderMode::PRM_LegacySceneCapture; PrimitiveRenderMode = ESceneCapturePrimitiveRenderMode::PRM_LegacySceneCapture;
bCaptureEveryFrame = 0; bCaptureEveryFrame = 0;
bCaptureOnMovement = 0; bCaptureOnMovement = 0;
LODDistanceFactor = 10000; LODDistanceFactor = 1;
bUseRayTracingIfEnabled = false; bUseRayTracingIfEnabled = false;
CaptureSource = ESceneCaptureSource::SCS_BaseColor; CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR;
CompositeMode = ESceneCaptureCompositeMode::SCCM_Overwrite; CompositeMode = ESceneCaptureCompositeMode::SCCM_Overwrite;
PostProcessBlendWeight = 0; PostProcessBlendWeight = 1;
auto ppMaterial = LoadObject<UMaterial>(this, TEXT("/Game/Misc/Interactables/M_InteractableScreencapturerPP"));
PostProcessSettings.AddBlendable(ppMaterial, 1.0f);
bUseCustomProjectionMatrix = false; bUseCustomProjectionMatrix = false;
bAlwaysPersistRenderingState = true; bAlwaysPersistRenderingState = true;
@ -57,6 +62,8 @@ UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitialize
ShowFlags.SetGame(true); ShowFlags.SetGame(true);
ShowFlags.SetMaterials(true); ShowFlags.SetMaterials(true);
ShowFlags.SetRendering(true); ShowFlags.SetRendering(true);
ShowFlags.SetPostProcessMaterial(true);
ShowFlags.SetPostProcessing(true);
PrimaryComponentTick.TickInterval = tickInterval; PrimaryComponentTick.TickInterval = tickInterval;
PrimaryComponentTick.bCanEverTick = true; PrimaryComponentTick.bCanEverTick = true;
@ -74,7 +81,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;
default: default:
@ -93,13 +100,71 @@ void UInteractableScreenCapturer::Process()
capture = TextureTarget->GetResource()->TextureRHI, capture = TextureTarget->GetResource()->TextureRHI,
world = GetWorld(), world = GetWorld(),
view = _view, view = _view,
//output = _output->GetResource()->TextureRHI,
this this
] ]
(FRHICommandListImmediate& RHICmdList) (FRHICommandListImmediate& RHICmdList)
{ {
#ifdef INTERACTABLE_ACTIVATOR_DEBUG
double StartTime = FPlatformTime::Seconds(); double StartTime = FPlatformTime::Seconds();
#endif // INTERACTABLE_ACTIVATOR_DEBUG
static FIntPoint _extent = capture->GetDesc().Extent; static FIntPoint _extent = capture->GetDesc().Extent;
static uint32 _size = _extent.X * _extent.Y; static int32 _size = _extent.X * _extent.Y;
//FRHIResourceCreateInfo outBufferCreateInfo(TEXT("InteractableScreenCapturerCSOutBuffer"));
//EBufferUsageFlags outBufferUsage = EBufferUsageFlags::UnorderedAccess | EBufferUsageFlags::SourceCopy;
//FBufferRHIRef outBuffer = RHICmdList.CreateBuffer(_size * sizeof(uint32), outBufferUsage, 0, ERHIAccess::UAVCompute, outBufferCreateInfo);
//auto outBufferUAVCreateDesc = FRHIViewDesc::CreateBufferUAV()
// .SetType(FRHIViewDesc::EBufferType::Typed)
// .SetFormat(PF_R32_UINT)
// .SetNumElements(_size);
//auto outBufferUAV = RHICmdList.CreateUnorderedAccessView(outBuffer, outBufferUAVCreateDesc);
//
//TShaderMapRef<FInteractableScreenCapturerBitMapCS> shader(GetGlobalShaderMap(GMaxRHIFeatureLevel));
//const uint32 threadsNum = FMath::DivideAndRoundUp(_size, FInteractableScreenCapturerBitMapCS::shader_threads_per_group_count);
//
//FInteractableScreenCapturerBitMapCS::FParameters shaderParams;
//shaderParams.Input = RHICmdList.CreateShaderResourceView(capture, FRHIViewDesc::CreateTextureSRV()
// .SetDimensionFromTexture(capture)
// .SetMipRange(0, 1));
//shaderParams.Output = outBufferUAV;
//
//FComputeShaderUtils::Dispatch(RHICmdList, shader, shaderParams, FIntVector(threadsNum, 1, 1));
//
//RHICmdList.Transition({ FRHITransitionInfo(outBufferUAV, ERHIAccess::UAVCompute, ERHIAccess::CopySrc) });
//
//// Kick off the readbacks.
//FRHIGPUBufferReadback outBufferReadback(TEXT("InteractableScreenCapturerCSOutBufferReadback"));
//outBufferReadback.EnqueueCopy(RHICmdList, outBuffer, _size * sizeof(uint32));
//
//// Sync the GPU. Unfortunately we can't use the fences because not all RHIs implement them yet.
//RHICmdList.BlockUntilGPUIdle();
//RHICmdList.FlushResources();
//
//uint32* outBufferData = (uint32*)outBufferReadback.Lock(_size * sizeof(uint32));
//uint32 sstride = 0;
//uint32* ddata = (uint32*)RHICmdList.LockTexture2D(
// output,
// 0,
// RLM_WriteOnly,
// sstride,
// false);
//for(int32 i = 0; i < _size; ++i)
//{
// ddata[i] = outBufferData[i];
// //switch(outBufferData[i])
// //{
// // case 0xFF:
// // ddata[i] = 0xFFFFFFFF;
// // default:
// // ddata[i] = 0x00000000;
// //}
//}
//RHICmdList.UnlockTexture2D(output, 0, false);
//
//outBufferReadback.Unlock();
static uint8* _bitMap = new uint8[_size]; // cv::Mat allocation is weird sometimes... static uint8* _bitMap = new uint8[_size]; // cv::Mat allocation is weird sometimes...
@ -110,7 +175,7 @@ void UInteractableScreenCapturer::Process()
RLM_ReadOnly, RLM_ReadOnly,
stride, stride,
false); false);
for(uint32 i = 0; i < _size; ++i) for(int32 i = 0; i < _size; ++i)
{ {
switch(data[i].R) switch(data[i].R)
{ {
@ -167,17 +232,15 @@ void UInteractableScreenCapturer::Process()
* (FInverseRotationMatrix(view.Rotation) * FMatrix(FPlane(0, 0, 1, 0), FPlane(1, 0, 0, 0), FPlane(0, 1, 0, 0), FPlane(0, 0, 0, 1))) * (FInverseRotationMatrix(view.Rotation) * FMatrix(FPlane(0, 0, 1, 0), FPlane(1, 0, 0, 0), FPlane(0, 1, 0, 0), FPlane(0, 0, 0, 1)))
* view.CalculateProjectionMatrix()) * view.CalculateProjectionMatrix())
.InverseFast(); .InverseFast();
GEngine->AddOnScreenDebugMessage(60, 0.5f, FColor::Yellow, FString::Printf(TEXT("x:%f, y:%f"), view.Rotation.Yaw, view.Rotation.Roll));
FVector worldLoc, worldDir; FVector worldLoc, worldDir;
for(int i = 1; i < components; ++i) for(int i = 1; i < components; ++i)
{ {
FVector2D screenPos = { ((double*)componentsCentroids.data)[i * 2], ((double*)componentsCentroids.data)[i * 2 + 1] }; FVector2D screenPos = { ((double*)componentsCentroids.data)[i * 2], ((double*)componentsCentroids.data)[i * 2 + 1] };
FSceneView::DeprojectScreenToWorld(screenPos, FIntRect{ {0, 0}, _extent }, _invProjection, worldLoc, worldDir); FSceneView::DeprojectScreenToWorld(screenPos, FIntRect{ {0, 0}, _extent }, _invProjection, worldLoc, worldDir);
//GEngine->AddOnScreenDebugMessage(66 + i, 0.5f, FColor::Yellow, FString::Printf(TEXT("x:%f, y:%f"), screenPos.X, screenPos.Y));
FHitResult result{}; FHitResult result{};
FVector startLocation = view.Location; FVector startLocation = view.Location;
FVector endLocation = worldLoc + worldDir * rayDistance; FVector endLocation = worldLoc + worldDir * scanDistance;
world->LineTraceSingleByChannel( world->LineTraceSingleByChannel(
result, result,
startLocation, startLocation,
@ -196,19 +259,23 @@ void UInteractableScreenCapturer::Process()
interactableInScreenDelegate.Execute(interactable); interactableInScreenDelegate.Execute(interactable);
}); });
} }
//GEngine->AddOnScreenDebugMessage(10 + i, 0.5f, FColor::Yellow, interactable->GetName());
GEngine->AddOnScreenDebugMessage(20 + i, 0.5f, FColor::Yellow, FString::Printf(TEXT("dist:%f"), (view.Location - interactable->GetActorLocation()).Length()));
} }
#ifdef INTERACTABLE_ACTIVATOR_DEBUG
DrawDebugLine(world, startLocation, endLocation, FColor::Green, false, tickInterval, 0, 0.5f); DrawDebugLine(world, startLocation, endLocation, FColor::Green, false, tickInterval, 0, 0.5f);
#endif // INTERACTABLE_ACTIVATOR_DEBUG
} }
#ifdef INTERACTABLE_ACTIVATOR_DEBUG
else else
{ {
DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 10, 0.5f); DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 10, 0.5f);
} }
//DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 0, 0.5f); #endif // INTERACTABLE_ACTIVATOR_DEBUG
} }
GEngine->AddOnScreenDebugMessage(667, 0.5f, FColor::Yellow, FString::Printf(TEXT("time:%f"), FPlatformTime::Seconds() - StartTime)); #ifdef INTERACTABLE_ACTIVATOR_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)EActivatorType::Saw, 0.5f, FColor::Yellow, FString::Printf(TEXT("ScreenCapturer calltime: %f"), FPlatformTime::Seconds() - StartTime));
#endif // INTERACTABLE_ACTIVATOR_DEBUG
running = false; running = false;
} }
); );

View File

@ -20,10 +20,14 @@ public:
FInteractableInScreen interactableInScreenDelegate; FInteractableInScreen interactableInScreenDelegate;
UPROPERTY(EditAnywhere)
float scanDistance = 7000;
protected: protected:
void Process(); void Process();
private: private:
FMinimalViewInfo _view; FMinimalViewInfo _view;
TSet<class AInteractable*> _sawInteractables; TSet<class AInteractable*> _sawInteractables;
//class UTextureRenderTarget2D* _output;
}; };

View File

@ -6,7 +6,11 @@
#include "DrawDebugHelpers.h" #include "DrawDebugHelpers.h"
#include "Engine/World.h" #include "Engine/World.h"
#include "Interactable.h" URaycastInteractableActivator::URaycastInteractableActivator(const FObjectInitializer& ObjectInitializer)
: UInteractableActivator(ObjectInitializer)
{
activatorType = EActivatorType::Use;
}
void URaycastInteractableActivator::Scan_Implementation() void URaycastInteractableActivator::Scan_Implementation()
{ {
@ -27,31 +31,40 @@ void URaycastInteractableActivator::Scan_Implementation()
{ {
if(_last != result.GetActor()) if(_last != result.GetActor())
{ {
if(_last)
{
interactableDeactivatedDelegate.Execute(_last, activatorType);
_last = nullptr;
}
_activated = true; _activated = true;
if(auto interactable = Cast<AInteractable>(result.GetActor())) if(auto interactable = Cast<AInteractable>(result.GetActor()))
{ {
_last = interactable; _last = interactable;
if(interactableActivatedDelegate.IsBound()) if(interactableActivatedDelegate.IsBound())
{ {
interactableActivatedDelegate.Execute(interactable); interactableActivatedDelegate.Execute(interactable, activatorType);
}
} }
} }
}
//DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Green, false, 0.5f, 0, 1.0f); #ifdef INTERACTABLE_ACTIVATOR_DEBUG
} DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Green, false, 0.5f, 0, 0.5f);
#endif // INTERACTABLE_ACTIVATOR_DEBUG
}
else else
{ {
if(_activated) if(_activated)
{ {
if(interactableDeactivatedDelegate.IsBound()) if(interactableDeactivatedDelegate.IsBound())
{ {
interactableDeactivatedDelegate.Execute(_last); interactableDeactivatedDelegate.Execute(_last, activatorType);
} }
_activated = false; _activated = false;
_last = nullptr; _last = nullptr;
} }
//DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, 0.5f, 10, 1.0f); #ifdef INTERACTABLE_ACTIVATOR_DEBUG
} DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, 0.5f, 10, 0.5f);
} #endif // INTERACTABLE_ACTIVATOR_DEBUG
}
}

View File

@ -12,6 +12,9 @@ class URaycastInteractableActivator : public UInteractableActivator
{ {
GENERATED_BODY() GENERATED_BODY()
public:
URaycastInteractableActivator(const FObjectInitializer& ObjectInitializer);
protected: protected:
void Scan(); void Scan();
virtual void Scan_Implementation() override; virtual void Scan_Implementation() override;

View File

@ -3,4 +3,59 @@
#include "Interactable.h" #include "Interactable.h"
#include "Kismet/GameplayStatics.h"
#include "../MainGameModeBase.h"
#include "../Widgets/WidgetsManager.h"
#include "Modificators/InteractableModificator.h"
void AInteractable::BeginPlay()
{
// FOR ADRESS TO COLOR
//if(auto m = material.LoadSynchronous())
//{
// if(material->VectorParameterValues.Num() > 0)
// {
// GEngine->AddOnScreenDebugMessage(5, 5.0f, FColor::Emerald, material->VectorParameterValues[0].ParameterInfo.Name.ToString());
// }
//}
TArray<UMeshComponent*> meshes;
GetComponents(meshes);
for(auto mesh : meshes)
{
mesh->CustomDepthStencilValue = 0;
mesh->CustomDepthStencilWriteMask = ERendererStencilMask::ERSM_Default;
mesh->SetRenderCustomDepth(true);
}
for(auto& modificatorClass : modificatorsClasses)
{
_modificators.Add(NewObject<UInteractableModificator>(this, modificatorClass));
}
}
void AInteractable::_Activate(EActivatorType type)
{
activated |= static_cast<uint8>(type);
if(auto WM = AMainGameModeBase::GetWidgetManager())
{
for(const auto modificator : _modificators)
{
WM->ShowInteractionHints(modificator);
}
}
Activate_Implementation(type);
}
void AInteractable::_Deactivate(EActivatorType type)
{
activated &= ~static_cast<uint8>(type);
if(auto WM = AMainGameModeBase::GetWidgetManager())
{
WM->HideInteractionHints(type);
}
Deactivate_Implementation(type);
}

View File

@ -4,19 +4,55 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "UObject/ScriptInterface.h"
#include "Interactable.generated.h" #include "Interactable.generated.h"
#define INTERACTABLE_DEBUG
//#define INTERACTABLE_ACTIVATOR_DEBUG
UENUM(BlueprintType, meta = (Bitflags))
enum class EActivatorType : uint8
{
None = 0,
Use = 1 << 0,
Saw = 1 << 1,
Custom1 = 1 << 2 UMETA(DisplayName = "Custom 1"),
Custom2 = 1 << 3 UMETA(DisplayName = "Custom 2"),
Custom3 = 1 << 4 UMETA(DisplayName = "Custom 3"),
Custom4 = 1 << 5 UMETA(DisplayName = "Custom 4"),
Custom5 = 1 << 6 UMETA(DisplayName = "Custom 5"),
Custom6 = 1 << 7 UMETA(DisplayName = "Custom 6")
};
ENUM_CLASS_FLAGS(EActivatorType)
UCLASS(Abstract, MinimalAPI, Blueprintable, BlueprintType) UCLASS(Abstract, MinimalAPI, Blueprintable, BlueprintType)
class AInteractable : public AActor class AInteractable : public AActor
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
void _Activate(EActivatorType type);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
TArray<TSubclassOf<class UInteractableComponent>> GetInteractableComponents(); void Activate(EActivatorType type);
virtual TArray<TSubclassOf<class UInteractableComponent>> GetInteractableComponents_Implementation() virtual void Activate_Implementation(EActivatorType type) {}
PURE_VIRTUAL(AInteractable::GetInteractableComponents_Implementation, return {};);
void _Deactivate(EActivatorType type);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Deactivate(EActivatorType type);
virtual void Deactivate_Implementation(EActivatorType type) {}
protected:
virtual void BeginPlay() override;
UPROPERTY(BlueprintReadWrite, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
uint8 activated = 0;
UPROPERTY(EditDefaultsOnly)
TArray<TSubclassOf<class UInteractableModificator>> modificatorsClasses;
private:
//UPROPERTY(EditDefaultsOnly)
//TSoftObjectPtr<UMaterialInstance> material;
TArray<class UInteractableModificator*> _modificators;
}; };

View File

@ -1,20 +0,0 @@
// Oleg Petruny proprietary.
#include "InteractableCaller.h"
UInteractableCaller::UInteractableCaller(const FObjectInitializer& ObjectInitializer)
: UActorComponent(ObjectInitializer)
{
if(HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
{
return;
}
RegisterComponent();
}
void UInteractableCaller::Init()
{
//GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, GetOwner()->GetName());
}

View File

@ -1,19 +0,0 @@
// Oleg Petruny proprietary.
#pragma once
#include "Components/ActorComponent.h"
#include "CoreMinimal.h"
#include "InteractableCaller.generated.h"
UCLASS(Abstract, Blueprintable, BlueprintType)
class UInteractableCaller : public UActorComponent
{
GENERATED_BODY()
public:
UInteractableCaller(const FObjectInitializer& ObjectInitializer);
void Init();
};

View File

@ -1,5 +0,0 @@
// Oleg Petruny proprietary.
#include "InteractableComponent.h"

View File

@ -1,29 +0,0 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "InputMappingContext.h"
#include "UObject/Interface.h"
#include "InteractableActivator.h"
#include "InteractableComponent.generated.h"
UCLASS(Abstract, Blueprintable, BlueprintType)
class UInteractableComponent : public UActorComponent
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
const FString GetName();
virtual const FString GetName_Implementation()
PURE_VIRTUAL(UInteractableComponent::GetInteractionName_Implementation, return "NONE";);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
const TArray<TSubclassOf<UInteractableActivator>> GetActivators();
virtual const TArray<TSubclassOf<UInteractableActivator>> GetActivators_Implementation()
PURE_VIRTUAL(UInteractableComponent::GetActivatorsZ_Implementation,
TArray<TSubclassOf<UInteractableActivator>> _activators{}; return _activators;);
};

View File

@ -0,0 +1,16 @@
// Oleg Petruny proprietary.
#include "InteractableModificator.h"
#include "InputMappingContext.h"
const UInputMappingContext* UInteractableModificator::GetMappingContext() const
{
return inputMapping.LoadSynchronous();
}
EActivatorType UInteractableModificator::GetActivatorTypes() const
{
return static_cast<EActivatorType>(activatorTypes);
}

View File

@ -0,0 +1,27 @@
// Oleg Petruny proprietary.
#pragma once
#include "Components/ActorComponent.h"
#include "CoreMinimal.h"
#include "InteractableModificator.generated.h"
enum class EActivatorType : uint8;
UCLASS(Abstract, Blueprintable, BlueprintType)
class UInteractableModificator : public UActorComponent
{
GENERATED_BODY()
public:
const class UInputMappingContext* GetMappingContext() const;
EActivatorType GetActivatorTypes() const;
protected:
UPROPERTY(EditDefaultsOnly)
TSoftObjectPtr<class UInputMappingContext> inputMapping;
UPROPERTY(EditAnywhere, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
uint8 activatorTypes = 0;
};

View File

@ -0,0 +1,5 @@
// Oleg Petruny proprietary.
#include "InteractableUsableModificator.h"

View File

@ -0,0 +1,18 @@
// Oleg Petruny proprietary.
#pragma once
#include "InteractableModificator.h"
#include "InteractableUsableModificator.generated.h"
UCLASS(Blueprintable, BlueprintType)
class UInteractableUsableModificator : public UInteractableModificator
{
GENERATED_BODY()
public:
protected:
};

View File

@ -1,21 +0,0 @@
// Oleg Petruny proprietary.
#include "SawInteractable.h"
#include "InCameraInteractableActivator.h"
#include "InteractableCaller.h"
const FString USawInteractable::GetName_Implementation()
{
static auto _name = TEXT("Saw");
return _name;
}
const TArray<TSubclassOf<UInteractableActivator>> USawInteractable::GetActivators_Implementation()
{
static TArray<TSubclassOf<UInteractableActivator>> _array = {
{UInCameraInteractableActivator::StaticClass()}
};
return _array;
}

View File

@ -1,23 +0,0 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "InteractableComponent.h"
#include "SawInteractable.generated.h"
UCLASS(Blueprintable, BlueprintType)
class USawInteractable : public UInteractableComponent
{
GENERATED_BODY()
public:
const FString GetName();
virtual const FString GetName_Implementation() override;
const TArray<TSubclassOf<UInteractableActivator>> GetActivators();
virtual const TArray<TSubclassOf<UInteractableActivator>> GetActivators_Implementation() override;
};

View File

@ -1,20 +0,0 @@
// Oleg Petruny proprietary.
#include "UsableInteractable.h"
#include "RaycastInteractableActivator.h"
const FString UUsableInteractable::GetName_Implementation()
{
static auto _name = TEXT("Use");
return _name;
}
const TArray<TSubclassOf<UInteractableActivator>> UUsableInteractable::GetActivators_Implementation()
{
static TArray<TSubclassOf<UInteractableActivator>> _array = {
{URaycastInteractableActivator::StaticClass()}
};
return _array;
}

View File

@ -1,23 +0,0 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "InteractableComponent.h"
#include "UsableInteractable.generated.h"
UCLASS(Blueprintable, BlueprintType)
class UUsableInteractable : public UInteractableComponent
{
GENERATED_BODY()
public:
const FString GetName();
virtual const FString GetName_Implementation() override;
const TArray<TSubclassOf<UInteractableActivator>> GetActivators();
virtual const TArray<TSubclassOf<UInteractableActivator>> GetActivators_Implementation() override;
};

View File

@ -9,8 +9,9 @@
#include "UObject/ScriptInterface.h" #include "UObject/ScriptInterface.h"
#include "CustomGameInstanceBase.h" #include "CustomGameInstanceBase.h"
#include "Interactable/InteractableComponent.h" #include "Widgets/WidgetsManager.h"
#include "WidgetsManager.h"
UWidgetsManager* AMainGameModeBase::_widgetsManager = nullptr;
void AMainGameModeBase::StartPlay() void AMainGameModeBase::StartPlay()
{ {
@ -37,6 +38,11 @@ bool AMainGameModeBase::SetPause(APlayerController* PC, FCanUnpause CanUnpauseDe
return AGameModeBase::SetPause(PC, CanUnpauseDelegate); return AGameModeBase::SetPause(PC, CanUnpauseDelegate);
} }
UWidgetsManager* AMainGameModeBase::GetWidgetManager()
{
return _widgetsManager;
}
void AMainGameModeBase::SwitchCameraMode() void AMainGameModeBase::SwitchCameraMode()
{ {
static TWeakObjectPtr<APawn> _playerPawn = nullptr; static TWeakObjectPtr<APawn> _playerPawn = nullptr;

View File

@ -18,10 +18,12 @@ public:
void SwitchCameraMode(); void SwitchCameraMode();
static class UWidgetsManager* GetWidgetManager();
protected: protected:
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UWidgetsManager> widgetManagerClass; TSubclassOf<class UWidgetsManager> widgetManagerClass;
private: private:
class UWidgetsManager* _widgetsManager; static class UWidgetsManager* _widgetsManager;
}; };

View File

@ -11,11 +11,7 @@
#include "Kismet/KismetMathLibrary.h" #include "Kismet/KismetMathLibrary.h"
#include "CustomGameInstanceBase.h" #include "CustomGameInstanceBase.h"
#include "Interactable/Interactable.h" #include "Interactable/Activators/InteractableActivator.h"
#include "Interactable/InteractableActivator.h"
#include "Interactable/InteractableCaller.h"
#include "Interactable/InteractableComponent.h"
#include "Interactable/UsableInteractable.h"
#include "CustomGameUserSettings.h" #include "CustomGameUserSettings.h"
#include "MainGameModeBase.h" #include "MainGameModeBase.h"
@ -73,7 +69,7 @@ void APlayerBase::BeginPlay()
} }
} }
LoadInteractable(); LoadInteractablesActivators();
} }
void APlayerBase::SwitchToCameraPawn() void APlayerBase::SwitchToCameraPawn()
@ -136,33 +132,46 @@ void APlayerBase::UpdatePitch(float min, float max)
} }
} }
void APlayerBase::LoadInteractable() void APlayerBase::LoadInteractablesActivators()
{ {
auto GI = Cast<UCustomGameInstanceBase>(GetWorld()->GetGameInstance()); if(auto GI = Cast<UCustomGameInstanceBase>(GetWorld()->GetGameInstance()))
if(!GI)
{ {
return; TSet<UClass*> instancedActivators;
} for(auto& act : GI->interactionsActivators)
TSet<TSubclassOf<UInteractableActivator>> activators;
for(auto& interaction : GI->interactionsActivators)
{
auto actArray = interaction->GetDefaultObject<UInteractableComponent>()->GetActivators_Implementation();
for(auto& act : actArray)
{ {
if(!activators.Contains(act)) if(instancedActivators.Contains(act))
{ continue;
activators.Add(act); instancedActivators.Add(act);
auto component = NewObject<UInteractableActivator>(this, act);
component->interactableActivatedDelegate.BindUObject(this, &APlayerBase::InteractableActivated); auto component = NewObject<UInteractableActivator>(this, act);
component->SetupAttachment(camera); component->interactableActivatedDelegate.BindUObject(this, &APlayerBase::InteractableActivated);
component->RegisterComponent(); component->interactableDeactivatedDelegate.BindUObject(this, &APlayerBase::InteractableDeactivated);
} component->SetupAttachment(camera);
component->RegisterComponent();
} }
} }
} }
void APlayerBase::InteractableActivated(AInteractable* interactable) void APlayerBase::InteractableActivated(AInteractable* interactable, EActivatorType type)
{ {
GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Cyan, TEXT("Player activate: ") + interactable->GetName()); if(interactionLocked)
return;
interactable->Activate(type);
#ifdef INTERACTABLE_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Cyan, TEXT("Player activate: ") + interactable->GetName()
+ TEXT(" by: ") + StaticEnum<EActivatorType>()->GetNameByValue(static_cast<int64>(type)).ToString());
#endif // INTERACTABLE_DEBUG
}
void APlayerBase::InteractableDeactivated(AInteractable* interactable, EActivatorType type)
{
if(interactionLocked)
return;
interactable->Deactivate(type);
#ifdef INTERACTABLE_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Magenta, TEXT("Player deactivate: ") + interactable->GetName()
+ TEXT(" by: ") + StaticEnum<EActivatorType>()->GetNameByValue(static_cast<int64>(type)).ToString());
#endif // INTERACTABLE_DEBUG
} }

View File

@ -5,6 +5,8 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "GameFramework/Character.h" #include "GameFramework/Character.h"
#include "Interactable/Interactable.h"
#include "PlayerBase.generated.h" #include "PlayerBase.generated.h"
UCLASS() UCLASS()
@ -49,6 +51,8 @@ protected:
bool jumpLocked = false; bool jumpLocked = false;
UPROPERTY(EditAnywhere) UPROPERTY(EditAnywhere)
bool runLocked = false; bool runLocked = false;
UPROPERTY(EditAnywhere)
bool interactionLocked = false;
APlayerCameraManager* cameraManager; APlayerCameraManager* cameraManager;
class UCameraComponent* camera; class UCameraComponent* camera;
@ -60,6 +64,7 @@ protected:
float maxPitch = 65; float maxPitch = 65;
private: private:
void LoadInteractable(); void LoadInteractablesActivators();
void InteractableActivated(class AInteractable* interactable); void InteractableActivated(AInteractable* interactable, EActivatorType type);
void InteractableDeactivated(AInteractable* interactable, EActivatorType type);
}; };

View File

@ -0,0 +1,5 @@
// Oleg Petruny proprietary.
#include "InteractableHintWidget.h"

View File

@ -0,0 +1,23 @@
// Oleg Petruny proprietary.
#pragma once
#include "Blueprint/UserWidget.h"
#include "CoreMinimal.h"
#include "InteractableHintWidget.generated.h"
UCLASS(Blueprintable)
class UInteractableHintWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Show();
virtual void Show_Implementation() {}
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Proceed();
virtual void Proceed_Implementation() {}
};

View File

@ -0,0 +1,4 @@
// Oleg Petruny proprietary.
#include "InteractableHintWidgetManager.h"

View File

@ -0,0 +1,35 @@
// Oleg Petruny proprietary.
#pragma once
#include "Blueprint/UserWidget.h"
#include "CoreMinimal.h"
#include "InteractableHintWidgetManager.generated.h"
enum class EActivatorType : uint8;
UCLASS(Blueprintable)
class UInteractableHintWidgetManager : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Append(const class UInteractableModificator* modificator);
virtual void Append_Implementation(const class UInteractableModificator* modificator) {}
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Remove(EActivatorType type);
virtual void Remove_Implementation(EActivatorType type) {}
protected:
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UInteractableHintWidget> interactableHintPressWidgetClass;
class UInteractableHintWidget* interactableHintPressWidget;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UInteractableHintWidget> interactableHintHoldWidgetClass;
class UInteractableHintWidget* interactableHintHoldWidget;
};

View File

@ -5,12 +5,14 @@
#include "Blueprint/UserWidget.h" #include "Blueprint/UserWidget.h"
#include "Engine/World.h" #include "Engine/World.h"
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "UObject/ScriptInterface.h" #include "UObject/ScriptInterface.h"
#include "CustomGameInstanceBase.h" #include "CustomGameInstanceBase.h"
#include "Interactable/Interactable.h" #include "Interactable/Interactable.h"
#include "Interactable/InteractableComponent.h" #include "Interactable/Modificators/InteractableModificator.h"
#include "InteractableHintWidgetManager.h"
void UWidgetsManager::Init() void UWidgetsManager::Init()
{ {
@ -33,6 +35,8 @@ void UWidgetsManager::Init()
} }
} }
} }
interactableHintWidgetManager = NewObject<UInteractableHintWidgetManager>(this, interactableHintWidgetManagerClass);
} }
void UWidgetsManager::HideOverlayWidgets() void UWidgetsManager::HideOverlayWidgets()
@ -78,8 +82,11 @@ void UWidgetsManager::UpdateOverlayWidgetsOwner()
} }
} }
void UWidgetsManager::ShowInteractionHints(AInteractable* interactable) void UWidgetsManager::ShowInteractionHints(const UInteractableModificator* modificator)
{ {
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Interaction Hint")); interactableHintWidgetManager->Append(modificator);
//interactable->GetInterfa }
void UWidgetsManager::HideInteractionHints(const EActivatorType type)
{
interactableHintWidgetManager->Remove(type);
} }

View File

@ -1,5 +1,3 @@
#pragma once
// Oleg Petruny proprietary. // Oleg Petruny proprietary.
#pragma once #pragma once
@ -9,6 +7,8 @@
#include "WidgetsManager.generated.h" #include "WidgetsManager.generated.h"
enum class EActivatorType : uint8;
UCLASS(Blueprintable) UCLASS(Blueprintable)
class UWidgetsManager : public UObject class UWidgetsManager : public UObject
{ {
@ -21,7 +21,8 @@ public:
void ShowOverlayWidgets(); void ShowOverlayWidgets();
void UpdateOverlayWidgetsOwner(); void UpdateOverlayWidgetsOwner();
void ShowInteractionHints(class AInteractable* interactable); void ShowInteractionHints(const class UInteractableModificator* modificator);
void HideInteractionHints(const EActivatorType type);
protected: protected:
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
@ -31,4 +32,8 @@ protected:
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
TArray<TSubclassOf<class UUserWidget>> overlayWidgets; // hidden in pause TArray<TSubclassOf<class UUserWidget>> overlayWidgets; // hidden in pause
TArray<TWeakObjectPtr<class UUserWidget>> overlayWidgetsInstances; TArray<TWeakObjectPtr<class UUserWidget>> overlayWidgetsInstances;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UInteractableHintWidgetManager> interactableHintWidgetManagerClass;
class UInteractableHintWidgetManager* interactableHintWidgetManager;
}; };

View File

@ -16,8 +16,8 @@ public:
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_SRV(Buffer<unsigned int>, Input) SHADER_PARAMETER_SRV(Buffer<uint>, Input)
SHADER_PARAMETER_UAV(RWBuffer<unsigned int>, Output) SHADER_PARAMETER_UAV(RWBuffer<uint>, Output)
END_SHADER_PARAMETER_STRUCT() END_SHADER_PARAMETER_STRUCT()