diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..56a33f06425feaaf69a41c710b30f9f990a3dbb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,74 @@ +# Visual Studio 2015 user specific files +.vs/ + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +*.ipa + +# These project files can be generated by the engine +*.xcodeproj +*.xcworkspace +*.sln +*.suo +*.opensdf +*.sdf +*.VC.db +*.VC.opendb + +# Precompiled Assets +SourceArt/**/*.png +SourceArt/**/*.tga + +# Binary Files +Binaries/* +Plugins/*/Binaries/* + +# Builds +Build/* + +# Whitelist PakBlacklist-<BuildConfiguration>.txt files +!Build/*/ +Build/*/** +!Build/*/PakBlacklist*.txt + +# Don't ignore icon files in Build +!Build/**/*.ico + +# Built data for maps +*_BuiltData.uasset + +# Configuration files generated by the Editor +Saved/* + +# Compiled source files for the engine to use +Intermediate/* +Plugins/*/Intermediate/* + +# Cache files for the editor to use +DerivedDataCache/* \ No newline at end of file diff --git a/Resources/Icon128.png b/Resources/Icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..77dcd239fa6f636b8032bdb878d85b8eacb8ef7f Binary files /dev/null and b/Resources/Icon128.png differ 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/Private/nDisplayExtensions.cpp b/Source/nDisplayExtensions/Private/nDisplayExtensions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b2d5aadf5dd4a4a3f1d9405205cc4f530ac3b9c --- /dev/null +++ b/Source/nDisplayExtensions/Private/nDisplayExtensions.cpp @@ -0,0 +1,16 @@ +#include "nDisplayExtensions.h" + +#define LOCTEXT_NAMESPACE "FnDisplayExtensionsModule" + +void FnDisplayExtensionsModule::StartupModule() +{ + +} +void FnDisplayExtensionsModule::ShutdownModule() +{ + +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FnDisplayExtensionsModule, nDisplayExtensions) \ No newline at end of file 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; +}; diff --git a/Source/nDisplayExtensions/Public/nDisplayExtensions.h b/Source/nDisplayExtensions/Public/nDisplayExtensions.h new file mode 100644 index 0000000000000000000000000000000000000000..d5e9096991ad70694240b1ce329f2222ba2456cb --- /dev/null +++ b/Source/nDisplayExtensions/Public/nDisplayExtensions.h @@ -0,0 +1,11 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class NDISPLAYEXTENSIONS_API FnDisplayExtensionsModule : public IModuleInterface +{ +public: + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Source/nDisplayExtensions/nDisplayExtensions.Build.cs b/Source/nDisplayExtensions/nDisplayExtensions.Build.cs new file mode 100644 index 0000000000000000000000000000000000000000..22f9d9dcf3e85da6b4565f32f5543364fc735762 --- /dev/null +++ b/Source/nDisplayExtensions/nDisplayExtensions.Build.cs @@ -0,0 +1,52 @@ +using UnrealBuildTool; + +public class nDisplayExtensions : ModuleRules +{ + public nDisplayExtensions(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] + { + + } + ); + + + PrivateIncludePaths.AddRange( + new string[] + { + + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "DisplayCluster", + "Engine", + "InputCore" + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + + } + ); + } +} diff --git a/nDisplayExtensions.uplugin b/nDisplayExtensions.uplugin new file mode 100644 index 0000000000000000000000000000000000000000..31dbd3836665bce4091212b10f9e0d711e258bc8 --- /dev/null +++ b/nDisplayExtensions.uplugin @@ -0,0 +1,29 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "nDisplayExtensions", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "nDisplayExtensions", + "Type": "Developer", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "nDisplay", + "Enabled": true + } + ] +} \ No newline at end of file