Merge pull request #1465 from dsnopek/4.2-cherrypicks-4
Cherry-picks for the godot-cpp 4.2 branch - 4th batchpull/1494/head
commit
2b6eb6832e
|
@ -181,6 +181,10 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
|
||||||
generate_utility_functions(api, target_dir)
|
generate_utility_functions(api, target_dir)
|
||||||
|
|
||||||
|
|
||||||
|
CLASS_ALIASES = {
|
||||||
|
"ClassDB": "ClassDBSingleton",
|
||||||
|
}
|
||||||
|
|
||||||
builtin_classes = []
|
builtin_classes = []
|
||||||
|
|
||||||
# Key is class name, value is boolean where True means the class is refcounted.
|
# Key is class name, value is boolean where True means the class is refcounted.
|
||||||
|
@ -1127,9 +1131,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
|
||||||
# First create map of classes and singletons.
|
# First create map of classes and singletons.
|
||||||
for class_api in api["classes"]:
|
for class_api in api["classes"]:
|
||||||
# Generate code for the ClassDB singleton under a different name.
|
# Generate code for the ClassDB singleton under a different name.
|
||||||
if class_api["name"] == "ClassDB":
|
if class_api["name"] in CLASS_ALIASES:
|
||||||
class_api["name"] = "ClassDBSingleton"
|
class_api["alias_for"] = class_api["name"]
|
||||||
class_api["alias_for"] = "ClassDB"
|
class_api["name"] = CLASS_ALIASES[class_api["alias_for"]]
|
||||||
engine_classes[class_api["name"]] = class_api["is_refcounted"]
|
engine_classes[class_api["name"]] = class_api["is_refcounted"]
|
||||||
for native_struct in api["native_structures"]:
|
for native_struct in api["native_structures"]:
|
||||||
if native_struct["name"] == "ObjectID":
|
if native_struct["name"] == "ObjectID":
|
||||||
|
@ -1139,9 +1143,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
|
||||||
|
|
||||||
for singleton in api["singletons"]:
|
for singleton in api["singletons"]:
|
||||||
# Generate code for the ClassDB singleton under a different name.
|
# Generate code for the ClassDB singleton under a different name.
|
||||||
if singleton["name"] == "ClassDB":
|
if singleton["name"] in CLASS_ALIASES:
|
||||||
singleton["name"] = "ClassDBSingleton"
|
singleton["alias_for"] = singleton["name"]
|
||||||
singleton["alias_for"] = "ClassDB"
|
singleton["name"] = CLASS_ALIASES[singleton["name"]]
|
||||||
singletons.append(singleton["name"])
|
singletons.append(singleton["name"])
|
||||||
|
|
||||||
for class_api in api["classes"]:
|
for class_api in api["classes"]:
|
||||||
|
@ -1346,6 +1350,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
||||||
result.append("#include <type_traits>")
|
result.append("#include <type_traits>")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
|
||||||
|
if class_name == "ClassDBSingleton":
|
||||||
|
result.append("#include <godot_cpp/core/binder_common.hpp>")
|
||||||
|
result.append("")
|
||||||
|
|
||||||
result.append("namespace godot {")
|
result.append("namespace godot {")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
|
||||||
|
@ -1367,6 +1375,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
||||||
result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
|
result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
|
||||||
|
if is_singleton:
|
||||||
|
result.append(f"\tstatic {class_name} *singleton;")
|
||||||
|
result.append("")
|
||||||
|
|
||||||
result.append("public:")
|
result.append("public:")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
|
||||||
|
@ -1447,6 +1459,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
||||||
|
|
||||||
result.append("\t}")
|
result.append("\t}")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
|
||||||
|
if is_singleton:
|
||||||
|
result.append(f"\t~{class_name}();")
|
||||||
|
result.append("")
|
||||||
|
|
||||||
result.append("public:")
|
result.append("public:")
|
||||||
|
|
||||||
# Special cases.
|
# Special cases.
|
||||||
|
@ -1504,6 +1521,19 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
||||||
|
|
||||||
if class_name == "ClassDBSingleton":
|
if class_name == "ClassDBSingleton":
|
||||||
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\")
|
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\")
|
||||||
|
|
||||||
|
if "enums" in class_api:
|
||||||
|
for enum_api in class_api["enums"]:
|
||||||
|
if enum_api["is_bitfield"]:
|
||||||
|
result.append(f'\tenum {enum_api["name"]} : uint64_t {{ \\')
|
||||||
|
else:
|
||||||
|
result.append(f'\tenum {enum_api["name"]} {{ \\')
|
||||||
|
|
||||||
|
for value in enum_api["values"]:
|
||||||
|
result.append(f'\t\t{value["name"]} = {value["value"]}, \\')
|
||||||
|
result.append("\t}; \\")
|
||||||
|
result.append("\t \\")
|
||||||
|
|
||||||
for method in class_api["methods"]:
|
for method in class_api["methods"]:
|
||||||
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them.
|
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them.
|
||||||
if vararg:
|
if vararg:
|
||||||
|
@ -1512,12 +1542,17 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
||||||
continue
|
continue
|
||||||
|
|
||||||
method_signature = "\tstatic "
|
method_signature = "\tstatic "
|
||||||
|
return_type = None
|
||||||
if "return_type" in method:
|
if "return_type" in method:
|
||||||
method_signature += f'{correct_type(method["return_type"])} '
|
return_type = correct_type(method["return_type"].replace("ClassDBSingleton", "ClassDB"), None, False)
|
||||||
elif "return_value" in method:
|
elif "return_value" in method:
|
||||||
method_signature += (
|
return_type = correct_type(
|
||||||
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " "
|
method["return_value"]["type"].replace("ClassDBSingleton", "ClassDB"),
|
||||||
|
method["return_value"].get("meta", None),
|
||||||
|
False,
|
||||||
)
|
)
|
||||||
|
if return_type is not None:
|
||||||
|
method_signature += return_type + " "
|
||||||
else:
|
else:
|
||||||
method_signature += "void "
|
method_signature += "void "
|
||||||
|
|
||||||
|
@ -1536,8 +1571,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
||||||
result.append(method_signature)
|
result.append(method_signature)
|
||||||
|
|
||||||
method_body = "\t\t"
|
method_body = "\t\t"
|
||||||
if "return_type" in method or "return_value" in method:
|
if return_type is not None:
|
||||||
method_body += "return "
|
method_body += "return "
|
||||||
|
if "alias_for" in class_api and return_type.startswith(class_api["alias_for"] + "::"):
|
||||||
|
method_body += f"({return_type})"
|
||||||
method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}('
|
method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}('
|
||||||
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
|
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
|
||||||
method_body += "); \\"
|
method_body += "); \\"
|
||||||
|
@ -1547,6 +1584,18 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
|
||||||
result.append("\t;")
|
result.append("\t;")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
|
||||||
|
result.append("#define CLASSDB_SINGLETON_VARIANT_CAST \\")
|
||||||
|
|
||||||
|
if "enums" in class_api:
|
||||||
|
for enum_api in class_api["enums"]:
|
||||||
|
if enum_api["is_bitfield"]:
|
||||||
|
result.append(f'\tVARIANT_BITFIELD_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\')
|
||||||
|
else:
|
||||||
|
result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\')
|
||||||
|
|
||||||
|
result.append("\t;")
|
||||||
|
result.append("")
|
||||||
|
|
||||||
result.append(f"#endif // ! {header_guard}")
|
result.append(f"#endif // ! {header_guard}")
|
||||||
|
|
||||||
return "\n".join(result)
|
return "\n".join(result)
|
||||||
|
@ -1564,6 +1613,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
|
||||||
|
|
||||||
result.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
|
result.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
result.append("#include <godot_cpp/core/class_db.hpp>")
|
||||||
result.append("#include <godot_cpp/core/engine_ptrcall.hpp>")
|
result.append("#include <godot_cpp/core/engine_ptrcall.hpp>")
|
||||||
result.append("#include <godot_cpp/core/error_macros.hpp>")
|
result.append("#include <godot_cpp/core/error_macros.hpp>")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
@ -1578,9 +1628,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
|
||||||
result.append("")
|
result.append("")
|
||||||
|
|
||||||
if is_singleton:
|
if is_singleton:
|
||||||
|
result.append(f"{class_name} *{class_name}::singleton = nullptr;")
|
||||||
|
result.append("")
|
||||||
result.append(f"{class_name} *{class_name}::get_singleton() {{")
|
result.append(f"{class_name} *{class_name}::get_singleton() {{")
|
||||||
# We assume multi-threaded access is OK because each assignment will assign the same value every time
|
# We assume multi-threaded access is OK because each assignment will assign the same value every time
|
||||||
result.append(f"\tstatic {class_name} *singleton = nullptr;")
|
|
||||||
result.append("\tif (unlikely(singleton == nullptr)) {")
|
result.append("\tif (unlikely(singleton == nullptr)) {")
|
||||||
result.append(
|
result.append(
|
||||||
f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());"
|
f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());"
|
||||||
|
@ -1594,11 +1645,22 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
|
||||||
result.append("#ifdef DEBUG_ENABLED")
|
result.append("#ifdef DEBUG_ENABLED")
|
||||||
result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);")
|
result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);")
|
||||||
result.append("#endif // DEBUG_ENABLED")
|
result.append("#endif // DEBUG_ENABLED")
|
||||||
|
result.append("\t\tif (likely(singleton)) {")
|
||||||
|
result.append(f"\t\t\tClassDB::_register_engine_singleton({class_name}::get_class_static(), singleton);")
|
||||||
|
result.append("\t\t}")
|
||||||
result.append("\t}")
|
result.append("\t}")
|
||||||
result.append("\treturn singleton;")
|
result.append("\treturn singleton;")
|
||||||
result.append("}")
|
result.append("}")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
|
||||||
|
result.append(f"{class_name}::~{class_name}() {{")
|
||||||
|
result.append("\tif (singleton == this) {")
|
||||||
|
result.append(f"\t\tClassDB::_unregister_engine_singleton({class_name}::get_class_static());")
|
||||||
|
result.append("\t\tsingleton = nullptr;")
|
||||||
|
result.append("\t}")
|
||||||
|
result.append("}")
|
||||||
|
result.append("")
|
||||||
|
|
||||||
if "methods" in class_api:
|
if "methods" in class_api:
|
||||||
for method in class_api["methods"]:
|
for method in class_api["methods"]:
|
||||||
if method["is_virtual"]:
|
if method["is_virtual"]:
|
||||||
|
@ -2384,7 +2446,7 @@ def correct_typed_array(type_name):
|
||||||
return type_name
|
return type_name
|
||||||
|
|
||||||
|
|
||||||
def correct_type(type_name, meta=None):
|
def correct_type(type_name, meta=None, use_alias=True):
|
||||||
type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
|
type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
|
||||||
if meta != None:
|
if meta != None:
|
||||||
if "int" in meta:
|
if "int" in meta:
|
||||||
|
@ -2400,11 +2462,15 @@ def correct_type(type_name, meta=None):
|
||||||
if is_enum(type_name):
|
if is_enum(type_name):
|
||||||
if is_bitfield(type_name):
|
if is_bitfield(type_name):
|
||||||
base_class = get_enum_class(type_name)
|
base_class = get_enum_class(type_name)
|
||||||
|
if use_alias and base_class in CLASS_ALIASES:
|
||||||
|
base_class = CLASS_ALIASES[base_class]
|
||||||
if base_class == "GlobalConstants":
|
if base_class == "GlobalConstants":
|
||||||
return f"BitField<{get_enum_name(type_name)}>"
|
return f"BitField<{get_enum_name(type_name)}>"
|
||||||
return f"BitField<{base_class}::{get_enum_name(type_name)}>"
|
return f"BitField<{base_class}::{get_enum_name(type_name)}>"
|
||||||
else:
|
else:
|
||||||
base_class = get_enum_class(type_name)
|
base_class = get_enum_class(type_name)
|
||||||
|
if use_alias and base_class in CLASS_ALIASES:
|
||||||
|
base_class = CLASS_ALIASES[base_class]
|
||||||
if base_class == "GlobalConstants":
|
if base_class == "GlobalConstants":
|
||||||
return f"{get_enum_name(type_name)}"
|
return f"{get_enum_name(type_name)}"
|
||||||
return f"{base_class}::{get_enum_name(type_name)}"
|
return f"{base_class}::{get_enum_name(type_name)}"
|
||||||
|
|
|
@ -88,14 +88,15 @@ protected:
|
||||||
::godot::List<::godot::PropertyInfo> plist_owned;
|
::godot::List<::godot::PropertyInfo> plist_owned;
|
||||||
|
|
||||||
void _postinitialize();
|
void _postinitialize();
|
||||||
|
virtual void _notificationv(int32_t p_what, bool p_reversed = false) {}
|
||||||
|
|
||||||
Wrapped(const StringName p_godot_class);
|
Wrapped(const StringName p_godot_class);
|
||||||
Wrapped(GodotObject *p_godot_object);
|
Wrapped(GodotObject *p_godot_object);
|
||||||
virtual ~Wrapped() {}
|
virtual ~Wrapped() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static StringName &get_class_static() {
|
static const StringName &get_class_static() {
|
||||||
static StringName string_name = StringName("Wrapped");
|
static const StringName string_name = StringName("Wrapped");
|
||||||
return string_name;
|
return string_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +194,7 @@ protected:
|
||||||
\
|
\
|
||||||
public: \
|
public: \
|
||||||
typedef m_class self_type; \
|
typedef m_class self_type; \
|
||||||
|
typedef m_inherits parent_type; \
|
||||||
\
|
\
|
||||||
static void initialize_class() { \
|
static void initialize_class() { \
|
||||||
static bool initialized = false; \
|
static bool initialized = false; \
|
||||||
|
@ -207,12 +209,12 @@ public:
|
||||||
initialized = true; \
|
initialized = true; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static ::godot::StringName &get_class_static() { \
|
static const ::godot::StringName &get_class_static() { \
|
||||||
static ::godot::StringName string_name = ::godot::StringName(#m_class); \
|
static const ::godot::StringName string_name = ::godot::StringName(#m_class); \
|
||||||
return string_name; \
|
return string_name; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static ::godot::StringName &get_parent_class_static() { \
|
static const ::godot::StringName &get_parent_class_static() { \
|
||||||
return m_inherits::get_class_static(); \
|
return m_inherits::get_class_static(); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
@ -352,6 +354,11 @@ public:
|
||||||
_gde_binding_reference_callback, \
|
_gde_binding_reference_callback, \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
|
protected: \
|
||||||
|
virtual void _notificationv(int32_t p_what, bool p_reversed = false) override { \
|
||||||
|
m_class::notification_bind(this, p_what, p_reversed); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Don't use this for your classes, use GDCLASS() instead.
|
// Don't use this for your classes, use GDCLASS() instead.
|
||||||
|
@ -359,6 +366,7 @@ private:
|
||||||
private: \
|
private: \
|
||||||
inline static ::godot::internal::EngineClassRegistration<m_class> _gde_engine_class_registration_helper; \
|
inline static ::godot::internal::EngineClassRegistration<m_class> _gde_engine_class_registration_helper; \
|
||||||
void operator=(const m_class &p_rval) {} \
|
void operator=(const m_class &p_rval) {} \
|
||||||
|
friend class ::godot::ClassDB; \
|
||||||
\
|
\
|
||||||
protected: \
|
protected: \
|
||||||
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
||||||
|
@ -368,6 +376,8 @@ protected:
|
||||||
m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \
|
m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \
|
||||||
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
|
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
|
||||||
\
|
\
|
||||||
|
static void _bind_methods() {} \
|
||||||
|
\
|
||||||
static void (*_get_bind_methods())() { \
|
static void (*_get_bind_methods())() { \
|
||||||
return nullptr; \
|
return nullptr; \
|
||||||
} \
|
} \
|
||||||
|
@ -410,15 +420,16 @@ protected:
|
||||||
\
|
\
|
||||||
public: \
|
public: \
|
||||||
typedef m_class self_type; \
|
typedef m_class self_type; \
|
||||||
|
typedef m_inherits parent_type; \
|
||||||
\
|
\
|
||||||
static void initialize_class() {} \
|
static void initialize_class() {} \
|
||||||
\
|
\
|
||||||
static ::godot::StringName &get_class_static() { \
|
static const ::godot::StringName &get_class_static() { \
|
||||||
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
|
static const ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
|
||||||
return string_name; \
|
return string_name; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static ::godot::StringName &get_parent_class_static() { \
|
static const ::godot::StringName &get_parent_class_static() { \
|
||||||
return m_inherits::get_class_static(); \
|
return m_inherits::get_class_static(); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include <godot_cpp/variant/callable_method_pointer.hpp>
|
#include <godot_cpp/variant/callable_method_pointer.hpp>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -104,6 +105,8 @@ private:
|
||||||
static std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks;
|
static std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks;
|
||||||
// Used to remember the custom class registration order.
|
// Used to remember the custom class registration order.
|
||||||
static std::vector<StringName> class_register_order;
|
static std::vector<StringName> class_register_order;
|
||||||
|
static std::unordered_map<StringName, Object *> engine_singletons;
|
||||||
|
static std::mutex engine_singletons_mutex;
|
||||||
|
|
||||||
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount);
|
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount);
|
||||||
static void initialize_class(const ClassInfo &cl);
|
static void initialize_class(const ClassInfo &cl);
|
||||||
|
@ -151,6 +154,21 @@ public:
|
||||||
instance_binding_callbacks[p_name] = p_callbacks;
|
instance_binding_callbacks[p_name] = p_callbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _register_engine_singleton(const StringName &p_class_name, Object *p_singleton) {
|
||||||
|
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
|
||||||
|
std::unordered_map<StringName, Object *>::const_iterator i = engine_singletons.find(p_class_name);
|
||||||
|
if (i != engine_singletons.end()) {
|
||||||
|
ERR_FAIL_COND((*i).second != p_singleton);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
engine_singletons[p_class_name] = p_singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _unregister_engine_singleton(const StringName &p_class_name) {
|
||||||
|
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
|
||||||
|
engine_singletons.erase(p_class_name);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename N, typename M, typename... VarArgs>
|
template <typename N, typename M, typename... VarArgs>
|
||||||
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
|
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
|
||||||
|
|
||||||
|
@ -198,6 +216,8 @@ public:
|
||||||
template <typename T, bool is_abstract>
|
template <typename T, bool is_abstract>
|
||||||
void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
||||||
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
|
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
|
||||||
|
static_assert(!FunctionsAreSame<T::self_type::_bind_methods, T::parent_type::_bind_methods>::value, "Class must declare 'static void _bind_methods'.");
|
||||||
|
static_assert(!std::is_abstract_v<T> || is_abstract, "Class is abstract, please use GDREGISTER_ABSTRACT_CLASS.");
|
||||||
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
|
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
|
||||||
|
|
||||||
// Register this class within our plugin
|
// Register this class within our plugin
|
||||||
|
@ -325,4 +345,6 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
||||||
|
CLASSDB_SINGLETON_VARIANT_CAST;
|
||||||
|
|
||||||
#endif // GODOT_CLASS_DB_HPP
|
#endif // GODOT_CLASS_DB_HPP
|
||||||
|
|
|
@ -613,6 +613,14 @@ inline bool is_inf(double p_val) {
|
||||||
return std::isinf(p_val);
|
return std::isinf(p_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool is_finite(float p_val) {
|
||||||
|
return std::isfinite(p_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_finite(double p_val) {
|
||||||
|
return std::isfinite(p_val);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool is_equal_approx(float a, float b) {
|
inline bool is_equal_approx(float a, float b) {
|
||||||
// Check for exact equality first, required to handle "infinity" values.
|
// Check for exact equality first, required to handle "infinity" values.
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
|
|
|
@ -170,11 +170,11 @@ template <typename T>
|
||||||
struct PtrToArg<T *> {
|
struct PtrToArg<T *> {
|
||||||
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
|
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
|
||||||
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
|
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
|
||||||
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
|
return likely(p_ptr) ? reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
|
||||||
}
|
}
|
||||||
typedef Object *EncodeT;
|
typedef Object *EncodeT;
|
||||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||||
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
|
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,11 +182,11 @@ template <typename T>
|
||||||
struct PtrToArg<const T *> {
|
struct PtrToArg<const T *> {
|
||||||
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
|
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
|
||||||
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
|
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
|
||||||
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
|
return likely(p_ptr) ? reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
|
||||||
}
|
}
|
||||||
typedef const Object *EncodeT;
|
typedef const Object *EncodeT;
|
||||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||||
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
|
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,40 @@ struct PropertyInfo {
|
||||||
PropertyInfo(const GDExtensionPropertyInfo *p_info) :
|
PropertyInfo(const GDExtensionPropertyInfo *p_info) :
|
||||||
PropertyInfo(p_info->type, *reinterpret_cast<StringName *>(p_info->name), (PropertyHint)p_info->hint, *reinterpret_cast<String *>(p_info->hint_string), p_info->usage, *reinterpret_cast<StringName *>(p_info->class_name)) {}
|
PropertyInfo(p_info->type, *reinterpret_cast<StringName *>(p_info->name), (PropertyHint)p_info->hint, *reinterpret_cast<String *>(p_info->hint_string), p_info->usage, *reinterpret_cast<StringName *>(p_info->class_name)) {}
|
||||||
|
|
||||||
|
operator Dictionary() const {
|
||||||
|
Dictionary dict;
|
||||||
|
dict["name"] = name;
|
||||||
|
dict["class_name"] = class_name;
|
||||||
|
dict["type"] = type;
|
||||||
|
dict["hint"] = hint;
|
||||||
|
dict["hint_string"] = hint_string;
|
||||||
|
dict["usage"] = usage;
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PropertyInfo from_dict(const Dictionary &p_dict) {
|
||||||
|
PropertyInfo pi;
|
||||||
|
if (p_dict.has("type")) {
|
||||||
|
pi.type = Variant::Type(int(p_dict["type"]));
|
||||||
|
}
|
||||||
|
if (p_dict.has("name")) {
|
||||||
|
pi.name = p_dict["name"];
|
||||||
|
}
|
||||||
|
if (p_dict.has("class_name")) {
|
||||||
|
pi.class_name = p_dict["class_name"];
|
||||||
|
}
|
||||||
|
if (p_dict.has("hint")) {
|
||||||
|
pi.hint = PropertyHint(int(p_dict["hint"]));
|
||||||
|
}
|
||||||
|
if (p_dict.has("hint_string")) {
|
||||||
|
pi.hint_string = p_dict["hint_string"];
|
||||||
|
}
|
||||||
|
if (p_dict.has("usage")) {
|
||||||
|
pi.usage = p_dict["usage"];
|
||||||
|
}
|
||||||
|
return pi;
|
||||||
|
}
|
||||||
|
|
||||||
void _update(GDExtensionPropertyInfo *p_info) {
|
void _update(GDExtensionPropertyInfo *p_info) {
|
||||||
p_info->type = (GDExtensionVariantType)type;
|
p_info->type = (GDExtensionVariantType)type;
|
||||||
*(reinterpret_cast<StringName *>(p_info->name)) = name;
|
*(reinterpret_cast<StringName *>(p_info->name)) = name;
|
||||||
|
|
|
@ -58,6 +58,16 @@ struct TypesAreSame<A, A> {
|
||||||
static bool const value = true;
|
static bool const value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <auto A, auto B>
|
||||||
|
struct FunctionsAreSame {
|
||||||
|
static bool const value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <auto A>
|
||||||
|
struct FunctionsAreSame<A, A> {
|
||||||
|
static bool const value = true;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename B, typename D>
|
template <typename B, typename D>
|
||||||
struct TypeInherits {
|
struct TypeInherits {
|
||||||
static D *get_d();
|
static D *get_d();
|
||||||
|
|
|
@ -160,6 +160,7 @@ extern "C" GDExtensionInterfaceObjectDestroy gdextension_interface_object_destro
|
||||||
extern "C" GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton;
|
extern "C" GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton;
|
||||||
extern "C" GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding;
|
extern "C" GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding;
|
||||||
extern "C" GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding;
|
extern "C" GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding;
|
||||||
|
extern "C" GDExtensionInterfaceObjectFreeInstanceBinding gdextension_interface_object_free_instance_binding;
|
||||||
extern "C" GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance;
|
extern "C" GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance;
|
||||||
extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name;
|
extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name;
|
||||||
extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to;
|
extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to;
|
||||||
|
|
|
@ -65,6 +65,7 @@ struct _NO_DISCARD_ AABB {
|
||||||
bool operator!=(const AABB &p_rval) const;
|
bool operator!=(const AABB &p_rval) const;
|
||||||
|
|
||||||
bool is_equal_approx(const AABB &p_aabb) const;
|
bool is_equal_approx(const AABB &p_aabb) const;
|
||||||
|
bool is_finite() const;
|
||||||
_FORCE_INLINE_ bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
|
_FORCE_INLINE_ bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
|
||||||
_FORCE_INLINE_ bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
|
_FORCE_INLINE_ bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
|
||||||
_FORCE_INLINE_ bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
|
_FORCE_INLINE_ bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
|
||||||
|
|
|
@ -128,6 +128,7 @@ struct _NO_DISCARD_ Basis {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_equal_approx(const Basis &p_basis) const;
|
bool is_equal_approx(const Basis &p_basis) const;
|
||||||
|
bool is_finite() const;
|
||||||
|
|
||||||
bool operator==(const Basis &p_matrix) const;
|
bool operator==(const Basis &p_matrix) const;
|
||||||
bool operator!=(const Basis &p_matrix) const;
|
bool operator!=(const Basis &p_matrix) const;
|
||||||
|
|
|
@ -77,6 +77,7 @@ struct _NO_DISCARD_ Plane {
|
||||||
Plane operator-() const { return Plane(-normal, -d); }
|
Plane operator-() const { return Plane(-normal, -d); }
|
||||||
bool is_equal_approx(const Plane &p_plane) const;
|
bool is_equal_approx(const Plane &p_plane) const;
|
||||||
bool is_equal_approx_any_side(const Plane &p_plane) const;
|
bool is_equal_approx_any_side(const Plane &p_plane) const;
|
||||||
|
bool is_finite() const;
|
||||||
|
|
||||||
_FORCE_INLINE_ bool operator==(const Plane &p_plane) const;
|
_FORCE_INLINE_ bool operator==(const Plane &p_plane) const;
|
||||||
_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;
|
_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct _NO_DISCARD_ Quaternion {
|
||||||
}
|
}
|
||||||
_FORCE_INLINE_ real_t length_squared() const;
|
_FORCE_INLINE_ real_t length_squared() const;
|
||||||
bool is_equal_approx(const Quaternion &p_quaternion) const;
|
bool is_equal_approx(const Quaternion &p_quaternion) const;
|
||||||
|
bool is_finite() const;
|
||||||
real_t length() const;
|
real_t length() const;
|
||||||
void normalize();
|
void normalize();
|
||||||
Quaternion normalized() const;
|
Quaternion normalized() const;
|
||||||
|
|
|
@ -209,6 +209,7 @@ struct _NO_DISCARD_ Rect2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_equal_approx(const Rect2 &p_rect) const;
|
bool is_equal_approx(const Rect2 &p_rect) const;
|
||||||
|
bool is_finite() const;
|
||||||
|
|
||||||
bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
|
bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
|
||||||
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
|
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
|
||||||
|
|
|
@ -99,6 +99,7 @@ struct _NO_DISCARD_ Transform2D {
|
||||||
void orthonormalize();
|
void orthonormalize();
|
||||||
Transform2D orthonormalized() const;
|
Transform2D orthonormalized() const;
|
||||||
bool is_equal_approx(const Transform2D &p_transform) const;
|
bool is_equal_approx(const Transform2D &p_transform) const;
|
||||||
|
bool is_finite() const;
|
||||||
|
|
||||||
Transform2D looking_at(const Vector2 &p_target) const;
|
Transform2D looking_at(const Vector2 &p_target) const;
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ struct _NO_DISCARD_ Transform3D {
|
||||||
void orthogonalize();
|
void orthogonalize();
|
||||||
Transform3D orthogonalized() const;
|
Transform3D orthogonalized() const;
|
||||||
bool is_equal_approx(const Transform3D &p_transform) const;
|
bool is_equal_approx(const Transform3D &p_transform) const;
|
||||||
|
bool is_finite() const;
|
||||||
|
|
||||||
bool operator==(const Transform3D &p_transform) const;
|
bool operator==(const Transform3D &p_transform) const;
|
||||||
bool operator!=(const Transform3D &p_transform) const;
|
bool operator!=(const Transform3D &p_transform) const;
|
||||||
|
|
|
@ -123,6 +123,7 @@ struct _NO_DISCARD_ Vector2 {
|
||||||
|
|
||||||
bool is_equal_approx(const Vector2 &p_v) const;
|
bool is_equal_approx(const Vector2 &p_v) const;
|
||||||
bool is_zero_approx() const;
|
bool is_zero_approx() const;
|
||||||
|
bool is_finite() const;
|
||||||
|
|
||||||
Vector2 operator+(const Vector2 &p_v) const;
|
Vector2 operator+(const Vector2 &p_v) const;
|
||||||
void operator+=(const Vector2 &p_v);
|
void operator+=(const Vector2 &p_v);
|
||||||
|
|
|
@ -146,6 +146,7 @@ struct _NO_DISCARD_ Vector3 {
|
||||||
|
|
||||||
bool is_equal_approx(const Vector3 &p_v) const;
|
bool is_equal_approx(const Vector3 &p_v) const;
|
||||||
bool is_zero_approx() const;
|
bool is_zero_approx() const;
|
||||||
|
bool is_finite() const;
|
||||||
|
|
||||||
/* Operators */
|
/* Operators */
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ struct _NO_DISCARD_ Vector4 {
|
||||||
_FORCE_INLINE_ real_t length_squared() const;
|
_FORCE_INLINE_ real_t length_squared() const;
|
||||||
bool is_equal_approx(const Vector4 &p_vec4) const;
|
bool is_equal_approx(const Vector4 &p_vec4) const;
|
||||||
bool is_zero_approx() const;
|
bool is_zero_approx() const;
|
||||||
|
bool is_finite() const;
|
||||||
real_t length() const;
|
real_t length() const;
|
||||||
void normalize();
|
void normalize();
|
||||||
Vector4 normalized() const;
|
Vector4 normalized() const;
|
||||||
|
|
|
@ -51,10 +51,7 @@ void Wrapped::_postinitialize() {
|
||||||
}
|
}
|
||||||
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
|
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
|
||||||
if (extension_class) {
|
if (extension_class) {
|
||||||
Object *obj = dynamic_cast<Object *>(this);
|
_notificationv(Object::NOTIFICATION_POSTINITIALIZE);
|
||||||
if (obj) {
|
|
||||||
obj->notification(Object::NOTIFICATION_POSTINITIALIZE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ namespace godot {
|
||||||
std::unordered_map<StringName, ClassDB::ClassInfo> ClassDB::classes;
|
std::unordered_map<StringName, ClassDB::ClassInfo> ClassDB::classes;
|
||||||
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> ClassDB::instance_binding_callbacks;
|
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> ClassDB::instance_binding_callbacks;
|
||||||
std::vector<StringName> ClassDB::class_register_order;
|
std::vector<StringName> ClassDB::class_register_order;
|
||||||
|
std::unordered_map<StringName, Object *> ClassDB::engine_singletons;
|
||||||
|
std::mutex ClassDB::engine_singletons_mutex;
|
||||||
GDExtensionInitializationLevel ClassDB::current_level = GDEXTENSION_INITIALIZATION_CORE;
|
GDExtensionInitializationLevel ClassDB::current_level = GDEXTENSION_INITIALIZATION_CORE;
|
||||||
|
|
||||||
MethodDefinition D_METHOD(StringName p_name) {
|
MethodDefinition D_METHOD(StringName p_name) {
|
||||||
|
@ -378,6 +380,22 @@ void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
|
||||||
});
|
});
|
||||||
class_register_order.erase(it, class_register_order.end());
|
class_register_order.erase(it, class_register_order.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_level == GDEXTENSION_INITIALIZATION_CORE) {
|
||||||
|
// Make a new list of the singleton objects, since freeing the instance bindings will lead to
|
||||||
|
// elements getting removed from engine_singletons.
|
||||||
|
std::vector<Object *> singleton_objects;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
|
||||||
|
singleton_objects.reserve(engine_singletons.size());
|
||||||
|
for (const std::pair<StringName, Object *> &pair : engine_singletons) {
|
||||||
|
singleton_objects.push_back(pair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (std::vector<Object *>::iterator i = singleton_objects.begin(); i != singleton_objects.end(); i++) {
|
||||||
|
internal::gdextension_interface_object_free_instance_binding((*i)->_owner, internal::token);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
|
@ -60,8 +60,66 @@ Object *get_object_instance_binding(GodotObject *p_engine_object) {
|
||||||
return reinterpret_cast<Object *>(gdextension_interface_object_get_instance_binding(p_engine_object, token, binding_callbacks));
|
return reinterpret_cast<Object *>(gdextension_interface_object_get_instance_binding(p_engine_object, token, binding_callbacks));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypedArray<Dictionary> convert_property_list(const std::vector<PropertyInfo> &p_list) {
|
||||||
|
TypedArray<Dictionary> va;
|
||||||
|
for (const PropertyInfo &pi : p_list) {
|
||||||
|
va.push_back(Dictionary(pi));
|
||||||
|
}
|
||||||
|
return va;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
MethodInfo::operator Dictionary() const {
|
||||||
|
Dictionary dict;
|
||||||
|
dict["name"] = name;
|
||||||
|
dict["args"] = internal::convert_property_list(arguments);
|
||||||
|
Array da;
|
||||||
|
for (int i = 0; i < default_arguments.size(); i++) {
|
||||||
|
da.push_back(default_arguments[i]);
|
||||||
|
}
|
||||||
|
dict["default_args"] = da;
|
||||||
|
dict["flags"] = flags;
|
||||||
|
dict["id"] = id;
|
||||||
|
Dictionary r = return_val;
|
||||||
|
dict["return"] = r;
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) {
|
||||||
|
MethodInfo mi;
|
||||||
|
|
||||||
|
if (p_dict.has("name")) {
|
||||||
|
mi.name = p_dict["name"];
|
||||||
|
}
|
||||||
|
Array args;
|
||||||
|
if (p_dict.has("args")) {
|
||||||
|
args = p_dict["args"];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < args.size(); i++) {
|
||||||
|
Dictionary d = args[i];
|
||||||
|
mi.arguments.push_back(PropertyInfo::from_dict(d));
|
||||||
|
}
|
||||||
|
Array defargs;
|
||||||
|
if (p_dict.has("default_args")) {
|
||||||
|
defargs = p_dict["default_args"];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < defargs.size(); i++) {
|
||||||
|
mi.default_arguments.push_back(defargs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_dict.has("return")) {
|
||||||
|
mi.return_val = PropertyInfo::from_dict(p_dict["return"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_dict.has("flags")) {
|
||||||
|
mi.flags = p_dict["flags"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return mi;
|
||||||
|
}
|
||||||
|
|
||||||
MethodInfo::MethodInfo() :
|
MethodInfo::MethodInfo() :
|
||||||
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}
|
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,7 @@ GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy = nullptr
|
||||||
GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton = nullptr;
|
GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton = nullptr;
|
||||||
GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding = nullptr;
|
GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding = nullptr;
|
||||||
GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding = nullptr;
|
GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding = nullptr;
|
||||||
|
GDExtensionInterfaceObjectFreeInstanceBinding gdextension_interface_object_free_instance_binding = nullptr;
|
||||||
GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance = nullptr;
|
GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance = nullptr;
|
||||||
GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name = nullptr;
|
GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name = nullptr;
|
||||||
GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
|
GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
|
||||||
|
@ -403,6 +404,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||||
LOAD_PROC_ADDRESS(global_get_singleton, GDExtensionInterfaceGlobalGetSingleton);
|
LOAD_PROC_ADDRESS(global_get_singleton, GDExtensionInterfaceGlobalGetSingleton);
|
||||||
LOAD_PROC_ADDRESS(object_get_instance_binding, GDExtensionInterfaceObjectGetInstanceBinding);
|
LOAD_PROC_ADDRESS(object_get_instance_binding, GDExtensionInterfaceObjectGetInstanceBinding);
|
||||||
LOAD_PROC_ADDRESS(object_set_instance_binding, GDExtensionInterfaceObjectSetInstanceBinding);
|
LOAD_PROC_ADDRESS(object_set_instance_binding, GDExtensionInterfaceObjectSetInstanceBinding);
|
||||||
|
LOAD_PROC_ADDRESS(object_free_instance_binding, GDExtensionInterfaceObjectFreeInstanceBinding);
|
||||||
LOAD_PROC_ADDRESS(object_set_instance, GDExtensionInterfaceObjectSetInstance);
|
LOAD_PROC_ADDRESS(object_set_instance, GDExtensionInterfaceObjectSetInstance);
|
||||||
LOAD_PROC_ADDRESS(object_get_class_name, GDExtensionInterfaceObjectGetClassName);
|
LOAD_PROC_ADDRESS(object_get_class_name, GDExtensionInterfaceObjectGetClassName);
|
||||||
LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo);
|
LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo);
|
||||||
|
|
|
@ -78,6 +78,10 @@ bool AABB::is_equal_approx(const AABB &p_aabb) const {
|
||||||
return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size);
|
return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AABB::is_finite() const {
|
||||||
|
return position.is_finite() && size.is_finite();
|
||||||
|
}
|
||||||
|
|
||||||
AABB AABB::intersection(const AABB &p_aabb) const {
|
AABB AABB::intersection(const AABB &p_aabb) const {
|
||||||
#ifdef MATH_CHECKS
|
#ifdef MATH_CHECKS
|
||||||
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
|
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
|
||||||
|
|
|
@ -692,6 +692,10 @@ bool Basis::is_equal_approx(const Basis &p_basis) const {
|
||||||
return rows[0].is_equal_approx(p_basis.rows[0]) && rows[1].is_equal_approx(p_basis.rows[1]) && rows[2].is_equal_approx(p_basis.rows[2]);
|
return rows[0].is_equal_approx(p_basis.rows[0]) && rows[1].is_equal_approx(p_basis.rows[1]) && rows[2].is_equal_approx(p_basis.rows[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Basis::is_finite() const {
|
||||||
|
return rows[0].is_finite() && rows[1].is_finite() && rows[2].is_finite();
|
||||||
|
}
|
||||||
|
|
||||||
bool Basis::operator==(const Basis &p_matrix) const {
|
bool Basis::operator==(const Basis &p_matrix) const {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
|
|
|
@ -178,6 +178,10 @@ bool Plane::is_equal_approx(const Plane &p_plane) const {
|
||||||
return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d);
|
return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Plane::is_finite() const {
|
||||||
|
return normal.is_finite() && Math::is_finite(d);
|
||||||
|
}
|
||||||
|
|
||||||
Plane::operator String() const {
|
Plane::operator String() const {
|
||||||
return "[N: " + normal.operator String() + ", D: " + String::num_real(d, false) + "]";
|
return "[N: " + normal.operator String() + ", D: " + String::num_real(d, false) + "]";
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,10 @@ bool Quaternion::is_equal_approx(const Quaternion &p_quaternion) const {
|
||||||
return Math::is_equal_approx(x, p_quaternion.x) && Math::is_equal_approx(y, p_quaternion.y) && Math::is_equal_approx(z, p_quaternion.z) && Math::is_equal_approx(w, p_quaternion.w);
|
return Math::is_equal_approx(x, p_quaternion.x) && Math::is_equal_approx(y, p_quaternion.y) && Math::is_equal_approx(z, p_quaternion.z) && Math::is_equal_approx(w, p_quaternion.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Quaternion::is_finite() const {
|
||||||
|
return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z) && Math::is_finite(w);
|
||||||
|
}
|
||||||
|
|
||||||
real_t Quaternion::length() const {
|
real_t Quaternion::length() const {
|
||||||
return Math::sqrt(length_squared());
|
return Math::sqrt(length_squared());
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
|
||||||
return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size);
|
return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Rect2::is_finite() const {
|
||||||
|
return position.is_finite() && size.is_finite();
|
||||||
|
}
|
||||||
|
|
||||||
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
|
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
|
||||||
#ifdef MATH_CHECKS
|
#ifdef MATH_CHECKS
|
||||||
if (unlikely(size.x < 0 || size.y < 0)) {
|
if (unlikely(size.x < 0 || size.y < 0)) {
|
||||||
|
|
|
@ -170,6 +170,10 @@ bool Transform2D::is_equal_approx(const Transform2D &p_transform) const {
|
||||||
return columns[0].is_equal_approx(p_transform.columns[0]) && columns[1].is_equal_approx(p_transform.columns[1]) && columns[2].is_equal_approx(p_transform.columns[2]);
|
return columns[0].is_equal_approx(p_transform.columns[0]) && columns[1].is_equal_approx(p_transform.columns[1]) && columns[2].is_equal_approx(p_transform.columns[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Transform2D::is_finite() const {
|
||||||
|
return columns[0].is_finite() && columns[1].is_finite() && columns[2].is_finite();
|
||||||
|
}
|
||||||
|
|
||||||
Transform2D Transform2D::looking_at(const Vector2 &p_target) const {
|
Transform2D Transform2D::looking_at(const Vector2 &p_target) const {
|
||||||
Transform2D return_trans = Transform2D(get_rotation(), get_origin());
|
Transform2D return_trans = Transform2D(get_rotation(), get_origin());
|
||||||
Vector2 target_position = affine_inverse().xform(p_target);
|
Vector2 target_position = affine_inverse().xform(p_target);
|
||||||
|
|
|
@ -175,6 +175,10 @@ bool Transform3D::is_equal_approx(const Transform3D &p_transform) const {
|
||||||
return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
|
return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Transform3D::is_finite() const {
|
||||||
|
return basis.is_finite() && origin.is_finite();
|
||||||
|
}
|
||||||
|
|
||||||
bool Transform3D::operator==(const Transform3D &p_transform) const {
|
bool Transform3D::operator==(const Transform3D &p_transform) const {
|
||||||
return (basis == p_transform.basis && origin == p_transform.origin);
|
return (basis == p_transform.basis && origin == p_transform.origin);
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,10 @@ bool Vector2::is_zero_approx() const {
|
||||||
return Math::is_zero_approx(x) && Math::is_zero_approx(y);
|
return Math::is_zero_approx(x) && Math::is_zero_approx(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Vector2::is_finite() const {
|
||||||
|
return Math::is_finite(x) && Math::is_finite(y);
|
||||||
|
}
|
||||||
|
|
||||||
Vector2::operator String() const {
|
Vector2::operator String() const {
|
||||||
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")";
|
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")";
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,10 @@ bool Vector3::is_zero_approx() const {
|
||||||
return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z);
|
return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Vector3::is_finite() const {
|
||||||
|
return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z);
|
||||||
|
}
|
||||||
|
|
||||||
Vector3::operator String() const {
|
Vector3::operator String() const {
|
||||||
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")";
|
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")";
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,10 @@ bool Vector4::is_zero_approx() const {
|
||||||
return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z) && Math::is_zero_approx(w);
|
return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z) && Math::is_zero_approx(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Vector4::is_finite() const {
|
||||||
|
return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z) && Math::is_finite(w);
|
||||||
|
}
|
||||||
|
|
||||||
real_t Vector4::length() const {
|
real_t Vector4::length() const {
|
||||||
return Math::sqrt(length_squared());
|
return Math::sqrt(length_squared());
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,6 +185,10 @@ func _ready():
|
||||||
control.queue_free()
|
control.queue_free()
|
||||||
sprite.queue_free()
|
sprite.queue_free()
|
||||||
|
|
||||||
|
# Test that passing null for objects works as expected too.
|
||||||
|
var example_null : Example = null
|
||||||
|
assert_equal(example.test_object_cast_to_node(example_null), false)
|
||||||
|
|
||||||
# Test conversions to and from Variant.
|
# Test conversions to and from Variant.
|
||||||
assert_equal(example.test_variant_vector2i_conversion(Vector2i(1, 1)), Vector2i(1, 1))
|
assert_equal(example.test_variant_vector2i_conversion(Vector2i(1, 1)), Vector2i(1, 1))
|
||||||
assert_equal(example.test_variant_vector2i_conversion(Vector2(1.0, 1.0)), Vector2i(1, 1))
|
assert_equal(example.test_variant_vector2i_conversion(Vector2(1.0, 1.0)), Vector2i(1, 1))
|
||||||
|
@ -242,6 +246,9 @@ func _ready():
|
||||||
assert_equal(new_example_ref.was_post_initialized(), true)
|
assert_equal(new_example_ref.was_post_initialized(), true)
|
||||||
assert_equal(example.test_post_initialize(), true)
|
assert_equal(example.test_post_initialize(), true)
|
||||||
|
|
||||||
|
# Test that we can access an engine singleton.
|
||||||
|
assert_equal(example.test_use_engine_singleton(), OS.get_name())
|
||||||
|
|
||||||
# Test that notifications happen on both parent and child classes.
|
# Test that notifications happen on both parent and child classes.
|
||||||
var example_child = $ExampleChild
|
var example_child = $ExampleChild
|
||||||
assert_equal(example_child.get_value1(), 11)
|
assert_equal(example_child.get_value1(), 11)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <godot_cpp/classes/label.hpp>
|
#include <godot_cpp/classes/label.hpp>
|
||||||
#include <godot_cpp/classes/multiplayer_api.hpp>
|
#include <godot_cpp/classes/multiplayer_api.hpp>
|
||||||
#include <godot_cpp/classes/multiplayer_peer.hpp>
|
#include <godot_cpp/classes/multiplayer_peer.hpp>
|
||||||
|
#include <godot_cpp/classes/os.hpp>
|
||||||
#include <godot_cpp/variant/utility_functions.hpp>
|
#include <godot_cpp/variant/utility_functions.hpp>
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
@ -231,6 +232,8 @@ void Example::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("callable_bind"), &Example::callable_bind);
|
ClassDB::bind_method(D_METHOD("callable_bind"), &Example::callable_bind);
|
||||||
ClassDB::bind_method(D_METHOD("test_post_initialize"), &Example::test_post_initialize);
|
ClassDB::bind_method(D_METHOD("test_post_initialize"), &Example::test_post_initialize);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("test_use_engine_singleton"), &Example::test_use_engine_singleton);
|
||||||
|
|
||||||
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
|
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
|
||||||
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
|
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
|
||||||
|
|
||||||
|
@ -654,3 +657,7 @@ void ExampleChild::_notification(int p_what) {
|
||||||
value2 = 33;
|
value2 = 33;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String Example::test_use_engine_singleton() const {
|
||||||
|
return OS::get_singleton()->get_name();
|
||||||
|
}
|
||||||
|
|
|
@ -182,6 +182,8 @@ public:
|
||||||
// Virtual function override (no need to bind manually).
|
// Virtual function override (no need to bind manually).
|
||||||
virtual bool _has_point(const Vector2 &point) const override;
|
virtual bool _has_point(const Vector2 &point) const override;
|
||||||
virtual void _input(const Ref<InputEvent> &event) override;
|
virtual void _input(const Ref<InputEvent> &event) override;
|
||||||
|
|
||||||
|
String test_use_engine_singleton() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(Example::Constants);
|
VARIANT_ENUM_CAST(Example::Constants);
|
||||||
|
|
Loading…
Reference in New Issue