BsScriptScriptCode.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Wrappers/BsScriptScriptCode.h"
  4. #include "BsScriptResourceManager.h"
  5. #include "BsScriptMeta.h"
  6. #include "BsMonoField.h"
  7. #include "BsMonoClass.h"
  8. #include "BsMonoManager.h"
  9. #include "BsMonoUtil.h"
  10. #include "Serialization/BsScriptAssemblyManager.h"
  11. #include "Serialization/BsManagedSerializableObjectInfo.h"
  12. #include <regex>
  13. using namespace std::placeholders;
  14. namespace bs
  15. {
  16. ScriptScriptCode::ScriptScriptCode(MonoObject* instance, const HScriptCode& scriptCode)
  17. :TScriptResource(instance, scriptCode)
  18. {
  19. }
  20. void ScriptScriptCode::initRuntimeData()
  21. {
  22. metaData.scriptClass->addInternalCall("Internal_CreateInstance", (void*)&ScriptScriptCode::internal_createInstance);
  23. metaData.scriptClass->addInternalCall("Internal_GetText", (void*)&ScriptScriptCode::internal_getText);
  24. metaData.scriptClass->addInternalCall("Internal_SetText", (void*)&ScriptScriptCode::internal_setText);
  25. metaData.scriptClass->addInternalCall("Internal_IsEditorScript", (void*)&ScriptScriptCode::internal_isEditorScript);
  26. metaData.scriptClass->addInternalCall("Internal_SetEditorScript", (void*)&ScriptScriptCode::internal_setEditorScript);
  27. metaData.scriptClass->addInternalCall("Internal_GetTypes", (void*)&ScriptScriptCode::internal_getTypes);
  28. }
  29. void ScriptScriptCode::internal_createInstance(MonoObject* instance, MonoString* text)
  30. {
  31. WString strText = MonoUtil::monoToWString(text);
  32. HScriptCode scriptCode = ScriptCode::create(strText);
  33. ScriptResourceManager::instance().createBuiltinScriptResource(scriptCode, instance);
  34. }
  35. MonoString* ScriptScriptCode::internal_getText(ScriptScriptCode* thisPtr)
  36. {
  37. HScriptCode scriptCode = thisPtr->getHandle();
  38. if (!scriptCode.isLoaded())
  39. MonoUtil::wstringToMono(L"");
  40. return MonoUtil::wstringToMono(scriptCode->getString());
  41. }
  42. void ScriptScriptCode::internal_setText(ScriptScriptCode* thisPtr, MonoString* text)
  43. {
  44. HScriptCode scriptCode = thisPtr->getHandle();
  45. if (!scriptCode.isLoaded())
  46. return;
  47. scriptCode->setString(MonoUtil::monoToWString(text));
  48. }
  49. bool ScriptScriptCode::internal_isEditorScript(ScriptScriptCode* thisPtr)
  50. {
  51. HScriptCode scriptCode = thisPtr->getHandle();
  52. if (!scriptCode.isLoaded())
  53. return false;
  54. return scriptCode->getIsEditorScript();
  55. }
  56. void ScriptScriptCode::internal_setEditorScript(ScriptScriptCode* thisPtr, bool value)
  57. {
  58. HScriptCode scriptCode = thisPtr->getHandle();
  59. if (!scriptCode.isLoaded())
  60. return;
  61. scriptCode->setIsEditorScript(value);
  62. }
  63. MonoArray* ScriptScriptCode::internal_getTypes(ScriptScriptCode* thisPtr)
  64. {
  65. HScriptCode scriptCode = thisPtr->getHandle();
  66. Vector<FullTypeName> types;
  67. if (scriptCode.isLoaded())
  68. types = parseTypes(scriptCode->getString());
  69. Vector<MonoReflectionType*> validTypes;
  70. for (auto& type : types)
  71. {
  72. SPtr<ManagedSerializableObjectInfo> objInfo;
  73. if (ScriptAssemblyManager::instance().getSerializableObjectInfo(toString(type.first), toString(type.second), objInfo))
  74. validTypes.push_back(MonoUtil::getType(objInfo->mTypeInfo->getMonoClass()));
  75. }
  76. UINT32 numValidTypes = (UINT32)validTypes.size();
  77. MonoClass* typeClass = ScriptAssemblyManager::instance().getSystemTypeClass();
  78. ScriptArray scriptArray(typeClass->_getInternalClass(), numValidTypes);
  79. for (UINT32 i = 0; i < numValidTypes; i++)
  80. scriptArray.set(i, validTypes[i]);
  81. return scriptArray.getInternal();
  82. }
  83. MonoObject* ScriptScriptCode::createInstance()
  84. {
  85. return metaData.scriptClass->createInstance();
  86. }
  87. Vector<ScriptScriptCode::FullTypeName> ScriptScriptCode::parseTypes(const WString& code)
  88. {
  89. struct NamespaceData
  90. {
  91. WString ns;
  92. INT32 bracketIdx;
  93. };
  94. Vector<FullTypeName> output;
  95. Stack<NamespaceData> namespaces;
  96. // TODO: Won't match non latin characters because C++ regex doesn't support unicode character classes
  97. // and writing out Unicode ranges for all the characters C# supports as identifiers is too tedious at the moment.
  98. // Classes that need to match: \p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\p{Cf}
  99. WString identifierPattern = LR"([_@a-zA-Z][_\da-zA-Z]*)";
  100. std::wregex identifierRegex(identifierPattern);
  101. WString nsToken = L"namespace";
  102. WString classToken = L"class";
  103. UINT32 idx = 0;
  104. INT32 bracketIdx = 0;
  105. for (auto iter = code.begin(); iter != code.end(); ++iter)
  106. {
  107. wchar_t ch = *iter;
  108. if (code.compare(idx, classToken.size(), classToken) == 0)
  109. {
  110. std::match_results<WString::const_iterator> results;
  111. if (std::regex_search(iter + classToken.size(), code.end(), results, identifierRegex))
  112. {
  113. WString ns = L"";
  114. if (!namespaces.empty())
  115. ns = namespaces.top().ns;
  116. std::wstring tempStr = results[0];
  117. WString typeName = tempStr.c_str();
  118. output.push_back(FullTypeName());
  119. FullTypeName& nsTypePair = output.back();
  120. nsTypePair.first = ns;
  121. nsTypePair.second = typeName;
  122. }
  123. }
  124. else if (code.compare(idx, nsToken.size(), nsToken) == 0)
  125. {
  126. std::match_results<WString::const_iterator> results;
  127. if (std::regex_search(iter + nsToken.size(), code.end(), results, identifierRegex))
  128. {
  129. std::wstring tempStr = results[0];
  130. WString ns = tempStr.c_str();
  131. namespaces.push({ ns, bracketIdx + 1 });
  132. }
  133. }
  134. else if (ch == '{')
  135. {
  136. bracketIdx++;
  137. }
  138. else if (ch == '}')
  139. {
  140. bracketIdx--;
  141. }
  142. idx++;
  143. }
  144. return output;
  145. }
  146. }