BsScriptObjectManager.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include "BsScriptObjectManager.h"
  2. #include "BsScriptObject.h"
  3. #include "BsMonoManager.h"
  4. #include "BsScriptAssemblyManager.h"
  5. #include "BsGameObjectManager.h"
  6. #include "BsMonoAssembly.h"
  7. namespace BansheeEngine
  8. {
  9. ScriptObjectManager::ScriptObjectManager()
  10. :mFinalizedQueueIdx(0)
  11. {
  12. }
  13. ScriptObjectManager::~ScriptObjectManager()
  14. {
  15. processFinalizedObjects();
  16. }
  17. void ScriptObjectManager::registerScriptObject(ScriptObjectBase* instance)
  18. {
  19. mScriptObjects.insert(instance);
  20. }
  21. void ScriptObjectManager::unregisterScriptObject(ScriptObjectBase* instance)
  22. {
  23. mScriptObjects.erase(instance);
  24. }
  25. void ScriptObjectManager::refreshAssemblies(const Vector<std::pair<String, Path>>& assemblies)
  26. {
  27. Map<ScriptObjectBase*, ScriptObjectBackup> backupData;
  28. onRefreshStarted();
  29. // Make sure any managed game objects are properly destroyed so their OnDestroy callbacks fire before unloading the domain
  30. GameObjectManager::instance().destroyQueuedObjects();
  31. for (auto& scriptObject : mScriptObjects)
  32. backupData[scriptObject] = scriptObject->beginRefresh();
  33. MonoManager::instance().unloadScriptDomain();
  34. // Unload script domain should trigger finalizers on everything, but since we usually delay
  35. // their processing we need to manually trigger it here.
  36. processFinalizedObjects();
  37. for (auto& scriptObject : mScriptObjects)
  38. assert(scriptObject->isPersistent() && "Non-persistent ScriptObject alive after domain unload.");
  39. for (auto& scriptObject : mScriptObjects)
  40. scriptObject->_clearManagedInstance();
  41. ScriptAssemblyManager::instance().clearAssemblyInfo();
  42. for (auto& assemblyPair : assemblies)
  43. {
  44. MonoManager::instance().loadAssembly(assemblyPair.second.toString(), assemblyPair.first);
  45. ScriptAssemblyManager::instance().loadAssemblyInfo(assemblyPair.first);
  46. }
  47. onRefreshDomainLoaded();
  48. Vector<ScriptObjectBase*> scriptObjCopy(mScriptObjects.size()); // Store originals as we could add new objects during the next iteration
  49. UINT32 idx = 0;
  50. for (auto& scriptObject : mScriptObjects)
  51. scriptObjCopy[idx++] = scriptObject;
  52. for (auto& scriptObject : scriptObjCopy)
  53. scriptObject->_restoreManagedInstance();
  54. for (auto& scriptObject : scriptObjCopy)
  55. scriptObject->endRefresh(backupData[scriptObject]);
  56. onRefreshComplete();
  57. }
  58. void ScriptObjectManager::notifyObjectFinalized(ScriptObjectBase* instance)
  59. {
  60. assert(instance != nullptr);
  61. BS_LOCK_MUTEX(mMutex);
  62. mFinalizedObjects[mFinalizedQueueIdx].push_back(instance);
  63. }
  64. void ScriptObjectManager::update()
  65. {
  66. processFinalizedObjects();
  67. }
  68. void ScriptObjectManager::processFinalizedObjects()
  69. {
  70. UINT32 readQueueIdx = 0;
  71. {
  72. BS_LOCK_MUTEX(mMutex);
  73. readQueueIdx = mFinalizedQueueIdx;
  74. mFinalizedQueueIdx = (mFinalizedQueueIdx + 1) % 2;
  75. }
  76. for (auto& finalizedObj : mFinalizedObjects[readQueueIdx])
  77. finalizedObj->_onManagedInstanceDeleted();
  78. mFinalizedObjects[readQueueIdx].clear();
  79. }
  80. }