diff --git a/Content/BP_VirtualRealityPawn.uasset b/Content/BP_VirtualRealityPawn.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..de6a205060c6131ae6724b3246de1ef437f2b6ec
Binary files /dev/null and b/Content/BP_VirtualRealityPawn.uasset differ
diff --git a/Content/Components/Movement/ContinuousMovementComponent.uasset b/Content/Components/Movement/ContinuousMovementComponent.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..9e004acae980e0517082dc4b43a66d1606b46956
Binary files /dev/null and b/Content/Components/Movement/ContinuousMovementComponent.uasset differ
diff --git a/Content/Components/Movement/IMC_MovementLeftHand.uasset b/Content/Components/Movement/IMC_MovementLeftHand.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..6762960518fa317c48d0effb0e173a6f09f2e763
Binary files /dev/null and b/Content/Components/Movement/IMC_MovementLeftHand.uasset differ
diff --git a/Content/Components/Movement/IMC_MovementRightHand.uasset b/Content/Components/Movement/IMC_MovementRightHand.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..c848335f083150cd0393bb64dac0495a9aaa949e
Binary files /dev/null and b/Content/Components/Movement/IMC_MovementRightHand.uasset differ
diff --git a/Content/Input/IMC_RWTH_Base.uasset b/Content/Input/IMC_RWTH_Base.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..9f2e4864bdd16cd30a452191d9ac298cd579e460
Binary files /dev/null and b/Content/Input/IMC_RWTH_Base.uasset differ
diff --git a/Content/Input/InputActions/IA_DesktopRotation.uasset b/Content/Input/InputActions/IA_DesktopRotation.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..b1abe311863a7a6f076c4e2c2bd2d39dd306386d
Binary files /dev/null and b/Content/Input/InputActions/IA_DesktopRotation.uasset differ
diff --git a/Content/Input/InputActions/IA_Fire.uasset b/Content/Input/InputActions/IA_Fire.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..aefe36aa0a33175490fbaf9b0b3a07ec2944a358
Binary files /dev/null and b/Content/Input/InputActions/IA_Fire.uasset differ
diff --git a/Content/Input/InputActions/IA_Grab.uasset b/Content/Input/InputActions/IA_Grab.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..d35442dff6c80662339e90fd71f0d084a42e7be6
Binary files /dev/null and b/Content/Input/InputActions/IA_Grab.uasset differ
diff --git a/Content/Input/InputActions/IA_LookUpRate.uasset b/Content/Input/InputActions/IA_LookUpRate.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..852c1b411c071ef591c0b9108d9b4d9c856c6c09
Binary files /dev/null and b/Content/Input/InputActions/IA_LookUpRate.uasset differ
diff --git a/Content/Input/InputActions/IA_Move.uasset b/Content/Input/InputActions/IA_Move.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..2423ae65f120424dbd02c40d85d242ccd9832e18
Binary files /dev/null and b/Content/Input/InputActions/IA_Move.uasset differ
diff --git a/Content/Input/InputActions/IA_MoveForward.uasset b/Content/Input/InputActions/IA_MoveForward.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..1ada444b1705599dd9a36f797c71fba69c0524df
Binary files /dev/null and b/Content/Input/InputActions/IA_MoveForward.uasset differ
diff --git a/Content/Input/InputActions/IA_MoveRight.uasset b/Content/Input/InputActions/IA_MoveRight.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..05aa4aff2ace49f2aaf67558affa2877d43a1f69
Binary files /dev/null and b/Content/Input/InputActions/IA_MoveRight.uasset differ
diff --git a/Content/Input/InputActions/IA_MoveUp.uasset b/Content/Input/InputActions/IA_MoveUp.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..6f38343e58e4bddd4b43fd94258fa9c4929a4765
Binary files /dev/null and b/Content/Input/InputActions/IA_MoveUp.uasset differ
diff --git a/Content/Input/InputActions/IA_Turn.uasset b/Content/Input/InputActions/IA_Turn.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..480126b060800e5a122f0f0f2f6c6bdefc7a7469
Binary files /dev/null and b/Content/Input/InputActions/IA_Turn.uasset differ
diff --git a/Content/Input/InputActions/IA_TurnRate.uasset b/Content/Input/InputActions/IA_TurnRate.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..d5e0153f09345b265bacba76e67eafc4ee5e5775
Binary files /dev/null and b/Content/Input/InputActions/IA_TurnRate.uasset differ
diff --git a/Content/Input/RWTHVRPawnInputConfig.uasset b/Content/Input/RWTHVRPawnInputConfig.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..ad08269ac07bbd98e93ddee7572a9262a0a32c63
Binary files /dev/null and b/Content/Input/RWTHVRPawnInputConfig.uasset differ
diff --git a/Content/RWTHVRGameMode.uasset b/Content/RWTHVRGameMode.uasset
index ea7345658120735d8871d7bf4d19a7abddd7c4d5..c3904e554dfa66dd200f0e61e318efac52b09a3a 100644
Binary files a/Content/RWTHVRGameMode.uasset and b/Content/RWTHVRGameMode.uasset differ
diff --git a/Content/TestMap.umap b/Content/TestMap.umap
new file mode 100644
index 0000000000000000000000000000000000000000..7e7113328a4bc24bfdcbdc7f61a83af3a8cc305f
Binary files /dev/null and b/Content/TestMap.umap differ
diff --git a/Source/RWTHVRToolkit/Private/Pawn/ContinuousMovementComponent.cpp b/Source/RWTHVRToolkit/Private/Pawn/ContinuousMovementComponent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c931c7c281a5050d4a11ea5e9e22621548fa5ac2
--- /dev/null
+++ b/Source/RWTHVRToolkit/Private/Pawn/ContinuousMovementComponent.cpp
@@ -0,0 +1,393 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Pawn/ContinuousMovementComponent.h"
+
+#include "DrawDebugHelpers.h"
+#include "EnhancedInputComponent.h"
+#include "EnhancedInputSubsystems.h"
+#include "Camera/CameraComponent.h"
+#include "Components/CapsuleComponent.h"
+#include "Engine/LocalPlayer.h"
+#include "GameFramework/PlayerController.h"
+#include "Pawn/VRPawnInputConfig.h"
+#include "Utility/VirtualRealityUtilities.h"
+
+UContinuousMovementComponent::UContinuousMovementComponent(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
+{
+	CapsuleColliderComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleCollider"));
+	CapsuleColliderComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
+	CapsuleColliderComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
+	CapsuleColliderComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
+	CapsuleColliderComponent->SetCapsuleSize(CapsuleRadius, 80.0f);
+
+	VRPawn = Cast<AVirtualRealityPawn>(GetOwner());
+}
+
+void UContinuousMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction){
+
+	SetCapsuleColliderToUserSize();
+
+	FVector PositionChange = GetPendingInputVector();
+
+	if (NavigationMode == EVRNavigationModes::NAV_WALK)
+	{
+		PositionChange.Z = 0.0f;
+		ConsumeInputVector();
+		AddInputVector(PositionChange);
+	}
+	
+	if(NavigationMode == EVRNavigationModes::NAV_FLY || NavigationMode == EVRNavigationModes::NAV_WALK)
+	{
+		MoveByGravityOrStepUp(DeltaTime);
+		CheckForPhysWalkingCollision();
+
+		if(CheckForVirtualMovCollision(PositionChange, DeltaTime))
+		{
+			ConsumeInputVector();
+		}
+	}
+
+	if(NavigationMode == EVRNavigationModes::NAV_NONE)
+	{
+		ConsumeInputVector();
+	}
+
+	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
+	
+	LastHeadPosition = HeadComponent->GetComponentLocation();
+}
+
+void UContinuousMovementComponent::BeginPlay()
+{
+	Super::BeginPlay();
+	
+	SetUpdatedComponent(VRPawn->GetRootComponent());
+	SetHeadComponent(VRPawn->CapsuleRotationFix);
+
+	SetupInputActions();
+	
+}
+
+bool UContinuousMovementComponent::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 UContinuousMovementComponent::SetHeadComponent(USceneComponent* NewHeadComponent)
+{
+	HeadComponent = 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));
+}
+
+void UContinuousMovementComponent::SetCapsuleColliderToUserSize()
+{
+	float CharachterSize = abs(UpdatedComponent->GetComponentLocation().Z - HeadComponent->GetComponentLocation().Z);
+
+	if (CharachterSize > MaxStepHeight)
+	{
+		float ColliderHeight = CharachterSize - MaxStepHeight;
+		float ColliderHalfHeight = ColliderHeight / 2.0f;
+		if (ColliderHalfHeight <= CapsuleRadius)
+		{//Make the collider to a Sphere
+			CapsuleColliderComponent->SetCapsuleSize(ColliderHalfHeight, ColliderHalfHeight);
+		}
+		else
+		{//Make the collider to a Capsule
+			CapsuleColliderComponent->SetCapsuleSize(CapsuleRadius, ColliderHalfHeight);
+		}
+
+		CapsuleColliderComponent->SetWorldLocation(HeadComponent->GetComponentLocation());
+		CapsuleColliderComponent->AddWorldOffset(FVector(0, 0, -ColliderHalfHeight));
+		CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1));
+	}
+	else
+	{
+		CapsuleColliderComponent->SetWorldLocation(HeadComponent->GetComponentLocation());
+		CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1));
+	}
+}
+
+void UContinuousMovementComponent::CheckForPhysWalkingCollision()
+{
+	FVector CurrentHeadPosition = HeadComponent->GetComponentLocation();
+	FVector Direction = CurrentHeadPosition - LastHeadPosition;
+	FHitResult FHitResultPhys;
+	CapsuleColliderComponent->AddWorldOffset(Direction, true, &FHitResultPhys);
+
+	if (FHitResultPhys.bBlockingHit)
+	{
+		UpdatedComponent->AddLocalOffset(FHitResultPhys.Normal*FHitResultPhys.PenetrationDepth);
+	}
+}
+
+void UContinuousMovementComponent::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::NAV_WALK && ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance > MaxStepHeight) || (HitDetailsMultiLineTrace.GetActor() == nullptr && HitDetailsMultiLineTrace.Distance != -1.0f)))
+	{
+		ShiftVertically(DistanceDifference, GravityAcceleration, DeltaSeconds, -1);
+	}
+}
+
+void UContinuousMovementComponent::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;
+	}
+}
+
+void UContinuousMovementComponent::SetupInputActions()
+{
+	// simple way of changing the handedness
+	if(bMoveWithRightHand)
+	{
+		MovementHand = VRPawn->RightHand;
+		RotationHand = VRPawn->LeftHand;
+		IMCMovement = IMCMovementRight;
+	} else
+	{
+		MovementHand = VRPawn->LeftHand;
+		RotationHand = VRPawn->RightHand;
+		IMCMovement = IMCMovementLeft;
+	}
+	
+	const APlayerController* PlayerController = Cast<APlayerController>(VRPawn->GetController());
+	UEnhancedInputLocalPlayerSubsystem* InputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
+	if(!InputSubsystem)
+	{
+		UE_LOG(LogTemp,Error,TEXT("InputSubsystem IS NOT VALID"));
+		return;
+	}
+	
+	InputSubsystem->ClearAllMappings();
+
+	// add Input Mapping context 
+	InputSubsystem->AddMappingContext(IMCMovement,0);
+	
+	UEnhancedInputComponent* EI = Cast<UEnhancedInputComponent>(VRPawn->InputComponent);
+	if(!EI)
+	{
+		UE_LOG(LogTemp,Error,TEXT("Cannot cast Input Component to Enhanced Inpu Component in VRPawnMovement"));
+		return;
+	}
+	
+	// walking
+	EI->BindAction(InputActions->Move, ETriggerEvent::Triggered, this, &UContinuousMovementComponent::OnBeginMove);
+
+	// turning
+	if(bSnapTurn && !UVirtualRealityUtilities::IsDesktopMode())
+	{
+		EI->BindAction(InputActions->Turn, ETriggerEvent::Started, this, &UContinuousMovementComponent::OnBeginSnapTurn);
+	} else
+	{
+		EI->BindAction(InputActions->Turn, ETriggerEvent::Triggered, this, &UContinuousMovementComponent::OnBeginTurn);
+	}
+	
+	// bind functions for desktop rotations only on holding down right mouse
+	if (UVirtualRealityUtilities::IsDesktopMode())
+	{
+		APlayerController* PC = Cast<APlayerController>(VRPawn->GetController());
+		if (PC)
+		{
+			PC->bShowMouseCursor = true; 
+			PC->bEnableClickEvents = true; 
+			PC->bEnableMouseOverEvents = true;
+		}
+		EI->BindAction(InputActions->DesktopRotation, ETriggerEvent::Started, this, &UContinuousMovementComponent::StartDesktopRotation);
+		EI->BindAction(InputActions->DesktopRotation, ETriggerEvent::Completed, this, &UContinuousMovementComponent::EndDesktopRotation);
+	}
+}
+
+
+
+FHitResult UContinuousMovementComponent::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 UContinuousMovementComponent::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.GetActor() == OutHits[0].GetActor()); //If all Hiting the same Object, then you are (going up/down) or (walking)
+		IsAllNothingHiting &= (OutHit.GetActor() == nullptr); //If all Hiting nothing, then you are falling
+	}
+
+	if (IsBlockingHitAndSameActor || IsAllNothingHiting)
+		HitDetailsMultiLineTrace = OutHits[0];
+
+	return HitDetailsMultiLineTrace;
+}
+
+void UContinuousMovementComponent::StartDesktopRotation()
+{
+	bApplyDesktopRotation = true;
+}
+
+void UContinuousMovementComponent::EndDesktopRotation()
+{
+	bApplyDesktopRotation = false;
+}
+
+void UContinuousMovementComponent::OnBeginMove(const FInputActionValue& Value)
+{
+	const FVector ForwardDir = UVirtualRealityUtilities::IsDesktopMode() ? VRPawn->Head->GetForwardVector() : MovementHand->GetForwardVector();
+	const FVector RightDir = UVirtualRealityUtilities::IsDesktopMode() ? VRPawn->Head->GetRightVector() : MovementHand->GetRightVector();
+	
+	if (VRPawn->Controller != nullptr)
+	{
+		const FVector2D MoveValue = Value.Get<FVector2D>();
+		const FRotator MovementRotation(0, VRPawn->Controller->GetControlRotation().Yaw, 0);
+ 
+		// Forward/Backward direction
+		if (MoveValue.X != 0.f)
+		{
+			VRPawn->AddMovementInput(ForwardDir, MoveValue.X);
+		}
+ 
+		// Right/Left direction
+		if (MoveValue.Y != 0.f)
+		{
+			VRPawn->AddMovementInput(RightDir, MoveValue.Y);
+		}
+	}
+}
+
+void UContinuousMovementComponent::OnBeginTurn(const FInputActionValue& Value)
+{
+	if(UVirtualRealityUtilities::IsDesktopMode() && !bApplyDesktopRotation) return;
+	if (VRPawn->Controller != nullptr)
+	{
+		const FVector2D TurnValue = Value.Get<FVector2D>();
+ 
+		if (TurnValue.X != 0.f)
+		{
+			VRPawn->AddControllerYawInput(TurnRateFactor * TurnValue.X);
+			if (UVirtualRealityUtilities::IsDesktopMode())
+			{
+				UpdateRightHandForDesktopInteraction();
+			}
+		}
+ 
+		if (TurnValue.Y != 0.f)
+		{
+			if (UVirtualRealityUtilities::IsDesktopMode() && bApplyDesktopRotation)
+			{
+				VRPawn->AddControllerPitchInput(TurnRateFactor * TurnValue.Y);
+				SetCameraOffset();
+			}
+		}
+	}
+}
+
+void UContinuousMovementComponent::OnBeginSnapTurn(const FInputActionValue& Value)
+{
+	const FVector2D TurnValue = Value.Get<FVector2D>();
+ 
+	if (TurnValue.X != 0.f)
+	{
+		VRPawn->AddControllerYawInput(SnapTurnAngle);
+	}
+}
+
+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>(GetController());
+	if (PC)
+	{
+		FVector MouseLocation, MouseDirection;
+		PC->DeprojectMousePositionToWorld(MouseLocation, MouseDirection);
+		FRotator HandOrientation = MouseDirection.ToOrientationRotator();
+		VRPawn->RightHand->SetWorldRotation(HandOrientation);
+	}
+}
+
+/*void UContinuousMovementComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
+{
+	Super::PostEditChangeProperty(PropertyChangedEvent);
+	
+	FName PropertyName = (PropertyChangedEvent.Property != NULL) ? PropertyChangedEvent.Property->GetFName() : NAME_None;
+
+	if (PropertyName == GET_MEMBER_NAME_CHECKED(AVirtualRealityPawn, bMoveWithRightHand) ||
+		PropertyName == GET_MEMBER_NAME_CHECKED(AVirtualRealityPawn, bSnapTurn))
+	{
+		// if we want to change input bindings, we need to setup the player input again to load a different mapping context,
+		// or assign a different function to an input action.
+		// This is automatically done by restarting the pawn(calling SetupPlayerInputComponent() directly results in crashes)
+		// only do this in the editor
+		#if WITH_EDITOR
+			VRPawn->Restart();
+#endif
+	}
+}*/
\ No newline at end of file
diff --git a/Source/RWTHVRToolkit/Private/Pawn/VRPawnInputConfig.cpp b/Source/RWTHVRToolkit/Private/Pawn/VRPawnInputConfig.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5444bd50ff7178c8a118f670e8eeaaf3b7fa4b41
--- /dev/null
+++ b/Source/RWTHVRToolkit/Private/Pawn/VRPawnInputConfig.cpp
@@ -0,0 +1,5 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Pawn/VRPawnInputConfig.h"
+
diff --git a/Source/RWTHVRToolkit/Private/Pawn/VRPawnMovement.cpp b/Source/RWTHVRToolkit/Private/Pawn/VRPawnMovement.cpp
deleted file mode 100644
index 4b32da4736f6a6e3ea7b9423fac8540926985126..0000000000000000000000000000000000000000
--- a/Source/RWTHVRToolkit/Private/Pawn/VRPawnMovement.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-
-#include "Pawn/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_Overlap);
-	CapsuleColliderComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
-	CapsuleColliderComponent->SetCapsuleSize(CapsuleRadius, 80.0f);
-}
-
-void UVRPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction){
-
-	SetCapsuleColliderToUserSize();
-
-	FVector PositionChange = GetPendingInputVector();
-
-	if (NavigationMode == EVRNavigationModes::NAV_WALK)
-	{
-		PositionChange.Z = 0.0f;
-		ConsumeInputVector();
-		AddInputVector(PositionChange);
-	}
-	
-	if(NavigationMode == EVRNavigationModes::NAV_FLY || NavigationMode == EVRNavigationModes::NAV_WALK)
-	{
-		MoveByGravityOrStepUp(DeltaTime);
-		CheckForPhysWalkingCollision();
-
-		if(CheckForVirtualMovCollision(PositionChange, DeltaTime))
-		{
-			ConsumeInputVector();
-		}
-	}
-
-	if(NavigationMode == EVRNavigationModes::NAV_NONE)
-	{
-		ConsumeInputVector();
-	}
-
-	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
-	
-	LastHeadPosition = HeadComponent->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::SetHeadComponent(USceneComponent* NewHeadComponent)
-{
-	HeadComponent = 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));
-}
-
-void UVRPawnMovement::SetCapsuleColliderToUserSize()
-{
-	float CharachterSize = abs(UpdatedComponent->GetComponentLocation().Z - HeadComponent->GetComponentLocation().Z);
-
-	if (CharachterSize > MaxStepHeight)
-	{
-		float ColliderHeight = CharachterSize - MaxStepHeight;
-		float ColliderHalfHeight = ColliderHeight / 2.0f;
-		if (ColliderHalfHeight <= CapsuleRadius)
-		{//Make the collider to a Sphere
-			CapsuleColliderComponent->SetCapsuleSize(ColliderHalfHeight, ColliderHalfHeight);
-		}
-		else
-		{//Make the collider to a Capsule
-			CapsuleColliderComponent->SetCapsuleSize(CapsuleRadius, ColliderHalfHeight);
-		}
-
-		CapsuleColliderComponent->SetWorldLocation(HeadComponent->GetComponentLocation());
-		CapsuleColliderComponent->AddWorldOffset(FVector(0, 0, -ColliderHalfHeight));
-		CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1));
-	}
-	else
-	{
-		CapsuleColliderComponent->SetWorldLocation(HeadComponent->GetComponentLocation());
-		CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1));
-	}
-}
-
-void UVRPawnMovement::CheckForPhysWalkingCollision()
-{
-	FVector CurrentHeadPosition = HeadComponent->GetComponentLocation();
-	FVector Direction = CurrentHeadPosition - LastHeadPosition;
-	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::NAV_WALK && ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance > MaxStepHeight) || (HitDetailsMultiLineTrace.GetActor() == 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.GetActor() == OutHits[0].GetActor()); //If all Hiting the same Object, then you are (going up/down) or (walking)
-		IsAllNothingHiting &= (OutHit.GetActor() == 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/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp b/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp
index d65ca8ab248d384fd9094b38b0f5cc1936947ccd..3676a7900a0d529223eeb5416d2a9aea6031994c 100644
--- a/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp
+++ b/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp
@@ -2,11 +2,15 @@
 
 #include "Pawn/VirtualRealityPawn.h"
 
-#include "GameFramework/InputSettings.h"
-#include "GameFramework/PlayerInput.h"
+#include "AITypes.h"
+#include "Engine/LocalPlayer.h"
+#include "GameFramework/PlayerController.h"
 #include "Pawn/UniversalTrackedComponent.h"
 #include "Utility/VirtualRealityUtilities.h"
-#include "Pawn/VRPawnMovement.h"
+#include "EnhancedInputComponent.h"
+#include "EnhancedInputSubsystems.h"
+#include "Camera/CameraComponent.h"
+#include "Pawn/VRPawnInputConfig.h"
 
 AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer)
 	: Super(ObjectInitializer)
@@ -15,7 +19,6 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial
 	bUseControllerRotationPitch = true;
 	bUseControllerRotationRoll = true;
 	BaseEyeHeight = 160.0f;
-	
 	AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events.
 
 	SetRootComponent(CreateDefaultSubobject<USceneComponent>(TEXT("Origin")));
@@ -32,14 +35,17 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial
 	CapsuleRotationFix->SetUsingAbsoluteRotation(true);
 	CapsuleRotationFix->SetupAttachment(Head);
 	
-	PawnMovement = CreateDefaultSubobject<UVRPawnMovement>(TEXT("Pawn Movement"));
+	/*PawnMovement = CreateDefaultSubobject<UVRPawnMovement>(TEXT("Pawn Movement"));
 	PawnMovement->SetUpdatedComponent(RootComponent);
-	PawnMovement->SetHeadComponent(CapsuleRotationFix);
+	PawnMovement->SetHeadComponent(CapsuleRotationFix);*/
 	
 	RightHand = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Right Hand"));
 	RightHand->ProxyType = ETrackedComponentType::TCT_RIGHT_HAND;
 	RightHand->AttachementType = EAttachementType::AT_FLYSTICK;
 	RightHand->SetupAttachment(RootComponent);
+
+	auto MCRight = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("MC Right"));
+	MCRight->SetTrackingSource(EControllerHand::Right);
 	
 	LeftHand = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Left Hand"));
 	LeftHand->ProxyType = ETrackedComponentType::TCT_LEFT_HAND;
