Browse Source

Merge pull request #28917 from Faless/gdnative/singleton_editor_fix_pr

Update GDNativeLibrarySingletonEditor.
Rémi Verschelde 6 years ago
parent
commit
eded8d52e3

+ 100 - 34
modules/gdnative/gdnative_library_singleton_editor.cpp

@@ -32,11 +32,16 @@
 #include "gdnative_library_singleton_editor.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
 
 	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") {
@@ -45,23 +50,57 @@ void GDNativeLibrarySingletonEditor::_find_gdnative_singletons(EditorFileSystemD
 
 		Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i));
 		if (lib.is_valid() && lib->is_singleton()) {
-			String path = 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));
+			file_paths.insert(p_dir->get_file_path(i));
 		}
 	}
 
 	// check subdirectories
 	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,22 +108,40 @@ void GDNativeLibrarySingletonEditor::_update_libraries() {
 
 	updating = true;
 	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")) {
-		enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons");
+		singletons = ProjectSettings::get_singleton()->get("gdnative/singletons");
 	}
-	Set<String> enabled_list;
-	for (int i = 0; i < enabled_paths.size(); i++) {
-		enabled_list.insert(enabled_paths[i]);
+	Array singletons_disabled;
+	if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons_disabled")) {
+		singletons_disabled = ProjectSettings::get_singleton()->get("gdnative/singletons_disabled");
 	}
 
-	EditorFileSystemDirectory *fs = EditorFileSystem::get_singleton()->get_filesystem();
-	if (fs) {
-		_find_gdnative_singletons(fs, enabled_list);
+	Array updated_disabled;
+	for (int i = 0; i < singletons.size(); i++) {
+		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;
 }
 
@@ -99,24 +156,29 @@ void GDNativeLibrarySingletonEditor::_item_edited() {
 	bool enabled = item->get_range(1);
 	String path = item->get_metadata(0);
 
-	Vector<String> enabled_paths;
-	if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
-		enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons");
+	Array disabled_paths;
+	Array undo_paths;
+	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_paths.find(path) == -1) {
-			enabled_paths.push_back(path);
-		}
+		disabled_paths.erase(path);
 	} else {
-		enabled_paths.erase(path);
+		if (disabled_paths.find(path) == -1)
+			disabled_paths.push_back(path);
 	}
 
-	if (enabled_paths.size()) {
-		ProjectSettings::get_singleton()->set("gdnative/singletons", enabled_paths);
-	} else {
-		ProjectSettings::get_singleton()->set("gdnative/singletons", Variant());
-	}
+	undo_redo->create_action(enabled ? TTR("Enabled GDNative Singleton") : TTR("Disabled GDNative Singleton"));
+	undo_redo->add_do_property(ProjectSettings::get_singleton(), "gdnative/singletons_disabled", disabled_paths);
+	undo_redo->add_do_method(this, "_update_libraries");
+	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) {
@@ -131,9 +193,12 @@ void GDNativeLibrarySingletonEditor::_notification(int p_what) {
 void GDNativeLibrarySingletonEditor::_bind_methods() {
 
 	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() {
+	undo_redo = EditorNode::get_singleton()->get_undo_redo();
 	libraries = memnew(Tree);
 	libraries->set_columns(2);
 	libraries->set_column_titles_visible(true);
@@ -143,6 +208,7 @@ GDNativeLibrarySingletonEditor::GDNativeLibrarySingletonEditor() {
 	add_margin_child(TTR("Libraries: "), libraries, true);
 	updating = false;
 	libraries->connect("item_edited", this, "_item_edited");
+	EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_discover_singletons");
 }
 
 #endif // TOOLS_ENABLED

+ 9 - 3
modules/gdnative/gdnative_library_singleton_editor.h

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

+ 14 - 108
modules/gdnative/register_types.cpp

@@ -50,97 +50,6 @@
 #include "editor/editor_node.h"
 #include "gdnative_library_editor_plugin.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 {
 
@@ -275,9 +184,6 @@ static void editor_init_callback() {
 	library_editor->set_name(TTR("GDNative"));
 	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;
 	export_plugin.instance();
 
@@ -335,30 +241,36 @@ void register_gdnative_types() {
 	if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
 		singletons = ProjectSettings::get_singleton()->get("gdnative/singletons");
 	}
-
-	singleton_gdnatives.resize(singletons.size());
+	Array excluded = Array();
+	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++) {
 		String path = singletons[i];
 
-		Ref<GDNativeLibrary> lib = ResourceLoader::load(path);
+		if (excluded.has(path))
+			continue;
 
-		singleton_gdnatives.write[i].instance();
-		singleton_gdnatives.write[i]->set_library(lib);
+		Ref<GDNativeLibrary> lib = ResourceLoader::load(path);
+		Ref<GDNative> singleton;
+		singleton.instance();
+		singleton->set_library(lib);
 
-		if (!singleton_gdnatives.write[i]->initialize()) {
+		if (!singleton->initialize()) {
 			// Can't initialize. Don't make a native_call then
 			continue;
 		}
 
 		void *proc_ptr;
-		Error err = singleton_gdnatives[i]->get_symbol(
+		Error err = singleton->get_symbol(
 				lib->get_symbol_prefix() + "gdnative_singleton",
 				proc_ptr);
 
 		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 {
+			singleton_gdnatives.push_back(singleton);
 			((void (*)())proc_ptr)();
 		}
 	}
@@ -388,12 +300,6 @@ void unregister_gdnative_types() {
 
 	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);
 	resource_loader_gdnlib.unref();