CARLA
 
载入中...
搜索中...
未找到
LoadAssetMaterialsCommandlet.cpp
浏览该文件的文档.
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 // 设置必要的标志以运行命令行工具
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 // 泥土
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 //滴水
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 // 道路标线
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 // 轮胎痕迹
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 //钩吻
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 // 裂缝很大
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 //裂缝
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 // 井盖
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 //泥
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 // 油渍
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 // 杂项
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// ApplyRoadPainterMaterials函数用于将道路绘制器材料应用于指定的地图
126void ULoadAssetMaterialsCommandlet::ApplyRoadPainterMaterials(const FString &LoadedMapName, const FString &PackageName, bool IsInTiles)
127{
128 // 如果当前处于瓦片模式,则执行以下逻辑
129 if (IsInTiles == true) {
130
131 // 如果尚未填充数据,则执行以下逻辑
132 if (FilledData == false) {
133
134 // 构建xodr文件的路径,OpenDrive文件与关卡同名,因此使用标签名称和游戏内容目录来构建路径
135 FString MapName = LoadedMapName;
136 if (IsInTiles)
137 {
138 int32 idx = MapName.Find("_Tile_");
139 if(idx > -1)
140 {
141 // 从地图名称中移除_Tile_及其后的索引,以获取基础地图名称
142 MapName = MapName.Mid(0, idx);
143 }
144 }
145 // 加载xodr文件内容
146 const FString XodrContent = UOpenDrive::LoadXODR(MapName);
147 // 使用carla::opendrive::OpenDriveParser加载OpenDrive数据
148 XODRMap = carla::opendrive::OpenDriveParser::Load(carla::rpc::FromLongFString(XodrContent));
149
150 // 获取TilesInfo.txt文件以存储瓦片数据(偏移量和大小)
151 TArray<FString> FileList;
152 // 在指定目录下递归查找TilesInfo.txt文件
153 IFileManager::Get().FindFilesRecursive(FileList, *(FPaths::ProjectContentDir() + "/" + PackageName + "/Maps/" + MapName), *(FString("TilesInfo.txt")), true, false, false);
154
155 FString TxtFile;
156 // 如果成功加载TilesInfo.txt文件,则执行以下逻辑
157 if (FFileHelper::LoadFileToString(TxtFile, *FileList[0]) == true) {
158
159 TArray<FString> Out;
160 // 解析TilesInfo.txt文件内容,假设格式为"X,Y,Size"
161 TxtFile.ParseIntoArray(Out, TEXT(","), true);
162
163 // 从解析的字符串数组中提取瓦片的中心X坐标、中心Y坐标和大小
164 TileData.FirstTileCenterX = (float) FCString::Atoi(*Out[0]);
165 TileData.FirstTileCenterY = (float) FCString::Atoi(*Out[1]);
166 TileData.Size = (float) FCString::Atoi(*Out[2]);
167 }
168 else {
169 // 如果无法读取TilesInfo.txt文件,则记录警告日志并返回
170 UE_LOG(LogTemp, Warning, TEXT("Could not read TilesInfo.txt file"));
171 return;
172 }
173
174 // 标记数据已填充
175 FilledData = true;
176 }
177
178 // 将加载的地图名称解析为字符串数组,以提取X和Y索引
179 TArray<FString> StringArray = {};
180 LoadedMapName.ParseIntoArray(StringArray, TEXT("_"), false);
181 // 从加载的地图名称(如 mymap_Tile_200_400)中获取X和Y(Tile_200_400 -> X = 200, Y = 400)
182 int32 XIndex = FCString::Atoi(*StringArray[StringArray.Num() - 2]);
183 int32 YIndex = FCString::Atoi(*StringArray[StringArray.Num() - 1]);
184 FVector TilePosition;
185 // 计算瓦片的位置,这是相对坐标
186 TilePosition.X = TileData.FirstTileCenterX + (TileData.Size * (float)XIndex);
187 TilePosition.Y = TileData.FirstTileCenterY - (TileData.Size * (float)YIndex);
188 TilePosition.Z = 0.0f; // 瓦片的Z坐标设置为0
189 }
190}
191
192#endif
193
194
195 float HalfSize = TileData.Size / 2.0f;
196
197 float MinXSize = (TilePosition.X - HalfSize);
198 float MaxXSize = (TilePosition.X + HalfSize);
199
200 float MinYSize = (TilePosition.Y - HalfSize);
201 float MaxYSize = (TilePosition.Y + HalfSize);
202
203 if (ReadConfigFile == true) {
204
205 DecalsProperties = ReadDecalsConfigurationFile(PackageName);
206 ReadConfigFile = false;
207 }
208
210
211 //存储结果以避免过度计算
212 float MinXSizeCm = MinXSize * 100.0f;
213 float MaxXSizeCm = MaxXSize * 100.0f;
214 float MinYSizeCm = MinYSize * 100.0f;
215 float MaxYSizeCm = MaxYSize * 100.0f;
216
217 float TileSizeCm = TileData.Size * 100.0f;
218 float FirstTileWorldLocationX = TileData.FirstTileCenterX * 100.0f;
219 float FirstTileWorldLocationY = TileData.FirstTileCenterY * 100.0f;
220
223
224 for (int32 i = 0; i < DecalsProperties.DecalMaterials.Num(); ++i) {
225
226 for (int32 j = 0; j < DecalsProperties.DecalNumToSpawn[i]; ++j) {
227
228 DecalLocation.x = FMath::RandRange(MinXSize, MaxXSize);
229 DecalLocation.y = FMath::RandRange(MinYSize, MaxYSize);
230 DecalLocation.z = 0.0f;
231
232 // 获取从计算的随机位置到最近的道路航点
233 auto Wp = XODRMap->GetClosestWaypointOnRoad(DecalLocation);
234 carla::geom::Location RoadLocation = XODRMap->ComputeTransform(Wp.get()).location;
235 FVector FinalLocation(RoadLocation);
236
237 // 检查我们是否超出了地图边界
238 if (FinalLocation.X > MinXSizeCm && FinalLocation.X < MaxXSizeCm) {
239
240 if (FinalLocation.Y > MinYSizeCm && FinalLocation.Y < MaxYSizeCm) {
241
242 FRotator FinalRotation(XODRMap->ComputeTransform(Wp.get()).rotation);
243
244 // 将位置从世界坐标转换为瓦片坐标
245 // 我们得到的定位是XODR路径点的定位,该定位采用的是世界坐标系
246 // Y坐标被反转了!-Y = Y,而Y = -Y
247
248 FinalLocation.X -= CenterOfTileX;
249 FinalLocation.Y -= CenterOfTileY;
250
251 FActorSpawnParameters SpawnParams;
252 SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
253 SpawnParams.bNoFail = true;
254 ADecalActor* Decal = World->SpawnActor<ADecalActor>(FinalLocation, FRotator(), SpawnParams);
255 Decal->SetDecalMaterial(DecalsProperties.DecalMaterials[i]);
256
257 // 计算贴花的随机缩放比例
258 float RandScale = FMath::RandRange(DecalsProperties.DecalMinScale, DecalsProperties.DecalMaxScale);
259 FVector FinalDecalScale;
260 FinalDecalScale.X = DecalsProperties.DecalScale.X + RandScale;
261 FinalDecalScale.Y = DecalsProperties.DecalScale.Y + RandScale;
262 FinalDecalScale.Z = 1.0f;
263 Decal->SetActorScale3D(FinalDecalScale);
264
265 // 计算贴花的随机偏航角
266 float RandomYaw = FMath::RandRange(0.0f, DecalsProperties.DecalRandomYaw);
267 FinalRotation.Yaw += RandomYaw;
268 FinalRotation.Pitch = -90.0f;
269 Decal->SetActorRotation(FinalRotation);
270 Decal->SetActorLabel("RoadDecal", true);
271 }
272 }
273 }
274 }
275
276#if WITH_EDITOR
277 UEditorLoadingAndSavingUtils::SaveDirtyPackages(true, true);
278#endif
279 }
280}
281
282FDecalsProperties ULoadAssetMaterialsCommandlet::ReadDecalsConfigurationFile(const FString &PackageName) {
283
284 //获取道路画笔配置文件
285 FString JsonConfigFile;
286
287 TArray<FString> FileList;
288 IFileManager::Get().FindFilesRecursive(FileList, *(FPaths::ProjectContentDir() + "/" + PackageName),
289 *(FString("roadpainter_decals.json")), true, false, false);
290
291 FDecalsProperties DecalConfiguration;
292 if (FFileHelper::LoadFileToString(JsonConfigFile, *(IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*FileList[0]))))
293 {
294 TSharedPtr<FJsonObject> JsonParsed;
295 TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonConfigFile);
296 if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
297 {
298 // 获取贴花对象数组
299 auto DecalJsonArray = JsonParsed->GetArrayField(TEXT("decals"));
300 for (auto &DecalJsonValue : DecalJsonArray)
301 {
302 const auto DecalJsonObject = DecalJsonValue->AsObject();
303
304 // 使用我们之前创建的贴花名称数组,我们遍历它
305 // 并在.json文件中查找它的名称
306 for (const TPair<FString, FString>& Pair : DecalNamesMap) {
307 if (DecalJsonObject->HasField(Pair.Key) == true) {
308 DecalConfiguration.DecalMaterials.Add(LoadObject<UMaterialInstanceConstant>(nullptr, *Pair.Value));
309 DecalConfiguration.DecalNumToSpawn.Add(DecalJsonObject->GetIntegerField(Pair.Key));
310 }
311 }
312
313 TSharedPtr<FJsonObject> VectorObject = DecalJsonObject->GetObjectField(TEXT("decal_scale"));
314 FVector DecalScale;
315 DecalScale.X = (float)VectorObject->GetNumberField(TEXT("x_axis"));
316 DecalScale.Y = (float)VectorObject->GetNumberField(TEXT("y_axis"));
317 DecalScale.Z = (float)VectorObject->GetNumberField(TEXT("z_axis"));
318 DecalConfiguration.DecalScale = DecalScale;
319 DecalConfiguration.FixedDecalOffset = DecalScale;
320 DecalConfiguration.DecalMinScale = (float)DecalJsonObject->GetNumberField(TEXT("decal_min_scale"));
321 DecalConfiguration.DecalMaxScale = (float)DecalJsonObject->GetNumberField(TEXT("decal_max_scale"));
322 DecalConfiguration.DecalRandomYaw = (float)DecalJsonObject->GetNumberField(TEXT("decal_random_yaw"));
323 DecalConfiguration.RandomOffset = (float)DecalJsonObject->GetNumberField(TEXT("random_offset"));
324 }
325 }
326 }
327 return DecalConfiguration;
328}
329
330FString ULoadAssetMaterialsCommandlet::GetFirstPackagePath(const FString &PackageName) const
331{
332 // 获取所有包名
333 TArray<FString> PackageList;
334 IFileManager::Get().FindFilesRecursive(PackageList, *(FPaths::ProjectContentDir()),
335 *(PackageName + TEXT(".Package.json")), true, false, false);
336
337 if (PackageList.Num() == 0)
338 {
339 UE_LOG(LogTemp, Error, TEXT("Package json file not found."));
340 return {};
341 }
342
343 return IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*PackageList[0]);
344}
345
346void ULoadAssetMaterialsCommandlet::LoadAssetsMaterials(const FString &PackageName, const TArray<FMapData> &MapsPaths)
347{
348 //加载世界
349 FAssetData AssetData;
350 MapObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(), false, GIsEditor);
351 const FString DefaultPath = TEXT("/Game/") + PackageName + TEXT("/Maps/");
352 MapObjectLibrary->AddToRoot();
353 for (auto &&data : MapsPaths)
354 {
355 MapObjectLibrary->LoadAssetDataFromPath(*data.Path);
356 }
357 MapObjectLibrary->LoadAssetsFromAssetData();
358 MapObjectLibrary->GetAssetDataList(AssetDatas);
359
360 if (AssetDatas.Num() > 0)
361 {
362 int32 NumAssets = AssetDatas.Num();
363 //如果地图是分块的,那么在同一个文件夹中会有多个umaps文件
364 for (int32 i = 0; i < NumAssets; ++i) {
365
366 //提取文件夹路径中找到的第一个资源(即导入的地图)
367 AssetData = AssetDatas.Pop();
368 World = Cast<UWorld>(AssetData.GetAsset());
369 if (World != nullptr) {
370
371 World->InitWorld();
372
373 //检查世界中是否存在用于生成贴花的路面网格
374 TArray<AActor*> FoundActors;
375 UGameplayStatics::GetAllActorsOfClass(World, AStaticMeshActor::StaticClass(), FoundActors);
376 bool HasRoadMesh = false;
377 for (int32 j = 0; j < FoundActors.Num() && HasRoadMesh == false; ++j) {
378
379 AStaticMeshActor *MeshActor = Cast<AStaticMeshActor>(FoundActors[j]);
380 if (MeshActor->GetName().Contains("Roads") || MeshActor->GetName().Contains("Road")){
381
382 HasRoadMesh = true;
383 }
384 }
385
386 if (HasRoadMesh == true) {
387
388 bool IsTiledMap = World->GetName().Contains("_Tile_", ESearchCase::Type::CaseSensitive);
389 ApplyRoadPainterMaterials(World->GetName(), PackageName, IsTiledMap);
390 }
391
392#if WITH_EDITOR
393 UEditorLoadingAndSavingUtils::SaveDirtyPackages(true, true);
394#endif
395 }
396 }
397 }
398}
399
400FPackageParams ULoadAssetMaterialsCommandlet::ParseParams(const FString &InParams) const
401{
402 TArray<FString> Tokens;
403 TArray<FString> Params;
404 TMap<FString, FString> ParamVals;
405
406 ParseCommandLine(*InParams, Tokens, Params);
407
408 FPackageParams PackageParams;
409
410 // 解析并存储包名
411 FParse::Value(*InParams, TEXT("PackageName="), PackageParams.Name);
412
413 return PackageParams;
414}
415
416FAssetsPaths ULoadAssetMaterialsCommandlet::GetAssetsPathFromPackage(const FString &PackageName) const
417{
418 const FString PackageJsonFilePath = GetFirstPackagePath(PackageName);
419
420 FAssetsPaths AssetsPaths;
421
422 // 获取所有地图路径
423 FString MapsFileJsonContent;
424 if (FFileHelper::LoadFileToString(MapsFileJsonContent, *PackageJsonFilePath))
425 {
426 TSharedPtr<FJsonObject> JsonParsed;
427 TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(MapsFileJsonContent);
428 if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
429 {
430 // 添加地图路径
431 auto MapsJsonArray = JsonParsed->GetArrayField(TEXT("maps"));
432
433 for (auto &MapJsonValue : MapsJsonArray)
434 {
435 TSharedPtr<FJsonObject> MapJsonObject = MapJsonValue->AsObject();
436
437 FMapData MapData;
438 MapData.Name = MapJsonObject->GetStringField(TEXT("name"));
439 MapData.Path = MapJsonObject->GetStringField(TEXT("path"));
440 MapData.bUseCarlaMapMaterials = MapJsonObject->GetBoolField(TEXT("use_carla_materials"));
441
442 AssetsPaths.MapsPaths.Add(std::move(MapData));
443 }
444
445 // 添加属性路径
446 auto PropJsonArray = JsonParsed->GetArrayField(TEXT("props"));
447
448 for (auto &PropJsonValue : PropJsonArray)
449 {
450 TSharedPtr<FJsonObject> PropJsonObject = PropJsonValue->AsObject();
451
452 const FString PropAssetPath = PropJsonObject->GetStringField(TEXT("path"));
453
454 AssetsPaths.PropsPaths.Add(std::move(PropAssetPath));
455 }
456 }
457 }
458 return AssetsPaths;
459}
460
461int32 ULoadAssetMaterialsCommandlet::Main(const FString &Params)
462{
463 FPackageParams PackageParams = ParseParams(Params);
464
465 // 获取属性和地图路径
466 FAssetsPaths AssetsPaths = GetAssetsPathFromPackage(PackageParams.Name);
467
468 LoadAssetsMaterials(PackageParams.Name, AssetsPaths.MapsPaths);
469
470#if WITH_EDITOR
471 UEditorLoadingAndSavingUtils::SaveDirtyPackages(true, true);
472#endif
473
474 return 0;
475}
476
477#endif
UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor)
TSharedPtr< const FActorInfo > carla::rpc::ActorState UWorld * World
carla::geom::Location DecalLocation
float FirstTileWorldLocationX
float FirstTileWorldLocationY
boost::optional< carla::road::Map > XODRMap
FString GetFirstPackagePath(const FString &PackageName) const
TSubclassOf< ARoadPainterWrapper > RoadPainterSubclass
static boost::optional< road::Map > Load(const std::string &opendrive)
包含从 .Package.json 文件中读取的所有资产数据的结构
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
包含从 .Package.json 文件中读取的地图数据的结构体
包含带有 Name 的 Package 和 bOnlyPrepareMaps 标志的结构体,用于 在不同阶段分离地图和道具的烹饪过程(地图将在 make import 命令期间导入,而道具将在 make...