13#include <util/ue-header-guard-begin.h>
15#include "JsonUtilities.h"
16#include "Misc/FileHelper.h"
17#include "Misc/Paths.h"
18#include "Components/StaticMeshComponent.h"
19#include "Materials/MaterialInstanceDynamic.h"
20#include <util/ue-header-guard-end.h>
29 FString UniqueVehicleParameters = GetWorld()->GetMapName().Mid(GetWorld()->StreamingLevelsPrefix.Len()) +
"/Vehicles.json";
34 for (
const FString &CatalogName : {FString(
"VehicleParameters.json"), FString(
"Vehicles.json"), UniqueVehicleParameters})
38 TArray<FVehicleParameters> PackVehiclesParams;
49 const FTransform &SpawnAtTransform,
55 UE_LOG(LogCarla, Error, TEXT(
"Actor Description Class is null."));
56 SpawnResult.
Status = EActorSpawnResultStatus::InvalidDescription;
60 AActor* SpawnedActor = GetWorld()->SpawnActor<
AActor>(ActorDescription.
Class, SpawnAtTransform);
61 SpawnResult.
Actor = SpawnedActor;
63 if(SpawnedActor ==
nullptr)
65 SpawnResult.
Status = EActorSpawnResultStatus::Collision;
72 if (SpawnedActor->ActorHasTag(TEXT(
"Carla.StaticBodyworkPaint")) &&
73 ActorDescription.
Variations.Contains(TEXT(
"color")))
76 TEXT(
"color"), ActorDescription.
Variations, FColor::White));
77 TArray<UStaticMeshComponent*> Panels;
78 SpawnedActor->GetComponents(Panels);
79 for (UStaticMeshComponent* Panel : Panels)
81 const TArray<FName> Slots = Panel->GetMaterialSlotNames();
82 for (int32 Index = 0; Index < Slots.Num(); ++Index)
84 if (Slots[Index] == TEXT(
"Bodywork_Mat"))
86 if (UMaterialInstanceDynamic* Paint = Panel->CreateDynamicMaterialInstance(Index))
88 Paint->SetVectorParameterValue(TEXT(
"Base Color"), Color);
94 SpawnResult.
Status = EActorSpawnResultStatus::Success;
97 SpawnResult.
Status = EActorSpawnResultStatus::UnknownError;
105 return V.Class.ToSoftObjectPath().ToString().StartsWith(MountPoint);
113 TSharedPtr<FJsonObject> JsonObject = MakeShareable(
new FJsonObject);
115 JsonObject->SetStringField(TEXT(
"Make"), VehicleParams.
Make);
116 JsonObject->SetStringField(TEXT(
"Model"), VehicleParams.
Model);
117 JsonObject->SetStringField(TEXT(
"Class"), VehicleParams.
Class.ToSoftObjectPath().ToString());
118 JsonObject->SetNumberField(TEXT(
"NumberOfWheels"), VehicleParams.
NumberOfWheels);
119 JsonObject->SetNumberField(TEXT(
"Generation"), VehicleParams.
Generation);
120 JsonObject->SetStringField(TEXT(
"ObjectType"), VehicleParams.
ObjectType);
121 JsonObject->SetStringField(TEXT(
"BaseType"), VehicleParams.
BaseType);
122 JsonObject->SetStringField(TEXT(
"SpecialType"), VehicleParams.
SpecialType);
123 JsonObject->SetBoolField(TEXT(
"HasDynamicDoors"), VehicleParams.
HasDynamicDoors);
124 JsonObject->SetBoolField(TEXT(
"HasLights"), VehicleParams.
HasLights);
127 TArray<TSharedPtr<FJsonValue>> ColorsArray;
130 TSharedPtr<FJsonObject> ColorObject = MakeShareable(
new FJsonObject);
131 ColorObject->SetNumberField(TEXT(
"R"), Color.R);
132 ColorObject->SetNumberField(TEXT(
"G"), Color.G);
133 ColorObject->SetNumberField(TEXT(
"B"), Color.B);
134 ColorObject->SetNumberField(TEXT(
"A"), Color.A);
135 ColorsArray.Add(MakeShareable(
new FJsonValueObject(ColorObject)));
137 JsonObject->SetArrayField(TEXT(
"RecommendedColors"), ColorsArray);
140 TArray<TSharedPtr<FJsonValue>> DriversArray;
143 DriversArray.Add(MakeShareable(
new FJsonValueNumber(DriverID)));
145 JsonObject->SetArrayField(TEXT(
"SupportedDrivers"), DriversArray);
152 TArray<TSharedPtr<FJsonValue>> JsonArray;
158 JsonArray.Add(MakeShareable(
new FJsonValueObject(JsonObject)));
162 TSharedRef<FJsonObject> RootObject = MakeShareable(
new FJsonObject);
163 RootObject->SetArrayField(TEXT(
"Vehicles"), JsonArray);
166 FString OutputString;
167 TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutputString);
168 FJsonSerializer::Serialize(RootObject, Writer);
175 FString FilePath = FPaths::ProjectContentDir() + TEXT(
"Carla/Config/") + FileName;
180 if (FFileHelper::SaveStringToFile(JsonContent, *FilePath))
182 UE_LOG(LogCarla, Log, TEXT(
"JSON file successfully saved at: %s"), *FilePath);
186 UE_LOG(LogCarla, Error, TEXT(
"Failed to save JSON file at: %s"), *FilePath);
192 if (!JsonObject.IsValid())
return false;
194 JsonObject->TryGetStringField(TEXT(
"Make"), OutVehicleParams.
Make);
195 JsonObject->TryGetStringField(TEXT(
"Model"), OutVehicleParams.
Model);
200 JsonObject->TryGetStringField(TEXT(
"Class"), ClassPath);
201 OutVehicleParams.
Class = TSoftClassPtr<ACarlaWheeledVehicle>(FSoftObjectPath(ClassPath));
203 JsonObject->TryGetNumberField(TEXT(
"NumberOfWheels"), OutVehicleParams.
NumberOfWheels);
204 JsonObject->TryGetNumberField(TEXT(
"Generation"), OutVehicleParams.
Generation);
205 JsonObject->TryGetStringField(TEXT(
"ObjectType"), OutVehicleParams.
ObjectType);
206 JsonObject->TryGetStringField(TEXT(
"BaseType"), OutVehicleParams.
BaseType);
207 JsonObject->TryGetStringField(TEXT(
"SpecialType"), OutVehicleParams.
SpecialType);
208 JsonObject->TryGetBoolField(TEXT(
"HasDynamicDoors"), OutVehicleParams.
HasDynamicDoors);
209 JsonObject->TryGetBoolField(TEXT(
"HasLights"), OutVehicleParams.
HasLights);
212 const TArray<TSharedPtr<FJsonValue>>* ColorsArray;
213 if (JsonObject->TryGetArrayField(TEXT(
"RecommendedColors"), ColorsArray))
216 for (
const TSharedPtr<FJsonValue>& ColorValue : *ColorsArray)
218 TSharedPtr<FJsonObject> ColorObject = ColorValue->AsObject();
219 if (ColorObject.IsValid())
222 Color.R = ColorObject->GetIntegerField(TEXT(
"R"));
223 Color.G = ColorObject->GetIntegerField(TEXT(
"G"));
224 Color.B = ColorObject->GetIntegerField(TEXT(
"B"));
225 Color.A = ColorObject->GetIntegerField(TEXT(
"A"));
232 const TArray<TSharedPtr<FJsonValue>>* DriversArray;
233 if (JsonObject->TryGetArrayField(TEXT(
"SupportedDrivers"), DriversArray))
236 for (
const TSharedPtr<FJsonValue>& DriverValue : *DriversArray)
247 TSharedPtr<FJsonObject> RootObject;
248 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
250 if (!FJsonSerializer::Deserialize(Reader, RootObject) || !RootObject.IsValid())
252 UE_LOG(LogCarla, Error, TEXT(
"Failed to parse JSON."));
257 const TArray<TSharedPtr<FJsonValue>>* VehiclesArray;
258 if (RootObject->TryGetArrayField(TEXT(
"Vehicles"), VehiclesArray))
260 OutVehicleParamsArray.Empty();
261 for (
const TSharedPtr<FJsonValue>& VehicleValue : *VehiclesArray)
263 TSharedPtr<FJsonObject> VehicleObject = VehicleValue->AsObject();
264 if (VehicleObject.IsValid())
269 OutVehicleParamsArray.Add(VehicleParams);
283 FString FilePath = FPaths::IsRelative(FileName)
284 ? FPaths::ProjectContentDir() + TEXT(
"Carla/Config/") + FileName
289 if (FFileHelper::LoadFileToString(JsonContent, *FilePath))
294 UE_LOG(LogCarla, Log, TEXT(
"Vehicle parameters loaded successfully from %s"), *FilePath);
298 UE_LOG(LogCarla, Error, TEXT(
"Failed to parse vehicle parameters from %s"), *FilePath);
301 else if(FileName ==
"VehicleParameters.json")
303 UE_LOG(LogCarla, Error, TEXT(
"Failed to load file: %s"), *FilePath);
307 UE_LOG(LogCarla, Warning, TEXT(
"Additional file not found: %s"), *FilePath);
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
static bool DefinitionReferencesPath(const FActorDefinition &Definition, const FString &MountPoint)
True when the definition's class or any attribute/variation value points at content under MountPoint.
static void SaveVehicleParametersArrayToFile(const TArray< FVehicleParameters > &VehicleParamsArray, const FString &FileName)
static bool JsonToFVehicleParametersArray(const FString &JsonString, TArray< FVehicleParameters > &OutVehicleParamsArray)
static bool JsonToFVehicleParameters(const TSharedPtr< FJsonObject > JsonObject, FVehicleParameters &OutVehicleParams)
static TSharedPtr< FJsonObject > FVehicleParametersToJsonObject(const FVehicleParameters &VehicleParams)
virtual FActorSpawnResult SpawnActor(const FTransform &SpawnAtTransform, const FActorDescription &ActorDescription) override
Spawn an actor based on ActorDescription and Transform.
bool PostProcessVehicle(AActor *SpawnedActor, const FActorDescription &VehicleParams)
virtual TArray< FActorDefinition > GetDefinitions() override
Retrieve the definitions of the static mesh actor.
static FString FVehicleParametersArrayToJson(const TArray< FVehicleParameters > &VehicleParamsArray)
static void LoadVehicleParametersArrayFromFile(const FString &FileName, TArray< FVehicleParameters > &OutVehicleParamsArray)
TArray< FVehicleParameters > VehiclesParams
TArray< FVehicleParameters > MineVehiclesParams
TArray< FActorDefinition > Definitions
virtual void ReleaseContentPack(const FString &MountPoint) override
Drop every cached definition, parameter and loaded asset that refers to content under MountPoint ("/<...
static FColor RetrieveActorAttributeToColor(const FString &Id, const TMap< FString, FActorAttribute > &Attributes, const FColor &Default)
static void MakeVehicleDefinitions(const TArray< FVehicleParameters > &ParameterArray, TArray< FActorDefinition > &Definitions)
static void MergeCatalog(TArray< T > &Into, const TArray< T > &From, KeyFn Key)
Merge catalog entries: an entry whose key already exists replaces it in place (later files override b...
static TArray< FString > FindPackCatalogFiles(const FString &RelativeName)
<ContentDir>/Config/<RelativeName> of every mounted pack where the file exists, in mount order (later...
A definition of a Carla Actor with all the variation and attributes.
A description of a Carla Actor with all its variation.
TMap< FString, FActorAttribute > Variations
User selected variations of the actor.
TSubclassOf< AActor > Class
Class of the actor to be spawned.
Result of an actor spawn function.
EActorSpawnResultStatus Status
TArray< FColor > RecommendedColors
TArray< int32 > SupportedDrivers
List of IDs of the drivers (pedestrians) supported by this vehicle, leave empty if no driver is suppo...
FString BaseType
(OPTIONAL) Use for a base classification of vehicles (car / truck / van / bycicle / motorcycle).
FString ObjectType
(OPTIONAL) Use for custom classification of vehicles.
TSoftClassPtr< ACarlaWheeledVehicle > Class
FString SpecialType
(OPTIONAL) Use for a more in-depth classification of vehicles (electric / emergency / taxi ....