BsEditorUtility.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Utility/BsEditorUtility.h"
  4. #include "Scene/BsSceneObject.h"
  5. #include "Components/BsCRenderable.h"
  6. namespace bs
  7. {
  8. AABox EditorUtility::calculateBounds(const HSceneObject& object)
  9. {
  10. Vector<HSceneObject> objects = { object };
  11. return calculateBounds(objects);
  12. }
  13. AABox EditorUtility::calculateBounds(const Vector<HSceneObject>& objects)
  14. {
  15. if (objects.size() == 0)
  16. return AABox(Vector3::ZERO, Vector3::ZERO);
  17. AABox bounds = AABox(Vector3::INF, -Vector3::INF);
  18. bool gotOneMesh = false;
  19. for (auto& object : objects)
  20. {
  21. AABox meshBounds;
  22. if (calculateMeshBounds(object, meshBounds))
  23. {
  24. bounds.merge(meshBounds);
  25. gotOneMesh = true;
  26. }
  27. }
  28. if (!gotOneMesh)
  29. {
  30. for (auto& object : objects)
  31. {
  32. if (object.isDestroyed())
  33. continue;
  34. bounds.merge(object->getTransform().getPosition());
  35. gotOneMesh = true;
  36. }
  37. }
  38. if(gotOneMesh)
  39. return bounds;
  40. return AABox(Vector3::ZERO, Vector3::ZERO);
  41. }
  42. Vector3 EditorUtility::calculateCenter(const Vector<HSceneObject>& objects)
  43. {
  44. if (objects.size() == 0)
  45. return Vector3::ZERO;
  46. Vector3 center = Vector3::ZERO;
  47. UINT32 count = 0;
  48. for (auto& object : objects)
  49. {
  50. AABox meshBounds;
  51. if (calculateMeshBounds(object, meshBounds))
  52. {
  53. if (meshBounds.getSize() == Vector3::INF)
  54. center += object->getTransform().getPosition();
  55. else
  56. center += meshBounds.getCenter();
  57. count++;
  58. }
  59. }
  60. if (count == 0)
  61. {
  62. for (auto& object : objects)
  63. {
  64. if (object.isDestroyed())
  65. continue;
  66. center += object->getTransform().getPosition();
  67. count++;
  68. }
  69. }
  70. if (count > 0)
  71. return center / (float)count;
  72. return Vector3::ZERO;
  73. }
  74. bool EditorUtility::calculateMeshBounds(const HSceneObject& object, AABox& bounds)
  75. {
  76. bounds = AABox(Vector3::ZERO, Vector3::ZERO);
  77. if (object.isDestroyed())
  78. return false;
  79. bool foundOne = false;
  80. const Vector<HComponent>& components = object->getComponents();
  81. for (auto& component : components)
  82. {
  83. Bounds curBounds;
  84. if (component->calculateBounds(curBounds))
  85. {
  86. if (!foundOne)
  87. {
  88. bounds = curBounds.getBox();
  89. foundOne = true;
  90. }
  91. else
  92. bounds.merge(curBounds.getBox());
  93. }
  94. else
  95. {
  96. if (!foundOne)
  97. bounds = curBounds.getBox();
  98. }
  99. }
  100. return foundOne;
  101. }
  102. EditorUtility::SceneObjProxy EditorUtility::createProxy(const HSceneObject& sceneObject)
  103. {
  104. struct TempData
  105. {
  106. TempData(SceneObjProxy& proxy, const HSceneObject& so)
  107. :proxy(proxy), obj(so)
  108. { }
  109. SceneObjProxy& proxy;
  110. HSceneObject obj;
  111. };
  112. SceneObjProxy rootProxy;
  113. Stack<TempData> todo;
  114. todo.push(TempData(rootProxy, sceneObject));
  115. while (!todo.empty())
  116. {
  117. TempData data = todo.top();
  118. todo.pop();
  119. data.proxy.instanceData = data.obj->_getInstanceData();
  120. const Vector<HComponent>& components = data.obj->getComponents();
  121. for (auto& component : components)
  122. data.proxy.componentInstanceData.push_back(component->_getInstanceData());
  123. UINT32 numChildren = data.obj->getNumChildren();
  124. data.proxy.children.resize(numChildren);
  125. for (UINT32 i = 0; i < numChildren; i++)
  126. {
  127. todo.push(TempData(data.proxy.children[i], data.obj->getChild(i)));
  128. }
  129. }
  130. return rootProxy;
  131. }
  132. void EditorUtility::restoreIds(const HSceneObject& restored, SceneObjProxy& proxy)
  133. {
  134. // Note: This method relies that all restored GameObject handles pointing to the
  135. // same object also have the same shared handle data (Since I only update instance
  136. // data on a single handle I know exists, and expect all others will be updated
  137. // by that as well).
  138. struct TempData
  139. {
  140. TempData(SceneObjProxy* proxy, const HSceneObject& restoredObj)
  141. :proxy(proxy), restoredObj(restoredObj)
  142. { }
  143. SceneObjProxy* proxy;
  144. HSceneObject restoredObj;
  145. };
  146. Stack<TempData> todo;
  147. todo.push(TempData(&proxy, restored));
  148. while (!todo.empty())
  149. {
  150. TempData data = todo.top();
  151. todo.pop();
  152. data.restoredObj->_setInstanceData(data.proxy->instanceData);
  153. // Find components that are still active and swap the old ones with restored ones,
  154. // keep any other as is.
  155. const Vector<HComponent>& restoredComponents = data.restoredObj->getComponents();
  156. UINT32 idx = 0;
  157. for (auto& restoredComponent : restoredComponents)
  158. {
  159. restoredComponent->_setInstanceData(data.proxy->componentInstanceData[idx]);
  160. SPtr<GameObject> restoredPtr = std::static_pointer_cast<GameObject>(restoredComponent.getInternalPtr());
  161. HComponent restoredComponentCopy = restoredComponent; // To remove const
  162. restoredComponentCopy._setHandleData(restoredPtr);
  163. idx++;
  164. }
  165. // Find children that are still active and swap the old ones with restored ones,
  166. // keep any other as is
  167. UINT32 restoredNumChildren = data.restoredObj->getNumChildren();
  168. for (UINT32 i = 0; i < restoredNumChildren; i++)
  169. {
  170. todo.push(TempData(&data.proxy->children[i], data.restoredObj->getChild(i)));
  171. }
  172. }
  173. }
  174. }