diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_node.cpp | 14 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 22 | ||||
-rw-r--r-- | editor/import/resource_importer_texture.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_map_editor.cpp | 4 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_set_atlas_source_editor.cpp | 1 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_set_editor.cpp | 57 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_set_editor.h | 21 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp | 2 | ||||
-rw-r--r-- | editor/pot_generator.cpp | 56 |
9 files changed, 141 insertions, 38 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 074dd2ffe0..a58e17724b 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -322,7 +322,7 @@ void EditorNode::_update_scene_tabs() { scene_tabs->set_current_tab(editor_data.get_edited_scene()); } - const Size2 add_button_size = Size2(0, scene_tabs->get_size().y); + const Size2 add_button_size = Size2(scene_tab_add->get_size().x, scene_tabs->get_size().y); if (scene_tabs->get_offset_buttons_visible()) { // Move the add button to a fixed position. if (scene_tab_add->get_parent() == scene_tabs) { @@ -345,7 +345,7 @@ void EditorNode::_update_scene_tabs() { Rect2 last_tab = scene_tabs->get_tab_rect(scene_tabs->get_tab_count() - 1); int hsep = scene_tabs->get_theme_constant(SNAME("h_separation")); if (scene_tabs->is_layout_rtl()) { - scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x - scene_tab_add->get_size().x - hsep, last_tab.position.y), add_button_size)); + scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x - add_button_size.x - hsep, last_tab.position.y), add_button_size)); } else { scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x + last_tab.size.width + hsep, last_tab.position.y), add_button_size)); } @@ -5680,11 +5680,17 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { if (mb->get_button_index() == MouseButton::MIDDLE && mb->is_pressed()) { _scene_tab_closed(scene_tabs->get_hovered_tab()); } - } else { - if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) { + } else if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) { + int tab_buttons = 0; + if (scene_tabs->get_offset_buttons_visible()) { + tab_buttons = theme->get_icon(SNAME("increment"), SNAME("TabBar"))->get_width() + theme->get_icon(SNAME("decrement"), SNAME("TabBar"))->get_width(); + } + + if ((gui_base->is_layout_rtl() && mb->get_position().x > tab_buttons) || (!gui_base->is_layout_rtl() && mb->get_position().x < scene_tabs->get_size().width - tab_buttons)) { _menu_option_confirm(FILE_NEW_SCENE, true); } } + if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { // Context menu. scene_tabs_context_menu->clear(); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 677b2e78bd..48fc20adf0 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1248,6 +1248,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< col->set_owner(p_node->get_owner()); col->set_transform(get_collision_shapes_transform(node_settings)); col->set_position(p_applied_root_scale * col->get_position()); + const Ref<PhysicsMaterial> &pmo = node_settings["physics/physics_material_override"]; + if (!pmo.is_null()) { + col->set_physics_material_override(pmo); + } base = col; } break; case MESH_PHYSICS_RIGID_BODY_AND_MESH: { @@ -1260,6 +1264,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< mi->set_transform(Transform3D()); rigid_body->add_child(mi, true); mi->set_owner(rigid_body->get_owner()); + const Ref<PhysicsMaterial> &pmo = node_settings["physics/physics_material_override"]; + if (!pmo.is_null()) { + rigid_body->set_physics_material_override(pmo); + } base = rigid_body; } break; case MESH_PHYSICS_STATIC_COLLIDER_ONLY: { @@ -1271,6 +1279,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< p_node->set_owner(nullptr); memdelete(p_node); p_node = col; + const Ref<PhysicsMaterial> &pmo = node_settings["physics/physics_material_override"]; + if (!pmo.is_null()) { + col->set_physics_material_override(pmo); + } base = col; } break; case MESH_PHYSICS_AREA_ONLY: { @@ -1287,6 +1299,9 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< } break; } + base->set_collision_layer(node_settings["physics/layer"]); + base->set_collision_mask(node_settings["physics/mask"]); + for (const Ref<Shape3D> &E : shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E); @@ -1605,6 +1620,9 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/navmesh", PROPERTY_HINT_ENUM, "Disabled,Mesh + NavMesh,NavMesh Only"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/body_type", PROPERTY_HINT_ENUM, "Static,Dynamic,Area"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/shape_type", PROPERTY_HINT_ENUM, "Decompose Convex,Simple Convex,Trimesh,Box,Sphere,Cylinder,Capsule", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "physics/physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), Variant())); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), 1)); // Decomposition Ref<MeshConvexDecompositionSettings> decomposition_default = Ref<MeshConvexDecompositionSettings>(); @@ -1703,9 +1721,7 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor p_options.has("generate/physics") && p_options["generate/physics"].operator bool(); - if ( - p_option == "physics/body_type" || - p_option == "physics/shape_type") { + if (p_option.find("physics/") >= 0) { // Show if need to generate collisions. return generate_physics; } diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 57139a511f..114ba5653a 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -418,7 +418,7 @@ void ResourceImporterTexture::_save_editor_meta(const Dictionary &p_metadata, co Dictionary ResourceImporterTexture::_load_editor_meta(const String &p_path) const { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V_MSG(f.is_null(), Dictionary(), "Missing required editor-specific import metadata for a texture; please, reimport."); + ERR_FAIL_COND_V_MSG(f.is_null(), Dictionary(), vformat("Missing required editor-specific import metadata for a texture (please reimport it using the 'Import' tab): '%s'", p_path)); return f->get_var(); } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 31e4692de9..8b58a45ea5 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -156,7 +156,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { // Common to all type of sources. if (!source->get_name().is_empty()) { - item_text = vformat(TTR("%s (ID: %d)"), source->get_name(), source_id); + item_text = source->get_name(); } // Atlas source. @@ -165,7 +165,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { texture = atlas_source->get_texture(); if (item_text.is_empty()) { if (texture.is_valid()) { - item_text = vformat(TTR("%s (ID: %d)"), texture->get_path().get_file(), source_id); + item_text = texture->get_path().get_file(); } else { item_text = vformat(TTR("No Texture Atlas Source (ID: %d)"), source_id); } diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 61d57e5eab..c98d9086d1 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -2529,6 +2529,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { atlas_source_inspector = memnew(EditorInspector); atlas_source_inspector->set_v_size_flags(SIZE_EXPAND_FILL); atlas_source_inspector->set_show_categories(true); + atlas_source_inspector->add_inspector_plugin(memnew(TileSourceInspectorPlugin)); atlas_source_inspector->edit(atlas_source_proxy_object); middle_vbox_container->add_child(atlas_source_inspector); diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index eb79394cc9..f620e434ab 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -34,6 +34,7 @@ #include "tiles_editor_plugin.h" #include "editor/editor_file_system.h" +#include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -42,6 +43,7 @@ #include "scene/gui/box_container.h" #include "scene/gui/control.h" +#include "scene/gui/dialogs.h" #include "scene/gui/tab_container.h" TileSetEditor *TileSetEditor::singleton = nullptr; @@ -158,7 +160,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) { // Common to all type of sources. if (!source->get_name().is_empty()) { - item_text = vformat(TTR("%s (ID: %d)"), source->get_name(), source_id); + item_text = source->get_name(); } // Atlas source. @@ -167,7 +169,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) { texture = atlas_source->get_texture(); if (item_text.is_empty()) { if (texture.is_valid()) { - item_text = vformat(TTR("%s (ID: %d)"), texture->get_path().get_file(), source_id); + item_text = texture->get_path().get_file(); } else { item_text = vformat(TTR("No Texture Atlas Source (ID: %d)"), source_id); } @@ -964,3 +966,54 @@ TileSetEditor::TileSetEditor() { EditorNode::get_singleton()->get_editor_data().add_move_array_element_function(SNAME("TileSet"), callable_mp(this, &TileSetEditor::_move_tile_set_array_element)); EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetEditor::_undo_redo_inspector_callback)); } + +void TileSourceInspectorPlugin::_show_id_edit_dialog(Object *p_for_source) { + if (!id_edit_dialog) { + id_edit_dialog = memnew(ConfirmationDialog); + TileSetEditor::get_singleton()->add_child(id_edit_dialog); + + VBoxContainer *vbox = memnew(VBoxContainer); + id_edit_dialog->add_child(vbox); + + Label *label = memnew(Label(TTR("Warning: Modifying a source ID will result in all TileMaps using that source to reference an invalid source instead. This may result in unexpected data loss. Change this ID carefully."))); + label->set_autowrap_mode(TextServer::AUTOWRAP_WORD); + vbox->add_child(label); + + id_input = memnew(SpinBox); + vbox->add_child(id_input); + id_input->set_max(INT_MAX); + + id_edit_dialog->connect("confirmed", callable_mp(this, &TileSourceInspectorPlugin::_confirm_change_id)); + } + edited_source = p_for_source; + id_input->set_value(p_for_source->get("id")); + id_edit_dialog->popup_centered(Vector2i(400, 0) * EDSCALE); + callable_mp((Control *)id_input->get_line_edit(), &Control::grab_focus).call_deferred(); +} + +void TileSourceInspectorPlugin::_confirm_change_id() { + edited_source->set("id", id_input->get_value()); + id_label->set_text(vformat(TTR("ID: %d"), edited_source->get("id"))); // Use get(), because the provided ID might've been invalid. +} + +bool TileSourceInspectorPlugin::can_handle(Object *p_object) { + return p_object->is_class("TileSetAtlasSourceProxyObject") || p_object->is_class("TileSetScenesCollectionProxyObject"); +} + +bool TileSourceInspectorPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { + if (p_path == "id") { + HBoxContainer *hbox = memnew(HBoxContainer); + hbox->set_alignment(BoxContainer::ALIGNMENT_CENTER); + + id_label = memnew(Label(vformat(TTR("ID: %d"), p_object->get("id")))); + hbox->add_child(id_label); + + Button *button = memnew(Button(TTR("Edit"))); + hbox->add_child(button); + button->connect("pressed", callable_mp(this, &TileSourceInspectorPlugin::_show_id_edit_dialog).bind(p_object)); + + add_custom_control(hbox); + return true; + } + return false; +} diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h index 40ca1f7ed7..86cd70d19e 100644 --- a/editor/plugins/tiles/tile_set_editor.h +++ b/editor/plugins/tiles/tile_set_editor.h @@ -38,9 +38,12 @@ #include "tile_set_atlas_source_editor.h" #include "tile_set_scenes_collection_source_editor.h" -class EditorFileDialog; +class AcceptDialog; +class SpinBox; class HBoxContainer; class SplitContainer; +class EditorFileDialog; +class EditorInspectorPlugin; class TileSetEditor : public Control { GDCLASS(TileSetEditor, Control); @@ -123,4 +126,20 @@ public: TileSetEditor(); }; +class TileSourceInspectorPlugin : public EditorInspectorPlugin { + GDCLASS(TileSourceInspectorPlugin, EditorInspectorPlugin); + + AcceptDialog *id_edit_dialog = nullptr; + Label *id_label = nullptr; + SpinBox *id_input = nullptr; + Object *edited_source = nullptr; + + void _show_id_edit_dialog(Object *p_for_source); + void _confirm_change_id(); + +public: + virtual bool can_handle(Object *p_object) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; +}; + #endif // TILE_SET_EDITOR_H diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index 5ffa7b4bd4..13270f3821 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -36,6 +36,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/plugins/tiles/tile_set_editor.h" #include "scene/gui/button.h" #include "scene/gui/item_list.h" @@ -504,6 +505,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { scenes_collection_source_inspector = memnew(EditorInspector); scenes_collection_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); + scenes_collection_source_inspector->add_inspector_plugin(memnew(TileSourceInspectorPlugin)); scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object); middle_vbox_container->add_child(scenes_collection_source_inspector); diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp index 9428d29088..ec044ee06e 100644 --- a/editor/pot_generator.cpp +++ b/editor/pot_generator.cpp @@ -99,25 +99,27 @@ void POTGenerator::_write_to_pot(const String &p_file) { return; } - String project_name = GLOBAL_GET("application/config/name"); + String project_name = GLOBAL_GET("application/config/name").operator String().replace("\n", "\\n"); Vector<String> files = GLOBAL_GET("internationalization/locale/translations_pot_files"); String extracted_files = ""; for (int i = 0; i < files.size(); i++) { - extracted_files += "# " + files[i] + "\n"; + extracted_files += "# " + files[i].replace("\n", "\\n") + "\n"; } const String header = - "# LANGUAGE translation for " + project_name + " for the following files:\n" + extracted_files + + "# LANGUAGE translation for " + project_name + " for the following files:\n" + + extracted_files + "#\n" - "# FIRST AUTHOR < EMAIL @ADDRESS>, YEAR.\n" + "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n" "#\n" "#, fuzzy\n" "msgid \"\"\n" "msgstr \"\"\n" "\"Project-Id-Version: " + - project_name + "\\n\"\n" - "\"MIME-Version: 1.0\\n\"\n" - "\"Content-Type: text/plain; charset=UTF-8\\n\"\n" - "\"Content-Transfer-Encoding: 8-bit\\n\"\n"; + project_name + + "\\n\"\n" + "\"MIME-Version: 1.0\\n\"\n" + "\"Content-Type: text/plain; charset=UTF-8\\n\"\n" + "\"Content-Transfer-Encoding: 8-bit\\n\"\n"; file->store_string(header); @@ -134,12 +136,12 @@ void POTGenerator::_write_to_pot(const String &p_file) { // Write file locations. for (const String &E : locations) { - file->store_line("#: " + E.trim_prefix("res://")); + file->store_line("#: " + E.trim_prefix("res://").replace("\n", "\\n")); } // Write context. if (!context.is_empty()) { - file->store_line("msgctxt \"" + context + "\""); + file->store_line("msgctxt " + context.c_escape().quote()); } // Write msgid. @@ -158,30 +160,34 @@ void POTGenerator::_write_to_pot(const String &p_file) { } void POTGenerator::_write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural) { - // Split \\n and \n. - Vector<String> msg_lines; - Vector<String> temp = p_id.split("\\n"); - for (int i = 0; i < temp.size(); i++) { - msg_lines.append_array(temp[i].split("\n")); - } - - // Add \n. - for (int i = 0; i < msg_lines.size() - 1; i++) { - msg_lines.set(i, msg_lines[i] + "\\n"); - } - if (p_plural) { r_file->store_string("msgid_plural "); } else { r_file->store_string("msgid "); } - if (msg_lines.size() > 1) { + if (p_id.is_empty()) { + r_file->store_line("\"\""); + return; + } + + const Vector<String> lines = p_id.split("\n"); + const String &last_line = lines[lines.size() - 1]; // `lines` cannot be empty. + int pot_line_count = lines.size(); + if (last_line.is_empty()) { + pot_line_count--; + } + + if (pot_line_count > 1) { r_file->store_line("\"\""); } - for (int i = 0; i < msg_lines.size(); i++) { - r_file->store_line("\"" + msg_lines[i] + "\""); + for (int i = 0; i < lines.size() - 1; i++) { + r_file->store_line((lines[i] + "\n").c_escape().quote()); + } + + if (!last_line.is_empty()) { + r_file->store_line(last_line.c_escape().quote()); } } |