1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Reflection/BsRTTIType.h"
7#include "Scene/BsGameObject.h"
8#include "Scene/BsSceneObject.h"
9#include "Scene/BsGameObjectManager.h"
10
11namespace bs
12{
13 /** @cond RTTI */
14 /** @addtogroup RTTI-Impl-Core
15 * @{
16 */
17
18 /** Provides temporary storage for data used during GameObject deserialization. */
19 struct GODeserializationData
20 {
21 SPtr<GameObject> ptr;
22 UINT64 originalId = 0;
23 };
24
25 class BS_CORE_EXPORT GameObjectRTTI : public RTTIType<GameObject, IReflectable, GameObjectRTTI>
26 {
27 private:
28 BS_BEGIN_RTTI_MEMBERS
29 BS_RTTI_MEMBER_PLAIN(mName, 1)
30 BS_RTTI_MEMBER_PLAIN(mLinkId, 2)
31 BS_RTTI_MEMBER_PLAIN(mUUID, 3)
32 BS_END_RTTI_MEMBERS
33
34 UINT64& getInstanceID(GameObject* obj) { return obj->mInstanceData->mInstanceId; }
35 void setInstanceID(GameObject* obj, UINT64& instanceId)
36 {
37 // We record the ID for later use. Any child RTTI of GameObject must call GameObjectManager::registerObject
38 // with this ID, so we know how to map deserialized GO handles to live objects, otherwise the handle
39 // references will get broken.
40 GameObject* go = static_cast<GameObject*>(obj);
41 GODeserializationData& deserializationData = any_cast_ref<GODeserializationData>(go->mRTTIData);
42
43 deserializationData.originalId = instanceId;
44 }
45
46 public:
47 GameObjectRTTI()
48 {
49 addPlainField("mInstanceID", 0, &GameObjectRTTI::getInstanceID, &GameObjectRTTI::setInstanceID);
50 }
51
52 void onDeserializationStarted(IReflectable* obj, SerializationContext* context) override
53 {
54 GameObject* gameObject = static_cast<GameObject*>(obj);
55
56 // It's possible we're just accessing the game object fields, in which case the process below is not needed
57 // (it's only required for new game objects).
58 if (gameObject->mRTTIData.empty())
59 return;
60
61 SPtr<GameObject> gameObjectPtr = any_cast<SPtr<GameObject>>(gameObject->mRTTIData);
62
63 // Every GameObject must store GODeserializationData in its RTTI data field during deserialization
64 gameObject->mRTTIData = GODeserializationData();
65 GODeserializationData& deserializationData = any_cast_ref<GODeserializationData>(gameObject->mRTTIData);
66
67 // Store shared pointer since the system only provides us with raw ones
68 deserializationData.ptr = gameObjectPtr;
69 }
70
71 const String& getRTTIName() override
72 {
73 static String name = "GameObject";
74 return name;
75 }
76
77 UINT32 getRTTIId() override
78 {
79 return TID_GameObject;
80 }
81
82 SPtr<IReflectable> newRTTIObject() override
83 {
84 BS_EXCEPT(InternalErrorException, "Cannot instantiate an abstract class.");
85 return nullptr;
86 }
87 };
88
89 /** @} */
90 /** @endcond */
91}