diff --git a/Source/nDisplayExtensions/Private/DisplayClusterGameModeCAVE.cpp b/Source/nDisplayExtensions/Private/DisplayClusterGameModeCAVE.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90f74ef07c5398e35cccdca6eba71554a06aa4f2 --- /dev/null +++ b/Source/nDisplayExtensions/Private/DisplayClusterGameModeCAVE.cpp @@ -0,0 +1,8 @@ +#include "DisplayClusterGameModeCAVE.h" +#include "DisplayClusterPawnCAVE.h" + +ADisplayClusterGameModeCAVE::ADisplayClusterGameModeCAVE() : Super() +{ + if (!bIsDisplayClusterActive) return; + DefaultPawnClass = ADisplayClusterPawnCAVE::StaticClass(); +} diff --git a/Source/nDisplayExtensions/Private/DisplayClusterPawnBase.cpp b/Source/nDisplayExtensions/Private/DisplayClusterPawnBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..270e3f17e86eca27e4a5ce3d22b4901766d7762c --- /dev/null +++ b/Source/nDisplayExtensions/Private/DisplayClusterPawnBase.cpp @@ -0,0 +1,153 @@ +#include "DisplayClusterPawnBase.h" + +#include "Engine/World.h" +#include "Game/IDisplayClusterGameManager.h" +#include "GameFramework/WorldSettings.h" +#include "DisplayClusterSceneComponentSyncParent.h" +#include "DisplayClusterSettings.h" +#include "DisplayClusterGameMode.h" +#include "IDisplayCluster.h" +#include "Kismet/GameplayStatics.h" + +ADisplayClusterPawnBase::ADisplayClusterPawnBase(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) +{ + MovementComponent = CreateDefaultSubobject<UFloatingPawnMovement> (TEXT("MovementComponent0")); + MovementComponent->UpdatedComponent = RootComponent; + + RotatingComponent = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotatingComponent0")); + RotatingComponent->UpdatedComponent = RootComponent; + RotatingComponent->bRotationInLocalSpace = true; + RotatingComponent->PivotTranslation = FVector::ZeroVector; + RotatingComponent->RotationRate = FRotator::ZeroRotator; + + RotatingComponent2 = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotatingComponent1")); + RotatingComponent2->UpdatedComponent = RootComponent; + RotatingComponent2->bRotationInLocalSpace = false; + RotatingComponent2->PivotTranslation = FVector::ZeroVector; + RotatingComponent2->RotationRate = FRotator::ZeroRotator; + + BaseTurnRate = 45.f; + BaseLookUpRate = 45.f; +} + +void ADisplayClusterPawnBase::MoveForward (float Value) +{ + if (Value == 0.f) return; + AddMovementInput((TranslationDirection ? TranslationDirection : RootComponent)->GetForwardVector(), Value); +} +void ADisplayClusterPawnBase::MoveRight (float Value) +{ + if (Value == 0.f) return; + AddMovementInput((TranslationDirection ? TranslationDirection : RootComponent)->GetRightVector (), Value); +} +void ADisplayClusterPawnBase::MoveUp (float Value) +{ + if (Value == 0.f) return; + AddMovementInput((TranslationDirection ? TranslationDirection : RootComponent)->GetUpVector (), Value); +} +void ADisplayClusterPawnBase::TurnAtRate (float Rate ) +{ + if (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster) + { + if (!RotatingComponent->UpdatedComponent) return; + auto Manager = IDisplayCluster::Get().GetGameMgr(); + if (!Manager) return; + auto Camera = Manager->GetActiveCamera(); + if (!Camera ) return; + + const FTransform TransformToRotate = RotatingComponent->UpdatedComponent->GetComponentTransform(); + const FVector RotateAroundPivot = TransformToRotate.InverseTransformPositionNoScale(Camera->GetComponentLocation()); + RotatingComponent->PivotTranslation = RotateAroundPivot; + RotatingComponent->RotationRate = FRotator(RotatingComponent->RotationRate.Pitch, Rate * BaseTurnRate, 0.f); + } + else if (Rate != 0.f) + AddControllerYawInput(BaseTurnRate * Rate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation); +} +void ADisplayClusterPawnBase::TurnAtRate2 (float Rate ) +{ + if (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster) + { + if (!RotatingComponent2->UpdatedComponent) return; + auto Manager = IDisplayCluster::Get().GetGameMgr(); + if (!Manager) return; + auto Camera = Manager->GetActiveCamera(); + if (!Camera ) return; + + const FTransform TransformToRotate = RotatingComponent2->UpdatedComponent->GetComponentTransform(); + const FVector RotateAroundPivot = TransformToRotate.InverseTransformPositionNoScale(Camera->GetComponentLocation()); + RotatingComponent2->PivotTranslation = RotateAroundPivot; + RotatingComponent2->RotationRate = FRotator(RotatingComponent2->RotationRate.Pitch, Rate * BaseTurnRate, 0.f); + } + else if (Rate != 0.f) + AddControllerYawInput(BaseTurnRate * Rate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation); +} +void ADisplayClusterPawnBase::LookUpAtRate(float Rate ) +{ + if (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster) + { + //@note: usually CAVE-like systems don't use roll and pitch rotation since it can cause dizziness. +#if 0 + //@todo: rotate around active camera + auto Manager = IDisplayCluster::Get().GetGameMgr(); + if (!Manager) return; + auto Camera = Manager->GetActiveCamera(); + if (!Camera ) return; + + RotatingComponent->bRotationInLocalSpace = true; + RotatingComponent->PivotTranslation = FVector::ZeroVector; + +#endif + } + else if (Rate != 0.f) + { + AddControllerPitchInput(BaseTurnRate * Rate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation); + } +} + +void ADisplayClusterPawnBase::BeginPlay () +{ + Super::BeginPlay(); + + if (!IDisplayCluster::Get().IsModuleInitialized() || !IDisplayCluster::Get().IsAvailable()) return; + + auto IsCluster = (IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster); + bUseControllerRotationYaw = !IsCluster; + bUseControllerRotationPitch = !IsCluster; + bUseControllerRotationRoll = !IsCluster; + + 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; + BaseLookUpRate = Settings->RotationSpeed; +} +void ADisplayClusterPawnBase::Tick (float DeltaSeconds) +{ + Super::Tick(DeltaSeconds); + const float Mult = GetWorld()->GetWorldSettings()->WorldToMeters / 100.f; + SetActorScale3D(FVector(Mult, Mult, Mult)); +} +UPawnMovementComponent* ADisplayClusterPawnBase::GetMovementComponent() const +{ + return MovementComponent; +} + +void ADisplayClusterPawnBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + check(PlayerInputComponent); + Super::SetupPlayerInputComponent(PlayerInputComponent); + if (PlayerInputComponent) + { + PlayerInputComponent->BindAxis("MoveForward", this, &ADisplayClusterPawnBase::MoveForward ); + PlayerInputComponent->BindAxis("MoveRight" , this, &ADisplayClusterPawnBase::MoveRight ); + PlayerInputComponent->BindAxis("MoveUp" , this, &ADisplayClusterPawnBase::MoveUp ); + PlayerInputComponent->BindAxis("TurnRate" , this, &ADisplayClusterPawnBase::TurnAtRate2 ); + PlayerInputComponent->BindAxis("LookUpRate" , this, &ADisplayClusterPawnBase::LookUpAtRate); + } +} diff --git a/Source/nDisplayExtensions/Private/DisplayClusterPawnCAVE.cpp b/Source/nDisplayExtensions/Private/DisplayClusterPawnCAVE.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a50b178c960acc9bd21ef00ba07c70751241b02f --- /dev/null +++ b/Source/nDisplayExtensions/Private/DisplayClusterPawnCAVE.cpp @@ -0,0 +1,17 @@ +#include "DisplayClusterPawnCAVE.h" + +#include "Game/IDisplayClusterGameManager.h" +#include "IDisplayCluster.h" + +void ADisplayClusterPawnCAVE::BeginPlay() +{ + Flystick = IDisplayCluster::Get().GetGameMgr()->GetNodeById("flystick_tracked"); +} +void ADisplayClusterPawnCAVE::MoveForward(float value) +{ + if (!Flystick) + Flystick = IDisplayCluster::Get().GetGameMgr()->GetNodeById("flystick_tracked"); + if (!Flystick || value == 0.0f) + return; + AddMovementInput(Flystick->GetForwardVector(), value); +} diff --git a/Source/nDisplayExtensions/Public/DisplayClusterGameModeCAVE.h b/Source/nDisplayExtensions/Public/DisplayClusterGameModeCAVE.h new file mode 100644 index 0000000000000000000000000000000000000000..2c68f15d371f05d18fb4f6fc97196b3e772fe0b6 --- /dev/null +++ b/Source/nDisplayExtensions/Public/DisplayClusterGameModeCAVE.h @@ -0,0 +1,14 @@ +#pragma once + +#include "CoreMinimal.h" +#include "DisplayClusterGameMode.h" +#include "DisplayClusterGameModeCAVE.generated.h" + +UCLASS() +class NDISPLAYEXTENSIONS_API ADisplayClusterGameModeCAVE : public ADisplayClusterGameMode +{ + GENERATED_BODY() + +public: + ADisplayClusterGameModeCAVE(); +}; \ No newline at end of file diff --git a/Source/nDisplayExtensions/Public/DisplayClusterPawnBase.h b/Source/nDisplayExtensions/Public/DisplayClusterPawnBase.h new file mode 100644 index 0000000000000000000000000000000000000000..5eb76f52ff42409c369b56f14f3ff7f3e0403217 --- /dev/null +++ b/Source/nDisplayExtensions/Public/DisplayClusterPawnBase.h @@ -0,0 +1,37 @@ +#pragma once + +#include "Components/InputComponent.h" +#include "GameFramework/FloatingPawnMovement.h" +#include "GameFramework/PawnMovementComponent.h" +#include "GameFramework/RotatingMovementComponent.h" +#include "CoreMinimal.h" +#include "DisplayClusterPawn.h" +#include "DisplayClusterPawnBase.generated.h" + +UCLASS() +class NDISPLAYEXTENSIONS_API ADisplayClusterPawnBase : public ADisplayClusterPawn +{ + GENERATED_UCLASS_BODY() + +public: + UFUNCTION(BlueprintCallable, Category = "Pawn") virtual void MoveForward (float Value); + UFUNCTION(BlueprintCallable, Category = "Pawn") virtual void MoveRight (float Value); + UFUNCTION(BlueprintCallable, Category = "Pawn") virtual void MoveUp (float Value); + UFUNCTION(BlueprintCallable, Category = "Pawn") virtual void TurnAtRate (float Rate ); + UFUNCTION(BlueprintCallable, Category = "Pawn") virtual void TurnAtRate2 (float Rate ); + UFUNCTION(BlueprintCallable, Category = "Pawn") virtual void LookUpAtRate(float Rate ); + + virtual void BeginPlay () override; + virtual void Tick (float DeltaSeconds) override; + virtual UPawnMovementComponent* GetMovementComponent() const override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") float BaseTurnRate ; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") float BaseLookUpRate; + +protected: + virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override; + + UPROPERTY(Category = Pawn, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) UFloatingPawnMovement* MovementComponent ; + UPROPERTY(Category = Pawn, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) URotatingMovementComponent* RotatingComponent ; + UPROPERTY(Category = Pawn, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) URotatingMovementComponent* RotatingComponent2; +}; \ No newline at end of file diff --git a/Source/nDisplayExtensions/Public/DisplayClusterPawnCAVE.h b/Source/nDisplayExtensions/Public/DisplayClusterPawnCAVE.h new file mode 100644 index 0000000000000000000000000000000000000000..48c64c90681f0aadf6b293247bfc3a9df5eb5b0b --- /dev/null +++ b/Source/nDisplayExtensions/Public/DisplayClusterPawnCAVE.h @@ -0,0 +1,19 @@ +#pragma once + +#include "CoreMinimal.h" +#include "DisplayClusterPawnBase.h" +#include "DisplayClusterSceneComponent.h" +#include "DisplayClusterPawnCAVE.generated.h" + +UCLASS() +class NDISPLAYEXTENSIONS_API ADisplayClusterPawnCAVE : public ADisplayClusterPawnBase +{ + GENERATED_BODY() + +public: + virtual void BeginPlay() override; + virtual void MoveForward(float value) override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Pawn") + UDisplayClusterSceneComponent* Flystick = nullptr; +};