// Lot STM1 (STM1-IMPL-03). Voir LPImportCityOSMCommandlet.h. #include "LPImportCityOSMCommandlet.h" #include "AssetRegistry/AssetRegistryModule.h" #include "Factories/Factory.h" #include "HAL/FileManager.h" #include "HAL/PlatformMemory.h" #include "HAL/PlatformTime.h" #include "Misc/FileHelper.h" #include "Misc/PackageName.h" #include "Modules/ModuleManager.h" #include "StreetMap.h" #include "UObject/Package.h" #include "UObject/SavePackage.h" DEFINE_LOG_CATEGORY_STATIC(LogLPImportCityOSM, Log, All); ULPImportCityOSMCommandlet::ULPImportCityOSMCommandlet() { IsClient = false; IsServer = false; IsEditor = true; LogToConsole = true; } int32 ULPImportCityOSMCommandlet::Main(const FString& Params) { TArray Tokens; TArray Switches; TMap ParamsMap; ParseCommandLine(*Params, Tokens, Switches, ParamsMap); const FString OsmPath = ParamsMap.FindRef(TEXT("Osm")); const FString PackageName = ParamsMap.FindRef(TEXT("Package")); const FString ReportPath = ParamsMap.FindRef(TEXT("Report")); TArray Report; auto Line = [&Report](const FString& Text) { UE_LOG(LogLPImportCityOSM, Display, TEXT("%s"), *Text); Report.Add(Text); }; auto Finish = [&](int32 Code) { Line(FString::Printf(TEXT("CODE %d"), Code)); if (!ReportPath.IsEmpty()) { FFileHelper::SaveStringArrayToFile(Report, *ReportPath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM); } return Code; }; if (OsmPath.IsEmpty() || PackageName.IsEmpty()) { Line(TEXT("usage : -Osm= -Package=/Game/Heavy/StreetMap/_Pilot/ [-Report=]")); return Finish(2); } Line(FString::Printf(TEXT("# LPImportCityOSM %s <- %s"), *PackageName, *OsmPath)); // Gardes : paquet d'essai seulement, jamais d'ecrasement. if (!PackageName.StartsWith(TEXT("/Game/Heavy/StreetMap/_Pilot/")) || !FPackageName::IsValidLongPackageName(PackageName)) { Line(TEXT("ECHEC : le paquet doit etre sous /Game/Heavy/StreetMap/_Pilot/ (pilote) ; aucun asset ecrit")); return Finish(1); } if (FPackageName::DoesPackageExist(PackageName)) { Line(FString::Printf(TEXT("ECHEC : %s existe deja ; aucun asset ecrit"), *PackageName)); return Finish(1); } const int64 OsmBytes = IFileManager::Get().FileSize(*OsmPath); if (OsmBytes <= 0) { Line(FString::Printf(TEXT("ECHEC : fichier introuvable ou vide : %s"), *OsmPath)); return Finish(1); } Line(FString::Printf(TEXT("fichier source : %lld octets"), OsmBytes)); // Fabrique du plugin, par reflexion (UStreetMapFactory n'est pas exportee). FModuleManager::Get().LoadModule(TEXT("StreetMapImporting")); UClass* FactoryClass = FindObject(nullptr, TEXT("/Script/StreetMapImporting.StreetMapFactory")); if (!FactoryClass || !FactoryClass->IsChildOf(UFactory::StaticClass())) { Line(TEXT("ECHEC : fabrique /Script/StreetMapImporting.StreetMapFactory introuvable")); return Finish(1); } UFactory* Factory = NewObject(GetTransientPackage(), FactoryClass); const FString AssetName = FPackageName::GetLongPackageAssetName(PackageName); UPackage* Package = CreatePackage(*PackageName); const double Start = FPlatformTime::Seconds(); bool bCanceled = false; UObject* Imported = Factory->ImportObject(UStreetMap::StaticClass(), Package, *AssetName, RF_Public | RF_Standalone, OsmPath, nullptr, bCanceled); const double ImportSeconds = FPlatformTime::Seconds() - Start; const UStreetMap* StreetMap = Cast(Imported); if (!StreetMap || bCanceled) { Line(FString::Printf(TEXT("ECHEC : import (%s) apres %.1f s ; aucun asset ecrit"), bCanceled ? TEXT("annule") : TEXT("objet nul"), ImportSeconds)); return Finish(1); } // Comptes. int32 Named = 0, WithAmenity = 0; TSet AmenityTypes; for (const FStreetMapBuilding& Building : StreetMap->GetBuildings()) { Named += Building.BuildingName.IsEmpty() ? 0 : 1; if (!Building.Amenity.IsEmpty()) { ++WithAmenity; AmenityTypes.Add(Building.Amenity); } } const FVector2D Min = StreetMap->GetBoundsMin(); const FVector2D Max = StreetMap->GetBoundsMax(); Line(FString::Printf(TEXT("import : %.1f s ; routes %d, noeuds %d, batiments %d (nommes %d, avec amenite %d, %d types), parcs %d, eaux %d"), ImportSeconds, StreetMap->GetRoads().Num(), StreetMap->GetNodes().Num(), StreetMap->GetBuildings().Num(), Named, WithAmenity, AmenityTypes.Num(), StreetMap->GetParks().Num(), StreetMap->GetWaters().Num())); Line(FString::Printf(TEXT("bornes (cm) : (%.0f, %.0f) a (%.0f, %.0f) ; soit %.2f x %.2f km"), Min.X, Min.Y, Max.X, Max.Y, (Max.X - Min.X) / 100000.0, (Max.Y - Min.Y) / 100000.0)); // Sauvegarde du paquet d'essai. FAssetRegistryModule::AssetCreated(const_cast(StreetMap)); FSavePackageArgs SaveArgs; SaveArgs.TopLevelFlags = RF_Public | RF_Standalone; const FString FileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension()); const double SaveStart = FPlatformTime::Seconds(); if (!UPackage::SavePackage(Package, const_cast(StreetMap), *FileName, SaveArgs)) { Line(FString::Printf(TEXT("ECHEC : sauvegarde de %s"), *FileName)); return Finish(1); } const double SaveSeconds = FPlatformTime::Seconds() - SaveStart; const FPlatformMemoryStats Mem = FPlatformMemory::GetStats(); Line(FString::Printf(TEXT("asset ecrit : %s (%s), %lld octets, sauvegarde %.1f s"), *PackageName, *FileName, IFileManager::Get().FileSize(*FileName), SaveSeconds)); Line(FString::Printf(TEXT("memoire : pic physique du processus %.2f Go ; pic virtuel %.2f Go"), double(Mem.PeakUsedPhysical) / (1024.0 * 1024.0 * 1024.0), double(Mem.PeakUsedVirtual) / (1024.0 * 1024.0 * 1024.0))); return Finish(0); }