@@ -48,23 +54,62 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial
 
 	BasicVRInteraction = CreateDefaultSubobject<UBasicVRInteractionComponent>(TEXT("Basic VR Interaction"));
 	BasicVRInteraction->Initialize(RightHand);
+	
 }
 
 void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
 {
-	Super::SetupPlayerInputComponent(PlayerInputComponent);
-	if (!PlayerInputComponent) return;
 	
-	PlayerInputComponent->BindAxis("MoveForward", this, &AVirtualRealityPawn::OnForward);
-	PlayerInputComponent->BindAxis("MoveRight", this, &AVirtualRealityPawn::OnRight);
-	PlayerInputComponent->BindAxis("MoveUp", this, &AVirtualRealityPawn::OnUp);
-	PlayerInputComponent->BindAxis("TurnRate", this, &AVirtualRealityPawn::OnTurnRate);
-	PlayerInputComponent->BindAxis("LookUpRate", this, &AVirtualRealityPawn::OnLookUpRate);
+	// simple way of changing the handedness
+	/*if(bMoveWithRightHand)
+	{
+		MovementHand = RightHand;
+		RotationHand = LeftHand;
+		IMCMovement = IMCMovementRight;
+	} else
+	{
+		MovementHand = LeftHand;
+		RotationHand = RightHand;
+		IMCMovement = IMCMovementLeft;
+	}*/
+	
+	const APlayerController* PlayerController = Cast<APlayerController>(GetController());
+	UEnhancedInputLocalPlayerSubsystem* InputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
+	if(!InputSubsystem)
+	{
+		UE_LOG(LogTemp,Error,TEXT("InputSubsystem IS NOT VALID"));
+	}
+	
+	InputSubsystem->ClearAllMappings();
 
-	// function bindings for grabbing and releasing
-	PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AVirtualRealityPawn::OnBeginFire);
-	PlayerInputComponent->BindAction("Fire", IE_Released, this, &AVirtualRealityPawn::OnEndFire);
+	// add Input Mapping context 
+	//InputSubsystem->AddMappingContext(IMCMovement,0);
+	InputSubsystem->AddMappingContext(IMCBase,0);
+	
+	UEnhancedInputComponent* EI = Cast<UEnhancedInputComponent>(PlayerInputComponent);
+	
+	// old function bindings for grabbing and releasing
+	EI->BindAction(InputActions->Fire, ETriggerEvent::Started, this, &AVirtualRealityPawn::OnBeginFire);
+	EI->BindAction(InputActions->Fire, ETriggerEvent::Completed, this, &AVirtualRealityPawn::OnEndFire);
+
+	// grabbing
+	EI->BindAction(InputActions->Grab, ETriggerEvent::Started, this, &AVirtualRealityPawn::OnBeginGrab);
+	EI->BindAction(InputActions->Grab, ETriggerEvent::Completed, this, &AVirtualRealityPawn::OnEndGrab);
+
+	/*// walking
+	EI->BindAction(InputActions->Move, ETriggerEvent::Triggered, this, &AVirtualRealityPawn::OnBeginMove);*/
 
