Skip to content

Commit

Permalink
Merge pull request #58917 from IndecisionTree/toggle-categorize-map
Browse files Browse the repository at this point in the history
Enable category toggle in pickup selectors
  • Loading branch information
dseguin authored Jul 8, 2022
2 parents b406bd1 + 12d80fe commit e4a81da
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 50 deletions.
149 changes: 99 additions & 50 deletions src/inventory_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ bool always_yes( const inventory_entry & )
return true;
}

bool return_item( const inventory_entry &entry )
{
return entry.is_item();
}

bool is_container( const item_location &loc )
{
return loc.where() == item_location::type::container;
}

} // namespace

bool is_worn_ablative( item_location const &container, item_location const &child )
Expand Down Expand Up @@ -171,7 +181,7 @@ struct container_data {

static int contained_offset( const item_location &loc )
{
if( loc.where() != item_location::type::container ) {
if( !is_container( loc ) ) {
return 0;
}
return 2 + contained_offset( loc.parent_item() );
Expand Down Expand Up @@ -682,8 +692,7 @@ bool inventory_holster_preset::is_shown( const item_location &contained ) const
if( contained.eventually_contains( holster ) || holster.eventually_contains( contained ) ) {
return false;
}
if( contained.where() != item_location::type::container
&& contained->made_of( phase_id::LIQUID ) ) {
if( !is_container( contained ) && contained->made_of( phase_id::LIQUID ) ) {
// spilt liquid cannot be picked up
return false;
}
Expand Down Expand Up @@ -2577,73 +2586,100 @@ bool inventory_selector::is_overflown( size_t client_width ) const
return get_columns_occupancy_ratio( client_width ) > 1.0;
}

void inventory_selector::_categorize( inventory_column &col )
{
// Remove custom category and allow entries to categorize by their item's category
for( inventory_entry *entry : col.get_entries( return_item, true ) ) {
const item_location loc = entry->any_item();
const item_category *custom_category = nullptr;

// ensure top-level equipped entries don't lose their special categories
if( &*loc == &u.get_wielded_item() ) {
custom_category = &item_category_WEAPON_HELD.obj();
} else if( u.is_worn( *loc ) ) {
custom_category = &item_category_ITEMS_WORN.obj();
}

entry->set_custom_category( custom_category );
}
col.set_indent_entries_override( false );
col.invalidate_paging();
}

void inventory_selector::_uncategorize( inventory_column &col )
{
for( inventory_entry *entry : col.get_entries( return_item, true ) ) {
// find the topmost parent of the entry's item and categorize it by that
// to form the hierarchy
item_location ancestor = entry->any_item();
while( ancestor.has_parent() ) {
ancestor = ancestor.parent_item();
}

const item_category *custom_category = nullptr;
if( ancestor.where() != item_location::type::character ) {
const std::string name = to_upper_case( remove_color_tags( ancestor.describe() ) );
const item_category map_cat( name, no_translation( name ), 100 );
custom_category = naturalize_category( map_cat, ancestor.position() );
} else if( &*ancestor == &u.get_wielded_item() ) {
custom_category = &item_category_WEAPON_HELD.obj();
} else if( u.is_worn( *ancestor ) ) {
custom_category = &item_category_ITEMS_WORN.obj();
}

entry->set_custom_category( custom_category );
}
col.clear_indent_entries_override();
col.invalidate_paging();
}

void inventory_selector::toggle_categorize_contained()
{
const auto return_item = []( const inventory_entry & entry ) {
return entry.is_item();
};
std::vector<item_location> highlighted;
if( get_highlighted().is_item() ) {
highlighted = get_highlighted().locations;
}

if( _uimode == uimode::hierarchy ) {
inventory_column replacement_column;
for( inventory_entry *entry : own_gear_column.get_entries( return_item, true ) ) {
item_location const loc = entry->locations.front();
if( entry->any_item().where() == item_location::type::container &&
!is_worn_ablative( loc.parent_item(), loc ) ) {
item_location ancestor = entry->any_item();
while( ancestor.has_parent() ) {
ancestor = ancestor.parent_item();
}
const item_category *custom_category = nullptr;
if( ancestor.where() != item_location::type::character ) {
// might have been merged from the map column
custom_category = entry->get_category_ptr();
}
inventory_entry *ret =
add_entry( own_inv_column, std::move( entry->locations ), custom_category,
entry->chosen_count, entry->topmost_parent, entry->chevron );
ret->generation = entry->generation;

} else {
replacement_column.add_entry( *entry );
}
// split entries into either worn/held gear or contained items
for( inventory_entry *entry : own_gear_column.get_entries( return_item, true ) ) {
const item_location loc = entry->any_item();
inventory_column *col = is_container( loc ) && !is_worn_ablative( loc.parent_item(), loc ) ?
&own_inv_column : &replacement_column;
col->add_entry( *entry );
}
own_gear_column.clear();
replacement_column.move_entries_to( own_gear_column );
own_inv_column.set_indent_entries_override( false );

for( inventory_column *col : columns ) {
_categorize( *col );
}
_uimode = uimode::categories;
} else {
for( inventory_entry *entry : own_inv_column.get_entries( return_item, true ) ) {
item_location ancestor = entry->any_item();
while( ancestor.has_parent() ) {
ancestor = ancestor.parent_item();
}
const item_category *custom_category = nullptr;
if( ancestor.where() != item_location::type::character ) {
// might have been merged from the map column
custom_category = entry->get_category_ptr();
} else if( &*ancestor == &u.get_wielded_item() ) {
custom_category = &item_category_WEAPON_HELD.obj();
} else if( u.is_worn( *ancestor ) ) {
custom_category = &item_category_ITEMS_WORN.obj();
}
inventory_entry *ret =
add_entry( own_gear_column, std::move( entry->locations ), custom_category,
entry->chosen_count, entry->topmost_parent, entry->chevron );
ret->generation = entry->generation;
// move all entries into one big gear column and turn into hierarchy
own_inv_column.move_entries_to( own_gear_column );
for( inventory_column *col : columns ) {
_uncategorize( *col );
}
own_inv_column.clear();
_uimode = uimode::hierarchy;
}

if( !highlighted.empty() ) {
highlight_one_of( highlighted );
}

// needs to be called now so that new invlets can be assigned
// and subclasses w/ selection columns can then re-populate entries
// using the new invlets
prepare_layout();

// invalidate, but dont mark resize, to avoid re-calling prepare_layout()
// and as a consequence reassign_custom_invlets()
shared_ptr_fast<ui_adaptor> current_ui = ui.lock();
if( current_ui ) {
current_ui->mark_resize();
current_ui->invalidate_ui();
}
}

Expand Down Expand Up @@ -2752,9 +2788,6 @@ void inventory_selector::action_examine( const item_location sitem )

void inventory_selector::highlight()
{
const auto return_item = []( const inventory_entry & entry ) {
return entry.is_item();
};
const inventory_entry &selected = get_active_column().get_highlighted();
if( !selected.is_item() ) {
return;
Expand Down Expand Up @@ -3117,6 +3150,20 @@ void inventory_multiselector::deselect_contained_items()
}
}

void inventory_multiselector::toggle_categorize_contained()
{
selection_col->clear();
inventory_selector::toggle_categorize_contained();

for( inventory_column *col : get_all_columns() ) {
for( inventory_entry *entry : col->get_entries( return_item, true ) ) {
if( entry->chosen_count > 0 ) {
toggle_entry( *entry, entry->chosen_count );
}
}
}
}

void inventory_multiselector::on_input( const inventory_input &input )
{
bool const noMarkCountBound = ctxt.keys_bound_to( "MARK_WITH_COUNT" ).empty();
Expand Down Expand Up @@ -3146,6 +3193,8 @@ void inventory_multiselector::on_input( const inventory_input &input )
? count < max ? count + 1 : max
: count > 1 ? count - 1 : 0;
toggle_entry( entry, newcount );
} else if( input.action == "VIEW_CATEGORY_MODE" ) {
toggle_categorize_contained();
} else {
inventory_selector::on_input( input );
}
Expand Down
12 changes: 12 additions & 0 deletions src/inventory_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ class inventory_entry
size_t generation = 0;
bool chevron = false;

void set_custom_category( const item_category *category ) {
custom_category = category;
}

private:
const item_category *custom_category = nullptr;
bool enabled = true;
Expand Down Expand Up @@ -424,6 +428,10 @@ class inventory_column
indent_entries_override = entry_override;
}

void clear_indent_entries_override() {
indent_entries_override = cata::nullopt;
}

void invalidate_paging() {
paging_is_valid = false;
}
Expand Down Expand Up @@ -844,6 +852,9 @@ class inventory_selector

uimode _uimode = uimode::categories;

void _categorize( inventory_column &col );
void _uncategorize( inventory_column &col );

public:
std::string action_bound_to_key( char key ) const;
};
Expand Down Expand Up @@ -890,6 +901,7 @@ class inventory_multiselector : public inventory_selector
void on_input( const inventory_input &input );
int count = 0;
stats get_raw_stats() const override;
void toggle_categorize_contained();
private:
std::unique_ptr<inventory_column> selection_col;
GetStats get_stats;
Expand Down

0 comments on commit e4a81da

Please sign in to comment.