From e837045b1e342f75ba708a5131b8e7726a49e046 Mon Sep 17 00:00:00 2001 From: kobewi Date: Wed, 10 Nov 2021 02:27:37 +0100 Subject: [PATCH] Allow sorting tileset sources --- editor/plugins/tiles/tile_map_editor.cpp | 123 +++++++++++++++++++++-- editor/plugins/tiles/tile_map_editor.h | 18 ++++ editor/plugins/tiles/tile_set_editor.cpp | 8 +- 3 files changed, 137 insertions(+), 12 deletions(-) diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 39fbd86f77..815d8ae43e 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -135,10 +135,9 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { if (!tile_set.is_valid()) { return; } + List source_ids = _get_sorted_sources(tile_set); - for (int i = 0; i < tile_set->get_source_count(); i++) { - int source_id = tile_set->get_source_id(i); - + for (const int &source_id : source_ids) { TileSetSource *source = *tile_set->get_source(source_id); Ref texture; @@ -180,7 +179,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { } sources_list->add_item(item_text, texture); - sources_list->set_item_metadata(i, source_id); + sources_list->set_item_metadata(sources_list->get_item_count() - 1, source_id); } if (sources_list->get_item_count() > 0) { @@ -439,6 +438,7 @@ void TileMapEditorTilesPlugin::_scenes_list_nothing_selected() { } void TileMapEditorTilesPlugin::_update_theme() { + source_sort_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Sort"), SNAME("EditorIcons"))); select_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); paint_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); line_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons"))); @@ -1947,6 +1947,91 @@ void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer tile_map_layer = p_tile_map_layer; } +void TileMapEditorTilesPlugin::_set_source_sort(int p_sort) { + for (int i = 0; i != SOURCE_SORT_MAX; i++) { + source_sort_button->get_popup()->set_item_checked(i, (i == (int)p_sort)); + } + source_sort = (SourceSortOption)p_sort; + _update_tile_set_sources_list(); +} + +Ref TileMapEditorTilesPlugin::SourceNameComparator::tile_set; + +bool TileMapEditorTilesPlugin::SourceNameComparator::operator()(const int &p_a, const int &p_b) const { + String name_a; + String name_b; + + { + TileSetSource *source = *tile_set->get_source(p_a); + + if (!source->get_name().is_empty()) { + name_a = source->get_name(); + } + + TileSetAtlasSource *atlas_source = Object::cast_to(source); + if (atlas_source) { + Ref texture = atlas_source->get_texture(); + if (name_a.is_empty() && texture.is_valid()) { + name_a = texture->get_path().get_file(); + } + } + + if (name_a.is_empty()) { + name_a = itos(p_a); + } + } + + { + TileSetSource *source = *tile_set->get_source(p_b); + + if (!source->get_name().is_empty()) { + name_b = source->get_name(); + } + + TileSetAtlasSource *atlas_source = Object::cast_to(source); + if (atlas_source) { + Ref texture = atlas_source->get_texture(); + if (name_b.is_empty() && texture.is_valid()) { + name_b = texture->get_path().get_file(); + } + } + + if (name_b.is_empty()) { + name_b = itos(p_b); + } + } + + return NaturalNoCaseComparator()(name_a, name_b); +} + +List TileMapEditorTilesPlugin::_get_sorted_sources(const Ref tile_set) const { + SourceNameComparator::tile_set = tile_set; + List source_ids; + + for (int i = 0; i < tile_set->get_source_count(); i++) { + source_ids.push_back(i); + } + + switch (source_sort) { + case SOURCE_SORT_ID_REVERSE: + // Already sorted. + source_ids.reverse(); + break; + case SOURCE_SORT_NAME: + source_ids.sort_custom(); + break; + case SOURCE_SORT_NAME_REVERSE: + source_ids.sort_custom(); + source_ids.reverse(); + break; + default: // SOURCE_SORT_ID + break; + } + + SourceNameComparator::tile_set.unref(); + return source_ids; +} + void TileMapEditorTilesPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileMapEditorTilesPlugin::_scene_thumbnail_done); ClassDB::bind_method(D_METHOD("_set_tile_map_selection", "selection"), &TileMapEditorTilesPlugin::_set_tile_map_selection); @@ -2103,17 +2188,39 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { atlas_sources_split_container->set_v_size_flags(Control::SIZE_EXPAND_FILL); tiles_bottom_panel->add_child(atlas_sources_split_container); + VBoxContainer *split_container_left_side = memnew(VBoxContainer); + split_container_left_side->set_h_size_flags(Control::SIZE_EXPAND_FILL); + split_container_left_side->set_v_size_flags(Control::SIZE_EXPAND_FILL); + split_container_left_side->set_stretch_ratio(0.25); + split_container_left_side->set_custom_minimum_size(Size2i(70, 0) * EDSCALE); + atlas_sources_split_container->add_child(split_container_left_side); + sources_list = memnew(ItemList); sources_list->set_fixed_icon_size(Size2i(60, 60) * EDSCALE); - sources_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); - sources_list->set_stretch_ratio(0.25); - sources_list->set_custom_minimum_size(Size2i(70, 0) * EDSCALE); + sources_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1)); sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_source_display).unbind(1)); sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current)); sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list), varray(sources_list)); - atlas_sources_split_container->add_child(sources_list); + split_container_left_side->add_child(sources_list); + + HBoxContainer *sources_bottom_actions = memnew(HBoxContainer); + sources_bottom_actions->set_alignment(HBoxContainer::ALIGN_END); + split_container_left_side->add_child(sources_bottom_actions); + + source_sort_button = memnew(MenuButton); + source_sort_button->set_flat(true); + source_sort_button->set_tooltip(TTR("Sort sources")); + + PopupMenu *p = source_sort_button->get_popup(); + p->connect("id_pressed", callable_mp(this, &TileMapEditorTilesPlugin::_set_source_sort)); + p->add_radio_check_item(TTR("Sort by ID (Ascending)"), SOURCE_SORT_ID); + p->add_radio_check_item(TTR("Sort by ID (Descending)"), SOURCE_SORT_ID_REVERSE); + p->add_radio_check_item(TTR("Sort by Name (Ascending)"), SOURCE_SORT_NAME); + p->add_radio_check_item(TTR("Sort by Name (Descending)"), SOURCE_SORT_NAME_REVERSE); + p->set_item_checked(source_sort, true); + sources_bottom_actions->add_child(source_sort_button); // Tile atlas source. tile_atlas_view = memnew(TileAtlasView); diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h index f462119727..e800957ae6 100644 --- a/editor/plugins/tiles/tile_map_editor.h +++ b/editor/plugins/tiles/tile_map_editor.h @@ -140,11 +140,29 @@ private: void _tab_changed(); ///// Bottom panel tiles //// + enum SourceSortOption { + SOURCE_SORT_ID = 0, + SOURCE_SORT_ID_REVERSE, + SOURCE_SORT_NAME, + SOURCE_SORT_NAME_REVERSE, + SOURCE_SORT_MAX + }; + + SourceSortOption source_sort = SOURCE_SORT_ID; + List _get_sorted_sources(const Ref tile_set) const; + void _set_source_sort(int p_sort); + + struct SourceNameComparator { + static Ref tile_set; + bool operator()(const int &p_a, const int &p_b) const; + }; + VBoxContainer *tiles_bottom_panel; Label *missing_source_label; Label *invalid_source_label; ItemList *sources_list; + MenuButton *source_sort_button; Ref missing_atlas_texture_icon; void _update_tile_set_sources_list(); diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index 915ce50836..d5ab1e28aa 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -156,9 +156,9 @@ 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("%s (ID:%d)", texture->get_path().get_file(), source_id); + item_text = vformat("%s (ID: %d)", texture->get_path().get_file(), source_id); } else { - item_text = vformat(TTR("No Texture Atlas Source (ID:%d)"), source_id); + item_text = vformat(TTR("No Texture Atlas Source (ID: %d)"), source_id); } } } @@ -168,13 +168,13 @@ void TileSetEditor::_update_sources_list(int force_selected_id) { if (scene_collection_source) { texture = get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")); if (item_text.is_empty()) { - item_text = vformat(TTR("Scene Collection Source (ID:%d)"), source_id); + item_text = vformat(TTR("Scene Collection Source (ID: %d)"), source_id); } } // Use default if not valid. if (item_text.is_empty()) { - item_text = vformat(TTR("Unknown Type Source (ID:%d)"), source_id); + item_text = vformat(TTR("Unknown Type Source (ID: %d)"), source_id); } if (!texture.is_valid()) { texture = missing_texture_texture;