summaryrefslogtreecommitdiffstats
path: root/core/object/object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/object/object.cpp')
-rw-r--r--core/object/object.cpp69
1 files changed, 44 insertions, 25 deletions
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 40df13849b..5db1d2534f 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -29,6 +29,7 @@
/**************************************************************************/
#include "object.h"
+#include "object.compat.inc"
#include "core/core_string_names.h"
#include "core/extension/gdextension_manager.h"
@@ -492,14 +493,22 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
ClassDB::get_property_list(current_extension->class_name, p_list, true, this);
if (current_extension->get_property_list) {
- uint32_t pcount;
- const GDExtensionPropertyInfo *pinfo = current_extension->get_property_list(_extension_instance, &pcount);
- for (uint32_t i = 0; i < pcount; i++) {
- p_list->push_back(PropertyInfo(pinfo[i]));
- }
- if (current_extension->free_property_list) {
- current_extension->free_property_list(_extension_instance, pinfo);
+#ifdef TOOLS_ENABLED
+ // If this is a placeholder, we can't call into the GDExtension on the parent class,
+ // because we don't have a real instance of the class to give it.
+ if (likely(!_extension->is_placeholder)) {
+#endif
+ uint32_t pcount;
+ const GDExtensionPropertyInfo *pinfo = current_extension->get_property_list(_extension_instance, &pcount);
+ for (uint32_t i = 0; i < pcount; i++) {
+ p_list->push_back(PropertyInfo(pinfo[i]));
+ }
+ if (current_extension->free_property_list) {
+ current_extension->free_property_list(_extension_instance, pinfo);
+ }
+#ifdef TOOLS_ENABLED
}
+#endif
}
current_extension = current_extension->parent;
@@ -728,7 +737,7 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_
r_error.expected = 0;
return Variant();
}
- if (Object::cast_to<RefCounted>(this)) {
+ if (is_ref_counted()) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
ERR_FAIL_V_MSG(Variant(), "Can't 'free' a reference.");
}
@@ -1347,12 +1356,10 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui
s = &signal_map[p_signal];
}
- Callable target = p_callable;
-
//compare with the base callable, so binds can be ignored
- if (s->slot_map.has(*target.get_base_comparator())) {
+ if (s->slot_map.has(*p_callable.get_base_comparator())) {
if (p_flags & CONNECT_REFERENCE_COUNTED) {
- s->slot_map[*target.get_base_comparator()].reference_count++;
+ s->slot_map[*p_callable.get_base_comparator()].reference_count++;
return OK;
} else {
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Signal '" + p_signal + "' is already connected to given callable '" + p_callable + "' in that object.");
@@ -1364,7 +1371,7 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui
SignalData::Slot slot;
Connection conn;
- conn.callable = target;
+ conn.callable = p_callable;
conn.signal = ::Signal(this, p_signal);
conn.flags = p_flags;
slot.conn = conn;
@@ -1376,7 +1383,7 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui
}
//use callable version as key, so binds can be ignored
- s->slot_map[*target.get_base_comparator()] = slot;
+ s->slot_map[*p_callable.get_base_comparator()] = slot;
return OK;
}
@@ -1397,9 +1404,7 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable
ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + ".");
}
- Callable target = p_callable;
-
- return s->slot_map.has(*target.get_base_comparator());
+ return s->slot_map.has(*p_callable.get_base_comparator());
}
void Object::disconnect(const StringName &p_signal, const Callable &p_callable) {
@@ -1468,6 +1473,7 @@ void Object::initialize_class() {
}
ClassDB::_add_class<Object>();
_bind_methods();
+ _bind_compatibility_methods();
initialized = true;
}
@@ -1643,8 +1649,8 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_message_translation", "enable"), &Object::set_message_translation);
ClassDB::bind_method(D_METHOD("can_translate_messages"), &Object::can_translate_messages);
- ClassDB::bind_method(D_METHOD("tr", "message", "context"), &Object::tr, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("tr_n", "message", "plural_message", "n", "context"), &Object::tr_n, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("tr", "message", "context"), &Object::tr, DEFVAL(StringName()));
+ ClassDB::bind_method(D_METHOD("tr_n", "message", "plural_message", "n", "context"), &Object::tr_n, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("is_queued_for_deletion"), &Object::is_queued_for_deletion);
ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free);
@@ -1687,6 +1693,7 @@ void Object::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_POSTINITIALIZE);
BIND_CONSTANT(NOTIFICATION_PREDELETE);
+ BIND_CONSTANT(NOTIFICATION_EXTENSION_RELOADED);
BIND_ENUM_CONSTANT(CONNECT_DEFERRED);
BIND_ENUM_CONSTANT(CONNECT_PERSIST);
@@ -1795,6 +1802,16 @@ uint32_t Object::get_edited_version() const {
#endif
StringName Object::get_class_name_for_extension(const GDExtension *p_library) const {
+#ifdef TOOLS_ENABLED
+ // If this is the library this extension comes from and it's a placeholder, we
+ // have to return the closest native parent's class name, so that it doesn't try to
+ // use this like the real object.
+ if (unlikely(_extension && _extension->library == p_library && _extension->is_placeholder)) {
+ const StringName *class_name = _get_class_namev();
+ return *class_name;
+ }
+#endif
+
// Only return the class name per the extension if it matches the given p_library.
if (_extension && _extension->library == p_library) {
return _extension->class_name;
@@ -1922,13 +1939,15 @@ void Object::clear_internal_extension() {
// Clear the instance bindings.
_instance_binding_mutex.lock();
- if (_instance_bindings[0].free_callback) {
- _instance_bindings[0].free_callback(_instance_bindings[0].token, this, _instance_bindings[0].binding);
+ if (_instance_bindings) {
+ if (_instance_bindings[0].free_callback) {
+ _instance_bindings[0].free_callback(_instance_bindings[0].token, this, _instance_bindings[0].binding);
+ }
+ _instance_bindings[0].binding = nullptr;
+ _instance_bindings[0].token = nullptr;
+ _instance_bindings[0].free_callback = nullptr;
+ _instance_bindings[0].reference_callback = nullptr;
}
- _instance_bindings[0].binding = nullptr;
- _instance_bindings[0].token = nullptr;
- _instance_bindings[0].free_callback = nullptr;
- _instance_bindings[0].reference_callback = nullptr;
_instance_binding_mutex.unlock();
// Clear the virtual methods.