diff --git a/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp b/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..37b75ccf3a9cdd10b80a17a41866d1a20352c0f1
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp
@@ -0,0 +1,192 @@
+
+#include "VRPawnMovement.h"
+#include "DrawDebugHelpers.h"
+
+UVRPawnMovement::UVRPawnMovement(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
+{
+	CapsuleColliderComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleCollider"));
+	CapsuleColliderComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
+	CapsuleColliderComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
+	CapsuleColliderComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
+	CapsuleColliderComponent->SetCapsuleSize(40.0f, 96.0f);
+}
+
+void UVRPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction){
+
+	SetCapsuleColliderToUserSize();
+
+	FVector PositionChange = GetPendingInputVector();
+
+	if (NavigationMode == EVRNavigationModes::Walk)
+	{
+		PositionChange.Z = 0.0f;
+		ConsumeInputVector();
+		AddInputVector(PositionChange);
+	}
+	
+	if(NavigationMode == EVRNavigationModes::Fly || NavigationMode == EVRNavigationModes::Walk)
+	{
+		MoveByGravityOrStepUp(DeltaTime);
+		CheckForPhysWalkingCollision();
+
+		if(CheckForVirtualMovCollision(PositionChange, DeltaTime))
+		{
+			ConsumeInputVector();
+		}
+	}
+
+	if(NavigationMode == EVRNavigationModes::None)
+	{
+		ConsumeInputVector();
+	}
+
+	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
+	
+	LastCameraPosition = CameraComponent->GetComponentLocation();
+}
+
+bool UVRPawnMovement::CheckForVirtualMovCollision(FVector PositionChange, float DeltaTime)
+{
+	FVector ProbePosition = PositionChange.GetSafeNormal() * GetMaxSpeed() * DeltaTime;
+	FHitResult FHitResultVR;
+	CapsuleColliderComponent->AddWorldOffset(ProbePosition, true, &FHitResultVR);
+	if (FVector::Distance(FHitResultVR.Location, CapsuleColliderComponent->GetComponentLocation()) < CapsuleColliderComponent->GetScaledCapsuleRadius())
+	{
+		return true;
+	}
+	return false;
+}
+
+void UVRPawnMovement::SetCameraComponent(UCameraComponent* NewCameraComponent)
+{
+	CameraComponent = NewCameraComponent;
+	CapsuleColliderComponent->SetupAttachment(CameraComponent);
+}
+
+
+void UVRPawnMovement::SetCapsuleColliderToUserSize()
+{
+	float CharachterSize = abs(UpdatedComponent->GetComponentLocation().Z - CameraComponent->GetComponentLocation().Z);
+
+	if (CharachterSize > MaxStepHeight)
+	{
+		float ColliderHeight = CharachterSize - MaxStepHeight;
+		float ColliderHalfHeight = ColliderHeight / 2.0f;
+		float ColliderRadius = 40.0f;
+		if (ColliderHalfHeight <= ColliderRadius)
+		{//Make the collider to a Sphere
+			CapsuleColliderComponent->SetCapsuleSize(ColliderHalfHeight, ColliderHalfHeight);
+		}
+		else
+		{//Make the collider to a Capsule
+			CapsuleColliderComponent->SetCapsuleSize(ColliderRadius, ColliderHalfHeight);
+		}
+
+		CapsuleColliderComponent->SetWorldLocation(CameraComponent->GetComponentLocation());
+		CapsuleColliderComponent->AddWorldOffset(FVector(0, 0, -ColliderHalfHeight));
+		CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1));
+	}
+	else
+	{
+		CapsuleColliderComponent->SetWorldLocation(CameraComponent->GetComponentLocation());
+		CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1));
+	}
+}
+
+void UVRPawnMovement::CheckForPhysWalkingCollision()
+{
+	FVector CurrentCameraPosition = CameraComponent->GetComponentLocation();
+	FVector Direction = CurrentCameraPosition - LastCameraPosition;
+	FHitResult FHitResultPhys;
+	CapsuleColliderComponent->AddWorldOffset(Direction, true, &FHitResultPhys);
+
+	if (FHitResultPhys.bBlockingHit)
+	{
+		UpdatedComponent->AddLocalOffset(FHitResultPhys.Normal*FHitResultPhys.PenetrationDepth);
+	}
+}
+
+void UVRPawnMovement::MoveByGravityOrStepUp(float DeltaSeconds)
+{
+	FVector StartLineTraceUnderCollider = CapsuleColliderComponent->GetComponentLocation();
+	StartLineTraceUnderCollider.Z -= CapsuleColliderComponent->GetScaledCapsuleHalfHeight();
+	FHitResult HitDetailsMultiLineTrace = CreateMultiLineTrace(FVector(0, 0, -1), StartLineTraceUnderCollider, CapsuleColliderComponent->GetScaledCapsuleRadius() / 4.0f, false);
+	float DistanceDifference = abs(MaxStepHeight - HitDetailsMultiLineTrace.Distance);
+	//Going up (in Fly and Walk Mode)
+	if ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance < MaxStepHeight))
+	{
+		ShiftVertically(DistanceDifference, UpSteppingAcceleration, DeltaSeconds, 1);
+	}
+	//Gravity (only in Walk Mode)
+	else if (NavigationMode==EVRNavigationModes::Walk && ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance > MaxStepHeight) || (HitDetailsMultiLineTrace.Actor == nullptr && HitDetailsMultiLineTrace.Distance != -1.0f)))
+	{
+		ShiftVertically(DistanceDifference, GravityAcceleration, DeltaSeconds, -1);
+	}
+}
+
+void UVRPawnMovement::ShiftVertically(float DiffernceDistance, float VerticalAcceleration, float DeltaSeconds, int Direction)
+{
+	VerticalSpeed += VerticalAcceleration * DeltaSeconds;
+	if (VerticalSpeed*DeltaSeconds < DiffernceDistance)
+	{
+		UpdatedComponent->AddLocalOffset(FVector(0.f, 0.f, Direction * VerticalSpeed * DeltaSeconds));
+	}
+	else
+	{
+		UpdatedComponent->AddLocalOffset(FVector(0.f, 0.f, Direction * DiffernceDistance));
+		VerticalSpeed = 0;
+	}
+}
+
+FHitResult UVRPawnMovement::CreateLineTrace(FVector Direction, const FVector Start, bool Visibility)
+{
+	//Re-initialize hit info
+	FHitResult HitDetails = FHitResult(ForceInit);
+
+	FVector End = ((Direction * 1000.f) + Start);
+	// additional trace parameters
+	FCollisionQueryParams TraceParams(FName(TEXT("InteractTrace")), true, NULL);
+	TraceParams.bTraceComplex = true; //to use complex collision on whatever we interact with to provide better precision.
+	TraceParams.bReturnPhysicalMaterial = true; //to provide details about the physical material, if one exists on the thing we hit, to come back in our hit result.
+
+	if (Visibility)
+		DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 1, 0, 1);
+
+	if (GetWorld()->LineTraceSingleByChannel(HitDetails, Start, End, ECC_Visibility, TraceParams))
+	{
+		if (HitDetails.bBlockingHit)
+		{
+		}
+	}
+	return HitDetails;
+}
+
+FHitResult UVRPawnMovement::CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility)
+{
+	TArray<FVector> StartVectors;
+	TArray<FHitResult> OutHits;
+	FHitResult HitDetailsMultiLineTrace;
+	HitDetailsMultiLineTrace.Distance = -1.0f;//(Distance=-1) not existing, but to know if this Variable not Initialized(when all Traces not compatible)
+
+	StartVectors.Add(Start); //LineTraceCenter
+	StartVectors.Add(Start + FVector(0, -Radius, 0)); //LineTraceLeft
+	StartVectors.Add(Start + FVector(0, +Radius, 0)); //LineTraceRight
+	StartVectors.Add(Start + FVector(+Radius, 0, 0)); //LineTraceFront
+	StartVectors.Add(Start + FVector(-Radius, 0, 0)); //LineTraceBehind
+
+	bool IsBlockingHitAndSameActor = true;
+	bool IsAllNothingHiting = true;
+	// loop through TArray
+	for (FVector& Vector : StartVectors)
+	{
+		FHitResult OutHit = CreateLineTrace(Direction, Vector, Visibility);
+		OutHits.Add(OutHit);
+		IsBlockingHitAndSameActor &= (OutHit.Actor == OutHits[0].Actor); //If all Hiting the same Object, then you are (going up/down) or (walking)
+		IsAllNothingHiting &= (OutHit.Actor == nullptr); //If all Hiting nothing, then you are falling
+	}
+
+	if (IsBlockingHitAndSameActor || IsAllNothingHiting)
+		HitDetailsMultiLineTrace = OutHits[0];
+
+	return HitDetailsMultiLineTrace;
+}
\ No newline at end of file
diff --git a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
index de17d478c5ac6bc9be9124d845fdc3f56b7aa960..57750819a5c2afac0f930263dd8e720201bed309 100644
--- a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
+++ b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
@@ -27,8 +27,9 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial
 
 	AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events.
 
