1#include "EntityWriter.h"
4#include "EntityStore.h"
7#include "Components/Core/TransformComponent.h"
8#include "Components/Core/ModelComponent.h"
9#include "Components/Core/SceneComponent.h"
11#include "Resources/Resources.h"
12#include "Resources/Model.h"
13#include "Resources/Texture.h"
14#include "Resources/MaterialInstance.h"
15#include "Resources/Mesh.h"
16#include "Resources/MaterialManager.h"
18#include "Foundation/Logging/Logger.h"
19#include "Foundation/Reflection/TypeDatabase.h"
25using namespace rapidjson;
36 template<
typename T,
typename AllocatorType>
37 void writeVectorVec(Value &
object,
const StringView & key,
const std::vector<T>& values,
const std::vector<T> defaultValue, AllocatorType & a)
39 if (values == defaultValue)
return;
41 Value vec(kArrayType);
43 for (
const auto & value : values)
45 for (
int i = 0; i < value.length(); ++i) {
46 vec.PushBack((
double)value[i], a);
50 Value v(key.
data(), a);
51 object.AddMember(v, vec, a);
54 template<
typename T,
typename AllocatorType>
55 void writeVectorInt(Value &
object,
const StringView & key,
const std::vector<T>& values,
const std::vector<T> defaultValue, AllocatorType & a)
57 if (values == defaultValue)
return;
59 Value vec(kArrayType);
61 for (
const auto & value : values)
63 vec.PushBack((
int)value, a);
66 Value v(key.
data(), a);
67 object.AddMember(v, vec, a);
70 template<
typename T,
typename AllocatorType>
71 void writeVectorDouble(Value &
object,
const StringView & key,
const std::vector<T>& values,
const std::vector<T> defaultValue, AllocatorType & a)
73 if (values == defaultValue)
return;
75 Value vec(kArrayType);
77 for (
const auto & value : values)
79 vec.PushBack((
double)value, a);
82 Value v(key.
data(), a);
83 object.AddMember(v, vec, a);
86 template<
typename T,
typename AllocatorType>
87 void writeVec(Value &
object,
const StringView & key, T value, T defaultValue, AllocatorType & a)
89 if (value == defaultValue)
return;
91 Value vec(kArrayType);
93 for (
int i = 0; i < value.length(); ++i) {
94 vec.PushBack((
double)value[i], a);
97 Value v(key.
data(), a);
98 object.AddMember(v, vec, a);
101 template<
typename AllocatorType>
102 void writeMat(Value&
object,
const StringView& key,
const glm::mat4& value,
const glm::mat4& defaultValue, AllocatorType& a)
104 if (value == defaultValue)
return;
106 Value vec(kArrayType);
108 for (
int i = 0; i < 16; ++i) {
109 vec.PushBack((
double)glm::value_ptr(value)[i], a);
112 Value v(key.
data(), a);
113 object.AddMember(v, vec, a);
116 template<
typename AllocatorType>
117 void writeDouble(Value &
object,
const StringView & key,
const double value,
const double defaultValue, AllocatorType & a)
119 if (value == defaultValue)
return;
122 if (std::isnan(value)) {
123 if (std::isnan(defaultValue)) {
124 LOG_WARNING(logger,
"Skipped serialization of NaN value in %s", key.
data());
130 Value v(key.
data(), a);
131 object.AddMember(v, (
double)value, a);
134 template<
typename T,
typename AllocatorType>
135 void writeInteger(Value &
object,
const StringView & key, T value, T defaultValue, AllocatorType & a)
137 if (value == defaultValue)
return;
139 Value v(key.
data(), a);
140 object.AddMember(v, (
int)value, a);
143 template<
typename AllocatorType>
144 void writeBool(Value &
object,
const StringView & key,
bool value,
bool defaultValue, AllocatorType & a)
146 if (value == defaultValue)
return;
151 Value v(key.
data(), a);
152 object.AddMember(v, b, a);
155 template<
typename AllocatorType>
158 if (value == defaultValue)
return;
160 Value v(key.
data(), a);
161 Value vv(value.
data(), a);
162 object.AddMember(v, vv, a);
165 std::string getUniqueMaterialName(Context * context)
167 static int resId = 0;
169 std::vector<ResourceBase*> allocated = context->materialInstanceManager->getAllocatedResources();
171 auto name =
"_MaterialInstance" + std::to_string(resId++);
175 for (
auto & m : allocated) {
176 if (m->getName() == name) {
183 name =
"_MaterialInstance" + std::to_string(resId++);
189 std::string getResourceName(Context * context, ResourceHandleBase * fieldValue, std::unordered_set<ResourceHandleBase> * resources)
191 if (fieldValue && *fieldValue) {
192 auto resource = fieldValue->get();
194 if (resource->getName().empty()) {
195 if (resource->getType() == ResourceTypes::Mesh) {
196 static int resId = 0;
197 resource->setName(
"_Mesh" + std::to_string(resId++));
198 }
else if (resource->getType() == ResourceTypes::Texture) {
199 static int resId = 0;
200 resource->setName(
"_Texture" + std::to_string(resId++));
201 }
else if (resource->getType() == ResourceTypes::Model) {
202 static int resId = 0;
203 resource->setName(
"_Model" + std::to_string(resId++));
204 }
else if (resource->getType() == ResourceTypes::MaterialInstance) {
205 resource->setName(getUniqueMaterialName(context));
210 resources->insert(*fieldValue);
213 std::string fieldName =
"$" + resource->getName().to_string();
223 auto & a = d.GetAllocator();
224 const bool saveGeometry = (flags & AssetWriteFlags::Geometry) == AssetWriteFlags::Geometry;
226 entityValue.AddMember(
"name", Value(entity->
getName().c_str(), a), a);
232 entityValue.AddMember(
"type", Value(definition->
name.c_str(), a), a);
236 Value compValue(kObjectType);
238 auto component = c.resolve();
240 auto type = &Reflection::TypeDatabase::getType(c.typeId);
241 auto typeName = type->getName();
244 if (type->getName() ==
"TransformComponent") {
248 if (transform->transformFlags != defaultTransform->
transformFlags) {
249 entityValue.AddMember(
"transformFlags", transform->transformFlags, a);
252 if (!transform->transformFlags) {
253 writeVec(compValue,
"coordinates", transform->coordinates, defaultTransform->
coordinates, a);
254 writeVec(compValue,
"position", transform->position, defaultTransform->
position, a);
255 writeVec(compValue,
"rotation", transform->rotation, defaultTransform->
rotation, a);
256 writeVec(compValue,
"scale", transform->scale, defaultTransform->
scale, a);
259 glm::mat4 defaultMat = glm::mat4(1.0f);
260 writeMat(compValue,
"transform", transform->transform, defaultMat, a);
264 size_t numFields = type->getNumFields();
266 for (FieldId f = 0; f < numFields; ++f) {
271 auto & fieldName = field->
getName();
273 auto & fieldHeader = fieldName.
getName();
277 if (fieldType.isEnum()) {
278 uint32_t value = *field->
getPtr<uint32_t>(component);
279 uint32_t defaultFieldValue = *field->
getPtr<uint32_t>(defaultComponent);
280 if (value != defaultFieldValue) {
282 if (fieldType.isEnumFlags()) {
283 std::string valueStr;
284 size_t numEnums = fieldType.getNumEnumerators();
286 for (
size_t i = 0; i < numEnums; ++i) {
287 auto enumerator = fieldType.getEnumerator(i);
288 uint32_t enumeratorValue =
static_cast<uint32_t
>(enumerator->getValue());
291 if (value == enumeratorValue) {
292 valueStr = enumerator->getName().getName();
296 if (std::popcount(enumeratorValue) == 1 && value & enumeratorValue) {
297 if (!valueStr.empty()) valueStr +=
'|';
298 valueStr += enumerator->getName().getName();
302 writeString(compValue, fieldHeader, valueStr.c_str(),
"", a);
304 else if (value < fieldType.getNumEnumerators()) {
305 for (
size_t i = 0; i < fieldType.getNumEnumerators(); ++i) {
306 auto fieldEnum = fieldType.getEnumerator(i);
307 if (
static_cast<uint32_t
>(fieldEnum->getValue()) == value) {
308 writeString(compValue, fieldHeader, fieldEnum->getName().c_str(),
"", a);
314 writeInteger(compValue, fieldHeader, value, ~value, a);
317 }
else if (fieldType == TypeDatabase::getType<bool>()) {
318 auto fieldValue = field->
getPtr<
bool>(component);
319 auto defaultFieldValue = field->
getPtr<
bool>(defaultComponent);
321 if (*fieldValue != *defaultFieldValue) {
322 writeBool(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
324 }
else if (fieldType == TypeDatabase::getType<int32_t>()) {
325 auto fieldValue = field->
getPtr<int32_t>(component);
326 auto defaultFieldValue = field->
getPtr<int32_t>(defaultComponent);
328 if (*fieldValue != *defaultFieldValue) {
329 writeInteger(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
331 }
else if (fieldType == TypeDatabase::getType<uint32_t>()) {
332 auto fieldValue = field->
getPtr<uint32_t>(component);
333 auto defaultFieldValue = field->
getPtr<uint32_t>(defaultComponent);
335 if (*fieldValue != *defaultFieldValue) {
336 writeInteger(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
338 }
else if (fieldType == TypeDatabase::getType<float>()) {
339 auto fieldValue = field->
getPtr<
float>(component);
340 auto defaultFieldValue = field->
getPtr<
float>(defaultComponent);
342 if (*fieldValue != *defaultFieldValue) {
343 writeDouble(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
345 }
else if (fieldType == TypeDatabase::getType<glm::vec2>()) {
346 auto fieldValue = field->
getPtr<glm::vec2>(component);
347 auto defaultFieldValue = field->
getPtr<glm::vec2>(defaultComponent);
349 writeVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
350 }
else if (fieldType == TypeDatabase::getType<glm::vec3>()) {
351 auto fieldValue = field->
getPtr<glm::vec3>(component);
352 auto defaultFieldValue = field->
getPtr<glm::vec3>(defaultComponent);
354 writeVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
355 }
else if (fieldType == TypeDatabase::getType<glm::vec4>()) {
356 auto fieldValue = field->
getPtr<glm::vec4>(component);
357 auto defaultFieldValue = field->
getPtr<glm::vec4>(defaultComponent);
359 writeVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
360 }
else if (fieldType == TypeDatabase::getType<glm::quat>()) {
361 auto fieldValue = field->
getPtr<glm::quat>(component);
362 auto defaultFieldValue = field->
getPtr<glm::quat>(defaultComponent);
364 writeVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
365 }
else if (fieldType == TypeDatabase::getType<glm::dvec2>()) {
366 auto fieldValue = field->
getPtr<glm::dvec2>(component);
367 auto defaultFieldValue = field->
getPtr<glm::dvec2>(defaultComponent);
369 writeVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
370 }
else if (fieldType == TypeDatabase::getType<glm::dvec3>()) {
371 auto fieldValue = field->
getPtr<glm::dvec3>(component);
372 auto defaultFieldValue = field->
getPtr<glm::dvec3>(defaultComponent);
374 writeVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
375 }
else if (fieldType == TypeDatabase::getType<glm::dvec4>()) {
376 auto fieldValue = field->
getPtr<glm::dvec4>(component);
377 auto defaultFieldValue = field->
getPtr<glm::dvec4>(defaultComponent);
379 writeVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
380 }
else if (fieldType == TypeDatabase::getType<glm::mat4>()) {
381 auto fieldValue = field->
getPtr<glm::mat4>(component);
382 auto defaultFieldValue = field->
getPtr<glm::mat4>(defaultComponent);
384 writeMat(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
385 }
else if (fieldType == TypeDatabase::getType<std::string>()) {
386 auto name = *field->
getPtr<std::string>(component);
387 writeString(compValue, fieldHeader, name,
"", a);
389 auto names = field->
getPtr<std::vector<std::string>>(component);
390 if (!names->empty()) {
391 Value fieldValues(kArrayType);
392 for (
auto& entry : *names) {
393 fieldValues.PushBack(rapidjson::StringRef(entry.data()), a);
396 compValue.AddMember(rapidjson::StringRef(fieldHeader.c_str()), fieldValues, a);
398 }
else if (fieldType == TypeDatabase::getType<AssetHandle>()) {
399 auto resourceName = getResourceName(context, field->
getPtr<
AssetHandle>(component), sc ? &sc->assets :
nullptr);
401 writeString(compValue, fieldHeader, resourceName,
"", a);
402 }
else if (fieldType == TypeDatabase::getType<ModelHandle>()) {
403 auto resourceName = getResourceName(context, field->
getPtr<
ModelHandle>(component), sc ? &sc->models :
nullptr);
405 writeString(compValue, fieldHeader, resourceName,
"", a);
406 }
else if (fieldType == TypeDatabase::getType<MeshHandle>()) {
407 auto resourceName = getResourceName(context, field->
getPtr<
MeshHandle>(component), sc ? &sc->meshes :
nullptr);
409 writeString(compValue, fieldHeader, resourceName,
"", a);
410 }
else if (fieldType == TypeDatabase::getType<TextureHandle>()) {
411 auto resourceName = getResourceName(context, field->
getPtr<
TextureHandle>(component), sc ? &sc->textures :
nullptr);
413 writeString(compValue, fieldHeader, resourceName,
"", a);
414 }
else if (fieldType == TypeDatabase::getType<MaterialInstanceHandle>()) {
417 writeString(compValue, fieldHeader, resourceName,
"", a);
418 }
else if (fieldType == TypeDatabase::getType<MaterialInstanceHandle>()) {
421 writeString(compValue, fieldHeader, resourceName,
"", a);
425 auto fieldValue = field->
getPtr<std::vector<glm::vec4>>(component);
426 auto defaultFieldValue = field->
getPtr<std::vector<glm::vec4>>(defaultComponent);
428 writeVectorVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
433 auto fieldValue = field->
getPtr<std::vector<glm::vec3>>(component);
434 auto defaultFieldValue = field->
getPtr<std::vector<glm::vec3>>(defaultComponent);
436 writeVectorVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
440 auto fieldValue = field->
getPtr<std::vector<glm::vec2>>(component);
441 auto defaultFieldValue = field->
getPtr<std::vector<glm::vec2>>(defaultComponent);
443 writeVectorVec(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
447 auto fieldValue = field->
getPtr<std::vector<int>>(component);
448 auto defaultFieldValue = field->
getPtr<std::vector<int>>(defaultComponent);
450 writeVectorInt(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
455 auto fieldValue = field->
getPtr<std::vector<float>>(component);
456 auto defaultFieldValue = field->
getPtr<std::vector<float>>(defaultComponent);
458 writeVectorDouble(compValue, fieldHeader, *fieldValue, *defaultFieldValue, a);
464 else if (fieldType == TypeDatabase::getType<EntityPtr>()) {
468 const std::string& name = fieldValue->getName();
470 LOG_WARNING(logger,
"Link to unnamed entity unsupported: Component: %s, Field: %s", type->getName().c_str(), fieldName.c_str());
473 writeString(compValue, fieldHeader,
"$" + name,
"", a);
477 else if (fieldType == TypeDatabase::getType<WeakEntityPtr>()) {
481 const std::string& name = fieldValue->getName();
483 LOG_WARNING(logger,
"Link to unnamed entity unsupported: Component: %s, Field: %s", type->getName().c_str(), fieldName.c_str());
486 writeString(compValue, fieldHeader,
"$" + name,
"", a);
492 LOG_WARNING(logger,
"Unsupported Field data type:%s, Component: %s, Field: %s",
493 fieldType.getName().c_str(), type->getName().c_str(), fieldName.c_str());
497 type = type->getBase();
501 entityValue.AddMember(Value(typeName.c_str(), a), compValue, a);
506 LOG_DEBUG(logger,
"Skipping children of ModelComponent");
508 else if (sceneComponent && sceneComponent->children.size()) {
509 Value childrenValue(kArrayType);
511 for (
auto & child : sceneComponent->children) {
512 Value childValue(kObjectType);
514 if ((flags & AssetWriteFlags::Hierarchy) == AssetWriteFlags::Hierarchy || context->
store->
hasEntityOwnership(child->getId())) {
515 writeEntity(context, child.get(), childValue, d, sc, flags);
517 childrenValue.PushBack(childValue, a);
521 entityValue.AddMember(
"children", childrenValue, a);
530 writeEntity(context, entity, d, d,
nullptr, flags);
Container for components, providing composition of dynamic entities.
T * getComponent() const
Get a pointer to the first component implementing the given type in the entity.
void getComponents(ComponentCollection< T > &collection) const
Get all the components implementing the templated type.
const std::string & getName() const noexcept
Get the name of this entity.
constexpr void * getUserData() const noexcept
Get user data.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
class EntityStore * store
Entity store.
const EntityDefinition * getEntityDefinition(const StringView &name) const
Fetch the entity definition with the given name from the store.
bool hasEntityOwnership(const EntityId entityId) const
Check if the given entityId has global ownership in EntityStore.
Contains information on how the entity behaves in the scene.
Log implementation class.
Field definition describing a single data member of a data structure.
const Name & getName() const
Get the name of the field.
FieldFlags getFlags() const
Get the field flags.
TypeId getTypeId() const
Get the type id of the field.
FieldValueType * getPtr(void *container) const
Get a pointer to this field on the given container.
static T * createInstance(const StringView &name)
Create an instance of the type with the given name.
static const Type & getType()
Get the Type of the given template argument.
constexpr const Name & getName() const
Get the unique name of the type.
Provides a weakly referenced view over the contents of a string.
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
std::weak_ptr< ComponentModel::Entity > WeakEntityPtr
Weak Smart pointer for Entity access.
AssetWriteFlags
Flags that control serialization of assets.
void COGSCORE_DLL_API writeEntity(Context *context, ComponentModel::Entity *entity, rapidjson::Value &object, rapidjson::Document &d, SerializationContext *sc=nullptr, const AssetWriteFlags flags=AssetWriteFlags::None)
Serialize entity adding entity to the given parent 'object'.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains reflection support.
@ NoSerialize
Skip Serialize field.
Holds extra housekeeping data for an Entity instance.
Defines how to construct entities of a certain type by a list of components to instantiate and defaul...
Contains a model reference to instance as children to the entity the ModelComponent belongs to.
const std::string & getName() const
Get the string name. This can be empty, even in valid instances of Name.