10#include "FileHelpers.h"
12#include "Misc/FileHelper.h"
13#include "JsonObject.h"
14#include "JsonSerializer.h"
15#include "UObject/ConstructorHelpers.h"
16#include "Runtime/Engine/Classes/Kismet/GameplayStatics.h"
17#include "Engine/StreamableManager.h"
18#include "Engine/StaticMeshActor.h"
20#include "Engine/DecalActor.h"
21#include "Components/DecalComponent.h"
33#if WITH_EDITORONLY_DATA
35 static ConstructorHelpers::FObjectFinder<UBlueprint> RoadPainterBlueprint(TEXT(
36 "Blueprint'/Game/Carla/Blueprints/LevelDesign/RoadPainterPreset.RoadPainterPreset'"));
41 DecalNamesMap.Add(
"dirt1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadDirt_01.DI_RoadDirt_01'");
42 DecalNamesMap.Add(
"dirt2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadDirt_02.DI_RoadDirt_02'");
43 DecalNamesMap.Add(
"dirt3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadDirt_03.DI_RoadDirt_03'");
44 DecalNamesMap.Add(
"dirt4",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadDirt_04.DI_RoadDirt_04'");
45 DecalNamesMap.Add(
"dirt5",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadDirt_05.DI_RoadDirt_05'");
48 DecalNamesMap.Add(
"drip1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadDrip_01.DI_RoadDrip_01'");
49 DecalNamesMap.Add(
"drip2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadDrip_02.DI_RoadDrip_02'");
50 DecalNamesMap.Add(
"drip3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadDrip_03.DI_RoadDrip_03'");
53 DecalNamesMap.Add(
"roadline1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadLine_01.DI_RoadLine_01'");
54 DecalNamesMap.Add(
"roadline2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadLine_02.DI_RoadLine_02'");
55 DecalNamesMap.Add(
"roadline3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadLine_03.DI_RoadLine_03'");
56 DecalNamesMap.Add(
"roadline4",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadLine_04.DI_RoadLine_04'");
57 DecalNamesMap.Add(
"roadline5",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_RoadLine_05.DI_RoadLine_05'");
60 DecalNamesMap.Add(
"tiremark1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_TireMark_01.DI_TireMark_01'");
61 DecalNamesMap.Add(
"tiremark2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_TireMark_02.DI_TireMark_02'");
62 DecalNamesMap.Add(
"tiremark3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/RoadDirt/DI_TireMark_03.DI_TireMark_03'");
65 DecalNamesMap.Add(
"tarsnake1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake1.DI_tarsnake1'");
66 DecalNamesMap.Add(
"tarsnake2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake2.DI_tarsnake2'");
67 DecalNamesMap.Add(
"tarsnake3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake3.DI_tarsnake3'");
68 DecalNamesMap.Add(
"tarsnake4",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake4.DI_tarsnake4'");
69 DecalNamesMap.Add(
"tarsnake5",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake5.DI_tarsnake5'");
70 DecalNamesMap.Add(
"tarsnake6",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake6.DI_tarsnake6'");
71 DecalNamesMap.Add(
"tarsnake7",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake7.DI_tarsnake7'");
72 DecalNamesMap.Add(
"tarsnake8",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake8.DI_tarsnake8'");
73 DecalNamesMap.Add(
"tarsnake9",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake9.DI_tarsnake9'");
74 DecalNamesMap.Add(
"tarsnake10",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake10.DI_tarsnake10'");
75 DecalNamesMap.Add(
"tarsnake11",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/TarSnakes/DI_tarsnake11.DI_tarsnake11'");
78 DecalNamesMap.Add(
"cracksbig1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_cracksBig1.DI_cracksBig1'");
79 DecalNamesMap.Add(
"cracksbig2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_cracksBig2.DI_cracksBig2'");
80 DecalNamesMap.Add(
"cracksbig3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_cracksBig3.DI_cracksBig3'");
81 DecalNamesMap.Add(
"cracksbig4",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_cracksBig4.DI_cracksBig4'");
82 DecalNamesMap.Add(
"cracksbig5",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_cracksBig5.DI_cracksBig5'");
83 DecalNamesMap.Add(
"cracksbig6",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_cracksBig6.DI_cracksBig6'");
84 DecalNamesMap.Add(
"cracksbig7",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_cracksBig7.DI_cracksBig7'");
85 DecalNamesMap.Add(
"cracksbig8",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_cracksBig8.DI_cracksBig8'");
88 DecalNamesMap.Add(
"crack1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_RoadCrack01.DI_RoadCrack01'");
89 DecalNamesMap.Add(
"crack2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_RoadCrack02.DI_RoadCrack02'");
90 DecalNamesMap.Add(
"crack3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_RoadCrack05.DI_RoadCrack05'");
91 DecalNamesMap.Add(
"crack4",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_RoadCrack09.DI_RoadCrack09'");
92 DecalNamesMap.Add(
"crack5",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_RoadCrack11.DI_RoadCrack11'");
93 DecalNamesMap.Add(
"crack6",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_RoadCrack13.DI_RoadCrack13'");
94 DecalNamesMap.Add(
"crack7",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_RoadCrack15.DI_RoadCrack15'");
95 DecalNamesMap.Add(
"crack8",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Cracks/DI_RoadCrack16.DI_RoadCrack16'");
98 DecalNamesMap.Add(
"manhole1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Manhole/DI_Manhole01.DI_Manhole01'");
99 DecalNamesMap.Add(
"manhole2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Manhole/DI_Manhole02.DI_Manhole02'");
100 DecalNamesMap.Add(
"manhole3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Manhole/DI_Manhole03.DI_Manhole03'");
103 DecalNamesMap.Add(
"mud1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/MudDecal/DI_Mud_1.DI_Mud_1'");
104 DecalNamesMap.Add(
"mud2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/MudDecal/DI_Mud_2.DI_Mud_2'");
105 DecalNamesMap.Add(
"mud3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/MudDecal/DI_Mud_3.DI_Mud_3'");
106 DecalNamesMap.Add(
"mud4",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/MudDecal/DI_Mud_4.DI_Mud_4'");
107 DecalNamesMap.Add(
"mud5",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/MudDecal/DI_Mud_5.DI_Mud_5'");
110 DecalNamesMap.Add(
"oilsplat1",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/OilSplats/DI_OilSplat1.DI_OilSplat1'");
111 DecalNamesMap.Add(
"oilsplat2",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/OilSplats/DI_OilSplat2.DI_OilSplat2'");
112 DecalNamesMap.Add(
"oilsplat3",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/OilSplats/DI_OilSplat3.DI_OilSplat3'");
113 DecalNamesMap.Add(
"oilsplat4",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/OilSplats/DI_OilSplat4.DI_OilSplat4'");
114 DecalNamesMap.Add(
"oilsplat5",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/OilSplats/DI_OilSplat5.DI_OilSplat5'");
117 DecalNamesMap.Add(
"gum",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/OilSplats/DI_Gum.DI_Gum'");
118 DecalNamesMap.Add(
"grate",
"MaterialInstanceConstant'/Game/Carla/Static/Decals/Road/Manhole/DI_Grate_01_v2.DI_Grate_01_v2'");
123#if WITH_EDITORONLY_DATA
125void ULoadAssetMaterialsCommandlet::ApplyRoadPainterMaterials(
const FString &LoadedMapName,
const FString &PackageName,
bool IsInTiles)
127 if (IsInTiles ==
true) {
133 FString MapName = LoadedMapName;
136 int32 idx = MapName.Find(
"_Tile_");
139 MapName = MapName.Mid(0, idx);
146 TArray<FString> FileList;
147 IFileManager::Get().FindFilesRecursive(FileList, *(FPaths::ProjectContentDir() +
"/" + PackageName +
"/Maps/" + MapName), *(FString(
"TilesInfo.txt")),
true,
false,
false);
150 if (FFileHelper::LoadFileToString(TxtFile, *FileList[0]) ==
true) {
153 TxtFile.ParseIntoArray(Out, TEXT(
","),
true);
160 UE_LOG(LogTemp, Warning, TEXT(
"Could not read TilesInfo.txt file"));
167 TArray<FString> StringArray = {};
168 LoadedMapName.ParseIntoArray(StringArray, TEXT(
"_"),
false);
170 int32 XIndex = FCString::Atoi(*StringArray[StringArray.Num() - 2]);
171 int32 YIndex = FCString::Atoi(*StringArray[StringArray.Num() - 1]);
172 FVector TilePosition;
177 TilePosition.Z = 0.0f;
181 float MinXSize = (TilePosition.X - HalfSize);
182 float MaxXSize = (TilePosition.X + HalfSize);
184 float MinYSize = (TilePosition.Y - HalfSize);
185 float MaxYSize = (TilePosition.Y + HalfSize);
196 float MinXSizeCm = MinXSize * 100.0f;
197 float MaxXSizeCm = MaxXSize * 100.0f;
198 float MinYSizeCm = MinYSize * 100.0f;
199 float MaxYSizeCm = MaxYSize * 100.0f;
205 float CenterOfTileX = FirstTileWorldLocationX + (XIndex * TileSizeCm);
206 float CenterOfTileY = FirstTileWorldLocationY - (YIndex * TileSizeCm);
212 DecalLocation.
x = FMath::RandRange(MinXSize, MaxXSize);
213 DecalLocation.
y = FMath::RandRange(MinYSize, MaxYSize);
214 DecalLocation.
z = 0.0f;
217 auto Wp =
XODRMap->GetClosestWaypointOnRoad(DecalLocation);
219 FVector FinalLocation(RoadLocation);
222 if (FinalLocation.X > MinXSizeCm && FinalLocation.X < MaxXSizeCm) {
224 if (FinalLocation.Y > MinYSizeCm && FinalLocation.Y < MaxYSizeCm) {
226 FRotator FinalRotation(
XODRMap->ComputeTransform(Wp.get()).rotation);
232 FinalLocation.X -= CenterOfTileX;
233 FinalLocation.Y -= CenterOfTileY;
235 FActorSpawnParameters SpawnParams;
236 SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
237 SpawnParams.bNoFail =
true;
238 ADecalActor* Decal =
World->SpawnActor<ADecalActor>(FinalLocation, FRotator(), SpawnParams);
243 FVector FinalDecalScale;
246 FinalDecalScale.Z = 1.0f;
247 Decal->SetActorScale3D(FinalDecalScale);
251 FinalRotation.Yaw += RandomYaw;
252 FinalRotation.Pitch = -90.0f;
253 Decal->SetActorRotation(FinalRotation);
254 Decal->SetActorLabel(
"RoadDecal",
true);
261 UEditorLoadingAndSavingUtils::SaveDirtyPackages(
true,
true);
266FDecalsProperties ULoadAssetMaterialsCommandlet::ReadDecalsConfigurationFile(
const FString &PackageName) {
269 FString JsonConfigFile;
271 TArray<FString> FileList;
272 IFileManager::Get().FindFilesRecursive(FileList, *(FPaths::ProjectContentDir() +
"/" + PackageName),
273 *(FString(
"roadpainter_decals.json")),
true,
false,
false);
276 if (FFileHelper::LoadFileToString(JsonConfigFile, *(IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*FileList[0]))))
278 TSharedPtr<FJsonObject> JsonParsed;
279 TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonConfigFile);
280 if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
283 auto DecalJsonArray = JsonParsed->GetArrayField(TEXT(
"decals"));
284 for (
auto &DecalJsonValue : DecalJsonArray)
286 const auto DecalJsonObject = DecalJsonValue->AsObject();
291 if (DecalJsonObject->HasField(Pair.Key) ==
true) {
292 DecalConfiguration.
DecalMaterials.Add(LoadObject<UMaterialInstanceConstant>(
nullptr, *Pair.Value));
293 DecalConfiguration.
DecalNumToSpawn.Add(DecalJsonObject->GetIntegerField(Pair.Key));
297 TSharedPtr<FJsonObject> VectorObject = DecalJsonObject->GetObjectField(TEXT(
"decal_scale"));
299 DecalScale.X = (float)VectorObject->GetNumberField(TEXT(
"x_axis"));
300 DecalScale.Y = (float)VectorObject->GetNumberField(TEXT(
"y_axis"));
301 DecalScale.Z = (float)VectorObject->GetNumberField(TEXT(
"z_axis"));
304 DecalConfiguration.
DecalMinScale = (float)DecalJsonObject->GetNumberField(TEXT(
"decal_min_scale"));
305 DecalConfiguration.
DecalMaxScale = (float)DecalJsonObject->GetNumberField(TEXT(
"decal_max_scale"));
306 DecalConfiguration.
DecalRandomYaw = (float)DecalJsonObject->GetNumberField(TEXT(
"decal_random_yaw"));
307 DecalConfiguration.
RandomOffset = (float)DecalJsonObject->GetNumberField(TEXT(
"random_offset"));
311 return DecalConfiguration;
317 TArray<FString> PackageList;
318 IFileManager::Get().FindFilesRecursive(PackageList, *(FPaths::ProjectContentDir()),
319 *(PackageName + TEXT(
".Package.json")),
true,
false,
false);
321 if (PackageList.Num() == 0)
323 UE_LOG(LogTemp, Error, TEXT(
"Package json file not found."));
327 return IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*PackageList[0]);
330void ULoadAssetMaterialsCommandlet::LoadAssetsMaterials(
const FString &PackageName,
const TArray<FMapData> &MapsPaths)
333 FAssetData AssetData;
334 MapObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(),
false, GIsEditor);
335 const FString DefaultPath = TEXT(
"/Game/") + PackageName + TEXT(
"/Maps/");
337 for (
auto &&data : MapsPaths)
348 for (int32 i = 0; i < NumAssets; ++i) {
352 World = Cast<UWorld>(AssetData.GetAsset());
353 if (
World !=
nullptr) {
358 TArray<AActor*> FoundActors;
359 UGameplayStatics::GetAllActorsOfClass(
World, AStaticMeshActor::StaticClass(), FoundActors);
360 bool HasRoadMesh =
false;
361 for (int32 j = 0; j < FoundActors.Num() && HasRoadMesh ==
false; ++j) {
363 AStaticMeshActor *MeshActor = Cast<AStaticMeshActor>(FoundActors[j]);
364 if (MeshActor->GetName().Contains(
"Roads") || MeshActor->GetName().Contains(
"Road")){
370 if (HasRoadMesh ==
true) {
372 bool IsTiledMap =
World->GetName().Contains(
"_Tile_", ESearchCase::Type::CaseSensitive);
373 ApplyRoadPainterMaterials(
World->GetName(), PackageName, IsTiledMap);
377 UEditorLoadingAndSavingUtils::SaveDirtyPackages(
true,
true);
384FPackageParams ULoadAssetMaterialsCommandlet::ParseParams(
const FString &InParams)
const
386 TArray<FString> Tokens;
387 TArray<FString> Params;
388 TMap<FString, FString> ParamVals;
390 ParseCommandLine(*InParams, Tokens, Params);
395 FParse::Value(*InParams, TEXT(
"PackageName="), PackageParams.
Name);
397 return PackageParams;
400FAssetsPaths ULoadAssetMaterialsCommandlet::GetAssetsPathFromPackage(
const FString &PackageName)
const
407 FString MapsFileJsonContent;
408 if (FFileHelper::LoadFileToString(MapsFileJsonContent, *PackageJsonFilePath))
410 TSharedPtr<FJsonObject> JsonParsed;
411 TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(MapsFileJsonContent);
412 if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
415 auto MapsJsonArray = JsonParsed->GetArrayField(TEXT(
"maps"));
417 for (
auto &MapJsonValue : MapsJsonArray)
419 TSharedPtr<FJsonObject> MapJsonObject = MapJsonValue->AsObject();
422 MapData.
Name = MapJsonObject->GetStringField(TEXT(
"name"));
423 MapData.
Path = MapJsonObject->GetStringField(TEXT(
"path"));
426 AssetsPaths.
MapsPaths.Add(std::move(MapData));
430 auto PropJsonArray = JsonParsed->GetArrayField(TEXT(
"props"));
432 for (
auto &PropJsonValue : PropJsonArray)
434 TSharedPtr<FJsonObject> PropJsonObject = PropJsonValue->AsObject();
436 const FString PropAssetPath = PropJsonObject->GetStringField(TEXT(
"path"));
438 AssetsPaths.
PropsPaths.Add(std::move(PropAssetPath));
445int32 ULoadAssetMaterialsCommandlet::Main(
const FString &Params)
452 LoadAssetsMaterials(PackageParams.
Name, AssetsPaths.
MapsPaths);
455 UEditorLoadingAndSavingUtils::SaveDirtyPackages(
true,
true);
TArray< FAssetData > AssetDatas
Loaded assets from any object library
UObjectLibrary * MapObjectLibrary
Used for loading maps in object library.
TMap< FString, FString > DecalNamesMap
Dictionary for translating the JSON file "decal_names" array to already loaded Material Instances,...
boost::optional< carla::road::Map > XODRMap
FString GetFirstPackagePath(const FString &PackageName) const
Gets the first .Package.json file found in Unreal Content Directory with PackageName
TSubclassOf< ARoadPainterWrapper > RoadPainterSubclass
Subclass for acquiring the RoadPainter blueprint
FLargeMapTileData TileData
FDecalsProperties DecalsProperties
ULoadAssetMaterialsCommandlet()
Default constructor.
static FString LoadXODR(const FString &MapName)
static boost::optional< road::Map > Load(const std::string &opendrive)
Struct containing all assets data read from .Package.json file.
TArray< FMapData > MapsPaths
TArray< FString > PropsPaths
float DecalRandomYaw
The decal yaw to be applied randomly
float DecalMaxScale
Maximum scale to be applied to the decals
TArray< int32 > DecalNumToSpawn
How many decals (or material instances) of each, should be applied to the road
float RandomOffset
Random offset from one decal to another
TArray< UMaterialInstance * > DecalMaterials
The decals used on the road
float DecalMinScale
Min scale to be applied to the decals
FVector DecalScale
Scale of each decal on the road
FVector FixedDecalOffset
Min offset from one decal to another
Struct containing map data read from .Package.json file.
bool bUseCarlaMapMaterials
Struct containing Package with Name and bOnlyPrepareMaps flag used to separate the cooking of maps an...