diff --git a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp index 1bcdfdec087afd30462f1cc503afd885c200c720..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; + LeftMotionController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("LeftMotionController")); + LeftMotionController->SetupAttachment (RootComponent); + LeftMotionController->SetTrackingSource (EControllerHand::Left); + LeftMotionController->SetShowDeviceModel (true ); + LeftMotionController->SetVisibility (false); - AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events. + 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,44 +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; + 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 ; + } - 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 (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster) + { + // Requires a scene node called flystick in the config. + Flystick = IDisplayCluster::Get().GetGameMgr()->GetNodeById(TEXT("flystick")); - RightMotionControllerComponent = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("RightMotionControllerComponent")); - RightMotionControllerComponent->SetTrackingSource (EControllerHand::Right); - RightMotionControllerComponent->SetShowDeviceModel(true); + 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 () @@ -146,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; };