2
0

BsUtility.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Utility/BsUtility.h"
  4. #include "Reflection/BsRTTIType.h"
  5. #include "Scene/BsSceneObject.h"
  6. namespace bs
  7. {
  8. Vector<ResourceDependency> Utility::findResourceDependencies(IReflectable& obj, bool recursive)
  9. {
  10. Map<UUID, ResourceDependency> dependencies;
  11. findResourceDependenciesInternal(obj, recursive, dependencies);
  12. Vector<ResourceDependency> dependencyList(dependencies.size());
  13. UINT32 i = 0;
  14. for (auto& entry : dependencies)
  15. {
  16. dependencyList[i] = entry.second;
  17. i++;
  18. }
  19. return dependencyList;
  20. }
  21. UINT32 Utility::getSceneObjectDepth(const HSceneObject& so)
  22. {
  23. HSceneObject parent = so->getParent();
  24. UINT32 depth = 0;
  25. while (parent != nullptr)
  26. {
  27. depth++;
  28. parent = parent->getParent();
  29. }
  30. return depth;
  31. }
  32. void Utility::findResourceDependenciesInternal(IReflectable& obj, bool recursive, Map<UUID, ResourceDependency>& dependencies)
  33. {
  34. static const UnorderedMap<String, UINT64> dummyParams;
  35. RTTITypeBase* rtti = obj.getRTTI();
  36. rtti->onSerializationStarted(&obj, dummyParams);
  37. UINT32 numFields = rtti->getNumFields();
  38. for (UINT32 i = 0; i < numFields; i++)
  39. {
  40. RTTIField* field = rtti->getField(i);
  41. if ((field->getFlags() & RTTI_Flag_SkipInReferenceSearch) != 0)
  42. continue;
  43. if (field->isReflectableType())
  44. {
  45. RTTIReflectableFieldBase* reflectableField = static_cast<RTTIReflectableFieldBase*>(field);
  46. if (reflectableField->getType()->getRTTIId() == TID_ResourceHandle)
  47. {
  48. if (reflectableField->isArray())
  49. {
  50. UINT32 numElements = reflectableField->getArraySize(&obj);
  51. for (UINT32 j = 0; j < numElements; j++)
  52. {
  53. HResource resource = (HResource&)reflectableField->getArrayValue(&obj, j);
  54. if (!resource.getUUID().empty())
  55. {
  56. ResourceDependency& dependency = dependencies[resource.getUUID()];
  57. dependency.resource = resource;
  58. dependency.numReferences++;
  59. }
  60. }
  61. }
  62. else
  63. {
  64. HResource resource = (HResource&)reflectableField->getValue(&obj);
  65. if (!resource.getUUID().empty())
  66. {
  67. ResourceDependency& dependency = dependencies[resource.getUUID()];
  68. dependency.resource = resource;
  69. dependency.numReferences++;
  70. }
  71. }
  72. }
  73. else if (recursive)
  74. {
  75. // Optimization, no need to retrieve its value and go deeper if it has no
  76. // reflectable children that may hold the reference.
  77. if (hasReflectableChildren(reflectableField->getType()))
  78. {
  79. if (reflectableField->isArray())
  80. {
  81. UINT32 numElements = reflectableField->getArraySize(&obj);
  82. for (UINT32 j = 0; j < numElements; j++)
  83. {
  84. IReflectable& childObj = reflectableField->getArrayValue(&obj, j);
  85. findResourceDependenciesInternal(childObj, true, dependencies);
  86. }
  87. }
  88. else
  89. {
  90. IReflectable& childObj = reflectableField->getValue(&obj);
  91. findResourceDependenciesInternal(childObj, true, dependencies);
  92. }
  93. }
  94. }
  95. }
  96. else if (field->isReflectablePtrType() && recursive)
  97. {
  98. RTTIReflectablePtrFieldBase* reflectablePtrField = static_cast<RTTIReflectablePtrFieldBase*>(field);
  99. // Optimization, no need to retrieve its value and go deeper if it has no
  100. // reflectable children that may hold the reference.
  101. if (hasReflectableChildren(reflectablePtrField->getType()))
  102. {
  103. if (reflectablePtrField->isArray())
  104. {
  105. UINT32 numElements = reflectablePtrField->getArraySize(&obj);
  106. for (UINT32 j = 0; j < numElements; j++)
  107. {
  108. SPtr<IReflectable> childObj = reflectablePtrField->getArrayValue(&obj, j);
  109. if (childObj != nullptr)
  110. findResourceDependenciesInternal(*childObj, true, dependencies);
  111. }
  112. }
  113. else
  114. {
  115. SPtr<IReflectable> childObj = reflectablePtrField->getValue(&obj);
  116. if (childObj != nullptr)
  117. findResourceDependenciesInternal(*childObj, true, dependencies);
  118. }
  119. }
  120. }
  121. }
  122. rtti->onSerializationEnded(&obj, dummyParams);
  123. }
  124. Vector<HComponent> Utility::findComponents(const HSceneObject& object, UINT32 typeId)
  125. {
  126. Vector<HComponent> output;
  127. Stack<HSceneObject> todo;
  128. todo.push(object);
  129. while(!todo.empty())
  130. {
  131. HSceneObject curSO = todo.top();
  132. todo.pop();
  133. const Vector<HComponent>& components = curSO->getComponents();
  134. for(auto& entry : components)
  135. {
  136. if (entry->getRTTI()->getRTTIId() == typeId)
  137. output.push_back(entry);
  138. }
  139. UINT32 numChildren = curSO->getNumChildren();
  140. for (UINT32 i = 0; i < numChildren; i++)
  141. todo.push(curSO->getChild(i));
  142. }
  143. return output;
  144. }
  145. bool Utility::hasReflectableChildren(RTTITypeBase* type)
  146. {
  147. UINT32 numFields = type->getNumFields();
  148. for (UINT32 i = 0; i < numFields; i++)
  149. {
  150. RTTIField* field = type->getField(i);
  151. if (field->isReflectableType() || field->isReflectablePtrType())
  152. return true;
  153. }
  154. const Vector<RTTITypeBase*>& derivedClasses = type->getDerivedClasses();
  155. for (auto& derivedClass : derivedClasses)
  156. {
  157. numFields = derivedClass->getNumFields();
  158. for (UINT32 i = 0; i < numFields; i++)
  159. {
  160. RTTIField* field = derivedClass->getField(i);
  161. if (field->isReflectableType() || field->isReflectablePtrType())
  162. return true;
  163. }
  164. }
  165. return false;
  166. }
  167. }