+	/*
+	// turning
+	if(bSnapTurn && !UVirtualRealityUtilities::IsDesktopMode())
+	{
+		EI->BindAction(InputActions->Turn, ETriggerEvent::Started, this, &AVirtualRealityPawn::OnBeginSnapTurn);
+	} else
+	{
+		EI->BindAction(InputActions->Turn, ETriggerEvent::Triggered, this, &AVirtualRealityPawn::OnBeginTurn);
+	}
+	*/
+	
 	// bind functions for desktop rotations only on holding down right mouse
 	if (UVirtualRealityUtilities::IsDesktopMode())
 	{
@@ -75,12 +120,12 @@ void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInput
 			PC->bEnableClickEvents = true; 
 			PC->bEnableMouseOverEvents = true;
 		}
-		PlayerInputComponent->BindAction("EnableDesktopRotation", IE_Pressed, this, &AVirtualRealityPawn::StartDesktopRotation);
-		PlayerInputComponent->BindAction("EnableDesktopRotation", IE_Released, this, &AVirtualRealityPawn::EndDesktopRotation);
+		/*EI->BindAction(InputActions->DesktopRotation, ETriggerEvent::Started, this, &AVirtualRealityPawn::StartDesktopRotation);
+		EI->BindAction(InputActions->DesktopRotation, ETriggerEvent::Completed, this, &AVirtualRealityPawn::EndDesktopRotation);*/
 	}
 }
 
