2024-12-20 17:10:46 -06:00
|
|
|
script_call = """ScriptInstance *_script_instance = ((Object *)(this))->get_script_instance();\\
|
2023-12-04 19:48:44 -06:00
|
|
|
if (_script_instance) {\\
|
|
|
|
Callable::CallError ce;\\
|
|
|
|
$CALLSIARGS\\
|
2024-12-20 17:10:46 -06:00
|
|
|
$CALLSIBEGIN_script_instance->callp(_gdvirtual_##$VARNAME##_sn, $CALLSIARGPASS, ce);\\
|
2023-12-04 19:48:44 -06:00
|
|
|
if (ce.error == Callable::CallError::CALL_OK) {\\
|
|
|
|
$CALLSIRET\\
|
|
|
|
return true;\\
|
|
|
|
}\\
|
2024-12-20 17:10:46 -06:00
|
|
|
}"""
|
|
|
|
|
|
|
|
script_has_method = """ScriptInstance *_script_instance = ((Object *)(this))->get_script_instance();\\
|
|
|
|
if (_script_instance && _script_instance->has_method(_gdvirtual_##$VARNAME##_sn)) {\\
|
|
|
|
return true;\\
|
|
|
|
}"""
|
|
|
|
|
|
|
|
proto = """#define GDVIRTUAL$VER($ALIAS $RET m_name $ARG)\\
|
|
|
|
mutable void *_gdvirtual_##$VARNAME = nullptr;\\
|
|
|
|
_FORCE_INLINE_ bool _gdvirtual_##$VARNAME##_call($CALLARGS) $CONST {\\
|
2025-04-03 22:09:35 +02:00
|
|
|
static const StringName _gdvirtual_##$VARNAME##_sn = StringName(#m_name, true);\\
|
2024-12-20 17:10:46 -06:00
|
|
|
$SCRIPTCALL\\
|
2025-03-17 13:17:33 +08:00
|
|
|
if (_get_extension()) {\\
|
|
|
|
if (unlikely(!_gdvirtual_##$VARNAME)) {\\
|
2025-10-06 21:56:06 +02:00
|
|
|
_gdvirtual_init_method_ptr(_gdvirtual_##$VARNAME##_get_method_info().get_compatibility_hash(), _gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT);\\
|
2023-12-04 19:48:44 -06:00
|
|
|
}\\
|
2025-03-17 13:17:33 +08:00
|
|
|
if (_gdvirtual_##$VARNAME != reinterpret_cast<void*>(_INVALID_GDVIRTUAL_FUNC_ADDR)) {\\
|
|
|
|
$CALLPTRARGS\\
|
|
|
|
$CALLPTRRETDEF\\
|
|
|
|
if (_get_extension()->call_virtual_with_data) {\\
|
|
|
|
_get_extension()->call_virtual_with_data(_get_extension_instance(), &_gdvirtual_##$VARNAME##_sn, _gdvirtual_##$VARNAME, $CALLPTRARGPASS, $CALLPTRRETPASS);\\
|
|
|
|
$CALLPTRRET\\
|
|
|
|
} else {\\
|
|
|
|
((GDExtensionClassCallVirtual)_gdvirtual_##$VARNAME)(_get_extension_instance(), $CALLPTRARGPASS, $CALLPTRRETPASS);\\
|
|
|
|
$CALLPTRRET\\
|
|
|
|
}\\
|
|
|
|
return true;\\
|
2023-12-04 19:48:44 -06:00
|
|
|
}\\
|
|
|
|
}\\
|
2024-06-18 10:07:35 -05:00
|
|
|
$REQCHECK\\
|
|
|
|
$RVOID\\
|
2023-12-04 19:48:44 -06:00
|
|
|
return false;\\
|
2021-06-19 12:58:49 -03:00
|
|
|
}\\
|
2024-12-20 17:10:46 -06:00
|
|
|
_FORCE_INLINE_ bool _gdvirtual_##$VARNAME##_overridden() const {\\
|
2025-04-03 22:09:35 +02:00
|
|
|
static const StringName _gdvirtual_##$VARNAME##_sn = StringName(#m_name, true);\\
|
2024-12-20 17:10:46 -06:00
|
|
|
$SCRIPTHASMETHOD\\
|
2025-03-17 13:17:33 +08:00
|
|
|
if (_get_extension()) {\\
|
|
|
|
if (unlikely(!_gdvirtual_##$VARNAME)) {\\
|
2025-10-06 21:56:06 +02:00
|
|
|
_gdvirtual_init_method_ptr(_gdvirtual_##$VARNAME##_get_method_info().get_compatibility_hash(), _gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT);\\
|
2025-03-17 13:17:33 +08:00
|
|
|
}\\
|
|
|
|
if (_gdvirtual_##$VARNAME != reinterpret_cast<void*>(_INVALID_GDVIRTUAL_FUNC_ADDR)) {\\
|
|
|
|
return true;\\
|
2023-12-04 19:48:44 -06:00
|
|
|
}\\
|
|
|
|
}\\
|
|
|
|
return false;\\
|
2021-08-21 22:52:44 -03:00
|
|
|
}\\
|
2024-12-20 17:10:46 -06:00
|
|
|
_FORCE_INLINE_ static MethodInfo _gdvirtual_##$VARNAME##_get_method_info() {\\
|
2023-12-04 19:48:44 -06:00
|
|
|
MethodInfo method_info;\\
|
|
|
|
method_info.name = #m_name;\\
|
|
|
|
method_info.flags = $METHOD_FLAGS;\\
|
|
|
|
$FILL_METHOD_INFO\\
|
|
|
|
return method_info;\\
|
|
|
|
}
|
2021-06-19 12:58:49 -03:00
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
2024-12-20 17:10:46 -06:00
|
|
|
def generate_version(argcount, const=False, returns=False, required=False, compat=False):
|
2021-06-19 12:58:49 -03:00
|
|
|
s = proto
|
2024-12-20 17:10:46 -06:00
|
|
|
if compat:
|
|
|
|
s = s.replace("$SCRIPTCALL", "")
|
|
|
|
s = s.replace("$SCRIPTHASMETHOD", "")
|
|
|
|
else:
|
|
|
|
s = s.replace("$SCRIPTCALL", script_call)
|
|
|
|
s = s.replace("$SCRIPTHASMETHOD", script_has_method)
|
|
|
|
|
2021-06-19 12:58:49 -03:00
|
|
|
sproto = str(argcount)
|
|
|
|
method_info = ""
|
2024-06-18 10:07:35 -05:00
|
|
|
method_flags = "METHOD_FLAG_VIRTUAL"
|
2021-06-19 12:58:49 -03:00
|
|
|
if returns:
|
|
|
|
sproto += "R"
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("$RET", "m_ret,")
|
2022-03-14 15:52:03 +01:00
|
|
|
s = s.replace("$RVOID", "(void)r_ret;") # If required, may lead to uninitialized errors
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;")
|
2023-12-04 19:48:44 -06:00
|
|
|
method_info += "method_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n"
|
|
|
|
method_info += "\t\tmethod_info.return_val_metadata = GetTypeInfo<m_ret>::METADATA;"
|
2021-06-19 12:58:49 -03:00
|
|
|
else:
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("$RET ", "")
|
2024-06-18 10:07:35 -05:00
|
|
|
s = s.replace("\t\t$RVOID\\\n", "")
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("\t\t\t$CALLPTRRETDEF\\\n", "")
|
2021-06-19 12:58:49 -03:00
|
|
|
|
|
|
|
if const:
|
|
|
|
sproto += "C"
|
2024-06-18 10:07:35 -05:00
|
|
|
method_flags += " | METHOD_FLAG_CONST"
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CONST", "const")
|
|
|
|
else:
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("$CONST ", "")
|
2021-06-19 12:58:49 -03:00
|
|
|
|
2024-06-18 10:07:35 -05:00
|
|
|
if required:
|
|
|
|
sproto += "_REQUIRED"
|
|
|
|
method_flags += " | METHOD_FLAG_VIRTUAL_REQUIRED"
|
|
|
|
s = s.replace(
|
|
|
|
"$REQCHECK",
|
|
|
|
'ERR_PRINT_ONCE("Required virtual method " + get_class() + "::" + #m_name + " must be overridden before calling.");',
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
s = s.replace("\t\t$REQCHECK\\\n", "")
|
|
|
|
|
2024-12-20 17:10:46 -06:00
|
|
|
if compat:
|
|
|
|
sproto += "_COMPAT"
|
|
|
|
s = s.replace("$COMPAT", "true")
|
|
|
|
s = s.replace("$ALIAS", "m_alias,")
|
|
|
|
s = s.replace("$VARNAME", "m_alias")
|
|
|
|
else:
|
|
|
|
s = s.replace("$COMPAT", "false")
|
|
|
|
s = s.replace("$ALIAS ", "")
|
|
|
|
s = s.replace("$VARNAME", "m_name")
|
|
|
|
|
2024-06-18 10:07:35 -05:00
|
|
|
s = s.replace("$METHOD_FLAGS", method_flags)
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$VER", sproto)
|
|
|
|
argtext = ""
|
|
|
|
callargtext = ""
|
|
|
|
callsiargs = ""
|
|
|
|
callsiargptrs = ""
|
|
|
|
callptrargsptr = ""
|
|
|
|
if argcount > 0:
|
|
|
|
argtext += ", "
|
2023-12-04 19:48:44 -06:00
|
|
|
callsiargs = f"Variant vargs[{argcount}] = {{ "
|
|
|
|
callsiargptrs = f"\t\t\tconst Variant *vargptrs[{argcount}] = {{ "
|
|
|
|
callptrargsptr = f"\t\t\tGDExtensionConstTypePtr argptrs[{argcount}] = {{ "
|
2025-10-06 18:17:45 +02:00
|
|
|
|
|
|
|
if method_info:
|
|
|
|
method_info += "\\\n\t\t"
|
|
|
|
method_info += (
|
|
|
|
"_gdvirtual_set_method_info_args<"
|
|
|
|
+ ", ".join(f"m_type{i + 1}" for i in range(argcount))
|
|
|
|
+ ">(method_info);"
|
|
|
|
)
|
|
|
|
|
2021-06-19 12:58:49 -03:00
|
|
|
callptrargs = ""
|
|
|
|
for i in range(argcount):
|
|
|
|
if i > 0:
|
|
|
|
argtext += ", "
|
|
|
|
callargtext += ", "
|
|
|
|
callsiargs += ", "
|
|
|
|
callsiargptrs += ", "
|
2023-12-04 19:48:44 -06:00
|
|
|
callptrargs += "\t\t\t"
|
2021-06-19 12:58:49 -03:00
|
|
|
callptrargsptr += ", "
|
2023-12-04 19:48:44 -06:00
|
|
|
argtext += f"m_type{i + 1}"
|
|
|
|
callargtext += f"m_type{i + 1} arg{i + 1}"
|
2024-12-29 16:35:10 +01:00
|
|
|
callsiargs += f"arg{i + 1}"
|
2023-12-04 19:48:44 -06:00
|
|
|
callsiargptrs += f"&vargs[{i}]"
|
2023-12-05 08:34:22 -06:00
|
|
|
callptrargs += (
|
|
|
|
f"PtrToArg<m_type{i + 1}>::EncodeT argval{i + 1} = (PtrToArg<m_type{i + 1}>::EncodeT)arg{i + 1};\\\n"
|
|
|
|
)
|
2023-12-04 19:48:44 -06:00
|
|
|
callptrargsptr += f"&argval{i + 1}"
|
2021-06-19 12:58:49 -03:00
|
|
|
|
|
|
|
if argcount:
|
2023-12-04 19:48:44 -06:00
|
|
|
callsiargs += " };\\\n"
|
|
|
|
callsiargptrs += " };"
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLSIARGS", callsiargs + callsiargptrs)
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("$CALLSIARGPASS", f"(const Variant **)vargptrs, {argcount}")
|
|
|
|
callptrargsptr += " };"
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLPTRARGS", callptrargs + callptrargsptr)
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("$CALLPTRARGPASS", "reinterpret_cast<GDExtensionConstTypePtr *>(argptrs)")
|
2021-06-19 12:58:49 -03:00
|
|
|
else:
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("\t\t\t$CALLSIARGS\\\n", "")
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLSIARGPASS", "nullptr, 0")
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("\t\t\t$CALLPTRARGS\\\n", "")
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLPTRARGPASS", "nullptr")
|
|
|
|
|
|
|
|
if returns:
|
|
|
|
if argcount > 0:
|
2023-12-04 19:48:44 -06:00
|
|
|
callargtext += ", "
|
|
|
|
callargtext += "m_ret &r_ret"
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLSIBEGIN", "Variant ret = ")
|
2022-02-03 15:03:51 +02:00
|
|
|
s = s.replace("$CALLSIRET", "r_ret = VariantCaster<m_ret>::cast(ret);")
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLPTRRETPASS", "&ret")
|
2022-02-03 15:03:51 +02:00
|
|
|
s = s.replace("$CALLPTRRET", "r_ret = (m_ret)ret;")
|
2021-06-19 12:58:49 -03:00
|
|
|
else:
|
|
|
|
s = s.replace("$CALLSIBEGIN", "")
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("\t\t\t\t$CALLSIRET\\\n", "")
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLPTRRETPASS", "nullptr")
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace("\t\t\t\t$CALLPTRRET\\\n", "")
|
2021-06-19 12:58:49 -03:00
|
|
|
|
2023-12-04 19:48:44 -06:00
|
|
|
s = s.replace(" $ARG", argtext)
|
2021-06-19 12:58:49 -03:00
|
|
|
s = s.replace("$CALLARGS", callargtext)
|
2023-12-04 19:48:44 -06:00
|
|
|
if method_info:
|
|
|
|
s = s.replace("$FILL_METHOD_INFO", method_info)
|
|
|
|
else:
|
|
|
|
s = s.replace("\t\t$FILL_METHOD_INFO\\\n", method_info)
|
2021-06-19 12:58:49 -03:00
|
|
|
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
def run(target, source, env):
|
|
|
|
max_versions = 12
|
|
|
|
|
2023-12-04 19:48:44 -06:00
|
|
|
txt = """/* THIS FILE IS GENERATED DO NOT EDIT */
|
2025-02-01 10:11:55 -06:00
|
|
|
#pragma once
|
2021-06-19 12:58:49 -03:00
|
|
|
|
2023-09-06 21:02:52 +02:00
|
|
|
#include "core/object/script_instance.h"
|
|
|
|
|
2025-03-17 13:17:33 +08:00
|
|
|
inline constexpr uintptr_t _INVALID_GDVIRTUAL_FUNC_ADDR = static_cast<uintptr_t>(-1);
|
|
|
|
|
2025-10-06 18:17:45 +02:00
|
|
|
template <typename... Args>
|
|
|
|
void _gdvirtual_set_method_info_args(MethodInfo &p_method_info) {
|
|
|
|
p_method_info.arguments = { GetTypeInfo<Args>::get_class_info()... };
|
|
|
|
p_method_info.arguments_metadata = { GetTypeInfo<Args>::METADATA... };
|
|
|
|
}
|
|
|
|
|
2021-06-19 12:58:49 -03:00
|
|
|
"""
|
|
|
|
|
|
|
|
for i in range(max_versions + 1):
|
2023-12-04 19:48:44 -06:00
|
|
|
txt += f"/* {i} Arguments */\n\n"
|
2021-06-19 12:58:49 -03:00
|
|
|
txt += generate_version(i, False, False)
|
|
|
|
txt += generate_version(i, False, True)
|
|
|
|
txt += generate_version(i, True, False)
|
|
|
|
txt += generate_version(i, True, True)
|
2024-06-18 10:07:35 -05:00
|
|
|
txt += generate_version(i, False, False, True)
|
|
|
|
txt += generate_version(i, False, True, True)
|
|
|
|
txt += generate_version(i, True, False, True)
|
|
|
|
txt += generate_version(i, True, True, True)
|
2024-12-20 17:10:46 -06:00
|
|
|
txt += generate_version(i, False, False, False, True)
|
|
|
|
txt += generate_version(i, False, True, False, True)
|
|
|
|
txt += generate_version(i, True, False, False, True)
|
|
|
|
txt += generate_version(i, True, True, False, True)
|
2021-06-19 12:58:49 -03:00
|
|
|
|
2024-03-11 13:05:37 -05:00
|
|
|
with open(str(target[0]), "w", encoding="utf-8", newline="\n") as f:
|
2021-06-19 12:58:49 -03:00
|
|
|
f.write(txt)
|