diff --git a/Content/DoorOverlay.uasset b/Content/DoorOverlay.uasset index 6034247a2e956c8770cf6dbff43f64b66dcb97f8..16120de5acd753b3846a98ed20e35e3121557c7a 100644 Binary files a/Content/DoorOverlay.uasset and b/Content/DoorOverlay.uasset differ diff --git a/Source/CAVEOverlay/Private/CAVEOverlayController.cpp b/Source/CAVEOverlay/Private/CAVEOverlayController.cpp index e270626a7c81eff973eb3d389c7c734fef1584e6..0c667b68a41cb1f3dae904fc53c019aa2f8bd27d 100644 --- a/Source/CAVEOverlay/Private/CAVEOverlayController.cpp +++ b/Source/CAVEOverlay/Private/CAVEOverlayController.cpp @@ -1,91 +1,115 @@ // Fill out your copyright notice in the Description page of Project Settings. - #include "CAVEOverlayController.h" - -DEFINE_LOG_CATEGORY(CAVEOverlayLog); - -template<std::size_t SIZE> bool containsFString(const std::array<FString, SIZE> &a, const FString &s) { - for (FString cs : a) { - if (cs.Equals(s, ESearchCase::IgnoreCase)) return true; +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "DoorOverlayData.h" +#include "IDisplayCluster.h" +#include "Engine/Engine.h" +#include "IXRTrackingSystem.h" +#include "Components/InputComponent.h" +#include "Cluster/IDisplayClusterClusterManager.h" +#include "IDisplayClusterGameManager.h" +#include "UObject/ConstructorHelpers.h" +#include <array> +#include "Components/StaticMeshComponent.h" +#include "Materials/Material.h" +#include "Materials/MaterialInstanceDynamic.h" +#include "DisplayClusterExtensions/Public/VirtualRealityPawn.h" +#include "DisplayCluster/Public/DisplayClusterSceneComponent.h" + +DEFINE_LOG_CATEGORY(LogCAVEOverlay); + +template <std::size_t S> +bool ContainsFString(const std::array<FString, S>& A, const FString& Entry) +{ + for (FString CS : A) + { + if (CS.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; +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(CAVEOverlayLog, Error, TEXT("Could not find %s. Have you renamed it?"), *path); - return loader.Succeeded(); +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. + // 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'/CAVEOverlay/DoorOverlay'")); - if (WidgetClassFinder.Succeeded()) { - overlay_class_ = WidgetClassFinder.Class; - } else { - UE_LOG(CAVEOverlayLog, Error, TEXT("Could not find the DoorOverlay class. Have you renamed it?")); + 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 subcomponents - root = CreateDefaultSubobject<USceneComponent>("DefaultSceneRoot"); - SetRootComponent(root); - tape_root = CreateDefaultSubobject<USceneComponent>("TapeRoot"); - sign_root = CreateDefaultSubobject<USceneComponent>("SignRoot"); - tape_root->SetupAttachment(root); - sign_root->SetupAttachment(root); + //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("/CAVEOverlay/Stripes", tape_material_); - loadAsset("/CAVEOverlay/StopMaterial", sign_material_); - loadAsset("/CAVEOverlay/Plane", plane_mesh_); + LoadAsset("/CAVEOverlay/Stripes", Tape_Material); + LoadAsset("/CAVEOverlay/StopMaterial", Sign_Material); + LoadAsset("/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); + 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); + 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->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)); + 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)); + 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() @@ -93,57 +117,61 @@ 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_); + 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<DOOR_MODE>((door_current_mode_ + 1) % DOOR_NUM_MODES); - SetDoorMode(door_current_mode_); + Door_Current_Mode = static_cast<EDoor_Mode>((Door_Current_Mode + 1) % DOOR_NUM_MODES); + SetDoorMode(Door_Current_Mode); } -void ACAVEOverlayController::SetDoorMode(DOOR_MODE m) +void ACAVEOverlayController::SetDoorMode(EDoor_Mode M) { - switch (door_current_mode_) { - case DOOR_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); + 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 DOOR_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(1, 1)); - overlay_->BlackBox->SetVisibility(ESlateVisibility::Visible); + 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(1, 1)); + Overlay->BlackBox->SetVisibility(ESlateVisibility::Visible); break; - case DOOR_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); + 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 + if (Screen_Type == SCREEN_NORMAL) Overlay->BlackBox->SetRenderScale(FVector2D(0, 1)); //no overlay - UE_LOG(CAVEOverlayLog, Log, TEXT("Switched door state to '%s'. New opening width is %f."), *door_mode_names_[door_current_mode_], door_current_opening_width_absolute_); + 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_])); + if (Screen_Type == SCREEN_MASTER) + { + Overlay->CornerText->SetText(FText::FromString(Door_Mode_Names[Door_Current_Mode])); } } @@ -153,62 +181,69 @@ void ACAVEOverlayController::BeginPlay() Super::BeginPlay(); //Read situation - hmd_mode_ = GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed(); - display_cluster_mode_ = IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster; + bHMD_Mode = GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed(); + bDisplay_Cluster_Mode = IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster; - if (!display_cluster_mode_) return; // Not our business + if (!bDisplay_Cluster_Mode) return; // Not our business //Input config - InputComponent->BindKey(FKey("nDisplayButton4"), EInputEvent::IE_Pressed, this, &ACAVEOverlayController::CycleDoorType); - // - //InputComponent->BindKey(EKeys::F10, EInputEvent::IE_Pressed, this, &ACAVEOverlayController::CycleDoorType); + InputComponent->BindAction("Action4", EInputEvent::IE_Pressed, this, &ACAVEOverlayController::CycleDoorType); - //Determine the screentype for later usage - if (IDisplayCluster::Get().GetClusterMgr()->GetNodeId().Equals(screen_main, ESearchCase::IgnoreCase)) { - screen_type_ = SCREEN_MASTER; + //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, IDisplayCluster::Get().GetClusterMgr()->GetNodeId())) + { + Screen_Type = SCREEN_DOOR; } - else if (containsFString(screens_door_partial_, IDisplayCluster::Get().GetClusterMgr()->GetNodeId())) { - screen_type_ = SCREEN_DOOR_PARTIAL; + else if (ContainsFString(Screens_Door_Partial, IDisplayCluster::Get().GetClusterMgr()->GetNodeId())) + { + Screen_Type = SCREEN_DOOR_PARTIAL; } - else { - screen_type_ = SCREEN_NORMAL; + 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 + 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()); - refreshPawnComponents(); + Player_Pawn = Cast<AVirtualRealityPawn>(GetWorld()->GetFirstPlayerController()->GetPawn()); + RefreshPawnComponents(); - if (!attached_ && cave_origin_) { - AttachToComponent(cave_origin_, FAttachmentTransformRules::SnapToTargetNotIncludingScale); - attached_ = true; + if (!bAttached && Cave_Origin) + { + AttachToComponent(Cave_Origin, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + bAttached = true; } } -float ACAVEOverlayController::calculateOpacityFromPosition(FVector position) { +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) - ); + 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 +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(){ - TArray<UDisplayClusterSceneComponent*> pawn_components; - player_pawn_->GetComponents<UDisplayClusterSceneComponent>(pawn_components); - for (UDisplayClusterSceneComponent* c : pawn_components) { - if (c->GetName().Equals("cave_origin", ESearchCase::IgnoreCase)) cave_origin_ = c; - if (c->GetName().Equals("shutter_glasses", ESearchCase::IgnoreCase)) shutter_glasses_ = c; +void ACAVEOverlayController::RefreshPawnComponents() +{ + TArray<UDisplayClusterSceneComponent*> Pawn_Components; + Player_Pawn->GetComponents<UDisplayClusterSceneComponent>(Pawn_Components); + for (UDisplayClusterSceneComponent* c : Pawn_Components) + { + if (c->GetName().Equals("cave_origin", ESearchCase::IgnoreCase)) Cave_Origin = c; + if (c->GetName().Equals("shutter_glasses", ESearchCase::IgnoreCase)) Shutter_Glasses = c; } } @@ -217,59 +252,79 @@ void ACAVEOverlayController::Tick(float DeltaTime) { Super::Tick(DeltaTime); - if (!display_cluster_mode_) return; // Not our business + if (!bDisplay_Cluster_Mode) return; // Not our business - refreshPawnComponents(); - if (!attached_ && cave_origin_) { - AttachToComponent(cave_origin_, FAttachmentTransformRules::SnapToTargetNotIncludingScale); - attached_ = true; + RefreshPawnComponents(); + if (!bAttached && Cave_Origin) + { + AttachToComponent(Cave_Origin, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + bAttached = true; } - if (!shutter_glasses_) return; //Display Cluster not initialized + if (!Shutter_Glasses) return; //Display Cluster not initialized //Tape Logic - FVector shutter_position = shutter_glasses_->GetRelativeTransform().GetLocation(); - bool overlay_visible = FMath::IsWithinInclusive(shutter_position.GetAbsMax(), wall_distance_ - wall_close_distance_, wall_distance_); + FVector Shutter_Position = Shutter_Glasses->GetRelativeTransform().GetLocation(); + bool bOverlay_Visible = FMath::IsWithinInclusive(Shutter_Position.GetAbsMax(), Wall_Distance - Wall_Close_Distance, Wall_Distance); - if (overlay_visible && !positionInDoorOpening(shutter_position)) { - tape_root->SetVisibility(true, true); - tape_root->SetRelativeLocation(shutter_position * FVector(0, 0, 1)); //Only apply Z + 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); + 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)); + 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); + } + else + { + Tape_Root->SetVisibility(false, true); } //Sign Logic - UDisplayClusterSceneComponent* flystick = IDisplayCluster::Get().GetGameMgr()->GetNodeById(TEXT("flystick")); - if (flystick) { - FVector flystick_position = flystick->GetRelativeTransform().GetLocation(); - bool flystick_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_) && !flystick_in_door); - sign_negative_y->SetVisibility(FMath::IsWithin(-flystick_position.Y, wall_distance_ - wall_close_distance_, wall_distance_) && !flystick_in_door); - sign_positive_x->SetVisibility(FMath::IsWithin(+flystick_position.X, wall_distance_ - wall_close_distance_, wall_distance_) && !flystick_in_door); - sign_positive_y->SetVisibility(FMath::IsWithin(+flystick_position.Y, wall_distance_ - wall_close_distance_, wall_distance_) && !flystick_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); + UDisplayClusterSceneComponent* Flystick = IDisplayCluster::Get().GetGameMgr()->GetNodeById(TEXT("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); } -} + //FPS + if (Overlay && 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("")); + } +} diff --git a/Source/CAVEOverlay/Public/CAVEOverlayController.h b/Source/CAVEOverlay/Public/CAVEOverlayController.h index 75821665d0bf5bb1dd38b0109e21d60174bef296..af238828aea072adf42eb07f02e502c6230507b1 100644 --- a/Source/CAVEOverlay/Public/CAVEOverlayController.h +++ b/Source/CAVEOverlay/Public/CAVEOverlayController.h @@ -5,25 +5,16 @@ #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "DoorOverlayData.h" -#include "HeadMountedDisplayFunctionLibrary.h" -#include "IDisplayCluster.h" #include "Engine/Engine.h" -#include "IXRTrackingSystem.h" -#include "Components/InputComponent.h" -#include "Cluster/IDisplayClusterClusterManager.h" -#include "IDisplayClusterGameManager.h" -#include "InputCoreTypes.h" -#include "UObject/ConstructorHelpers.h" #include <array> #include "Components/StaticMeshComponent.h" -#include "Engine/Engine.h" #include "Materials/Material.h" #include "Materials/MaterialInstanceDynamic.h" #include "DisplayClusterExtensions/Public/VirtualRealityPawn.h" #include "DisplayCluster/Public/DisplayClusterSceneComponent.h" #include "CAVEOverlayController.generated.h" -DECLARE_LOG_CATEGORY_EXTERN(CAVEOverlayLog, Log, All); +DECLARE_LOG_CATEGORY_EXTERN(LogCAVEOverlay, Log, All); UCLASS() class CAVEOVERLAY_API ACAVEOverlayController : public AActor @@ -37,46 +28,49 @@ protected: virtual void PostInitializeComponents() override; private: - //Execution Modes - bool hmd_mode_ = false; - bool display_cluster_mode_ = false; - + //Execution Modes + bool bHMD_Mode = false; + bool bDisplay_Cluster_Mode = false; + //Screen Types - enum SCREEEN_TYPE { SCREEN_MASTER, SCREEN_NORMAL, SCREEN_DOOR_PARTIAL, SCREEN_DOOR }; - SCREEEN_TYPE screen_type_ = SCREEN_NORMAL; - const std::array<FString, 4> screens_door_ = {"node_bul_left_eye", "node_bul_right_eye", "node_bll_left_eye", "node_bll_right_eye"}; - const std::array<FString, 4> screens_door_partial_ = {"node_bur_left_eye", "node_bur_right_eye", "node_blr_left_eye", "node_blr_right_eye"}; - const FString screen_main = "node_main"; + enum EScreen_Type { SCREEN_MASTER, SCREEN_NORMAL, SCREEN_DOOR_PARTIAL, SCREEN_DOOR }; + + EScreen_Type Screen_Type = SCREEN_NORMAL; + const std::array<FString, 4> Screens_Door = {"node_bul_left_eye", "node_bul_right_eye", "node_bll_left_eye", "node_bll_right_eye"}; + const std::array<FString, 4> Screens_Door_Partial = {"node_bur_left_eye", "node_bur_right_eye", "node_blr_left_eye", "node_blr_right_eye"}; + const std::array<FString, 5> 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 DOOR_MODE { DOOR_CLOSED = 0, DOOR_OPEN = 1, DOOR_PARTIALLY_OPEN = 2, DOOR_NUM_MODES = 3}; - const FString door_mode_names_[DOOR_NUM_MODES] = {"Closed", "Open", "Partially Open" }; - DOOR_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, measurred from wall - float door_current_opening_width_absolute_ = 0; + 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_; - UDoorOverlayData* overlay_; + TSubclassOf<class UDoorOverlayData> Overlay_Class; + UDoorOverlayData* Overlay; //Geometry and Material - UStaticMeshComponent* createMeshComponent(const FName &name, UStaticMesh* mesh, USceneComponent* parent); - UMaterial* tape_material_ = nullptr; - UMaterial* sign_material_ = nullptr; - float calculateOpacityFromPosition(FVector position); - bool positionInDoorOpening(FVector position); + UStaticMeshComponent* CreateMeshComponent(const FName& Name, UStaticMesh* Mesh, USceneComponent* Parent); + UMaterial* Tape_Material = nullptr; + UMaterial* Sign_Material = nullptr; + float CalculateOpacityFromPosition(FVector Position); + bool PositionInDoorOpening(FVector Position); //Pawn Components - bool attached_ = false; - void refreshPawnComponents(); - AVirtualRealityPawn* player_pawn_; - UDisplayClusterSceneComponent* cave_origin_; - UDisplayClusterSceneComponent* shutter_glasses_; + bool bAttached = false; + void RefreshPawnComponents(); + AVirtualRealityPawn* Player_Pawn; + UDisplayClusterSceneComponent* Cave_Origin; + UDisplayClusterSceneComponent* Shutter_Glasses; public: @@ -84,24 +78,24 @@ public: virtual void Tick(float DeltaTime) override; void CycleDoorType(); - void SetDoorMode(DOOR_MODE m); - + 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; - - UMaterialInstanceDynamic* tape_material_dynamic_ = nullptr; - UMaterialInstanceDynamic* sign_material_dynamic_ = nullptr; - UStaticMesh* plane_mesh_ = nullptr; + 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; + + UMaterialInstanceDynamic* Tape_Material_Dynamic_ = nullptr; + UMaterialInstanceDynamic* Sign_Material_Dynamic_ = nullptr; + UStaticMesh* Plane_Mesh_ = nullptr; }; diff --git a/Source/CAVEOverlay/Public/DoorOverlayData.h b/Source/CAVEOverlay/Public/DoorOverlayData.h index e693a492852045605766fb74c9fe7fb8a254fabe..97dbb5987b79a5467e8075b1a3a5dba4569a8f2c 100644 --- a/Source/CAVEOverlay/Public/DoorOverlayData.h +++ b/Source/CAVEOverlay/Public/DoorOverlayData.h @@ -24,4 +24,7 @@ public: UPROPERTY(BlueprintReadWrite, meta = (BindWidget)) UBorder* BlackBox; + + UPROPERTY(BlueprintReadWrite, meta = (BindWidget)) + UTextBlock* FPS; };