BsMenuItemManager.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "BsMenuItemManager.h"
  2. #include "BsScriptAssemblyManager.h"
  3. #include "BsMonoAssembly.h"
  4. #include "BsMonoClass.h"
  5. #include "BsMonoMethod.h"
  6. #include "BsMonoField.h"
  7. #include "BsMonoManager.h"
  8. #include "BsMonoUtil.h"
  9. #include "BsScriptObjectManager.h"
  10. #include "BsShortcutKey.h"
  11. #include "BsEditorWindowManager.h"
  12. #include "BsMainEditorWindow.h"
  13. #include "BsGUIMenuBar.h"
  14. using namespace std::placeholders;
  15. namespace BansheeEngine
  16. {
  17. MenuItemManager::MenuItemManager(ScriptAssemblyManager& scriptObjectManager)
  18. :mScriptObjectManager(scriptObjectManager), mMenuItemAttribute(nullptr), mPathField(nullptr),
  19. mShortcutField(nullptr), mPriorityField(nullptr)
  20. {
  21. mDomainLoadedConn = ScriptObjectManager::instance().onRefreshDomainLoaded.connect(std::bind(&MenuItemManager::reloadAssemblyData, this));
  22. reloadAssemblyData();
  23. }
  24. MenuItemManager::~MenuItemManager()
  25. {
  26. mDomainLoadedConn.disconnect();
  27. }
  28. void MenuItemManager::clearMenuItems()
  29. {
  30. MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
  31. for (auto& menuItem : mMenuItems)
  32. mainWindow->getMenuBar().removeMenuItem(menuItem);
  33. }
  34. void MenuItemManager::reloadAssemblyData()
  35. {
  36. clearMenuItems();
  37. // Reload MenuItem attribute from editor assembly
  38. MonoAssembly* editorAssembly = MonoManager::instance().getAssembly(EDITOR_ASSEMBLY);
  39. mMenuItemAttribute = editorAssembly->getClass("BansheeEditor", "MenuItem");
  40. if (mMenuItemAttribute == nullptr)
  41. BS_EXCEPT(InvalidStateException, "Cannot find MenuItem managed class.");
  42. mPathField = mMenuItemAttribute->getField("path");
  43. mShortcutField = mMenuItemAttribute->getField("shortcut");
  44. mPriorityField = mMenuItemAttribute->getField("priority");
  45. mSeparatorField = mMenuItemAttribute->getField("separator");
  46. MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
  47. Vector<String> scriptAssemblyNames = mScriptObjectManager.getScriptAssemblies();
  48. for (auto& assemblyName : scriptAssemblyNames)
  49. {
  50. MonoAssembly* assembly = MonoManager::instance().getAssembly(assemblyName);
  51. // Find new menu item methods
  52. const Vector<MonoClass*>& allClasses = assembly->getAllClasses();
  53. for (auto curClass : allClasses)
  54. {
  55. const Vector<MonoMethod*>& methods = curClass->getAllMethods();
  56. for (auto& curMethod : methods)
  57. {
  58. WString path;
  59. ShortcutKey shortcutKey = ShortcutKey::NONE;
  60. INT32 priority = 0;
  61. bool separator = false;
  62. if (parseMenuItemMethod(curMethod, path, shortcutKey, priority, separator))
  63. {
  64. std::function<void()> callback = std::bind(&MenuItemManager::menuItemCallback, curMethod);
  65. if (separator)
  66. {
  67. Vector<WString> pathElements = StringUtil::split(path, L"/");
  68. WString separatorPath;
  69. if (pathElements.size() > 1)
  70. {
  71. const WString& lastElem = pathElements[pathElements.size() - 1];
  72. separatorPath = path;
  73. separatorPath.erase(path.size() - lastElem.size() - 1, lastElem.size() + 1);
  74. }
  75. mainWindow->getMenuBar().addMenuItemSeparator(separatorPath, priority);
  76. }
  77. mainWindow->getMenuBar().addMenuItem(path, callback, priority, shortcutKey);
  78. mMenuItems.push_back(path);
  79. }
  80. }
  81. }
  82. }
  83. }
  84. bool MenuItemManager::parseMenuItemMethod(MonoMethod* method, WString& path, ShortcutKey& shortcut, INT32& priority, bool& separator) const
  85. {
  86. if (!method->hasAttribute(mMenuItemAttribute))
  87. return false;
  88. if (method->getNumParameters() != 0)
  89. return false;
  90. if (!method->isStatic())
  91. return false;
  92. MonoObject* menuItemAttrib = method->getAttribute(mMenuItemAttribute);
  93. MonoString* monoPath;
  94. mPathField->getValue(menuItemAttrib, &monoPath);
  95. mShortcutField->getValue(menuItemAttrib, &shortcut);
  96. path = MonoUtil::monoToWString(monoPath);
  97. mPriorityField->getValue(menuItemAttrib, &priority);
  98. mSeparatorField->getValue(menuItemAttrib, &separator);
  99. return true;
  100. }
  101. void MenuItemManager::menuItemCallback(MonoMethod* method)
  102. {
  103. method->invoke(nullptr, nullptr);
  104. }
  105. }