2
0

BsRuntimeScriptObjects.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #include "BsRuntimeScriptObjects.h"
  2. #include "BsScriptResourceManager.h"
  3. #include "BsScriptGameObjectManager.h"
  4. #include "BsScriptSerializableObjectInfo.h"
  5. #include "BsMonoManager.h"
  6. #include "BsMonoAssembly.h"
  7. #include "BsMonoClass.h"
  8. #include "BsMonoField.h"
  9. #include "BsMonoUtil.h"
  10. #include "CmRTTIType.h"
  11. using namespace CamelotFramework;
  12. namespace BansheeEngine
  13. {
  14. RuntimeScriptObjects::RuntimeScriptObjects()
  15. :mBaseTypesInitialized(false), mSerializableAttribute(nullptr), mNonSerializedAttribute(nullptr),
  16. mComponentClass(nullptr), mSceneObjectClass(nullptr), mTextureClass(nullptr), mSpriteTextureClass(nullptr),
  17. mSerializeFieldAttribute(nullptr), mHideInInspectorAttribute(nullptr), mSystemArrayClass(nullptr)
  18. {
  19. }
  20. RuntimeScriptObjects::~RuntimeScriptObjects()
  21. {
  22. }
  23. void RuntimeScriptObjects::refreshScriptObjects(const String& assemblyName)
  24. {
  25. clearScriptObjects(assemblyName);
  26. if(!mBaseTypesInitialized)
  27. initializeBaseTypes();
  28. // Process all classes and fields
  29. CM::UINT32 mUniqueTypeId = 1;
  30. MonoAssembly* curAssembly = MonoManager::instance().getAssembly(assemblyName);
  31. if(curAssembly == nullptr)
  32. return;
  33. std::shared_ptr<ScriptSerializableAssemblyInfo> assemblyInfo = cm_shared_ptr<ScriptSerializableAssemblyInfo>();
  34. assemblyInfo->mName = assemblyName;
  35. mAssemblyInfos[assemblyName] = assemblyInfo;
  36. // Populate class data
  37. const Vector<MonoClass*>::type& allClasses = curAssembly->getAllClasses();
  38. for(auto& curClass : allClasses)
  39. {
  40. if((curClass->isSubClassOf(mComponentClass) || curClass->hasAttribute(mSerializableAttribute)) && curClass != mComponentClass)
  41. {
  42. ScriptSerializableTypeInfoPtr typeInfo = determineType(curClass);
  43. if(rtti_is_of_type<ScriptSerializableTypeInfoObject>(typeInfo))
  44. {
  45. std::shared_ptr<ScriptSerializableObjectInfo> objInfo = cm_shared_ptr<ScriptSerializableObjectInfo>();
  46. objInfo->mTypeId = mUniqueTypeId++;
  47. objInfo->mTypeInfo = std::static_pointer_cast<ScriptSerializableTypeInfoObject>(typeInfo);
  48. objInfo->mMonoClass = curClass;
  49. assemblyInfo->mTypeNameToId[objInfo->getFullTypeName()] = objInfo->mTypeId;
  50. assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
  51. }
  52. }
  53. }
  54. // Populate field data
  55. for(auto& curClassInfo : assemblyInfo->mObjectInfos)
  56. {
  57. std::shared_ptr<ScriptSerializableObjectInfo> objInfo = curClassInfo.second;
  58. String fullTypeName = objInfo->getFullTypeName();
  59. assemblyInfo->mTypeNameToId[fullTypeName] = objInfo->mTypeId;
  60. assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
  61. CM::UINT32 mUniqueFieldId = 1;
  62. const CM::Vector<MonoField*>::type& fields = objInfo->mMonoClass->getAllFields();
  63. for(auto& field : fields)
  64. {
  65. if(field->isStatic())
  66. continue;
  67. std::shared_ptr<ScriptSerializableFieldInfo> fieldInfo = cm_shared_ptr<ScriptSerializableFieldInfo>();
  68. fieldInfo->mFieldId = mUniqueFieldId++;
  69. fieldInfo->mName = field->getName();
  70. fieldInfo->mMonoField = field;
  71. fieldInfo->mTypeInfo = determineType(field->getType());
  72. if(fieldInfo->mTypeInfo != nullptr)
  73. {
  74. MonoFieldVisibility visibility = field->getVisibility();
  75. if(visibility == MonoFieldVisibility::Public)
  76. {
  77. if(!field->hasAttribute(mNonSerializedAttribute))
  78. fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
  79. if(!field->hasAttribute(mHideInInspectorAttribute))
  80. fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Inspectable);
  81. }
  82. else
  83. {
  84. if(field->hasAttribute(mSerializeFieldAttribute))
  85. fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
  86. }
  87. }
  88. objInfo->mFieldNameToId[fieldInfo->mName] = fieldInfo->mFieldId;
  89. objInfo->mFields[fieldInfo->mFieldId] = fieldInfo;
  90. }
  91. }
  92. // Form parent/child connections
  93. for(auto& curClass : assemblyInfo->mObjectInfos)
  94. {
  95. MonoClass* base = curClass.second->mMonoClass->getBaseClass();
  96. while(base != nullptr)
  97. {
  98. std::shared_ptr<ScriptSerializableObjectInfo> baseObjInfo;
  99. if(getSerializableObjectInfo(base->getNamespace(), base->getTypeName(), baseObjInfo))
  100. {
  101. curClass.second->mBaseClass = baseObjInfo;
  102. baseObjInfo->mDerivedClasses.push_back(curClass.second);
  103. break;
  104. }
  105. base = base->getBaseClass();
  106. }
  107. }
  108. }
  109. ScriptSerializableTypeInfoPtr RuntimeScriptObjects::determineType(MonoClass* monoClass)
  110. {
  111. if(!mBaseTypesInitialized)
  112. CM_EXCEPT(InvalidStateException, "Calling determineType without previously initializing base types.");
  113. MonoType* monoType = mono_class_get_type(monoClass->_getInternalClass());
  114. int monoPrimitiveType = mono_type_get_type(monoType);
  115. // Determine field type
  116. switch(monoPrimitiveType)
  117. {
  118. case MONO_TYPE_BOOLEAN:
  119. {
  120. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  121. typeInfo->mType = ScriptPrimitiveType::Bool;
  122. return typeInfo;
  123. }
  124. case MONO_TYPE_CHAR:
  125. {
  126. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  127. typeInfo->mType = ScriptPrimitiveType::Char;
  128. return typeInfo;
  129. }
  130. case MONO_TYPE_I1:
  131. {
  132. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  133. typeInfo->mType = ScriptPrimitiveType::I8;
  134. return typeInfo;
  135. }
  136. case MONO_TYPE_U1:
  137. {
  138. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  139. typeInfo->mType = ScriptPrimitiveType::U8;
  140. return typeInfo;
  141. }
  142. case MONO_TYPE_I2:
  143. {
  144. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  145. typeInfo->mType = ScriptPrimitiveType::I16;
  146. return typeInfo;
  147. }
  148. case MONO_TYPE_U2:
  149. {
  150. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  151. typeInfo->mType = ScriptPrimitiveType::U16;
  152. return typeInfo;
  153. }
  154. case MONO_TYPE_I4:
  155. {
  156. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  157. typeInfo->mType = ScriptPrimitiveType::I32;
  158. return typeInfo;
  159. }
  160. case MONO_TYPE_U4:
  161. {
  162. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  163. typeInfo->mType = ScriptPrimitiveType::U32;
  164. return typeInfo;
  165. }
  166. case MONO_TYPE_I8:
  167. {
  168. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  169. typeInfo->mType = ScriptPrimitiveType::I64;
  170. return typeInfo;
  171. }
  172. case MONO_TYPE_U8:
  173. {
  174. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  175. typeInfo->mType = ScriptPrimitiveType::U64;
  176. return typeInfo;
  177. }
  178. case MONO_TYPE_STRING:
  179. {
  180. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  181. typeInfo->mType = ScriptPrimitiveType::String;
  182. return typeInfo;
  183. }
  184. case MONO_TYPE_R4:
  185. {
  186. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  187. typeInfo->mType = ScriptPrimitiveType::Float;
  188. return typeInfo;
  189. }
  190. case MONO_TYPE_R8:
  191. {
  192. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  193. typeInfo->mType = ScriptPrimitiveType::Double;
  194. return typeInfo;
  195. }
  196. case MONO_TYPE_CLASS:
  197. if(monoClass->isSubClassOf(mTextureClass))
  198. {
  199. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  200. typeInfo->mType = ScriptPrimitiveType::TextureRef;
  201. return typeInfo;
  202. }
  203. else if(monoClass->isSubClassOf(mSpriteTextureClass))
  204. {
  205. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  206. typeInfo->mType = ScriptPrimitiveType::SpriteTextureRef;
  207. return typeInfo;
  208. }
  209. else if(monoClass->isSubClassOf(mSceneObjectClass))
  210. {
  211. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  212. typeInfo->mType = ScriptPrimitiveType::SceneObjectRef;
  213. return typeInfo;
  214. }
  215. else if(monoClass->isSubClassOf(mComponentClass))
  216. {
  217. std::shared_ptr<ScriptSerializableTypeInfoPrimitive> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoPrimitive>();
  218. typeInfo->mType = ScriptPrimitiveType::ComponentRef;
  219. return typeInfo;
  220. }
  221. else
  222. {
  223. if(hasSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName()))
  224. {
  225. std::shared_ptr<ScriptSerializableTypeInfoObject> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoObject>();
  226. typeInfo->mTypeNamespace = monoClass->getNamespace();
  227. typeInfo->mTypeName = monoClass->getTypeName();
  228. typeInfo->mValueType = false;
  229. return typeInfo;
  230. }
  231. else
  232. {
  233. // TODO - Later check for List or Dictionary here
  234. }
  235. }
  236. break;
  237. case MONO_TYPE_VALUETYPE:
  238. if(hasSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName()))
  239. {
  240. std::shared_ptr<ScriptSerializableTypeInfoObject> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoObject>();
  241. typeInfo->mTypeNamespace = monoClass->getNamespace();
  242. typeInfo->mTypeName = monoClass->getTypeName();
  243. typeInfo->mValueType = true;
  244. return typeInfo;
  245. }
  246. break;
  247. case MONO_TYPE_ARRAY:
  248. {
  249. std::shared_ptr<ScriptSerializableTypeInfoArray> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoArray>();
  250. ::MonoClass* elementClass = mono_class_get_element_class(monoClass->_getInternalClass());
  251. if(elementClass != nullptr)
  252. {
  253. monoType = mono_class_get_type(elementClass);
  254. monoPrimitiveType = mono_type_get_type(monoType);
  255. ::MonoClass* elementClass = mono_type_get_class(monoType);
  256. String elementNs = mono_class_get_namespace(elementClass);
  257. String elementTypeName = mono_class_get_name(elementClass);
  258. MonoClass* monoElementClass = MonoManager::instance().findClass(elementNs, elementTypeName);
  259. if(monoElementClass != nullptr)
  260. typeInfo->mElementType = determineType(monoElementClass);
  261. }
  262. typeInfo->mRank = (UINT32)mono_class_get_rank(monoClass->_getInternalClass());
  263. return typeInfo;
  264. }
  265. }
  266. return nullptr;
  267. }
  268. void RuntimeScriptObjects::clearScriptObjects(const CM::String& assemblyName)
  269. {
  270. mAssemblyInfos.erase(assemblyName);
  271. mBaseTypesInitialized = false;
  272. mSystemArrayClass = nullptr;
  273. mSerializableAttribute = nullptr;
  274. mNonSerializedAttribute = nullptr;
  275. mComponentClass = nullptr;
  276. mSceneObjectClass = nullptr;
  277. mTextureClass = nullptr;
  278. mSpriteTextureClass = nullptr;
  279. mSerializeFieldAttribute = nullptr;
  280. mHideInInspectorAttribute = nullptr;
  281. }
  282. void RuntimeScriptObjects::initializeBaseTypes()
  283. {
  284. // Get necessary classes for detecting needed class & field information
  285. MonoAssembly* mscorlib = MonoManager::instance().getAssembly("mscorlib");
  286. if(mscorlib == nullptr)
  287. CM_EXCEPT(InvalidStateException, "mscorlib assembly is not loaded.");
  288. MonoAssembly* bansheeEngineAssembly = MonoManager::instance().getAssembly(BansheeEngineAssemblyName);
  289. if(bansheeEngineAssembly == nullptr)
  290. CM_EXCEPT(InvalidStateException, String(BansheeEngineAssemblyName) + " assembly is not loaded.");
  291. mSystemArrayClass = mscorlib->getClass("System", "Array");
  292. if(mSystemArrayClass == nullptr)
  293. CM_EXCEPT(InvalidStateException, "Cannot find System.Array managed class.");
  294. mSerializableAttribute = mscorlib->getClass("System", "SerializableAttribute");
  295. if(mSerializableAttribute == nullptr)
  296. CM_EXCEPT(InvalidStateException, "Cannot find SerializableAttribute managed class.");
  297. mNonSerializedAttribute = mscorlib->getClass("System", "NonSerializedAttribute");
  298. if(mNonSerializedAttribute == nullptr)
  299. CM_EXCEPT(InvalidStateException, "Cannot find NonSerializedAttribute managed class.");
  300. mComponentClass = bansheeEngineAssembly->getClass("BansheeEngine", "Component");
  301. if(mComponentClass == nullptr)
  302. CM_EXCEPT(InvalidStateException, "Cannot find Component managed class.");
  303. mSceneObjectClass = bansheeEngineAssembly->getClass("BansheeEngine", "SceneObject");
  304. if(mSceneObjectClass == nullptr)
  305. CM_EXCEPT(InvalidStateException, "Cannot find SceneObject managed class.");
  306. mTextureClass = bansheeEngineAssembly->getClass("BansheeEngine", "Texture2D");
  307. if(mTextureClass == nullptr)
  308. CM_EXCEPT(InvalidStateException, "Cannot find Texture2D managed class.");
  309. mSpriteTextureClass = bansheeEngineAssembly->getClass("BansheeEngine", "SpriteTexture");
  310. if(mSpriteTextureClass == nullptr)
  311. CM_EXCEPT(InvalidStateException, "Cannot find SpriteTexture managed class.");
  312. mSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeField");
  313. if(mSerializeFieldAttribute == nullptr)
  314. CM_EXCEPT(InvalidStateException, "Cannot find SerializeField managed class.");
  315. mHideInInspectorAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "HideInInspector");
  316. if(mHideInInspectorAttribute == nullptr)
  317. CM_EXCEPT(InvalidStateException, "Cannot find HideInInspector managed class.");
  318. mBaseTypesInitialized = true;
  319. }
  320. bool RuntimeScriptObjects::getSerializableObjectInfo(const CM::String& ns, const CM::String& typeName, std::shared_ptr<ScriptSerializableObjectInfo>& outInfo)
  321. {
  322. String fullName = ns + "." + typeName;
  323. for(auto& curAssembly : mAssemblyInfos)
  324. {
  325. auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
  326. if(iterFind != curAssembly.second->mTypeNameToId.end())
  327. {
  328. outInfo = curAssembly.second->mObjectInfos[iterFind->second];
  329. return true;
  330. }
  331. }
  332. return false;
  333. }
  334. bool RuntimeScriptObjects::hasSerializableObjectInfo(const CM::String& ns, const CM::String& typeName)
  335. {
  336. String fullName = ns + "." + typeName;
  337. for(auto& curAssembly : mAssemblyInfos)
  338. {
  339. auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
  340. if(iterFind != curAssembly.second->mTypeNameToId.end())
  341. return true;
  342. }
  343. return false;
  344. }
  345. bool RuntimeScriptObjects::isArray(MonoObject* object)
  346. {
  347. if(!mBaseTypesInitialized)
  348. CM_EXCEPT(InvalidStateException, "Calling isArray without previously initializing base types.");
  349. ::MonoClass* monoClass = mono_object_get_class(object);
  350. return mono_class_is_subclass_of(monoClass, mSystemArrayClass->_getInternalClass(), false) != 0;
  351. }
  352. }