summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/engine.cpp30
-rw-r--r--core/config/engine.h7
-rw-r--r--core/core_bind.cpp35
-rw-r--r--core/core_bind.h7
-rw-r--r--core/doc_data.h1
-rw-r--r--core/extension/native_extension.cpp2
-rw-r--r--core/extension/native_extension.h2
-rw-r--r--core/extension/native_extension_manager.cpp19
-rw-r--r--core/extension/native_extension_manager.h3
-rw-r--r--core/io/config_file.cpp2
-rw-r--r--core/object/class_db.cpp26
-rw-r--r--core/object/class_db.h28
-rw-r--r--core/register_core_types.cpp8
13 files changed, 154 insertions, 16 deletions
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 495670bc88..d8fbb50a75 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -199,17 +199,41 @@ bool Engine::is_printing_error_messages() const {
}
void Engine::add_singleton(const Singleton &p_singleton) {
+ ERR_FAIL_COND_MSG(singleton_ptrs.has(p_singleton.name), "Can't register singleton that already exists: " + String(p_singleton.name));
singletons.push_back(p_singleton);
singleton_ptrs[p_singleton.name] = p_singleton.ptr;
}
-Object *Engine::get_singleton_object(const String &p_name) const {
+Object *Engine::get_singleton_object(const StringName &p_name) const {
const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name);
- ERR_FAIL_COND_V_MSG(!E, nullptr, "Failed to retrieve non-existent singleton '" + p_name + "'.");
+ ERR_FAIL_COND_V_MSG(!E, nullptr, "Failed to retrieve non-existent singleton '" + String(p_name) + "'.");
return E->get();
}
-bool Engine::has_singleton(const String &p_name) const {
+bool Engine::is_singleton_user_created(const StringName &p_name) const {
+ ERR_FAIL_COND_V(!singleton_ptrs.has(p_name), false);
+
+ for (const Singleton &E : singletons) {
+ if (E.name == p_name && E.user_created) {
+ return true;
+ }
+ }
+
+ return false;
+}
+void Engine::remove_singleton(const StringName &p_name) {
+ ERR_FAIL_COND(!singleton_ptrs.has(p_name));
+
+ for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) {
+ if (E->get().name == p_name) {
+ singletons.erase(E);
+ singleton_ptrs.erase(p_name);
+ return;
+ }
+ }
+}
+
+bool Engine::has_singleton(const StringName &p_name) const {
return singleton_ptrs.has(p_name);
}
diff --git a/core/config/engine.h b/core/config/engine.h
index e6b5df2d5a..ae33acede2 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -42,6 +42,7 @@ public:
StringName name;
Object *ptr;
StringName class_name; //used for binding generation hinting
+ bool user_created = false;
Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr, const StringName &p_class_name = StringName());
};
@@ -109,8 +110,10 @@ public:
void add_singleton(const Singleton &p_singleton);
void get_singletons(List<Singleton> *p_singletons);
- bool has_singleton(const String &p_name) const;
- Object *get_singleton_object(const String &p_name) const;
+ bool has_singleton(const StringName &p_name) const;
+ Object *get_singleton_object(const StringName &p_name) const;
+ void remove_singleton(const StringName &p_name);
+ bool is_singleton_user_created(const StringName &p_name) const;
#ifdef TOOLS_ENABLED
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) { editor_hint = p_enabled; }
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index efb4b84716..83a3b80803 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -2165,14 +2165,41 @@ bool Engine::is_in_physics_frame() const {
return ::Engine::get_singleton()->is_in_physics_frame();
}
-bool Engine::has_singleton(const String &p_name) const {
+bool Engine::has_singleton(const StringName &p_name) const {
return ::Engine::get_singleton()->has_singleton(p_name);
}
-Object *Engine::get_singleton_object(const String &p_name) const {
+Object *Engine::get_singleton_object(const StringName &p_name) const {
return ::Engine::get_singleton()->get_singleton_object(p_name);
}
+void Engine::register_singleton(const StringName &p_name, Object *p_object) {
+ ERR_FAIL_COND_MSG(has_singleton(p_name), "Singleton already registered: " + String(p_name));
+ ERR_FAIL_COND_MSG(p_name.operator String().is_valid_identifier(), "Singleton name is not a valid identifier: " + String(p_name));
+ ::Engine::Singleton s;
+ s.class_name = p_name;
+ s.name = p_name;
+ s.ptr = p_object;
+ s.user_created = true;
+ ::Engine::get_singleton()->add_singleton(s);
+ ;
+}
+void Engine::unregister_singleton(const StringName &p_name) {
+ ERR_FAIL_COND_MSG(!has_singleton(p_name), "Attempt to remove unregisteres singleton: " + String(p_name));
+ ERR_FAIL_COND_MSG(!::Engine::get_singleton()->is_singleton_user_created(p_name), "Attempt to remove non-user created singleton: " + String(p_name));
+ ::Engine::get_singleton()->remove_singleton(p_name);
+}
+
+Vector<String> Engine::get_singleton_list() const {
+ List<::Engine::Singleton> singletons;
+ ::Engine::get_singleton()->get_singletons(&singletons);
+ Vector<String> ret;
+ for (List<::Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
+ ret.push_back(E->get().name);
+ }
+ return ret;
+}
+
void Engine::set_editor_hint(bool p_enabled) {
::Engine::get_singleton()->set_editor_hint(p_enabled);
}
@@ -2220,6 +2247,10 @@ void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_singleton", "name"), &Engine::has_singleton);
ClassDB::bind_method(D_METHOD("get_singleton", "name"), &Engine::get_singleton_object);
+ ClassDB::bind_method(D_METHOD("register_singleton", "name", "instance"), &Engine::register_singleton);
+ ClassDB::bind_method(D_METHOD("unregister_singleton", "name"), &Engine::unregister_singleton);
+ ClassDB::bind_method(D_METHOD("get_singleton_list"), &Engine::get_singleton_list);
+
ClassDB::bind_method(D_METHOD("set_editor_hint", "enabled"), &Engine::set_editor_hint);
ClassDB::bind_method(D_METHOD("is_editor_hint"), &Engine::is_editor_hint);
diff --git a/core/core_bind.h b/core/core_bind.h
index 1dbe49f418..a6fac63edd 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -639,8 +639,11 @@ public:
bool is_in_physics_frame() const;
- bool has_singleton(const String &p_name) const;
- Object *get_singleton_object(const String &p_name) const;
+ bool has_singleton(const StringName &p_name) const;
+ Object *get_singleton_object(const StringName &p_name) const;
+ void register_singleton(const StringName &p_name, Object *p_object);
+ void unregister_singleton(const StringName &p_name);
+ Vector<String> get_singleton_list() const;
void set_editor_hint(bool p_enabled);
bool is_editor_hint() const;
diff --git a/core/doc_data.h b/core/doc_data.h
index a3011fe275..19dec71927 100644
--- a/core/doc_data.h
+++ b/core/doc_data.h
@@ -67,6 +67,7 @@ public:
String qualifiers;
String description;
Vector<ArgumentDoc> arguments;
+ Vector<int> errors_returned;
bool operator<(const MethodDoc &p_method) const {
if (name == p_method.name) {
// Must be a constructor since there is no overloading.
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 0556c9c84d..a3cd7ca14c 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -35,6 +35,8 @@
#include "core/object/method_bind.h"
#include "core/os/os.h"
+const char *NativeExtension::EXTENSION_LIST_CONFIG_FILE = "res://.godot/extension_list.cfg";
+
class NativeExtensionMethodBind : public MethodBind {
GDNativeExtensionClassMethodCall call_func;
GDNativeExtensionClassMethodPtrCall ptrcall_func;
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
index a961b21cc9..b661381d64 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/native_extension.h
@@ -60,6 +60,8 @@ protected:
static void _bind_methods();
public:
+ static const char *EXTENSION_LIST_CONFIG_FILE;
+
Error open_library(const String &p_path, const String &p_entry_symbol);
void close_library();
diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp
index 7be2593845..8b7a9df4f1 100644
--- a/core/extension/native_extension_manager.cpp
+++ b/core/extension/native_extension_manager.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "native_extension_manager.h"
+#include "core/io/file_access.h"
NativeExtensionManager::LoadStatus NativeExtensionManager::load_extension(const String &p_path) {
if (native_extension_map.has(p_path)) {
@@ -76,6 +77,11 @@ NativeExtensionManager::LoadStatus NativeExtensionManager::unload_extension(cons
native_extension_map.erase(p_path);
return LOAD_STATUS_OK;
}
+
+bool NativeExtensionManager::is_extension_loaded(const String &p_path) const {
+ return native_extension_map.has(p_path);
+}
+
Vector<String> NativeExtensionManager::get_loaded_extensions() const {
Vector<String> ret;
for (const Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
@@ -105,6 +111,17 @@ void NativeExtensionManager::deinitialize_extensions(NativeExtension::Initializa
level = int32_t(p_level) - 1;
}
+void NativeExtensionManager::load_extensions() {
+ FileAccessRef f = FileAccess::open(NativeExtension::EXTENSION_LIST_CONFIG_FILE, FileAccess::READ);
+ while (f && !f->eof_reached()) {
+ String s = f->get_line().strip_edges();
+ if (s != String()) {
+ LoadStatus err = load_extension(s);
+ ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, "Error loading extension: " + s);
+ }
+ }
+}
+
NativeExtensionManager *NativeExtensionManager::get_singleton() {
return singleton;
}
@@ -112,6 +129,8 @@ void NativeExtensionManager::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_extension", "path"), &NativeExtensionManager::load_extension);
ClassDB::bind_method(D_METHOD("reload_extension", "path"), &NativeExtensionManager::reload_extension);
ClassDB::bind_method(D_METHOD("unload_extension", "path"), &NativeExtensionManager::unload_extension);
+ ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &NativeExtensionManager::is_extension_loaded);
+
ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &NativeExtensionManager::get_loaded_extensions);
ClassDB::bind_method(D_METHOD("get_extension", "path"), &NativeExtensionManager::get_extension);
diff --git a/core/extension/native_extension_manager.h b/core/extension/native_extension_manager.h
index 78465bd5cf..89ccd155fe 100644
--- a/core/extension/native_extension_manager.h
+++ b/core/extension/native_extension_manager.h
@@ -55,6 +55,7 @@ public:
LoadStatus load_extension(const String &p_path);
LoadStatus reload_extension(const String &p_path);
LoadStatus unload_extension(const String &p_path);
+ bool is_extension_loaded(const String &p_path) const;
Vector<String> get_loaded_extensions() const;
Ref<NativeExtension> get_extension(const String &p_path);
@@ -63,6 +64,8 @@ public:
static NativeExtensionManager *get_singleton();
+ void load_extensions();
+
NativeExtensionManager();
};
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index aeaf25f321..55793aa5a4 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -315,6 +315,8 @@ void ConfigFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("parse", "data"), &ConfigFile::parse);
ClassDB::bind_method(D_METHOD("save", "path"), &ConfigFile::save);
+ BIND_METHOD_ERR_RETURN_DOC("load", ERR_FILE_CANT_OPEN);
+
ClassDB::bind_method(D_METHOD("load_encrypted", "path", "key"), &ConfigFile::load_encrypted);
ClassDB::bind_method(D_METHOD("load_encrypted_pass", "path", "password"), &ConfigFile::load_encrypted_pass);
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index b29b2bd421..e268a8d292 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -892,6 +892,32 @@ void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_
}
}
+void ClassDB::set_method_error_return_values(const StringName &p_class, const StringName &p_method, const Vector<Error> &p_values) {
+ OBJTYPE_RLOCK;
+#ifdef DEBUG_METHODS_ENABLED
+ ClassInfo *type = classes.getptr(p_class);
+
+ ERR_FAIL_COND(!type);
+
+ type->method_error_values[p_method] = p_values;
+#endif
+}
+
+Vector<Error> ClassDB::get_method_error_return_values(const StringName &p_class, const StringName &p_method) {
+#ifdef DEBUG_METHODS_ENABLED
+ ClassInfo *type = classes.getptr(p_class);
+
+ ERR_FAIL_COND_V(!type, Vector<Error>());
+
+ if (!type->method_error_values.has(p_method)) {
+ return Vector<Error>();
+ }
+ return type->method_error_values[p_method];
+#else
+ return Vector<Error>();
+#endif
+}
+
bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
OBJTYPE_RLOCK;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 45572517be..166aa35469 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -132,6 +132,7 @@ public:
List<MethodInfo> virtual_methods;
Map<StringName, MethodInfo> virtual_methods_map;
StringName category;
+ Map<StringName, Vector<Error>> method_error_values;
#endif
HashMap<StringName, PropertySetGet> property_setget;
@@ -385,6 +386,8 @@ public:
static void get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance = false);
static bool has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
+ static void set_method_error_return_values(const StringName &p_class, const StringName &p_method, const Vector<Error> &p_values);
+ static Vector<Error> get_method_error_return_values(const StringName &p_class, const StringName &p_method);
static Variant class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid = nullptr);
static StringName get_category(const StringName &p_node);
@@ -415,6 +418,29 @@ public:
#define BIND_ENUM_CONSTANT(m_constant) \
::ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
+_FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr) {
+}
+
+_FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr, const Error &p_err) {
+ arr.push_back(p_err);
+}
+
+template <class... P>
+_FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr, const Error &p_err, P... p_args) {
+ arr.push_back(p_err);
+ errarray_add_str(arr, p_args...);
+}
+
+template <class... P>
+_FORCE_INLINE_ Vector<Error> errarray(P... p_args) {
+ Vector<Error> arr;
+ errarray_add_str(arr, p_args...);
+ return arr;
+}
+
+#define BIND_METHOD_ERR_RETURN_DOC(m_method, ...) \
+ ::ClassDB::set_method_error_return_values(get_class_static(), m_method, errarray(__VA_ARGS__));
+
#else
#define BIND_CONSTANT(m_constant) \
@@ -423,6 +449,8 @@ public:
#define BIND_ENUM_CONSTANT(m_constant) \
::ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
+#define BIND_METHOD_ERR_RETURN_DOC(m_method, ...)
+
#endif
#define GDREGISTER_CLASS(m_class) \
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 35f4532abb..6c7d9cbd89 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -308,13 +308,7 @@ void register_core_singletons() {
void register_core_extensions() {
// Hardcoded for now.
NativeExtension::initialize_native_extensions();
- if (ProjectSettings::get_singleton()->has_setting("native_extensions/paths")) {
- Vector<String> paths = ProjectSettings::get_singleton()->get("native_extensions/paths");
- for (int i = 0; i < paths.size(); i++) {
- NativeExtensionManager::LoadStatus status = native_extension_manager->load_extension(paths[i]);
- ERR_CONTINUE_MSG(status != NativeExtensionManager::LOAD_STATUS_OK, "Error loading extension: " + paths[i]);
- }
- }
+ native_extension_manager->load_extensions();
native_extension_manager->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE);
}