Update GDNativeLibrarySingletonEditor.

Moved GDNative singletons discoverer from register_types to
GDNativeSingletonEditor.
Fix enable/disable switch in GDNativeLibrarySingletonEditor.
Separate `gdnative/singletons` and `gdnative/singletons_disabled`
project settings, keeping "on by default" behavior.
This commit is contained in:
Fabio Alessandrelli 2019-05-15 18:08:17 +02:00
parent aa3c5f59f2
commit a95563208f
3 changed files with 123 additions and 145 deletions

View file

@ -32,11 +32,16 @@
#include "gdnative_library_singleton_editor.h" #include "gdnative_library_singleton_editor.h"
#include "gdnative.h" #include "gdnative.h"
void GDNativeLibrarySingletonEditor::_find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set<String> &enabled_list) { #include "editor/editor_node.h"
Set<String> GDNativeLibrarySingletonEditor::_find_singletons_recursive(EditorFileSystemDirectory *p_dir) {
Set<String> file_paths;
// check children // check children
for (int i = 0; i < p_dir->get_file_count(); i++) { for (int i = 0; i < p_dir->get_file_count(); i++) {
String file_name = p_dir->get_file(i);
String file_type = p_dir->get_file_type(i); String file_type = p_dir->get_file_type(i);
if (file_type != "GDNativeLibrary") { if (file_type != "GDNativeLibrary") {
@ -45,23 +50,57 @@ void GDNativeLibrarySingletonEditor::_find_gdnative_singletons(EditorFileSystemD
Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i)); Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i));
if (lib.is_valid() && lib->is_singleton()) { if (lib.is_valid() && lib->is_singleton()) {
String path = p_dir->get_file_path(i); file_paths.insert(p_dir->get_file_path(i));
TreeItem *ti = libraries->create_item(libraries->get_root());
ti->set_text(0, path.get_file());
ti->set_tooltip(0, path);
ti->set_metadata(0, path);
ti->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
ti->set_text(1, "Disabled,Enabled");
bool enabled = enabled_list.has(path) ? true : false;
ti->set_range(1, enabled ? 1 : 0);
ti->set_custom_color(1, enabled ? Color(0, 1, 0) : Color(1, 0, 0));
} }
} }
// check subdirectories // check subdirectories
for (int i = 0; i < p_dir->get_subdir_count(); i++) { for (int i = 0; i < p_dir->get_subdir_count(); i++) {
_find_gdnative_singletons(p_dir->get_subdir(i), enabled_list); Set<String> paths = _find_singletons_recursive(p_dir->get_subdir(i));
for (Set<String>::Element *E = paths.front(); E; E = E->next()) {
file_paths.insert(E->get());
}
}
return file_paths;
}
void GDNativeLibrarySingletonEditor::_discover_singletons() {
EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem();
Set<String> file_paths = _find_singletons_recursive(dir);
bool changed = false;
Array current_files;
if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
current_files = ProjectSettings::get_singleton()->get("gdnative/singletons");
}
Array files;
for (Set<String>::Element *E = file_paths.front(); E; E = E->next()) {
if (!current_files.has(E->get())) {
changed = true;
}
files.append(E->get());
}
// Check for removed files
if (!changed) {
// Removed singleton
for (int j = 0; j < current_files.size(); j++) {
if (!files.has(current_files[j])) {
changed = true;
break;
}
}
}
if (changed) {
ProjectSettings::get_singleton()->set("gdnative/singletons", files);
_update_libraries(); // So singleton options (i.e. disabled) updates too
ProjectSettings::get_singleton()->save();
} }
} }
@ -69,21 +108,39 @@ void GDNativeLibrarySingletonEditor::_update_libraries() {
updating = true; updating = true;
libraries->clear(); libraries->clear();
libraries->create_item(); //rppt libraries->create_item(); // root item
Vector<String> enabled_paths; Array singletons;
if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) { if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons"); singletons = ProjectSettings::get_singleton()->get("gdnative/singletons");
} }
Set<String> enabled_list; Array singletons_disabled;
for (int i = 0; i < enabled_paths.size(); i++) { if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons_disabled")) {
enabled_list.insert(enabled_paths[i]); singletons_disabled = ProjectSettings::get_singleton()->get("gdnative/singletons_disabled");
} }
EditorFileSystemDirectory *fs = EditorFileSystem::get_singleton()->get_filesystem(); Array updated_disabled;
if (fs) { for (int i = 0; i < singletons.size(); i++) {
_find_gdnative_singletons(fs, enabled_list); bool enabled = true;
String path = singletons[i];
if (singletons_disabled.has(path)) {
enabled = false;
updated_disabled.push_back(path);
} }
TreeItem *ti = libraries->create_item(libraries->get_root());
ti->set_text(0, path.get_file());
ti->set_tooltip(0, path);
ti->set_metadata(0, path);
ti->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
ti->set_text(1, "Disabled,Enabled");
ti->set_range(1, enabled ? 1 : 0);
ti->set_custom_color(1, enabled ? Color(0, 1, 0) : Color(1, 0, 0));
ti->set_editable(1, true);
}
// The singletons list changed, we must update the settings
if (updated_disabled.size() != singletons_disabled.size())
ProjectSettings::get_singleton()->set("gdnative/singletons_disabled", updated_disabled);
updating = false; updating = false;
} }
@ -99,24 +156,29 @@ void GDNativeLibrarySingletonEditor::_item_edited() {
bool enabled = item->get_range(1); bool enabled = item->get_range(1);
String path = item->get_metadata(0); String path = item->get_metadata(0);
Vector<String> enabled_paths; Array disabled_paths;
if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) { Array undo_paths;
enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons"); if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons_disabled")) {
disabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons_disabled");
// Duplicate so redo works (not a reference)
disabled_paths = disabled_paths.duplicate();
// For undo, so we can reset the property.
undo_paths = disabled_paths.duplicate();
} }
if (enabled) { if (enabled) {
if (enabled_paths.find(path) == -1) { disabled_paths.erase(path);
enabled_paths.push_back(path);
}
} else { } else {
enabled_paths.erase(path); if (disabled_paths.find(path) == -1)
disabled_paths.push_back(path);
} }
if (enabled_paths.size()) { undo_redo->create_action(enabled ? TTR("Enabled GDNative Singleton") : TTR("Disabled GDNative Singleton"));
ProjectSettings::get_singleton()->set("gdnative/singletons", enabled_paths); undo_redo->add_do_property(ProjectSettings::get_singleton(), "gdnative/singletons_disabled", disabled_paths);
} else { undo_redo->add_do_method(this, "_update_libraries");
ProjectSettings::get_singleton()->set("gdnative/singletons", Variant()); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "gdnative/singletons_disabled", undo_paths);
} undo_redo->add_undo_method(this, "_update_libraries");
undo_redo->commit_action();
} }
void GDNativeLibrarySingletonEditor::_notification(int p_what) { void GDNativeLibrarySingletonEditor::_notification(int p_what) {
@ -131,9 +193,12 @@ void GDNativeLibrarySingletonEditor::_notification(int p_what) {
void GDNativeLibrarySingletonEditor::_bind_methods() { void GDNativeLibrarySingletonEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_item_edited"), &GDNativeLibrarySingletonEditor::_item_edited); ClassDB::bind_method(D_METHOD("_item_edited"), &GDNativeLibrarySingletonEditor::_item_edited);
ClassDB::bind_method(D_METHOD("_discover_singletons"), &GDNativeLibrarySingletonEditor::_discover_singletons);
ClassDB::bind_method(D_METHOD("_update_libraries"), &GDNativeLibrarySingletonEditor::_update_libraries);
} }
GDNativeLibrarySingletonEditor::GDNativeLibrarySingletonEditor() { GDNativeLibrarySingletonEditor::GDNativeLibrarySingletonEditor() {
undo_redo = EditorNode::get_singleton()->get_undo_redo();
libraries = memnew(Tree); libraries = memnew(Tree);
libraries->set_columns(2); libraries->set_columns(2);
libraries->set_column_titles_visible(true); libraries->set_column_titles_visible(true);
@ -143,6 +208,7 @@ GDNativeLibrarySingletonEditor::GDNativeLibrarySingletonEditor() {
add_margin_child(TTR("Libraries: "), libraries, true); add_margin_child(TTR("Libraries: "), libraries, true);
updating = false; updating = false;
libraries->connect("item_edited", this, "_item_edited"); libraries->connect("item_edited", this, "_item_edited");
EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_discover_singletons");
} }
#endif // TOOLS_ENABLED #endif // TOOLS_ENABLED

View file

@ -36,18 +36,24 @@
#include "editor/project_settings_editor.h" #include "editor/project_settings_editor.h"
class GDNativeLibrarySingletonEditor : public VBoxContainer { class GDNativeLibrarySingletonEditor : public VBoxContainer {
GDCLASS(GDNativeLibrarySingletonEditor, VBoxContainer);
private:
Tree *libraries; Tree *libraries;
UndoRedo *undo_redo;
bool updating; bool updating;
void _update_libraries();
void _find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set<String> &enabled_list); static Set<String> _find_singletons_recursive(EditorFileSystemDirectory *p_dir);
void _item_edited();
protected: protected:
void _notification(int p_what); void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();
void _discover_singletons();
void _item_edited();
void _update_libraries();
public: public:
GDNativeLibrarySingletonEditor(); GDNativeLibrarySingletonEditor();
}; };

View file

@ -50,97 +50,6 @@
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "gdnative_library_editor_plugin.h" #include "gdnative_library_editor_plugin.h"
#include "gdnative_library_singleton_editor.h" #include "gdnative_library_singleton_editor.h"
// Class used to discover singleton gdnative files
static void actual_discoverer_handler();
class GDNativeSingletonDiscover : public Object {
// GDCLASS(GDNativeSingletonDiscover, Object)
virtual String get_class() const {
// okay, this is a really dirty hack.
// We're overriding get_class so we can connect it to a signal
// This works because get_class is a virtual method, so we don't
// need to register a new class to ClassDB just for this one
// little signal.
actual_discoverer_handler();
return "Object";
}
};
static Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) {
Set<String> file_paths;
// check children
for (int i = 0; i < p_dir->get_file_count(); i++) {
String file_name = p_dir->get_file(i);
String file_type = p_dir->get_file_type(i);
if (file_type != "GDNativeLibrary") {
continue;
}
Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i));
if (lib.is_valid() && lib->is_singleton()) {
file_paths.insert(p_dir->get_file_path(i));
}
}
// check subdirectories
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
Set<String> paths = get_gdnative_singletons(p_dir->get_subdir(i));
for (Set<String>::Element *E = paths.front(); E; E = E->next()) {
file_paths.insert(E->get());
}
}
return file_paths;
}
static void actual_discoverer_handler() {
EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem();
Set<String> file_paths = get_gdnative_singletons(dir);
bool changed = false;
Array current_files;
if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
current_files = ProjectSettings::get_singleton()->get("gdnative/singletons");
}
Array files;
files.resize(file_paths.size());
int i = 0;
for (Set<String>::Element *E = file_paths.front(); E; i++, E = E->next()) {
if (!current_files.has(E->get())) {
changed = true;
}
files.set(i, E->get());
}
// Check for removed files
if (!changed) {
for (int j = 0; j < current_files.size(); j++) {
if (!file_paths.has(current_files[j])) {
changed = true;
break;
}
}
}
if (changed) {
ProjectSettings::get_singleton()->set("gdnative/singletons", files);
ProjectSettings::get_singleton()->save();
}
}
static GDNativeSingletonDiscover *discoverer = NULL;
class GDNativeExportPlugin : public EditorExportPlugin { class GDNativeExportPlugin : public EditorExportPlugin {
@ -275,9 +184,6 @@ static void editor_init_callback() {
library_editor->set_name(TTR("GDNative")); library_editor->set_name(TTR("GDNative"));
ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor); ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor);
discoverer = memnew(GDNativeSingletonDiscover);
EditorFileSystem::get_singleton()->connect("filesystem_changed", discoverer, "get_class");
Ref<GDNativeExportPlugin> export_plugin; Ref<GDNativeExportPlugin> export_plugin;
export_plugin.instance(); export_plugin.instance();
@ -335,30 +241,36 @@ void register_gdnative_types() {
if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) { if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
singletons = ProjectSettings::get_singleton()->get("gdnative/singletons"); singletons = ProjectSettings::get_singleton()->get("gdnative/singletons");
} }
Array excluded = Array();
singleton_gdnatives.resize(singletons.size()); if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons_disabled")) {
excluded = ProjectSettings::get_singleton()->get("gdnative/singletons_disabled");
}
for (int i = 0; i < singletons.size(); i++) { for (int i = 0; i < singletons.size(); i++) {
String path = singletons[i]; String path = singletons[i];
if (excluded.has(path))
continue;
Ref<GDNativeLibrary> lib = ResourceLoader::load(path); Ref<GDNativeLibrary> lib = ResourceLoader::load(path);
Ref<GDNative> singleton;
singleton.instance();
singleton->set_library(lib);
singleton_gdnatives.write[i].instance(); if (!singleton->initialize()) {
singleton_gdnatives.write[i]->set_library(lib);
if (!singleton_gdnatives.write[i]->initialize()) {
// Can't initialize. Don't make a native_call then // Can't initialize. Don't make a native_call then
continue; continue;
} }
void *proc_ptr; void *proc_ptr;
Error err = singleton_gdnatives[i]->get_symbol( Error err = singleton->get_symbol(
lib->get_symbol_prefix() + "gdnative_singleton", lib->get_symbol_prefix() + "gdnative_singleton",
proc_ptr); proc_ptr);
if (err != OK) { if (err != OK) {
ERR_PRINT((String("No godot_gdnative_singleton in \"" + singleton_gdnatives[i]->get_library()->get_current_library_path()) + "\" found").utf8().get_data()); ERR_PRINT((String("No godot_gdnative_singleton in \"" + singleton->get_library()->get_current_library_path()) + "\" found").utf8().get_data());
} else { } else {
singleton_gdnatives.push_back(singleton);
((void (*)())proc_ptr)(); ((void (*)())proc_ptr)();
} }
} }
@ -388,12 +300,6 @@ void unregister_gdnative_types() {
memdelete(GDNativeCallRegistry::singleton); memdelete(GDNativeCallRegistry::singleton);
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint() && discoverer != NULL) {
memdelete(discoverer);
}
#endif
ResourceLoader::remove_resource_format_loader(resource_loader_gdnlib); ResourceLoader::remove_resource_format_loader(resource_loader_gdnlib);
resource_loader_gdnlib.unref(); resource_loader_gdnlib.unref();