-void AVirtualRealityPawn::StartDesktopRotation()
+/*void AVirtualRealityPawn::StartDesktopRotation()
 {
 	bApplyDesktopRotation = true;
 }
@@ -88,9 +133,9 @@ void AVirtualRealityPawn::StartDesktopRotation()
 void AVirtualRealityPawn::EndDesktopRotation()
 {
 	bApplyDesktopRotation = false;
-}
+}*/
 
-void AVirtualRealityPawn::SetCameraOffset() const
+/*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
@@ -98,9 +143,9 @@ void AVirtualRealityPawn::SetCameraOffset() const
 	FRotator Rotation;
 	GetActorEyesViewPoint(Location, Rotation);
 	CameraComponent->SetWorldLocationAndRotation(Location, Rotation);
-}
+}*/
 
-void AVirtualRealityPawn::UpdateRightHandForDesktopInteraction()
+/*void AVirtualRealityPawn::UpdateRightHandForDesktopInteraction()
 {
 	APlayerController* PC = Cast<APlayerController>(GetController());
 	if (PC)
@@ -110,76 +155,126 @@ void AVirtualRealityPawn::UpdateRightHandForDesktopInteraction()
 		FRotator HandOrientation = MouseDirection.ToOrientationRotator();
 		RightHand->SetWorldRotation(HandOrientation);
 	}
-}
+}*/
 
-void AVirtualRealityPawn::OnForward_Implementation(float Value)
+/*void AVirtualRealityPawn::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
 {
-	//the right hand is rotated on desktop to follow the cursor so it's forward is also changing with cursor position
-	if (RightHand && !UVirtualRealityUtilities::IsDesktopMode())
-	{
-		AddMovementInput(RightHand->GetForwardVector(), Value);
-	}
-	else if (Head)
+	Super::PostEditChangeProperty(PropertyChangedEvent);
+	
+	FName PropertyName = (PropertyChangedEvent.Property != NULL) ? PropertyChangedEvent.Property->GetFName() : NAME_None;
+
+	if (PropertyName == GET_MEMBER_NAME_CHECKED(AVirtualRealityPawn, bMoveWithRightHand) ||
+		PropertyName == GET_MEMBER_NAME_CHECKED(AVirtualRealityPawn, bSnapTurn))
 	{
-		AddMovementInput(Head->GetForwardVector(), Value);
+		// if we want to change input bindings, we need to setup the player input again to load a different mapping context,
+		// or assign a different function to an input action.
+		// This is automatically done by restarting the pawn(calling SetupPlayerInputComponent() directly results in crashes)
+		// only do this in the editor
+		#if WITH_EDITOR
+			Restart();
+		#endif
 	}
-}
+}*/
+
 
