// Copyright 2020-2024 CesiumGS, Inc. and Contributors #include "CesiumCameraManager.h" #include "CesiumRuntime.h" #include "Engine/World.h" #include "EngineUtils.h" #include #include FName ACesiumCameraManager::DEFAULT_CAMERAMANAGER_TAG = FName("DEFAULT_CAMERAMANAGER"); /*static*/ ACesiumCameraManager* ACesiumCameraManager::GetDefaultCameraManager( const UObject* WorldContextObject) { // A null world context means a null return value (no camera manager // available) if (WorldContextObject == nullptr) return nullptr; UWorld* world = WorldContextObject->GetWorld(); // This method can be called by actors even when opening the content browser. if (!IsValid(world)) { return nullptr; } UE_LOG( LogCesium, Verbose, TEXT("World name for GetDefaultCameraManager: %s"), *world->GetFullName()); // Note: The actor iterator will be created with the // "EActorIteratorFlags::SkipPendingKill" flag, // meaning that we don't have to handle objects // that have been deleted. (This is the default, // but made explicit here) ACesiumCameraManager* pCameraManager = nullptr; EActorIteratorFlags flags = EActorIteratorFlags::OnlyActiveLevels | EActorIteratorFlags::SkipPendingKill; for (TActorIterator actorIterator( world, ACesiumCameraManager::StaticClass(), flags); actorIterator; ++actorIterator) { AActor* actor = *actorIterator; if (actor->GetLevel() == world->PersistentLevel && actor->ActorHasTag(DEFAULT_CAMERAMANAGER_TAG)) { pCameraManager = Cast(actor); break; } } if (!pCameraManager) { UE_LOG( LogCesium, Verbose, TEXT("Creating default ACesiumCameraManager for actor %s"), *WorldContextObject->GetName()); // Spawn georeference in the persistent level FActorSpawnParameters spawnParameters; spawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; spawnParameters.OverrideLevel = world->PersistentLevel; pCameraManager = world->SpawnActor(spawnParameters); // Null check so the editor doesn't crash when it makes arbitrary calls to // this function without a valid world context object. if (pCameraManager) { pCameraManager->Tags.Add(DEFAULT_CAMERAMANAGER_TAG); } } else { UE_LOG( LogCesium, Verbose, TEXT("Using existing ACesiumCameraManager %s for actor %s"), *pCameraManager->GetName(), *WorldContextObject->GetName()); } return pCameraManager; } ACesiumCameraManager::ACesiumCameraManager() : AActor() { #if WITH_EDITOR this->SetIsSpatiallyLoaded(false); #endif } bool ACesiumCameraManager::ShouldTickIfViewportsOnly() const { return true; } void ACesiumCameraManager::Tick(float DeltaTime) { Super::Tick(DeltaTime); } int32 ACesiumCameraManager::AddCamera(UPARAM(ref) const FCesiumCamera& camera) { int32 cameraId = this->_currentCameraId++; this->_cameras.Emplace(cameraId, camera); return cameraId; } bool ACesiumCameraManager::RemoveCamera(int32 cameraId) { int32 numRemovedPairs = this->_cameras.Remove(cameraId); bool success = numRemovedPairs > 0; return success; } bool ACesiumCameraManager::UpdateCamera( int32 cameraId, UPARAM(ref) const FCesiumCamera& camera) { FCesiumCamera* pCurrentCamera = this->_cameras.Find(cameraId); if (pCurrentCamera) { *pCurrentCamera = camera; return true; } return false; } const TMap& ACesiumCameraManager::GetCameras() const { return this->_cameras; }