diff --git a/data/raw/keybindings.json b/data/raw/keybindings.json index e45dd777ad115..3dbe89e52bf99 100644 --- a/data/raw/keybindings.json +++ b/data/raw/keybindings.json @@ -1396,6 +1396,12 @@ "name": "Toggle category selection mode", "bindings": [ { "input_method": "keyboard", "key": "TAB" } ] }, + { + "type": "keybinding", + "id": "VIEW_CATEGORY_MODE", + "name": "Toggle inventory view to show item categories", + "bindings": [ { "input_method": "keyboard", "key": ";" } ] + }, { "type": "keybinding", "id": "INVENTORY_FILTER", diff --git a/src/inventory_ui.cpp b/src/inventory_ui.cpp index 75ef08df59080..1fc9001082bd2 100644 --- a/src/inventory_ui.cpp +++ b/src/inventory_ui.cpp @@ -1256,6 +1256,10 @@ void inventory_selector::add_character_items( Character &character ) } } } + // this is a little trick; we want the default behavior for contained items to be in own_inv_column + // and this function iterates over all the entries after we added them to the inventory selector + // to put them in the right place + toggle_categorize_contained(); } void inventory_selector::add_map_items( const tripoint &target ) @@ -1758,6 +1762,7 @@ inventory_selector::inventory_selector( player &u, const inventory_selector_pres ctxt.register_action( "HOME", to_translation( "Home" ) ); ctxt.register_action( "END", to_translation( "End" ) ); ctxt.register_action( "HELP_KEYBINDINGS" ); + ctxt.register_action( "VIEW_CATEGORY_MODE" ); ctxt.register_action( "ANY_INPUT" ); // For invlets ctxt.register_action( "INVENTORY_FILTER" ); @@ -1803,6 +1808,8 @@ void inventory_selector::on_input( const inventory_input &input ) toggle_active_column( scroll_direction::BACKWARD ); } else if( input.action == "RIGHT" ) { toggle_active_column( scroll_direction::FORWARD ); + } else if( input.action == "VIEW_CATEGORY_MODE" ) { + toggle_categorize_contained(); } else { for( auto &elem : columns ) { elem->on_input( input ); @@ -1877,6 +1884,51 @@ bool inventory_selector::is_overflown( size_t client_width ) const return get_columns_occupancy_ratio( client_width ) > 1.0; } +void inventory_selector::toggle_categorize_contained() +{ + const auto return_true = []( const inventory_entry & ) { + return true; + }; + const auto return_item = []( const inventory_entry & entry ) { + return entry.is_item(); + }; + if( own_inv_column.empty() ) { + inventory_column replacement_column; + for( inventory_entry *entry : own_gear_column.get_entries( return_item ) ) { + if( entry->any_item().where() == item_location::type::container ) { + add_entry( own_inv_column, std::move( entry->locations ) ); + } else { + replacement_column.add_entry( *entry ); + } + } + own_gear_column.clear(); + for( inventory_entry *entry : replacement_column.get_entries( return_true ) ) { + own_gear_column.add_entry( *entry ); + } + own_inv_column.set_indent_entries_override( false ); + } else { + for( inventory_entry *entry : own_inv_column.get_entries( return_item ) ) { + // all item entries in own_inv_column are always contained items + item_location parent = entry->any_item().parent_item(); + while( parent.where() == item_location::type::container ) { + parent = parent.parent_item(); + } + + if( parent.get_item() == &u.weapon ) { + add_entry( own_gear_column, std::move( entry->locations ), + &item_category_id( "WEAPON_HELD" ).obj() ); + } else { + add_entry( own_gear_column, std::move( entry->locations ), + &item_category_id( "ITEMS_WORN" ).obj() ); + } + } + own_inv_column.clear(); + } + + resize_window( std::max( { get_layout_width() + 6, get_header_min_width() } ), + get_layout_height() + get_header_height() ); +} + void inventory_selector::toggle_active_column( scroll_direction dir ) { if( columns.empty() ) { diff --git a/src/inventory_ui.h b/src/inventory_ui.h index 132091e590c81..f51ebeb48eaa9 100644 --- a/src/inventory_ui.h +++ b/src/inventory_ui.h @@ -336,9 +336,17 @@ class inventory_column // whether or not to indent contained entries bool indent_entries() const { - return preset.indent_entries(); + if( indent_entries_override ) { + return *indent_entries_override; + } else { + return preset.indent_entries(); + } }; + void set_indent_entries_override( bool entry_override ) { + indent_entries_override = entry_override; + } + protected: struct entry_cell_cache_t { bool assigned = false; @@ -409,6 +417,7 @@ class inventory_column std::vector cells; mutable std::vector entries_cell_cache; + cata::optional indent_entries_override = cata::nullopt; /** @return Number of visible cells */ size_t visible_cells() const; }; @@ -592,6 +601,7 @@ class inventory_selector return get_column( active_column_index ); } + void toggle_categorize_contained(); void set_active_column( size_t index ); protected: