diff --git a/Content/Ray_Material.uasset b/Content/Ray_Material.uasset new file mode 100644 index 0000000000000000000000000000000000000000..4ae373bdf3e090fe996f4c48f4ccfc8ec9555b65 Binary files /dev/null and b/Content/Ray_Material.uasset differ diff --git a/Content/Ray_Mesh.uasset b/Content/Ray_Mesh.uasset new file mode 100644 index 0000000000000000000000000000000000000000..77e19c730861e7a568503abac21893633ea697f9 Binary files /dev/null and b/Content/Ray_Mesh.uasset differ diff --git a/Source/WidgetInteraction/Private/RwthComponent.cpp b/Source/WidgetInteraction/Private/RwthComponent.cpp deleted file mode 100644 index 2685e08e4b8d766cadea1404b1057f71ff6308dc..0000000000000000000000000000000000000000 --- a/Source/WidgetInteraction/Private/RwthComponent.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#include "RwthComponent.h" -#include "Runtime/InputCore/Classes/InputCoreTypes.h" -#include "Runtime/Engine/Classes/Components/InputComponent.h" -#include "VirtualRealityPawn.h" - -URwthComponent::URwthComponent() -{ - -} - -void URwthComponent::Init() -{ - SetVisibility(true); - InteractionDistance = 1000000.0f; - - auto input_cmp = dynamic_cast<UInputComponent*>(GetOwner()->GetComponentByClass(UInputComponent::StaticClass())); - - input_cmp->BindAction<FFireDelegate>("Fire", IE_Pressed, this, &URwthComponent::OnFire, true); - input_cmp->BindAction<FFireDelegate>("Fire", IE_Released, this, &URwthComponent::OnFire, false); - - RegisterComponent(); -} - -void URwthComponent::SetVisibility(bool visible) { - bShowDebug = visible; -} - -void URwthComponent::OnFire(bool val) -{ - if (val == true) - PressPointerKey(EKeys::LeftMouseButton); - else - ReleasePointerKey(EKeys::LeftMouseButton); -} \ No newline at end of file diff --git a/Source/WidgetInteraction/Private/VRWidgetInteractionComponent.cpp b/Source/WidgetInteraction/Private/VRWidgetInteractionComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6b52e4586a2d2645a2bb45ea01aa888eaf8acec --- /dev/null +++ b/Source/WidgetInteraction/Private/VRWidgetInteractionComponent.cpp @@ -0,0 +1,55 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "VRWidgetInteractionComponent.h" + +#include "Runtime/InputCore/Classes/InputCoreTypes.h" +#include "Runtime/Engine/Classes/Components/InputComponent.h" +#include "ConstructorHelpers.h" +#include "Modules/ModuleManager.h" +#include "Interfaces/IPluginManager.h" +#include "VirtualRealityPawn.h" + + +UVRWidgetInteractionComponent::UVRWidgetInteractionComponent() { + InteractionRay = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Interaction Ray")); + + //this ray model as a inlayed cross with flipped normals so it can be seen as a cross in desktop mode where the right hand is attached to the head + ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/WidgetInteraction/Ray_Mesh")); + if (MeshAsset.Object != nullptr) + { + InteractionRay->SetStaticMesh(MeshAsset.Object); + } + + bShowDebug = false; +} + +void UVRWidgetInteractionComponent::Init(USceneComponent* parent) +{ + SetVisibility(true); + InteractionDistance = 1000000.0f; + + auto input_cmp = dynamic_cast<UInputComponent*>(GetOwner()->GetComponentByClass(UInputComponent::StaticClass())); + + input_cmp->BindAction<FFireDelegate>("Fire", IE_Pressed, this, &UVRWidgetInteractionComponent::OnFire, true); + input_cmp->BindAction<FFireDelegate>("Fire", IE_Released, this, &UVRWidgetInteractionComponent::OnFire, false); + + RegisterComponent(); + InteractionRay->RegisterComponent(); + + if (parent != nullptr) { + InteractionRay->AttachToComponent(parent, FAttachmentTransformRules::KeepRelativeTransform); + this->AttachToComponent(parent, FAttachmentTransformRules::KeepRelativeTransform); + } +} + +void UVRWidgetInteractionComponent::SetVisibility(bool visible) { + InteractionRay->SetVisibility(visible); +} + +void UVRWidgetInteractionComponent::OnFire(bool val) +{ + if (val == true) + PressPointerKey(EKeys::LeftMouseButton); + else + ReleasePointerKey(EKeys::LeftMouseButton); +} diff --git a/Source/WidgetInteraction/Private/WidgetInteraction.cpp b/Source/WidgetInteraction/Private/WidgetInteraction.cpp index f414d1d36a5e20cf120c0af09964b85bffd57fe5..c35cd28584c7a34b85e3282f37011aa8c5f7449a 100644 --- a/Source/WidgetInteraction/Private/WidgetInteraction.cpp +++ b/Source/WidgetInteraction/Private/WidgetInteraction.cpp @@ -8,6 +8,8 @@ #define LOCTEXT_NAMESPACE "FWidgetInteractionModule" +DEFINE_LOG_CATEGORY(WidgetIntLog); + void FWidgetInteractionModule::StartupModule() { on_world_tick_start_delegate_.BindRaw(this, &FWidgetInteractionModule::OnWorldTickStart); @@ -21,83 +23,49 @@ void FWidgetInteractionModule::ShutdownModule() void FWidgetInteractionModule::OnWorldTickStart(ELevelTick level_tick, float val) { - //called every Tick() - - auto worlds = GEngine->GetWorldContexts(); - - for (auto world_context : worlds) { - - auto world = world_context.World(); - - if (last_world == world && widget_interaction_cmp_ != nullptr) { - if (widget_interaction_cmp_->IsValidLowLevel() == true) { - continue; - } - else { - widget_interaction_cmp_ = nullptr; - } - } - - if (world == nullptr) - continue; - - auto player_controller = world->GetFirstPlayerController(); - if (player_controller == nullptr) - continue; - - auto vr_pawn = dynamic_cast<AVirtualRealityPawn*>(player_controller->AcknowledgedPawn); - if (vr_pawn == nullptr) - continue; - - UE_LOG(LogTemp, Warning, TEXT("OnWorldTickStart called and interaction component will be updated")); - - FString name = ""; - UClass* component_class = UMotionControllerComponent::StaticClass(); - - - if (IDisplayCluster::Get().GetClusterMgr()->IsStandalone()) { - //if this is a standalone setup ... - if (UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled()) { - //.. with an HMD, we attach the intercation component to the right hand - name = FString("RightMotionController"); - component_class = UMotionControllerComponent::StaticClass(); - } - else { - //... without an HMD, we also attach it to the virtual right hand, since it exists in this case - name = TEXT("RightMotionController"); - component_class = UMotionControllerComponent::StaticClass(); - } - } - else { - //if this is a cluster setup we attach it to the flystick - name = TEXT("flystick"); - component_class = UDisplayClusterSceneComponent::StaticClass(); - } - - auto parent_vec = vr_pawn->GetComponentsByClass(component_class); - bool success; - for (auto parent : parent_vec) { - if (parent->GetName() == FString(name)) { - CreateWidgetInteraction(dynamic_cast<USceneComponent*>(parent), vr_pawn); - success = true; - last_world = world; - } - } - - if (!success) - UE_LOG(LogTemp, Error, TEXT("Failed to load widget asset \"%s\", cannot attach widget interaction component"), *name); - } + //since OnWorldTickStart is called independent of the world/level we are in, + //we need to check whether the level changed and, if so, reattach the interaction component + auto worlds = GEngine->GetWorldContexts(); + + for (auto world_context : worlds) { + + auto world = world_context.World(); + + if (last_world == world && widget_interaction_cmp_ != nullptr) { + if (widget_interaction_cmp_->IsValidLowLevel() == true) { + continue; + } + else { + widget_interaction_cmp_ = nullptr; + } + } + + if (world == nullptr) + continue; + + auto player_controller = world->GetFirstPlayerController(); + if (player_controller == nullptr) + continue; + + auto vr_pawn = dynamic_cast<AVirtualRealityPawn*>(player_controller->AcknowledgedPawn); + if (vr_pawn == nullptr) + continue; + + CreateWidgetInteraction(vr_pawn->GetRightHandComponent(), vr_pawn); + last_world = world; + + UE_LOG(WidgetIntLog, Verbose, TEXT("VRInteractionComponent attached to right hand")); + } } -URwthComponent* FWidgetInteractionModule::GetWidgetInteractionComponent() { +UVRWidgetInteractionComponent* FWidgetInteractionModule::GetWidgetInteractionComponent() { return widget_interaction_cmp_; } -void FWidgetInteractionModule::CreateWidgetInteraction(USceneComponent * parent, AVirtualRealityPawn* outer) +void FWidgetInteractionModule::CreateWidgetInteraction(USceneComponent* parent, AVirtualRealityPawn* outer) { - widget_interaction_cmp_ = NewObject<URwthComponent>(outer, URwthComponent::StaticClass()); - widget_interaction_cmp_->AttachToComponent(parent, FAttachmentTransformRules(EAttachmentRule::KeepRelative, false)); - widget_interaction_cmp_->Init(); + widget_interaction_cmp_ = NewObject<UVRWidgetInteractionComponent>(outer, UVRWidgetInteractionComponent::StaticClass()); + widget_interaction_cmp_->Init(parent); } #undef LOCTEXT_NAMESPACE diff --git a/Source/WidgetInteraction/Public/RwthComponent.h b/Source/WidgetInteraction/Public/RwthComponent.h deleted file mode 100644 index d5fda411e5ad92d4c1b3d9ed6f4a6e9fa4c9f0ed..0000000000000000000000000000000000000000 --- a/Source/WidgetInteraction/Public/RwthComponent.h +++ /dev/null @@ -1,27 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" -#include "Components/WidgetInteractionComponent.h" -#include "RwthComponent.generated.h" - -/** - * - */ -UCLASS() -class WIDGETINTERACTION_API URwthComponent : public UWidgetInteractionComponent -{ - GENERATED_BODY() -public: - URwthComponent(); - - void Init(); - - void SetVisibility(bool visible); - -protected: - void OnFire(bool val); - - DECLARE_DELEGATE_OneParam(FFireDelegate, bool); -}; diff --git a/Source/WidgetInteraction/Public/VRWidgetInteractionComponent.h b/Source/WidgetInteraction/Public/VRWidgetInteractionComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..4722527ccd7a5bf90a54a35fcf55ce20e6d1eca2 --- /dev/null +++ b/Source/WidgetInteraction/Public/VRWidgetInteractionComponent.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/WidgetInteractionComponent.h" +#include "Components/StaticMeshComponent.h" + +#include "VRWidgetInteractionComponent.generated.h" + +/** + * + */ +UCLASS() +class WIDGETINTERACTION_API UVRWidgetInteractionComponent : public UWidgetInteractionComponent +{ + GENERATED_BODY() +public: + UVRWidgetInteractionComponent(); + + void Init(USceneComponent* parent); + + void SetVisibility(bool visible); + +protected: + void OnFire(bool val); + + UPROPERTY(VisibleAnywhere) UStaticMeshComponent* InteractionRay; + + DECLARE_DELEGATE_OneParam(FFireDelegate, bool); +}; diff --git a/Source/WidgetInteraction/Public/WidgetInteraction.h b/Source/WidgetInteraction/Public/WidgetInteraction.h index d1b7bb79aa5179f5b8a93e08283233ad0516feb7..d1403ee72a7a1d1c53a6b793b7808ca6da01156f 100644 --- a/Source/WidgetInteraction/Public/WidgetInteraction.h +++ b/Source/WidgetInteraction/Public/WidgetInteraction.h @@ -4,9 +4,11 @@ #include "CoreMinimal.h" #include "VirtualRealityPawn.h" -#include "RwthComponent.h" +#include "VRWidgetInteractionComponent.h" #include "Modules/ModuleManager.h" +DECLARE_LOG_CATEGORY_EXTERN(WidgetIntLog, Log, All); + class WIDGETINTERACTION_API FWidgetInteractionModule : public IModuleInterface { public: @@ -15,17 +17,16 @@ public: virtual void StartupModule() override; virtual void ShutdownModule() override; - UFUNCTION() - void OnWorldTickStart(ELevelTick, float); + UFUNCTION() void OnWorldTickStart(ELevelTick, float); - URwthComponent* GetWidgetInteractionComponent(); + UVRWidgetInteractionComponent* GetWidgetInteractionComponent(); private: - void CreateWidgetInteraction(USceneComponent * parent, AVirtualRealityPawn* outer); + void CreateWidgetInteraction(USceneComponent* parent, AVirtualRealityPawn* outer); private: TBaseDelegate<void, ELevelTick, float> on_world_tick_start_delegate_; - URwthComponent * widget_interaction_cmp_; - UWorld* last_world; + UVRWidgetInteractionComponent* widget_interaction_cmp_; + UWorld* last_world; }; diff --git a/Source/WidgetInteraction/WidgetInteraction.Build.cs b/Source/WidgetInteraction/WidgetInteraction.Build.cs index 5ce59609dc87fef9d3e6387da7ece1eeb3ed7d99..df4ab3bf5449ff699def407c480f224c25a3ba5d 100644 --- a/Source/WidgetInteraction/WidgetInteraction.Build.cs +++ b/Source/WidgetInteraction/WidgetInteraction.Build.cs @@ -25,7 +25,7 @@ public class WidgetInteraction : ModuleRules PublicDependencyModuleNames.AddRange( new string[] { - "Core", + "Core" // ... add other public dependencies that you statically link with here ... } ); @@ -35,15 +35,16 @@ public class WidgetInteraction : ModuleRules new string[] { "CoreUObject", + "Engine", + "Projects", "DisplayCluster", "DisplayClusterInput", - "Engine", "HeadMountedDisplay", "DisplayClusterExtensions", "InputCore", "UMG", "Slate", - "SlateCore", + "SlateCore" // ... add private dependencies that you statically link with here ... } );