Create GDExtension clases for PhysicsServer3D
* Allows creating a GDExtension based 3D Physics Server (for Bullet, PhysX, etc. support) * Some changes on native struct binding for PhysicsServer This allows a 3D Physics server created entirely from GDExtension. Once it works, the idea is to port the 2D one to it.
This commit is contained in:
parent
41edfc88a3
commit
8b547331be
44 changed files with 2486 additions and 110 deletions
|
|
@ -841,27 +841,16 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
|
|||
{
|
||||
Array native_structures;
|
||||
|
||||
// AudioStream structures
|
||||
{
|
||||
Dictionary d;
|
||||
d["name"] = "AudioFrame";
|
||||
d["format"] = "float left,float right";
|
||||
List<StringName> native_structs;
|
||||
ClassDB::get_native_struct_list(&native_structs);
|
||||
native_structs.sort_custom<StringName::AlphCompare>();
|
||||
|
||||
native_structures.push_back(d);
|
||||
}
|
||||
for (const StringName &E : native_structs) {
|
||||
String code = ClassDB::get_native_struct_code(E);
|
||||
|
||||
// TextServer structures
|
||||
{
|
||||
Dictionary d;
|
||||
d["name"] = "Glyph";
|
||||
d["format"] = "int start,int end,uint8_t count,uint8_t repeat,uint16_t flags,float x_off,float y_off,float advance,RID font_rid,int font_size,int32_t index";
|
||||
|
||||
native_structures.push_back(d);
|
||||
}
|
||||
{
|
||||
Dictionary d;
|
||||
d["name"] = "CaretInfo";
|
||||
d["format"] = "Rect2 leading_caret,Rect2 trailing_caret,TextServer::Direction leading_direction,TextServer::Direction trailing_direction";
|
||||
d["name"] = String(E);
|
||||
d["format"] = code;
|
||||
|
||||
native_structures.push_back(d);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ static void gdnative_print_script_error(const char *p_description, const char *p
|
|||
_err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT);
|
||||
}
|
||||
|
||||
uint64_t gdnative_get_native_struct_size(const char *p_name) {
|
||||
return ClassDB::get_native_struct_size(p_name);
|
||||
}
|
||||
|
||||
// Variant functions
|
||||
|
||||
static void gdnative_variant_new_copy(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src) {
|
||||
|
|
@ -902,6 +906,8 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
|
|||
gdni.print_warning = gdnative_print_warning;
|
||||
gdni.print_script_error = gdnative_print_script_error;
|
||||
|
||||
gdni.get_native_struct_size = gdnative_get_native_struct_size;
|
||||
|
||||
/* GODOT VARIANT */
|
||||
|
||||
// variant general
|
||||
|
|
|
|||
|
|
@ -306,6 +306,8 @@ typedef struct {
|
|||
void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
|
||||
void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
|
||||
|
||||
uint64_t (*get_native_struct_size)(const char *p_name);
|
||||
|
||||
/* GODOT VARIANT */
|
||||
|
||||
/* variant general */
|
||||
|
|
|
|||
|
|
@ -1606,7 +1606,7 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
|
|||
if (Engine::get_singleton()->has_singleton(p_class)) {
|
||||
c = Engine::get_singleton()->get_singleton_object(p_class);
|
||||
cleanup_c = false;
|
||||
} else if (ClassDB::can_instantiate(p_class)) {
|
||||
} else if (ClassDB::can_instantiate(p_class) && !ClassDB::is_virtual(p_class)) {
|
||||
c = ClassDB::instantiate(p_class);
|
||||
cleanup_c = true;
|
||||
}
|
||||
|
|
@ -1694,6 +1694,30 @@ void ClassDB::unregister_extension_class(const StringName &p_class) {
|
|||
classes.erase(p_class);
|
||||
}
|
||||
|
||||
Map<StringName, ClassDB::NativeStruct> ClassDB::native_structs;
|
||||
void ClassDB::register_native_struct(const StringName &p_name, const String &p_code, uint64_t p_current_size) {
|
||||
NativeStruct ns;
|
||||
ns.ccode = p_code;
|
||||
ns.struct_size = p_current_size;
|
||||
native_structs[p_name] = ns;
|
||||
}
|
||||
|
||||
void ClassDB::get_native_struct_list(List<StringName> *r_names) {
|
||||
for (const KeyValue<StringName, NativeStruct> &E : native_structs) {
|
||||
r_names->push_back(E.key);
|
||||
}
|
||||
}
|
||||
|
||||
String ClassDB::get_native_struct_code(const StringName &p_name) {
|
||||
ERR_FAIL_COND_V(!native_structs.has(p_name), String());
|
||||
return native_structs[p_name].ccode;
|
||||
}
|
||||
|
||||
uint64_t ClassDB::get_native_struct_size(const StringName &p_name) {
|
||||
ERR_FAIL_COND_V(!native_structs.has(p_name), 0);
|
||||
return native_structs[p_name].struct_size;
|
||||
}
|
||||
|
||||
RWLock ClassDB::lock;
|
||||
|
||||
void ClassDB::cleanup_defaults() {
|
||||
|
|
@ -1717,6 +1741,7 @@ void ClassDB::cleanup() {
|
|||
classes.clear();
|
||||
resource_base_extensions.clear();
|
||||
compat_classes.clear();
|
||||
native_structs.clear();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -144,6 +144,13 @@ public:
|
|||
static HashMap<StringName, HashMap<StringName, Variant>> default_values;
|
||||
static Set<StringName> default_values_cached;
|
||||
|
||||
// Native structs, used by binder
|
||||
struct NativeStruct {
|
||||
String ccode; // C code to create the native struct, fields separated by ; Arrays accepted (even containing other structs), also function pointers. All types must be Godot types.
|
||||
uint64_t struct_size; // local size of struct, for comparison
|
||||
};
|
||||
static Map<StringName, NativeStruct> native_structs;
|
||||
|
||||
private:
|
||||
// Non-locking variants of get_parent_class and is_parent_class.
|
||||
static StringName _get_parent_class(const StringName &p_class);
|
||||
|
|
@ -390,6 +397,11 @@ public:
|
|||
static APIType get_current_api();
|
||||
static void cleanup_defaults();
|
||||
static void cleanup();
|
||||
|
||||
static void register_native_struct(const StringName &p_name, const String &p_code, uint64_t p_current_size);
|
||||
static void get_native_struct_list(List<StringName> *r_names);
|
||||
static String get_native_struct_code(const StringName &p_name);
|
||||
static uint64_t get_native_struct_size(const StringName &p_name); // Used for asserting
|
||||
};
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
|
@ -448,6 +460,8 @@ _FORCE_INLINE_ Vector<Error> errarray(P... p_args) {
|
|||
::ClassDB::register_abstract_class<m_class>(); \
|
||||
}
|
||||
|
||||
#define GDREGISTER_NATIVE_STRUCT(m_class, m_code) ClassDB::register_native_struct(#m_class, m_code, sizeof(m_class))
|
||||
|
||||
#include "core/disabled_classes.gen.h"
|
||||
|
||||
#endif // CLASS_DB_H
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
|
|||
}\\
|
||||
\\
|
||||
if (required) {\\
|
||||
WARN_PRINT_ONCE("Required virtual method: "+get_class()+"::" + #m_name + " must be overriden before calling.");\\
|
||||
ERR_PRINT_ONCE("Required virtual method: "+get_class()+"::" + #m_name + " must be overriden before calling.");\\
|
||||
$RVOID\\
|
||||
}\\
|
||||
\\
|
||||
return false;\\
|
||||
|
|
@ -66,10 +67,12 @@ def generate_version(argcount, const=False, returns=False):
|
|||
if returns:
|
||||
sproto += "R"
|
||||
s = s.replace("$RET", "m_ret, ")
|
||||
s = s.replace("$RVOID", "(void)r_ret;") # If required, may lead to uninitialized errors
|
||||
s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;")
|
||||
method_info += "\tmethod_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n"
|
||||
else:
|
||||
s = s.replace("$RET", "")
|
||||
s = s.replace("$RVOID", "")
|
||||
s = s.replace("$CALLPTRRETDEF", "")
|
||||
|
||||
if const:
|
||||
|
|
|
|||
|
|
@ -261,6 +261,8 @@ void register_core_types() {
|
|||
_classdb = memnew(core_bind::special::ClassDB);
|
||||
_marshalls = memnew(core_bind::Marshalls);
|
||||
_engine_debugger = memnew(core_bind::EngineDebugger);
|
||||
|
||||
GDREGISTER_NATIVE_STRUCT(AudioFrame, "float left;float right");
|
||||
}
|
||||
|
||||
void register_core_settings() {
|
||||
|
|
|
|||
|
|
@ -100,6 +100,10 @@ struct VariantCaster<const T &> {
|
|||
_FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \
|
||||
*(int64_t *)p_ptr = (int64_t)p_val; \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct ZeroInitializer<m_enum> { \
|
||||
static void initialize(m_enum &value) { value = (m_enum)0; } \
|
||||
};
|
||||
|
||||
// Object enum casts must go here
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ struct PtrToArg<GDNativePtr<T>> {
|
|||
}
|
||||
};
|
||||
|
||||
GDVIRTUAL_NATIVE_PTR(void)
|
||||
GDVIRTUAL_NATIVE_PTR(AudioFrame)
|
||||
GDVIRTUAL_NATIVE_PTR(bool)
|
||||
GDVIRTUAL_NATIVE_PTR(char)
|
||||
|
|
|
|||
|
|
@ -281,4 +281,38 @@ inline StringName __constant_get_enum_name(T param, const String &p_constant) {
|
|||
|
||||
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
|
||||
|
||||
template <typename T>
|
||||
struct ZeroInitializer {
|
||||
static void initialize(T &value) {} //no initialization by default
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ZeroInitializer<bool> {
|
||||
static void initialize(bool &value) { value = false; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ZeroInitializer<T *> {
|
||||
static void initialize(T *&value) { value = nullptr; }
|
||||
};
|
||||
|
||||
#define ZERO_INITIALIZER_NUMBER(m_type) \
|
||||
template <> \
|
||||
struct ZeroInitializer<m_type> { \
|
||||
static void initialize(m_type &value) { value = 0; } \
|
||||
};
|
||||
|
||||
ZERO_INITIALIZER_NUMBER(uint8_t)
|
||||
ZERO_INITIALIZER_NUMBER(int8_t)
|
||||
ZERO_INITIALIZER_NUMBER(uint16_t)
|
||||
ZERO_INITIALIZER_NUMBER(int16_t)
|
||||
ZERO_INITIALIZER_NUMBER(uint32_t)
|
||||
ZERO_INITIALIZER_NUMBER(int32_t)
|
||||
ZERO_INITIALIZER_NUMBER(uint64_t)
|
||||
ZERO_INITIALIZER_NUMBER(int64_t)
|
||||
ZERO_INITIALIZER_NUMBER(char16_t)
|
||||
ZERO_INITIALIZER_NUMBER(char32_t)
|
||||
ZERO_INITIALIZER_NUMBER(float)
|
||||
ZERO_INITIALIZER_NUMBER(double)
|
||||
|
||||
#endif // TYPE_INFO_H
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue