BsSceneObjectRTTI.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "Reflection/BsRTTIType.h"
  6. #include "Scene/BsSceneObject.h"
  7. #include "Scene/BsGameObjectHandle.h"
  8. #include "Scene/BsGameObjectManager.h"
  9. #include "Scene/BsComponent.h"
  10. #include "RTTI/BsGameObjectRTTI.h"
  11. #include "Scene/BsPrefabDiff.h"
  12. namespace bs
  13. {
  14. /** @cond RTTI */
  15. /** @addtogroup RTTI-Impl-Core
  16. * @{
  17. */
  18. /** Provides temporary storage for data used during SceneObject deserialization. */
  19. struct SODeserializationData
  20. {
  21. Vector<SPtr<SceneObject>> children;
  22. Vector<SPtr<Component>> components;
  23. };
  24. class BS_CORE_EXPORT SceneObjectRTTI : public RTTIType<SceneObject, GameObject, SceneObjectRTTI>
  25. {
  26. private:
  27. Vector3& getPosition(SceneObject* obj) { return obj->mPosition; }
  28. void setPosition(SceneObject* obj, Vector3& value) { obj->mPosition = value; }
  29. Quaternion& getRotation(SceneObject* obj) { return obj->mRotation; }
  30. void setRotation(SceneObject* obj, Quaternion& value) { obj->mRotation = value; }
  31. Vector3& getScale(SceneObject* obj) { return obj->mScale; }
  32. void setScale(SceneObject* obj, Vector3& value) { obj->mScale = value; }
  33. bool& getActive(SceneObject* obj) { return obj->mActiveSelf; }
  34. void setActive(SceneObject* obj, bool& value) { obj->mActiveSelf = value; }
  35. SPtr<SceneObject> getChild(SceneObject* obj, UINT32 idx) { return obj->mChildren[idx].getInternalPtr(); }
  36. void setChild(SceneObject* obj, UINT32 idx, SPtr<SceneObject> param)
  37. {
  38. SceneObject* so = static_cast<SceneObject*>(obj);
  39. GODeserializationData& goDeserializationData = any_cast_ref<GODeserializationData>(so->mRTTIData);
  40. SODeserializationData& soDeserializationData = any_cast_ref<SODeserializationData>(goDeserializationData.moreData);
  41. // It's important that child indices remain the same after deserialization, as some systems (like SO
  42. // record/restore) depend on it
  43. if(idx >= soDeserializationData.children.size())
  44. soDeserializationData.children.resize(idx + 1);
  45. soDeserializationData.children[idx] = param;
  46. }
  47. UINT32 getNumChildren(SceneObject* obj) { return (UINT32)obj->mChildren.size(); }
  48. void setNumChildren(SceneObject* obj, UINT32 size) { /* DO NOTHING */ }
  49. // NOTE - These can only be set sequentially, specific array index is ignored
  50. SPtr<Component> getComponent(SceneObject* obj, UINT32 idx) { return obj->mComponents[idx].getInternalPtr(); }
  51. void setComponent(SceneObject* obj, UINT32 idx, SPtr<Component> param)
  52. {
  53. SceneObject* so = static_cast<SceneObject*>(obj);
  54. GODeserializationData& goDeserializationData = any_cast_ref<GODeserializationData>(so->mRTTIData);
  55. SODeserializationData& soDeserializationData = any_cast_ref<SODeserializationData>(goDeserializationData.moreData);
  56. // It's important that child indices remain the same after deserialization, as some systems (like SO
  57. // record/restore) depend on it
  58. if(idx >= soDeserializationData.components.size())
  59. soDeserializationData.components.resize(idx + 1);
  60. soDeserializationData.components[idx] = param;
  61. }
  62. UINT32 getNumComponents(SceneObject* obj) { return (UINT32)obj->mComponents.size(); }
  63. void setNumComponents(SceneObject* obj, UINT32 size) { /* DO NOTHING */ }
  64. String& getPrefabLink(SceneObject* obj) { return obj->mPrefabLinkUUID; }
  65. void setPrefabLink(SceneObject* obj, String& value) { obj->mPrefabLinkUUID = value; }
  66. SPtr<PrefabDiff> getPrefabDiff(SceneObject* obj) { return obj->mPrefabDiff; }
  67. void setPrefabDiff(SceneObject* obj, SPtr<PrefabDiff> value) { obj->mPrefabDiff = value; }
  68. UINT32& getFlags(SceneObject* obj) { return obj->mFlags; }
  69. void setFlags(SceneObject* obj, UINT32& value) { obj->mFlags = value; }
  70. UINT32& getPrefabHash(SceneObject* obj) { return obj->mPrefabHash; }
  71. void setPrefabHash(SceneObject* obj, UINT32& value) { obj->mPrefabHash = value; }
  72. ObjectMobility& getMobility(SceneObject* obj) { return obj->mMobility; }
  73. void setMobility(SceneObject* obj, ObjectMobility& value) { obj->mMobility = value; }
  74. public:
  75. SceneObjectRTTI()
  76. {
  77. addReflectablePtrArrayField("mChildren", 0, &SceneObjectRTTI::getChild,
  78. &SceneObjectRTTI::getNumChildren, &SceneObjectRTTI::setChild, &SceneObjectRTTI::setNumChildren);
  79. addReflectablePtrArrayField("mComponents", 1, &SceneObjectRTTI::getComponent,
  80. &SceneObjectRTTI::getNumComponents, &SceneObjectRTTI::setComponent, &SceneObjectRTTI::setNumComponents);
  81. addPlainField("mPrefabLink", 2, &SceneObjectRTTI::getPrefabLink, &SceneObjectRTTI::setPrefabLink);
  82. addPlainField("mFlags", 3, &SceneObjectRTTI::getFlags, &SceneObjectRTTI::setFlags);
  83. addReflectablePtrField("mPrefabDiff", 4, &SceneObjectRTTI::getPrefabDiff, &SceneObjectRTTI::setPrefabDiff);
  84. addPlainField("mPrefabHash", 5, &SceneObjectRTTI::getPrefabHash, &SceneObjectRTTI::setPrefabHash);
  85. addPlainField("mPosition", 6, &SceneObjectRTTI::getPosition, &SceneObjectRTTI::setPosition);
  86. addPlainField("mRotation", 7, &SceneObjectRTTI::getRotation, &SceneObjectRTTI::setRotation);
  87. addPlainField("mScale", 8, &SceneObjectRTTI::getScale, &SceneObjectRTTI::setScale);
  88. addPlainField("mActiveSelf", 9, &SceneObjectRTTI::getActive, &SceneObjectRTTI::setActive);
  89. addPlainField("mMobility", 10, &SceneObjectRTTI::getMobility, &SceneObjectRTTI::setMobility);
  90. }
  91. void onDeserializationStarted(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
  92. {
  93. // If this is the root scene object we're deserializing, activate game object deserialization so the system
  94. // can resolve deserialized handles to the newly created objects
  95. SceneObject* so = static_cast<SceneObject*>(obj);
  96. // It's possible we're just accessing the game object fields, in which case the process below is not needed
  97. // (it's only required for new scene objects).
  98. if (so->mRTTIData.empty())
  99. return;
  100. // Every GameObject must store GODeserializationData in its RTTI data field during deserialization
  101. GODeserializationData& deserializationData = any_cast_ref<GODeserializationData>(so->mRTTIData);
  102. // We delay adding children/components and instead store them here
  103. deserializationData.moreData = SODeserializationData();
  104. if (!GameObjectManager::instance().isGameObjectDeserializationActive())
  105. {
  106. GameObjectManager::instance().startDeserialization();
  107. // Mark it as the object that started the GO deserialization so it knows to end it
  108. deserializationData.isDeserializationParent = true;
  109. }
  110. else
  111. deserializationData.isDeserializationParent = false;
  112. }
  113. void onDeserializationEnded(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
  114. {
  115. SceneObject* so = static_cast<SceneObject*>(obj);
  116. // It's possible we're just accessing the game object fields, in which case the process below is not needed
  117. // (it's only required for new scene objects).
  118. if (so->mRTTIData.empty())
  119. return;
  120. GODeserializationData& goDeserializationData = any_cast_ref<GODeserializationData>(so->mRTTIData);
  121. // Register the newly created SO with the GameObjectManager and provide it with the original ID so that
  122. // deserialized handles pointing to this object can be resolved.
  123. SPtr<SceneObject> soPtr = std::static_pointer_cast<SceneObject>(goDeserializationData.ptr);
  124. SceneObject::createInternal(soPtr, goDeserializationData.originalId);
  125. // We stored all components and children in a temporary structure because they rely on the SceneObject being
  126. // initialized with the GameObjectManager. Now that it is, we add them.
  127. SODeserializationData& soDeserializationData = any_cast_ref<SODeserializationData>(goDeserializationData.moreData);
  128. for (auto& component : soDeserializationData.components)
  129. so->addComponentInternal(component);
  130. for (auto& child : soDeserializationData.children)
  131. {
  132. if(child != nullptr)
  133. child->_setParent(so->mThisHandle, false);
  134. }
  135. // If this is the deserialization parent, end deserialization (which resolves all game object handles, if we
  136. // provided valid IDs), and instantiate (i.e. activate) the deserialized hierarchy.
  137. if (goDeserializationData.isDeserializationParent)
  138. {
  139. GameObjectManager::instance().endDeserialization();
  140. bool parentActive = true;
  141. if (so->getParent() != nullptr)
  142. parentActive = so->getParent()->getActive();
  143. so->setActiveHierarchy(parentActive, false);
  144. if ((so->mFlags & SOF_DontInstantiate) == 0)
  145. so->_instantiate();
  146. }
  147. so->mRTTIData = nullptr;
  148. }
  149. const String& getRTTIName() override
  150. {
  151. static String name = "SceneObject";
  152. return name;
  153. }
  154. UINT32 getRTTIId() override
  155. {
  156. return TID_SceneObject;
  157. }
  158. SPtr<IReflectable> newRTTIObject() override
  159. {
  160. SPtr<SceneObject> sceneObject = SPtr<SceneObject>(new (bs_alloc<SceneObject>()) SceneObject("", SOF_DontInstantiate),
  161. &bs_delete<SceneObject>, StdAlloc<SceneObject>());
  162. sceneObject->mRTTIData = sceneObject;
  163. return sceneObject;
  164. }
  165. };
  166. /** @} */
  167. /** @endcond */
  168. }