-void AVirtualRealityPawn::OnRight_Implementation(float Value)
+void AVirtualRealityPawn::OnUp(const FInputActionValue& Value)
 {
+	const float MoveValue =  Value.Get<FVector2D>().X;
+	UE_LOG(LogTemp,Warning,TEXT("MoveUp: %f"),MoveValue);
 	//the right hand is rotated on desktop to follow the cursor so it's forward is also changing with cursor position
 	if (RightHand && !UVirtualRealityUtilities::IsDesktopMode())
 	{
-		AddMovementInput(RightHand->GetRightVector(), Value);
+		AddMovementInput(RightHand->GetUpVector(), MoveValue);
 	}
 	else if (Head)
 	{
-		AddMovementInput(Head->GetRightVector(), Value);
+		AddMovementInput(Head->GetUpVector(), MoveValue);
 	}
 }
 
-void AVirtualRealityPawn::OnUp_Implementation(float Value)
+// legacy grabbing
+void AVirtualRealityPawn::OnBeginFire(const FInputActionValue& Value)
 {
-	//the right hand is rotated on desktop to follow the cursor so it's forward is also changing with cursor position
-	if (RightHand && !UVirtualRealityUtilities::IsDesktopMode())
-	{
-		AddMovementInput(RightHand->GetUpVector(), Value);
-	}
-	else if (Head)
-	{
-		AddMovementInput(Head->GetUpVector(), Value);
-	}
+	UE_LOG(LogTemp,Warning,TEXT("BeginFire"));
+	BasicVRInteraction->BeginInteraction();
 }
 
-void AVirtualRealityPawn::OnTurnRate_Implementation(float Rate)
+// legacy grabbing
+void AVirtualRealityPawn::OnEndFire(const FInputActionValue& Value)
 {
-	/* Turning the user externally will make them sick */
-	if (UVirtualRealityUtilities::IsDesktopMode() && bApplyDesktopRotation)
+	UE_LOG(LogTemp,Warning,TEXT("EndFire"));
+	BasicVRInteraction->EndInteraction();
+}
+
+void AVirtualRealityPawn::OnBeginGrab(const FInputActionValue& Value)
+{
+	UE_LOG(LogTemp,Warning,TEXT("BeginGrab"));
+}
+
+void AVirtualRealityPawn::OnEndGrab(const FInputActionValue& Value)
+{
+	UE_LOG(LogTemp,Warning,TEXT("EndGrab"));
+}
+
+/*void AVirtualRealityPawn::OnBeginMove(const FInputActionValue& Value)
+{
+	const FVector ForwardDir = UVirtualRealityUtilities::IsDesktopMode() ? Head->GetForwardVector() : MovementHand->GetForwardVector();
+	const FVector RightDir = UVirtualRealityUtilities::IsDesktopMode() ? Head->GetRightVector() : MovementHand->GetRightVector();
+	
+	if (Controller != nullptr)
 	{
-		AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
+		const FVector2D MoveValue = Value.Get<FVector2D>();
+		const FRotator MovementRotation(0, Controller->GetControlRotation().Yaw, 0);
+ 
+		// Forward/Backward direction
+		if (MoveValue.X != 0.f)
+		{
+			AddMovementInput(ForwardDir, MoveValue.X);
+		}
+ 
+		// Right/Left direction
+		if (MoveValue.Y != 0.f)
+		{
+			AddMovementInput(RightDir, MoveValue.Y);
+		}
 	}
-	if (UVirtualRealityUtilities::IsDesktopMode())
+}*/
+
+/*void AVirtualRealityPawn::OnBeginTurn(const FInputActionValue& Value)
+{
+	if(UVirtualRealityUtilities::IsDesktopMode() && !bApplyDesktopRotation) return;
+	if (Controller != nullptr)
 	{
-		UpdateRightHandForDesktopInteraction();
+		const FVector2D TurnValue = Value.Get<FVector2D>();
+ 
+		if (TurnValue.X != 0.f)
+		{
+			AddControllerYawInput(TurnRateFactor * TurnValue.X);
+			if (UVirtualRealityUtilities::IsDesktopMode())
+			{
+				UpdateRightHandForDesktopInteraction();
+			}
+		}
+ 
+		if (TurnValue.Y != 0.f)
+		{
+			if (UVirtualRealityUtilities::IsDesktopMode() && bApplyDesktopRotation)
+			{
+				AddControllerPitchInput(TurnRateFactor * TurnValue.Y);
+				SetCameraOffset();
+			}
+		}
 	}
 }
 
-void AVirtualRealityPawn::OnLookUpRate_Implementation(float Rate)
+void AVirtualRealityPawn::OnBeginSnapTurn(const FInputActionValue& Value)
 {
-	/* Turning the user externally will make them sick */
-	if (UVirtualRealityUtilities::IsDesktopMode() && bApplyDesktopRotation)
+	const FVector2D TurnValue = Value.Get<FVector2D>();
+ 
+	if (TurnValue.X != 0.f)
 	{
-		AddControllerPitchInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
-		SetCameraOffset();
+		AddControllerYawInput(SnapTurnAngle);
 	}
-}
+}*/
 
-void AVirtualRealityPawn::OnBeginFire_Implementation()
-{
-	BasicVRInteraction->BeginInteraction();
-}
 
