diff --git a/src/options.cpp b/src/options.cpp index 3de63856f7868..f3ed90d568b92 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -2713,6 +2713,10 @@ std::string options_manager::show( bool ingame, const bool world_options_only, ingame = false; } + size_t sel_worldgen_tab = 1; + std::map> worldgen_tab_map; + std::map> opt_tab_map; + std::map> opt_line_map; std::map mapLines; mapLines[4] = true; mapLines[60] = true; @@ -2730,11 +2734,18 @@ std::string options_manager::show( bool ingame, const bool world_options_only, ctxt.register_action( "PREV_TAB" ); ctxt.register_action( "CONFIRM" ); ctxt.register_action( "HELP_KEYBINDINGS" ); + // for mouse selection + ctxt.register_action( "SELECT" ); + ctxt.register_action( "MOUSE_MOVE" ); + ctxt.register_action( "SEC_SELECT" ); + ctxt.register_action( "SCROLL_UP" ); + ctxt.register_action( "SCROLL_DOWN" ); const int iWorldOffset = world_options_only ? 2 : 0; int iMinScreenWidth = 0; const int iTooltipHeight = 6; int iContentHeight = 0; + bool recalc_startpos = false; catacurses::window w_options_border; catacurses::window w_options_tooltip; @@ -2779,8 +2790,10 @@ std::string options_manager::show( bool ingame, const bool world_options_only, ui.on_screen_resize( init_windows ); init_windows( ui ); ui.on_redraw( [&]( const ui_adaptor & ) { + opt_line_map.clear(); + opt_tab_map.clear(); if( world_options_only ) { - worldfactory::draw_worldgen_tabs( w_options_border, 1 ); + worldgen_tab_map = worldfactory::draw_worldgen_tabs( w_options_border, sel_worldgen_tab ); } draw_borders_external( w_options_border, iTooltipHeight + 1 + iWorldOffset, mapLines, @@ -2808,7 +2821,9 @@ std::string options_manager::show( bool ingame, const bool world_options_only, } } - calcStartPos( iStartPos, iCurrentLine, iContentHeight, page_items.size() ); + if( recalc_startpos ) { + calcStartPos( iStartPos, iCurrentLine, iContentHeight, page_items.size() ); + } // where the column with the names starts const size_t name_col = 5; @@ -2857,8 +2872,10 @@ std::string options_manager::show( bool ingame, const bool world_options_only, const std::string value = utf8_truncate( current_opt.getValueName(), value_width ); mvwprintz( w_options, point( value_col, line_pos ), - iCurrentLine == i ? hilite( cLineColor ) : cLineColor, - value ); + iCurrentLine == i ? hilite( cLineColor ) : cLineColor, value ); + + opt_line_map.emplace( i, inclusive_rectangle( point( name_col, line_pos ), + point( value_col + value_width - 1, line_pos ) ) ); } scrollbar() @@ -2872,6 +2889,7 @@ std::string options_manager::show( bool ingame, const bool world_options_only, wnoutrefresh( w_options_border ); //Draw Tabs + int tab_x = 0; if( !world_options_only ) { mvwprintz( w_options_header, point( 7, 0 ), c_white, "" ); for( int i = 0; i < static_cast( pages_.size() ); i++ ) { @@ -2885,6 +2903,11 @@ std::string options_manager::show( bool ingame, const bool world_options_only, } wprintz( w_options_header, c_white, "]" ); wputch( w_options_header, BORDER_COLOR, LINE_OXOX ); + tab_x++; + int tab_w = utf8_width( pages_[i].get().name_.translated(), true ); + opt_tab_map.emplace( i, inclusive_rectangle( point( 7 + tab_x, 0 ), + point( 6 + tab_x + tab_w, 0 ) ) ); + tab_x += tab_w + 2; } } @@ -2945,48 +2968,102 @@ std::string options_manager::show( bool ingame, const bool world_options_only, while( true ) { ui_manager::redraw(); + recalc_startpos = false; Page &page = pages_[iCurrentPage]; auto &page_items = page.items_; auto &cOPTIONS = ( ingame || world_options_only ) && iCurrentPage == iWorldOptPage ? ACTIVE_WORLD_OPTIONS : OPTIONS; - const std::string &opt_name = *page_items[iCurrentLine]; - cOpt ¤t_opt = cOPTIONS[opt_name]; + std::string action = ctxt.handle_input(); - const std::string action = ctxt.handle_input(); - - if( world_options_only && ( action == "NEXT_TAB" || action == "PREV_TAB" || - ( action == "QUIT" && ( !on_quit || on_quit() ) ) ) ) { + if( world_options_only && + ( action == "NEXT_TAB" || action == "PREV_TAB" || + ( ( action == "QUIT" || action == "SEC_SELECT" ) && ( !on_quit || on_quit() ) ) ) ) { return action; } + if( action == "MOUSE_MOVE" || action == "SELECT" ) { + bool found_opt = false; + sel_worldgen_tab = 1; + if( world_options_only ) { + // worldgen tabs + cata::optional coord = ctxt.get_coordinates_text( w_options_border ); + for( const auto &ent : worldgen_tab_map ) { + if( coord.has_value() && ent.second.contains( coord.value() ) ) { + found_opt = true; + sel_worldgen_tab = ent.first; + if( action == "SELECT" && sel_worldgen_tab != 1 ) { + return sel_worldgen_tab == 0 ? "PREV_TAB" : "NEXT_TAB"; + } + break; + } + } + } + if( !found_opt ) { + // option category tabs + cata::optional coord = ctxt.get_coordinates_text( w_options_header ); + for( const auto &ent : opt_tab_map ) { + if( coord.has_value() && ent.second.contains( coord.value() ) ) { + found_opt = true; + if( iCurrentPage != ent.first ) { + iCurrentLine = 0; + iStartPos = 0; + recalc_startpos = true; + iCurrentPage = clamp( ent.first, 0, pages_.size() - 1 ); + sfx::play_variant_sound( "menu_move", "default", 100 ); + } + break; + } + } + } + if( !found_opt ) { + // option lines + cata::optional coord = ctxt.get_coordinates_text( w_options ); + for( const auto &ent : opt_line_map ) { + if( coord.has_value() && ent.second.contains( coord.value() ) ) { + found_opt = true; + iCurrentLine = clamp( ent.first, 0, page_items.size() - 1 ); + if( action == "SELECT" ) { + action = "CONFIRM"; + } + break; + } + } + } + } + + const std::string &opt_name = *page_items[iCurrentLine]; + cOpt ¤t_opt = cOPTIONS[opt_name]; + bool hasPrerequisite = current_opt.hasPrerequisite(); bool hasPrerequisiteFulfilled = current_opt.checkPrerequisite(); if( hasPrerequisite && !hasPrerequisiteFulfilled && ( action == "RIGHT" || action == "LEFT" || action == "CONFIRM" ) ) { - popup( _( "Prerequisite for this option not met!\n(%s)" ), - get_options().get_option( current_opt.getPrerequisite() ).getMenuText() ); + popup( string_format( _( "Prerequisite for this option not met!\n(%s)" ), + get_options().get_option( current_opt.getPrerequisite() ).getMenuText() ), PF_MOUSECTRL ); continue; } const int recmax = static_cast( page_items.size() ); const int scroll_rate = recmax > 20 ? 10 : 3; - if( action == "DOWN" ) { + if( action == "DOWN" || action == "SCROLL_DOWN" ) { do { iCurrentLine++; if( iCurrentLine >= recmax ) { iCurrentLine = 0; } } while( !page_items[iCurrentLine] ); - } else if( action == "UP" ) { + recalc_startpos = true; + } else if( action == "UP" || action == "SCROLL_UP" ) { do { iCurrentLine--; if( iCurrentLine < 0 ) { iCurrentLine = page_items.size() - 1; } } while( !page_items[iCurrentLine] ); + recalc_startpos = true; } else if( action == "PAGE_DOWN" ) { if( iCurrentLine == recmax - 1 ) { iCurrentLine = 0; @@ -2998,6 +3075,7 @@ std::string options_manager::show( bool ingame, const bool world_options_only, iCurrentLine++; } } + recalc_startpos = true; } else if( action == "PAGE_UP" ) { if( iCurrentLine == 0 ) { iCurrentLine = recmax - 1; @@ -3009,13 +3087,17 @@ std::string options_manager::show( bool ingame, const bool world_options_only, iCurrentLine--; } } + recalc_startpos = true; } else if( action == "RIGHT" ) { current_opt.setNext(); + recalc_startpos = true; } else if( action == "LEFT" ) { current_opt.setPrev(); + recalc_startpos = true; } else if( action == "NEXT_TAB" ) { iCurrentLine = 0; iStartPos = 0; + recalc_startpos = true; iCurrentPage++; if( iCurrentPage >= static_cast( pages_.size() ) ) { iCurrentPage = 0; @@ -3024,6 +3106,7 @@ std::string options_manager::show( bool ingame, const bool world_options_only, } else if( action == "PREV_TAB" ) { iCurrentLine = 0; iStartPos = 0; + recalc_startpos = true; iCurrentPage--; if( iCurrentPage < 0 ) { iCurrentPage = pages_.size() - 1; @@ -3054,7 +3137,7 @@ std::string options_manager::show( bool ingame, const bool world_options_only, current_opt.setValue( tmpFloat ); } else { - popup( _( "Invalid input: not a number" ) ); + popup( _( "Invalid input: not a number" ), PF_MOUSECTRL ); } } else { // option is of type "int": string_input_popup @@ -3064,7 +3147,7 @@ std::string options_manager::show( bool ingame, const bool world_options_only, } } } - } else if( action == "QUIT" ) { + } else if( action == "QUIT" || action == "SEC_SELECT" ) { break; } } @@ -3110,7 +3193,7 @@ std::string options_manager::show( bool ingame, const bool world_options_only, } if( options_changed ) { - if( query_yn( _( "Save changes?" ) ) ) { + if( query_yn_mouse( _( "Save changes?" ) ) ) { static_popup popup; popup.message( "%s", _( "Please wait…\nApplying option changes…" ) ); ui_manager::redraw();