Skip to content
Snippets Groups Projects
Select Git revision
  • 1f4ddf2a555086793b63d18d5e754a465555fa86
  • 4.26 default protected
  • dev/5.5
  • 5.3
  • dev/5.3
  • dev/5.1
  • deprecated/4.22
7 results

VAReceiverActor.cpp

Blame
  • VAReceiverActor.cpp 13.19 KiB
    // Fill out your copyright notice in the Description page of Project Settings.
    // what's up?
    
    #include "VAReceiverActor.h"
    
    #include "VAPlugin.h"
    #include "VAUtils.h"
    #include "VADefines.h"
    
    #include "SoundSource/VAAbstractSourceComponent.h"
    #include "ImageSourceModel/VAReflectionWall.h"
    #include "Directivity/VADirectivityManager.h"
    #include "HRIR/VAHRIRManager.h"
    
    
    #include "Cluster/DisplayClusterClusterEvent.h"
    #include "Engine/World.h"							// World
    #include "GameFramework/PlayerController.h"			// Viewport
    #include "IDisplayCluster.h"						// For Events
    #include "Pawn/VirtualRealityPawn.h"						// VR Pawn
    #include "Kismet/GameplayStatics.h"					// Get Actors of class
    #include "Utility/VirtualRealityUtilities.h"
    
    
    // ****************************************************************** // 
    // ******* Initialization Functions ********************************* //
    // ****************************************************************** //
    
    AVAReceiverActor::AVAReceiverActor()
    {
    	PrimaryActorTick.bCanEverTick = true;
    
      DirManager = MakeShared<FVADirectivityManager>();
      HRIRManager = MakeShared<FVAHRIRManager>();
    
      AuralizationModeController = CreateDefaultSubobject<UVAAuralizationModeController>(TEXT("AuralizationModeController"));
    }
    
    void AVAReceiverActor::BeginPlay()
    {
    	Super::BeginPlay();
    
    	FVAPlugin::SetReceiverActor(this);
    
    	// Cluster Stuff for Events //
    	RunOnAllNodesEvent.Attach(this);
    
    	// CurrentReceiverActor = this;
    	if(bReconnecToVAServer && UVirtualRealityUtilities::IsMaster() && FVAPlugin::IsConnected())
    	{
    		//this might be needed if different server version should be started between levels
    		FVAPlugin::DisconnectServer();
    	}
    
    	//try to start (remote) VAServer automatically
    	bool bStartedVAServer = false;
    	if (bAutomaticRemoteVAStart)
    	{
    		FVAPlugin::VAServerLauncher.StartVAServerLauncher(); //if possible
    		bStartedVAServer = FVAPlugin::VAServerLauncher.RemoteStartVAServer(GetIPAddress(), RemoteVAStarterPort, WhichVAServerVersionToStart, VARendererIniFile, ReproductionInputType);
    		if(bStartedVAServer){
    			FVAPlugin::SetUseVA(true);
    		}
    	}
    	
    	// Ask if used or not
    	FVAPlugin::AskForSettings(GetIPAddress(), GetPort(), bAskForDebugMode, !bStartedVAServer);
    
    	if (UVirtualRealityUtilities::IsMaster())
    	{
    		if (FVAPlugin::GetUseVA())
    		{
    			RunOnAllNodes("useVA = true");
    		}
    		else
    		{
    			RunOnAllNodes("useVA = false");
    			return;
    		}
    	}
    
    	bWallsInitialized = false;
    
    	TimeSinceUpdate = 0.0f;
    	TotalTime = 0.0f;
    
    	if (!FVAPlugin::GetUseVA())
    	{
    		return;
    	}
    
    
    	if (UVirtualRealityUtilities::IsMaster())
    	{
    		FVAPlugin::SetScale(WorldScale);
    
    		if (!FVAPlugin::IsConnected())
    		{
    			FVAPlugin::ConnectServer(GetIPAddress(), GetPort());
    		}
    		else
    		{
    			FVAPlugin::ResetServer();
    		}
    
    		if (AuralizationModeController)
    		{
    			AuralizationModeController->Initialize();
    		}
    		
    		// Initialize the dirManager
    		DirManager->ResetManager();
    		if (bReadInitialMappingFile)
    		{
    			DirManager->ReadConfigFile(DirMappingFileName);
    		}
    
    		// Initialize the HRIRManager
    		HRIRManager->ResetManager();
    
    		// Initialize Receiver Actor
    		ReceiverID = FVAPlugin::CreateNewSoundReceiver(this);
    		if (FVAHRIRManager::GetDefaultHRIR().IsValid() && VA::IsValidID( FVAHRIRManager::GetDefaultHRIR()->GetID() ))
    		{
    			CurrentHRIR = FVAHRIRManager::GetDefaultHRIR();
    		}
    
    	}
    
    	// Initialize Walls for Sound Reflection
    	if (!bWallsInitialized)
    	{
    		InitializeWalls();
    	}
    
    
    	// Handle all sound Sources
    	TArray<AActor*> ActorsA;
    	UGameplayStatics::GetAllActorsOfClass(this->GetWorld(), AActor::StaticClass(), ActorsA);
    
    	for (AActor* Actor : ActorsA)
    	{
    		TArray<UVAAbstractSourceComponent*> VASourceComponents;
    		Actor->GetComponents(VASourceComponents);
    		for (UVAAbstractSourceComponent* SourceComponent : VASourceComponents)
    		{
    			SourceComponent->Initialize();
    		}
    	}
    
    	if (UVirtualRealityUtilities::IsMaster())
    	{
    		if (FVAPlugin::GetDebugMode())
    		{
    			RunOnAllNodes("debugMode = true");
    		}
    		else
    		{
    			RunOnAllNodes("debugMode = false");
    		}
    	}
    
    	bInitialized = true;
    }
    
    void AVAReceiverActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
    {
    	RunOnAllNodesEvent.Detach();
    
    	if(!FVAPlugin::GetWasStarted())
    	{
    		return;
    	}
    
    	DirManager->ResetManager();
    	HRIRManager->ResetManager();
    
    	Super::EndPlay(EndPlayReason);
    }
    
    void AVAReceiverActor::InitializeWalls()
    {
    	TArray<AActor*> WallsA;
    	UGameplayStatics::GetAllActorsOfClass(this->GetWorld(), AVAReflectionWall::StaticClass(), WallsA);
    	for (AActor* EntryWalls : WallsA)
    	{
    		ReflectionWalls.Add(static_cast<AVAReflectionWall*>(EntryWalls));
    	}
    	bWallsInitialized = true;
    }
    
    void AVAReceiverActor::SetUpdateRate(const int Rate)
    {
    	UpdateRate = Rate;
    }
    
    // ****************************************************************** // 
    // ******* Tick Function ******************************************** //
    // ****************************************************************** //
    
    void AVAReceiverActor::Tick(const float DeltaTime)
    {
    	Super::Tick(DeltaTime);
    
    	if (!FVAPlugin::GetUseVA() || !UVirtualRealityUtilities::IsMaster())
    	{
    		return;
    	}
    
    	if (!bInitialized)
    	{
    		FVAUtils::OpenMessageBox("[AVAReceiverActor::Tick()]: Receiver Actor is not initialized", true);
    	}
    
    	TimeSinceUpdate += DeltaTime;
    	TotalTime += DeltaTime;
    
    	if (TimeSinceUpdate > (1.0f / float(UpdateRate)))
    	{
    		UpdateVirtualWorldPose();
    		UpdateRealWorldPose();
    
    		TimeSinceUpdate = 0.0f;
    	}
    }
    
    
    // ****************************************************************** // 
    // ******* Position updates ***************************************** //
    // ****************************************************************** //
    
    bool AVAReceiverActor::SetManualReceiverData(FVector VirtualPos, FRotator VirtualRot, FVector RealWorldPos /*= FVector(0, 0, 0)*/, FRotator RealWorldRot /*= FRotator(0, 0, 0)*/)
    {
    	if (TrackingSource != ETrackingSource::ManualData)
    	{
    		FVAUtils::LogStuff("[AVAReceiverActor::SetManualReceiverData()]: SetManualReceiverData() called, but TrackingSource != ManualData", true);
    		return false;
    	}
    
    
    	const FVector HeadCenterPosition = VirtualPos + VirtualRot.RotateVector(ViewpointToHeadcenterOffset);
    
    	bool bResult = true;
    
    	//Update VirtualWorldPose
    	bResult &= FVAPlugin::SetSoundReceiverPosition(ReceiverID, HeadCenterPosition);
    	bResult &= FVAPlugin::SetSoundReceiverRotation(ReceiverID, VirtualRot);
    
    	//Update RealWorldPose
    	bResult &= FVAPlugin::SetSoundReceiverRealWorldPose(ReceiverID, RealWorldPos, RealWorldRot);
    
    	return bResult;
    }
    
    bool AVAReceiverActor::UpdateVirtualWorldPose()
    {
    
    	if(TrackingSource == ETrackingSource::VirtualRealityPawn)
    	{
    		// Auralization Pose is coppled to the Virtual Reality Pawn, e.g, HMD, CAVE
    		FVector ViewPos;
    		FRotator ViewRot;
    		GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(ViewPos, ViewRot);
    
    		bool bResult = true;
    		bResult &= FVAPlugin::SetSoundReceiverPosition(ReceiverID, ViewPos + ViewRot.RotateVector(ViewpointToHeadcenterOffset)); //Offset from ViewPoint (between eyes) to head center, rotate according to view rotation 
    		bResult &= FVAPlugin::SetSoundReceiverRotation(ReceiverID, ViewRot);
    		return bResult;
    	}
    
    	return false;
    }
    
    bool AVAReceiverActor::UpdateRealWorldPose()
    {
    
    	if (TrackingSource==ETrackingSource::VirtualRealityPawn)
    	{
    		if (!UVirtualRealityUtilities::IsMaster() || !FVAPlugin::GetUseVA())
    		{
    			return false;
    		}
    
    		if (GetWorld() == nullptr)
    		{
    			return false;
    		}
    
    		APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
    		if (PlayerController == nullptr)
    		{
    			return false;
    		}
    
    		AVirtualRealityPawn* VirtualRealityPawn = Cast<AVirtualRealityPawn>(PlayerController->AcknowledgedPawn);
    		if (VirtualRealityPawn == nullptr)
    		{
    			return false;
    		}
    
    		USceneComponent* Head = VirtualRealityPawn->Head;
    
    		if (!Head)
    		{
    			return false;
    		}
    
    		// calculate positions
    		const FQuat InverseOriginRot = VirtualRealityPawn->GetActorQuat().Inverse(); //Inverse Quaternion of Actor in Virtual World
    		const FVector HeadCenter = Head->GetComponentLocation() + Head->GetComponentRotation().RotateVector(ViewpointToHeadcenterOffset); //Location of Head Center in Virtual World
    		const FVector Pos = InverseOriginRot.RotateVector(
    			HeadCenter - VirtualRealityPawn->GetActorLocation()); //Get position by subtraction virtual origin
    		const FQuat Quat = InverseOriginRot * Head->GetComponentQuat();
    
    		return FVAPlugin::SetSoundReceiverRealWorldPose(ReceiverID, Pos, Quat.Rotator());
    	}
    
    	return false;
    }
    
    
    // ****************************************************************** // 
    // ******* Directivity / HRIR Handling ****************************** //
    // ****************************************************************** //
    
    TSharedPtr<FVADirectivity> AVAReceiverActor::GetDirectivityByMapping(const FString Phoneme) const
    {
    	return DirManager->GetDirectivityByPhoneme(Phoneme);
    }
    
    TSharedPtr<FVADirectivity> AVAReceiverActor::GetDirectivityByFileName(const FString FileName)
    {
    	return DirManager->GetDirectivityByFileName(FileName);
    }
    
    bool AVAReceiverActor::ReadDirMappingFile(const FString FileName)
    {
    	if (DirManager->GetFileName() == FileName)
    	{
    		FVAUtils::LogStuff("[AVAReceiverActor::ReadDirMappingFile()]: file already loaded", false);
    		return false;
    	}
    
    	DirMappingFileName = FileName;
    	DirManager->ResetManager();
    	return DirManager->ReadConfigFile(DirMappingFileName);
    }
    
    bool AVAReceiverActor::SetHRIRByFileName(const FString FileName)
    {
    	TSharedPtr<FVAHRIR> NewHRIR = HRIRManager->GetHRIRByFileName(FileName);
    	if (!NewHRIR.IsValid())
    	{
    		return false;
    	}
    	
    	if(CurrentHRIR.IsValid() && NewHRIR->GetID() == CurrentHRIR->GetID())
    	{
    		return true;
    	}
    	
    	if (FVAPlugin::SetSoundReceiverHRIR(ReceiverID, NewHRIR->GetID()))
    	{
    		CurrentHRIR = NewHRIR;
    		return true;
    	}
    	return false;
    }
    
    
    // ****************************************************************** // 
    // ******* Getter Functions ***************************************** //
    // ****************************************************************** //
    
    bool AVAReceiverActor::IsInitialized() const
    {
    	return bInitialized;
    }
    
    float AVAReceiverActor::GetScale() const
    {
    	return WorldScale;
    }
    
    
    FString AVAReceiverActor::GetIPAddress() const
    {
    	switch (AddressSetting)
    	{
    	case EConnectionSetting::Automatic:
    #if PLATFORM_WINDOWS
    		return FString("127.0.0.1");
    #else
    		return FString("10.0.1.240");
    #endif
    		break;
    	case EConnectionSetting::Cave:
    		return FString("10.0.1.240");
    		break;
    	case EConnectionSetting::Localhost:
    		return FString("127.0.0.1");
    		break;
    	case EConnectionSetting::Manual:
    		return ServerIPAddress;
    		break;
    	default:
    		break;
    	}
    
    	FVAUtils::LogStuff("[AVAReceiverActor::GetIPAddress()]: Unreachable Error", true);
    
    	return FString("127.0.0.1");
    }
    
    int AVAReceiverActor::GetPort() const
    {
    	switch (AddressSetting)
    	{
    	case EConnectionSetting::Automatic:
    	case EConnectionSetting::Cave:
    	case EConnectionSetting::Localhost:
    		return 12340;
    		break;
    	case EConnectionSetting::Manual:
    		return ServerPort;
    		break;
    	default:
    		break;
    	}
    
    	FVAUtils::LogStuff("[AVAReceiverActor::GetPort()]: Unreachable Error", true);
    
    	return -1;
    }
    
    UVAAuralizationModeController* AVAReceiverActor::GetAuralizationModeController() const
    {
    	return AuralizationModeController;
    }
    
    int AVAReceiverActor::GetReceiverID() const
    {
    	return ReceiverID;
    }
    
    int AVAReceiverActor::GetUpdateRate() const
    {
    	return UpdateRate;
    }
    
    TArray<AVAReflectionWall*> AVAReceiverActor::GetReflectionWalls()
    {
    	if (!bWallsInitialized)
    	{
    		InitializeWalls();
    	}
    	return ReflectionWalls;
    }
    
    
    
    // ****************************************************************** // 
    // ******* Cluster Stuff ******************************************** // 
    // ****************************************************************** //
    
    void AVAReceiverActor::SetDebugMode(const bool bDebugMode)
    {
    	if (bDebugMode)
    	{
    		RunOnAllNodes("debugMode = true");
    	}
    	else
    	{
    		RunOnAllNodes("debugMode = false");
    	}
    }
    
    
    void AVAReceiverActor::RunOnAllNodes(FString Command)
    {
    	FVAUtils::LogStuff("[AVAReceiverActor::RunOnAllNodes()]: Cluster Command " + 
    		Command + " received", false);
    	
    	if (Command == "useVA = true")
    	{
    		FVAPlugin::SetUseVA(true);
    	}
    	else if (Command == "useVA = false")
    	{
    		FVAPlugin::SetUseVA(false);
    	}
    	else if (Command == "debugMode = true")
    	{
    		FVAPlugin::SetDebugMode(true);
    	}
    	else if (Command == "debugMode = false")
    	{
    		FVAPlugin::SetDebugMode(false);
    	}
    	else
    	{
    		FVAUtils::LogStuff("[AVAReceiverActor::RunOnAllNodes()]: Cluster Command " + 
    			Command + " could not be evaluated.", true);
    	}
    }
    
    // ****************************************************************** // 
    // ******* Blueprint Settings *************************************** // 
    // ****************************************************************** //
    
    #if WITH_EDITOR
    bool AVAReceiverActor::CanEditChange(const FProperty* InProperty) const
    {
    	// Check manual Address
    	if (InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, ServerIPAddress) ||
    		InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, ServerPort))
    	{
    		return AddressSetting == EConnectionSetting::Manual;
    	}
    
    	if (InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, RemoteVAStarterPort) ||
    		InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, WhichVAServerVersionToStart) ||
    		InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, VARendererIniFile))
    	{
    		return bAutomaticRemoteVAStart;
    	}
    
    	if (InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, DirMappingFileName))
    	{
    		return bReadInitialMappingFile;
    	}
    
    	return true;
    }
    #endif