in Ambit/Source/Ambit/Mode/ConfigImportExport.cpp [493:606]
FReply UConfigImportExport::OnExportGltf()
{
FAmbitMode* AmbitMode = FAmbitMode::GetEditorMode();
check(AmbitMode);
const TArray<FString> TargetPlatforms = AmbitMode->UISettings->ExportPlatforms.GetSelectedPlatforms();
FString AwsRegion;
FString BucketName;
const bool bFoundBucket = GetAwsSettings(AwsRegion, BucketName, true);
if (!bFoundBucket)
{
return FReply::Handled();
}
// Find World and compare to CurrentWorldContext to make sure we're not accidentally referring to valid static
// object from another world context.
UWorld* CurrentWorldContext = GEngine->GetWorldContexts()[0].World();
bool bFoundWorld = false;
for (TObjectIterator<UStaticMeshComponent> Itr; Itr; ++Itr)
{
AActor* Parent = (*Itr)->GetOwner();
if (Parent == nullptr)
{
continue;
}
// Two steps to determine validity of actor as a static mesh actor:
// 1. It should be of type AStaticMeshActor or AHoudiniAssetActor.
// 2. It should not be marked for deletion in the editor.
const bool bIsStaticMeshActor = Parent->IsA(AStaticMeshActor::StaticClass());
const bool bIsHoudiniAssetActor = UHoudiniPublicAPIAssetWrapper::CanWrapHoudiniObject(Parent);
const bool bIsValidActor = bIsStaticMeshActor || bIsHoudiniAssetActor;
const bool bIsActorBeingDeleted = Parent->IsActorBeingDestroyed();
if (!bIsValidActor || bIsActorBeingDeleted)
{
continue;
}
// Important to check if ParentWorld == nullptr because it is possible for an Actor to be of type
// AStaticMeshActor or AHoudiniAssetActor but not be associated with a World object,
// (e.g) AInteractiveFoliageActor, which derives from AStaticMeshActor but doesn't point to a World object.
UWorld* ParentWorld = Parent->GetWorld();
if (ParentWorld != nullptr && ParentWorld == CurrentWorldContext)
{
bFoundWorld = true;
break;
}
}
FString ErrorMessage;
if (!bFoundWorld)
{
ErrorMessage = "Cannot find a static mesh to export.";
FMenuHelpers::LogErrorAndPopup(ErrorMessage);
return FReply::Handled();
}
const FString GltfExtension = AmbitMode->UISettings->GltfType.ToLower();
const FString MapName = CurrentWorldContext->GetName();
const FString FolderName = MapName + TEXT("_") + GltfExtension;
const FString Filename = MapName + TEXT(".") + GltfExtension;
const FString OutputDir = FPaths::Combine(*FPaths::ProjectDir(), TEXT("Saved"), TEXT("Cooked"), FolderName);
const FString FilePath = FPaths::Combine(OutputDir, Filename);
// Perform the export to glTF.
const UGltfExport::GltfExportReturnCode ReturnCode = LambdaExportGltf(CurrentWorldContext, FilePath);
if (ReturnCode == UGltfExport::ExporterNotInitialized)
{
ErrorMessage = "glTF Exporter not initialized.";
FMenuHelpers::LogErrorAndPopup(ErrorMessage);
return FReply::Handled();
}
if(ReturnCode == UGltfExport::ExporterNotFound)
{
ErrorMessage = "glTF Export: glTF Exporter plugin is not installed. \
Follow the instructions in the User Guide to install the glTF Exporter plugin from the marketplace.";
FMenuHelpers::LogErrorAndPopup(ErrorMessage);
return FReply::Handled();
}
if (ReturnCode == UGltfExport::WriteToFileError)
{
ErrorMessage = "glTF Export: Error writing to file " + FilePath;
FMenuHelpers::LogErrorAndPopup(ErrorMessage);
return FReply::Handled();
}
if (ReturnCode == UGltfExport::Failed)
{
ErrorMessage = "glTF Export: Error completing export to " + FilePath;
FMenuHelpers::LogErrorAndPopup(ErrorMessage);
return FReply::Handled();
}
for (const FString& TargetPlatform : TargetPlatforms)
{
const FString& CompressedFile = AmbitFileHelpers::CompressFile(OutputDir, FPaths::ProjectIntermediateDir(),
FolderName, TargetPlatform);
LambdaS3FileUpload(AwsRegion, BucketName, CompressedFile,
FPaths::Combine(*FPaths::ProjectIntermediateDir(), *CompressedFile));
}
const FText NotificationText = NSLOCTEXT("Ambit", "MapUploadComplete", "Successfully uploaded to S3.");
FAmbitModule::CreateAmbitNotification(NotificationText);
return FReply::Handled();
}