BsScriptSerializableObject.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #include "BsScriptSerializableObject.h"
  2. #include "BsScriptSerializableObjectRTTI.h"
  3. #include "BsScriptSerializableObjectInfo.h"
  4. #include "BsScriptSerializableField.h"
  5. #include "BsRuntimeScriptObjects.h"
  6. #include "BsMonoField.h"
  7. using namespace CamelotFramework;
  8. namespace BansheeEngine
  9. {
  10. ScriptSerializableObject::ScriptSerializableObject(const ConstructPrivately& dummy)
  11. :mManagedInstance(nullptr)
  12. {
  13. }
  14. ScriptSerializableObject::ScriptSerializableObject(const ConstructPrivately& dummy, ScriptSerializableObjectInfoPtr objInfo, MonoObject* managedInstance)
  15. :mObjInfo(objInfo), mManagedInstance(managedInstance)
  16. {
  17. }
  18. ScriptSerializableObjectPtr ScriptSerializableObject::create(MonoObject* managedInstance)
  19. {
  20. if(managedInstance == nullptr)
  21. return nullptr;
  22. ::MonoClass* monoClass = mono_object_get_class(managedInstance);
  23. String elementNs = mono_class_get_namespace(monoClass);
  24. String elementTypeName = mono_class_get_name(monoClass);
  25. ScriptSerializableObjectInfoPtr objInfo;
  26. if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo))
  27. return nullptr;
  28. return cm_shared_ptr<ScriptSerializableObject>(ConstructPrivately(), objInfo, managedInstance);
  29. }
  30. ScriptSerializableObjectPtr ScriptSerializableObject::createEmpty()
  31. {
  32. return cm_shared_ptr<ScriptSerializableObject>(ConstructPrivately());
  33. }
  34. void ScriptSerializableObject::serializeManagedInstance()
  35. {
  36. ScriptSerializableObjectInfoPtr curType = mObjInfo;
  37. UINT32 numFields = 0;
  38. while(curType != nullptr)
  39. {
  40. for(auto& field : mObjInfo->mFields)
  41. {
  42. if(field.second->isSerializable())
  43. numFields++;
  44. }
  45. curType = curType->mBaseClass;
  46. }
  47. mFieldEntries.resize(numFields);
  48. curType = mObjInfo;
  49. UINT32 curIdx = 0;
  50. while(curType != nullptr)
  51. {
  52. for(auto& field : mObjInfo->mFields)
  53. {
  54. if(!field.second->isSerializable())
  55. continue;
  56. ScriptSerializableFieldKeyPtr fieldKey = ScriptSerializableFieldKey::create(curType->mTypeId, field.second->mFieldId);
  57. ScriptSerializableFieldDataPtr fieldData = getFieldData(field.second);
  58. mFieldEntries[curIdx] = ScriptSerializableFieldDataEntry::create(fieldKey, fieldData);
  59. curIdx++;
  60. }
  61. curType = curType->mBaseClass;
  62. }
  63. }
  64. void ScriptSerializableObject::deserializeManagedInstance()
  65. {
  66. ScriptSerializableObjectInfoPtr storedObjInfo = mObjInfo;
  67. ScriptSerializableObjectInfoPtr currentObjInfo = nullptr;
  68. // See if this type even still exists
  69. if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(storedObjInfo->mTypeInfo->mTypeNamespace, storedObjInfo->mTypeInfo->mTypeName, currentObjInfo))
  70. return;
  71. if(storedObjInfo->mTypeInfo->mValueType)
  72. mManagedInstance = currentObjInfo->mMonoClass->createInstance(false);
  73. else
  74. mManagedInstance = currentObjInfo->mMonoClass->createInstance();
  75. auto findFieldInfoFromKey = [&] (CM::UINT16 typeId, CM::UINT16 fieldId, ScriptSerializableObjectInfoPtr objInfo,
  76. ScriptSerializableFieldInfoPtr& outFieldInfo, ScriptSerializableObjectInfoPtr &outObjInfo) -> bool
  77. {
  78. while(objInfo != nullptr)
  79. {
  80. if(objInfo->mTypeId == typeId)
  81. {
  82. auto iterFind = objInfo->mFields.find(fieldId);
  83. if(iterFind != objInfo->mFields.end())
  84. {
  85. outFieldInfo = iterFind->second;
  86. outObjInfo = objInfo;
  87. return true;
  88. }
  89. return false;
  90. }
  91. objInfo = objInfo->mBaseClass;
  92. }
  93. return false;
  94. };
  95. auto findTypeNameMatchingFieldInfo = [&] (const ScriptSerializableFieldInfoPtr& fieldInfo, const ScriptSerializableObjectInfoPtr& fieldObjInfo,
  96. ScriptSerializableObjectInfoPtr objInfo) -> ScriptSerializableFieldInfoPtr
  97. {
  98. while(objInfo != nullptr)
  99. {
  100. if(objInfo->mTypeInfo->matches(fieldObjInfo->mTypeInfo))
  101. {
  102. auto iterFind = objInfo->mFieldNameToId.find(fieldInfo->mName);
  103. if(iterFind != objInfo->mFieldNameToId.end())
  104. {
  105. auto iterFind2 = objInfo->mFields.find(iterFind->second);
  106. if(iterFind2 != objInfo->mFields.end())
  107. {
  108. ScriptSerializableFieldInfoPtr foundField = iterFind2->second;
  109. if(foundField->isSerializable())
  110. {
  111. if(fieldInfo->mTypeInfo->matches(foundField->mTypeInfo))
  112. return foundField;
  113. }
  114. }
  115. }
  116. return nullptr;
  117. }
  118. objInfo = objInfo->mBaseClass;
  119. }
  120. return nullptr;
  121. };
  122. // Scan all fields and ensure the fields still exist
  123. for(auto& fieldEntry : mFieldEntries)
  124. {
  125. ScriptSerializableFieldInfoPtr storedFieldEntry;
  126. ScriptSerializableObjectInfoPtr storedFieldObjEntry;
  127. if(!findFieldInfoFromKey(fieldEntry->mKey->mTypeId, fieldEntry->mKey->mFieldId, storedObjInfo, storedFieldEntry, storedFieldObjEntry))
  128. continue;
  129. ScriptSerializableFieldInfoPtr matchingFieldInfo = findTypeNameMatchingFieldInfo(storedFieldEntry, storedFieldObjEntry, currentObjInfo);
  130. if(matchingFieldInfo != nullptr)
  131. setFieldData(matchingFieldInfo, fieldEntry->mValue);
  132. }
  133. }
  134. void ScriptSerializableObject::setFieldData(const ScriptSerializableFieldInfoPtr& fieldInfo, const ScriptSerializableFieldDataPtr& val)
  135. {
  136. fieldInfo->mMonoField->setValue(mManagedInstance, val->getValue(fieldInfo->mTypeInfo));
  137. }
  138. ScriptSerializableFieldDataPtr ScriptSerializableObject::getFieldData(const ScriptSerializableFieldInfoPtr& fieldInfo)
  139. {
  140. MonoObject* fieldValue = fieldInfo->mMonoField->getValueBoxed(mManagedInstance);
  141. return ScriptSerializableFieldData::create(fieldInfo->mTypeInfo, fieldValue);
  142. }
  143. RTTITypeBase* ScriptSerializableObject::getRTTIStatic()
  144. {
  145. return ScriptSerializableObjectRTTI::instance();
  146. }
  147. RTTITypeBase* ScriptSerializableObject::getRTTI() const
  148. {
  149. return ScriptSerializableObject::getRTTIStatic();
  150. }
  151. }