Skip to content

Commit 2d719de

Browse files
authored
Merge pull request #85023 from mqrause/vmenu_sorting
Improve vmenu sorting
2 parents 1bbbecf + 6cc46e5 commit 2d719de

File tree

8 files changed

+97
-49
lines changed

8 files changed

+97
-49
lines changed

src/enums.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,20 @@ struct enum_traits<bionic_ui_sort_mode> {
7474
static constexpr bionic_ui_sort_mode last = bionic_ui_sort_mode::nsort;
7575
};
7676

77-
enum class list_item_sort_mode : int {
78-
DISTANCE,
79-
NAME,
80-
CATEGORY_DISTANCE,
81-
CATEGORY_NAME,
77+
// default is sorting by distance
78+
enum class surroundings_menu_sort_flags : int {
79+
DEFAULT = 0,
80+
NAME = 1 << 0,
81+
CATEGORY = 1 << 1,
82+
CATEGORY_NAME = NAME | CATEGORY, // this is currently needed to cycle through the option
8283
count
8384
};
8485

8586
template<>
86-
struct enum_traits<list_item_sort_mode> {
87-
static constexpr list_item_sort_mode last = list_item_sort_mode::count;
87+
struct enum_traits<surroundings_menu_sort_flags> {
88+
static constexpr surroundings_menu_sort_flags first = surroundings_menu_sort_flags::DEFAULT;
89+
static constexpr surroundings_menu_sort_flags last = surroundings_menu_sort_flags::count;
90+
static constexpr bool is_flag_enum = true;
8891
};
8992

9093
// When bool is not enough. NONE, SOME or ALL

src/game.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6413,23 +6413,6 @@ bool game::take_screenshot() const
64136413
}
64146414
#endif
64156415

6416-
template<>
6417-
std::string io::enum_to_string<list_item_sort_mode>( list_item_sort_mode data )
6418-
{
6419-
switch( data ) {
6420-
case list_item_sort_mode::count:
6421-
case list_item_sort_mode::DISTANCE:
6422-
return "DISTANCE";
6423-
case list_item_sort_mode::NAME:
6424-
return "NAME";
6425-
case list_item_sort_mode::CATEGORY_DISTANCE:
6426-
return "CATEGORY_DISTANCE";
6427-
case list_item_sort_mode::CATEGORY_NAME:
6428-
return "CATEGORY_NAME";
6429-
}
6430-
cata_fatal( "Invalid list item sort mode" );
6431-
}
6432-
64336416
void game::list_surroundings()
64346417
{
64356418
temp_exit_fullscreen();

src/inventory_ui.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,9 @@ void uistatedata::serialize( JsonOut &json ) const
383383
json.member( "overmap_show_revealed_omts", overmap_show_revealed_omts );
384384
json.member( "overmap_show_forest_trails", overmap_show_forest_trails );
385385
json.member( "vmenu_tab", vmenu_tab );
386-
json.member( "list_item_sort", list_item_sort );
386+
json.member( "vmenu_item_sort", vmenu_item_sort );
387+
json.member( "vmenu_monster_sort", vmenu_monster_sort );
388+
json.member( "vmenu_terfurn_sort", vmenu_terfurn_sort );
387389
json.member( "read_items", read_items );
388390
json.member( "list_item_filter_active", list_item_filter_active );
389391
json.member( "list_item_downvote_active", list_item_downvote_active );
@@ -507,7 +509,9 @@ void uistatedata::deserialize( const JsonObject &jo )
507509
jo.read( "distraction_withdrawal", distraction_withdrawal );
508510
jo.read( "numpad_navigation", numpad_navigation );
509511
jo.read( "vmenu_tab", vmenu_tab );
510-
jo.read( "list_item_sort", list_item_sort );
512+
jo.read( "vmenu_item_sort", vmenu_item_sort );
513+
jo.read( "vmenu_monster_sort", vmenu_monster_sort );
514+
jo.read( "vmenu_terfurn_sort", vmenu_terfurn_sort );
511515
jo.read( "read_items", read_items );
512516
jo.read( "list_item_filter_active", list_item_filter_active );
513517
jo.read( "list_item_downvote_active", list_item_downvote_active );

src/map_entity_stack.cpp

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
#include "character.h"
66
#include "color.h"
77
#include "creature.h"
8+
#include "enums.h"
9+
#include "enum_traits.h"
810
#include "item.h"
911
#include "item_category.h"
1012
#include "item_search.h"
13+
#include "item_tname.h"
1114
#include "line.h"
15+
#include "localized_comparator.h"
1216
#include "mapdata.h"
1317
#include "monster.h"
18+
#include "output.h"
1419
#include "string_formatter.h"
1520
#include "translation.h"
1621
#include "translations.h"
@@ -238,18 +243,29 @@ std::string map_entity_stack<map_data_common_t>::get_category() const
238243
}
239244

240245
template<typename T>
241-
bool map_entity_stack<T>::compare( const map_entity_stack<T> &, bool ) const
246+
bool map_entity_stack<T>::compare( const map_entity_stack<T> &, surroundings_menu_sort_flags ) const
242247
{
243248
return false;
244249
}
245250

246251
template<>
247-
bool map_entity_stack<item>::compare( const map_entity_stack<item> &rhs, bool use_category ) const
252+
bool map_entity_stack<item>::compare( const map_entity_stack<item> &rhs,
253+
surroundings_menu_sort_flags sort_flags ) const
248254
{
249-
bool compare_dist = rl_dist( tripoint_rel_ms(), entities[0].pos ) <
250-
rl_dist( tripoint_rel_ms(), rhs.entities[0].pos );
255+
bool compare_dist;
256+
if( sort_flags & surroundings_menu_sort_flags::NAME ) {
257+
const item *lhs_it = get_selected_entity();
258+
const item *rhs_it = rhs.get_selected_entity();
259+
260+
compare_dist = localized_compare(
261+
to_lower_case( lhs_it->tname( get_selected_count(), tname::unprefixed_tname ) ),
262+
to_lower_case( rhs_it->tname( rhs.get_selected_count(), tname::unprefixed_tname ) ) );
263+
} else {
264+
compare_dist = rl_dist( tripoint_rel_ms(), entities[0].pos ) <
265+
rl_dist( tripoint_rel_ms(), rhs.entities[0].pos );
266+
}
251267

252-
if( !use_category ) {
268+
if( !( sort_flags & surroundings_menu_sort_flags::CATEGORY ) ) {
253269
return compare_dist;
254270
}
255271

@@ -263,14 +279,32 @@ bool map_entity_stack<item>::compare( const map_entity_stack<item> &rhs, bool us
263279
return lhs_cat < rhs_cat;
264280
}
265281

282+
static std::string mon_name( const map_entity_stack<Creature> &map_stack )
283+
{
284+
std::string mon_name;
285+
const Creature *critter = map_stack.get_selected_entity();
286+
if( critter->is_monster() ) {
287+
return critter->as_monster()->name();
288+
} else {
289+
return critter->disp_name();
290+
}
291+
}
292+
293+
266294
template<>
267295
bool map_entity_stack<Creature>::compare( const map_entity_stack<Creature> &rhs,
268-
bool use_category ) const
296+
surroundings_menu_sort_flags sort_flags ) const
269297
{
270-
bool compare_dist = rl_dist( tripoint_rel_ms(), entities[0].pos ) <
271-
rl_dist( tripoint_rel_ms(), rhs.entities[0].pos );
298+
bool compare_dist;
299+
if( sort_flags & surroundings_menu_sort_flags::NAME ) {
300+
compare_dist = localized_compare( to_lower_case( mon_name( *this ) ),
301+
to_lower_case( mon_name( rhs ) ) );
302+
} else {
303+
compare_dist = rl_dist( tripoint_rel_ms(), entities[0].pos ) <
304+
rl_dist( tripoint_rel_ms(), rhs.entities[0].pos );
305+
}
272306

273-
if( !use_category ) {
307+
if( !( sort_flags & surroundings_menu_sort_flags::CATEGORY ) ) {
274308
return compare_dist;
275309
}
276310

@@ -287,12 +321,20 @@ bool map_entity_stack<Creature>::compare( const map_entity_stack<Creature> &rhs,
287321

288322
template<>
289323
bool map_entity_stack<map_data_common_t>::compare( const map_entity_stack<map_data_common_t> &rhs,
290-
bool use_category ) const
324+
surroundings_menu_sort_flags sort_flags ) const
291325
{
292-
bool compare_dist = rl_dist( tripoint_rel_ms(), entities[0].pos ) <
293-
rl_dist( tripoint_rel_ms(), rhs.entities[0].pos );
326+
bool compare_dist;
327+
if( sort_flags & surroundings_menu_sort_flags::NAME ) {
328+
const map_data_common_t *lhs_it = get_selected_entity();
329+
const map_data_common_t *rhs_it = rhs.get_selected_entity();
330+
compare_dist = localized_compare( to_lower_case( lhs_it->name() ),
331+
to_lower_case( rhs_it->name() ) );
332+
} else {
333+
compare_dist = rl_dist( tripoint_rel_ms(), entities[0].pos ) <
334+
rl_dist( tripoint_rel_ms(), rhs.entities[0].pos );
335+
}
294336

295-
if( !use_category ) {
337+
if( !( sort_flags & surroundings_menu_sort_flags::CATEGORY ) ) {
296338
return compare_dist;
297339
}
298340

src/map_entity_stack.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <vector>
88

99
#include "coordinates.h"
10+
#include "enums.h"
1011
#include "point.h"
1112

1213
template<typename T>
@@ -55,7 +56,8 @@ class map_entity_stack
5556
// through all older entity groups for a match.
5657
void add_at_pos( const T *entity, const tripoint_rel_ms &pos, int count = 1 );
5758

58-
bool compare( const map_entity_stack<T> &rhs, bool use_category = false ) const;
59+
bool compare( const map_entity_stack<T> &rhs,
60+
surroundings_menu_sort_flags sort_flags = surroundings_menu_sort_flags::DEFAULT ) const;
5961
std::string get_category() const;
6062
};
6163

src/surroundings_menu.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "creature.h"
2121
#include "debug.h"
2222
#include "enums.h"
23+
#include "enum_traits.h"
2324
#include "game.h"
2425
#include "game_constants.h"
2526
#include "game_inventory.h"
@@ -230,6 +231,7 @@ void item_tab_data::init( const Character &you, map &m )
230231
if( uistate.list_item_downvote_active ) {
231232
filter_priority_minus = uistate.list_item_downvote;
232233
}
234+
sort_flags = static_cast<surroundings_menu_sort_flags>( uistate.vmenu_item_sort );
233235
apply_filter();
234236
if( !filtered_list.empty() ) {
235237
selected_entry = filtered_list.front();
@@ -306,6 +308,7 @@ void item_tab_data::apply_filter()
306308
uistate.list_item_filter = filter;
307309
uistate.list_item_priority = filter_priority_plus;
308310
uistate.list_item_downvote = filter_priority_minus;
311+
uistate.vmenu_item_sort = static_cast<int>( sort_flags );
309312

310313
auto filter_function = item_filter_from_string( uistate.list_item_filter );
311314

@@ -318,7 +321,7 @@ void item_tab_data::apply_filter()
318321
// then apply regular sorting
319322
std::sort( filtered_list.begin(), filtered_list.end(),
320323
[&]( const map_entity_stack<item> *lhs, const map_entity_stack<item> *rhs ) {
321-
return lhs->compare( *rhs, draw_categories );
324+
return lhs->compare( *rhs, sort_flags );
322325
} );
323326

324327
// then apply priorities
@@ -421,6 +424,7 @@ void monster_tab_data::init( const Character &you )
421424
if( uistate.list_monster_filter_active ) {
422425
filter = uistate.monster_filter;
423426
}
427+
sort_flags = static_cast<surroundings_menu_sort_flags>( uistate.vmenu_item_sort );
424428
apply_filter();
425429
if( !filtered_list.empty() ) {
426430
selected_entry = filtered_list.front();
@@ -459,6 +463,7 @@ void monster_tab_data::apply_filter()
459463
{
460464
filtered_list.clear();
461465
uistate.monster_filter = filter;
466+
uistate.vmenu_monster_sort = static_cast<int>( sort_flags );
462467

463468
// todo: filter_from_string<Creature>
464469
// for now just matching creature name
@@ -474,7 +479,7 @@ void monster_tab_data::apply_filter()
474479
// then apply regular sorting
475480
std::sort( filtered_list.begin(), filtered_list.end(),
476481
[&]( const map_entity_stack<Creature> *lhs, const map_entity_stack<Creature> *rhs ) {
477-
return lhs->compare( *rhs, draw_categories );
482+
return lhs->compare( *rhs, sort_flags );
478483
} );
479484
}
480485

@@ -573,6 +578,7 @@ void terfurn_tab_data::init( const Character &you, map &m )
573578
if( uistate.list_terfurn_filter_active ) {
574579
filter = uistate.terfurn_filter;
575580
}
581+
sort_flags = static_cast<surroundings_menu_sort_flags>( uistate.vmenu_item_sort );
576582
apply_filter();
577583
if( !filtered_list.empty() ) {
578584
selected_entry = filtered_list.front();
@@ -647,6 +653,7 @@ void terfurn_tab_data::apply_filter()
647653
{
648654
filtered_list.clear();
649655
uistate.terfurn_filter = filter;
656+
uistate.vmenu_terfurn_sort = static_cast<int>( sort_flags );
650657

651658
// todo: filter_from_string<map_data_common_t>
652659
// for now just matching creature name
@@ -662,7 +669,7 @@ void terfurn_tab_data::apply_filter()
662669
std::sort( filtered_list.begin(), filtered_list.end(),
663670
[&]( const map_entity_stack<map_data_common_t> *lhs,
664671
const map_entity_stack<map_data_common_t> *rhs ) {
665-
return lhs->compare( *rhs, draw_categories );
672+
return lhs->compare( *rhs, sort_flags );
666673
} );
667674
}
668675

@@ -850,7 +857,7 @@ void surroundings_menu::draw_item_tab()
850857
for( map_entity_stack<item> *it : item_data.filtered_list ) {
851858
bool prio_plus = entry_no <= item_data.priority_plus_end;
852859
bool prio_minus = entry_no >= item_data.priority_minus_start;
853-
if( item_data.draw_categories ) {
860+
if( item_data.sort_flags & surroundings_menu_sort_flags::CATEGORY ) {
854861
std::string cat = prio_plus ? _( "HIGH PRIORITY" ) : prio_minus ? _( "LOW PRIORITY" ) :
855862
it->get_category();
856863
draw_category_separator( cat, last_category, 0 );
@@ -995,7 +1002,7 @@ void surroundings_menu::draw_monster_tab()
9951002
std::string last_category;
9961003
int entry_no = 0;
9971004
for( map_entity_stack<Creature> *it : monster_data.filtered_list ) {
998-
if( monster_data.draw_categories ) {
1005+
if( monster_data.sort_flags & surroundings_menu_sort_flags::CATEGORY ) {
9991006
draw_category_separator( it->get_category(), last_category, 1 );
10001007
}
10011008
bool is_selected = it == monster_data.selected_entry;
@@ -1119,7 +1126,7 @@ void surroundings_menu::draw_terfurn_tab()
11191126
std::string last_category;
11201127
int entry_no = 0;
11211128
for( map_entity_stack<map_data_common_t> *it : terfurn_data.filtered_list ) {
1122-
if( terfurn_data.draw_categories ) {
1129+
if( terfurn_data.sort_flags & surroundings_menu_sort_flags::CATEGORY ) {
11231130
draw_category_separator( it->get_category(), last_category, 0 );
11241131
}
11251132
bool is_selected = it == terfurn_data.selected_entry;
@@ -1441,7 +1448,7 @@ void surroundings_menu::change_selected_tab_sorting()
14411448
{
14421449
auto_scroll = true;
14431450
tab_data *data = get_selected_data();
1444-
data->draw_categories = !data->draw_categories;
1451+
++data->sort_flags;
14451452
data->apply_filter();
14461453
}
14471454

src/surroundings_menu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class tab_data
3434
input_context ctxt;
3535
std::string title;
3636

37-
bool draw_categories = false;
37+
surroundings_menu_sort_flags sort_flags = surroundings_menu_sort_flags::DEFAULT;
3838
// each group will start at a new line
3939
// currently roughly grouped by actions on an entry and actions on the list as a whole
4040
std::vector<std::unordered_set<std::string>> hotkey_groups;

src/uistate.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,14 @@ class uistatedata
216216
bool numpad_navigation = false;
217217

218218
// V Menu Stuff
219-
list_item_sort_mode list_item_sort = list_item_sort_mode::DISTANCE;
219+
// enum serialization relies on string conversion,
220+
// which doesn't make too much sense for flag enums
221+
// so we store them as ints instead
222+
// todo: turn into surroundings_menu_sort_flags
223+
// when flag enums can be serialized as numbers
224+
int vmenu_item_sort = 0;
225+
int vmenu_monster_sort = 0;
226+
int vmenu_terfurn_sort = 0;
220227
std::set<itype_id> read_items;
221228

222229
// These five aren't serialized because deserialize can extract them

0 commit comments

Comments
 (0)