diff --git a/Content/BP_VirtualRealityPawn.uasset b/Content/BP_VirtualRealityPawn.uasset
index d3ab67b1d5e35aa30a09884d6070777d908d76db..d712f953c0b6b7115269a19395b8ec42c8998aed 100644
Binary files a/Content/BP_VirtualRealityPawn.uasset and b/Content/BP_VirtualRealityPawn.uasset differ
diff --git a/Content/RWTHVRGameMode.uasset b/Content/RWTHVRGameMode.uasset
index 6e3b11f843990e7dd4f9418596c8987874829aa1..bbe367b340d7b98310000099bb7ffa8e3e088b0f 100644
Binary files a/Content/RWTHVRGameMode.uasset and b/Content/RWTHVRGameMode.uasset differ
diff --git a/Source/RWTHVRToolkit/Private/Pawn/ContinuousMovementComponent.cpp b/Source/RWTHVRToolkit/Private/Pawn/ContinuousMovementComponent.cpp
index af46f80934f02d316a5680f35a1a0a684c809cd3..cf8213737de30479629cc84aeb80dca1cae7a04e 100644
--- a/Source/RWTHVRToolkit/Private/Pawn/ContinuousMovementComponent.cpp
+++ b/Source/RWTHVRToolkit/Private/Pawn/ContinuousMovementComponent.cpp
@@ -1,6 +1,5 @@
// Fill out your copyright notice in the Description page of Project Settings.
-
#include "Pawn/ContinuousMovementComponent.h"
#include "EnhancedInputComponent.h"
@@ -9,6 +8,7 @@
#include "GameFramework/PlayerController.h"
#include "Pawn/VRPawnInputConfig.h"
#include "Utility/VirtualRealityUtilities.h"
+#include "MotionControllerComponent.h"
void UContinuousMovementComponent::BeginPlay()
{
@@ -71,16 +71,6 @@ void UContinuousMovementComponent::SetupInputActions()
// bind additional functions for desktop rotations
if (UVirtualRealityUtilities::IsDesktopMode())
{
- APlayerController* PC = Cast<APlayerController>(VRPawn->GetController());
- if (PC)
- {
- PC->bShowMouseCursor = true;
- PC->bEnableClickEvents = true;
- PC->bEnableMouseOverEvents = true;
- } else
- {
- UE_LOG(LogTemp,Error,TEXT("PC Player Controller is invalid"));
- }
EI->BindAction(DesktopRotation, ETriggerEvent::Started, this, &UContinuousMovementComponent::StartDesktopRotation);
EI->BindAction(DesktopRotation, ETriggerEvent::Completed, this, &UContinuousMovementComponent::EndDesktopRotation);
EI->BindAction(MoveUp, ETriggerEvent::Triggered,this,&UContinuousMovementComponent::OnBeginUp);
@@ -102,8 +92,8 @@ void UContinuousMovementComponent::OnBeginMove(const FInputActionValue& Value)
const bool bGazeDirected = UVirtualRealityUtilities::IsDesktopMode() || SteeringMode == EVRSteeringModes::STEER_GAZE_DIRECTED;
- const FVector ForwardDir = bGazeDirected ? VRPawn->Head->GetForwardVector() : MovementHand->GetForwardVector();
- const FVector RightDir = bGazeDirected ? VRPawn->Head->GetRightVector() : MovementHand->GetRightVector();
+ const FVector ForwardDir = bGazeDirected ? VRPawn->HeadCameraComponent->GetForwardVector() : MovementHand->GetForwardVector();
+ const FVector RightDir = bGazeDirected ? VRPawn->HeadCameraComponent->GetRightVector() : MovementHand->GetRightVector();
if (VRPawn->Controller != nullptr)
{
@@ -133,10 +123,6 @@ void UContinuousMovementComponent::OnBeginTurn(const FInputActionValue& Value)
if (TurnValue.X != 0.f)
{
VRPawn->AddControllerYawInput(TurnRateFactor * TurnValue.X);
- if (UVirtualRealityUtilities::IsDesktopMode())
- {
- UpdateRightHandForDesktopInteraction();
- }
}
if (TurnValue.Y != 0.f)
@@ -144,7 +130,6 @@ void UContinuousMovementComponent::OnBeginTurn(const FInputActionValue& Value)
if (UVirtualRealityUtilities::IsDesktopMode() && bApplyDesktopRotation)
{
VRPawn->AddControllerPitchInput(TurnRateFactor * -TurnValue.Y);
- SetCameraOffset();
}
}
}
@@ -162,28 +147,6 @@ void UContinuousMovementComponent::OnBeginSnapTurn(const FInputActionValue& Valu
}
}
-void UContinuousMovementComponent::SetCameraOffset() const
-{
- // this also incorporates the BaseEyeHeight, if set as static offset,
- // rotations are still around the center of the pawn (on the floor), so pitch rotations look weird
- FVector Location;
- FRotator Rotation;
- VRPawn->GetActorEyesViewPoint(Location, Rotation);
- VRPawn->CameraComponent->SetWorldLocationAndRotation(Location, Rotation);
-}
-
-void UContinuousMovementComponent::UpdateRightHandForDesktopInteraction()
-{
- APlayerController* PC = Cast<APlayerController>(VRPawn->GetController());
- if (PC)
- {
- FVector MouseLocation, MouseDirection;
- PC->DeprojectMousePositionToWorld(MouseLocation, MouseDirection);
- FRotator HandOrientation = MouseDirection.ToOrientationRotator();
- VRPawn->RightHand->SetWorldRotation(HandOrientation);
- }
-}
-
void UContinuousMovementComponent::OnBeginUp(const FInputActionValue& Value)
{
const float MoveValue = Value.Get<FVector2D>().X;
diff --git a/Source/RWTHVRToolkit/Private/Pawn/TeleportationComponent.cpp b/Source/RWTHVRToolkit/Private/Pawn/TeleportationComponent.cpp
index b775efcac63506828c7112e3675cad196a652ce5..0fd9bd5a3e170d723b28c39fd047d575c1780542 100644
--- a/Source/RWTHVRToolkit/Private/Pawn/TeleportationComponent.cpp
+++ b/Source/RWTHVRToolkit/Private/Pawn/TeleportationComponent.cpp
@@ -13,6 +13,7 @@
#include "Kismet/GameplayStatics.h"
#include "NiagaraDataInterfaceArrayFunctionLibrary.h"
#include "Utility/VirtualRealityUtilities.h"
+#include "MotionControllerComponent.h"
// Sets default values for this component's properties
UTeleportationComponent::UTeleportationComponent()
@@ -273,7 +274,7 @@ void UTeleportationComponent::SetCameraOffset() const
FVector Location;
FRotator Rotation;
VRPawn->GetActorEyesViewPoint(Location, Rotation);
- VRPawn->CameraComponent->SetWorldLocationAndRotation(Location, Rotation);
+ VRPawn->HeadCameraComponent->SetWorldLocationAndRotation(Location, Rotation);
}
void UTeleportationComponent::UpdateRightHandForDesktopInteraction()
diff --git a/Source/RWTHVRToolkit/Private/Pawn/UniversalTrackedComponent.cpp b/Source/RWTHVRToolkit/Private/Pawn/UniversalTrackedComponent.cpp
deleted file mode 100644
index 18320ca4b9a3a1378918f7df114507550102d0f5..0000000000000000000000000000000000000000
--- a/Source/RWTHVRToolkit/Private/Pawn/UniversalTrackedComponent.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-
-#include "Pawn/UniversalTrackedComponent.h"
-
-#include "Camera/CameraComponent.h"
-#include "Utility/VirtualRealityUtilities.h"
-#include "Roles/LiveLinkTransformTypes.h"
-#include "ILiveLinkClient.h"
-
-DEFINE_LOG_CATEGORY(LogUniversalTrackedComponent);
-
-// Sets default values for this component's properties
-UUniversalTrackedComponent::UUniversalTrackedComponent()
-{
- PrimaryComponentTick.bCanEverTick = true;
- PrimaryComponentTick.TickGroup = ETickingGroup::TG_PrePhysics;
- bAlwaysUseLiveLinkTracking = false;
-}
-
-void UUniversalTrackedComponent::SetShowDeviceModel(const bool bShowControllerModel)
-{
- if (!UVirtualRealityUtilities::IsHeadMountedMode() || TrackedComponent == nullptr) return;
-
- bShowDeviceModelInHMD = bShowControllerModel;
- Cast<UMotionControllerComponent>(TrackedComponent)->SetShowDeviceModel(bShowDeviceModelInHMD);
-}
-
-void UUniversalTrackedComponent::BeginPlay()
-{
- Super::BeginPlay();
-
- if (UVirtualRealityUtilities::IsHeadMountedMode())
- {
- if (ProxyType == ETrackedComponentType::TCT_HEAD)
- {
- TrackedComponent = GetOwner()->FindComponentByClass<UCameraComponent>();
- }
- else
- {
- /* Spawn Motion Controller Components in HMD Mode*/
- UMotionControllerComponent* MotionController = Cast<UMotionControllerComponent>(GetOwner()->AddComponentByClass(UMotionControllerComponent::StaticClass(), false, FTransform::Identity, false));
- GetOwner()->AddInstanceComponent(MotionController); // makes it show correctly in the hierarchy
-
- // Todo: If bAlwaysUseLiveLinkTracking is true, those should be sourced by LiveLink
- switch(ProxyType)
- {
- case ETrackedComponentType::TCT_TRACKER_1:
- MotionController->SetTrackingMotionSource(FName("Special_1"));
- break;
- case ETrackedComponentType::TCT_TRACKER_2:
- MotionController->SetTrackingMotionSource(FName("Special_2"));
- break;
- case ETrackedComponentType::TCT_RIGHT_HAND:
- MotionController->SetTrackingMotionSource(FName("Right"));
- break;
- case ETrackedComponentType::TCT_LEFT_HAND:
- MotionController->SetTrackingMotionSource(FName("Left"));
- break;
- default: break;
- }
- MotionController->SetShowDeviceModel(bShowDeviceModelInHMD);
-
- TrackedComponent = MotionController;
- }
- if (TrackedComponent)
- AttachToComponent(Cast<USceneComponent>(TrackedComponent), FAttachmentTransformRules::SnapToTargetIncludingScale);
-
- }
- // Check for bAlwaysUseLiveLinkTracking here too in case we want to use LiveLink in Editor/Desktop mode.
- else if (UVirtualRealityUtilities::IsDesktopMode() && !bAlwaysUseLiveLinkTracking)
- {
- switch(ProxyType)
- {
- case ETrackedComponentType::TCT_RIGHT_HAND:
- case ETrackedComponentType::TCT_LEFT_HAND:
- case ETrackedComponentType::TCT_HEAD:
- TrackedComponent = GetOwner()->FindComponentByClass<UCameraComponent>(); //All are attached to camera
- break;
- case ETrackedComponentType::TCT_TRACKER_1:
- case ETrackedComponentType::TCT_TRACKER_2:
- TrackedComponent = GetOwner()->GetRootComponent();
- break;
- }
- if (TrackedComponent) AttachToComponent(Cast<USceneComponent>(TrackedComponent), FAttachmentTransformRules::SnapToTargetIncludingScale);
-
- }
- // If we're either in the cave or using LiveLink, set it up here. Might want to differentiate between the two cases later on,
- // for now both should be equivalent. Maybe set up some additional stuff automatically like presets etc.
- else if (UVirtualRealityUtilities::IsRoomMountedMode() || bAlwaysUseLiveLinkTracking)
- {
- // Instead of using the clumsy LiveLinkComponentController, we just directly check the LiveLink Data in Tick later on.
- // Set up this Component to Tick, and check whether Subject and Role is set.
-
- // TODO: Check for AttachmentType and automatically get the respective Subject/Role. Need to investigate how those are called by DTrack.
- TrackedComponent = this;
- bUseLiveLinkTracking = true; // override this in case someone forgot to set it.
- if (SubjectRepresentation.Subject.IsNone() || SubjectRepresentation.Role == nullptr)
- {
- UE_LOG(LogUniversalTrackedComponent, Error, TEXT("UUniversalTrackedComponent::BeginPlay(): No LiveLink Subject or Role is set! Tracking will not work"));
- }
- SetComponentTickEnabled(true);
- }
-}
-
-void UUniversalTrackedComponent::PostLoad()
-{
- Super::PostLoad();
-
- // This is required in PostLoad (and theoretically in OnComponentCreated too) because just setting this in
- // the constructor or PostInitializeProperties will load the CDO's property values.
- // Just calling it in BeginPlay() won't let us see the LiveLink preview in the editor.
- bTickInEditor = bAlwaysUseLiveLinkTracking;
- PrimaryComponentTick.bStartWithTickEnabled = bAlwaysUseLiveLinkTracking;
-}
-
-#if WITH_EDITOR
-void UUniversalTrackedComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
-{
- // Catch the change to bAlwaysUseLiveLinkTracking, and disable/enable tick respectively for in-editor tracking.
- const FName PropertyName(PropertyChangedEvent.GetPropertyName());
- if(PropertyName == GET_MEMBER_NAME_CHECKED(UUniversalTrackedComponent, bAlwaysUseLiveLinkTracking))
- {
- bTickInEditor = bAlwaysUseLiveLinkTracking;
- SetComponentTickEnabled(bAlwaysUseLiveLinkTracking);
- }
- Super::PostEditChangeProperty(PropertyChangedEvent);
-}
-#endif
-
-
-void UUniversalTrackedComponent::TickComponent(const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
-{
- Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
-
- // Check whether we need to update the component with new LiveLink data. This is either the case if
- // nDisplay uses bUseLiveLinkTracking (Play Mode), or if bAlwaysUseLiveLinkTracking is true, then we tick both in Play Mode and Editor.
- const bool bEvaluateLiveLink = bUseLiveLinkTracking || bAlwaysUseLiveLinkTracking;
-
- if(!bEvaluateLiveLink || SubjectRepresentation.Subject.IsNone() || SubjectRepresentation.Role == nullptr)
- {
- return;
- }
-
- // Get the LiveLink interface and evaluate the current existing frame data for the given Subject and Role.
- ILiveLinkClient& LiveLinkClient = IModularFeatures::Get().GetModularFeature<ILiveLinkClient>(ILiveLinkClient::ModularFeatureName);
- FLiveLinkSubjectFrameData SubjectData;
- const bool bHasValidData = LiveLinkClient.EvaluateFrame_AnyThread(SubjectRepresentation.Subject, SubjectRepresentation.Role, SubjectData);
-
- if(!bHasValidData)
- return;
-
- // Assume we are using a Transform Role to track the components! This is a slightly dangerous assumption, and could be further improved.
- const FLiveLinkTransformStaticData* StaticData = SubjectData.StaticData.Cast<FLiveLinkTransformStaticData>();
- const FLiveLinkTransformFrameData* FrameData = SubjectData.FrameData.Cast<FLiveLinkTransformFrameData>();
-
- if (StaticData && FrameData)
- {
- // Finally, apply the transform to this component according to the static data.
- ApplyLiveLinkTransform(FrameData->Transform, *StaticData);
- }
-}
-
-UMotionControllerComponent* UUniversalTrackedComponent::GetMotionControllerComponentByMotionSource(EControllerHand MotionSource) const
-{
- TArray<UActorComponent*> Components;
- GetOwner()->GetComponents(UMotionControllerComponent::StaticClass(),Components);
- return Cast<UMotionControllerComponent>(
- Components.FindByPredicate([&MotionSource](UActorComponent* Current)
- {
- switch(MotionSource)
- {
- case EControllerHand::Right:
- return Cast<UMotionControllerComponent>(Current)->MotionSource == FName("Right");
- case EControllerHand::Left:
- return Cast<UMotionControllerComponent>(Current)->MotionSource == FName("Left");
- default: return true;
- }
- })[0]
- );
-}
-
-void UUniversalTrackedComponent::ApplyLiveLinkTransform(const FTransform& Transform, const FLiveLinkTransformStaticData& StaticData)
-{
- if (bUseLocation && StaticData.bIsLocationSupported)
- {
- if (bWorldTransform)
- {
- this->SetWorldLocation(Transform.GetLocation(), bSweep, nullptr, bTeleport ? ETeleportType::TeleportPhysics : ETeleportType::ResetPhysics);
- }
- else
- {
- this->SetRelativeLocation(Transform.GetLocation(), bSweep, nullptr, bTeleport ? ETeleportType::TeleportPhysics : ETeleportType::ResetPhysics);
- }
- }
-
- if (bUseRotation && StaticData.bIsRotationSupported)
- {
- if (bWorldTransform)
- {
- this->SetWorldRotation(Transform.GetRotation(), bSweep, nullptr, bTeleport ? ETeleportType::TeleportPhysics : ETeleportType::ResetPhysics);
- }
- else
- {
- this->SetRelativeRotation(Transform.GetRotation(), bSweep, nullptr, bTeleport ? ETeleportType::TeleportPhysics : ETeleportType::ResetPhysics);
- }
- }
-
- if (bUseScale && StaticData.bIsScaleSupported)
- {
- if (bWorldTransform)
- {
- this->SetWorldScale3D(Transform.GetScale3D());
- }
- else
- {
- this->SetRelativeScale3D(Transform.GetScale3D());
- }
- }
-}
diff --git a/Source/RWTHVRToolkit/Private/Pawn/VRPawnMovement.cpp b/Source/RWTHVRToolkit/Private/Pawn/VRPawnMovement.cpp
index 40b293ecdbc5da4bbf250bb32bafd97986000a4a..1d6ac46295f055d38c206a6757c0e0771d8fe103 100644
--- a/Source/RWTHVRToolkit/Private/Pawn/VRPawnMovement.cpp
+++ b/Source/RWTHVRToolkit/Private/Pawn/VRPawnMovement.cpp
@@ -85,7 +85,7 @@ void UVRPawnMovement::SetHeadComponent(USceneComponent* NewHeadComponent)
CapsuleColliderComponent->SetupAttachment(HeadComponent);
const float HalfHeight = 80.0f; //this is just an initial value to look good in editor
CapsuleColliderComponent->SetCapsuleSize(CapsuleRadius, HalfHeight);
- CapsuleColliderComponent->SetWorldLocation(FVector(0.0f, 0.0f,HalfHeight));
+ CapsuleColliderComponent->SetWorldLocation(FVector(0.0f, 0.0f,-HalfHeight));
}
void UVRPawnMovement::SetCapsuleColliderToUserSize()
diff --git a/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp b/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp
index 324da1efed37f74ea74239577279b479bc192854..8cd1fd2992101b33b8f872833c8ecad8134798d8 100644
--- a/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp
+++ b/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp
@@ -4,9 +4,9 @@
#include "Engine/LocalPlayer.h"
#include "GameFramework/PlayerController.h"
-#include "Pawn/UniversalTrackedComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
+#include "MotionControllerComponent.h"
#include "Camera/CameraComponent.h"
#include "Pawn/VRPawnInputConfig.h"
#include "Pawn/VRPawnMovement.h"
@@ -23,45 +23,54 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial
SetRootComponent(CreateDefaultSubobject<USceneComponent>(TEXT("Origin")));
- CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
- CameraComponent->SetupAttachment(RootComponent);
- CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, BaseEyeHeight)); //so it is rendered correctly in editor
+ HeadCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
+ HeadCameraComponent->SetupAttachment(RootComponent);
+ HeadCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, BaseEyeHeight)); //so it is rendered correctly in editor
- Head = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Head"));
- Head->ProxyType = ETrackedComponentType::TCT_HEAD;
- Head->SetupAttachment(RootComponent);
-
- CapsuleRotationFix = CreateDefaultSubobject<USceneComponent>(TEXT("CapsuleRotationFix"));
- CapsuleRotationFix->SetUsingAbsoluteRotation(true);
- CapsuleRotationFix->SetupAttachment(Head);
-
PawnMovement = CreateDefaultSubobject<UVRPawnMovement>(TEXT("Pawn Movement"));
PawnMovement->SetUpdatedComponent(RootComponent);
- PawnMovement->SetHeadComponent(CapsuleRotationFix);
+ PawnMovement->SetHeadComponent(HeadCameraComponent);
- RightHand = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Right Hand"));
- RightHand->ProxyType = ETrackedComponentType::TCT_RIGHT_HAND;
- RightHand->AttachementType = EAttachementType::AT_FLYSTICK;
+ RightHand = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("Right Hand MCC"));
RightHand->SetupAttachment(RootComponent);
- LeftHand = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Left Hand"));
- LeftHand->ProxyType = ETrackedComponentType::TCT_LEFT_HAND;
- LeftHand->AttachementType = EAttachementType::AT_HANDTARGET;
+ LeftHand = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("Left Hand MCC"));
LeftHand->SetupAttachment(RootComponent);
BasicVRInteraction = CreateDefaultSubobject<UBasicVRInteractionComponent>(TEXT("Basic VR Interaction"));
BasicVRInteraction->Initialize(RightHand);
-
+}
+
+void AVirtualRealityPawn::Tick(float DeltaSeconds)
+{
+ Super::Tick(DeltaSeconds);
+
+ if (UVirtualRealityUtilities::IsDesktopMode())
+ {
+ SetCameraOffset();
+ UpdateRightHandForDesktopInteraction();
+ }
}
void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
- const APlayerController* PlayerController = Cast<APlayerController>(GetController());
+ APlayerController* PlayerController = Cast<APlayerController>(GetController());
+ if (!PlayerController) {
+ UE_LOG(LogTemp, Error, TEXT("PC Player Controller is invalid"));
+ return;
+ }
UEnhancedInputLocalPlayerSubsystem* InputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
if(!InputSubsystem)
{
UE_LOG(Toolkit,Error,TEXT("[VirtualRealiytPawn.cpp] InputSubsystem IS NOT VALID"));
}
+
+ if(UVirtualRealityUtilities::IsDesktopMode())
+ {
+ PlayerController->bShowMouseCursor = true;
+ PlayerController->bEnableClickEvents = true;
+ PlayerController->bEnableMouseOverEvents = true;
+ }
InputSubsystem->ClearAllMappings();
@@ -74,8 +83,30 @@ void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInput
EI->BindAction(Fire, ETriggerEvent::Started, this, &AVirtualRealityPawn::OnBeginFire);
EI->BindAction(Fire, ETriggerEvent::Completed, this, &AVirtualRealityPawn::OnEndFire);
- EI->BindAction(ToggleNavigationMode,ETriggerEvent::Started,this,&AVirtualRealityPawn::OnToggleNavigationMode);
-
+ EI->BindAction(ToggleNavigationMode,ETriggerEvent::Started,this,&AVirtualRealityPawn::OnToggleNavigationMode);
+}
+
+void AVirtualRealityPawn::UpdateRightHandForDesktopInteraction()
+{
+ APlayerController* PC = Cast<APlayerController>(GetController());
+ if (PC)
+ {
+ FVector MouseLocation, MouseDirection;
+ PC->DeprojectMousePositionToWorld(MouseLocation, MouseDirection);
+ FRotator HandOrientation = MouseDirection.ToOrientationRotator();
+ RightHand->SetWorldRotation(HandOrientation);
+ RightHand->SetRelativeLocation(HeadCameraComponent->GetRelativeLocation());
+ }
+}
+
+void AVirtualRealityPawn::SetCameraOffset() const
+{
+ // this also incorporates the BaseEyeHeight, if set as static offset,
+ // rotations are still around the center of the pawn (on the floor), so pitch rotations look weird
+ FVector Location;
+ FRotator Rotation;
+ GetActorEyesViewPoint(Location, Rotation);
+ HeadCameraComponent->SetWorldLocationAndRotation(Location, Rotation);
}
// legacy grabbing
diff --git a/Source/RWTHVRToolkit/Private/RWTHVRToolkit.cpp b/Source/RWTHVRToolkit/Private/RWTHVRToolkit.cpp
index 2cfd23435ddcd3ae6a0f31c66e3a0b07d1f9b0d4..c335e156518151ccef60a186e8a4bc67b0c55903 100644
--- a/Source/RWTHVRToolkit/Private/RWTHVRToolkit.cpp
+++ b/Source/RWTHVRToolkit/Private/RWTHVRToolkit.cpp
@@ -4,12 +4,24 @@
void FRWTHVRToolkitModule::StartupModule ()
{
+
+ IModularFeatures& ModularFeatures = IModularFeatures::Get();
+ if (ModularFeatures.IsModularFeatureAvailable(ILiveLinkClient::ModularFeatureName))
+ {
+ FLiveLinkClient* LiveLinkClient = static_cast<FLiveLinkClient*>(&IModularFeatures::Get().GetModularFeature<ILiveLinkClient>(
+ ILiveLinkClient::ModularFeatureName));
+ LiveLinkMotionController = MakeUnique<FLiveLinkMotionControllerFix>(*LiveLinkClient);
+ LiveLinkMotionController->RegisterController();
+ }
+
ConsoleActivation.Register();
}
void FRWTHVRToolkitModule::ShutdownModule()
{
- ConsoleActivation.Unregister();
+ ConsoleActivation.Unregister();
+ if (LiveLinkMotionController)
+ LiveLinkMotionController->UnregisterController();
}
diff --git a/Source/RWTHVRToolkit/Public/Fixes/LiveLinkMotionControllerFix.h b/Source/RWTHVRToolkit/Public/Fixes/LiveLinkMotionControllerFix.h
new file mode 100644
index 0000000000000000000000000000000000000000..3e8bb02b97f5c333281fd3b23df5109f9370b1ce
--- /dev/null
+++ b/Source/RWTHVRToolkit/Public/Fixes/LiveLinkMotionControllerFix.h
@@ -0,0 +1,221 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include "Features/IModularFeatures.h"
+#include "IMotionController.h"
+#include "LiveLinkClient.h"
+
+#include "Roles/LiveLinkTransformRole.h"
+#include "Roles/LiveLinkTransformTypes.h"
+
+
+#define LOCTEXT_NAMESPACE "LiveLinkMotionController"
+
+
+class FLiveLinkMotionControllerFix : public IMotionController
+{
+ // Internal structure for caching enumerated data
+ struct FLiveLinkMotionControllerEnumeratedSource
+ {
+ // Subject key for talking to live link
+ FLiveLinkSubjectKey SubjectKey;
+
+ // MotionSource name for interacting with Motion Controller system
+ FName MotionSource;
+
+ FLiveLinkMotionControllerEnumeratedSource(const FLiveLinkSubjectKey& Key, FName MotionSourceName) : SubjectKey(Key), MotionSource(MotionSourceName) {}
+ };
+
+ // Built array of Live Link Sources to give to Motion Controller system
+ TArray<FLiveLinkMotionControllerEnumeratedSource> EnumeratedSources;
+
+public:
+ FLiveLinkMotionControllerFix(FLiveLinkClient& InClient) : Client(InClient)
+ {
+ BuildSourceData();
+ OnSubjectsChangedHandle = Client.OnLiveLinkSubjectsChanged().AddRaw(this, &FLiveLinkMotionControllerFix::OnSubjectsChangedHandler);
+ WildcardSource = FGuid::NewGuid();
+ }
+
+ ~FLiveLinkMotionControllerFix()
+ {
+ Client.OnLiveLinkSubjectsChanged().Remove(OnSubjectsChangedHandle);
+ OnSubjectsChangedHandle.Reset();
+ }
+
+ void RegisterController()
+ {
+ IModularFeatures::Get().RegisterModularFeature(GetModularFeatureName(), this);
+ }
+
+ void UnregisterController()
+ {
+ IModularFeatures::Get().UnregisterModularFeature(GetModularFeatureName(), this);
+ }
+
+ virtual bool GetControllerOrientationAndPosition(const int32 ControllerIndex, const FName MotionSource, FRotator& OutOrientation, FVector& OutPosition, float) const override
+ {
+ FLiveLinkSubjectKey SubjectKey = GetSubjectKeyFromMotionSource(MotionSource);
+
+ FLiveLinkSubjectFrameData FrameData;
+ if (Client.EvaluateFrame_AnyThread(SubjectKey.SubjectName, ULiveLinkTransformRole::StaticClass(), FrameData))
+ {
+ if (FLiveLinkTransformFrameData* TransformFrameData = FrameData.FrameData.Cast<FLiveLinkTransformFrameData>())
+ {
+ OutPosition = TransformFrameData->Transform.GetLocation();
+ OutOrientation = TransformFrameData->Transform.GetRotation().Rotator();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual bool GetControllerOrientationAndPosition(const int32 ControllerIndex, const FName MotionSource, FRotator& OutOrientation, FVector& OutPosition, bool& OutbProvidedLinearVelocity, FVector& OutLinearVelocity, bool& OutbProvidedAngularVelocity, FVector& OutAngularVelocityAsAxisAndLength, bool& OutbProvidedLinearAcceleration, FVector& OutLinearAcceleration, float WorldToMetersScale) const override
+ {
+ OutbProvidedLinearVelocity = false;
+ OutbProvidedAngularVelocity = false;
+ OutbProvidedLinearAcceleration = false;
+ return GetControllerOrientationAndPosition(ControllerIndex, MotionSource, OutOrientation, OutPosition, WorldToMetersScale);
+ }
+
+ virtual bool GetControllerOrientationAndPositionForTime(const int32 ControllerIndex, const FName MotionSource, FTimespan Time, bool& OutTimeWasUsed, FRotator& OutOrientation, FVector& OutPosition, bool& OutbProvidedLinearVelocity, FVector& OutLinearVelocity, bool& OutbProvidedAngularVelocity, FVector& OutAngularVelocityAsAxisAndLength, bool& OutbProvidedLinearAcceleration, FVector& OutLinearAcceleration, float WorldToMetersScale) const override
+ {
+ OutTimeWasUsed = false;
+ OutbProvidedLinearVelocity = false;
+ OutbProvidedAngularVelocity = false;
+ OutbProvidedLinearAcceleration = false;
+ return GetControllerOrientationAndPosition(ControllerIndex, MotionSource, OutOrientation, OutPosition, WorldToMetersScale);
+ }
+
+ float GetCustomParameterValue(const FName MotionSource, FName ParameterName, bool& bValueFound) const override
+ {
+ FLiveLinkSubjectKey SubjectKey = GetSubjectKeyFromMotionSource(MotionSource);
+
+ FLiveLinkSubjectFrameData EvaluatedData;
+ if (Client.EvaluateFrame_AnyThread(SubjectKey.SubjectName, ULiveLinkBasicRole::StaticClass(), EvaluatedData))
+ {
+ if (EvaluatedData.FrameData.GetBaseData())
+ {
+ FLiveLinkBaseFrameData& BaseFrameData = *EvaluatedData.FrameData.GetBaseData();
+
+ float FoundValue = 0.f;
+ if (EvaluatedData.StaticData.GetBaseData()->FindPropertyValue(BaseFrameData, ParameterName, FoundValue))
+ {
+ bValueFound = true;
+ return FoundValue;
+ }
+ }
+ }
+
+ bValueFound = false;
+ return 0.f;
+ }
+
+ virtual ETrackingStatus GetControllerTrackingStatus(const int32 ControllerIndex, const FName MotionSource) const override
+ {
+ FLiveLinkSubjectKey SubjectKey = GetSubjectKeyFromMotionSource(MotionSource);
+
+ FLiveLinkSubjectFrameData EvaluatedData;
+ if (Client.EvaluateFrame_AnyThread(SubjectKey.SubjectName, ULiveLinkBasicRole::StaticClass(), EvaluatedData))
+ {
+ return ETrackingStatus::Tracked;
+ }
+ return ETrackingStatus::NotTracked;
+ }
+
+
+ virtual FName GetMotionControllerDeviceTypeName() const override
+ {
+ static FName LiveLinkMotionControllerName(TEXT("LiveLinkMotionController"));
+ return LiveLinkMotionControllerName;
+ }
+
+ // Builds cached source data for passing to motion controller system
+ void BuildSourceData()
+ {
+ TArray<FLiveLinkSubjectKey> SubjectKeys = Client.GetSubjects(true, true);
+
+ TMap<FGuid, TArray<FName>> LiveLinkSubjects;
+ LiveLinkSubjects.Add(WildcardSource);
+
+ for (const FLiveLinkSubjectKey& Subject : SubjectKeys)
+ {
+ LiveLinkSubjects.FindOrAdd(Subject.Source).Add(Subject.SubjectName);
+ LiveLinkSubjects.FindChecked(WildcardSource).Add(Subject.SubjectName);
+ }
+
+ TArray<FGuid> SourceGuids;
+ LiveLinkSubjects.GenerateKeyArray(SourceGuids);
+
+ typedef TPair<FGuid, FText> FHeaderEntry;
+ TArray<FHeaderEntry> Headers;
+ Headers.Reserve(SourceGuids.Num());
+
+ for (const FGuid& Source : SourceGuids)
+ {
+ FText SourceName = (Source == WildcardSource) ? LOCTEXT("LiveLinkAnySource", "Any") : Client.GetSourceType(Source);
+ Headers.Emplace(Source, SourceName);
+ }
+
+ {
+ FGuid& CaptureWildcardSource = WildcardSource;
+ Headers.Sort([CaptureWildcardSource](const FHeaderEntry& A, const FHeaderEntry& B) { return A.Key == CaptureWildcardSource || A.Value.CompareToCaseIgnored(B.Value) <= 0; });
+ }
+
+ //Build EnumeratedSources data
+ EnumeratedSources.Reset();
+ EnumeratedSources.Reserve(SubjectKeys.Num());
+
+ for (const FHeaderEntry& Header : Headers)
+ {
+ TArray<FName> Subjects = LiveLinkSubjects.FindChecked(Header.Key);
+ Subjects.Sort(FNameLexicalLess());
+ for (FName Subject : Subjects)
+ {
+ FName FullName = *FString::Format(TEXT("{0} ({1})"), { Subject.ToString(), Header.Value.ToString() });
+ EnumeratedSources.Emplace(FLiveLinkSubjectKey(Header.Key, Subject), FullName);
+ }
+ }
+ }
+
+ virtual void EnumerateSources(TArray<FMotionControllerSource>& Sources) const override
+ {
+ for (const FLiveLinkMotionControllerEnumeratedSource& Source : EnumeratedSources)
+ {
+ FMotionControllerSource SourceDesc(Source.MotionSource);
+#if WITH_EDITOR
+ static const FName LiveLinkCategoryName(TEXT("LiveLink"));
+ SourceDesc.EditorCategory = LiveLinkCategoryName;
+#endif
+ Sources.Add(SourceDesc);
+ }
+ }
+
+ virtual bool GetHandJointPosition(const FName MotionSource, int jointIndex, FVector& OutPosition) const override { return false; }
+
+private:
+ FLiveLinkSubjectKey GetSubjectKeyFromMotionSource(FName MotionSource) const
+ {
+ const FLiveLinkMotionControllerEnumeratedSource* EnumeratedSource = EnumeratedSources.FindByPredicate([&](const FLiveLinkMotionControllerEnumeratedSource& Item) { return Item.MotionSource == MotionSource; });
+ if (EnumeratedSource)
+ {
+ return EnumeratedSource->SubjectKey;
+ }
+ return FLiveLinkSubjectKey(FGuid(), MotionSource);
+ }
+
+ // Registered with the client and called when client's subjects change
+ void OnSubjectsChangedHandler() { BuildSourceData(); }
+
+ // Reference to the live link client
+ FLiveLinkClient& Client;
+
+ // Handle to delegate registered with client so we can update when subject state changes
+ FDelegateHandle OnSubjectsChangedHandle;
+
+ // Wildcard source, we don't care about the source itself, just the subject name
+ FGuid WildcardSource;
+};
+
+#undef LOCTEXT_NAMESPACE
diff --git a/Source/RWTHVRToolkit/Public/Pawn/ContinuousMovementComponent.h b/Source/RWTHVRToolkit/Public/Pawn/ContinuousMovementComponent.h
index 38bada0c11d392d7e011b4d9d2830c3399197bf2..7ef4d501d729ad9fb800bba06571bb7ee57add3f 100644
--- a/Source/RWTHVRToolkit/Public/Pawn/ContinuousMovementComponent.h
+++ b/Source/RWTHVRToolkit/Public/Pawn/ContinuousMovementComponent.h
@@ -89,10 +89,10 @@ public:
private:
UPROPERTY()
- UUniversalTrackedComponent* MovementHand;
+ UMotionControllerComponent* MovementHand;
UPROPERTY()
- UUniversalTrackedComponent* RotationHand;
+ UMotionControllerComponent* RotationHand;
UPROPERTY()
class UInputMappingContext* IMCMovement;
@@ -101,11 +101,5 @@ private:
UPROPERTY()
AVirtualRealityPawn* VRPawn;
-
- /**
- * Fixes camera rotation in desktop mode.
- */
- void SetCameraOffset() const;
- void UpdateRightHandForDesktopInteraction();
};
diff --git a/Source/RWTHVRToolkit/Public/Pawn/TeleportationComponent.h b/Source/RWTHVRToolkit/Public/Pawn/TeleportationComponent.h
index 4521fdd7322e5880f533d674b73ee992ffbf926e..003f6a96f01ca828e2da9f1cde509a01a913d194 100644
--- a/Source/RWTHVRToolkit/Public/Pawn/TeleportationComponent.h
+++ b/Source/RWTHVRToolkit/Public/Pawn/TeleportationComponent.h
@@ -117,10 +117,10 @@ public:
private:
UPROPERTY()
- UUniversalTrackedComponent* TeleportationHand;
+ UMotionControllerComponent* TeleportationHand;
UPROPERTY()
- UUniversalTrackedComponent* RotationHand;
+ UMotionControllerComponent* RotationHand;
UPROPERTY()
class UInputMappingContext* IMCMovement;
diff --git a/Source/RWTHVRToolkit/Public/Pawn/UniversalTrackedComponent.h b/Source/RWTHVRToolkit/Public/Pawn/UniversalTrackedComponent.h
deleted file mode 100644
index 254863d0dec9643ccae920fbc3e6a6b0453d9d0e..0000000000000000000000000000000000000000
--- a/Source/RWTHVRToolkit/Public/Pawn/UniversalTrackedComponent.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-#pragma once
-
-#include "CoreMinimal.h"
-#include "LiveLinkRole.h"
-#include "Components/SceneComponent.h"
-#include "MotionControllerComponent.h"
-#include "UniversalTrackedComponent.generated.h"
-
-DECLARE_LOG_CATEGORY_EXTERN(LogUniversalTrackedComponent, Log, All);
-
-struct FLiveLinkTransformStaticData;
-
-UENUM(BlueprintType)
-enum class ETrackedComponentType : uint8
-{
- TCT_TRACKER_1 UMETA(DisplayName = "VIVE Tracker 1"),
- TCT_TRACKER_2 UMETA(DisplayName = "VIVE Tracker 2"),
- TCT_RIGHT_HAND UMETA(DisplayName = "Right Hand"),
- TCT_LEFT_HAND UMETA(DisplayName = "Left Hand"),
- TCT_HEAD UMETA(DisplayName = "Head")
-};
-
-UENUM(BlueprintType)
-enum class EAttachementType : uint8
-{
- AT_NONE UMETA(DisplayName = "Not attached"),
- AT_HANDTARGET UMETA(DisplayName = "To the right/left hand target"),
- AT_FLYSTICK UMETA(DisplayName = "To the Flystick"),
- AT_CUSTOM_SUBJECT UMETA(DisplayName = "Custom LiveLink Subject|Role")
-};
-
-/*
- * Acts as an intelligent proxy object, when attached to a Pawn class
- * Attaches itself to the specified controller (Camera, MotionController, TrackedDevice) once they are available
- * Behaves according to the ETrackedComponentType which has to be set before starting
- */
-
-UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
-class RWTHVRTOOLKIT_API UUniversalTrackedComponent : public USceneComponent
-{
- GENERATED_BODY()
-
-public:
- // Sets default values for this component's properties
- UUniversalTrackedComponent();
-
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tracking")
- ETrackedComponentType ProxyType = ETrackedComponentType::TCT_HEAD;
-
- /** Set whether LiveLink should always be enabled, even in the editor or desktop mode. Overrides bUseLiveLinkTracking.*/
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tracking", meta = (DisplayName = "Override all tracking with LiveLink"))
- bool bAlwaysUseLiveLinkTracking;
-
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tracking|nDisplay")
- EAttachementType AttachementType = EAttachementType::AT_NONE;
-
- /** Set whether nDisplay should use LiveLink tracking. Requires a valid Subject Representation!*/
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tracking|nDisplay")
- bool bUseLiveLinkTracking = true;
-
- /** Set the LiveLink Subject Representation to be used by this component. */
- UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Tracking|nDisplay|LiveLink", meta = (EditCondition = "AttachementType==EAttachementType::AT_CUSTOM_SUBJECT"))
- FLiveLinkSubjectRepresentation SubjectRepresentation;
-
- /** Set the transform of the component in world space of in its local reference frame. */
- UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Tracking|nDisplay|LiveLink", meta = (EditCondition = "AttachementType==EAttachementType::AT_CUSTOM_SUBJECT"))
- bool bWorldTransform = false;
-
- /** Whether we should set the owning actor's location with the value coming from live link. */
- UPROPERTY(EditAnywhere, Category = "Tracking|nDisplay|LiveLink", meta = (EditCondition = "AttachementType==EAttachementType::AT_CUSTOM_SUBJECT"))
- bool bUseLocation = true;
-
- /** Whether we should set the owning actor's rotation with the value coming from live link. */
- UPROPERTY(EditAnywhere, Category = "Tracking|nDisplay|LiveLink", meta = (EditCondition = "AttachementType==EAttachementType::AT_CUSTOM_SUBJECT"))
- bool bUseRotation = true;
-
- /** Whether we should set the owning actor's scale with the value coming from live link. */
- UPROPERTY(EditAnywhere, Category = "Tracking|nDisplay|LiveLink", meta = (EditCondition = "AttachementType==EAttachementType::AT_CUSTOM_SUBJECT"))
- bool bUseScale = true;
-
- /**
- * Whether we sweep to the destination location, triggering overlaps along the way and stopping short of the target if blocked by something.
- * Only the root component is swept and checked for blocking collision, child components move without sweeping. If collision is off, this has no effect.
- */
- UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tracking|nDisplay|LiveLink", meta = (EditCondition = "AttachementType==EAttachementType::AT_CUSTOM_SUBJECT"))
- bool bSweep = false;
-
- /**
- * Whether we teleport the physics state (if physics collision is enabled for this object).
- * If true, physics velocity for this object is unchanged (so ragdoll parts are not affected by change in location).
- * If false, physics velocity is updated based on the change in position (affecting ragdoll parts).
- * If CCD is on and not teleporting, this will affect objects along the entire sweep volume.
- */
- UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tracking|nDisplay|LiveLink", meta = (EditCondition = "AttachementType==EAttachementType::AT_CUSTOM_SUBJECT"))
- bool bTeleport = true;
-
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tracking|HMD", BlueprintSetter=SetShowDeviceModel)
- bool bShowDeviceModelInHMD = true;
-
- UFUNCTION(BlueprintSetter)
- void SetShowDeviceModel(const bool bShowControllerModel);
-
- //~ Begin SceneComponent Interface
- virtual void BeginPlay() override;
- virtual void PostLoad() override;
- virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
-
-#if WITH_EDITOR
- virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
-#endif
- //~ End SceneComponent Interface
-
-private:
-
- /**
- * @brief Helper function that applies the LiveLink data to this component. Taken from the LiveLink Transform Controller.
- * @param Transform Transform read from the LiveLink Client.
- * @param StaticData Static data from the LiveLink Subject, defines what is and isn't supported.
- * @return void
- */
- void ApplyLiveLinkTransform(const FTransform& Transform, const FLiveLinkTransformStaticData& StaticData);
-
- USceneComponent* TrackedComponent = nullptr;
- UMotionControllerComponent* GetMotionControllerComponentByMotionSource(EControllerHand MotionSource) const;
-
-};
diff --git a/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h b/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h
index 21ba56b809f3c642243650ce6df4774f12cf19c0..36bd4233955a8fdbb0f3eb13d4d6e5a56bed92c1 100644
--- a/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h
+++ b/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h
@@ -4,13 +4,12 @@
#include "BasicVRInteractionComponent.h"
#include "CoreMinimal.h"
-#include "UniversalTrackedComponent.h"
#include "Pawn/VRPawnMovement.h"
#include "VirtualRealityPawn.generated.h"
class UCameraComponent;
class ULiveLinkComponentController;
-
+class UMotionControllerComponent;
/**
*
@@ -21,32 +20,26 @@ class RWTHVRTOOLKIT_API AVirtualRealityPawn : public APawn
GENERATED_BODY()
public:
AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer);
+
+ virtual void Tick(float DeltaSeconds) override;
- /* Proxy */
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Proxy Objects")
- UUniversalTrackedComponent* Head;
-
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Proxy Objects")
- UUniversalTrackedComponent* RightHand;
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|MotionControllers")
+ UMotionControllerComponent* RightHand;
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Proxy Objects")
- UUniversalTrackedComponent* LeftHand;
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|MotionControllers")
+ UMotionControllerComponent* LeftHand;
/* Interaction */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Interaction")
UBasicVRInteractionComponent* BasicVRInteraction;
/* Movement */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement")
- UVRPawnMovement* PawnMovement;
-
-
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Movement")
- USceneComponent* CapsuleRotationFix;
+ UVRPawnMovement* PawnMovement;
/* CameraComponent */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Camera")
- UCameraComponent* CameraComponent;
+ UCameraComponent* HeadCameraComponent;
protected:
@@ -72,4 +65,10 @@ protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pawn|Input")
class UInputAction* ToggleNavigationMode;
+ /**
+ * Fixes camera rotation in desktop mode.
+ */
+ void SetCameraOffset() const;
+ void UpdateRightHandForDesktopInteraction();
+
};
diff --git a/Source/RWTHVRToolkit/Public/RWTHVRToolkit.h b/Source/RWTHVRToolkit/Public/RWTHVRToolkit.h
index fa1843ded226c6fcd438ea1e22f1acdc83632906..c1d682b4edf75806bf8d48debc8eb4bafbb0b06c 100644
--- a/Source/RWTHVRToolkit/Public/RWTHVRToolkit.h
+++ b/Source/RWTHVRToolkit/Public/RWTHVRToolkit.h
@@ -2,6 +2,7 @@
#include "CoreMinimal.h"
#include "Fixes/ActivateConsoleInShipping.h"
+#include "Fixes/LiveLinkMotionControllerFix.h"
class FRWTHVRToolkitModule : public IModuleInterface
@@ -11,5 +12,6 @@ public:
virtual void ShutdownModule() override;
private:
- FActivateConsoleInShipping ConsoleActivation;
+ FActivateConsoleInShipping ConsoleActivation;
+ TUniquePtr<FLiveLinkMotionControllerFix> LiveLinkMotionController;
};