diff --git a/Source/RWTHVRCluster/Private/CAVEOverlay/CAVEOverlayController.cpp b/Source/RWTHVRCluster/Private/CAVEOverlay/CAVEOverlayController.cpp index 6553ad4ea869f745d92ff95b04b258c0851dcb61..4805e433258ea8a8fd01cda88e03bf125e00a2a0 100644 --- a/Source/RWTHVRCluster/Private/CAVEOverlay/CAVEOverlayController.cpp +++ b/Source/RWTHVRCluster/Private/CAVEOverlay/CAVEOverlayController.cpp @@ -149,6 +149,10 @@ void ACAVEOverlayController::BeginPlay() if (GetNetMode() != NM_Standalone) return; + // If we're not in room-mounted mode, return as well + if (!URWTHVRClusterUtilities::IsRoomMountedMode()) + return; + // This should return the respective client's local playercontroller or, if we're a listen server, our own PC. auto* PC = GetWorld() ? GetWorld()->GetFirstPlayerController() : nullptr; @@ -157,7 +161,7 @@ void ACAVEOverlayController::BeginPlay() // Not sure which place would be best... const bool bValidPC = PC && PC->GetLocalPlayer(); - if (!bValidPC || !URWTHVRClusterUtilities::IsRoomMountedMode()) + if (!bValidPC) return; // Input config @@ -223,11 +227,33 @@ void ACAVEOverlayController::BeginPlay() return; } + PC->OnPossessedPawnChanged.AddUniqueDynamic(this, &ACAVEOverlayController::UpdatePossessedPawn); + + // I think this breaks in multiplayer mode + InitFromPawn(PC->GetPawn()); + + // Create dynamic material for tape + TapeMaterialDynamic = Tape->CreateDynamicMaterialInstance(0); + + UE_LOGFMT(LogCAVEOverlay, Display, "CaveOverlay Initialization was successfull."); +} + +void ACAVEOverlayController::UpdatePossessedPawn(APawn* OldPawn, APawn* NewPawn) { InitFromPawn(NewPawn); } + + +void ACAVEOverlayController::InitFromPawn(const APawn* CurrentPawn) +{ + // Clear previous properties. We could reuse the SMCs and MIDs, clearing them might be dangerous. + // Too much in a hurry here to make this better. + MotionControllers.Empty(); + SignsStaticMeshComponents.Empty(); + SignsMIDs.Empty(); + // Get the pawn so we can have access to head and hand positions - if (const auto* VRPawn = Cast<APawn>(PC->GetPawnOrSpectator())) + if (CurrentPawn) { - PawnCamera = VRPawn->GetComponentByClass<UCameraComponent>(); - auto FoundMotionControllers = VRPawn->K2_GetComponentsByClass(UMotionControllerComponent::StaticClass()); + PawnCamera = CurrentPawn->GetComponentByClass<UCameraComponent>(); + auto FoundMotionControllers = CurrentPawn->K2_GetComponentsByClass(UMotionControllerComponent::StaticClass()); for (const auto FoundMotionController : FoundMotionControllers) { @@ -261,13 +287,9 @@ void ACAVEOverlayController::BeginPlay() } else { + bInitialized = false; UE_LOGFMT(LogCAVEOverlay, Error, "No VirtualRealityPawn found which we could attach to!"); } - - // Create dynamic material for tape - TapeMaterialDynamic = Tape->CreateDynamicMaterialInstance(0); - - UE_LOGFMT(LogCAVEOverlay, Display, "CaveOverlay Initialization was successfull."); } void ACAVEOverlayController::EndPlay(const EEndPlayReason::Type EndPlayReason) @@ -386,6 +408,12 @@ void ACAVEOverlayController::Tick(float DeltaTime) // Hand Logic for (int i = 0; i < MotionControllers.Num(); i++) { + if (MotionControllers[i] == nullptr) + { + UE_LOGFMT(LogCAVEOverlay, Error, "Motion Controller was nullptr, disabling overlay!"); + bInitialized = false; + return; + } const FVector HandPosition = MotionControllers[i]->GetRelativeLocation(); // Set the position rotation, opacity, visibility of the hand warning signs. diff --git a/Source/RWTHVRCluster/Public/CAVEOverlay/CAVEOverlayController.h b/Source/RWTHVRCluster/Public/CAVEOverlay/CAVEOverlayController.h index 0e8c09fc6d0648cf98c0e917e2a4a10260feb805..c46cabc14e6a18987eb7610adce29255c4979a3e 100644 --- a/Source/RWTHVRCluster/Public/CAVEOverlay/CAVEOverlayController.h +++ b/Source/RWTHVRCluster/Public/CAVEOverlay/CAVEOverlayController.h @@ -78,6 +78,12 @@ private: const float WallWarningDistance = 40; // cm, distance on which the tape turns red, measured from wall float DoorCurrentOpeningWidthAbsolute = 0; + // Function that initializes things from the currently possessed pawn + void InitFromPawn(const APawn* CurrentPawn); + + UFUNCTION() + void UpdatePossessedPawn(APawn* OldPawn, APawn* NewPawn); + // Helper function to create a mesh component in the constructor UStaticMeshComponent* CreateMeshComponent(const FName& Name, USceneComponent* Parent);