-	Movement = CreateDefaultSubobject<UFloatingPawnMovement>(TEXT("Movement"));
-	Movement->UpdatedComponent = RootComponent;
+	VRMovement = CreateDefaultSubobject<UVRPawnMovement>(TEXT("WalkingMovement"));
+	VRMovement->SetUpdatedComponent(RootComponent);
+	VRMovement->SetCameraComponent(CameraComponent);
 
 	RotatingMovement = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotatingMovement"));
 	RotatingMovement->UpdatedComponent = RootComponent;
@@ -55,13 +56,6 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial
 	HmdRightMotionController->SetShowDeviceModel(true);
 	HmdRightMotionController->SetVisibility(false);
 
-	CapsuleColliderComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleCollider"));
-	CapsuleColliderComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
-	CapsuleColliderComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
-	CapsuleColliderComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
-	CapsuleColliderComponent->SetupAttachment(CameraComponent);
-	CapsuleColliderComponent->SetCapsuleSize(40.0f, 96.0f);
-
 	HmdTracker1 = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("HmdTracker1"));
 	HmdTracker1->SetupAttachment(RootComponent);
 	HmdTracker1->SetTrackingSource(EControllerHand::Special_1);
@@ -79,7 +73,7 @@ void AVirtualRealityPawn::OnForward_Implementation(float Value)
 {
 	if (RightHand)
 	{
-		HandleMovementInput(Value, RightHand->GetForwardVector());
+		AddMovementInput(RightHand->GetForwardVector(), Value);
 	}
 }
 
@@ -87,7 +81,7 @@ void AVirtualRealityPawn::OnRight_Implementation(float Value)
 {
 	if (RightHand)
 	{
-		HandleMovementInput(Value, RightHand->GetRightVector());
+		AddMovementInput(RightHand->GetRightVector(), Value);
 	}
 }
 
@@ -118,11 +112,6 @@ void AVirtualRealityPawn::SetBaseTurnRate(float Value)
 	BaseTurnRate = Value;
 }
 
-UFloatingPawnMovement* AVirtualRealityPawn::GetFloatingPawnMovement()
-{
-	return Movement;
-}
-
 URotatingMovementComponent* AVirtualRealityPawn::GetRotatingMovementComponent()
 {
 	return RotatingMovement;
@@ -221,10 +210,10 @@ void AVirtualRealityPawn::BeginPlay()
 	if (SettingsActors.Num() > 0)
 	{
 		ADisplayClusterSettings* Settings = Cast<ADisplayClusterSettings>(SettingsActors[0]);
-		Movement->MaxSpeed = Settings->MovementMaxSpeed;
-		Movement->Acceleration = Settings->MovementAcceleration;
-		Movement->Deceleration = Settings->MovementDeceleration;
-		Movement->TurningBoost = Settings->MovementTurningBoost;
+		VRMovement->MaxSpeed = Settings->MovementMaxSpeed;
+		VRMovement->Acceleration = Settings->MovementAcceleration;
+		VRMovement->Deceleration = Settings->MovementDeceleration;
+		VRMovement->TurningBoost = Settings->MovementTurningBoost;
 		BaseTurnRate = Settings->RotationSpeed;
 	}
 
@@ -288,8 +277,6 @@ void AVirtualRealityPawn::BeginPlay()
 
 	CollisionComponent->SetCollisionProfileName(FName("NoCollision"));
 	CollisionComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
-
-	LastCameraPosition = CameraComponent->GetComponentLocation();
 }
 
 void AVirtualRealityPawn::EndPlay(const EEndPlayReason::Type EndPlayReason)
