diff --git a/Source/DisplayClusterExtensions/Private/Clickable.cpp b/Source/DisplayClusterExtensions/Private/Clickable.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..38d5fd80840f3358866775e20e1e98f97d64c871
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Private/Clickable.cpp
@@ -0,0 +1,8 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Clickable.h"
+
+UClickable::UClickable(const FObjectInitializer& ObjectInitializer)
+	:Super(ObjectInitializer)
+{}
diff --git a/Source/DisplayClusterExtensions/Private/Grabable.cpp b/Source/DisplayClusterExtensions/Private/Grabable.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..99330b38597c05fb5e3ea8d476edd77c3e16b797
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Private/Grabable.cpp
@@ -0,0 +1,10 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Grabable.h"
+
+// to avoid some bugs
+UGrabable::UGrabable(const FObjectInitializer& ObjectInitializer)
+	:Super(ObjectInitializer)
+{}
+
diff --git a/Source/DisplayClusterExtensions/Private/GrabbingBehaviorComponent.cpp b/Source/DisplayClusterExtensions/Private/GrabbingBehaviorComponent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5942605fe35abe48776669c183c4d0e17264e6c4
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Private/GrabbingBehaviorComponent.cpp
@@ -0,0 +1,34 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "GrabbingBehaviorComponent.h"
+
+// Sets default values for this component's properties
+UGrabbingBehaviorComponent::UGrabbingBehaviorComponent()
+{
+	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
+	// off to improve performance if you don't need them.
+	PrimaryComponentTick.bCanEverTick = true;
+
+	// ...
+}
+
+
+// Called when the game starts
+void UGrabbingBehaviorComponent::BeginPlay()
+{
+	Super::BeginPlay();
+
+	// ...
+	
+}
+
+
+// Called every frame
+void UGrabbingBehaviorComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
+{
+	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
+
+	// ...
+}
+
diff --git a/Source/DisplayClusterExtensions/Private/GrabbingBehaviorOnLineComponent.cpp b/Source/DisplayClusterExtensions/Private/GrabbingBehaviorOnLineComponent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c09f1be1bfa1b2fb92750ebe6d84868e986b6abf
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Private/GrabbingBehaviorOnLineComponent.cpp
@@ -0,0 +1,77 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "GrabbingBehaviorOnLineComponent.h"
+
+// Sets default values for this component's properties
+UGrabbingBehaviorOnLineComponent::UGrabbingBehaviorOnLineComponent()
+{
+	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
+	// off to improve performance if you don't need them.
+	PrimaryComponentTick.bCanEverTick = true;
+
+	bAbsoluteLocation = true;
+	bAbsoluteRotation = true;
+	bAbsoluteScale    = true;
+	
+	this->Distance = 0;
+}
+
+
+void UGrabbingBehaviorOnLineComponent::SetDistance(float Dist)
+{
+
+	check(Dist > 0 && "max distance has to be greater than 0");
+	this->Distance = Dist;
+}
+
+float UGrabbingBehaviorOnLineComponent::GetDistance() const 
+{
+	return this->Distance;
+}
+
+void UGrabbingBehaviorOnLineComponent::HandleNewPositionAndDirection(FVector Position, FQuat Orientation)
+{
+	FVector AttachmentPoint = this->RelativeLocation;
+	FVector ConstraintAxis = this->GetComponentQuat().GetUpVector();
+	FVector Direction = Orientation.GetForwardVector();
+	FVector FromHandToMe = -Position + AttachmentPoint;
+
+	// Vector perpendicular to both points
+	FVector Temp = FVector::CrossProduct(FromHandToMe, ConstraintAxis);
+	Temp.Normalize();
+
+	FVector PlaneNormal = FVector::CrossProduct(ConstraintAxis,Temp);
+
+	// get intersection point defined by plane
+	FVector Intersection =  FMath::LinePlaneIntersection(Position, Position + Direction, AttachmentPoint, PlaneNormal);
+	FVector FromOriginToIntersection = Intersection - AttachmentPoint;
+
+	// point along the constraint axis with length of the projection from intersection point onto the axis
+	FVector NewPosition = FVector::DotProduct(FromOriginToIntersection, ConstraintAxis)* ConstraintAxis;
+	
+	NewPosition = NewPosition.GetClampedToMaxSize(Distance);
+	NewPosition += AttachmentPoint;
+
+	// transform the targeted actor which is owner of this component with calculated quaternion and posiition
+	// here rotation is not changed
+	GetOwner()->SetActorLocation(NewPosition);
+}
+
+// Called when the game starts
+void UGrabbingBehaviorOnLineComponent::BeginPlay()
+{
+	Super::BeginPlay();
+
+	// ...
+	
+}
+
+
+// Called every frame
+void UGrabbingBehaviorOnLineComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
+{
+	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
+
+}
+
diff --git a/Source/DisplayClusterExtensions/Private/GrabbingBehaviorOnPlaneComponent.cpp b/Source/DisplayClusterExtensions/Private/GrabbingBehaviorOnPlaneComponent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5d5e5e23e648e14a8d6e32a9b5c85c34c37facc8
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Private/GrabbingBehaviorOnPlaneComponent.cpp
@@ -0,0 +1,73 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+//TODO rename distance to maxDistance
+
+#include "GrabbingBehaviorOnPlaneComponent.h"
+
+// Sets default values for this component's properties
+UGrabbingBehaviorOnPlaneComponent::UGrabbingBehaviorOnPlaneComponent()
+{
+	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
+	// off to improve performance if you don't need them.
+	PrimaryComponentTick.bCanEverTick = true;
+
+	bAbsoluteLocation = true;
+	bAbsoluteRotation = true;
+	bAbsoluteScale    = true;
+	// ...
+}
+
+
+void UGrabbingBehaviorOnPlaneComponent::SetDistance(float Dist)
+{
+	check(Dist > 0 && "max distance has to be greater than 0");
+	this->Distance = Dist;
+}
+
+float UGrabbingBehaviorOnPlaneComponent::GetDistance() const 
+{
+	return this->Distance;
+}
+
+
+void UGrabbingBehaviorOnPlaneComponent::HandleNewPositionAndDirection(FVector Position, FQuat Orientation)
+{
+	FVector AttachmentPoint = this->RelativeLocation;
+	FVector PlaneNormal = this->GetComponentQuat().GetUpVector(); 
+	FVector Direction = Orientation.GetForwardVector();
+	
+	// calculate point on plane which is pointed to by hand ray
+	FVector Intersection = FMath::LinePlaneIntersection(Position, Position + Direction, AttachmentPoint, PlaneNormal);
+	FVector NewPosition = -AttachmentPoint + Intersection;
+	
+	// clamp size by maxDistance
+	NewPosition = NewPosition.GetClampedToMaxSize(Distance);
+	
+	// after this NewPoint is in world position
+	NewPosition += AttachmentPoint;
+
+
+	// set new position and orientation using calculated quaternion and position
+	// here rotation is not changed
+	GetOwner()->SetActorLocation(NewPosition);
+}
+
+
+// Called when the game starts
+void UGrabbingBehaviorOnPlaneComponent::BeginPlay()
+{
+	Super::BeginPlay();
+
+	// ...
+	
+}
+
+
+// Called every frame
+void UGrabbingBehaviorOnPlaneComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
+{
+	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
+	
+	// ...
+
+}
+
diff --git a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
index c9c719b38331a72d7f8f1bcadd57b4f2dc95c924..de17d478c5ac6bc9be9124d845fdc3f56b7aa960 100644
--- a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
+++ b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
@@ -1,7 +1,6 @@
-#include "VirtualRealityPawn.h"
+#include "VirtualRealityPawn.h"
 
 #include "Camera/CameraComponent.h"
