From 13bd5c22c698e5b36db9012d4d5a5fd14076dfdc Mon Sep 17 00:00:00 2001 From: geequlim Date: Fri, 15 Dec 2017 22:35:16 +0800 Subject: Add plugin to edit GDNativeLibrary Rename GDNativeLibraryEditor to GDNativeLibrarySingletonEditor --- modules/gdnative/SCsub | 4 +- modules/gdnative/gd_native_library_editor.cpp | 148 ------- modules/gdnative/gd_native_library_editor.h | 55 --- .../gdnative/gdnative_library_editor_plugin.cpp | 423 +++++++++++++++++++++ modules/gdnative/gdnative_library_editor_plugin.h | 113 ++++++ .../gdnative/gdnative_library_singleton_editor.cpp | 147 +++++++ .../gdnative/gdnative_library_singleton_editor.h | 55 +++ modules/gdnative/register_types.cpp | 7 +- 8 files changed, 745 insertions(+), 207 deletions(-) delete mode 100644 modules/gdnative/gd_native_library_editor.cpp delete mode 100644 modules/gdnative/gd_native_library_editor.h create mode 100644 modules/gdnative/gdnative_library_editor_plugin.cpp create mode 100644 modules/gdnative/gdnative_library_editor_plugin.h create mode 100644 modules/gdnative/gdnative_library_singleton_editor.cpp create mode 100644 modules/gdnative/gdnative_library_singleton_editor.h (limited to 'modules') diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index fd11c8d094..4e73ebfb9d 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -3,12 +3,12 @@ Import('env') gdn_env = env.Clone() - -gdn_env.add_source_files(env.modules_sources, "gd_native_library_editor.cpp") gdn_env.add_source_files(env.modules_sources, "gdnative.cpp") gdn_env.add_source_files(env.modules_sources, "register_types.cpp") gdn_env.add_source_files(env.modules_sources, "gdnative/*.cpp") gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp") +gdn_env.add_source_files(env.modules_sources, "gdnative_library_singleton_editor.cpp") +gdn_env.add_source_files(env.modules_sources, "gdnative_library_editor_plugin.cpp") gdn_env.Append(CPPPATH=['#modules/gdnative/include/']) diff --git a/modules/gdnative/gd_native_library_editor.cpp b/modules/gdnative/gd_native_library_editor.cpp deleted file mode 100644 index fda5dcdcad..0000000000 --- a/modules/gdnative/gd_native_library_editor.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/*************************************************************************/ -/* gd_native_library_editor.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* 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. */ -/*************************************************************************/ -#ifdef TOOLS_ENABLED -#include "gd_native_library_editor.h" - -#include "gdnative.h" - -void GDNativeLibraryEditor::_find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set &enabled_list) { - - // check children - - for (int i = 0; i < p_dir->get_file_count(); i++) { - String file_type = p_dir->get_file_type(i); - - if (file_type != "GDNativeLibrary") { - continue; - } - - Ref 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)); - } - } - - // check subdirectories - for (int i = 0; i < p_dir->get_subdir_count(); i++) { - _find_gdnative_singletons(p_dir->get_subdir(i), enabled_list); - } -} - -void GDNativeLibraryEditor::_update_libraries() { - - updating = true; - libraries->clear(); - libraries->create_item(); //rppt - - Vector enabled_paths; - if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) { - enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons"); - } - Set enabled_list; - for (int i = 0; i < enabled_paths.size(); i++) { - enabled_list.insert(enabled_paths[i]); - } - - EditorFileSystemDirectory *fs = EditorFileSystem::get_singleton()->get_filesystem(); - if (fs) { - _find_gdnative_singletons(fs, enabled_list); - } - - updating = false; -} - -void GDNativeLibraryEditor::_item_edited() { - if (updating) - return; - - TreeItem *item = libraries->get_edited(); - if (!item) - return; - - bool enabled = item->get_range(1); - String path = item->get_metadata(0); - - Vector enabled_paths; - if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) { - enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons"); - } - - if (enabled) { - if (enabled_paths.find(path) == -1) { - enabled_paths.push_back(path); - } - } else { - enabled_paths.erase(path); - } - - if (enabled_paths.size()) { - ProjectSettings::get_singleton()->set("gdnative/singletons", enabled_paths); - } else { - ProjectSettings::get_singleton()->set("gdnative/singletons", Variant()); - } -} - -void GDNativeLibraryEditor::_notification(int p_what) { - - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (is_visible_in_tree()) { - _update_libraries(); - } - } -} - -void GDNativeLibraryEditor::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_item_edited"), &GDNativeLibraryEditor::_item_edited); -} - -GDNativeLibraryEditor::GDNativeLibraryEditor() { - libraries = memnew(Tree); - libraries->set_columns(2); - libraries->set_column_titles_visible(true); - libraries->set_column_title(0, TTR("Library")); - libraries->set_column_title(1, TTR("Status")); - libraries->set_hide_root(true); - add_margin_child(TTR("Libraries: "), libraries, true); - updating = false; - libraries->connect("item_edited", this, "_item_edited"); -} - -#endif // TOOLS_ENABLED diff --git a/modules/gdnative/gd_native_library_editor.h b/modules/gdnative/gd_native_library_editor.h deleted file mode 100644 index a11c4620dd..0000000000 --- a/modules/gdnative/gd_native_library_editor.h +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************/ -/* gd_native_library_editor.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* 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 GD_NATIVE_LIBRARY_EDITOR_H -#define GD_NATIVE_LIBRARY_EDITOR_H - -#ifdef TOOLS_ENABLED -#include "editor/editor_file_system.h" -#include "editor/project_settings_editor.h" - -class GDNativeLibraryEditor : public VBoxContainer { - Tree *libraries; - - bool updating; - void _update_libraries(); - - void _find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set &enabled_list); - void _item_edited(); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - GDNativeLibraryEditor(); -}; - -#endif -#endif // GD_NATIVE_LIBRARY_EDITOR_H diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp new file mode 100644 index 0000000000..1e638ab702 --- /dev/null +++ b/modules/gdnative/gdnative_library_editor_plugin.cpp @@ -0,0 +1,423 @@ +/*************************************************************************/ +/* gdnative_library_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifdef TOOLS_ENABLED +#include "gdnative_library_editor_plugin.h" +#include "gdnative.h" + +void GDNativeLibraryEditor::edit(Ref p_library) { + library = p_library; + Ref config = p_library->get_config_file(); + + for (Map::Element *E = platforms.front(); E; E = E->next()) { + for (List::Element *it = E->value().entries.front(); it; it = it->next()) { + + String target = E->key() + "." + it->get(); + TargetConfig ecfg; + ecfg.library = config->get_value("entry", target, ""); + ecfg.dependencies = config->get_value("dependencies", target, Array()); + entry_configs[target] = ecfg; + } + } + + _update_tree(); +} + +void GDNativeLibraryEditor::_bind_methods() { + + ClassDB::bind_method("_on_item_button", &GDNativeLibraryEditor::_on_item_button); + ClassDB::bind_method("_on_library_selected", &GDNativeLibraryEditor::_on_library_selected); + ClassDB::bind_method("_on_dependencies_selected", &GDNativeLibraryEditor::_on_dependencies_selected); + ClassDB::bind_method("_on_filter_selected", &GDNativeLibraryEditor::_on_filter_selected); + ClassDB::bind_method("_on_item_collapsed", &GDNativeLibraryEditor::_on_item_collapsed); + ClassDB::bind_method("_on_item_activated", &GDNativeLibraryEditor::_on_item_activated); + ClassDB::bind_method("_on_create_new_entry", &GDNativeLibraryEditor::_on_create_new_entry); +} + +void GDNativeLibraryEditor::_update_tree() { + + tree->clear(); + TreeItem *root = tree->create_item(); + + for (Map::Element *E = platforms.front(); E; E = E->next()) { + + if (showing_platform != E->key() && showing_platform != "All") + continue; + + TreeItem *platform = tree->create_item(root); + platform->set_text(0, E->get().name); + platform->set_metadata(0, E->get().library_extension); + + platform->set_custom_bg_color(0, get_color("prop_category", "Editor")); + platform->set_custom_bg_color(1, get_color("prop_category", "Editor")); + platform->set_custom_bg_color(2, get_color("prop_category", "Editor")); + platform->set_selectable(0, false); + platform->set_expand_right(0, true); + + for (List::Element *it = E->value().entries.front(); it; it = it->next()) { + + String target = E->key() + "." + it->get(); + TreeItem *bit = tree->create_item(platform); + + bit->set_text(0, it->get()); + bit->set_metadata(0, target); + bit->set_selectable(0, false); + bit->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); + + bit->add_button(1, get_icon("Folder", "EditorIcons"), BUTTON_SELECT_LIBRARY, false, TTR("Select the dynamic library for this entry")); + String file = entry_configs[target].library; + if (!file.empty()) { + bit->add_button(1, get_icon("Clear", "EditorIcons"), BUTTON_CLEAR_LIBRARY, false, TTR("Clear")); + } + bit->set_text(1, file); + + bit->add_button(2, get_icon("Folder", "EditorIcons"), BUTTON_SELECT_DEPENDENCES, false, TTR("Select dependencies of the library for this entry")); + Array files = entry_configs[target].dependencies; + if (files.size()) { + bit->add_button(2, get_icon("Clear", "EditorIcons"), BUTTON_CLEAR_DEPENDENCES, false, TTR("Clear")); + } + bit->set_text(2, Variant(files)); + + bit->add_button(3, get_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP, false, TTR("Move Up")); + bit->add_button(3, get_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN, false, TTR("Move Down")); + bit->add_button(3, get_icon("Remove", "EditorIcons"), BUTTON_ERASE_ENTRY, false, TTR("Remove current entry")); + } + + TreeItem *new_arch = tree->create_item(platform); + new_arch->set_text(0, TTR("Double click to create a new entry")); + new_arch->set_text_align(0, TreeItem::ALIGN_CENTER); + new_arch->set_custom_color(0, get_color("accent_color", "Editor")); + new_arch->set_expand_right(0, true); + new_arch->set_metadata(1, E->key()); + + platform->set_collapsed(collapsed_items.find(E->get().name) != NULL); + } +} + +void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) { + + String target = Object::cast_to(item)->get_metadata(0); + String platform = target.substr(0, target.find(".")); + String entry = target.substr(platform.length() + 1, target.length()); + String section = (id == BUTTON_SELECT_DEPENDENCES || id == BUTTON_CLEAR_DEPENDENCES) ? "dependencies" : "entry"; + + if (id == BUTTON_SELECT_LIBRARY || id == BUTTON_SELECT_DEPENDENCES) { + + EditorFileDialog::Mode mode = EditorFileDialog::MODE_OPEN_FILE; + if (id == BUTTON_SELECT_DEPENDENCES) + mode = EditorFileDialog::MODE_OPEN_FILES; + + file_dialog->set_meta("target", target); + file_dialog->set_meta("section", section); + file_dialog->clear_filters(); + file_dialog->add_filter(Object::cast_to(item)->get_parent()->get_metadata(0)); + file_dialog->set_mode(mode); + file_dialog->popup_centered_ratio(); + + } else if (id == BUTTON_CLEAR_LIBRARY) { + _set_target_value(section, target, ""); + } else if (id == BUTTON_CLEAR_DEPENDENCES) { + _set_target_value(section, target, Array()); + } else if (id == BUTTON_ERASE_ENTRY) { + _erase_entry(platform, entry); + } else if (id == BUTTON_MOVE_UP || id == BUTTON_MOVE_DOWN) { + _move_entry(platform, entry, id); + } +} + +void GDNativeLibraryEditor::_on_library_selected(const String &file) { + + _set_target_value(file_dialog->get_meta("section"), file_dialog->get_meta("target"), file); +} + +void GDNativeLibraryEditor::_on_dependencies_selected(const PoolStringArray &files) { + + _set_target_value(file_dialog->get_meta("section"), file_dialog->get_meta("target"), files); +} + +void GDNativeLibraryEditor::_on_filter_selected(int id) { + + showing_platform = filter->get_item_metadata(id); + _update_tree(); +} + +void GDNativeLibraryEditor::_on_item_collapsed(Object *p_item) { + + TreeItem *item = Object::cast_to(p_item); + String name = item->get_text(0); + + if (item->is_collapsed()) { + collapsed_items.insert(name); + } else if (Set::Element *e = collapsed_items.find(name)) { + collapsed_items.erase(e); + } +} + +void GDNativeLibraryEditor::_on_item_activated() { + + TreeItem *item = tree->get_selected(); + if (item && tree->get_selected_column() == 0 && item->get_metadata(0).get_type() == Variant::NIL) { + new_architecture_dialog->set_meta("platform", item->get_metadata(1)); + new_architecture_dialog->popup_centered(); + } +} + +void GDNativeLibraryEditor::_on_create_new_entry() { + + String platform = new_architecture_dialog->get_meta("platform"); + String entry = new_architecture_input->get_text().strip_edges(); + if (!entry.empty()) { + platforms[platform].entries.push_back(entry); + _update_tree(); + } +} + +void GDNativeLibraryEditor::_set_target_value(const String §ion, const String &target, Variant file) { + if (section == "entry") + entry_configs[target].library = file; + else if (section == "dependencies") + entry_configs[target].dependencies = file; + _translate_to_config_file(); + _update_tree(); +} + +void GDNativeLibraryEditor::_erase_entry(const String &platform, const String &entry) { + + if (platforms.has(platform)) { + if (List::Element *E = platforms[platform].entries.find(entry)) { + + String target = platform + "." + entry; + Ref config = library->get_config_file(); + + platforms[platform].entries.erase(E); + _set_target_value("entry", target, ""); + _set_target_value("dependencies", target, Array()); + _translate_to_config_file(); + _update_tree(); + } + } +} + +void GDNativeLibraryEditor::_move_entry(const String &platform, const String &entry, int dir) { + if (List::Element *E = platforms[platform].entries.find(entry)) { + if (E->prev() && dir == BUTTON_MOVE_UP) { + platforms[platform].entries.insert_before(E->prev(), E->get()); + platforms[platform].entries.erase(E); + } else if (E->next() && dir == BUTTON_MOVE_DOWN) { + platforms[platform].entries.insert_after(E->next(), E->get()); + platforms[platform].entries.erase(E); + } + _translate_to_config_file(); + _update_tree(); + } +} + +void GDNativeLibraryEditor::_translate_to_config_file() { + + if (!library.is_null()) { + + Ref config = library->get_config_file(); + config->erase_section("entry"); + config->erase_section("dependencies"); + + for (Map::Element *E = platforms.front(); E; E = E->next()) { + for (List::Element *it = E->value().entries.front(); it; it = it->next()) { + + String target = E->key() + "." + it->get(); + if (entry_configs[target].library.empty() && entry_configs[target].dependencies.empty()) + continue; + + config->set_value("entry", target, entry_configs[target].library); + config->set_value("dependencies", target, entry_configs[target].dependencies); + } + } + + library->_change_notify(); + } +} + +GDNativeLibraryEditor::GDNativeLibraryEditor() { + + showing_platform = "All"; + + { // Define platforms + NativePlatformConfig platform_windows; + platform_windows.name = "Windows"; + platform_windows.entries.push_back("64"); + platform_windows.entries.push_back("32"); + platform_windows.library_extension = "*.dll"; + platforms["Windows"] = platform_windows; + + NativePlatformConfig platform_linux; + platform_linux.name = "Linux/X11"; + platform_linux.entries.push_back("64"); + platform_linux.entries.push_back("32"); + platform_linux.library_extension = "*.so"; + platforms["X11"] = platform_linux; + + NativePlatformConfig platform_osx; + platform_osx.name = "Mac OSX"; + platform_osx.entries.push_back("64"); + platform_osx.entries.push_back("32"); + platform_osx.library_extension = "*.dylib"; + platforms["OSX"] = platform_osx; + + NativePlatformConfig platform_haiku; + platform_haiku.name = "Haiku"; + platform_haiku.entries.push_back("64"); + platform_haiku.entries.push_back("32"); + platform_haiku.library_extension = "*.so"; + platforms["Haiku"] = platform_haiku; + + NativePlatformConfig platform_uwp; + platform_uwp.name = "Windows Universal"; + platform_uwp.entries.push_back("arm"); + platform_uwp.entries.push_back("x86"); + platform_uwp.entries.push_back("x64"); + platform_uwp.library_extension = "*.dll"; + platforms["UWP"] = platform_uwp; + + NativePlatformConfig platform_android; + platform_android.name = "Android"; + platform_android.entries.push_back("armeabi-v7a"); + platform_android.entries.push_back("arm64-v8a"); + platform_android.entries.push_back("x86"); + platform_android.entries.push_back("x86_64"); + platform_android.library_extension = "*.so"; + platforms["Android"] = platform_android; + + // TODO: Javascript platform is not supported yet + // NativePlatformConfig platform_html5; + // platform_html5.name = "HTML5"; + // platform_html5.library_extension = "*.wasm"; + // platforms["Javascript"] = platform_html5; + + NativePlatformConfig platform_ios; + platform_ios.name = "iOS"; + platform_ios.entries.push_back("armv7"); + platform_ios.entries.push_back("arm64"); + platform_ios.library_extension = "*.dylib"; + platforms["iOS"] = platform_ios; + } + + VBoxContainer *container = memnew(VBoxContainer); + add_child(container); + container->set_anchors_and_margins_preset(PRESET_WIDE); + + HBoxContainer *hbox = memnew(HBoxContainer); + container->add_child(hbox); + Label *label = memnew(Label); + label->set_text(TTR("Platform:")); + hbox->add_child(label); + filter = memnew(OptionButton); + hbox->add_child(filter); + filter->set_h_size_flags(SIZE_EXPAND_FILL); + + int idx = 0; + filter->add_item(TTR("All"), idx); + filter->set_item_metadata(idx, "All"); + idx += 1; + for (Map::Element *E = platforms.front(); E; E = E->next()) { + filter->add_item(E->get().name, idx); + filter->set_item_metadata(idx, E->key()); + idx += 1; + } + filter->connect("item_selected", this, "_on_filter_selected"); + + tree = memnew(Tree); + container->add_child(tree); + tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_hide_root(true); + tree->set_column_titles_visible(true); + tree->set_columns(4); + tree->set_column_expand(0, false); + tree->set_column_min_width(0, int(200 * EDSCALE)); + tree->set_column_title(0, TTR("Platform")); + tree->set_column_title(1, TTR("Dynamic Library")); + tree->set_column_title(2, TTR("Dependencies")); + tree->set_column_expand(3, false); + tree->set_column_min_width(3, int(110 * EDSCALE)); + tree->connect("button_pressed", this, "_on_item_button"); + tree->connect("item_collapsed", this, "_on_item_collapsed"); + tree->connect("item_activated", this, "_on_item_activated"); + + file_dialog = memnew(EditorFileDialog); + file_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); + file_dialog->set_resizable(true); + add_child(file_dialog); + file_dialog->connect("file_selected", this, "_on_library_selected"); + file_dialog->connect("files_selected", this, "_on_dependencies_selected"); + + new_architecture_dialog = memnew(ConfirmationDialog); + add_child(new_architecture_dialog); + new_architecture_dialog->set_title(TTR("Add an architecture entry")); + new_architecture_input = memnew(LineEdit); + new_architecture_dialog->add_child(new_architecture_input); + new_architecture_dialog->set_custom_minimum_size(Vector2(300, 80) * EDSCALE); + new_architecture_input->set_anchors_and_margins_preset(PRESET_HCENTER_WIDE, PRESET_MODE_MINSIZE, 5 * EDSCALE); + new_architecture_dialog->get_ok()->connect("pressed", this, "_on_create_new_entry"); +} + +void GDNativeLibraryEditorPlugin::edit(Object *p_node) { + + if (Object::cast_to(p_node)) { + library_editor->edit(Object::cast_to(p_node)); + library_editor->show(); + } else + library_editor->hide(); +} + +bool GDNativeLibraryEditorPlugin::handles(Object *p_node) const { + + return p_node->is_class("GDNativeLibrary"); +} + +void GDNativeLibraryEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + button->show(); + EditorNode::get_singleton()->make_bottom_panel_item_visible(library_editor); + + } else { + if (library_editor->is_visible_in_tree()) + EditorNode::get_singleton()->hide_bottom_panel(); + button->hide(); + } +} + +GDNativeLibraryEditorPlugin::GDNativeLibraryEditorPlugin(EditorNode *p_node) { + + library_editor = memnew(GDNativeLibraryEditor); + library_editor->set_custom_minimum_size(Size2(0, 250 * EDSCALE)); + button = p_node->add_bottom_panel_item(TTR("GDNativeLibrary"), library_editor); + button->hide(); +} + +#endif diff --git a/modules/gdnative/gdnative_library_editor_plugin.h b/modules/gdnative/gdnative_library_editor_plugin.h new file mode 100644 index 0000000000..1fa6a0c945 --- /dev/null +++ b/modules/gdnative/gdnative_library_editor_plugin.h @@ -0,0 +1,113 @@ +/*************************************************************************/ +/* gdnative_library_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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 GDNATIVE_LIBRARY_EDITOR_PLUGIN_H +#define GDNATIVE_LIBRARY_EDITOR_PLUGIN_H + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#include "gdnative.h" + +class GDNativeLibraryEditor : public Control { + + GDCLASS(GDNativeLibraryEditor, Control); + + struct NativePlatformConfig { + String name; + String library_extension; + List entries; + }; + + struct TargetConfig { + String library; + Array dependencies; + }; + + enum ItemButton { + BUTTON_SELECT_LIBRARY, + BUTTON_CLEAR_LIBRARY, + BUTTON_SELECT_DEPENDENCES, + BUTTON_CLEAR_DEPENDENCES, + BUTTON_ERASE_ENTRY, + BUTTON_MOVE_UP, + BUTTON_MOVE_DOWN, + }; + + Tree *tree; + OptionButton *filter; + EditorFileDialog *file_dialog; + ConfirmationDialog *new_architecture_dialog; + LineEdit *new_architecture_input; + Set collapsed_items; + + String showing_platform; + Ref library; + Map platforms; + Map entry_configs; + +protected: + static void _bind_methods(); + void _update_tree(); + void _on_item_button(Object *item, int column, int id); + void _on_library_selected(const String &file); + void _on_dependencies_selected(const PoolStringArray &files); + void _on_filter_selected(int id); + void _on_item_collapsed(Object *item); + void _on_item_activated(); + void _on_create_new_entry(); + void _set_target_value(const String §ion, const String &target, Variant file); + void _erase_entry(const String &platform, const String &entry); + void _move_entry(const String &platform, const String &entry, int dir); + void _translate_to_config_file(); + +public: + void edit(Ref p_library); + + GDNativeLibraryEditor(); +}; + +class GDNativeLibraryEditorPlugin : public EditorPlugin { + + GDCLASS(GDNativeLibraryEditorPlugin, EditorPlugin); + + GDNativeLibraryEditor *library_editor; + EditorNode *editor; + Button *button; + +public: + virtual String get_name() const { return "GDNativeLibrary"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + GDNativeLibraryEditorPlugin(EditorNode *p_node); +}; +#endif +#endif // GDNATIVE_LIBRARY_EDITOR_PLUGIN_H diff --git a/modules/gdnative/gdnative_library_singleton_editor.cpp b/modules/gdnative/gdnative_library_singleton_editor.cpp new file mode 100644 index 0000000000..2ad497fcad --- /dev/null +++ b/modules/gdnative/gdnative_library_singleton_editor.cpp @@ -0,0 +1,147 @@ +/*************************************************************************/ +/* gdnative_library_singleton_editor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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. */ +/*************************************************************************/ +#ifdef TOOLS_ENABLED +#include "gdnative_library_singleton_editor.h" +#include "gdnative.h" + +void GDNativeLibrarySingletonEditor::_find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set &enabled_list) { + + // check children + + for (int i = 0; i < p_dir->get_file_count(); i++) { + String file_type = p_dir->get_file_type(i); + + if (file_type != "GDNativeLibrary") { + continue; + } + + Ref 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)); + } + } + + // check subdirectories + for (int i = 0; i < p_dir->get_subdir_count(); i++) { + _find_gdnative_singletons(p_dir->get_subdir(i), enabled_list); + } +} + +void GDNativeLibrarySingletonEditor::_update_libraries() { + + updating = true; + libraries->clear(); + libraries->create_item(); //rppt + + Vector enabled_paths; + if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) { + enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons"); + } + Set enabled_list; + for (int i = 0; i < enabled_paths.size(); i++) { + enabled_list.insert(enabled_paths[i]); + } + + EditorFileSystemDirectory *fs = EditorFileSystem::get_singleton()->get_filesystem(); + if (fs) { + _find_gdnative_singletons(fs, enabled_list); + } + + updating = false; +} + +void GDNativeLibrarySingletonEditor::_item_edited() { + if (updating) + return; + + TreeItem *item = libraries->get_edited(); + if (!item) + return; + + bool enabled = item->get_range(1); + String path = item->get_metadata(0); + + Vector enabled_paths; + if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) { + enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons"); + } + + if (enabled) { + if (enabled_paths.find(path) == -1) { + enabled_paths.push_back(path); + } + } else { + enabled_paths.erase(path); + } + + if (enabled_paths.size()) { + ProjectSettings::get_singleton()->set("gdnative/singletons", enabled_paths); + } else { + ProjectSettings::get_singleton()->set("gdnative/singletons", Variant()); + } +} + +void GDNativeLibrarySingletonEditor::_notification(int p_what) { + + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (is_visible_in_tree()) { + _update_libraries(); + } + } +} + +void GDNativeLibrarySingletonEditor::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_item_edited"), &GDNativeLibrarySingletonEditor::_item_edited); +} + +GDNativeLibrarySingletonEditor::GDNativeLibrarySingletonEditor() { + libraries = memnew(Tree); + libraries->set_columns(2); + libraries->set_column_titles_visible(true); + libraries->set_column_title(0, TTR("Library")); + libraries->set_column_title(1, TTR("Status")); + libraries->set_hide_root(true); + add_margin_child(TTR("Libraries: "), libraries, true); + updating = false; + libraries->connect("item_edited", this, "_item_edited"); +} + +#endif // TOOLS_ENABLED diff --git a/modules/gdnative/gdnative_library_singleton_editor.h b/modules/gdnative/gdnative_library_singleton_editor.h new file mode 100644 index 0000000000..ee1a32c5a5 --- /dev/null +++ b/modules/gdnative/gdnative_library_singleton_editor.h @@ -0,0 +1,55 @@ +/*************************************************************************/ +/* gdnative_library_singleton_editor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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 GD_NATIVE_LIBRARY_EDITOR_H +#define GD_NATIVE_LIBRARY_EDITOR_H + +#ifdef TOOLS_ENABLED +#include "editor/editor_file_system.h" +#include "editor/project_settings_editor.h" + +class GDNativeLibrarySingletonEditor : public VBoxContainer { + Tree *libraries; + + bool updating; + void _update_libraries(); + + void _find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set &enabled_list); + void _item_edited(); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + GDNativeLibrarySingletonEditor(); +}; + +#endif +#endif // GD_NATIVE_LIBRARY_EDITOR_H diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 1cb35ec006..bd9bae5294 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -45,7 +45,8 @@ #ifdef TOOLS_ENABLED #include "editor/editor_node.h" -#include "gd_native_library_editor.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(); @@ -267,7 +268,7 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty static void editor_init_callback() { - GDNativeLibraryEditor *library_editor = memnew(GDNativeLibraryEditor); + GDNativeLibrarySingletonEditor *library_editor = memnew(GDNativeLibrarySingletonEditor); library_editor->set_name(TTR("GDNative")); ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor); @@ -278,6 +279,8 @@ static void editor_init_callback() { export_plugin.instance(); EditorExport::get_singleton()->add_export_plugin(export_plugin); + + EditorNode::get_singleton()->add_editor_plugin(memnew(GDNativeLibraryEditorPlugin(EditorNode::get_singleton()))); } #endif -- cgit v1.2.3