@@ -306,14 +293,6 @@ void AVirtualRealityPawn::EndPlay(const EEndPlayReason::Type EndPlayReason)
 void AVirtualRealityPawn::Tick(float DeltaSeconds)
 {
 	Super::Tick(DeltaSeconds);
-	//if the walking-mode is activated
-	if (NavigationMode == EVRNavigationModes::nav_mode_walk)
-	{
-		DeltaTime = DeltaSeconds;
-		SetCapsuleColliderCharacterSizeVR();
-		MoveByGravityOrStepUp(DeltaSeconds);
-		CheckForPhysWalkingCollision();
-	}
 
 	// if an actor is grabbed and a behavior is defined move move him accordingly  
 	if (GrabbedActor != nullptr)
@@ -333,8 +312,6 @@ void AVirtualRealityPawn::Tick(float DeltaSeconds)
 
 	//Flystick might not be available at start, hence is checked every frame.
 	InitRoomMountedComponentReferences();
-
-	LastCameraPosition = CameraComponent->GetComponentLocation();
 }
 
 void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
@@ -440,111 +417,7 @@ FTwoVectors AVirtualRealityPawn::GetHandRay(float Length)
 
 UPawnMovementComponent* AVirtualRealityPawn::GetMovementComponent() const
 {
-	return Movement;
-}
-
-void AVirtualRealityPawn::SetCapsuleColliderCharacterSizeVR()
-{
-	float CharachterSize = abs(RootComponent->GetComponentLocation().Z - CameraComponent->GetComponentLocation().Z);
-
-	if (CharachterSize > MaxStepHeight)
-	{
-		float ColliderHeight = CharachterSize - MaxStepHeight;
-		float ColliderHalfHeight = ColliderHeight / 2.0f;
-		float ColliderRadius = 40.0f;
-		if (ColliderHalfHeight <= ColliderRadius)
-		{//Make the collider to a Sphere
-			CapsuleColliderComponent->SetCapsuleSize(ColliderHalfHeight, ColliderHalfHeight);
-		}
-		else
-		{//Make the collider to a Capsule
-			CapsuleColliderComponent->SetCapsuleSize(ColliderRadius, ColliderHalfHeight);
-		}
-
-		CapsuleColliderComponent->SetWorldLocation(CameraComponent->GetComponentLocation());
-		CapsuleColliderComponent->AddWorldOffset(FVector(0, 0, -ColliderHalfHeight));
-		CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1));
-	}
-	else
-	{
-		CapsuleColliderComponent->SetWorldLocation(CameraComponent->GetComponentLocation());
-		CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1));
-	}
-}
-
-void AVirtualRealityPawn::CheckForPhysWalkingCollision()
-{
-	FVector CurrentCameraPosition = CameraComponent->GetComponentLocation();
-	FVector Direction = CurrentCameraPosition - LastCameraPosition;
-	FHitResult FHitResultPhys;
-	CapsuleColliderComponent->AddWorldOffset(Direction, true, &FHitResultPhys);
-
-	if (FHitResultPhys.bBlockingHit)
-	{
-		RootComponent->AddLocalOffset(FHitResultPhys.Normal*FHitResultPhys.PenetrationDepth);
-	}
-}
-
-void AVirtualRealityPawn::HandleMovementInput(float Value, FVector Direction)
-{
-	if (NavigationMode == EVRNavigationModes::nav_mode_walk)
-	{
-		VRWalkingMode(Value, Direction);
-	}
-	else if (NavigationMode == EVRNavigationModes::nav_mode_fly)
-	{
-		VRFlyingMode(Value, Direction);
-	}
-}
-
-void AVirtualRealityPawn::VRWalkingMode(float Value, FVector Direction)
-{
-	Direction.Z = 0.0f;//walking
-	FVector End = (Direction * GetFloatingPawnMovement()->GetMaxSpeed());
-	FHitResult FHitResultVR;
-	CapsuleColliderComponent->AddWorldOffset(End* DeltaTime*Value, true, &FHitResultVR);
-
-	if (FVector::Distance(FHitResultVR.Location, CapsuleColliderComponent->GetComponentLocation()) > CapsuleColliderComponent->GetScaledCapsuleRadius())
-	{
-		AddMovementInput(Direction, Value);
-	}
-}
-
-void AVirtualRealityPawn::VRFlyingMode(float Value, FVector Direction)
-{
-	AddMovementInput(Direction, Value);
-}
-
-void AVirtualRealityPawn::MoveByGravityOrStepUp(float DeltaSeconds)
-{
-	FVector StartLineTraceUnderCollider = CapsuleColliderComponent->GetComponentLocation();
-	StartLineTraceUnderCollider.Z -= CapsuleColliderComponent->GetScaledCapsuleHalfHeight();
-	FHitResult HitDetailsMultiLineTrace = CreateMultiLineTrace(FVector(0, 0, -1), StartLineTraceUnderCollider, CapsuleColliderComponent->GetScaledCapsuleRadius() / 4.0f, false);
-	float DiffernceDistance = abs(MaxStepHeight - HitDetailsMultiLineTrace.Distance);
-	//Going up
-	if ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance < MaxStepHeight))
-	{
-		ShiftVertically(DiffernceDistance, UpSteppingAcceleration, DeltaSeconds, 1);
-	}
-	//Falling, Gravity, Going down
-	else if ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance > MaxStepHeight) || (HitDetailsMultiLineTrace.Actor == nullptr && HitDetailsMultiLineTrace.Distance != -1.0f))
-	{
-		ShiftVertically(DiffernceDistance, GravityAcceleration, DeltaSeconds, -1);
-	}
-}
-
-void AVirtualRealityPawn::ShiftVertically(float DiffernceDistance, float Acceleration, float DeltaSeconds, int Direction)
-{
-	VerticalSpeed += Acceleration * DeltaSeconds;
-	if (VerticalSpeed*DeltaSeconds < DiffernceDistance)
-	{
-		RootComponent->AddLocalOffset(FVector(0.f, 0.f, Direction * VerticalSpeed * DeltaSeconds));
-	}
-	else
-	{
-		RootComponent->AddLocalOffset(FVector(0.f, 0.f, Direction * DiffernceDistance));
-		VerticalSpeed = 0;
-	}
+	return VRMovement;
 }
 
 void AVirtualRealityPawn::InitRoomMountedComponentReferences()