-#include "Cluster/IDisplayClusterClusterManager.h"
 #include "Engine/Engine.h"
 #include "Engine/World.h"
 #include "Game/IDisplayClusterGameManager.h"
@@ -10,8 +9,16 @@
 #include "Kismet/GameplayStatics.h"
 #include "DisplayClusterSettings.h"
 #include "IDisplayCluster.h"
+#include "Components/SphereComponent.h"
+#include "DrawDebugHelpers.h"
+#include "Math/Vector.h"
 #include "VirtualRealityUtilities.h"
 
+#include "GrabbingBehaviorComponent.h"
+#include "Grabable.h"
+#include "Clickable.h"
+
+
 AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
 {
 	bUseControllerRotationYaw = true;
@@ -30,8 +37,11 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial
 	RotatingMovement->RotationRate = FRotator::ZeroRotator;
 
 	Head = CreateDefaultSubobject<USceneComponent>(TEXT("Head"));
+	Head->SetupAttachment(RootComponent);
 	RightHand = CreateDefaultSubobject<USceneComponent>(TEXT("RightHand"));
+	RightHand->SetupAttachment(RootComponent);
 	LeftHand = CreateDefaultSubobject<USceneComponent>(TEXT("LeftHand"));
+	LeftHand->SetupAttachment(RootComponent);
 
 	HmdLeftMotionController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("HmdLeftMotionController"));
 	HmdLeftMotionController->SetupAttachment(RootComponent);
@@ -44,40 +54,45 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial
 	HmdRightMotionController->SetTrackingSource(EControllerHand::Right);
 	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);
+	HmdTracker1->SetShowDeviceModel(true);
+	HmdTracker1->SetVisibility(false);
+
+	HmdTracker2 = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("HmdTracker2"));
+	HmdTracker2->SetupAttachment(RootComponent);
+	HmdTracker2->SetTrackingSource(EControllerHand::Special_2);
+	HmdTracker2->SetShowDeviceModel(true);
+	HmdTracker2->SetVisibility(false);
 }
 
 void AVirtualRealityPawn::OnForward_Implementation(float Value)
 {
-	// Check if this function triggers correctly on ROLV.
-	if (RightHand && (NavigationMode == EVRNavigationModes::nav_mode_fly || UVirtualRealityUtilities::IsDesktopMode() || UVirtualRealityUtilities::IsHeadMountedMode()))
+	if (RightHand)
 	{
-		AddMovementInput(RightHand->GetForwardVector(), Value);
+		HandleMovementInput(Value, RightHand->GetForwardVector());
 	}
 }
 
 void AVirtualRealityPawn::OnRight_Implementation(float Value)
 {
-	if (RightHand && (NavigationMode == EVRNavigationModes::nav_mode_fly || UVirtualRealityUtilities::IsDesktopMode() || UVirtualRealityUtilities::IsHeadMountedMode()))
+	if (RightHand)
 	{
-		AddMovementInput(RightHand->GetRightVector(), Value);
+		HandleMovementInput(Value, RightHand->GetRightVector());
 	}
 }
 
 void AVirtualRealityPawn::OnTurnRate_Implementation(float Rate)
 {
-	//if (IsRoomMountedMode())
-	//{
-	//	//const FVector CameraLocation = IDisplayCluster::Get().GetGameMgr()->GetActiveCamera()->GetComponentLocation();
-	//	//RotatingMovement->PivotTranslation = RotatingMovement
-	//	//                                     ->UpdatedComponent->GetComponentTransform().
-	//	//                                     InverseTransformPositionNoScale(CameraLocation);
-	//	//RotatingMovement->RotationRate = FRotator(RotatingMovement->RotationRate.Pitch, Rate * BaseTurnRate, 0.0f);
-
-	//}
-	//else
-	//{
-	//	AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
-	//}
 	AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
 }
 
@@ -93,14 +108,6 @@ void AVirtualRealityPawn::OnLookUpRate_Implementation(float Rate)
 	}
 }
 
-void AVirtualRealityPawn::OnFire_Implementation(bool Pressed)
-{
-}
-
-void AVirtualRealityPawn::OnAction_Implementation(bool Pressed, int32 Index)
-{
-}
-
 float AVirtualRealityPawn::GetBaseTurnRate() const
 {
 	return BaseTurnRate;
@@ -146,6 +153,16 @@ UMotionControllerComponent* AVirtualRealityPawn::GetHmdRightMotionControllerComp
 	return HmdRightMotionController;
 }
 
+UMotionControllerComponent* AVirtualRealityPawn::GetHmdTracker1MotionControllerComponent()
+{
+	return HmdTracker1;
+}
+
+UMotionControllerComponent* AVirtualRealityPawn::GetHmdTracker2MotionControllerComponent()
+{
+	return HmdTracker2;
+}
+
 USceneComponent* AVirtualRealityPawn::GetHeadComponent()
 {
 	return Head;
@@ -225,18 +242,24 @@ void AVirtualRealityPawn::BeginPlay()
 
 		HmdLeftMotionController->SetVisibility(ShowHMDControllers);
 		HmdRightMotionController->SetVisibility(ShowHMDControllers);
+		if (HmdTracker1->IsActive()) {
+			HmdTracker1->SetVisibility(ShowHMDControllers);
+		}
+		if (HmdTracker2->IsActive()) {
+			HmdTracker2->SetVisibility(ShowHMDControllers);
+		}
 
-		LeftHand->AttachToComponent(HmdLeftMotionController, FAttachmentTransformRules::KeepRelativeTransform);
-		RightHand->AttachToComponent(HmdRightMotionController, FAttachmentTransformRules::KeepRelativeTransform);
-		Head->AttachToComponent(GetCameraComponent(), FAttachmentTransformRules::KeepRelativeTransform);
+		LeftHand->AttachToComponent(HmdLeftMotionController, FAttachmentTransformRules::SnapToTargetIncludingScale);
+		RightHand->AttachToComponent(HmdRightMotionController, FAttachmentTransformRules::SnapToTargetIncludingScale);
+		Head->AttachToComponent(GetCameraComponent(), FAttachmentTransformRules::SnapToTargetIncludingScale);
 	}
 	else //Desktop
 	{
-		Head->AttachToComponent(GetCameraComponent(), FAttachmentTransformRules::KeepRelativeTransform);
+		Head->AttachToComponent(GetCameraComponent(), FAttachmentTransformRules::SnapToTargetIncludingScale);
 
 		//also attach the hands to the camera component so we can use them for interaction
-		LeftHand->AttachToComponent(GetCameraComponent(), FAttachmentTransformRules::KeepRelativeTransform);
-		RightHand->AttachToComponent(GetCameraComponent(), FAttachmentTransformRules::KeepRelativeTransform);
+		LeftHand->AttachToComponent(GetCameraComponent(), FAttachmentTransformRules::SnapToTargetIncludingScale);
+		RightHand->AttachToComponent(GetCameraComponent(), FAttachmentTransformRules::SnapToTargetIncludingScale);
 
 
 		//move to eyelevel
@@ -262,6 +285,11 @@ void AVirtualRealityPawn::BeginPlay()
 		ClusterEventListenerDelegate = FOnClusterEventListener::CreateUObject(this, &AVirtualRealityPawn::HandleClusterEvent);
 		ClusterManager->AddClusterEventListener(ClusterEventListenerDelegate);
 	}
