make_virtuals.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. proto = """
  2. #define GDVIRTUAL$VER($RET m_name $ARG) \\
  3. StringName _gdvirtual_##m_name##_sn = #m_name;\\
  4. GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
  5. _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
  6. ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
  7. if (script_instance) {\\
  8. Callable::CallError ce; \\
  9. $CALLSIARGS\\
  10. $CALLSIBEGINscript_instance->call(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
  11. if (ce.error == Callable::CallError::CALL_OK) {\\
  12. $CALLSIRET\\
  13. return true;\\
  14. } \\
  15. }\\
  16. if (_gdvirtual_##m_name) {\\
  17. $CALLPTRARGS\\
  18. $CALLPTRRETDEF\\
  19. _gdvirtual_##m_name(_get_extension_instance(),$CALLPTRARGPASS,$CALLPTRRETPASS);\\
  20. $CALLPTRRET\\
  21. return true;\\
  22. }\\
  23. \\
  24. return false;\\
  25. }\\
  26. _FORCE_INLINE_ bool _gdvirtual_##m_name##_overriden() const { \\
  27. ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
  28. if (script_instance) {\\
  29. return script_instance->has_method(_gdvirtual_##m_name##_sn);\\
  30. }\\
  31. if (_gdvirtual_##m_name) {\\
  32. return true;\\
  33. }\\
  34. return false;\\
  35. }\\
  36. \\
  37. _FORCE_INLINE_ static MethodInfo _gdvirtual_##m_name##_get_method_info() { \\
  38. MethodInfo method_info;\\
  39. method_info.name = #m_name;\\
  40. method_info.flags = METHOD_FLAG_VIRTUAL;\\
  41. $FILL_METHOD_INFO\\
  42. return method_info;\\
  43. }
  44. """
  45. def generate_version(argcount, const=False, returns=False):
  46. s = proto
  47. sproto = str(argcount)
  48. method_info = ""
  49. if returns:
  50. sproto += "R"
  51. s = s.replace("$RET", "m_ret, ")
  52. s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;")
  53. method_info += "\tmethod_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n"
  54. else:
  55. s = s.replace("$RET", "")
  56. s = s.replace("$CALLPTRRETDEF", "")
  57. if const:
  58. sproto += "C"
  59. s = s.replace("$CONST", "const")
  60. method_info += "\tmethod_info.flags|=METHOD_FLAG_CONST;\\\n"
  61. else:
  62. s = s.replace("$CONST", "")
  63. s = s.replace("$VER", sproto)
  64. argtext = ""
  65. callargtext = ""
  66. callsiargs = ""
  67. callsiargptrs = ""
  68. callptrargsptr = ""
  69. if argcount > 0:
  70. argtext += ", "
  71. callsiargs = "Variant vargs[" + str(argcount) + "]={"
  72. callsiargptrs = "\t\tconst Variant *vargptrs[" + str(argcount) + "]={"
  73. callptrargsptr = "\t\tconst GDNativeTypePtr argptrs[" + str(argcount) + "]={"
  74. callptrargs = ""
  75. for i in range(argcount):
  76. if i > 0:
  77. argtext += ", "
  78. callargtext += ", "
  79. callsiargs += ", "
  80. callsiargptrs += ", "
  81. callptrargs += "\t\t"
  82. callptrargsptr += ", "
  83. argtext += "m_type" + str(i + 1)
  84. callargtext += "m_type" + str(i + 1) + " arg" + str(i + 1)
  85. callsiargs += "Variant(arg" + str(i + 1) + ")"
  86. callsiargptrs += "&vargs[" + str(i) + "]"
  87. callptrargs += (
  88. "PtrToArg<m_type" + str(i + 1) + ">::EncodeT argval" + str(i + 1) + " = arg" + str(i + 1) + ";\\\n"
  89. )
  90. callptrargsptr += "&argval" + str(i + 1)
  91. method_info += "\tmethod_info.arguments.push_back(GetTypeInfo<m_type" + str(i + 1) + ">::get_class_info());\\\n"
  92. if argcount:
  93. callsiargs += "};\\\n"
  94. callsiargptrs += "};\\\n"
  95. s = s.replace("$CALLSIARGS", callsiargs + callsiargptrs)
  96. s = s.replace("$CALLSIARGPASS", "(const Variant **)vargptrs," + str(argcount))
  97. callptrargsptr += "};\\\n"
  98. s = s.replace("$CALLPTRARGS", callptrargs + callptrargsptr)
  99. s = s.replace("$CALLPTRARGPASS", "(const GDNativeTypePtr*)argptrs")
  100. else:
  101. s = s.replace("$CALLSIARGS", "")
  102. s = s.replace("$CALLSIARGPASS", "nullptr, 0")
  103. s = s.replace("$CALLPTRARGS", "")
  104. s = s.replace("$CALLPTRARGPASS", "nullptr")
  105. if returns:
  106. if argcount > 0:
  107. callargtext += ","
  108. callargtext += " m_ret& r_ret"
  109. s = s.replace("$CALLSIBEGIN", "Variant ret = ")
  110. s = s.replace("$CALLSIRET", "r_ret = ret;")
  111. s = s.replace("$CALLPTRRETPASS", "&ret")
  112. s = s.replace("$CALLPTRRET", "r_ret = ret;")
  113. else:
  114. s = s.replace("$CALLSIBEGIN", "")
  115. s = s.replace("$CALLSIRET", "")
  116. s = s.replace("$CALLPTRRETPASS", "nullptr")
  117. s = s.replace("$CALLPTRRET", "")
  118. s = s.replace("$ARG", argtext)
  119. s = s.replace("$CALLARGS", callargtext)
  120. s = s.replace("$FILL_METHOD_INFO", method_info)
  121. return s
  122. def run(target, source, env):
  123. max_versions = 12
  124. txt = """
  125. #ifndef GDVIRTUAL_GEN_H
  126. #define GDVIRTUAL_GEN_H
  127. """
  128. for i in range(max_versions + 1):
  129. txt += "/* " + str(i) + " Arguments */\n\n"
  130. txt += generate_version(i, False, False)
  131. txt += generate_version(i, False, True)
  132. txt += generate_version(i, True, False)
  133. txt += generate_version(i, True, True)
  134. txt += "#endif"
  135. with open(target[0], "w") as f:
  136. f.write(txt)
  137. if __name__ == "__main__":
  138. from platform_methods import subprocess_main
  139. subprocess_main(globals())