#pragma once #include "BsCorePrerequisites.h" #include "BsRTTIType.h" #include "BsGameObject.h" #include "BsSceneObject.h" #include "BsGameObjectManager.h" namespace BansheeEngine { /** * @brief Provides temporary storage for data used during GameObject deserialization. */ struct GODeserializationData { GODeserializationData() :isDeserializationParent(false), originalId(0) { } GameObjectPtr ptr; bool isDeserializationParent; UINT64 originalId; Any moreData; }; class BS_CORE_EXPORT GameObjectRTTI : public RTTIType { private: String& getName(GameObject* obj) { return obj->mName; } void setName(GameObject* obj, String& name) { obj->mName = name; } UINT64& getInstanceID(GameObject* obj) { return obj->mInstanceData->mInstanceId; } void setInstanceID(GameObject* obj, UINT64& instanceId) { // We record the ID for later use. Any child RTTI of GameObject must call GameObjectManager::registerObject // with this ID, so we know how to map deserialized GO handles to live objects, otherwise the handle // references will get broken. GameObject* go = static_cast(obj); GODeserializationData& deserializationData = any_cast_ref(go->mRTTIData); deserializationData.originalId = instanceId; } UINT32& getLinkId(GameObject* obj) { return obj->mLinkId; } void setLinkId(GameObject* obj, UINT32& linkId) { obj->mLinkId = linkId; } public: /** * @brief Helper method used for creating Component objects used during deserialization. */ template static std::shared_ptr createGameObject() { SPtr component = SceneObject::createEmptyComponent(); // Every GameObject must store GODeserializationData in its RTTI data field during deserialization component->mRTTIData = GODeserializationData(); GODeserializationData& deserializationData = any_cast_ref(component->mRTTIData); // Store shared pointer since the system only provides us with raw ones deserializationData.ptr = component; return component; } public: GameObjectRTTI() { addPlainField("mInstanceID", 0, &GameObjectRTTI::getInstanceID, &GameObjectRTTI::setInstanceID); addPlainField("mName", 1, &GameObjectRTTI::getName, &GameObjectRTTI::setName); addPlainField("mLinkId", 2, &GameObjectRTTI::getLinkId, &GameObjectRTTI::setLinkId); } virtual const String& getRTTIName() override { static String name = "GameObject"; return name; } virtual UINT32 getRTTIId() override { return TID_GameObject; } virtual std::shared_ptr newRTTIObject() override { BS_EXCEPT(InternalErrorException, "Cannot instantiate an abstract class."); } }; }