BsScriptModalWindow.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include "BsScriptModalWindow.h"
  2. #include "BsScriptMeta.h"
  3. #include "BsScriptGUIPanel.h"
  4. #include "BsMonoField.h"
  5. #include "BsMonoClass.h"
  6. #include "BsMonoMethod.h"
  7. #include "BsMonoManager.h"
  8. #include "BsMonoUtil.h"
  9. #include "BsMonoAssembly.h"
  10. #include "BsScriptObjectManager.h"
  11. #include "BsScriptHString.h"
  12. #include "BsRenderWindow.h"
  13. using namespace std::placeholders;
  14. namespace BansheeEngine
  15. {
  16. MonoMethod* ScriptModalWindow::onInitializedInternalMethod = nullptr;
  17. MonoMethod* ScriptModalWindow::onDestroyInternalMethod = nullptr;
  18. ScriptModalWindow::ScriptModalWindow(ManagedModalWindow* window)
  19. :ScriptObject(window->getManagedInstance()), mModalWindow(window), mRefreshInProgress(false)
  20. {
  21. mOnAssemblyRefreshStartedConn = ScriptObjectManager::instance().onRefreshStarted.connect(std::bind(&ScriptModalWindow::onAssemblyRefreshStarted, this));
  22. }
  23. ScriptModalWindow::~ScriptModalWindow()
  24. {
  25. mOnAssemblyRefreshStartedConn.disconnect();
  26. }
  27. void ScriptModalWindow::initRuntimeData()
  28. {
  29. metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptModalWindow::internal_createInstance);
  30. metaData.scriptClass->addInternalCall("Internal_Close", &ScriptModalWindow::internal_close);
  31. metaData.scriptClass->addInternalCall("Internal_InitializeGUIPanel", &ScriptModalWindow::internal_initializeGUIPanel);
  32. metaData.scriptClass->addInternalCall("Internal_GetWidth", &ScriptModalWindow::internal_getWidth);
  33. metaData.scriptClass->addInternalCall("Internal_GetHeight", &ScriptModalWindow::internal_getHeight);
  34. metaData.scriptClass->addInternalCall("Internal_SetWidth", &ScriptModalWindow::internal_setWidth);
  35. metaData.scriptClass->addInternalCall("Internal_SetHeight", &ScriptModalWindow::internal_setHeight);
  36. metaData.scriptClass->addInternalCall("Internal_SetTitle", &ScriptModalWindow::internal_setTitle);
  37. metaData.scriptClass->addInternalCall("Internal_ScreenToWindowPos", &ScriptModalWindow::internal_screenToWindowPos);
  38. metaData.scriptClass->addInternalCall("Internal_WindowToScreenPos", &ScriptModalWindow::internal_windowToScreenPos);
  39. onInitializedInternalMethod = metaData.scriptClass->getMethod("OnInitializeInternal", 0);
  40. onDestroyInternalMethod = metaData.scriptClass->getMethod("OnDestroyInternal", 0);
  41. }
  42. void ScriptModalWindow::internal_createInstance(MonoObject* instance, bool allowCloseButton)
  43. {
  44. ManagedModalWindow* modalWindow = bs_new<ManagedModalWindow>(allowCloseButton, instance);
  45. ScriptModalWindow* nativeInstance = new (bs_alloc<ScriptModalWindow>()) ScriptModalWindow(modalWindow);
  46. modalWindow->initialize(nativeInstance);
  47. modalWindow->triggerOnInitialize();
  48. }
  49. void ScriptModalWindow::internal_close(ScriptModalWindow* thisPtr)
  50. {
  51. thisPtr->closeWindow();
  52. }
  53. void ScriptModalWindow::internal_setTitle(ScriptModalWindow* thisPtr, MonoObject* title)
  54. {
  55. HString titleStr = HString::dummy();
  56. if (title != nullptr)
  57. {
  58. ScriptHString* textScript = ScriptHString::toNative(title);
  59. titleStr = textScript->getInternalValue();
  60. }
  61. thisPtr->mModalWindow->setTitle(titleStr);
  62. }
  63. void ScriptModalWindow::closeWindow()
  64. {
  65. if (mModalWindow == nullptr)
  66. return;
  67. mModalWindow->triggerOnDestroy();
  68. mModalWindow->releaseManagedInstance();
  69. mModalWindow->close();
  70. mModalWindow = nullptr;
  71. }
  72. void ScriptModalWindow::_onManagedInstanceDeleted()
  73. {
  74. if (!mRefreshInProgress)
  75. {
  76. // Note: This should only ever get triggered after "internal_close" is called
  77. ScriptObject::_onManagedInstanceDeleted();
  78. }
  79. else
  80. mManagedInstance = nullptr;
  81. }
  82. ScriptObjectBackup ScriptModalWindow::beginRefresh()
  83. {
  84. mRefreshInProgress = true;
  85. if (mModalWindow != nullptr)
  86. mModalWindow->releaseManagedInstance();
  87. return PersistentScriptObjectBase::beginRefresh();
  88. }
  89. void ScriptModalWindow::endRefresh(const ScriptObjectBackup& backupData)
  90. {
  91. mRefreshInProgress = false;
  92. if (mModalWindow != nullptr)
  93. mManagedInstance = mModalWindow->getManagedInstance();
  94. else
  95. mManagedInstance = nullptr;
  96. if (mManagedInstance != nullptr)
  97. {
  98. mModalWindow->triggerOnInitialize();
  99. }
  100. else
  101. {
  102. // We couldn't restore managed instance because window class cannot be found
  103. _onManagedInstanceDeleted();
  104. }
  105. PersistentScriptObjectBase::endRefresh(backupData);
  106. }
  107. void ScriptModalWindow::onAssemblyRefreshStarted()
  108. {
  109. if (mModalWindow != nullptr)
  110. mModalWindow->triggerOnDestroy();
  111. }
  112. MonoObject* ScriptModalWindow::_createManagedInstance(bool construct)
  113. {
  114. if (mModalWindow != nullptr)
  115. {
  116. mModalWindow->createManagedInstance();
  117. return mModalWindow->getManagedInstance();
  118. }
  119. else
  120. return nullptr;
  121. }
  122. UINT32 ScriptModalWindow::internal_getWidth(ScriptModalWindow* thisPtr)
  123. {
  124. if (thisPtr->mModalWindow != nullptr)
  125. return thisPtr->mModalWindow->getWidth();
  126. return 0;
  127. }
  128. UINT32 ScriptModalWindow::internal_getHeight(ScriptModalWindow* thisPtr)
  129. {
  130. if (thisPtr->mModalWindow != nullptr)
  131. return thisPtr->mModalWindow->getHeight();
  132. return 0;
  133. }
  134. void ScriptModalWindow::internal_setWidth(ScriptModalWindow* thisPtr, UINT32 value)
  135. {
  136. if (thisPtr->mModalWindow != nullptr)
  137. thisPtr->mModalWindow->setSize(value, thisPtr->mModalWindow->getHeight());
  138. }
  139. void ScriptModalWindow::internal_setHeight(ScriptModalWindow* thisPtr, UINT32 value)
  140. {
  141. if (thisPtr->mModalWindow != nullptr)
  142. thisPtr->mModalWindow->setSize(thisPtr->mModalWindow->getWidth(), value);
  143. }
  144. void ScriptModalWindow::internal_initializeGUIPanel(ScriptModalWindow* thisPtr, MonoObject* panel)
  145. {
  146. ScriptGUIPanel* scriptGUIPanel = ScriptGUIPanel::toNative(panel);
  147. thisPtr->mGUIPanel = scriptGUIPanel;
  148. Rect2I contentArea = thisPtr->mModalWindow->getContentArea();
  149. scriptGUIPanel->setParentArea(contentArea.x, contentArea.y, contentArea.width, contentArea.height);
  150. scriptGUIPanel->setParentWidget(thisPtr->mModalWindow->getGUIWidget().get());
  151. }
  152. void ScriptModalWindow::internal_screenToWindowPos(ScriptModalWindow* thisPtr, Vector2I screenPos, Vector2I* windowPos)
  153. {
  154. RenderWindowPtr parentRenderWindow = thisPtr->mModalWindow->getRenderWindow();
  155. *windowPos = parentRenderWindow->screenToWindowPos(screenPos);
  156. }
  157. void ScriptModalWindow::internal_windowToScreenPos(ScriptModalWindow* thisPtr, Vector2I windowPos, Vector2I* screenPos)
  158. {
  159. RenderWindowPtr parentRenderWindow = thisPtr->mModalWindow->getRenderWindow();
  160. *screenPos = parentRenderWindow->windowToScreenPos(windowPos);
  161. }
  162. ManagedModalWindow::ManagedModalWindow(bool allowCloseButton, MonoObject* managedInstance)
  163. :ModalWindow(HString::dummy(), allowCloseButton), mUpdateThunk(nullptr), mManagedInstance(managedInstance),
  164. mOnInitializeThunk(nullptr), mOnDestroyThunk(nullptr), mOnWindowResizedMethod(nullptr), mGCHandle(0),
  165. mScriptParent(nullptr)
  166. {
  167. mGCHandle = mono_gchandle_new(mManagedInstance, false);
  168. ::MonoClass* rawMonoClass = mono_object_get_class(mManagedInstance);
  169. MonoClass* monoClass = MonoManager::instance().findClass(rawMonoClass);
  170. mNamespace = monoClass->getNamespace();
  171. mTypename = monoClass->getTypeName();
  172. reloadMonoTypes(monoClass);
  173. }
  174. ManagedModalWindow::~ManagedModalWindow()
  175. {
  176. assert(mGCHandle == 0); // We expect "close" to be called either from C++ or C# before destruction
  177. }
  178. bool ManagedModalWindow::createManagedInstance()
  179. {
  180. MonoAssembly* assembly = MonoManager::instance().getAssembly(EDITOR_ASSEMBLY);
  181. if (assembly != nullptr)
  182. {
  183. MonoClass* editorWindowClass = assembly->getClass(mNamespace, mTypename);
  184. if (editorWindowClass != nullptr)
  185. {
  186. mManagedInstance = editorWindowClass->createInstance();
  187. mGCHandle = mono_gchandle_new(mManagedInstance, false);
  188. reloadMonoTypes(editorWindowClass);
  189. return true;
  190. }
  191. }
  192. return false;
  193. }
  194. void ManagedModalWindow::releaseManagedInstance()
  195. {
  196. mono_gchandle_free(mGCHandle);
  197. mGCHandle = 0;
  198. }
  199. void ManagedModalWindow::triggerOnInitialize()
  200. {
  201. if (mManagedInstance != nullptr)
  202. ScriptModalWindow::onInitializedInternalMethod->invoke(mManagedInstance, nullptr);
  203. if (mOnInitializeThunk != nullptr && mManagedInstance != nullptr)
  204. {
  205. MonoException* exception = nullptr;
  206. // Note: Not calling virtual methods. Can be easily done if needed but for now doing this
  207. // for some extra speed.
  208. mOnInitializeThunk(mManagedInstance, &exception);
  209. MonoUtil::throwIfException(exception);
  210. }
  211. }
  212. void ManagedModalWindow::triggerOnDestroy()
  213. {
  214. if (mManagedInstance != nullptr)
  215. ScriptModalWindow::onDestroyInternalMethod->invoke(mManagedInstance, nullptr);
  216. if (mOnDestroyThunk != nullptr && mManagedInstance != nullptr)
  217. {
  218. MonoException* exception = nullptr;
  219. // Note: Not calling virtual methods. Can be easily done if needed but for now doing this
  220. // for some extra speed.
  221. mOnDestroyThunk(mManagedInstance, &exception);
  222. MonoUtil::throwIfException(exception);
  223. }
  224. }
  225. void ManagedModalWindow::initialize(ScriptModalWindow* parent)
  226. {
  227. mScriptParent = parent;
  228. }
  229. void ManagedModalWindow::update()
  230. {
  231. if (mUpdateThunk != nullptr && mManagedInstance != nullptr)
  232. {
  233. MonoException* exception = nullptr;
  234. // Note: Not calling virtual methods. Can be easily done if needed but for now doing this
  235. // for some extra speed.
  236. mUpdateThunk(mManagedInstance, &exception);
  237. MonoUtil::throwIfException(exception);
  238. }
  239. }
  240. void ManagedModalWindow::resized()
  241. {
  242. UINT32 width = getWidth();
  243. UINT32 height = getHeight();
  244. Rect2I contentArea = getContentArea();
  245. mScriptParent->mGUIPanel->setParentArea(contentArea.x, contentArea.y, contentArea.width, contentArea.height);
  246. if (mOnWindowResizedMethod != nullptr && mManagedInstance != nullptr)
  247. {
  248. void* params[] = { &width, &height };
  249. mOnWindowResizedMethod->invokeVirtual(mManagedInstance, params);
  250. }
  251. ModalWindow::resized();
  252. }
  253. void ManagedModalWindow::close()
  254. {
  255. mScriptParent->closeWindow();
  256. }
  257. void ManagedModalWindow::reloadMonoTypes(MonoClass* windowClass)
  258. {
  259. MonoMethod* updateMethod = windowClass->getMethod("OnEditorUpdate", 0);
  260. if (updateMethod != nullptr)
  261. mUpdateThunk = (UpdateThunkDef)updateMethod->getThunk();
  262. MonoMethod* onInitializeMethod = windowClass->getMethod("OnInitialize", 0);
  263. if (onInitializeMethod != nullptr)
  264. mOnInitializeThunk = (OnInitializeThunkDef)onInitializeMethod->getThunk();
  265. MonoMethod* onDestroyMethod = windowClass->getMethod("OnDestroy", 0);
  266. if (onDestroyMethod != nullptr)
  267. mOnDestroyThunk = (OnDestroyThunkDef)onDestroyMethod->getThunk();
  268. MonoClass* modalWindowClass = windowClass->getBaseClass();
  269. mOnWindowResizedMethod = modalWindowClass->getMethod("OnWindowResized", 2);
  270. }
  271. }