-void AVirtualRealityPawn::OnEndFire_Implementation()
-{
-	BasicVRInteraction->EndInteraction();
-}
diff --git a/Source/RWTHVRToolkit/Public/Pawn/VRPawnMovement.h b/Source/RWTHVRToolkit/Public/Pawn/ContinuousMovementComponent.h
similarity index 55%
rename from Source/RWTHVRToolkit/Public/Pawn/VRPawnMovement.h
rename to Source/RWTHVRToolkit/Public/Pawn/ContinuousMovementComponent.h
index 298799e58c5a0e3e5b9d03649ae3b71b94d1c87c..fb335133431678cc9a7e4bd312bc8cc8a23ea959 100644
--- a/Source/RWTHVRToolkit/Public/Pawn/VRPawnMovement.h
+++ b/Source/RWTHVRToolkit/Public/Pawn/ContinuousMovementComponent.h
@@ -1,73 +1,149 @@
-#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
-{
-	NAV_NONE UMETA(DisplayName = "None (no controller movement)"),
-	NAV_GHOST UMETA(DisplayName = "Ghost (flying, also through walls)"),
-	NAV_FLY UMETA(DisplayName = "Fly (prohibiting collisions)"),
-	NAV_WALK UMETA(DisplayName = "Walk (gravity and prohibiting collisions)")
-};
-
-UCLASS()
-class RWTHVRTOOLKIT_API UVRPawnMovement : public UFloatingPawnMovement
-{
-	GENERATED_UCLASS_BODY()
-
-public:
-
-	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType,
-	                           FActorComponentTickFunction* ThisTickFunction) override;
-
-	void SetHeadComponent(USceneComponent* NewHeadComponent);
-
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
-	EVRNavigationModes NavigationMode = EVRNavigationModes::NAV_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;
-
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
-	float CapsuleRadius = 40.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(VisibleAnywhere) UCapsuleComponent* CapsuleColliderComponent = nullptr;
-	UPROPERTY() USceneComponent* HeadComponent = nullptr;
-
-	float VerticalSpeed = 0.0f;
-	FVector LastHeadPosition;
-};
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/FloatingPawnMovement.h"
+#include "Components/CapsuleComponent.h"
+#include "Pawn/VirtualRealityPawn.h"
+
+#include "ContinuousMovementComponent.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
+{
+	NAV_NONE UMETA(DisplayName = "None (no controller movement)"),
+	NAV_GHOST UMETA(DisplayName = "Ghost (flying, also through walls)"),
+	NAV_FLY UMETA(DisplayName = "Fly (prohibiting collisions)"),
+	NAV_WALK UMETA(DisplayName = "Walk (gravity and prohibiting collisions)")
+};
+
+
+/**
+ * 
+ */
+UCLASS(Blueprintable)
+class RWTHVRTOOLKIT_API UContinuousMovementComponent : public UFloatingPawnMovement
+{
+	GENERATED_BODY()
+
+public:
+
+	UContinuousMovementComponent(const FObjectInitializer& ObjectInitializer);
+
+	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType,
+	                           FActorComponentTickFunction* ThisTickFunction) override;
+
+	virtual void BeginPlay() override;
+	
+	void SetHeadComponent(USceneComponent* NewHeadComponent);
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
+	EVRNavigationModes NavigationMode = EVRNavigationModes::NAV_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;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
+	float CapsuleRadius = 40.0f;
+
+
+	/*Movement Input*/
+	UFUNCTION(BlueprintCallable)
+	void OnBeginMove(const FInputActionValue& Value);
+	
+	UFUNCTION(BlueprintCallable)
+	void OnBeginTurn(const FInputActionValue& Value);
+
+	UFUNCTION(BlueprintCallable)
+	void OnBeginSnapTurn(const FInputActionValue& Value);
+
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VR Movement|Input")
+	class UInputMappingContext* IMCMovementRight;
+	
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VR Movement|Input")
+	class UInputMappingContext* IMCMovementLeft;
+		
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VR Movement|Input")
+	class UVRPawnInputConfig* InputActions;
+	
+	/*Desktop Testing*/
+	// the idea is that you have to hold the right mouse button to do rotations
+	UFUNCTION()
+	void StartDesktopRotation();
+	
+	UFUNCTION()
+	void EndDesktopRotation();
+	
+	bool bApplyDesktopRotation = false;
+	
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
+	bool bMoveWithRightHand = false;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement")
+	bool bSnapTurn = false;
+	
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement", meta=(EditCondition="!bSnapTurn"))
+	float TurnRateFactor = 1.0f;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement", meta=(EditCondition="bSnapTurn",ClampMin=0,ClampMax=360))
+	float SnapTurnAngle = 22.5;
+
+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(VisibleAnywhere) UCapsuleComponent* CapsuleColliderComponent = nullptr;
+	UPROPERTY() USceneComponent* HeadComponent = nullptr;
+
+	float VerticalSpeed = 0.0f;
+	FVector LastHeadPosition;
+
+
+	UPROPERTY()
+	UUniversalTrackedComponent* MovementHand;
+	
+	UPROPERTY()
+	UUniversalTrackedComponent* RotationHand;
+
+	UPROPERTY()
+	class UInputMappingContext* IMCMovement;
+
+	void SetupInputActions();
+
+	AVirtualRealityPawn* VRPawn;
+
+	/*virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;*/
+
+	/**
+	* Fixes camera rotation in desktop mode.
+	*/
+	void SetCameraOffset() const;
+	void UpdateRightHandForDesktopInteraction();
+	
+};
diff --git a/Source/RWTHVRToolkit/Public/Pawn/VRPawnInputConfig.h b/Source/RWTHVRToolkit/Public/Pawn/VRPawnInputConfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..a75687f3b1fd07dbdb595d3bd3eacc429116fbc7
--- /dev/null
+++ b/Source/RWTHVRToolkit/Public/Pawn/VRPawnInputConfig.h
@@ -0,0 +1,40 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "InputAction.h"
+#include "Engine/DataAsset.h"
+#include "VRPawnInputConfig.generated.h"
+
+/**
+ * 
+ */
+UCLASS()
+class RWTHVRTOOLKIT_API UVRPawnInputConfig : public UDataAsset
+{
+	GENERATED_BODY()
+
+public:
+
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
+	UInputAction* MoveUp;
+	
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
+	UInputAction* DesktopRotation;
+
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
+	UInputAction* Fire;
+	
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
+	UInputAction* Grab;
+
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
+	UInputAction* Move;
+
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
+	UInputAction* Turn;
+	
+
+
+};
diff --git a/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h b/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h
index c1c0789f9f48b5f5a6d03a9b9d7448cd7d00cd4b..79f7af9b8729e98943aef606f2001291956ef0df 100644
--- a/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h
+++ b/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h
@@ -4,16 +4,15 @@
 
 #include "BasicVRInteractionComponent.h"
 #include "CoreMinimal.h"
