Skip to content

Commit

Permalink
Compass widgets: Legend widget [code, data, doc, tests]
Browse files Browse the repository at this point in the history
  • Loading branch information
dseguin committed Jan 3, 2022
1 parent c240f49 commit 5975192
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 5 deletions.
10 changes: 8 additions & 2 deletions data/json/ui/compass.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,18 @@
"//": "An empty space indicating threats nearby",
"id": "compass_local_text",
"type": "widget",
"label": " ",
"style": "text",
"direction": "L",
"var": "compass_text",
"width": 6
},
{
"id": "compass_legend_text",
"type": "widget",
"style": "text",
"var": "compass_legend_text",
"width": 100
},
{
"id": "compass_top_layout",
"type": "widget",
Expand Down Expand Up @@ -108,6 +114,6 @@
"label": "Compass Alt",
"style": "layout",
"arrange": "rows",
"widgets": [ "compass_top_layout", "compass_middle_layout", "compass_bottom_layout" ]
"widgets": [ "compass_top_layout", "compass_middle_layout", "compass_bottom_layout", "compass_legend_text" ]
}
]
14 changes: 14 additions & 0 deletions data/mods/TEST_DATA/widgets.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@
"direction": "N",
"width": 4
},
{
"id": "test_compass_legend_5",
"type": "widget",
"style": "text",
"var": "compass_legend_text",
"width": 5
},
{
"id": "test_compass_legend_100",
"type": "widget",
"style": "text",
"var": "compass_legend_text",
"width": 100
},
{
"id": "test_speed_num",
"type": "widget",
Expand Down
1 change: 1 addition & 0 deletions doc/SIDEBAR_MOD.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ Some vars refer to text descriptors. These must use style "text". Examples:
| `weight_text` | "Emaciated", "Normal", "Overweight", etc.
| `date_text` | Current day within season, like "Summer, day 15"
| `compass_text` | A compass direction (ex: NE), displaying visible creatures in that direction
| `compass_legend_text` | A list of creatures visible by the player, corresponding to compass symbols

For example, a widget to show the current STR stat would define this "var":

Expand Down
53 changes: 53 additions & 0 deletions src/panels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2190,6 +2190,54 @@ static std::string get_compass_for_direction( const cardinal_direction dir, int
return ret;
}

static std::string get_compass_legend( const int max_width )
{
int wavail = max_width;
const monster_visible_info &mon_visible = get_avatar().get_mon_visible();
//~ Creature name format in compass legend. 1$ = symbol, 2$ = name. ex: "Z shocker zombie"
const std::string name_fmt = _( "%1$s %2$s" );
std::vector<std::string> names;
for( const std::vector<npc *> &nv : mon_visible.unique_types ) {
for( const npc *n : nv ) {
if( wavail < 0 ) {
break;
}
std::string name;
switch( n->get_attitude() ) {
case NPCATT_KILL:
name = colorize( "@", c_red );
break;
case NPCATT_FOLLOW:
name = colorize( "@", c_light_green );
break;
default:
name = colorize( "@", c_pink );
break;
}
name = string_format( name_fmt, name, n->name );
wavail -= utf8_width( name, true );
names.emplace_back( name );
}
}
std::map<const mtype *, int> mlist;
for( const auto &mv : mon_visible.unique_mons ) {
for( const std::pair<const mtype *, int> &m : mv ) {
mlist[m.first] += m.second;
}
}
for( const auto &m : mlist ) {
if( wavail < 0 ) {
break;
}
std::string name = m.second > 1 ? string_format( "%d ", m.second ) : "";
name += string_format( name_fmt, colorize( m.first->sym, m.first->color ),
m.first->nname( m.second ) );
wavail -= utf8_width( name, true );
names.emplace_back( name );
}
return enumerate_as_string( names, enumeration_conjunction::none );
}

std::pair<std::string, nc_color> display::compass_text_color( const cardinal_direction dir,
int width )
{
Expand All @@ -2199,6 +2247,11 @@ std::pair<std::string, nc_color> display::compass_text_color( const cardinal_dir
return { get_compass_for_direction( dir, width ), c_white };
}

std::pair<std::string, nc_color> display::compass_legend_text_color( int width )
{
return { get_compass_legend( width ), c_white };
}

static void draw_health_classic( const draw_args &args )
{
const avatar &u = args._ava;
Expand Down
1 change: 1 addition & 0 deletions src/panels.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ std::pair<std::string, nc_color> wind_text_color( const Character &u );

// Get visible threats by cardinal direction
std::pair<std::string, nc_color> compass_text_color( const cardinal_direction dir, int width );
std::pair<std::string, nc_color> compass_legend_text_color( int width );

// Define color for displaying the body temperature
nc_color bodytemp_color( const Character &u, const bodypart_id &bp );
Expand Down
19 changes: 16 additions & 3 deletions src/widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ std::string enum_to_string<widget_var>( widget_var data )
// Compass
case widget_var::compass_text:
return "compass_text";
case widget_var::compass_legend_text:
return "compass_legend_text";
// Base stats
case widget_var::stat_str:
return "stat_str";
Expand Down Expand Up @@ -441,6 +443,7 @@ bool widget::uses_text_function()
case widget_var::activity_text:
case widget_var::body_temp_text:
case widget_var::compass_text:
case widget_var::compass_legend_text:
case widget_var::date_text:
case widget_var::env_temp_text:
case widget_var::fatigue_text:
Expand Down Expand Up @@ -549,6 +552,11 @@ std::string widget::color_text_function_string( const avatar &ava )
// Skip colorization.
desc = display::compass_text_color( _direction, _width );
return desc.first;
case widget_var::compass_legend_text:
// Compass color is specific to individual threats.
// Skip colorization.
desc = display::compass_legend_text_color( _width );
return desc.first;
default:
debugmsg( "Unexpected widget_var %s - no text_color function defined",
io::enum_to_string<widget_var>( _var ) );
Expand Down Expand Up @@ -723,10 +731,15 @@ std::string widget::layout( const avatar &ava, const unsigned int max_width )
std::string shown = show( ava );
const std::string tlabel = _label.translated();
// Width used by label, ": " and value, using utf8_width to ignore color tags
unsigned int used_width = utf8_width( tlabel, true ) + 2 + utf8_width( shown, true );
unsigned int used_width = utf8_width( shown, true );

// If the label is blank or omitted, don't reserve space for it
if( !tlabel.empty() ) {
used_width += utf8_width( tlabel, true ) + 2;
// Label and ": " first
ret += tlabel + ": ";
}

// Label and ": " first
ret += tlabel + ": ";
// then enough padding to fit max_width
if( used_width < max_width ) {
ret += std::string( max_width - used_width, ' ' );
Expand Down
1 change: 1 addition & 0 deletions src/widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum class widget_var : int {
activity_text, // Activity level text, color string
body_temp_text, // Felt body temperature, color string
compass_text, // Compass / visible threats by cardinal direction
compass_legend_text, // Names of visible creatures that appear on the compass
date_text, // Current date, in terms of day within season
env_temp_text, // Environment temperature, if character has thermometer
fatigue_text, // Fagitue description text, color string
Expand Down
23 changes: 23 additions & 0 deletions tests/widget_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ static const widget_id widget_test_color_number_widget( "test_color_number_widge
static const widget_id widget_test_compass_N( "test_compass_N" );
static const widget_id widget_test_compass_N_nodir_nowidth( "test_compass_N_nodir_nowidth" );
static const widget_id widget_test_compass_N_nowidth( "test_compass_N_nowidth" );
static const widget_id widget_test_compass_legend_100( "test_compass_legend_100" );
static const widget_id widget_test_compass_legend_5( "test_compass_legend_5" );
static const widget_id widget_test_dex_num( "test_dex_num" );
static const widget_id widget_test_focus_num( "test_focus_num" );
static const widget_id widget_test_hp_head_graph( "test_hp_head_graph" );
Expand Down Expand Up @@ -407,6 +409,8 @@ TEST_CASE( "compass widget", "[widget]" )
widget c5s_N = widget_test_compass_N.obj();
widget c5s_N_nowidth = widget_test_compass_N_nowidth.obj();
widget c5s_N_nodir_nowidth = widget_test_compass_N_nodir_nowidth.obj();
widget c5s_legend5 = widget_test_compass_legend_5.obj();
widget c5s_legend100 = widget_test_compass_legend_100.obj();

avatar &ava = get_avatar();
clear_avatar();
Expand All @@ -420,6 +424,8 @@ TEST_CASE( "compass widget", "[widget]" )
CHECK( c5s_N.layout( ava ) == "N: " );
CHECK( c5s_N_nowidth.layout( ava ) == "N: " );
CHECK( c5s_N_nodir_nowidth.layout( ava ) == "N: " );
CHECK( c5s_legend5.layout( ava ).empty() );
CHECK( c5s_legend100.layout( ava ).empty() );
}

SECTION( "1 monster NE" ) {
Expand All @@ -433,6 +439,10 @@ TEST_CASE( "compass widget", "[widget]" )
CHECK( c5s_N.layout( ava ) == "N: " );
CHECK( c5s_N_nowidth.layout( ava ) == "N: " );
CHECK( c5s_N_nodir_nowidth.layout( ava ) == "N: " );
CHECK( c5s_legend5.layout( ava ) ==
"<color_c_white>B</color> monster producing CBMs when dissected" );
CHECK( c5s_legend100.layout( ava ) ==
"<color_c_white>B</color> monster producing CBMs when dissected" );
}

SECTION( "1 monster N" ) {
Expand All @@ -446,6 +456,10 @@ TEST_CASE( "compass widget", "[widget]" )
CHECK( c5s_N.layout( ava ) == "N: <color_c_white>B</color>" );
CHECK( c5s_N_nowidth.layout( ava ) == "N: <color_c_white>+</color>" );
CHECK( c5s_N_nodir_nowidth.layout( ava ) == "N: " );
CHECK( c5s_legend5.layout( ava ) ==
"<color_c_white>B</color> monster producing CBMs when dissected" );
CHECK( c5s_legend100.layout( ava ) ==
"<color_c_white>B</color> monster producing CBMs when dissected" );
}

SECTION( "3 same monsters N" ) {
Expand All @@ -464,6 +478,10 @@ TEST_CASE( "compass widget", "[widget]" )
CHECK( c5s_N.layout( ava ) == "N: <color_c_white>B</color>" );
CHECK( c5s_N_nowidth.layout( ava ) == "N: <color_c_white>+</color>" );
CHECK( c5s_N_nodir_nowidth.layout( ava ) == "N: " );
CHECK( c5s_legend5.layout( ava ) ==
"3 <color_c_white>B</color> monster producing CBMs when dissected" );
CHECK( c5s_legend100.layout( ava ) ==
"3 <color_c_white>B</color> monster producing CBMs when dissected" );
}

SECTION( "3 different monsters N" ) {
Expand All @@ -483,6 +501,11 @@ TEST_CASE( "compass widget", "[widget]" )
"N: <color_c_white>B</color><color_c_white>B</color><color_c_white>S</color>" );
CHECK( c5s_N_nowidth.layout( ava ) == "N: <color_c_white>+</color>" );
CHECK( c5s_N_nodir_nowidth.layout( ava ) == "N: " );
CHECK( c5s_legend5.layout( ava ) == "<color_c_white>S</color> shearable monster" );
CHECK( c5s_legend100.layout( ava ) ==
"<color_c_white>S</color> shearable monster, "
"<color_c_white>B</color> monster producing bovine samples when dissected, "
"<color_c_white>B</color> monster producing CBMs when dissected" );
}
}

Expand Down

0 comments on commit 5975192

Please sign in to comment.