Files
UnrealEngine/Engine/Plugins/Runtime/nDisplay/Source/DisplayCluster/Private/Blueprints/DisplayClusterBlueprintLib.cpp
2025-05-18 13:04:45 +08:00

353 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Blueprints/DisplayClusterBlueprintLib.h"
#include "Blueprints/DisplayClusterBlueprintAPIImpl.h"
#include "Cluster/IDisplayClusterClusterManager.h"
#include "Components/DisplayClusterICVFXCameraComponent.h"
#include "Game/IDisplayClusterGameManager.h"
#include "Misc/DisplayClusterLog.h"
#include "IDisplayCluster.h"
#include "DisplayClusterChromakeyCardActor.h"
#include "DisplayClusterLightCardActor.h"
#include "DisplayClusterRootActor.h"
#include "DisplayClusterConfigurationTypes.h"
#include "UObject/Package.h"
#if WITH_EDITOR
#include "ScopedTransaction.h"
#endif
#define LOCTEXT_NAMESPACE "UDisplayClusterBlueprintLib"
// [DEPRECATED]
void UDisplayClusterBlueprintLib::GetAPI(TScriptInterface<IDisplayClusterBlueprintAPI>& OutAPI)
{
static UDisplayClusterBlueprintAPIImpl* Obj = NewObject<UDisplayClusterBlueprintAPIImpl>(GetTransientPackage(), NAME_None, RF_MarkAsRootSet);
OutAPI = Obj;
}
EDisplayClusterOperationMode UDisplayClusterBlueprintLib::GetOperationMode()
{
return IDisplayCluster::Get().GetOperationMode();
}
ADisplayClusterRootActor* UDisplayClusterBlueprintLib::GetRootActor()
{
return IDisplayCluster::Get().GetGameMgr()->GetRootActor();
}
FString UDisplayClusterBlueprintLib::GetNodeId()
{
return IDisplayCluster::Get().GetClusterMgr()->GetNodeId();
}
void UDisplayClusterBlueprintLib::GetActiveNodeIds(TArray<FString>& OutNodeIds)
{
IDisplayCluster::Get().GetClusterMgr()->GetNodeIds(OutNodeIds);
}
int32 UDisplayClusterBlueprintLib::GetActiveNodesAmount()
{
return IDisplayCluster::Get().GetClusterMgr()->GetNodesAmount();
}
bool UDisplayClusterBlueprintLib::IsPrimary()
{
return IDisplayCluster::Get().GetClusterMgr()->IsPrimary();
}
bool UDisplayClusterBlueprintLib::IsSecondary()
{
return IDisplayCluster::Get().GetClusterMgr()->IsSecondary();
}
bool UDisplayClusterBlueprintLib::IsBackup()
{
return IDisplayCluster::Get().GetClusterMgr()->IsBackup();
}
bool UDisplayClusterBlueprintLib::HasClusterRole(EDisplayClusterNodeRole Role)
{
return IDisplayCluster::Get().GetClusterMgr()->HasClusterRole(Role);
}
EDisplayClusterNodeRole UDisplayClusterBlueprintLib::GetClusterRole()
{
return IDisplayCluster::Get().GetClusterMgr()->GetClusterRole();
}
void UDisplayClusterBlueprintLib::AddClusterEventListener(TScriptInterface<IDisplayClusterClusterEventListener> Listener)
{
IDisplayCluster::Get().GetClusterMgr()->AddClusterEventListener(Listener);
}
void UDisplayClusterBlueprintLib::RemoveClusterEventListener(TScriptInterface<IDisplayClusterClusterEventListener> Listener)
{
IDisplayCluster::Get().GetClusterMgr()->RemoveClusterEventListener(Listener);
}
void UDisplayClusterBlueprintLib::EmitClusterEventJson(const FDisplayClusterClusterEventJson& Event, bool bPrimaryOnly)
{
IDisplayCluster::Get().GetClusterMgr()->EmitClusterEventJson(Event, bPrimaryOnly);
}
void UDisplayClusterBlueprintLib::EmitClusterEventBinary(const FDisplayClusterClusterEventBinary& Event, bool bPrimaryOnly)
{
IDisplayCluster::Get().GetClusterMgr()->EmitClusterEventBinary(Event, bPrimaryOnly);
}
void UDisplayClusterBlueprintLib::SendClusterEventJsonTo(const FString& Address, const int32 Port, const FDisplayClusterClusterEventJson& Event, bool bPrimaryOnly)
{
if (Port >= 0 && Port <= 0xffff)
{
const uint16 PortNumber = static_cast<uint16>(Port);
IDisplayCluster::Get().GetClusterMgr()->SendClusterEventTo(Address, PortNumber, Event, bPrimaryOnly);
}
else
{
UE_LOG(LogDisplayClusterBlueprint, Warning, TEXT("Wrong port number: %d"), Port);
}
}
void UDisplayClusterBlueprintLib::SendClusterEventBinaryTo(const FString& Address, const int32 Port, const FDisplayClusterClusterEventBinary& Event, bool bPrimaryOnly)
{
if (Port >= 0 && Port <= 0xffff)
{
const uint16 PortNumber = static_cast<uint16>(Port);
IDisplayCluster::Get().GetClusterMgr()->SendClusterEventTo(Address, PortNumber, Event, bPrimaryOnly);
}
else
{
UE_LOG(LogDisplayClusterBlueprint, Warning, TEXT("Wrong port number: %d"), Port);
}
}
ADisplayClusterLightCardActor* UDisplayClusterBlueprintLib::CreateLightCard(ADisplayClusterRootActor* RootActor)
{
if (!RootActor)
{
return nullptr;
}
// Create the light card
#if WITH_EDITOR
FScopedTransaction Transaction(LOCTEXT("CreateLightCard", "Create Light Card"));
#endif
const FVector SpawnLocation = RootActor->GetDefaultCamera()->GetComponentLocation();
FRotator SpawnRotation = RootActor->GetDefaultCamera()->GetComponentRotation();
SpawnRotation.Yaw -= 180.f;
FActorSpawnParameters SpawnParameters;
SpawnParameters.bNoFail = true;
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
SpawnParameters.Name = TEXT("LightCard");
SpawnParameters.NameMode = FActorSpawnParameters::ESpawnActorNameMode::Requested;
SpawnParameters.OverrideLevel = RootActor->GetLevel();
ADisplayClusterLightCardActor* NewActor = CastChecked<ADisplayClusterLightCardActor>(
RootActor->GetWorld()->SpawnActor(ADisplayClusterLightCardActor::StaticClass(),
&SpawnLocation, &SpawnRotation, MoveTemp(SpawnParameters)));
NewActor->Latitude = 30.0;
NewActor->Longitude = 180.0;
NewActor->Color = FLinearColor::Gray;
#if WITH_EDITOR
NewActor->SetActorLabel(NewActor->GetName());
#endif
FAttachmentTransformRules AttachmentRules(EAttachmentRule::KeepWorld, false);
NewActor->AttachToActor(RootActor, AttachmentRules);
// Add it to the root actor
NewActor->AddToRootActor(RootActor);
#if WITH_EDITOR
// Required so operator panel updates
RootActor->PostEditChange();
#endif
return NewActor;
}
void UDisplayClusterBlueprintLib::DuplicateLightCards(TArray<ADisplayClusterLightCardActor*> OriginalLightcards, TArray<ADisplayClusterLightCardActor*>& OutNewLightCards)
{
#if WITH_EDITOR
TMap<UWorld*, FCachedActorLabels> ActorLabelsByWorld;
FScopedTransaction Transaction(LOCTEXT("DuplicateLightCard", "Duplicate Light Cards"));
#endif
for (ADisplayClusterLightCardActor* OriginalLightcard : OriginalLightcards)
{
if (!OriginalLightcard)
{
continue;
}
ADisplayClusterRootActor* RootActor = OriginalLightcard->GetRootActorOwner();
if (!RootActor)
{
continue;
}
UWorld* World = RootActor->GetWorld();
ULevel* Level = World ? World->GetCurrentLevel() : nullptr;
if (!Level)
{
continue;
}
const FName UniqueName = MakeUniqueObjectName(Level, OriginalLightcard->GetClass());
ADisplayClusterLightCardActor* NewLightCard = CastChecked<ADisplayClusterLightCardActor>(StaticDuplicateObject(OriginalLightcard, Level, UniqueName));
#if WITH_EDITOR
Level->AddLoadedActor(NewLightCard);
FCachedActorLabels* ActorLabels = ActorLabelsByWorld.Find(World);
if (!ActorLabels)
{
ActorLabels = &ActorLabelsByWorld.Emplace(World, World);
}
FActorLabelUtilities::SetActorLabelUnique(NewLightCard, NewLightCard->GetActorLabel(), ActorLabels);
ActorLabels->Add(NewLightCard->GetActorLabel());
#endif
FAttachmentTransformRules AttachmentRules(EAttachmentRule::KeepWorld, false);
NewLightCard->AttachToActor(RootActor, AttachmentRules);
// Add it to the root actor
NewLightCard->AddToRootActor(RootActor);
#if WITH_EDITOR
// Required so operator panel updates
RootActor->PostEditChange();
#endif
#if WITH_EDITOR
if (GIsEditor)
{
GEditor->BroadcastLevelActorAdded(NewLightCard);
}
#endif
OutNewLightCards.Add(NewLightCard);
}
}
void UDisplayClusterBlueprintLib::FindLightCardsForRootActor(const ADisplayClusterRootActor* RootActor, TSet<ADisplayClusterLightCardActor*>& OutLightCards)
{
if (!RootActor)
{
return;
}
FDisplayClusterConfigurationICVFX_VisibilityList& RootActorLightCards = RootActor->GetConfigData()->StageSettings.Lightcard.ShowOnlyList;
for (const TSoftObjectPtr<AActor>& LightCardActor : RootActorLightCards.Actors)
{
if (!LightCardActor.IsValid() || !LightCardActor->IsA<ADisplayClusterLightCardActor>())
{
continue;
}
OutLightCards.Add(Cast<ADisplayClusterLightCardActor>(LightCardActor.Get()));
}
if (const UWorld* World = RootActor->GetWorld())
{
for (TActorIterator<ADisplayClusterLightCardActor> ActorIt(World); ActorIt; ++ActorIt)
{
if (!IsValid(*ActorIt))
{
continue;
}
if (ActorIt->GetRootActorOwner() == RootActor)
{
OutLightCards.Add(*ActorIt);
}
else
{
// If there are any layers that are specified as light card layers, iterate over all actors in the world and
// add any that are members of any of the light card layers to the list. Only add an actor once, even if it is
// in multiple layers
for (const FActorLayer& ActorLayer : RootActorLightCards.ActorLayers)
{
if (ActorIt->Layers.Contains(ActorLayer.Name))
{
OutLightCards.Add(*ActorIt);
break;
}
}
}
}
}
}
void UDisplayClusterBlueprintLib::FindChromakeyCardsForRootActor(const ADisplayClusterRootActor* RootActor,
TSet<ADisplayClusterChromakeyCardActor*>& OutChromakeyCards)
{
if (!RootActor)
{
return;
}
TArray<UDisplayClusterICVFXCameraComponent*> CameraComponents;
RootActor->GetComponents(CameraComponents);
for (const UDisplayClusterICVFXCameraComponent* Camera : CameraComponents)
{
const FDisplayClusterConfigurationICVFX_ChromakeyRenderSettings* CameraChromakeyRenderSettings = Camera->GetCameraSettingsICVFX().Chromakey.GetChromakeyRenderSettings(RootActor->GetStageSettings());
const FDisplayClusterConfigurationICVFX_VisibilityList* CameraChromakeyShowOnlyList = CameraChromakeyRenderSettings ? &CameraChromakeyRenderSettings->ShowOnlyList : nullptr;
if (CameraChromakeyShowOnlyList)
{
for (const TSoftObjectPtr<AActor>& ChromakeyCardActor : CameraChromakeyShowOnlyList->Actors)
{
if (!ChromakeyCardActor.IsValid() || !ChromakeyCardActor->IsA<ADisplayClusterChromakeyCardActor>())
{
continue;
}
OutChromakeyCards.Add(Cast<ADisplayClusterChromakeyCardActor>(ChromakeyCardActor.Get()));
}
}
if (const UWorld* World = RootActor->GetWorld())
{
for (TActorIterator<ADisplayClusterChromakeyCardActor> ActorIt(World); ActorIt; ++ActorIt)
{
if (!IsValid(*ActorIt))
{
continue;
}
if (ActorIt->GetRootActorOwner() == RootActor)
{
OutChromakeyCards.Add(*ActorIt);
}
else if(CameraChromakeyShowOnlyList)
{
for (const FActorLayer& ActorLayer : CameraChromakeyShowOnlyList->ActorLayers)
{
if (ActorIt->Layers.Contains(ActorLayer.Name))
{
OutChromakeyCards.Add(*ActorIt);
break;
}
}
}
}
}
}
}
#undef LOCTEXT_NAMESPACE