-#include "GameFramework/DefaultPawn.h"
 #include "UniversalTrackedComponent.h"
-#include "VRPawnMovement.h"
 #include "VirtualRealityPawn.generated.h"
 
+class UCameraComponent;
 class ULiveLinkComponentController;
 /**
  * 
  */
-UCLASS()
+UCLASS(Abstract)
 class RWTHVRTOOLKIT_API AVirtualRealityPawn : public APawn
 {
 	GENERATED_BODY()
@@ -21,15 +20,34 @@ public:
 	AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer);
 	
 	/* Proxy */
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects") UUniversalTrackedComponent* Head;
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects") UUniversalTrackedComponent* RightHand;
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects") UUniversalTrackedComponent* LeftHand;
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects")
+	UUniversalTrackedComponent* Head;
+	
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects")
+	UUniversalTrackedComponent* RightHand;
+	
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects")
+	UUniversalTrackedComponent* LeftHand;
 
 	/* Interaction */
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Interaction") UBasicVRInteractionComponent* BasicVRInteraction;
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Interaction")
+	UBasicVRInteractionComponent* BasicVRInteraction;
 
 	/* Movement */
-	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Movement") UVRPawnMovement* PawnMovement;
+	/*UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Movement")
+	UVRPawnMovement* PawnMovement;*/
+	
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement")
+	bool bMoveWithRightHand = false;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement")
+	bool bSnapTurn = false;
+	
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement", meta=(EditCondition="!bSnapTurn"))
+	float TurnRateFactor = 1.0f;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement", meta=(EditCondition="bSnapTurn",ClampMin=0,ClampMax=360))
+	float SnapTurnAngle = 22.5;
 
 	/** Workaround dummy component to prevent the Capsule from rotating in the editor, if LiveLink tracking is being used.
 	 *  This happens due to the rotation of the Capsule being set only while in Play Mode (instead of using e.g. absolute rotation).
@@ -38,32 +56,79 @@ public:
 	 *  The dummy seems to fix this, because its absolute rotation just catches all parent rotations and prevents them from
 	 *  overriding any of the capsules'.
 	 */
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement") USceneComponent* CapsuleRotationFix;
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement") float BaseTurnRate = 45.0f;
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement")
+	USceneComponent* CapsuleRotationFix;
+
 
 	/* CameraComponent */
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Camera") UCameraComponent* CameraComponent;
+	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Camera")
+	UCameraComponent* CameraComponent;
+
 
 protected:
 	virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
 
 	/* Movement */
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnForward(float Value);
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnRight(float Value);
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnUp(float Value);
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnTurnRate(float Rate);
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnLookUpRate(float Rate);
+	UFUNCTION(BlueprintCallable, Category = "Pawn|Movement")
+	void OnUp(const FInputActionValue& Value);
 
 	/* Interaction */
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Interaction") void OnBeginFire(); 
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Interaction") void OnEndFire();
+	UFUNCTION(BlueprintCallable, Category = "Pawn|Interaction")
+	void OnBeginFire(const FInputActionValue& Value);
+	
+	UFUNCTION(BlueprintCallable, Category = "Pawn|Interaction")
+	void OnEndFire(const FInputActionValue& Value);
+
+	UFUNCTION(BlueprintCallable, Category = "Pawn|Interaction")
+	void OnBeginGrab(const FInputActionValue& Value);
+	
+	UFUNCTION(BlueprintCallable, Category = "Pawn|Interaction")
+	void OnEndGrab(const FInputActionValue& Value);
+
+	/*
+	UFUNCTION(BlueprintCallable, Category = "Pawn|Interaction")
+	void OnBeginMove(const FInputActionValue& Value);
+	
+	UFUNCTION(BlueprintCallable, Category = "Pawn|Interaction")
+	void OnBeginTurn(const FInputActionValue& Value);
 
+	UFUNCTION(BlueprintCallable, Category = "Pawn|Interaction")
+	void OnBeginSnapTurn(const FInputActionValue& Value);
+	*/
+	
+	/* Input */
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pawn|Input")
+	class UInputMappingContext* IMCBase;
+	
+	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pawn|Input")
+	class UVRPawnInputConfig* InputActions;
+	
 	/*Desktop Testing*/
 	// the idea is that you have to hold the right mouse button to do rotations
-	UFUNCTION() void StartDesktopRotation();
-	UFUNCTION() void EndDesktopRotation();
-	bool bApplyDesktopRotation = false;
+	/*UFUNCTION()
+	void StartDesktopRotation();
+	
+	UFUNCTION()
+	void EndDesktopRotation();
+	
+	bool bApplyDesktopRotation = false;*/
+
+	/**
+	 * Fixes camera rotation in desktop mode.
+	 */
+	/*void SetCameraOffset() const;
+	void UpdateRightHandForDesktopInteraction();*/
+
+private:
+	/*UPROPERTY()
+	UUniversalTrackedComponent* MovementHand;
+	
+	UPROPERTY()
+	UUniversalTrackedComponent* RotationHand;
+
+	UPROPERTY()
+	class UInputMappingContext* IMCMovement;*/
+
+	/*virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;*/
 
-	void SetCameraOffset() const;
-	void UpdateRightHandForDesktopInteraction();
 };
diff --git a/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs b/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs
index 7a3abd662bc3d1c68586b690556f8bec4a52384e..8345d954abb2ade18d2974e89a1ca9ace8c42c12 100644
--- a/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs
+++ b/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs
@@ -28,7 +28,8 @@ public class RWTHVRToolkit : ModuleRules
 			"DeveloperSettings",
 			"HTTP",
 			"LiveLink",
-			"LiveLinkInterface"
+			"LiveLinkInterface",
+			"EnhancedInput"
 			}
 		);