bmh/FlightSimulation/Plugins/CesiumForUnreal_5.4/Source/CesiumRuntime/Private/CesiumRasterOverlay.cpp
2025-02-07 22:52:32 +08:00

216 lines
6.6 KiB
C++

// Copyright 2020-2024 CesiumGS, Inc. and Contributors
#include "CesiumRasterOverlay.h"
#include "Async/Async.h"
#include "Cesium3DTilesSelection/Tileset.h"
#include "Cesium3DTileset.h"
#include "CesiumAsync/IAssetResponse.h"
#include "CesiumRasterOverlays/RasterOverlayLoadFailureDetails.h"
#include "CesiumRuntime.h"
FCesiumRasterOverlayLoadFailure OnCesiumRasterOverlayLoadFailure{};
// Sets default values for this component's properties
UCesiumRasterOverlay::UCesiumRasterOverlay()
: _pOverlay(nullptr), _overlaysBeingDestroyed(0) {
this->bAutoActivate = true;
// Set this component to be initialized when the game starts, and to be ticked
// every frame. You can turn these features off to improve performance if you
// don't need them.
PrimaryComponentTick.bCanEverTick = false;
// Allow DestroyComponent to be called from Blueprints by anyone. Without
// this, only the Actor (Cesium3DTileset) itself can destroy raster overlays.
// That's really annoying because it's fairly common to dynamically add/remove
// overlays at runtime.
bAllowAnyoneToDestroyMe = true;
}
#if WITH_EDITOR
// Called when properties are changed in the editor
void UCesiumRasterOverlay::PostEditChangeProperty(
FPropertyChangedEvent& PropertyChangedEvent) {
Super::PostEditChangeProperty(PropertyChangedEvent);
this->Refresh();
}
#endif
void UCesiumRasterOverlay::AddToTileset() {
if (this->_pOverlay) {
return;
}
Cesium3DTilesSelection::Tileset* pTileset = FindTileset();
if (!pTileset) {
return;
}
CesiumRasterOverlays::RasterOverlayOptions options{};
options.ellipsoid = pTileset->getOptions().ellipsoid;
options.maximumScreenSpaceError = this->MaximumScreenSpaceError;
options.maximumSimultaneousTileLoads = this->MaximumSimultaneousTileLoads;
options.maximumTextureSize = this->MaximumTextureSize;
options.subTileCacheBytes = this->SubTileCacheBytes;
options.showCreditsOnScreen = this->ShowCreditsOnScreen;
options.rendererOptions = &this->rendererOptions;
options.loadErrorCallback =
[this](const CesiumRasterOverlays::RasterOverlayLoadFailureDetails&
details) {
static_assert(
uint8_t(ECesiumRasterOverlayLoadType::CesiumIon) ==
uint8_t(CesiumRasterOverlays::RasterOverlayLoadType::CesiumIon));
static_assert(
uint8_t(ECesiumRasterOverlayLoadType::TileProvider) ==
uint8_t(CesiumRasterOverlays::RasterOverlayLoadType::TileProvider));
static_assert(
uint8_t(ECesiumRasterOverlayLoadType::Unknown) ==
uint8_t(CesiumRasterOverlays::RasterOverlayLoadType::Unknown));
uint8_t typeValue = uint8_t(details.type);
assert(
uint8_t(details.type) <=
uint8_t(
Cesium3DTilesSelection::RasterOverlayLoadType::TilesetJson));
assert(this->_pTileset == details.pTileset);
FCesiumRasterOverlayLoadFailureDetails ueDetails{};
ueDetails.Overlay = this;
ueDetails.Type = ECesiumRasterOverlayLoadType(typeValue);
ueDetails.HttpStatusCode =
details.pRequest && details.pRequest->response()
? details.pRequest->response()->statusCode()
: 0;
ueDetails.Message = UTF8_TO_TCHAR(details.message.c_str());
// Broadcast the event from the game thread.
// Even if we're already in the game thread, let the stack unwind.
// Otherwise actions that destroy the Tileset will cause a deadlock.
AsyncTask(
ENamedThreads::GameThread,
[ueDetails = std::move(ueDetails)]() {
OnCesiumRasterOverlayLoadFailure.Broadcast(ueDetails);
});
};
std::unique_ptr<CesiumRasterOverlays::RasterOverlay> pOverlay =
this->CreateOverlay(options);
if (pOverlay) {
this->_pOverlay = pOverlay.release();
pTileset->getOverlays().add(this->_pOverlay);
this->OnAdd(pTileset, this->_pOverlay);
}
}
void UCesiumRasterOverlay::RemoveFromTileset() {
if (!this->_pOverlay) {
return;
}
Cesium3DTilesSelection::Tileset* pTileset = FindTileset();
if (!pTileset) {
return;
}
// Don't allow this RasterOverlay to be fully destroyed until
// any cesium-native RasterOverlays it created have wrapped up any async
// operations in progress and have been fully destroyed.
// See IsReadyForFinishDestroy.
++this->_overlaysBeingDestroyed;
this->_pOverlay->getAsyncDestructionCompleteEvent(getAsyncSystem())
.thenInMainThread([this]() { --this->_overlaysBeingDestroyed; });
this->OnRemove(pTileset, this->_pOverlay);
pTileset->getOverlays().remove(this->_pOverlay);
this->_pOverlay = nullptr;
}
void UCesiumRasterOverlay::Refresh() {
this->RemoveFromTileset();
if (this->IsActive()) {
this->AddToTileset();
}
}
double UCesiumRasterOverlay::GetMaximumScreenSpaceError() const {
return this->MaximumScreenSpaceError;
}
void UCesiumRasterOverlay::SetMaximumScreenSpaceError(double Value) {
this->MaximumScreenSpaceError = Value;
this->Refresh();
}
int32 UCesiumRasterOverlay::GetMaximumTextureSize() const {
return this->MaximumTextureSize;
}
void UCesiumRasterOverlay::SetMaximumTextureSize(int32 Value) {
this->MaximumTextureSize = Value;
this->Refresh();
}
int32 UCesiumRasterOverlay::GetMaximumSimultaneousTileLoads() const {
return this->MaximumSimultaneousTileLoads;
}
void UCesiumRasterOverlay::SetMaximumSimultaneousTileLoads(int32 Value) {
this->MaximumSimultaneousTileLoads = Value;
if (this->_pOverlay) {
this->_pOverlay->getOptions().maximumSimultaneousTileLoads = Value;
}
}
int64 UCesiumRasterOverlay::GetSubTileCacheBytes() const {
return this->SubTileCacheBytes;
}
void UCesiumRasterOverlay::SetSubTileCacheBytes(int64 Value) {
this->SubTileCacheBytes = Value;
if (this->_pOverlay) {
this->_pOverlay->getOptions().subTileCacheBytes = Value;
}
}
void UCesiumRasterOverlay::Activate(bool bReset) {
Super::Activate(bReset);
this->AddToTileset();
}
void UCesiumRasterOverlay::Deactivate() {
Super::Deactivate();
this->RemoveFromTileset();
}
void UCesiumRasterOverlay::OnComponentDestroyed(bool bDestroyingHierarchy) {
this->RemoveFromTileset();
Super::OnComponentDestroyed(bDestroyingHierarchy);
}
bool UCesiumRasterOverlay::IsReadyForFinishDestroy() {
bool ready = Super::IsReadyForFinishDestroy();
ready &= this->_overlaysBeingDestroyed == 0;
if (!ready) {
getAssetAccessor()->tick();
getAsyncSystem().dispatchMainThreadTasks();
}
return ready;
}
Cesium3DTilesSelection::Tileset* UCesiumRasterOverlay::FindTileset() const {
ACesium3DTileset* pActor = this->GetOwner<ACesium3DTileset>();
if (!pActor) {
return nullptr;
}
return pActor->GetTileset();
}