From 0f95bcd7602b466ed294fc3a419a9cc73fadcacc Mon Sep 17 00:00:00 2001
From: David Gilbert <gilbert@vr.rwth-aachen.de>
Date: Mon, 3 Feb 2025 09:14:54 +0100
Subject: [PATCH 1/6] fix(utilities): Fixes problem with check for HMD, now
 using new Unreal internal function.

---
 Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp | 5 ++---
 Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs              | 2 +-
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp b/Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp
index 0ac047f0..4e7403fc 100644
--- a/Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp
+++ b/Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp
@@ -1,6 +1,7 @@
 #include "Utility/RWTHVRUtilities.h"
 
 #include "AudioDevice.h"
+#include "HeadMountedDisplayFunctionLibrary.h"
 #include "IHeadMountedDisplay.h"
 #include "IXRTrackingSystem.h"
 #include "Engine/Engine.h"
@@ -18,9 +19,7 @@ bool URWTHVRUtilities::IsDesktopMode() { return !IsRoomMountedMode() && !IsHeadM
 
 bool URWTHVRUtilities::IsHeadMountedMode()
 {
-	// In editor builds: checks for EdEngine->IsVRPreviewActive()
-	// In packaged builds: checks for `-vr` in commandline or bStartInVR in UGeneralProjectSettings
-	return FAudioDevice::CanUseVRAudioDevice();
+	return UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled();
 }
 
 bool URWTHVRUtilities::IsRoomMountedMode()
diff --git a/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs b/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs
index a949553a..3ca3534e 100644
--- a/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs
+++ b/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs
@@ -38,7 +38,7 @@ public class RWTHVRToolkit : ModuleRules
 		PrivateDependencyModuleNames.AddRange(
 			new string[]
 			{
-				"NetCore"
+				"NetCore", "XRBase"
 			}
 		);
 		if (Target.bBuildEditor == true)
-- 
GitLab


From 1ce174ce76b7a449eb98d136f847d5c20c583c24 Mon Sep 17 00:00:00 2001
From: David Gilbert <gilbert@vr.rwth-aachen.de>
Date: Mon, 3 Feb 2025 10:06:40 +0100
Subject: [PATCH 2/6] fix(pawn): Fixes issue with setting player type to hmd,
 it was never actually set.

---
 Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp b/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp
index f6f9f1c0..ba4519c6 100644
--- a/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp
+++ b/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp
@@ -122,14 +122,18 @@ void ARWTHVRPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponen
 	if (ARWTHVRPlayerState* State = GetPlayerState<ARWTHVRPlayerState>())
 	{
 		// Might not be properly synced yet?
-		const EPlayerType Type = State->GetPlayerType();
+		EPlayerType Type = State->GetPlayerType();
 
 		// Don't do anything with the type if it's been set to clustertype or anything.
 		// This is already being done when connecting to the server.
 		const bool bClusterType = Type == EPlayerType::nDisplayPrimary || Type == EPlayerType::nDisplaySecondary;
-
-		if (!bClusterType && URWTHVRUtilities::IsHeadMountedMode())
+		
+		if (!bClusterType)
 		{
+			if (URWTHVRUtilities::IsHeadMountedMode())
+				Type = EPlayerType::HMD;
+			
+			UE_LOGFMT(Toolkit, Display, "Pawn: Requesting Player Type {T}...", StaticCast<int8>(Type));
 			// Could be too early to call this RPC...
 			State->RequestSetPlayerType(Type);
 		}
-- 
GitLab


From b82a2022d66b35311dce7fb7946e5d5fbc8478c9 Mon Sep 17 00:00:00 2001
From: David Gilbert <gilbert@vr.rwth-aachen.de>
Date: Wed, 19 Mar 2025 13:15:07 +0100
Subject: [PATCH 3/6] style: fixes clang format issues in pawn and utilities

---
 Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp         | 4 ++--
 Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp | 7 ++-----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp b/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp
index ba4519c6..96e490aa 100644
--- a/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp
+++ b/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp
@@ -127,12 +127,12 @@ void ARWTHVRPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponen
 		// Don't do anything with the type if it's been set to clustertype or anything.
 		// This is already being done when connecting to the server.
 		const bool bClusterType = Type == EPlayerType::nDisplayPrimary || Type == EPlayerType::nDisplaySecondary;
-		
+
 		if (!bClusterType)
 		{
 			if (URWTHVRUtilities::IsHeadMountedMode())
 				Type = EPlayerType::HMD;
-			
+
 			UE_LOGFMT(Toolkit, Display, "Pawn: Requesting Player Type {T}...", StaticCast<int8>(Type));
 			// Could be too early to call this RPC...
 			State->RequestSetPlayerType(Type);
diff --git a/Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp b/Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp
index 4e7403fc..af8fc108 100644
--- a/Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp
+++ b/Source/RWTHVRToolkit/Private/Utility/RWTHVRUtilities.cpp
@@ -17,10 +17,7 @@ DEFINE_LOG_CATEGORY(Toolkit);
 
 bool URWTHVRUtilities::IsDesktopMode() { return !IsRoomMountedMode() && !IsHeadMountedMode(); }
 
-bool URWTHVRUtilities::IsHeadMountedMode()
-{
-	return UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled();
-}
+bool URWTHVRUtilities::IsHeadMountedMode() { return UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled(); }
 
 bool URWTHVRUtilities::IsRoomMountedMode()
 {
@@ -37,7 +34,7 @@ bool URWTHVRUtilities::IsPrimaryNode()
 	return URWTHVRClusterUtilities::IsPrimaryNode();
 #else
 	return false;
-#endif	
+#endif
 }
 
 float URWTHVRUtilities::GetEyeDistance()
-- 
GitLab


From 75b578cad14a69ec1527aeb2c17c859291da96fd Mon Sep 17 00:00:00 2001
From: David Gilbert <gilbert@vr.rwth-aachen.de>
Date: Wed, 19 Mar 2025 15:43:56 +0100
Subject: [PATCH 4/6] fix(replication): Makes ClientTransformReplication use
 relative position and rotation.

---
 .../Private/Core/ClientTransformReplication.cpp              | 4 ++--
 .../RWTHVRToolkit/Public/Core/ClientTransformReplication.h   | 5 ++++-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/Source/RWTHVRToolkit/Private/Core/ClientTransformReplication.cpp b/Source/RWTHVRToolkit/Private/Core/ClientTransformReplication.cpp
index 0bce9302..011c8337 100644
--- a/Source/RWTHVRToolkit/Private/Core/ClientTransformReplication.cpp
+++ b/Source/RWTHVRToolkit/Private/Core/ClientTransformReplication.cpp
@@ -26,8 +26,8 @@ void UClientTransformReplication::UpdateState(float DeltaTime)
 		// Only do this if we actually replicate the actor
 		if (GetIsReplicated())
 		{
-			const FVector Loc = OwningActor->GetActorLocation();
-			const FRotator Rot = OwningActor->GetActorRotation();
+			const FVector Loc = OwningActor->GetRootComponent()->GetRelativeLocation();
+			const FRotator Rot = OwningActor->GetRootComponent()->GetRelativeRotation();
 
 			// Only update state if the local state changed
 			if (!Loc.Equals(ReplicatedTransform.Position) || !Rot.Equals(ReplicatedTransform.Rotation))
diff --git a/Source/RWTHVRToolkit/Public/Core/ClientTransformReplication.h b/Source/RWTHVRToolkit/Public/Core/ClientTransformReplication.h
index ac364067..c31ed9bd 100644
--- a/Source/RWTHVRToolkit/Public/Core/ClientTransformReplication.h
+++ b/Source/RWTHVRToolkit/Public/Core/ClientTransformReplication.h
@@ -56,7 +56,10 @@ protected:
 		// For now, directly apply the transforms:
 		auto* OwningActor = GetOwner();
 		if (OwningActor && OwningActor->HasValidRootComponent())
-			OwningActor->SetActorLocationAndRotation(ReplicatedTransform.Position, ReplicatedTransform.Rotation);
+		{
+			OwningActor->SetActorRelativeLocation(ReplicatedTransform.Position);
+			OwningActor->SetActorRelativeRotation(ReplicatedTransform.Rotation);
+		}
 	}
 
 	// Unreliable Server RPC that sends the transform from owning client to the server
-- 
GitLab


From ec48445925c9bf656934887a1f557e3429aceb7f Mon Sep 17 00:00:00 2001
From: David Gilbert <gilbert@vr.rwth-aachen.de>
Date: Sat, 29 Mar 2025 11:57:05 +0100
Subject: [PATCH 5/6] hotfix(interaction): fixes crash that can happen when a
 previously grabbed item gets destroyed

---
 .../Interaction/Interactors/DirectInteractionComponent.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp
index 18e51581..f759b37b 100644
--- a/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp
+++ b/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp
@@ -70,6 +70,13 @@ void UDirectInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tick
 	// Call hover end events on all components that were previously in range, but not anymore
 	for (UInteractableComponent* PrevInteractableComp : PreviousInteractableComponentsInRange)
 	{
+		// It can happen that a previous component was destroyed
+		if (!PrevInteractableComp || !PrevInteractableComp->IsValidLowLevel())
+		{
+			ComponentsToRemove.Add(PrevInteractableComp); // might have to use indices here
+			continue;
+		}
+		
 		if (!CurrentInteractableCompsInRange.Contains(PrevInteractableComp))
 		{
 			ComponentsToRemove.AddUnique(PrevInteractableComp);
-- 
GitLab


From 8df591ea3e4e131dbae822820461d6a5c5ebc28d Mon Sep 17 00:00:00 2001
From: David Gilbert <gilbert@vr.rwth-aachen.de>
Date: Mon, 28 Apr 2025 08:42:31 +0200
Subject: [PATCH 6/6] style(interaction): Makes clang formatting happy.

---
 .../Interaction/Interactors/DirectInteractionComponent.cpp      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp
index f759b37b..fac35ab8 100644
--- a/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp
+++ b/Source/RWTHVRToolkit/Private/Interaction/Interactors/DirectInteractionComponent.cpp
@@ -76,7 +76,7 @@ void UDirectInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tick
 			ComponentsToRemove.Add(PrevInteractableComp); // might have to use indices here
 			continue;
 		}
-		
+
 		if (!CurrentInteractableCompsInRange.Contains(PrevInteractableComp))
 		{
 			ComponentsToRemove.AddUnique(PrevInteractableComp);
-- 
GitLab