From: terencehill <piuntn@gmail.com>
Date: Mon, 1 Apr 2024 16:36:02 +0000 (+0200)
Subject: Scoreboard: limit width of field titles and show too long titles compressed. Max... 
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=640ba835e8cbe803fe66ec0e4c8457b91db6ad27;p=xonotic%2Fxonotic-data.pk3dir.git

Scoreboard: limit width of field titles and show too long titles compressed. Max width can be configured via hud_panel_scoreboard_table_fieldtitle_maxwidth
---

diff --git a/_hud_common.cfg b/_hud_common.cfg
index 95f1e9758b..954ffbd808 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 725baa408e..13434ec05c 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 de5a0d8095..ade633c22e 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;