diff options
Diffstat (limited to 'editor')
49 files changed, 1128 insertions, 305 deletions
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index f97f1d0871..8433f4ff7b 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -86,7 +86,7 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { memdelete(f); } - _update_favorite_list(); + _save_and_update_favorite_list(); // Restore valid window bounds or pop up at default size. if (EditorSettings::get_singleton()->has_setting("interface/dialogs/create_new_node_bounds")) { @@ -157,6 +157,18 @@ Ref<Texture> CreateDialog::_get_editor_icon(const String &p_type) const { return get_icon(p_type, "EditorIcons"); } + if (ScriptServer::is_global_class(p_type)) { + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(p_type); + RES icon; + if (FileAccess::exists(icon_path)) { + icon = ResourceLoader::load(icon_path); + } + if (!icon.is_valid()) { + icon = get_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons"); + } + return icon; + } + const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types(); for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) { const Vector<EditorData::CustomType> &ct = E->value(); @@ -180,7 +192,7 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p return; bool cpp_type = ClassDB::class_exists(p_type); - EditorData &ed = EditorNode::get_singleton()->get_editor_data(); + EditorData &ed = EditorNode::get_editor_data(); if (p_type == base_type) return; @@ -262,13 +274,7 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p const String &description = EditorHelp::get_doc_data()->class_list[p_type].brief_description; item->set_tooltip(0, description); - if (cpp_type && has_icon(p_type, "EditorIcons")) { - - item->set_icon(0, get_icon(p_type, "EditorIcons")); - } else if (!cpp_type && has_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")) { - - item->set_icon(0, get_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")); - } + item->set_icon(0, _get_editor_icon(p_type)); p_types[p_type] = item; } @@ -287,7 +293,7 @@ void CreateDialog::_update_search() { HashMap<String, TreeItem *> types; TreeItem *root = search_options->create_item(); - EditorData &ed = EditorNode::get_singleton()->get_editor_data(); + EditorData &ed = EditorNode::get_editor_data(); root->set_text(0, base_type); if (has_icon(base_type, "EditorIcons")) { @@ -330,7 +336,7 @@ void CreateDialog::_update_search() { break; } - type = ClassDB::get_parent_class(type); + type = cpp_type ? ClassDB::get_parent_class(type) : ed.script_class_get_base(type); } if (found) @@ -490,16 +496,8 @@ Object *CreateDialog::instance_selected() { custom = md; if (custom != String()) { - if (ScriptServer::is_global_class(custom)) { - RES script = ResourceLoader::load(ScriptServer::get_global_class_path(custom)); - ERR_FAIL_COND_V(!script.is_valid(), NULL); - - Object *obj = ClassDB::instance(ScriptServer::get_global_class_base(custom)); - ERR_FAIL_COND_V(!obj, NULL); - - obj->set_script(script.get_ref_ptr()); - return obj; + return EditorNode::get_editor_data().script_class_instance(custom); } return EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom); } else { @@ -545,8 +543,7 @@ void CreateDialog::_favorite_toggled() { favorite->set_pressed(false); } - _save_favorite_list(); - _update_favorite_list(); + _save_and_update_favorite_list(); } void CreateDialog::_save_favorite_list() { @@ -556,8 +553,11 @@ void CreateDialog::_save_favorite_list() { if (f) { for (int i = 0; i < favorite_list.size(); i++) { - - f->store_line(favorite_list[i]); + String l = favorite_list[i]; + String name = l.split(" ")[0]; + if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) + continue; + f->store_line(l); } memdelete(f); } @@ -568,11 +568,15 @@ void CreateDialog::_update_favorite_list() { favorites->clear(); TreeItem *root = favorites->create_item(); for (int i = 0; i < favorite_list.size(); i++) { - TreeItem *ti = favorites->create_item(root); String l = favorite_list[i]; + String name = l.split(" ")[0]; + if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) + continue; + TreeItem *ti = favorites->create_item(root); ti->set_text(0, l); ti->set_icon(0, _get_editor_icon(l)); } + emit_signal("favorites_updated"); } void CreateDialog::_history_selected() { @@ -581,7 +585,7 @@ void CreateDialog::_history_selected() { if (!item) return; - search_box->set_text(item->get_text(0)); + search_box->set_text(item->get_text(0).get_slicec(' ', 0)); _update_search(); } @@ -591,7 +595,7 @@ void CreateDialog::_favorite_selected() { if (!item) return; - search_box->set_text(item->get_text(0)); + search_box->set_text(item->get_text(0).get_slicec(' ', 0)); _update_search(); } @@ -675,6 +679,10 @@ void CreateDialog::drop_data_fw(const Point2 &p_point, const Variant &p_data, Co } } + _save_and_update_favorite_list(); +} + +void CreateDialog::_save_and_update_favorite_list() { _save_favorite_list(); _update_favorite_list(); } @@ -690,12 +698,14 @@ void CreateDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("_favorite_selected"), &CreateDialog::_favorite_selected); ClassDB::bind_method(D_METHOD("_history_activated"), &CreateDialog::_history_activated); ClassDB::bind_method(D_METHOD("_favorite_activated"), &CreateDialog::_favorite_activated); + ClassDB::bind_method(D_METHOD("_save_and_update_favorite_list"), &CreateDialog::_save_and_update_favorite_list); ClassDB::bind_method("get_drag_data_fw", &CreateDialog::get_drag_data_fw); ClassDB::bind_method("can_drop_data_fw", &CreateDialog::can_drop_data_fw); ClassDB::bind_method("drop_data_fw", &CreateDialog::drop_data_fw); ADD_SIGNAL(MethodInfo("create")); + ADD_SIGNAL(MethodInfo("favorites_updated")); } CreateDialog::CreateDialog() { diff --git a/editor/create_dialog.h b/editor/create_dialog.h index f8eec231a4..6df9eebc8c 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -90,6 +90,8 @@ protected: void _notification(int p_what); static void _bind_methods(); + void _save_and_update_favorite_list(); + public: Object *instance_selected(); String get_selected_type(); diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index f4ef11eb36..69c120bb3c 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -888,11 +888,56 @@ StringName EditorData::script_class_get_base(const String &p_class) { return script->get_language()->get_global_class_name(base_script->get_path()); } +Object *EditorData::script_class_instance(const String &p_class) { + if (ScriptServer::is_global_class(p_class)) { + Object *obj = ClassDB::instance(ScriptServer::get_global_class_base(p_class)); + if (obj) { + RES script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class)); + if (script.is_valid()) + obj->set_script(script.get_ref_ptr()); + + RES icon = ResourceLoader::load(script_class_get_icon_path(p_class)); + if (icon.is_valid()) + obj->set_meta("_editor_icon", icon); + + return obj; + } + } + return NULL; +} + +void EditorData::script_class_save_icon_paths() { + List<StringName> keys; + _script_class_icon_paths.get_key_list(&keys); + + Dictionary d; + for (List<StringName>::Element *E = keys.front(); E; E = E->next()) { + d[E->get()] = _script_class_icon_paths[E->get()]; + } + + ProjectSettings::get_singleton()->set("_global_script_class_icons", d); + ProjectSettings::get_singleton()->save(); +} + +void EditorData::script_class_load_icon_paths() { + script_class_clear_icon_paths(); + + Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons"); + List<Variant> keys; + d.get_key_list(&keys); + + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { + String key = E->get().operator String(); + _script_class_icon_paths[key] = d[key]; + } +} + EditorData::EditorData() { current_edited_scene = -1; //load_imported_scenes_from_globals(); + script_class_load_icon_paths(); } /////////// diff --git a/editor/editor_data.h b/editor/editor_data.h index fac6635cd2..285769aa78 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -146,6 +146,8 @@ private: bool _find_updated_instances(Node *p_root, Node *p_node, Set<String> &checked_paths); + HashMap<StringName, String> _script_class_icon_paths; + public: EditorPlugin *get_editor(Object *p_object); EditorPlugin *get_subeditor(Object *p_object); @@ -213,6 +215,12 @@ public: bool script_class_is_parent(const String &p_class, const String &p_inherits); StringName script_class_get_base(const String &p_class); + Object *script_class_instance(const String &p_class); + String script_class_get_icon_path(const String &p_class) const { return _script_class_icon_paths.has(p_class) ? _script_class_icon_paths[p_class] : String(); } + void script_class_set_icon_path(const String &p_class, const String &p_icon_path) { _script_class_icon_paths[p_class] = p_icon_path; } + void script_class_clear_icon_paths() { _script_class_icon_paths.clear(); } + void script_class_save_icon_paths(); + void script_class_load_icon_paths(); EditorData(); }; diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 7d56c4985a..d240f4ed25 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -558,7 +558,9 @@ void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p } if (single_item_selected) { item_menu->add_separator(); - item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Show In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); + Dictionary item_meta = item_list->get_item_metadata(p_item); + String item_text = item_meta["dir"] ? TTR("Open In File Manager") : TTR("Show In File Manager"); + item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), item_text, ITEM_MENU_SHOW_IN_EXPLORER); } if (item_menu->get_item_count() > 0) { @@ -582,7 +584,7 @@ void EditorFileDialog::_item_list_rmb_clicked(const Vector2 &p_pos) { } item_menu->add_icon_item(get_icon("Reload", "EditorIcons"), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5); item_menu->add_separator(); - item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Show In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); + item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Open In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); item_menu->set_position(item_list->get_global_position() + p_pos); item_menu->popup(); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index d8ab41fa05..9562a8c63c 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -133,6 +133,10 @@ String EditorFileSystemDirectory::get_file_script_class_extends(int p_idx) const return files[p_idx]->script_class_extends; } +String EditorFileSystemDirectory::get_file_script_class_icon_path(int p_idx) const { + return files[p_idx]->script_class_icon_path; +} + StringName EditorFileSystemDirectory::get_file_type(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, files.size(), ""); @@ -233,6 +237,7 @@ void EditorFileSystem::_scan_filesystem() { fc.import_valid = split[4].to_int64() != 0; fc.script_class_name = split[5].get_slice("<>", 0); fc.script_class_extends = split[5].get_slice("<>", 1); + fc.script_class_icon_path = split[5].get_slice("<>", 2); String deps = split[6].strip_edges(); if (deps.length()) { @@ -721,6 +726,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess fi->import_valid = fc->import_valid; fi->script_class_name = fc->script_class_name; fi->script_class_extends = fc->script_class_extends; + fi->script_class_icon_path = fc->script_class_icon_path; if (fc->type == String()) { fi->type = ResourceLoader::get_resource_type(path); @@ -731,7 +737,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess } else { fi->type = ResourceFormatImporter::get_singleton()->get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->modified_time = 0; fi->import_modified_time = 0; fi->import_valid = ResourceLoader::is_import_valid(path); @@ -753,10 +759,11 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess fi->import_valid = true; fi->script_class_name = fc->script_class_name; fi->script_class_extends = fc->script_class_extends; + fi->script_class_icon_path = fc->script_class_icon_path; } else { //new or modified time fi->type = ResourceLoader::get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->deps = _get_dependencies(path); fi->modified_time = mt; fi->import_modified_time = 0; @@ -855,7 +862,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const fi->modified_time = FileAccess::get_modified_time(path); fi->import_modified_time = 0; fi->type = ResourceLoader::get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->import_valid = ResourceLoader::is_import_valid(path); { @@ -1110,7 +1117,7 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, for (int i = 0; i < p_dir->files.size(); i++) { - String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends; + String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path; s += "::"; for (int j = 0; j < p_dir->files[i]->deps.size(); j++) { @@ -1316,19 +1323,22 @@ Vector<String> EditorFileSystem::_get_dependencies(const String &p_path) { return ret; } -String EditorFileSystem::_get_global_script_class(const String &p_type, const String &p_path, String *r_extends) const { +String EditorFileSystem::_get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const { for (int i = 0; i < ScriptServer::get_language_count(); i++) { if (ScriptServer::get_language(i)->handles_global_class_type(p_type)) { String global_name; String extends; + String icon_path; - global_name = ScriptServer::get_language(i)->get_global_class_name(p_path, &extends); + global_name = ScriptServer::get_language(i)->get_global_class_name(p_path, &extends, &icon_path); *r_extends = extends; + *r_icon_path = icon_path; return global_name; } } *r_extends = String(); + *r_icon_path = String(); return String(); } @@ -1346,8 +1356,8 @@ void EditorFileSystem::_scan_script_classes(EditorFileSystemDirectory *p_dir) { lang = ScriptServer::get_language(j)->get_name(); } } - ScriptServer::add_global_class(files[i]->script_class_name, files[i]->script_class_extends, lang, p_dir->get_file_path(i)); + EditorNode::get_editor_data().script_class_set_icon_path(files[i]->script_class_name, files[i]->script_class_icon_path); } for (int i = 0; i < p_dir->get_subdir_count(); i++) { _scan_script_classes(p_dir->get_subdir(i)); @@ -1366,6 +1376,8 @@ void EditorFileSystem::update_script_classes() { } ScriptServer::save_global_classes(); + EditorNode::get_editor_data().script_class_save_icon_paths(); + emit_signal("script_classes_updated"); } void EditorFileSystem::_queue_update_script_classes() { @@ -1437,7 +1449,7 @@ void EditorFileSystem::update_file(const String &p_file) { } fs->files[cpos]->type = type; - fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends); + fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path); fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); fs->files[cpos]->deps = _get_dependencies(p_file); fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file); @@ -1704,6 +1716,7 @@ void EditorFileSystem::_bind_methods() { ADD_SIGNAL(MethodInfo("filesystem_changed")); ADD_SIGNAL(MethodInfo("sources_changed", PropertyInfo(Variant::BOOL, "exist"))); ADD_SIGNAL(MethodInfo("resources_reimported", PropertyInfo(Variant::POOL_STRING_ARRAY, "resources"))); + ADD_SIGNAL(MethodInfo("script_classes_updated")); } void EditorFileSystem::_update_extensions() { diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 1aa35f4782..75ca79932f 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -60,6 +60,7 @@ class EditorFileSystemDirectory : public Object { bool verified; //used for checking changes String script_class_name; String script_class_extends; + String script_class_icon_path; }; struct FileInfoSort { @@ -90,6 +91,7 @@ public: bool get_file_import_is_valid(int p_idx) const; String get_file_script_class_name(int p_idx) const; //used for scripts String get_file_script_class_extends(int p_idx) const; //used for scripts + String get_file_script_class_icon_path(int p_idx) const; //used for scripts EditorFileSystemDirectory *get_parent(); @@ -163,6 +165,7 @@ class EditorFileSystem : public Node { bool import_valid; String script_class_name; String script_class_extends; + String script_class_icon_path; }; HashMap<String, FileCache> file_cache; @@ -225,7 +228,7 @@ class EditorFileSystem : public Node { volatile bool update_script_classes_queued; void _queue_update_script_classes(); - String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends) const; + String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const; protected: void _notification(int p_what); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 1ac6eef8b4..60826aa81b 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -718,16 +718,22 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { if (p_class == edited_class) return OK; //already there + edited_class = p_class; + _update_doc(); + return OK; +} + +void EditorHelp::_update_doc() { + scroll_locked = true; class_desc->clear(); method_line.clear(); section_line.clear(); - edited_class = p_class; _init_colors(); - DocData::ClassDoc cd = doc->class_list[p_class]; //make a copy, so we can sort without worrying + DocData::ClassDoc cd = doc->class_list[edited_class]; //make a copy, so we can sort without worrying Ref<Font> doc_font = get_font("doc", "EditorFonts"); Ref<Font> doc_title_font = get_font("doc_title", "EditorFonts"); @@ -739,7 +745,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->push_color(title_color); class_desc->add_text(TTR("Class:") + " "); class_desc->push_color(headline_color); - _add_text(p_class); + _add_text(edited_class); class_desc->pop(); class_desc->pop(); class_desc->pop(); @@ -1458,8 +1464,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { } scroll_locked = false; - - return OK; } void EditorHelp::_request_help(const String &p_string) { @@ -1756,9 +1760,6 @@ void EditorHelp::_add_text(const String &p_bbcode) { _add_text_to_rt(p_bbcode, class_desc); } -void EditorHelp::_update_doc() { -} - void EditorHelp::generate_doc() { doc = memnew(DocData); @@ -1781,6 +1782,7 @@ void EditorHelp::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor")); + _update_doc(); } break; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 158eedfb0f..b3ec717d85 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -54,7 +54,11 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f self->emit_signal("show_request"); */ - self->add_message(err_str, true); + if (p_type == ERR_HANDLER_WARNING) { + self->add_message(err_str, MSG_TYPE_WARNING); + } else { + self->add_message(err_str, MSG_TYPE_ERROR); + } } void EditorLog::_notification(int p_what) { @@ -95,22 +99,32 @@ void EditorLog::clear() { _clear_request(); } -void EditorLog::add_message(const String &p_msg, bool p_error) { +void EditorLog::add_message(const String &p_msg, MessageType p_type) { log->add_newline(); - if (p_error) { - log->push_color(get_color("error_color", "Editor")); - Ref<Texture> icon = get_icon("Error", "EditorIcons"); - log->add_image(icon); - log->add_text(" "); - tool_button->set_icon(icon); + bool restore = p_type != MSG_TYPE_STD; + switch (p_type) { + case MSG_TYPE_ERROR: { + log->push_color(get_color("error_color", "Editor")); + Ref<Texture> icon = get_icon("Error", "EditorIcons"); + log->add_image(icon); + log->add_text(" "); + tool_button->set_icon(icon); + } break; + case MSG_TYPE_WARNING: { + log->push_color(get_color("warning_color", "Editor")); + Ref<Texture> icon = get_icon("Warning", "EditorIcons"); + log->add_image(icon); + log->add_text(" "); + tool_button->set_icon(icon); + } break; } log->add_text(p_msg); //button->set_text(p_msg); - if (p_error) + if (restore) log->pop(); } diff --git a/editor/editor_log.h b/editor/editor_log.h index f9bc82de7d..8d0310d914 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -42,6 +42,7 @@ #include "scene/gui/panel_container.h" #include "scene/gui/texture_rect.h" #include "scene/gui/tool_button.h" + class EditorLog : public VBoxContainer { GDCLASS(EditorLog, VBoxContainer); @@ -68,7 +69,13 @@ protected: void _notification(int p_what); public: - void add_message(const String &p_msg, bool p_error = false); + enum MessageType { + MSG_TYPE_STD, + MSG_TYPE_ERROR, + MSG_TYPE_WARNING + }; + + void add_message(const String &p_msg, MessageType p_type = MSG_TYPE_STD); void set_tool_button(ToolButton *p_tool_button); void deinit(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 81b7a66361..0be6ee8759 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -411,6 +411,18 @@ void EditorNode::_notification(int p_what) { } } +void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_name) { + Ref<Script> script = Object::cast_to<Script>(p_script); + if (script.is_null()) + return; + if (p_activate_name.length()) { + set_addon_plugin_enabled(p_activate_name, true); + } + project_settings->update_plugins(); + project_settings->hide(); + push_item(script.operator->()); +} + void EditorNode::_fs_changed() { for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) { @@ -2547,6 +2559,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled) EditorPlugin *ep = memnew(EditorPlugin); ep->set_script(script.get_ref_ptr()); + ep->set_dir_cache(p_addon); plugin_addons[p_addon] = ep; add_editor_plugin(ep); @@ -4548,6 +4561,8 @@ void EditorNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_resources_reimported"), &EditorNode::_resources_reimported); ClassDB::bind_method(D_METHOD("_bottom_panel_raise_toggled"), &EditorNode::_bottom_panel_raise_toggled); + ClassDB::bind_method(D_METHOD("_on_plugin_ready"), &EditorNode::_on_plugin_ready); + ClassDB::bind_method(D_METHOD("_video_driver_selected"), &EditorNode::_video_driver_selected); ADD_SIGNAL(MethodInfo("play_pressed")); @@ -4566,7 +4581,7 @@ static Node *_resource_get_edited_scene() { void EditorNode::_print_handler(void *p_this, const String &p_string, bool p_error) { EditorNode *en = (EditorNode *)p_this; - en->log->add_message(p_string, p_error); + en->log->add_message(p_string, p_error ? EditorLog::MSG_TYPE_ERROR : EditorLog::MSG_TYPE_STD); } EditorNode::EditorNode() { @@ -4776,7 +4791,7 @@ EditorNode::EditorNode() { EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false); EDITOR_DEF("interface/inspector/horizontal_vector3_editing", true); EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true); - EDITOR_DEF("interface/inspector/resources_types_to_open_in_new_inspector", "SpatialMaterial"); + EDITOR_DEF("interface/inspector/resources_types_to_open_in_new_inspector", "SpatialMaterial,Script"); EDITOR_DEF("run/auto_save/save_before_running", true); theme_base = memnew(Control); @@ -5134,6 +5149,10 @@ EditorNode::EditorNode() { p->connect("id_pressed", this, "_menu_option"); p->add_item(TTR("Export"), FILE_EXPORT_PROJECT); + plugin_config_dialog = memnew(PluginConfigDialog); + plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready"); + gui_base->add_child(plugin_config_dialog); + tool_menu = memnew(PopupMenu); tool_menu->set_name("Tools"); tool_menu->connect("index_pressed", this, "_tool_menu_option"); @@ -5409,7 +5428,7 @@ EditorNode::EditorNode() { } filesystem_dock = memnew(FileSystemDock(this)); - filesystem_dock->set_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); + filesystem_dock->set_file_list_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); if (use_single_dock_column) { dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(filesystem_dock); @@ -5448,6 +5467,7 @@ EditorNode::EditorNode() { bottom_panel->add_child(bottom_panel_vb); bottom_panel_hb = memnew(HBoxContainer); + bottom_panel_hb->set_custom_minimum_size(Size2(0, 24)); // Adjust for the height of the "Expand Bottom Dock" icon. bottom_panel_vb->add_child(bottom_panel_hb); bottom_panel_hb_editors = memnew(HBoxContainer); diff --git a/editor/editor_node.h b/editor/editor_node.h index 85aa37ec7e..5a17ab6ca0 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -56,6 +56,7 @@ #include "editor/inspector_dock.h" #include "editor/node_dock.h" #include "editor/pane_drag.h" +#include "editor/plugin_config_dialog.h" #include "editor/progress_dialog.h" #include "editor/project_export.h" #include "editor/project_settings_editor.h" @@ -257,6 +258,8 @@ private: ToolButton *search_button; TextureProgress *audio_vu; + PluginConfigDialog *plugin_config_dialog; + RichTextLabel *load_errors; AcceptDialog *load_error_dialog; @@ -416,6 +419,8 @@ private: void _tool_menu_option(int p_idx); void _update_debug_options(); + void _on_plugin_ready(Object *p_script, const String &p_activate_name); + void _fs_changed(); void _resources_reimported(const Vector<String> &p_resources); void _sources_changed(bool p_exist); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index a926401558..137e710c5c 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -309,6 +309,12 @@ void EditorPlugin::remove_autoload_singleton(const String &p_name) { EditorNode::get_singleton()->get_project_settings()->get_autoload_settings()->autoload_remove(p_name); } +Ref<ConfigFile> EditorPlugin::get_config() { + Ref<ConfigFile> cf = memnew(ConfigFile); + cf->load(_dir_cache.plus_file("plugin.cfg")); + return cf; +} + ToolButton *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) { ERR_FAIL_NULL_V(p_control, NULL); return EditorNode::get_singleton()->add_bottom_panel_item(p_title, p_control); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index c417f487dc..903b82937f 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -114,6 +114,7 @@ class EditorPlugin : public Node { bool force_draw_over_forwarding_enabled; String last_main_screen_name; + String _dir_cache; protected: static void _bind_methods(); @@ -221,6 +222,10 @@ public: void add_autoload_singleton(const String &p_name, const String &p_path); void remove_autoload_singleton(const String &p_name); + void set_dir_cache(const String &p_dir) { _dir_cache = p_dir; } + String get_dir_cache() { return _dir_cache; } + Ref<ConfigFile> get_config(); + EditorPlugin(); virtual ~EditorPlugin(); }; diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index ea1e0fe99e..68f8ed6d94 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -41,6 +41,9 @@ void EditorPluginSettings::_notification(int p_what) { if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) { update_plugins(); + } else if (p_what == Node::NOTIFICATION_READY) { + plugin_config_dialog->connect("plugin_ready", EditorNode::get_singleton(), "_on_plugin_ready"); + plugin_list->connect("button_pressed", this, "_cell_button_pressed"); } } @@ -124,6 +127,7 @@ void EditorPluginSettings::update_plugins() { item->set_range_config(3, 0, 1, 1); item->set_text(3, "Inactive,Active"); item->set_editable(3, true); + item->add_button(4, get_icon("Edit", "EditorIcons"), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin")); if (EditorNode::get_singleton()->is_addon_plugin_enabled(d)) { item->set_custom_color(3, get_color("success_color", "Editor")); @@ -164,17 +168,44 @@ void EditorPluginSettings::_plugin_activity_changed() { ti->set_custom_color(3, get_color("disabled_font_color", "Editor")); } +void EditorPluginSettings::_create_clicked() { + plugin_config_dialog->config(""); + plugin_config_dialog->popup_centered(); +} + +void EditorPluginSettings::_cell_button_pressed(Object *p_item, int p_column, int p_id) { + TreeItem *item = Object::cast_to<TreeItem>(p_item); + if (!item) + return; + if (p_id == BUTTON_PLUGIN_EDIT) { + if (p_column == 4) { + String dir = item->get_metadata(0); + plugin_config_dialog->config("res://addons/" + dir + "/plugin.cfg"); + plugin_config_dialog->popup_centered(); + } + } +} + void EditorPluginSettings::_bind_methods() { ClassDB::bind_method("update_plugins", &EditorPluginSettings::update_plugins); + ClassDB::bind_method("_create_clicked", &EditorPluginSettings::_create_clicked); ClassDB::bind_method("_plugin_activity_changed", &EditorPluginSettings::_plugin_activity_changed); + ClassDB::bind_method("_cell_button_pressed", &EditorPluginSettings::_cell_button_pressed); } EditorPluginSettings::EditorPluginSettings() { + plugin_config_dialog = memnew(PluginConfigDialog); + plugin_config_dialog->config(""); + add_child(plugin_config_dialog); + HBoxContainer *title_hb = memnew(HBoxContainer); title_hb->add_child(memnew(Label(TTR("Installed Plugins:")))); title_hb->add_spacer(); + create_plugin = memnew(Button(TTR("Create"))); + create_plugin->connect("pressed", this, "_create_clicked"); + title_hb->add_child(create_plugin); update_list = memnew(Button(TTR("Update"))); update_list->connect("pressed", this, "update_plugins"); title_hb->add_child(update_list); @@ -182,19 +213,22 @@ EditorPluginSettings::EditorPluginSettings() { plugin_list = memnew(Tree); plugin_list->set_v_size_flags(SIZE_EXPAND_FILL); - plugin_list->set_columns(4); + plugin_list->set_columns(5); plugin_list->set_column_titles_visible(true); plugin_list->set_column_title(0, TTR("Name:")); plugin_list->set_column_title(1, TTR("Version:")); plugin_list->set_column_title(2, TTR("Author:")); plugin_list->set_column_title(3, TTR("Status:")); + plugin_list->set_column_title(4, TTR("Edit:")); plugin_list->set_column_expand(0, true); plugin_list->set_column_expand(1, false); plugin_list->set_column_expand(2, false); plugin_list->set_column_expand(3, false); + plugin_list->set_column_expand(4, false); plugin_list->set_column_min_width(1, 100 * EDSCALE); plugin_list->set_column_min_width(2, 250 * EDSCALE); plugin_list->set_column_min_width(3, 80 * EDSCALE); + plugin_list->set_column_min_width(4, 40 * EDSCALE); plugin_list->set_hide_root(true); plugin_list->connect("item_edited", this, "_plugin_activity_changed"); diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h index aacbd05dd4..310cab699f 100644 --- a/editor/editor_plugin_settings.h +++ b/editor/editor_plugin_settings.h @@ -31,6 +31,7 @@ #ifndef EDITORPLUGINSETTINGS_H #define EDITORPLUGINSETTINGS_H +#include "editor/plugin_config_dialog.h"; #include "editor_data.h" #include "property_editor.h" #include "scene/gui/dialogs.h" @@ -40,11 +41,19 @@ class EditorPluginSettings : public VBoxContainer { GDCLASS(EditorPluginSettings, VBoxContainer); + enum { + BUTTON_PLUGIN_EDIT + }; + + PluginConfigDialog *plugin_config_dialog; + Button *create_plugin; Button *update_list; Tree *plugin_list; bool updating; void _plugin_activity_changed(); + void _create_clicked(); + void _cell_button_pressed(Object *p_item, int p_column, int p_id); protected: void _notification(int p_what); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 83a3662f21..0cbd5f0bff 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -46,11 +46,22 @@ EditorPropertyNil::EditorPropertyNil() { } ///////////////////// TEXT ///////////////////////// + +void EditorPropertyText::_text_entered(const String &p_string) { + if (updating) + return; + + if (text->has_focus()) { + text->release_focus(); + _text_changed(p_string); + } +} + void EditorPropertyText::_text_changed(const String &p_string) { if (updating) return; - emit_signal("property_changed", get_edited_property(), p_string, true); + emit_signal("property_changed", get_edited_property(), p_string); } void EditorPropertyText::update_property() { @@ -64,6 +75,7 @@ void EditorPropertyText::update_property() { void EditorPropertyText::_bind_methods() { ClassDB::bind_method(D_METHOD("_text_changed", "txt"), &EditorPropertyText::_text_changed); + ClassDB::bind_method(D_METHOD("_text_entered", "txt"), &EditorPropertyText::_text_entered); } EditorPropertyText::EditorPropertyText() { @@ -71,6 +83,8 @@ EditorPropertyText::EditorPropertyText() { add_child(text); add_focusable(text); text->connect("text_changed", this, "_text_changed"); + text->connect("text_entered", this, "_text_entered"); + updating = false; } @@ -78,12 +92,12 @@ EditorPropertyText::EditorPropertyText() { void EditorPropertyMultilineText::_big_text_changed() { text->set_text(big_text->get_text()); - emit_signal("property_changed", get_edited_property(), big_text->get_text(), true); + emit_signal("property_changed", get_edited_property(), big_text->get_text()); } void EditorPropertyMultilineText::_text_changed() { - emit_signal("property_changed", get_edited_property(), text->get_text(), true); + emit_signal("property_changed", get_edited_property(), text->get_text()); } void EditorPropertyMultilineText::_open_big_text() { @@ -2038,7 +2052,7 @@ void EditorPropertyResource::_menu_option(int p_which) { ERR_BREAK(!resp); if (get_edited_object() && base_type != String() && base_type == "Script") { //make visual script the right type - res->call("set_instance_base_type", get_edited_object()->get_class()); + resp->call("set_instance_base_type", get_edited_object()->get_class()); } res = Ref<Resource>(resp); @@ -2240,7 +2254,7 @@ void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) { void EditorPropertyResource::_open_editor_pressed() { RES res = get_edited_object()->get(get_edited_property()); if (res.is_valid()) { - EditorNode::get_singleton()->edit_resource(res.ptr()); + EditorNode::get_singleton()->edit_item(res.ptr()); } } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index ccd73d2539..d5fac9c1a0 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -54,6 +54,7 @@ class EditorPropertyText : public EditorProperty { bool updating; void _text_changed(const String &p_string); + void _text_entered(const String &p_string); protected: static void _bind_methods(); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 2bd28170e7..8203c85c6a 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -210,8 +210,8 @@ void EditorPropertyArray::update_property() { default: {} } - if (!array.is_array()) { - edit->set_text(arrtype + "[" + Variant::get_type_name(array.get_type()) + "]"); + if (array.get_type() == Variant::NIL) { + edit->set_text(String("(Nil) ") + arrtype); edit->set_pressed(false); if (vbox) { memdelete(vbox); @@ -219,7 +219,7 @@ void EditorPropertyArray::update_property() { return; } - edit->set_text(arrtype + "[" + itos(array.call("size")) + "]"); + edit->set_text(arrtype + "(size " + itos(array.call("size")) + ")"); #ifdef TOOLS_ENABLED @@ -613,7 +613,13 @@ void EditorPropertyDictionary::_change_type(Object *p_button, int p_index) { void EditorPropertyDictionary::_add_key_value() { + // Do not allow nil as valid key. I experienced errors with this + if (object->get_new_item_key().get_type() == Variant::NIL) { + return; + } + Dictionary dict = object->get_dict(); + dict[object->get_new_item_key()] = object->get_new_item_value(); object->set_new_item_key(Variant()); object->set_new_item_value(Variant()); @@ -663,9 +669,20 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) { void EditorPropertyDictionary::update_property() { - Dictionary dict = get_edited_object()->get(get_edited_property()); + Variant updated_val = get_edited_object()->get(get_edited_property()); + + if (updated_val.get_type() == Variant::NIL) { + edit->set_text("Dictionary (Nil)"); //This provides symmetry with the array property. + edit->set_pressed(false); + if (vbox) { + memdelete(vbox); + } + return; + } + + Dictionary dict = updated_val; - edit->set_text("Dict[" + itos(dict.size()) + "]"); + edit->set_text("Dictionary (size " + itos(dict.size()) + ")"); #ifdef TOOLS_ENABLED @@ -695,9 +712,9 @@ void EditorPropertyDictionary::update_property() { page->set_h_size_flags(SIZE_EXPAND_FILL); page->connect("value_changed", this, "_page_changed"); } else { - //bye bye children of the box - while (vbox->get_child_count() > 1) { - memdelete(vbox->get_child(1)); + // Queue childs for deletion, delete immediately might cause errors. + for (size_t i = 1; i < vbox->get_child_count(); i++) { + vbox->get_child(i)->queue_delete(); } } @@ -941,10 +958,10 @@ void EditorPropertyDictionary::update_property() { prop->update_property(); if (i == amount + 1) { - Button *add_item = memnew(Button); - add_item->set_text(TTR("Add Key/Value Pair")); - add_vbox->add_child(add_item); - add_item->connect("pressed", this, "_add_key_value"); + Button *butt_add_item = memnew(Button); + butt_add_item->set_text(TTR("Add Key/Value Pair")); + butt_add_item->connect("pressed", this, "_add_key_value"); + add_vbox->add_child(butt_add_item); } } @@ -965,8 +982,16 @@ void EditorPropertyDictionary::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { } } + void EditorPropertyDictionary::_edit_pressed() { + Variant prop_val = get_edited_object()->get(get_edited_property()); + if (prop_val.get_type() == Variant::NIL) { + Variant::CallError ce; + prop_val = Variant::construct(Variant::DICTIONARY, NULL, 0, ce); + get_edited_object()->set(get_edited_property(), prop_val); + } + get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed()); update_property(); } diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index a14ced1340..d24816ee02 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -511,6 +511,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("filesystem/file_dialog/thumbnail_size", 64); hints["filesystem/file_dialog/thumbnail_size"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16"); + _initial_set("docks/filesystem/disable_split", false); + _initial_set("docks/filesystem/split_mode_minimum_height", 600); _initial_set("docks/filesystem/display_mode", 0); hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"); _initial_set("docks/filesystem/thumbnail_size", 64); @@ -755,7 +757,7 @@ void EditorSettings::create() { } if (dir->change_dir(data_dir) != OK) { - dir->make_dir(data_dir); + dir->make_dir_recursive(data_dir); if (dir->change_dir(data_dir) != OK) { ERR_PRINT("Cannot create data directory!"); memdelete(dir); @@ -771,14 +773,8 @@ void EditorSettings::create() { // Validate/create cache dir - if (dir->change_dir(cache_path) != OK) { - ERR_PRINT("Cannot find path for cache directory!"); - memdelete(dir); - goto fail; - } - if (dir->change_dir(cache_dir) != OK) { - dir->make_dir(cache_dir); + dir->make_dir_recursive(cache_dir); if (dir->change_dir(cache_dir) != OK) { ERR_PRINT("Cannot create cache directory!"); memdelete(dir); @@ -788,14 +784,8 @@ void EditorSettings::create() { // Validate/create config dir and subdirectories - if (dir->change_dir(config_path) != OK) { - ERR_PRINT("Cannot find path for config directory!"); - memdelete(dir); - goto fail; - } - if (dir->change_dir(config_dir) != OK) { - dir->make_dir(config_dir); + dir->make_dir_recursive(config_dir); if (dir->change_dir(config_dir) != OK) { ERR_PRINT("Cannot create config directory!"); memdelete(dir); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 76fc7fd0cd..69a013dd00 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -173,9 +173,9 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = const Color error_color = p_theme->get_color("error_color", "Editor"); const Color success_color = p_theme->get_color("success_color", "Editor"); const Color warning_color = p_theme->get_color("warning_color", "Editor"); - dark_icon_color_dictionary[Color::html("#ff5d5d")] = error_color; + dark_icon_color_dictionary[Color::html("#ff0000")] = error_color; dark_icon_color_dictionary[Color::html("#45ff8b")] = success_color; - dark_icon_color_dictionary[Color::html("#ffdd65")] = warning_color; + dark_icon_color_dictionary[Color::html("#dbab09")] = warning_color; List<String> exceptions; exceptions.push_back("EditorPivot"); @@ -365,13 +365,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("mono_color", "Editor", mono_color); Color success_color = accent_color.linear_interpolate(Color(0.2, 1, 0.2), 0.6) * 1.2; - Color warning_color = accent_color.linear_interpolate(Color(1, 1, 0), 0.7) * 1.2; + Color warning_color = accent_color.linear_interpolate(Color(1, 1, 0), 0.7) * 1.0; Color error_color = accent_color.linear_interpolate(Color(1, 0, 0), 0.8) * 1.7; Color property_color = font_color.linear_interpolate(Color(0.5, 0.5, 0.5), 0.5); if (!dark_theme) { // yellow on white themes is a P.I.T.A. - warning_color = accent_color.linear_interpolate(Color(1, 0.8, 0), 0.9); + warning_color = accent_color.linear_interpolate(Color(0.9, 0.7, 0), 0.9); warning_color = warning_color.linear_interpolate(mono_color, 0.2); success_color = success_color.linear_interpolate(mono_color, 0.2); error_color = error_color.linear_interpolate(mono_color, 0.2); diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 931785333f..6c9d1568fa 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -178,7 +178,7 @@ void ExportTemplateManager::_uninstall_template_confirm() { _update_template_list(); } -void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_progress) { +bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_progress) { FileAccess *fa = NULL; zlib_filefunc_def io = zipio_create_io_from_file(&fa); @@ -187,7 +187,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ if (!pkg) { EditorNode::get_singleton()->show_warning(TTR("Can't open export templates zip.")); - return; + return false; } int ret = unzGoToFirstFile(pkg); @@ -221,7 +221,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ if (data_str.get_slice_count(".") < 3) { EditorNode::get_singleton()->show_warning(vformat(TTR("Invalid version.txt format inside templates: %s."), data_str)); unzClose(pkg); - return; + return false; } version = data_str; @@ -237,7 +237,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ if (version == String()) { EditorNode::get_singleton()->show_warning(TTR("No version.txt found inside templates.")); unzClose(pkg); - return; + return false; } String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version); @@ -247,7 +247,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ if (err != OK) { EditorNode::get_singleton()->show_warning(TTR("Error creating path for templates:") + "\n" + template_path); unzClose(pkg); - return; + return false; } memdelete(d); @@ -310,6 +310,8 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ unzClose(pkg); _update_template_list(); + + return true; } void ExportTemplateManager::popup_manager() { @@ -401,7 +403,15 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int String path = download_templates->get_download_file(); template_list_state->set_text(TTR("Download Complete.")); template_downloader->hide(); - _install_from_file(path, false); + int ret = _install_from_file(path, false); + if (ret) { + Error err = OS::get_singleton()->move_to_trash(path); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:") + "\n" + path + "\n"); + } + } else { + WARN_PRINTS(vformat(TTR("Templates installation failed. The problematic templates archives can be found at '%s'."), path)); + } } } break; } diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h index 54a645c69f..bd43fe5dc5 100644 --- a/editor/export_template_manager.h +++ b/editor/export_template_manager.h @@ -70,7 +70,7 @@ class ExportTemplateManager : public ConfirmationDialog { void _uninstall_template_confirm(); virtual void ok_pressed(); - void _install_from_file(const String &p_file, bool p_use_progress = true); + bool _install_from_file(const String &p_file, bool p_use_progress = true); void _http_download_mirror_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data); void _http_download_templates_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 7b8a7afa87..ec1153a015 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -139,41 +139,56 @@ void FileSystemDock::_update_tree(bool keep_collapse_state, bool p_uncollapse_ro updating_tree = false; } -void FileSystemDock::_notification(int p_what) { +void FileSystemDock::_update_display_mode() { - switch (p_what) { + bool disable_split = bool(EditorSettings::get_singleton()->get("docks/filesystem/disable_split")); + bool compact_mode = get_size().height < int(EditorSettings::get_singleton()->get("docks/filesystem/split_mode_minimum_height")); + DisplayMode new_mode; + if (disable_split || compact_mode) { + new_mode = file_list_view ? DISPLAY_FILE_LIST_ONLY : DISPLAY_TREE_ONLY; + } else { + new_mode = DISPLAY_SPLIT; + } - case NOTIFICATION_RESIZED: { + if (new_mode != display_mode) { + switch (new_mode) { + case DISPLAY_TREE_ONLY: + tree->show(); + tree->set_v_size_flags(SIZE_EXPAND_FILL); + _update_tree(true); - bool new_mode = get_size().height < get_viewport_rect().size.height / 2; + file_list_vb->hide(); + break; - if (new_mode != low_height_mode) { + case DISPLAY_FILE_LIST_ONLY: + tree->hide(); + button_tree->show(); - low_height_mode = new_mode; + file_list_vb->show(); + _update_files(true); + break; - if (low_height_mode) { + case DISPLAY_SPLIT: + tree->show(); + tree->set_v_size_flags(SIZE_EXPAND_FILL); + button_tree->hide(); + tree->ensure_cursor_is_visible(); + _update_tree(true); - tree->hide(); - tree->set_v_size_flags(SIZE_EXPAND_FILL); - button_tree->show(); - } else { + file_list_vb->show(); + _update_files(true); + break; + } + display_mode = new_mode; + } +} - tree->set_v_size_flags(SIZE_FILL); - button_tree->hide(); - if (!tree->is_visible()) { - tree->show(); - button_favorite->show(); - _update_tree(true); - } - tree->ensure_cursor_is_visible(); +void FileSystemDock::_notification(int p_what) { - if (!file_list_vb->is_visible()) { - file_list_vb->show(); - _update_files(true); - } - } - } + switch (p_what) { + case NOTIFICATION_RESIZED: { + _update_display_mode(); } break; case NOTIFICATION_ENTER_TREE: { @@ -190,8 +205,8 @@ void FileSystemDock::_notification(int p_what) { //button_instance->set_icon(get_icon("Add", ei)); //button_open->set_icon(get_icon("Folder", ei)); button_tree->set_icon(get_icon("Filesystem", ei)); - _update_file_display_toggle_button(); - button_display_mode->connect("pressed", this, "_change_file_display"); + _update_file_list_display_mode_button(); + button_file_list_display_mode->connect("pressed", this, "_change_file_display"); //file_options->set_icon( get_icon("Tools","ei")); files->connect("item_activated", this, "_select_file"); button_hist_next->connect("pressed", this, "_fw_history"); @@ -208,6 +223,8 @@ void FileSystemDock::_notification(int p_what) { button_tree->connect("pressed", this, "_go_to_tree", varray(), CONNECT_DEFERRED); current_path->connect("text_entered", this, "navigate_to_path"); + _update_display_mode(); + if (EditorFileSystem::get_singleton()->is_scanning()) { _set_scanning_mode(); } else { @@ -241,12 +258,8 @@ void FileSystemDock::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - + // Update icons String ei = "EditorIcons"; - int new_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")); - - //_update_icons - button_reload->set_icon(get_icon("Reload", ei)); button_favorite->set_icon(get_icon("Favorites", ei)); button_tree->set_icon(get_icon("Filesystem", ei)); @@ -256,14 +269,18 @@ void FileSystemDock::_notification(int p_what) { search_box->set_right_icon(get_icon("Search", ei)); search_box->set_clear_button_enabled(true); - if (new_mode != display_mode) { - set_display_mode(new_mode); + // Change size mode + int new_file_list_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")); + if (new_file_list_mode != file_list_display_mode) { + set_file_list_display_mode(new_file_list_mode); } else { - _update_file_display_toggle_button(); + _update_file_list_display_mode_button(); _update_files(true); } - _update_tree(true); + // Change full tree mode + _update_display_mode(); + } break; } } @@ -289,7 +306,7 @@ void FileSystemDock::_dir_selected() { current_path->set_text(path); _push_to_history(); - if (!low_height_mode) { + if (display_mode == DISPLAY_SPLIT) { _update_files(false); } } @@ -360,7 +377,7 @@ void FileSystemDock::navigate_to_path(const String &p_path) { current_path->set_text(path); _push_to_history(); - if (!low_height_mode) { + if (display_mode == DISPLAY_SPLIT) { _update_tree(true); _update_files(false); } else { @@ -390,24 +407,24 @@ void FileSystemDock::_thumbnail_done(const String &p_path, const Ref<Texture> &p } } -void FileSystemDock::_update_file_display_toggle_button() { +void FileSystemDock::_update_file_list_display_mode_button() { - if (button_display_mode->is_pressed()) { - display_mode = DISPLAY_LIST; - button_display_mode->set_icon(get_icon("FileThumbnail", "EditorIcons")); - button_display_mode->set_tooltip(TTR("View items as a grid of thumbnails.")); + if (button_file_list_display_mode->is_pressed()) { + file_list_display_mode = FILE_LIST_DISPLAY_LIST; + button_file_list_display_mode->set_icon(get_icon("FileThumbnail", "EditorIcons")); + button_file_list_display_mode->set_tooltip(TTR("View items as a grid of thumbnails.")); } else { - display_mode = DISPLAY_THUMBNAILS; - button_display_mode->set_icon(get_icon("FileList", "EditorIcons")); - button_display_mode->set_tooltip(TTR("View items as a list.")); + file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; + button_file_list_display_mode->set_icon(get_icon("FileList", "EditorIcons")); + button_file_list_display_mode->set_tooltip(TTR("View items as a list.")); } } void FileSystemDock::_change_file_display() { - _update_file_display_toggle_button(); + _update_file_list_display_mode_button(); - EditorSettings::get_singleton()->set("docks/filesystem/display_mode", display_mode); + EditorSettings::get_singleton()->set("docks/filesystem/display_mode", file_list_display_mode); _update_files(true); } @@ -472,8 +489,8 @@ void FileSystemDock::_update_files(bool p_keep_selection) { bool always_show_folders = EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"); - bool use_thumbnails = (display_mode == DISPLAY_THUMBNAILS); - bool use_folders = search_box->get_text().length() == 0 && (low_height_mode || always_show_folders); + bool use_thumbnails = (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS); + bool use_folders = search_box->get_text().length() == 0 && ((display_mode == DISPLAY_FILE_LIST_ONLY || display_mode == DISPLAY_TREE_ONLY) || always_show_folders); if (use_thumbnails) { @@ -617,24 +634,28 @@ void FileSystemDock::_select_file(int p_idx) { } } -void FileSystemDock::_go_to_tree() { +void FileSystemDock::_go_to_file_list() { - if (low_height_mode) { - tree->show(); - button_favorite->show(); - file_list_vb->hide(); + if (display_mode == DISPLAY_TREE_ONLY) { + file_list_view = true; + _update_display_mode(); + } else { + bool collapsed = tree->get_selected()->is_collapsed(); + tree->get_selected()->set_collapsed(!collapsed); + _update_files(false); } +} +void FileSystemDock::_go_to_tree() { - _update_tree(true); + file_list_view = false; tree->grab_focus(); + _update_display_mode(); tree->ensure_cursor_is_visible(); - //button_open->hide(); - //file_options->hide(); } void FileSystemDock::_preview_invalidated(const String &p_path) { - if (display_mode == DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) { + if (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) { for (int i = 0; i < files->get_item_count(); i++) { @@ -1413,24 +1434,6 @@ void FileSystemDock::_resource_created() const { editor->save_resource_as(current_res, path); } -void FileSystemDock::_go_to_file_list() { - - if (low_height_mode) { - tree->hide(); - file_list_vb->show(); - button_favorite->hide(); - } else { - bool collapsed = tree->get_selected()->is_collapsed(); - tree->get_selected()->set_collapsed(!collapsed); - } - - //file_options->show(); - - _update_files(false); - - //emit_signal("open",path); -} - void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) { folder_options->clear(); folder_options->set_size(Size2(1, 1)); @@ -1450,7 +1453,7 @@ void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) { } folder_options->add_separator(); folder_options->add_item(TTR("New Folder..."), FOLDER_NEW_FOLDER); - folder_options->add_item(TTR("Show In File Manager"), FOLDER_SHOW_IN_EXPLORER); + folder_options->add_item(TTR("Open In File Manager"), FOLDER_SHOW_IN_EXPLORER); } folder_options->set_position(tree->get_global_position() + p_pos); folder_options->popup(); @@ -1474,7 +1477,7 @@ void FileSystemDock::fix_dependencies(const String &p_for_file) { void FileSystemDock::focus_on_filter() { - if (low_height_mode && tree->is_visible()) { + if (display_mode == DISPLAY_FILE_LIST_ONLY && tree->is_visible()) { // Tree mode, switch to files list with search box tree->hide(); file_list_vb->show(); @@ -1484,12 +1487,12 @@ void FileSystemDock::focus_on_filter() { search_box->grab_focus(); } -void FileSystemDock::set_display_mode(int p_mode) { +void FileSystemDock::set_file_list_display_mode(int p_mode) { - if (p_mode == display_mode) + if (p_mode == file_list_display_mode) return; - button_display_mode->set_pressed(p_mode == DISPLAY_LIST); + button_file_list_display_mode->set_pressed(p_mode == FILE_LIST_DISPLAY_LIST); _change_file_display(); } @@ -1759,7 +1762,10 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) { file_options->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); file_options->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); file_options->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); - file_options->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER); + + String fpath = files->get_item_metadata(p_item); + String item_text = fpath.ends_with("/") ? TTR("Open In File Manager") : TTR("Show In File Manager"); + file_options->add_item(item_text, FILE_SHOW_IN_EXPLORER); file_options->set_position(files->get_global_position() + p_pos); file_options->popup(); @@ -2027,9 +2033,9 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { search_box->connect("text_changed", this, "_search_changed"); path_hb->add_child(search_box); - button_display_mode = memnew(ToolButton); - button_display_mode->set_toggle_mode(true); - path_hb->add_child(button_display_mode); + button_file_list_display_mode = memnew(ToolButton); + button_file_list_display_mode->set_toggle_mode(true); + path_hb->add_child(button_file_list_display_mode); files = memnew(ItemList); files->set_v_size_flags(SIZE_EXPAND_FILL); @@ -2125,8 +2131,8 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { history_max_size = 20; history.push_back("res://"); - low_height_mode = false; - display_mode = DISPLAY_THUMBNAILS; + display_mode = DISPLAY_SPLIT; + file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; } FileSystemDock::~FileSystemDock() { diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 6a0c73d52e..fbbe87fc16 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -60,12 +60,18 @@ class FileSystemDock : public VBoxContainer { GDCLASS(FileSystemDock, VBoxContainer); public: - enum DisplayMode { - DISPLAY_THUMBNAILS, - DISPLAY_LIST + enum FileListDisplayMode { + FILE_LIST_DISPLAY_THUMBNAILS, + FILE_LIST_DISPLAY_LIST }; private: + enum DisplayMode { + DISPLAY_TREE_ONLY, + DISPLAY_FILE_LIST_ONLY, + DISPLAY_SPLIT, + }; + enum FileMenu { FILE_OPEN, FILE_INSTANCE, @@ -106,7 +112,7 @@ private: Button *button_reload; Button *button_favorite; Button *button_tree; - Button *button_display_mode; + Button *button_file_list_display_mode; Button *button_hist_next; Button *button_hist_prev; Button *button_show; @@ -115,8 +121,9 @@ private: TextureRect *search_icon; HBoxContainer *path_hb; - bool low_height_mode; + FileListDisplayMode file_list_display_mode; DisplayMode display_mode; + bool file_list_view; PopupMenu *file_options; PopupMenu *folder_options; @@ -172,7 +179,7 @@ private: void _files_gui_input(Ref<InputEvent> p_event); void _update_files(bool p_keep_selection); - void _update_file_display_toggle_button(); + void _update_file_list_display_mode_button(); void _change_file_display(); void _fs_changed(); @@ -245,6 +252,8 @@ private: void _preview_invalidated(const String &p_path); void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata); + void _update_display_mode(); + protected: void _notification(int p_what); static void _bind_methods(); @@ -258,7 +267,7 @@ public: void fix_dependencies(const String &p_for_file); - void set_display_mode(int p_mode); + void set_file_list_display_mode(int p_mode); int get_split_offset() { return split_box->get_split_offset(); } void set_split_offset(int p_offset) { split_box->set_split_offset(p_offset); } diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp new file mode 100644 index 0000000000..418936ac9f --- /dev/null +++ b/editor/plugin_config_dialog.cpp @@ -0,0 +1,230 @@ +/*************************************************************************/ +/* plugin_config_dialog.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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. */ +/*************************************************************************/ + +#include "plugin_config_dialog.h" +#include "core/io/config_file.h" +#include "core/os/dir_access.h" +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "modules/gdscript/gdscript.h" +#include "scene/gui/grid_container.h" + +void PluginConfigDialog::_clear_fields() { + name_edit->set_text(""); + subfolder_edit->set_text(""); + desc_edit->set_text(""); + author_edit->set_text(""); + version_edit->set_text(""); + script_edit->set_text(""); +} + +void PluginConfigDialog::_on_confirmed() { + + String path = "res://addons/" + subfolder_edit->get_text(); + + if (!_edit_mode) { + DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (!d || d->make_dir_recursive(path) != OK) + return; + } + + Ref<ConfigFile> cf = memnew(ConfigFile); + cf->set_value("plugin", "name", name_edit->get_text()); + cf->set_value("plugin", "description", desc_edit->get_text()); + cf->set_value("plugin", "author", author_edit->get_text()); + cf->set_value("plugin", "version", version_edit->get_text()); + cf->set_value("plugin", "script", script_edit->get_text()); + + cf->save(path.plus_file("plugin.cfg")); + + if (!_edit_mode) { + String type = script_option_edit->get_item_text(script_option_edit->get_selected()); + + Ref<Script> script; + + if (type == GDScriptLanguage::get_singleton()->get_name()) { + Ref<GDScript> gdscript = memnew(GDScript); + gdscript->set_source_code( + "tool\n" + "extends EditorPlugin\n" + "\n" + "func _enter_tree():\n" + "\tpass"); + String script_path = path.plus_file(script_edit->get_text()); + gdscript->set_path(script_path); + ResourceSaver::save(script_path, gdscript); + script = gdscript; + } + //TODO: other languages + + emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? name_edit->get_text() : ""); + } else { + EditorNode::get_singleton()->get_project_settings()->update_plugins(); + } + _clear_fields(); +} + +void PluginConfigDialog::_on_cancelled() { + _clear_fields(); +} + +void PluginConfigDialog::_on_required_text_changed(const String &p_text) { + String ext = script_option_edit->get_item_metadata(script_option_edit->get_selected()); + get_ok()->set_disabled(script_edit->get_text().get_basename().empty() || script_edit->get_text().get_extension() != ext || name_edit->get_text().empty()); +} + +void PluginConfigDialog::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + connect("confirmed", this, "_on_confirmed"); + get_cancel()->connect("pressed", this, "_on_cancelled"); + } break; + } +} + +void PluginConfigDialog::config(const String &p_config_path) { + if (p_config_path.length()) { + Ref<ConfigFile> cf = memnew(ConfigFile); + print_line(p_config_path); + cf->load(p_config_path); + + name_edit->set_text(cf->get_value("plugin", "name", "")); + subfolder_edit->set_text(p_config_path.get_base_dir().get_basename().get_file()); + desc_edit->set_text(cf->get_value("plugin", "description", "")); + author_edit->set_text(cf->get_value("plugin", "author", "")); + version_edit->set_text(cf->get_value("plugin", "version", "")); + script_edit->set_text(cf->get_value("plugin", "script", "")); + + _edit_mode = true; + active_edit->hide(); + Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 1))->hide(); + subfolder_edit->hide(); + Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 1))->hide(); + set_title(TTR("Edit a Plugin")); + } else { + _clear_fields(); + _edit_mode = false; + active_edit->show(); + Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 1))->show(); + subfolder_edit->show(); + Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 1))->show(); + set_title(TTR("Create a Plugin")); + } + get_ok()->set_disabled(!_edit_mode); + get_ok()->set_text(_edit_mode ? TTR("Update") : TTR("Create")); +} + +void PluginConfigDialog::_bind_methods() { + ClassDB::bind_method("_on_required_text_changed", &PluginConfigDialog::_on_required_text_changed); + ClassDB::bind_method("_on_confirmed", &PluginConfigDialog::_on_confirmed); + ClassDB::bind_method("_on_cancelled", &PluginConfigDialog::_on_cancelled); + ADD_SIGNAL(MethodInfo("plugin_ready", PropertyInfo(Variant::STRING, "script_path", PROPERTY_HINT_NONE, ""), PropertyInfo(Variant::STRING, "activate_name"))); +} + +PluginConfigDialog::PluginConfigDialog() { + get_ok()->set_disabled(true); + set_hide_on_ok(true); + + GridContainer *grid = memnew(GridContainer); + grid->set_columns(2); + add_child(grid); + + Label *name_lb = memnew(Label); + name_lb->set_text(TTR("Plugin Name:")); + grid->add_child(name_lb); + + name_edit = memnew(LineEdit); + name_edit->connect("text_changed", this, "_on_required_text_changed"); + name_edit->set_placeholder("MyPlugin"); + grid->add_child(name_edit); + + Label *subfolder_lb = memnew(Label); + subfolder_lb->set_text(TTR("Subfolder:")); + grid->add_child(subfolder_lb); + + subfolder_edit = memnew(LineEdit); + subfolder_edit->set_placeholder("\"my_plugin\" -> res://addons/my_plugin"); + grid->add_child(subfolder_edit); + + Label *desc_lb = memnew(Label); + desc_lb->set_text(TTR("Description:")); + grid->add_child(desc_lb); + + desc_edit = memnew(TextEdit); + desc_edit->set_custom_minimum_size(Size2(400.0f, 50.0f)); + grid->add_child(desc_edit); + + Label *author_lb = memnew(Label); + author_lb->set_text(TTR("Author:")); + grid->add_child(author_lb); + + author_edit = memnew(LineEdit); + author_edit->set_placeholder("Godette"); + grid->add_child(author_edit); + + Label *version_lb = memnew(Label); + version_lb->set_text(TTR("Version:")); + grid->add_child(version_lb); + + version_edit = memnew(LineEdit); + version_edit->set_placeholder("1.0"); + grid->add_child(version_edit); + + Label *script_option_lb = memnew(Label); + script_option_lb->set_text(TTR("Language:")); + grid->add_child(script_option_lb); + + script_option_edit = memnew(OptionButton); + script_option_edit->add_item(GDScriptLanguage::get_singleton()->get_name()); + script_option_edit->set_item_metadata(0, GDScriptLanguage::get_singleton()->get_extension()); + script_option_edit->select(0); + //TODO: add other languages + grid->add_child(script_option_edit); + + Label *script_lb = memnew(Label); + script_lb->set_text(TTR("Script Name:")); + grid->add_child(script_lb); + + script_edit = memnew(LineEdit); + script_edit->connect("text_changed", this, "_on_required_text_changed"); + script_edit->set_placeholder("\"plugin.gd\" -> res://addons/my_plugin/plugin.gd"); + grid->add_child(script_edit); + + Label *active_lb = memnew(Label); + active_lb->set_text(TTR("Activate now?")); + grid->add_child(active_lb); + + active_edit = memnew(CheckBox); + active_edit->set_pressed(true); + grid->add_child(active_edit); +} + +PluginConfigDialog::~PluginConfigDialog() { +} diff --git a/editor/plugin_config_dialog.h b/editor/plugin_config_dialog.h new file mode 100644 index 0000000000..2d321a479d --- /dev/null +++ b/editor/plugin_config_dialog.h @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* plugin_config_dialog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 PLUGIN_CONFIG_DIALOG_H +#define PLUGIN_CONFIG_DIALOG_H + +#include "scene/gui/check_box.h" +#include "scene/gui/dialogs.h" +#include "scene/gui/line_edit.h" +#include "scene/gui/option_button.h" +#include "scene/gui/text_edit.h" + +class PluginConfigDialog : public ConfirmationDialog { + + GDCLASS(PluginConfigDialog, ConfirmationDialog); + + LineEdit *name_edit; + LineEdit *subfolder_edit; + TextEdit *desc_edit; + LineEdit *author_edit; + LineEdit *version_edit; + OptionButton *script_option_edit; + LineEdit *script_edit; + CheckBox *active_edit; + + bool _edit_mode; + + void _clear_fields(); + void _on_confirmed(); + void _on_cancelled(); + void _on_required_text_changed(const String &p_text); + +protected: + virtual void _notification(int p_what); + static void _bind_methods(); + +public: + void config(const String &p_plugin_dir_name); + + PluginConfigDialog(); + ~PluginConfigDialog(); +}; + +#endif // PLUGIN_CONFIG_DIALOG_H diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index ddd84aa563..4ed2b051aa 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -384,14 +384,11 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int return; } - progress->set_max(download->get_body_size()); - progress->set_value(download->get_downloaded_bytes()); - install->set_disabled(false); + status->set_text(TTR("Success!")); + // Make the progress bar invisible but don't reflow other Controls around it + progress->set_modulate(Color(0, 0, 0, 0)); - progress->set_value(download->get_downloaded_bytes()); - - status->set_text(TTR("Success!") + " (" + String::humanize_size(download->get_downloaded_bytes()) + ")"); set_process(false); } @@ -413,25 +410,37 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) { if (p_what == NOTIFICATION_PROCESS) { - progress->set_max(download->get_body_size()); - progress->set_value(download->get_downloaded_bytes()); + // Make the progress bar visible again when retrying the download + progress->set_modulate(Color(1, 1, 1, 1)); + + if (download->get_downloaded_bytes() > 0) { + progress->set_max(download->get_body_size()); + progress->set_value(download->get_downloaded_bytes()); + } int cstatus = download->get_http_client_status(); - if (cstatus == HTTPClient::STATUS_BODY) - status->set_text(TTR("Fetching:") + " " + String::humanize_size(download->get_downloaded_bytes())); + if (cstatus == HTTPClient::STATUS_BODY) { + status->set_text(vformat(TTR("Downloading (%s / %s)..."), String::humanize_size(download->get_downloaded_bytes()), String::humanize_size(download->get_body_size()))); + } if (cstatus != prev_status) { switch (cstatus) { case HTTPClient::STATUS_RESOLVING: { status->set_text(TTR("Resolving...")); + progress->set_max(1); + progress->set_value(0); } break; case HTTPClient::STATUS_CONNECTING: { status->set_text(TTR("Connecting...")); + progress->set_max(1); + progress->set_value(0); } break; case HTTPClient::STATUS_REQUESTING: { status->set_text(TTR("Requesting...")); + progress->set_max(1); + progress->set_value(0); } break; default: {} } @@ -527,7 +536,7 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { hb2->add_child(retry); hb2->add_child(install); - set_custom_minimum_size(Size2(250, 0)); + set_custom_minimum_size(Size2(310, 0)); download = memnew(HTTPRequest); add_child(download); diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index c2b17189ef..b50e0dfe88 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -68,6 +68,11 @@ void Particles2DEditorPlugin::_menu_callback(int p_idx) { switch (p_idx) { case MENU_GENERATE_VISIBILITY_RECT: { + float gen_time = particles->get_lifetime(); + if (gen_time < 1.0) + generate_seconds->set_value(1.0); + else + generate_seconds->set_value(trunc(gen_time) + 1.0); generate_aabb->popup_centered_minsize(); } break; case MENU_LOAD_EMISSION_MASK: { @@ -90,6 +95,12 @@ void Particles2DEditorPlugin::_generate_visibility_rect() { EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time)); + bool was_emitting = particles->is_emitting(); + if (!was_emitting) { + particles->set_emitting(true); + OS::get_singleton()->delay_usec(1000); + } + Rect2 rect; while (running < time) { @@ -106,6 +117,10 @@ void Particles2DEditorPlugin::_generate_visibility_rect() { running += (OS::get_singleton()->get_ticks_usec() - ticks) / 1000000.0; } + if (!was_emitting) { + particles->set_emitting(false); + } + particles->set_visibility_rect(rect); } diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 1f5a4a8a36..6a99dcb9a5 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -270,6 +270,12 @@ void ParticlesEditor::_menu_option(int p_option) { switch (p_option) { case MENU_OPTION_GENERATE_AABB: { + float gen_time = node->get_lifetime(); + + if (gen_time < 1.0) + generate_seconds->set_value(1.0); + else + generate_seconds->set_value(trunc(gen_time) + 1.0); generate_aabb->popup_centered_minsize(); } break; case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: { @@ -323,7 +329,14 @@ void ParticlesEditor::_generate_aabb() { EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time)); + bool was_emitting = node->is_emitting(); + if (!was_emitting) { + node->set_emitting(true); + OS::get_singleton()->delay_usec(1000); + } + AABB rect; + while (running < time) { uint64_t ticks = OS::get_singleton()->get_ticks_usec(); @@ -339,6 +352,10 @@ void ParticlesEditor::_generate_aabb() { running += (OS::get_singleton()->get_ticks_usec() - ticks) / 1000000.0; } + if (!was_emitting) { + node->set_emitting(false); + } + node->set_visibility_aabb(rect); } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 7d72537e32..1bb7c98114 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -842,6 +842,19 @@ bool ScriptEditor::_test_script_times_on_disk(RES p_for_script) { void ScriptEditor::_file_dialog_action(String p_file) { switch (file_dialog_option) { + case FILE_NEW_TEXTFILE: { + Error err; + FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err); + if (err) { + memdelete(file); + editor->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!")); + break; + } + file->close(); + memdelete(file); + + // fallthrough to open the file. + } case FILE_OPEN: { List<String> extensions; @@ -870,7 +883,7 @@ void ScriptEditor::_file_dialog_action(String p_file) { file_dialog_option = -1; return; } - } + } break; case FILE_SAVE_AS: { ScriptEditorBase *current = _get_current_editor(); @@ -929,6 +942,15 @@ void ScriptEditor::_menu_option(int p_option) { script_create_dialog->config("Node", ".gd"); script_create_dialog->popup_centered(Size2(300, 300) * EDSCALE); } break; + case FILE_NEW_TEXTFILE: { + file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); + file_dialog_option = FILE_NEW_TEXTFILE; + + file_dialog->clear_filters(); + file_dialog->popup_centered_ratio(); + file_dialog->set_title(TTR("New TextFile...")); + } break; case FILE_OPEN: { file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); @@ -1937,7 +1959,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra if (!se) continue; - if (se->get_edited_resource() == p_resource) { + if ((script != NULL && se->get_edited_resource() == p_resource) || se->get_edited_resource()->get_path() == p_resource->get_path()) { if (should_open) { if (tab_container->get_current_tab() != i) { @@ -2387,9 +2409,23 @@ void ScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) { void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventMouseButton> mb = ev; - if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + if (mb.is_valid() && mb->is_pressed()) { + switch (mb->get_button_index()) { + + case BUTTON_MIDDLE: { + // Right-click selects automatically; middle-click does not. + int idx = script_list->get_item_at_position(mb->get_position(), true); + if (idx >= 0) { + script_list->select(idx); + _script_selected(idx); + _menu_option(FILE_CLOSE); + } + } break; - _make_script_list_context_menu(); + case BUTTON_RIGHT: { + _make_script_list_context_menu(); + } break; + } } } @@ -2960,7 +2996,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_child(file_menu); file_menu->set_text(TTR("File")); file_menu->get_popup()->set_hide_on_window_lose_focus(true); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New")), FILE_NEW); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script")), FILE_NEW); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New TextFile")), FILE_NEW_TEXTFILE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open")), FILE_OPEN); file_menu->get_popup()->add_submenu_item(TTR("Open Recent"), "RecentScripts", FILE_OPEN_RECENT); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 186c80a5f9..737f17358b 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -130,6 +130,7 @@ class ScriptEditor : public PanelContainer { EditorNode *editor; enum { FILE_NEW, + FILE_NEW_TEXTFILE, FILE_OPEN, FILE_OPEN_RECENT, FILE_SAVE, diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 40d6b67426..9782b9d1f4 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -2081,6 +2081,15 @@ void SpatialEditorViewport::set_message(String p_message, float p_time) { message_time = p_time; } +void SpatialEditorPlugin::edited_scene_changed() { + for (int i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { + SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(i); + if (viewport->is_visible()) { + viewport->notification(Control::NOTIFICATION_VISIBILITY_CHANGED); + } + } +} + void SpatialEditorViewport::_notification(int p_what) { if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { @@ -2824,7 +2833,7 @@ void SpatialEditorViewport::update_transform_gizmo_view() { dd = 0.0001; float gsize = EditorSettings::get_singleton()->get("editors/3d/manipulator_gizmo_size"); - gizmo_scale = (gsize / Math::abs(dd)); + gizmo_scale = (gsize / Math::abs(dd)) * MAX(1, EDSCALE) / viewport_container->get_stretch_shrink(); Vector3 scale = Vector3(1, 1, 1) * gizmo_scale; xform.basis.scale(scale); @@ -3346,7 +3355,7 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p if (root_node) { list.push_back(root_node); } else { - accept->get_ok()->set_text(TTR("OK :(")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("No parent to instance a child at.")); accept->popup_centered_minsize(); _remove_preview(); @@ -3386,6 +3395,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed clicked = 0; clicked_includes_current = false; orthogonal = false; + lock_rotation = false; message_time = 0; zoom_indicator_delay = 0.0; @@ -4517,9 +4527,9 @@ void SpatialEditor::_init_indicators() { nivec * 0.0 + ivec * (GIZMO_ARROW_OFFSET + GIZMO_ARROW_SIZE), }; - int arrow_sides = 6; + int arrow_sides = 16; - for (int k = 0; k < 6; k++) { + for (int k = 0; k < arrow_sides; k++) { Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides); Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides); @@ -4603,10 +4613,10 @@ void SpatialEditor::_init_indicators() { ivec * 0.02 + ivec2 * 0.02 + ivec2 * GIZMO_CIRCLE_SIZE, }; - for (int k = 0; k < 32; k++) { + for (int k = 0; k < 64; k++) { - Basis ma(ivec, Math_PI * 2 * float(k) / 32); - Basis mb(ivec, Math_PI * 2 * float(k + 1) / 32); + Basis ma(ivec, Math_PI * 2 * float(k) / 64); + Basis mb(ivec, Math_PI * 2 * float(k + 1) / 64); for (int j = 0; j < 4; j++) { diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 0ebc11e5df..4057145c2f 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -741,6 +741,8 @@ public: virtual void set_state(const Dictionary &p_state); virtual void clear() { spatial_editor->clear(); } + virtual void edited_scene_changed(); + SpatialEditorPlugin(EditorNode *p_node); ~SpatialEditorPlugin(); }; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 0419c3d4b1..d13e01dc1e 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -603,7 +603,6 @@ void TextureRegionEditor::_notification(int p_what) { zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons")); zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); zoom_in->set_icon(get_icon("ZoomMore", "EditorIcons")); - icon_zoom->set_texture(get_icon("Zoom", "EditorIcons")); } break; } } @@ -865,7 +864,7 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { hb_grid->add_child(sb_step_y); hb_grid->add_child(memnew(VSeparator)); - hb_grid->add_child(memnew(Label(TTR("Separation:")))); + hb_grid->add_child(memnew(Label(TTR("Sep.:")))); sb_sep_x = memnew(SpinBox); sb_sep_x->set_min(0); @@ -898,10 +897,6 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { separator->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb_tools->add_child(separator); - icon_zoom = memnew(TextureRect); - icon_zoom->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); - hb_tools->add_child(icon_zoom); - zoom_out = memnew(ToolButton); zoom_out->connect("pressed", this, "_zoom_out"); hb_tools->add_child(zoom_out); @@ -940,16 +935,15 @@ bool TextureRegionEditorPlugin::handles(Object *p_object) const { void TextureRegionEditorPlugin::make_visible(bool p_visible) { if (p_visible) { texture_region_button->show(); - if (region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region())) { + if (region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region()) || texture_region_button->is_pressed()) { editor->make_bottom_panel_item_visible(region_editor); - } else { - if (texture_region_button->is_pressed()) - region_editor->show(); } } else { + if (region_editor->is_visible_in_tree()) { + editor->hide_bottom_panel(); + } texture_region_button->hide(); region_editor->edit(NULL); - region_editor->hide(); } } @@ -1001,10 +995,9 @@ TextureRegionEditorPlugin::TextureRegionEditorPlugin(EditorNode *p_node) { editor = p_node; region_editor = memnew(TextureRegionEditor(p_node)); - texture_region_button = p_node->add_bottom_panel_item(TTR("TextureRegion"), region_editor); - texture_region_button->set_tooltip(TTR("Texture Region Editor")); - region_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); region_editor->hide(); + + texture_region_button = p_node->add_bottom_panel_item(TTR("TextureRegion"), region_editor); texture_region_button->hide(); } diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index bd93be9267..670cc86bbb 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -56,7 +56,6 @@ class TextureRegionEditor : public Control { friend class TextureRegionEditorPlugin; MenuButton *snap_mode_button; - TextureRect *icon_zoom; ToolButton *zoom_in; ToolButton *zoom_reset; ToolButton *zoom_out; diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 101dc3037f..3d14db7d0e 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -533,10 +533,9 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era return PoolVector<Vector2>(); } - for (int i = ids.size() - 1; i >= 0; i--) { - if (ids[i] == prev_id) { - return PoolVector<Vector2>(); - } + if (ids.size() == 1 && ids[0] == prev_id) { + // Same ID, nothing to change + return PoolVector<Vector2>(); } Rect2i r = node->get_used_rect(); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 8d1db5de8f..490ebeca26 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -307,6 +307,11 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { tool_workspacemode[i]->connect("pressed", this, "_on_workspace_mode_changed", p); tool_hb->add_child(tool_workspacemode[i]); } + Control *spacer = memnew(Control); + spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tool_hb->add_child(spacer); + tool_hb->move_child(spacer, (int)WORKSPACE_CREATE_SINGLE); + tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true); workspace_mode = WORKSPACE_EDIT; @@ -314,9 +319,6 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { main_vb->add_child(memnew(HSeparator)); tool_hb = memnew(HBoxContainer); - Control *spacer = memnew(Control); - spacer->set_custom_minimum_size(Size2(30, 0)); - tool_hb->add_child(spacer); g = Ref<ButtonGroup>(memnew(ButtonGroup)); String label[EDITMODE_MAX] = { "Region", "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon" }; @@ -335,7 +337,8 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { edit_mode = EDITMODE_COLLISION; main_vb->add_child(tool_hb); - main_vb->add_child(memnew(HSeparator)); + separator_editmode = memnew(HSeparator); + main_vb->add_child(separator_editmode); toolbar = memnew(HBoxContainer); Ref<ButtonGroup> tg(memnew(ButtonGroup)); @@ -369,13 +372,17 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { toolbar->add_child(tools[SHAPE_NEW_POLYGON]); tools[SHAPE_NEW_POLYGON]->set_toggle_mode(true); tools[SHAPE_NEW_POLYGON]->set_button_group(tg); - toolbar->add_child(memnew(VSeparator)); + + separator_delete = memnew(VSeparator); + toolbar->add_child(separator_delete); tools[SHAPE_DELETE] = memnew(ToolButton); p = Vector<Variant>(); p.push_back((int)SHAPE_DELETE); tools[SHAPE_DELETE]->connect("pressed", this, "_on_tool_clicked", p); toolbar->add_child(tools[SHAPE_DELETE]); - toolbar->add_child(memnew(VSeparator)); + + separator_grid = memnew(VSeparator); + toolbar->add_child(separator_grid); tools[SHAPE_KEEP_INSIDE_TILE] = memnew(ToolButton); tools[SHAPE_KEEP_INSIDE_TILE]->set_toggle_mode(true); tools[SHAPE_KEEP_INSIDE_TILE]->set_pressed(true); @@ -588,10 +595,16 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->hide(); - if (workspace_mode == WORKSPACE_EDIT) + + if (workspace_mode == WORKSPACE_EDIT) { + separator_delete->show(); tools[SHAPE_DELETE]->show(); - else + } else { + separator_delete->hide(); tools[SHAPE_DELETE]->hide(); + } + + separator_grid->show(); tools[SHAPE_KEEP_INSIDE_TILE]->hide(); tools[TOOL_GRID_SNAP]->show(); @@ -605,7 +618,11 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->show(); tools[BITMASK_CLEAR]->show(); tools[SHAPE_NEW_POLYGON]->hide(); + + separator_delete->hide(); tools[SHAPE_DELETE]->hide(); + + separator_grid->hide(); tools[SHAPE_KEEP_INSIDE_TILE]->hide(); tools[TOOL_GRID_SNAP]->hide(); @@ -621,7 +638,11 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->show(); + + separator_delete->show(); tools[SHAPE_DELETE]->show(); + + separator_grid->show(); tools[SHAPE_KEEP_INSIDE_TILE]->show(); tools[TOOL_GRID_SNAP]->show(); @@ -635,9 +656,14 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->hide(); + + separator_delete->hide(); tools[SHAPE_DELETE]->hide(); + + separator_grid->show(); tools[SHAPE_KEEP_INSIDE_TILE]->hide(); tools[TOOL_GRID_SNAP]->show(); + if (edit_mode == EDITMODE_ICON) { tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.\nClick on another Tile to edit it.")); spin_priority->hide(); @@ -661,6 +687,7 @@ void TileSetEditor::_on_workspace_mode_changed(int p_workspace_mode) { tool_editmode[EDITMODE_REGION]->show(); tool_editmode[EDITMODE_REGION]->set_pressed(true); _on_edit_mode_changed(EDITMODE_REGION); + separator_editmode->show(); } } @@ -2076,6 +2103,7 @@ void TileSetEditor::update_workspace_tile_mode() { tool_editmode[EDITMODE_REGION]->show(); tool_editmode[EDITMODE_REGION]->set_pressed(true); _on_edit_mode_changed(EDITMODE_REGION); + separator_editmode->show(); return; } @@ -2086,12 +2114,16 @@ void TileSetEditor::update_workspace_tile_mode() { for (int i = 0; i < ZOOM_OUT; i++) { tools[i]->hide(); } + separator_editmode->hide(); + separator_delete->hide(); + separator_grid->hide(); return; } for (int i = 0; i < EDITMODE_MAX; i++) { tool_editmode[i]->show(); } + separator_editmode->show(); if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { if (tool_editmode[EDITMODE_ICON]->is_pressed() || tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed()) { @@ -2336,12 +2368,10 @@ bool TileSetEditorPlugin::handles(Object *p_node) const { void TileSetEditorPlugin::make_visible(bool p_visible) { if (p_visible) { tileset_editor_button->show(); - if (tileset_editor_button->is_pressed()) { - tileset_editor->show(); - } + editor->make_bottom_panel_item_visible(tileset_editor); get_tree()->connect("idle_frame", tileset_editor, "_on_workspace_process"); } else { - tileset_editor->hide(); + editor->hide_bottom_panel(); tileset_editor_button->hide(); get_tree()->disconnect("idle_frame", tileset_editor, "_on_workspace_process"); } diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 0c175e718c..23bf68b90f 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -40,12 +40,12 @@ #define WORKSPACE_MARGIN Vector2(10, 10) class TilesetEditorContext; -class TileSetEditor : public Panel { +class TileSetEditor : public Control { friend class TileSetEditorPlugin; friend class TilesetEditorContext; - GDCLASS(TileSetEditor, Panel) + GDCLASS(TileSetEditor, Control) enum TextureToolButtons { TOOL_TILESET_ADD_TEXTURE, @@ -131,8 +131,11 @@ class TileSetEditor : public Panel { Control *workspace; Button *tool_workspacemode[WORKSPACE_MODE_MAX]; Button *tool_editmode[EDITMODE_MAX]; + HSeparator *separator_editmode; HBoxContainer *toolbar; ToolButton *tools[TOOL_MAX]; + VSeparator *separator_delete; + VSeparator *separator_grid; SpinBox *spin_priority; WorkspaceMode workspace_mode; EditMode edit_mode; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 9218fed907..63e89b78ea 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -119,6 +119,9 @@ void VisualShaderEditor::_update_graph() { if (updating) return; + if (visual_shader.is_null()) + return; + graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE); VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 170546f14c..3cebbb5d21 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -231,7 +231,7 @@ void ProjectExportDialog::_edit_preset(int p_index) { if (error != String()) { - Vector<String> items = error.split("\n"); + Vector<String> items = error.split("\n", false); error = ""; for (int i = 0; i < items.size(); i++) { if (i > 0) @@ -756,7 +756,7 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) { Error err = platform->export_project(current, export_debug->is_pressed(), p_path, 0); if (err != OK) { - error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted: ") + platform->get_name()); + error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted:") + " " + platform->get_name()); error_dialog->show(); error_dialog->popup_centered_minsize(Size2(300, 80)); ERR_PRINT("Failed to export project"); @@ -956,7 +956,7 @@ ProjectExportDialog::ProjectExportDialog() { export_error = memnew(Label); main_vb->add_child(export_error); export_error->hide(); - export_error->add_color_override("font_color", get_color("error_color", "Editor")); + export_error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); export_templates_error = memnew(HBoxContainer); main_vb->add_child(export_templates_error); @@ -964,7 +964,7 @@ ProjectExportDialog::ProjectExportDialog() { Label *export_error2 = memnew(Label); export_templates_error->add_child(export_error2); - export_error2->add_color_override("font_color", get_color("error_color", "Editor")); + export_error2->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); export_error2->set_text(" - " + TTR("Export templates for this platform are missing:") + " "); error_dialog = memnew(AcceptDialog); @@ -975,6 +975,7 @@ ProjectExportDialog::ProjectExportDialog() { LinkButton *download_templates = memnew(LinkButton); download_templates->set_text(TTR("Manage Export Templates")); + download_templates->set_v_size_flags(SIZE_SHRINK_CENTER); export_templates_error->add_child(download_templates); download_templates->connect("pressed", this, "_open_export_template_manager"); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 6af7779575..aad9258ed9 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -915,12 +915,6 @@ void ProjectManager::_update_project_buttons() { CanvasItem *item = Object::cast_to<CanvasItem>(scroll_children->get_child(i)); item->update(); - - Button *show = Object::cast_to<Button>(item->get_node(NodePath("project/path_box/show"))); - if (show) { - String current = item->get_meta("name"); - show->set_visible(selected_list.has(current)); - } } bool empty_selection = selected_list.empty(); @@ -1316,7 +1310,6 @@ void ProjectManager::_load_recent_projects() { path_hb->add_child(show); show->connect("pressed", this, "_show_project", varray(path)); show->set_tooltip(TTR("Show In File Manager")); - show->set_visible(false); Label *fpath = memnew(Label(path)); fpath->set_name("path"); @@ -1757,6 +1750,8 @@ ProjectManager::ProjectManager() { editor_set_scale(custom_display_scale); } break; } + + OS::get_singleton()->set_window_size(OS::get_singleton()->get_window_size() * MAX(1, EDSCALE)); } FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); @@ -1824,7 +1819,7 @@ ProjectManager::ProjectManager() { project_filter = memnew(ProjectListFilter); search_box->add_child(project_filter); project_filter->connect("filter_changed", this, "_load_recent_projects"); - project_filter->set_custom_minimum_size(Size2(250, 10)); + project_filter->set_custom_minimum_size(Size2(280, 10) * EDSCALE); search_tree_vb->add_child(search_box); PanelContainer *pc = memnew(PanelContainer); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index d52538f67b..970302e058 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -215,10 +215,8 @@ void ProjectSettingsEditor::_action_edited() { undo_redo->create_action(TTR("Change Action deadzone")); undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, new_action); - undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_do_method(this, "_settings_changed"); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_action); - undo_redo->add_undo_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_settings_changed"); undo_redo->commit_action(); } @@ -808,6 +806,10 @@ void ProjectSettingsEditor::popup_project_settings() { plugin_settings->update_plugins(); } +void ProjectSettingsEditor::update_plugins() { + plugin_settings->update_plugins(); +} + void ProjectSettingsEditor::_item_selected(const String &p_path) { String selected_path = p_path; diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index b738c4ae20..1344da1de7 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -186,6 +186,7 @@ public: static ProjectSettingsEditor *get_singleton() { return singleton; } void popup_project_settings(); void set_plugins_page(); + void update_plugins(); EditorAutoloadSettings *get_autoload_settings() { return autoload_settings; } diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index b370a711e3..408e67149a 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -287,7 +287,11 @@ void CustomPropertyEditor::_menu_option(int p_which) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_BREAK(!obj); @@ -1132,7 +1136,11 @@ void CustomPropertyEditor::_type_create_selected(int p_idx) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_FAIL_COND(!obj); @@ -1334,7 +1342,11 @@ void CustomPropertyEditor::_action_pressed(int p_which) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_BREAK(!obj); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index e1bb622ea4..607d974025 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -119,7 +119,7 @@ void SceneTreeDock::instance(const String &p_file) { if (!edited_scene) { current_option = -1; - accept->get_ok()->set_text(TTR("OK :(")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("No parent to instance a child at.")); accept->popup_centered_minsize(); return; @@ -365,10 +365,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptLanguage *l = ScriptServer::get_language(i); if (l->get_type() == existing->get_class()) { - if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { - String name = l->get_global_class_name(existing->get_path(), NULL); - inherits = editor->get_editor_data().script_class_get_base(name); - } else if (l->can_inherit_from_file()) { + String name = l->get_global_class_name(existing->get_path()); + if (ScriptServer::is_global_class(name)) { + if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { + inherits = editor->get_editor_data().script_class_get_base(name); + } else if (l->can_inherit_from_file()) { + inherits = "\"" + existing->get_path() + "\""; + } + } else { inherits = "\"" + existing->get_path() + "\""; } } @@ -395,6 +399,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { const RefPtr empty; editor_data->get_undo_redo().add_do_method(E->get(), "set_script", empty); editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + + editor_data->get_undo_redo().add_do_method(E->get(), "set_meta", "_editor_icon", get_icon(E->get()->get_class(), "EditorIcons")); + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", E->get()->get_meta("_editor_icon")); } } @@ -402,7 +409,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); editor_data->get_undo_redo().commit_action(); - } break; case TOOL_MOVE_UP: case TOOL_MOVE_DOWN: { @@ -797,18 +803,38 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } break; case TOOL_CREATE_2D_SCENE: case TOOL_CREATE_3D_SCENE: - case TOOL_CREATE_USER_INTERFACE: { + case TOOL_CREATE_USER_INTERFACE: + case TOOL_CREATE_FAVORITE: { Node *new_node; - switch (p_tool) { - case TOOL_CREATE_2D_SCENE: new_node = memnew(Node2D); break; - case TOOL_CREATE_3D_SCENE: new_node = memnew(Spatial); break; - case TOOL_CREATE_USER_INTERFACE: { - Control *node = memnew(Control); - node->set_anchors_and_margins_preset(PRESET_WIDE); //more useful for resizable UIs. - new_node = node; - } break; + if (TOOL_CREATE_FAVORITE == p_tool) { + String name = selected_favorite_root.get_slicec(' ', 0); + if (ScriptServer::is_global_class(name)) { + new_node = Object::cast_to<Node>(ClassDB::instance(ScriptServer::get_global_class_base(name))); + Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(name), "Script"); + if (new_node && script.is_valid()) { + new_node->set_script(script.get_ref_ptr()); + new_node->set_name(name); + } + } else { + new_node = Object::cast_to<Node>(ClassDB::instance(selected_favorite_root)); + } + if (!new_node) { + ERR_EXPLAIN("Creating root from favorite '" + selected_favorite_root + "' failed. Creating 'Node' instead."); + new_node = memnew(Node); + } + } else { + switch (p_tool) { + case TOOL_CREATE_2D_SCENE: new_node = memnew(Node2D); break; + case TOOL_CREATE_3D_SCENE: new_node = memnew(Spatial); break; + case TOOL_CREATE_USER_INTERFACE: { + Control *node = memnew(Control); + node->set_anchors_and_margins_preset(PRESET_WIDE); //more useful for resizable UIs. + new_node = node; + + } break; + } } editor_data->get_undo_redo().create_action("New Scene Root"); @@ -867,35 +893,62 @@ void SceneTreeDock::_notification(int p_what) { EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed", this, "_selection_changed"); - create_root_dialog->add_child(memnew(Label(TTR("Create Root Node:")))); + // create_root_dialog + HBoxContainer *top_row = memnew(HBoxContainer); + top_row->set_name("NodeShortcutsTopRow"); + top_row->set_h_size_flags(SIZE_EXPAND_FILL); + top_row->add_child(memnew(Label(TTR("Create Root Node:")))); + top_row->add_spacer(); - Button *button_2d = memnew(Button); - create_root_dialog->add_child(button_2d); + ToolButton *node_shortcuts_toggle = memnew(ToolButton); + node_shortcuts_toggle->set_name("NodeShortcutsToggle"); + node_shortcuts_toggle->set_icon(get_icon("Favorites", "EditorIcons")); + node_shortcuts_toggle->set_toggle_mode(true); + node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection")); + node_shortcuts_toggle->set_anchors_and_margins_preset(Control::PRESET_CENTER_RIGHT); + node_shortcuts_toggle->connect("pressed", this, "_update_create_root_dialog"); + top_row->add_child(node_shortcuts_toggle); + + create_root_dialog->add_child(top_row); + VBoxContainer *node_shortcuts = memnew(VBoxContainer); + node_shortcuts->set_name("NodeShortcuts"); + + VBoxContainer *beginner_node_shortcuts = memnew(VBoxContainer); + beginner_node_shortcuts->set_name("BeginnerNodeShortcuts"); + node_shortcuts->add_child(beginner_node_shortcuts); + + Button *button_2d = memnew(Button); + beginner_node_shortcuts->add_child(button_2d); button_2d->set_text(TTR("2D Scene")); button_2d->set_icon(get_icon("Node2D", "EditorIcons")); button_2d->connect("pressed", this, "_tool_selected", make_binds(TOOL_CREATE_2D_SCENE, false)); Button *button_3d = memnew(Button); - create_root_dialog->add_child(button_3d); + beginner_node_shortcuts->add_child(button_3d); button_3d->set_text(TTR("3D Scene")); button_3d->set_icon(get_icon("Spatial", "EditorIcons")); button_3d->connect("pressed", this, "_tool_selected", make_binds(TOOL_CREATE_3D_SCENE, false)); Button *button_ui = memnew(Button); - create_root_dialog->add_child(button_ui); + beginner_node_shortcuts->add_child(button_ui); button_ui->set_text(TTR("User Interface")); button_ui->set_icon(get_icon("Control", "EditorIcons")); button_ui->connect("pressed", this, "_tool_selected", make_binds(TOOL_CREATE_USER_INTERFACE, false)); + VBoxContainer *favorite_node_shortcuts = memnew(VBoxContainer); + favorite_node_shortcuts->set_name("FavoriteNodeShortcuts"); + node_shortcuts->add_child(favorite_node_shortcuts); + Button *button_custom = memnew(Button); - create_root_dialog->add_child(button_custom); + node_shortcuts->add_child(button_custom); button_custom->set_text(TTR("Custom Node")); button_custom->set_icon(get_icon("Add", "EditorIcons")); button_custom->connect("pressed", this, "_tool_selected", make_binds(TOOL_NEW, false)); - create_root_dialog->add_spacer(); - + node_shortcuts->add_spacer(); + create_root_dialog->add_child(node_shortcuts); + _update_create_root_dialog(); } break; case NOTIFICATION_ENTER_TREE: { @@ -1251,7 +1304,7 @@ bool SceneTreeDock::_validate_no_foreign() { if (E->get() != edited_scene && E->get()->get_owner() != edited_scene) { - accept->get_ok()->set_text(TTR("Makes Sense!")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("Can't operate on nodes from a foreign scene!")); accept->popup_centered_minsize(); return false; @@ -1259,7 +1312,7 @@ bool SceneTreeDock::_validate_no_foreign() { if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene->get_scene_inherited_state()->find_node_by_path(edited_scene->get_path_to(E->get())) >= 0) { - accept->get_ok()->set_text(TTR("Makes Sense!")); + accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("Can't operate on nodes the current scene inherits from!")); accept->popup_centered_minsize(); return false; @@ -1443,9 +1496,23 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { Ref<Script> existing = E->get()->get_script(); editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script.get_ref_ptr()); editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + + String icon_path; + String name = p_script->get_language()->get_global_class_name(p_script->get_path(), NULL, &icon_path); + if (ScriptServer::is_global_class(name)) { + RES icon = ResourceLoader::load(icon_path); + editor_data->get_undo_redo().add_do_method(E->get(), "set_meta", "_editor_icon", icon); + String existing_name = existing.is_valid() ? existing->get_language()->get_global_class_name(existing->get_path()) : String(); + if (existing.is_null() || !ScriptServer::is_global_class(existing_name)) { + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", get_icon(E->get()->get_class(), "EditorIcons")); + } else { + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", editor_data->script_class_get_icon_path(existing_name)); + } + } } editor_data->get_undo_redo().commit_action(); + print_line("test: " + String(Variant(selected.front()->get()->get_meta("_editor_icon")))); editor->push_item(p_script.operator->()); } @@ -2150,6 +2217,67 @@ void SceneTreeDock::_local_tree_selected() { edit_local->set_pressed(true); } +void SceneTreeDock::_update_create_root_dialog() { + + BaseButton *toggle = Object::cast_to<BaseButton>(create_root_dialog->get_node(String("NodeShortcutsTopRow/NodeShortcutsToggle"))); + Node *node_shortcuts = create_root_dialog->get_node(String("NodeShortcuts")); + + if (!toggle || !node_shortcuts) + return; + + Control *beginner_nodes = Object::cast_to<Control>(node_shortcuts->get_node(String("BeginnerNodeShortcuts"))); + Control *favorite_nodes = Object::cast_to<Control>(node_shortcuts->get_node(String("FavoriteNodeShortcuts"))); + + if (!beginner_nodes || !favorite_nodes) + return; + + EditorSettings::get_singleton()->set_setting("_use_favorites_root_selection", toggle->is_pressed()); + EditorSettings::get_singleton()->save(); + if (toggle->is_pressed()) { + + for (int i = 0; i < favorite_nodes->get_child_count(); i++) { + favorite_nodes->get_child(i)->queue_delete(); + } + + FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ); + + if (f) { + + while (!f->eof_reached()) { + String l = f->get_line().strip_edges(); + + if (l != String()) { + Button *button = memnew(Button); + favorite_nodes->add_child(button); + button->set_text(TTR(l)); + String name = l.get_slicec(' ', 0); + if (ScriptServer::is_global_class(name)) + name = ScriptServer::get_global_class_base(name); + button->set_icon(get_icon(name, "EditorIcons")); + button->connect("pressed", this, "_favorite_root_selected", make_binds(l)); + } + } + + memdelete(f); + } + + if (!favorite_nodes->is_visible_in_tree()) { + favorite_nodes->show(); + beginner_nodes->hide(); + } + } else { + if (!beginner_nodes->is_visible_in_tree()) { + beginner_nodes->show(); + favorite_nodes->hide(); + } + } +} + +void SceneTreeDock::_favorite_root_selected(const String &p_class) { + selected_favorite_root = p_class; + _tool_selected(TOOL_CREATE_FAVORITE, false); +} + void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_tool_selected"), &SceneTreeDock::_tool_selected, DEFVAL(false)); @@ -2178,6 +2306,8 @@ void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_remote_tree_selected"), &SceneTreeDock::_remote_tree_selected); ClassDB::bind_method(D_METHOD("_local_tree_selected"), &SceneTreeDock::_local_tree_selected); ClassDB::bind_method(D_METHOD("_update_script_button"), &SceneTreeDock::_update_script_button); + ClassDB::bind_method(D_METHOD("_favorite_root_selected"), &SceneTreeDock::_favorite_root_selected); + ClassDB::bind_method(D_METHOD("_update_create_root_dialog"), &SceneTreeDock::_update_create_root_dialog); ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance); @@ -2303,6 +2433,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel create_dialog->set_base_type("Node"); add_child(create_dialog); create_dialog->connect("create", this, "_create"); + create_dialog->connect("favorites_updated", this, "_update_create_root_dialog"); + EditorFileSystem::get_singleton()->connect("script_classes_updated", create_dialog, "_save_and_update_favorite_list"); rename_dialog = memnew(RenameDialog(scene_tree, &editor_data->get_undo_redo())); add_child(rename_dialog); @@ -2349,11 +2481,12 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel clear_inherit_confirm = memnew(ConfirmationDialog); clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)")); - clear_inherit_confirm->get_ok()->set_text(TTR("Clear!")); + clear_inherit_confirm->get_ok()->set_text(TTR("Clear")); add_child(clear_inherit_confirm); set_process_input(true); set_process(true); EDITOR_DEF("interface/editors/show_scene_tree_root_selection", true); + EDITOR_DEF("_use_favorites_root_selection", false); } diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 57f4759747..34a7c98d11 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -86,6 +86,7 @@ class SceneTreeDock : public VBoxContainer { TOOL_CREATE_2D_SCENE, TOOL_CREATE_3D_SCENE, TOOL_CREATE_USER_INTERFACE, + TOOL_CREATE_FAVORITE, }; @@ -141,6 +142,7 @@ class SceneTreeDock : public VBoxContainer { EditorNode *editor; VBoxContainer *create_root_dialog; + String selected_favorite_root; void _add_children_to_popup(Object *p_obj, int p_depth); @@ -201,6 +203,9 @@ class SceneTreeDock : public VBoxContainer { void _remote_tree_selected(); void _local_tree_selected(); + void _update_create_root_dialog(); + void _favorite_root_selected(const String &p_class); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index e483fde4bc..97147535c0 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -734,7 +734,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da error_list->set_item_metadata(error_list->get_item_count() - 1, stack); - error_count++; + if (warning) + warning_count++; + else + error_count++; } else if (p_msg == "profile_sig") { //cache a signature @@ -1011,20 +1014,26 @@ void ScriptEditorDebugger::_notification(int p_what) { } } - if (error_count != last_error_count) { + if (error_count != last_error_count || warning_count != last_warning_count) { - if (error_count == 0) { + if (error_count == 0 && warning_count == 0) { error_split->set_name(TTR("Errors")); debugger_button->set_text(TTR("Debugger")); debugger_button->set_icon(Ref<Texture>()); tabs->set_tab_icon(error_split->get_index(), Ref<Texture>()); } else { - error_split->set_name(TTR("Errors") + " (" + itos(error_count) + ")"); - debugger_button->set_text(TTR("Debugger") + " (" + itos(error_count) + ")"); - debugger_button->set_icon(get_icon("Error", "EditorIcons")); - tabs->set_tab_icon(error_split->get_index(), get_icon("Error", "EditorIcons")); + error_split->set_name(TTR("Errors") + " (" + itos(error_count + warning_count) + ")"); + debugger_button->set_text(TTR("Debugger") + " (" + itos(error_count + warning_count) + ")"); + if (error_count == 0) { + debugger_button->set_icon(get_icon("Warning", "EditorIcons")); + tabs->set_tab_icon(error_split->get_index(), get_icon("Warning", "EditorIcons")); + } else { + debugger_button->set_icon(get_icon("Error", "EditorIcons")); + tabs->set_tab_icon(error_split->get_index(), get_icon("Error", "EditorIcons")); + } } last_error_count = error_count; + last_warning_count = warning_count; } if (connection.is_null()) { @@ -1054,6 +1063,7 @@ void ScriptEditorDebugger::_notification(int p_what) { error_list->clear(); error_stack->clear(); error_count = 0; + warning_count = 0; profiler_signature.clear(); //live_edit_root->set_text("/root"); @@ -1198,7 +1208,7 @@ void ScriptEditorDebugger::start() { int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port"); if (server->listen(remote_port) != OK) { - EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), true); + EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), EditorLog::MSG_TYPE_ERROR); return; } @@ -1750,6 +1760,7 @@ void ScriptEditorDebugger::_clear_errors_list() { error_list->clear(); error_count = 0; + warning_count = 0; _notification(NOTIFICATION_PROCESS); } @@ -2162,9 +2173,11 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { live_debug = false; last_path_id = false; error_count = 0; + warning_count = 0; hide_on_stop = true; enable_external_editor = false; last_error_count = 0; + last_warning_count = 0; EditorNode::get_singleton()->get_pause_button()->connect("pressed", this, "_paused"); } diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index f7fe348b65..ce705aa35b 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -96,7 +96,9 @@ class ScriptEditorDebugger : public Control { EditorFileDialog *file_dialog; int error_count; + int warning_count; int last_error_count; + int last_warning_count; bool hide_on_stop; bool enable_external_editor; |