BsScriptGizmoManager.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #include "BsScriptGizmoManager.h"
  2. #include "BsRuntimeScriptObjects.h"
  3. #include "BsMonoAssembly.h"
  4. #include "BsMonoClass.h"
  5. #include "BsMonoMethod.h"
  6. #include "BsMonoField.h"
  7. #include "BsMonoManager.h"
  8. #include "BsSceneManager.h"
  9. #include "BsSceneObject.h"
  10. #include "BsComponent.h"
  11. #include "BsManagedComponent.h"
  12. #include "BsGizmoManager.h"
  13. using namespace std::placeholders;
  14. namespace BansheeEngine
  15. {
  16. ScriptGizmoManager::ScriptGizmoManager(RuntimeScriptObjects& scriptObjectManager)
  17. :mScriptObjectManager(scriptObjectManager), mDrawGizmoAttribute(nullptr), mNextAssemblyId(0), mFlagsField(nullptr)
  18. {
  19. mScriptObjectManager.onAssemblyRefreshed.connect(std::bind(&ScriptGizmoManager::reloadAssemblyMethods, this, _1));
  20. Vector<String> initializedAssemblyNames = mScriptObjectManager.getInitializedAssemblies();
  21. for (auto& assemblyName : initializedAssemblyNames)
  22. {
  23. MonoAssembly* assembly = MonoManager::instance().getAssembly(assemblyName);
  24. if (assembly != nullptr)
  25. reloadAssemblyMethods(assembly);
  26. }
  27. }
  28. ScriptGizmoManager::~ScriptGizmoManager()
  29. {
  30. mAssemblyRefreshedConn.disconnect();
  31. }
  32. bool dummyIsSelected(const HSceneObject& so)
  33. {
  34. return false; // TODO - Replace with a call to Selection class once I have it
  35. }
  36. void ScriptGizmoManager::update()
  37. {
  38. HSceneObject rootSO = SceneManager::instance().getRootNode();
  39. Stack<HSceneObject> todo;
  40. todo.push(rootSO);
  41. bool isParentSelected = false;
  42. while (!todo.empty())
  43. {
  44. HSceneObject curSO = todo.top();
  45. todo.pop();
  46. bool isSelected = dummyIsSelected(curSO);
  47. bool isParentSelected = false; // TODO - Currently ignoring this
  48. const Vector<HComponent>& components = curSO->getComponents();
  49. for (auto& component : components)
  50. {
  51. if (rtti_is_of_type<ManagedComponent>(component.get()))
  52. {
  53. ManagedComponent* managedComponent = static_cast<ManagedComponent*>(component.get());
  54. auto iterFind = mGizmoDrawers.find(managedComponent->getManagedFullTypeName());
  55. if (iterFind != mGizmoDrawers.end())
  56. {
  57. UINT32 flags = iterFind->second.flags;
  58. // TODO - Check if gizmo is to be drawn only when selected
  59. // TODO - Set pickable if needed
  60. bool drawGizmo = false;
  61. if (((flags & (UINT32)DrawGizmoFlags::Selected) != 0) && isSelected)
  62. drawGizmo = true;
  63. if (((flags & (UINT32)DrawGizmoFlags::ParentSelected) != 0) && isParentSelected)
  64. drawGizmo = true;
  65. if (((flags & (UINT32)DrawGizmoFlags::NotSelected) != 0) && !isSelected && !isParentSelected)
  66. drawGizmo = true;
  67. if (drawGizmo)
  68. {
  69. bool pickable = (flags & (UINT32)DrawGizmoFlags::Pickable) != 0;
  70. GizmoManager::instance().setPickable(pickable);
  71. if ((flags & (UINT32)DrawGizmoFlags::Pickable) != 0)
  72. {
  73. void* params[1] = { managedComponent->getManagedInstance() };
  74. iterFind->second.drawGizmosMethod->invoke(nullptr, params);
  75. }
  76. }
  77. }
  78. }
  79. }
  80. for (UINT32 i = 0; i < curSO->getNumChildren(); i++)
  81. todo.push(curSO->getChild(i));
  82. }
  83. }
  84. void ScriptGizmoManager::reloadAssemblyMethods(MonoAssembly* assembly)
  85. {
  86. String assemblyName = assembly->getName();
  87. // If editor assembly, reload DrawGizmo attribute
  88. if (assemblyName == BansheeEditorAssemblyName)
  89. {
  90. mDrawGizmoAttribute = assembly->getClass("BansheeEditor", "DrawGizmo");
  91. if (mDrawGizmoAttribute == nullptr)
  92. BS_EXCEPT(InvalidStateException, "Cannot find DrawGizmo managed class.");
  93. mFlagsField = mDrawGizmoAttribute->getField("flags");
  94. // Load delayed assemblies first
  95. for (auto iter = mDelayedLoad.rbegin(); iter != mDelayedLoad.rend(); ++iter)
  96. reloadAssemblyMethods(*iter);
  97. mDelayedLoad.clear();
  98. }
  99. else
  100. {
  101. // If we haven't loaded editor assembly yet, wait until we do before continuing
  102. if (mDrawGizmoAttribute == nullptr)
  103. {
  104. mDelayedLoad.push_back(assembly);
  105. return;
  106. }
  107. }
  108. // If we had this assembly previously loaded, clear all of its methods
  109. UINT32 assemblyId = 0;
  110. auto iterFind = mAssemblyNameToId.find(assemblyName);
  111. if (iterFind != mAssemblyNameToId.end())
  112. {
  113. assemblyId = iterFind->second;
  114. Map<String, GizmoData> newGizmoDrawers;
  115. for (auto& gizmoMethod : mGizmoDrawers)
  116. {
  117. if (gizmoMethod.second.assemblyId != assemblyId)
  118. newGizmoDrawers[gizmoMethod.first] = gizmoMethod.second;
  119. }
  120. mGizmoDrawers.swap(newGizmoDrawers);
  121. }
  122. else
  123. {
  124. assemblyId = mNextAssemblyId++;
  125. mAssemblyNameToId[assemblyName] = assemblyId;
  126. }
  127. // Find new gizmo drawer methods
  128. const Vector<MonoClass*>& allClasses = assembly->getAllClasses();
  129. for (auto curClass : allClasses)
  130. {
  131. const Vector<MonoMethod*>& methods = curClass->getAllMethods();
  132. for (auto& curMethod : methods)
  133. {
  134. UINT32 drawGizmoFlags = 0;
  135. MonoClass* componentType = nullptr;
  136. if (isValidDrawGizmoMethod(curMethod, componentType, drawGizmoFlags))
  137. {
  138. String fullComponentName = componentType->getFullName();
  139. GizmoData& newGizmoData = mGizmoDrawers[fullComponentName];
  140. newGizmoData.assemblyId = assemblyId;
  141. newGizmoData.componentType = componentType;
  142. newGizmoData.drawGizmosMethod = curMethod;
  143. newGizmoData.flags = drawGizmoFlags;
  144. }
  145. }
  146. }
  147. }
  148. bool ScriptGizmoManager::isValidDrawGizmoMethod(MonoMethod* method, MonoClass*& componentType, UINT32& drawGizmoFlags)
  149. {
  150. componentType = nullptr;
  151. drawGizmoFlags = 0;
  152. if (!method->hasAttribute(mDrawGizmoAttribute))
  153. return false;
  154. if (method->getNumParameters() != 1)
  155. return false;
  156. if (!method->isStatic())
  157. return false;
  158. MonoClass* paramType = method->getParameterType(0);
  159. MonoClass* componentClass = mScriptObjectManager.getComponentClass();
  160. if (!paramType->isSubClassOf(componentClass))
  161. return false;
  162. componentType = paramType;
  163. MonoObject* drawGizmoAttrib = method->getAttribute(mDrawGizmoAttribute);
  164. mFlagsField->getValue(drawGizmoAttrib, &drawGizmoFlags);
  165. return true;
  166. }
  167. }