Skip to content
Snippets Groups Projects
Commit 3fdb8b79 authored by Sebastian Pape's avatar Sebastian Pape
Browse files

Merge branch 'feature/CAVEOverlay' into 'develop'

Feature/cave overlay

See merge request VR-Group/unreal-development/ndisplayextensions!33
parents be6baacc 8eb388a3
Branches
No related tags found
1 merge request!33Feature/cave overlay
Showing
with 617 additions and 5 deletions
File added
File added
File added
File added
File added
...@@ -30,7 +30,11 @@ public class DisplayClusterExtensions : ModuleRules ...@@ -30,7 +30,11 @@ public class DisplayClusterExtensions : ModuleRules
"DisplayCluster", "DisplayCluster",
"Engine", "Engine",
"HeadMountedDisplay", "HeadMountedDisplay",
"InputCore" "InputCore",
"UMG",
"Slate",
"SlateCore",
"DeveloperSettings"
} }
); );
......
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "Cluster/CAVEOverlay/CAVEOverlay.h"
void FCAVEOverlay::Register()
{
On_Post_World_Initialization_Delegate.BindRaw(this, &FCAVEOverlay::OnSessionStart);
SessionStartDelegate = FWorldDelegates::OnPostWorldInitialization.Add(On_Post_World_Initialization_Delegate);
}
void FCAVEOverlay::Unregister() const
{
FWorldDelegates::OnPostWorldInitialization.Remove(SessionStartDelegate);
}
void FCAVEOverlay::OnSessionStart(UWorld* World, const UWorld::InitializationValues)
{
if (!World->IsGameWorld())
return;
const UCAVEOverlaySettings* Settings = GetDefault<UCAVEOverlaySettings>();
/* Test if we already spawned a CAVEOverlayController */
TArray<AActor*> Actors;
UGameplayStatics::GetAllActorsOfClass(World, ACAVEOverlayController::StaticClass(), Actors);
if((Settings->DefaultActivationType == DefaultActivationType_ON
!= Settings->excludedMaps.ContainsByPredicate(
[World](const FSoftObjectPath& Map) {return Map.GetAssetName() == World->GetName();}
)) && Actors.Num() == 0)
{
World->SpawnActor(ACAVEOverlayController::StaticClass());
}
}
#include "Cluster/CAVEOverlay/CAVEOverlayController.h"
#include "CoreMinimal.h"
#include "Cluster/CAVEOverlay/DoorOverlayData.h"
#include "IDisplayCluster.h"
#include "IXRTrackingSystem.h"
#include "Cluster/IDisplayClusterClusterManager.h"
#include "Game/IDisplayClusterGameManager.h"
#include "UObject/ConstructorHelpers.h"
#include <array>
#include "Components/StaticMeshComponent.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "Pawn/VirtualRealityPawn.h"
#include "Components/DisplayClusterSceneComponent.h"
#include "Utility/VirtualRealityUtilities.h"
DEFINE_LOG_CATEGORY(LogCAVEOverlay);
bool ContainsFString(const TArray<FString>& Array, const FString& Entry)
{
for (FString Current_Entry : Array)
{
if (Current_Entry.Equals(Entry, ESearchCase::IgnoreCase)) return true;
}
return false;
}
UStaticMeshComponent* ACAVEOverlayController::CreateMeshComponent(const FName& Name, UStaticMesh* Mesh, USceneComponent* Parent)
{
UStaticMeshComponent* Result = CreateDefaultSubobject<UStaticMeshComponent>(Name);
Result->SetStaticMesh(Mesh);
Result->SetupAttachment(Parent);
Result->SetVisibility(false);
return Result;
}
template <typename T>
bool LoadAsset(const FString& Path, T* & Result)
{
ConstructorHelpers::FObjectFinder<T> Loader(*Path);
Result = Loader.Object;
if (!Loader.Succeeded()) UE_LOG(LogCAVEOverlay, Error, TEXT("Could not find %s. Have you renamed it?"), *Path);
return Loader.Succeeded();
}
// Sets default values
ACAVEOverlayController::ACAVEOverlayController()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
bAllowTickBeforeBeginPlay = false;
AutoReceiveInput = EAutoReceiveInput::Player0;
ConstructorHelpers::FClassFinder<UDoorOverlayData> WidgetClassFinder(TEXT("Blueprint'/nDisplayExtensions/CAVEOverlay/DoorOverlay'"));
if (WidgetClassFinder.Succeeded())
{
Overlay_Class = WidgetClassFinder.Class;
}
else
{
UE_LOG(LogCAVEOverlay, Error, TEXT("Could not find the DoorOverlay class. Have you renamed it?"));
}
//Creation of sub-components
Root = CreateDefaultSubobject<USceneComponent>("DefaultSceneRoot");
SetRootComponent(Root);
Tape_Root = CreateDefaultSubobject<USceneComponent>("TapeRoot");
Sign_Root = CreateDefaultSubobject<USceneComponent>("SignRoot");
Tape_Root->SetupAttachment(Root);
Sign_Root->SetupAttachment(Root);
//Loading of Materials and Meshes
LoadAsset("/nDisplayExtensions/CAVEOverlay/Stripes", Tape_Material);
LoadAsset("/nDisplayExtensions/CAVEOverlay/StopMaterial", Sign_Material);
LoadAsset("/nDisplayExtensions/CAVEOverlay/Plane", Plane_Mesh_);
Tape_Negative_Y = CreateMeshComponent("TapeNegY", Plane_Mesh_, Tape_Root);
Tape_Negative_X = CreateMeshComponent("TapeNegX", Plane_Mesh_, Tape_Root);
Tape_Positive_Y = CreateMeshComponent("TapePosY", Plane_Mesh_, Tape_Root);
Tape_Positive_X = CreateMeshComponent("TapePosX", Plane_Mesh_, Tape_Root);
Sign_Negative_Y = CreateMeshComponent("SignNegY", Plane_Mesh_, Sign_Root);
Sign_Negative_X = CreateMeshComponent("SignNegX", Plane_Mesh_, Sign_Root);
Sign_Positive_Y = CreateMeshComponent("SignPosY", Plane_Mesh_, Sign_Root);
Sign_Positive_X = CreateMeshComponent("SignPosX", Plane_Mesh_, Sign_Root);
//Set initial Position, Rotation and Scale of Tape
Tape_Negative_Y->SetRelativeLocationAndRotation(FVector(0, -Wall_Distance, 0), FRotator(0, 0, 90));
Tape_Positive_Y->SetRelativeLocationAndRotation(FVector(0, +Wall_Distance, 0), FRotator(0, 180, 90));
Tape_Negative_X->SetRelativeLocationAndRotation(FVector(-Wall_Distance, 0, 0), FRotator(0, -90, 90));
Tape_Positive_X->SetRelativeLocationAndRotation(FVector(+Wall_Distance, 0, 0), FRotator(0, 90, 90));
Tape_Negative_Y->SetRelativeScale3D(FVector(Wall_Distance / 100 * 2, 0.15, 1));
Tape_Positive_Y->SetRelativeScale3D(FVector(Wall_Distance / 100 * 2, 0.15, 1));
Tape_Negative_X->SetRelativeScale3D(FVector(Wall_Distance / 100 * 2, 0.15, 1));
Tape_Positive_X->SetRelativeScale3D(FVector(Wall_Distance / 100 * 2, 0.15, 1));
//Set initial Position, Rotation and Scale of Signs
Sign_Negative_Y->SetRelativeLocationAndRotation(FVector(0, -Wall_Distance, 0), FRotator(0, 0, 90));
Sign_Positive_Y->SetRelativeLocationAndRotation(FVector(0, +Wall_Distance, 0), FRotator(0, 180, 90));
Sign_Negative_X->SetRelativeLocationAndRotation(FVector(-Wall_Distance, 0, 0), FRotator(0, -90, 90));
Sign_Positive_X->SetRelativeLocationAndRotation(FVector(+Wall_Distance, 0, 0), FRotator(0, 90, 90));
Sign_Negative_Y->SetRelativeScale3D(FVector(0.5f));
Sign_Positive_Y->SetRelativeScale3D(FVector(0.5f));
Sign_Negative_X->SetRelativeScale3D(FVector(0.5f));
Sign_Positive_X->SetRelativeScale3D(FVector(0.5f));
}
void ACAVEOverlayController::PostInitializeComponents()
{
Super::PostInitializeComponents();
//Create dynamic materials in runtime
Tape_Material_Dynamic_ = UMaterialInstanceDynamic::Create(Tape_Material, Tape_Root);
Sign_Material_Dynamic_ = UMaterialInstanceDynamic::Create(Sign_Material, Sign_Root);
Tape_Negative_Y->SetMaterial(0, Tape_Material_Dynamic_);
Tape_Negative_X->SetMaterial(0, Tape_Material_Dynamic_);
Tape_Positive_Y->SetMaterial(0, Tape_Material_Dynamic_);
Tape_Positive_X->SetMaterial(0, Tape_Material_Dynamic_);
Sign_Negative_Y->SetMaterial(0, Sign_Material_Dynamic_);
Sign_Negative_X->SetMaterial(0, Sign_Material_Dynamic_);
Sign_Positive_Y->SetMaterial(0, Sign_Material_Dynamic_);
Sign_Positive_X->SetMaterial(0, Sign_Material_Dynamic_);
}
void ACAVEOverlayController::CycleDoorType()
{
Door_Current_Mode = static_cast<EDoor_Mode>((Door_Current_Mode + 1) % DOOR_NUM_MODES);
IDisplayClusterClusterManager* const Manager = IDisplayCluster::Get().GetClusterMgr();
if (Manager)
{
FDisplayClusterClusterEventJson cluster_event;
cluster_event.Name = "CAVEOverlay Change Door to " + Door_Mode_Names[Door_Current_Mode];
cluster_event.Type = "DoorChange";
cluster_event.Category = "CAVEOverlay";
cluster_event.Parameters.Add("NewDoorState", FString::FromInt(Door_Current_Mode));
Manager->EmitClusterEventJson(cluster_event, true);
}
}
void ACAVEOverlayController::HandleClusterEvent(const FDisplayClusterClusterEventJson& Event)
{
if (Event.Category.Equals("CAVEOverlay") && Event.Type.Equals("DoorChange") && Event.Parameters.Contains("NewDoorState"))
{
SetDoorMode(static_cast<EDoor_Mode>(FCString::Atoi(*Event.Parameters["NewDoorState"])));
}
}
void ACAVEOverlayController::SetDoorMode(EDoor_Mode NewMode)
{
Door_Current_Mode = NewMode;
switch (Door_Current_Mode)
{
case EDoor_Mode::DOOR_DEBUG:
case EDoor_Mode::DOOR_PARTIALLY_OPEN:
Door_Current_Opening_Width_Absolute = Door_Opening_Width_Absolute;
if (Screen_Type == SCREEN_DOOR) Overlay->BlackBox->SetRenderScale(FVector2D(0, 1));
if (Screen_Type == SCREEN_DOOR_PARTIAL) Overlay->BlackBox->SetRenderScale(FVector2D(Door_Opening_Width_Relative, 1));
if (Screen_Type == SCREEN_MASTER) Overlay->BlackBox->SetRenderScale(FVector2D(0, 1));
Overlay->BlackBox->SetVisibility(ESlateVisibility::Visible);
break;
case EDoor_Mode::DOOR_OPEN:
Door_Current_Opening_Width_Absolute = Wall_Distance * 2;
if (Screen_Type == SCREEN_DOOR) Overlay->BlackBox->SetRenderScale(FVector2D(1, 1));
if (Screen_Type == SCREEN_DOOR_PARTIAL) Overlay->BlackBox->SetRenderScale(FVector2D(1, 1));
if (Screen_Type == SCREEN_MASTER) Overlay->BlackBox->SetRenderScale(FVector2D(0, 1));
Overlay->BlackBox->SetVisibility(ESlateVisibility::Visible);
break;
case EDoor_Mode::DOOR_CLOSED:
Door_Current_Opening_Width_Absolute = 0;
if (Screen_Type == SCREEN_DOOR) Overlay->BlackBox->SetRenderScale(FVector2D(0, 1));
if (Screen_Type == SCREEN_DOOR_PARTIAL) Overlay->BlackBox->SetRenderScale(FVector2D(0, 1));
if (Screen_Type == SCREEN_MASTER) Overlay->BlackBox->SetRenderScale(FVector2D(0, 1));
Overlay->BlackBox->SetVisibility(ESlateVisibility::Hidden);
break;
default: ;
}
if (Screen_Type == SCREEN_NORMAL) Overlay->BlackBox->SetRenderScale(FVector2D(0, 1)); //no overlay
UE_LOG(LogCAVEOverlay, Log, TEXT("Switched door state to '%s'. New opening width is %f."), *Door_Mode_Names[Door_Current_Mode], Door_Current_Opening_Width_Absolute);
if (Screen_Type == SCREEN_MASTER)
{
Overlay->CornerText->SetText(FText::FromString(Door_Mode_Names[Door_Current_Mode]));
}
}
// Called when the game starts or when spawned
void ACAVEOverlayController::BeginPlay()
{
Super::BeginPlay();
bCAVE_Mode = UVirtualRealityUtilities::IsCave(); /* Store current situation */
if (!bCAVE_Mode) return; // Not our business
//Input config
InputComponent->BindKey(EKeys::F10, EInputEvent::IE_Pressed, this, &ACAVEOverlayController::CycleDoorType);
IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
if (ClusterManager && !ClusterEventListenerDelegate.IsBound())
{
ClusterEventListenerDelegate = FOnClusterEventJsonListener::CreateUObject(this, &ACAVEOverlayController::HandleClusterEvent);
ClusterManager->AddClusterEventJsonListener(ClusterEventListenerDelegate);
}
//Determine the screen-type for later usage
if (IDisplayCluster::Get().GetClusterMgr()->GetNodeId().Equals(Screen_Main, ESearchCase::IgnoreCase))
{
Screen_Type = SCREEN_MASTER;
}
else if (ContainsFString(Screens_Door, IDisplayCluster::Get().GetClusterMgr()->GetNodeId()))
{
Screen_Type = SCREEN_DOOR;
}
else if (ContainsFString(Screens_Door_Partial, IDisplayCluster::Get().GetClusterMgr()->GetNodeId()))
{
Screen_Type = SCREEN_DOOR_PARTIAL;
}
else
{
Screen_Type = SCREEN_NORMAL;
}
Overlay = CreateWidget<UDoorOverlayData>(GetWorld()->GetFirstPlayerController(), Overlay_Class);
Overlay->AddToViewport(0);
SetDoorMode(Door_Current_Mode);
Overlay->CornerText->SetText(FText::FromString("")); //Set Text to "" until someone presses the key for the first time
Player_Pawn = Cast<AVirtualRealityPawn>(GetWorld()->GetFirstPlayerController()->GetPawn());
if (!bAttached && Cave_Origin)
{
AttachToComponent(Cave_Origin, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
bAttached = true;
}
}
void ACAVEOverlayController::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
if (ClusterManager && ClusterEventListenerDelegate.IsBound())
{
ClusterManager->RemoveClusterEventJsonListener(ClusterEventListenerDelegate);
}
Super::EndPlay(EndPlayReason);
}
float ACAVEOverlayController::CalculateOpacityFromPosition(FVector Position)
{
return FMath::Max(
FMath::Clamp((FMath::Abs(Position.X) - (Wall_Distance - Wall_Close_Distance)) / Wall_Fade_Distance, 0.0f, 1.0f),
FMath::Clamp((FMath::Abs(Position.Y) - (Wall_Distance - Wall_Close_Distance)) / Wall_Fade_Distance, 0.0f, 1.0f)
);
}
bool ACAVEOverlayController::PositionInDoorOpening(FVector Position)
{
return FMath::IsWithinInclusive(-Position.X, Wall_Distance + 10 - 20 - Wall_Close_Distance, Wall_Distance + 10) //Overlap both sides 10cm
&& FMath::IsWithinInclusive(-Position.Y, Wall_Distance + 10 - Door_Current_Opening_Width_Absolute, Wall_Distance + 10); //Overlap one side 10cm
}
void ACAVEOverlayController::RefreshPawnComponents()
{
Cave_Origin = UVirtualRealityUtilities::GetNamedClusterComponent(ENamedClusterComponent::NCC_CAVE_ORIGIN);
Head = Player_Pawn->Head;
}
// Called every frame
void ACAVEOverlayController::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!bCAVE_Mode) return; // Not our business
if (!Cave_Origin || !Head)
{
RefreshPawnComponents();
}
if (!bAttached && Cave_Origin)
{
AttachToComponent(Cave_Origin, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
bAttached = true;
}
//FPS Counter
if (Overlay)
{
if (Door_Current_Mode == EDoor_Mode::DOOR_DEBUG && ContainsFString(Screens_FPS, IDisplayCluster::Get().GetClusterMgr()->GetNodeId()))
{
Overlay->FPS->SetText(FText::FromString(FString::Printf(TEXT("FPS: %.1f"), 1.0f / DeltaTime)));
}
else
{
Overlay->FPS->SetText(FText::FromString(""));
}
}
if (!Head || !Cave_Origin) return; //Display Cluster not initialized
//Tape Logic
FVector Shutter_Position = Head->GetComponentLocation() - Cave_Origin->GetComponentLocation();
bool bOverlay_Visible = FMath::IsWithinInclusive(Shutter_Position.GetAbsMax(), Wall_Distance - Wall_Close_Distance, Wall_Distance);
if (bOverlay_Visible && !PositionInDoorOpening(Shutter_Position))
{
Tape_Root->SetVisibility(true, true);
Tape_Root->SetRelativeLocation(Shutter_Position * FVector(0, 0, 1)); //Only apply Z
float Tape_Opacity = CalculateOpacityFromPosition(Shutter_Position);
Tape_Material_Dynamic_->SetScalarParameterValue("BarrierOpacity", Tape_Opacity);
if (FMath::IsWithin(FVector2D(Shutter_Position).GetAbsMax(), Wall_Distance - Wall_Warning_Distance, Wall_Distance))
{
//in warning distance == red tape
Tape_Material_Dynamic_->SetVectorParameterValue("StripeColor", FVector(1, 0, 0));
}
else
{
Tape_Material_Dynamic_->SetVectorParameterValue("StripeColor", FVector(1, 1, 0));
}
}
else
{
Tape_Root->SetVisibility(false, true);
}
//Sign Logic
UDisplayClusterSceneComponent* Flystick = UVirtualRealityUtilities::GetNamedClusterComponent(ENamedClusterComponent::NCC_FLYSTICK);
if (Flystick)
{
FVector Flystick_Position = Flystick->GetRelativeTransform().GetLocation();
bool bFlystick_In_Door = PositionInDoorOpening(Flystick_Position);
float Sign_Opacity = CalculateOpacityFromPosition(Flystick_Position);
Sign_Negative_X->SetRelativeLocation(FVector(-Wall_Distance, Flystick_Position.Y, Flystick_Position.Z));
Sign_Negative_Y->SetRelativeLocation(FVector(Flystick_Position.X, -Wall_Distance, Flystick_Position.Z));
Sign_Positive_X->SetRelativeLocation(FVector(+Wall_Distance, Flystick_Position.Y, Flystick_Position.Z));
Sign_Positive_Y->SetRelativeLocation(FVector(Flystick_Position.X, +Wall_Distance, Flystick_Position.Z));
Sign_Negative_X->SetVisibility(FMath::IsWithin(-Flystick_Position.X, Wall_Distance - Wall_Close_Distance, Wall_Distance) && !bFlystick_In_Door);
Sign_Negative_Y->SetVisibility(FMath::IsWithin(-Flystick_Position.Y, Wall_Distance - Wall_Close_Distance, Wall_Distance) && !bFlystick_In_Door);
Sign_Positive_X->SetVisibility(FMath::IsWithin(+Flystick_Position.X, Wall_Distance - Wall_Close_Distance, Wall_Distance) && !bFlystick_In_Door);
Sign_Positive_Y->SetVisibility(FMath::IsWithin(+Flystick_Position.Y, Wall_Distance - Wall_Close_Distance, Wall_Distance) && !bFlystick_In_Door);
Sign_Material_Dynamic_->SetScalarParameterValue("SignOpacity", Sign_Opacity);
}
else
{
Sign_Negative_X->SetVisibility(false);
Sign_Negative_Y->SetVisibility(false);
Sign_Positive_X->SetVisibility(false);
Sign_Positive_Y->SetVisibility(false);
}
}
...@@ -6,11 +6,13 @@ void FDisplayClusterExtensionsModule::StartupModule () ...@@ -6,11 +6,13 @@ void FDisplayClusterExtensionsModule::StartupModule ()
{ {
ClusterConsole.Register(); ClusterConsole.Register();
StereoDeviceFix.Register(); StereoDeviceFix.Register();
CAVEOverlay.Register();
} }
void FDisplayClusterExtensionsModule::ShutdownModule() void FDisplayClusterExtensionsModule::ShutdownModule()
{ {
ClusterConsole.Unregister(); ClusterConsole.Unregister();
StereoDeviceFix.Unregister(); StereoDeviceFix.Unregister();
CAVEOverlay.Unregister();
} }
#undef LOCTEXT_NAMESPACE #undef LOCTEXT_NAMESPACE
......
...@@ -92,7 +92,7 @@ void UUniversalTrackedComponent::TickComponent(float DeltaTime, ELevelTick TickT ...@@ -92,7 +92,7 @@ void UUniversalTrackedComponent::TickComponent(float DeltaTime, ELevelTick TickT
TrackedComponent = GetComponentForSelectedAttachment(AttachementType); TrackedComponent = GetComponentForSelectedAttachment(AttachementType);
break; break;
case ETrackedComponentType::TCT_HEAD: case ETrackedComponentType::TCT_HEAD:
TrackedComponent = GetOwner()->FindComponentByClass<UCameraComponent>(); TrackedComponent = UVirtualRealityUtilities::GetNamedClusterComponent(ENamedClusterComponent::NCC_SHUTTERGLASSES);
break; break;
case ETrackedComponentType::TCT_TRACKER_1: case ETrackedComponentType::TCT_TRACKER_1:
case ETrackedComponentType::TCT_TRACKER_2: case ETrackedComponentType::TCT_TRACKER_2:
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "Cluster/IDisplayClusterClusterManager.h" #include "Cluster/IDisplayClusterClusterManager.h"
#include "Components/DisplayClusterCameraComponent.h" #include "Components/DisplayClusterCameraComponent.h"
#include "Config/IDisplayClusterConfigManager.h"
#include "DisplayClusterRootActor.h" #include "DisplayClusterRootActor.h"
#include "DisplayClusterConfigurationTypes.h" #include "DisplayClusterConfigurationTypes.h"
#include "Engine/Engine.h" #include "Engine/Engine.h"
...@@ -22,6 +23,33 @@ bool UVirtualRealityUtilities::IsHeadMountedMode() ...@@ -22,6 +23,33 @@ bool UVirtualRealityUtilities::IsHeadMountedMode()
return GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed(); return GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed();
} }
bool UVirtualRealityUtilities::IsCave()
{
if(!IsRoomMountedMode()) return false;
const UDisplayClusterConfigurationData* ClusterConfig = IDisplayCluster::Get().GetConfigMgr()->GetConfig();
return ClusterConfig->CustomParameters.Contains("Hardware_Platform")
&& ClusterConfig->CustomParameters.Find("Hardware_Platform")->Equals("aixcave", ESearchCase::IgnoreCase);
}
bool UVirtualRealityUtilities::IsTdw()
{
if(!IsRoomMountedMode()) return false;
const UDisplayClusterConfigurationData* ClusterConfig = IDisplayCluster::Get().GetConfigMgr()->GetConfig();
return ClusterConfig->CustomParameters.Contains("Hardware_Platform")
&& ClusterConfig->CustomParameters.Find("Hardware_Platform")->Equals("TiledDisplayWall", ESearchCase::IgnoreCase);
}
bool UVirtualRealityUtilities::IsRolv()
{
if(!IsRoomMountedMode()) return false;
const UDisplayClusterConfigurationData* ClusterConfig = IDisplayCluster::Get().GetConfigMgr()->GetConfig();
return ClusterConfig->CustomParameters.Contains("Hardware_Platform")
&& ClusterConfig->CustomParameters.Find("Hardware_Platform")->Equals("ROLV", ESearchCase::IgnoreCase);
}
/* Return true on the Master in cluster mode and in a normal desktop session. Otherwise false */ /* Return true on the Master in cluster mode and in a normal desktop session. Otherwise false */
bool UVirtualRealityUtilities::IsMaster() bool UVirtualRealityUtilities::IsMaster()
{ {
......
#pragma once
#include "CoreMinimal.h"
#include "Engine/World.h"
#include "Cluster/CAVEOverlay/CAVEOverlaySettings.h"
#include "Cluster/CAVEOverlay/CAVEOverlayController.h"
#include "Kismet/GameplayStatics.h"
#include "CAVEOverlay.generated.h"
/**
* Adds the warning tape, which appears if the user gets too close to the wall for the aixCAVE
*/
USTRUCT()
struct DISPLAYCLUSTEREXTENSIONS_API FCAVEOverlay
{
GENERATED_BODY()
void Register();
void Unregister() const;
private:
TBaseDelegate<void, UWorld*, const UWorld::InitializationValues> On_Post_World_Initialization_Delegate;
void OnSessionStart(UWorld* World, UWorld::InitializationValues);
FDelegateHandle SessionStartDelegate;
};
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Cluster/CAVEOverlay/DoorOverlayData.h"
#include "Pawn/VirtualRealityPawn.h"
#include "Cluster/IDisplayClusterClusterManager.h"
#include "Cluster/DisplayClusterClusterEvent.h"
#include "CAVEOverlayController.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogCAVEOverlay, Log, All);
UCLASS()
class DISPLAYCLUSTEREXTENSIONS_API ACAVEOverlayController : public AActor
{
GENERATED_BODY()
public:
ACAVEOverlayController();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void PostInitializeComponents() override;
private:
//Execution Modes
bool bCAVE_Mode = false;
//Screen Types
enum EScreen_Type { SCREEN_MASTER, SCREEN_NORMAL, SCREEN_DOOR_PARTIAL, SCREEN_DOOR };
EScreen_Type Screen_Type = SCREEN_NORMAL;
const TArray<FString> Screens_Door = {"node_bul_left_eye", "node_bul_right_eye", "node_bll_left_eye", "node_bll_right_eye"};
const TArray<FString> Screens_Door_Partial = {"node_bur_left_eye", "node_bur_right_eye", "node_blr_left_eye", "node_blr_right_eye"};
const TArray<FString> Screens_FPS = {"node_rur_left_eye", "node_rur_right_eye", "node_lur_left_eye", "node_lur_right_eye", "node_main"};
const FString Screen_Main = "node_main";
//Door Mode
enum EDoor_Mode { DOOR_PARTIALLY_OPEN = 0, DOOR_OPEN = 1, DOOR_CLOSED = 2, DOOR_DEBUG = 3, DOOR_NUM_MODES = 4 };
const FString Door_Mode_Names[DOOR_NUM_MODES] = {"Partially Open", "Open", "Closed", "Debug"};
EDoor_Mode Door_Current_Mode = DOOR_PARTIALLY_OPEN;
const float Door_Opening_Width_Relative = 0.522; //%, used for the overlay width on the screen
const float Door_Opening_Width_Absolute = 165; //cm, used for the non tape part at the door
const float Wall_Distance = 262.5; //cm, distance from center to a wall, *2 = wall width
const float Wall_Close_Distance = 75; //cm, the distance considered to be too close to the walls
const float Wall_Fade_Distance = 35; //cm, the distance over which the tape is faded
const float Wall_Warning_Distance = 40; //cm, distance on which the tape turns red, measured from wall
float Door_Current_Opening_Width_Absolute = 0;
//Overlay
TSubclassOf<class UDoorOverlayData> Overlay_Class;
UPROPERTY() UDoorOverlayData* Overlay;
//Geometry and Material
UStaticMeshComponent* CreateMeshComponent(const FName& Name, UStaticMesh* Mesh, USceneComponent* Parent);
UPROPERTY() UMaterial* Tape_Material = nullptr;
UPROPERTY() UMaterial* Sign_Material = nullptr;
float CalculateOpacityFromPosition(FVector Position);
bool PositionInDoorOpening(FVector Position);
//Pawn Components
bool bAttached = false;
void RefreshPawnComponents();
UPROPERTY() AVirtualRealityPawn* Player_Pawn;
UPROPERTY() USceneComponent* Cave_Origin;
UPROPERTY() USceneComponent* Head;
//Cluster Events
FOnClusterEventJsonListener ClusterEventListenerDelegate;
void HandleClusterEvent(const FDisplayClusterClusterEventJson& Event);
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
void CycleDoorType();
void SetDoorMode(EDoor_Mode M);
//Signs and Banners
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) USceneComponent* Root = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) USceneComponent* Tape_Root = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) USceneComponent* Sign_Root = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) UStaticMeshComponent* Tape_Negative_Y = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) UStaticMeshComponent* Tape_Negative_X = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) UStaticMeshComponent* Tape_Positive_Y = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) UStaticMeshComponent* Tape_Positive_X = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) UStaticMeshComponent* Sign_Negative_Y = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) UStaticMeshComponent* Sign_Negative_X = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) UStaticMeshComponent* Sign_Positive_Y = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CAVEOverlay", meta = (AllowPrivateAccess = "true")) UStaticMeshComponent* Sign_Positive_X = nullptr;
UPROPERTY() UMaterialInstanceDynamic* Tape_Material_Dynamic_ = nullptr;
UPROPERTY() UMaterialInstanceDynamic* Sign_Material_Dynamic_ = nullptr;
UPROPERTY() UStaticMesh* Plane_Mesh_ = nullptr;
};
#pragma once
#include "CoreMinimal.h"
#include "Engine/DeveloperSettings.h"
#include "CAVEOverlaySettings.generated.h"
UENUM(BlueprintType)
enum DefaultActivationType
{
DefaultActivationType_OFF UMETA(DisplayName = "Off by default"),
DefaultActivationType_ON UMETA(DisplayName = "On by default")
};
UCLASS(config=Game, defaultconfig, meta=(DisplayName="CAVE Overlay"))
class DISPLAYCLUSTEREXTENSIONS_API UCAVEOverlaySettings : public UDeveloperSettings
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, config, Category = "General", meta = (DisplayName = "Default Activation Type"))
TEnumAsByte<DefaultActivationType> DefaultActivationType = DefaultActivationType_ON;
UPROPERTY(EditAnywhere, config, Category = Maps, meta=(AllowedClasses="World"))
TArray<FSoftObjectPath> excludedMaps;
};
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/TextBlock.h"
#include "Components/Border.h"
#include "DoorOverlayData.generated.h"
/**
* Used as a parent-class in the overlay widget. Like this we can access the UMG properties in C++
*/
UCLASS()
class DISPLAYCLUSTEREXTENSIONS_API UDoorOverlayData : public UUserWidget
{
GENERATED_BODY()
public:
//These declarations are magically bound to the UMG blueprints elements,
//if they are named the same
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UTextBlock* CornerText;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UBorder* BlackBox;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UTextBlock* FPS;
};
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "Cluster/CAVEOverlay/CAVEOverlay.h"
#include "Fixes/FixNDisplayStereoDevice.h" #include "Fixes/FixNDisplayStereoDevice.h"
#include "Modules/ModuleManager.h" #include "Modules/ModuleManager.h"
#include "Cluster/ClusterConsole.h" #include "Cluster/ClusterConsole.h"
...@@ -15,4 +16,5 @@ public: ...@@ -15,4 +16,5 @@ public:
private: private:
FClusterConsole ClusterConsole; FClusterConsole ClusterConsole;
FFixNDisplayStereoDevice StereoDeviceFix; FFixNDisplayStereoDevice StereoDeviceFix;
FCAVEOverlay CAVEOverlay;
}; };
...@@ -33,9 +33,12 @@ class DISPLAYCLUSTEREXTENSIONS_API UVirtualRealityUtilities : public UBlueprintF ...@@ -33,9 +33,12 @@ class DISPLAYCLUSTEREXTENSIONS_API UVirtualRealityUtilities : public UBlueprintF
GENERATED_BODY() GENERATED_BODY()
public: public:
UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsDesktopMode(); UFUNCTION(BlueprintPure, Category = "DisplayCluster|Platform") static bool IsDesktopMode();
UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsRoomMountedMode(); UFUNCTION(BlueprintPure, Category = "DisplayCluster|Platform") static bool IsRoomMountedMode();
UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsHeadMountedMode(); UFUNCTION(BlueprintPure, Category = "DisplayCluster|Platform") static bool IsHeadMountedMode();
UFUNCTION(BlueprintPure, Category = "DisplayCluster|Platform") static bool IsCave();
UFUNCTION(BlueprintPure, Category = "DisplayCluster|Platform") static bool IsTdw();
UFUNCTION(BlueprintPure, Category = "DisplayCluster|Platform") static bool IsRolv();
UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsMaster(); UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsMaster();
UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsSlave(); UFUNCTION(BlueprintPure, Category = "DisplayCluster") static bool IsSlave();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment