Plugin.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "EditorDefs.h"
  9. #include "Plugin.h"
  10. #include <QMessageBox>
  11. CClassFactory* CClassFactory::s_pInstance = nullptr;
  12. CAutoRegisterClassHelper* CAutoRegisterClassHelper::s_pFirst = nullptr;
  13. CAutoRegisterClassHelper* CAutoRegisterClassHelper::s_pLast = nullptr;
  14. CClassFactory::CClassFactory()
  15. {
  16. m_classes.reserve(100);
  17. RegisterAutoTypes();
  18. }
  19. CClassFactory::~CClassFactory()
  20. {
  21. for (int i = 0; i < m_classes.size(); i++)
  22. {
  23. m_classes[i]->Release();
  24. }
  25. }
  26. void CClassFactory::RegisterAutoTypes()
  27. {
  28. CAutoRegisterClassHelper* pClass = CAutoRegisterClassHelper::s_pFirst;
  29. while (pClass)
  30. {
  31. RegisterClass(pClass->m_pClassDesc);
  32. pClass = pClass->m_pNext;
  33. }
  34. }
  35. CClassFactory* CClassFactory::Instance()
  36. {
  37. if (!s_pInstance)
  38. {
  39. s_pInstance = new CClassFactory;
  40. }
  41. return s_pInstance;
  42. }
  43. void CClassFactory::RegisterClass(IClassDesc* pClassDesc)
  44. {
  45. assert(pClassDesc);
  46. auto findByGuid = m_guidToClass.find(pClassDesc->ClassID());
  47. if (findByGuid != m_guidToClass.end())
  48. {
  49. // you may not re-use UUIDs!
  50. // this can happen when someone makes a new plugin or downloads one
  51. // where the author copied and pasted code. This can also happen if two DLLs exist which are actually the same plugin
  52. // either way, give info if you can:
  53. char errorMessageBuffer[512] = { 0 };
  54. AZ::Uuid newUUID(pClassDesc->ClassID());
  55. char existingUUIDString[64] = { 0 };
  56. newUUID.ToString(existingUUIDString, 64, true, true);
  57. sprintf_s(errorMessageBuffer, 512,
  58. "Error registering class '%s' - UUID of that class already exists (%s), and belongs to class named '%s.'\n"
  59. "You may not have duplicate class identifiers.\n"
  60. "Check for duplicate plugins or copy and pasted code for plugins that duplicates UUIDs returned.",
  61. pClassDesc->ClassName().toUtf8().data(),
  62. existingUUIDString,
  63. findByGuid->second->ClassName().toUtf8().data());
  64. QMessageBox::critical(nullptr,"Invalid class registration - Duplicate UUID",QString::fromLatin1(errorMessageBuffer));
  65. return;
  66. }
  67. auto findByName = m_nameToClass.find(pClassDesc->ClassName());
  68. if (findByName != m_nameToClass.end())
  69. {
  70. // you may not re-use names, either!
  71. char errorMessageBuffer[512] = { 0 };
  72. AZ::Uuid newUUID(pClassDesc->ClassID());
  73. char newUUIDString[64] = { 0 };
  74. newUUID.ToString(newUUIDString, 64, true, true);
  75. AZ::Uuid existingUUID(findByName->second->ClassID());
  76. char existingUUIDString[64] = { 0 };
  77. existingUUID.ToString(existingUUIDString, 64, true, true);
  78. sprintf_s(errorMessageBuffer, 512,
  79. "Error registering class '%s' - that name is already taken by a different class.\n"
  80. "New class's UUID is %s\n"
  81. "Existing class's UUID is %s\n"
  82. "You may not have duplicate class names.\n"
  83. "Check for duplicate plugins or copy and pasted code for plugins.",
  84. pClassDesc->ClassName().toUtf8().constData(),
  85. newUUIDString,
  86. existingUUIDString);
  87. QMessageBox::critical(nullptr, "Invalid class registration - Duplicate Class Name", QString::fromLatin1(errorMessageBuffer));
  88. return;
  89. }
  90. #if defined(DEBUG_CLASS_NAME_REGISTRATION)
  91. m_debugClassNames.push_back(pClassDesc->ClassName());
  92. #endif // DEBUG_CLASS_NAME_REGISTRATION
  93. m_classes.push_back(pClassDesc);
  94. m_guidToClass[pClassDesc->ClassID()] = pClassDesc;
  95. m_nameToClass[pClassDesc->ClassName()] = pClassDesc;
  96. }
  97. IClassDesc* CClassFactory::FindClass(const char* pClassName) const
  98. {
  99. IClassDesc* pClassDesc = stl::find_in_map(m_nameToClass, pClassName, (IClassDesc*)nullptr);
  100. if (pClassDesc)
  101. {
  102. return pClassDesc;
  103. }
  104. const char* pSubClassName = strstr(pClassName, "::");
  105. if (!pSubClassName)
  106. {
  107. return nullptr;
  108. }
  109. QString name = QString(pClassName).left(static_cast<int>(pSubClassName - pClassName));
  110. return stl::find_in_map(m_nameToClass, name, (IClassDesc*)nullptr);
  111. }
  112. IClassDesc* CClassFactory::FindClass(const GUID& rClassID) const
  113. {
  114. IClassDesc* pClassDesc = stl::find_in_map(m_guidToClass, rClassID, (IClassDesc*)nullptr);
  115. return pClassDesc;
  116. }
  117. void CClassFactory::UnregisterClass(const char* pClassName)
  118. {
  119. IClassDesc* pClassDesc = FindClass(pClassName);
  120. if (pClassDesc == nullptr)
  121. {
  122. return;
  123. }
  124. #if defined(DEBUG_CLASS_NAME_REGISTRATION)
  125. stl::find_and_erase(m_debugClassNames, pClassDesc->ClassName());
  126. #endif // DEBUG_CLASS_NAME_REGISTRATION
  127. stl::find_and_erase(m_classes, pClassDesc);
  128. stl::member_find_and_erase(m_guidToClass, pClassDesc->ClassID());
  129. stl::member_find_and_erase(m_nameToClass, pClassDesc->ClassName());
  130. }
  131. void CClassFactory::UnregisterClass(const GUID& rClassID)
  132. {
  133. IClassDesc* pClassDesc = FindClass(rClassID);
  134. if (!pClassDesc)
  135. {
  136. return;
  137. }
  138. #if defined(DEBUG_CLASS_NAME_REGISTRATION)
  139. stl::find_and_erase(m_debugClassNames, pClassDesc->ClassName());
  140. #endif // DEBUG_CLASS_NAME_REGISTRATION
  141. stl::find_and_erase(m_classes, pClassDesc);
  142. stl::member_find_and_erase(m_guidToClass, pClassDesc->ClassID());
  143. stl::member_find_and_erase(m_nameToClass, pClassDesc->ClassName());
  144. }
  145. bool ClassDescNameCompare(IClassDesc* pArg1, IClassDesc* pArg2)
  146. {
  147. return (QString::compare(pArg1->ClassName(), pArg2->ClassName(), Qt::CaseInsensitive) < 0);
  148. }
  149. void CClassFactory::GetClassesBySystemID(ESystemClassID aSystemClassID, std::vector<IClassDesc*>& rOutClasses)
  150. {
  151. rOutClasses.clear();
  152. for (size_t i = 0; i < m_classes.size(); ++i)
  153. {
  154. if (m_classes[i]->SystemClassID() == aSystemClassID)
  155. {
  156. rOutClasses.push_back(m_classes[i]);
  157. }
  158. }
  159. std::sort(rOutClasses.begin(), rOutClasses.end(), ClassDescNameCompare);
  160. }
  161. void CClassFactory::GetClassesByCategory(const char* pCategory, std::vector<IClassDesc*>& rOutClasses)
  162. {
  163. rOutClasses.clear();
  164. for (size_t i = 0; i < m_classes.size(); ++i)
  165. {
  166. if (!QString::compare(pCategory, m_classes[i]->Category(), Qt::CaseInsensitive))
  167. {
  168. rOutClasses.push_back(m_classes[i]);
  169. }
  170. }
  171. std::sort(rOutClasses.begin(), rOutClasses.end(), ClassDescNameCompare);
  172. }