| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #include "Scene/BsPrefab.h"
- #include "RTTI/BsPrefabRTTI.h"
- #include "Resources/BsResources.h"
- #include "Scene/BsSceneObject.h"
- #include "Scene/BsPrefabUtility.h"
- #include "BsCoreApplication.h"
- namespace bs
- {
- Prefab::Prefab()
- :Resource(false), mHash(0), mIsScene(true)
- {
-
- }
- Prefab::~Prefab()
- {
- if (mRoot != nullptr)
- mRoot->destroy(true);
- }
- HPrefab Prefab::create(const HSceneObject& sceneObject, bool isScene)
- {
- SPtr<Prefab> newPrefab = createEmpty();
- newPrefab->mIsScene = isScene;
- PrefabUtility::clearPrefabIds(sceneObject, true, false);
- newPrefab->initialize(sceneObject);
- HPrefab handle = static_resource_cast<Prefab>(gResources()._createResourceHandle(newPrefab));
- newPrefab->mUUID = handle.getUUID();
- sceneObject->mPrefabLinkUUID = newPrefab->mUUID;
- newPrefab->_getRoot()->mPrefabLinkUUID = newPrefab->mUUID;
- return handle;
- }
- SPtr<Prefab> Prefab::createEmpty()
- {
- SPtr<Prefab> newPrefab = bs_core_ptr<Prefab>(new (bs_alloc<Prefab>()) Prefab());
- newPrefab->_setThisPtr(newPrefab);
- return newPrefab;
- }
- void Prefab::initialize(const HSceneObject& sceneObject)
- {
- sceneObject->mPrefabDiff = nullptr;
- PrefabUtility::generatePrefabIds(sceneObject);
- // If there are any child prefab instances, make sure to update their diffs so they are saved with this prefab
- Stack<HSceneObject> todo;
- todo.push(sceneObject);
- while (!todo.empty())
- {
- HSceneObject current = todo.top();
- todo.pop();
- UINT32 childCount = current->getNumChildren();
- for (UINT32 i = 0; i < childCount; i++)
- {
- HSceneObject child = current->getChild(i);
- if (!child->mPrefabLinkUUID.empty())
- PrefabUtility::recordPrefabDiff(child);
- else
- todo.push(child);
- }
- }
- // Clone the hierarchy for internal storage
- if (mRoot != nullptr)
- mRoot->destroy(true);
- mRoot = sceneObject->clone(false);
- mRoot->mParent = nullptr;
- mRoot->mLinkId = -1;
- // Remove objects with "dont save" flag
- todo.push(mRoot);
- while (!todo.empty())
- {
- HSceneObject current = todo.top();
- todo.pop();
- if (current->hasFlag(SOF_DontSave))
- current->destroy();
- else
- {
- UINT32 numChildren = current->getNumChildren();
- for (UINT32 i = 0; i < numChildren; i++)
- todo.push(current->getChild(i));
- }
- }
- }
- void Prefab::update(const HSceneObject& sceneObject)
- {
- initialize(sceneObject);
- sceneObject->mPrefabLinkUUID = mUUID;
- mRoot->mPrefabLinkUUID = mUUID;
- mHash++;
- }
- void Prefab::_updateChildInstances()
- {
- Stack<HSceneObject> todo;
- todo.push(mRoot);
- while (!todo.empty())
- {
- HSceneObject current = todo.top();
- todo.pop();
- UINT32 childCount = current->getNumChildren();
- for (UINT32 i = 0; i < childCount; i++)
- {
- HSceneObject child = current->getChild(i);
- if (!child->mPrefabLinkUUID.empty())
- PrefabUtility::updateFromPrefab(child);
- else
- todo.push(child);
- }
- }
- }
- HSceneObject Prefab::instantiate()
- {
- if (mRoot == nullptr)
- return HSceneObject();
- #if BS_EDITOR_BUILD
- if (gCoreApplication().isEditor())
- {
- // Update any child prefab instances in case their prefabs changed
- _updateChildInstances();
- }
- #endif
- HSceneObject clone = _clone();
- clone->_instantiate();
-
- return clone;
- }
- HSceneObject Prefab::_clone()
- {
- if (mRoot == nullptr)
- return HSceneObject();
- mRoot->mPrefabHash = mHash;
- mRoot->mLinkId = -1;
- return mRoot->clone(false);
- }
- RTTITypeBase* Prefab::getRTTIStatic()
- {
- return PrefabRTTI::instance();
- }
- RTTITypeBase* Prefab::getRTTI() const
- {
- return Prefab::getRTTIStatic();
- }
- }
|