CARLA
LoadAssetMaterialsCommandlet.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021 Computer Vision Center (CVC) at the Universitat Autonoma
2 // de Barcelona (UAB).
3 //
4 // This work is licensed under the terms of the MIT license.
5 // For a copy, see <https://opensource.org/licenses/MIT>.
6 
8 
9 #if WITH_EDITOR
10 #include "FileHelpers.h"
11 #endif
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"
22 
24 {
25  // Set necessary flags to run commandlet
26  IsClient = false;
27  IsEditor = true;
28  IsServer = false;
29  LogToConsole = true;
30  FilledData = false;
31  ReadConfigFile = true;
32 
33 #if WITH_EDITORONLY_DATA
34 
35  static ConstructorHelpers::FObjectFinder<UBlueprint> RoadPainterBlueprint(TEXT(
36  "Blueprint'/Game/Carla/Blueprints/LevelDesign/RoadPainterPreset.RoadPainterPreset'"));
37 
38  RoadPainterSubclass = (UClass*)RoadPainterBlueprint.Object->GeneratedClass;
39 
40  // Dirt
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'");
46 
47  // Drip
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'");
51 
52  // Road lines
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'");
58 
59  // Tiremarks
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'");
63 
64  // Tarsnakes
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'");
76 
77  // Cracks big
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'");
86 
87  // Cracks
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'");
96 
97  // Manholes
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'");
101 
102  // Mud
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'");
108 
109  // Oil splats
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'");
115 
116  // Misc
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'");
119 
120 #endif
121 }
122 
123 #if WITH_EDITORONLY_DATA
124 
125 void ULoadAssetMaterialsCommandlet::ApplyRoadPainterMaterials(const FString &LoadedMapName, const FString &PackageName, bool IsInTiles)
126 {
127  if (IsInTiles == true) {
128 
129  if (FilledData == false) {
130 
131  // As the OpenDrive file has the same name as level, build the path to the
132  // xodr file using the label name and the game content directory.
133  FString MapName = LoadedMapName;
134  if (IsInTiles)
135  {
136  int32 idx = MapName.Find("_Tile_");
137  if(idx > -1)
138  {
139  MapName = MapName.Mid(0, idx);
140  }
141  }
142  const FString XodrContent = UOpenDrive::LoadXODR(MapName);
143  XODRMap = carla::opendrive::OpenDriveParser::Load(carla::rpc::FromLongFString(XodrContent));
144 
145  // Acquire the TilesInfo.txt file for storing the tile data (offset and size)
146  TArray<FString> FileList;
147  IFileManager::Get().FindFilesRecursive(FileList, *(FPaths::ProjectContentDir() + "/" + PackageName + "/Maps/" + MapName), *(FString("TilesInfo.txt")), true, false, false);
148 
149  FString TxtFile;
150  if (FFileHelper::LoadFileToString(TxtFile, *FileList[0]) == true) {
151 
152  TArray<FString> Out;
153  TxtFile.ParseIntoArray(Out, TEXT(","), true);
154 
155  TileData.FirstTileCenterX = (float) FCString::Atoi(*Out[0]);
156  TileData.FirstTileCenterY = (float) FCString::Atoi(*Out[1]);
157  TileData.Size = (float) FCString::Atoi(*Out[2]);
158  }
159  else {
160  UE_LOG(LogTemp, Warning, TEXT("Could not read TilesInfo.txt file"));
161  return;
162  }
163 
164  FilledData = true;
165  }
166 
167  TArray<FString> StringArray = {};
168  LoadedMapName.ParseIntoArray(StringArray, TEXT("_"), false);
169  // From the loaded map name (in style mymap_Tile_200_400) get the X and the Y (Tile_200_400 -> X = 200, Y = 400)
170  int32 XIndex = FCString::Atoi(*StringArray[StringArray.Num() - 2]);
171  int32 YIndex = FCString::Atoi(*StringArray[StringArray.Num() - 1]);
172  FVector TilePosition;
173  // This means it's the initial tile (mymap_Tile_0_0)
174  // This is in RELATIVE coords
175  TilePosition.X = TileData.FirstTileCenterX + (TileData.Size * (float)XIndex);
176  TilePosition.Y = TileData.FirstTileCenterY - (TileData.Size * (float)YIndex);
177  TilePosition.Z = 0.0f;
178 
179  float HalfSize = TileData.Size / 2.0f;
180 
181  float MinXSize = (TilePosition.X - HalfSize);
182  float MaxXSize = (TilePosition.X + HalfSize);
183 
184  float MinYSize = (TilePosition.Y - HalfSize);
185  float MaxYSize = (TilePosition.Y + HalfSize);
186 
187  if (ReadConfigFile == true) {
188 
189  DecalsProperties = ReadDecalsConfigurationFile(PackageName);
190  ReadConfigFile = false;
191  }
192 
193  carla::geom::Location DecalLocation;
194 
195  //Store results for avoiding excessive calculations
196  float MinXSizeCm = MinXSize * 100.0f;
197  float MaxXSizeCm = MaxXSize * 100.0f;
198  float MinYSizeCm = MinYSize * 100.0f;
199  float MaxYSizeCm = MaxYSize * 100.0f;
200 
201  float TileSizeCm = TileData.Size * 100.0f;
202  float FirstTileWorldLocationX = TileData.FirstTileCenterX * 100.0f;
203  float FirstTileWorldLocationY = TileData.FirstTileCenterY * 100.0f;
204 
205  float CenterOfTileX = FirstTileWorldLocationX + (XIndex * TileSizeCm);
206  float CenterOfTileY = FirstTileWorldLocationY - (YIndex * TileSizeCm);
207 
208  for (int32 i = 0; i < DecalsProperties.DecalMaterials.Num(); ++i) {
209 
210  for (int32 j = 0; j < DecalsProperties.DecalNumToSpawn[i]; ++j) {
211 
212  DecalLocation.x = FMath::RandRange(MinXSize, MaxXSize);
213  DecalLocation.y = FMath::RandRange(MinYSize, MaxYSize);
214  DecalLocation.z = 0.0f;
215 
216  // Get the closest road waypoint from the random location calculated
217  auto Wp = XODRMap->GetClosestWaypointOnRoad(DecalLocation);
218  carla::geom::Location RoadLocation = XODRMap->ComputeTransform(Wp.get()).location;
219  FVector FinalLocation(RoadLocation);
220 
221  // Check we don't exceed the map boundaries
222  if (FinalLocation.X > MinXSizeCm && FinalLocation.X < MaxXSizeCm) {
223 
224  if (FinalLocation.Y > MinYSizeCm && FinalLocation.Y < MaxYSizeCm) {
225 
226  FRotator FinalRotation(XODRMap->ComputeTransform(Wp.get()).rotation);
227 
228  // Transform the location from world coords to tile coordinates.
229  // The location we get is the location of the XODR waypoint, which is in WORLD coordinates
230  // The Y coordinates are reversed! -Y = Y and Y = -Y
231 
232  FinalLocation.X -= CenterOfTileX;
233  FinalLocation.Y -= CenterOfTileY;
234 
235  FActorSpawnParameters SpawnParams;
236  SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
237  SpawnParams.bNoFail = true;
238  ADecalActor* Decal = World->SpawnActor<ADecalActor>(FinalLocation, FRotator(), SpawnParams);
239  Decal->SetDecalMaterial(DecalsProperties.DecalMaterials[i]);
240 
241  // Calculate random scale for decal
242  float RandScale = FMath::RandRange(DecalsProperties.DecalMinScale, DecalsProperties.DecalMaxScale);
243  FVector FinalDecalScale;
244  FinalDecalScale.X = DecalsProperties.DecalScale.X + RandScale;
245  FinalDecalScale.Y = DecalsProperties.DecalScale.Y + RandScale;
246  FinalDecalScale.Z = 1.0f;
247  Decal->SetActorScale3D(FinalDecalScale);
248 
249  // Calculate random yaw for decal
250  float RandomYaw = FMath::RandRange(0.0f, DecalsProperties.DecalRandomYaw);
251  FinalRotation.Yaw += RandomYaw;
252  FinalRotation.Pitch = -90.0f;
253  Decal->SetActorRotation(FinalRotation);
254  Decal->SetActorLabel("RoadDecal", true);
255  }
256  }
257  }
258  }
259 
260 #if WITH_EDITOR
261  UEditorLoadingAndSavingUtils::SaveDirtyPackages(true, true);
262 #endif
263  }
264 }
265 
266 FDecalsProperties ULoadAssetMaterialsCommandlet::ReadDecalsConfigurationFile(const FString &PackageName) {
267 
268  // Get road painter configuration file
269  FString JsonConfigFile;
270 
271  TArray<FString> FileList;
272  IFileManager::Get().FindFilesRecursive(FileList, *(FPaths::ProjectContentDir() + "/" + PackageName),
273  *(FString("roadpainter_decals.json")), true, false, false);
274 
275  FDecalsProperties DecalConfiguration;
276  if (FFileHelper::LoadFileToString(JsonConfigFile, *(IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*FileList[0]))))
277  {
278  TSharedPtr<FJsonObject> JsonParsed;
279  TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonConfigFile);
280  if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
281  {
282  // Get decals object array
283  auto DecalJsonArray = JsonParsed->GetArrayField(TEXT("decals"));
284  for (auto &DecalJsonValue : DecalJsonArray)
285  {
286  const auto DecalJsonObject = DecalJsonValue->AsObject();
287 
288  // With the decal name array we created earlier, we traverse it
289  // and look up it's name in the .json file
290  for (const TPair<FString, FString>& Pair : DecalNamesMap) {
291  if (DecalJsonObject->HasField(Pair.Key) == true) {
292  DecalConfiguration.DecalMaterials.Add(LoadObject<UMaterialInstanceConstant>(nullptr, *Pair.Value));
293  DecalConfiguration.DecalNumToSpawn.Add(DecalJsonObject->GetIntegerField(Pair.Key));
294  }
295  }
296 
297  TSharedPtr<FJsonObject> VectorObject = DecalJsonObject->GetObjectField(TEXT("decal_scale"));
298  FVector DecalScale;
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"));
302  DecalConfiguration.DecalScale = DecalScale;
303  DecalConfiguration.FixedDecalOffset = DecalScale;
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"));
308  }
309  }
310  }
311  return DecalConfiguration;
312 }
313 
314 FString ULoadAssetMaterialsCommandlet::GetFirstPackagePath(const FString &PackageName) const
315 {
316  // Get all Package names
317  TArray<FString> PackageList;
318  IFileManager::Get().FindFilesRecursive(PackageList, *(FPaths::ProjectContentDir()),
319  *(PackageName + TEXT(".Package.json")), true, false, false);
320 
321  if (PackageList.Num() == 0)
322  {
323  UE_LOG(LogTemp, Error, TEXT("Package json file not found."));
324  return {};
325  }
326 
327  return IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*PackageList[0]);
328 }
329 
330 void ULoadAssetMaterialsCommandlet::LoadAssetsMaterials(const FString &PackageName, const TArray<FMapData> &MapsPaths)
331 {
332  // Load World
333  FAssetData AssetData;
334  MapObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(), false, GIsEditor);
335  const FString DefaultPath = TEXT("/Game/") + PackageName + TEXT("/Maps/");
336  MapObjectLibrary->AddToRoot();
337  for (auto &&data : MapsPaths)
338  {
339  MapObjectLibrary->LoadAssetDataFromPath(*data.Path);
340  }
341  MapObjectLibrary->LoadAssetsFromAssetData();
342  MapObjectLibrary->GetAssetDataList(AssetDatas);
343 
344  if (AssetDatas.Num() > 0)
345  {
346  int32 NumAssets = AssetDatas.Num();
347  //If the map is tiled, there will be several umaps in the same folder
348  for (int32 i = 0; i < NumAssets; ++i) {
349 
350  // Extract first asset found in folder path (i.e. the imported map)
351  AssetData = AssetDatas.Pop();
352  World = Cast<UWorld>(AssetData.GetAsset());
353  if (World != nullptr) {
354 
355  World->InitWorld();
356 
357  // Check if there's any road meshes in the world for spawning the decals.
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) {
362 
363  AStaticMeshActor *MeshActor = Cast<AStaticMeshActor>(FoundActors[j]);
364  if (MeshActor->GetName().Contains("Roads") || MeshActor->GetName().Contains("Road")){
365 
366  HasRoadMesh = true;
367  }
368  }
369 
370  if (HasRoadMesh == true) {
371 
372  bool IsTiledMap = World->GetName().Contains("_Tile_", ESearchCase::Type::CaseSensitive);
373  ApplyRoadPainterMaterials(World->GetName(), PackageName, IsTiledMap);
374  }
375 
376 #if WITH_EDITOR
377  UEditorLoadingAndSavingUtils::SaveDirtyPackages(true, true);
378 #endif
379  }
380  }
381  }
382 }
383 
384 FPackageParams ULoadAssetMaterialsCommandlet::ParseParams(const FString &InParams) const
385 {
386  TArray<FString> Tokens;
387  TArray<FString> Params;
388  TMap<FString, FString> ParamVals;
389 
390  ParseCommandLine(*InParams, Tokens, Params);
391 
392  FPackageParams PackageParams;
393 
394  // Parse and store Package name
395  FParse::Value(*InParams, TEXT("PackageName="), PackageParams.Name);
396 
397  return PackageParams;
398 }
399 
400 FAssetsPaths ULoadAssetMaterialsCommandlet::GetAssetsPathFromPackage(const FString &PackageName) const
401 {
402  const FString PackageJsonFilePath = GetFirstPackagePath(PackageName);
403 
404  FAssetsPaths AssetsPaths;
405 
406  // Get All Maps Path
407  FString MapsFileJsonContent;
408  if (FFileHelper::LoadFileToString(MapsFileJsonContent, *PackageJsonFilePath))
409  {
410  TSharedPtr<FJsonObject> JsonParsed;
411  TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(MapsFileJsonContent);
412  if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
413  {
414  // Add Maps Path
415  auto MapsJsonArray = JsonParsed->GetArrayField(TEXT("maps"));
416 
417  for (auto &MapJsonValue : MapsJsonArray)
418  {
419  TSharedPtr<FJsonObject> MapJsonObject = MapJsonValue->AsObject();
420 
421  FMapData MapData;
422  MapData.Name = MapJsonObject->GetStringField(TEXT("name"));
423  MapData.Path = MapJsonObject->GetStringField(TEXT("path"));
424  MapData.bUseCarlaMapMaterials = MapJsonObject->GetBoolField(TEXT("use_carla_materials"));
425 
426  AssetsPaths.MapsPaths.Add(std::move(MapData));
427  }
428 
429  // Add Props Path
430  auto PropJsonArray = JsonParsed->GetArrayField(TEXT("props"));
431 
432  for (auto &PropJsonValue : PropJsonArray)
433  {
434  TSharedPtr<FJsonObject> PropJsonObject = PropJsonValue->AsObject();
435 
436  const FString PropAssetPath = PropJsonObject->GetStringField(TEXT("path"));
437 
438  AssetsPaths.PropsPaths.Add(std::move(PropAssetPath));
439  }
440  }
441  }
442  return AssetsPaths;
443 }
444 
445 int32 ULoadAssetMaterialsCommandlet::Main(const FString &Params)
446 {
447  FPackageParams PackageParams = ParseParams(Params);
448 
449  // Get Props and Maps Path
450  FAssetsPaths AssetsPaths = GetAssetsPathFromPackage(PackageParams.Name);
451 
452  LoadAssetsMaterials(PackageParams.Name, AssetsPaths.MapsPaths);
453 
454 #if WITH_EDITOR
455  UEditorLoadingAndSavingUtils::SaveDirtyPackages(true, true);
456 #endif
457 
458  return 0;
459 }
460 
461 #endif
float DecalMaxScale
Maximum scale to be applied to the decals.
FVector FixedDecalOffset
Min offset from one decal to another.
float DecalRandomYaw
The decal yaw to be applied randomly.
Struct containing Package with Name and bOnlyPrepareMaps flag used to separate the cooking of maps an...
TArray< UMaterialInstance * > DecalMaterials
The decals used on the road.
Struct containing map data read from .Package.json file.
TArray< FAssetData > AssetDatas
Loaded assets from any object library.
ULoadAssetMaterialsCommandlet()
Default constructor.
static T Get(carla::rpc::Response< T > &response)
UObjectLibrary * MapObjectLibrary
Used for loading maps in object library.
static boost::optional< road::Map > Load(const std::string &opendrive)
Struct containing all assets data read from .Package.json file.
boost::optional< carla::road::Map > XODRMap
TArray< int32 > DecalNumToSpawn
How many decals (or material instances) of each, should be applied to the road.
FString GetFirstPackagePath(const FString &PackageName) const
Gets the first .Package.json file found in Unreal Content Directory with PackageName.
TMap< FString, FString > DecalNamesMap
Dictionary for translating the JSON file "decal_names" array to already loaded Material Instances...
float DecalMinScale
Min scale to be applied to the decals.
TSubclassOf< ARoadPainterWrapper > RoadPainterSubclass
Subclass for acquiring the RoadPainter blueprint.
float RandomOffset
Random offset from one decal to another.
FVector DecalScale
Scale of each decal on the road.