2
0

BsMenuItemManager.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. clearMenuItems();
  28. }
  29. void MenuItemManager::clearMenuItems()
  30. {
  31. MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
  32. for (auto& menuItem : mMenuItems)
  33. mainWindow->getMenuBar().removeMenuItem(menuItem);
  34. }
  35. void MenuItemManager::reloadAssemblyData()
  36. {
  37. clearMenuItems();
  38. // Reload MenuItem attribute from editor assembly
  39. MonoAssembly* editorAssembly = MonoManager::instance().getAssembly(EDITOR_ASSEMBLY);
  40. mMenuItemAttribute = editorAssembly->getClass("BansheeEditor", "MenuItem");
  41. if (mMenuItemAttribute == nullptr)
  42. BS_EXCEPT(InvalidStateException, "Cannot find MenuItem managed class.");
  43. mPathField = mMenuItemAttribute->getField("path");
  44. mShortcutField = mMenuItemAttribute->getField("shortcut");
  45. mPriorityField = mMenuItemAttribute->getField("priority");
  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. if (parseMenuItemMethod(curMethod, path, shortcutKey, priority))
  62. {
  63. std::function<void()> callback = std::bind(&MenuItemManager::menuItemCallback, curMethod);
  64. mainWindow->getMenuBar().addMenuItem(path, callback, priority, shortcutKey);
  65. mMenuItems.push_back(path);
  66. }
  67. }
  68. }
  69. }
  70. }
  71. bool MenuItemManager::parseMenuItemMethod(MonoMethod* method, WString& path, ShortcutKey& shortcut, INT32& priority) const
  72. {
  73. if (!method->hasAttribute(mMenuItemAttribute))
  74. return false;
  75. if (method->getNumParameters() != 0)
  76. return false;
  77. if (!method->isStatic())
  78. return false;
  79. MonoObject* menuItemAttrib = method->getAttribute(mMenuItemAttribute);
  80. MonoString* monoPath;
  81. mPathField->getValue(menuItemAttrib, &monoPath);
  82. mShortcutField->getValue(menuItemAttrib, &shortcut);
  83. path = MonoUtil::monoToWString(monoPath);
  84. mPriorityField->getValue(menuItemAttrib, &priority);
  85. return true;
  86. }
  87. void MenuItemManager::menuItemCallback(MonoMethod* method)
  88. {
  89. method->invoke(nullptr, nullptr);
  90. }
  91. }