APITemplates.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Copyright (c) 2008-2023 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 (asUINT 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, asUINT size, const char* arrayName)
  51. {
  52. assert(size <= M_MAX_I32);
  53. Context* context = GetScriptContext();
  54. if (context)
  55. {
  56. asITypeInfo* type = context->GetSubsystem<Script>()->GetObjectType(arrayName);
  57. CScriptArray* arr = CScriptArray::Create(type, size);
  58. for (asUINT i = 0; i < arr->GetSize(); ++i)
  59. *(static_cast<T*>(arr->At(i))) = buffer[i];
  60. return arr;
  61. }
  62. else
  63. return nullptr;
  64. }
  65. /// Template function for Vector to handle array conversion.
  66. template <class T> CScriptArray* VectorToHandleArray(const Vector<T*>& vector, const char* arrayName)
  67. {
  68. Context* context = GetScriptContext();
  69. if (context)
  70. {
  71. asITypeInfo* type = context->GetSubsystem<Script>()->GetObjectType(arrayName);
  72. CScriptArray* arr = CScriptArray::Create(type, vector.Size());
  73. for (asUINT i = 0; i < arr->GetSize(); ++i)
  74. {
  75. // Increment reference count for storing in the array
  76. T* ptr = vector[i];
  77. if (ptr)
  78. ptr->AddRef();
  79. *(static_cast<T**>(arr->At(i))) = ptr;
  80. }
  81. return arr;
  82. }
  83. else
  84. return nullptr;
  85. }
  86. /// Template function for shared pointer Vector to handle array conversion.
  87. template <class T> CScriptArray* VectorToHandleArray(const Vector<SharedPtr<T>>& vector, const char* arrayName)
  88. {
  89. Context* context = GetScriptContext();
  90. if (!context)
  91. return nullptr;
  92. asITypeInfo* type = context->GetSubsystem<Script>()->GetObjectType(arrayName);
  93. CScriptArray* arr = CScriptArray::Create(type, vector.Size());
  94. for (asUINT i = 0; i < arr->GetSize(); ++i)
  95. {
  96. // Increment reference count for storing in the array
  97. T* ptr = vector[i];
  98. if (ptr)
  99. ptr->AddRef();
  100. *(static_cast<T**>(arr->At(i))) = ptr;
  101. }
  102. return arr;
  103. }
  104. /// Template function for array to Vector conversion.
  105. template <class T> Vector<T> ArrayToVector(CScriptArray* arr)
  106. {
  107. Vector<T> dest(arr ? arr->GetSize() : 0);
  108. if (arr)
  109. {
  110. for (asUINT i = 0; i < arr->GetSize(); ++i)
  111. dest[i] = *static_cast<T*>(arr->At(i));
  112. }
  113. return dest;
  114. }
  115. template <class T> Vector<SharedPtr<T>> HandleArrayToVector(CScriptArray* arr)
  116. {
  117. Vector<T*> rawPtrs = ArrayToVector<T*>(arr);
  118. Vector<SharedPtr<T>> result(rawPtrs.Size());
  119. for (i32 i = 0; i < rawPtrs.Size(); ++i)
  120. result[i] = SharedPtr<T>(rawPtrs[i]);
  121. return result;
  122. }
  123. /// Template function for dynamic cast between two script classes.
  124. template <class From, class To> To* RefCast(From* from)
  125. {
  126. if (!from)
  127. return nullptr;
  128. return dynamic_cast<To*>(from);
  129. }
  130. /// Template function for registering casts between base and subclass.
  131. // https://www.angelcode.com/angelscript/sdk/docs/manual/doc_adv_class_hierarchy.html
  132. template <class BaseType, class DerivedType> void RegisterSubclass(asIScriptEngine* engine, const char* baseClassName, const char* derivedClassName)
  133. {
  134. if (!strcmp(baseClassName, derivedClassName))
  135. return;
  136. String declReturnBase = String(baseClassName) +
  137. ((engine->GetTypeInfoByName(baseClassName)->GetFlags() & asOBJ_NOCOUNT) ? "@" : "@+") +
  138. " opImplCast()";
  139. engine->RegisterObjectMethod(derivedClassName, declReturnBase.CString(), AS_FUNCTION_OBJLAST((RefCast<DerivedType, BaseType>)), AS_CALL_CDECL_OBJLAST);
  140. String declReturnBaseConst("const " + declReturnBase + " const");
  141. engine->RegisterObjectMethod(derivedClassName, declReturnBaseConst.CString(), AS_FUNCTION_OBJLAST((RefCast<DerivedType, BaseType>)), AS_CALL_CDECL_OBJLAST);
  142. //String declReturnDerived(String(derivedClassName) + "@+ opCast()");
  143. String declReturnDerived(String(derivedClassName) +
  144. ((engine->GetTypeInfoByName(derivedClassName)->GetFlags() & asOBJ_NOCOUNT) ? "@" : "@+") +
  145. " opImplCast()");
  146. engine->RegisterObjectMethod(baseClassName, declReturnDerived.CString(), AS_FUNCTION_OBJLAST((RefCast<BaseType, DerivedType>)), AS_CALL_CDECL_OBJLAST);
  147. //String declReturnDerivedConst("const " + String(derivedClassName) + "@+ opCast() const");
  148. String declReturnDerivedConst("const " + declReturnDerived + " const");
  149. engine->RegisterObjectMethod(baseClassName, declReturnDerivedConst.CString(), AS_FUNCTION_OBJLAST((RefCast<BaseType, DerivedType>)), AS_CALL_CDECL_OBJLAST);
  150. }
  151. // ================================================================================
  152. // TODO Incorrect
  153. // Template function for dynamic cast between two script value classes.
  154. template <class SrcClass, class DstClass> DstClass* ValCast(SrcClass* src)
  155. {
  156. if (!src)
  157. return nullptr;
  158. return dynamic_cast<DstClass*>(src);
  159. }
  160. template <class baseClass, class subclass> void RegisterSubclassValue(asIScriptEngine* engine, const char* baseClassName, const char* subclassName)
  161. {
  162. assert(!strcmp(baseClassName, subclassName));
  163. String decl(String(baseClassName) + " opImplConvCast() const");
  164. engine->RegisterObjectMethod(subclassName, decl.CString(), asFUNCTION((ValCast<subclass, baseClass>)), asCALL_CDECL_OBJLAST);
  165. }
  166. // ================================================================================
  167. // https://en.cppreference.com/w/cpp/types/enable_if
  168. // We need detect implicitly-declared assign operator on complie time because Doxygen not povide this information
  169. template<typename classType, typename std::enable_if<std::is_copy_assignable<classType>::value, int>::type = 0>
  170. void RegisterImplicitlyDeclaredAssignOperatorIfPossible(asIScriptEngine* engine, const String& className)
  171. {
  172. String decl = className + "& opAssign(const " + className + "&in)";
  173. engine->RegisterObjectMethod(className.CString(), decl.CString(), AS_METHODPR(classType, operator=, (const classType&), classType&), AS_CALL_THISCALL);
  174. }
  175. // This empty function need to prevent build errors when classType have no assing operator
  176. template<typename classType, typename std::enable_if<!std::is_copy_assignable<classType>::value, int>::type = 0>
  177. void RegisterImplicitlyDeclaredAssignOperatorIfPossible(asIScriptEngine* engine, const String& className)
  178. {
  179. }
  180. // ================================================================================
  181. // To keep Xcode LLVM/Clang happy - it erroneously warns on unused functions defined below which are actually being referenced in the code
  182. #if __clang__
  183. #pragma clang diagnostic push
  184. #pragma clang diagnostic ignored "-Wunused-function"
  185. #endif
  186. template <class T> T* ConstructObject()
  187. {
  188. auto* object = new T(GetScriptContext());
  189. object->AddRef();
  190. return object;
  191. }
  192. template <class T> T* ConstructNamedObject(const String& name)
  193. {
  194. auto* object = new T(GetScriptContext());
  195. object->AddRef();
  196. object->SetName(name);
  197. return object;
  198. }
  199. /// Template function for registering a default constructor for a class derived from Object.
  200. template <class T> void RegisterObjectConstructor(asIScriptEngine* engine, const char* className)
  201. {
  202. String declFactory(String(className) + "@ f()");
  203. engine->RegisterObjectBehaviour(className, asBEHAVE_FACTORY, declFactory.CString(), AS_FUNCTION(ConstructObject<T>), AS_CALL_CDECL);
  204. }
  205. /// Template function for registering a named constructor for a class derived from Object.
  206. template <class T> void RegisterNamedObjectConstructor(asIScriptEngine* engine, const char* className)
  207. {
  208. String declFactoryWithName(String(className) + "@ f(const String&in)");
  209. engine->RegisterObjectBehaviour(className, asBEHAVE_FACTORY, declFactoryWithName.CString(), AS_FUNCTION(ConstructNamedObject<T>), AS_CALL_CDECL);
  210. }
  211. #if __clang__
  212. #pragma clang diagnostic pop
  213. #endif
  214. }
  215. #ifdef _MSC_VER
  216. #pragma warning(pop)
  217. #endif