+
+	CollisionComponent->SetCollisionProfileName(FName("NoCollision"));
+	CollisionComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
+
+	LastCameraPosition = CameraComponent->GetComponentLocation();
 }
 
 void AVirtualRealityPawn::EndPlay(const EEndPlayReason::Type EndPlayReason)
@@ -278,9 +306,35 @@ 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)
+	{
+		UGrabbingBehaviorComponent* Behavior = GrabbedActor->FindComponentByClass<UGrabbingBehaviorComponent>();
+
+		// if our Grabable Actor is not constrained
+		if (Behavior != nullptr)
+		{	
+			// specifies the hand in space
+			FVector HandPos = this->RightHand->GetComponentLocation();	
+			FQuat HandQuat = this->RightHand->GetComponentQuat();
+
+			Behavior->HandleNewPositionAndDirection(HandPos, HandQuat); 
+		}
+	}
 
 	//Flystick might not be available at start, hence is checked every frame.
 	InitRoomMountedComponentReferences();
+
+	LastCameraPosition = CameraComponent->GetComponentLocation();
 }
 
 void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
@@ -292,14 +346,207 @@ void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInput
 		PlayerInputComponent->BindAxis("MoveRight", this, &AVirtualRealityPawn::OnRight);
 		PlayerInputComponent->BindAxis("TurnRate", this, &AVirtualRealityPawn::OnTurnRate);
 		PlayerInputComponent->BindAxis("LookUpRate", this, &AVirtualRealityPawn::OnLookUpRate);
+
+		// function bindings for grabbing and releasing
+		PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AVirtualRealityPawn::OnBeginFire);
+		PlayerInputComponent->BindAction("Fire", IE_Released, this, &AVirtualRealityPawn::OnEndFire);
 	}
 }
 
+void AVirtualRealityPawn::OnBeginFire_Implementation()
+{
+	// start and end point for raytracing
+	FTwoVectors StartEnd = GetHandRay(MaxClickDistance);	
+	FVector Start = StartEnd.v1;
+	FVector End   = StartEnd.v2;	
+
+	// will be filled by the Line Trace Function
+	FHitResult Hit;
+	AActor* HitActor;
+
+	//if hit was not found return  
+	FCollisionObjectQueryParams Params;
+	if (!GetWorld()->LineTraceSingleByObjectType(Hit, Start, End, Params))
+		return;
+
+	HitActor = Hit.GetActor();
+	
+	// try to cast HitActor int a Grabable if not succeeded will become a nullptr
+	IGrabable*  GrabableActor  = Cast<IGrabable>(HitActor);
+	IClickable* ClickableActor = Cast<IClickable>(HitActor);
+
+	if (GrabableActor != nullptr && Hit.Distance < MaxGrabDistance)
+	{
+		// call grabable actors function so he reacts to our grab
+		GrabableActor->OnGrabbed_Implementation();
+		
+
+		UGrabbingBehaviorComponent* Behavior = HitActor->FindComponentByClass<UGrabbingBehaviorComponent>();
+		if ( Behavior == nullptr)
+			HandlePhysicsAndAttachActor(HitActor);
+
+		// we save the grabbedActor in a general form to access all of AActors functions easily later
+		GrabbedActor = HitActor;
+	}
+	else if (ClickableActor != nullptr && Hit.Distance < MaxClickDistance)
+	{
+		ClickableActor->OnClicked_Implementation(Hit.Location);
+	}
+}
+
+void AVirtualRealityPawn::HandlePhysicsAndAttachActor(AActor* HitActor)
+{
+	UPrimitiveComponent* PhysicsComp = HitActor->FindComponentByClass<UPrimitiveComponent>();	
+	
+	bDidSimulatePhysics = PhysicsComp->IsSimulatingPhysics(); // remember if we need to tun physics back on or not	
+	PhysicsComp->SetSimulatePhysics(false);
+	FAttachmentTransformRules Rules = FAttachmentTransformRules::KeepWorldTransform;
+	Rules.bWeldSimulatedBodies = true;
+	HitActor->AttachToComponent(this->RightHand, Rules);
+}
+
+void AVirtualRealityPawn::OnEndFire_Implementation() {
+
+	// if we didnt grab anyone there is no need to release
+	if (GrabbedActor == nullptr)
+		return;
+
+	// let the grabbed object reacot to release
+	Cast<IGrabable>(GrabbedActor)->OnReleased_Implementation();
+
+	// Detach the Actor
+
+	UPrimitiveComponent* PhysicsComp = GrabbedActor->FindComponentByClass<UPrimitiveComponent>();
+	UGrabbingBehaviorComponent* Behavior = GrabbedActor->FindComponentByClass<UGrabbingBehaviorComponent>();
+	if (Behavior == nullptr)
+	{
+		GrabbedActor->GetRootComponent()->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
+		PhysicsComp->SetSimulatePhysics(bDidSimulatePhysics);
+	}
+
+	// forget about the actor
+	GrabbedActor = nullptr;
+}
+
+FTwoVectors AVirtualRealityPawn::GetHandRay(float Length)
+{
+	FVector Start = this->RightHand->GetComponentLocation();
+	FVector Direction = this->RightHand->GetForwardVector();
+	FVector End = Start + Length * Direction;
+
+	return FTwoVectors(Start, End);
+}
+
+
 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;
+	}
+}
+
 void AVirtualRealityPawn::InitRoomMountedComponentReferences()
 {
 	if (!UVirtualRealityUtilities::IsRoomMountedMode()) return;
@@ -311,26 +558,80 @@ void AVirtualRealityPawn::InitRoomMountedComponentReferences()
 	if (!ShutterGlasses)
 	{
 		ShutterGlasses = UVirtualRealityUtilities::GetClusterComponent("shutter_glasses");
-		Head->AttachToComponent(ShutterGlasses, FAttachmentTransformRules::KeepRelativeTransform);
+		Head->AttachToComponent(ShutterGlasses, FAttachmentTransformRules::SnapToTargetIncludingScale);
 	}
 	if (!Flystick)
 	{
 		Flystick = UVirtualRealityUtilities::GetClusterComponent("flystick");
 		if (AttachRightHandInCAVE == EAttachementType::AT_FLYSTICK)
-			RightHand->AttachToComponent(Flystick, FAttachmentTransformRules::KeepRelativeTransform);
+			RightHand->AttachToComponent(Flystick, FAttachmentTransformRules::SnapToTargetIncludingScale);
 		if (AttachLeftHandInCAVE == EAttachementType::AT_FLYSTICK)
-			LeftHand->AttachToComponent(Flystick, FAttachmentTransformRules::KeepRelativeTransform);
+			LeftHand->AttachToComponent(Flystick, FAttachmentTransformRules::SnapToTargetIncludingScale);
 	}
 	if (!LeftHandTarget)
 	{
 		LeftHandTarget = UVirtualRealityUtilities::GetClusterComponent("left_hand_target");
 		if (AttachLeftHandInCAVE == EAttachementType::AT_HANDTARGET)
-			LeftHand->AttachToComponent(LeftHandTarget, FAttachmentTransformRules::KeepRelativeTransform);
+			LeftHand->AttachToComponent(LeftHandTarget, FAttachmentTransformRules::SnapToTargetIncludingScale);
 	}
 	if (!RightHandTarget)
 	{
 		RightHandTarget = UVirtualRealityUtilities::GetClusterComponent("right_hand_target");
 		if (AttachRightHandInCAVE == EAttachementType::AT_HANDTARGET)
-			RightHand->AttachToComponent(RightHandTarget, FAttachmentTransformRules::KeepRelativeTransform);
+			RightHand->AttachToComponent(RightHandTarget, FAttachmentTransformRules::SnapToTargetIncludingScale);
+	}
+}
+
+
+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)
+{
+	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;
 }
