From 196f7ec9f2fe35ef6cb1b2eec93b9d5b307c14d2 Mon Sep 17 00:00:00 2001 From: mqrause Date: Thu, 2 May 2024 14:28:15 +0200 Subject: [PATCH 1/2] imgui iteminfo window --- src/output.h | 1 + src/ui_iteminfo.cpp | 194 ++++++++++++++++++++++++++++++++++++++++++++ src/ui_iteminfo.h | 42 ++++++++++ 3 files changed, 237 insertions(+) create mode 100644 src/ui_iteminfo.cpp create mode 100644 src/ui_iteminfo.h diff --git a/src/output.h b/src/output.h index cf0db139347b3..05239be551cc3 100644 --- a/src/output.h +++ b/src/output.h @@ -573,6 +573,7 @@ struct item_info_data { bool without_getch = false; bool without_border = false; bool handle_scrolling = false; + bool arrow_scrolling = false; bool any_input = true; bool scrollbar_left = true; bool use_full_win = false; diff --git a/src/ui_iteminfo.cpp b/src/ui_iteminfo.cpp new file mode 100644 index 0000000000000..9d30676d54f07 --- /dev/null +++ b/src/ui_iteminfo.cpp @@ -0,0 +1,194 @@ +#include "ui_iteminfo.h" + +#include "messages.h" +#include "ui_manager.h" +#include "imgui/imgui_internal.h" + + +static void set_scroll( scroll &s ) +{ + int scroll_px = 0; + int line_height = ImGui::GetTextLineHeightWithSpacing(); + int page_height = ImGui::GetContentRegionAvail().y; + + switch( s ) { + case scroll::none: + break; + case scroll::line_up: + scroll_px = -line_height; + break; + case scroll::line_down: + scroll_px = line_height; + break; + case scroll::page_up: + scroll_px = -page_height; + break; + case scroll::page_down: + scroll_px = page_height; + break; + } + + ImGui::SetScrollY( ImGui::GetScrollY() + scroll_px ); + + s = scroll::none; +} + +void draw_item_info_imgui( cataimgui::window &window, item_info_data &data, int width, scroll &s ) +{ + // Setting scroll needs to happen before drawing contents for page scroll to work properly + set_scroll( s ); + + float wrap_width = window.str_width_to_pixels( width - 2 ); + nc_color base_color = c_light_gray; + + if( !data.get_item_name().empty() ) { + cataimgui::draw_colored_text( data.get_item_name(), base_color, wrap_width ); + ImGui::Spacing(); + } + if( !data.get_type_name().empty() && + data.get_item_name().find( data.get_type_name() ) == std::string::npos ) { + cataimgui::draw_colored_text( data.get_type_name(), base_color, wrap_width ); + } + + bool same_line = false; + for( const iteminfo &i : data.get_item_display() ) { + if( i.sType == "DESCRIPTION" ) { + if( i.bDrawName ) { + if( i.sName == "--" ) { + ImGui::Separator(); + } else { + cataimgui::draw_colored_text( i.sName, base_color, wrap_width ); + } + } + } else { + std::string formatted_string; + if( i.bDrawName ) { + formatted_string = i.sName; + } + + std::string sFmt = i.sFmt; + + //A bit tricky, find %d and split the string + size_t pos = sFmt.find( "" ); + if( pos != std::string::npos ) { + formatted_string += sFmt.substr( 0, pos ); + } else { + formatted_string += sFmt; + } + + if( i.sValue != "-999" ) { + nc_color this_color = c_yellow; + for( const iteminfo &k : data.get_item_compare() ) { + if( k.sValue != "-999" ) { + if( i.sName == k.sName && i.sType == k.sType ) { + double iVal = i.dValue; + double kVal = k.dValue; + if( i.sFmt != k.sFmt ) { + // Different units, compare unit adjusted vals + iVal = i.dUnitAdjustedVal; + kVal = k.dUnitAdjustedVal; + } + if( iVal > kVal - .01 && + iVal < kVal + .01 ) { + this_color = c_light_gray; + } else if( iVal > kVal ) { + if( i.bLowerIsBetter ) { + this_color = c_light_red; + } else { + this_color = c_light_green; + } + } else if( iVal < kVal ) { + if( i.bLowerIsBetter ) { + this_color = c_light_green; + } else { + this_color = c_light_red; + } + } + break; + } + } + } + formatted_string += colorize( i.sValue, this_color ); + } + + if( pos != std::string::npos ) { + formatted_string += sFmt.substr( pos + 5 ); + } + + if( !formatted_string.empty() ) { + if( same_line ) { + ImGui::SameLine( 0, 0 ); + } + cataimgui::draw_colored_text( formatted_string, base_color, wrap_width ); + } + same_line = !i.bNewLine; + } + } +} + +iteminfo_window::iteminfo_window( item_info_data &info, point pos, int width, int height, + ImGuiWindowFlags flags ) : + cataimgui::window( _( "Item info" ), flags ), + data( info ), pos( pos ), width( width ), height( height ) +{ + ctxt = input_context( "default" ); + if( info.handle_scrolling ) { + ctxt.register_action( "PAGE_UP" ); + ctxt.register_action( "PAGE_DOWN" ); + if( info.arrow_scrolling ) { + ctxt.register_action( "UP" ); + ctxt.register_action( "DOWN" ); + } + } + ctxt.register_action( "CONFIRM" ); + ctxt.register_action( "QUIT" ); + if( info.any_input ) { + ctxt.register_action( "ANY_INPUT" ); + } + + ctxt.set_timeout( 10 ); +} + +cataimgui::bounds iteminfo_window::get_bounds() +{ + return { pos.x < 0 ? -1.f : static_cast( str_width_to_pixels( pos.x ) ), + pos.y < 0 ? -1.f : static_cast( str_height_to_pixels( pos.y ) ), + static_cast( str_width_to_pixels( width ) ), + static_cast( str_height_to_pixels( height ) ) }; +} + +void iteminfo_window::draw_controls() +{ + draw_item_info_imgui( *this, data, width, s ); +} + +void iteminfo_window::execute() +{ + if( data.without_getch ) { + ui_manager::redraw(); + return; + } + + while( true ) { + ui_manager::redraw(); + std::string action = ctxt.handle_input(); + + if( data.handle_scrolling && data.arrow_scrolling && action == "UP" ) { + s = scroll::line_up; + } else if( data.handle_scrolling && data.arrow_scrolling && action == "DOWN" ) { + s = scroll::line_down; + } else if( data.handle_scrolling && action == "PAGE_UP" ) { + s = scroll::page_up; + } else if( data.handle_scrolling && action == "PAGE_DOWN" ) { + s = scroll::page_down; + } else if( action == "CONFIRM" || action == "QUIT" || + ( data.any_input && action == "ANY_INPUT" && !ctxt.get_raw_input().sequence.empty() ) ) { + break; + } + + // mouse click on x to close leads here + if( !get_is_open() ) { + break; + } + } +} diff --git a/src/ui_iteminfo.h b/src/ui_iteminfo.h new file mode 100644 index 0000000000000..038f523bee08e --- /dev/null +++ b/src/ui_iteminfo.h @@ -0,0 +1,42 @@ +#pragma once +#ifndef CATA_SRC_UI_ITEMINFO_H +#define CATA_SRC_UI_ITEMINFO_H + +#include "cata_imgui.h" +#include "input_context.h" +#include "output.h" +#include "imgui/imgui.h" + +enum class scroll : int { + none = 0, + line_up, + line_down, + page_up, + page_down +}; + +void draw_item_info_imgui( cataimgui::window &window, item_info_data &data, int width, + scroll &s ); + +class iteminfo_window : public cataimgui::window +{ + public: + iteminfo_window( item_info_data &info, point pos, int width, int height, + ImGuiWindowFlags flags = ImGuiWindowFlags_None ); + void execute(); + + protected: + void draw_controls() override; + cataimgui::bounds get_bounds() override; + + private: + item_info_data data; + point pos; + int width; + int height; + input_context ctxt; + + scroll s; +}; + +#endif // CATA_SRC_UI_ITEMINFO_H From 9fce736edceac48ed5a2677118e44ec500a64a75 Mon Sep 17 00:00:00 2001 From: mqrause Date: Thu, 2 May 2024 14:29:03 +0200 Subject: [PATCH 2/2] enable imgui iteminfo on examine in inventory selector, aim and crafting menu --- src/advanced_inv.cpp | 7 ++++--- src/crafting_gui.cpp | 12 +++++++----- src/inventory_ui.cpp | 11 ++++++----- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/advanced_inv.cpp b/src/advanced_inv.cpp index 3f947f9ef7942..472fcc73fee81 100644 --- a/src/advanced_inv.cpp +++ b/src/advanced_inv.cpp @@ -60,6 +60,7 @@ #include "translations.h" #include "type_id.h" #include "ui.h" +#include "ui_iteminfo.h" #include "ui_manager.h" #include "uistate.h" #include "units.h" @@ -1792,10 +1793,10 @@ void advanced_inventory::action_examine( advanced_inv_listitem *sitem, item_info_data data( it.tname(), it.type_name(), vThisItem, vDummy ); data.handle_scrolling = true; + data.arrow_scrolling = true; - ret = draw_item_info( [&]() -> catacurses::window { - return catacurses::newwin( 0, info_width(), point( info_startx(), 0 ) ); - }, data ).get_first_input(); + iteminfo_window info_window( data, point( info_startx(), 0 ), info_width(), TERMY ); + info_window.execute(); } if( ret == KEY_NPAGE || ret == KEY_DOWN ) { spane.scroll_by( +1 ); diff --git a/src/crafting_gui.cpp b/src/crafting_gui.cpp index 06a15c5d356e9..7643b38f69293 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -59,6 +59,7 @@ #include "translations.h" #include "type_id.h" #include "ui.h" +#include "ui_iteminfo.h" #include "ui_manager.h" #include "uistate.h" @@ -1865,11 +1866,12 @@ std::pair select_crafter_and_crafting_recipe( int & item_info_data data = result_info.get_result_data( current[line], 1, line_item_info_popup, w_iteminfo ); data.handle_scrolling = true; - draw_item_info( []() -> catacurses::window { - const int width = std::min( TERMX, FULL_SCREEN_WIDTH ); - const int height = std::min( TERMY, FULL_SCREEN_HEIGHT ); - return catacurses::newwin( height, width, point( ( TERMX - width ) / 2, ( TERMY - height ) / 2 ) ); - }, data ); + data.arrow_scrolling = true; + const int info_width = std::min( TERMX, FULL_SCREEN_WIDTH ); + const int info_height = std::min( TERMY, FULL_SCREEN_HEIGHT ); + iteminfo_window info_window( data, point( ( TERMX - info_width ) / 2, ( TERMY - info_height ) / 2 ), + info_width, info_height ); + info_window.execute(); } else if( action == "FILTER" ) { int max_example_length = 0; for( const auto &prefix : prefixes ) { diff --git a/src/inventory_ui.cpp b/src/inventory_ui.cpp index ca45c87b48a1e..0146fb152f673 100644 --- a/src/inventory_ui.cpp +++ b/src/inventory_ui.cpp @@ -40,6 +40,7 @@ #include "translations.h" #include "type_id.h" #include "uistate.h" +#include "ui_iteminfo.h" #include "ui_manager.h" #include "units.h" #include "units_utility.h" @@ -3476,11 +3477,11 @@ void inventory_selector::action_examine( const item_location &sitem ) item_info_data data( sitem->tname(), sitem->type_name(), vThisItem, vDummy ); data.handle_scrolling = true; - draw_item_info( [&]() -> catacurses::window { - int maxwidth = std::max( FULL_SCREEN_WIDTH, TERMX ); - int width = std::min( 80, maxwidth ); - return catacurses::newwin( 0, width, point( maxwidth / 2 - width / 2, 0 ) ); }, - data ).get_first_input(); + data.arrow_scrolling = true; + int maxwidth = std::max( FULL_SCREEN_WIDTH, TERMX ); + int width = std::min( 80, maxwidth ); + iteminfo_window info_window( data, point( maxwidth / 2 - width / 2, -1 ), width, 0 ); + info_window.execute(); } void inventory_selector::highlight()