BsPrefab.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include "BsPrefab.h"
  2. #include "BsPrefabRTTI.h"
  3. #include "BsResources.h"
  4. #include "BsSceneObject.h"
  5. namespace BansheeEngine
  6. {
  7. Prefab::Prefab()
  8. :Resource(false)
  9. {
  10. }
  11. HPrefab Prefab::create(const HSceneObject& sceneObject)
  12. {
  13. assert(sceneObject->mPrefabLink == nullptr);
  14. PrefabPtr newPrefab = createEmpty();
  15. newPrefab->initialize(sceneObject);
  16. HPrefab handle = static_resource_cast<Prefab>(gResources()._createResourceHandle(newPrefab));
  17. sceneObject->mPrefabLink = handle;
  18. return handle;
  19. }
  20. PrefabPtr Prefab::createEmpty()
  21. {
  22. PrefabPtr newPrefab = bs_core_ptr<Prefab, PoolAlloc>(new (bs_alloc<Prefab, PoolAlloc>()) Prefab());
  23. newPrefab->_setThisPtr(newPrefab);
  24. return newPrefab;
  25. }
  26. void Prefab::generatePrefabIds(const HSceneObject& sceneObject)
  27. {
  28. Vector<HGameObject> objectsToId;
  29. Set<INT32> existingIds;
  30. Stack<HSceneObject> todo;
  31. todo.push(sceneObject);
  32. while (!todo.empty())
  33. {
  34. HSceneObject currentSO = todo.top();
  35. todo.pop();
  36. if (currentSO->mLinkId == -1)
  37. objectsToId.push_back(currentSO);
  38. else
  39. existingIds.insert(currentSO->mLinkId);
  40. for (auto& component : currentSO->mComponents)
  41. {
  42. if (component->mLinkId == -1)
  43. objectsToId.push_back(component);
  44. else
  45. existingIds.insert(component->mLinkId);
  46. }
  47. UINT32 numChildren = (UINT32)currentSO->getNumChildren();
  48. for (UINT32 i = 0; i < numChildren; i++)
  49. todo.push(currentSO->getChild(i));
  50. }
  51. auto setIter = existingIds.begin();
  52. INT32 nextId = 0;
  53. for (auto& object : objectsToId)
  54. {
  55. INT32 freeId = -1;
  56. for (; setIter != existingIds.end(); ++setIter)
  57. {
  58. if (nextId < (*setIter))
  59. freeId = nextId++;
  60. else
  61. nextId++;
  62. }
  63. if (freeId == -1)
  64. freeId = nextId++;
  65. object->mLinkId = freeId;
  66. }
  67. }
  68. void Prefab::initialize(const HSceneObject& sceneObject)
  69. {
  70. generatePrefabIds(sceneObject);
  71. sceneObject->setFlags(SOF_DontInstantiate);
  72. mRoot = sceneObject->clone();
  73. sceneObject->unsetFlags(SOF_DontInstantiate);
  74. // Remove objects with "dont save" flag
  75. Stack<HSceneObject> todo;
  76. todo.push(mRoot);
  77. while (!todo.empty())
  78. {
  79. HSceneObject current = todo.top();
  80. todo.pop();
  81. if (current->hasFlag(SOF_DontSave))
  82. current->destroy();
  83. else
  84. {
  85. UINT32 numChildren = current->getNumChildren();
  86. for (UINT32 i = 0; i < numChildren; i++)
  87. todo.push(current->getChild(i));
  88. }
  89. }
  90. }
  91. HSceneObject Prefab::instantiate()
  92. {
  93. if (mRoot == nullptr)
  94. return HSceneObject();
  95. HSceneObject clone = mRoot->clone();
  96. clone->instantiate();
  97. return clone;
  98. }
  99. RTTITypeBase* Prefab::getRTTIStatic()
  100. {
  101. return PrefabRTTI::instance();
  102. }
  103. RTTITypeBase* Prefab::getRTTI() const
  104. {
  105. return Prefab::getRTTIStatic();
  106. }
  107. }