2
0

BsScriptSerializableObject.cpp 5.7 KB

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