diff --git a/src/crafting_gui.cpp b/src/crafting_gui.cpp index c6049894b9731..fefd4a87f0dc9 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -2308,7 +2308,8 @@ static void compare_recipe_with_item( const item &recipe_item, Character &crafte if( !to_compare ) { break; } - game_menus::inv::compare_items( recipe_item, *to_compare ); + game_menus::inv::compare_item_menu menu( recipe_item, *to_compare ); + menu.show(); } while( true ); } diff --git a/src/game_inventory.cpp b/src/game_inventory.cpp index 1062f9d0e6345..8897127bcb6f9 100644 --- a/src/game_inventory.cpp +++ b/src/game_inventory.cpp @@ -41,7 +41,6 @@ #include "messages.h" #include "npctrade.h" #include "options.h" -#include "output.h" #include "pimpl.h" #include "point.h" #include "recipe.h" @@ -2296,106 +2295,107 @@ drop_locations game_menus::inv::smoke_food( Character &you, units::volume total_ return smoke_s.execute(); } -bool game_menus::inv::compare_items( const item &first, const item &second, - const std::string &confirm_message ) -{ - std::string action; - input_context ctxt; - ui_adaptor ui; - item_info_data item_info_first; - item_info_data item_info_second; - int page_size = 0; - int scroll_pos_first = 0; - int scroll_pos_second = 0; - bool first_execution = true; - static int lang_version = detail::get_current_language_version(); - do { - //lang check here is needed to redraw the menu when using "Toggle language to English" option - if( first_execution || lang_version != detail::get_current_language_version() ) { - std::vector v_item_first; - std::vector v_item_second; - - first.info( true, v_item_first ); - second.info( true, v_item_second ); - - item_info_first = item_info_data( first.tname(), first.type_name(), - v_item_first, v_item_second, scroll_pos_first ); - - item_info_second = item_info_data( second.tname(), second.type_name(), - v_item_second, v_item_first, scroll_pos_second ); - - item_info_first.without_getch = true; - item_info_second.without_getch = true; - - ctxt.register_action( "HELP_KEYBINDINGS" ); - if( !confirm_message.empty() ) { - ctxt.register_action( "CONFIRM" ); - } - ctxt.register_action( "QUIT" ); - ctxt.register_action( "UP" ); - ctxt.register_action( "DOWN" ); - ctxt.register_action( "PAGE_UP" ); - ctxt.register_action( "PAGE_DOWN" ); - - catacurses::window wnd_first; - catacurses::window wnd_second; - catacurses::window wnd_message; - - ui.reset(); - ui.on_screen_resize( [&]( ui_adaptor & ui ) { - const int half_width = TERMX / 2; - const int height = TERMY; - const int offset_y = confirm_message.empty() ? 0 : 3; - page_size = TERMY - offset_y - 2; - wnd_first = catacurses::newwin( height - offset_y, half_width, point::zero ); - wnd_second = catacurses::newwin( height - offset_y, half_width, point( half_width, 0 ) ); - - if( !confirm_message.empty() ) { - wnd_message = catacurses::newwin( offset_y, TERMX, point( 0, height - offset_y ) ); - } - - ui.position( point::zero, point( half_width * 2, height ) ); - } ); - ui.mark_resize(); - ui.on_redraw( [&]( const ui_adaptor & ) { - if( !confirm_message.empty() ) { - draw_border( wnd_message ); - nc_color col = c_white; - print_colored_text( - wnd_message, point( 3, 1 ), col, col, - confirm_message + " " + - ctxt.describe_key_and_name( "CONFIRM" ) + " " + - ctxt.describe_key_and_name( "QUIT" ) ); - wnoutrefresh( wnd_message ); - } +game_menus::inv::compare_item_menu::compare_item_menu( const item &first, const item &second, + const std::string &confirm_message ) : + cataimgui::window( "compare", ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoNavInputs ), + first( first ), + second( second ), + confirm_message( confirm_message ) +{ + ctxt.register_action( "HELP_KEYBINDINGS" ); + if( !confirm_message.empty() ) { + ctxt.register_action( "CONFIRM" ); + } + ctxt.register_action( "QUIT" ); + ctxt.register_action( "UP" ); + ctxt.register_action( "DOWN" ); + ctxt.register_action( "PAGE_UP" ); + ctxt.register_action( "PAGE_DOWN" ); + ctxt.set_timeout( 10 ); + + // todo: regen info when toggling language? + first.info( true, first_info ); + second.info( true, second_info ); +} - draw_item_info( wnd_first, item_info_first ); - draw_item_info( wnd_second, item_info_second ); - } ); - lang_version = detail::get_current_language_version(); - first_execution = false; +static void draw_column( const std::string &label, const ImVec2 &size, const item &it, + std::vector &first, std::vector &second, cataimgui::scroll &s ) +{ + if( ImGui::BeginChild( label.c_str(), size ) ) { + cataimgui::TextColoredParagraph( c_light_gray, it.tname() ); + ImGui::NewLine(); + if( it.tname().find( it.type_name() ) == std::string::npos ) { + cataimgui::TextColoredParagraph( c_light_gray, it.type_name() ); + ImGui::NewLine(); } + ImGui::NewLine(); + cataimgui::set_scroll( s ); + display_item_info( first, second ); + } + ImGui::EndChild(); +} +void game_menus::inv::compare_item_menu::draw_controls() +{ + float half_width = ImGui::GetContentRegionAvail().x / 2; + float height = ImGui::GetContentRegionAvail().y; + ImGuiStyle &style = ImGui::GetStyle(); + float spacing_x = style.ItemSpacing.x; + float top_y = ImGui::GetCursorPosY(); + float confirm_height = confirm_message.empty() ? 0.f : ImGui::GetFrameHeightWithSpacing(); + + // cataimgui::set_scroll resets scroll, so we need a copy for parallel scrolling + // not ideal, but this is such a special use case it's probably not worth changing + // todo: also synchronize scrolling when using mouse wheel/dragging scroll bar? + cataimgui::scroll s_copy = s; + + draw_column( "compare_left", ImVec2( half_width - spacing_x, height - confirm_height ), first, + first_info, second_info, s ); + ImGui::SetCursorPos( { half_width + spacing_x, top_y } ); + draw_column( "compare_right", ImVec2( half_width - spacing_x, height - confirm_height ), second, + second_info, first_info, s_copy ); + + if( !confirm_message.empty() ) { + ImGui::AlignTextToFramePadding(); + cataimgui::TextColoredParagraph( c_white, confirm_message ); + // todo: spacing should be part of paragraph so it behaves the same as other elements + ImGui::Spacing(); + ImGui::SameLine(); + action_button( "CONFIRM", ctxt.get_button_text( "CONFIRM" ) ); + ImGui::SameLine(); + action_button( "QUIT", ctxt.get_button_text( "QUIT" ) ); + } +} + +cataimgui::bounds game_menus::inv::compare_item_menu::get_bounds() +{ + return { 0.f, 0.f, ImGui::GetMainViewport()->Size.x, ImGui::GetMainViewport()->Size.y }; +} + +bool game_menus::inv::compare_item_menu::show() +{ + while( true ) { ui_manager::redraw(); - action = ctxt.handle_input(); + std::string action = has_button_action() ? get_button_action() : ctxt.handle_input(); if( action == "UP" ) { - scroll_pos_first--; - scroll_pos_second--; + s = cataimgui::scroll::line_up; } else if( action == "DOWN" ) { - scroll_pos_first++; - scroll_pos_second++; + s = cataimgui::scroll::line_down; } else if( action == "PAGE_UP" ) { - scroll_pos_first -= page_size; - scroll_pos_second -= page_size; + s = cataimgui::scroll::page_up; } else if( action == "PAGE_DOWN" ) { - scroll_pos_first += page_size; - scroll_pos_second += page_size; + s = cataimgui::scroll::page_down; + } else if( action == "CONFIRM" ) { + return true; + } else if( action == "QUIT" ) { + return false; } - } while( action != "QUIT" && action != "CONFIRM" ); + } - return action == "CONFIRM"; + return false; } void game_menus::inv::compare( const std::optional &offset ) @@ -2428,7 +2428,8 @@ void game_menus::inv::compare( const std::optional &offset ) break; } - compare_items( *to_compare.first, *to_compare.second ); + compare_item_menu menu( *to_compare.first, *to_compare.second ); + menu.show(); } while( true ); } diff --git a/src/game_inventory.h b/src/game_inventory.h index cc8e6ad8036fa..7b42187a67b51 100644 --- a/src/game_inventory.h +++ b/src/game_inventory.h @@ -6,6 +6,7 @@ #include #include +#include "cata_imgui.h" #include "inventory_ui.h" #include "item.h" #include "item_location.h" @@ -71,6 +72,25 @@ void swap_letters(); * pressed, false for "quit" input. * @return False if confirm_message is empty or QUIT input was pressed. */ +class compare_item_menu : public cataimgui::window +{ + public: + compare_item_menu( const item &first, const item &second, const std::string &confirm_message = "" ); + bool show(); + + protected: + void draw_controls() override; + cataimgui::bounds get_bounds() override; + + private: + item first; + item second; + const std::string confirm_message; + input_context ctxt; + std::vector first_info; + std::vector second_info; + cataimgui::scroll s = cataimgui::scroll::none; +}; bool compare_items( const item &first, const item &second, const std::string &confirm_message = "" ); diff --git a/src/iuse.cpp b/src/iuse.cpp index 9004b4dbd9e25..c917647e26000 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -5327,7 +5327,7 @@ std::optional iuse::gunmod_attach( Character *p, item *it, const tripoint_b modded_gun.put_in( mod_copy, pocket_type::MOD ); - if( !game_menus::inv::compare_items( *loc, modded_gun, _( "Attach modification?" ) ) ) { + if( !game_menus::inv::compare_item_menu( *loc, modded_gun, _( "Attach modification?" ) ).show() ) { continue; } diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 46e1d039bdaea..e4f9e08e520c9 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -4421,7 +4421,7 @@ std::optional detach_gunmods_actor::use( Character *p, item &it, if( p->meets_requirements( *mods[mod_index], gun_copy ) || query_yn( _( "Are you sure? You may be lacking the skills needed to reattach this modification." ) ) ) { - if( game_menus::inv::compare_items( it, gun_copy, _( "Remove modification?" ) ) ) { + if( game_menus::inv::compare_item_menu( it, gun_copy, _( "Remove modification?" ) ).show() ) { p->gunmod_remove( it, *mods[mod_index] ); return 0; }