From f7ffc4fe4dcda59a3e9fd0c7250972238cdf8e04 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Wed, 11 Oct 2023 22:59:59 -0500 Subject: [PATCH] Automatically register only engine classes whose header has been included (cherry picked from commit b507b3e5913344a97e90ba27b221e28924f555ab) --- binding_generator.py | 64 +------------------ .../classes/editor_plugin_registration.hpp | 62 ++++++++++++++++++ include/godot_cpp/classes/wrapped.hpp | 21 ++++++ include/godot_cpp/core/class_db.hpp | 11 ++-- include/godot_cpp/godot.hpp | 3 - ...gin.cpp => editor_plugin_registration.cpp} | 6 +- src/classes/wrapped.cpp | 29 +++++++++ src/godot.cpp | 4 +- 8 files changed, 122 insertions(+), 78 deletions(-) create mode 100644 include/godot_cpp/classes/editor_plugin_registration.hpp rename src/classes/{editor_plugin.cpp => editor_plugin_registration.cpp} (95%) diff --git a/binding_generator.py b/binding_generator.py index 54ae9af6..18db9fd0 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -130,8 +130,6 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False): if sources: utility_functions_source_path = source_gen_folder / "variant" / "utility_functions.cpp" files.append(str(utility_functions_source_path.as_posix())) - register_engine_classes_source_path = source_gen_folder / "register_engine_classes.cpp" - files.append(str(register_engine_classes_source_path.as_posix())) return files @@ -1170,10 +1168,6 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): generate_engine_class_source(class_api, used_classes, fully_used_classes, use_template_get_node) ) - register_engine_classes_filename = Path(output_dir) / "src" / "register_engine_classes.cpp" - with register_engine_classes_filename.open("w+", encoding="utf-8") as source_file: - source_file.write(generate_register_engine_classes_source(api)) - for native_struct in api["native_structures"]: struct_name = native_struct["name"] snake_struct_name = camel_to_snake(struct_name) @@ -1248,7 +1242,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(f"#include ") if class_name == "EditorPlugin": - result.append("#include ") + result.append("#include ") if len(fully_used_classes) > 0: result.append("") @@ -1400,30 +1394,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("};") result.append("") - if class_name == "EditorPlugin": - result.append("class EditorPlugins {") - result.append("private:") - result.append("\tstatic Vector plugin_classes;") - result.append("") - result.append("public:") - result.append("\tstatic void add_plugin_class(const StringName &p_class_name);") - result.append("\tstatic void remove_plugin_class(const StringName &p_class_name);") - result.append("\tstatic void deinitialize(GDExtensionInitializationLevel p_level);") - result.append("") - - result.append("\ttemplate ") - result.append("\tstatic void add_by_type() {") - result.append("\t\tadd_plugin_class(T::get_class_static());") - result.append("\t}") - - result.append("\ttemplate ") - result.append("\tstatic void remove_by_type() {") - result.append("\t\tremove_plugin_class(T::get_class_static());") - result.append("\t}") - - result.append("};") - result.append("") - result.append("} // namespace godot") result.append("") @@ -1648,38 +1618,6 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us return "\n".join(result) -def generate_register_engine_classes_source(api): - includes = [] - registrations = [] - - for class_api in api["classes"]: - if class_api["name"] == "ClassDB": - continue - - class_name = class_api["name"] - snake_class_name = camel_to_snake(class_name) - - includes.append(f"#include ") - registrations.append(f"\tClassDB::register_engine_class<{class_name}>();") - - result = [] - add_header(f"register_engine_classes.cpp", result) - - result.append("#include ") - result.append("") - result = result + includes - result.append("") - result.append("namespace godot {") - result.append("") - result.append("void GDExtensionBinding::register_engine_classes() {") - result = result + registrations - result.append("}") - result.append("") - result.append("} // namespace godot ") - - return "\n".join(result) - - def generate_global_constants(api, output_dir): include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes" source_gen_folder = Path(output_dir) / "src" / "classes" diff --git a/include/godot_cpp/classes/editor_plugin_registration.hpp b/include/godot_cpp/classes/editor_plugin_registration.hpp new file mode 100644 index 00000000..1ccde314 --- /dev/null +++ b/include/godot_cpp/classes/editor_plugin_registration.hpp @@ -0,0 +1,62 @@ +/**************************************************************************/ +/* editor_plugin_registration.hpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef GODOT_EDITOR_PLUGIN_REGISTRATION_HPP +#define GODOT_EDITOR_PLUGIN_REGISTRATION_HPP + +#include + +namespace godot { + +class EditorPlugin; +class StringName; + +class EditorPlugins { +private: + static Vector plugin_classes; + +public: + static void add_plugin_class(const StringName &p_class_name); + static void remove_plugin_class(const StringName &p_class_name); + static void deinitialize(GDExtensionInitializationLevel p_level); + + template + static void add_by_type() { + add_plugin_class(T::get_class_static()); + } + template + static void remove_by_type() { + remove_plugin_class(T::get_class_static()); + } +}; + +} // namespace godot + +#endif // GODOT_EDITOR_PLUGIN_REGISTRATION_HPP diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 00d36798..83a6fe09 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -95,6 +95,26 @@ public: GodotObject *_owner = nullptr; }; +namespace internal { + +typedef void (*EngineClassRegistrationCallback)(); +void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback); +void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks); +void register_engine_classes(); + +template +struct EngineClassRegistration { + EngineClassRegistration() { + add_engine_class_registration_callback(&EngineClassRegistration::callback); + } + + static void callback() { + register_engine_class(T::get_class_static(), &T::_gde_binding_callbacks); + } +}; + +} // namespace internal + } // namespace godot #define GDCLASS(m_class, m_inherits) \ @@ -308,6 +328,7 @@ public: // Don't use this for your classes, use GDCLASS() instead. #define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) \ private: \ + inline static ::godot::internal::EngineClassRegistration _gde_engine_class_registration_helper; \ void operator=(const m_class &p_rval) {} \ \ protected: \ diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 5c3f2dbc..46032fb9 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -122,8 +122,10 @@ public: static void register_class(bool p_virtual = false); template static void register_abstract_class(); - template - static void register_engine_class(); + + _FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) { + instance_binding_callbacks[p_name] = p_callbacks; + } template static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args); @@ -226,11 +228,6 @@ void ClassDB::register_abstract_class() { ClassDB::_register_class(); } -template -void ClassDB::register_engine_class() { - instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks; -} - template MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index 2e28ad3f..1478403b 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -191,9 +191,6 @@ enum ModuleInitializationLevel { }; class GDExtensionBinding { -private: - static void register_engine_classes(); - public: using Callback = void (*)(ModuleInitializationLevel p_level); diff --git a/src/classes/editor_plugin.cpp b/src/classes/editor_plugin_registration.cpp similarity index 95% rename from src/classes/editor_plugin.cpp rename to src/classes/editor_plugin_registration.cpp index ca98a892..99819bee 100644 --- a/src/classes/editor_plugin.cpp +++ b/src/classes/editor_plugin_registration.cpp @@ -1,5 +1,5 @@ /**************************************************************************/ -/* editor_plugin.cpp */ +/* editor_plugin_registration.cpp */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#include +#include -#include +#include namespace godot { diff --git a/src/classes/wrapped.cpp b/src/classes/wrapped.cpp index 62088a51..2c5e1b60 100644 --- a/src/classes/wrapped.cpp +++ b/src/classes/wrapped.cpp @@ -28,12 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ +#include + #include #include #include +#include + namespace godot { const StringName *Wrapped::_get_extension_class_name() const { @@ -60,4 +64,29 @@ void postinitialize_handler(Wrapped *p_wrapped) { p_wrapped->_postinitialize(); } +namespace internal { + +std::vector &get_engine_class_registration_callbacks() { + static std::vector engine_class_registration_callbacks; + return engine_class_registration_callbacks; +} + +void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback) { + get_engine_class_registration_callbacks().push_back(p_callback); +} + +void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) { + ClassDB::_register_engine_class(p_name, p_callbacks); +} + +void register_engine_classes() { + std::vector &engine_class_registration_callbacks = get_engine_class_registration_callbacks(); + for (EngineClassRegistrationCallback cb : engine_class_registration_callbacks) { + cb(); + } + engine_class_registration_callbacks.clear(); +} + +} // namespace internal + } // namespace godot diff --git a/src/godot.cpp b/src/godot.cpp index bc0a3c69..14214c0d 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -30,7 +30,7 @@ #include -#include +#include #include #include #include @@ -406,7 +406,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined."); Variant::init_bindings(); - register_engine_classes(); + godot::internal::register_engine_classes(); return true; }