BsCmdBreakPrefab.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include "BsCmdBreakPrefab.h"
  2. #include "BsSceneObject.h"
  3. namespace BansheeEngine
  4. {
  5. CmdBreakPrefab::CmdBreakPrefab(const WString& description, const HSceneObject& sceneObject)
  6. :EditorCommand(description), mSceneObject(sceneObject)
  7. {
  8. }
  9. CmdBreakPrefab::~CmdBreakPrefab()
  10. {
  11. mSceneObject = nullptr;
  12. }
  13. void CmdBreakPrefab::execute(const HSceneObject& sceneObject, const WString& description)
  14. {
  15. // Register command and commit it
  16. CmdBreakPrefab* command = new (bs_alloc<CmdBreakPrefab>()) CmdBreakPrefab(description, sceneObject);
  17. UndoRedo::instance().registerCommand(command);
  18. command->commit();
  19. }
  20. void CmdBreakPrefab::commit()
  21. {
  22. clear();
  23. if (mSceneObject == nullptr || mSceneObject.isDestroyed())
  24. return;
  25. HSceneObject rootObj = mSceneObject;
  26. while (rootObj != nullptr)
  27. {
  28. if (!rootObj->_getPrefabLinkUUID().empty())
  29. return;
  30. if (rootObj->getParent() != nullptr)
  31. rootObj = rootObj->getParent();
  32. else
  33. rootObj = nullptr;
  34. }
  35. if (rootObj != nullptr)
  36. {
  37. mPrefabRoot = rootObj;
  38. mPrefabLinkUUID = rootObj->_getPrefabLinkUUID();
  39. mPrefabDiff = rootObj->_getPrefabDiff();
  40. Stack<HSceneObject> todo;
  41. todo.push(mPrefabRoot);
  42. while (!todo.empty())
  43. {
  44. HSceneObject currentSO = todo.top();
  45. todo.pop();
  46. const Vector<HComponent>& components = currentSO->getComponents();
  47. for (auto& component : components)
  48. {
  49. UINT32 linkId = component->getLinkId();
  50. if (linkId != (UINT32)-1)
  51. mLinkIds[component->getInstanceId()] = linkId;
  52. mLinkIds[component->getInstanceId()] = component->getLinkId();
  53. }
  54. UINT32 numChildren = (UINT32)currentSO->getNumChildren();
  55. for (UINT32 i = 0; i < numChildren; i++)
  56. {
  57. HSceneObject child = currentSO->getChild(i);
  58. UINT32 linkId = child->getLinkId();
  59. if (linkId != (UINT32)-1)
  60. mLinkIds[child->getInstanceId()] = linkId;
  61. if (child->_getPrefabLinkUUID().empty())
  62. todo.push(child);
  63. }
  64. }
  65. }
  66. mSceneObject->breakPrefabLink();
  67. }
  68. void CmdBreakPrefab::revert()
  69. {
  70. if (mPrefabRoot == nullptr || mPrefabRoot.isDestroyed())
  71. return;
  72. mPrefabRoot->_setPrefabLinkUUID(mPrefabLinkUUID);
  73. mPrefabRoot->_setPrefabDiff(mPrefabDiff);
  74. Stack<HSceneObject> todo;
  75. todo.push(mPrefabRoot);
  76. while (!todo.empty())
  77. {
  78. HSceneObject currentSO = todo.top();
  79. todo.pop();
  80. const Vector<HComponent>& components = currentSO->getComponents();
  81. for (auto& component : components)
  82. {
  83. auto iterFind = mLinkIds.find(component->getInstanceId());
  84. if (iterFind != mLinkIds.end())
  85. component->_setLinkId(iterFind->second);
  86. }
  87. UINT32 numChildren = (UINT32)currentSO->getNumChildren();
  88. for (UINT32 i = 0; i < numChildren; i++)
  89. {
  90. HSceneObject child = currentSO->getChild(i);
  91. auto iterFind = mLinkIds.find(child->getInstanceId());
  92. if (iterFind != mLinkIds.end())
  93. child->_setLinkId(iterFind->second);
  94. if (child->_getPrefabLinkUUID().empty())
  95. todo.push(child);
  96. }
  97. }
  98. }
  99. void CmdBreakPrefab::clear()
  100. {
  101. mPrefabRoot = nullptr;
  102. mPrefabLinkUUID = "";
  103. mPrefabDiff = nullptr;
  104. mLinkIds.clear();
  105. }
  106. }