2
0

BsManagedEditorCommand.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsManagedEditorCommand.h"
  4. #include "BsScriptMeta.h"
  5. #include "BsMonoField.h"
  6. #include "BsMonoClass.h"
  7. #include "BsMonoMethod.h"
  8. #include "BsMonoManager.h"
  9. #include "BsMonoUtil.h"
  10. namespace bs
  11. {
  12. MonoMethod* ScriptCmdManaged::sCommitMethod = nullptr;
  13. MonoMethod* ScriptCmdManaged::sRevertMethod = nullptr;
  14. ScriptCmdManaged::ScriptCmdManaged(MonoObject* managedInstance)
  15. :ScriptObject(managedInstance), mManagedCommand(nullptr)
  16. {
  17. mManagedCommand = bs_shared_ptr(new (bs_alloc<CmdManaged>()) CmdManaged(this));
  18. }
  19. ScriptCmdManaged::~ScriptCmdManaged()
  20. {
  21. if(mManagedCommand != nullptr)
  22. {
  23. mManagedCommand->notifyScriptInstanceDestroyed();
  24. mManagedCommand = nullptr;
  25. }
  26. }
  27. void ScriptCmdManaged::initRuntimeData()
  28. {
  29. metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptCmdManaged::internal_CreateInstance);
  30. sCommitMethod = metaData.scriptClass->getMethod("Commit");
  31. sRevertMethod = metaData.scriptClass->getMethod("Revert");
  32. }
  33. void ScriptCmdManaged::internal_CreateInstance(MonoObject* managedInstance)
  34. {
  35. new (bs_alloc<ScriptCmdManaged>()) ScriptCmdManaged(managedInstance);
  36. }
  37. void ScriptCmdManaged::triggerCommit()
  38. {
  39. if (sCommitMethod == nullptr)
  40. return;
  41. sCommitMethod->invokeVirtual(mManagedInstance, nullptr);
  42. }
  43. void ScriptCmdManaged::triggerRevert()
  44. {
  45. if (sRevertMethod == nullptr)
  46. return;
  47. sRevertMethod->invokeVirtual(mManagedInstance, nullptr);
  48. }
  49. void ScriptCmdManaged::notifyCommandDestroyed()
  50. {
  51. mManagedCommand = nullptr;
  52. }
  53. CmdManaged::CmdManaged(ScriptCmdManaged* scriptObj)
  54. : EditorCommand(L""), mScriptObj(scriptObj), mGCHandle(0), mRefCount(0)
  55. {
  56. }
  57. CmdManaged::~CmdManaged()
  58. {
  59. if (mScriptObj != nullptr)
  60. mScriptObj->notifyCommandDestroyed();
  61. }
  62. void CmdManaged::commit()
  63. {
  64. if(mScriptObj == nullptr)
  65. {
  66. LOGWRN("Trying to execute a managed undo/redo command whose managed object has been destroyed, ignoring.");
  67. // Note: This can most likely happen if managed undo commands are queued on a global undo/redo stack. When
  68. // assembly refresh happens those commands will be destroyed but not removed from the stack. To fix the issue
  69. // implement assembly refresh handling for such commands.
  70. return;
  71. }
  72. mScriptObj->triggerCommit();
  73. }
  74. void CmdManaged::revert()
  75. {
  76. if (mScriptObj == nullptr)
  77. {
  78. LOGWRN("Trying to execute a managed undo/redo command whose managed object has been destroyed, ignoring.");
  79. // Note: This can most likely happen if managed undo commands are queued on a global undo/redo stack. When
  80. // assembly refresh happens those commands will be destroyed but not removed from the stack. To fix the issue
  81. // implement assembly refresh handling for such commands.
  82. return;
  83. }
  84. mScriptObj->triggerRevert();
  85. }
  86. void CmdManaged::onCommandAdded()
  87. {
  88. if (mGCHandle == 0 && mScriptObj != nullptr)
  89. mGCHandle = MonoUtil::newGCHandle(mScriptObj->getManagedInstance());
  90. mRefCount++;
  91. }
  92. void CmdManaged::onCommandRemoved()
  93. {
  94. assert(mRefCount > 0);
  95. mRefCount--;
  96. if (mRefCount == 0 && mGCHandle != 0)
  97. MonoUtil::freeGCHandle(mGCHandle);
  98. }
  99. void CmdManaged::notifyScriptInstanceDestroyed()
  100. {
  101. mScriptObj = nullptr;
  102. }
  103. }