@@ -582,56 +455,7 @@ void AVirtualRealityPawn::InitRoomMountedComponentReferences()
 	}
 }
 
-
-FHitResult AVirtualRealityPawn::CreateLineTrace(FVector Direction, const FVector Start, bool Visibility)
-{
-	//Re-initialize hit info
-	FHitResult HitDetails = FHitResult(ForceInit);
-
-	FVector End = ((Direction * 1000.f) + Start);
-	// additional trace parameters
-	FCollisionQueryParams TraceParams(FName(TEXT("InteractTrace")), true, NULL);
-	TraceParams.bTraceComplex = true; //to use complex collision on whatever we interact with to provide better precision.
-	TraceParams.bReturnPhysicalMaterial = true; //to provide details about the physical material, if one exists on the thing we hit, to come back in our hit result.
-
-	if (Visibility)
-		DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 1, 0, 1);
-
-	if (GetWorld()->LineTraceSingleByChannel(HitDetails, Start, End, ECC_Visibility, TraceParams))
-	{
-		if (HitDetails.bBlockingHit)
-		{
-		}
-	}
-	return HitDetails;
-}
-
-FHitResult AVirtualRealityPawn::CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility)
+void AVirtualRealityPawn::SetNavigationMode(EVRNavigationModes Mode)
 {
-	TArray<FVector> StartVectors;
-	TArray<FHitResult> OutHits;
-	FHitResult HitDetailsMultiLineTrace;
-	HitDetailsMultiLineTrace.Distance = -1.0f;//(Distance=-1) not existing, but to know if this Variable not Initialized(when all Traces not compatible)
-
-	StartVectors.Add(Start); //LineTraceCenter
-	StartVectors.Add(Start + FVector(0, -Radius, 0)); //LineTraceLeft
-	StartVectors.Add(Start + FVector(0, +Radius, 0)); //LineTraceRight
-	StartVectors.Add(Start + FVector(+Radius, 0, 0)); //LineTraceFront
-	StartVectors.Add(Start + FVector(-Radius, 0, 0)); //LineTraceBehind
-
-	bool IsBlockingHitAndSameActor = true;
-	bool IsAllNothingHiting = true;
-	// loop through TArray
-	for (FVector& Vector : StartVectors)
-	{
-		FHitResult OutHit = CreateLineTrace(Direction, Vector, Visibility);
-		OutHits.Add(OutHit);
-		IsBlockingHitAndSameActor &= (OutHit.Actor == OutHits[0].Actor); //If all Hiting the same Object, then you are (going up/down) or (walking)
-		IsAllNothingHiting &= (OutHit.Actor == nullptr); //If all Hiting nothing, then you are falling
-	}
-
-	if (IsBlockingHitAndSameActor || IsAllNothingHiting)
-		HitDetailsMultiLineTrace = OutHits[0];
-
-	return HitDetailsMultiLineTrace;
+	VRMovement->NavigationMode = Mode;
 }
