|
|
@@ -35,17 +35,114 @@
|
|
|
#include "os/file_access.h"
|
|
|
#include "os/os.h"
|
|
|
|
|
|
+#include "scene/main/scene_main_loop.h"
|
|
|
#include "scene/resources/scene_format_text.h"
|
|
|
|
|
|
-#ifdef TOOLS_ENABLED
|
|
|
-// #include "editor/editor_import_export.h"
|
|
|
-#endif
|
|
|
-
|
|
|
#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
|
|
|
#include "api_generator.h"
|
|
|
#endif
|
|
|
|
|
|
+#ifdef TOOLS_ENABLED
|
|
|
+#include "editor/editor_node.h"
|
|
|
+#endif
|
|
|
+
|
|
|
+Error NativeLibrary::initialize(NativeLibrary *&p_native_lib, const StringName p_path) {
|
|
|
+
|
|
|
+ if (DLScriptLanguage::get_singleton()->initialized_libraries.has(p_path)) {
|
|
|
+ p_native_lib = DLScriptLanguage::get_singleton()->initialized_libraries[p_path];
|
|
|
+ return OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ NativeLibrary *lib = memnew(NativeLibrary);
|
|
|
+ lib->path = p_path;
|
|
|
+
|
|
|
+ p_native_lib = lib;
|
|
|
+
|
|
|
+ // Open the file
|
|
|
+
|
|
|
+ Error error;
|
|
|
+ error = OS::get_singleton()->open_dynamic_library(p_path, lib->handle);
|
|
|
+ if (error) return error;
|
|
|
+ ERR_FAIL_COND_V(!lib->handle, ERR_BUG);
|
|
|
+
|
|
|
+ // Get the method
|
|
|
+
|
|
|
+ void *library_init;
|
|
|
+ error = OS::get_singleton()->get_dynamic_library_symbol_handle(lib->handle, DLScriptLanguage::get_init_symbol_name(), library_init);
|
|
|
+ if (error) return error;
|
|
|
+ ERR_FAIL_COND_V(!library_init, ERR_BUG);
|
|
|
+
|
|
|
+ void (*library_init_fpointer)(godot_dlscript_init_options *) = (void (*)(godot_dlscript_init_options *))library_init;
|
|
|
+
|
|
|
+ godot_dlscript_init_options options;
|
|
|
+
|
|
|
+ options.in_editor = SceneTree::get_singleton()->is_editor_hint();
|
|
|
+ /*
|
|
|
+ options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE);
|
|
|
+ options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR);
|
|
|
+ options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE);
|
|
|
+ */
|
|
|
+
|
|
|
+ library_init_fpointer(&options); // Catch errors?
|
|
|
+
|
|
|
+ DLScriptLanguage::get_singleton()->initialized_libraries[p_path] = lib;
|
|
|
+
|
|
|
+ return OK;
|
|
|
+}
|
|
|
+
|
|
|
+Error NativeLibrary::terminate(NativeLibrary *&p_native_lib) {
|
|
|
+
|
|
|
+ if (!DLScriptLanguage::get_singleton()->initialized_libraries.has(p_native_lib->path)) {
|
|
|
+ OS::get_singleton()->close_dynamic_library(p_native_lib->handle);
|
|
|
+ p_native_lib->handle = 0;
|
|
|
+ return OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ Error error = OK;
|
|
|
+ void *library_terminate;
|
|
|
+ error = OS::get_singleton()->get_dynamic_library_symbol_handle(p_native_lib->handle, DLScriptLanguage::get_terminate_symbol_name(), library_terminate);
|
|
|
+ if (error)
|
|
|
+ return OK; // no terminate? okay, not that important lol
|
|
|
+
|
|
|
+ void (*library_terminate_pointer)(godot_dlscript_terminate_options *) = (void (*)(godot_dlscript_terminate_options *))library_terminate;
|
|
|
+
|
|
|
+ godot_dlscript_terminate_options options;
|
|
|
+ options.in_editor = SceneTree::get_singleton()->is_editor_hint();
|
|
|
+
|
|
|
+ library_terminate_pointer(&options);
|
|
|
+
|
|
|
+ DLScriptLanguage::get_singleton()->initialized_libraries.erase(p_native_lib->path);
|
|
|
+
|
|
|
+ OS::get_singleton()->close_dynamic_library(p_native_lib->handle);
|
|
|
+ p_native_lib->handle = 0;
|
|
|
+
|
|
|
+ return OK;
|
|
|
+}
|
|
|
+
|
|
|
// Script
|
|
|
+#ifdef TOOLS_ENABLED
|
|
|
+
|
|
|
+void DLScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) {
|
|
|
+
|
|
|
+ List<PropertyInfo> pinfo;
|
|
|
+ Map<StringName, Variant> values;
|
|
|
+
|
|
|
+ for (Map<StringName, DLScriptData::Property>::Element *E = script_data->properties.front(); E; E = E->next()) {
|
|
|
+ PropertyInfo p = E->get().info;
|
|
|
+ p.name = String(E->key());
|
|
|
+ pinfo.push_back(p);
|
|
|
+ values[p.name] = E->get().default_value;
|
|
|
+ }
|
|
|
+
|
|
|
+ p_placeholder->update(pinfo, values);
|
|
|
+}
|
|
|
+
|
|
|
+void DLScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
|
|
|
+
|
|
|
+ placeholders.erase(p_placeholder);
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
|
|
|
bool DLScript::can_instance() const {
|
|
|
#ifdef DLSCRIPT_EDITOR_FEATURES
|
|
|
@@ -92,14 +189,11 @@ ScriptInstance *DLScript::instance_create(Object *p_this) {
|
|
|
PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(DLScriptLanguage::singleton, Ref<Script>((Script *)this), p_this));
|
|
|
placeholders.insert(sins);
|
|
|
|
|
|
- List<PropertyInfo> pinfo;
|
|
|
- Map<StringName, Variant> values;
|
|
|
-
|
|
|
if (!library.is_valid())
|
|
|
return sins;
|
|
|
|
|
|
- if (!library->library_handle) {
|
|
|
- Error err = library->_initialize_handle(true);
|
|
|
+ if (!library->native_library) {
|
|
|
+ Error err = library->_initialize();
|
|
|
if (err != OK) {
|
|
|
return sins;
|
|
|
}
|
|
|
@@ -108,20 +202,11 @@ ScriptInstance *DLScript::instance_create(Object *p_this) {
|
|
|
if (!script_data) {
|
|
|
script_data = library->get_script_data(script_name);
|
|
|
}
|
|
|
- if (script_data)
|
|
|
+ if (script_data && script_data->create_func.create_func) {
|
|
|
script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data);
|
|
|
-
|
|
|
- if (script_data) {
|
|
|
- for (Map<StringName, DLScriptData::Property>::Element *E = script_data->properties.front(); E; E = E->next()) {
|
|
|
-
|
|
|
- PropertyInfo p = E->get().info;
|
|
|
- p.name = String(E->key());
|
|
|
- pinfo.push_back(p);
|
|
|
- values[p.name] = E->get().default_value;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
- sins->update(pinfo, values);
|
|
|
+ _update_placeholder(sins);
|
|
|
|
|
|
return sins;
|
|
|
}
|
|
|
@@ -321,10 +406,10 @@ void DLScript::set_library(Ref<DLLibrary> p_library) {
|
|
|
return;
|
|
|
#endif
|
|
|
if (library.is_valid()) {
|
|
|
- Error initalize_status = library->_initialize_handle(!ScriptServer::is_scripting_enabled());
|
|
|
+ Error initalize_status = library->_initialize();
|
|
|
ERR_FAIL_COND(initalize_status != OK);
|
|
|
if (script_name) {
|
|
|
- script_data = library->get_script_data(script_name);
|
|
|
+ script_data = library->native_library->scripts[script_name];
|
|
|
ERR_FAIL_COND(!script_data);
|
|
|
}
|
|
|
}
|
|
|
@@ -338,8 +423,15 @@ void DLScript::set_script_name(StringName p_script_name) {
|
|
|
script_name = p_script_name;
|
|
|
|
|
|
if (library.is_valid()) {
|
|
|
- script_data = library->get_script_data(script_name);
|
|
|
- ERR_FAIL_COND(!script_data);
|
|
|
+#ifdef DLSCRIPT_EDITOR_FEATURES
|
|
|
+ if (!library->native_library) {
|
|
|
+ library->_initialize();
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ if (library->native_library) {
|
|
|
+ script_data = library->get_script_data(script_name);
|
|
|
+ ERR_FAIL_COND(!script_data);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -355,10 +447,12 @@ void DLScript::_bind_methods() {
|
|
|
|
|
|
DLScript::DLScript() {
|
|
|
script_data = NULL;
|
|
|
+ DLScriptLanguage::get_singleton()->script_list.insert(this);
|
|
|
}
|
|
|
|
|
|
DLScript::~DLScript() {
|
|
|
//hmm
|
|
|
+ DLScriptLanguage::get_singleton()->script_list.erase(this);
|
|
|
}
|
|
|
|
|
|
// Library
|
|
|
@@ -401,11 +495,9 @@ String DLLibrary::get_platform_file(StringName p_platform) const {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-Error DLLibrary::_initialize_handle(bool p_in_editor) {
|
|
|
+Error DLLibrary::_initialize() {
|
|
|
_THREAD_SAFE_METHOD_
|
|
|
|
|
|
- void *_library_handle;
|
|
|
-
|
|
|
// Get the file
|
|
|
|
|
|
const String platform_name = OS::get_singleton()->get_name();
|
|
|
@@ -435,90 +527,62 @@ Error DLLibrary::_initialize_handle(bool p_in_editor) {
|
|
|
}
|
|
|
ERR_FAIL_COND_V(platform_file == "", ERR_DOES_NOT_EXIST);
|
|
|
|
|
|
- library_path = GlobalConfig::get_singleton()->globalize_path(platform_file);
|
|
|
-
|
|
|
- if (DLScriptLanguage::get_singleton()->is_library_initialized(library_path)) {
|
|
|
- *this = *DLScriptLanguage::get_singleton()->get_library_dllibrary(library_path);
|
|
|
- return OK;
|
|
|
- }
|
|
|
-
|
|
|
- // Open the file
|
|
|
-
|
|
|
- Error error;
|
|
|
- error = OS::get_singleton()->open_dynamic_library(library_path, _library_handle);
|
|
|
- if (error) return error;
|
|
|
- ERR_FAIL_COND_V(!_library_handle, ERR_BUG);
|
|
|
-
|
|
|
- // Get the method
|
|
|
-
|
|
|
- void *library_init;
|
|
|
- error = OS::get_singleton()->get_dynamic_library_symbol_handle(_library_handle, DLScriptLanguage::get_init_symbol_name(), library_init);
|
|
|
- if (error) return error;
|
|
|
- ERR_FAIL_COND_V(!library_init, ERR_BUG);
|
|
|
+ StringName path = GlobalConfig::get_singleton()->globalize_path(platform_file);
|
|
|
|
|
|
DLLibrary::currently_initialized_library = this;
|
|
|
|
|
|
- void (*library_init_fpointer)(godot_dlscript_init_options *) = (void (*)(godot_dlscript_init_options *))library_init;
|
|
|
-
|
|
|
- godot_dlscript_init_options options;
|
|
|
-
|
|
|
- options.in_editor = p_in_editor;
|
|
|
- options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE);
|
|
|
- options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR);
|
|
|
- options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE);
|
|
|
-
|
|
|
- library_init_fpointer(&options); // Catch errors?
|
|
|
- /*{
|
|
|
- ERR_EXPLAIN("Couldn't initialize library");
|
|
|
- ERR_FAIL_V(ERR_SCRIPT_FAILED);
|
|
|
- }*/
|
|
|
+ Error ret = NativeLibrary::initialize(native_library, path);
|
|
|
+ native_library->dllib = this;
|
|
|
|
|
|
DLLibrary::currently_initialized_library = NULL;
|
|
|
- library_handle = _library_handle;
|
|
|
-
|
|
|
- DLScriptLanguage::get_singleton()->set_library_initialized(library_path, this);
|
|
|
|
|
|
- return OK;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-Error DLLibrary::_free_handle(bool p_in_editor) {
|
|
|
- ERR_FAIL_COND_V(!library_handle, ERR_BUG);
|
|
|
+Error DLLibrary::_terminate() {
|
|
|
+ ERR_FAIL_COND_V(!native_library, ERR_BUG);
|
|
|
+ ERR_FAIL_COND_V(!native_library->handle, ERR_BUG);
|
|
|
|
|
|
- if (!DLScriptLanguage::get_singleton()->is_library_initialized(library_path)) {
|
|
|
- OS::get_singleton()->close_dynamic_library(library_handle);
|
|
|
- library_handle = 0;
|
|
|
- return OK;
|
|
|
- }
|
|
|
+ // de-init stuff
|
|
|
|
|
|
- Error error = OK;
|
|
|
- void *library_terminate;
|
|
|
- error = OS::get_singleton()->get_dynamic_library_symbol_handle(library_handle, DLScriptLanguage::get_terminate_symbol_name(), library_terminate);
|
|
|
- if (error)
|
|
|
- return OK; // no terminate? okay, not that important lol
|
|
|
-
|
|
|
- void (*library_terminate_pointer)(godot_dlscript_terminate_options *) = (void (*)(godot_dlscript_terminate_options *))library_terminate;
|
|
|
+ for (Map<StringName, DLScriptData *>::Element *E = native_library->scripts.front(); E; E = E->next()) {
|
|
|
+ for (Map<StringName, DLScriptData::Method>::Element *M = E->get()->methods.front(); M; M = M->next()) {
|
|
|
+ if (M->get().method.free_func) {
|
|
|
+ M->get().method.free_func(M->get().method.method_data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (E->get()->create_func.free_func) {
|
|
|
+ E->get()->create_func.free_func(E->get()->create_func.method_data);
|
|
|
+ }
|
|
|
+ if (E->get()->destroy_func.free_func) {
|
|
|
+ E->get()->destroy_func.free_func(E->get()->destroy_func.method_data);
|
|
|
+ }
|
|
|
|
|
|
- godot_dlscript_terminate_options options;
|
|
|
- options.in_editor = p_in_editor;
|
|
|
+ for (Set<DLScript *>::Element *S = DLScriptLanguage::get_singleton()->script_list.front(); S; S = S->next()) {
|
|
|
+ if (S->get()->script_data == E->get()) {
|
|
|
+ S->get()->script_data = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- library_terminate_pointer(&options);
|
|
|
+ memdelete(E->get());
|
|
|
+ }
|
|
|
|
|
|
- DLScriptLanguage::get_singleton()->set_library_uninitialized(library_path);
|
|
|
+ Error ret = NativeLibrary::terminate(native_library);
|
|
|
|
|
|
- OS::get_singleton()->close_dynamic_library(library_handle);
|
|
|
- library_handle = 0;
|
|
|
+ native_library->scripts.clear();
|
|
|
|
|
|
- return OK;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
void DLLibrary::_register_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func) {
|
|
|
- ERR_FAIL_COND(scripts.has(p_name));
|
|
|
+ ERR_FAIL_COND(!native_library);
|
|
|
+ ERR_FAIL_COND(native_library->scripts.has(p_name));
|
|
|
|
|
|
DLScriptData *s = memnew(DLScriptData);
|
|
|
s->base = p_base;
|
|
|
s->create_func = p_instance_func;
|
|
|
s->destroy_func = p_destroy_func;
|
|
|
- Map<StringName, DLScriptData *>::Element *E = scripts.find(p_base);
|
|
|
+ Map<StringName, DLScriptData *>::Element *E = native_library->scripts.find(p_base);
|
|
|
if (E) {
|
|
|
s->base_data = E->get();
|
|
|
s->base_native_type = s->base_data->base_native_type;
|
|
|
@@ -531,18 +595,19 @@ void DLLibrary::_register_script(const StringName p_name, const StringName p_bas
|
|
|
s->base_native_type = p_base;
|
|
|
}
|
|
|
|
|
|
- scripts.insert(p_name, s);
|
|
|
+ native_library->scripts.insert(p_name, s);
|
|
|
}
|
|
|
|
|
|
void DLLibrary::_register_tool_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func) {
|
|
|
- ERR_FAIL_COND(scripts.has(p_name));
|
|
|
+ ERR_FAIL_COND(!native_library);
|
|
|
+ ERR_FAIL_COND(native_library->scripts.has(p_name));
|
|
|
|
|
|
DLScriptData *s = memnew(DLScriptData);
|
|
|
s->base = p_base;
|
|
|
s->create_func = p_instance_func;
|
|
|
s->destroy_func = p_destroy_func;
|
|
|
s->is_tool = true;
|
|
|
- Map<StringName, DLScriptData *>::Element *E = scripts.find(p_base);
|
|
|
+ Map<StringName, DLScriptData *>::Element *E = native_library->scripts.find(p_base);
|
|
|
if (E) {
|
|
|
s->base_data = E->get();
|
|
|
s->base_native_type = s->base_data->base_native_type;
|
|
|
@@ -555,22 +620,24 @@ void DLLibrary::_register_tool_script(const StringName p_name, const StringName
|
|
|
s->base_native_type = p_base;
|
|
|
}
|
|
|
|
|
|
- scripts.insert(p_name, s);
|
|
|
+ native_library->scripts.insert(p_name, s);
|
|
|
}
|
|
|
|
|
|
void DLLibrary::_register_script_method(const StringName p_name, const StringName p_method, godot_method_attributes p_attr, godot_instance_method p_func, MethodInfo p_info) {
|
|
|
- ERR_FAIL_COND(!scripts.has(p_name));
|
|
|
+ ERR_FAIL_COND(!native_library);
|
|
|
+ ERR_FAIL_COND(!native_library->scripts.has(p_name));
|
|
|
|
|
|
p_info.name = p_method;
|
|
|
DLScriptData::Method method;
|
|
|
|
|
|
method = DLScriptData::Method(p_func, p_info, p_attr.rpc_type);
|
|
|
|
|
|
- scripts[p_name]->methods.insert(p_method, method);
|
|
|
+ native_library->scripts[p_name]->methods.insert(p_method, method);
|
|
|
}
|
|
|
|
|
|
void DLLibrary::_register_script_property(const StringName p_name, const String p_path, godot_property_attributes *p_attr, godot_property_set_func p_setter, godot_property_get_func p_getter) {
|
|
|
- ERR_FAIL_COND(!scripts.has(p_name));
|
|
|
+ ERR_FAIL_COND(!native_library);
|
|
|
+ ERR_FAIL_COND(!native_library->scripts.has(p_name));
|
|
|
|
|
|
DLScriptData::Property p;
|
|
|
|
|
|
@@ -583,11 +650,12 @@ void DLLibrary::_register_script_property(const StringName p_name, const String
|
|
|
p = DLScriptData::Property(p_setter, p_getter, pi, *(Variant *)&p_attr->default_value, p_attr->rset_type);
|
|
|
}
|
|
|
|
|
|
- scripts[p_name]->properties.insert(p_path, p);
|
|
|
+ native_library->scripts[p_name]->properties.insert(p_path, p);
|
|
|
}
|
|
|
|
|
|
void DLLibrary::_register_script_signal(const StringName p_name, const godot_signal *p_signal) {
|
|
|
- ERR_FAIL_COND(!scripts.has(p_name));
|
|
|
+ ERR_FAIL_COND(!native_library);
|
|
|
+ ERR_FAIL_COND(!native_library->scripts.has(p_name));
|
|
|
ERR_FAIL_COND(!p_signal);
|
|
|
|
|
|
DLScriptData::Signal signal;
|
|
|
@@ -627,19 +695,15 @@ void DLLibrary::_register_script_signal(const StringName p_name, const godot_sig
|
|
|
signal.signal.default_arguments = default_arguments;
|
|
|
}
|
|
|
|
|
|
- scripts[p_name]->signals_.insert(*(String *)&p_signal->name, signal);
|
|
|
+ native_library->scripts[p_name]->signals_.insert(*(String *)&p_signal->name, signal);
|
|
|
}
|
|
|
|
|
|
DLScriptData *DLLibrary::get_script_data(const StringName p_name) {
|
|
|
+ ERR_FAIL_COND_V(!native_library, NULL);
|
|
|
|
|
|
- if (!scripts.has(p_name)) {
|
|
|
- if (DLScriptLanguage::get_singleton()->is_library_initialized(library_path)) {
|
|
|
- _update_library(*DLScriptLanguage::get_singleton()->get_library_dllibrary(library_path));
|
|
|
- }
|
|
|
- ERR_FAIL_COND_V(!scripts.has(p_name), NULL);
|
|
|
- }
|
|
|
+ ERR_FAIL_COND_V(!native_library->scripts.has(p_name), NULL);
|
|
|
|
|
|
- return scripts[p_name];
|
|
|
+ return native_library->scripts[p_name];
|
|
|
}
|
|
|
|
|
|
bool DLLibrary::_set(const StringName &p_name, const Variant &p_value) {
|
|
|
@@ -668,6 +732,9 @@ void DLLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
|
List<StringName> ep;
|
|
|
// ep.push_back("X11");
|
|
|
// EditorImportExport::get_singleton()->get_export_platforms(&ep);
|
|
|
+
|
|
|
+ // @Todo
|
|
|
+ // get export platforms with the new export system somehow.
|
|
|
for (List<StringName>::Element *E = ep.front(); E; E = E->next()) {
|
|
|
registered_platform_names.insert(String(E->get()).to_lower());
|
|
|
}
|
|
|
@@ -712,26 +779,17 @@ void DLLibrary::_bind_methods() {
|
|
|
}
|
|
|
|
|
|
DLLibrary::DLLibrary() {
|
|
|
- library_handle = NULL;
|
|
|
+ native_library = NULL;
|
|
|
}
|
|
|
|
|
|
DLLibrary::~DLLibrary() {
|
|
|
|
|
|
- for (Map<StringName, DLScriptData *>::Element *E = scripts.front(); E; E = E->next()) {
|
|
|
- for (Map<StringName, DLScriptData::Method>::Element *M = E->get()->methods.front(); M; M = M->next()) {
|
|
|
- if (M->get().method.free_func) {
|
|
|
- M->get().method.free_func(M->get().method.method_data);
|
|
|
- }
|
|
|
- }
|
|
|
- memdelete(E->get());
|
|
|
+ if (!native_library) {
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- if (library_handle) {
|
|
|
- bool in_editor = false;
|
|
|
-#ifdef TOOLS_ENABLED
|
|
|
- in_editor = !ScriptServer::is_scripting_enabled();
|
|
|
-#endif
|
|
|
- _free_handle(in_editor);
|
|
|
+ if (native_library->handle) {
|
|
|
+ _terminate();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -907,24 +965,11 @@ String DLScriptLanguage::get_name() const {
|
|
|
return "DLScript";
|
|
|
}
|
|
|
|
|
|
-bool DLScriptLanguage::is_library_initialized(const String &p_path) {
|
|
|
-
|
|
|
- return initialized_libraries.has(p_path);
|
|
|
-}
|
|
|
-
|
|
|
-void DLScriptLanguage::set_library_initialized(const String &p_path, DLLibrary *p_dllibrary) {
|
|
|
-
|
|
|
- initialized_libraries[p_path] = p_dllibrary;
|
|
|
-}
|
|
|
-
|
|
|
-DLLibrary *DLScriptLanguage::get_library_dllibrary(const String &p_path) {
|
|
|
-
|
|
|
- return initialized_libraries[p_path];
|
|
|
-}
|
|
|
-
|
|
|
-void DLScriptLanguage::set_library_uninitialized(const String &p_path) {
|
|
|
-
|
|
|
- initialized_libraries.erase(p_path);
|
|
|
+void _add_reload_node() {
|
|
|
+#ifdef TOOLS_ENABLED
|
|
|
+ DLReloadNode *rn = memnew(DLReloadNode);
|
|
|
+ EditorNode::get_singleton()->add_child(rn);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
void DLScriptLanguage::init() {
|
|
|
@@ -946,6 +991,12 @@ void DLScriptLanguage::init() {
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
+
|
|
|
+#ifdef TOOLS_ENABLED
|
|
|
+ // if (SceneTree::get_singleton()->is_editor_hint()) {
|
|
|
+ EditorNode::add_init_callback(&_add_reload_node);
|
|
|
+// }
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
String DLScriptLanguage::get_type() const {
|
|
|
@@ -1080,13 +1131,78 @@ DLScriptLanguage::DLScriptLanguage() {
|
|
|
ERR_FAIL_COND(singleton);
|
|
|
strings._notification = StringName("_notification");
|
|
|
singleton = this;
|
|
|
- initialized_libraries = Map<String, DLLibrary *>();
|
|
|
+ initialized_libraries = Map<StringName, NativeLibrary *>();
|
|
|
}
|
|
|
|
|
|
DLScriptLanguage::~DLScriptLanguage() {
|
|
|
singleton = NULL;
|
|
|
}
|
|
|
|
|
|
+// DLReloadNode
|
|
|
+
|
|
|
+void DLReloadNode::_bind_methods() {
|
|
|
+ ClassDB::bind_method("_notification", &DLReloadNode::_notification);
|
|
|
+}
|
|
|
+
|
|
|
+void DLReloadNode::_notification(int p_what) {
|
|
|
+#ifdef TOOLS_ENABLED
|
|
|
+
|
|
|
+ switch (p_what) {
|
|
|
+ case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
|
|
|
+
|
|
|
+ // break; // For now.
|
|
|
+
|
|
|
+ Set<NativeLibrary *> libs_to_reload;
|
|
|
+
|
|
|
+ for (Map<StringName, NativeLibrary *>::Element *L = DLScriptLanguage::get_singleton()->initialized_libraries.front(); L; L = L->next()) {
|
|
|
+ // check if file got modified at all
|
|
|
+ // @Todo
|
|
|
+
|
|
|
+ libs_to_reload.insert(L->get());
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Set<NativeLibrary *>::Element *L = libs_to_reload.front(); L; L = L->next()) {
|
|
|
+
|
|
|
+ DLLibrary *lib = L->get()->dllib;
|
|
|
+
|
|
|
+ lib->_terminate();
|
|
|
+ lib->_initialize();
|
|
|
+
|
|
|
+ // update placeholders (if any)
|
|
|
+
|
|
|
+ DLScript *script = NULL;
|
|
|
+
|
|
|
+ for (Set<DLScript *>::Element *S = DLScriptLanguage::get_singleton()->script_list.front(); S; S = S->next()) {
|
|
|
+ if (lib->native_library->scripts.has(S->get()->get_script_name())) {
|
|
|
+ script = S->get();
|
|
|
+ script->script_data = lib->get_script_data(script->get_script_name());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (script == NULL) {
|
|
|
+ // new class, cool. Nothing to do here
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (script->placeholders.size() == 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ for (Set<PlaceHolderScriptInstance *>::Element *P = script->placeholders.front(); P; P = P->next()) {
|
|
|
+ PlaceHolderScriptInstance *p = P->get();
|
|
|
+ script->_update_placeholder(p);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } break;
|
|
|
+ default: {
|
|
|
+ };
|
|
|
+ }
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+// Resource loader/saver
|
|
|
+
|
|
|
RES ResourceFormatLoaderDLScript::load(const String &p_path, const String &p_original_path, Error *r_error) {
|
|
|
ResourceFormatLoaderText rsflt;
|
|
|
return rsflt.load(p_path, p_original_path, r_error);
|