diff options
Diffstat (limited to 'editor')
130 files changed, 3258 insertions, 1575 deletions
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index f880ece88b..17b03fd479 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -31,6 +31,7 @@ #include "animation_bezier_editor.h" #include "editor/editor_node.h" +#include "editor_scale.h" float AnimationBezierTrackEdit::_bezier_h_to_pixel(float p_h) { float h = p_h; @@ -539,7 +540,7 @@ void AnimationBezierTrackEdit::_play_position_draw() { if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) { Color color = get_theme_color("accent_color", "Editor"); - play_position->draw_line(Point2(px, 0), Point2(px, h), color); + play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE)); } } @@ -558,6 +559,7 @@ void AnimationBezierTrackEdit::set_root(Node *p_root) { void AnimationBezierTrackEdit::_zoom_changed() { update(); + play_position->update(); } String AnimationBezierTrackEdit::get_tooltip(const Point2 &p_pos) const { diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index f36e84dab6..1d6770a32e 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3557,7 +3557,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p if (track_path == np) { value = p_value; //all good } else { - int sep = track_path.find_last(":"); + int sep = track_path.rfind(":"); if (sep != -1) { String base_path = track_path.substr(0, sep); if (base_path == np) { @@ -3656,7 +3656,7 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari value = p_value; //all good } else { String tpath = animation->track_get_path(i); - int index = tpath.find_last(":"); + int index = tpath.rfind(":"); if (NodePath(tpath.substr(0, index + 1)) == np) { String subindex = tpath.substr(index + 1, tpath.length() - index); value = p_value.get(subindex); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index c5df947d64..70747b4956 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -108,22 +108,25 @@ void FindReplaceBar::_notification(int p_what) { void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (k.is_valid()) { - if (k->is_pressed() && (text_edit->has_focus() || vbc_lineedit->is_a_parent_of(get_focus_owner()))) { - bool accepted = true; - - switch (k->get_keycode()) { - case KEY_ESCAPE: { - _hide_bar(); - } break; - default: { - accepted = false; - } break; - } + if (!k.is_valid() || !k->is_pressed()) { + return; + } - if (accepted) { - accept_event(); - } + Control *focus_owner = get_focus_owner(); + if (text_edit->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) { + bool accepted = true; + + switch (k->get_keycode()) { + case KEY_ESCAPE: { + _hide_bar(); + } break; + default: { + accepted = false; + } break; + } + + if (accepted) { + accept_event(); } } } @@ -1541,7 +1544,7 @@ void CodeTextEditor::_toggle_scripts_pressed() { void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - emit_signal("error_pressed"); + goto_error(); } } @@ -1651,7 +1654,6 @@ void CodeTextEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("validate_script")); ADD_SIGNAL(MethodInfo("load_theme_settings")); ADD_SIGNAL(MethodInfo("show_warnings_panel")); - ADD_SIGNAL(MethodInfo("error_pressed")); } void CodeTextEditor::set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud) { diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 310de9dd90..99a2a73a75 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -32,60 +32,38 @@ #include "core/class_db.h" #include "core/os/keyboard.h" -#include "core/print_string.h" #include "editor_feature_profile.h" -#include "editor_help.h" #include "editor_node.h" #include "editor_scale.h" #include "editor_settings.h" -#include "scene/gui/box_container.h" void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_select_type) { - type_list.clear(); - ClassDB::get_class_list(&type_list); - ScriptServer::get_global_class_list(&type_list); - type_list.sort_custom<StringName::AlphCompare>(); - - recent->clear(); - - FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ); + _fill_type_list(); - if (f) { - TreeItem *root = recent->create_item(); + icon_fallback = search_options->has_theme_icon(base_type, "EditorIcons") ? base_type : "Object"; - String icon_fallback = search_options->has_theme_icon(base_type, "EditorIcons") ? base_type : "Object"; - - while (!f->eof_reached()) { - String l = f->get_line().strip_edges(); - String name = l.split(" ")[0]; - if ((ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) && !_is_class_disabled_by_feature_profile(name)) { - TreeItem *ti = recent->create_item(root); - ti->set_text(0, l); - ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback)); - } - } - - memdelete(f); + if (p_dont_clear) { + search_box->select_all(); + } else { + search_box->clear(); } - favorites->clear(); - - f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::READ); - - favorite_list.clear(); - - if (f) { - while (!f->eof_reached()) { - String l = f->get_line().strip_edges(); + if (p_replace_mode) { + search_box->set_text(p_select_type); + } - if (l != String()) { - favorite_list.push_back(l); - } - } + search_box->grab_focus(); + _update_search(); - memdelete(f); + if (p_replace_mode) { + set_title(vformat(TTR("Change %s Type"), base_type)); + get_ok()->set_text(TTR("Change")); + } else { + set_title(vformat(TTR("Create New %s"), base_type)); + get_ok()->set_text(TTR("Create")); } + _load_favorites_and_history(); _save_and_update_favorite_list(); // Restore valid window bounds or pop up at default size. @@ -95,357 +73,263 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const St } else { popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); } +} - if (p_dont_clear) { - search_box->select_all(); - } else { - search_box->clear(); - } +void CreateDialog::_fill_type_list() { + List<StringName> complete_type_list; + ClassDB::get_class_list(&complete_type_list); + ScriptServer::get_global_class_list(&complete_type_list); - search_box->grab_focus(); + EditorData &ed = EditorNode::get_editor_data(); - _update_search(); + for (List<StringName>::Element *I = complete_type_list.front(); I; I = I->next()) { + String type = I->get(); + if (!_should_hide_type(type)) { + type_list.push_back(type); - is_replace_mode = p_replace_mode; + if (!ed.get_custom_types().has(type)) { + continue; + } - if (p_replace_mode) { - select_type(p_select_type); - set_title(vformat(TTR("Change %s Type"), base_type)); - get_ok()->set_text(TTR("Change")); - } else { - set_title(vformat(TTR("Create New %s"), base_type)); - get_ok()->set_text(TTR("Create")); + const Vector<EditorData::CustomType> &ct = ed.get_custom_types()[type]; + for (int i = 0; i < ct.size(); i++) { + custom_type_parents[ct[i].name] = type; + custom_type_indices[ct[i].name] = i; + type_list.push_back(ct[i].name); + } + } } + type_list.sort_custom<StringName::AlphCompare>(); } -void CreateDialog::_text_changed(const String &p_newtext) { - _update_search(); +bool CreateDialog::_is_type_preferred(const String &p_type) const { + if (ClassDB::class_exists(p_type)) { + return ClassDB::is_parent_class(p_type, preferred_search_result_type); + } + + return EditorNode::get_editor_data().script_class_is_parent(p_type, preferred_search_result_type); } -void CreateDialog::_sbox_input(const Ref<InputEvent> &p_ie) { - Ref<InputEventKey> k = p_ie; - if (k.is_valid() && (k->get_keycode() == KEY_UP || - k->get_keycode() == KEY_DOWN || - k->get_keycode() == KEY_PAGEUP || - k->get_keycode() == KEY_PAGEDOWN)) { - search_options->call("_gui_input", k); - search_box->accept_event(); - } +bool CreateDialog::_is_class_disabled_by_feature_profile(const StringName &p_class) const { + Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile(); + + return !profile.is_null() && profile->is_class_disabled(p_class); } -void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root, TreeItem **to_select) { - if (p_types.has(p_type)) { - return; +bool CreateDialog::_should_hide_type(const String &p_type) const { + if (_is_class_disabled_by_feature_profile(p_type)) { + return true; } - bool cpp_type = ClassDB::class_exists(p_type); - EditorData &ed = EditorNode::get_editor_data(); + if (base_type == "Node" && p_type.begins_with("Editor")) { + return true; // Do not show editor nodes. + } if (p_type == base_type) { - return; + return true; // Root is already added. } - if (cpp_type) { + if (ClassDB::class_exists(p_type)) { + if (!ClassDB::can_instance(p_type)) { + return true; // Can't create abstract class. + } + if (!ClassDB::is_parent_class(p_type, base_type)) { - return; + return true; // Wrong inheritance. + } + + for (Set<StringName>::Element *E = type_blacklist.front(); E; E = E->next()) { + if (ClassDB::is_parent_class(p_type, E->get())) { + return true; // Parent type is blacklisted. + } } } else { - if (!search_loaded_scripts.has(p_type)) { - search_loaded_scripts[p_type] = ed.script_class_load_script(p_type); + if (!EditorNode::get_editor_data().script_class_is_parent(p_type, base_type)) { + return true; // Wrong inheritance. } - - if (!ScriptServer::is_global_class(p_type) || !ed.script_class_is_parent(p_type, base_type)) { - return; + if (!ScriptServer::is_global_class(p_type)) { + return true; } String script_path = ScriptServer::get_global_class_path(p_type); - if (script_path.find("res://addons/", 0) != -1) { + if (script_path.begins_with("res://addons/")) { if (!EditorNode::get_singleton()->is_addon_plugin_enabled(script_path.get_slicec('/', 3))) { - return; + return true; // Plugin is not enabled. } } } - String inherits = cpp_type ? ClassDB::get_parent_class(p_type) : ed.script_class_get_base(p_type); - - TreeItem *parent = p_root; + return false; +} - if (inherits.length()) { - if (!p_types.has(inherits)) { - add_type(inherits, p_types, p_root, to_select); - } +void CreateDialog::_update_search() { + search_options->clear(); + search_options_types.clear(); - if (p_types.has(inherits)) { - parent = p_types[inherits]; - } else if (ScriptServer::is_global_class(inherits)) { - return; - } - } + TreeItem *root = search_options->create_item(); + root->set_text(0, base_type); + root->set_icon(0, search_options->get_theme_icon(icon_fallback, "EditorIcons")); + search_options_types[base_type] = root; - bool can_instance = (cpp_type && ClassDB::can_instance(p_type)) || ScriptServer::is_global_class(p_type); + const String search_text = search_box->get_text(); + bool empty_search = search_text == ""; - TreeItem *item = search_options->create_item(parent); - if (cpp_type) { - item->set_text(0, p_type); - } else { - item->set_metadata(0, p_type); - item->set_text(0, p_type + " (" + ScriptServer::get_global_class_path(p_type).get_file() + ")"); + // Filter all candidate results. + Vector<String> candidates; + for (List<StringName>::Element *I = type_list.front(); I; I = I->next()) { + if (empty_search || search_text.is_subsequence_ofi(I->get())) { + candidates.push_back(I->get()); + } } - if (!can_instance) { - item->set_custom_color(0, search_options->get_theme_color("disabled_font_color", "Editor")); - item->set_selectable(0, false); - } else if (!(*to_select && (*to_select)->get_text(0) == search_box->get_text())) { - String search_term = search_box->get_text().to_lower(); - - // if the node name matches exactly as the search, the node should be selected. - // this also fixes when the user clicks on recent nodes. - if (p_type.to_lower() == search_term) { - *to_select = item; - } else { - bool current_type_prefered = _is_type_prefered(p_type); - bool selected_type_prefered = *to_select ? _is_type_prefered((*to_select)->get_text(0).split(" ")[0]) : false; - - bool is_subsequence_of_type = search_box->get_text().is_subsequence_ofi(p_type); - bool is_substring_of_type = p_type.to_lower().find(search_term) >= 0; - bool is_substring_of_selected = false; - bool is_subsequence_of_selected = false; - bool is_selected_equal = false; - - if (*to_select) { - String name = (*to_select)->get_text(0).split(" ")[0].to_lower(); - is_substring_of_selected = name.find(search_term) >= 0; - is_subsequence_of_selected = search_term.is_subsequence_of(name); - is_selected_equal = name == search_term; - } - if (is_subsequence_of_type && !is_selected_equal) { - if (is_substring_of_type) { - if (!is_substring_of_selected || (current_type_prefered && !selected_type_prefered)) { - *to_select = item; - } - } else { - // substring results weigh more than subsequences, so let's make sure we don't override them - if (!is_substring_of_selected) { - if (!is_subsequence_of_selected || (current_type_prefered && !selected_type_prefered)) { - *to_select = item; - } - } - } - } - } + // Build the type tree. + for (int i = 0; i < candidates.size(); i++) { + _add_type(candidates[i], ClassDB::class_exists(candidates[i])); } - if (bool(EditorSettings::get_singleton()->get("docks/scene_tree/start_create_dialog_fully_expanded"))) { - item->set_collapsed(false); + // Select the best result. + if (empty_search) { + select_type(base_type); + } else if (candidates.size() > 0) { + select_type(_top_result(candidates, search_text)); } else { - // don't collapse search results - bool collapse = (search_box->get_text() == ""); - // don't collapse the root node - collapse &= (item != p_root); - // don't collapse abstract nodes on the first tree level - collapse &= ((parent != p_root) || (can_instance)); - item->set_collapsed(collapse); + favorite->set_disabled(true); + help_bit->set_text(""); + get_ok()->set_disabled(true); + search_options->deselect_all(); } - - const String &description = DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description); - item->set_tooltip(0, description); - - String icon_fallback = search_options->has_theme_icon(base_type, "EditorIcons") ? base_type : "Object"; - item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, icon_fallback)); - - p_types[p_type] = item; } -bool CreateDialog::_is_type_prefered(const String &type) { - bool cpp_type = ClassDB::class_exists(type); - EditorData &ed = EditorNode::get_editor_data(); - - if (cpp_type) { - return ClassDB::is_parent_class(type, preferred_search_result_type); +void CreateDialog::_add_type(const String &p_type, bool p_cpp_type) { + if (search_options_types.has(p_type)) { + return; } - return ed.script_class_is_parent(type, preferred_search_result_type); -} -bool CreateDialog::_is_class_disabled_by_feature_profile(const StringName &p_class) { - Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile(); - if (profile.is_null()) { - return false; + String inherits; + if (p_cpp_type) { + inherits = ClassDB::get_parent_class(p_type); + } else if (ScriptServer::is_global_class(p_type)) { + inherits = EditorNode::get_editor_data().script_class_get_base(p_type); + } else { + inherits = custom_type_parents[p_type]; } - return profile->is_class_disabled(p_class); + _add_type(inherits, p_cpp_type || ClassDB::class_exists(inherits)); + + TreeItem *item = search_options->create_item(search_options_types[inherits]); + search_options_types[p_type] = item; + _configure_search_option_item(item, p_type, p_cpp_type); } -void CreateDialog::select_type(const String &p_type) { - TreeItem *to_select; - if (search_options_types.has(p_type)) { - to_select = search_options_types[p_type]; +void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String &p_type, const bool p_cpp_type) { + bool script_type = ScriptServer::is_global_class(p_type); + if (p_cpp_type) { + r_item->set_text(0, p_type); + } else if (script_type) { + r_item->set_metadata(0, p_type); + r_item->set_text(0, p_type + " (" + ScriptServer::get_global_class_path(p_type).get_file() + ")"); } else { - to_select = search_options->get_root(); + r_item->set_metadata(0, custom_type_parents[p_type]); + r_item->set_text(0, p_type); } - // uncollapse from selected type to top level - // TODO: should this be in tree? - TreeItem *cur = to_select; - while (cur) { - cur->set_collapsed(false); - cur = cur->get_parent(); + bool can_instance = (p_cpp_type && ClassDB::can_instance(p_type)) || !p_cpp_type; + if (!can_instance) { + r_item->set_custom_color(0, search_options->get_theme_color("disabled_font_color", "Editor")); + r_item->set_selectable(0, false); } - to_select->select(0); - - search_options->scroll_to_item(to_select); -} - -void CreateDialog::_update_search() { - search_options->clear(); - favorite->set_disabled(true); - - help_bit->set_text(""); - - search_options_types.clear(); - - TreeItem *root = search_options->create_item(); - EditorData &ed = EditorNode::get_editor_data(); - - root->set_text(0, base_type); - String base_icon = search_options->has_theme_icon(base_type, "EditorIcons") ? base_type : "Object"; - root->set_icon(0, search_options->get_theme_icon(base_icon, "EditorIcons")); - - TreeItem *to_select = search_box->get_text() == base_type ? root : nullptr; - - for (List<StringName>::Element *I = type_list.front(); I; I = I->next()) { - String type = I->get(); + if (search_box->get_text() != "") { + r_item->set_collapsed(false); + } else { + // Don't collapse the root node or an abstract node on the first tree level. + bool should_collapse = p_type != base_type && (r_item->get_parent()->get_text(0) != base_type || can_instance); - if (_is_class_disabled_by_feature_profile(type)) { - continue; + if (should_collapse && bool(EditorSettings::get_singleton()->get("docks/scene_tree/start_create_dialog_fully_expanded"))) { + should_collapse = false; // Collapse all nodes anyway. } - bool cpp_type = ClassDB::class_exists(type); + r_item->set_collapsed(should_collapse); + } - if (base_type == "Node" && type.begins_with("Editor")) { - continue; // do not show editor nodes - } + const String &description = DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description); + r_item->set_tooltip(0, description); + r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, icon_fallback)); - if (cpp_type && !ClassDB::can_instance(type)) { - continue; // can't create what can't be instanced + if (!p_cpp_type && !script_type) { + Ref<Texture2D> icon = EditorNode::get_editor_data().get_custom_types()[custom_type_parents[p_type]][custom_type_indices[p_type]].icon; + if (icon.is_valid()) { + r_item->set_icon(0, icon); } + } +} - if (cpp_type) { - bool skip = false; - - for (Set<StringName>::Element *E = type_blacklist.front(); E && !skip; E = E->next()) { - if (ClassDB::is_parent_class(type, E->get())) { - skip = true; - } - } - if (skip) { - continue; - } +String CreateDialog::_top_result(const Vector<String> p_candidates, const String &p_search_text) const { + float highest_score = 0; + int highest_index = 0; + for (int i = 0; i < p_candidates.size(); i++) { + float score = _score_type(p_candidates[i].get_slicec(' ', 0), p_search_text); + if (score > highest_score) { + highest_score = score; + highest_index = i; } + } - if (search_box->get_text() == "") { - add_type(type, search_options_types, root, &to_select); - } else { - bool found = false; - String type2 = type; - bool cpp_type2 = cpp_type; - - if (!cpp_type && !search_loaded_scripts.has(type)) { - search_loaded_scripts[type] = ed.script_class_load_script(type); - } + return p_candidates[highest_index]; +} - while (type2 != "" && (cpp_type2 ? ClassDB::is_parent_class(type2, base_type) : ed.script_class_is_parent(type2, base_type)) && type2 != base_type) { - if (search_box->get_text().is_subsequence_ofi(type2)) { - found = true; - break; - } +float CreateDialog::_score_type(const String &p_type, const String &p_search) const { + float inverse_length = 1.f / float(p_type.length()); - type2 = cpp_type2 ? ClassDB::get_parent_class(type2) : ed.script_class_get_base(type2); - cpp_type2 = cpp_type2 || ClassDB::class_exists(type2); // Built-in class can't inherit from custom type, so we can skip the check if it's already true. + // Favor types where search term is a substring close to the start of the type. + float w = 0.5f; + int pos = p_type.findn(p_search); + float score = (pos > -1) ? 1.0f - w * MIN(1, 3 * pos * inverse_length) : MAX(0.f, .9f - w); - if (!cpp_type2 && !search_loaded_scripts.has(type2)) { - search_loaded_scripts[type2] = ed.script_class_load_script(type2); - } - } + // Favor shorter items: they resemble the search term more. + w = 0.1f; + score *= (1 - w) + w * (p_search.length() * inverse_length); - if (found) { - add_type(type, search_options_types, root, &to_select); - } - } + score *= _is_type_preferred(p_type) ? 1.0f : 0.8f; - if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) { - //there are custom types based on this... cool. + // Add score for being a favorite type. + score *= (favorite_list.find(p_type) > -1) ? 1.0f : 0.7f; - const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[type]; - for (int i = 0; i < ct.size(); i++) { - bool show = search_box->get_text().is_subsequence_ofi(ct[i].name); - - if (!show) { - continue; - } - - if (!search_options_types.has(type)) { - add_type(type, search_options_types, root, &to_select); - } - - TreeItem *ti; - if (search_options_types.has(type)) { - ti = search_options_types[type]; - } else { - ti = search_options->get_root(); - } - - TreeItem *item = search_options->create_item(ti); - item->set_metadata(0, type); - item->set_text(0, ct[i].name); - item->set_icon(0, ct[i].icon.is_valid() ? ct[i].icon : search_options->get_theme_icon(base_icon, "EditorIcons")); - - if (!to_select || ct[i].name == search_box->get_text()) { - to_select = item; - } - } + // Look through at most 5 recent items + bool in_recent = false; + for (int i = 0; i < MIN(5, recent->get_item_count()); i++) { + if (recent->get_item_text(i) == p_type) { + in_recent = true; + break; } } + score *= in_recent ? 1.0f : 0.8f; - if (search_box->get_text() == "") { - to_select = root; - } - - if (to_select) { - to_select->select(0); - search_options->scroll_to_item(to_select); - favorite->set_disabled(false); - favorite->set_pressed(favorite_list.find(to_select->get_text(0)) != -1); - } + return score; +} - get_ok()->set_disabled(root->get_children() == nullptr); +void CreateDialog::_cleanup() { + type_list.clear(); + favorite_list.clear(); + favorites->clear(); + recent->clear(); + custom_type_parents.clear(); + custom_type_indices.clear(); } void CreateDialog::_confirmed() { - TreeItem *ti = search_options->get_selected(); - if (!ti) { + String selected_item = get_selected_type(); + if (selected_item == String()) { return; } FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE); - if (f) { - f->store_line(get_selected_type()); - TreeItem *t = recent->get_root(); - if (t) { - t = t->get_children(); - } - int count = 0; - while (t) { - if (t->get_text(0) != get_selected_type()) { - f->store_line(t->get_text(0)); - } + f->store_line(selected_item); - if (count > 32) { - //limit it to 32 entries.. - break; + for (int i = 0; i < MIN(32, recent->get_item_count()); i++) { + if (recent->get_item_text(i) != selected_item) { + f->store_line(recent->get_item_text(i)); } - t = t->get_next(); - count++; } memdelete(f); @@ -453,6 +337,26 @@ void CreateDialog::_confirmed() { emit_signal("create"); hide(); + _cleanup(); +} + +void CreateDialog::_text_changed(const String &p_newtext) { + _update_search(); +} + +void CreateDialog::_sbox_input(const Ref<InputEvent> &p_ie) { + Ref<InputEventKey> k = p_ie; + if (k.is_valid()) { + switch (k->get_keycode()) { + case KEY_UP: + case KEY_DOWN: + case KEY_PAGEUP: + case KEY_PAGEDOWN: { + search_options->call("_gui_input", k); + search_box->accept_event(); + } break; + } + } } void CreateDialog::_notification(int p_what) { @@ -472,42 +376,36 @@ void CreateDialog::_notification(int p_what) { search_box->select_all(); } else { EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "create_new_node", Rect2(get_position(), get_size())); - search_loaded_scripts.clear(); } } break; } } -void CreateDialog::set_base_type(const String &p_base) { - base_type = p_base; - if (is_replace_mode) { - set_title(vformat(TTR("Change %s Type"), p_base)); - } else { - set_title(vformat(TTR("Create New %s"), p_base)); +void CreateDialog::select_type(const String &p_type) { + if (!search_options_types.has(p_type)) { + return; } - _update_search(); -} - -String CreateDialog::get_base_type() const { - return base_type; -} + TreeItem *to_select = search_options_types[p_type]; + to_select->select(0); + search_options->scroll_to_item(to_select); -void CreateDialog::set_preferred_search_result_type(const String &p_preferred_type) { - preferred_search_result_type = p_preferred_type; -} + if (EditorHelp::get_doc_data()->class_list.has(p_type)) { + help_bit->set_text(DTR(EditorHelp::get_doc_data()->class_list[p_type].brief_description)); + } -String CreateDialog::get_preferred_search_result_type() { - return preferred_search_result_type; + favorite->set_disabled(false); + favorite->set_pressed(favorite_list.find(p_type) != -1); + get_ok()->set_disabled(false); } String CreateDialog::get_selected_type() { TreeItem *selected = search_options->get_selected(); - if (selected) { - return selected->get_text(0); - } else { + if (!selected) { return String(); } + + return selected->get_text(0); } Object *CreateDialog::instance_selected() { @@ -518,21 +416,15 @@ Object *CreateDialog::instance_selected() { } Variant md = selected->get_metadata(0); - String custom; - if (md.get_type() != Variant::NIL) { - custom = md; - } - Object *obj = nullptr; - - if (!custom.empty()) { + if (md.get_type() != Variant::NIL) { + String custom = md; if (ScriptServer::is_global_class(custom)) { obj = EditorNode::get_editor_data().script_class_instance(custom); Node *n = Object::cast_to<Node>(obj); if (n) { n->set_name(custom); } - obj = n; } else { obj = EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom); } @@ -545,9 +437,10 @@ Object *CreateDialog::instance_selected() { obj->get_property_list(&pinfo); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - if (E->get().type == Variant::OBJECT && E->get().usage & PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT) { - Object *prop = ClassDB::instance(E->get().class_name); - obj->set(E->get().name, prop); + PropertyInfo pi = E->get(); + if (pi.type == Variant::OBJECT && pi.usage & PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT) { + Object *prop = ClassDB::instance(pi.class_name); + obj->set(pi.name, prop); } } @@ -555,29 +448,18 @@ Object *CreateDialog::instance_selected() { } void CreateDialog::_item_selected() { - TreeItem *item = search_options->get_selected(); - if (!item) { - return; - } - - String name = item->get_text(0); - - favorite->set_disabled(false); - favorite->set_pressed(favorite_list.find(name) != -1); - - if (!EditorHelp::get_doc_data()->class_list.has(name)) { - return; - } - - help_bit->set_text(DTR(EditorHelp::get_doc_data()->class_list[name].brief_description)); - - get_ok()->set_disabled(false); + String name = get_selected_type(); + select_type(name); } void CreateDialog::_hide_requested() { _cancel_pressed(); // From AcceptDialog. } +void CreateDialog::cancel_pressed() { + _cleanup(); +} + void CreateDialog::_favorite_toggled() { TreeItem *item = search_options->get_selected(); if (!item) { @@ -597,50 +479,8 @@ void CreateDialog::_favorite_toggled() { _save_and_update_favorite_list(); } -void CreateDialog::_save_favorite_list() { - FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE); - - if (f) { - for (int i = 0; i < favorite_list.size(); 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); - } -} - -void CreateDialog::_update_favorite_list() { - favorites->clear(); - - TreeItem *root = favorites->create_item(); - - String icon_fallback = search_options->has_theme_icon(base_type, "EditorIcons") ? base_type : "Object"; - - for (int i = 0; i < favorite_list.size(); i++) { - String l = favorite_list[i]; - String name = l.split(" ")[0]; - if (!((ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) && !_is_class_disabled_by_feature_profile(name))) { - continue; - } - - TreeItem *ti = favorites->create_item(root); - ti->set_text(0, l); - ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback)); - } - emit_signal("favorites_updated"); -} - -void CreateDialog::_history_selected() { - TreeItem *item = recent->get_selected(); - if (!item) { - return; - } - - search_box->set_text(item->get_text(0).get_slicec(' ', 0)); +void CreateDialog::_history_selected(int p_idx) { + search_box->set_text(recent->get_item_text(p_idx).get_slicec(' ', 0)); favorites->deselect_all(); _update_search(); } @@ -652,12 +492,12 @@ void CreateDialog::_favorite_selected() { } search_box->set_text(item->get_text(0).get_slicec(' ', 0)); - recent->deselect_all(); + recent->unselect_all(); _update_search(); } -void CreateDialog::_history_activated() { - _history_selected(); +void CreateDialog::_history_activated(int p_idx) { + _history_selected(p_idx); _confirmed(); } @@ -740,8 +580,61 @@ void CreateDialog::drop_data_fw(const Point2 &p_point, const Variant &p_data, Co } void CreateDialog::_save_and_update_favorite_list() { - _save_favorite_list(); - _update_favorite_list(); + favorites->clear(); + TreeItem *root = favorites->create_item(); + + FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE); + if (f) { + for (int i = 0; i < favorite_list.size(); i++) { + String l = favorite_list[i]; + String name = l.get_slicec(' ', 0); + if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) { + continue; + } + f->store_line(l); + + if (_is_class_disabled_by_feature_profile(name)) { + continue; + } + + TreeItem *ti = favorites->create_item(root); + ti->set_text(0, l); + ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback)); + } + memdelete(f); + } + + emit_signal("favorites_updated"); +} + +void CreateDialog::_load_favorites_and_history() { + String dir = EditorSettings::get_singleton()->get_project_settings_dir(); + FileAccess *f = FileAccess::open(dir.plus_file("create_recent." + base_type), FileAccess::READ); + if (f) { + while (!f->eof_reached()) { + String l = f->get_line().strip_edges(); + String name = l.get_slicec(' ', 0); + + if ((ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) && !_is_class_disabled_by_feature_profile(name)) { + recent->add_item(l, EditorNode::get_singleton()->get_class_icon(name, icon_fallback)); + } + } + + memdelete(f); + } + + f = FileAccess::open(dir.plus_file("favorites." + base_type), FileAccess::READ); + if (f) { + while (!f->eof_reached()) { + String l = f->get_line().strip_edges(); + + if (l != String()) { + favorite_list.push_back(l); + } + } + + memdelete(f); + } } void CreateDialog::_bind_methods() { @@ -756,7 +649,11 @@ void CreateDialog::_bind_methods() { } CreateDialog::CreateDialog() { - is_replace_mode = false; + base_type = "Object"; + preferred_search_result_type = ""; + + type_blacklist.insert("PluginScript"); // PluginScript must be initialized before use, which is not possible here. + type_blacklist.insert("ScriptCreateDialog"); // This is an exposed editor Node that doesn't have an Editor prefix. HSplitContainer *hsc = memnew(HSplitContainer); add_child(hsc); @@ -765,67 +662,64 @@ CreateDialog::CreateDialog() { hsc->add_child(vsc); VBoxContainer *fav_vb = memnew(VBoxContainer); - vsc->add_child(fav_vb); fav_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE); fav_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL); + vsc->add_child(fav_vb); favorites = memnew(Tree); - fav_vb->add_margin_child(TTR("Favorites:"), favorites, true); favorites->set_hide_root(true); favorites->set_hide_folding(true); favorites->set_allow_reselect(true); favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected)); favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated)); + favorites->add_theme_constant_override("draw_guides", 1); #ifndef _MSC_VER #warning cant forward drag data to a non control, must be fixed #endif //favorites->set_drag_forwarding(this); - favorites->add_theme_constant_override("draw_guides", 1); + fav_vb->add_margin_child(TTR("Favorites:"), favorites, true); VBoxContainer *rec_vb = memnew(VBoxContainer); vsc->add_child(rec_vb); rec_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE); rec_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL); - recent = memnew(Tree); + recent = memnew(ItemList); rec_vb->add_margin_child(TTR("Recent:"), recent, true); - recent->set_hide_root(true); - recent->set_hide_folding(true); recent->set_allow_reselect(true); - recent->connect("cell_selected", callable_mp(this, &CreateDialog::_history_selected)); + recent->connect("item_selected", callable_mp(this, &CreateDialog::_history_selected)); recent->connect("item_activated", callable_mp(this, &CreateDialog::_history_activated)); recent->add_theme_constant_override("draw_guides", 1); VBoxContainer *vbc = memnew(VBoxContainer); - hsc->add_child(vbc); vbc->set_custom_minimum_size(Size2(300, 0) * EDSCALE); vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); - HBoxContainer *search_hb = memnew(HBoxContainer); + hsc->add_child(vbc); + search_box = memnew(LineEdit); search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + search_box->connect("text_changed", callable_mp(this, &CreateDialog::_text_changed)); + search_box->connect("gui_input", callable_mp(this, &CreateDialog::_sbox_input)); + + HBoxContainer *search_hb = memnew(HBoxContainer); search_hb->add_child(search_box); + favorite = memnew(Button); favorite->set_flat(true); favorite->set_toggle_mode(true); - search_hb->add_child(favorite); favorite->connect("pressed", callable_mp(this, &CreateDialog::_favorite_toggled)); + search_hb->add_child(favorite); vbc->add_margin_child(TTR("Search:"), search_hb); - search_box->connect("text_changed", callable_mp(this, &CreateDialog::_text_changed)); - search_box->connect("gui_input", callable_mp(this, &CreateDialog::_sbox_input)); + search_options = memnew(Tree); - vbc->add_margin_child(TTR("Matches:"), search_options, true); - get_ok()->set_disabled(true); - register_text_enter(search_box); - set_hide_on_ok(false); search_options->connect("item_activated", callable_mp(this, &CreateDialog::_confirmed)); search_options->connect("cell_selected", callable_mp(this, &CreateDialog::_item_selected)); - base_type = "Object"; - preferred_search_result_type = ""; + vbc->add_margin_child(TTR("Matches:"), search_options, true); help_bit = memnew(EditorHelpBit); - vbc->add_margin_child(TTR("Description:"), help_bit); help_bit->connect("request_hide", callable_mp(this, &CreateDialog::_hide_requested)); + vbc->add_margin_child(TTR("Description:"), help_bit); - type_blacklist.insert("PluginScript"); // PluginScript must be initialized before use, which is not possible here - type_blacklist.insert("ScriptCreateDialog"); // This is an exposed editor Node that doesn't have an Editor prefix. + register_text_enter(search_box); + set_hide_on_ok(false); } diff --git a/editor/create_dialog.h b/editor/create_dialog.h index cdc91ae535..52eb9945af 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -35,60 +35,65 @@ #include "scene/gui/button.h" #include "scene/gui/dialogs.h" #include "scene/gui/item_list.h" -#include "scene/gui/label.h" #include "scene/gui/line_edit.h" #include "scene/gui/tree.h" class CreateDialog : public ConfirmationDialog { GDCLASS(CreateDialog, ConfirmationDialog); - Vector<String> favorite_list; - Tree *favorites; - Tree *recent; - - Button *favorite; LineEdit *search_box; Tree *search_options; - HashMap<String, TreeItem *> search_options_types; - HashMap<String, RES> search_loaded_scripts; - bool is_replace_mode; + String base_type; + String icon_fallback; String preferred_search_result_type; + + Button *favorite; + Vector<String> favorite_list; + Tree *favorites; + ItemList *recent; EditorHelpBit *help_bit; + + HashMap<String, TreeItem *> search_options_types; + HashMap<String, String> custom_type_parents; + HashMap<String, int> custom_type_indices; List<StringName> type_list; Set<StringName> type_blacklist; - void _item_selected(); - void _hide_requested(); - void _update_search(); - void _update_favorite_list(); - void _save_favorite_list(); - void _favorite_toggled(); + bool _should_hide_type(const String &p_type) const; + void _add_type(const String &p_current, bool p_cpp_type); + void _configure_search_option_item(TreeItem *r_item, const String &p_type, const bool p_cpp_type); + String _top_result(const Vector<String> p_candidates, const String &p_search_text) const; + float _score_type(const String &p_type, const String &p_search) const; + bool _is_type_preferred(const String &p_type) const; - void _history_selected(); - void _favorite_selected(); - - void _history_activated(); - void _favorite_activated(); + void _fill_type_list(); + void _cleanup(); void _sbox_input(const Ref<InputEvent> &p_ie); + void _text_changed(const String &p_newtext); + void select_type(const String &p_type); + void _item_selected(); + void _hide_requested(); void _confirmed(); - void _text_changed(const String &p_newtext); + virtual void cancel_pressed(); - Ref<Texture2D> _get_editor_icon(const String &p_type) const; + void _favorite_toggled(); - void add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root, TreeItem **to_select); + void _history_selected(int p_idx); + void _favorite_selected(); - void select_type(const String &p_type); + void _history_activated(int p_idx); + void _favorite_activated(); Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); - bool _is_class_disabled_by_feature_profile(const StringName &p_class); - bool _is_type_prefered(const String &type); + bool _is_class_disabled_by_feature_profile(const StringName &p_class) const; + void _load_favorites_and_history(); protected: void _notification(int p_what); @@ -100,11 +105,11 @@ public: Object *instance_selected(); String get_selected_type(); - void set_base_type(const String &p_base); - String get_base_type() const; + void set_base_type(const String &p_base) { base_type = p_base; } + String get_base_type() const { return base_type; } - void set_preferred_search_result_type(const String &p_preferred_type); - String get_preferred_search_result_type(); + void set_preferred_search_result_type(const String &p_preferred_type) { preferred_search_result_type = p_preferred_type; } + String get_preferred_search_result_type() { return preferred_search_result_type; } void popup_create(bool p_dont_clear, bool p_replace_mode = false, const String &p_select_type = "Node"); diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp new file mode 100644 index 0000000000..47fe282758 --- /dev/null +++ b/editor/debugger/editor_performance_profiler.cpp @@ -0,0 +1,394 @@ +/*************************************************************************/ +/* editor_performance_profiler.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "editor_performance_profiler.h" + +#include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "main/performance.h" + +EditorPerformanceProfiler::Monitor::Monitor() {} + +EditorPerformanceProfiler::Monitor::Monitor(String p_name, String p_base, int p_frame_index, Performance::MonitorType p_type, TreeItem *p_item) { + type = p_type; + item = p_item; + frame_index = p_frame_index; + name = p_name; + base = p_base; +} + +void EditorPerformanceProfiler::Monitor::update_value(float p_value) { + ERR_FAIL_COND(!item); + String label = EditorPerformanceProfiler::_create_label(p_value, type); + String tooltip = label; + switch (type) { + case Performance::MONITOR_TYPE_MEMORY: { + tooltip = label; + } break; + case Performance::MONITOR_TYPE_TIME: { + tooltip = label; + } break; + default: { + tooltip += " " + item->get_text(0); + } break; + } + item->set_text(1, label); + item->set_tooltip(1, tooltip); + + if (p_value > max) { + max = p_value; + } +} + +void EditorPerformanceProfiler::Monitor::reset() { + history.clear(); + max = 0.0f; + if (item) { + item->set_text(1, ""); + item->set_tooltip(1, ""); + } +} + +String EditorPerformanceProfiler::_create_label(float p_value, Performance::MonitorType p_type) { + switch (p_type) { + case Performance::MONITOR_TYPE_MEMORY: { + return String::humanize_size(p_value); + } + case Performance::MONITOR_TYPE_TIME: { + return rtos(p_value * 1000).pad_decimals(2) + " ms"; + } + default: { + return rtos(p_value); + } + } +} + +void EditorPerformanceProfiler::_monitor_select() { + monitor_draw->update(); +} + +void EditorPerformanceProfiler::_monitor_draw() { + Vector<StringName> active; + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (i.value().item->is_checked(0)) { + active.push_back(i.key()); + } + } + + if (active.empty()) { + info_message->show(); + return; + } + + info_message->hide(); + + Ref<StyleBox> graph_style_box = get_theme_stylebox("normal", "TextEdit"); + Ref<Font> graph_font = get_theme_font("font", "TextEdit"); + + int columns = int(Math::ceil(Math::sqrt(float(active.size())))); + int rows = int(Math::ceil(float(active.size()) / float(columns))); + if (active.size() == 1) { + rows = 1; + } + Size2i cell_size = Size2i(monitor_draw->get_size()) / Size2i(columns, rows); + float spacing = float(POINT_SEPARATION) / float(columns); + float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4f : 0.55f; + float hue_shift = 1.0f / float(monitors.size()); + + for (int i = 0; i < active.size(); i++) { + Monitor ¤t = monitors[active[i]]; + Rect2i rect(Point2i(i % columns, i / columns) * cell_size + Point2i(MARGIN, MARGIN), cell_size - Point2i(MARGIN, MARGIN) * 2); + monitor_draw->draw_style_box(graph_style_box, rect); + + rect.position += graph_style_box->get_offset(); + rect.size -= graph_style_box->get_minimum_size(); + Color draw_color = get_theme_color("accent_color", "Editor"); + draw_color.set_hsv(Math::fmod(hue_shift * float(current.frame_index), 0.9f), draw_color.get_s() * 0.9f, draw_color.get_v() * value_multiplier, 0.6f); + monitor_draw->draw_string(graph_font, rect.position + Point2(0, graph_font->get_ascent()), current.item->get_text(0), draw_color, rect.size.x); + + draw_color.a = 0.9f; + float value_position = rect.size.width - graph_font->get_string_size(current.item->get_text(1)).width; + if (value_position < 0) { + value_position = 0; + } + monitor_draw->draw_string(graph_font, rect.position + Point2(value_position, graph_font->get_ascent()), current.item->get_text(1), draw_color, rect.size.x); + + rect.position.y += graph_font->get_height(); + rect.size.height -= graph_font->get_height(); + + int line_count = rect.size.height / (graph_font->get_height() * 2); + if (line_count > 5) { + line_count = 5; + } + if (line_count > 0) { + Color horizontal_line_color; + horizontal_line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.5f, draw_color.get_v() * 0.5f, 0.3f); + monitor_draw->draw_line(rect.position, rect.position + Vector2(rect.size.width, 0), horizontal_line_color, Math::round(EDSCALE)); + monitor_draw->draw_string(graph_font, rect.position + Vector2(0, graph_font->get_ascent()), _create_label(current.max, current.type), horizontal_line_color, rect.size.width); + + for (int j = 0; j < line_count; j++) { + Vector2 y_offset = Vector2(0, rect.size.height * (1.0f - float(j) / float(line_count))); + monitor_draw->draw_line(rect.position + y_offset, rect.position + Vector2(rect.size.width, 0) + y_offset, horizontal_line_color, Math::round(EDSCALE)); + monitor_draw->draw_string(graph_font, rect.position - Vector2(0, graph_font->get_descent()) + y_offset, _create_label(current.max * float(j) / float(line_count), current.type), horizontal_line_color, rect.size.width); + } + } + + float from = rect.size.width; + float prev = -1.0f; + int count = 0; + List<float>::Element *e = current.history.front(); + + while (from >= 0 && e) { + float m = current.max; + float h2 = 0; + if (m != 0) { + h2 = (e->get() / m); + } + h2 = (1.0f - h2) * float(rect.size.y); + if (e != current.history.front()) { + monitor_draw->draw_line(rect.position + Point2(from, h2), rect.position + Point2(from + spacing, prev), draw_color, Math::round(EDSCALE)); + } + + if (marker_key == active[i] && count == marker_frame) { + Color line_color; + line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.8f, draw_color.get_v(), 0.5f); + monitor_draw->draw_line(rect.position + Point2(from, 0), rect.position + Point2(from, rect.size.y), line_color, Math::round(EDSCALE)); + + String label = _create_label(e->get(), current.type); + Size2 size = graph_font->get_string_size(label); + Vector2 text_top_left_position = Vector2(from, h2) - (size + Vector2(MARKER_MARGIN, MARKER_MARGIN)); + if (text_top_left_position.x < 0) { + text_top_left_position.x = from + MARKER_MARGIN; + } + if (text_top_left_position.y < 0) { + text_top_left_position.y = h2 + MARKER_MARGIN; + } + monitor_draw->draw_string(graph_font, rect.position + text_top_left_position + Point2(0, graph_font->get_ascent()), label, line_color, rect.size.x); + } + prev = h2; + e = e->next(); + from -= spacing; + count++; + } + } +} + +void EditorPerformanceProfiler::_build_monitor_tree() { + Set<StringName> monitor_checked; + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (i.value().item && i.value().item->is_checked(0)) { + monitor_checked.insert(i.key()); + } + } + + base_map.clear(); + monitor_tree->get_root()->clear_children(); + + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + TreeItem *base = _get_monitor_base(i.value().base); + TreeItem *item = _create_monitor_item(i.value().name, base); + item->set_checked(0, monitor_checked.has(i.key())); + i.value().item = item; + if (!i.value().history.empty()) { + i.value().update_value(i.value().history.front()->get()); + } + } +} + +TreeItem *EditorPerformanceProfiler::_get_monitor_base(const StringName &p_base_name) { + if (base_map.has(p_base_name)) { + return base_map[p_base_name]; + } + + TreeItem *base = monitor_tree->create_item(monitor_tree->get_root()); + base->set_text(0, p_base_name); + base->set_editable(0, false); + base->set_selectable(0, false); + base->set_expand_right(0, true); + base_map.insert(p_base_name, base); + return base; +} + +TreeItem *EditorPerformanceProfiler::_create_monitor_item(const StringName &p_monitor_name, TreeItem *p_base) { + TreeItem *item = monitor_tree->create_item(p_base); + item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + item->set_editable(0, true); + item->set_selectable(0, false); + item->set_selectable(1, false); + item->set_text(0, p_monitor_name); + return item; +} + +void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + Vector<StringName> active; + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (i.value().item->is_checked(0)) { + active.push_back(i.key()); + } + } + if (active.size() > 0) { + int columns = int(Math::ceil(Math::sqrt(float(active.size())))); + int rows = int(Math::ceil(float(active.size()) / float(columns))); + if (active.size() == 1) { + rows = 1; + } + Size2i cell_size = Size2i(monitor_draw->get_size()) / Size2i(columns, rows); + Vector2i index = mb->get_position() / cell_size; + Rect2i rect(index * cell_size + Point2i(MARGIN, MARGIN), cell_size - Point2i(MARGIN, MARGIN) * 2); + if (rect.has_point(mb->get_position())) { + if (index.x + index.y * columns < active.size()) { + marker_key = active[index.x + index.y * columns]; + } else { + marker_key = ""; + } + Ref<StyleBox> graph_style_box = get_theme_stylebox("normal", "TextEdit"); + rect.position += graph_style_box->get_offset(); + rect.size -= graph_style_box->get_minimum_size(); + Vector2 point = mb->get_position() - rect.position; + if (point.x >= rect.size.x) { + marker_frame = 0; + } else { + int point_sep = 5; + float spacing = float(point_sep) / float(columns); + marker_frame = (rect.size.x - point.x) / spacing; + } + monitor_draw->update(); + return; + } + } + marker_key = ""; + monitor_draw->update(); + } +} + +void EditorPerformanceProfiler::reset() { + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (String(i.key()).begins_with("custom:")) { + monitors.erase(i); + } else { + i.value().reset(); + } + } + + _build_monitor_tree(); + marker_key = ""; + marker_frame = 0; + monitor_draw->update(); +} + +void EditorPerformanceProfiler::update_monitors(const Vector<StringName> &p_names) { + OrderedHashMap<StringName, int> names; + for (int i = 0; i < p_names.size(); i++) { + names.insert("custom:" + p_names[i], Performance::MONITOR_MAX + i); + } + + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (String(i.key()).begins_with("custom:")) { + if (!names.has(i.key())) { + monitors.erase(i); + } else { + i.value().frame_index = names[i.key()]; + names.erase(i.key()); + } + } + } + + for (OrderedHashMap<StringName, int>::Element i = names.front(); i; i = i.next()) { + String name = String(i.key()).replace_first("custom:", ""); + String base = "Custom"; + if (name.get_slice_count("/") == 2) { + base = name.get_slicec('/', 0); + name = name.get_slicec('/', 1); + } + monitors.insert(i.key(), Monitor(name, base, i.value(), Performance::MONITOR_TYPE_QUANTITY, nullptr)); + } + + _build_monitor_tree(); +} + +void EditorPerformanceProfiler::add_profile_frame(const Vector<float> &p_values) { + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + float data = 0.0f; + if (i.value().frame_index >= 0 && i.value().frame_index < p_values.size()) { + data = p_values[i.value().frame_index]; + } + i.value().history.push_front(data); + i.value().update_value(data); + } + marker_frame++; + monitor_draw->update(); +} + +List<float> *EditorPerformanceProfiler::get_monitor_data(const StringName &p_name) { + if (monitors.has(p_name)) { + return &monitors[p_name].history; + } + return nullptr; +} + +EditorPerformanceProfiler::EditorPerformanceProfiler() { + set_name(TTR("Monitors")); + set_split_offset(340 * EDSCALE); + + monitor_tree = memnew(Tree); + monitor_tree->set_columns(2); + monitor_tree->set_column_title(0, TTR("Monitor")); + monitor_tree->set_column_title(1, TTR("Value")); + monitor_tree->set_column_titles_visible(true); + monitor_tree->connect("item_edited", callable_mp(this, &EditorPerformanceProfiler::_monitor_select)); + monitor_tree->create_item(); + monitor_tree->set_hide_root(true); + add_child(monitor_tree); + + monitor_draw = memnew(Control); + monitor_draw->set_clip_contents(true); + monitor_draw->connect("draw", callable_mp(this, &EditorPerformanceProfiler::_monitor_draw)); + monitor_draw->connect("gui_input", callable_mp(this, &EditorPerformanceProfiler::_marker_input)); + add_child(monitor_draw); + + info_message = memnew(Label); + info_message->set_text(TTR("Pick one or more items from the list to display the graph.")); + info_message->set_valign(Label::VALIGN_CENTER); + info_message->set_align(Label::ALIGN_CENTER); + info_message->set_autowrap(true); + info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + monitor_draw->add_child(info_message); + + for (int i = 0; i < Performance::MONITOR_MAX; i++) { + String base = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)).get_slicec('/', 0).capitalize(); + String name = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)).get_slicec('/', 1).capitalize(); + monitors.insert(Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)), Monitor(name, base, i, Performance::get_singleton()->get_monitor_type(Performance::Monitor(i)), nullptr)); + } + + _build_monitor_tree(); +} diff --git a/editor/debugger/editor_performance_profiler.h b/editor/debugger/editor_performance_profiler.h new file mode 100644 index 0000000000..144dd34103 --- /dev/null +++ b/editor/debugger/editor_performance_profiler.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* editor_performance_profiler.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 EDITOR_PERFORMANCE_PROFILER_H +#define EDITOR_PERFORMANCE_PROFILER_H + +#include "core/map.h" +#include "core/ordered_hash_map.h" +#include "main/performance.h" +#include "scene/gui/control.h" +#include "scene/gui/label.h" +#include "scene/gui/split_container.h" +#include "scene/gui/tree.h" + +class EditorPerformanceProfiler : public HSplitContainer { + GDCLASS(EditorPerformanceProfiler, HSplitContainer); + +private: + class Monitor { + public: + String name; + String base; + List<float> history; + float max = 0.0f; + TreeItem *item = nullptr; + Performance::MonitorType type = Performance::MONITOR_TYPE_QUANTITY; + int frame_index = 0; + + Monitor(); + Monitor(String p_name, String p_base, int p_frame_index, Performance::MonitorType p_type, TreeItem *p_item); + void update_value(float p_value); + void reset(); + }; + + OrderedHashMap<StringName, Monitor> monitors; + + Map<StringName, TreeItem *> base_map; + Tree *monitor_tree; + Control *monitor_draw; + Label *info_message; + StringName marker_key; + int marker_frame; + const int MARGIN = 4; + const int POINT_SEPARATION = 5; + const int MARKER_MARGIN = 2; + + static String _create_label(float p_value, Performance::MonitorType p_type); + void _monitor_select(); + void _monitor_draw(); + void _build_monitor_tree(); + TreeItem *_get_monitor_base(const StringName &p_base_name); + TreeItem *_create_monitor_item(const StringName &p_monitor_name, TreeItem *p_base); + void _marker_input(const Ref<InputEvent> &p_event); + +public: + void reset(); + void update_monitors(const Vector<StringName> &p_names); + void add_profile_frame(const Vector<float> &p_values); + List<float> *get_monitor_data(const StringName &p_name); + EditorPerformanceProfiler(); +}; + +#endif // EDITOR_PERFORMANCE_PROFILER_H diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index a042afc788..a828e29558 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -36,6 +36,7 @@ #include "core/project_settings.h" #include "core/ustring.h" #include "editor/debugger/editor_network_profiler.h" +#include "editor/debugger/editor_performance_profiler.h" #include "editor/debugger/editor_profiler.h" #include "editor/debugger/editor_visual_profiler.h" #include "editor/editor_log.h" @@ -172,14 +173,25 @@ void ScriptEditorDebugger::_file_selected(const String &p_file) { file->store_csv_line(line); // values - List<Vector<float>>::Element *E = perf_history.back(); - while (E) { - Vector<float> &perf_data = E->get(); - for (int i = 0; i < perf_data.size(); i++) { - line.write[i] = String::num_real(perf_data[i]); + Vector<List<float>::Element *> iterators; + iterators.resize(Performance::MONITOR_MAX); + bool continue_iteration = false; + for (int i = 0; i < Performance::MONITOR_MAX; i++) { + iterators.write[i] = performance_profiler->get_monitor_data(Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)))->back(); + continue_iteration = continue_iteration || iterators[i]; + } + while (continue_iteration) { + continue_iteration = false; + for (int i = 0; i < Performance::MONITOR_MAX; i++) { + if (iterators[i]) { + line.write[i] = String::num_real(iterators[i]->get()); + iterators.write[i] = iterators[i]->prev(); + } else { + line.write[i] = ""; + } + continue_iteration = continue_iteration || iterators[i]; } file->store_csv_line(line); - E = E->prev(); } file->store_string("\n"); @@ -409,37 +421,12 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da EditorNode::get_log()->add_message(output_strings[i], msg_type); } } else if (p_msg == "performance:profile_frame") { - Vector<float> p; - p.resize(p_data.size()); + Vector<float> frame_data; + frame_data.resize(p_data.size()); for (int i = 0; i < p_data.size(); i++) { - p.write[i] = p_data[i]; - if (i < perf_items.size()) { - const float value = p[i]; - String label = rtos(value); - String tooltip = label; - switch (Performance::MonitorType((int)perf_items[i]->get_metadata(1))) { - case Performance::MONITOR_TYPE_MEMORY: { - label = String::humanize_size(value); - tooltip = label; - } break; - case Performance::MONITOR_TYPE_TIME: { - label = rtos(value * 1000).pad_decimals(2) + " ms"; - tooltip = label; - } break; - default: { - tooltip += " " + perf_items[i]->get_text(0); - } break; - } - - perf_items[i]->set_text(1, label); - perf_items[i]->set_tooltip(1, tooltip); - if (p[i] > perf_max[i]) { - perf_max.write[i] = p[i]; - } - } + frame_data.write[i] = p_data[i]; } - perf_history.push_front(p); - perf_draw->update(); + performance_profiler->add_profile_frame(frame_data); } else if (p_msg == "visual:profile_frame") { DebuggerMarshalls::VisualProfilerFrame frame; @@ -704,6 +691,15 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da emit_signal("stop_requested"); _stop_and_notify(); + } else if (p_msg == "performance:profile_names") { + Vector<StringName> monitors; + monitors.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + ERR_FAIL_COND(p_data[i].get_type() != Variant::STRING_NAME); + monitors.set(i, p_data[i]); + } + performance_profiler->update_monitors(monitors); + } else { WARN_PRINT("unknown message " + p_msg); } @@ -724,80 +720,6 @@ void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType reason->set_tooltip(p_reason.word_wrap(80)); } -void ScriptEditorDebugger::_performance_select() { - perf_draw->update(); -} - -void ScriptEditorDebugger::_performance_draw() { - Vector<int> which; - for (int i = 0; i < perf_items.size(); i++) { - if (perf_items[i]->is_checked(0)) { - which.push_back(i); - } - } - - if (which.empty()) { - info_message->show(); - return; - } - - info_message->hide(); - - Ref<StyleBox> graph_sb = get_theme_stylebox("normal", "TextEdit"); - Ref<Font> graph_font = get_theme_font("font", "TextEdit"); - - int cols = Math::ceil(Math::sqrt((float)which.size())); - int rows = Math::ceil((float)which.size() / cols); - if (which.size() == 1) { - rows = 1; - } - - int margin = 3; - int point_sep = 5; - Size2i s = Size2i(perf_draw->get_size()) / Size2i(cols, rows); - for (int i = 0; i < which.size(); i++) { - Point2i p(i % cols, i / cols); - Rect2i r(p * s, s); - r.position += Point2(margin, margin); - r.size -= Point2(margin, margin) * 2.0; - perf_draw->draw_style_box(graph_sb, r); - r.position += graph_sb->get_offset(); - r.size -= graph_sb->get_minimum_size(); - int pi = which[i]; - Color c = get_theme_color("accent_color", "Editor"); - float h = (float)which[i] / (float)(perf_items.size()); - // Use a darker color on light backgrounds for better visibility - float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4 : 0.55; - c.set_hsv(Math::fmod(h + 0.4, 0.9), c.get_s() * 0.9, c.get_v() * value_multiplier); - - c.a = 0.6; - perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent()), perf_items[pi]->get_text(0), c, r.size.x); - c.a = 0.9; - perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent() + graph_font->get_height()), perf_items[pi]->get_text(1), c, r.size.y); - - float spacing = point_sep / float(cols); - float from = r.size.width; - - List<Vector<float>>::Element *E = perf_history.front(); - float prev = -1; - while (from >= 0 && E) { - float m = perf_max[pi]; - if (m == 0) { - m = 0.00001; - } - float h2 = E->get()[pi] / m; - h2 = (1.0 - h2) * r.size.y; - - if (E != perf_history.front()) { - perf_draw->draw_line(r.position + Point2(from, h2), r.position + Point2(from + spacing, prev), c, Math::round(EDSCALE)); - } - prev = h2; - E = E->next(); - from -= spacing; - } - } -} - void ScriptEditorDebugger::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -915,10 +837,7 @@ void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) { peer = p_peer; ERR_FAIL_COND(p_peer.is_null()); - perf_history.clear(); - for (int i = 0; i < Performance::MONITOR_MAX; i++) { - perf_max.write[i] = 0; - } + performance_profiler->reset(); set_process(true); breaked = false; @@ -1666,63 +1585,8 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { } { //monitors - - HSplitContainer *hsp = memnew(HSplitContainer); - - perf_monitors = memnew(Tree); - perf_monitors->set_columns(2); - perf_monitors->set_column_title(0, TTR("Monitor")); - perf_monitors->set_column_title(1, TTR("Value")); - perf_monitors->set_column_titles_visible(true); - perf_monitors->connect("item_edited", callable_mp(this, &ScriptEditorDebugger::_performance_select)); - hsp->add_child(perf_monitors); - - perf_draw = memnew(Control); - perf_draw->set_clip_contents(true); - perf_draw->connect("draw", callable_mp(this, &ScriptEditorDebugger::_performance_draw)); - hsp->add_child(perf_draw); - - hsp->set_name(TTR("Monitors")); - hsp->set_split_offset(340 * EDSCALE); - tabs->add_child(hsp); - perf_max.resize(Performance::MONITOR_MAX); - - Map<String, TreeItem *> bases; - TreeItem *root = perf_monitors->create_item(); - perf_monitors->set_hide_root(true); - for (int i = 0; i < Performance::MONITOR_MAX; i++) { - String n = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)); - Performance::MonitorType mtype = Performance::get_singleton()->get_monitor_type(Performance::Monitor(i)); - String base = n.get_slice("/", 0); - String name = n.get_slice("/", 1); - if (!bases.has(base)) { - TreeItem *b = perf_monitors->create_item(root); - b->set_text(0, base.capitalize()); - b->set_editable(0, false); - b->set_selectable(0, false); - b->set_expand_right(0, true); - bases[base] = b; - } - - TreeItem *it = perf_monitors->create_item(bases[base]); - it->set_metadata(1, mtype); - it->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - it->set_editable(0, true); - it->set_selectable(0, false); - it->set_selectable(1, false); - it->set_text(0, name.capitalize()); - perf_items.push_back(it); - perf_max.write[i] = 0; - } - - info_message = memnew(Label); - info_message->set_text(TTR("Pick one or more items from the list to display the graph.")); - info_message->set_valign(Label::VALIGN_CENTER); - info_message->set_align(Label::ALIGN_CENTER); - info_message->set_autowrap(true); - info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); - perf_draw->add_child(info_message); + performance_profiler = memnew(EditorPerformanceProfiler); + tabs->add_child(performance_profiler); } { //vmem inspect diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index 2984051aa1..12fb82cc6f 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -52,6 +52,7 @@ class ItemList; class EditorProfiler; class EditorVisualProfiler; class EditorNetworkProfiler; +class EditorPerformanceProfiler; class SceneDebuggerTree; class ScriptEditorDebugger : public MarginContainer { @@ -113,16 +114,8 @@ private: // Each debugger should have it's tree in the future I guess. const Tree *editor_remote_tree = nullptr; - List<Vector<float>> perf_history; - Vector<float> perf_max; - Vector<TreeItem *> perf_items; - Map<int, String> profiler_signature; - Tree *perf_monitors; - Control *perf_draw; - Label *info_message; - Tree *vmem_tree; Button *vmem_refresh; Button *vmem_export; @@ -141,6 +134,7 @@ private: EditorProfiler *profiler; EditorVisualProfiler *visual_profiler; EditorNetworkProfiler *network_profiler; + EditorPerformanceProfiler *performance_profiler; EditorNode *editor; @@ -152,8 +146,6 @@ private: EditorDebuggerNode::CameraOverride camera_override; - void _performance_draw(); - void _performance_select(); void _stack_dump_frame_selected(); void _file_selected(const String &p_file); diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index b43ee0e245..edb299bb90 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -159,7 +159,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { isdir = true; } - int pp = path.find_last("/"); + int pp = path.rfind("/"); TreeItem *parent; if (pp == -1) { diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index da0ff9f18f..4cd4f68fa2 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -477,6 +477,8 @@ void EditorAutoloadSettings::update_autoload() { info.node->queue_delete(); info.node = nullptr; } + + ProjectSettings::get_singleton()->remove_autoload(info.name); } // Load new/changed autoloads @@ -503,6 +505,12 @@ void EditorAutoloadSettings::update_autoload() { } } + ProjectSettings::AutoloadInfo prop_info; + prop_info.name = info->name; + prop_info.path = info->path; + prop_info.is_singleton = info->is_singleton; + ProjectSettings::get_singleton()->add_autoload(prop_info); + if (!info->in_editor && !info->is_singleton) { // No reason to keep this node memdelete(info->node); diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 2a410c03e7..0d349eb247 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -335,7 +335,7 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr } if (!d->current_is_dir()) { - int last_pos = f.find_last(".profile"); + int last_pos = f.rfind(".profile"); if (last_pos != -1) { profiles.push_back(f.substr(0, last_pos)); } diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 663f3dd856..50be291c91 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -55,7 +55,7 @@ VBoxContainer *EditorFileDialog::get_vbox() { } void EditorFileDialog::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { + if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_THEME_CHANGED) { // update icons mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons")); mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons")); @@ -936,7 +936,7 @@ void EditorFileDialog::set_current_file(const String &p_file) { file->set_text(p_file); update_dir(); invalidate(); - int lp = p_file.find_last("."); + int lp = p_file.rfind("."); if (lp != -1) { file->select(0, lp); file->grab_focus(); @@ -951,7 +951,7 @@ void EditorFileDialog::set_current_path(const String &p_path) { if (!p_path.size()) { return; } - int pos = MAX(p_path.find_last("/"), p_path.find_last("\\")); + int pos = MAX(p_path.rfind("/"), p_path.rfind("\\")); if (pos == -1) { set_current_file(p_path); } else { diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index d88c61d7b2..e367ed4989 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -233,9 +233,9 @@ void EditorFileSystem::_scan_filesystem() { FileCache fc; fc.type = split[1]; - fc.modification_time = split[2].to_int64(); - fc.import_modification_time = split[3].to_int64(); - fc.import_valid = split[4].to_int64() != 0; + fc.modification_time = split[2].to_int(); + fc.import_modification_time = split[3].to_int(); + fc.import_valid = split[4].to_int() != 0; fc.import_group_file = split[5].strip_edges(); fc.script_class_name = split[6].get_slice("<>", 0); fc.script_class_extends = split[6].get_slice("<>", 1); @@ -1107,7 +1107,7 @@ void EditorFileSystem::_notification(int p_what) { _queue_update_script_classes(); first_scan = false; } - } else if (!scanning) { + } else if (!scanning && thread) { set_process(false); if (filesystem) { diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp index f0e6e3a799..a7e76e9b2b 100644 --- a/editor/editor_folding.cpp +++ b/editor/editor_folding.cpp @@ -251,7 +251,7 @@ void EditorFolding::_do_object_unfolds(Object *p_object, Set<RES> &resources) { } } } else { //path - int last = E->get().name.find_last("/"); + int last = E->get().name.rfind("/"); if (last != -1) { bool can_revert = EditorPropertyRevert::can_property_revert(p_object, E->get().name); if (can_revert) { diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index cf00c536a7..100c76c32b 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -231,7 +231,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { // Default font MAKE_DEFAULT_FONT(df, default_font_size); - p_theme->set_font("font", "Node", df); // Default theme font + p_theme->set_default_font(df); // Default theme font p_theme->set_font("main", "EditorFonts", df); // Bold font diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index d2b9405552..4392538737 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -332,17 +332,10 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { if (search_flags & SEARCH_METHODS) { for (int i = 0; i < class_doc.methods.size(); i++) { String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower(); - String aux_term = (search_flags & SEARCH_CASE_SENSITIVE) ? term : term.to_lower(); - - if (aux_term.begins_with(".")) { - aux_term = aux_term.right(1); - } - - if (aux_term.ends_with("(")) { - aux_term = aux_term.left(aux_term.length() - 1).strip_edges(); - } - - if (aux_term.is_subsequence_of(method_name)) { + if (method_name.find(term) > -1 || + (term.begins_with(".") && method_name.begins_with(term.right(1))) || + (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || + (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) { match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i])); } } @@ -448,9 +441,9 @@ bool EditorHelpSearch::Runner::_phase_select_match() { bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String &p_string) const { if (search_flags & SEARCH_CASE_SENSITIVE) { - return p_term.is_subsequence_of(p_string); + return p_string.find(p_term) > -1; } else { - return p_term.is_subsequence_ofi(p_string); + return p_string.findn(p_term) > -1; } } diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index a8ded44323..cf32ffb4e0 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1504,9 +1504,9 @@ void EditorInspector::update_tree() { String subgroup_base; VBoxContainer *category_vbox = nullptr; - List<PropertyInfo> - plist; + List<PropertyInfo> plist; object->get_property_list(&plist, true); + _update_script_class_properties(*object, plist); HashMap<String, VBoxContainer *> item_path; Map<VBoxContainer *, EditorInspectorSection *> section_map; @@ -1572,7 +1572,30 @@ void EditorInspector::update_tree() { category_vbox = nullptr; //reset String type = p.name; - category->icon = EditorNode::get_singleton()->get_class_icon(type, "Object"); + if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) { + Ref<Script> s = ResourceLoader::load(p.hint_string, "Script"); + String base_type; + if (s.is_valid()) { + base_type = s->get_instance_base_type(); + } + while (s.is_valid()) { + StringName name = EditorNode::get_editor_data().script_class_get_name(s->get_path()); + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); + if (name != StringName() && icon_path.length()) { + category->icon = ResourceLoader::load(icon_path, "Texture"); + break; + } + s = s->get_base_script(); + } + if (category->icon.is_null() && has_theme_icon(base_type, "EditorIcons")) { + category->icon = get_theme_icon(base_type, "EditorIcons"); + } + } + if (category->icon.is_null()) { + if (type != String()) { // Can happen for built-in scripts. + category->icon = EditorNode::get_singleton()->get_class_icon(type, "Object"); + } + } category->label = type; category->bg_color = get_theme_color("prop_category", "Editor"); @@ -1643,7 +1666,7 @@ void EditorInspector::update_tree() { basename = group + "/" + basename; } - String name = (basename.find("/") != -1) ? basename.right(basename.find_last("/") + 1) : basename; + String name = (basename.find("/") != -1) ? basename.right(basename.rfind("/") + 1) : basename; if (capitalize_paths) { int dot = name.find("."); @@ -1658,7 +1681,7 @@ void EditorInspector::update_tree() { } } - String path = basename.left(basename.find_last("/")); + String path = basename.left(basename.rfind("/")); if (use_filter && filter != "") { String cat = path; @@ -2370,6 +2393,93 @@ void EditorInspector::_feature_profile_changed() { update_tree(); } +void EditorInspector::_update_script_class_properties(const Object &p_object, List<PropertyInfo> &r_list) const { + Ref<Script> script = p_object.get_script(); + if (script.is_null()) { + return; + } + + List<StringName> classes; + Map<StringName, String> paths; + + // NodeC -> NodeB -> NodeA + while (script.is_valid()) { + String n = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + if (n.length()) { + classes.push_front(n); + } else if (script->get_path() != String() && script->get_path().find("::") == -1) { + n = script->get_path().get_file(); + classes.push_front(n); + } else { + n = TTR("Built-in script"); + classes.push_front(n); + } + paths[n] = script->get_path(); + script = script->get_base_script(); + } + + if (classes.empty()) { + return; + } + + // Script Variables -> to insert: NodeC..B..A -> bottom (insert_here) + List<PropertyInfo>::Element *script_variables = NULL; + List<PropertyInfo>::Element *bottom = NULL; + List<PropertyInfo>::Element *insert_here = NULL; + for (List<PropertyInfo>::Element *E = r_list.front(); E; E = E->next()) { + PropertyInfo &pi = E->get(); + if (pi.name != "Script Variables") { + continue; + } + script_variables = E; + bottom = r_list.insert_after(script_variables, PropertyInfo()); + insert_here = bottom; + break; + } + + Set<StringName> added; + for (List<StringName>::Element *E = classes.front(); E; E = E->next()) { + StringName name = E->get(); + String path = paths[name]; + Ref<Script> s; + if (path == String()) { + // Built-in script. It can't be inherited, so must be the script attached to the object. + s = p_object.get_script(); + } else { + s = ResourceLoader::load(path, "Script"); + } + ERR_FAIL_COND(!s->is_valid()); + List<PropertyInfo> props; + s->get_script_property_list(&props); + + // Script Variables -> NodeA -> bottom (insert_here) + List<PropertyInfo>::Element *category = r_list.insert_before(insert_here, PropertyInfo(Variant::NIL, name, PROPERTY_HINT_NONE, path, PROPERTY_USAGE_CATEGORY)); + + // Script Variables -> NodeA -> A props... -> bottom (insert_here) + for (List<PropertyInfo>::Element *P = props.front(); P; P = P->next()) { + PropertyInfo &pi = P->get(); + if (added.has(pi.name)) { + continue; + } + added.insert(pi.name); + + r_list.insert_before(insert_here, pi); + } + + // Script Variables -> NodeA (insert_here) -> A props... -> bottom + insert_here = category; + } + + // NodeC -> C props... -> NodeB..C.. + r_list.erase(script_variables); + List<PropertyInfo>::Element *to_delete = bottom->next(); + while (to_delete && !(to_delete->get().usage & PROPERTY_USAGE_CATEGORY)) { + r_list.erase(to_delete); + to_delete = bottom->next(); + } + r_list.erase(bottom); +} + void EditorInspector::_bind_methods() { ClassDB::bind_method("_edit_request_change", &EditorInspector::_edit_request_change); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 90d995e36d..615ad97766 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -332,6 +332,7 @@ class EditorInspector : public ScrollContainer { void _vscroll_changed(double); void _feature_profile_changed(); + void _update_script_class_properties(const Object &p_object, List<PropertyInfo> &r_list) const; bool _is_property_disabled_by_feature_profile(const StringName &p_property); diff --git a/editor/editor_log.h b/editor/editor_log.h index 3bf5615346..73a8c3f0c5 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -32,7 +32,6 @@ #define EDITOR_LOG_H #include "core/os/thread.h" -#include "pane_drag.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/control.h" @@ -50,7 +49,6 @@ class EditorLog : public VBoxContainer { Label *title; RichTextLabel *log; HBoxContainer *title_hb; - //PaneDrag *pd; Button *tool_button; static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bb34a45938..454170647f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -85,6 +85,7 @@ #include "editor/editor_settings.h" #include "editor/editor_spin_slider.h" #include "editor/editor_themes.h" +#include "editor/editor_translation_parser.h" #include "editor/export_template_manager.h" #include "editor/filesystem_dock.h" #include "editor/import/editor_import_collada.h" @@ -103,7 +104,6 @@ #include "editor/import_dock.h" #include "editor/multi_node_edit.h" #include "editor/node_dock.h" -#include "editor/pane_drag.h" #include "editor/plugin_config_dialog.h" #include "editor/plugins/animation_blend_space_1d_editor.h" #include "editor/plugins/animation_blend_space_2d_editor.h" @@ -138,6 +138,7 @@ #include "editor/plugins/multimesh_editor_plugin.h" #include "editor/plugins/navigation_polygon_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" +#include "editor/plugins/packed_scene_translation_parser_plugin.h" #include "editor/plugins/path_2d_editor_plugin.h" #include "editor/plugins/path_3d_editor_plugin.h" #include "editor/plugins/physical_bone_3d_editor_plugin.h" @@ -178,6 +179,111 @@ EditorNode *EditorNode::singleton = nullptr; +void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames) { + // Keep track of a list of "index sets," i.e. sets of indices + // within disambiguated_scene_names which contain the same name. + Vector<Set<int>> index_sets; + Map<String, int> scene_name_to_set_index; + for (int i = 0; i < r_filenames.size(); i++) { + String scene_name = r_filenames[i]; + if (!scene_name_to_set_index.has(scene_name)) { + index_sets.append(Set<int>()); + scene_name_to_set_index.insert(r_filenames[i], index_sets.size() - 1); + } + index_sets.write[scene_name_to_set_index[scene_name]].insert(i); + } + + // For each index set with a size > 1, we need to disambiguate + for (int i = 0; i < index_sets.size(); i++) { + Set<int> iset = index_sets[i]; + while (iset.size() > 1) { + // Append the parent folder to each scene name + for (Set<int>::Element *E = iset.front(); E; E = E->next()) { + int set_idx = E->get(); + String scene_name = r_filenames[set_idx]; + String full_path = p_full_paths[set_idx]; + + // Get rid of file extensions and res:// prefixes + if (scene_name.rfind(".") >= 0) { + scene_name = scene_name.substr(0, scene_name.rfind(".")); + } + if (full_path.begins_with("res://")) { + full_path = full_path.substr(6); + } + if (full_path.rfind(".") >= 0) { + full_path = full_path.substr(0, full_path.rfind(".")); + } + + int scene_name_size = scene_name.size(); + int full_path_size = full_path.size(); + int difference = full_path_size - scene_name_size; + + // Find just the parent folder of the current path and append it. + // If the current name is foo.tscn, and the full path is /some/folder/foo.tscn + // then slash_idx is the second '/', so that we select just "folder", and + // append that to yield "folder/foo.tscn". + if (difference > 0) { + String parent = full_path.substr(0, difference); + int slash_idx = parent.rfind("/"); + slash_idx = parent.rfind("/", slash_idx - 1); + parent = slash_idx >= 0 ? parent.substr(slash_idx + 1) : parent; + r_filenames.write[set_idx] = parent + r_filenames[set_idx]; + } + } + + // Loop back through scene names and remove non-ambiguous names + bool can_proceed = false; + Set<int>::Element *E = iset.front(); + while (E) { + String scene_name = r_filenames[E->get()]; + bool duplicate_found = false; + for (Set<int>::Element *F = iset.front(); F; F = F->next()) { + if (E->get() == F->get()) { + continue; + } + String other_scene_name = r_filenames[F->get()]; + if (other_scene_name == scene_name) { + duplicate_found = true; + break; + } + } + + Set<int>::Element *to_erase = duplicate_found ? nullptr : E; + + // We need to check that we could actually append anymore names + // if we wanted to for disambiguation. If we can't, then we have + // to abort even with ambiguous names. We clean the full path + // and the scene name first to remove extensions so that this + // comparison actually works. + String path = p_full_paths[E->get()]; + if (path.begins_with("res://")) { + path = path.substr(6); + } + if (path.rfind(".") >= 0) { + path = path.substr(0, path.rfind(".")); + } + if (scene_name.rfind(".") >= 0) { + scene_name = scene_name.substr(0, scene_name.rfind(".")); + } + + // We can proceed iff the full path is longer than the scene name, + // meaning that there is at least one more parent folder we can + // tack onto the name. + can_proceed = can_proceed || (path.size() - scene_name.size()) >= 1; + + E = E->next(); + if (to_erase) { + iset.erase(to_erase); + } + } + + if (!can_proceed) { + break; + } + } + } +} + void EditorNode::_update_scene_tabs() { bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button"); @@ -185,6 +291,16 @@ void EditorNode::_update_scene_tabs() { DisplayServer::get_singleton()->global_menu_clear("_dock"); } + // Get all scene names, which may be ambiguous + Vector<String> disambiguated_scene_names; + Vector<String> full_path_names; + for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { + disambiguated_scene_names.append(editor_data.get_scene_title(i)); + full_path_names.append(editor_data.get_scene_path(i)); + } + + disambiguate_filenames(full_path_names, disambiguated_scene_names); + scene_tabs->clear_tabs(); Ref<Texture2D> script_icon = gui_base->get_theme_icon("Script", "EditorIcons"); for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { @@ -196,7 +312,7 @@ void EditorNode::_update_scene_tabs() { int current = editor_data.get_edited_scene(); bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0; - scene_tabs->add_tab(editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), icon); + scene_tabs->add_tab(disambiguated_scene_names[i] + (unsaved ? "(*)" : ""), icon); if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { DisplayServer::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), callable_mp(this, &EditorNode::_global_menu_scene), i); @@ -360,7 +476,7 @@ void EditorNode::_notification(int p_what) { bool dof_jitter = GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter"); RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter); RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); - RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_curve")); + RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit")); bool glow_bicubic = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0; RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic); RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality"))); @@ -376,6 +492,12 @@ void EditorNode::_notification(int p_what) { RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality); float probe_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed"); RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed); + RS::EnvironmentSDFGIFramesToConverge frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(int(GLOBAL_GET("rendering/sdfgi/frames_to_converge"))); + RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge); + RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/sdfgi/probe_ray_count"))); + RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count); + RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/quality/gi_probes/quality"))); + RS::get_singleton()->gi_probe_set_quality(gi_probe_quality); } ResourceImporterTexture::get_singleton()->update_imports(); @@ -429,14 +551,14 @@ void EditorNode::_notification(int p_what) { /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_APPLICATION_FOCUS_IN: { // Restore the original FPS cap after focusing back on the editor OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec"))); EditorFileSystem::get_singleton()->scan_changes(); } break; - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_APPLICATION_FOCUS_OUT: { // Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec"))); } break; @@ -1103,20 +1225,25 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { _find_node_types(editor_data.get_edited_scene_root(), c2d, c3d); - bool is2d; - if (c3d < c2d) { - is2d = true; - } else { - is2d = false; - } save.step(TTR("Creating Thumbnail"), 1); //current view? Ref<Image> img; - if (is2d) { + // If neither 3D or 2D nodes are present, make a 1x1 black texture. + // We cannot fallback on the 2D editor, because it may not have been used yet, + // which would result in an invalid texture. + if (c3d == 0 && c2d == 0) { + img.instance(); + img->create(1, 1, 0, Image::FORMAT_RGB8); + } else if (c3d < c2d) { img = scene_root->get_texture()->get_data(); } else { - img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data(); + // The 3D editor may be disabled as a feature, but scenes can still be opened. + // This check prevents the preview from regenerating in case those scenes are then saved. + Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile(); + if (!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)) { + img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data(); + } } if (img.is_valid()) { @@ -1921,7 +2048,6 @@ void EditorNode::_run(bool p_current, const String &p_custom) { play_custom_scene_button->set_pressed(false); play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons")); - String main_scene; String run_filename; String args; bool skip_breakpoints; @@ -2342,8 +2468,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_PLAY: { - _menu_option_confirm(RUN_STOP, true); - _run(false); + run_play(); } break; case RUN_PLAY_CUSTOM_SCENE: { @@ -2354,8 +2479,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { play_custom_scene_button->set_pressed(false); } else { String last_custom_scene = run_custom_filename; - _menu_option_confirm(RUN_STOP, true); - _run(false, last_custom_scene); + run_play_custom(last_custom_scene); } } break; @@ -2395,9 +2519,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_PLAY_SCENE: { - _save_default_environment(); - _menu_option_confirm(RUN_STOP, true); - _run(true); + run_play_current(); } break; case RUN_SCENE_SETTINGS: { @@ -3405,10 +3527,14 @@ void EditorNode::_update_recent_scenes() { void EditorNode::_quick_opened() { Vector<String> files = quick_open->get_selected_files(); + bool open_scene_dialog = quick_open->get_base_type() == "PackedScene"; for (int i = 0; i < files.size(); i++) { String res_path = files[i]; - if (quick_open->get_base_type() == "PackedScene") { + List<String> scene_extensions; + ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions); + + if (open_scene_dialog || scene_extensions.find(files[i].get_extension())) { open_request(res_path); } else { load_resource(res_path); @@ -3464,6 +3590,7 @@ void EditorNode::register_editor_types() { ResourceSaver::set_timestamp_on_save(true); ClassDB::register_class<EditorPlugin>(); + ClassDB::register_class<EditorTranslationParserPlugin>(); ClassDB::register_class<EditorImportPlugin>(); ClassDB::register_class<EditorScript>(); ClassDB::register_class<EditorSelection>(); @@ -3637,22 +3764,14 @@ Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p_fallback) const { ERR_FAIL_COND_V_MSG(p_class.empty(), nullptr, "Class name cannot be empty."); - if (gui_base->has_theme_icon(p_class, "EditorIcons")) { - return gui_base->get_theme_icon(p_class, "EditorIcons"); - } - if (ScriptServer::is_global_class(p_class)) { - String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(p_class); - Ref<ImageTexture> icon = _load_custom_class_icon(icon_path); - if (icon.is_valid()) { - return icon; - } - - Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class), "Script"); + Ref<ImageTexture> icon; + Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_class); + StringName name = p_class; while (script.is_valid()) { - String current_icon_path; - script->get_language()->get_global_class_name(script->get_path(), nullptr, ¤t_icon_path); + name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + String current_icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); icon = _load_custom_class_icon(current_icon_path); if (icon.is_valid()) { return icon; @@ -3661,10 +3780,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } if (icon.is_null()) { - icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(p_class), "EditorIcons"); + icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(name), "EditorIcons"); } - - return icon; } const Map<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types(); @@ -3679,6 +3796,10 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } } + if (gui_base->has_theme_icon(p_class, "EditorIcons")) { + return gui_base->get_theme_icon(p_class, "EditorIcons"); + } + if (p_fallback.length() && gui_base->has_theme_icon(p_fallback, "EditorIcons")) { return gui_base->get_theme_icon(p_fallback, "EditorIcons"); } @@ -4157,7 +4278,6 @@ void EditorNode::_update_dock_slots_visibility() { } right_hsplit->hide(); - bottom_panel->hide(); } else { for (int i = 0; i < DOCK_SLOT_MAX; i++) { int tabs_visible = 0; @@ -4187,7 +4307,6 @@ void EditorNode::_update_dock_slots_visibility() { dock_slot[i]->set_current_tab(0); } } - bottom_panel->show(); if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible()) { right_hsplit->show(); @@ -4405,10 +4524,35 @@ void EditorNode::run_play() { _run(false); } +void EditorNode::run_play_current() { + _save_default_environment(); + _menu_option_confirm(RUN_STOP, true); + _run(true); +} + +void EditorNode::run_play_custom(const String &p_custom) { + _menu_option_confirm(RUN_STOP, true); + _run(false, p_custom); +} + void EditorNode::run_stop() { _menu_option_confirm(RUN_STOP, false); } +bool EditorNode::is_run_playing() const { + EditorRun::Status status = editor_run.get_status(); + return (status == EditorRun::STATUS_PLAY || status == EditorRun::STATUS_PAUSED); +} + +String EditorNode::get_run_playing_scene() const { + String run_filename = editor_run.get_running_scene(); + if (run_filename == "" && is_run_playing()) { + run_filename = GLOBAL_DEF("application/run/main_scene", ""); // Must be the main scene then. + } + + return run_filename; +} + int EditorNode::get_current_tab() { return scene_tabs->get_current_tab(); } @@ -5401,10 +5545,10 @@ EditorNode::EditorNode() { switch (display_scale) { case 0: { // Try applying a suitable display scale automatically - const int screen = DisplayServer::get_singleton()->window_get_current_screen(); #ifdef OSX_ENABLED - editor_set_scale(DisplayServer::get_singleton()->screen_get_scale(screen)); + editor_set_scale(DisplayServer::get_singleton()->screen_get_max_scale()); #else + const int screen = DisplayServer::get_singleton()->window_get_current_screen(); editor_set_scale(DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000 ? 2.0 : 1.0); #endif } break; @@ -6488,6 +6632,7 @@ EditorNode::EditorNode() { } resource_preview->add_preview_generator(Ref<EditorTexturePreviewPlugin>(memnew(EditorTexturePreviewPlugin))); + resource_preview->add_preview_generator(Ref<EditorImagePreviewPlugin>(memnew(EditorImagePreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorPackedScenePreviewPlugin>(memnew(EditorPackedScenePreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorMaterialPreviewPlugin>(memnew(EditorMaterialPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorScriptPreviewPlugin>(memnew(EditorScriptPreviewPlugin))); @@ -6539,6 +6684,10 @@ EditorNode::EditorNode() { EditorExport::get_singleton()->add_export_plugin(export_text_to_binary_plugin); + Ref<PackedSceneEditorTranslationParserPlugin> packed_scene_translation_parser_plugin; + packed_scene_translation_parser_plugin.instance(); + EditorTranslationParser::get_singleton()->add_parser(packed_scene_translation_parser_plugin, EditorTranslationParser::STANDARD); + _edit_current(); current = nullptr; saving_resource = Ref<Resource>(); diff --git a/editor/editor_node.h b/editor/editor_node.h index b0e0c5614c..dec28b0d2b 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -71,7 +71,6 @@ class ImportDock; class MenuButton; class NodeDock; class OrphanResourcesDialog; -class PaneDrag; class Panel; class PanelContainer; class PluginConfigDialog; @@ -255,7 +254,6 @@ private: VSplitContainer *top_split; HBoxContainer *bottom_hb; Control *vp_base; - PaneDrag *pd; HBoxContainer *menu_hb; Control *viewport; @@ -687,6 +685,8 @@ public: static void add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); static void remove_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); + static void disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames); + void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE, false); } void set_docks_visible(bool p_show); @@ -865,7 +865,11 @@ public: bool ensure_main_scene(bool p_from_native); void run_play(); + void run_play_current(); + void run_play_custom(const String &p_custom); void run_stop(); + bool is_run_playing() const; + String get_run_playing_scene() const; }; struct EditorProgress { diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 32b799cd61..da0a0827d2 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -176,6 +176,30 @@ void EditorInterface::reload_scene_from_path(const String &scene_path) { EditorNode::get_singleton()->reload_scene(scene_path); } +void EditorInterface::play_main_scene() { + EditorNode::get_singleton()->run_play(); +} + +void EditorInterface::play_current_scene() { + EditorNode::get_singleton()->run_play_current(); +} + +void EditorInterface::play_custom_scene(const String &scene_path) { + EditorNode::get_singleton()->run_play_custom(scene_path); +} + +void EditorInterface::stop_playing_scene() { + EditorNode::get_singleton()->run_stop(); +} + +bool EditorInterface::is_playing_scene() const { + return EditorNode::get_singleton()->is_run_playing(); +} + +String EditorInterface::get_playing_scene() const { + return EditorNode::get_singleton()->get_run_playing_scene(); +} + Node *EditorInterface::get_edited_scene_root() { return EditorNode::get_singleton()->get_edited_scene(); } @@ -285,6 +309,12 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("edit_resource", "resource"), &EditorInterface::edit_resource); ClassDB::bind_method(D_METHOD("open_scene_from_path", "scene_filepath"), &EditorInterface::open_scene_from_path); ClassDB::bind_method(D_METHOD("reload_scene_from_path", "scene_filepath"), &EditorInterface::reload_scene_from_path); + ClassDB::bind_method(D_METHOD("play_main_scene"), &EditorInterface::play_main_scene); + ClassDB::bind_method(D_METHOD("play_current_scene"), &EditorInterface::play_current_scene); + ClassDB::bind_method(D_METHOD("play_custom_scene", "scene_filepath"), &EditorInterface::play_custom_scene); + ClassDB::bind_method(D_METHOD("stop_playing_scene"), &EditorInterface::stop_playing_scene); + ClassDB::bind_method(D_METHOD("is_playing_scene"), &EditorInterface::is_playing_scene); + ClassDB::bind_method(D_METHOD("get_playing_scene"), &EditorInterface::get_playing_scene); ClassDB::bind_method(D_METHOD("get_open_scenes"), &EditorInterface::get_open_scenes); ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &EditorInterface::get_edited_scene_root); ClassDB::bind_method(D_METHOD("get_resource_previewer"), &EditorInterface::get_resource_previewer); @@ -663,6 +693,14 @@ bool EditorPlugin::get_remove_list(List<Node *> *p_list) { void EditorPlugin::restore_global_state() {} void EditorPlugin::save_global_state() {} +void EditorPlugin::add_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser) { + EditorTranslationParser::get_singleton()->add_parser(p_parser, EditorTranslationParser::CUSTOM); +} + +void EditorPlugin::remove_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser) { + EditorTranslationParser::get_singleton()->remove_parser(p_parser, EditorTranslationParser::CUSTOM); +} + void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer) { ResourceFormatImporter::get_singleton()->add_importer(p_importer); EditorFileSystem::get_singleton()->call_deferred("scan"); @@ -796,6 +834,8 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("get_undo_redo"), &EditorPlugin::_get_undo_redo); ClassDB::bind_method(D_METHOD("queue_save_layout"), &EditorPlugin::queue_save_layout); + ClassDB::bind_method(D_METHOD("add_translation_parser_plugin", "parser"), &EditorPlugin::add_translation_parser_plugin); + ClassDB::bind_method(D_METHOD("remove_translation_parser_plugin", "parser"), &EditorPlugin::remove_translation_parser_plugin); ClassDB::bind_method(D_METHOD("add_import_plugin", "importer"), &EditorPlugin::add_import_plugin); ClassDB::bind_method(D_METHOD("remove_import_plugin", "importer"), &EditorPlugin::remove_import_plugin); ClassDB::bind_method(D_METHOD("add_scene_import_plugin", "scene_importer"), &EditorPlugin::add_scene_import_plugin); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index e84984d57a..685f69bf3f 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -34,6 +34,7 @@ #include "core/io/config_file.h" #include "core/undo_redo.h" #include "editor/editor_inspector.h" +#include "editor/editor_translation_parser.h" #include "editor/import/editor_import_plugin.h" #include "editor/import/resource_importer_scene.h" #include "editor/script_create_dialog.h" @@ -72,6 +73,13 @@ public: void open_scene_from_path(const String &scene_path); void reload_scene_from_path(const String &scene_path); + void play_main_scene(); + void play_current_scene(); + void play_custom_scene(const String &scene_path); + void stop_playing_scene(); + bool is_playing_scene() const; + String get_playing_scene() const; + Node *get_edited_scene_root(); Array get_open_scenes() const; ScriptEditor *get_script_editor(); @@ -220,6 +228,9 @@ public: virtual void restore_global_state(); virtual void save_global_state(); + void add_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser); + void remove_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser); + void add_import_plugin(const Ref<EditorImportPlugin> &p_importer); void remove_import_plugin(const Ref<EditorImportPlugin> &p_importer); diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index b5f1133a9e..fe49198e8f 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -39,7 +39,7 @@ #include "scene/gui/margin_container.h" void EditorPluginSettings::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { update_plugins(); } else if (p_what == Node::NOTIFICATION_READY) { plugin_config_dialog->connect_compat("plugin_ready", EditorNode::get_singleton(), "_on_plugin_ready"); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index eee610e9a8..8f9c92ea15 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -377,13 +377,13 @@ void EditorPropertyMember::_property_select() { selector->select_method_from_base_type(hint_text, current); } else if (hint == MEMBER_METHOD_OF_INSTANCE) { - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (instance) { selector->select_method_from_instance(instance, current); } } else if (hint == MEMBER_METHOD_OF_SCRIPT) { - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (Object::cast_to<Script>(obj)) { selector->select_method_from_script(Object::cast_to<Script>(obj), current); } @@ -408,13 +408,13 @@ void EditorPropertyMember::_property_select() { selector->select_property_from_base_type(hint_text, current); } else if (hint == MEMBER_PROPERTY_OF_INSTANCE) { - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (instance) { selector->select_property_from_instance(instance, current); } } else if (hint == MEMBER_PROPERTY_OF_SCRIPT) { - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (Object::cast_to<Script>(obj)) { selector->select_property_from_script(Object::cast_to<Script>(obj), current); } @@ -488,7 +488,7 @@ void EditorPropertyEnum::setup(const Vector<String> &p_options) { for (int i = 0; i < p_options.size(); i++) { Vector<String> text_split = p_options[i].split(":"); if (text_split.size() != 1) { - current_val = text_split[1].to_int64(); + current_val = text_split[1].to_int(); } options->add_item(text_split[0]); options->set_item_metadata(i, current_val); @@ -2983,8 +2983,16 @@ bool EditorPropertyResource::_is_drop_valid(const Dictionary &p_drag_data) const String allowed_type = base_type; Dictionary drag_data = p_drag_data; - if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - Ref<Resource> res = drag_data["resource"]; + + Ref<Resource> res; + if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); + res = se->get_edited_resource(); + } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + res = drag_data["resource"]; + } + + if (res.is_valid()) { for (int i = 0; i < allowed_type.get_slice_count(","); i++) { String at = allowed_type.get_slice(",", i).strip_edges(); if (res.is_valid() && ClassDB::is_parent_class(res->get_class(), at)) { @@ -3022,13 +3030,19 @@ void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant & ERR_FAIL_COND(!_is_drop_valid(p_data)); Dictionary drag_data = p_data; - if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - Ref<Resource> res = drag_data["resource"]; - if (res.is_valid()) { - emit_changed(get_edited_property(), res); - update_property(); - return; - } + + Ref<Resource> res; + if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); + res = se->get_edited_resource(); + } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + res = drag_data["resource"]; + } + + if (res.is_valid()) { + emit_changed(get_edited_property(), res); + update_property(); + return; } if (drag_data.has("type") && String(drag_data["type"]) == "files") { @@ -3036,9 +3050,9 @@ void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant & if (files.size() == 1) { String file = files[0]; - RES res = ResourceLoader::load(file); - if (res.is_valid()) { - emit_changed(get_edited_property(), res); + RES file_res = ResourceLoader::load(file); + if (file_res.is_valid()) { + emit_changed(get_edited_property(), file_res); update_property(); return; } diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 7ac8fae156..d2250fed7a 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -110,7 +110,7 @@ void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Textur uint64_t modified_time = 0; if (p_str.begins_with("ID:")) { - hash = uint32_t(p_str.get_slicec(':', 2).to_int64()); + hash = uint32_t(p_str.get_slicec(':', 2).to_int()); path = "ID:" + p_str.get_slicec(':', 1); } else { modified_time = FileAccess::get_modified_time(path); @@ -257,9 +257,9 @@ void EditorResourcePreview::_thread() { _generate_preview(texture, small_texture, item, cache_base); } else { uint64_t modtime = FileAccess::get_modified_time(item.path); - int tsize = f->get_line().to_int64(); + int tsize = f->get_line().to_int(); bool has_small_texture = f->get_line().to_int(); - uint64_t last_modtime = f->get_line().to_int64(); + uint64_t last_modtime = f->get_line().to_int(); bool cache_valid = true; diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index 1148a6c7ec..b49c50fa31 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -38,6 +38,10 @@ EditorRun::Status EditorRun::get_status() const { return status; } +String EditorRun::get_running_scene() const { + return running_scene; +} + Error EditorRun::run(const String &p_scene, const String &p_custom_args, const List<String> &p_breakpoints, const bool &p_skip_breakpoints) { List<String> args; @@ -108,24 +112,33 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L } int window_placement = EditorSettings::get_singleton()->get("run/window_placement/rect"); + bool hidpi_proj = ProjectSettings::get_singleton()->get("display/window/dpi/allow_hidpi"); + int display_scale = 1; + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_HIDPI)) { + if (OS::get_singleton()->is_hidpi_allowed()) { + if (hidpi_proj) { + display_scale = 1; // Both editor and project runs in hiDPI mode, do not scale. + } else { + display_scale = DisplayServer::get_singleton()->screen_get_max_scale(); // Editor is in hiDPI mode, project is not, scale down. + } + } else { + if (hidpi_proj) { + display_scale = (1.f / DisplayServer::get_singleton()->screen_get_max_scale()); // Editor is not in hiDPI mode, project is, scale up. + } else { + display_scale = 1; // Both editor and project runs in lowDPI mode, do not scale. + } + } + screen_rect.position /= display_scale; + screen_rect.size /= display_scale; + } switch (window_placement) { case 0: { // top left - args.push_back("--position"); args.push_back(itos(screen_rect.position.x) + "," + itos(screen_rect.position.y)); } break; case 1: { // centered - int display_scale = 1; -#ifdef OSX_ENABLED - display_scale = DisplayServer::get_singleton()->screen_get_scale(screen); -#else - if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000) { - display_scale = 2; - } -#endif - - Vector2 pos = screen_rect.position + ((screen_rect.size / display_scale - desired_size) / 2).floor(); + Vector2 pos = (screen_rect.position) + ((screen_rect.size - desired_size) / 2).floor(); args.push_back("--position"); args.push_back(itos(pos.x) + "," + itos(pos.y)); } break; @@ -140,10 +153,8 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L args.push_back("--position"); args.push_back(itos(pos.x) + "," + itos(pos.y)); args.push_back("--maximized"); - } break; case 4: { // force fullscreen - Vector2 pos = screen_rect.position; args.push_back("--position"); args.push_back(itos(pos.x) + "," + itos(pos.y)); @@ -196,6 +207,9 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L } status = STATUS_PLAY; + if (p_scene != "") { + running_scene = p_scene; + } return OK; } @@ -224,8 +238,10 @@ void EditorRun::stop() { } status = STATUS_STOP; + running_scene = ""; } EditorRun::EditorRun() { status = STATUS_STOP; + running_scene = ""; } diff --git a/editor/editor_run.h b/editor/editor_run.h index 06050436a9..a15d65d91b 100644 --- a/editor/editor_run.h +++ b/editor/editor_run.h @@ -46,9 +46,11 @@ public: private: Status status; + String running_scene; public: Status get_status() const; + String get_running_scene() const; Error run(const String &p_scene, const String &p_custom_args, const List<String> &p_breakpoints, const bool &p_skip_breakpoints = false); void run_native_notify() { status = STATUS_PLAY; } void stop(); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 67d92c4839..d76a3d2da7 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -182,8 +182,8 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) { } void EditorSpinSlider::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_OUT || - p_what == NOTIFICATION_WM_FOCUS_IN || + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_OUT || + p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN || p_what == NOTIFICATION_EXIT_TREE) { if (grabbing_spinner) { grabber->hide(); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 5f59e6e70a..a93763810b 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -570,17 +570,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("focus", "PopupMenu", style_menu); theme->set_stylebox("disabled", "PopupMenu", style_menu); - theme->set_stylebox("normal", "Button", style_menu); - theme->set_stylebox("hover", "Button", style_menu); - theme->set_stylebox("pressed", "Button", style_menu); - theme->set_stylebox("focus", "Button", style_menu); - theme->set_stylebox("disabled", "Button", style_menu); - theme->set_color("font_color", "MenuButton", font_color); theme->set_color("font_color_hover", "MenuButton", font_color_hl); - theme->set_color("font_color", "Button", font_color); - theme->set_color("font_color_hover", "Button", font_color_hl); - theme->set_color("font_color_pressed", "Button", accent_color); theme->set_stylebox("MenuHover", "EditorStyles", style_menu_hover_border); diff --git a/editor/editor_translation_parser.cpp b/editor/editor_translation_parser.cpp new file mode 100644 index 0000000000..3f4864ad1e --- /dev/null +++ b/editor/editor_translation_parser.cpp @@ -0,0 +1,163 @@ +/*************************************************************************/ +/* editor_translation_parser.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "editor_translation_parser.h" + +#include "core/error_macros.h" +#include "core/os/file_access.h" +#include "core/script_language.h" +#include "core/set.h" + +EditorTranslationParser *EditorTranslationParser::singleton = nullptr; + +Error EditorTranslationParserPlugin::parse_file(const String &p_path, Vector<String> *r_extracted_strings) { + if (!get_script_instance()) + return ERR_UNAVAILABLE; + + if (get_script_instance()->has_method("parse_file")) { + Array extracted_strings; + get_script_instance()->call("parse_file", p_path, extracted_strings); + for (int i = 0; i < extracted_strings.size(); i++) { + r_extracted_strings->append(extracted_strings[i]); + } + return OK; + } else { + ERR_PRINT("Custom translation parser plugin's \"func parse_file(path, extracted_strings)\" is undefined."); + return ERR_UNAVAILABLE; + } +} + +void EditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { + if (!get_script_instance()) + return; + + if (get_script_instance()->has_method("get_recognized_extensions")) { + Array extensions = get_script_instance()->call("get_recognized_extensions"); + for (int i = 0; i < extensions.size(); i++) { + r_extensions->push_back(extensions[i]); + } + } else { + ERR_PRINT("Custom translation parser plugin's \"func get_recognized_extensions()\" is undefined."); + } +} + +void EditorTranslationParserPlugin::_bind_methods() { + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::NIL, "parse_file", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::ARRAY, "extracted_strings"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::ARRAY, "get_recognized_extensions")); +} + +///////////////////////// + +void EditorTranslationParser::get_recognized_extensions(List<String> *r_extensions) const { + Set<String> extensions; + List<String> temp; + for (int i = 0; i < standard_parsers.size(); i++) { + standard_parsers[i]->get_recognized_extensions(&temp); + } + for (int i = 0; i < custom_parsers.size(); i++) { + custom_parsers[i]->get_recognized_extensions(&temp); + } + // Remove duplicates. + for (int i = 0; i < temp.size(); i++) { + extensions.insert(temp[i]); + } + for (auto E = extensions.front(); E; E = E->next()) { + r_extensions->push_back(E->get()); + } +} + +bool EditorTranslationParser::can_parse(const String &p_extension) const { + List<String> extensions; + get_recognized_extensions(&extensions); + for (int i = 0; i < extensions.size(); i++) { + if (p_extension == extensions[i]) { + return true; + } + } + return false; +} + +Ref<EditorTranslationParserPlugin> EditorTranslationParser::get_parser(const String &p_extension) const { + // Consider user-defined parsers first. + for (int i = 0; i < custom_parsers.size(); i++) { + List<String> temp; + custom_parsers[i]->get_recognized_extensions(&temp); + for (int j = 0; j < temp.size(); j++) { + if (temp[j] == p_extension) { + return custom_parsers[i]; + } + } + } + + for (int i = 0; i < standard_parsers.size(); i++) { + List<String> temp; + standard_parsers[i]->get_recognized_extensions(&temp); + for (int j = 0; j < temp.size(); j++) { + if (temp[j] == p_extension) { + return standard_parsers[i]; + } + } + } + + WARN_PRINT("No translation parser available for \"" + p_extension + "\" extension."); + + return nullptr; +} + +void EditorTranslationParser::add_parser(const Ref<EditorTranslationParserPlugin> &p_parser, ParserType p_type) { + if (p_type == ParserType::STANDARD) { + standard_parsers.push_back(p_parser); + } else if (p_type == ParserType::CUSTOM) { + custom_parsers.push_back(p_parser); + } +} + +void EditorTranslationParser::remove_parser(const Ref<EditorTranslationParserPlugin> &p_parser, ParserType p_type) { + if (p_type == ParserType::STANDARD) { + standard_parsers.erase(p_parser); + } else if (p_type == ParserType::CUSTOM) { + custom_parsers.erase(p_parser); + } +} + +EditorTranslationParser *EditorTranslationParser::get_singleton() { + if (!singleton) { + singleton = memnew(EditorTranslationParser); + } + return singleton; +} + +EditorTranslationParser::EditorTranslationParser() { +} + +EditorTranslationParser::~EditorTranslationParser() { + memdelete(singleton); + singleton = nullptr; +} diff --git a/editor/editor_translation_parser.h b/editor/editor_translation_parser.h new file mode 100644 index 0000000000..6d00bedfa4 --- /dev/null +++ b/editor/editor_translation_parser.h @@ -0,0 +1,72 @@ +/*************************************************************************/ +/* editor_translation_parser.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 EDITOR_TRANSLATION_PARSER_H +#define EDITOR_TRANSLATION_PARSER_H + +#include "core/error_list.h" +#include "core/reference.h" + +class EditorTranslationParserPlugin : public Reference { + GDCLASS(EditorTranslationParserPlugin, Reference); + +protected: + static void _bind_methods(); + +public: + virtual Error parse_file(const String &p_path, Vector<String> *r_extracted_strings); + virtual void get_recognized_extensions(List<String> *r_extensions) const; +}; + +class EditorTranslationParser { + static EditorTranslationParser *singleton; + +public: + enum ParserType { + STANDARD, // GDScript, CSharp, ... + CUSTOM // User-defined parser plugins. This will override standard parsers if the same extension type is defined. + }; + + static EditorTranslationParser *get_singleton(); + + Vector<Ref<EditorTranslationParserPlugin>> standard_parsers; + Vector<Ref<EditorTranslationParserPlugin>> custom_parsers; + + void get_recognized_extensions(List<String> *r_extensions) const; + bool can_parse(const String &p_extension) const; + Ref<EditorTranslationParserPlugin> get_parser(const String &p_extension) const; + void add_parser(const Ref<EditorTranslationParserPlugin> &p_parser, ParserType p_type); + void remove_parser(const Ref<EditorTranslationParserPlugin> &p_parser, ParserType p_type); + + EditorTranslationParser(); + ~EditorTranslationParser(); +}; + +#endif // EDITOR_TRANSLATION_PARSER_H diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index c700fdccad..4f37fcf39c 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1688,7 +1688,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected String name = to_rename.path.get_file(); rename_dialog->set_title(TTR("Renaming file:") + " " + name); rename_dialog_text->set_text(name); - rename_dialog_text->select(0, name.find_last(".")); + rename_dialog_text->select(0, name.rfind(".")); } else { String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file(); rename_dialog->set_title(TTR("Renaming folder:") + " " + name); @@ -1732,7 +1732,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected String name = to_duplicate.path.get_file(); duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name); duplicate_dialog_text->set_text(name); - duplicate_dialog_text->select(0, name.find_last(".")); + duplicate_dialog_text->select(0, name.rfind(".")); } else { String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file(); duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name); @@ -2313,7 +2313,7 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { tree_popup->clear(); tree_popup->set_size(Size2(1, 1)); _file_and_folders_fill_popup(tree_popup, paths); - tree_popup->set_position(tree->get_global_position() + p_pos); + tree_popup->set_position(tree->get_screen_position() + p_pos); tree_popup->popup(); } } @@ -2508,10 +2508,10 @@ void FileSystemDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_tree_thumbnail_done"), &FileSystemDock::_tree_thumbnail_done); ClassDB::bind_method(D_METHOD("_select_file"), &FileSystemDock::_select_file); - ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &FileSystemDock::get_drag_data_fw); - ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &FileSystemDock::can_drop_data_fw); - ClassDB::bind_method(D_METHOD("drop_data_fw"), &FileSystemDock::drop_data_fw); - ClassDB::bind_method(D_METHOD("navigate_to_path"), &FileSystemDock::navigate_to_path); + ClassDB::bind_method(D_METHOD("get_drag_data_fw", "position", "from"), &FileSystemDock::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("can_drop_data_fw", "position", "data", "from"), &FileSystemDock::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw", "position", "data", "from"), &FileSystemDock::drop_data_fw); + ClassDB::bind_method(D_METHOD("navigate_to_path", "path"), &FileSystemDock::navigate_to_path); ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock); diff --git a/editor/icons/InterpolatedCamera.svg b/editor/icons/InterpolatedCamera.svg deleted file mode 100644 index 4bc4ba1ee9..0000000000 --- a/editor/icons/InterpolatedCamera.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9.5.00004c-1.5691.0017903-2.8718 1.2125-2.9883 2.7773-.55103-.49952-1.268-.77655-2.0117-.77734-1.6569 0-3 1.3431-3 3 .00179 1.2698.80282 2.4009 2 2.8242v2.1758c0 .554.44599 1 1 1h6c.55401 0 .9853-.4462 1-1v-1l3 2v-6l-3 2v-1.7695c.63486-.56783.99842-1.3788 1-2.2305 0-1.6569-1.3431-3-3-3zm-6 12v4h1v-4zm3 0v4h1v-1h1c.55228 0 1-.44772 1-1v-1c0-.55228-.44824-1.024-1-1h-1zm5 0c-.55228 0-1 .44772-1 1v2c0 .55228.44772 1 1 1h1c.55228 0 1-.44772 1-1v-2c0-.55228-.44772-1-1-1zm-4 1h1v1h-1zm4 0h1v2h-1z" fill="#fc9c9c"/></svg>
\ No newline at end of file diff --git a/editor/icons/ToolButton.svg b/editor/icons/ToolButton.svg deleted file mode 100644 index 98a41d2a08..0000000000 --- a/editor/icons/ToolButton.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11 1.1738c-1.1979.4235-1.999 1.5557-2 2.8262.0009552 1.2705.80214 2.4027 2 2.8262v7.1738c0 .554.446 1 1 1s1-.446 1-1v-7.1758c1.1972-.4232 1.9982-1.5544 2-2.8242-.0018-1.2698-.80282-2.401-2-2.8242v2.8242c0 .5523-.44772 1-1 1s-1-.4477-1-1zm-7 1.8262v3.1328l-1.4453-.96484-1.1094 1.6641 3 2c.3359.22389.77347.22389 1.1094 0l3-2-1.1094-1.6641-1.4453.96484v-3.1328zm-.5 8c-.831 0-1.5.669-1.5 1.5v.5h-1v2h8v-2h-1v-.5c0-.831-.669-1.5-1.5-1.5z" fill="#a5efac"/></svg>
\ No newline at end of file diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 65ebf9dc4f..5dcdf6bec4 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -943,9 +943,9 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String ERR_CONTINUE(anim.is_null()); if (!p_animations.has(anim)) { - // We are making external files so they are modifiable + // Tracks from source file should be set as imported, anything else is a custom track. for (int i = 0; i < anim->get_track_count(); i++) { - anim->track_set_imported(i, false); + anim->track_set_imported(i, true); } String ext_name; @@ -957,10 +957,9 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String } if (FileAccess::exists(ext_name) && p_keep_animations) { - //try to keep custom animation tracks + // Copy custom animation tracks from previously imported files. Ref<Animation> old_anim = ResourceLoader::load(ext_name, "Animation", true); if (old_anim.is_valid()) { - //meergeee for (int i = 0; i < old_anim->get_track_count(); i++) { if (!old_anim->track_is_imported(i)) { old_anim->copy_track(i, anim); @@ -970,7 +969,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String } } - anim->set_path(ext_name, true); //if not set, then its never saved externally + anim->set_path(ext_name, true); // Set path to save externally. ResourceSaver::save(ext_name, anim, ResourceSaver::FLAG_CHANGE_PATH); p_animations[anim] = anim; } diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index e99ffe2b83..49e67f3605 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -369,7 +369,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } else { const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); - if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { + if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(xform.xform(cpoint)) < grab_threshold) { //wip closed _wip_close(); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 035526ca55..de04a299fb 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -702,30 +702,26 @@ void AnimationPlayerEditor::_animation_edit() { } } -void AnimationPlayerEditor::_dialog_action(String p_file) { +void AnimationPlayerEditor::_dialog_action(String p_path) { switch (current_option) { case RESOURCE_LOAD: { ERR_FAIL_COND(!player); - Ref<Resource> res = ResourceLoader::load(p_file, "Animation"); - ERR_FAIL_COND_MSG(res.is_null(), "Cannot load Animation from file '" + p_file + "'."); - ERR_FAIL_COND_MSG(!res->is_class("Animation"), "Loaded resource from file '" + p_file + "' is not Animation."); - if (p_file.find_last("/") != -1) { - p_file = p_file.substr(p_file.find_last("/") + 1, p_file.length()); - } - if (p_file.find_last("\\") != -1) { - p_file = p_file.substr(p_file.find_last("\\") + 1, p_file.length()); - } + Ref<Resource> res = ResourceLoader::load(p_path, "Animation"); + ERR_FAIL_COND_MSG(res.is_null(), "Cannot load Animation from file '" + p_path + "'."); + ERR_FAIL_COND_MSG(!res->is_class("Animation"), "Loaded resource from file '" + p_path + "' is not Animation."); - if (p_file.find(".") != -1) { - p_file = p_file.substr(0, p_file.find(".")); + String anim_name = p_path.get_file(); + int ext_pos = anim_name.rfind("."); + if (ext_pos != -1) { + anim_name = anim_name.substr(0, ext_pos); } undo_redo->create_action(TTR("Load Animation")); - undo_redo->add_do_method(player, "add_animation", p_file, res); - undo_redo->add_undo_method(player, "remove_animation", p_file); - if (player->has_animation(p_file)) { - undo_redo->add_undo_method(player, "add_animation", p_file, player->get_animation(p_file)); + undo_redo->add_do_method(player, "add_animation", anim_name, res); + undo_redo->add_undo_method(player, "remove_animation", anim_name); + if (player->has_animation(anim_name)) { + undo_redo->add_undo_method(player, "add_animation", anim_name, player->get_animation(anim_name)); } undo_redo->add_do_method(this, "_animation_player_changed", player); undo_redo->add_undo_method(this, "_animation_player_changed", player); @@ -741,7 +737,7 @@ void AnimationPlayerEditor::_dialog_action(String p_file) { RES current_res = RES(Object::cast_to<Resource>(*anim)); - _animation_save_in_path(current_res, p_file); + _animation_save_in_path(current_res, p_path); } } } diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index ec3e25f999..dc813896ff 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -238,7 +238,7 @@ AnimationTreeEditor::AnimationTreeEditor() { add_child(memnew(HSeparator)); singleton = this; - editor_base = memnew(PanelContainer); + editor_base = memnew(MarginContainer); editor_base->set_v_size_flags(SIZE_EXPAND_FILL); add_child(editor_base); diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h index 25af81ea9b..79a010b0c0 100644 --- a/editor/plugins/animation_tree_editor_plugin.h +++ b/editor/plugins/animation_tree_editor_plugin.h @@ -55,7 +55,7 @@ class AnimationTreeEditor : public VBoxContainer { HBoxContainer *path_hb; AnimationTree *tree; - PanelContainer *editor_base; + MarginContainer *editor_base; Vector<String> button_path; Vector<String> edited_path; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index bf698a5ceb..3af0b0d4e1 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1326,6 +1326,18 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid() && !p_already_accepted) { + // If control key pressed, then zoom instead of pan + if (pan_gesture->get_control()) { + const float factor = pan_gesture->get_delta().y; + float new_zoom = _get_next_zoom_value(-1); + + if (factor != 1.f) { + new_zoom = zoom * ((new_zoom / zoom - 1.f) * factor + 1.f); + } + _zoom_on_position(new_zoom, pan_gesture->get_position()); + return true; + } + // Pan gesture const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta(); view_offset.x += delta.x; @@ -6137,6 +6149,11 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons Vector2 target_pos = canvas_item_editor->get_canvas_transform().affine_inverse().xform(p_point); target_pos = canvas_item_editor->snap_point(target_pos); target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos); + // Preserve instance position of the original scene. + CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instanced_scene); + if (instance_ci) { + target_pos += instance_ci->_edit_get_position(); + } editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); } diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 596629f8e8..105ac24950 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -242,9 +242,11 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { } break; case CONCAVE_POLYGON_SHAPE: { + // Cannot be edited directly, use CollisionPolygon2D instead. } break; case CONVEX_POLYGON_SHAPE: { + // Cannot be edited directly, use CollisionPolygon2D instead. } break; case LINE_SHAPE: { diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 896471dab5..b51ea9e1c6 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -487,6 +487,10 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b Vector3 pos = _get_ray_pos(p_pos); Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink(); + if (viewport->get_debug_draw() == Viewport::DEBUG_DRAW_SDFGI_PROBES) { + RS::get_singleton()->sdfgi_set_debug_probe_select(pos, ray); + } + Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world_3d()->get_scenario()); Set<Ref<EditorNode3DGizmo>> found_gizmos; @@ -2106,12 +2110,7 @@ void Node3DEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, cons cursor.x_rot += p_relative.y * radians_per_pixel; } cursor.y_rot += p_relative.x * radians_per_pixel; - if (cursor.x_rot > Math_PI / 2.0) { - cursor.x_rot = Math_PI / 2.0; - } - if (cursor.x_rot < -Math_PI / 2.0) { - cursor.x_rot = -Math_PI / 2.0; - } + cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57); name = ""; _update_name(); } @@ -2139,12 +2138,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const cursor.x_rot += p_relative.y * radians_per_pixel; } cursor.y_rot += p_relative.x * radians_per_pixel; - if (cursor.x_rot > Math_PI / 2.0) { - cursor.x_rot = Math_PI / 2.0; - } - if (cursor.x_rot < -Math_PI / 2.0) { - cursor.x_rot = -Math_PI / 2.0; - } + cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57); // Look is like the opposite of Orbit: the focus point rotates around the camera Transform camera_transform = to_camera_transform(cursor); @@ -2994,7 +2988,9 @@ void Node3DEditorViewport::_menu_option(int p_option) { case VIEW_DISPLAY_DEBUG_SSAO: case VIEW_DISPLAY_DEBUG_PSSM_SPLITS: case VIEW_DISPLAY_DEBUG_DECAL_ATLAS: - case VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER: { + case VIEW_DISPLAY_DEBUG_SDFGI: + case VIEW_DISPLAY_DEBUG_SDFGI_PROBES: + case VIEW_DISPLAY_DEBUG_GI_BUFFER: { static const int display_options[] = { VIEW_DISPLAY_NORMAL, VIEW_DISPLAY_WIREFRAME, @@ -3010,9 +3006,11 @@ void Node3DEditorViewport::_menu_option(int p_option) { VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, - VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER, + VIEW_DISPLAY_DEBUG_GI_BUFFER, VIEW_DISPLAY_DEBUG_PSSM_SPLITS, VIEW_DISPLAY_DEBUG_DECAL_ATLAS, + VIEW_DISPLAY_DEBUG_SDFGI, + VIEW_DISPLAY_DEBUG_SDFGI_PROBES, VIEW_MAX }; static const Viewport::DebugDraw debug_draw_modes[] = { @@ -3030,9 +3028,11 @@ void Node3DEditorViewport::_menu_option(int p_option) { Viewport::DEBUG_DRAW_GI_PROBE_EMISSION, Viewport::DEBUG_DRAW_SCENE_LUMINANCE, Viewport::DEBUG_DRAW_SSAO, - Viewport::DEBUG_DRAW_ROUGHNESS_LIMITER, + Viewport::DEBUG_DRAW_GI_BUFFER, Viewport::DEBUG_DRAW_PSSM_SPLITS, Viewport::DEBUG_DRAW_DECAL_ATLAS, + Viewport::DEBUG_DRAW_SDFGI, + Viewport::DEBUG_DRAW_SDFGI_PROBES, }; int idx = 0; @@ -3218,7 +3218,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() { Vector3 camz = -camera_xform.get_basis().get_axis(2).normalized(); Vector3 camy = -camera_xform.get_basis().get_axis(1).normalized(); Plane p(camera_xform.origin, camz); - float gizmo_d = Math::abs(p.distance_to(xform.origin)); + float gizmo_d = MAX(Math::abs(p.distance_to(xform.origin)), CMP_EPSILON); float d0 = camera->unproject_position(camera_xform.origin + camz * gizmo_d).y; float d1 = camera->unproject_position(camera_xform.origin + camz * gizmo_d + camy).y; float dd = Math::abs(d0 - d1); @@ -3908,11 +3908,14 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO); display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION); display_submenu->add_separator(); + display_submenu->add_radio_check_item(TTR("SDFGI Cascades"), VIEW_DISPLAY_DEBUG_SDFGI); + display_submenu->add_radio_check_item(TTR("SDFGI Probes"), VIEW_DISPLAY_DEBUG_SDFGI_PROBES); + display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("Scene Luminance"), VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE); display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("SSAO"), VIEW_DISPLAY_DEBUG_SSAO); display_submenu->add_separator(); - display_submenu->add_radio_check_item(TTR("Roughness Limiter"), VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER); + display_submenu->add_radio_check_item(TTR("GI Buffer"), VIEW_DISPLAY_DEBUG_GI_BUFFER); display_submenu->set_name("display_advanced"); view_menu->get_popup()->add_submenu_item(TTR("Display Advanced..."), "display_advanced", VIEW_DISPLAY_ADVANCED); view_menu->get_popup()->add_separator(); @@ -4958,7 +4961,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node3D *spatial = Object::cast_to<Node3D>(E->get()); - if (!spatial || !spatial->is_visible_in_tree()) { + if (!spatial || !spatial->is_inside_tree()) { continue; } @@ -4972,8 +4975,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed"); } - undo_redo->add_do_method(this, "_refresh_menu_icons", Variant()); - undo_redo->add_undo_method(this, "_refresh_menu_icons", Variant()); + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; case MENU_UNLOCK_SELECTED: { @@ -4983,7 +4986,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node3D *spatial = Object::cast_to<Node3D>(E->get()); - if (!spatial || !spatial->is_visible_in_tree()) { + if (!spatial || !spatial->is_inside_tree()) { continue; } @@ -4997,8 +5000,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed"); } - undo_redo->add_do_method(this, "_refresh_menu_icons", Variant()); - undo_redo->add_undo_method(this, "_refresh_menu_icons", Variant()); + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; case MENU_GROUP_SELECTED: { @@ -5008,7 +5011,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node3D *spatial = Object::cast_to<Node3D>(E->get()); - if (!spatial || !spatial->is_visible_in_tree()) { + if (!spatial || !spatial->is_inside_tree()) { continue; } @@ -5022,8 +5025,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed"); } - undo_redo->add_do_method(this, "_refresh_menu_icons", Variant()); - undo_redo->add_undo_method(this, "_refresh_menu_icons", Variant()); + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; case MENU_UNGROUP_SELECTED: { @@ -5032,7 +5035,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node3D *spatial = Object::cast_to<Node3D>(E->get()); - if (!spatial || !spatial->is_visible_in_tree()) { + if (!spatial || !spatial->is_inside_tree()) { continue; } @@ -5046,8 +5049,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed"); } - undo_redo->add_do_method(this, "_refresh_menu_icons", Variant()); - undo_redo->add_undo_method(this, "_refresh_menu_icons", Variant()); + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; } @@ -5989,6 +5992,7 @@ void Node3DEditor::_bind_methods() { ClassDB::bind_method("_unhandled_key_input", &Node3DEditor::_unhandled_key_input); ClassDB::bind_method("_get_editor_data", &Node3DEditor::_get_editor_data); ClassDB::bind_method("_request_gizmo", &Node3DEditor::_request_gizmo); + ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons); ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); @@ -6096,24 +6100,28 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_LOCK_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]); + tool_button[TOOL_LOCK_SELECTED]->set_flat(true); button_binds.write[0] = MENU_LOCK_SELECTED; tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); + tool_button[TOOL_UNLOCK_SELECTED]->set_flat(true); button_binds.write[0] = MENU_UNLOCK_SELECTED; tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved).")); tool_button[TOOL_GROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]); + tool_button[TOOL_GROUP_SELECTED]->set_flat(true); button_binds.write[0] = MENU_GROUP_SELECTED; tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable.")); tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]); + tool_button[TOOL_UNGROUP_SELECTED]->set_flat(true); button_binds.write[0] = MENU_UNGROUP_SELECTED; tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected.")); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 2fe1938f28..a40de78795 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -214,9 +214,11 @@ class Node3DEditorViewport : public Control { VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, - VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER, VIEW_DISPLAY_DEBUG_PSSM_SPLITS, VIEW_DISPLAY_DEBUG_DECAL_ATLAS, + VIEW_DISPLAY_DEBUG_SDFGI, + VIEW_DISPLAY_DEBUG_SDFGI_PROBES, + VIEW_DISPLAY_DEBUG_GI_BUFFER, VIEW_LOCK_ROTATION, VIEW_CINEMATIC_PREVIEW, VIEW_AUTO_ORTHOGONAL, diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp new file mode 100644 index 0000000000..52af0008b7 --- /dev/null +++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp @@ -0,0 +1,114 @@ +/*************************************************************************/ +/* packed_scene_translation_parser_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "packed_scene_translation_parser_plugin.h" + +#include "core/io/resource_loader.h" +#include "scene/resources/packed_scene.h" + +void PackedSceneEditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { + ResourceLoader::get_recognized_extensions_for_type("PackedScene", r_extensions); +} + +Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, Vector<String> *r_extracted_strings) { + // Parse specific scene Node's properties (see in constructor) that are auto-translated by the engine when set. E.g Label's text property. + // These properties are translated with the tr() function in the C++ code when being set or updated. + + Error err; + RES loaded_res = ResourceLoader::load(p_path, "PackedScene", false, &err); + if (err) { + ERR_PRINT("Failed to load " + p_path); + return err; + } + Ref<SceneState> state = Ref<PackedScene>(loaded_res)->get_state(); + + Vector<String> parsed_strings; + String property_name; + Variant property_value; + for (int i = 0; i < state->get_node_count(); i++) { + if (!ClassDB::is_parent_class(state->get_node_type(i), "Control") && !ClassDB::is_parent_class(state->get_node_type(i), "Viewport")) { + continue; + } + + for (int j = 0; j < state->get_node_property_count(i); j++) { + property_name = state->get_node_property_name(i, j); + if (!lookup_properties.has(property_name)) { + continue; + } + + property_value = state->get_node_property_value(i, j); + + if (property_name == "script" && property_value.get_type() == Variant::OBJECT && !property_value.is_null()) { + // Parse built-in script. + Ref<Script> s = Object::cast_to<Script>(property_value); + String extension = s->get_language()->get_extension(); + if (EditorTranslationParser::get_singleton()->can_parse(extension)) { + Vector<String> temp; + EditorTranslationParser::get_singleton()->get_parser(extension)->parse_file(s->get_path(), &temp); + parsed_strings.append_array(temp); + } + } else if (property_name == "filters") { + // Extract FileDialog's filters property with values in format "*.png ; PNG Images","*.gd ; GDScript Files". + Vector<String> str_values = property_value; + for (int k = 0; k < str_values.size(); k++) { + String desc = str_values[k].get_slice(";", 1).strip_edges(); + if (!desc.empty()) { + parsed_strings.push_back(desc); + } + } + } else if (property_value.get_type() == Variant::STRING) { + String str_value = String(property_value); + // Prevent reading text containing only spaces. + if (!str_value.strip_edges().empty()) { + parsed_strings.push_back(str_value); + } + } + } + } + + r_extracted_strings->append_array(parsed_strings); + + return OK; +} + +PackedSceneEditorTranslationParserPlugin::PackedSceneEditorTranslationParserPlugin() { + // Scene Node's properties containing strings that will be fetched for translation. + lookup_properties.insert("text"); + lookup_properties.insert("hint_tooltip"); + lookup_properties.insert("placeholder_text"); + lookup_properties.insert("dialog_text"); + lookup_properties.insert("filters"); + lookup_properties.insert("script"); + + //Add exception list (to prevent false positives) + //line edit, text edit, richtextlabel + //Set<String> exception_list; + //exception_list.insert("RichTextLabel"); +} diff --git a/editor/pane_drag.cpp b/editor/plugins/packed_scene_translation_parser_plugin.h index 09f2b90b90..9fead84c3f 100644 --- a/editor/pane_drag.cpp +++ b/editor/plugins/packed_scene_translation_parser_plugin.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pane_drag.cpp */ +/* packed_scene_translation_parser_plugin.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,48 +28,22 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "pane_drag.h" +#ifndef PACKED_SCENE_TRANSLATION_PARSER_PLUGIN_H +#define PACKED_SCENE_TRANSLATION_PARSER_PLUGIN_H -void PaneDrag::_gui_input(const Ref<InputEvent> &p_input) { - Ref<InputEventMouseMotion> mm = p_input; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { - emit_signal("dragged", Point2(mm->get_relative().x, mm->get_relative().y)); - } -} +#include "editor/editor_translation_parser.h" -void PaneDrag::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_DRAW: { - Ref<Texture2D> icon = mouse_over ? get_theme_icon("PaneDragHover", "EditorIcons") : get_theme_icon("PaneDrag", "EditorIcons"); - if (!icon.is_null()) { - icon->draw(get_canvas_item(), Point2(0, 0)); - } +class PackedSceneEditorTranslationParserPlugin : public EditorTranslationParserPlugin { + GDCLASS(PackedSceneEditorTranslationParserPlugin, EditorTranslationParserPlugin); - } break; - case NOTIFICATION_MOUSE_ENTER: - mouse_over = true; - update(); - break; - case NOTIFICATION_MOUSE_EXIT: - mouse_over = false; - update(); - break; - } -} + // Scene Node's properties that contain translation strings. + Set<String> lookup_properties; -Size2 PaneDrag::get_minimum_size() const { - Ref<Texture2D> icon = get_theme_icon("PaneDrag", "EditorIcons"); - if (!icon.is_null()) { - return icon->get_size(); - } - return Size2(); -} +public: + virtual Error parse_file(const String &p_path, Vector<String> *r_extracted_strings); + virtual void get_recognized_extensions(List<String> *r_extensions) const; -void PaneDrag::_bind_methods() { - ClassDB::bind_method("_gui_input", &PaneDrag::_gui_input); - ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::VECTOR2, "amount"))); -} + PackedSceneEditorTranslationParserPlugin(); +}; -PaneDrag::PaneDrag() { - mouse_over = false; -} +#endif // PACKED_SCENE_TRANSLATION_PARSER_PLUGIN_H diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 1d273f74f0..dd1194d020 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -485,7 +485,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else { Vector2 tuv = mtx.affine_inverse().xform(snap_point(Vector2(mb->get_position().x, mb->get_position().y))); - if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < 8) { + // Close the polygon if selected point is near start. Threshold for closing scaled by zoom level + if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < (8 / uv_draw_zoom)) { undo_redo->create_action(TTR("Create Polygon & UV")); undo_redo->add_do_method(node, "set_uv", node->get_uv()); undo_redo->add_undo_method(node, "set_uv", uv_create_uv_prev); @@ -727,35 +728,37 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { bone_painting_bone = bone_selected; } } + } else { + if (uv_drag && !uv_create) { + if (uv_edit_mode[0]->is_pressed()) { // Edit UV. + undo_redo->create_action(TTR("Transform UV Map")); + undo_redo->add_do_method(node, "set_uv", node->get_uv()); + undo_redo->add_undo_method(node, "set_uv", points_prev); + undo_redo->add_do_method(uv_edit_draw, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); + undo_redo->commit_action(); + } else if (uv_edit_mode[1]->is_pressed() && uv_move_current == UV_MODE_EDIT_POINT) { // Edit polygon. + undo_redo->create_action(TTR("Transform Polygon")); + undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); + undo_redo->add_undo_method(node, "set_polygon", points_prev); + undo_redo->add_do_method(uv_edit_draw, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); + undo_redo->commit_action(); + } - } else if (uv_drag && !uv_create) { - if (uv_edit_mode[0]->is_pressed()) { // Edit UV. - undo_redo->create_action(TTR("Transform UV Map")); - undo_redo->add_do_method(node, "set_uv", node->get_uv()); - undo_redo->add_undo_method(node, "set_uv", points_prev); - undo_redo->add_do_method(uv_edit_draw, "update"); - undo_redo->add_undo_method(uv_edit_draw, "update"); - undo_redo->commit_action(); - } else if (uv_edit_mode[1]->is_pressed() && uv_move_current == UV_MODE_EDIT_POINT) { // Edit polygon. - undo_redo->create_action(TTR("Transform Polygon")); - undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_undo_method(node, "set_polygon", points_prev); + uv_drag = false; + } + + if (bone_painting) { + undo_redo->create_action(TTR("Paint Bone Weights")); + undo_redo->add_do_method(node, "set_bone_weights", bone_painting_bone, node->get_bone_weights(bone_painting_bone)); + undo_redo->add_undo_method(node, "set_bone_weights", bone_painting_bone, prev_weights); undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); + bone_painting = false; } - - uv_drag = false; - } else if (bone_painting) { - undo_redo->create_action(TTR("Paint Bone Weights")); - undo_redo->add_do_method(node, "set_bone_weights", bone_painting_bone, node->get_bone_weights(bone_painting_bone)); - undo_redo->add_undo_method(node, "set_bone_weights", bone_painting_bone, prev_weights); - undo_redo->add_do_method(uv_edit_draw, "update"); - undo_redo->add_undo_method(uv_edit_draw, "update"); - undo_redo->commit_action(); - bone_painting = false; } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { _cancel_editing(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 3f17bf57c4..66f0155c6a 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -538,7 +538,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected)); if (current) { if (p_save) { - apply_scripts(); + _menu_option(FILE_SAVE); } Ref<Script> script = current->get_edited_resource(); @@ -1337,7 +1337,7 @@ void ScriptEditor::_notification(int p_what) { editor->disconnect("stop_pressed", callable_mp(this, &ScriptEditor::_editor_stop)); } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { _test_script_times_on_disk(); _update_modified_scripts_for_external_editor(); } break; @@ -1731,6 +1731,19 @@ void ScriptEditor::_update_script_names() { sedata.push_back(sd); } + Vector<String> disambiguated_script_names; + Vector<String> full_script_paths; + for (int j = 0; j < sedata.size(); j++) { + disambiguated_script_names.append(sedata[j].name); + full_script_paths.append(sedata[j].tooltip); + } + + EditorNode::disambiguate_filenames(full_script_paths, disambiguated_script_names); + + for (int j = 0; j < sedata.size(); j++) { + sedata.write[j].name = disambiguated_script_names[j]; + } + EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(i)); if (eh) { String name = eh->get_class(); @@ -3050,7 +3063,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KEY_MASK_ALT | KEY_MASK_CMD | KEY_S), FILE_SAVE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As...")), FILE_SAVE_AS); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_S), FILE_SAVE_ALL); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_S), FILE_SAVE_ALL); file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 4b79d8c344..9304683d77 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -343,16 +343,11 @@ void ScriptTextEditor::_set_theme_for_script() { } //colorize singleton autoloads (as types, just as engine singletons are) - List<PropertyInfo> props; - ProjectSettings::get_singleton()->get_property_list(&props); - for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - String s = E->get().name; - if (!s.begins_with("autoload/")) { - continue; - } - String path = ProjectSettings::get_singleton()->get(s); - if (path.begins_with("*")) { - text_edit->add_keyword_color(s.get_slice("/", 1), colors_cache.usertype_color); + Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) { + const ProjectSettings::AutoloadInfo &info = E->value(); + if (info.is_singleton) { + text_edit->add_keyword_color(info.name, colors_cache.usertype_color); } } @@ -383,10 +378,6 @@ void ScriptTextEditor::_show_warnings_panel(bool p_show) { warnings_panel->set_visible(p_show); } -void ScriptTextEditor::_error_pressed() { - code_editor->goto_error(); -} - void ScriptTextEditor::_warning_clicked(Variant p_line) { if (p_line.get_type() == Variant::INT) { code_editor->get_text_edit()->cursor_set_line(p_line.operator int64_t()); @@ -946,12 +937,11 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c emit_signal("go_to_help", "class_global:" + result.class_name + ":" + result.class_member); } break; } - } else if (ProjectSettings::get_singleton()->has_setting("autoload/" + p_symbol)) { - //check for Autoload scenes - String path = ProjectSettings::get_singleton()->get("autoload/" + p_symbol); - if (path.begins_with("*")) { - path = path.substr(1, path.length()); - EditorNode::get_singleton()->load_scene(path); + } else if (ProjectSettings::get_singleton()->has_autoload(p_symbol)) { + // Check for Autoload scenes. + const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(p_symbol); + if (info.is_singleton) { + EditorNode::get_singleton()->load_scene(info.path); } } else if (p_symbol.is_rel_path()) { // Every symbol other than absolute path is relative path so keep this condition at last. @@ -978,7 +968,7 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) { } ScriptLanguage::LookupResult result; - if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || ProjectSettings::get_singleton()->has_setting("autoload/" + p_symbol)) { + if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) { text_edit->set_highlighted_word(p_symbol); } else if (p_symbol.is_rel_path()) { String path = _get_absolute_path(p_symbol); @@ -1759,7 +1749,6 @@ ScriptTextEditor::ScriptTextEditor() { warnings_panel->set_focus_mode(FOCUS_CLICK); warnings_panel->hide(); - code_editor->connect("error_pressed", callable_mp(this, &ScriptTextEditor::_error_pressed)); code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel)); warnings_panel->connect("meta_clicked", callable_mp(this, &ScriptTextEditor::_warning_clicked)); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index adcd0218bc..8fa380b64d 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -159,7 +159,6 @@ protected: void _load_theme_settings(); void _set_theme_for_script(); void _show_warnings_panel(bool p_show); - void _error_pressed(); void _warning_clicked(Variant p_line); void _notification(int p_what); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 0c3a44e4cd..7dd0b8a238 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -338,7 +338,7 @@ void ShaderEditor::_menu_option(int p_option) { } void ShaderEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { _check_for_external_edit(); } } diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp index 0ac29f68f6..f15a801530 100644 --- a/editor/plugins/shader_file_editor_plugin.cpp +++ b/editor/plugins/shader_file_editor_plugin.cpp @@ -200,7 +200,7 @@ void ShaderFileEditor::_update_options() { } void ShaderFileEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { if (is_visible_in_tree() && shader_file.is_valid()) { _update_options(); } diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 3a92818779..762f42abeb 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -780,7 +780,7 @@ void TextureRegionEditor::_notification(int p_what) { _update_autoslice(); } } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { // This happens when the user leaves the Editor and returns, // they could have changed the textures, so the cache is cleared. cache_map.clear(); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 158f9e8587..307a8a9001 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -64,6 +64,8 @@ void TileMapEditor::_notification(int p_what) { } paint_button->set_icon(get_theme_icon("Edit", "EditorIcons")); + line_button->set_icon(get_theme_icon("CurveLinear", "EditorIcons")); + rectangle_button->set_icon(get_theme_icon("RectangleShape2D", "EditorIcons")); bucket_fill_button->set_icon(get_theme_icon("Bucket", "EditorIcons")); picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons")); select_button->set_icon(get_theme_icon("ActionCopy", "EditorIcons")); @@ -91,9 +93,10 @@ void TileMapEditor::_notification(int p_what) { } void TileMapEditor::_update_button_tool() { - Button *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button }; + Button *tb[6] = { paint_button, line_button, rectangle_button, bucket_fill_button, picker_button, select_button }; + // Unpress all buttons - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 6; i++) { tb[i]->set_pressed(false); } @@ -103,6 +106,12 @@ void TileMapEditor::_update_button_tool() { case TOOL_PAINTING: { paint_button->set_pressed(true); } break; + case TOOL_LINE_PAINT: { + line_button->set_pressed(true); + } break; + case TOOL_RECTANGLE_PAINT: { + rectangle_button->set_pressed(true); + } break; case TOOL_BUCKET: { bucket_fill_button->set_pressed(true); } break; @@ -993,19 +1002,8 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } if (tool == TOOL_NONE) { - if (mb->get_shift()) { - if (mb->get_command()) { - tool = TOOL_RECTANGLE_PAINT; - } else { - tool = TOOL_LINE_PAINT; - } - - selection_active = false; - rectangle_begin = over_tile; - - _update_button_tool(); - return true; - } + tool = TOOL_PAINTING; + _update_button_tool(); if (mb->get_command()) { tool = TOOL_PICKING; @@ -1014,12 +1012,14 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return true; } - - tool = TOOL_PAINTING; - _update_button_tool(); } - if (tool == TOOL_PAINTING) { + if (tool == TOOL_LINE_PAINT || tool == TOOL_RECTANGLE_PAINT) { + selection_active = false; + rectangle_begin = over_tile; + + mouse_down = true; + } else if (tool == TOOL_PAINTING) { Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1050,6 +1050,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { paint_undo.clear(); } } else if (tool == TOOL_LINE_PAINT) { + if (!mouse_down) { + return true; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1062,8 +1066,17 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { paint_undo.clear(); CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } + + mouse_down = false; } else if (tool == TOOL_RECTANGLE_PAINT) { + if (!mouse_down) { + return true; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1076,7 +1089,12 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { _finish_undo(); CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } + + mouse_down = false; } else if (tool == TOOL_PASTING) { Point2 ofs = over_tile - rectangle.position; Vector<int> ids; @@ -1141,6 +1159,28 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (tool == TOOL_PASTING) { tool = TOOL_NONE; + + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + + if (tool == TOOL_LINE_PAINT) { + tool = TOOL_LINE_ERASE; + mouse_down = true; + rectangle_begin = over_tile; + + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + + if (tool == TOOL_RECTANGLE_PAINT) { + tool = TOOL_RECTANGLE_ERASE; + mouse_down = true; + rectangle_begin = over_tile; copydata.clear(); CanvasItemEditor::get_singleton()->update_viewport(); @@ -1155,39 +1195,74 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Point2 local = node->world_to_map(xform_inv.xform(mb->get_position())); _start_undo(TTR("Erase TileMap")); + tool = TOOL_ERASING; + _set_cell(local, invalid_cell); - if (mb->get_shift()) { - if (mb->get_command()) { - tool = TOOL_RECTANGLE_ERASE; - } else { - tool = TOOL_LINE_ERASE; + _update_button_tool(); + return true; + } + + } else { + if (tool == TOOL_LINE_ERASE) { + if (!mouse_down) { + return true; + } + + tool = TOOL_LINE_PAINT; + _update_button_tool(); + + Vector<int> ids = get_selected_tiles(); + + if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { + _start_undo(TTR("Line Erase")); + for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { + _set_cell(E->key(), invalid_cell, flip_h, flip_v, transpose); } + _finish_undo(); + paint_undo.clear(); - selection_active = false; - rectangle_begin = local; - } else { - tool = TOOL_ERASING; + CanvasItemEditor::get_singleton()->update_viewport(); - _set_cell(local, invalid_cell); + mouse_down = false; + return true; } + mouse_down = false; + } else if (tool == TOOL_RECTANGLE_ERASE) { + if (!mouse_down) { + return true; + } + + tool = TOOL_RECTANGLE_PAINT; _update_button_tool(); - return true; - } - } else { - if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { - _finish_undo(); + Vector<int> ids = get_selected_tiles(); + + if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { + _start_undo(TTR("Rectangle Erase")); + for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) { + for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) { + _set_cell(Point2i(j, i), invalid_cell, flip_h, flip_v, transpose); + } + } + _finish_undo(); + paint_undo.clear(); - if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } - tool = TOOL_NONE; + mouse_down = false; + tool = TOOL_RECTANGLE_PAINT; + } + if (tool == TOOL_ERASING) { + tool = TOOL_NONE; _update_button_tool(); - return true; + return true; } else if (tool == TOOL_BUCKET) { Vector<int> ids; ids.push_back(node->get_cell(over_tile.x, over_tile.y)); @@ -1278,6 +1353,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Vector<int> tmp_cell; bool erasing = (tool == TOOL_LINE_ERASE); + if (!mouse_down) { + return true; + } + tmp_cell.push_back(0); if (erasing && paint_undo.size()) { for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { @@ -1308,7 +1387,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Vector<int> tmp_cell; tmp_cell.push_back(0); - _select(rectangle_begin, over_tile); + Point2i end_tile = over_tile; + + if (!mouse_down) { + return true; + } + + if (mm->get_shift()) { + int size = fmax(ABS(end_tile.x - rectangle_begin.x), ABS(end_tile.y - rectangle_begin.y)); + int xDirection = MAX(MIN(end_tile.x - rectangle_begin.x, 1), -1); + int yDirection = MAX(MIN(end_tile.y - rectangle_begin.y, 1), -1); + end_tile = rectangle_begin + Point2i(xDirection * size, yDirection * size); + } + + _select(rectangle_begin, end_tile); if (tool == TOOL_RECTANGLE_ERASE) { if (paint_undo.size()) { @@ -1379,6 +1471,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { _update_button_tool(); return true; } + if (ED_IS_SHORTCUT("tile_map_editor/line_fill", p_event)) { + tool = TOOL_LINE_PAINT; + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + if (ED_IS_SHORTCUT("tile_map_editor/rectangle_fill", p_event)) { + tool = TOOL_RECTANGLE_PAINT; + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) { tool = TOOL_BUCKET; CanvasItemEditor::get_singleton()->update_viewport(); @@ -1637,6 +1743,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { } if (tool == TOOL_LINE_PAINT) { + if (!mouse_down) { + return; + } + if (paint_undo.empty()) { return; } @@ -1652,6 +1762,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { } } else if (tool == TOOL_RECTANGLE_PAINT) { + if (!mouse_down) { + return; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() == 1 && ids[0] == TileMap::INVALID_CELL) { @@ -1865,6 +1979,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { tool = TOOL_NONE; selection_active = false; mouse_over = false; + mouse_down = false; flip_h = false; flip_v = false; @@ -1962,11 +2077,27 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { paint_button = memnew(Button); paint_button->set_flat(true); paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P)); - paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Ctrl+LMB: Rectangle Paint")); + paint_button->set_tooltip(TTR("RMB: Erase")); paint_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_NONE)); paint_button->set_toggle_mode(true); toolbar->add_child(paint_button); + line_button = memnew(Button); + line_button->set_flat(true); + line_button->set_shortcut(ED_SHORTCUT("tile_map_editor/line_fill", TTR("Line Fill"), KEY_L)); + line_button->set_tooltip(TTR("RMB: Erase")); + line_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_LINE_PAINT)); + line_button->set_toggle_mode(true); + toolbar->add_child(line_button); + + rectangle_button = memnew(Button); + rectangle_button->set_flat(true); + rectangle_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rectangle_fill", TTR("Rectangle Fill"), KEY_O)); + rectangle_button->set_tooltip(TTR("Shift+LMB: Keep 1:1 proporsions\nRMB: Erase")); + rectangle_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_RECTANGLE_PAINT)); + rectangle_button->set_toggle_mode(true); + toolbar->add_child(rectangle_button); + bucket_fill_button = memnew(Button); bucket_fill_button->set_flat(true); bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_B)); diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index 1d2ecdb61f..135a9bd5a5 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -88,6 +88,8 @@ class TileMapEditor : public VBoxContainer { MenuButton *options; Button *paint_button; + Button *line_button; + Button *rectangle_button; Button *bucket_fill_button; Button *picker_button; Button *select_button; @@ -106,6 +108,7 @@ class TileMapEditor : public VBoxContainer { bool selection_active; bool mouse_over; + bool mouse_down; bool flip_h; bool flip_v; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 89ab747cde..13d8f0c856 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -2450,6 +2450,7 @@ VisualShaderEditor::VisualShaderEditor() { members_dialog = memnew(ConfirmationDialog); members_dialog->set_title(TTR("Create Shader Node")); + members_dialog->set_exclusive(false); members_dialog->add_child(members_vb); members_dialog->get_ok()->set_text(TTR("Create")); members_dialog->get_ok()->connect("pressed", callable_mp(this, &VisualShaderEditor::_member_create)); diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp new file mode 100644 index 0000000000..f9b8722aad --- /dev/null +++ b/editor/pot_generator.cpp @@ -0,0 +1,166 @@ +/*************************************************************************/ +/* pot_generator.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "pot_generator.h" + +#include "core/error_macros.h" +#include "core/os/file_access.h" +#include "core/project_settings.h" +#include "editor_translation_parser.h" +#include "plugins/packed_scene_translation_parser_plugin.h" + +POTGenerator *POTGenerator::singleton = nullptr; + +//#define DEBUG_POT + +#ifdef DEBUG_POT +void _print_all_translation_strings(const OrderedHashMap<String, Set<String>> &p_all_translation_strings) { + for (auto E_pair = p_all_translation_strings.front(); E_pair; E_pair = E_pair.next()) { + String msg = static_cast<String>(E_pair.key()) + " : "; + for (Set<String>::Element *E = E_pair.value().front(); E; E = E->next()) { + msg += E->get() + " "; + } + print_line(msg); + } +} +#endif + +void POTGenerator::generate_pot(const String &p_file) { + if (!ProjectSettings::get_singleton()->has_setting("locale/translations_pot_files")) { + WARN_PRINT("No files selected for POT generation."); + return; + } + + // Clear all_translation_strings of the previous round. + all_translation_strings.clear(); + + Vector<String> files = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + + // Collect all translatable strings according to files order in "POT Generation" setting. + for (int i = 0; i < files.size(); i++) { + Vector<String> translation_strings; + String file_path = files[i]; + String file_extension = file_path.get_extension(); + + if (EditorTranslationParser::get_singleton()->can_parse(file_extension)) { + EditorTranslationParser::get_singleton()->get_parser(file_extension)->parse_file(file_path, &translation_strings); + } else { + ERR_PRINT("Unrecognized file extension " + file_extension + " in generate_pot()"); + return; + } + + // Store translation strings parsed in this iteration along with their corresponding source file - to write into POT later on. + for (int j = 0; j < translation_strings.size(); j++) { + all_translation_strings[translation_strings[j]].insert(file_path); + } + } + +#ifdef DEBUG_POT + _print_all_translation_strings(all_translation_strings); +#endif + + _write_to_pot(p_file); +} + +void POTGenerator::_write_to_pot(const String &p_file) { + Error err; + FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err); + if (err != OK) { + ERR_PRINT("Failed to open " + p_file); + return; + } + + String project_name = ProjectSettings::get_singleton()->get("application/config/name"); + Vector<String> files = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + String extracted_files = ""; + for (int i = 0; i < files.size(); i++) { + extracted_files += "# " + files[i] + "\n"; + } + const String header = + "# LANGUAGE translation for " + project_name + " for the following files:\n" + extracted_files + + "#\n" + "#\n" + "# FIRST AUTHOR < EMAIL @ADDRESS>, YEAR.\n" + "#\n" + "#, fuzzy\n" + "msgid \"\"\n" + "msgstr \"\"\n" + "\"Project-Id-Version: " + + project_name + "\\n\"\n" + "\"Content-Type: text/plain; charset=UTF-8\\n\"\n" + "\"Content-Transfer-Encoding: 8-bit\\n\"\n\n"; + + file->store_string(header); + + for (OrderedHashMap<String, Set<String>>::Element E_pair = all_translation_strings.front(); E_pair; E_pair = E_pair.next()) { + String msg = E_pair.key(); + + // Write file locations. + for (Set<String>::Element *E = E_pair.value().front(); E; E = E->next()) { + file->store_line("#: " + E->get().trim_prefix("res://")); + } + + // Split \\n and \n. + Vector<String> temp = msg.split("\\n"); + Vector<String> msg_lines; + for (int i = 0; i < temp.size(); i++) { + msg_lines.append_array(temp[i].split("\n")); + if (i < temp.size() - 1) { + // Add \n. + msg_lines.set(msg_lines.size() - 1, msg_lines[msg_lines.size() - 1] + "\\n"); + } + } + + // Write msgid. + file->store_string("msgid "); + for (int i = 0; i < msg_lines.size(); i++) { + file->store_line("\"" + msg_lines[i] + "\""); + } + + file->store_line("msgstr \"\"\n"); + } + + file->close(); +} + +POTGenerator *POTGenerator::get_singleton() { + if (!singleton) { + singleton = memnew(POTGenerator); + } + return singleton; +} + +POTGenerator::POTGenerator() { +} + +POTGenerator::~POTGenerator() { + memdelete(singleton); + singleton = nullptr; +} diff --git a/editor/pane_drag.h b/editor/pot_generator.h index 81aff4b2a8..abe1a21d41 100644 --- a/editor/pane_drag.h +++ b/editor/pot_generator.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pane_drag.h */ +/* pot_generator.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,24 +28,25 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PANE_DRAG_H -#define PANE_DRAG_H +#ifndef POT_GENERATOR_H +#define POT_GENERATOR_H -#include "scene/gui/control.h" +#include "core/ordered_hash_map.h" +#include "core/set.h" -class PaneDrag : public Control { - GDCLASS(PaneDrag, Control); +class POTGenerator { + static POTGenerator *singleton; + // Stores all translatable strings and the source files containing them. + OrderedHashMap<String, Set<String>> all_translation_strings; - bool mouse_over; - -protected: - void _gui_input(const Ref<InputEvent> &p_input); - void _notification(int p_what); - virtual Size2 get_minimum_size() const; - static void _bind_methods(); + void _write_to_pot(const String &p_file); public: - PaneDrag(); + static POTGenerator *get_singleton(); + void generate_pot(const String &p_file); + + POTGenerator(); + ~POTGenerator(); }; -#endif // PANE_DRAG_H +#endif // POT_GENERATOR_H diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index a800f9e8eb..5184793760 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -294,7 +294,7 @@ private: // If the project name is empty or default, infer the project name from the selected folder name if (project_name->get_text() == "" || project_name->get_text() == TTR("New Game Project")) { sp = sp.replace("\\", "/"); - int lidx = sp.find_last("/"); + int lidx = sp.rfind("/"); if (lidx != -1) { sp = sp.substr(lidx + 1, sp.length()).capitalize(); @@ -2336,10 +2336,10 @@ ProjectManager::ProjectManager() { switch (display_scale) { case 0: { // Try applying a suitable display scale automatically - const int screen = DisplayServer::get_singleton()->window_get_current_screen(); #ifdef OSX_ENABLED - editor_set_scale(DisplayServer::get_singleton()->screen_get_scale(screen)); + editor_set_scale(DisplayServer::get_singleton()->screen_get_max_scale()); #else + const int screen = DisplayServer::get_singleton()->window_get_current_screen(); editor_set_scale(DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000 ? 2.0 : 1.0); #endif } break; @@ -2371,11 +2371,8 @@ ProjectManager::ProjectManager() { // Define a minimum window size to prevent UI elements from overlapping or being cut off DisplayServer::get_singleton()->window_set_min_size(Size2(750, 420) * EDSCALE); -#ifndef OSX_ENABLED - // The macOS platform implementation uses its own hiDPI window resizing code // TODO: Resize windows on hiDPI displays on Windows and Linux and remove the line below DisplayServer::get_singleton()->window_set_size(DisplayServer::get_singleton()->window_get_size() * MAX(1, EDSCALE)); -#endif } FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index f2c4a533ea..f84845179b 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -38,6 +38,8 @@ #include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_translation_parser.h" +#include "editor/pot_generator.h" #include "scene/gui/margin_container.h" #include "scene/gui/tab_container.h" @@ -120,6 +122,7 @@ void ProjectSettingsEditor::_notification(int p_what) { action_add_error->add_theme_color_override("font_color", input_editor->get_theme_color("error_color", "Editor")); translation_list->connect("button_pressed", callable_mp(this, &ProjectSettingsEditor::_translation_delete)); + translation_pot_list->connect("button_pressed", callable_mp(this, &ProjectSettingsEditor::_translation_pot_delete)); _update_actions(); popup_add->add_icon_item(input_editor->get_theme_icon("Keyboard", "EditorIcons"), TTR("Key"), INPUT_KEY); popup_add->add_icon_item(input_editor->get_theme_icon("KeyboardPhysical", "EditorIcons"), TTR("Physical Key"), INPUT_KEY_PHYSICAL); @@ -140,6 +143,9 @@ void ProjectSettingsEditor::_notification(int p_what) { translation_res_option_file_open->add_filter("*." + E->get()); } + _update_translation_pot_file_extensions(); + translation_pot_generate->add_filter("*.pot"); + restart_close_button->set_icon(input_editor->get_theme_icon("Close", "EditorIcons")); restart_container->add_theme_style_override("panel", input_editor->get_theme_stylebox("bg", "Tree")); restart_icon->set_texture(input_editor->get_theme_icon("StatusWarning", "EditorIcons")); @@ -865,6 +871,8 @@ void ProjectSettingsEditor::popup_project_settings() { _update_translations(); autoload_settings->update_autoload(); plugin_settings->update_plugins(); + // New translation parser plugin might extend possible file extensions in POT generation. + _update_translation_pot_file_extensions(); set_process_unhandled_input(true); } @@ -1519,8 +1527,71 @@ void ProjectSettingsEditor::_translation_filter_mode_changed(int p_mode) { undo_redo->commit_action(); } +void ProjectSettingsEditor::_translation_pot_add(const String &p_path) { + PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + + for (int i = 0; i < pot_translations.size(); i++) { + if (pot_translations[i] == p_path) { + return; //exists + } + } + + pot_translations.push_back(p_path); + undo_redo->create_action(TTR("Add files for POT generation")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", pot_translations); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", ProjectSettings::get_singleton()->get("locale/translations_pot_files")); + undo_redo->add_do_method(this, "_update_translations"); + undo_redo->add_undo_method(this, "_update_translations"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); +} + +void ProjectSettingsEditor::_translation_pot_delete(Object *p_item, int p_column, int p_button) { + TreeItem *ti = Object::cast_to<TreeItem>(p_item); + ERR_FAIL_COND(!ti); + + int idx = ti->get_metadata(0); + + PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + + ERR_FAIL_INDEX(idx, pot_translations.size()); + + pot_translations.remove(idx); + + undo_redo->create_action(TTR("Remove file from POT generation")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", pot_translations); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", ProjectSettings::get_singleton()->get("locale/translations_pot_files")); + undo_redo->add_do_method(this, "_update_translations"); + undo_redo->add_undo_method(this, "_update_translations"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); +} + +void ProjectSettingsEditor::_translation_pot_file_open() { + translation_pot_file_open->popup_centered_ratio(); +} + +void ProjectSettingsEditor::_translation_pot_generate_open() { + translation_pot_generate->popup_centered_ratio(); +} + +void ProjectSettingsEditor::_translation_pot_generate(const String &p_file) { + POTGenerator::get_singleton()->generate_pot(p_file); +} + +void ProjectSettingsEditor::_update_translation_pot_file_extensions() { + translation_pot_file_open->clear_filters(); + List<String> translation_parse_file_extensions; + EditorTranslationParser::get_singleton()->get_recognized_extensions(&translation_parse_file_extensions); + for (List<String>::Element *E = translation_parse_file_extensions.front(); E; E = E->next()) { + translation_pot_file_open->add_filter("*." + E->get()); + } +} + void ProjectSettingsEditor::_update_translations() { - //update translations + // Update translations. if (updating_translations) { return; @@ -1601,7 +1672,7 @@ void ProjectSettingsEditor::_update_translations() { } } - //update translation remaps + // Update translation remaps. String remap_selected; if (translation_remap->get_selected()) { @@ -1666,7 +1737,7 @@ void ProjectSettingsEditor::_update_translations() { PackedStringArray selected = remaps[keys[i]]; for (int j = 0; j < selected.size(); j++) { String s2 = selected[j]; - int qp = s2.find_last(":"); + int qp = s2.rfind(":"); String path = s2.substr(0, qp); String locale = s2.substr(qp + 1, s2.length()); @@ -1696,6 +1767,23 @@ void ProjectSettingsEditor::_update_translations() { } } + // Update translation POT files. + + translation_pot_list->clear(); + root = translation_pot_list->create_item(nullptr); + translation_pot_list->set_hide_root(true); + if (ProjectSettings::get_singleton()->has_setting("locale/translations_pot_files")) { + PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + for (int i = 0; i < pot_translations.size(); i++) { + TreeItem *t = translation_pot_list->create_item(root); + t->set_editable(0, false); + t->set_text(0, pot_translations[i].replace_first("res://", "")); + t->set_tooltip(0, pot_translations[i]); + t->set_metadata(0, i); + t->add_button(0, input_editor->get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove")); + } + } + updating_translations = false; } @@ -1865,7 +1953,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { restart_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER); restart_hb->add_child(restart_icon); restart_label = memnew(Label); - restart_label->set_text(TTR("The editor must be restarted for changes to take effect.")); + restart_label->set_text(TTR("Changed settings will be applied to the editor after restarting.")); restart_hb->add_child(restart_label); restart_hb->add_spacer(); Button *restart_button = memnew(Button); @@ -2108,6 +2196,38 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { translation_filter->connect("item_edited", callable_mp(this, &ProjectSettingsEditor::_translation_filter_option_changed)); } + { + VBoxContainer *tvb = memnew(VBoxContainer); + translations->add_child(tvb); + tvb->set_name(TTR("POT Generation")); + HBoxContainer *thb = memnew(HBoxContainer); + tvb->add_child(thb); + thb->add_child(memnew(Label(TTR("Files with translation strings:")))); + thb->add_spacer(); + Button *addtr = memnew(Button(TTR("Add..."))); + addtr->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_translation_pot_file_open)); + thb->add_child(addtr); + Button *generate = memnew(Button(TTR("Generate POT"))); + generate->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_translation_pot_generate_open)); + thb->add_child(generate); + VBoxContainer *tmc = memnew(VBoxContainer); + tvb->add_child(tmc); + tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); + translation_pot_list = memnew(Tree); + translation_pot_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + tmc->add_child(translation_pot_list); + + translation_pot_generate = memnew(EditorFileDialog); + add_child(translation_pot_generate); + translation_pot_generate->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + translation_pot_generate->connect("file_selected", callable_mp(this, &ProjectSettingsEditor::_translation_pot_generate)); + + translation_pot_file_open = memnew(EditorFileDialog); + add_child(translation_pot_file_open); + translation_pot_file_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + translation_pot_file_open->connect("file_selected", callable_mp(this, &ProjectSettingsEditor::_translation_pot_add)); + } + autoload_settings = memnew(EditorAutoloadSettings); autoload_settings->set_name(TTR("AutoLoad")); tab_container->add_child(autoload_settings); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 728f31efa8..cf47b1df4a 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -110,6 +110,10 @@ class ProjectSettingsEditor : public AcceptDialog { Vector<TreeItem *> translation_filter_treeitems; Vector<int> translation_locales_idxs_remap; + Tree *translation_pot_list; + EditorFileDialog *translation_pot_file_open; + EditorFileDialog *translation_pot_generate; + EditorAutoloadSettings *autoload_settings; EditorPluginSettings *plugin_settings; @@ -159,6 +163,13 @@ class ProjectSettingsEditor : public AcceptDialog { void _translation_filter_option_changed(); void _translation_filter_mode_changed(int p_mode); + void _translation_pot_add(const String &p_path); + void _translation_pot_delete(Object *p_item, int p_column, int p_button); + void _translation_pot_file_open(); + void _translation_pot_generate_open(); + void _translation_pot_generate(const String &p_file); + void _update_translation_pot_file_extensions(); + void _toggle_search_bar(bool p_pressed); Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 49b9ca167b..f4838d336f 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -597,7 +597,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_METHOD_OF_INSTANCE) { MAKE_PROPSELECT - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (instance) { property_select->select_method_from_instance(instance, v); } @@ -607,7 +607,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_METHOD_OF_SCRIPT) { MAKE_PROPSELECT - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (Object::cast_to<Script>(obj)) { property_select->select_method_from_script(Object::cast_to<Script>(obj), v); } @@ -646,7 +646,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_PROPERTY_OF_INSTANCE) { MAKE_PROPSELECT - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (instance) { property_select->select_property_from_instance(instance, v); } @@ -657,7 +657,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_PROPERTY_OF_SCRIPT) { MAKE_PROPSELECT - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (Object::cast_to<Script>(obj)) { property_select->select_property_from_script(Object::cast_to<Script>(obj), v); } diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index bcef29dfa6..4af6fb2053 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -32,21 +32,18 @@ #include "core/os/keyboard.h" -void EditorQuickOpen::popup_dialog(const StringName &p_base, bool p_enable_multi, bool p_add_dirs, bool p_dontclear) { - add_directories = p_add_dirs; - popup_centered_ratio(0.6); +void EditorQuickOpen::popup_dialog(const StringName &p_base, bool p_enable_multi, bool p_dontclear) { + base_type = p_base; + search_options->set_select_mode(p_enable_multi ? Tree::SELECT_MULTI : Tree::SELECT_SINGLE); + popup_centered_ratio(0.4); + if (p_dontclear) { search_box->select_all(); } else { search_box->clear(); } - if (p_enable_multi) { - search_options->set_select_mode(Tree::SELECT_MULTI); - } else { - search_options->set_select_mode(Tree::SELECT_SINGLE); - } + search_box->grab_focus(); - base_type = p_base; _update_search(); } @@ -65,7 +62,6 @@ Vector<String> EditorQuickOpen::get_selected_files() const { TreeItem *item = search_options->get_next_selected(search_options->get_root()); while (item) { files.push_back("res://" + item->get_text(0)); - item = search_options->get_next_selected(item); } @@ -93,7 +89,6 @@ void EditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) { } TreeItem *current = search_options->get_selected(); - TreeItem *item = search_options->get_next_selected(root); while (item) { item->deselect(0); @@ -101,88 +96,55 @@ void EditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) { } current->select(0); - + current->set_as_cursor(0); } break; } } } -float EditorQuickOpen::_path_cmp(String search, String path) const { - // Exact match. - if (search == path) { - return 1.2f; +float EditorQuickOpen::_score_path(String search, String path) const { + // Positive bias for matches close to the _beginning of the file name_. + String file = path.get_file(); + int pos = file.findn(search); + if (pos != -1) { + return 1.0f - 0.1f * (float(pos) / file.length()); } - // Substring match, with positive bias for matches close to the end of the path. - int pos = path.rfindn(search); + // Positive bias for matches close to the _end of the path_. + String base = path.get_base_dir(); + pos = base.rfindn(search); if (pos != -1) { - return 1.1f + 0.09 / (path.length() - pos + 1); + return 0.9f - 0.1f * (float(base.length() - pos) / base.length()); } - // Similarity. - return path.to_lower().similarity(search.to_lower()); + // Results that contain all characters but not the string. + return path.similarity(search) * 0.8f; } void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<String, Ref<Texture2D>>> &list) { - if (!add_directories) { - for (int i = 0; i < efsd->get_subdir_count(); i++) { - _parse_fs(efsd->get_subdir(i), list); - } + for (int i = 0; i < efsd->get_subdir_count(); i++) { + _parse_fs(efsd->get_subdir(i), list); } - String search_text = search_box->get_text(); - - if (add_directories) { - String path = efsd->get_path(); - if (!path.ends_with("/")) { - path += "/"; - } - if (path != "res://") { - path = path.substr(6, path.length()); - if (search_text.is_subsequence_ofi(path)) { - Pair<String, Ref<Texture2D>> pair; - pair.first = path; - pair.second = search_options->get_theme_icon("folder", "FileDialog"); - - if (search_text != String() && list.size() > 0) { - float this_sim = _path_cmp(search_text, path); - float other_sim = _path_cmp(list[0].first, path); - int pos = 1; - - while (pos < list.size() && this_sim <= other_sim) { - other_sim = _path_cmp(list[pos++].first, path); - } + for (int i = 0; i < efsd->get_file_count(); i++) { + StringName file_type = efsd->get_file_type(i); - pos = this_sim >= other_sim ? pos - 1 : pos; - list.insert(pos, pair); + if (ClassDB::is_parent_class(file_type, base_type)) { + String file = efsd->get_file_path(i); + file = file.substr(6, file.length()); - } else { - list.push_back(pair); - } + if (search_box->get_text().is_subsequence_ofi(file)) { + Pair<String, Ref<Texture2D>> pair; + pair.first = file; + pair.second = search_options->get_theme_icon(search_options->has_theme_icon(file_type, ei) ? file_type : ot, ei); + list.push_back(pair); } } } - for (int i = 0; i < efsd->get_file_count(); i++) { - String file = efsd->get_file_path(i); - file = file.substr(6, file.length()); - - if (ClassDB::is_parent_class(efsd->get_file_type(i), base_type) && (search_text.is_subsequence_ofi(file))) { - Pair<String, Ref<Texture2D>> pair; - pair.first = file; - pair.second = search_options->get_theme_icon((search_options->has_theme_icon(efsd->get_file_type(i), ei) ? efsd->get_file_type(i) : ot), ei); - list.push_back(pair); - } - } - - if (add_directories) { - for (int i = 0; i < efsd->get_subdir_count(); i++) { - _parse_fs(efsd->get_subdir(i), list); - } - } } Vector<Pair<String, Ref<Texture2D>>> EditorQuickOpen::_sort_fs(Vector<Pair<String, Ref<Texture2D>>> &list) { - String search_text = search_box->get_text(); + String search_text = search_box->get_text().to_lower(); Vector<Pair<String, Ref<Texture2D>>> sorted_list; if (search_text == String() || list.size() == 0) { @@ -192,7 +154,7 @@ Vector<Pair<String, Ref<Texture2D>>> EditorQuickOpen::_sort_fs(Vector<Pair<Strin Vector<float> scores; scores.resize(list.size()); for (int i = 0; i < list.size(); i++) { - scores.write[i] = _path_cmp(search_text, list[i].first); + scores.write[i] = _score_path(search_text, list[i].first.to_lower()); } while (list.size() > 0) { @@ -230,19 +192,17 @@ void EditorQuickOpen::_update_search() { ti->set_icon(0, list[i].second); } - if (root->get_children()) { - TreeItem *ti = root->get_children(); - - ti->select(0); - ti->set_as_cursor(0); + TreeItem *result = root->get_children(); + if (result) { + result->select(0); + result->set_as_cursor(0); } - get_ok()->set_disabled(root->get_children() == nullptr); + get_ok()->set_disabled(!result); } void EditorQuickOpen::_confirmed() { - TreeItem *ti = search_options->get_selected(); - if (!ti) { + if (!search_options->get_selected()) { return; } emit_signal("quick_open"); @@ -250,7 +210,7 @@ void EditorQuickOpen::_confirmed() { } void EditorQuickOpen::_theme_changed() { - search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons")); + search_box->set_right_icon(search_options->get_theme_icon("Search", ei)); } void EditorQuickOpen::_notification(int p_what) { @@ -277,23 +237,24 @@ void EditorQuickOpen::_bind_methods() { EditorQuickOpen::EditorQuickOpen() { VBoxContainer *vbc = memnew(VBoxContainer); vbc->connect("theme_changed", callable_mp(this, &EditorQuickOpen::_theme_changed)); - add_child(vbc); + search_box = memnew(LineEdit); - vbc->add_margin_child(TTR("Search:"), search_box); search_box->connect("text_changed", callable_mp(this, &EditorQuickOpen::_text_changed)); search_box->connect("gui_input", callable_mp(this, &EditorQuickOpen::_sbox_input)); + vbc->add_margin_child(TTR("Search:"), search_box); + search_options = memnew(Tree); - vbc->add_margin_child(TTR("Matches:"), search_options, true); - get_ok()->set_text(TTR("Open")); - get_ok()->set_disabled(true); - register_text_enter(search_box); - set_hide_on_ok(false); search_options->connect("item_activated", callable_mp(this, &EditorQuickOpen::_confirmed)); search_options->set_hide_root(true); search_options->set_hide_folding(true); search_options->add_theme_constant_override("draw_guides", 1); + vbc->add_margin_child(TTR("Matches:"), search_options, true); + + get_ok()->set_text(TTR("Open")); + register_text_enter(search_box); + set_hide_on_ok(false); + ei = "EditorIcons"; ot = "Object"; - add_directories = false; } diff --git a/editor/quick_open.h b/editor/quick_open.h index e446ed6823..5bcdfc7bf2 100644 --- a/editor/quick_open.h +++ b/editor/quick_open.h @@ -35,22 +35,23 @@ #include "editor_file_system.h" #include "scene/gui/dialogs.h" #include "scene/gui/tree.h" + class EditorQuickOpen : public ConfirmationDialog { GDCLASS(EditorQuickOpen, ConfirmationDialog); LineEdit *search_box; Tree *search_options; + StringName base_type; StringName ei; StringName ot; - bool add_directories; void _update_search(); void _sbox_input(const Ref<InputEvent> &p_ie); void _parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<String, Ref<Texture2D>>> &list); Vector<Pair<String, Ref<Texture2D>>> _sort_fs(Vector<Pair<String, Ref<Texture2D>>> &list); - float _path_cmp(String search, String path) const; + float _score_path(String search, String path) const; void _confirmed(); void _text_changed(const String &p_newtext); @@ -67,7 +68,7 @@ public: String get_selected() const; Vector<String> get_selected_files() const; - void popup_dialog(const StringName &p_base, bool p_enable_multi = false, bool p_add_dirs = false, bool p_dontclear = false); + void popup_dialog(const StringName &p_base, bool p_enable_multi = false, bool p_dontclear = false); EditorQuickOpen(); }; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index dd42ed9760..41b8baeb2f 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -350,17 +350,26 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (!profile_allow_editing) { break; } - String preferred = ""; - Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene(); + // Prefer nodes that inherit from the current scene root. + Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene(); if (current_edited_scene_root) { - if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node2D")) { - preferred = "Node2D"; - } else if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node3D")) { - preferred = "Node3D"; + String root_class = current_edited_scene_root->get_class_name(); + static Vector<String> preferred_types; + if (preferred_types.empty()) { + preferred_types.push_back("Control"); + preferred_types.push_back("Node2D"); + preferred_types.push_back("Node3D"); + } + + for (int i = 0; i < preferred_types.size(); i++) { + if (ClassDB::is_parent_class(root_class, preferred_types[i])) { + create_dialog->set_preferred_search_result_type(preferred_types[i]); + break; + } } } - create_dialog->set_preferred_search_result_type(preferred); + create_dialog->popup_create(true); } break; case TOOL_INSTANCE: { @@ -736,17 +745,28 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { _delete_confirm(); } else { - if (remove_list.size() >= 2) { - delete_dialog->set_text(vformat(TTR("Delete %d nodes?"), remove_list.size())); - } else if (remove_list.size() == 1 && remove_list[0] == editor_data->get_edited_scene_root()) { - delete_dialog->set_text(vformat(TTR("Delete the root node \"%s\"?"), remove_list[0]->get_name())); - } else if (remove_list.size() == 1 && remove_list[0]->get_filename() == "" && remove_list[0]->get_child_count() >= 1) { - // Display this message only for non-instanced scenes - delete_dialog->set_text(vformat(TTR("Delete node \"%s\" and its children?"), remove_list[0]->get_name())); + String msg; + if (remove_list.size() > 1) { + bool any_children = false; + for (int i = 0; !any_children && i < remove_list.size(); i++) { + any_children = remove_list[i]->get_child_count() > 0; + } + + msg = vformat(any_children ? TTR("Delete %d nodes and any children?") : TTR("Delete %d nodes?"), remove_list.size()); } else { - delete_dialog->set_text(vformat(TTR("Delete node \"%s\"?"), remove_list[0]->get_name())); + Node *node = remove_list[0]; + if (node == editor_data->get_edited_scene_root()) { + msg = vformat(TTR("Delete the root node \"%s\"?"), node->get_name()); + } else if (node->get_filename() == "" && node->get_child_count() > 0) { + // Display this message only for non-instanced scenes + msg = vformat(TTR("Delete node \"%s\" and its children?"), node->get_name()); + } else { + msg = vformat(TTR("Delete node \"%s\"?"), node->get_name()); + } } + delete_dialog->set_text(msg); + // Resize the dialog to its minimum size. // This prevents the dialog from being too wide after displaying // a deletion confirmation for a node with a long name. @@ -2383,7 +2403,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { } menu->set_size(Size2(1, 1)); - menu->set_position(p_menu_pos); + menu->set_position(get_screen_position() + p_menu_pos); menu->popup(); return; } diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 1b818036e1..f30e57579f 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -902,6 +902,10 @@ Variant SceneTreeEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from return Variant(); //not editable tree } + if (tree->get_button_id_at_position(p_point) != -1) { + return Variant(); //dragging from button + } + Vector<Node *> selected; Vector<Ref<Texture2D>> icons; TreeItem *next = tree->get_next_selected(nullptr); @@ -1072,7 +1076,7 @@ void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, } void SceneTreeEditor::_rmb_select(const Vector2 &p_pos) { - emit_signal("rmb_pressed", tree->get_global_transform().xform(p_pos)); + emit_signal("rmb_pressed", tree->get_screen_transform().xform(p_pos)); } void SceneTreeEditor::_warning_changed(Node *p_for_node) { diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index ae5229b628..40e0582046 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -78,7 +78,7 @@ void ScriptCreateDialog::_notification(int p_what) { void ScriptCreateDialog::_path_hbox_sorted() { if (is_visible()) { - int filename_start_pos = initial_bp.find_last("/") + 1; + int filename_start_pos = initial_bp.rfind("/") + 1; int filename_end_pos = initial_bp.length(); if (!is_built_in) { @@ -553,7 +553,7 @@ void ScriptCreateDialog::_file_selected(const String &p_file) { _path_changed(p); String filename = p.get_file().get_basename(); - int select_start = p.find_last(filename); + int select_start = p.rfind(filename); file_path->select(select_start, select_start + filename.length()); file_path->set_cursor_position(select_start + filename.length()); file_path->grab_focus(); diff --git a/editor/translations/af.po b/editor/translations/af.po index 1f598ef5e5..daa0737106 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -784,6 +784,11 @@ msgstr "Metode in teiken Nodus moet gespesifiseer word!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metode in teiken Nodus moet gespesifiseer word!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ar.po b/editor/translations/ar.po index a60de1a41e..5a0b6d1e17 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -45,8 +45,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-09 02:02+0000\n" -"Last-Translator: HeroFight dev <abdkafi2002@gmail.com>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: Airbus5717 <Abdussamadf350@gmail.com>\n" "Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/" "godot/ar/>\n" "Language: ar\n" @@ -55,7 +55,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -785,6 +785,10 @@ msgid "Method in target node must be specified." msgstr "يجب تحديد الدالة في العقدة المستهدفة." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "اسم الدالة يجب أن تكون مميزاً و صالحاً." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1477,7 +1481,7 @@ msgstr "اعادة ترتيب التحميلات التلقائية" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "لا يمكن اضافة التحميل التلقائي" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -2426,15 +2430,16 @@ msgid "Can't reload a scene that was never saved." msgstr "لا يمكن إعادة تحميل مشهد لم يتم حفظه من قبل." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "حفظ المشهد" +msgstr "إعادة تحميل المشهد المحفوظ" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"يحتوي المشهد الحالي على تغييرات غير محفوظة.\n" +"إعادة تحميل المشهد المحفوظ على أي حال؟ لا يمكن التراجع عن هذا الإجراء." #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -3361,11 +3366,9 @@ msgid "Did you forget the '_run' method?" msgstr "هل نسيت الطريقة '_run' ؟" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." msgstr "" -"اضغط مطولاً على Ctrl لإسقاط جالب Getter. اضغط مطولاً على Shift لإسقاط توقيع " -"عام generic signature." +"امسك Ctrl للتدوير للأعداد الصحيحة. اضغط على Shift لإجراء تغييرات أكثر دقة." #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -3962,7 +3965,7 @@ msgstr "خطأ في تشغيل الكود الملصق- المستورد:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "هل قمت بإرجاع كائن مشتق من العقدة في دالة`post_import ()`؟" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -4181,14 +4184,12 @@ msgid "Move Node Point" msgstr "تحريك نقطة العقدة" #: editor/plugins/animation_blend_space_1d_editor.cpp -#, fuzzy msgid "Change BlendSpace1D Limits" -msgstr "تغيير وقت الدمج" +msgstr "تغيير حدود BlendSpace1D" #: editor/plugins/animation_blend_space_1d_editor.cpp -#, fuzzy msgid "Change BlendSpace1D Labels" -msgstr "تغيير وقت الدمج" +msgstr "تغيير ملصقات BlendSpace1D" #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp @@ -4204,9 +4205,8 @@ msgstr "إضافة نقطة العقدة" #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp -#, fuzzy msgid "Add Animation Point" -msgstr "أضف حركة" +msgstr "أضف نقطة حركة" #: editor/plugins/animation_blend_space_1d_editor.cpp msgid "Remove BlendSpace1D Point" @@ -4240,7 +4240,6 @@ msgstr "حدد وحرك النقاط، أنشئ النقاط باستخدام RM #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp scene/gui/graph_edit.cpp -#, fuzzy msgid "Enable snap and show grid." msgstr "تمكين المحاذاة وإظهار الشبكة." @@ -4452,14 +4451,12 @@ msgid "Remove Animation" msgstr "مسح الحركة" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Invalid animation name!" -msgstr "خطأ: إسم حركة خاطئ!" +msgstr "خطأ: إسم الرسوم المتحركة خاطئ!" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Animation name already exists!" -msgstr "خطأ: إسم الحركة موجود بالفعل!" +msgstr "اسم الحركة موجود بالفعل!" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -4675,19 +4672,16 @@ msgid "Start and end nodes are needed for a sub-transition." msgstr "عُقد البداية والنهاية مطلوبة لأجل الانتقال الجزيئ sub-transition." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "No playback resource set at path: %s." -msgstr "ليس في مسار الموارد." +msgstr "لم يتم تعيين موارد التشغيل في المسار:٪ s." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Node Removed" -msgstr "مُسِح:" +msgstr "مُسِحت العقدة" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition Removed" -msgstr "عقدة التنقل" +msgstr "تمت إزالة النقل" #: editor/plugins/animation_state_machine_editor.cpp msgid "Set Start Node (Autoplay)" @@ -4704,19 +4698,16 @@ msgstr "" "LMB + Shift (زر الفأرة الأيسر) لإنشاء الوصلات." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Create new nodes." -msgstr "إنشاء %s جديد" +msgstr "إنشاء عُقد جديدة." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Connect nodes." -msgstr "صلها بالعقدة:" +msgstr "توصيل عقد." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Remove selected node or transition." -msgstr "ازالة المسار المحدد." +msgstr "ازالة الكائن المحدد او الإنتقال المحدد." #: editor/plugins/animation_state_machine_editor.cpp msgid "Toggle autoplay this animation on start, restart or seek to zero." @@ -4730,9 +4721,8 @@ msgstr "" "تحديد الرسومية المتحركة الخاصة بالنهاية. سيكون ذلك مفيداً للحركات الفرعية." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition: " -msgstr "تحول" +msgstr "التحريك " #: editor/plugins/animation_state_machine_editor.cpp #, fuzzy diff --git a/editor/translations/bg.po b/editor/translations/bg.po index f08f2b1362..c9f38d518a 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -746,6 +746,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/bn.po b/editor/translations/bn.po index 3680e4ce6c..c438934246 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -809,6 +809,11 @@ msgstr "নির্দেশিত নোডের মেথড নির্দ #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "নামটি কার্যকর সনাক্তকারী নয়:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ca.po b/editor/translations/ca.po index 1640367701..5fb91db7b4 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -765,6 +765,11 @@ msgid "Method in target node must be specified." msgstr "S'ha d'especificar el mètode al node de destinació." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "El nom no és un identificador vàlid:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/cs.po b/editor/translations/cs.po index fabec77283..722fa52d92 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -24,7 +24,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-06 10:15+0000\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" "Last-Translator: Zbyněk <zbynek.fiala@gmail.com>\n" "Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/" "cs/>\n" @@ -33,7 +33,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -773,6 +773,11 @@ msgid "Method in target node must be specified." msgstr "Je nutné zadat metodu v cílovém uzlu." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Jméno není platný identifikátor:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -10055,7 +10060,7 @@ msgstr "Přidat akci" #: editor/project_settings_editor.cpp msgid "Button" -msgstr "Tlačítko" +msgstr "Button" #: editor/project_settings_editor.cpp msgid "Left Button." @@ -11013,9 +11018,8 @@ msgid "Copy Error" msgstr "Kopírovat chybu" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Video RAM" -msgstr "Video pamět" +msgstr "Video RAM" #: editor/script_editor_debugger.cpp #, fuzzy diff --git a/editor/translations/da.po b/editor/translations/da.po index 8eeaaafaea..70b05c08ff 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -16,12 +16,13 @@ # Kristoffer Andersen <kjaa@google.com>, 2019. # Joe Osborne <reachjoe.o@gmail.com>, 2020. # Autowinto <happymansi@hotmail.com>, 2020. +# Mikkel Mouridsen <mikkelmouridsen@me.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-02-02 08:51+0000\n" -"Last-Translator: Autowinto <happymansi@hotmail.com>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: Mikkel Mouridsen <mikkelmouridsen@me.com>\n" "Language-Team: Danish <https://hosted.weblate.org/projects/godot-engine/" "godot/da/>\n" "Language: da\n" @@ -29,7 +30,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.11-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -443,7 +444,7 @@ msgstr "Det er ikke muligt at tilføje et nyt spor uden en rod" #: editor/animation_track_editor.cpp msgid "Invalid track for Bezier (no suitable sub-properties)" -msgstr "" +msgstr "Ugyldigt spor for Bezier (ingen passende underegenskaber)" #: editor/animation_track_editor.cpp #, fuzzy @@ -785,7 +786,7 @@ msgstr "Advarsler" #: editor/code_editor.cpp msgid "Line and column numbers." -msgstr "" +msgstr "Linje- og kolonnenumre." #: editor/connections_dialog.cpp #, fuzzy @@ -794,6 +795,11 @@ msgstr "Metode i target Node skal angives!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Navnet er ikke et gyldigt id:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1252,7 +1258,7 @@ msgstr "Udpakker Aktiver" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "The following files failed extraction from package:" -msgstr "" +msgstr "De følgende filer kunne ikke trækkes ud af pakken:" #: editor/editor_asset_installer.cpp #, fuzzy diff --git a/editor/translations/de.po b/editor/translations/de.po index b52206e56e..eb533ff15e 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -56,7 +56,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" "Last-Translator: So Wieso <sowieso@dukun.de>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" @@ -65,7 +65,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -806,6 +806,10 @@ msgid "Method in target node must be specified." msgstr "Methode des Ziel-Nodes muss angegeben werden." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "Methodenname muss ein gültiger Bezeichner sein." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index 4dca7e4c5f..01121a8156 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -730,6 +730,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/el.po b/editor/translations/el.po index 127da8ec1f..8ff5881a9e 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -7,13 +7,13 @@ # Overloaded <manoschool@yahoo.gr>, 2019. # Eternal Death <eternaldeath0001@gmail.com>, 2019. # Overloaded @ Orama Interactive http://orama-interactive.com/ <manoschool@yahoo.gr>, 2020. +# pandektis <pandektis@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-05-10 12:37+0000\n" -"Last-Translator: Overloaded @ Orama Interactive http://orama-interactive." -"com/ <manoschool@yahoo.gr>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: pandektis <pandektis@gmail.com>\n" "Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/" "el/>\n" "Language: el\n" @@ -21,7 +21,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -744,11 +744,11 @@ msgstr "Μεγέθυνση" #: editor/plugins/texture_region_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp msgid "Zoom Out" -msgstr "Σμύκρινση" +msgstr "Σμίκρυνση" #: editor/code_editor.cpp msgid "Reset Zoom" -msgstr "Επαναφορά μεγέθυνσης" +msgstr "Επαναφορά μεγένθυνσης" #: editor/code_editor.cpp msgid "Warnings" @@ -763,6 +763,10 @@ msgid "Method in target node must be specified." msgstr "Πρέπει να οριστεί συνάρτηση στον στοχευμένο κόμβο." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "Το όνομα δεν είναι έγκυρο αναγνωριστικό." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1461,7 +1465,7 @@ msgstr "Αναδιάταξη των AutoLoad" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "Αδυναμία προσθήκης autoload:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -2423,15 +2427,17 @@ msgstr "" "Δεν είναι δυνατό να φορτώσετε εκ νέου μια σκηνή που δεν αποθηκεύτηκε ποτέ." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "Αποθηκεύσετε σκηνής" +msgstr "Ανανέωση Αποθηκευμένης Σκηνής" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"Η τρέχουσα σκηνή έχει μη αποθηκευμένες αλλαγές.\n" +"Επαναφόρτωση της αποθηκευμένης σκηνής; Αυτή η ενέργεια δεν μπορεί να " +"αναιρεθεί." #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -3378,11 +3384,10 @@ msgid "Did you forget the '_run' method?" msgstr "Μήπως ξεχάσατε τη μέθοδο '_run';" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." msgstr "" -"Πατήστε παρατεταμένα το Ctrl για να προσθέσετε έναν Getter. Πατήστε " -"παρατεταμένα το Shift για να προσθέσετε μία γενική υπογραφή." +"Πατήστε παρατεταμένα το Ctrl για στρογγυλοποίηση ακεραίων και το Shift για " +"πιο ακριβείς αλλαγές." #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" diff --git a/editor/translations/eo.po b/editor/translations/eo.po index 3addde45ce..f98f043118 100644 --- a/editor/translations/eo.po +++ b/editor/translations/eo.po @@ -764,6 +764,11 @@ msgstr "Metodo en celo nodo devas esti specifita." #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metodo en celo nodo devas esti specifita." + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/es.po b/editor/translations/es.po index f8c4134d07..a200653685 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -53,8 +53,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" -"Last-Translator: paco <pacosoftfree@protonmail.com>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/" "godot/es/>\n" "Language: es\n" @@ -62,7 +62,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -79,7 +79,8 @@ msgstr "Se esperaba un string de longitud 1 (un carácter)." #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." msgstr "" -"No hay suficientes bytes para decodificar bytes, o el formato es invalido." +"No hay suficientes bytes para decodificar los bytes, o el formato es " +"inválido." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -96,11 +97,11 @@ msgstr "Operandos inválidos para el operador %s, %s y %s." #: core/math/expression.cpp msgid "Invalid index of type %s for base type %s" -msgstr "Indice inválido de tipo %s para tipo base %s" +msgstr "Índice inválido de tipo %s para el tipo base %s" #: core/math/expression.cpp msgid "Invalid named index '%s' for base type %s" -msgstr "El índice de nombre «%s» no es válido para el tipo de base %s" +msgstr "El índice de nombre '%s' no es válido para el tipo de base %s" #: core/math/expression.cpp msgid "Invalid arguments to construct '%s'" @@ -806,6 +807,10 @@ msgid "Method in target node must be specified." msgstr "Se debe establecer un método en el nodo destino." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "El nombre del método debe ser un identificador válido." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -2014,7 +2019,7 @@ msgstr "Propiedades del Tema" #: editor/editor_help.cpp msgid "Enumerations" -msgstr "Enumeraciones" +msgstr "Enumerados" #: editor/editor_help.cpp msgid "Constants" @@ -3039,7 +3044,7 @@ msgstr "Reproducir Escena Personalizada" #: editor/editor_node.cpp msgid "Changing the video driver requires restarting the editor." -msgstr "Cambiar el driver de video requiere reiniciar el editor." +msgstr "Cambiar el driver de vídeo requiere reiniciar el editor." #: editor/editor_node.cpp editor/project_settings_editor.cpp #: editor/settings_config_dialog.cpp @@ -3378,7 +3383,7 @@ msgstr "Página: " #: editor/editor_properties_array_dict.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Remove Item" -msgstr "Eliminar Item" +msgstr "Eliminar Ítem" #: editor/editor_properties_array_dict.cpp msgid "New Key:" @@ -5906,15 +5911,15 @@ msgstr "Degradado Editado" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item %d" -msgstr "Elemento %d" +msgstr "Ítem %d" #: editor/plugins/item_list_editor_plugin.cpp msgid "Items" -msgstr "Elementos" +msgstr "Ítems" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item List Editor" -msgstr "Editor de Lista de Items" +msgstr "Editor de Lista de Ítems" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Create Occluder Polygon" @@ -6104,7 +6109,7 @@ msgstr "Depuración del Canal UV" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Remove item %d?" -msgstr "¿Quieres borrar el elemento %d?" +msgstr "¿Eliminar el ítem %d?" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "" @@ -6121,11 +6126,11 @@ msgstr "Librería de Mallas" #: editor/plugins/mesh_library_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Add Item" -msgstr "Añadir Item" +msgstr "Añadir Ítem" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Remove Selected Item" -msgstr "Borrar elemento seleccionado" +msgstr "Eliminar Ítem Seleccionado" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Import from Scene" @@ -7935,7 +7940,7 @@ msgstr "Región de Textura" #: editor/plugins/theme_editor_plugin.cpp msgid "Add All Items" -msgstr "Añadir Todos los Elementos" +msgstr "Añadir Todos los Ítems" #: editor/plugins/theme_editor_plugin.cpp msgid "Add All" @@ -7959,11 +7964,11 @@ msgstr "Menú de edición de tema." #: editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" -msgstr "Añadir elementos de clase" +msgstr "Añadir Clases de Ítems" #: editor/plugins/theme_editor_plugin.cpp msgid "Remove Class Items" -msgstr "Eliminar Ítems de Clases" +msgstr "Eliminar Clases de Ítems" #: editor/plugins/theme_editor_plugin.cpp msgid "Create Empty Template" @@ -9558,11 +9563,11 @@ msgstr "Exportar todos los recursos del proyecto" #: editor/project_export.cpp msgid "Export selected scenes (and dependencies)" -msgstr "Exportar las escenas seleccionadas (incluyendo dependencias)" +msgstr "Exportar escenas seleccionadas (y dependencias)" #: editor/project_export.cpp msgid "Export selected resources (and dependencies)" -msgstr "Exportar los recursos seleccionado (incluyendo dependencias)" +msgstr "Exportar los recursos seleccionados (y dependencias)" #: editor/project_export.cpp msgid "Export Mode:" @@ -11106,7 +11111,7 @@ msgstr "Copiar Error" #: editor/script_editor_debugger.cpp msgid "Video RAM" -msgstr "Vídeo RAM" +msgstr "Memoria de Vídeo" #: editor/script_editor_debugger.cpp msgid "Skip Breakpoints" @@ -11146,11 +11151,11 @@ msgstr "Monitores" #: editor/script_editor_debugger.cpp msgid "Pick one or more items from the list to display the graph." -msgstr "Elige uno o más elementos de la lista para mostrar el gráfico." +msgstr "Elige uno o más ítems de la lista para mostrar el gráfico." #: editor/script_editor_debugger.cpp msgid "List of Video Memory Usage by Resource:" -msgstr "Lista de uso de memoria de video por recurso:" +msgstr "Listado de la Memoria de Vídeo Utilizada por Recurso:" #: editor/script_editor_debugger.cpp msgid "Total:" @@ -12606,7 +12611,7 @@ msgid "" "GIProbes are not supported by the GLES2 video driver.\n" "Use a BakedLightmap instead." msgstr "" -"Las GIProbes no están soportadas por el controlador de video GLES2.\n" +"Las GIProbes no están soportadas por el controlador de vídeo GLES2.\n" "Usa un BakedLightmap en su lugar." #: scene/3d/light.cpp diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index 46cb219e14..ca9f5a7a49 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -19,7 +19,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" "Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n" "Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/" "godot-engine/godot/es_AR/>\n" @@ -28,7 +28,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -770,6 +770,10 @@ msgid "Method in target node must be specified." msgstr "El método en el nodo objetivo debe ser especificado." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "El nombre del método debe ser un identificador válido." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/et.po b/editor/translations/et.po index 7be6996d69..5fd61347e1 100644 --- a/editor/translations/et.po +++ b/editor/translations/et.po @@ -744,6 +744,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/eu.po b/editor/translations/eu.po index b47056d82b..e461c0f1ec 100644 --- a/editor/translations/eu.po +++ b/editor/translations/eu.po @@ -735,6 +735,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/fa.po b/editor/translations/fa.po index 3f94d1112b..428b69062a 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -784,6 +784,11 @@ msgstr "متد در گره مقصد باید مشخص شده باشد!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "نام یک شناسهی معتبر نیست:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/fi.po b/editor/translations/fi.po index a95c65be41..8ea9a940f0 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -15,7 +15,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" "Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n" "Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/" "godot/fi/>\n" @@ -24,7 +24,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -757,6 +757,10 @@ msgid "Method in target node must be specified." msgstr "Kohdesolmun metodi täytyy määrittää." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "Metodin nimen täytyy olla kelvollinen tunniste." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/fil.po b/editor/translations/fil.po index 920b91a30c..ceda61c802 100644 --- a/editor/translations/fil.po +++ b/editor/translations/fil.po @@ -743,6 +743,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/fr.po b/editor/translations/fr.po index fac3b9b84b..9dd9b3e166 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -79,7 +79,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" "Last-Translator: Nathan <bonnemainsnathan@gmail.com>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" @@ -88,7 +88,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -834,6 +834,10 @@ msgid "Method in target node must be specified." msgstr "La méthode du nœud cible doit être spécifiée." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "Le nom de la méthode doit être un identifiant valide." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -7066,7 +7070,7 @@ msgstr "" #: editor/plugins/script_text_editor.cpp msgid "Lookup Symbol" -msgstr "Symbole de recherche" +msgstr "Rechercher un symbole" #: editor/plugins/script_text_editor.cpp msgid "Pick Color" @@ -8594,7 +8598,7 @@ msgstr "Détecter de nouveaux changements" #: editor/plugins/version_control_editor_plugin.cpp msgid "Changes" -msgstr "Changements" +msgstr "Modifications" #: editor/plugins/version_control_editor_plugin.cpp msgid "Modified" @@ -9608,15 +9612,15 @@ msgstr "Ressources" #: editor/project_export.cpp msgid "Export all resources in the project" -msgstr "Exporter toutes les ressources dans le projet" +msgstr "Exporter toutes les ressources du projet" #: editor/project_export.cpp msgid "Export selected scenes (and dependencies)" -msgstr "Exporter les scènes sélectionnées (y compris les dépendences)" +msgstr "Exporter les scènes sélectionnées (y compris les dépendances)" #: editor/project_export.cpp msgid "Export selected resources (and dependencies)" -msgstr "Exporter les ressources sélectionnées (y compris les dépendences)" +msgstr "Exporter les ressources sélectionnées (y compris les dépendances)" #: editor/project_export.cpp msgid "Export Mode:" diff --git a/editor/translations/ga.po b/editor/translations/ga.po index b9e6ba69c6..70dd5eada7 100644 --- a/editor/translations/ga.po +++ b/editor/translations/ga.po @@ -736,6 +736,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/he.po b/editor/translations/he.po index 56126249dc..7895ae48fe 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -777,6 +777,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/hi.po b/editor/translations/hi.po index 4782afecb0..e3ae2aabe5 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -756,6 +756,11 @@ msgid "Method in target node must be specified." msgstr "Method को target node में निर्दिष्ट कीजिए." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Method को target node में निर्दिष्ट कीजिए." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/hr.po b/editor/translations/hr.po index ad095145b2..5355ee1dc9 100644 --- a/editor/translations/hr.po +++ b/editor/translations/hr.po @@ -741,6 +741,11 @@ msgid "Method in target node must be specified." msgstr "Metoda u ciljnom čvoru mora biti određena." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metoda u ciljnom čvoru mora biti određena." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/hu.po b/editor/translations/hu.po index ef15f85977..b57028a426 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -790,6 +790,11 @@ msgstr "Nevezze meg a metódust a cél Node-ban!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Nevezze meg a metódust a cél Node-ban!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/id.po b/editor/translations/id.po index f7a86197b6..92c0c25da9 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -778,6 +778,11 @@ msgid "Method in target node must be specified." msgstr "Method dalam node target harus ditentukan." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Nama bukan sebuah pengidentifikasi yang sah:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/is.po b/editor/translations/is.po index 5a1ac9b73c..f0d93d1242 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -770,6 +770,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/it.po b/editor/translations/it.po index eeec1e05eb..7c929b7779 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -50,12 +50,14 @@ # J. Lavoie <j.lavoie@net-c.ca>, 2020. # Andrea Terenziani <andrea.terenziani.at@gmail.com>, 2020. # Anonymous <noreply@weblate.org>, 2020. +# riccardo boffelli <riccardo.boffelli.96@gmail.com>, 2020. +# Lorenzo Asolan <brixiumx@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-05-07 21:28+0000\n" -"Last-Translator: Sean Bone <seanbone@zumguy.com>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: Lorenzo Asolan <brixiumx@gmail.com>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot/it/>\n" "Language: it\n" @@ -63,7 +65,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -802,6 +804,11 @@ msgid "Method in target node must be specified." msgstr "Il metodo del nodo designato deve essere specificato." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Il nome del metodo dev'essere un identificatore valido." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1499,7 +1506,7 @@ msgstr "Riordina gli Autoload" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "Non è possibile aggiungere l'autoload:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -2463,15 +2470,16 @@ msgid "Can't reload a scene that was never saved." msgstr "Impossibile ricaricare una scena che non è mai stata salvata." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "Salva Scena" +msgstr "Ricarica scena salvata" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"La scena attuale ha dei cambiamenti non salvati.\n" +"Ricaricare comunque la scena salvata? Questa azione non può essere annullata." #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -3418,11 +3426,10 @@ msgid "Did you forget the '_run' method?" msgstr "Hai dimenticato il metodo '_run'?" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." msgstr "" -"Mantieni premuto Control per rilasciare un Getter. Mantieni premuto Shift " -"per rilasciare una firma generica." +"Tenere premuto il tasto Ctrl per arrotondare ai numeri interi. Tenere " +"premuto Shift per modifiche più precise." #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -4022,8 +4029,10 @@ msgid "Error running post-import script:" msgstr "Errore di esecuzione dello script di post-import:" #: editor/import/resource_importer_scene.cpp +#, fuzzy msgid "Did you return a Node-derived object in the `post_import()` method?" msgstr "" +"Avete restituito un oggetto derivato da un Nodo nel metodo `post_import()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -6992,9 +7001,8 @@ msgstr "" "Manca il metodo '%s' connesso per il segnale '%s' dal nodo '%s' al nodo '%s'." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(ignora)" +msgstr "[ignora]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -7480,6 +7488,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Fare clic per passare da uno stato di visibilità all'altro.\n" +"\n" +"Apri gli occhi: Gizmo è visibile.\n" +"Occhio chiuso: Gizmo è nascosto.\n" +"Occhio semiaperto: Gizmo è visibile anche attraverso superfici opache " +"(\"raggi X\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -10579,9 +10593,8 @@ msgid "Instance Child Scene" msgstr "Istanzia Scena Figlia" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "Allega Script" +msgstr "Rimuovi Script" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10747,11 +10760,15 @@ msgid "Open Documentation" msgstr "Apri la documentazione" #: editor/scene_tree_dock.cpp +#, fuzzy msgid "" "Cannot attach a script: there are no languages registered.\n" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Non è possibile allegare uno script: non ci sono linguaggi registrati.\n" +"Questo probabilmente perché questo editor è stato costruito con tutti i " +"moduli di lingua disabilitati." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10802,14 +10819,12 @@ msgstr "" "root esiste." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." -msgstr "Allega un nuovo script o uno esistente al nodo selezionato." +msgstr "Allega un nuovo script o uno già esistente al nodo selezionato." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "Svuota uno script per il nodo selezionato." +msgstr "Rimuovi lo script per il nodo selezionato." #: editor/scene_tree_dock.cpp msgid "Remote" @@ -12041,7 +12056,8 @@ msgstr "" #, fuzzy msgid "Release keystore incorrectly configured in the export preset." msgstr "" -"Debug keystore non configurato nelle Impostazioni dell'Editor né nel preset." +"Debug keystore non configurato correttamente nelle Impostazioni dell'Editor " +"né nel preset." #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." @@ -12072,30 +12088,40 @@ msgid "Invalid package name:" msgstr "Nome del pacchetto non valido:" #: platform/android/export/export.cpp +#, fuzzy msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Modulo \"GodotPaymentV3\" non valido incluso nell'impostazione del progetto " +"\"android/moduli\" (modificato in Godot 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "Per utilizzare i plugin \"Use Custom Build\" deve essere abilitato." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"\"Degrees Of Freedom\" è valido solo quando \"Xr Mode\" è \"Oculus Mobile VR" +"\"." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Hand Tracking\" è valido solo quando \"Xr Mode\" è \"Oculus Mobile VR\"." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Focus Awareness\" è valida solo quando \"Xr Mode\" è \"Oculus Mobile VR\"." #: platform/android/export/export.cpp msgid "" diff --git a/editor/translations/ja.po b/editor/translations/ja.po index 7d4aed4b29..35e590d629 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -36,8 +36,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-03 20:09+0000\n" -"Last-Translator: BinotaLIU <me@binota.org>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: Wataru Onuki <bettawat@yahoo.co.jp>\n" "Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/" "godot/ja/>\n" "Language: ja\n" @@ -45,7 +45,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -786,6 +786,10 @@ msgid "Method in target node must be specified." msgstr "対象ノードのメソッドを指定してください。" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "メソッド名は有効な識別子である必要があります。" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1595,8 +1599,9 @@ msgid "" "Enabled'." msgstr "" "対象プラットフォームではGLES2へフォールバックするために'ETC'テクスチャ圧縮が" -"必要です。プロジェクト設定より 'Import Etc' をオンにするか、'Fallback To " -"Gles 2' をオフにしてください。" +"必要です。\n" +"プロジェクト設定より 'Import Etc' をオンにするか、'Fallback To Gles 2' をオフ" +"にしてください。" #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp @@ -2436,9 +2441,8 @@ msgid "Can't reload a scene that was never saved." msgstr "保存されていないシーンを読み込むことはできません。" #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "シーンを保存" +msgstr "保存済みのシーンをリロード" #: editor/editor_node.cpp msgid "" @@ -3378,11 +3382,8 @@ msgid "Did you forget the '_run' method?" msgstr "'_run' メソッドを忘れていませんか?" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." -msgstr "" -"Ctrlを押したままGetterを(ドラッグ&)ドロップする。Shiftを押したまま汎用シグネ" -"チャを(ドラッグ&)ドロップする." +msgstr "Ctrlを押したままで整数値に丸める。Shiftを押したままで精密調整。" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -3518,8 +3519,8 @@ msgid "" "Templates installation failed.\n" "The problematic templates archives can be found at '%s'." msgstr "" -"テンプレートのインストールに失敗しました。 問題のテンプレートのアーカイブは " -"'%s' にあります。" +"テンプレートのインストールに失敗しました。\n" +"問題のテンプレートのアーカイブは '%s' にあります。" #: editor/export_template_manager.cpp msgid "Error requesting URL:" @@ -6924,9 +6925,8 @@ msgstr "" "ド'%s'へのシグナル用です。" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(無視)" +msgstr "[無視]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -9451,8 +9451,9 @@ msgid "" "Only one preset per platform may be marked as runnable." msgstr "" "チェックを入れると、1クリック・デプロイでもこのプリセットが使われるようにな" -"ります。ひとつのプラットフォームに対し、ひとつのプリセットのみが実行可能とし" -"てマークできます。" +"ります。\n" +"ひとつのプラットフォームに対し、ひとつのプリセットのみが実行可能としてマーク" +"できます。" #: editor/project_export.cpp msgid "Export Path" @@ -10493,9 +10494,8 @@ msgid "Instance Child Scene" msgstr "子シーンをインスタンス化" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "スクリプトをアタッチ" +msgstr "スクリプトをデタッチ" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10714,14 +10714,12 @@ msgstr "" "合は、継承されたシーンを作成します。" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." msgstr "選択したノードに新規または既存のスクリプトをアタッチする。" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "選択したノードのスクリプトをクリアする。" +msgstr "選択したノードのスクリプトをデタッチする。" #: editor/scene_tree_dock.cpp msgid "Remote" @@ -10768,7 +10766,7 @@ msgid "" "Node has %s connection(s).\n" "Click to show signals dock." msgstr "" -"ノードに %s 個接続があります。\n" +"ノードに %s 個接続があります。\n" "クリックでシグナル ドックを表示。" #: editor/scene_tree_editor.cpp @@ -11947,9 +11945,8 @@ msgid "Debug keystore not configured in the Editor Settings nor in the preset." msgstr "デバッグキーストアがエディタ設定にもプリセットにも設定されていません。" #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." -msgstr "デバッグキーストアがエディタ設定にもプリセットにも設定されていません。" +msgstr "エクスポート設定にてリリース キーストアが誤って設定されています。" #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." diff --git a/editor/translations/ka.po b/editor/translations/ka.po index 2435a50898..af03b1af9e 100644 --- a/editor/translations/ka.po +++ b/editor/translations/ka.po @@ -790,6 +790,11 @@ msgstr "სამიზნე კვანძში მეთოდი უნდ #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "სამიზნე კვანძში მეთოდი უნდა იყოს განსაზღვრული!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ko.po b/editor/translations/ko.po index c568dc19b8..462c59d319 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -22,8 +22,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-05-22 21:01+0000\n" -"Last-Translator: Doyun Kwon <caen4516@gmail.com>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: Ch. <ccwpc@hanmail.net>\n" "Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/" "godot/ko/>\n" "Language: ko\n" @@ -31,7 +31,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -768,6 +768,10 @@ msgid "Method in target node must be specified." msgstr "대상 노드에 있는 메서드는 반드시 지정해야 합니다." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "메서드 이름은 올바른 식별자여야 합니다." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -977,7 +981,7 @@ msgid "" "Changes will only take effect when reloaded." msgstr "" "씬 '%s'이(가) 현재 편집중입니다.\n" -"변경 사항은 다시 로드된 뒤에 반영됩니다." +"변경 사항은 다시 불러온 뒤에 반영됩니다." #: editor/dependency_editor.cpp msgid "" @@ -985,7 +989,7 @@ msgid "" "Changes will only take effect when reloaded." msgstr "" "리소스 '%s'이(가) 현재 사용중입니다.\n" -"변경 사항은 다시 로드된 뒤에 반영됩니다." +"변경 사항은 다시 불러온 뒤에 반영됩니다." #: editor/dependency_editor.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp @@ -1461,7 +1465,7 @@ msgstr "오토로드 다시 정렬" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "오토로드를 추가할 수 없음:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -2413,15 +2417,16 @@ msgid "Can't reload a scene that was never saved." msgstr "저장하지 않은 씬은 새로고침할 수 없습니다." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "씬 저장" +msgstr "저장된 씬 새로고침" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"현재 씬에는 저장하지 않은 변경사항이 있습니다.\n" +"그래도 저장된 씬을 새로고침하시겠습니까? 이 동작은 되돌릴 수 없습니다." #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -2841,8 +2846,8 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"이 설정이 활성화된 경우, 어떤 스크립트든 저장하면 실행중인 게임에도 반영됩니" -"다.\n" +"이 설정이 활성화된 경우, 어떤 스크립트든 저장하면 실행중인 게임에도 새로고침" +"되어 반영됩니다.\n" "원격 장치에서 사용중인 경우 네트워크 파일 시스템 기능을 활성화하면 더욱 효율" "적입니다." @@ -3347,11 +3352,9 @@ msgid "Did you forget the '_run' method?" msgstr "'_run' 메서드를 잊었나요?" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." msgstr "" -"Ctrl을 누르고 있으면 Getter를 드롭합니다. Shift를 누르고 있으면 일반적인 시그" -"니처를 드롭합니다." +"Ctrl을 눌러 정수로 반올림합니다. Shift를 눌러 좀 더 정밀하게 조작합니다." #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -3948,7 +3951,7 @@ msgstr "후 가져오기 스크립트 실행 중 오류:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "`post_import()` 메소드에서 Node에서 상속받은 객체를 반환했습니까?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -6646,7 +6649,7 @@ msgstr "실행하기 위한 스크립트를 가질 수 없습니다." #: editor/plugins/script_editor_plugin.cpp msgid "Script failed reloading, check console for errors." -msgstr "스크립트 다시 불러오기에 실패했습니다. 콘솔에서 오류를 확인하세요." +msgstr "스크립트 새로고침에 실패했습니다. 콘솔에서 오류를 확인하세요." #: editor/plugins/script_editor_plugin.cpp msgid "Script is not in tool mode, will not be able to run." @@ -6743,7 +6746,7 @@ msgstr "모두 저장" #: editor/plugins/script_editor_plugin.cpp msgid "Soft Reload Script" -msgstr "스크립트 다시 불러오기" +msgstr "스크립트 새로고침" #: editor/plugins/script_editor_plugin.cpp msgid "Copy Script Path" @@ -6768,7 +6771,7 @@ msgstr "테마 가져오기..." #: editor/plugins/script_editor_plugin.cpp msgid "Reload Theme" -msgstr "테마 다시 불러오기" +msgstr "테마 새로고침" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme" @@ -6842,7 +6845,7 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/shader_editor_plugin.cpp msgid "Reload" -msgstr "다시 불러오기" +msgstr "새로고침" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/shader_editor_plugin.cpp @@ -6881,9 +6884,8 @@ msgstr "" "다." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(무시함)" +msgstr "[무시]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -7361,6 +7363,7 @@ msgid "XForm Dialog" msgstr "XForm 대화 상자" #: editor/plugins/spatial_editor_plugin.cpp +#, fuzzy msgid "" "Click to toggle between visibility states.\n" "\n" @@ -7368,6 +7371,11 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"표시 상태를 토글하려면 클릭하세요.\n" +"\n" +"열린 눈: 기즈모가 보입니다.\n" +"닫힌 눈: 기즈모가 숨겨집니다.\n" +"반 열린 눈: 불투명한 표면에도 기즈모가 보입니다 (\"엑스레이\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -10419,9 +10427,8 @@ msgid "Instance Child Scene" msgstr "자식 씬 인스턴스화" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "스크립트 붙이기" +msgstr "스크립트 떼기" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10589,6 +10596,8 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"스크립트를 붙일 수 없습니다: 언어가 하나도 등록되지 않았습니다.\n" +"에디터가 모든 언어를 비활성화한 채로 빌드되어서 그럴 가능성이 높습니다." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10638,14 +10647,12 @@ msgstr "" "씬 파일을 노드로 인스턴스합니다. 루트 노드가 없으면 상속된 씬을 만듭니다." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." -msgstr "선택한 노드에 새로운 혹은 존재하는 스크립트를 붙입니다." +msgstr "선택한 노드에 새 스크립트나 기존 스크립트를 붙입니다." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "선택한 노드의 스크립트를 삭제합니다." +msgstr "선택한 노드에서 스크립트를 뗍니다." #: editor/scene_tree_dock.cpp msgid "Remote" @@ -11866,9 +11873,8 @@ msgid "Debug keystore not configured in the Editor Settings nor in the preset." msgstr "Debug keystore를 편집기 설정과 프리셋에 설정하지 않았습니다." #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." -msgstr "Debug keystore를 편집기 설정과 프리셋에 설정하지 않았습니다." +msgstr "내보내기 프리셋에 배포 keystorke가 잘못 설정되어 있습니다." #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." @@ -11899,26 +11905,33 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"\"android/modules\" 프로젝트 세팅에 잘못된 \"GodotPaymentV3\" 모듈이 포함되" +"어 있습니다. (Godot 3.2.2 에서 변경됨).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "플러그인을 사용하려면 \"커스텀 빌드 사용\"이 활성화되어야 합니다." #: platform/android/export/export.cpp msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"\"자유도(DoF)\"는 \"Xr 모드\" 가 \"Oculus Mobile VR\" 일 때만 사용 가능합니" +"다." #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"손 추적\" 은 \"Xr 모드\" 가 \"Oculus Mobile VR\"일 때만 사용 가능합니다." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"포커스 인식\"은 \"Xr 모드\"가 \"Oculus Mobile VR\" 인 경우에만 사용 가능합" +"니다." #: platform/android/export/export.cpp msgid "" diff --git a/editor/translations/lt.po b/editor/translations/lt.po index bbbe630d4a..fdf9ef15ae 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -773,6 +773,11 @@ msgstr "Metodas pasirinktame Node turi būti nurodytas!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metodas pasirinktame Node turi būti nurodytas!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/lv.po b/editor/translations/lv.po index b69ecf7eef..8417a6b650 100644 --- a/editor/translations/lv.po +++ b/editor/translations/lv.po @@ -757,6 +757,11 @@ msgid "Method in target node must be specified." msgstr "Metodi mērķa mezglā nepieciešams specificēt." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metodi mērķa mezglā nepieciešams specificēt." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/mi.po b/editor/translations/mi.po index fbf4bce3d6..ab68a71ee2 100644 --- a/editor/translations/mi.po +++ b/editor/translations/mi.po @@ -728,6 +728,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ml.po b/editor/translations/ml.po index 77ac327f71..db5f5638f3 100644 --- a/editor/translations/ml.po +++ b/editor/translations/ml.po @@ -738,6 +738,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/mr.po b/editor/translations/mr.po index 38e3ee7185..1700bcb138 100644 --- a/editor/translations/mr.po +++ b/editor/translations/mr.po @@ -735,6 +735,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ms.po b/editor/translations/ms.po index 233b5cb428..160fa6e69f 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -758,6 +758,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/nb.po b/editor/translations/nb.po index 5c80321d03..4e7ca2dce1 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -19,7 +19,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-03 20:09+0000\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/godot-" "engine/godot/nb_NO/>\n" @@ -28,7 +28,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -796,6 +796,11 @@ msgstr "Metode i mål-Node må spesifiseres!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Navn er ikke en gyldig identifikator:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -3772,12 +3777,9 @@ msgid "Favorites" msgstr "Favoritter:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" -"\n" -"Status: Import av fil feilet. Vennligst reparer filen eller reimporter " -"manuelt." +"Status: Import av fil feilet. Reparer filen eller importer igjen manuelt." #: editor/filesystem_dock.cpp #, fuzzy diff --git a/editor/translations/nl.po b/editor/translations/nl.po index 8e6c4bcfa4..3d560d3d6d 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -44,7 +44,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" "Last-Translator: Stijn Hinlopen <f.a.hinlopen@gmail.com>\n" "Language-Team: Dutch <https://hosted.weblate.org/projects/godot-engine/godot/" "nl/>\n" @@ -53,7 +53,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -790,6 +790,11 @@ msgid "Method in target node must be specified." msgstr "Methode in doelknoop moet gespecificeerd worden." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Naam is geen geldige identifier:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1987,15 +1992,15 @@ msgstr "standaard:" #: editor/editor_help.cpp msgid "Methods" -msgstr "Methodes" +msgstr "Methoden" #: editor/editor_help.cpp msgid "Theme Properties" -msgstr "Thema Eigenschappen" +msgstr "Thema-eigenschappen" #: editor/editor_help.cpp msgid "Enumerations" -msgstr "Enumeraties" +msgstr "Enumeratie" #: editor/editor_help.cpp msgid "Constants" @@ -2003,7 +2008,7 @@ msgstr "Constanten" #: editor/editor_help.cpp msgid "Property Descriptions" -msgstr "Eigenschap Beschrijvingen" +msgstr "Eigenschapbeschrijvingen" #: editor/editor_help.cpp msgid "(value)" @@ -2019,7 +2024,7 @@ msgstr "" #: editor/editor_help.cpp msgid "Method Descriptions" -msgstr "Methode Beschrijvingen" +msgstr "Methodebeschrijvingen" #: editor/editor_help.cpp msgid "" diff --git a/editor/translations/or.po b/editor/translations/or.po index afff834dee..d6678c2819 100644 --- a/editor/translations/or.po +++ b/editor/translations/or.po @@ -734,6 +734,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/pl.po b/editor/translations/pl.po index 414e66685a..ed53a98bed 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -39,12 +39,13 @@ # Maciej Chamera <chameramaciej@gmail.com>, 2019. # Cezary Stasiak <cezary.p.stasiak@gmail.com>, 2019. # Jan Ligudziński <jan.ligudzinski@gmail.com>, 2020. +# Adam Jagoda <kontakt@lukasz.xyz>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-06 10:15+0000\n" -"Last-Translator: Tomek <kobewi4e@gmail.com>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: Adam Jagoda <kontakt@lukasz.xyz>\n" "Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/" "godot/pl/>\n" "Language: pl\n" @@ -53,7 +54,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -791,6 +792,10 @@ msgid "Method in target node must be specified." msgstr "Metoda w węźle docelowym musi zostać podana." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "Nazwa metody musi być poprawnym identyfikatorem." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1484,7 +1489,7 @@ msgstr "Przestaw Autoloady" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "Nie można dodać Autoload:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -1858,11 +1863,11 @@ msgstr "Przełącz ukryte pliki" #: editor/editor_file_dialog.cpp msgid "Toggle Favorite" -msgstr "Ustaw jako ulubione" +msgstr "Przełącz ulubione" #: editor/editor_file_dialog.cpp msgid "Toggle Mode" -msgstr "Przełącz tryby" +msgstr "Przełącz tryb" #: editor/editor_file_dialog.cpp msgid "Focus Path" @@ -1870,11 +1875,11 @@ msgstr "Przejdź do wprowadzania ścieżki" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" -msgstr "Przesuń Ulubiony w górę" +msgstr "Przesuń ulubiony w górę" #: editor/editor_file_dialog.cpp msgid "Move Favorite Down" -msgstr "Przesuń Ulubiony w dół" +msgstr "Przesuń ulubiony w dół" #: editor/editor_file_dialog.cpp msgid "Go to previous folder." @@ -2122,7 +2127,7 @@ msgstr "Wyczyść" #: editor/editor_log.cpp msgid "Clear Output" -msgstr "Wyczyść dane wyjściowe" +msgstr "Wyczyść wyjście" #: editor/editor_network_profiler.cpp editor/editor_node.cpp #: editor/editor_profiler.cpp @@ -2440,15 +2445,16 @@ msgid "Can't reload a scene that was never saved." msgstr "Nie można przeładować sceny która nie została zapisana." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "Zapisz scenę" +msgstr "Przywróć zapisaną scenę" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"Aktualna scena ma niezapisane zmiany.\n" +"Przywrócić zapisaną scenę tak czy inaczej? Ta akcja nie może zostać cofnięta." #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -2854,8 +2860,10 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"Wszelkie zmiany sceny w edytorze będą odtworzone w uruchomionej grze na " -"urządzeniu zdalnym. Opcja ta działa szybciej na sieciowych systemach plików." +"Kiedy ta opcja jest włączona, wszystkie zmiany na scenie w edytorze będą " +"powtórzone w uruchomionej grze.\n" +"Kiedy używane zdalnie na urządzeniu, ta opcja jest wydajniejsza w sieciowym " +"systemie plików." #: editor/editor_node.cpp msgid "Sync Script Changes" @@ -2868,9 +2876,10 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"Wszelkie zmiany skryptów będą synchronizowane z urządzeniem zdalnym " -"(działające instancje będą zrestartowane). Opcja ta działa szybciej z " -"użyciem sieciowych systemów plików." +"Kiedy ta opcja jest włączona, każdy zapisany skrypt będzie przeładowany w " +"uruchomionej grze.\n" +"Kiedy używane zdalnie na urządzeniu, ta opcja jest wydajniejsza w sieciowym " +"systemie plików." #: editor/editor_node.cpp editor/script_create_dialog.cpp msgid "Editor" @@ -2894,7 +2903,7 @@ msgstr "Zrzuty ekranu są przechowywane w folderze danych/ustawień edytora." #: editor/editor_node.cpp msgid "Toggle Fullscreen" -msgstr "Pełny ekran" +msgstr "Przełącz pełny ekran" #: editor/editor_node.cpp msgid "Toggle System Console" @@ -3378,11 +3387,10 @@ msgid "Did you forget the '_run' method?" msgstr "Zapomniano metody \"_run\"?" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." msgstr "" -"Przytrzymaj Ctrl, by upuścić pobieracz (Getter). Przytrzymaj Shift, by " -"upuścić generyczną sygnaturę." +"Przytrzyma Ctrl, by zaokrąglić do liczb całkowitych. Przytrzymaj Shift dla " +"bardziej precyzyjnych zmian." #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -3983,7 +3991,7 @@ msgstr "Błąd podczas uruchamiania skryptu po imporcie:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "Czy zwracasz obiekt dziedziczący po Node w metodzie `post_import()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -5416,7 +5424,7 @@ msgstr "Tryb przesuwania" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Mode" -msgstr "Tryb Rotacji" +msgstr "Tryb obrotu" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5556,7 +5564,7 @@ msgstr "Widok" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Always Show Grid" -msgstr "Zawsze pokaż siatkę" +msgstr "Zawsze pokazuj siatkę" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Helpers" @@ -6938,9 +6946,8 @@ msgstr "" "\"%s\"." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(ignoruj)" +msgstr "[Ignoruj]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -6978,7 +6985,7 @@ msgstr "Wielkie litery" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Lowercase" -msgstr "Małe Litery" +msgstr "Małe litery" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Capitalize" @@ -7054,7 +7061,7 @@ msgstr "Wylicz wyrażenie" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" -msgstr "Przytnij końcowe spacje" +msgstr "Przytnij końcowe białe znaki" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent to Spaces" @@ -7387,7 +7394,7 @@ msgstr "\"Wolny widok\" w tył" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Up" -msgstr "\"Wolny widok\" w góre" +msgstr "\"Wolny widok\" w górę" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Down" @@ -7425,6 +7432,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Kliknij, by przełączyć pomiędzy stanami widoczności.\n" +"\n" +"Otwarte oko: uchwyt jest widzialny.\n" +"Zamknięte oko: uchwyt jest ukryty.\n" +"Półotwarte oko: uchwyt jest również widoczny przez nieprzezroczyste " +"powierzchnie (\"x-ray\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7519,7 +7532,7 @@ msgstr "2 widoki" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports (Alt)" -msgstr "2 widoki (Alt)" +msgstr "2 widoki (alternatywnie)" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports" @@ -7527,7 +7540,7 @@ msgstr "3 widoki" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports (Alt)" -msgstr "3 widoki (Alt)" +msgstr "3 widoki (alternatywnie)" #: editor/plugins/spatial_editor_plugin.cpp msgid "4 Viewports" @@ -8807,7 +8820,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "'%s' input parameter for fragment and light shader modes." -msgstr "Parametr wejściowy \"%s\" dla dla fragmentowego i światłowego shadera." +msgstr "Parametr wejściowy \"%s\" dla fragmentowego i światłowego shadera." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "'%s' input parameter for fragment shader mode." @@ -9507,16 +9520,16 @@ msgid "" "Filters to export non-resource files/folders\n" "(comma-separated, e.g: *.json, *.txt, docs/*)" msgstr "" -"Filtry do eksportowania plików/folderów nie będących zasobami (oddzielone " -"przecinkami, np. *.json, *.txt)" +"Filtry do eksportowania plików/folderów nie będących zasobami\n" +"(oddzielone przecinkami, np. *.json, *.txt, docs/*)" #: editor/project_export.cpp msgid "" "Filters to exclude files/folders from project\n" "(comma-separated, e.g: *.json, *.txt, docs/*)" msgstr "" -"Filtry do wykluczenia plików/folderów z projektu (rozdzielone przecinkami, " -"np. *.json, *.txt)" +"Filtry do wykluczenia plików/folderów z projektu\n" +"(oddzielone przecinkami, np. *.json, *.txt, docs/*)" #: editor/project_export.cpp msgid "Patches" @@ -10515,9 +10528,8 @@ msgid "Instance Child Scene" msgstr "Dodaj instancję sceny" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "Dodaj skrypt" +msgstr "Odłącz skrypt" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10635,7 +10647,7 @@ msgstr "Nie można działać na węzłach z których dziedziczy obecna scena!" #: editor/scene_tree_dock.cpp msgid "Attach Script" -msgstr "Dodaj skrypt" +msgstr "Dołącz skrypt" #: editor/scene_tree_dock.cpp msgid "Remove Node(s)" @@ -10687,6 +10699,9 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Nie można dołączyć skryptu: brak zarejestrowanych języków.\n" +"To prawdopodobnie przez to, że ten edytor został zbudowany z wyłączonymi " +"wszystkimi modułami języków." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10737,14 +10752,12 @@ msgstr "" "główny nie istnieje." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." msgstr "Dołącz nowy lub istniejący skrypt do zaznaczonego węzła." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "Wyczyść skrypt dla zaznaczonego węzła." +msgstr "Odłącz skrypt z zaznaczonego węzła." #: editor/scene_tree_dock.cpp msgid "Remote" @@ -10783,7 +10796,7 @@ msgid "" "Node has %s connection(s) and %s group(s).\n" "Click to show signals dock." msgstr "" -"Węzeł posiada %s połączeń i %s grup.\n" +"Węzeł posiada %s połączeń i %s grup.\n" "Kliknij, aby wyświetlić panel sygnałów." #: editor/scene_tree_editor.cpp @@ -11839,15 +11852,15 @@ msgstr "Znajdź typ węzła" #: modules/visual_script/visual_script_editor.cpp msgid "Copy Nodes" -msgstr "Skopiuj Węzeł" +msgstr "Skopiuj węzły" #: modules/visual_script/visual_script_editor.cpp msgid "Cut Nodes" -msgstr "Wytnij Węzły" +msgstr "Wytnij węzły" #: modules/visual_script/visual_script_editor.cpp msgid "Make Function" -msgstr "Zmień na funkcję" +msgstr "Zamień na funkcję" #: modules/visual_script/visual_script_editor.cpp msgid "Refresh Graph" @@ -11969,11 +11982,9 @@ msgstr "" "eksportu." #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." msgstr "" -"Debugowy keystore nieskonfigurowany w Ustawieniach Edytora ani w profilu " -"eksportu." +"Wydaniowy keystore jest niepoprawnie skonfigurowany w profilu eksportu." #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." @@ -12007,26 +12018,34 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Niepoprawny moduł \"GodotPaymentV3\" załączony w ustawieniu projektu " +"\"android/modules\" (zmieniony w Godocie 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "\"Use Custom Build\" musi być włączone, by używać wtyczek." #: platform/android/export/export.cpp msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"\"Degrees Of Freedom\" jest poprawne tylko gdy \"Xr Mode\" jest \"Oculus " +"Mobile VR\"." #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Hand Tracking\" jest poprawne tylko gdy \"Xr Mode\" jest \"Oculus Mobile VR" +"\"." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Focus Awareness\" jest poprawne tylko gdy \"Xr Mode\" jest \"Oculus Mobile " +"VR\"." #: platform/android/export/export.cpp msgid "" diff --git a/editor/translations/pr.po b/editor/translations/pr.po index 9d46edcbae..bfa3d0b52c 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -5,12 +5,13 @@ # Calum Knott <calum@calumk.com>, 2017. # Zion Nimchuk <zionnimchuk@gmail.com>, 2016-2017. # Allan Nordhøy <epost@anotheragency.no>, 2018. +# David Fatheree <david.fathereewcchs@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:42+0100\n" -"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: David Fatheree <david.fathereewcchs@gmail.com>\n" "Language-Team: Pirate <https://hosted.weblate.org/projects/godot-engine/" "godot/pr/>\n" "Language: pr\n" @@ -18,7 +19,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 2.2\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -29,7 +30,7 @@ msgstr "" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "" +msgstr "Expected a strin' o' length 1 (a character)." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp @@ -39,19 +40,17 @@ msgstr "Nah enough bytes fer decodin' bytes, or ye got th' wrong ship." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "" +msgstr "Shiver me timbers! Ye input %i (not passed) in ye expression!" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" msgstr "" #: core/math/expression.cpp -#, fuzzy msgid "Invalid operands to operator %s, %s and %s." msgstr "Yer index property name '%s' in node %s be walkin' th' plank!" #: core/math/expression.cpp -#, fuzzy msgid "Invalid index of type %s for base type %s" msgstr "Yer index property name '%s' in node %s be walkin' th' plank!" @@ -102,11 +101,11 @@ msgstr "" #: editor/animation_bezier_editor.cpp msgid "Balanced" -msgstr "" +msgstr "Smooth Sailin'" #: editor/animation_bezier_editor.cpp msgid "Mirror" -msgstr "" +msgstr "See'in Double" #: editor/animation_bezier_editor.cpp editor/editor_profiler.cpp msgid "Time:" @@ -767,6 +766,11 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Yer name's got no valid identifier:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index 199d828897..70878acad2 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -16,7 +16,7 @@ # jonathan railarem <railarem@gmail.com>, 2017. # Lucas Silva <lucasb.hpp@gmail.com>, 2018. # Luiz G. Correia <luizgabriell2.0@gmail.com>, 2017. -# Mailson Silva Marins <mailsons335@gmail.com>, 2016. +# Mailson Silva Marins <mailsons335@gmail.com>, 2016, 2020. # MalcomRF <malcomkbk@gmail.com>, 2017. # Marcus Correia <marknokalt@live.com>, 2017-2018. # Michael Alexsander Silva Dias <michaelalexsander@protonmail.com>, 2017-2018. @@ -73,7 +73,7 @@ # Alan Tavares <alan1tavares@gmail.com>, 2019. # Rafael Silveira <res883@gmail.com>, 2019. # Luigi <luigimendeszanchett@gmail.com>, 2019. -# Nicolas Abril <nicolas.abril@protonmail.ch>, 2019. +# Nicolas Abril <nicolas.abril@protonmail.ch>, 2019, 2020. # johnnybigoode <jamarson@gmail.com>, 2019, 2020. # Zeero <igcdzeero@gmail.com>, 2019. # Gian Penna <gianfrancopen@gmail.com>, 2020. @@ -92,13 +92,14 @@ # Anonymous <noreply@weblate.org>, 2020. # André Sousa <andrelvsousa@gmail.com>, 2020. # Kleyton Luiz de Sousa Vieira <kleytonluizdesouzavieira@gmail.com>, 2020. +# Felipe Jesus Macedo <fmacedo746@gmail.com>, 2020. +# José Paulo <jose.paulo1919@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" -"Last-Translator: Kleyton Luiz de Sousa Vieira " -"<kleytonluizdesouzavieira@gmail.com>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: José Paulo <jose.paulo1919@gmail.com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_BR/>\n" "Language: pt_BR\n" @@ -106,7 +107,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -125,11 +126,11 @@ msgstr "Não há bytes suficientes para decodificar, ou o formato é inválido." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "Entrada inválida %i (não passou) na expressão" +msgstr "Entrada inválida %i (não passada) na expressão" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" -msgstr "self não pode ser usado porque a instância é nula (não passou)" +msgstr "self não pode ser usado porque a instância é nula (não passada)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." @@ -145,7 +146,7 @@ msgstr "Nome inválido de índice '%s' para base tipo %s" #: core/math/expression.cpp msgid "Invalid arguments to construct '%s'" -msgstr "Argumento inválido para construir '%s'" +msgstr "Argumentos inválidos para o construto '%s'" #: core/math/expression.cpp msgid "On call to '%s':" @@ -579,7 +580,7 @@ msgstr "" "Esta animação pertence a uma cena importada, dessa forma, mudanças das " "trilhas importadas não serão salvas.\n" "\n" -"Para ativar a possibilidade de adicionar trilhas customizadas, navegue até " +"Para ativar a possibilidade de adicionar trilhas customizadas, navegue até " "as configurações de importação da cena e defina\n" "\"Animação > Armazenamento\" para \"Arquivos\", ative \"Animação > Mantenha " "Trilhas Customizadas\", então reimporte.\n" @@ -843,6 +844,10 @@ msgid "Method in target node must be specified." msgstr "O método no nó alvo precisa ser especificado." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "O nome do método deve ser um identificador válido." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1919,7 +1924,7 @@ msgstr "Alternar Modo" #: editor/editor_file_dialog.cpp msgid "Focus Path" -msgstr "Focar no Caminho" +msgstr "Habilitar" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" @@ -2622,8 +2627,8 @@ msgid "" "category." msgstr "" "A cena principal não foi definida, selecionar uma?\n" -"Você pode alterá-la mais tarde nas \"Configurações do Projeto\" na " -"categoria 'Application'." +"Você pode alterá-la mais tarde nas \"Configurações do Projeto\" na categoria " +"'Application'." #: editor/editor_node.cpp msgid "" @@ -2899,8 +2904,8 @@ msgid "" "Navigation meshes and polygons will be visible on the running game if this " "option is turned on." msgstr "" -"Malhas e polígonos de navegação serão visíveis no jogo se esta opção estiver " -"ligada." +"Malhas e polígonos de navegação serão visíveis no jogo em execução se esta " +"opção estiver ligada." #: editor/editor_node.cpp msgid "Sync Scene Changes" @@ -3121,13 +3126,13 @@ msgid "" "the \"Use Custom Build\" option should be enabled in the Android export " "preset." msgstr "" -"Isso vai configurar seu projeto para construções customizadas do Android, " -"instalando o modelo de fonte para \"res://android/build\".\n" -"Você pode então aplicar modificações e construir seu próprio APK na guia " -"Exportação (Adicionando módulos, trocando o AndroidManifest.xml, etc.).\n" -"Note que para fazer uma construção customizada, em vez de usar APKs pre-" -"construídos, a opção \"Usar Construção Customizada\" deve estar ativa nas " -"predefinições de exportação Android." +"Isso irá configurar o projeto para usar uma build do Android customizada " +"instalando a template raiz para \"res://android/build\".\n" +"Você poderá aplicar modificações e construir um APK customizado em exportar " +"(adicionando módulos, changing the AndroidManifest.xml, etc.).\n" +"Note que para fazer builds customizadas ao invés de usar APKs pré-" +"construídas, a opção \"Usar Build Customizada\" deve sestar habilitada na " +"pré-configuração de exportação Android." #: editor/editor_node.cpp msgid "" @@ -4047,7 +4052,7 @@ msgstr "Erro ao rodar script pós-importação:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "Você retornou um objeto derivado de nó no método `post import ()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -5659,7 +5664,7 @@ msgstr "Seleção de Frame" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Preview Canvas Scale" -msgstr "Visualizar Canvas Scale" +msgstr "Pré-visualização da escala do Canvas" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Translation mask for inserting keys." @@ -5667,7 +5672,7 @@ msgstr "Máscara de tradução para inserção de chaves." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation mask for inserting keys." -msgstr "Mascara de rotação para inserção de chaves." +msgstr "Máscara de rotação para inserção de chaves." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Scale mask for inserting keys." @@ -7005,9 +7010,8 @@ msgid "" msgstr "Falta método conectado '%s' para sinal '%s' do nó '%s' para nó '%s'." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(ignore)" +msgstr "(Ignore)" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -7438,27 +7442,27 @@ msgstr "Não disponível ao usar o renderizador GLES2." #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Left" -msgstr "Visão Livre Esquerda" +msgstr "Visão Livre na Esquerda" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Right" -msgstr "Visão Livre Direita" +msgstr "Visão Livre na Direita" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Forward" -msgstr "Visão Livre Frente" +msgstr "Visão Livre na Frente" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Backwards" -msgstr "Visão Livre Trás" +msgstr "Visão Livre Atrás" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Up" -msgstr "Visão Livre Cima" +msgstr "Visão Livre em Cima" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Down" -msgstr "Visão Livre Baixo" +msgstr "Visão Livre Embaixo" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Speed Modifier" @@ -7492,6 +7496,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Clique para alternar entre estados de visibilidade.\n" +"\n" +"Olhos abertos: Gizmo está visível.\n" +"Olhos fechados: Gizmo não está visível.\n" +"Olhos semi-abertos: Gizmo está visível através de superficies opacas (\"raio-" +"x\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7517,7 +7527,7 @@ msgstr "Usar Espaço Local" #: editor/plugins/spatial_editor_plugin.cpp msgid "Use Snap" -msgstr "Usar Snap" +msgstr "Use Snap" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" @@ -8379,9 +8389,9 @@ msgid "" "Shift+LMB: Set wildcard bit.\n" "Click on another Tile to edit it." msgstr "" -"LMB: ligar bit.\n" -"RMB: desligar bit.\n" -"Shift+LMB: Escolher bit wildcard.\n" +"LMB: Ligar bit.\n" +"RMB: Desligar bit.\n" +"Shift+LMB: Escolher bit curinga.\n" "Clique em outro Mosaico para editá-lo." #: editor/plugins/tile_set_editor_plugin.cpp @@ -8516,7 +8526,7 @@ msgstr "Nenhuma mensagem de confirmação foi fornecida" #: editor/plugins/version_control_editor_plugin.cpp msgid "No files added to stage" -msgstr "Nenhum arquivo adicionado ao palco" +msgstr "Nenhum arquivo em espera" #: editor/plugins/version_control_editor_plugin.cpp msgid "Commit" @@ -8524,11 +8534,11 @@ msgstr "Confirmação" #: editor/plugins/version_control_editor_plugin.cpp msgid "VCS Addon is not initialized" -msgstr "Extensão VCS não está inicializada" +msgstr "VCS Addon não inicializado" #: editor/plugins/version_control_editor_plugin.cpp msgid "Version Control System" -msgstr "Sistema de Controle de Versionamento" +msgstr "Sistema de Controle de Versão" #: editor/plugins/version_control_editor_plugin.cpp msgid "Initialize" @@ -8536,7 +8546,7 @@ msgstr "Inicializar" #: editor/plugins/version_control_editor_plugin.cpp msgid "Staging area" -msgstr "Área Temporária" +msgstr "Área de espera" #: editor/plugins/version_control_editor_plugin.cpp msgid "Detect new changes" @@ -8560,7 +8570,7 @@ msgstr "Excluído" #: editor/plugins/version_control_editor_plugin.cpp msgid "Typechange" -msgstr "Alterar tipo" +msgstr "Alteração de tipo" #: editor/plugins/version_control_editor_plugin.cpp msgid "Stage Selected" @@ -8572,11 +8582,11 @@ msgstr "Salvar Tudo" #: editor/plugins/version_control_editor_plugin.cpp msgid "Add a commit message" -msgstr "Adicione uma mensagem de confirmação" +msgstr "Adicione uma mensagem ao commit" #: editor/plugins/version_control_editor_plugin.cpp msgid "Commit Changes" -msgstr "Confirmar Mudanças de Script" +msgstr "Confirmar Mudanças" #: editor/plugins/version_control_editor_plugin.cpp #: modules/gdnative/gdnative_library_singleton_editor.cpp @@ -8774,7 +8784,7 @@ msgstr "Cor constante." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Color uniform." -msgstr "Cor uniforme." +msgstr "Uniformidade de cor." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the boolean result of the %s comparison between two parameters." @@ -8890,7 +8900,7 @@ msgstr "Parâmetro de entrada '%s' para o modo de sombra do vértice." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "'%s' input parameter for vertex and fragment shader mode." msgstr "" -"Parâmetro de entrada '%s' para os modos de sombra de vértice e fragmentada." +"Parâmetro de entrada '%s' para os modo de sombra fragmentada e vértice." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Scalar function." @@ -9144,7 +9154,7 @@ msgstr "Execute a pesquisa de textura cúbica." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Perform the texture lookup." -msgstr "Faz uma busca de texturas." +msgstr "Faz uma busca por texturas." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Cubic texture uniform lookup." @@ -9160,7 +9170,7 @@ msgstr "Consulta de textura 2D uniforme com triplanar." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Transform function." -msgstr "Função Transform." +msgstr "Função Transformação..." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9182,7 +9192,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Composes transform from four vectors." -msgstr "Compõe transformação a partir de quatro vetores." +msgstr "Compõe a transformação de quatro vetores." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Decomposes transform to four vectors." @@ -9190,19 +9200,19 @@ msgstr "Decompõe transformação em quatro vetores." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the determinant of a transform." -msgstr "Calcula o determinante de uma transformada." +msgstr "Calcula o determinante de uma transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the inverse of a transform." -msgstr "Calcula a inversa de uma transformada." +msgstr "Calcula a inversa de uma transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the transpose of a transform." -msgstr "Calcula a transposta de uma transformada." +msgstr "Calcula a transposta de uma transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Multiplies transform by transform." -msgstr "Multiplica a transformação por transformação." +msgstr "Multiplica transformação por transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Multiplies vector by transform." @@ -9210,11 +9220,11 @@ msgstr "Multiplica vetor por transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Transform constant." -msgstr "Constante de transformação." +msgstr "Transformar constante." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Transform uniform." -msgstr "Uniforme de transformação." +msgstr "Transformação uniforme." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector function." @@ -9363,11 +9373,11 @@ msgstr "Subtrai vetor de vetor." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector constant." -msgstr "Vetor constante." +msgstr "Constante vetorial." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector uniform." -msgstr "Vector uniforme." +msgstr "Uniformidade vetorial." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9385,8 +9395,8 @@ msgid "" "Returns falloff based on the dot product of surface normal and view " "direction of camera (pass associated inputs to it)." msgstr "" -"Retorna falloff baseado no produto escalar do normal da superfície e da " -"direção de visualização da câmera (passe entradas associadas a ela)." +"Retorna decaimento com base no produto escalar da normal da superfície com o " +"a direção de visão da câmera (passe as entradas associadas a ele)." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9413,7 +9423,7 @@ msgid "" "(Fragment/Light mode only) (Vector) Derivative in 'x' using local " "differencing." msgstr "" -"(Apenas modo Fragmento/Luz) (Vetor) Derivada em 'x' usando diferenciação " +"(Apenas modo Fragmento/Luz) (Vetor) Derivativo em 'x' usando diferenciação " "local." #: editor/plugins/visual_shader_editor_plugin.cpp @@ -9832,7 +9842,7 @@ msgstr "Projeto ausente" #: editor/project_manager.cpp msgid "Error: Project is missing on the filesystem." -msgstr "Erro: O Projeto está ausente no sistema de arquivos." +msgstr "Erro: Projeto não encontrado no sistema de arquivos." #: editor/project_manager.cpp msgid "Can't open project at '%s'." @@ -9854,14 +9864,15 @@ msgid "" "Warning: You won't be able to open the project with previous versions of the " "engine anymore." msgstr "" -"O seguinte arquivo de configurações do projeto não especifica com qual " -"versão do Godot ele foi criado.\n" +"O seguinte arquivo de configurações do projeto não especifica a versão do " +"Godot pelo qual ele foi criado.\n" "\n" "%s\n" "\n" -"Se escolher abrí-lo, será convertido para o formato atual de arquivo de " -"configuração do Godot\n" -"Aviso: Você não poderá mais abrir o projeto com versões anteriores do Godot." +"Se você o abrir, ele será convertido para o formato de arquivo da " +"configuração atual do Godot.\n" +"Atenção: Você não será mais capaz de abrir o projeto com versões anteriores " +"da engine." #: editor/project_manager.cpp msgid "" @@ -9981,7 +9992,7 @@ msgstr "Novo Projeto" #: editor/project_manager.cpp msgid "Remove Missing" -msgstr "Remover Ausentes" +msgstr "Remover Ausente" #: editor/project_manager.cpp msgid "Templates" @@ -10144,7 +10155,7 @@ msgstr "Botão Direito." #: editor/project_settings_editor.cpp msgid "Middle Button." -msgstr "Botão do Meio." +msgstr "Botão do Meio." #: editor/project_settings_editor.cpp msgid "Wheel Up." @@ -10572,16 +10583,15 @@ msgstr "Instanciar Cena(s)" #: editor/scene_tree_dock.cpp msgid "Replace with Branch Scene" -msgstr "Substituir com Ramo como Cena" +msgstr "Substituir por cena ramo" #: editor/scene_tree_dock.cpp msgid "Instance Child Scene" msgstr "Instânciar Cena Filha" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "Adicionar Script" +msgstr "Remover Script" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10751,6 +10761,9 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Não pode associar um script: Não existem linguagens registradas.\n" +"É provável que o editor tenha sido construido com todos os módulos de " +"linguagem desabilitados." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10801,14 +10814,12 @@ msgstr "" "existir um nó raiz." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." -msgstr "Adicionar um script novo ou existente para o nó selecionado." +msgstr "Adicionar um novo script, ou um já existente, para o nó selecionado." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "Remove um script do nó selecionado." +msgstr "Remove o script do nó selecionado." #: editor/scene_tree_dock.cpp msgid "Remote" @@ -10920,7 +10931,7 @@ msgstr "Selecione um Nó" #: editor/script_create_dialog.cpp msgid "Path is empty." -msgstr "O caminho está vazio." +msgstr "Caminho vazio." #: editor/script_create_dialog.cpp msgid "Filename is empty." @@ -11328,7 +11339,7 @@ msgstr "Singleton GDNative ativado" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Disabled GDNative Singleton" -msgstr "Singleton GDNative Desabilitado" +msgstr "GDNative Singleton desativado" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Library" @@ -11589,8 +11600,8 @@ msgid "" "Node yielded, but did not return a function state in the first working " "memory." msgstr "" -"Nó entrou em yield, mas não retornou um estado de função na primeira memória " -"de trabalho." +"O nó cedeu, mas não retornou um estado de função na primeira memória de " +"trabalho." #: modules/visual_script/visual_script.cpp msgid "" @@ -12041,20 +12052,20 @@ msgstr "" #, fuzzy msgid "Release keystore incorrectly configured in the export preset." msgstr "" -"Porta-chaves de depuração não configurado nas Configurações do Editor e nem " -"na predefinição." +"Keystore de liberação icorretamente configurada na predefinição de " +"exportação." #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." msgstr "" -"A compilação personalizada requer um caminho SDK do Android válido nas " +"Build personalizada precisa de um caminho Android SDK válido em " "Configurações do Editor." #: platform/android/export/export.cpp msgid "Invalid Android SDK path for custom build in Editor Settings." msgstr "" -"Caminho SDK do Android inválido para a compilação personalizada nas " -"Configurações do Editor." +"Caminho do Android SDK inválido para o build personalizado em Configurações " +"do Editor." #: platform/android/export/export.cpp msgid "" @@ -12066,7 +12077,7 @@ msgstr "" #: platform/android/export/export.cpp msgid "Invalid public key for APK expansion." -msgstr "Chave pública inválida para expansão de APK." +msgstr "Chave pública inválida para expansão do APK." #: platform/android/export/export.cpp msgid "Invalid package name:" @@ -12077,34 +12088,45 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Módulo inválido \"GodotPaymentV3\" incluido na configuração de projeto " +"\"android/modules\" (changed in Godot 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." msgstr "" +"\"Use Custom Build\" precisa estar ativo para ser possível utilizar plugins." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"\"Degrees Of Freedom\" só é válido quando o \"Oculus Mobile VR\" está no " +"\"Mode Xr\"." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Hand Tracking\" só é válido quando o\"Oculus Mobile VR\" está no \"Xr Mode" +"\"." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Focus Awareness\" só é válido quando o \"Oculus Mobile VR\" está no \"Xr " +"Mode\"." #: platform/android/export/export.cpp msgid "" "Trying to build from a custom built template, but no version info for it " "exists. Please reinstall from the 'Project' menu." msgstr "" -"Tentando compilar a partir de um modelo compilado personalizado, mas nenhuma " -"informação de versão para ele existe. Por favor, reinstale pelo menu " +"Tentando construir a partir de um modelo compilado personalizado, mas " +"nenhuma informação de versão para ele existe. Por favor, reinstale pelo menu " "'Projeto'." #: platform/android/export/export.cpp @@ -12114,7 +12136,7 @@ msgid "" " Godot Version: %s\n" "Please reinstall Android build template from 'Project' menu." msgstr "" -"Diferença de versão da compilação do Android:\n" +"Diferença na versão da build do Android:\n" " Modelo instalado: %s\n" " Versão do Godot: %s\n" "Por favor reinstale o modelo de compilação do Android pelo menu 'Projeto'." @@ -12128,13 +12150,13 @@ msgid "" "Building of Android project failed, check output for the error.\n" "Alternatively visit docs.godotengine.org for Android build documentation." msgstr "" -"A compilação do projeto Android falhou, verifique a saída pelo erro.\n" +"A construção do projeto Android falhou, verifique a saída para detalhes.\n" "Alternativamente, visite docs.godotengine.org para ver a documentação de " "compilação do Android." #: platform/android/export/export.cpp msgid "No build apk generated at: " -msgstr "Nenhuma compilação apk gerada em: " +msgstr "Nenhuma construção apk gerada em: " #: platform/iphone/export/export.cpp msgid "Identifier is missing." @@ -12545,7 +12567,8 @@ msgstr "" #: scene/3d/collision_shape.cpp msgid "" "ConcavePolygonShape doesn't support RigidBody in another mode than static." -msgstr "Lol." +msgstr "" +"ConcavePolygonShape não suporta um RigidBody em outro modo além do estático." #: scene/3d/cpu_particles.cpp msgid "Nothing is visible because no mesh has been assigned." @@ -12718,7 +12741,7 @@ msgstr "Nada está ligado à entrada '%s' do nó '%s'." #: scene/animation/animation_tree.cpp msgid "No root AnimationNode for the graph is set." -msgstr "Um AnimationNode raiz para o gráfico não está definido." +msgstr "Nenhuma raiz AnimationNode para o gráfico está definida." #: scene/animation/animation_tree.cpp msgid "Path to an AnimationPlayer node containing animations is not set." @@ -12784,9 +12807,9 @@ msgid "" "The Hint Tooltip won't be displayed as the control's Mouse Filter is set to " "\"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\"." msgstr "" -"A Dica não será exibida quando o controle de Filtro do Mouse estiver " -"definido como \"Ignorar\". Para resolver, defina o Filtro do Mouse como " -"\"Parar\" ou \"Continuar\"." +"A sugestão de dica não será exibida quando o Filtro do Mouse do controle " +"estiver definido como \"Ignorar\". Para resolver isto, defina o Filtro do " +"Mouse como \"Parar\" ou \"Passar\"." #: scene/gui/dialogs.cpp msgid "Alert!" @@ -12831,7 +12854,7 @@ msgid "" "Environment -> Default Environment) could not be loaded." msgstr "" "O Ambiente Padrão especificado nas Configurações de Projeto (Rendering -> " -"Environment -> Default Environment) não pôde ser carregado." +"Environment -> Default Environment) não pôde ser carregado." #: scene/main/viewport.cpp msgid "" diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po index 40a83eaa87..54accb0d6f 100644 --- a/editor/translations/pt_PT.po +++ b/editor/translations/pt_PT.po @@ -768,6 +768,11 @@ msgid "Method in target node must be specified." msgstr "Método no nó alvo deve ser especificado." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "O nome não é um identificador válido:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ro.po b/editor/translations/ro.po index 5e362de330..cbf6a8f0a0 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -749,6 +749,11 @@ msgid "Method in target node must be specified." msgstr "Metoda din nodul țintă trebuie specificată." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metoda din nodul țintă trebuie specificată." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ru.po b/editor/translations/ru.po index 8bae9207d0..a2e562446d 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -27,7 +27,7 @@ # Yan <uvokinuvokines@gmail.com>, 2018. # V. <Unit68189@gmail.com>, 2018, 2019. # Victor Butorin <mrwebsterchannel@gmail.com>, 2018. -# Александр <ol-vin@mail.ru>, 2018, 2019. +# Александр <ol-vin@mail.ru>, 2018, 2019, 2020. # Анатолий Горбунов <afgorbunov@gmail.com>, 2018, 2019. # Vadim Vergasov <vadim.vergasov2003@gmail.com>, 2018, 2019. # Аслан Снупов <aslan170505@gmail.com>, 2018. @@ -76,12 +76,14 @@ # Nikita <Kulacnikita@ya.ru>, 2020. # Alexander <ramzi7208@gmail.com>, 2020. # Alex Tern <ternvein@gmail.com>, 2020. +# Varion Drakon Neonovich <variondrakon@gmail.com>, 2020. +# d2cyb <dmitrydpb@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 12:01+0000\n" -"Last-Translator: Alex Tern <ternvein@gmail.com>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: Александр <ol-vin@mail.ru>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" "Language: ru\n" @@ -90,7 +92,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.1\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -99,13 +101,13 @@ msgstr "Неверный тип аргумента для convert(), испол #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "Ожидалась строка длиной 1 (символ)." +msgstr "Ожидалась строка длиной 1 (т.е. символ)." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." -msgstr "Недостаточно байтов для декодирования или неверный формат." +msgstr "Недостаточно байтов для декодирования байтов или неверный формат." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -134,7 +136,7 @@ msgstr "Недопустимые аргументы для построения #: core/math/expression.cpp msgid "On call to '%s':" -msgstr "На вызове '%s':" +msgstr "При вызове '%s':" #: core/ustring.cpp msgid "B" @@ -190,11 +192,11 @@ msgstr "Вставить ключ здесь" #: editor/animation_bezier_editor.cpp msgid "Duplicate Selected Key(s)" -msgstr "Дублировать выделенные ключ(и)" +msgstr "Дублировать выделенные ключи" #: editor/animation_bezier_editor.cpp msgid "Delete Selected Key(s)" -msgstr "Удалить выделенные ключ(и)" +msgstr "Удалить выделенные ключи" #: editor/animation_bezier_editor.cpp msgid "Add Bezier Point" @@ -242,7 +244,7 @@ msgstr "Многократное изменение перехода" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Transform" -msgstr "Анимационное многократное изменение положения" +msgstr "Анимационное многосменное преобразование" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Value" @@ -250,7 +252,7 @@ msgstr "Изменить значение ключевого кадра" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Call" -msgstr "Анимационный многократный вызов изменения" +msgstr "Изменить вызов анимации" #: editor/animation_track_editor.cpp msgid "Change Animation Length" @@ -320,7 +322,7 @@ msgstr "Изменить Путь Следования" #: editor/animation_track_editor.cpp msgid "Toggle this track on/off." -msgstr "Переключить этот трек вкл/выкл." +msgstr "Включить/выключить этот трек." #: editor/animation_track_editor.cpp msgid "Update Mode (How this property is set)" @@ -328,16 +330,15 @@ msgstr "Режим Обновления (Как это свойство уста #: editor/animation_track_editor.cpp msgid "Interpolation Mode" -msgstr "Режим Перехода" +msgstr "Режим интерполяции" #: editor/animation_track_editor.cpp msgid "Loop Wrap Mode (Interpolate end with beginning on loop)" -msgstr "" -"Режим Обработки Зацикливания (Переход заканчивается с началом нового цикла)" +msgstr "Режим зацикливания (интерполировать начало и конец при зацикливании)" #: editor/animation_track_editor.cpp msgid "Remove this track." -msgstr "Удалить этот трек." +msgstr "Удалить эту дорожку." #: editor/animation_track_editor.cpp msgid "Time (s): " @@ -403,7 +404,7 @@ msgstr "Изменить режим обновления анимации" #: editor/animation_track_editor.cpp msgid "Change Animation Interpolation Mode" -msgstr "Изменить режим интерполяции анимации" +msgstr "Изменить способ интерполяции анимации" #: editor/animation_track_editor.cpp msgid "Change Animation Loop Mode" @@ -463,7 +464,8 @@ msgstr "Переставить дорожки" #: editor/animation_track_editor.cpp msgid "Transform tracks only apply to Spatial-based nodes." -msgstr "Трек трансформации применяется только к основанным на Spatial узлам." +msgstr "" +"Дорожка преобразования применяется только к основанным на Spatial узлам." #: editor/animation_track_editor.cpp msgid "" @@ -472,14 +474,14 @@ msgid "" "-AudioStreamPlayer2D\n" "-AudioStreamPlayer3D" msgstr "" -"Aудио треки могут указывать только на узлы типа:\n" +"Аудио дорожки могут указывать только на узлы типа:\n" "-AudioStreamPlayer\n" "-AudioStreamPlayer2D\n" "-AudioStreamPlayer3D" #: editor/animation_track_editor.cpp msgid "Animation tracks can only point to AnimationPlayer nodes." -msgstr "Треки Анимации могут указывать только на узлы типа AnimationPlayer." +msgstr "Дорожки анимации могут указывать только на узлы типа AnimationPlayer." #: editor/animation_track_editor.cpp msgid "An animation player can't animate itself, only other players." @@ -487,11 +489,11 @@ msgstr "Проигрыватель анимации не может анимир #: editor/animation_track_editor.cpp msgid "Not possible to add a new track without a root" -msgstr "Нельзя добавить новый трек без корневого узла" +msgstr "Нельзя добавить новую дорожку без корневого узла" #: editor/animation_track_editor.cpp msgid "Invalid track for Bezier (no suitable sub-properties)" -msgstr "Неверный трек для кривой Безье (нет подходящих подсвойств)" +msgstr "Неверная дорожка для кривой Безье (нет подходящих подсвойств)" #: editor/animation_track_editor.cpp msgid "Add Bezier Track" @@ -499,11 +501,11 @@ msgstr "Добавить дорожку Безье" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a key." -msgstr "Путь трека некорректен, потому нельзя добавить ключ." +msgstr "Путь к дорожке некорректен, потому нельзя добавить ключ." #: editor/animation_track_editor.cpp msgid "Track is not of type Spatial, can't insert key" -msgstr "Трек не имеет тип Spatial, нельзя добавить ключ" +msgstr "Дорожка не имеет тип Spatial, нельзя добавить ключ" #: editor/animation_track_editor.cpp msgid "Add Transform Track Key" @@ -515,11 +517,11 @@ msgstr "Добавить ключ дорожки" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a method key." -msgstr "Путь трека некорректен, потому нельзя добавить ключ метода." +msgstr "Путь к дорожке некорректен, потому нельзя добавить ключ метода." #: editor/animation_track_editor.cpp msgid "Add Method Track Key" -msgstr "Добавить ключ отслеживания метода" +msgstr "Добавить ключ дорожки для метода" #: editor/animation_track_editor.cpp msgid "Method not found in object: " @@ -546,7 +548,7 @@ msgid "" "This option does not work for Bezier editing, as it's only a single track." msgstr "" "Эта опция не работает для редактирования кривыми Безье, так как это только " -"один трек." +"одна дорожка." #: editor/animation_track_editor.cpp msgid "" @@ -561,14 +563,14 @@ msgid "" "files." msgstr "" "Данная анимация принадлежит импортированной сцене, поэтому изменения, " -"внесенные в импортированные треки, не будут сохранены.\n" +"внесенные в импортированные дорожки, не будут сохранены.\n" "\n" -"Чтобы активировать возможность добавления пользовательских треков, перейдите " -"к настройкам импорта сцены и установите\n" +"Чтобы активировать возможность добавления пользовательских дорожек, " +"перейдите к настройкам импорта сцены и установите\n" "\"Анимация > Хранилище\" в значение \"Файлы\", а также включите пункт " -"\"Анимация > Сохранять пользовательские треки\", и заново импортируйте " +"\"Анимация > Сохранять пользовательские дорожки\", и заново импортируйте " "сцену.\n" -"В качестве альтернативы используйте пресет импорта, который импортирует " +"В качестве альтернативы используйте шаблон импорта, который импортирует " "анимации в отдельные файлы." #: editor/animation_track_editor.cpp @@ -581,11 +583,11 @@ msgstr "Выберите узел AnimationPlayer для создания и р #: editor/animation_track_editor.cpp msgid "Only show tracks from nodes selected in tree." -msgstr "Показывать треки только выделенных в дереве узлов." +msgstr "Показывать дорожки только выделенных в дереве узлов." #: editor/animation_track_editor.cpp msgid "Group tracks by node or display them as plain list." -msgstr "Группировать треки по узлам или показывать их как простой список." +msgstr "Группировать дорожки по узлам или показывать их как простой список." #: editor/animation_track_editor.cpp msgid "Snap:" @@ -619,7 +621,7 @@ msgstr "Свойства анимации." #: editor/animation_track_editor.cpp msgid "Copy Tracks" -msgstr "Копировать треки" +msgstr "Копировать дорожки" #: editor/animation_track_editor.cpp msgid "Scale Selection" @@ -635,7 +637,7 @@ msgstr "Дублировать выделенное" #: editor/animation_track_editor.cpp msgid "Duplicate Transposed" -msgstr "Дублировать и переместить" +msgstr "Дублировать и транспонировать" #: editor/animation_track_editor.cpp msgid "Delete Selection" @@ -825,7 +827,12 @@ msgstr "Номера строк и столбцов." #: editor/connections_dialog.cpp msgid "Method in target node must be specified." -msgstr "Метод должен быть указан в целевом узле." +msgstr "Метод в целевом узле должен быть указан." + +#: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Имя не является допустимым идентификатором:" #: editor/connections_dialog.cpp msgid "" @@ -837,7 +844,7 @@ msgstr "" #: editor/connections_dialog.cpp msgid "Connect to Node:" -msgstr "Присоединить к узлу:" +msgstr "Присоединить к Узлу:" #: editor/connections_dialog.cpp msgid "Connect to Script:" @@ -849,7 +856,7 @@ msgstr "От сигнала:" #: editor/connections_dialog.cpp msgid "Scene does not contain any script." -msgstr "Узел не содержит скрипт." +msgstr "Сцена не содержит каких-либо скриптов." #: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp #: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp @@ -870,7 +877,7 @@ msgstr "Удалить" #: editor/connections_dialog.cpp msgid "Add Extra Call Argument:" -msgstr "Добавить дополнительный параметр вызова:" +msgstr "Добавить дополнительный аргумент вызова:" #: editor/connections_dialog.cpp msgid "Extra Call Arguments:" @@ -956,7 +963,7 @@ msgstr "Подключить сигнал к методу" #: editor/connections_dialog.cpp msgid "Edit Connection:" -msgstr "Редактировать подключение:" +msgstr "Редактировать соединение:" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from the \"%s\" signal?" @@ -1093,7 +1100,7 @@ msgstr "Владельцы:" #: editor/dependency_editor.cpp msgid "Remove selected files from the project? (Can't be restored)" -msgstr "Удалить выбранные файлы из проекта? (Нельзя отменить!)" +msgstr "Удалить выбранные файлы из проекта? (Нельзя восстановить)" #: editor/dependency_editor.cpp msgid "" @@ -1522,7 +1529,7 @@ msgstr "Перестановка автозагрузок" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "Нельзя добваить автозагрузку:" +msgstr "Не удаётся добавить автозагрузку:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -2482,7 +2489,7 @@ msgstr "Не возможно загрузить сцену, которая не #: editor/editor_node.cpp msgid "Reload Saved Scene" -msgstr "Перезагрузить сохранённую сцену" +msgstr "Перезагрузить сохраненную сцену" #: editor/editor_node.cpp msgid "" @@ -2768,12 +2775,12 @@ msgstr "Набор тайлов..." #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Undo" -msgstr "Отменить" +msgstr "Отменить (Undo)" #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Redo" -msgstr "Повторить" +msgstr "Повторить (Redo)" #: editor/editor_node.cpp msgid "Miscellaneous project or scene-wide tools." @@ -2930,7 +2937,7 @@ msgstr "Макет редактора" #: editor/editor_node.cpp msgid "Take Screenshot" -msgstr "Сделать снимок экрана" +msgstr "Сделать скриншот" #: editor/editor_node.cpp msgid "Screenshots are stored in the Editor Data/Settings Folder." @@ -3000,7 +3007,7 @@ msgstr "Сообщество" #: editor/editor_node.cpp msgid "About" -msgstr "О движке" +msgstr "О Godot Engine" #: editor/editor_node.cpp msgid "Play the project." @@ -3181,7 +3188,7 @@ msgstr "Открыть предыдущий редактор" #: editor/editor_node.h msgid "Warning!" -msgstr "Внимание!" +msgstr "Предупреждение!" #: editor/editor_path.cpp msgid "No sub-resources found." @@ -3290,7 +3297,7 @@ msgstr "[Пусто]" #: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp msgid "Assign..." -msgstr "Назначается..." +msgstr "Устанавливать.." #: editor/editor_properties.cpp msgid "Invalid RID" @@ -4025,7 +4032,7 @@ msgstr "Ошибка запуска пост-импорт скрипта:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "Вы вернули производный от Node объект в методе `post_import ()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -4243,7 +4250,7 @@ msgstr "Загрузка..." #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Move Node Point" -msgstr "Передвинуть узел" +msgstr "Передвинуть точку узла" #: editor/plugins/animation_blend_space_1d_editor.cpp msgid "Change BlendSpace1D Limits" @@ -4698,7 +4705,7 @@ msgstr "Переместить узел" #: editor/plugins/animation_state_machine_editor.cpp msgid "Transition exists!" -msgstr "Переход уже существует!" +msgstr "Переход существует!" #: editor/plugins/animation_state_machine_editor.cpp msgid "Add Transition" @@ -5632,7 +5639,7 @@ msgstr "Масштаб при просмотре холста" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Translation mask for inserting keys." -msgstr "Маска перемещения для добавляемых ключей." +msgstr "Маска трансформации для вставки ключей." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation mask for inserting keys." @@ -5665,7 +5672,7 @@ msgstr "Автовставка ключа" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Animation Key and Pose Options" -msgstr "Настройки ключевых кадров и поз" +msgstr "Опции анимационных ключей и поз" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Key (Existing Tracks)" @@ -5777,7 +5784,7 @@ msgstr "Маска излучения" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Solid Pixels" -msgstr "Сплошные пиксели" +msgstr "Залитые пиксели" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp @@ -5923,16 +5930,15 @@ msgstr "Это не работает на корне сцены!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Shape" -msgstr "Создать треугольную сетку статической формы" +msgstr "Создать сетку статической формы" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Can't create a single convex collision shape for the scene root." -msgstr "" -"Не удается создать единственную выпуклую форму столкновения для корня сцены." +msgstr "Нельзя создать единую выпуклую форму столкновения для корня сцены." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Couldn't create a single convex collision shape." -msgstr "Не удалось создать одну выпуклую форму столкновений." +msgstr "Не удалось создать ни одной выпуклой формы столкновения." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Single Convex Shape" @@ -5945,11 +5951,11 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Couldn't create any collision shapes." -msgstr "Не удалось создать ни одной форму столкновения." +msgstr "Не удалось создать ни одну форму столкновения." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Multiple Convex Shapes" -msgstr "Создать несколько выпуклых форм" +msgstr "Создать нескольких выпуклых фигур" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Navigation Mesh" @@ -6035,7 +6041,7 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Multiple Convex Collision Siblings" -msgstr "Создать несколько соседних выпуклых форм столкновения" +msgstr "Создать выпуклую область столкновения" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "" @@ -6056,10 +6062,10 @@ msgid "" "This can be used instead of the SpatialMaterial Grow property when using " "that property isn't possible." msgstr "" -"Создаёт статичную обводочную полисетку. Её нормали переворачиваются " -"автоматически.\n" -"Она может быть использована в случае, если использовать свойство Grow " -"материала SpatialMaterial не представляется возможным." +"Создать статичную контурную полисетку. Контурная полисетка будет иметь свои " +"нормали, перевернутые автоматически.\n" +"Можно использовать вместо свойства Grow в SpatialMaterial, в случае когда " +"оно не применимо." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "View UV1" @@ -6974,7 +6980,6 @@ msgstr "" "'%s'." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" msgstr "(игнорировать)" @@ -7335,7 +7340,7 @@ msgstr "Выравнять преобразование с областью пр #: editor/plugins/spatial_editor_plugin.cpp msgid "Align Rotation with View" -msgstr "Выравнять поворот с областью просмотра" +msgstr "Совместить поворот с направлением взгляда" #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "No parent to instance a child at." @@ -7462,6 +7467,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Нажмите для переключения между состояниями видимости.\n" +"\n" +"Открытый глаз: Гизмо видно.\n" +"Закрытый глаз: Гизмо скрыто.\n" +"Полуоткрытый глаз: Гизмо также видно сквозь непрозрачные поверхности " +"(«рентген»)." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7694,7 +7705,7 @@ msgstr "" #: editor/plugins/sprite_editor_plugin.cpp msgid "Invalid geometry, can't replace by mesh." -msgstr "Некорректная геометрия, не может быть заменена сеткой." +msgstr "Недопустимая геометрия, не может быть заменена полисеткой." #: editor/plugins/sprite_editor_plugin.cpp msgid "Convert to Mesh2D" @@ -8597,7 +8608,7 @@ msgstr "Добавить входной порт" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Add output port" -msgstr "Добавить выходной порт" +msgstr "Добавить исходящий порт" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Change input port type" @@ -8678,7 +8689,7 @@ msgstr "Показать полученный код шейдера." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Create Shader Node" -msgstr "Создать узел шейдера" +msgstr "Создать Шейдерный узел" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Color function." @@ -8722,7 +8733,7 @@ msgstr "Оператор выцветания." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "HardLight operator." -msgstr "Оператор HardLight." +msgstr "Оператор жёсткого света." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Lighten operator." @@ -9239,7 +9250,7 @@ msgstr "Линейная интерполяция между двумя вект #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Linear interpolation between two vectors using scalar." -msgstr "Линейная интерполяция между двумя векторами с использованием скаляра." +msgstr "Линейная интерполяция между двумя векторами используя скаляр." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the normalize product of vector." @@ -10166,7 +10177,7 @@ msgstr "Настройки сохранены нормально." #: editor/project_settings_editor.cpp msgid "Moved Input Action Event" -msgstr "Событие ввода действия перемещено" +msgstr "Перенесите событие ввода действия" #: editor/project_settings_editor.cpp msgid "Override for Feature" @@ -10551,7 +10562,6 @@ msgid "Instance Child Scene" msgstr "Добавить дочернюю сцену" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" msgstr "Прикрепить скрипт" @@ -10724,6 +10734,9 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Невозможно прикрепить скрипт: нет зарегистрированных языков.\n" +"Вероятно, это связано с тем, что этот редактор был построен с отключенными " +"всеми языковыми модулями." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10774,12 +10787,10 @@ msgstr "" "не существует." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." msgstr "Прикрепить новый или существующий скрипт к выбранному узлу." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." msgstr "Убрать скрипт у выбранного узла." @@ -11387,7 +11398,7 @@ msgstr "Залить выделенную GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "GridMap Paste Selection" -msgstr "Вставить выделенную сетку" +msgstr "Вставка выделенной сетки" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "GridMap Paint" @@ -12008,7 +12019,6 @@ msgstr "" "предустановках." #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." msgstr "" "Отладочная клавиатура не настроена ни в настройках редактора, ни в " @@ -12046,26 +12056,34 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Недопустимый модуль «GodotPaymentV3», включенный в настройку проекта " +"«android/modules» (изменен в Godot 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "«Use Custom Build» должен быть включен для использования плагинов." #: platform/android/export/export.cpp msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"«Степени свободы» действительны только тогда, когда «Xr Mode» - это «Oculus " +"Mobile VR»." #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"«Отслеживание рук» действует только тогда, когда «Xr Mode» - это «Oculus " +"Mobile VR»." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"«Осведомленность о фокусе» действительна только в том случае, если «Режим " +"Xr» - это «Oculus Mobile VR»." #: platform/android/export/export.cpp msgid "" @@ -12298,7 +12316,7 @@ msgstr "" #: scene/2d/light_occluder_2d.cpp msgid "The occluder polygon for this occluder is empty. Please draw a polygon." msgstr "" -"Заслоняющий полигон для этого окклюдера пуст. Пожалуйста, нарисуйте полигон." +"Заслоняющий полигон для этого окклюдера пуст. Пожалуйста, добавьте полигон." #: scene/2d/navigation_polygon.cpp msgid "" diff --git a/editor/translations/si.po b/editor/translations/si.po index 4d252a53d6..141696c00a 100644 --- a/editor/translations/si.po +++ b/editor/translations/si.po @@ -756,6 +756,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sk.po b/editor/translations/sk.po index a341552d1c..0920487af3 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -756,6 +756,11 @@ msgid "Method in target node must be specified." msgstr "Metóda v target node-e musí byť špecifikovaná." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metóda v target node-e musí byť špecifikovaná." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sl.po b/editor/translations/sl.po index faec304f67..114dce1e63 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -799,6 +799,11 @@ msgstr "Metoda v ciljnem gradniku mora biti navedena!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Ime ni pravilen identifikator:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sq.po b/editor/translations/sq.po index 5bcf15eb82..32d08c7bc9 100644 --- a/editor/translations/sq.po +++ b/editor/translations/sq.po @@ -744,6 +744,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index 4e7064f00c..01d8c4ca91 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -841,6 +841,11 @@ msgstr "Метода у циљаном чвору мора бити наведе #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Име није важећи идентификатор:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index e62d152c45..fe13877f42 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -765,6 +765,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sv.po b/editor/translations/sv.po index e316c74160..ddd0188d5d 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -772,6 +772,11 @@ msgstr "Metod i Mål-Node måste specificeras!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metod i Mål-Node måste specificeras!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ta.po b/editor/translations/ta.po index b8ea8d3538..8f161acfc9 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -757,6 +757,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/te.po b/editor/translations/te.po index 589064278d..87fb947dd0 100644 --- a/editor/translations/te.po +++ b/editor/translations/te.po @@ -736,6 +736,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/th.po b/editor/translations/th.po index db7fd6adea..3af6fde5a0 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -744,6 +744,11 @@ msgid "Method in target node must be specified." msgstr "ต้องระบุเมธอดในโหนดเป้าหมาย" #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "ไม่สามารถใช้ชื่อนี้ได้:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/tr.po b/editor/translations/tr.po index 277cc2c807..27886e1d4d 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -798,6 +798,11 @@ msgid "Method in target node must be specified." msgstr "Hedef düğümdeki metod tanımlanmalı." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Ad doğru bir belirleyici değil:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/uk.po b/editor/translations/uk.po index 75cce04e0e..03990a655e 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -18,7 +18,7 @@ msgid "" msgstr "" "Project-Id-Version: Ukrainian (Godot Engine)\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/" "godot/uk/>\n" @@ -28,7 +28,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -773,6 +773,10 @@ msgid "Method in target node must be specified." msgstr "Має бути вказано метод у цільовому вузлі." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "Назва методу має бути коректним ідентифікатором." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1976,7 +1980,7 @@ msgstr "Властивості теми" #: editor/editor_help.cpp msgid "Enumerations" -msgstr "Перелічуваний" +msgstr "Переліки" #: editor/editor_help.cpp msgid "Constants" diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index 10558ad98e..6985cbdc39 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -746,6 +746,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/vi.po b/editor/translations/vi.po index fe846d5e08..ff214a7091 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -763,6 +763,11 @@ msgid "Method in target node must be specified." msgstr "Phương thức trong nút đích phải được chỉ định." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Phương thức trong nút đích phải được chỉ định." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index 5dc2b5948f..f9dc64aea2 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -64,12 +64,14 @@ # binotaliu <binota@protonmail.ch>, 2020. # BinotaLIU <binota@protonmail.ch>, 2020. # Tim Bao <honiebao@gmail.com>, 2020. +# UnluckyNinja <unluckyninja1994@gmail.com>, 2020. +# 无双流 <1257678024@qq.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Chinese (Simplified) (Godot Engine)\n" "POT-Creation-Date: 2018-01-20 12:15+0200\n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" -"Last-Translator: Tim Bao <honiebao@gmail.com>\n" +"PO-Revision-Date: 2020-06-25 08:40+0000\n" +"Last-Translator: UnluckyNinja <unluckyninja1994@gmail.com>\n" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hans/>\n" "Language: zh_CN\n" @@ -77,7 +79,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -806,6 +808,10 @@ msgid "Method in target node must be specified." msgstr "必须指定目标节点的方法。" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "方法名称必须是一个有效的标识符。" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -2438,6 +2444,8 @@ msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"当前场景有未保存的更改。\n" +"是否重新加载保存的场景? 此操作无法撤消。" #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -2655,7 +2663,7 @@ msgstr "下一个标签页" #: editor/editor_node.cpp msgid "Previous tab" -msgstr "上一个标签页" +msgstr "上一个标签" #: editor/editor_node.cpp msgid "Filter Files..." @@ -2855,7 +2863,7 @@ msgstr "编辑器布局" #: editor/editor_node.cpp msgid "Take Screenshot" -msgstr "截取屏幕" +msgstr "截屏" #: editor/editor_node.cpp msgid "Screenshots are stored in the Editor Data/Settings Folder." @@ -3339,9 +3347,8 @@ msgid "Did you forget the '_run' method?" msgstr "您是否遗漏了_run()方法?" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." -msgstr "按住Ctrl键放置一个Getter节点。按住Shift键放置一个通用签名。" +msgstr "按住Ctrl键来四舍五入至整数。 按住Shift键获取更精确的变化。" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -3932,7 +3939,7 @@ msgstr "后处理脚本运行发生错误:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "你是否在 `post_import()` 方法中返回了 Node 衍生对象?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -6652,7 +6659,7 @@ msgstr "查找下一项" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find Previous" -msgstr "查找上一项" +msgstr "查找上一个" #: editor/plugins/script_editor_plugin.cpp msgid "Filter scripts" @@ -6844,9 +6851,8 @@ msgid "" msgstr "未找到方法“%s”(连接于信号“%s”、来自节点“%s”、目标节点“%s”)。" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(忽略)" +msgstr "[忽略]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -6935,7 +6941,7 @@ msgstr "切换注释" #: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" -msgstr "折叠/展开当前行" +msgstr "折叠/展开行" #: editor/plugins/script_text_editor.cpp msgid "Fold All Lines" @@ -6951,7 +6957,7 @@ msgstr "拷贝到下一行" #: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" -msgstr "代码补全" +msgstr "符号自动补全" #: editor/plugins/script_text_editor.cpp msgid "Evaluate Selection" @@ -6959,7 +6965,7 @@ msgstr "所选内容求值" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" -msgstr "修剪行后空白" +msgstr "移除尾部空格" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent to Spaces" @@ -7276,27 +7282,27 @@ msgstr "使用GLES2渲染器时不可用。" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Left" -msgstr "自由视图 左" +msgstr "自由观看向左" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Right" -msgstr "自由视图 右" +msgstr "自由观看向右" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Forward" -msgstr "自由视图 前" +msgstr "自由观看向前" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Backwards" -msgstr "自由视图 后" +msgstr "自由观看向后" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Up" -msgstr "自由视图 上" +msgstr "自由观看向上" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Down" -msgstr "自由视图 下" +msgstr "自由观看向下" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Speed Modifier" @@ -7330,6 +7336,11 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"点击以切换可见状态。\n" +"\n" +"睁眼:标志可见。\n" +"闭眼:标志隐藏。\n" +"半睁眼:标志也可穿过不透明的表面可见(“X光”)。" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7359,11 +7370,11 @@ msgstr "使用吸附" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" -msgstr "底视图" +msgstr "仰视图。" #: editor/plugins/spatial_editor_plugin.cpp msgid "Top View" -msgstr "顶视图" +msgstr "俯视" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rear View" @@ -7371,7 +7382,7 @@ msgstr "后视图" #: editor/plugins/spatial_editor_plugin.cpp msgid "Front View" -msgstr "前视图" +msgstr "正视图" #: editor/plugins/spatial_editor_plugin.cpp msgid "Left View" @@ -7383,7 +7394,7 @@ msgstr "右视图" #: editor/plugins/spatial_editor_plugin.cpp msgid "Switch Perspective/Orthogonal View" -msgstr "切换投影/正交视图" +msgstr "切换透视图/正交视图" #: editor/plugins/spatial_editor_plugin.cpp msgid "Insert Animation Key" @@ -7399,7 +7410,7 @@ msgstr "聚焦选中项" #: editor/plugins/spatial_editor_plugin.cpp msgid "Toggle Freelook" -msgstr "切换自由观察模式" +msgstr "切换自由观看" #: editor/plugins/spatial_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp @@ -7408,7 +7419,7 @@ msgstr "变换" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Object to Floor" -msgstr "将对象吸附到地板" +msgstr "吸附物体到地面" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog..." @@ -10354,9 +10365,8 @@ msgid "Instance Child Scene" msgstr "实例化子场景" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "添加脚本" +msgstr "分离脚本" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10519,6 +10529,8 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"无法附加脚本:没有语言被注册。\n" +"这可能是因为这个编辑器是在所有语言模块被关闭的状态下被构建的。" #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10567,14 +10579,12 @@ msgid "" msgstr "实例化场景文件为一个节点,如果没有根节点则创建一个继承自该文件的场景。" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." msgstr "为选中节点创建或设置脚本。" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "清除选中节点的脚本。" +msgstr "从选中节点分离脚本。" #: editor/scene_tree_dock.cpp msgid "Remote" @@ -11780,9 +11790,8 @@ msgid "Debug keystore not configured in the Editor Settings nor in the preset." msgstr "未在编辑器设置或预设中配置调试密钥库。" #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." -msgstr "未在编辑器设置或预设中配置调试密钥库。" +msgstr "用于发布的密钥存储在导出预设中未被正确设置。" #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." @@ -11811,26 +11820,28 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"“android/modules”项目设置(变更于Godot 3.2.2)中包含了无效模" +"组“GodotPaymentV3”.\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "必须启用“使用自定义构建”才能使用插件。" #: platform/android/export/export.cpp msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." -msgstr "" +msgstr "“自由度”只有在当“Xr Mode”是“Oculus Mobile VR”时才有效。" #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." -msgstr "" +msgstr "“手部追踪”只有在当“Xr Mode”是“Oculus Mobile VR”时才有效。" #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." -msgstr "" +msgstr "“焦点感知”只有在当“Xr Mode”是“Oculus Mobile VR”时才有效。" #: platform/android/export/export.cpp msgid "" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index 4832307ce5..90c85892f6 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -793,6 +793,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index 22051058ad..129a3fdad4 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -28,7 +28,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" "Last-Translator: BinotaLIU <me@binota.org>\n" "Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hant/>\n" @@ -37,7 +37,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -766,6 +766,11 @@ msgid "Method in target node must be specified." msgstr "必須指定目標節點的方法。" #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "名稱不是一個有效的識別符:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -9880,7 +9885,7 @@ msgstr "新增事件" #: editor/project_settings_editor.cpp msgid "Button" -msgstr "Button(按鈕)" +msgstr "Button (按鈕)" #: editor/project_settings_editor.cpp msgid "Left Button." |