diff --git a/Source/DisplayClusterExtensions/Public/VRPawnMovement.h b/Source/DisplayClusterExtensions/Public/VRPawnMovement.h
new file mode 100644
index 0000000000000000000000000000000000000000..20a6f4b6707cd7a8ec60116f4fb0386d9fc017a4
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Public/VRPawnMovement.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/FloatingPawnMovement.h"
+#include "Components/CapsuleComponent.h"
+#include "Camera/CameraComponent.h"
+
+#include "VRPawnMovement.generated.h"
+
+/*
+ * This Movement component is needed since in VR not only the pawn itself (UpdatedComponent) is moved but also the
+ * user herself can walk and thereby move the CameraComponent, which can also lead to collisions or e.g. going up steps 
+ *
+ * The four modes are:
+ * None: No controller movement is applied and no corrections regarding steps or collisions with walls are done
+ * Ghost: The same as above but now the Inputs can be used for unconstrained flying (also through objects)
+ * Fly: The user can fly but not through walls etc. When the user walks against a wall the scene is moved with her to avoid walking through
+ *      The user can also walk up stairs with a maximum step height of MaxStepHeight
+ * Walk: Additionally to Fly now gravity keeps the user on the floor
+ */
+
+UENUM(BlueprintType)
+enum class EVRNavigationModes : uint8
+{
+	None UMETA(DisplayName = "None (no controller movement)"),
+	Ghost UMETA(DisplayName = "Ghost (flying, also through walls)"),
+	Fly UMETA(DisplayName = "Fly (prohibiting collisions)"),
+	Walk UMETA(DisplayName = "Walk (gravity and prohibiting collisions)")
+};
+
+UCLASS()
+class DISPLAYCLUSTEREXTENSIONS_API UVRPawnMovement : public UFloatingPawnMovement
+{
+	GENERATED_UCLASS_BODY()
+
+public:
+
+	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType,
+	                           FActorComponentTickFunction* ThisTickFunction) override;
+
+	void SetCameraComponent(UCameraComponent* NewCameraComponent);
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
+	EVRNavigationModes NavigationMode = EVRNavigationModes::Walk;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
+	float MaxStepHeight = 40.0f;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
+	float GravityAcceleration = 981.0f;
+	
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
+	float UpSteppingAcceleration = 500.0f;
+
+private:
+	FHitResult CreateLineTrace(FVector Direction, const FVector Start, bool Visibility);
+	FHitResult CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility);
+	void SetCapsuleColliderToUserSize();
+	void CheckForPhysWalkingCollision();
+	bool CheckForVirtualMovCollision(FVector PositionChange, float DeltaTime);
+	void MoveByGravityOrStepUp(float DeltaSeconds);
+	void ShiftVertically(float DiffernceDistance, float VerticalAcceleration, float DeltaSeconds, int Direction);
+	//(direction = Down = -1), (direction = Up = 1)
+
+	UPROPERTY() UCapsuleComponent* CapsuleColliderComponent = nullptr;
+	UPROPERTY() UCameraComponent* CameraComponent = nullptr;
+
+	float VerticalSpeed = 0.0f;
+	FVector LastCameraPosition;
+};
diff --git a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
index 0570e8aa290c2325b927bca9d036108b0df95741..b02f183320a14b199290438a8f3d4a21f50389ee 100644
--- a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
+++ b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
@@ -6,20 +6,13 @@
 #include "DisplayClusterPawn.h"
 #include "DisplayClusterSceneComponent.h"
 #include "Components/CapsuleComponent.h"
