APITemplates.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // Copyright (c) 2008-2022 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../AngelScript/Addons.h"
  5. #include "../AngelScript/Script.h"
  6. #include "../AngelScript/ScriptInstance.h"
  7. #include "../Audio/SoundSource.h"
  8. #include "../Core/Context.h"
  9. #include "../Container/HashSet.h"
  10. #include "../Container/Sort.h"
  11. #include "../Graphics/Drawable.h"
  12. #include "../Graphics/StaticModel.h"
  13. #include "../GraphicsAPI/Texture.h"
  14. #include "../IO/File.h"
  15. #include "../IO/Log.h"
  16. #include "../IO/VectorBuffer.h"
  17. #include "../Resource/Resource.h"
  18. #include "../Scene/Animatable.h"
  19. #include "../Scene/Node.h"
  20. #include "../UI/BorderImage.h"
  21. #ifdef URHO3D_URHO2D
  22. #include "../Urho2D/Drawable2D.h"
  23. #endif
  24. #include <AngelScript/angelscript.h>
  25. #include <cstring>
  26. #include "../AngelScript/RegistrationMacros.h"
  27. #ifdef _MSC_VER
  28. #pragma warning(push)
  29. #pragma warning(disable:4505)
  30. #endif
  31. namespace Urho3D
  32. {
  33. class Camera;
  34. /// Template function for Vector to array conversion.
  35. template <class T> CScriptArray* VectorToArray(const Vector<T>& vector, const char* arrayName)
  36. {
  37. Context* context = GetScriptContext();
  38. if (context)
  39. {
  40. asITypeInfo* type = context->GetSubsystem<Script>()->GetObjectType(arrayName);
  41. CScriptArray* arr = CScriptArray::Create(type, vector.Size());
  42. for (unsigned i = 0; i < arr->GetSize(); ++i)
  43. *(static_cast<T*>(arr->At(i))) = vector[i];
  44. return arr;
  45. }
  46. else
  47. return nullptr;
  48. }
  49. /// Template function for data buffer to array conversion.
  50. template <class T> CScriptArray* BufferToArray(const T* buffer, unsigned size, const char* arrayName)
  51. {
  52. Context* context = GetScriptContext();
  53. if (context)
  54. {
  55. asITypeInfo* type = context->GetSubsystem<Script>()->GetObjectType(arrayName);
  56. CScriptArray* arr = CScriptArray::Create(type, size);
  57. for (unsigned i = 0; i < arr->GetSize(); ++i)
  58. *(static_cast<T*>(arr->At(i))) = buffer[i];
  59. return arr;
  60. }
  61. else
  62. return nullptr;
  63. }
  64. /// Template function for Vector to handle array conversion.
  65. template <class T> CScriptArray* VectorToHandleArray(const Vector<T*>& vector, const char* arrayName)
  66. {
  67. Context* context = GetScriptContext();
  68. if (context)
  69. {
  70. asITypeInfo* type = context->GetSubsystem<Script>()->GetObjectType(arrayName);
  71. CScriptArray* arr = CScriptArray::Create(type, vector.Size());
  72. for (unsigned i = 0; i < arr->GetSize(); ++i)
  73. {
  74. // Increment reference count for storing in the array
  75. T* ptr = vector[i];
  76. if (ptr)
  77. ptr->AddRef();
  78. *(static_cast<T**>(arr->At(i))) = ptr;
  79. }
  80. return arr;
  81. }
  82. else
  83. return nullptr;
  84. }
  85. /// Template function for shared pointer Vector to handle array conversion.
  86. template <class T> CScriptArray* VectorToHandleArray(const Vector<SharedPtr<T>>& vector, const char* arrayName)
  87. {
  88. Context* context = GetScriptContext();
  89. if (!context)
  90. return nullptr;
  91. asITypeInfo* type = context->GetSubsystem<Script>()->GetObjectType(arrayName);
  92. CScriptArray* arr = CScriptArray::Create(type, vector.Size());
  93. for (unsigned i = 0; i < arr->GetSize(); ++i)
  94. {
  95. // Increment reference count for storing in the array
  96. T* ptr = vector[i];
  97. if (ptr)
  98. ptr->AddRef();
  99. *(static_cast<T**>(arr->At(i))) = ptr;
  100. }
  101. return arr;
  102. }
  103. /// Template function for array to Vector conversion.
  104. template <class T> Vector<T> ArrayToVector(CScriptArray* arr)
  105. {
  106. Vector<T> dest(arr ? arr->GetSize() : 0);
  107. if (arr)
  108. {
  109. for (unsigned i = 0; i < arr->GetSize(); ++i)
  110. dest[i] = *static_cast<T*>(arr->At(i));
  111. }
  112. return dest;
  113. }
  114. template <class T> Vector<SharedPtr<T>> HandleArrayToVector(CScriptArray* arr)
  115. {
  116. Vector<T*> rawPtrs = ArrayToVector<T*>(arr);
  117. Vector<SharedPtr<T>> result(rawPtrs.Size());
  118. for (unsigned i = 0; i < rawPtrs.Size(); ++i)
  119. result[i] = SharedPtr<T>(rawPtrs[i]);
  120. return result;
  121. }
  122. /// Template function for dynamic cast between two script classes.
  123. template <class From, class To> To* RefCast(From* from)
  124. {
  125. if (!from)
  126. return nullptr;
  127. return dynamic_cast<To*>(from);
  128. }
  129. /// Template function for registering casts between base and subclass.
  130. // https://www.angelcode.com/angelscript/sdk/docs/manual/doc_adv_class_hierarchy.html
  131. template <class BaseType, class DerivedType> void RegisterSubclass(asIScriptEngine* engine, const char* baseClassName, const char* derivedClassName)
  132. {
  133. if (!strcmp(baseClassName, derivedClassName))
  134. return;
  135. String declReturnBase = String(baseClassName) +
  136. ((engine->GetTypeInfoByName(baseClassName)->GetFlags() & asOBJ_NOCOUNT) ? "@" : "@+") +
  137. " opImplCast()";
  138. engine->RegisterObjectMethod(derivedClassName, declReturnBase.CString(), AS_FUNCTION_OBJLAST((RefCast<DerivedType, BaseType>)), AS_CALL_CDECL_OBJLAST);
  139. String declReturnBaseConst("const " + declReturnBase + " const");
  140. engine->RegisterObjectMethod(derivedClassName, declReturnBaseConst.CString(), AS_FUNCTION_OBJLAST((RefCast<DerivedType, BaseType>)), AS_CALL_CDECL_OBJLAST);
  141. //String declReturnDerived(String(derivedClassName) + "@+ opCast()");
  142. String declReturnDerived(String(derivedClassName) +
  143. ((engine->GetTypeInfoByName(derivedClassName)->GetFlags() & asOBJ_NOCOUNT) ? "@" : "@+") +
  144. " opImplCast()");
  145. engine->RegisterObjectMethod(baseClassName, declReturnDerived.CString(), AS_FUNCTION_OBJLAST((RefCast<BaseType, DerivedType>)), AS_CALL_CDECL_OBJLAST);
  146. //String declReturnDerivedConst("const " + String(derivedClassName) + "@+ opCast() const");
  147. String declReturnDerivedConst("const " + declReturnDerived + " const");
  148. engine->RegisterObjectMethod(baseClassName, declReturnDerivedConst.CString(), AS_FUNCTION_OBJLAST((RefCast<BaseType, DerivedType>)), AS_CALL_CDECL_OBJLAST);
  149. }
  150. // ================================================================================
  151. // TODO Incorrect
  152. // Template function for dynamic cast between two script value classes.
  153. template <class SrcClass, class DstClass> DstClass* ValCast(SrcClass* src)
  154. {
  155. if (!src)
  156. return nullptr;
  157. return dynamic_cast<DstClass*>(src);
  158. }
  159. template <class baseClass, class subclass> void RegisterSubclassValue(asIScriptEngine* engine, const char* baseClassName, const char* subclassName)
  160. {
  161. assert(!strcmp(baseClassName, subclassName));
  162. String decl(String(baseClassName) + " opImplConvCast() const");
  163. engine->RegisterObjectMethod(subclassName, decl.CString(), asFUNCTION((ValCast<subclass, baseClass>)), asCALL_CDECL_OBJLAST);
  164. }
  165. // ================================================================================
  166. // https://en.cppreference.com/w/cpp/types/enable_if
  167. // We need detect implicitly-declared assign operator on complie time because Doxygen not povide this information
  168. template<typename classType, typename std::enable_if<std::is_copy_assignable<classType>::value, int>::type = 0>
  169. void RegisterImplicitlyDeclaredAssignOperatorIfPossible(asIScriptEngine* engine, const String& className)
  170. {
  171. String decl = className + "& opAssign(const " + className + "&in)";
  172. engine->RegisterObjectMethod(className.CString(), decl.CString(), AS_METHODPR(classType, operator=, (const classType&), classType&), AS_CALL_THISCALL);
  173. }
  174. // This empty function need to prevent build errors when classType have no assing operator
  175. template<typename classType, typename std::enable_if<!std::is_copy_assignable<classType>::value, int>::type = 0>
  176. void RegisterImplicitlyDeclaredAssignOperatorIfPossible(asIScriptEngine* engine, const String& className)
  177. {
  178. }
  179. // ================================================================================
  180. // To keep Xcode LLVM/Clang happy - it erroneously warns on unused functions defined below which are actually being referenced in the code
  181. #if __clang__
  182. #pragma clang diagnostic push
  183. #pragma clang diagnostic ignored "-Wunused-function"
  184. #endif
  185. template <class T> T* ConstructObject()
  186. {
  187. auto* object = new T(GetScriptContext());
  188. object->AddRef();
  189. return object;
  190. }
  191. template <class T> T* ConstructNamedObject(const String& name)
  192. {
  193. auto* object = new T(GetScriptContext());
  194. object->AddRef();
  195. object->SetName(name);
  196. return object;
  197. }
  198. /// Template function for registering a default constructor for a class derived from Object.
  199. template <class T> void RegisterObjectConstructor(asIScriptEngine* engine, const char* className)
  200. {
  201. String declFactory(String(className) + "@ f()");
  202. engine->RegisterObjectBehaviour(className, asBEHAVE_FACTORY, declFactory.CString(), AS_FUNCTION(ConstructObject<T>), AS_CALL_CDECL);
  203. }
  204. /// Template function for registering a named constructor for a class derived from Object.
  205. template <class T> void RegisterNamedObjectConstructor(asIScriptEngine* engine, const char* className)
  206. {
  207. String declFactoryWithName(String(className) + "@ f(const String&in)");
  208. engine->RegisterObjectBehaviour(className, asBEHAVE_FACTORY, declFactoryWithName.CString(), AS_FUNCTION(ConstructNamedObject<T>), AS_CALL_CDECL);
  209. }
  210. #if __clang__
  211. #pragma clang diagnostic pop
  212. #endif
  213. }
  214. #ifdef _MSC_VER
  215. #pragma warning(pop)
  216. #endif