CARLA
CarlaBlueprintRegistry.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019 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 
7 #include "Carla.h"
10 
11 #include "Dom/JsonObject.h"
12 #include "Misc/FileHelper.h"
13 #include "Serialization/JsonReader.h"
14 #include "Serialization/JsonSerializer.h"
15 
16 namespace CommonAttributes {
17  static const FString PATH = FPaths::ProjectContentDir();
18  static const FString DEFAULT = TEXT("/Carla/Config/Default");
19  static const FString DEFINITIONS = TEXT("props");
20 }
21 
22 namespace PropAttributes {
23  static const FString REGISTRY_FORMAT = TEXT(".Package.json");
24  static const FString NAME = TEXT("name");
25  static const FString MESH_PATH = TEXT("path");
26  static const FString SIZE = TEXT("size");
27 }
28 
29 static FString PropSizeTypeToString(EPropSize PropSizeType)
30 {
31  const UEnum *ptr = FindObject<UEnum>(ANY_PACKAGE, TEXT("EPropSize"), true);
32  if (!ptr)
33  {
34  return FString("unknown");
35  }
36  return ptr->GetNameStringByIndex(static_cast<int32>(PropSizeType));
37 }
38 
39 static EPropSize StringToPropSizeType(FString PropSize)
40 {
41  const UEnum *EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("EPropSize"), true);
42  if (EnumPtr)
43  {
44  return (EPropSize) EnumPtr->GetIndexByName(FName(*PropSize));
45  }
46  return EPropSize::INVALID;
47 }
48 
49 void UCarlaBlueprintRegistry::AddToCarlaBlueprintRegistry(const TArray<FPropParameters> &PropParametersArray)
50 {
51  TArray<TSharedPtr<FJsonValue>> ResultPropJsonArray;
52 
53  // Load default props file
54  FString DefaultPropFilePath = CommonAttributes::PATH + CommonAttributes::DEFAULT +
56  FString JsonString;
57  FFileHelper::LoadFileToString(JsonString, *DefaultPropFilePath);
58 
59  TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject());
60  TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(JsonString);
61 
62  // Fill Array of Props and save indexes of each prop in PropIndexes Map
63  TMap<FString, int> PropIndexes;
64  if (FJsonSerializer::Deserialize(JsonReader, JsonObject) && JsonObject.IsValid())
65  {
66  ResultPropJsonArray = JsonObject->GetArrayField(CommonAttributes::DEFINITIONS);
67  for (int32 i = 0; i < ResultPropJsonArray.Num(); ++i)
68  {
69  TSharedPtr<FJsonObject> PropJsonObject = ResultPropJsonArray[i]->AsObject();
70 
71  FString Name = PropJsonObject->GetStringField(PropAttributes::NAME);
72 
73  PropIndexes.Add(Name, i);
74  }
75  }
76 
77  // Add Input Props or Update them if already exists
78  for (auto &PropParameter : PropParametersArray)
79  {
80  TSharedPtr<FJsonObject> PropJsonObject;
81 
82  // Create object or update existing one
83  int *PropIndex = PropIndexes.Find(PropParameter.Name);
84  if (PropIndex)
85  {
86  PropJsonObject = ResultPropJsonArray[*PropIndex]->AsObject();
87  }
88  else
89  {
90  PropJsonObject = MakeShareable(new FJsonObject);
91  }
92 
93  // Fill Prop Json
94  PropJsonObject->SetStringField(PropAttributes::NAME, PropParameter.Name);
95  PropJsonObject->SetStringField(PropAttributes::MESH_PATH, PropParameter.Mesh->GetPathName());
96  PropJsonObject->SetStringField(PropAttributes::SIZE, PropSizeTypeToString(PropParameter.Size));
97 
98  // Add or Update
99  TSharedRef<FJsonValue> PropJsonValue = MakeShareable(new FJsonValueObject(PropJsonObject));
100  if (PropIndex)
101  {
102  ResultPropJsonArray[*PropIndex] = PropJsonValue;
103  }
104  else
105  {
106  ResultPropJsonArray.Add(PropJsonValue);
107 
108  PropIndexes.Add(PropParameter.Name, ResultPropJsonArray.Num() - 1);
109  }
110  }
111 
112  // Update Json Object
113  JsonObject->SetArrayField(CommonAttributes::DEFINITIONS, ResultPropJsonArray);
114 
115  // Serialize file
116  FString OutputString;
117  TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutputString);
118  FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
119 
120  // Save file
121  FFileHelper::SaveStringToFile(OutputString, *DefaultPropFilePath);
122 
123 }
124 
125 void UCarlaBlueprintRegistry::LoadPropDefinitions(TArray<FPropParameters> &PropParametersArray)
126 {
127 
128  // Find all Package.json files inside Unreal Content folder
129  const FString WildCard = FString("*").Append(PropAttributes::REGISTRY_FORMAT);
130 
131  TArray<FString> PropFileNames;
132  IFileManager::Get().FindFilesRecursive(PropFileNames,
134  *WildCard,
135  true,
136  false,
137  false);
138 
139  // Sort and place Default File First if it exists
140  PropFileNames.Sort();
141  FString DefaultFileName;
142  for (int32 i = 0; i < PropFileNames.Num() && DefaultFileName.IsEmpty(); ++i)
143  {
144  if (PropFileNames[i].Contains(CommonAttributes::DEFAULT))
145  {
146  DefaultFileName = PropFileNames[i];
147  PropFileNames.RemoveAt(i);
148  }
149  }
150  if (!DefaultFileName.IsEmpty())
151  {
152  PropFileNames.Insert(DefaultFileName, 0);
153  }
154 
155  // Read all registry files and overwrite default registry values with user
156  // registry files
157  TMap<FString, int> PropIndexes;
158 
159  for (int32 i = 0; i < PropFileNames.Num(); ++i)
160  {
161  FString FileJsonContent;
162  if (FFileHelper::LoadFileToString(FileJsonContent, *PropFileNames[i]))
163  {
164  TSharedPtr<FJsonObject> JsonParsed;
165  TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(FileJsonContent);
166  if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
167  {
168  auto PropJsonArray = JsonParsed->GetArrayField(CommonAttributes::DEFINITIONS);
169 
170  for (auto &PropJsonValue : PropJsonArray)
171  {
172  // Read Prop Json
173  TSharedPtr<FJsonObject> PropJsonObject = PropJsonValue->AsObject();
174 
175  FString PropName = PropJsonObject->GetStringField(PropAttributes::NAME);
176  FString PropMeshPath = PropJsonObject->GetStringField(PropAttributes::MESH_PATH);
177  FString PropSize = PropJsonObject->GetStringField(PropAttributes::SIZE);
178 
179  // Build Prop Parameter
180  UStaticMesh *PropMesh = LoadObject<UStaticMesh>(nullptr, *PropMeshPath);
181  EPropSize PropSizeType = StringToPropSizeType(PropSize);
182  FPropParameters Params {PropName, PropMesh, PropSizeType};
183 
184  // Add or Update
185  if (PropIndexes.Contains(PropName))
186  {
187  PropParametersArray[PropIndexes[PropName]] = Params;
188  }
189  else
190  {
191  PropParametersArray.Add(Params);
192  PropIndexes.Add(Params.Name, PropParametersArray.Num() - 1);
193  }
194  }
195  }
196  }
197  }
198 }
static void AddToCarlaBlueprintRegistry(const TArray< FPropParameters > &PropParametersArray)
EPropSize
static const FString PATH
static const FString MESH_PATH
static EPropSize StringToPropSizeType(FString PropSize)
static const FString SIZE
static T Get(carla::rpc::Response< T > &response)
static const FString REGISTRY_FORMAT
static void LoadPropDefinitions(TArray< FPropParameters > &PropParametersArray)
static const FString NAME
static const FString DEFAULT
static const FString DEFINITIONS
static FString PropSizeTypeToString(EPropSize PropSizeType)