diff --git a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
index abfb9095407a0d8fd99af00eb422fafc372a3702..8281ebbb15dff70fbc6bb41303f81854255bf40c 100644
--- a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
+++ b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp
@@ -12,52 +12,60 @@
AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
- MovementComponent = CreateDefaultSubobject<UFloatingPawnMovement> (TEXT("MovementComponent0"));
- MovementComponent->UpdatedComponent = RootComponent;
+ AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events.
+
+ Movement = CreateDefaultSubobject<UFloatingPawnMovement> (TEXT("Movement"));
+ Movement->UpdatedComponent = RootComponent;
- RotatingComponent = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotatingComponent0"));
- RotatingComponent->UpdatedComponent = RootComponent;
- RotatingComponent->bRotationInLocalSpace = false;
- RotatingComponent->PivotTranslation = FVector::ZeroVector;
- RotatingComponent->RotationRate = FRotator::ZeroRotator;
+ RotatingMovement = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotatingMovement"));
+ RotatingMovement->UpdatedComponent = RootComponent;
+ RotatingMovement->bRotationInLocalSpace = false;
+ RotatingMovement->PivotTranslation = FVector::ZeroVector;
+ RotatingMovement->RotationRate = FRotator::ZeroRotator;
- TranslationDirection = RootComponent;
-
- AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events.
+ LeftMotionController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("LeftMotionController"));
+ LeftMotionController->SetupAttachment (RootComponent);
+ LeftMotionController->SetTrackingSource (EControllerHand::Left);
+ LeftMotionController->SetShowDeviceModel (true );
+ LeftMotionController->SetVisibility (false);
+
+ RightMotionController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("RightMotionController"));
+ RightMotionController->SetupAttachment (RootComponent);
+ RightMotionController->SetTrackingSource (EControllerHand::Right);
+ RightMotionController->SetShowDeviceModel(true );
+ RightMotionController->SetVisibility (false);
}
void AVirtualRealityPawn::OnForward_Implementation (float Value)
{
- AddMovementInput(TranslationDirection->GetForwardVector(), Value);
+ AddMovementInput(Forward->GetForwardVector(), Value);
}
void AVirtualRealityPawn::OnRight_Implementation (float Value)
{
- AddMovementInput(TranslationDirection->GetRightVector (), Value);
+ AddMovementInput(Forward->GetRightVector (), Value);
}
void AVirtualRealityPawn::OnTurnRate_Implementation (float Rate )
{
if (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster)
{
- if (!RotatingComponent->UpdatedComponent || !IDisplayCluster::Get().GetGameMgr() || !IDisplayCluster::Get().GetGameMgr()->GetActiveCamera()) return;
-
- const FVector CameraLocation = IDisplayCluster::Get().GetGameMgr()->GetActiveCamera()->GetComponentLocation();
- RotatingComponent->PivotTranslation = RotatingComponent->UpdatedComponent->GetComponentTransform().InverseTransformPositionNoScale(CameraLocation);
- RotatingComponent->RotationRate = FRotator(RotatingComponent->RotationRate.Pitch, Rate * BaseTurnRate, 0.0f);
+ 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(BaseTurnRate * Rate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
+ AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
}
}
void AVirtualRealityPawn::OnLookUpRate_Implementation(float Rate )
{
if (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster)
{
- // User-centered projection causes motion sickness on look up interaction hence not implemented.
+ // User-centered projection causes simulation sickness on look up interaction hence not implemented.
}
else
{
- AddControllerPitchInput(BaseTurnRate * Rate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
+ AddControllerPitchInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
}
}
void AVirtualRealityPawn::OnFire_Implementation (bool Pressed)
@@ -73,46 +81,61 @@ void AVirtualRealityPawn::BeginPlay ()
{
Super::BeginPlay();
- if (!IDisplayCluster::Get().IsModuleInitialized() || !IDisplayCluster::Get().IsAvailable()) return;
-
- auto IsCluster = (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster);
- bUseControllerRotationYaw = !IsCluster;
- bUseControllerRotationPitch = !IsCluster;
- bUseControllerRotationRoll = !IsCluster;
-
+ // Display cluster settings apply to all setups (PC, HMD, CAVE/ROLV) despite the unfortunate name due to being an UE4 internal.
TArray<AActor*> SettingsActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ADisplayClusterSettings::StaticClass(), SettingsActors);
- if (SettingsActors.Num() == 0) return;
-
- ADisplayClusterSettings* Settings = Cast<ADisplayClusterSettings>(SettingsActors[0]);
- MovementComponent->MaxSpeed = Settings->MovementMaxSpeed ;
- MovementComponent->Acceleration = Settings->MovementAcceleration;
- MovementComponent->Deceleration = Settings->MovementDeceleration;
- MovementComponent->TurningBoost = Settings->MovementTurningBoost;
- BaseTurnRate = Settings->RotationSpeed ;
-
- if (UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled())
- {
- LeftMotionControllerComponent = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("LeftMotionControllerComponent"));
- LeftMotionControllerComponent->SetTrackingSource (EControllerHand::Left);
- LeftMotionControllerComponent->SetShowDeviceModel(true);
+ if (SettingsActors.Num() > 0)
+ {
+ ADisplayClusterSettings* Settings = Cast<ADisplayClusterSettings>(SettingsActors[0]);
+ Movement->MaxSpeed = Settings->MovementMaxSpeed ;
+ Movement->Acceleration = Settings->MovementAcceleration;
+ Movement->Deceleration = Settings->MovementDeceleration;
+ Movement->TurningBoost = Settings->MovementTurningBoost;
+ BaseTurnRate = Settings->RotationSpeed ;
+ }
- RightMotionControllerComponent = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("RightMotionControllerComponent"));
- RightMotionControllerComponent->SetTrackingSource (EControllerHand::Right);
- RightMotionControllerComponent->SetShowDeviceModel(true);
+ if (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster)
+ {
+ // Requires a scene node called flystick in the config.
+ Flystick = IDisplayCluster::Get().GetGameMgr()->GetNodeById(TEXT("flystick"));
- TranslationDirection = LeftMotionControllerComponent;
+ Forward = Flystick;
+ LeftHand = Flystick;
+ RightHand = Flystick;
+ }
+ else if (UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled())
+ {
+ LeftMotionController ->SetVisibility(true);
+ RightMotionController->SetVisibility(true);
+
+ Forward = LeftMotionController ;
+ LeftHand = LeftMotionController ;
+ RightHand = RightMotionController;
+ }
+ else
+ {
+ bUseControllerRotationYaw = true;
+ bUseControllerRotationPitch = true;
+ bUseControllerRotationRoll = true;
+
+ Forward = RootComponent;
+ LeftHand = RootComponent;
+ RightHand = RootComponent;
}
}
void AVirtualRealityPawn::Tick (float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
-
+
+ // Flystick might not be available at start, hence is checked every frame.
if (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster && !Flystick)
- {
- Flystick = IDisplayCluster::Get().GetGameMgr()->GetNodeById(TEXT("flystick")); // Note: Requires a scene node called flystick in the config. Make settable.
- if (Flystick)
- TranslationDirection = Flystick;
+ {
+ // Requires a scene node called flystick in the config.
+ Flystick = IDisplayCluster::Get().GetGameMgr()->GetNodeById(TEXT("flystick"));
+
+ Forward = Flystick;
+ LeftHand = Flystick;
+ RightHand = Flystick;
}
}
void AVirtualRealityPawn::BeginDestroy ()
@@ -148,5 +171,5 @@ void AVirtualRealityPawn::SetupPlayerInputComponent (UInputC
}
UPawnMovementComponent* AVirtualRealityPawn::GetMovementComponent () const
{
- return MovementComponent;
+ return Movement;
}
diff --git a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
index 8cae171605da946cd8072ee4b70acf591a4f7216..0569fdfa0a747634943faa43be1555cac59c2e60 100644
--- a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
+++ b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h
@@ -23,9 +23,6 @@ public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn") void OnFire (bool Pressed);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn") void OnAction (bool Pressed, int32 Index);
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") float BaseTurnRate = 45.0f ;
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") UDisplayClusterSceneComponent* Flystick = nullptr;
-
protected:
DECLARE_DELEGATE_OneParam (FFireDelegate , bool);
DECLARE_DELEGATE_TwoParams(FActionDelegate, bool, int32);
@@ -36,8 +33,21 @@ protected:
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
virtual UPawnMovementComponent* GetMovementComponent () const override;
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UFloatingPawnMovement* MovementComponent = nullptr;
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) URotatingMovementComponent* RotatingComponent = nullptr;
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UMotionControllerComponent* LeftMotionControllerComponent = nullptr;
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UMotionControllerComponent* RightMotionControllerComponent = nullptr;
+ UPROPERTY(EditAnywhere , BlueprintReadWrite, Category = "Pawn", meta = (AllowPrivateAccess = "true")) float BaseTurnRate = 45.0f ;
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly , Category = "Pawn", meta = (AllowPrivateAccess = "true")) UFloatingPawnMovement* Movement = nullptr;
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly , Category = "Pawn", meta = (AllowPrivateAccess = "true")) URotatingMovementComponent* RotatingMovement = nullptr;
+
+ // Use only when handling cross-device (PC, HMD, CAVE/ROLV) compatibility manually. CAVE/ROLV flystick.
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly , Category = "Pawn", meta = (AllowPrivateAccess = "true")) UDisplayClusterSceneComponent* Flystick = nullptr;
+ // Use only when handling cross-device (PC, HMD, CAVE/ROLV) compatibility manually. HMD left motion controller.
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly , Category = "Pawn", meta = (AllowPrivateAccess = "true")) UMotionControllerComponent* LeftMotionController = nullptr;
+ // Use only when handling cross-device (PC, HMD, CAVE/ROLV) compatibility manually. HMD right motion controller.
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly , Category = "Pawn", meta = (AllowPrivateAccess = "true")) UMotionControllerComponent* RightMotionController = nullptr;
+
+ // PC: RootComponent, HMD: LeftMotionController , CAVE/ROLV: Flystick. Movement follows this component.
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly , Category = "Pawn", meta = (AllowPrivateAccess = "true")) USceneComponent* Forward = nullptr;
+ // PC: RootComponent, HMD: LeftMotionController , CAVE/ROLV: Flystick. Useful for line trace (e.g. for holding objects).
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly , Category = "Pawn", meta = (AllowPrivateAccess = "true")) USceneComponent* LeftHand = nullptr;
+ // PC: RootComponent, HMD: RightMotionController, CAVE/ROLV: Flystick. Useful for line trace (e.g. for holding objects).
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly , Category = "Pawn", meta = (AllowPrivateAccess = "true")) USceneComponent* RightHand = nullptr;
};