BsPrefab.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. }
  48. auto setIter = existingIds.begin();
  49. INT32 nextId = 0;
  50. for (auto& object : objectsToId)
  51. {
  52. INT32 freeId = -1;
  53. for (; setIter != existingIds.end(); ++setIter)
  54. {
  55. if (nextId < (*setIter))
  56. freeId = nextId++;
  57. else
  58. nextId++;
  59. }
  60. if (freeId == -1)
  61. freeId = nextId++;
  62. object->mLinkId = freeId;
  63. }
  64. }
  65. void Prefab::initialize(const HSceneObject& sceneObject)
  66. {
  67. generatePrefabIds(sceneObject);
  68. sceneObject->setFlags(SOF_DontInstantiate);
  69. mRoot = sceneObject->clone();
  70. sceneObject->unsetFlags(SOF_DontInstantiate);
  71. // Remove objects with "dont save" flag
  72. Stack<HSceneObject> todo;
  73. todo.push(mRoot);
  74. while (!todo.empty())
  75. {
  76. HSceneObject current = todo.top();
  77. todo.pop();
  78. if (current->hasFlag(SOF_DontSave))
  79. current->destroy();
  80. else
  81. {
  82. UINT32 numChildren = current->getNumChildren();
  83. for (UINT32 i = 0; i < numChildren; i++)
  84. todo.push(current->getChild(i));
  85. }
  86. }
  87. }
  88. HSceneObject Prefab::instantiate()
  89. {
  90. if (mRoot == nullptr)
  91. return HSceneObject();
  92. HSceneObject clone = mRoot->clone();
  93. clone->instantiate();
  94. return clone;
  95. }
  96. RTTITypeBase* Prefab::getRTTIStatic()
  97. {
  98. return PrefabRTTI::instance();
  99. }
  100. RTTITypeBase* Prefab::getRTTI() const
  101. {
  102. return Prefab::getRTTIStatic();
  103. }
  104. }