-#include "GameFramework/FloatingPawnMovement.h"
-#include "GameFramework/PawnMovementComponent.h"
+#include "VRPawnMovement.h"
 #include "GameFramework/RotatingMovementComponent.h"
 
 #include "MotionControllerComponent.h"
 #include "VirtualRealityPawn.generated.h"
 
-UENUM(BlueprintType)
-enum class EVRNavigationModes : uint8
-{
-	nav_mode_none UMETA(DisplayName = "Navigation Mode None"),
-	nav_mode_walk UMETA(DisplayName = "Navigation Mode Walk"),
-	nav_mode_fly UMETA(DisplayName = "Navigation Mode Fly")
-};
+
 
 UENUM(BlueprintType)
 enum class EAttachementType : uint8
@@ -44,7 +37,6 @@ public:
 
 	UFUNCTION(Category = "Pawn") float GetBaseTurnRate() const;
 	UFUNCTION(Category = "Pawn") void SetBaseTurnRate(float Value);
-	UFUNCTION(Category = "Pawn") UFloatingPawnMovement* GetFloatingPawnMovement();
 	UFUNCTION(Category = "Pawn") URotatingMovementComponent* GetRotatingMovementComponent();
 
 	//Bunch of Getter Functions for components to avoid users having to know the names
@@ -63,6 +55,8 @@ public:
 
 	UFUNCTION(Category = "Pawn") USceneComponent* GetTrackingOriginComponent();
 
+	UFUNCTION(Category = "Pawn") void SetNavigationMode(EVRNavigationModes Mode);
+
 private:
 	UFUNCTION(Category = "Pawn") USceneComponent* GetCaveCenterComponent();
 	UFUNCTION(Category = "Pawn") USceneComponent* GetShutterGlassesComponent();
@@ -70,9 +64,6 @@ private:
 	UFUNCTION(Category = "Pawn") void HandlePhysicsAndAttachActor(AActor* HitActor);   
 
 public:
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") EVRNavigationModes NavigationMode = EVRNavigationModes::nav_mode_fly;
-
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") float MaxStepHeight = 40.0f;
 	//Execute specified console command on all nDisplayCluster Nodes
 	UFUNCTION(Exec, BlueprintCallable, Category = "DisplayCluster") static void ClusterExecute(const FString& Command);
 private:
@@ -87,7 +78,7 @@ protected:
 	virtual UPawnMovementComponent* GetMovementComponent() const override;
 
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn", meta = (AllowPrivateAccess = "true")) float BaseTurnRate = 45.0f;
-	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UFloatingPawnMovement* Movement = nullptr;
+	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UVRPawnMovement* VRMovement = nullptr;
 	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) URotatingMovementComponent* RotatingMovement = nullptr;
 
 	// Use only when handling cross-device (PC, HMD, CAVE/ROLV) compatibility manually. CAVE/ROLV flystick.
@@ -131,22 +122,6 @@ protected:
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") EAttachementType AttachRightHandInCAVE = EAttachementType::AT_FLYSTICK;
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") EAttachementType AttachLeftHandInCAVE = EAttachementType::AT_NONE;
 
-	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UCapsuleComponent* CapsuleColliderComponent = nullptr;
 private:
-	float DeltaTime = 0.0f;
-	float VerticalSpeed = 0.0f;
-	UPROPERTY() float GravityAcceleration = 981.0f;
-	UPROPERTY() float UpSteppingAcceleration = 500.0f;
-	FVector LastCameraPosition;
-
-	FHitResult CreateLineTrace(FVector Direction, const FVector Start, bool Visibility);
-	FHitResult CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility);
-	void SetCapsuleColliderCharacterSizeVR();
-	void CheckForPhysWalkingCollision();
-	void HandleMovementInput(float Value, FVector Direction);
-	void VRWalkingMode(float Value, FVector Direction);
-	void VRFlyingMode(float Value, FVector Direction);
-	void MoveByGravityOrStepUp(float DeltaSeconds);
-	void ShiftVertically(float DiffernceDistance, float Acceleration, float DeltaSeconds, int Direction);//(direction = Down = -1), (direction = Up = 1)
 	void InitRoomMountedComponentReferences();
 };