From 8f702409c7e7573670e2fe83437578bc244d6b74 Mon Sep 17 00:00:00 2001 From: Oleg Petruny Date: Mon, 20 May 2024 18:06:31 +0200 Subject: [PATCH] Shaders module, Interactable screen capturer --- .vsconfig | 4 +- Config/DefaultEditor.ini | 3 + .../Characters/BP_CameraMode.uasset | Bin 58093 -> 49384 bytes .../Other/BP_CustomGameInstance.uasset | Bin 6111 -> 6111 bytes Content/tempStaff/Input.uasset | Bin 0 -> 4671 bytes Lost_Edge.uproject | 19 +- .../InteractableScreenCapturerBitMapCS.usf | 23 ++ Source/Lost_Edge.Target.cs | 17 +- Source/Lost_Edge/Lost_Edge.Build.cs | 8 +- .../Private/CustomGameInstanceBase.h | 1 + .../InCameraInteractableActivator.cpp | 5 + .../InCameraInteractableActivator.h | 15 ++ .../Interactable/InteractableActivator.cpp | 3 +- .../Interactable/InteractableActivator.h | 9 +- .../Interactable/InteractableCaller.cpp | 14 ++ .../Private/Interactable/InteractableCaller.h | 4 +- .../Interactable/InteractableComponent.cpp | 1 - .../Interactable/InteractableComponent.h | 7 +- .../InteractableScreenCapturer.cpp | 234 ++++++++++++++++++ .../Interactable/InteractableScreenCapturer.h | 27 ++ .../RaycastInteractableActivator.cpp | 35 ++- .../Interactable/UsableInteractable.cpp | 6 - .../Private/Interactable/UsableInteractable.h | 5 +- Source/Lost_Edge/Private/PlayerBase.cpp | 46 +++- Source/Lost_Edge/Private/PlayerBase.h | 5 + Source/Lost_EdgeEditor.Target.cs | 17 +- .../Lost_EdgeShaders.Build.cs | 17 ++ .../InteractableScreenCapturerBitMapCS.cpp | 6 + .../Private/Lost_EdgeShaders.cpp | 20 ++ .../InteractableScreenCapturerBitMapCS.h | 38 +++ .../Public/Lost_EdgeShaders.h | 26 ++ 31 files changed, 558 insertions(+), 57 deletions(-) create mode 100644 Content/tempStaff/Input.uasset create mode 100644 Shaders/Private/InteractableScreenCapturerBitMapCS.usf create mode 100644 Source/Lost_Edge/Private/Interactable/InCameraInteractableActivator.cpp create mode 100644 Source/Lost_Edge/Private/Interactable/InCameraInteractableActivator.h create mode 100644 Source/Lost_Edge/Private/Interactable/InteractableScreenCapturer.cpp create mode 100644 Source/Lost_Edge/Private/Interactable/InteractableScreenCapturer.h create mode 100644 Source/Lost_EdgeShaders/Lost_EdgeShaders.Build.cs create mode 100644 Source/Lost_EdgeShaders/Private/InteractableScreenCapturerBitMapCS.cpp create mode 100644 Source/Lost_EdgeShaders/Private/Lost_EdgeShaders.cpp create mode 100644 Source/Lost_EdgeShaders/Public/InteractableScreenCapturerBitMapCS.h create mode 100644 Source/Lost_EdgeShaders/Public/Lost_EdgeShaders.h diff --git a/.vsconfig b/.vsconfig index 1a9d718..7f5f4b3 100644 --- a/.vsconfig +++ b/.vsconfig @@ -2,9 +2,9 @@ "version": "1.0", "components": [ "Microsoft.Net.Component.4.6.2.TargetingPack", - "Microsoft.VisualStudio.Component.VC.14.36.17.6.x86.x64", + "Microsoft.VisualStudio.Component.VC.14.38.17.8.x86.x64", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", - "Microsoft.VisualStudio.Component.Windows10SDK.22000", + "Microsoft.VisualStudio.Component.Windows10SDK.22621", "Microsoft.VisualStudio.Workload.CoreEditor", "Microsoft.VisualStudio.Workload.ManagedDesktop", "Microsoft.VisualStudio.Workload.NativeDesktop", diff --git a/Config/DefaultEditor.ini b/Config/DefaultEditor.ini index f38756e..162636e 100644 --- a/Config/DefaultEditor.ini +++ b/Config/DefaultEditor.ini @@ -1,2 +1,5 @@ [/Script/AdvancedPreviewScene.SharedProfiles] +[/Script/UnrealEd.EditorPerformanceProjectSettings] +MaxViewportRenderingResolution=720 + diff --git a/Content/Blueprints/Characters/BP_CameraMode.uasset b/Content/Blueprints/Characters/BP_CameraMode.uasset index 538b09371b7f10f2c918fb8a3d14b63254d38334..fe3cce2b55f79c6ec05e30e30dbba8a223ff9dd6 100644 GIT binary patch literal 49384 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 R3uo{1z4xf{}0J4<4phn literal 58093 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 N{AF0WcBugWe*wIT6|VpQ diff --git a/Content/Blueprints/Other/BP_CustomGameInstance.uasset b/Content/Blueprints/Other/BP_CustomGameInstance.uasset index 9a1d396380bf95cd8f03ffdb7b8c8ea4fe790a7b..c2fc8931031c20b5583717f1842674532d67b7b9 100644 GIT binary patch delta 29 lcmcbwe_wxt6Qe-*KOyY}MlLRsZN%UIc5*Y_9K_fw1^}@T3qk+@ delta 29 ncmV+&0OJ4OFW)b)LIDt2s;tm!psh-)#iSz9tX!9~QUQ$?)%6YV diff --git a/Content/tempStaff/Input.uasset b/Content/tempStaff/Input.uasset new file mode 100644 index 0000000000000000000000000000000000000000..85e327b582dfb77617d543c4400d531e1a794465 GIT binary patch literal 4671 zcmeHLdvH|M89$rdkj-w=WS94&l{_F1CE2_-2^~xJoz3LEn?Q8h^k#Fjxv($py_*mQ zC!k^@`cKqWaik6yC`xAv6{WSU1&gg^#y{et3e*+~qA<0CG-wp;_WRD>yScj%vHn}X z$=!R-_d4JAopbK_ogBNb^rzFYSnP*tLUd__Ou-vT1JBbBO&hN_MaQyEZrNAzyVZ3j z;Jp`pzof|d%$cD#a(7+&>m3CK;B9;R9`1mp?ZQ7hnw~3u@yN@=!24+M;Q5Qz$ENhB zD)v}@<18x%-a|QrEP!{piwUyjA{&f&L}p;1+#QNUMc@;%5*|TCn`9C~$b+WMVX8IP zS}ax76*hB?y{5jZzS>$-S!Few9F_I8HB=jwG4h@1guov)zBq@9$W?gbvnh*^f$fzW z{~kQ!d}NV6XX(VkEk4otFZ0Bp_3+NMoga)}nZ~iv4+ip8sPJqy9c2Q1>y614P}LZw zd>gQH6ta2HFZcL(E+UrO!aUp6*0-MZiDcTn>U*G`kU2trF2s@t8n(N?1#An?Gb8PM zIKuMc2yq`g$K@hd5LnS2jD&g7&WH^8@aG*~bkgT)@A3>XJlpRKFn(fxZ}c2al{FCd zZ9v7gfdMcSNRMgi;cOIy!-0hJT+P89lsO`@3Fd{?RY%cQ}Q-Cq8)zf0onFU-~w% z+Zo>m#?Ll~p;Fvt1}oJHt6qpOK9(58k+Hd;bdxkLjl9yJLy_0n+v&1e>d58wcfEvb z%)@PF*OAx8OJA0IJ!JIZwv!ns3rBhI+g*R?2nOf@OVUzn+>ZfzL_X@9N!Uc5x{jMr znwOLm*W7)+8Ve^$CBKbDqvPnx+v4){wuZqb$V3G4`ts3hv+w5(U%dVlMrsQ%f$@AWM^#_rFAUJENSblINYdiYT-Fr=~(!8JA?m$%eU=lJXEMTRblodVr z12CerTzX%JU6?Pm6`N4v5F+bc13l^6M{cEu>lW!|dIfP&((kSGq%U5QzyClyvJ;F; zjtzPE1wq2E%WNe3L^-%h_>%Q;*&tz+ky3RE<7@(F0Vva|HrhGj-WPL3ge@sfGVN(yf;EiNo7T2%~x&BU@ zqtV@XySc5a)#+_;H9F9VDl0qNkYmU*8uJ`wMP-ivnPNwYK}(LRh+36T(hMrKK@~fW zr-~|FMM*A-Dow3PpOc}@)agOtghyFC9FMAdKu$Df`Ut)Gb)JXz`L2D~pOtN~>$kwRQEYZFYy#)#z^Wc)PmS zuIstW*Ut|42f6iv7#$kkG_v`=`?o*vqp=5fJo4ycKmN(%Pwaeh&odKy_x)`Dv(NqV z`NJ=~c;r{Ve(9Az9DntXe|qiDC*FATt+)U3&bud1o&CqT^Y35y;KPfTKECqrsjHuS zI{n$_m>1?LQ#`YjybO?6nnt76WME#Zv|)JE22FZi#T=uhBZJvEH@|Y5cAj;7_n~8% z1y!Aw=lAiGx&?*RXIFfTsnN{7T4MKpt;`aM&E$28WT{m!d1?b$L#~t-@7b#R=J}=u z|EFtUP3$Com1jT5XOO~Y&>WSH0koNs;2|u-=r~j^lTb?vDp&}LcxB%0~1vmiX@O34Cx9R!aXNihoK#eTVh%6u_ zfrjj40s>1gj}%~zaLvm{S$d}1!odiJ2w*V*I`KU8+IsEm022*}1dnYeg~jxw1e7RC zDBcy~h^-qyXTM@#%(%JDZsiz(9_S{TH*j2hI2s{Ka16&fZ&#kMNvkUf1txbu8TWu}kO%Es-;Qzl zBPp>IE?9a|#wd|)5FUkS;#%=N7gvk_=FXRTGKR#Uup~&>#z!VxDs-pg8*hY2c$Y&$ zMZ7H`r5e^F6YGN{0Ya*T3tc8Us&Y6PYRj-zITB7Il2RZ0sH7bzKga&$L|vci z@`(d7-o`~H6D)8iMZE9mi0_HHfv?(s=9l@pRJhW=L9p*ivU5|hM0{r>`wa#J?| literal 0 HcmV?d00001 diff --git a/Lost_Edge.uproject b/Lost_Edge.uproject index 13b827c..1c0f94b 100644 --- a/Lost_Edge.uproject +++ b/Lost_Edge.uproject @@ -1,6 +1,6 @@ { "FileVersion": 3, - "EngineAssociation": "{1596D39D-4A14-8FE8-BC5C-21A6B54321BE}", + "EngineAssociation": "{0DD41C75-443A-77B1-7C02-5F9B73D04B7B}", "Category": "", "Description": "", "Modules": [ @@ -14,6 +14,14 @@ "SlateCore", "UMG" ] + }, + { + "Name": "Lost_EdgeShaders", + "Type": "Runtime", + "LoadingPhase": "PostConfigInit", + "AdditionalDependencies": [ + "Engine" + ] } ], "Plugins": [ @@ -342,6 +350,15 @@ { "Name": "RiderSourceCodeAccess", "Enabled": false + }, + { + "Name": "OpenCV", + "Enabled": true + }, + { + "Name": "AutoSizeComments", + "Enabled": false, + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/ae89a2c4ab384de0a3f213b23de324f3" } ], "TargetPlatforms": [ diff --git a/Shaders/Private/InteractableScreenCapturerBitMapCS.usf b/Shaders/Private/InteractableScreenCapturerBitMapCS.usf new file mode 100644 index 0000000..97059f8 --- /dev/null +++ b/Shaders/Private/InteractableScreenCapturerBitMapCS.usf @@ -0,0 +1,23 @@ +// Oleg Petruny proprietary. + + +#include "/Engine/Public/Platform.ush" + +Buffer Input; +RWBuffer Output; + +[numthreads(THREADGROUPSIZE_X, 1, 1)] +void InteractableScreenCapturerBitMapCS( + uint3 dti : SV_DispatchThreadID) +{ + 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 + break; + default: + //Output[dti.x / 4] = Output[dti.x / 4] & ~(0xFF << 8 * (3 - (dti.x % 4))); // sets n-th byte to 0x00 + break; + } + //Output[0] = 1; +} \ No newline at end of file diff --git a/Source/Lost_Edge.Target.cs b/Source/Lost_Edge.Target.cs index e782bf0..7ca225a 100644 --- a/Source/Lost_Edge.Target.cs +++ b/Source/Lost_Edge.Target.cs @@ -1,15 +1,12 @@ // Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; -using System.Collections.Generic; -public class Lost_EdgeTarget : TargetRules -{ - public Lost_EdgeTarget( TargetInfo Target) : base(Target) - { - Type = TargetType.Game; - DefaultBuildSettings = BuildSettingsVersion.V2; - IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_1; - ExtraModuleNames.Add("Lost_Edge"); - } +public class Lost_EdgeTarget : TargetRules { + public Lost_EdgeTarget(TargetInfo Target) : base(Target) { + Type = TargetType.Game; + DefaultBuildSettings = BuildSettingsVersion.Latest; + IncludeOrderVersion = EngineIncludeOrderVersion.Latest; + ExtraModuleNames.AddRange(new string[] { "Lost_Edge", "Lost_EdgeShaders" }); + } } diff --git a/Source/Lost_Edge/Lost_Edge.Build.cs b/Source/Lost_Edge/Lost_Edge.Build.cs index abe6f48..3b65c26 100644 --- a/Source/Lost_Edge/Lost_Edge.Build.cs +++ b/Source/Lost_Edge/Lost_Edge.Build.cs @@ -6,15 +6,19 @@ public class Lost_Edge : ModuleRules { public Lost_Edge(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "OpenCV" }); // "OpenCVHelper" - PrivateDependencyModuleNames.AddRange(new string[] { "EnhancedInput", "UMG" }); //"Slate", "SlateCore" + //PrivateIncludePaths.AddRange(new string[] { "OpenCV/Private" }); + PrivateDependencyModuleNames.AddRange(new string[] { "EnhancedInput", "UMG", "RHI", "RenderCore", "Lost_EdgeShaders", "TextureCompressor" }); // "Slate", "SlateCore" // Uncomment if you are using online features // PrivateDependencyModuleNames.Add("OnlineSubsystem"); // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true + // UE_LOG(LogTemp, Log, TEXT("capture: %s"), (capture ? TEXT("true") : TEXT("false"))); + // GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("1")); // GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("Rescaled: %f"), scale)); } + } diff --git a/Source/Lost_Edge/Private/CustomGameInstanceBase.h b/Source/Lost_Edge/Private/CustomGameInstanceBase.h index e4ff7bc..1753c45 100644 --- a/Source/Lost_Edge/Private/CustomGameInstanceBase.h +++ b/Source/Lost_Edge/Private/CustomGameInstanceBase.h @@ -18,6 +18,7 @@ public: UFUNCTION(BlueprintCallable, Category = Settings) void ApplyMouseSettings(); + UPROPERTY(EditDefaultsOnly) TArray> interactionsCollection; protected: diff --git a/Source/Lost_Edge/Private/Interactable/InCameraInteractableActivator.cpp b/Source/Lost_Edge/Private/Interactable/InCameraInteractableActivator.cpp new file mode 100644 index 0000000..2b1c289 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InCameraInteractableActivator.cpp @@ -0,0 +1,5 @@ +// Oleg Petruny proprietary. + + +#include "Interactable/InCameraInteractableActivator.h" + diff --git a/Source/Lost_Edge/Private/Interactable/InCameraInteractableActivator.h b/Source/Lost_Edge/Private/Interactable/InCameraInteractableActivator.h new file mode 100644 index 0000000..2961490 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InCameraInteractableActivator.h @@ -0,0 +1,15 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "CoreMinimal.h" +#include "InteractableActivator.h" + +#include "InCameraInteractableActivator.generated.h" + +UCLASS() +class UInCameraInteractableActivator : public UInteractableActivator +{ + GENERATED_BODY() + +}; diff --git a/Source/Lost_Edge/Private/Interactable/InteractableActivator.cpp b/Source/Lost_Edge/Private/Interactable/InteractableActivator.cpp index 79387a3..f706301 100644 --- a/Source/Lost_Edge/Private/Interactable/InteractableActivator.cpp +++ b/Source/Lost_Edge/Private/Interactable/InteractableActivator.cpp @@ -44,13 +44,12 @@ UInteractableActivator::UInteractableActivator(const FObjectInitializer& ObjectI void UInteractableActivator::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { - USceneComponent::TickComponent(DeltaTime, TickType, ThisTickFunction); - switch(TickType) { case ELevelTick::LEVELTICK_TimeOnly: case ELevelTick::LEVELTICK_ViewportsOnly: case ELevelTick::LEVELTICK_All: + USceneComponent::TickComponent(DeltaTime, TickType, ThisTickFunction); Scan_Implementation(); break; default: diff --git a/Source/Lost_Edge/Private/Interactable/InteractableActivator.h b/Source/Lost_Edge/Private/Interactable/InteractableActivator.h index be3a19f..6db0a17 100644 --- a/Source/Lost_Edge/Private/Interactable/InteractableActivator.h +++ b/Source/Lost_Edge/Private/Interactable/InteractableActivator.h @@ -7,9 +7,10 @@ #include "InteractableActivator.generated.h" -DECLARE_DELEGATE(FInteractableActivated); +DECLARE_DELEGATE_OneParam(FInteractableActivated, class AInteractable*); +DECLARE_DELEGATE_OneParam(FInteractableDeactivated, class AInteractable*); -UCLASS(Blueprintable, BlueprintType) +UCLASS(Abstract, Blueprintable, BlueprintType) class UInteractableActivator : public USceneComponent { GENERATED_BODY() @@ -18,6 +19,9 @@ public: UInteractableActivator(const FObjectInitializer& ObjectInitializer); virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + FInteractableActivated interactableActivatedDelegate; + FInteractableActivated interactableDeactivatedDelegate; + protected: UFUNCTION(BlueprintNativeEvent, BlueprintCallable) inline void Scan(); @@ -30,5 +34,4 @@ protected: class APlayerBase* player; bool isTrace = true; enum ECollisionChannel collisionChannel; - FInteractableActivated interactableActivatedDelegate; }; diff --git a/Source/Lost_Edge/Private/Interactable/InteractableCaller.cpp b/Source/Lost_Edge/Private/Interactable/InteractableCaller.cpp index c520bfd..2c2a03f 100644 --- a/Source/Lost_Edge/Private/Interactable/InteractableCaller.cpp +++ b/Source/Lost_Edge/Private/Interactable/InteractableCaller.cpp @@ -3,4 +3,18 @@ #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()); +} \ No newline at end of file diff --git a/Source/Lost_Edge/Private/Interactable/InteractableCaller.h b/Source/Lost_Edge/Private/Interactable/InteractableCaller.h index 656415c..a3f8018 100644 --- a/Source/Lost_Edge/Private/Interactable/InteractableCaller.h +++ b/Source/Lost_Edge/Private/Interactable/InteractableCaller.h @@ -7,11 +7,13 @@ #include "InteractableCaller.generated.h" -UCLASS(Abstract, MinimalAPI, Blueprintable, BlueprintType) +UCLASS(Abstract, Blueprintable, BlueprintType) class UInteractableCaller : public UActorComponent { GENERATED_BODY() public: + UInteractableCaller(const FObjectInitializer& ObjectInitializer); + void Init(); }; \ No newline at end of file diff --git a/Source/Lost_Edge/Private/Interactable/InteractableComponent.cpp b/Source/Lost_Edge/Private/Interactable/InteractableComponent.cpp index 8906d63..5a6caa3 100644 --- a/Source/Lost_Edge/Private/Interactable/InteractableComponent.cpp +++ b/Source/Lost_Edge/Private/Interactable/InteractableComponent.cpp @@ -3,4 +3,3 @@ #include "InteractableComponent.h" -// Add default functionality here for any IInteractableInterface functions that are not pure virtual. diff --git a/Source/Lost_Edge/Private/Interactable/InteractableComponent.h b/Source/Lost_Edge/Private/Interactable/InteractableComponent.h index 0dc7a31..3a1aa2d 100644 --- a/Source/Lost_Edge/Private/Interactable/InteractableComponent.h +++ b/Source/Lost_Edge/Private/Interactable/InteractableComponent.h @@ -30,7 +30,7 @@ public: TSubclassOf caller; }; -UCLASS() +UCLASS(Abstract, Blueprintable, BlueprintType) class UInteractableComponent : public UActorComponent { GENERATED_BODY() @@ -41,11 +41,6 @@ public: virtual const FString GetName_Implementation() PURE_VIRTUAL(UInteractableComponent::GetInteractionName_Implementation, return "NONE";); - UFUNCTION(BlueprintNativeEvent, BlueprintCallable) - const UInputMappingContext* GetInputMapping(); - virtual const UInputMappingContext* GetInputMapping_Implementation() - PURE_VIRTUAL(UInteractableComponent::GetInputMapping_Implementation, static UInputMappingContext _inputMapping{}; return &_inputMapping;); - UFUNCTION(BlueprintNativeEvent, BlueprintCallable) const TArray GetActivatorsAndCallers(); virtual const TArray GetActivatorsAndCallers_Implementation() diff --git a/Source/Lost_Edge/Private/Interactable/InteractableScreenCapturer.cpp b/Source/Lost_Edge/Private/Interactable/InteractableScreenCapturer.cpp new file mode 100644 index 0000000..2991cf6 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InteractableScreenCapturer.cpp @@ -0,0 +1,234 @@ +// Oleg Petruny proprietary. + + +#include "InteractableScreenCapturer.h" + +#include "Engine/Texture.h" +#include "Interactable.h" +#include "Kismet/GameplayStatics.h" +#include "opencv2/imgproc.hpp" +#include "RHIResources.h" +#include "SceneView.h" +#include "TextureCompressorModule.h" + +constexpr float tickInterval = 1.0f / 5; + +UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer) + : USceneCaptureComponent2D(ObjectInitializer) +{ + //TextureTarget = CreateDefaultSubobject(TEXT("TextureTarget")); + //TextureTarget->InitAutoFormat(textureWidth, textureHeight); + //TextureTarget->RenderTargetFormat = ETextureRenderTargetFormat::RTF_RGBA16f; + PrimaryComponentTick.bCanEverTick = false; + PrimaryComponentTick.bStartWithTickEnabled = false; + + auto input = LoadObject(nullptr, TEXT("/Game/tempStaff/Input")); + if(!input) + { + return; + } + + _capture = input->GetResource()->TextureRHI; + if(!_capture) + { + return; + } + + switch(_capture->GetFormat()) + { + case EPixelFormat::PF_R8G8B8A8: + case EPixelFormat::PF_B8G8R8A8: + break; + default: + return; + } + + _world = GetWorld(); + + PrimitiveRenderMode = ESceneCapturePrimitiveRenderMode::PRM_LegacySceneCapture; + bCaptureEveryFrame = 0; + bCaptureOnMovement = 0; + LODDistanceFactor = 100; + bUseRayTracingIfEnabled = false; + CaptureSource = ESceneCaptureSource::SCS_BaseColor; + + CompositeMode = ESceneCaptureCompositeMode::SCCM_Overwrite; + PostProcessBlendWeight = 0; + bUseCustomProjectionMatrix = false; + bAlwaysPersistRenderingState = true; + + ShowFlags = { EShowFlagInitMode::ESFIM_All0 }; + ShowFlags.SetBSP(true); + ShowFlags.SetLandscape(true); + ShowFlags.SetSkeletalMeshes(true); + ShowFlags.SetStaticMeshes(true); + ShowFlags.SetInstancedFoliage(true); + ShowFlags.SetInstancedGrass(true); + ShowFlags.SetInstancedStaticMeshes(true); + ShowFlags.SetPaper2DSprites(true); + ShowFlags.SetGame(true); + ShowFlags.SetMaterials(true); + ShowFlags.SetRendering(true); + + PrimaryComponentTick.TickInterval = tickInterval; + PrimaryComponentTick.bCanEverTick = true; + PrimaryComponentTick.bStartWithTickEnabled = true; +} + +void UInteractableScreenCapturer::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + switch(TickType) + { + case ELevelTick::LEVELTICK_TimeOnly: + case ELevelTick::LEVELTICK_ViewportsOnly: + case ELevelTick::LEVELTICK_All: + { + USceneCaptureComponent2D::TickComponent(DeltaTime, TickType, ThisTickFunction); + CaptureScene(); + GetCameraView(DeltaTime, _view); + Process(); + } + break; + default: + break; + } +} + +void UInteractableScreenCapturer::Process() +{ + static FThreadSafeBool running = false; + if(!running) + { + running = true; + ENQUEUE_RENDER_COMMAND(GetInteractablesFromScreen)( + [ + capture = _capture, + output = _output, + world = _world, + view = _view + ] + (FRHICommandListImmediate& RHICmdList) + { + double StartTime = FPlatformTime::Seconds(); + static FIntPoint _extent = capture->GetDesc().Extent; + static uint32 _size = _extent.X * _extent.Y; + + static TArray _capturePixels; + static uint8* _bitMap = new uint8[_size]; // cv::Mat allocation is weird sometimes... + + uint32 stride = 0; + FColor* data = (FColor*)RHICmdList.LockTexture2D( + capture, + 0, + RLM_ReadOnly, + stride, + false); + for(uint32 i = 0; i < _size; ++i) + { + switch(data[i].R) + { + case 0xFF: + switch(data[i].G) + { + case 0x00: + switch(data[i].B) + { + case 0xFF: + _bitMap[i] = static_cast(0xFF); + continue; + default: + break; + } + [[fallthrough]]; + default: + break; + } + [[fallthrough]]; + default: + _bitMap[i] = static_cast(0x00); + break; + } + } + RHICmdList.UnlockTexture2D(capture, 0, false); + + cv::Mat componentsMap, componentsStats, componentsCentroids; + static cv::Mat bitMapCVProxy{ _extent.Y, _extent.X, CV_8UC1, _bitMap }; + auto components = cv::connectedComponentsWithStats( + bitMapCVProxy, + componentsMap, + componentsStats, + componentsCentroids, + 4, + CV_16U + ); + + //static FVector _oldLocation; + //static FRotator _oldRotation; + //static FMatrix _invProjection; + //if(view.Location != _oldLocation || view.Rotation != _oldRotation) + //{ + // _oldLocation = view.Location; + // _oldRotation = view.Rotation; + // _invProjection = + // (FTranslationMatrix(-(view.Location)) + // * (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()) + // .InverseFast(); + //} + FMatrix _invProjection = + (FTranslationMatrix(-(view.Location)) + * (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()) + .InverseFast(); + + FVector worldLoc, worldDir; + for(int i = 1; i < components; ++i) + { + FVector2D screenPos = { ((double*)componentsCentroids.data)[i * 2], ((double*)componentsCentroids.data)[i * 2 + 1] }; + 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{}; + FVector startLocation = view.Location; + FVector endLocation = worldLoc + worldDir * 1000000; + world->LineTraceSingleByChannel( + result, + startLocation, + endLocation, + ECC_GameTraceChannel1 + ); + static AInteractable* _last = nullptr; + static bool _activated = false; + if(result.bBlockingHit) + { + if(_last != result.GetActor()) + { + _activated = true; + if(auto interactable = Cast(result.GetActor())) + { + _last = interactable; + GEngine->AddOnScreenDebugMessage(10 + i, 0.5f, FColor::Yellow, interactable->GetName()); + } + } + + DrawDebugLine(world, startLocation, endLocation, FColor::Green, false, tickInterval, 0, 0.5f); + } + else + { + if(_activated) + { + + _activated = false; + _last = nullptr; + } + + DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 10, 0.5f); + } + //DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 0, 0.5f); + } + GEngine->AddOnScreenDebugMessage(667, 0.5f, FColor::Yellow, FString::Printf(TEXT("time:%f"), FPlatformTime::Seconds() - StartTime)); + running = false; + } + ); + } +} \ No newline at end of file diff --git a/Source/Lost_Edge/Private/Interactable/InteractableScreenCapturer.h b/Source/Lost_Edge/Private/Interactable/InteractableScreenCapturer.h new file mode 100644 index 0000000..97f156c --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InteractableScreenCapturer.h @@ -0,0 +1,27 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "Components/SceneCaptureComponent2D.h" +#include "CoreMinimal.h" + +#include "InteractableScreenCapturer.generated.h" + +UCLASS(hidecategories = (Collision, Object, Physics, SceneComponent), ClassGroup = Rendering, editinlinenew, meta = (BlueprintSpawnableComponent), MinimalAPI) +class UInteractableScreenCapturer : public USceneCaptureComponent2D +{ + GENERATED_BODY() + +public: + UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer); + virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + +protected: + void Process(); + +private: + FTextureRHIRef _capture; + FBufferRHIRef _output; + UWorld* _world; + FMinimalViewInfo _view; +}; diff --git a/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.cpp b/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.cpp index a00633a..59516e0 100644 --- a/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.cpp +++ b/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.cpp @@ -6,6 +6,8 @@ #include "DrawDebugHelpers.h" #include "Engine/World.h" +#include "Interactable.h" + void URaycastInteractableActivator::Scan_Implementation() { FHitResult result{}; @@ -19,8 +21,37 @@ void URaycastInteractableActivator::Scan_Implementation() collisionChannel ); + static AInteractable* _last = nullptr; + static bool _activated = false; if(result.bBlockingHit) - DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Green, false, 0.5f, 0, 1.0f); + { + if(_last != result.GetActor()) + { + _activated = true; + if(auto interactable = Cast(result.GetActor())) + { + _last = interactable; + if(interactableActivatedDelegate.IsBound()) + { + interactableActivatedDelegate.Execute(interactable); + } + } + } + + //DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Green, false, 0.5f, 0, 1.0f); + } else - DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, 0.5f, 10, 1.0f); + { + if(_activated) + { + if(interactableDeactivatedDelegate.IsBound()) + { + interactableDeactivatedDelegate.Execute(_last); + } + _activated = false; + _last = nullptr; + } + + //DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, 0.5f, 10, 1.0f); + } } \ No newline at end of file diff --git a/Source/Lost_Edge/Private/Interactable/UsableInteractable.cpp b/Source/Lost_Edge/Private/Interactable/UsableInteractable.cpp index 361cd95..a41f49b 100644 --- a/Source/Lost_Edge/Private/Interactable/UsableInteractable.cpp +++ b/Source/Lost_Edge/Private/Interactable/UsableInteractable.cpp @@ -12,12 +12,6 @@ const FString UUsableInteractable::GetName_Implementation() return _name; } -const UInputMappingContext* UUsableInteractable::GetInputMapping_Implementation() -{ - static auto _mapping = UInputMappingContext{}; - return &_mapping; -} - const TArray UUsableInteractable::GetActivatorsAndCallers_Implementation() { static TArray _array = { diff --git a/Source/Lost_Edge/Private/Interactable/UsableInteractable.h b/Source/Lost_Edge/Private/Interactable/UsableInteractable.h index b39b388..6d03655 100644 --- a/Source/Lost_Edge/Private/Interactable/UsableInteractable.h +++ b/Source/Lost_Edge/Private/Interactable/UsableInteractable.h @@ -9,7 +9,7 @@ #include "UsableInteractable.generated.h" -UCLASS() +UCLASS(Blueprintable, BlueprintType) class UUsableInteractable : public UInteractableComponent { GENERATED_BODY() @@ -18,9 +18,6 @@ public: const FString GetName(); virtual const FString GetName_Implementation() override; - const UInputMappingContext* GetInputMapping(); - virtual const UInputMappingContext* GetInputMapping_Implementation() override; - const TArray GetActivatorsAndCallers(); virtual const TArray GetActivatorsAndCallers_Implementation() override; }; \ No newline at end of file diff --git a/Source/Lost_Edge/Private/PlayerBase.cpp b/Source/Lost_Edge/Private/PlayerBase.cpp index 05a9732..5eb62f2 100644 --- a/Source/Lost_Edge/Private/PlayerBase.cpp +++ b/Source/Lost_Edge/Private/PlayerBase.cpp @@ -11,6 +11,7 @@ #include "Kismet/KismetMathLibrary.h" #include "CustomGameInstanceBase.h" +#include "Interactable/Interactable.h" #include "Interactable/InteractableActivator.h" #include "Interactable/InteractableCaller.h" #include "Interactable/InteractableComponent.h" @@ -144,18 +145,49 @@ void APlayerBase::LoadInteractable() } TSet> activators; + TMap, UInteractableCaller*> callers; for(auto& interaction : GI->interactionsCollection) { auto actAndCallArray = interaction->GetDefaultObject()->GetActivatorsAndCallers_Implementation(); for(auto& actAndCall : actAndCallArray) { - activators.Add(actAndCall.activator); + if(!activators.Contains(actAndCall.activator)) + { + activators.Add(actAndCall.activator); + auto component = NewObject(this, actAndCall.activator); + component->AttachToComponent(camera, FAttachmentTransformRules::SnapToTargetIncludingScale); + component->interactableActivatedDelegate.BindUObject(this, &APlayerBase::InteractableActivated); + } + + if(!callers.Contains(actAndCall.caller)) + { + auto component = NewObject(this, actAndCall.caller); + this->AddOwnedComponent(component); + component->Init(); + callers.Add(actAndCall.caller, component); + AddInteractionCallersMapping(interaction, component); + } + else + { + AddInteractionCallersMapping(interaction, callers[actAndCall.caller]); + } } } - - for(auto& activator : activators) - { - auto component = NewObject(this, activator); - component->AttachToComponent(camera, FAttachmentTransformRules::SnapToTargetIncludingScale); - } } + +void APlayerBase::InteractableActivated(AInteractable* interactable) +{ + GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Yellow, interactable->GetName()); +} + +void APlayerBase::AddInteractionCallersMapping(TSubclassOf interaction, UInteractableCaller* caller) +{ + if(!_interactionsToCallers.Contains(interaction)) + { + _interactionsToCallers.Add(interaction, { caller }); + } + else + { + _interactionsToCallers[interaction].Add(caller); + } +} \ No newline at end of file diff --git a/Source/Lost_Edge/Private/PlayerBase.h b/Source/Lost_Edge/Private/PlayerBase.h index 194b3fb..36d6b6f 100644 --- a/Source/Lost_Edge/Private/PlayerBase.h +++ b/Source/Lost_Edge/Private/PlayerBase.h @@ -61,4 +61,9 @@ protected: private: void LoadInteractable(); + void InteractableActivated(class AInteractable* interactable); + + void AddInteractionCallersMapping(TSubclassOf interaction, class UInteractableCaller* caller); + + TMap, TSet> _interactionsToCallers; }; diff --git a/Source/Lost_EdgeEditor.Target.cs b/Source/Lost_EdgeEditor.Target.cs index b36475d..49b23a9 100644 --- a/Source/Lost_EdgeEditor.Target.cs +++ b/Source/Lost_EdgeEditor.Target.cs @@ -1,15 +1,12 @@ // Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; -using System.Collections.Generic; -public class Lost_EdgeEditorTarget : TargetRules -{ - public Lost_EdgeEditorTarget( TargetInfo Target) : base(Target) - { - Type = TargetType.Editor; - DefaultBuildSettings = BuildSettingsVersion.V2; - IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_1; - ExtraModuleNames.Add("Lost_Edge"); - } +public class Lost_EdgeEditorTarget : TargetRules { + public Lost_EdgeEditorTarget(TargetInfo Target) : base(Target) { + Type = TargetType.Editor; + DefaultBuildSettings = BuildSettingsVersion.Latest; + IncludeOrderVersion = EngineIncludeOrderVersion.Latest; + ExtraModuleNames.AddRange(new string[] { "Lost_Edge", "Lost_EdgeShaders" }); + } } diff --git a/Source/Lost_EdgeShaders/Lost_EdgeShaders.Build.cs b/Source/Lost_EdgeShaders/Lost_EdgeShaders.Build.cs new file mode 100644 index 0000000..660a4d6 --- /dev/null +++ b/Source/Lost_EdgeShaders/Lost_EdgeShaders.Build.cs @@ -0,0 +1,17 @@ +// Oleg Petruny proprietary. + +using UnrealBuildTool; + +public class Lost_EdgeShaders : ModuleRules { + public Lost_EdgeShaders(ReadOnlyTargetRules Target) : base(Target) { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + PublicDependencyModuleNames.AddRange(new string[] { }); + PrivateDependencyModuleNames.AddRange(new string[] { "Core", + "CoreUObject", + "Engine", + "Renderer", + "RenderCore", + "RHI", + "Projects" }); + } +} diff --git a/Source/Lost_EdgeShaders/Private/InteractableScreenCapturerBitMapCS.cpp b/Source/Lost_EdgeShaders/Private/InteractableScreenCapturerBitMapCS.cpp new file mode 100644 index 0000000..e691a2c --- /dev/null +++ b/Source/Lost_EdgeShaders/Private/InteractableScreenCapturerBitMapCS.cpp @@ -0,0 +1,6 @@ +// Oleg Petruny proprietary. + + +#include "InteractableScreenCapturerBitMapCS.h" + +IMPLEMENT_GLOBAL_SHADER(FInteractableScreenCapturerBitMapCS, "/Lost_EdgeShaders/InteractableScreenCapturerBitMapCS.usf", "InteractableScreenCapturerBitMapCS", SF_Compute); diff --git a/Source/Lost_EdgeShaders/Private/Lost_EdgeShaders.cpp b/Source/Lost_EdgeShaders/Private/Lost_EdgeShaders.cpp new file mode 100644 index 0000000..52098da --- /dev/null +++ b/Source/Lost_EdgeShaders/Private/Lost_EdgeShaders.cpp @@ -0,0 +1,20 @@ +// Oleg Petruny proprietary. + +#include "Lost_EdgeShaders.h" + +#include "GlobalShader.h" +#include "Misc/Paths.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_GAME_MODULE(FLost_EdgeShaders, Lost_EdgeShaders); + + +void FLost_EdgeShaders::StartupModule() +{ + // Maps virtual shader source directory to actual shaders directory on disk. + FString ShaderDirectory = FPaths::Combine(FPaths::ProjectDir(), TEXT("Shaders/Private")); + AddShaderSourceDirectoryMapping("/Lost_EdgeShaders", ShaderDirectory); +} + +void FLost_EdgeShaders::ShutdownModule() +{} \ No newline at end of file diff --git a/Source/Lost_EdgeShaders/Public/InteractableScreenCapturerBitMapCS.h b/Source/Lost_EdgeShaders/Public/InteractableScreenCapturerBitMapCS.h new file mode 100644 index 0000000..fc976c8 --- /dev/null +++ b/Source/Lost_EdgeShaders/Public/InteractableScreenCapturerBitMapCS.h @@ -0,0 +1,38 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "CoreMinimal.h" +#include "DataDrivenShaderPlatformInfo.h" +#include "GlobalShader.h" +#include "ShaderParameterStruct.h" + + +class LOST_EDGESHADERS_API FInteractableScreenCapturerBitMapCS : public FGlobalShader +{ +public: + DECLARE_GLOBAL_SHADER(FInteractableScreenCapturerBitMapCS); + SHADER_USE_PARAMETER_STRUCT(FInteractableScreenCapturerBitMapCS, FGlobalShader); + + BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) + + SHADER_PARAMETER_SRV(Buffer, Input) + SHADER_PARAMETER_UAV(RWBuffer, Output) + + END_SHADER_PARAMETER_STRUCT() + +public: + static constexpr int32 shader_threads_per_group_count = 64; + + static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) + { + return true; + } + + static inline void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) + { + FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); + + OutEnvironment.SetDefine(TEXT("THREADGROUPSIZE_X"), shader_threads_per_group_count); + } +}; diff --git a/Source/Lost_EdgeShaders/Public/Lost_EdgeShaders.h b/Source/Lost_EdgeShaders/Public/Lost_EdgeShaders.h new file mode 100644 index 0000000..0ec9fa0 --- /dev/null +++ b/Source/Lost_EdgeShaders/Public/Lost_EdgeShaders.h @@ -0,0 +1,26 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "CoreMinimal.h" + +#include "Modules/ModuleInterface.h" +#include "Modules/ModuleManager.h" + +class FLost_EdgeShaders : public IModuleInterface +{ +public: + static inline FLost_EdgeShaders& Get() + { + return FModuleManager::LoadModuleChecked("Lost_EdgeShaders"); + } + + static inline bool IsAvailable() + { + return FModuleManager::Get().IsModuleLoaded("Lost_EdgeShaders"); + } + +public: + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file