1#include "EntityReader.h"
4#include "EntityStore.h"
5#include "ReaderCommon.h"
6#include "ResourceReader.h"
8#include "Utilities/Parsing.h"
10#include "Foundation/Logging/Logger.h"
11#include "Foundation/HashFunctions.h"
14#include <glm/gtx/quaternion.hpp>
23 void readMaterialInstanceField(Context * context,
const Value & value, FieldValue & fieldValue, ExpressionContext * ec)
25 fieldValue.type = DefaultValueType::MaterialInstance;
27 static_assert(
sizeof(MaterialInstanceDefinition) <=
sizeof(fieldValue.storage));
28 auto & materialInstance = *(
new (fieldValue.storage) MaterialInstanceDefinition());
29 materialInstance.type = ResourceTypes::MaterialInstance;
31 if (value.IsString()) {
32 std::string v = toString(value);
35 materialInstance.reference = v.substr(1);
38 materialInstance.material = v;
40 }
else if (value.IsObject()) {
41 ReaderContext rc{ context, ec,
nullptr };
42 readMaterialInstanceDefinition(&rc, value, materialInstance);
47void Cogs::Core::readEntityDefaults(Context * context,
const Value & value, std::vector<FieldValue> & defaultValues, ExpressionContext * ec)
49 if (value.IsArray()) {
50 for (
auto & d : value.GetArray()) {
51 readFieldValues(context, d.MemberBegin()->value, toKey(d.MemberBegin()->name), defaultValues, ec);
54 else if (value.IsObject()) {
55 for (
auto & d : value.GetObject()) {
56 readFieldValues(context, d.value, toKey(d.name), defaultValues, ec);
61bool Cogs::Core::readFieldValue(Context * context,
const Value & jsonValue,
const Reflection::Type & type,
const StringView & fieldName, std::vector<FieldValue>& fieldValues, ExpressionContext * ec)
63 const auto field = type.getField(fieldName.to_string());
66 LOG_ERROR(logger,
"Field \"%.*s\" not found in type %s.", StringViewFormat(fieldName), type.getName().c_str());
71 if (jsonValue.IsNull()) {
75 const auto & fieldType = Reflection::TypeDatabase::getType(field->getTypeId());
77 FieldValue value = {};
78 value.componentId = type.getTypeId();
79 value.fieldId = type.getFieldId(field);
81 if (fieldType.isEnum()) {
82 if (jsonValue.IsString()) {
83 if (fieldType.isEnumFlags()) {
84 value.intValue = parseEnumFlags(toKey(jsonValue), fieldType, value.intValue);
87 value.intValue = parseEnum(toKey(jsonValue), fieldType, value.intValue);
89 value.type = DefaultValueType::Enum;
91 else if (jsonValue.IsNumber()) {
92 value.type = DefaultValueType::Enum;
93 if (jsonValue.IsInt()) {
94 value.intValue = jsonValue.GetInt();
97 value.intValue = (int)jsonValue.GetDouble();
101 LOG_ERROR(logger,
"Invalid enum of field: %.*s of type %s.", StringViewFormat(fieldName), type.getName().c_str());
104 else if (fieldType == Reflection::TypeDatabase::getType<bool>()) {
105 if (jsonValue.IsBool()) {
106 value.boolValue = jsonValue.GetBool();
107 value.type = DefaultValueType::Bool;
109 else if (jsonValue.IsString()) {
110 value.boolValue = readValue<bool>(jsonValue, ec);
111 value.type = DefaultValueType::Bool;
114 LOG_ERROR(logger,
"Invalid bool of field: %.*s of type %s.", StringViewFormat(fieldName), type.getName().c_str());
117 else if (fieldType == Reflection::TypeDatabase::getType<glm::vec2>()) {
118 readArray(jsonValue, value.float2, ec);
119 value.type = DefaultValueType::Vec2;
121 else if (fieldType == Reflection::TypeDatabase::getType<glm::vec3>()) {
122 readArray(jsonValue, value.float3, ec);
123 value.type = DefaultValueType::Vec3;
125 else if (fieldType == Reflection::TypeDatabase::getType<glm::vec4>()) {
126 readArray(jsonValue, value.float4, ec);
127 value.type = DefaultValueType::Vec4;
129 else if (fieldType == Reflection::TypeDatabase::getType<glm::mat4>()) {
130 readArray(jsonValue, glm::value_ptr(value.mat4), 16, ec);
131 value.type = DefaultValueType::Mat4;
133 else if (fieldType == Reflection::TypeDatabase::getType<glm::dvec2>()) {
134 readArray(jsonValue, value.double2, ec);
135 value.type = DefaultValueType::DVec2;
137 else if (fieldType == Reflection::TypeDatabase::getType<glm::dvec3>()) {
138 readArray(jsonValue, value.double3, ec);
139 value.type = DefaultValueType::DVec3;
141 else if (fieldType == Reflection::TypeDatabase::getType<glm::dvec4>()) {
142 readArray(jsonValue, value.double4, ec);
143 value.type = DefaultValueType::DVec4;
145 else if (fieldType == Reflection::TypeDatabase::getType<glm::quat>()) {
146 bool success =
false;
147 auto arr = jsonValue.GetArray();
148 if (arr.Size() == 2) {
149 if (arr[0].IsArray()) {
150 auto A0 = arr[0].GetArray();
151 if (A0.Size() == 3) {
152 if (arr[1].IsArray()) {
153 auto A1 = arr[1].GetArray();
154 if (A1.Size() == 3) {
157 readArray(arr[0], src, ec);
158 readArray(arr[1], dst, ec);
159 value.quat = glm::rotation(glm::normalize(src), glm::normalize(dst));
162 }
else if (arr[1].IsNumber() || arr[1].IsString()) {
165 readArray(arr[0], axisValue, ec);
166 float angleValue = readValue(arr[1], 1.0f, ec);
167 value.quat = glm::angleAxis(angleValue, axisValue);
173 else if (arr.Size() == 4) {
175 readArray(jsonValue, value.float4, ec);
178 value.type = DefaultValueType::Quaternion;
179 if (success ==
false) {
180 LOG_ERROR(logger,
"Failed to parse quaternion of field: %.*s of type %s.", StringViewFormat(fieldName), type.getName().c_str());
182 }
else if (fieldType == Reflection::TypeDatabase::getType<MaterialInstanceHandle>()) {
183 readMaterialInstanceField(context, jsonValue, value, ec);
184 }
else if (fieldType == Reflection::TypeDatabase::getType<ModelHandle>()) {
185 value.type = DefaultValueType::Model;
186 value.value = jsonValue.GetString();
187 }
else if (fieldType == Reflection::TypeDatabase::getType<AssetHandle>()) {
188 value.type = DefaultValueType::Asset;
189 value.value = jsonValue.GetString();
190 }
else if (fieldType == Reflection::TypeDatabase::getType<GuiDocumentHandle>()) {
191 value.type = DefaultValueType::Gui;
192 value.value = jsonValue.GetString();
193 }
else if (fieldType == Reflection::TypeDatabase::getType<MeshHandle>()) {
194 value.type = DefaultValueType::Mesh;
195 if (jsonValue.IsString()) {
196 auto meshName = toString(jsonValue);
197 if (meshName.size() < 2 || meshName[0] !=
'$') {
198 LOG_ERROR(logger,
"Mesh field must be set to existing field resource using $Name syntax.");
201 value.value = meshName.substr(1);
203 ResourceDefinition def;
204 value.value = readMesh(context, def, jsonValue).
to_string();
206 }
else if (fieldType == Reflection::TypeDatabase::getType<TextureHandle>()) {
207 value.type = DefaultValueType::Texture;
208 value.value = toString(jsonValue);
209 }
else if (fieldType == Reflection::TypeDatabase::getType<std::string>()) {
210 value.type = DefaultValueType::String;
211 value.value = toString(jsonValue);
212 }
else if (fieldType == Reflection::TypeDatabase::getType<std::vector<std::string>>()) {
213 value.type = DefaultValueType::MultiString;
214 auto arr = jsonValue.GetArray();
215 for (
auto & element : arr) {
216 value.values.push_back(toString(element));
218 }
else if (fieldType == Reflection::TypeDatabase::getType<std::vector<int>>()) {
219 value.type = DefaultValueType::IntArray;
220 auto arr = jsonValue.GetArray();
221 for (
auto & element : arr) {
222 value.intValues.push_back(element.GetInt());
224 }
else if (fieldType == Reflection::TypeDatabase::getType<std::vector<float>>()) {
225 value.type = DefaultValueType::FloatArray;
226 auto arr = jsonValue.GetArray();
227 for (
auto & element : arr) {
228 value.floatValues.push_back(element.GetFloat());
230 }
else if (fieldType == Reflection::TypeDatabase::getType<std::vector<glm::vec2>>()) {
231 value.type = DefaultValueType::Vec2Array;
232 auto arr = jsonValue.GetArray();
234 const auto & first = arr.Begin();
236 if (first->IsArray()) {
237 for (
auto & a : arr) {
239 if (readArray(a, v, ec) != 2) {
240 LOG_WARNING(logger,
"Vector length mismatch in %s.", field->getName().c_str());
243 value.vec2Values.push_back(v);
245 }
else if ((arr.Size() % 2) == 0) {
246 for (
unsigned int indx = 0; indx < arr.Size(); indx += 2) {
247 value.vec2Values.push_back(glm::vec2{ readValue(arr[indx], 0.0f, ec), readValue(arr[indx + 1], 0.0f, ec) });
250 LOG_ERROR(logger,
"Invalid length of %s in entity type %s.",
251 field->getName().c_str(),
252 type.getName().c_str());
255 }
else if (fieldType == Reflection::TypeDatabase::getType<std::vector<glm::vec3>>()) {
256 value.type = DefaultValueType::Vec3Array;
257 auto arr = jsonValue.GetArray();
259 const auto & first = arr.Begin();
261 if (first->IsArray()) {
262 for (
auto & a : arr) {
264 if (readArray(a, v, ec) != 3) {
265 LOG_WARNING(logger,
"Vector length mismatch in %s.", field->getName().c_str());
268 value.vec3Values.push_back(v);
270 }
else if ((arr.Size() % 3) == 0) {
271 for (
unsigned int indx = 0; indx < arr.Size(); indx += 3) {
272 value.vec3Values.push_back(glm::vec3{ readValue(arr[indx], 0.0f, ec), readValue(arr[indx + 1], 0.0f, ec), readValue(arr[indx + 2], 0.0f, ec) });
275 LOG_ERROR(logger,
"Invalid length of %s in entity type %s.",
276 field->getName().c_str(),
277 type.getName().c_str());
280 }
else if (fieldType == Reflection::TypeDatabase::getType<std::vector<glm::vec4>>()) {
281 value.type = DefaultValueType::Vec4Array;
282 auto arr = jsonValue.GetArray();
284 const auto & first = arr.Begin();
286 if (first->IsArray()) {
287 for (
auto & a : arr) {
289 if (readArray(a, v, ec) != 4) {
290 LOG_WARNING(logger,
"Vector length mismatch in %s.", field->getName().c_str());
293 value.vec4Values.push_back(v);
295 }
else if ((arr.Size() % 4) == 0) {
296 for (
unsigned int indx = 0; indx < arr.Size(); indx += 4) {
297 value.vec4Values.push_back(glm::vec4{ readValue(arr[indx], 0.0f, ec), readValue(arr[indx + 1], 0.0f, ec), readValue(arr[indx + 2], 0.0f, ec), readValue(arr[indx + 3], 0.0f, ec) });
300 LOG_ERROR(logger,
"Invalid length of %s in entity type %s.",
301 field->getName().c_str(),
302 type.getName().c_str());
305 }
else if (fieldType == Reflection::TypeDatabase::getType<EntityPtr>() || fieldType == Reflection::TypeDatabase::getType<WeakEntityPtr>()) {
306 value.type = DefaultValueType::Entity;
307 value.value = toString(jsonValue);
308 }
else if (fieldType == Reflection::TypeDatabase::getType<std::vector<EntityPtr>>() || fieldType == Reflection::TypeDatabase::getType<std::vector<WeakEntityPtr>>()) {
309 value.type = DefaultValueType::EntityArray;
310 auto arr = jsonValue.GetArray();
311 for (
auto & element : arr) {
312 value.values.push_back(toString(element));
315 auto ext = getExtensionReader(fieldType.getTypeId());
318 value.type = DefaultValueType::Extension;
319 value.value = toString(jsonValue);
320 }
else if (fieldType == Reflection::TypeDatabase::getType<float>()) {
321 value.type = DefaultValueType::Float;
322 value.floatValue = readValue<float>(jsonValue, 0.0f, ec);
323 }
else if (fieldType == Reflection::TypeDatabase::getType<uint32_t>()) {
324 value.type = DefaultValueType::Int;
325 value.intValue = readValue<int>(jsonValue, ec);
327 else if (fieldType == Reflection::TypeDatabase::getType<int32_t>()) {
328 value.type = DefaultValueType::Int;
329 value.intValue = readValue<int>(jsonValue, ec);
332 LOG_WARNING(logger,
"Value defined for Field: %s, Component type: %s Unsupported.",
333 field->getName().c_str(),
334 type.getName().c_str());
339 if (value.fieldId != Reflection::NoField) {
340 fieldValues.push_back(value);
342 LOG_ERROR(logger,
"Value defined for field %s which was not found on entity type %s.",
343 field->getName().c_str(),
344 type.getName().c_str());
350bool Cogs::Core::readFieldValues(Context * context,
const Value & jsonFieldValues,
const StringView & typeName, std::vector<FieldValue> & fieldValues, ExpressionContext * ec)
352 const auto & type = Reflection::TypeDatabase::getType(typeName);
354 if (!type.isValid()) {
355 LOG_ERROR(logger,
"Type \"%.*s\" invalid.", StringViewFormat(typeName));
360 if (!jsonFieldValues.IsObject())
return false;
362 auto valuesObject = jsonFieldValues.GetObject();
364 if (valuesObject.ObjectEmpty()) {
365 FieldValue value = {};
366 value.componentId = type.getTypeId();
368 fieldValues.push_back(value);
372 for (
auto & member : valuesObject) {
373 const auto fieldName = toKey(member.name);
375 if (!fieldName.size()) {
376 LOG_ERROR(logger,
"Field name cannot be empty.");
381 success &= readFieldValue(context, member.value, type, fieldName, fieldValues, ec);
387void Cogs::Core::readEntityDefinition(EntityStore * store,
const StringView & name,
const Value & value)
389 EntityDefinition definition;
391 readEntityDefinition(store, name, value, definition);
393 if (!definition.name.empty()) {
394 store->addEntityDefinition(definition);
396 LOG_WARNING(logger,
"Discarding anonymous entity definition.");
400bool Cogs::Core::readEntityDefinition(EntityStore * store,
const StringView & name,
const Value & value, EntityDefinition & definition)
402 if (name.size()) definition.name = name.to_string();
404 if (value.IsString()) {
405 StringView aliasedName(value.GetString(), value.GetStringLength());
406 auto aliasedDefinition = store->getEntityDefinition(aliasedName);
408 if (!aliasedDefinition) {
409 LOG_ERROR(logger,
"Cannot alias unknown enitity definition %.*s.", StringViewFormat(aliasedName));
414 definition.components = aliasedDefinition->components;
415 definition.defaultValues = aliasedDefinition->defaultValues;
418 }
else if (!value.IsObject()) {
419 LOG_ERROR(logger,
"Invalid JSON value structure.");
423 ExpressionContext ec;
427 for (
const auto & member : value.GetObject()) {
428 auto key = StringView(member.name.GetString());
431 definition.name = member.value.GetString();
432 }
else if (key ==
"description") {
433#if !defined( EMSCRIPTEN )
434 definition.description = member.value.GetString();
436 }
else if (key ==
"components") {
437 auto arr = member.value.GetArray();
440 LOG_WARNING(logger,
"Entity definition created for %s with zero components defined.", definition.name.c_str());
443 for (
auto & m : arr) {
444 definition.components.push_back(m.GetString());
446 }
else if (key ==
"defaults") {
447 readEntityDefaults(store->getContext(), member.value, definition.defaultValues, &ec);
448 }
else if (key ==
"inherits") {
449 StringView inheritedName(member.value.GetString(), member.value.GetStringLength());
450 auto inheritedDefinition = store->getEntityDefinition(inheritedName);
452 if (!inheritedDefinition) {
453 LOG_ERROR(logger,
"Cannot inherit unknown enitity definition %.*s.", StringViewFormat(inheritedName));
458 for (
auto & c : inheritedDefinition->components) {
459 definition.components.push_back(c);
462 for (
auto & d : inheritedDefinition->defaultValues) {
463 definition.defaultValues.push_back(d);
466 readFieldValues(store->getContext(), member.value, key, definition.defaultValues, &ec);
470 return !definition.name.empty();
475 auto document = parseJson(content, JsonParseFlags::NoCachedContent);
477 readEntityDefinition(entityStore,
"", document);
Stores top level entities for the engine.
Log implementation class.
Provides a weakly referenced view over the contents of a string.
std::string to_string() const
String conversion method.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
constexpr Log getLogger(const char(&name)[LEN]) noexcept