diff --git a/Source/DisplayClusterExtensions/Private/VirtualRealityUtilities.cpp b/Source/DisplayClusterExtensions/Private/VirtualRealityUtilities.cpp
index 30a85dd360f560bdc7772418b0e3a653b2a2dfb8..33720fc021c44066651d123029068748d81cc78b 100644
--- a/Source/DisplayClusterExtensions/Private/VirtualRealityUtilities.cpp
+++ b/Source/DisplayClusterExtensions/Private/VirtualRealityUtilities.cpp
@@ -20,6 +20,20 @@ bool UVirtualRealityUtilities::IsHeadMountedMode()
 	return GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed();
 }
 
+bool UVirtualRealityUtilities::IsMaster()
+{
+	IDisplayClusterClusterManager* manager = IDisplayCluster::Get().GetClusterMgr();
+	if (manager == nullptr) // no manager means we are not in clustermode and therefore master
+		return true;
+
+	return manager->IsMaster();
+}
+
+bool UVirtualRealityUtilities::IsSlave()
+{
+	return !IsMaster();
+}
+
 FString UVirtualRealityUtilities::GetNodeName()
 {
 	return IsRoomMountedMode() ? IDisplayCluster::Get().GetClusterMgr()->GetNodeId() : FString(TEXT("Localhost"));
diff --git a/Source/DisplayClusterExtensions/Public/Clickable.h b/Source/DisplayClusterExtensions/Public/Clickable.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c96585c9f23feb319d86f4f1063dfec9643ffd0
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Public/Clickable.h
@@ -0,0 +1,29 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Object.h"
+#include "UObject/Interface.h"
+#include "Clickable.generated.h"
+
+
+UINTERFACE(BlueprintType)
+class DISPLAYCLUSTEREXTENSIONS_API UClickable : public UInterface
+{
+	// has to be empty, this is Unreals syntax to make it visible in blueprints
+	GENERATED_UINTERFACE_BODY()
+};
+
+class IClickable
+{
+	GENERATED_IINTERFACE_BODY()
+
+public:
+	// function that will be called when clickable actor got clicked, and passed the world pos of the click
+	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Gameplay)
+	void OnClicked(FVector WorldPositionOfClick);
+	
+
+};
+
diff --git a/Source/DisplayClusterExtensions/Public/DisplayClusterEventParameterHelper.h b/Source/DisplayClusterExtensions/Public/DisplayClusterEventParameterHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..705d893d14456b800995b17c2e20fb830e6f07d0
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Public/DisplayClusterEventParameterHelper.h
@@ -0,0 +1,125 @@
+#pragma once
+
+#include "Serialization/MemoryReader.h"
+#include "Serialization/MemoryWriter.h"
+
+// Helper function to put the arguments into a string map. It uses template substitution to choose the correct specialization.
+template <typename... Values>
+struct FillParameterMapImpl;
+
+// This specialization is chosen when there no argument left to serialize.
+template <>
+struct FillParameterMapImpl<>
+{
+	template <int ArgumentIndex>
+	static inline void Invoke(TMap<FString, FString>*)
+	{
+		// There is nothing left to do here.
+	}
+};
+
+// This specialization is chosen when there is at least one argument left to serialize.
+template <typename CurrentValueType, typename... RemainingValueTypes>
+struct FillParameterMapImpl<CurrentValueType, RemainingValueTypes...>
+{
+	template <int ArgumentIndex>
+	static inline void Invoke(
+		TMap<FString, FString>* ParameterMap, const CurrentValueType& CurrentValue, RemainingValueTypes&&... RemainingValues)
+	{
+		// If this assertion fails: implement the workaround described below!
+		static_assert(sizeof(TCHAR) > sizeof(uint8), "TCHAR needs to have extra room!");
+
+		TArray<uint8> SerializedValue;
+		// TODO: maybe it is a good idea to guess the amount of bytes the serialized value will have. This would probably reduce the
+		// number of reallocations in the serialization process. However, I don't know if this is already taken care of in the
+		// FArchive class. Also it is hard to implement correctly, so we have to see whether it is worth it.
+		FMemoryWriter writer(SerializedValue);
+
+		// Const cast is necessary here because the "<<" operator is used for reading and writing and thus does not take a const
+		// argument. However, it should be fine as, hopefully, the "<<" operator doesn't modify the value in "reading mode".
+		auto NonConstCurrentValue = const_cast<CurrentValueType&>(CurrentValue);
+		writer << NonConstCurrentValue;
+
+		// We have an array of bytes. Now we need to convert them to a string.
+		FString SerializedDataString;
+		SerializedDataString.Empty(SerializedValue.Num());	  // Preallocate memory to avoid reallocations.
+		for (const uint8 Byte : SerializedValue)
+		{
+			// This is potentially dangerous:
+			// We treat the individual bytes as characters in a string. The character with the value 0 is normally used to mark the
+			// end of the string. Because of this, FString will not add zero values to the underlying data array. To avoid this I
+			// add 1 to every value. This only works, because the TCHAR is usually more than one byte long. However, this is not
+			// guaranteed. Currently I enforce it with a static_assert above. If this is not the case we would need to split each
+			// byte into two characters. Another option would be to access the underlying TCHAR array directly. However I don't know
+			// if they are transported correctly using the cluster events.
+			SerializedDataString += static_cast<TCHAR>(static_cast<TCHAR>(Byte) + 1);
+		}
+
+		ParameterMap->Add(FString::FromInt(ArgumentIndex), SerializedDataString);
+
+		// Recursive call for the remaining values.
+		FillParameterMapImpl<RemainingValueTypes...>::template Invoke<ArgumentIndex + 1>(
+			ParameterMap, Forward<RemainingValueTypes>(RemainingValues)...);
+	}
+};
+
+// This function creates a string map with the arguments it gets passed. The resulting map will contain an entry for every argument.
+// The first argument will have the key "0", the second "1" and so on.
+template <typename... ArgTypes>
+inline TMap<FString, FString> CreateParameterMap(ArgTypes&&... Arguments)
+{
+	TMap<FString, FString> ParameterMap;
+	ParameterMap.Empty(sizeof...(ArgTypes));	// Preallocate to avoid allocations.
+	FillParameterMapImpl<ArgTypes...>::template Invoke<0>(&ParameterMap, Forward<ArgTypes>(Arguments)...);
+	return ParameterMap;
+}
+
+// This is a wrapper function to recursively fill the argument tuple. This overload is only used if the index indicating the
+// currently handled attribute is less than the number of total attributes. I.e., if the attribute index is valid.
+template <int CurrentIndex, typename... ArgTypes>
+inline typename TEnableIf<(CurrentIndex < sizeof...(ArgTypes))>::Type FillArgumentTuple(
+	TTuple<ArgTypes...>* ArgumentTuple, const TMap<FString, FString>& Parameters)
+{
+	const FString& SerializedDataString = Parameters[FString::FromInt(CurrentIndex)];
+	TArray<uint8> SerializedData;
+	// Preallocate to avoid reallocation
+	SerializedData.Empty(SerializedDataString.Len());
+
+	// Reconstruct the original bytes. I.e., reversing the addition by one.
+	for (const auto Character : SerializedDataString)
+	{
+		SerializedData.Add(static_cast<uint8>(Character - 1));
+	}
+
+	FMemoryReader Reader(SerializedData);
+	// Read the "<<" as ">>" operator here. FArchive uses the same for both and decides based on an internal type on what to do. So
+	// this statement parses the bytes that were passed into reader and puts the parsed object into the tuple at index CurrentIndex.
+	Reader << ArgumentTuple->template Get<CurrentIndex>();
+
+	// Recursive call for the remaining attributes.
+	FillArgumentTuple<CurrentIndex + 1>(
+		Forward<TTuple<ArgTypes...>*>(ArgumentTuple), Forward<const TMap<FString, FString>&>(Parameters));
+}
+
+// The overload that is called if we are "passed the end" of attributes.
+template <int CurrentIndex, typename... ArgTypes>
+inline typename TEnableIf<(CurrentIndex >= sizeof...(ArgTypes))>::Type FillArgumentTuple(
+	TTuple<ArgTypes...>* ArgumentTuple, const TMap<FString, FString>& Parameters)
+{
+}
+
+template <typename RetType, typename... ArgTypes>
+inline RetType CallDelegateWithParameterMap(
+	const TBaseDelegate<RetType, ArgTypes...>& Delegate, const TMap<FString, FString>& Parameters)
+{
+	// Create a tuple that holds all arguments. This assumes that all argument types are default constructible. However, all
+	// types that overload the FArchive "<<" operator probably are.
+	TTuple<typename TRemoveCV<typename TRemoveReference<ArgTypes>::Type>::Type...> ArgumentTuple;
+
+	// This call will parse the string map and fill all values in the tuple appropriately.
+	FillArgumentTuple<0>(&ArgumentTuple, Parameters);
+
+	// The lambda function is only necessary because delegates do not overload the ()-operator but use the Execute() method
+	// instead. So, the lambda acts as a wrapper.
+	return ArgumentTuple.ApplyBefore([Delegate](ArgTypes&&... Arguments) { Delegate.Execute(Forward<ArgTypes>(Arguments)...); });
+}
diff --git a/Source/DisplayClusterExtensions/Public/DisplayClusterEventWrapper.h b/Source/DisplayClusterExtensions/Public/DisplayClusterEventWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ed716cdd5d9c22a8286058782a5b434a69880ba
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Public/DisplayClusterEventWrapper.h
@@ -0,0 +1,108 @@
+#pragma once
+
+#include "IDisplayCluster.h"
+#include "IDisplayClusterClusterManager.h"
+#include "Cluster/DisplayClusterClusterEvent.h"
+#include "DisplayClusterEventParameterHelper.h"
+#include "Templates/IsInvocable.h"
+
+template <typename MemberFunctionType, MemberFunctionType MemberFunction>
+class ClusterEventWrapperEvent;
+
+template <typename ObjectType, typename ReturnType, typename... ArgTypes, ReturnType (ObjectType::*MemberFunction)(ArgTypes...)>
+class ClusterEventWrapperEvent<ReturnType (ObjectType::*)(ArgTypes...), MemberFunction>
+{
+	static_assert(TIsDerivedFrom<ObjectType, AActor>::IsDerived, "Object needs to derive from AActor");
+
+public:
+	using MemberFunctionType = decltype(MemberFunction);
+
+	ClusterEventWrapperEvent(const TCHAR* EventTypeName) : EventTypeName{EventTypeName}
+	{
+	}
+
+	void Attach(ObjectType* NewObject)
+	{
+		IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
+		check(ClusterManager != nullptr);
+
+		checkf(Object == nullptr, TEXT("The event is already attached."));
+		Object = NewObject;
+		ObjectName = AActor::GetDebugName(Object);
+
+		if (!ClusterManager->IsStandalone())
+		{
+			check(!ClusterEventListenerDelegate.IsBound());
+			ClusterEventListenerDelegate = FOnClusterEventListener::CreateLambda([this](const FDisplayClusterClusterEvent& Event) {
+				if (Event.Type == EventTypeName && Event.Name == ObjectName)
+				{
+					// Create a tuple that holds all arguments. This assumes that all
+					// argument types are default constructible. However, all
+					// types that overload the FArchive "<<" operator probably are.
+					TTuple<typename TRemoveCV<typename TRemoveReference<ArgTypes>::Type>::Type...> ArgumentTuple;
+
+					// This call will parse the string map and fill all values in the
+					// tuple appropriately.
+					FillArgumentTuple<0>(&ArgumentTuple, Event.Parameters);
+
+					ArgumentTuple.ApplyBefore([this](const ArgTypes&... Arguments) {
+						(Object->*MemberFunction)(Forward<const ArgTypes&>(Arguments)...);
+					});
+				}
+			});
+			ClusterManager->AddClusterEventListener(ClusterEventListenerDelegate);
+		}
+	}
+
+	void Detach()
+	{
+		checkf(Object != nullptr, TEXT("The event was never attached."));
+
+		IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
+		check(ClusterManager != nullptr);
+
+		if (!ClusterManager->IsStandalone())
+		{
+			// check(ClusterEventListenerDelegate.IsBound());
+			ClusterManager->RemoveClusterEventListener(ClusterEventListenerDelegate);
+		}
+	}
+
+	void Send(ArgTypes&&... Arguments)
+	{
+		IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
+		check(ClusterManager != nullptr);
+
+		checkf(Object != nullptr, TEXT("The event was not attached."));
+
+		if (ClusterManager->IsStandalone())
+		{
+			(Object->*MemberFunction)(Forward<ArgTypes>(Arguments)...);
+		}
+		else
+		{
+			FDisplayClusterClusterEvent ClusterEvent;
+			ClusterEvent.Category = "DisplayClusterEventWrapper";
+			ClusterEvent.Type = EventTypeName;
+			ClusterEvent.Name = ObjectName;
+			ClusterEvent.Parameters = CreateParameterMap(Forward<ArgTypes>(Arguments)...);
+
+			ClusterManager->EmitClusterEvent(ClusterEvent, true);
+		}
+	}
+
+private:
+	const TCHAR* EventTypeName;
+	ObjectType* Object = nullptr;
+	FString ObjectName;
+	FOnClusterEventListener ClusterEventListenerDelegate;
+};
+
+#define DCEW_STRINGIFY(x) #x
+#define DCEW_TOSTRING(x) DCEW_STRINGIFY(x)
+
+#define DECLARE_DISPLAY_CLUSTER_EVENT(OwningType, MethodIdentifier)                                                          \
+	ClusterEventWrapperEvent<decltype(&OwningType::MethodIdentifier), &OwningType::MethodIdentifier> MethodIdentifier##Event \
+	{                                                                                                                        \
+		TEXT(DCEW_TOSTRING(OwningType) DCEW_TOSTRING(MethodIdentifier))                                                      \
+	}
diff --git a/Source/DisplayClusterExtensions/Public/Grabable.h b/Source/DisplayClusterExtensions/Public/Grabable.h
new file mode 100644
index 0000000000000000000000000000000000000000..873e3346002055ea6b513d9c9b2a18ec4eb5a2c4
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Public/Grabable.h
@@ -0,0 +1,30 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Object.h"
+#include "UObject/Interface.h"
+#include "Grabable.generated.h"
+
+UINTERFACE(BlueprintType)
+class DISPLAYCLUSTEREXTENSIONS_API UGrabable : public UInterface
+{
+	// has to be empty, this is Unreals syntax to make it visible in blueprints
+	GENERATED_UINTERFACE_BODY()
+};
+
+class IGrabable
+{
+	GENERATED_IINTERFACE_BODY()
+
+public:
+	// function that will be called when grabbed by a pawn
+	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Gameplay)
+	void OnGrabbed();
+	
+	// called when pawn released the object
+	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Gameplay)
+	void OnReleased();
+
+};
diff --git a/Source/DisplayClusterExtensions/Public/GrabbingBehaviorComponent.h b/Source/DisplayClusterExtensions/Public/GrabbingBehaviorComponent.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f28127d23627cd14c2aa1a9586fc0e5652cea04
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Public/GrabbingBehaviorComponent.h
@@ -0,0 +1,30 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Components/SceneComponent.h"
+#include "GrabbingBehaviorComponent.generated.h"
+
+
+UCLASS(Abstract, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
+class DISPLAYCLUSTEREXTENSIONS_API UGrabbingBehaviorComponent : public USceneComponent
+{
+	GENERATED_BODY()
+
+public:	
+	// Sets default values for this component's properties
+	UGrabbingBehaviorComponent();
+
+
+	// takes the hand ray and moves the parent actor to a new possible position, also might change rotation
+	virtual void HandleNewPositionAndDirection(FVector position, FQuat orientation) PURE_VIRTUAL(UGrabbingBehaviorComponent::GeneratePossiblePosition,);
+
+protected:
+	// Called when the game starts
+	virtual void BeginPlay() override;
+
+public:	
+	// Called every frame
+	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;	
+};
diff --git a/Source/DisplayClusterExtensions/Public/GrabbingBehaviorOnLineComponent.h b/Source/DisplayClusterExtensions/Public/GrabbingBehaviorOnLineComponent.h
new file mode 100644
index 0000000000000000000000000000000000000000..decc8ead1962e9e8f825b3cf9511c4a827f3e759
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Public/GrabbingBehaviorOnLineComponent.h
@@ -0,0 +1,37 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GrabbingBehaviorComponent.h"
+#include "GrabbingBehaviorOnLineComponent.generated.h"
+
+
+UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
+class DISPLAYCLUSTEREXTENSIONS_API UGrabbingBehaviorOnLineComponent : public UGrabbingBehaviorComponent
+{
+	GENERATED_BODY()
+
+public:	
+	// Sets default values for this component's properties
+	UGrabbingBehaviorOnLineComponent();
+
+	// defining a constraint line with these 3 parameters
+	UFUNCTION(BlueprintCallable) void SetDistance(float Dist);
+	UFUNCTION(BlueprintCallable) float GetDistance() const;
+
+	virtual void HandleNewPositionAndDirection(FVector position, FQuat orientation) override;
+
+protected:
+	// Called when the game starts
+	virtual void BeginPlay() override;
+
+public:	
+	// Called every frame
+	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
+
+
+private:
+	UPROPERTY(EditAnywhere)	float Distance; // distance the object can be moved from the center 
+
+};
diff --git a/Source/DisplayClusterExtensions/Public/GrabbingBehaviorOnPlaneComponent.h b/Source/DisplayClusterExtensions/Public/GrabbingBehaviorOnPlaneComponent.h
new file mode 100644
index 0000000000000000000000000000000000000000..d37120b788ce12fb8927b363ccf8aeca9c02275b
--- /dev/null
+++ b/Source/DisplayClusterExtensions/Public/GrabbingBehaviorOnPlaneComponent.h
@@ -0,0 +1,37 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GrabbingBehaviorComponent.h"
+#include "GrabbingBehaviorOnPlaneComponent.generated.h"
+
+
+UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
+class DISPLAYCLUSTEREXTENSIONS_API UGrabbingBehaviorOnPlaneComponent : public UGrabbingBehaviorComponent
+{
+	GENERATED_BODY()
+
+public:	
+	// Sets default values for this component's properties
+	UGrabbingBehaviorOnPlaneComponent();
+
+	// defining the constraint plane with these 3 parameters
+	UFUNCTION(BlueprintCallable) void SetDistance(float Dist);
+	UFUNCTION(BlueprintCallable) float GetDistance() const;
+	
+	virtual void HandleNewPositionAndDirection(FVector position, FQuat orientation) override;
+
+protected:
+	// Called when the game starts
+	virtual void BeginPlay() override;
+
+public:	
+	// Called every frame
+	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
+
+	
+private:
+	UPROPERTY(EditAnywhere) float Distance; // distance the object can be moved from the center 
+
+};
diff --git a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
index d5b3b4c8db035bbd1e0095f25d570de5940d0620..0570e8aa290c2325b927bca9d036108b0df95741 100644
--- a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
+++ b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
@@ -5,9 +5,11 @@
 #include "Cluster/IDisplayClusterClusterManager.h"
 #include "DisplayClusterPawn.h"
 #include "DisplayClusterSceneComponent.h"
+#include "Components/CapsuleComponent.h"
 #include "GameFramework/FloatingPawnMovement.h"
 #include "GameFramework/PawnMovementComponent.h"
 #include "GameFramework/RotatingMovementComponent.h"
+
 #include "MotionControllerComponent.h"
 #include "VirtualRealityPawn.generated.h"
 
@@ -15,6 +17,7 @@ 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")
 };
 
