BsScriptSerializableObjectRTTI.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #pragma once
  2. #include "BsScriptEnginePrerequisites.h"
  3. #include "CmRTTIType.h"
  4. #include "BsRuntimeScriptObjects.h"
  5. #include "BsScriptSerializableObject.h"
  6. #include "BsScriptSerializableField.h"
  7. #include "BsMonoClass.h"
  8. namespace BansheeEngine
  9. {
  10. class BS_SCR_BE_EXPORT ScriptSerializableObjectRTTI : public CM::RTTIType<ScriptSerializableObject, CM::IReflectable, ScriptSerializableObjectRTTI>
  11. {
  12. private:
  13. ScriptSerializableObjectInfoPtr getInfo(ScriptSerializableObject* obj)
  14. {
  15. return obj->mObjInfo;
  16. }
  17. void setInfo(ScriptSerializableObject* obj, ScriptSerializableObjectInfoPtr val)
  18. {
  19. obj->mObjInfo = val;
  20. }
  21. ScriptSerializableFieldDataEntryPtr getFieldEntry(ScriptSerializableObject* obj, CM::UINT32 arrayIdx)
  22. {
  23. return obj->mFieldEntries[arrayIdx];
  24. }
  25. void setFieldsEntry(ScriptSerializableObject* obj, CM::UINT32 arrayIdx, ScriptSerializableFieldDataEntryPtr val)
  26. {
  27. obj->mFieldEntries[arrayIdx] = val;
  28. }
  29. CM::UINT32 getNumFieldEntries(ScriptSerializableObject* obj)
  30. {
  31. return (CM::UINT32)obj->mFieldEntries.size();
  32. }
  33. void setNumFieldEntries(ScriptSerializableObject* obj, CM::UINT32 numEntries)
  34. {
  35. obj->mFieldEntries.resize(numEntries);
  36. }
  37. public:
  38. ScriptSerializableObjectRTTI()
  39. {
  40. addReflectablePtrField("mObjInfo", 0, &ScriptSerializableObjectRTTI::getInfo, &ScriptSerializableObjectRTTI::setInfo);
  41. addReflectablePtrArrayField("mFieldEntries", 1, &ScriptSerializableObjectRTTI::getFieldEntry, &ScriptSerializableObjectRTTI::getNumFieldEntries,
  42. &ScriptSerializableObjectRTTI::setFieldsEntry, &ScriptSerializableObjectRTTI::setNumFieldEntries);
  43. }
  44. virtual void onDeserializationEnded(CM::IReflectable* obj)
  45. {
  46. ScriptSerializableObject* serializableObject = static_cast<ScriptSerializableObject*>(obj);
  47. ScriptSerializableObjectInfoPtr storedObjInfo = serializableObject->getObjectInfo();
  48. ScriptSerializableObjectInfoPtr currentObjInfo = nullptr;
  49. // See if this type even still exists
  50. if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(storedObjInfo->mTypeInfo->mTypeNamespace, storedObjInfo->mTypeInfo->mTypeName, currentObjInfo))
  51. return;
  52. serializableObject->mManagedInstance = currentObjInfo->mMonoClass->createInstance();
  53. auto findFieldInfoFromKey = [&] (CM::UINT16 typeId, CM::UINT16 fieldId, ScriptSerializableObjectInfoPtr objInfo,
  54. ScriptSerializableFieldInfoPtr& outFieldInfo, ScriptSerializableObjectInfoPtr &outObjInfo) -> bool
  55. {
  56. while(objInfo != nullptr)
  57. {
  58. if(objInfo->mTypeId == typeId)
  59. {
  60. auto iterFind = objInfo->mFields.find(fieldId);
  61. if(iterFind != objInfo->mFields.end())
  62. {
  63. outFieldInfo = iterFind->second;
  64. outObjInfo = objInfo;
  65. return true;
  66. }
  67. return false;
  68. }
  69. objInfo = objInfo->mBaseClass;
  70. }
  71. return false;
  72. };
  73. auto findTypeNameMatchingFieldInfo = [&] (const ScriptSerializableFieldInfoPtr& fieldInfo, const ScriptSerializableObjectInfoPtr& fieldObjInfo,
  74. ScriptSerializableObjectInfoPtr objInfo) -> ScriptSerializableFieldInfoPtr
  75. {
  76. while(objInfo != nullptr)
  77. {
  78. if(objInfo->mTypeInfo->matches(fieldObjInfo->mTypeInfo))
  79. {
  80. auto iterFind = objInfo->mFieldNameToId.find(fieldInfo->mName);
  81. if(iterFind != objInfo->mFieldNameToId.end())
  82. {
  83. auto iterFind2 = objInfo->mFields.find(iterFind->second);
  84. if(iterFind2 != objInfo->mFields.end())
  85. {
  86. ScriptSerializableFieldInfoPtr foundField = iterFind2->second;
  87. if(foundField->isSerializable())
  88. {
  89. if(fieldInfo->mTypeInfo->matches(foundField->mTypeInfo))
  90. return foundField;
  91. }
  92. }
  93. }
  94. return nullptr;
  95. }
  96. objInfo = objInfo->mBaseClass;
  97. }
  98. return nullptr;
  99. };
  100. // Scan all fields and ensure the fields still exist
  101. for(auto& fieldEntry : serializableObject->mFieldEntries)
  102. {
  103. ScriptSerializableFieldInfoPtr storedFieldEntry;
  104. ScriptSerializableObjectInfoPtr storedFieldObjEntry;
  105. if(!findFieldInfoFromKey(fieldEntry->mKey->mTypeId, fieldEntry->mKey->mFieldId, storedObjInfo, storedFieldEntry, storedFieldObjEntry))
  106. continue;
  107. ScriptSerializableFieldInfoPtr matchingFieldInfo = findTypeNameMatchingFieldInfo(storedFieldEntry, storedFieldObjEntry, currentObjInfo);
  108. if(matchingFieldInfo != nullptr)
  109. serializableObject->setFieldData(matchingFieldInfo, fieldEntry->mValue);
  110. }
  111. }
  112. virtual const CM::String& getRTTIName()
  113. {
  114. static CM::String name = "ScriptSerializableObject";
  115. return name;
  116. }
  117. virtual CM::UINT32 getRTTIId()
  118. {
  119. return TID_ScriptSerializableObject;
  120. }
  121. virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
  122. {
  123. return ScriptSerializableObject::createEmpty();
  124. }
  125. };
  126. }