diff options
author | Gilles Roudière <gilles.roudiere@gmail.com> | 2024-03-05 13:55:23 +0100 |
---|---|---|
committer | Gilles Roudière <gilles.roudiere@gmail.com> | 2024-04-03 11:02:34 +0200 |
commit | 3cd4b2859c9d715459325b070643773b47472324 (patch) | |
tree | 694a929eaff4f7a12b860c955f4f68a0d5c7b66c /editor | |
parent | 7d151c83811f8ac8873439826c16d88c83aba12f (diff) | |
download | redot-engine-3cd4b2859c9d715459325b070643773b47472324.tar.gz |
Expose TileMapLayer
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_node.cpp | 4 | ||||
-rw-r--r-- | editor/editor_settings.cpp | 1 | ||||
-rw-r--r-- | editor/icons/TileMapLayer.svg | 2 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_map_layer_editor.cpp | 586 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_map_layer_editor.h | 32 | ||||
-rw-r--r-- | editor/plugins/tiles/tiles_editor_plugin.cpp | 98 | ||||
-rw-r--r-- | editor/plugins/tiles/tiles_editor_plugin.h | 4 |
7 files changed, 484 insertions, 243 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index edb6fee75c..03e8f3ac84 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2506,8 +2506,8 @@ void EditorNode::_edit_current(bool p_skip_foreign, bool p_skip_inspector_update editable_info, info_is_warning); - Object *editor_owner = is_node ? (Object *)SceneTreeDock::get_singleton() : is_resource ? (Object *)InspectorDock::get_inspector_singleton() - : (Object *)this; + Object *editor_owner = (is_node || current_obj->is_class("MultiNodeEdit")) ? (Object *)SceneTreeDock::get_singleton() : is_resource ? (Object *)InspectorDock::get_inspector_singleton() + : (Object *)this; // Take care of the main editor plugin. diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index ee33e171e3..89580b83b0 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -755,6 +755,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Tiles editor _initial_set("editors/tiles_editor/display_grid", true); + _initial_set("editors/tiles_editor/highlight_selected_layer", true); _initial_set("editors/tiles_editor/grid_color", Color(1.0, 0.5, 0.2, 0.5)); // Polygon editor diff --git a/editor/icons/TileMapLayer.svg b/editor/icons/TileMapLayer.svg index 1903a87e3b..90664dee03 100644 --- a/editor/icons/TileMapLayer.svg +++ b/editor/icons/TileMapLayer.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 7v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#8da5f3"/></svg>
\ No newline at end of file +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M8 2 6.25 3.375 8 4.75l1.75-1.375zm2.624 2.062-1.75 1.375 1.75 1.375 1.75-1.375Zm2.626 2.063L11.5 7.5l1.75 1.375L15 7.5ZM5.376 4.062l-1.75 1.375 1.75 1.375 1.75-1.375zM8 6.124 6.25 7.499 8 8.874l1.75-1.375zm2.626 2.063-1.75 1.375 1.75 1.375 1.75-1.375ZM2.75 6.125 1 7.5l1.75 1.375L4.5 7.5Zm2.624 2.062-1.75 1.375 1.75 1.375 1.75-1.375ZM8 10.25l-1.75 1.375L8 13l1.75-1.375z" fill="#8da5f3"/></svg>
\ No newline at end of file diff --git a/editor/plugins/tiles/tile_map_layer_editor.cpp b/editor/plugins/tiles/tile_map_layer_editor.cpp index ccadc0643b..ac4708aa06 100644 --- a/editor/plugins/tiles/tile_map_layer_editor.cpp +++ b/editor/plugins/tiles/tile_map_layer_editor.cpp @@ -36,9 +36,9 @@ #include "editor/editor_resource_preview.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/multi_node_edit.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/themes/editor_scale.h" - #include "scene/2d/camera_2d.h" #include "scene/2d/tile_map_layer.h" #include "scene/gui/center_container.h" @@ -107,7 +107,7 @@ void TileMapLayerEditorTilesPlugin::_update_transform_buttons() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null() || selection_pattern.is_null()) { return; } @@ -171,7 +171,7 @@ void TileMapLayerEditorTilesPlugin::_update_tile_set_sources_list() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -256,7 +256,7 @@ void TileMapLayerEditorTilesPlugin::_update_source_display() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -302,7 +302,7 @@ void TileMapLayerEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<Inpu return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -348,7 +348,7 @@ void TileMapLayerEditorTilesPlugin::_update_patterns_list() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -380,7 +380,7 @@ void TileMapLayerEditorTilesPlugin::_update_atlas_view() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -401,7 +401,7 @@ void TileMapLayerEditorTilesPlugin::_update_scenes_collection_view() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -459,7 +459,7 @@ void TileMapLayerEditorTilesPlugin::_scenes_list_multi_selected(int p_index, boo return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -538,7 +538,7 @@ bool TileMapLayerEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEven return false; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return false; } @@ -784,7 +784,7 @@ void TileMapLayerEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -1021,7 +1021,7 @@ TileMapCell TileMapLayerEditorTilesPlugin::_pick_random_tile(Ref<TileMapPattern> return TileMapCell(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return TileMapCell(); } @@ -1073,7 +1073,7 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_line(Vector2 return HashMap<Vector2i, TileMapCell>(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return HashMap<Vector2i, TileMapCell>(); } @@ -1122,7 +1122,7 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_rect(Vector2 return HashMap<Vector2i, TileMapCell>(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return HashMap<Vector2i, TileMapCell>(); } @@ -1181,7 +1181,7 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_bucket_fill( return HashMap<Vector2i, TileMapCell>(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return HashMap<Vector2i, TileMapCell>(); } @@ -1293,7 +1293,7 @@ void TileMapLayerEditorTilesPlugin::_stop_dragging() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -1601,7 +1601,7 @@ void TileMapLayerEditorTilesPlugin::_update_fix_selected_and_hovered() { selection_pattern.instantiate(); return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { hovered_tile.source_id = TileSet::INVALID_SOURCE; hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); @@ -1688,7 +1688,7 @@ void TileMapLayerEditorTilesPlugin::_update_selection_pattern_from_tilemap_selec return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -1709,7 +1709,7 @@ void TileMapLayerEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -1783,7 +1783,7 @@ void TileMapLayerEditorTilesPlugin::_update_selection_pattern_from_tileset_patte return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -1822,7 +1822,7 @@ void TileMapLayerEditorTilesPlugin::_tile_atlas_control_draw() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -1901,7 +1901,7 @@ void TileMapLayerEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<Inpu return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -2007,7 +2007,7 @@ void TileMapLayerEditorTilesPlugin::_tile_alternatives_control_draw() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -2059,7 +2059,7 @@ void TileMapLayerEditorTilesPlugin::_tile_alternatives_control_gui_input(const R return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -2157,16 +2157,21 @@ void TileMapLayerEditorTilesPlugin::edit(ObjectID p_tile_map_layer_id) { // Disable sort button if the tileset is read-only TileMapLayer *edited_layer = _get_edited_layer(); + Ref<TileSet> tile_set; if (edited_layer) { - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + tile_set = edited_layer->get_tile_set(); if (tile_set.is_valid()) { source_sort_button->set_disabled(EditorNode::get_singleton()->is_resource_read_only(tile_set)); } } - if (edited_tile_map_layer_id != p_tile_map_layer_id) { - edited_tile_map_layer_id = p_tile_map_layer_id; + TileMapLayer *new_tile_map_layer = Object::cast_to<TileMapLayer>(ObjectDB::get_instance(edited_tile_map_layer_id)); + Ref<TileSet> new_tile_set; + if (new_tile_map_layer) { + new_tile_set = new_tile_map_layer->get_tile_set(); + } + if (tile_set.is_valid() && tile_set != new_tile_set) { // Clear the selection. tile_set_selection.clear(); patterns_item_list->deselect_all(); @@ -2531,7 +2536,7 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_terrain_p return HashMap<Vector2i, TileMapCell>(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return HashMap<Vector2i, TileMapCell>(); } @@ -2583,7 +2588,7 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_terrain_p return HashMap<Vector2i, TileMapCell>(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return HashMap<Vector2i, TileMapCell>(); } @@ -2630,7 +2635,7 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_line(Vect return HashMap<Vector2i, TileMapCell>(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return HashMap<Vector2i, TileMapCell>(); } @@ -2654,7 +2659,7 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_rect(Vect return HashMap<Vector2i, TileMapCell>(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return HashMap<Vector2i, TileMapCell>(); } @@ -2688,7 +2693,7 @@ RBSet<Vector2i> TileMapLayerEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vec return RBSet<Vector2i>(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return RBSet<Vector2i>(); } @@ -2799,7 +2804,7 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_bucket_fi return HashMap<Vector2i, TileMapCell>(); } - const Ref<TileSet> &tile_set = edited_layer->get_effective_tile_set(); + const Ref<TileSet> &tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return HashMap<Vector2i, TileMapCell>(); } @@ -2827,7 +2832,7 @@ void TileMapLayerEditorTerrainsPlugin::_stop_dragging() { return; } - const Ref<TileSet> &tile_set = edited_layer->get_effective_tile_set(); + const Ref<TileSet> &tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -2961,7 +2966,7 @@ void TileMapLayerEditorTerrainsPlugin::_update_selection() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -3013,7 +3018,7 @@ bool TileMapLayerEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputE return false; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return false; } @@ -3150,7 +3155,7 @@ void TileMapLayerEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -3275,7 +3280,7 @@ void TileMapLayerEditorTerrainsPlugin::_update_terrains_cache() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -3342,7 +3347,7 @@ void TileMapLayerEditorTerrainsPlugin::_update_terrains_tree() { const TileMapLayer *edited_layer = _get_edited_layer(); ERR_FAIL_NULL(edited_layer); - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -3389,7 +3394,7 @@ void TileMapLayerEditorTerrainsPlugin::_update_tiles_list() { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -3627,57 +3632,258 @@ TileMapLayer *TileMapLayerEditor::_get_edited_layer() const { return Object::cast_to<TileMapLayer>(ObjectDB::get_instance(edited_tile_map_layer_id)); } +void TileMapLayerEditor::_find_tile_map_layers_in_scene(Node *p_current, const Node *p_owner, Vector<TileMapLayer *> &r_list) const { + ERR_FAIL_COND(!p_current || !p_owner); + if (p_current != p_owner && p_current->get_owner() != p_owner) { + return; + } + TileMapLayer *layer = Object::cast_to<TileMapLayer>(p_current); + if (layer) { + r_list.append(layer); + } + for (int i = 0; i < p_current->get_child_count(); i++) { + Node *child = p_current->get_child(i); + _find_tile_map_layers_in_scene(child, p_owner, r_list); + } +} + +void TileMapLayerEditor::_update_tile_map_layers_in_scene_list_cache() { + if (!layers_in_scene_list_cache_needs_update) { + return; + } + EditorNode *en = EditorNode::get_singleton(); + Node *edited_scene_root = en->get_edited_scene(); + if (!edited_scene_root) { + return; + } + + tile_map_layers_in_scene_cache.clear(); + _find_tile_map_layers_in_scene(edited_scene_root, edited_scene_root, tile_map_layers_in_scene_cache); + layers_in_scene_list_cache_needs_update = false; +} + +void TileMapLayerEditor::_node_change(Node *p_node) { + if (!layers_in_scene_list_cache_needs_update && p_node->is_part_of_edited_scene() && Object::cast_to<TileMapLayer>(p_node)) { + layers_in_scene_list_cache_needs_update = true; + } +} + void TileMapLayerEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_READY: { + get_tree()->connect("node_added", callable_mp(this, &TileMapLayerEditor::_node_change)); + get_tree()->connect("node_removed", callable_mp(this, &TileMapLayerEditor::_node_change)); + } break; case NOTIFICATION_THEME_CHANGED: { missing_tile_texture = get_editor_theme_icon(SNAME("StatusWarning")); warning_pattern_texture = get_editor_theme_icon(SNAME("WarningPattern")); advanced_menu_button->set_icon(get_editor_theme_icon(SNAME("Tools"))); + select_previous_layer->set_icon(get_editor_theme_icon(SNAME("MoveUp"))); + select_next_layer->set_icon(get_editor_theme_icon(SNAME("MoveDown"))); + select_all_layers->set_icon(get_editor_theme_icon(SNAME("FileList"))); toggle_grid_button->set_icon(get_editor_theme_icon(SNAME("Grid"))); - toggle_grid_button->set_pressed(EDITOR_GET("editors/tiles_editor/display_grid")); toggle_highlight_selected_layer_button->set_icon(get_editor_theme_icon(SNAME("TileMapHighlightSelected"))); } break; case NOTIFICATION_INTERNAL_PROCESS: { - if (is_visible_in_tree() && tileset_changed_needs_update) { + if (is_visible_in_tree() && tile_map_layer_changed_needs_update) { _update_bottom_panel(); - update_layers_selector(); - _update_highlighting_toggle(); + _update_layers_selector(); tabs_plugins[tabs_bar->get_current_tab()]->tile_set_changed(); CanvasItemEditor::get_singleton()->update_viewport(); - tileset_changed_needs_update = false; + tile_map_layer_changed_needs_update = false; } } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/tiles_editor")) { toggle_grid_button->set_pressed_no_signal(EDITOR_GET("editors/tiles_editor/display_grid")); + toggle_highlight_selected_layer_button->set_pressed_no_signal(EDITOR_GET("editors/tiles_editor/highlight_selected_layer")); } } break; } } -void TileMapLayerEditor::_bind_methods() { - ADD_SIGNAL(MethodInfo("change_selected_layer_request", PropertyInfo(Variant::STRING_NAME, "layer_name"))); -} - void TileMapLayerEditor::_on_grid_toggled(bool p_pressed) { EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed); CanvasItemEditor::get_singleton()->update_viewport(); } -void TileMapLayerEditor::_layers_selection_item_selected(int p_index) { - emit_signal("change_selected_layer_request", layers_selection_button->get_item_metadata(p_index)); +void TileMapLayerEditor::_select_previous_layer_pressed() { + _layers_select_next_or_previous(false); } -void TileMapLayerEditor::_highlight_selected_layer_button_toggled(bool p_pressed) { +void TileMapLayerEditor::_select_next_layer_pressed() { + _layers_select_next_or_previous(true); +} + +void TileMapLayerEditor::_select_all_layers_pressed() { + EditorNode *en = EditorNode::get_singleton(); + Node *edited_scene_root = en->get_edited_scene(); + ERR_FAIL_NULL(edited_scene_root); + + en->get_editor_selection()->clear(); + if (tile_map_layers_in_scene_cache.size() == 1) { + en->edit_node(tile_map_layers_in_scene_cache[0]); + en->get_editor_selection()->add_node(tile_map_layers_in_scene_cache[0]); + } else { + _update_tile_map_layers_in_scene_list_cache(); + Ref<MultiNodeEdit> multi_node_edit = memnew(MultiNodeEdit); + for (TileMapLayer *layer : tile_map_layers_in_scene_cache) { + multi_node_edit->add_node(edited_scene_root->get_path_to(layer)); + en->get_editor_selection()->add_node(layer); + } + en->push_item(multi_node_edit.ptr()); + } +} + +void TileMapLayerEditor::_layers_selection_item_selected(int p_index) { TileMapLayer *edited_layer = _get_edited_layer(); ERR_FAIL_NULL(edited_layer); - TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent()); - ERR_FAIL_NULL(tile_map_layer_group); + TileMap *tile_map = Object::cast_to<TileMap>(edited_layer->get_parent()); + ERR_FAIL_NULL(tile_map); + + TileMapLayer *new_edited = Object::cast_to<TileMapLayer>(tile_map->get_child(p_index)); + edit(new_edited); +} + +void TileMapLayerEditor::_update_layers_selector() { + const TileMapLayer *edited_layer = _get_edited_layer(); + + // Update the selector. + layers_selection_button->clear(); + layers_selection_button->hide(); + select_all_layers->show(); + select_next_layer->set_disabled(false); + select_previous_layer->set_disabled(false); + advanced_menu_button->get_popup()->set_item_disabled(ADVANCED_MENU_EXTRACT_TILE_MAP_LAYERS, true); + if (edited_layer) { + TileMap *tile_map = Object::cast_to<TileMap>(edited_layer->get_parent()); + if (tile_map && edited_layer->get_index_in_tile_map() >= 0) { + // Build the list of layers. + for (int i = 0; i < tile_map->get_layers_count(); i++) { + const TileMapLayer *layer = Object::cast_to<TileMapLayer>(tile_map->get_child(i)); + if (layer) { + int index = layers_selection_button->get_item_count(); + layers_selection_button->add_item(layer->get_name()); + layers_selection_button->set_item_metadata(index, layer->get_name()); + if (edited_layer == layer) { + layers_selection_button->select(index); + } + } + } + + // Disable selector if there's no layer to select. + layers_selection_button->set_disabled(false); + if (layers_selection_button->get_item_count() == 0) { + layers_selection_button->set_disabled(true); + layers_selection_button->set_text(TTR("No Layers")); + } + + // Disable next/previous if there's one or less layers. + if (layers_selection_button->get_item_count() <= 1) { + select_next_layer->set_disabled(true); + select_previous_layer->set_disabled(true); + } + layers_selection_button->show(); + select_all_layers->hide(); + + // Enable the "extract as TileMapLayer" option only if we are editing a TleMap. + advanced_menu_button->get_popup()->set_item_disabled(ADVANCED_MENU_EXTRACT_TILE_MAP_LAYERS, false); + } + } else { + select_all_layers->hide(); + select_next_layer->set_disabled(true); + select_previous_layer->set_disabled(true); + } +} + +void TileMapLayerEditor::_clear_all_layers_highlighting() { + // Note: This function might be removed if we remove the TileMap node at some point. + // All processing could be done in _update_all_layers_highlighting otherwise. + TileMapLayer *edited_layer = _get_edited_layer(); + + // Use default mode. + if (edited_layer && edited_layer->get_index_in_tile_map() >= 0) { + // For the TileMap node. + TileMap *tile_map = Object::cast_to<TileMap>(edited_layer->get_parent()); + if (tile_map) { + for (int i = 0; i < tile_map->get_layers_count(); i++) { + TileMapLayer *layer = Object::cast_to<TileMapLayer>(tile_map->get_child(i)); + layer->set_highlight_mode(TileMapLayer::HIGHLIGHT_MODE_DEFAULT); + } + } + } else { + // For other TileMapLayer nodes. + _update_tile_map_layers_in_scene_list_cache(); + for (TileMapLayer *layer : tile_map_layers_in_scene_cache) { + layer->set_highlight_mode(TileMapLayer::HIGHLIGHT_MODE_DEFAULT); + } + } +} + +void TileMapLayerEditor::_update_all_layers_highlighting() { + EditorNode *en = EditorNode::get_singleton(); + Node *edited_scene_root = en->get_edited_scene(); + if (!edited_scene_root) { + return; + } + + // Get selected layer. + TileMapLayer *edited_layer = _get_edited_layer(); + + bool highlight_selected_layer = EDITOR_GET("editors/tiles_editor/highlight_selected_layer"); + if (edited_layer && highlight_selected_layer) { + int edited_z_index = edited_layer->get_z_index(); + + if (edited_layer->get_index_in_tile_map() >= 0) { + // For the TileMap node. + TileMap *tile_map = Object::cast_to<TileMap>(edited_layer->get_parent()); + ERR_FAIL_NULL(tile_map); + + bool passed = false; + for (int i = 0; i < tile_map->get_layers_count(); i++) { + TileMapLayer *layer = Object::cast_to<TileMapLayer>(tile_map->get_child(i)); + if (layer == edited_layer) { + passed = true; + layer->set_highlight_mode(TileMapLayer::HIGHLIGHT_MODE_DEFAULT); + } else { + if (passed || layer->get_z_index() > edited_z_index) { + layer->set_highlight_mode(TileMapLayer::HIGHLIGHT_MODE_ABOVE); + } else { + layer->set_highlight_mode(TileMapLayer::HIGHLIGHT_MODE_BELOW); + } + } + } + } else { + // Update highlight mode for independent layers. + _update_tile_map_layers_in_scene_list_cache(); + bool passed = false; + for (TileMapLayer *layer : tile_map_layers_in_scene_cache) { + if (layer == edited_layer) { + passed = true; + layer->set_highlight_mode(TileMapLayer::HIGHLIGHT_MODE_DEFAULT); + } else { + if (passed || layer->get_z_index() > edited_z_index) { + layer->set_highlight_mode(TileMapLayer::HIGHLIGHT_MODE_ABOVE); + } else { + layer->set_highlight_mode(TileMapLayer::HIGHLIGHT_MODE_BELOW); + } + } + } + } + } +} + +void TileMapLayerEditor::_highlight_selected_layer_button_toggled(bool p_pressed) { + TileMapLayer *edited_layer = _get_edited_layer(); + if (!edited_layer) { + return; + } - tile_map_layer_group->set_highlight_selected_layer(p_pressed); + EditorSettings::get_singleton()->set("editors/tiles_editor/highlight_selected_layer", p_pressed); + _update_all_layers_highlighting(); } void TileMapLayerEditor::_advanced_menu_button_id_pressed(int p_id) { @@ -3686,12 +3892,12 @@ void TileMapLayerEditor::_advanced_menu_button_id_pressed(int p_id) { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } - if (p_id == 0) { // Replace Tile Proxies + if (p_id == ADVANCED_MENU_REPLACE_WITH_PROXIES) { // Replace Tile Proxies EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Replace Tiles with Proxies")); TypedArray<Vector2i> used_cells = edited_layer->get_used_cells(); @@ -3710,31 +3916,74 @@ void TileMapLayerEditor::_advanced_menu_button_id_pressed(int p_id) { } undo_redo->commit_action(); + } else if (p_id == ADVANCED_MENU_EXTRACT_TILE_MAP_LAYERS) { // Transform internal TileMap layers into TileMapLayers. + ERR_FAIL_COND(edited_layer->get_index_in_tile_map() < 0); + + EditorNode *en = EditorNode::get_singleton(); + Node *edited_scene_root = en->get_edited_scene(); + ERR_FAIL_NULL(edited_scene_root); + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Extract TileMap layers as individual TileMapLayer nodes")); + + TileMap *tile_map = Object::cast_to<TileMap>(edited_layer->get_parent()); + for (int i = 0; i < tile_map->get_layers_count(); i++) { + undo_redo->add_do_method(tile_map, "remove_layer", 0); + } + + for (int i = 0; i < tile_map->get_layers_count(); i++) { + TileMapLayer *new_layer = tile_map->duplicate_layer_from_internal(i); + undo_redo->add_do_method(tile_map, "add_child", new_layer); + undo_redo->add_do_method(new_layer, "set_owner", edited_scene_root); + undo_redo->add_do_property(new_layer, "tile_set", tile_map->get_tileset()); // Workaround for a bug: #89947. + undo_redo->add_undo_method(tile_map, "remove_child", new_layer); + undo_redo->add_do_reference(new_layer); + } + + List<PropertyInfo> prop_list; + tile_map->get_property_list(&prop_list); + for (PropertyInfo &prop : prop_list) { + undo_redo->add_undo_property(tile_map, prop.name, tile_map->get(prop.name)); + } + undo_redo->commit_action(); } } void TileMapLayerEditor::_update_bottom_panel() { const TileMapLayer *edited_layer = _get_edited_layer(); - if (!edited_layer) { - return; + Ref<TileSet> tile_set; + if (edited_layer) { + tile_set = edited_layer->get_tile_set(); + } + + // Update state labels. + if (is_multi_node_edit) { + cant_edit_label->set_text(TTR("Can't edit multiple layers at once.")); + cant_edit_label->show(); + } else if (!edited_layer) { + cant_edit_label->set_text(TTR("The selected TileMap has no layer to edit.")); + cant_edit_label->show(); + } else if (!edited_layer->is_enabled() || !edited_layer->is_visible_in_tree()) { + cant_edit_label->set_text(TTR("The edited layer is disabled or invisible")); + cant_edit_label->show(); + } else if (tile_set.is_null()) { + cant_edit_label->set_text(TTR("The edited TileMap or TileMapLayer node has no TileSet resource.\nCreate or load a TileSet resource in the Tile Set property in the inspector.")); + cant_edit_label->show(); + } else { + cant_edit_label->hide(); } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); - - // Update the visibility of controls. - missing_tileset_label->set_visible(tile_set.is_null()); + // Update tabs visibility. for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) { tab_data.panel->hide(); } - if (tile_set.is_valid()) { - tabs_data[tabs_bar->get_current_tab()].panel->show(); - } + tabs_data[tabs_bar->get_current_tab()].panel->set_visible(!cant_edit_label->is_visible()); } Vector<Vector2i> TileMapLayerEditor::get_line(const TileMapLayer *p_tile_map_layer, Vector2i p_from_cell, Vector2i p_to_cell) { ERR_FAIL_NULL_V(p_tile_map_layer, Vector<Vector2i>()); - Ref<TileSet> tile_set = p_tile_map_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = p_tile_map_layer->get_tile_set(); ERR_FAIL_COND_V(tile_set.is_null(), Vector<Vector2i>()); if (tile_set->get_tile_shape() == TileSet::TILE_SHAPE_SQUARE) { @@ -3805,7 +4054,7 @@ Vector<Vector2i> TileMapLayerEditor::get_line(const TileMapLayer *p_tile_map_lay } void TileMapLayerEditor::_tile_map_layer_changed() { - tileset_changed_needs_update = true; + tile_map_layer_changed_needs_update = true; } void TileMapLayerEditor::_tab_changed(int p_tab_id) { @@ -3825,7 +4074,7 @@ void TileMapLayerEditor::_tab_changed(int p_tab_id) { TileMapLayer *tile_map_layer = _get_edited_layer(); if (tile_map_layer) { - if (tile_map_layer->get_effective_tile_set().is_valid()) { + if (tile_map_layer->get_tile_set().is_valid()) { tabs_data[tabs_bar->get_current_tab()].panel->show(); } } @@ -3841,36 +4090,38 @@ void TileMapLayerEditor::_layers_select_next_or_previous(bool p_next) { return; } - TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent()); - if (!tile_map_layer_group) { - return; - } + EditorNode *en = EditorNode::get_singleton(); + Node *edited_scene_root = en->get_edited_scene(); + ERR_FAIL_NULL(edited_scene_root); + TileMapLayer *new_selected_layer = nullptr; int inc = p_next ? 1 : -1; - int index = Math::posmod(edited_layer->get_index() + inc, tile_map_layer_group->get_child_count()); - const TileMapLayer *new_selected_layer = Object::cast_to<TileMapLayer>(tile_map_layer_group->get_child(index)); - while (new_selected_layer != edited_layer) { - if (new_selected_layer && new_selected_layer->is_enabled()) { - break; + if (edited_layer->get_index_in_tile_map() >= 0) { + // Part of a TileMap. + TileMap *tile_map = Object::cast_to<TileMap>(edited_layer->get_parent()); + new_selected_layer = Object::cast_to<TileMapLayer>(tile_map->get_child(Math::posmod(edited_layer->get_index_in_tile_map() + inc, tile_map->get_layers_count()))); + } else { + // Individual layer. + _update_tile_map_layers_in_scene_list_cache(); + int edited_index = -1; + for (int i = 0; i < tile_map_layers_in_scene_cache.size(); i++) { + if (tile_map_layers_in_scene_cache[i] == edited_layer) { + edited_index = i; + break; + } } - index = Math::posmod((index + inc), tile_map_layer_group->get_child_count()); - new_selected_layer = Object::cast_to<TileMapLayer>(tile_map_layer_group->get_child(index)); + new_selected_layer = tile_map_layers_in_scene_cache[Math::posmod(edited_index + inc, tile_map_layers_in_scene_cache.size())]; } - if (new_selected_layer != edited_layer) { - emit_signal("change_selected_layer_request", new_selected_layer->get_name()); - } -} + ERR_FAIL_NULL(new_selected_layer); -void TileMapLayerEditor::_update_highlighting_toggle() { - const TileMapLayer *edited_layer = _get_edited_layer(); - if (!edited_layer) { - return; - } - - TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent()); - if (tile_map_layer_group) { - toggle_highlight_selected_layer_button->set_pressed(tile_map_layer_group->is_highlighting_selected_layer()); + if (edited_layer->get_index_in_tile_map() < 0) { + // Only if not part of a TileMap. + en->edit_node(new_selected_layer); + en->get_editor_selection()->clear(); + en->get_editor_selection()->add_node(new_selected_layer); + } else { + edit(new_selected_layer); } } @@ -3966,7 +4217,7 @@ void TileMapLayerEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { return; } - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_null()) { return; } @@ -3994,29 +4245,25 @@ void TileMapLayerEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { } if (!source || !source->has_tile(tile_atlas_coords) || !source->has_alternative_tile(tile_atlas_coords, tile_alternative_tile)) { - // Generate a random color from the hashed values of the tiles. - Array a = tile_set->map_tile_proxy(tile_source_id, tile_atlas_coords, tile_alternative_tile); - if (int(a[0]) == tile_source_id && Vector2i(a[1]) == tile_atlas_coords && int(a[2]) == tile_alternative_tile) { - // Only display the pattern if we have no proxy tile. - Array to_hash; - to_hash.push_back(tile_source_id); - to_hash.push_back(tile_atlas_coords); - to_hash.push_back(tile_alternative_tile); - uint32_t hash = RandomPCG(to_hash.hash()).rand(); - - Color color; - color = color.from_hsv( - (float)((hash >> 24) & 0xFF) / 256.0, - Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0), - Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0), - 0.8); - - // Draw the scaled tile. - Transform2D tile_xform; - tile_xform.set_origin(tile_set->map_to_local(coords)); - tile_xform.set_scale(tile_shape_size); - tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, true, warning_pattern_texture); - } + // Generate a random color from the hashed identifier of the tiles. + Array to_hash; + to_hash.push_back(tile_source_id); + to_hash.push_back(tile_atlas_coords); + to_hash.push_back(tile_alternative_tile); + uint32_t hash = RandomPCG(to_hash.hash()).rand(); + + Color color; + color = color.from_hsv( + (float)((hash >> 24) & 0xFF) / 256.0, + Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0), + Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0), + 0.8); + + // Display the warning pattern. + Transform2D tile_xform; + tile_xform.set_origin(tile_set->map_to_local(coords)); + tile_xform.set_scale(tile_shape_size); + tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, true, warning_pattern_texture); // Draw the warning icon. Vector2::Axis min_axis = missing_tile_texture->get_size().min_axis_index(); @@ -4092,75 +4339,50 @@ void TileMapLayerEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { tabs_plugins[tabs_bar->get_current_tab()]->forward_canvas_draw_over_viewport(p_overlay); } -void TileMapLayerEditor::edit(TileMapLayer *p_tile_map_layer) { - if (p_tile_map_layer && p_tile_map_layer->get_instance_id() == edited_tile_map_layer_id) { +void TileMapLayerEditor::edit(Object *p_edited) { + if (p_edited && p_edited->get_instance_id() == edited_tile_map_layer_id) { return; } + _clear_all_layers_highlighting(); + // Disconnect to changes. TileMapLayer *tile_map_layer = _get_edited_layer(); if (tile_map_layer) { tile_map_layer->disconnect("changed", callable_mp(this, &TileMapLayerEditor::_tile_map_layer_changed)); + tile_map_layer->disconnect("visibility_changed", callable_mp(this, &TileMapLayerEditor::_tile_map_layer_changed)); } // Update the edited layer. - if (p_tile_map_layer) { + TileMapLayer *new_layer = Object::cast_to<TileMapLayer>(p_edited); + if (new_layer) { // Change the edited object. - edited_tile_map_layer_id = p_tile_map_layer->get_instance_id(); + edited_tile_map_layer_id = new_layer->get_instance_id(); tile_map_layer = _get_edited_layer(); // Connect to changes. if (!tile_map_layer->is_connected("changed", callable_mp(this, &TileMapLayerEditor::_tile_map_layer_changed))) { tile_map_layer->connect("changed", callable_mp(this, &TileMapLayerEditor::_tile_map_layer_changed)); + tile_map_layer->connect("visibility_changed", callable_mp(this, &TileMapLayerEditor::_tile_map_layer_changed)); } } else { edited_tile_map_layer_id = ObjectID(); } - update_layers_selector(); - _update_highlighting_toggle(); + // Check if we are trying to use a MultiNodeEdit. + is_multi_node_edit = Object::cast_to<MultiNodeEdit>(p_edited); - // Call the plugins. + // Call the plugins and update everything. tabs_plugins[tabs_bar->get_current_tab()]->edit(edited_tile_map_layer_id); + _update_layers_selector(); + _update_all_layers_highlighting(); _tile_map_layer_changed(); } -void TileMapLayerEditor::update_layers_selector() { - const TileMapLayer *edited_layer = _get_edited_layer(); - if (!edited_layer) { - return; - } - - TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent()); - if (tile_map_layer_group) { - // Update the selector - layers_selection_button->show(); - layers_selection_button->clear(); - - // Build the list of layers. - for (int i = 0; i < tile_map_layer_group->get_child_count(); i++) { - const TileMapLayer *layer = Object::cast_to<TileMapLayer>(tile_map_layer_group->get_child(i)); - if (layer) { - int index = layers_selection_button->get_item_count(); - layers_selection_button->add_item(layer->get_name()); - layers_selection_button->set_item_disabled(index, !layer->is_enabled()); - layers_selection_button->set_item_metadata(index, layer->get_name()); - if (edited_layer == layer) { - layers_selection_button->select(index); - } - } - } - - // Disable the button if there's no layer to select. - layers_selection_button->set_disabled(false); - if (layers_selection_button->get_item_count() == 0) { - layers_selection_button->set_disabled(true); - layers_selection_button->set_text(TTR("No Layers")); - } - } else { - layers_selection_button->hide(); - } +void TileMapLayerEditor::set_show_layer_selector(bool p_show_layer_selector) { + show_layers_selector = p_show_layer_selector; + _update_layers_selector(); } TileMapLayerEditor::TileMapLayerEditor() { @@ -4210,13 +4432,36 @@ TileMapLayerEditor::TileMapLayerEditor() { tile_map_toolbar->add_child(c); // Layer selector. + layer_selection_hbox = memnew(HBoxContainer); + tile_map_toolbar->add_child(layer_selection_hbox); + layers_selection_button = memnew(OptionButton); layers_selection_button->set_custom_minimum_size(Size2(200, 0)); layers_selection_button->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); layers_selection_button->set_tooltip_text(TTR("TileMap Layers")); layers_selection_button->connect("item_selected", callable_mp(this, &TileMapLayerEditor::_layers_selection_item_selected)); - tile_map_toolbar->add_child(layers_selection_button); - + layer_selection_hbox->add_child(layers_selection_button); + + select_previous_layer = memnew(Button); + select_previous_layer->set_theme_type_variation("FlatButton"); + select_previous_layer->set_tooltip_text(TTR("Select previous layer")); + select_previous_layer->connect("pressed", callable_mp(this, &TileMapLayerEditor::_select_previous_layer_pressed)); + layer_selection_hbox->add_child(select_previous_layer); + + select_next_layer = memnew(Button); + select_next_layer->set_theme_type_variation("FlatButton"); + select_next_layer->set_tooltip_text(TTR("Select next layer")); + select_next_layer->connect("pressed", callable_mp(this, &TileMapLayerEditor::_select_next_layer_pressed)); + layer_selection_hbox->add_child(select_next_layer); + + select_all_layers = memnew(Button); + select_all_layers->set_theme_type_variation("FlatButton"); + select_all_layers->set_text(TTR("Select all layers")); + select_all_layers->connect("pressed", callable_mp(this, &TileMapLayerEditor::_select_all_layers_pressed)); + select_all_layers->set_tooltip_text(TTR("Select all TileMapLayers in scene")); + layer_selection_hbox->add_child(select_all_layers); + + // Highlighting selected layer. toggle_highlight_selected_layer_button = memnew(Button); toggle_highlight_selected_layer_button->set_theme_type_variation("FlatButton"); toggle_highlight_selected_layer_button->set_toggle_mode(true); @@ -4239,18 +4484,19 @@ TileMapLayerEditor::TileMapLayerEditor() { advanced_menu_button = memnew(MenuButton); advanced_menu_button->set_flat(false); advanced_menu_button->set_theme_type_variation("FlatButton"); - advanced_menu_button->get_popup()->add_item(TTR("Automatically Replace Tiles with Proxies")); + advanced_menu_button->get_popup()->add_item(TTR("Automatically Replace Tiles with Proxies"), ADVANCED_MENU_REPLACE_WITH_PROXIES); + advanced_menu_button->get_popup()->add_item(TTR("Extract TileMap layers as individual TileMapLayer nodes"), ADVANCED_MENU_EXTRACT_TILE_MAP_LAYERS); advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileMapLayerEditor::_advanced_menu_button_id_pressed)); tile_map_toolbar->add_child(advanced_menu_button); - missing_tileset_label = memnew(Label); - missing_tileset_label->set_text(TTR("The edited TileMap node has no TileSet resource.\nCreate or load a TileSet resource in the Tile Set property in the inspector.")); - missing_tileset_label->set_h_size_flags(SIZE_EXPAND_FILL); - missing_tileset_label->set_v_size_flags(SIZE_EXPAND_FILL); - missing_tileset_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); - missing_tileset_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); - missing_tileset_label->hide(); - add_child(missing_tileset_label); + // A label for editing errors. + cant_edit_label = memnew(Label); + cant_edit_label->set_h_size_flags(SIZE_EXPAND_FILL); + cant_edit_label->set_v_size_flags(SIZE_EXPAND_FILL); + cant_edit_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); + cant_edit_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); + cant_edit_label->hide(); + add_child(cant_edit_label); for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { add_child(tabs_data[tab_index].panel); diff --git a/editor/plugins/tiles/tile_map_layer_editor.h b/editor/plugins/tiles/tile_map_layer_editor.h index a7fea2abcf..2603261449 100644 --- a/editor/plugins/tiles/tile_map_layer_editor.h +++ b/editor/plugins/tiles/tile_map_layer_editor.h @@ -339,10 +339,16 @@ class TileMapLayerEditor : public VBoxContainer { GDCLASS(TileMapLayerEditor, VBoxContainer); private: - bool tileset_changed_needs_update = false; + bool tile_map_layer_changed_needs_update = false; ObjectID edited_tile_map_layer_id; + bool is_multi_node_edit = false; + Vector<TileMapLayer *> tile_map_layers_in_scene_cache; + bool layers_in_scene_list_cache_needs_update = false; TileMapLayer *_get_edited_layer() const; + void _find_tile_map_layers_in_scene(Node *p_current, const Node *p_owner, Vector<TileMapLayer *> &r_list) const; + void _update_tile_map_layers_in_scene_list_cache(); + void _node_change(Node *p_node); // Vector to keep plugins. Vector<TileMapLayerSubEditorPlugin *> tile_map_editor_plugins; @@ -350,20 +356,36 @@ private: // Toolbar. HFlowContainer *tile_map_toolbar = nullptr; + bool show_layers_selector = false; + + HBoxContainer *layer_selection_hbox = nullptr; + Button *select_previous_layer = nullptr; + void _select_previous_layer_pressed(); + Button *select_next_layer = nullptr; + void _select_next_layer_pressed(); + Button *select_all_layers = nullptr; + void _select_all_layers_pressed(); OptionButton *layers_selection_button = nullptr; void _layers_selection_item_selected(int p_index); + void _update_layers_selector(); Button *toggle_highlight_selected_layer_button = nullptr; + void _clear_all_layers_highlighting(); + void _update_all_layers_highlighting(); void _highlight_selected_layer_button_toggled(bool p_pressed); Button *toggle_grid_button = nullptr; void _on_grid_toggled(bool p_pressed); + enum { + ADVANCED_MENU_REPLACE_WITH_PROXIES, + ADVANCED_MENU_EXTRACT_TILE_MAP_LAYERS, + }; MenuButton *advanced_menu_button = nullptr; void _advanced_menu_button_id_pressed(int p_id); // Bottom panel. - Label *missing_tileset_label = nullptr; + Label *cant_edit_label = nullptr; TabBar *tabs_bar = nullptr; LocalVector<TileMapLayerSubEditorPlugin::TabData> tabs_data; LocalVector<TileMapLayerSubEditorPlugin *> tabs_plugins; @@ -379,22 +401,20 @@ private: // Updates. void _layers_select_next_or_previous(bool p_next); - void _update_highlighting_toggle(); // Inspector undo/redo callback. void _move_tile_map_array_element(Object *p_undo_redo, Object *p_edited, const String &p_array_prefix, int p_from_index, int p_to_pos); protected: void _notification(int p_what); - static void _bind_methods(); void _draw_shape(Control *p_control, Rect2 p_region, TileSet::TileShape p_shape, TileSet::TileOffsetAxis p_offset_axis, Color p_color); public: bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); void forward_canvas_draw_over_viewport(Control *p_overlay); - void edit(TileMapLayer *p_tile_map_layer); - void update_layers_selector(); + void edit(Object *p_tile_map_layer); + void set_show_layer_selector(bool p_show_layer_selector); TileMapLayerEditor(); ~TileMapLayerEditor(); diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index ed21a29487..c3141beb1a 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -40,6 +40,7 @@ #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_bottom_panel.h" +#include "editor/multi_node_edit.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/themes/editor_scale.h" #include "scene/2d/tile_map.h" @@ -336,7 +337,7 @@ void TileMapEditorPlugin::_tile_map_layer_removed() { void TileMapEditorPlugin::_update_tile_map() { TileMapLayer *edited_layer = Object::cast_to<TileMapLayer>(ObjectDB::get_instance(tile_map_layer_id)); if (edited_layer) { - Ref<TileSet> tile_set = edited_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = edited_layer->get_tile_set(); if (tile_set.is_valid() && tile_set_id != tile_set->get_instance_id()) { tile_set_plugin_singleton->edit(tile_set.ptr()); tile_set_plugin_singleton->make_visible(true); @@ -355,38 +356,25 @@ void TileMapEditorPlugin::_select_layer(const StringName &p_name) { ERR_FAIL_NULL(edited_layer); Node *parent = edited_layer->get_parent(); - ERR_FAIL_NULL(parent); - - TileMapLayer *new_layer = Object::cast_to<TileMapLayer>(parent->get_node_or_null(String(p_name))); - edit(new_layer); + if (parent) { + TileMapLayer *new_layer = Object::cast_to<TileMapLayer>(parent->get_node_or_null(String(p_name))); + edit(new_layer); + } } -void TileMapEditorPlugin::_edit_tile_map_layer(TileMapLayer *p_tile_map_layer) { +void TileMapEditorPlugin::_edit_tile_map_layer(TileMapLayer *p_tile_map_layer, bool p_show_layer_selector) { ERR_FAIL_NULL(p_tile_map_layer); editor->edit(p_tile_map_layer); - - // Update the selected layers in the TileMapLayerGroup parent node. - TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(p_tile_map_layer->get_parent()); - if (tile_map_layer_group) { - Vector<StringName> selected; - selected.push_back(p_tile_map_layer->get_name()); - tile_map_layer_group->set_selected_layers(selected); - } + editor->set_show_layer_selector(p_show_layer_selector); // Update the object IDs. tile_map_layer_id = p_tile_map_layer->get_instance_id(); p_tile_map_layer->connect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_changed)); p_tile_map_layer->connect("tree_exited", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_removed)); - if (tile_map_layer_group) { - tile_map_group_id = tile_map_layer_group->get_instance_id(); - tile_map_layer_group->connect("child_entered_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1)); - tile_map_layer_group->connect("child_exiting_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1)); - tile_map_layer_group->connect("child_order_changed", callable_mp(editor, &TileMapLayerEditor::update_layers_selector)); - } // Update the edited tileset. - Ref<TileSet> tile_set = p_tile_map_layer->get_effective_tile_set(); + Ref<TileSet> tile_set = p_tile_map_layer->get_tile_set(); if (tile_set.is_valid()) { tile_set_plugin_singleton->edit(tile_set.ptr()); tile_set_plugin_singleton->make_visible(true); @@ -397,30 +385,15 @@ void TileMapEditorPlugin::_edit_tile_map_layer(TileMapLayer *p_tile_map_layer) { } } -void TileMapEditorPlugin::_edit_tile_map_layer_group(TileMapLayerGroup *p_tile_map_layer_group) { - ERR_FAIL_NULL(p_tile_map_layer_group); - - Vector<StringName> selected_layers = p_tile_map_layer_group->get_selected_layers(); - - TileMapLayer *selected_layer = nullptr; - if (selected_layers.size() > 0) { - // Edit the selected layer. - selected_layer = Object::cast_to<TileMapLayer>(p_tile_map_layer_group->get_node_or_null(String(selected_layers[0]))); - } - if (!selected_layer) { - // Edit the first layer found. - for (int i = 0; i < p_tile_map_layer_group->get_child_count(); i++) { - selected_layer = Object::cast_to<TileMapLayer>(p_tile_map_layer_group->get_child(i)); - if (selected_layer) { - break; - } - } - } +void TileMapEditorPlugin::_edit_tile_map(TileMap *p_tile_map) { + ERR_FAIL_NULL(p_tile_map); - if (selected_layer) { - _edit_tile_map_layer(selected_layer); + if (p_tile_map->get_layers_count() > 0) { + TileMapLayer *selected_layer = Object::cast_to<TileMapLayer>(p_tile_map->get_child(0)); + _edit_tile_map_layer(selected_layer, true); } else { editor->edit(nullptr); + editor->set_show_layer_selector(false); } } @@ -437,36 +410,38 @@ void TileMapEditorPlugin::edit(Object *p_object) { edited_layer->disconnect("tree_exited", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_removed)); } - TileMapLayerGroup *tile_map_group = Object::cast_to<TileMapLayerGroup>(ObjectDB::get_instance(tile_map_group_id)); - if (tile_map_group) { - tile_map_group->disconnect("child_entered_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1)); - tile_map_group->disconnect("child_exiting_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1)); - tile_map_group->disconnect("child_order_changed", callable_mp(editor, &TileMapLayerEditor::update_layers_selector)); - } - tile_map_group_id = ObjectID(); tile_map_layer_id = ObjectID(); tile_set_id = ObjectID(); - TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMap>(p_object); + TileMap *tile_map = Object::cast_to<TileMap>(p_object); TileMapLayer *tile_map_layer = Object::cast_to<TileMapLayer>(p_object); - if (tile_map_layer_group) { - _edit_tile_map_layer_group(tile_map_layer_group); + MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(p_object); + if (tile_map) { + _edit_tile_map(tile_map); } else if (tile_map_layer) { - _edit_tile_map_layer(tile_map_layer); + _edit_tile_map_layer(tile_map_layer, false); + } else if (multi_node_edit) { + editor->edit(multi_node_edit); } else { - // Deselect the layer in the group. - if (edited_layer) { - tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent()); - if (tile_map_layer_group) { - tile_map_layer_group->set_selected_layers(Vector<StringName>()); - } - } + editor->edit(nullptr); } } bool TileMapEditorPlugin::handles(Object *p_object) const { - return Object::cast_to<TileMapLayer>(p_object) != nullptr || Object::cast_to<TileMapLayerGroup>(p_object) != nullptr; + MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(p_object); + Node *edited_scene = EditorNode::get_singleton()->get_edited_scene(); + if (multi_node_edit && edited_scene) { + bool only_tile_map_layers = true; + for (int i = 0; i < multi_node_edit->get_node_count(); i++) { + if (!Object::cast_to<TileMapLayer>(edited_scene->get_node(multi_node_edit->get_node(i)))) { + only_tile_map_layers = false; + break; + } + } + return only_tile_map_layers; + } + return Object::cast_to<TileMapLayer>(p_object) != nullptr || Object::cast_to<TileMap>(p_object) != nullptr; } void TileMapEditorPlugin::make_visible(bool p_visible) { @@ -509,7 +484,6 @@ TileMapEditorPlugin::TileMapEditorPlugin() { editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); - editor->connect("change_selected_layer_request", callable_mp(this, &TileMapEditorPlugin::_select_layer)); editor->hide(); button = EditorNode::get_bottom_panel()->add_item(TTR("TileMap"), editor, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_tile_map_bottom_panel", TTR("Toggle TileMap Bottom Panel"))); diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h index ac3e8986d6..23a6a52a5c 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.h +++ b/editor/plugins/tiles/tiles_editor_plugin.h @@ -126,8 +126,8 @@ class TileMapEditorPlugin : public EditorPlugin { void _update_tile_map(); void _select_layer(const StringName &p_name); - void _edit_tile_map_layer(TileMapLayer *p_tile_map_layer); - void _edit_tile_map_layer_group(TileMapLayerGroup *p_tile_map_layer_group); + void _edit_tile_map_layer(TileMapLayer *p_tile_map_layer, bool p_show_layer_selector); + void _edit_tile_map(TileMap *p_tile_map); protected: void _notification(int p_notification); |