@@ -36,8 +39,8 @@ public:
 	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn") void OnRight(float Value);
 	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn") void OnTurnRate(float Rate);
 	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn") void OnLookUpRate(float Rate);
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, BlueprintCallable, Category = "Pawn") void OnFire(bool Pressed);
-	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn") void OnAction(bool Pressed, int32 Index);
+	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn") void OnBeginFire(); 
+	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn") void OnEndFire();   	
 
 	UFUNCTION(Category = "Pawn") float GetBaseTurnRate() const;
 	UFUNCTION(Category = "Pawn") void SetBaseTurnRate(float Value);
@@ -50,29 +53,32 @@ public:
 	UFUNCTION(Category = "Pawn") UDisplayClusterSceneComponent* GetLeftHandtargetComponent();
 	UFUNCTION(Category = "Pawn") UMotionControllerComponent* GetHmdLeftMotionControllerComponent();
 	UFUNCTION(Category = "Pawn") UMotionControllerComponent* GetHmdRightMotionControllerComponent();
+	UFUNCTION(Category = "Pawn") UMotionControllerComponent* GetHmdTracker1MotionControllerComponent();
+	UFUNCTION(Category = "Pawn") UMotionControllerComponent* GetHmdTracker2MotionControllerComponent();
 
 	UFUNCTION(Category = "Pawn") USceneComponent* GetHeadComponent();
 	UFUNCTION(Category = "Pawn") USceneComponent* GetLeftHandComponent();
 	UFUNCTION(Category = "Pawn") USceneComponent* GetRightHandComponent();
 
