BsPrefab.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Scene/BsPrefab.h"
  4. #include "RTTI/BsPrefabRTTI.h"
  5. #include "Resources/BsResources.h"
  6. #include "Scene/BsSceneObject.h"
  7. #include "Scene/BsPrefabUtility.h"
  8. #include "BsCoreApplication.h"
  9. namespace bs
  10. {
  11. Prefab::Prefab()
  12. :Resource(false), mHash(0), mIsScene(true)
  13. {
  14. }
  15. Prefab::~Prefab()
  16. {
  17. if (mRoot != nullptr)
  18. mRoot->destroy(true);
  19. }
  20. HPrefab Prefab::create(const HSceneObject& sceneObject, bool isScene)
  21. {
  22. SPtr<Prefab> newPrefab = createEmpty();
  23. newPrefab->mIsScene = isScene;
  24. PrefabUtility::clearPrefabIds(sceneObject, true, false);
  25. newPrefab->initialize(sceneObject);
  26. HPrefab handle = static_resource_cast<Prefab>(gResources()._createResourceHandle(newPrefab));
  27. newPrefab->mUUID = handle.getUUID();
  28. sceneObject->mPrefabLinkUUID = newPrefab->mUUID;
  29. newPrefab->_getRoot()->mPrefabLinkUUID = newPrefab->mUUID;
  30. return handle;
  31. }
  32. SPtr<Prefab> Prefab::createEmpty()
  33. {
  34. SPtr<Prefab> newPrefab = bs_core_ptr<Prefab>(new (bs_alloc<Prefab>()) Prefab());
  35. newPrefab->_setThisPtr(newPrefab);
  36. return newPrefab;
  37. }
  38. void Prefab::initialize(const HSceneObject& sceneObject)
  39. {
  40. sceneObject->mPrefabDiff = nullptr;
  41. PrefabUtility::generatePrefabIds(sceneObject);
  42. // If there are any child prefab instances, make sure to update their diffs so they are saved with this prefab
  43. Stack<HSceneObject> todo;
  44. todo.push(sceneObject);
  45. while (!todo.empty())
  46. {
  47. HSceneObject current = todo.top();
  48. todo.pop();
  49. UINT32 childCount = current->getNumChildren();
  50. for (UINT32 i = 0; i < childCount; i++)
  51. {
  52. HSceneObject child = current->getChild(i);
  53. if (!child->mPrefabLinkUUID.empty())
  54. PrefabUtility::recordPrefabDiff(child);
  55. else
  56. todo.push(child);
  57. }
  58. }
  59. // Clone the hierarchy for internal storage
  60. mRoot = sceneObject->clone(false);
  61. mRoot->mParent = nullptr;
  62. mRoot->mLinkId = -1;
  63. // Remove objects with "dont save" flag
  64. todo.push(mRoot);
  65. while (!todo.empty())
  66. {
  67. HSceneObject current = todo.top();
  68. todo.pop();
  69. if (current->hasFlag(SOF_DontSave))
  70. current->destroy();
  71. else
  72. {
  73. UINT32 numChildren = current->getNumChildren();
  74. for (UINT32 i = 0; i < numChildren; i++)
  75. todo.push(current->getChild(i));
  76. }
  77. }
  78. }
  79. void Prefab::update(const HSceneObject& sceneObject)
  80. {
  81. initialize(sceneObject);
  82. sceneObject->mPrefabLinkUUID = mUUID;
  83. mRoot->mPrefabLinkUUID = mUUID;
  84. mHash++;
  85. }
  86. void Prefab::_updateChildInstances()
  87. {
  88. Stack<HSceneObject> todo;
  89. todo.push(mRoot);
  90. while (!todo.empty())
  91. {
  92. HSceneObject current = todo.top();
  93. todo.pop();
  94. UINT32 childCount = current->getNumChildren();
  95. for (UINT32 i = 0; i < childCount; i++)
  96. {
  97. HSceneObject child = current->getChild(i);
  98. if (!child->mPrefabLinkUUID.empty())
  99. PrefabUtility::updateFromPrefab(child);
  100. else
  101. todo.push(child);
  102. }
  103. }
  104. }
  105. HSceneObject Prefab::instantiate()
  106. {
  107. if (mRoot == nullptr)
  108. return HSceneObject();
  109. #if BS_EDITOR_BUILD
  110. if (gCoreApplication().isEditor())
  111. {
  112. // Update any child prefab instances in case their prefabs changed
  113. _updateChildInstances();
  114. }
  115. #endif
  116. HSceneObject clone = _clone();
  117. clone->_instantiate();
  118. return clone;
  119. }
  120. HSceneObject Prefab::_clone()
  121. {
  122. if (mRoot == nullptr)
  123. return HSceneObject();
  124. mRoot->mPrefabHash = mHash;
  125. mRoot->mLinkId = -1;
  126. return mRoot->clone(false);
  127. }
  128. RTTITypeBase* Prefab::getRTTIStatic()
  129. {
  130. return PrefabRTTI::instance();
  131. }
  132. RTTITypeBase* Prefab::getRTTI() const
  133. {
  134. return Prefab::getRTTIStatic();
  135. }
  136. }