From 640ba835e8cbe803fe66ec0e4c8457b91db6ad27 Mon Sep 17 00:00:00 2001 From: terencehill Date: Mon, 1 Apr 2024 18:36:02 +0200 Subject: [PATCH] Scoreboard: limit width of field titles and show too long titles compressed. Max width can be configured via hud_panel_scoreboard_table_fieldtitle_maxwidth --- _hud_common.cfg | 1 + qcsrc/client/command/cl_cmd.qh | 2 +- qcsrc/client/hud/panel/scoreboard.qc | 100 ++++++++++++++++++++++----- 3 files changed, 83 insertions(+), 20 deletions(-) diff --git a/_hud_common.cfg b/_hud_common.cfg index 95f1e9758..954ffbd80 100644 --- a/_hud_common.cfg +++ b/_hud_common.cfg @@ -142,6 +142,7 @@ seta hud_panel_scoreboard_spectators_showping 1 "show ping of spectators" seta hud_panel_scoreboard_spectators_aligned 0 "align spectators in columns" seta hud_panel_scoreboard_spectators_position 1 "spectator list position (0 = before accuracy and itemstats, 1 = before rankings, 2 = after rankings, 3 = after map stats)" seta hud_panel_scoreboard_minwidth 0.6 "minimum width of the scoreboard" +seta hud_panel_scoreboard_table_fieldtitle_maxwidth 0.07 "max width of a field title; if the title is longer it will be shown compressed" seta hud_panel_scoreboard_team_size_position 0 "where to show the team size (0 = do not show, 1 = left of scoreboard, 2 = right of scoreboard), will move team scores to the other side if necessary" seta hud_panel_scoreboard_ping_best 0 "use best_color for this ping" seta hud_panel_scoreboard_ping_medium 70 "use medium_color for this ping" diff --git a/qcsrc/client/command/cl_cmd.qh b/qcsrc/client/command/cl_cmd.qh index 725baa408..13434ec05 100644 --- a/qcsrc/client/command/cl_cmd.qh +++ b/qcsrc/client/command/cl_cmd.qh @@ -1,6 +1,6 @@ #pragma once -void Cmd_Scoreboard_SetFields(int); +void Cmd_Scoreboard_SetFields(int argc); void Cmd_Scoreboard_Help(); void ConsoleCommand_macro_init(); diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index de5a0d809..ade633c22 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -43,10 +43,12 @@ const int MAX_SBT_FIELDS = MAX_SCORE; PlayerScoreField sbt_field[MAX_SBT_FIELDS + 1]; float sbt_field_size[MAX_SBT_FIELDS + 1]; string sbt_field_title[MAX_SBT_FIELDS + 1]; +float sbt_field_title_condense_factor[MAX_SBT_FIELDS + 1]; +float sbt_field_title_width[MAX_SBT_FIELDS + 1]; int sbt_num_fields; +float sbt_field_title_maxwidth; string autocvar_hud_fontsize; -string hud_fontsize_str; float max_namesize; float sbt_bg_alpha; @@ -75,6 +77,7 @@ float autocvar_hud_panel_scoreboard_table_bg_alpha = 0; float autocvar_hud_panel_scoreboard_table_bg_scale = 0.25; float autocvar_hud_panel_scoreboard_table_fg_alpha = 0.9; float autocvar_hud_panel_scoreboard_table_fg_alpha_self = 1; +float autocvar_hud_panel_scoreboard_table_fieldtitle_maxwidth = 0.07; bool autocvar_hud_panel_scoreboard_table_highlight = true; float autocvar_hud_panel_scoreboard_table_highlight_alpha = 0.2; float autocvar_hud_panel_scoreboard_table_highlight_alpha_self = 0.4; @@ -839,7 +842,6 @@ void Cmd_Scoreboard_SetFields(int argc) str = strtolower(str); strcpy(sbt_field_title[sbt_num_fields], TranslateScoresLabel(str)); - sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize); PlayerScoreField j; switch(str) @@ -870,7 +872,6 @@ void Cmd_Scoreboard_SetFields(int argc) LOG_INFOF("^1Error:^7 Unknown score field: '%s'", str); strfree(sbt_field_title[sbt_num_fields]); - sbt_field_size[sbt_num_fields] = 0; continue; LABEL(found) @@ -903,7 +904,6 @@ void Cmd_Scoreboard_SetFields(int argc) for(i = sbt_num_fields; i > 0; --i) { sbt_field_title[i] = sbt_field_title[i-1]; - sbt_field_size[i] = sbt_field_size[i-1]; sbt_field[i] = sbt_field[i-1]; } sbt_field_title[0] = strzone(TranslateScoresLabel("name")); @@ -917,12 +917,10 @@ void Cmd_Scoreboard_SetFields(int argc) for(i = sbt_num_fields; i > 1; --i) { sbt_field_title[i] = sbt_field_title[i-1]; - sbt_field_size[i] = sbt_field_size[i-1]; sbt_field[i] = sbt_field[i-1]; } sbt_field_title[1] = strzone("|"); sbt_field[1] = SP_SEPARATOR; - sbt_field_size[1] = stringwidth("|", false, hud_fontsize); ++sbt_num_fields; LOG_INFO("fixed missing field '|'"); } @@ -930,7 +928,6 @@ void Cmd_Scoreboard_SetFields(int argc) else if(!have_separator) { strcpy(sbt_field_title[sbt_num_fields], "|"); - sbt_field_size[sbt_num_fields] = stringwidth("|", false, hud_fontsize); sbt_field[sbt_num_fields] = SP_SEPARATOR; ++sbt_num_fields; LOG_INFO("fixed missing field '|'"); @@ -938,7 +935,6 @@ void Cmd_Scoreboard_SetFields(int argc) if(!have_secondary) { strcpy(sbt_field_title[sbt_num_fields], TranslateScoresLabel(scores_label(ps_secondary))); - sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize); sbt_field[sbt_num_fields] = ps_secondary; ++sbt_num_fields; LOG_INFOF("fixed missing field '%s'", scores_label(ps_secondary)); @@ -946,7 +942,6 @@ void Cmd_Scoreboard_SetFields(int argc) if(!have_primary) { strcpy(sbt_field_title[sbt_num_fields], TranslateScoresLabel(scores_label(ps_primary))); - sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize); sbt_field[sbt_num_fields] = ps_primary; ++sbt_num_fields; LOG_INFOF("fixed missing field '%s'", scores_label(ps_primary)); @@ -954,6 +949,7 @@ void Cmd_Scoreboard_SetFields(int argc) } sbt_field[sbt_num_fields] = SP_END; + sbt_field_size[0] = 0; // tells Scoreboard_Draw to initialize all field sizes } string Scoreboard_AddPlayerId(string pl_name, entity pl) @@ -1165,7 +1161,7 @@ float sbt_fixcolumnwidth_len; float sbt_fixcolumnwidth_iconlen; float sbt_fixcolumnwidth_marginlen; -string Scoreboard_FixColumnWidth(int i, string str) +string Scoreboard_FixColumnWidth(int i, string str, bool init) { TC(int, i); float f; @@ -1205,6 +1201,9 @@ string Scoreboard_FixColumnWidth(int i, string str) else sbt_fixcolumnwidth_marginlen = 0; + if (init) + sbt_field_title_width[i] = stringwidth(sbt_field_title[i], false, hud_fontsize); + if(sbt_field[i] == SP_NAME) // name gets all remaining space { int j; @@ -1213,33 +1212,59 @@ string Scoreboard_FixColumnWidth(int i, string str) if(j != i) if (sbt_field[i] != SP_SEPARATOR) remaining_space += sbt_field_size[j] + hud_fontsize.x; - sbt_field_size[i] = panel_size.x - remaining_space; + sbt_field_size[i] = max(sbt_field_title_width[i], panel_size.x - remaining_space); if (sbt_fixcolumnwidth_iconlen != 0) remaining_space += sbt_fixcolumnwidth_marginlen + sbt_fixcolumnwidth_iconlen * hud_fontsize.x; - float namesize = panel_size.x - remaining_space; + float namesize = max(sbt_field_title_width[i], panel_size.x - remaining_space); str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors); sbt_fixcolumnwidth_len = stringwidth(str, true, hud_fontsize); - max_namesize = vid_conwidth - remaining_space; + max_namesize = max(sbt_field_title_width[i], vid_conwidth - remaining_space); } else + { + if (init) + { + sbt_field_size[i] = sbt_field_title_width[i]; + if (sbt_field_size[i] && sbt_field_size[i] > sbt_field_title_maxwidth) + sbt_field_size[i] = sbt_field_title_maxwidth; + } sbt_fixcolumnwidth_len = stringwidth(str, false, hud_fontsize); + } f = sbt_fixcolumnwidth_len + sbt_fixcolumnwidth_marginlen + sbt_fixcolumnwidth_iconlen * hud_fontsize.x; if(sbt_field_size[i] < f) sbt_field_size[i] = f; + sbt_field_title_condense_factor[i] = 0; + if (sbt_field_title_width[i] > sbt_field_size[i]) + { + float real_maxwidth = sbt_field_size[i]; + if (sbt_field_title_width[i] > sbt_field_title_maxwidth) + real_maxwidth = max(sbt_field_size[i], sbt_field_title_maxwidth); + sbt_field_title_condense_factor[i] = real_maxwidth / sbt_field_title_width[i]; + } + return str; } void Scoreboard_initFieldSizes() { + int name_index = 0; for(int i = 0; i < sbt_num_fields; ++i) { - sbt_field_size[i] = stringwidth(sbt_field_title[i], false, hud_fontsize); - Scoreboard_FixColumnWidth(i, ""); + if (sbt_field[i] == SP_NAME) + { + name_index = i; + continue; + } + + Scoreboard_FixColumnWidth(i, "", true); } + + // update name field size in the end as it takes remaining space + Scoreboard_FixColumnWidth(name_index, "", true); } vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players) @@ -1258,7 +1283,15 @@ vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players) if (sbt_highlight) if (i % 2) drawfill(pos - eX * hud_fontsize.x * 0.5, column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL); + vector prev_drawfontscale = drawfontscale; + if (sbt_field_title_condense_factor[i]) + drawfontscale.x *= sbt_field_title_condense_factor[i]; drawstring(pos + text_offset, sbt_field_title[i], hud_fontsize, rgb * 1.5, sbt_fg_alpha, DRAWFLAG_NORMAL); + if (sbt_field_title_condense_factor[i]) + { + drawfontscale.x *= sbt_field_title_condense_factor[i]; + drawfontscale = prev_drawfontscale; + } pos.x += column_dim.x; } if(sbt_field[i] == SP_SEPARATOR) @@ -1278,8 +1311,21 @@ vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players) drawfill(pos - eX * hud_fontsize.x * 0.5, column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL); } - text_offset.x = sbt_field_size[i] - stringwidth(sbt_field_title[i], false, hud_fontsize); + vector prev_drawfontscale = drawfontscale; + float titlewidth = stringwidth(sbt_field_title[i], false, hud_fontsize); + if (sbt_field_title_condense_factor[i]) + { + drawfontscale.x *= sbt_field_title_condense_factor[i]; + text_offset.x = sbt_field_size[i] - titlewidth * sbt_field_title_condense_factor[i]; + } + else + text_offset.x = sbt_field_size[i] - titlewidth; drawstring(pos + text_offset, sbt_field_title[i], hud_fontsize, rgb * 1.5, sbt_fg_alpha, DRAWFLAG_NORMAL); + if (sbt_field_title_condense_factor[i]) + { + drawfontscale.x *= sbt_field_title_condense_factor[i]; + drawfontscale = prev_drawfontscale; + } pos.x -= hud_fontsize.x; } } @@ -1331,7 +1377,7 @@ void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, i continue; } str = Scoreboard_GetField(pl, field, autocvar_hud_panel_scoreboard_scores_per_round); - str = Scoreboard_FixColumnWidth(i, str); + str = Scoreboard_FixColumnWidth(i, str, false); pos.x += sbt_field_size[i] + hud_fontsize.x; @@ -1367,7 +1413,7 @@ void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, i } str = Scoreboard_GetField(pl, field, autocvar_hud_panel_scoreboard_scores_per_round); - str = Scoreboard_FixColumnWidth(i, str); + str = Scoreboard_FixColumnWidth(i, str, false); if(field == SP_NAME) { tmp.x = sbt_fixcolumnwidth_len; // left or right aligned? let's put it right... @@ -2240,6 +2286,8 @@ string Scoreboard_Fraglimit_Draw(float limit, bool is_leadlimit) void Scoreboard_Draw() { + bool sb_init_field_sizes = false; + if(!autocvar__hud_configure) { if(!hud_draw_maximized) return; @@ -2255,11 +2303,21 @@ void Scoreboard_Draw() scoreboard_fade_alpha = min(1, scoreboard_fade_alpha + frametime * scoreboard_fadeinspeed); else scoreboard_fade_alpha = 1; + + static string hud_fontsize_str; if(hud_fontsize_str != autocvar_hud_fontsize) { hud_fontsize = HUD_GetFontsize("hud_fontsize"); - Scoreboard_initFieldSizes(); strcpy(hud_fontsize_str, autocvar_hud_fontsize); + sb_init_field_sizes = true; + } + + static float scoreboard_table_fieldtitle_maxwidth_prev; + if (scoreboard_table_fieldtitle_maxwidth_prev != autocvar_hud_panel_scoreboard_table_fieldtitle_maxwidth) + { + scoreboard_table_fieldtitle_maxwidth_prev = autocvar_hud_panel_scoreboard_table_fieldtitle_maxwidth; + sbt_field_title_maxwidth = vid_conwidth * max(0.01, autocvar_hud_panel_scoreboard_table_fieldtitle_maxwidth); + sb_init_field_sizes = true; } } else { @@ -2309,6 +2367,10 @@ void Scoreboard_Draw() panel_pos.x = scoreboard_left; panel_size.x = fixed_scoreboard_width; + // field sizes can be initialized now after panel_size.x calculation + if (!sbt_field_size[0] || sb_init_field_sizes) + Scoreboard_initFieldSizes(); + Scoreboard_UpdatePlayerTeams(); scoreboard_top = panel_pos.y; -- 2.39.2