+
 	UFUNCTION(Category = "Pawn") USceneComponent* GetTrackingOriginComponent();
+
 private:
 	UFUNCTION(Category = "Pawn") USceneComponent* GetCaveCenterComponent();
 	UFUNCTION(Category = "Pawn") USceneComponent* GetShutterGlassesComponent();
+	UFUNCTION(Category = "Pawn") FTwoVectors GetHandRay(float Distance);   
+	UFUNCTION(Category = "Pawn") void HandlePhysicsAndAttachActor(AActor* HitActor);   
 
 public:
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") EVRNavigationModes NavigationMode = EVRNavigationModes::nav_mode_fly;
 
-  //Execute specified console command on all nDisplayCluster Nodes
-  UFUNCTION(Exec, BlueprintCallable, Category = "DisplayCluster") static void ClusterExecute(const FString& Command);
-
+	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:
 	FOnClusterEventListener ClusterEventListenerDelegate;
 	UFUNCTION() void HandleClusterEvent(const FDisplayClusterClusterEvent& Event);
-
 protected:
-	DECLARE_DELEGATE_OneParam(FFireDelegate, bool);
-	DECLARE_DELEGATE_TwoParams(FActionDelegate, bool, int32);
 
 	virtual void BeginPlay() override;
 	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
@@ -92,9 +98,13 @@ protected:
 	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UDisplayClusterSceneComponent* LeftHandTarget = nullptr;
 
 	// Use only when handling cross-device (PC, HMD, CAVE/ROLV) compatibility manually. HMD left  motion controller.
