Change initialization to allow custom level callbacks
Now it needs a callback for each level so custom logic (like loading singletons) can be performed.pull/602/head
parent
dfa526ce16
commit
aef0f1e248
|
@ -63,6 +63,10 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, Args... args)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassDB {
|
class ClassDB {
|
||||||
|
static GDNativeInitializationLevel current_level;
|
||||||
|
|
||||||
|
friend class godot::GDExtensionBinding;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct PropertySetGet {
|
struct PropertySetGet {
|
||||||
int index;
|
int index;
|
||||||
|
@ -98,7 +102,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <class T>
|
template <class T>
|
||||||
static void register_class(GDNativeInitializationLevel p_level = GDNATIVE_INITIALIZATION_SCENE);
|
static void register_class();
|
||||||
|
|
||||||
template <class N, class M>
|
template <class N, class M>
|
||||||
static MethodBind *bind_method(N p_method_name, M p_method);
|
static MethodBind *bind_method(N p_method_name, M p_method);
|
||||||
|
@ -132,11 +136,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void ClassDB::register_class(GDNativeInitializationLevel p_level) {
|
void ClassDB::register_class() {
|
||||||
ClassInfo cl;
|
ClassInfo cl;
|
||||||
cl.name = T::get_class_static();
|
cl.name = T::get_class_static();
|
||||||
cl.parent_name = T::get_parent_class_static();
|
cl.parent_name = T::get_parent_class_static();
|
||||||
cl.level = p_level;
|
cl.level = current_level;
|
||||||
cl.constructor = T::create;
|
cl.constructor = T::create;
|
||||||
cl.destructor = T::free;
|
cl.destructor = T::free;
|
||||||
cl.object_instance = T::set_object_instance;
|
cl.object_instance = T::set_object_instance;
|
||||||
|
|
|
@ -45,12 +45,47 @@ extern "C" void *token;
|
||||||
|
|
||||||
class GDExtensionBinding {
|
class GDExtensionBinding {
|
||||||
public:
|
public:
|
||||||
|
using Callback = void (*)();
|
||||||
|
|
||||||
|
static Callback core_init;
|
||||||
|
static Callback server_init;
|
||||||
|
static Callback scene_init;
|
||||||
|
static Callback editor_init;
|
||||||
|
static Callback core_terminate;
|
||||||
|
static Callback server_terminate;
|
||||||
|
static Callback scene_terminate;
|
||||||
|
static Callback editor_terminate;
|
||||||
static GDNativeBool init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization);
|
static GDNativeBool init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization);
|
||||||
|
|
||||||
|
public:
|
||||||
static void initialize_level(void *userdata, GDNativeInitializationLevel p_level);
|
static void initialize_level(void *userdata, GDNativeInitializationLevel p_level);
|
||||||
static void deinitialize_level(void *userdata, GDNativeInitializationLevel p_level);
|
static void deinitialize_level(void *userdata, GDNativeInitializationLevel p_level);
|
||||||
|
|
||||||
static void *create_instance_callback(void *p_token, void *p_instance);
|
static void *create_instance_callback(void *p_token, void *p_instance);
|
||||||
static void free_instance_callback(void *p_token, void *p_instance, void *p_binding);
|
static void free_instance_callback(void *p_token, void *p_instance, void *p_binding);
|
||||||
|
|
||||||
|
class InitObject {
|
||||||
|
const GDNativeInterface *interface;
|
||||||
|
const GDNativeExtensionClassLibraryPtr library;
|
||||||
|
GDNativeInitialization *initialization;
|
||||||
|
|
||||||
|
public:
|
||||||
|
InitObject(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) :
|
||||||
|
interface(p_interface),
|
||||||
|
library(p_library),
|
||||||
|
initialization(r_initialization) {}
|
||||||
|
|
||||||
|
void register_core_initializer(Callback p_core_init) const;
|
||||||
|
void register_server_initializer(Callback p_server_init) const;
|
||||||
|
void register_scene_initializer(Callback p_scene_init) const;
|
||||||
|
void register_editor_initializer(Callback p_editor_init) const;
|
||||||
|
void register_core_terminator(Callback p_core_terminate) const;
|
||||||
|
void register_server_terminator(Callback p_server_terminate) const;
|
||||||
|
void register_scene_terminator(Callback p_scene_terminate) const;
|
||||||
|
void register_editor_terminator(Callback p_editor_terminate) const;
|
||||||
|
|
||||||
|
GDNativeBool init() const;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
namespace godot {
|
namespace godot {
|
||||||
|
|
||||||
std::unordered_map<std::string, ClassDB::ClassInfo> ClassDB::classes;
|
std::unordered_map<std::string, ClassDB::ClassInfo> ClassDB::classes;
|
||||||
|
GDNativeInitializationLevel ClassDB::current_level = GDNATIVE_INITIALIZATION_CORE;
|
||||||
|
|
||||||
MethodDefinition D_METHOD(const char *p_name) {
|
MethodDefinition D_METHOD(const char *p_name) {
|
||||||
return MethodDefinition(p_name);
|
return MethodDefinition(p_name);
|
||||||
|
|
108
src/godot.cpp
108
src/godot.cpp
|
@ -41,12 +41,21 @@ namespace godot {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
const GDNativeInterface *interface;
|
const GDNativeInterface *interface = nullptr;
|
||||||
GDNativeExtensionClassLibraryPtr library;
|
GDNativeExtensionClassLibraryPtr library = nullptr;
|
||||||
void *token;
|
void *token = nullptr;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
GDExtensionBinding::Callback GDExtensionBinding::core_init = nullptr;
|
||||||
|
GDExtensionBinding::Callback GDExtensionBinding::server_init = nullptr;
|
||||||
|
GDExtensionBinding::Callback GDExtensionBinding::scene_init = nullptr;
|
||||||
|
GDExtensionBinding::Callback GDExtensionBinding::editor_init = nullptr;
|
||||||
|
GDExtensionBinding::Callback GDExtensionBinding::core_terminate = nullptr;
|
||||||
|
GDExtensionBinding::Callback GDExtensionBinding::server_terminate = nullptr;
|
||||||
|
GDExtensionBinding::Callback GDExtensionBinding::scene_terminate = nullptr;
|
||||||
|
GDExtensionBinding::Callback GDExtensionBinding::editor_terminate = nullptr;
|
||||||
|
|
||||||
GDNativeBool GDExtensionBinding::init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
|
GDNativeBool GDExtensionBinding::init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
|
||||||
internal::interface = p_interface;
|
internal::interface = p_interface;
|
||||||
internal::library = p_library;
|
internal::library = p_library;
|
||||||
|
@ -54,7 +63,18 @@ GDNativeBool GDExtensionBinding::init(const GDNativeInterface *p_interface, cons
|
||||||
|
|
||||||
r_initialization->initialize = initialize_level;
|
r_initialization->initialize = initialize_level;
|
||||||
r_initialization->deinitialize = deinitialize_level;
|
r_initialization->deinitialize = deinitialize_level;
|
||||||
|
|
||||||
|
if (core_init) {
|
||||||
r_initialization->minimum_initialization_level = GDNATIVE_INITIALIZATION_CORE;
|
r_initialization->minimum_initialization_level = GDNATIVE_INITIALIZATION_CORE;
|
||||||
|
} else if (server_init) {
|
||||||
|
r_initialization->minimum_initialization_level = GDNATIVE_INITIALIZATION_SERVERS;
|
||||||
|
} else if (scene_init) {
|
||||||
|
r_initialization->minimum_initialization_level = GDNATIVE_INITIALIZATION_SCENE;
|
||||||
|
} else if (editor_init) {
|
||||||
|
r_initialization->minimum_initialization_level = GDNATIVE_INITIALIZATION_EDITOR;
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_V_MSG(false, "At least one initialization callback must be defined.");
|
||||||
|
}
|
||||||
|
|
||||||
Variant::init_bindings();
|
Variant::init_bindings();
|
||||||
|
|
||||||
|
@ -62,11 +82,57 @@ GDNativeBool GDExtensionBinding::init(const GDNativeInterface *p_interface, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::initialize_level(void *userdata, GDNativeInitializationLevel p_level) {
|
void GDExtensionBinding::initialize_level(void *userdata, GDNativeInitializationLevel p_level) {
|
||||||
|
ClassDB::current_level = p_level;
|
||||||
|
switch (p_level) {
|
||||||
|
case GDNATIVE_INITIALIZATION_CORE:
|
||||||
|
if (core_init) {
|
||||||
|
core_init();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GDNATIVE_INITIALIZATION_SERVERS:
|
||||||
|
if (server_init) {
|
||||||
|
server_init();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GDNATIVE_INITIALIZATION_SCENE:
|
||||||
|
if (scene_init) {
|
||||||
|
scene_init();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GDNATIVE_INITIALIZATION_EDITOR:
|
||||||
|
if (editor_init) {
|
||||||
|
editor_init();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
ClassDB::initialize(p_level);
|
ClassDB::initialize(p_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDExtensionBinding::deinitialize_level(void *userdata, GDNativeInitializationLevel p_level) {
|
void GDExtensionBinding::deinitialize_level(void *userdata, GDNativeInitializationLevel p_level) {
|
||||||
|
ClassDB::current_level = p_level;
|
||||||
ClassDB::deinitialize(p_level);
|
ClassDB::deinitialize(p_level);
|
||||||
|
switch (p_level) {
|
||||||
|
case GDNATIVE_INITIALIZATION_CORE:
|
||||||
|
if (core_terminate) {
|
||||||
|
core_terminate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GDNATIVE_INITIALIZATION_SERVERS:
|
||||||
|
if (server_terminate) {
|
||||||
|
server_terminate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GDNATIVE_INITIALIZATION_SCENE:
|
||||||
|
if (scene_terminate) {
|
||||||
|
scene_terminate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GDNATIVE_INITIALIZATION_EDITOR:
|
||||||
|
if (editor_terminate) {
|
||||||
|
editor_terminate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *GDExtensionBinding::create_instance_callback(void *p_token, void *p_instance) {
|
void *GDExtensionBinding::create_instance_callback(void *p_token, void *p_instance) {
|
||||||
|
@ -80,6 +146,42 @@ void GDExtensionBinding::free_instance_callback(void *p_token, void *p_instance,
|
||||||
memdelete((Wrapped *)p_binding);
|
memdelete((Wrapped *)p_binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitObject::register_core_initializer(Callback p_core_init) const {
|
||||||
|
GDExtensionBinding::core_init = p_core_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitObject::register_server_initializer(Callback p_server_init) const {
|
||||||
|
GDExtensionBinding::server_init = p_server_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitObject::register_scene_initializer(Callback p_scene_init) const {
|
||||||
|
GDExtensionBinding::scene_init = p_scene_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitObject::register_editor_initializer(Callback p_editor_init) const {
|
||||||
|
GDExtensionBinding::editor_init = p_editor_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitObject::register_core_terminator(Callback p_core_terminate) const {
|
||||||
|
GDExtensionBinding::core_terminate = p_core_terminate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitObject::register_server_terminator(Callback p_server_terminate) const {
|
||||||
|
GDExtensionBinding::server_terminate = p_server_terminate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitObject::register_scene_terminator(Callback p_scene_terminate) const {
|
||||||
|
GDExtensionBinding::scene_terminate = p_scene_terminate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionBinding::InitObject::register_editor_terminator(Callback p_editor_terminate) const {
|
||||||
|
GDExtensionBinding::editor_terminate = p_editor_terminate;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDNativeBool GDExtensionBinding::InitObject::init() const {
|
||||||
|
return GDExtensionBinding::init(interface, library, initialization);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -51,12 +51,11 @@ extern "C" {
|
||||||
// Initialization.
|
// Initialization.
|
||||||
|
|
||||||
GDNativeBool GDN_EXPORT example_library_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
|
GDNativeBool GDN_EXPORT example_library_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
|
||||||
GDNativeBool result = godot::GDExtensionBinding::init(p_interface, p_library, r_initialization);
|
godot::GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
|
||||||
|
|
||||||
if (result) {
|
init_obj.register_scene_initializer(register_example_types);
|
||||||
register_example_types();
|
init_obj.register_scene_terminator(unregister_example_types);
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return init_obj.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue