| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- #include "BsGameObjectManager.h"
- #include "BsGameObject.h"
- namespace BansheeEngine
- {
- GameObjectManager::GameObjectManager()
- :mNextAvailableID(1), mIsDeserializationActive(false), mGODeserializationMode(GODM_UseNewIds | GODM_BreakExternal)
- {
- }
- GameObjectManager::~GameObjectManager()
- {
- destroyQueuedObjects();
- }
- GameObjectHandleBase GameObjectManager::getObject(UINT64 id) const
- {
- auto iterFind = mObjects.find(id);
- if (iterFind != mObjects.end())
- return iterFind->second;
- return nullptr;
- }
- bool GameObjectManager::tryGetObject(UINT64 id, GameObjectHandleBase& object) const
- {
- auto iterFind = mObjects.find(id);
- if (iterFind != mObjects.end())
- {
- object = iterFind->second;
- return true;
- }
- return false;
- }
- bool GameObjectManager::objectExists(UINT64 id) const
- {
- return mObjects.find(id) != mObjects.end();
- }
- void GameObjectManager::remapId(UINT64 oldId, UINT64 newId)
- {
- if (oldId == newId)
- return;
- mObjects[newId] = mObjects[oldId];
- mObjects.erase(oldId);
- }
- void GameObjectManager::queueForDestroy(const GameObjectHandleBase& object)
- {
- if (object.isDestroyed())
- return;
- UINT64 instanceId = object->getInstanceId();
- mQueuedForDestroy[instanceId] = object;
- }
- void GameObjectManager::destroyQueuedObjects()
- {
- for (auto& objPair : mQueuedForDestroy)
- objPair.second->destroyInternal(objPair.second, true);
- mQueuedForDestroy.clear();
- }
- GameObjectHandleBase GameObjectManager::registerObject(const std::shared_ptr<GameObject>& object, UINT64 originalId)
- {
- object->initialize(object, mNextAvailableID);
- // If deserialization is active we must ensure all handles pointing to the same object share GameObjectHandleData,
- // so check if any handles referencing this object have been created. See ::registerUnresolvedHandle for
- // further explanation.
- if (mIsDeserializationActive)
- {
- assert(originalId != 0 && "You must provide an original ID when registering a deserialized game object.");
- auto iterFind = mUnresolvedHandleData.find(originalId);
- if (iterFind != mUnresolvedHandleData.end())
- {
- GameObjectHandleBase handle;
- handle.mData = iterFind->second;
- handle._setHandleData(object);
- mObjects[mNextAvailableID] = handle;
- mIdMapping[originalId] = mNextAvailableID;
- mNextAvailableID++;
- return handle;
- }
- else
- {
- GameObjectHandleBase handle(object);
- mObjects[mNextAvailableID] = handle;
- mIdMapping[originalId] = mNextAvailableID;
- mNextAvailableID++;
- return handle;
- }
- }
- GameObjectHandleBase handle(object);
- mObjects[mNextAvailableID] = handle;
- mNextAvailableID++;
- return handle;
- }
- void GameObjectManager::unregisterObject(GameObjectHandleBase& object)
- {
- mObjects.erase(object->getInstanceId());
- onDestroyed(object);
- object.destroy();
- }
- void GameObjectManager::startDeserialization()
- {
- assert(!mIsDeserializationActive);
- mIsDeserializationActive = true;
- }
- void GameObjectManager::endDeserialization()
- {
- assert(mIsDeserializationActive);
- for (auto& unresolvedHandle : mUnresolvedHandles)
- resolveDeserializedHandle(unresolvedHandle, mGODeserializationMode);
- for (auto iter = mEndCallbacks.rbegin(); iter != mEndCallbacks.rend(); ++iter)
- {
- (*iter)();
- }
- mIsDeserializationActive = false;
- mActiveDeserializedObject = nullptr;
- mIdMapping.clear();
- mUnresolvedHandles.clear();
- mEndCallbacks.clear();
- mUnresolvedHandleData.clear();
- }
- void GameObjectManager::resolveDeserializedHandle(UnresolvedHandle& data, UINT32 flags)
- {
- assert(mIsDeserializationActive);
- UINT64 instanceId = data.originalInstanceId;
- bool isInternalReference = false;
- auto findIter = mIdMapping.find(instanceId);
- if (findIter != mIdMapping.end())
- {
- if ((flags & GODM_UseNewIds) != 0)
- instanceId = findIter->second;
- isInternalReference = true;
- }
- if (isInternalReference || (!isInternalReference && (flags & GODM_RestoreExternal) != 0))
- {
- auto findIterObj = mObjects.find(instanceId);
- if (findIterObj != mObjects.end())
- data.handle._resolve(findIterObj->second);
- else
- {
- if ((flags & GODM_KeepMissing) == 0)
- data.handle._resolve(nullptr);
- }
- }
- else
- {
- if ((flags & GODM_KeepMissing) == 0)
- data.handle._resolve(nullptr);
- }
- }
- void GameObjectManager::registerUnresolvedHandle(UINT64 originalId, GameObjectHandleBase& object)
- {
- #if BS_DEBUG_MODE
- if (!mIsDeserializationActive)
- {
- BS_EXCEPT(InvalidStateException, "Unresolved handle queue only be modified while deserialization is active.");
- }
- #endif
- // All handles that are deserialized during a single begin/endDeserialization session pointing to the same object
- // must share the same GameObjectHandleData as that makes certain operations in other systems much simpler.
- // Therefore we store all the unresolved handles, and if a handle pointing to the same object was already
- // processed, or that object was already created we replace the handle's internal GameObjectHandleData.
- // Update the provided handle to ensure all handles pointing to the same object share the same handle data
- bool foundHandleData = false;
- // Search object that are currently being deserialized
- auto iterFind = mIdMapping.find(originalId);
- if (iterFind != mIdMapping.end())
- {
- auto iterFind2 = mObjects.find(iterFind->second);
- if (iterFind2 != mObjects.end())
- {
- object.mData = iterFind2->second.mData;
- foundHandleData = true;
- }
- }
- // Search previously deserialized handles
- if (!foundHandleData)
- {
- auto iterFind = mUnresolvedHandleData.find(originalId);
- if (iterFind != mUnresolvedHandleData.end())
- {
- object.mData = iterFind->second;
- foundHandleData = true;
- }
- }
- // If still not found, this is the first such handle so register its handle data
- if (!foundHandleData)
- mUnresolvedHandleData[originalId] = object.mData;
- mUnresolvedHandles.push_back({ originalId, object });
- }
- void GameObjectManager::registerOnDeserializationEndCallback(std::function<void()> callback)
- {
- #if BS_DEBUG_MODE
- if (!mIsDeserializationActive)
- {
- BS_EXCEPT(InvalidStateException, "Callback queue only be modified while deserialization is active.");
- }
- #endif
- mEndCallbacks.push_back(callback);
- }
- void GameObjectManager::setDeserializationMode(UINT32 gameObjectDeserializationMode)
- {
- #if BS_DEBUG_MODE
- if (mIsDeserializationActive)
- {
- BS_EXCEPT(InvalidStateException, "Deserialization modes can not be modified when deserialization is not active.");
- }
- #endif
- mGODeserializationMode = gameObjectDeserializationMode;
- }
- }
|