-	UMotionControllerComponent* HmdLeftMotionController = nullptr;
+	UPROPERTY() UMotionControllerComponent* HmdLeftMotionController = nullptr;
 	// Use only when handling cross-device (PC, HMD, CAVE/ROLV) compatibility manually. HMD right motion controller.
-	UMotionControllerComponent* HmdRightMotionController = nullptr;
+	UPROPERTY() UMotionControllerComponent* HmdRightMotionController = nullptr;
+
+	// used only for HMDs, tested with the additional Vive Trackers
+	UPROPERTY() UMotionControllerComponent* HmdTracker1 = nullptr;
+	UPROPERTY() UMotionControllerComponent* HmdTracker2 = nullptr;
 
 	// PC: Camera, HMD: Camera, CAVE/ROLV: Shutter glasses.
 	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) USceneComponent* Head = nullptr;
@@ -110,10 +120,33 @@ protected:
 	// Holding the Shutter Glasses Component that is attached to this Pawn
 	UPROPERTY() USceneComponent* ShutterGlasses = nullptr;
 
+	// Holding a reference to the actor that is currently being grabbed
+	UPROPERTY() AActor* GrabbedActor; 
+	// indicates if the grabbed actor was simulating physics before we grabbed it
+	UPROPERTY() bool bDidSimulatePhysics;
+	UPROPERTY(EditAnywhere) float MaxGrabDistance = 50;
+	UPROPERTY(EditAnywhere) float MaxClickDistance = 500;
+
 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") bool ShowHMDControllers = true;
 	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();
-};
\ No newline at end of file
+};
diff --git a/Source/DisplayClusterExtensions/Public/VirtualRealityUtilities.h b/Source/DisplayClusterExtensions/Public/VirtualRealityUtilities.h
index 1aef9acc66c039c996c28bb32a1ee830108f2730..f9135f848c48306f3760e1672886627aed39e33e 100644
--- a/Source/DisplayClusterExtensions/Public/VirtualRealityUtilities.h
+++ b/Source/DisplayClusterExtensions/Public/VirtualRealityUtilities.h
@@ -23,6 +23,9 @@ public:
 	UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsRoomMountedMode();
 	UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsHeadMountedMode();
 
+	UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsMaster();
+	UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsSlave();
+
 	UFUNCTION(BlueprintPure, Category = "DisplayCluster") static FString GetNodeName();
 	UFUNCTION(BlueprintPure, Category = "DisplayCluster") static float GetEyeDistance();
 
diff --git a/Source/DisplayClusterExtensionsEditor/DIsplayClusterExtensionsEditor.Build.cs b/Source/DisplayClusterExtensionsEditor/DIsplayClusterExtensionsEditor.Build.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7a96cbafacb2e141d57f368defa510b69fde4449
--- /dev/null
+++ b/Source/DisplayClusterExtensionsEditor/DIsplayClusterExtensionsEditor.Build.cs
@@ -0,0 +1,52 @@
+using UnrealBuildTool;
+
+public class DisplayClusterExtensionsEditor : ModuleRules
+{
+    public DisplayClusterExtensionsEditor(ReadOnlyTargetRules Target) : base(Target)
+    {
+        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
+        
+        PublicDependencyModuleNames.AddRange(
+            new string[] 
+            { 
+                "Core",
+			    "CoreUObject",
+			    "DisplayCluster",
+				"Engine",
+				"UnrealEd",
+				"ComponentVisualizers",
+				"HeadMountedDisplay",
+				"InputCore",
+				"DisplayClusterExtensions"
+
+
+                // ... add public dependencies that you statically link with here ...   
+            }
+        );
+
+        PrivateDependencyModuleNames.AddRange(
+            new string[] 
+            {
+              
+
+                // ... add private dependencies that you statically link with here ...    
+            }
+        );
+
+        PublicIncludePaths.AddRange(
+          new string[] 
+            {
+         
+                // ... add private dependencies that you statically link with here ...    
+            }
+        );
+
+        PrivateIncludePaths.AddRange(
+           new string[] 
+            {
+            
+                // ... add private dependencies that you statically link with here ...    
+            }
+        );
+    }
+}
\ No newline at end of file
diff --git a/Source/DisplayClusterExtensionsEditor/Private/DisplayClusterExtensionsEditor.cpp b/Source/DisplayClusterExtensionsEditor/Private/DisplayClusterExtensionsEditor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..22fcd5862b5a97353cc8ca08990999095d7ce25f
--- /dev/null
+++ b/Source/DisplayClusterExtensionsEditor/Private/DisplayClusterExtensionsEditor.cpp
@@ -0,0 +1,48 @@
+#include "DisplayClusterExtensionsEditor.h"
+
+#include "ComponentVisualizers.h"
+#include "GrabbingBehaviorOnLineVisualizer.h"
+#include "GrabbingBehaviorPlaneVisualizer.h"
+
+#include "GrabbingBehaviorOnPlaneComponent.h"
+#include "GrabbingBehaviorOnLineComponent.h"
+
+#include "UnrealEdGlobals.h"
+#include "Editor/UnrealEdEngine.h"
+
+IMPLEMENT_GAME_MODULE(FDisplayClusterExtensionsEditorModule, DisplayClusterExtensionsEditor);
+
+#define LOCTEXT_NAMESPACE "DisplayClusterExtensionsEdito"
+
+void FDisplayClusterExtensionsEditorModule::StartupModule()
+{
+	if (GUnrealEd != NULL)
+	{
+		TSharedPtr<FComponentVisualizer> LineVisualizer = MakeShareable(new FGrabbingBehaviorOnLineVisualizer());
+
+		if (LineVisualizer.IsValid())
+		{
+			GUnrealEd->RegisterComponentVisualizer(UGrabbingBehaviorOnLineComponent::StaticClass()->GetFName(), LineVisualizer);
+			LineVisualizer->OnRegister();
+		}
+
+		TSharedPtr<FComponentVisualizer> PlaneVisualizer = MakeShareable(new FGrabbingBehaviorPlaneVisualizer());
+		
+		if (PlaneVisualizer.IsValid())
+		{
+			GUnrealEd->RegisterComponentVisualizer(UGrabbingBehaviorOnPlaneComponent::StaticClass()->GetFName(), PlaneVisualizer);
+			PlaneVisualizer->OnRegister();
+		}
+	}
+}
+
+void FDisplayClusterExtensionsEditorModule::ShutdownModule()
+{
+	if (GUnrealEd != NULL)
+	{
+		GUnrealEd->UnregisterComponentVisualizer(UGrabbingBehaviorOnLineComponent::StaticClass()->GetFName());
+		GUnrealEd->UnregisterComponentVisualizer(UGrabbingBehaviorOnPlaneComponent::StaticClass()->GetFName());
+	}
+}
+
+#undef LOCTEXT_NAMESPACE
\ No newline at end of file
diff --git a/Source/DisplayClusterExtensionsEditor/Private/GrabbingBehaviorOnLineVisualizer.cpp b/Source/DisplayClusterExtensionsEditor/Private/GrabbingBehaviorOnLineVisualizer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..27fee70ab128be1dbc83ca76a191ac3e531f1efe
--- /dev/null
+++ b/Source/DisplayClusterExtensionsEditor/Private/GrabbingBehaviorOnLineVisualizer.cpp
@@ -0,0 +1,35 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "GrabbingBehaviorOnLineVisualizer.h"
+#include "GrabbingBehaviorOnLineComponent.h"
+
+#include "SceneManagement.h"
+
+FGrabbingBehaviorOnLineVisualizer::FGrabbingBehaviorOnLineVisualizer()
+{
+}
+
+FGrabbingBehaviorOnLineVisualizer::~FGrabbingBehaviorOnLineVisualizer()
+{
+}
+
+
+// Fill out your copyright notice in the Description page of Project Settings.
+
+void FGrabbingBehaviorOnLineVisualizer::DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI) {
+
+
+	const UGrabbingBehaviorOnLineComponent* LineBehavior = Cast<const UGrabbingBehaviorOnLineComponent>(Component);
+
+	if (LineBehavior != nullptr)
+	{
+		FVector Attachment = LineBehavior->GetComponentLocation();
+		FVector Forward = LineBehavior->GetComponentQuat().GetUpVector();
+		float Distance = LineBehavior->GetDistance();
+
+		PDI->DrawLine(Attachment + Forward * Distance, Attachment - Forward * Distance, FColor::Blue, SDPG_World);
+	}
+}
+
+
diff --git a/Source/DisplayClusterExtensionsEditor/Private/GrabbingBehaviorPlaneVisualizer.cpp b/Source/DisplayClusterExtensionsEditor/Private/GrabbingBehaviorPlaneVisualizer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..455e62ce23a46d09f771097bbac41c61a1c54bba
--- /dev/null
+++ b/Source/DisplayClusterExtensionsEditor/Private/GrabbingBehaviorPlaneVisualizer.cpp
@@ -0,0 +1,43 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "GrabbingBehaviorPlaneVisualizer.h"
+#include "GrabbingBehaviorOnPlaneComponent.h"
+#include "SceneManagement.h"
+
+FGrabbingBehaviorPlaneVisualizer::FGrabbingBehaviorPlaneVisualizer()
+{
+}
+
+FGrabbingBehaviorPlaneVisualizer::~FGrabbingBehaviorPlaneVisualizer()
+{
+}
+
+void FGrabbingBehaviorPlaneVisualizer::DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI) {
+
+
+	const UGrabbingBehaviorOnPlaneComponent* PlaneBehavior = Cast<const UGrabbingBehaviorOnPlaneComponent>(Component);
+
+	if (PlaneBehavior != nullptr)
+	{
+		FVector Attachment = PlaneBehavior->GetComponentLocation();
+		FVector Forward = PlaneBehavior->GetComponentQuat().GetUpVector();
+		FVector Right = PlaneBehavior->GetComponentQuat().GetRightVector();
+		FVector Next;
+		Right.Normalize();
+
+
+		float Distance = PlaneBehavior->GetDistance();
+		int Segments = 60;
+		check(360% Segments == 0 && "circle cannot be divided equally");
+
+		for (int i = 1; i < Segments + 1; i++) // draw circle using lines
+		{
+			Next = Right.RotateAngleAxis(360/Segments, Forward);
+
+			PDI->DrawLine(Attachment + Right*Distance,Attachment + Next*Distance, FColor::Blue, SDPG_World);
+			Right = Next;
+		}
+	}
+}
+
diff --git a/Source/DisplayClusterExtensionsEditor/Public/DisplayClusterExtensionsEditor.h b/Source/DisplayClusterExtensionsEditor/Public/DisplayClusterExtensionsEditor.h
new file mode 100644
index 0000000000000000000000000000000000000000..0858723e62a2600af6824861fff42f519ee8833f
--- /dev/null
+++ b/Source/DisplayClusterExtensionsEditor/Public/DisplayClusterExtensionsEditor.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Modules/ModuleInterface.h"
+#include "ModuleManager.h"
+
+class FDisplayClusterExtensionsEditorModule : public IModuleInterface
+{
+public:
+	// Begin IModuleInterface implementation
+	virtual void StartupModule() override;
+	virtual void ShutdownModule() override;
+	// End IModuleInterface implementation
+
+};
\ No newline at end of file
diff --git a/Source/DisplayClusterExtensionsEditor/Public/GrabbingBehaviorOnLineVisualizer.h b/Source/DisplayClusterExtensionsEditor/Public/GrabbingBehaviorOnLineVisualizer.h
new file mode 100644
index 0000000000000000000000000000000000000000..60257dbd5fa090d7703c867a9d2c5f1a4b45e2b7
--- /dev/null
+++ b/Source/DisplayClusterExtensionsEditor/Public/GrabbingBehaviorOnLineVisualizer.h
@@ -0,0 +1,24 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "ComponentVisualizer.h"
+/**
+ * 
+ */
+class FPrimitiveDrawInterface;
+class FSceneView;
+
+class DISPLAYCLUSTEREXTENSIONSEDITOR_API FGrabbingBehaviorOnLineVisualizer : public FComponentVisualizer
+{
+public:
+	FGrabbingBehaviorOnLineVisualizer();
+	~FGrabbingBehaviorOnLineVisualizer();
+
+	virtual void DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI) override;
+};
+
+
+
+
diff --git a/Source/DisplayClusterExtensionsEditor/Public/GrabbingBehaviorPlaneVisualizer.h b/Source/DisplayClusterExtensionsEditor/Public/GrabbingBehaviorPlaneVisualizer.h
new file mode 100644
index 0000000000000000000000000000000000000000..517bb3ca97e066043f9de30b3fa103b6a236e305
--- /dev/null
+++ b/Source/DisplayClusterExtensionsEditor/Public/GrabbingBehaviorPlaneVisualizer.h
@@ -0,0 +1,20 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "ComponentVisualizer.h"
+/**
+ * 
+ */
+class FPrimitiveDrawInterface;
+class FSceneView;
+
+class DISPLAYCLUSTEREXTENSIONSEDITOR_API FGrabbingBehaviorPlaneVisualizer : public FComponentVisualizer
+{
+public:
+	FGrabbingBehaviorPlaneVisualizer();
+	~FGrabbingBehaviorPlaneVisualizer();
+
+	virtual void DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI) override;
+};
diff --git a/nDisplayExtensions.uplugin b/nDisplayExtensions.uplugin
index 87da40fd19d5c7397b17ac213df5f60c649378d4..f9391e6242275ad266313d4e45974c9b1cd5985c 100644
--- a/nDisplayExtensions.uplugin
+++ b/nDisplayExtensions.uplugin
@@ -19,7 +19,15 @@
       "Name": "DisplayClusterExtensions",
       "Type": "Developer",
       "LoadingPhase": "Default"
-    }
+    },
+	
+	{	
+	  "Name": "DisplayClusterExtensionsEditor",
+	  "Type": "Editor",
+	  "LoadingPhase": "PostEngineInit"
+	}
+
+
   ],
   "Plugins": [
     {