From 83aaf9e2c9e1873e8e3825c1a0a4a2833859b84b Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Sun, 15 Oct 2023 13:52:11 -0400 Subject: [PATCH] Tweak display of alt name, also add to tooltip info --- doc/AutoratingServer.md | 4 +- src/multiint.cpp | 123 ++++++++++++++++++++++++++++++++-------- src/multistat.cpp | 12 ++-- src/multistat.h | 4 +- 4 files changed, 110 insertions(+), 33 deletions(-) diff --git a/doc/AutoratingServer.md b/doc/AutoratingServer.md index c153c40d783..a6297bdfc67 100644 --- a/doc/AutoratingServer.md +++ b/doc/AutoratingServer.md @@ -27,8 +27,8 @@ The server must return a response code 200 and some data json format. Otherwise * `elo` (string): the text to display under the player's name. * `autohoster` (boolean): if the player is a dedicated hoster. It will have an hoster icon instead of a medal and no stars. * `details` (string): notes to display in the player's tooltip. -* `name` (string): overrides name of the player in lobby (optional) (ignored if empty). -* `nameTextColorOverride` (array of three integers): overrides name color in lobby (rgb 0-255) ([255,255,255] will result in default coloring) (optional). +* `name` (string): provides an alternative name of the player in lobby (optional) (ignored if empty). +* `nameTextColorOverride` (array of three integers): overrides alt name color in lobby (rgb 0-255) ([255,255,255] will result in default coloring) (optional). * `eloTextColorOverride` (array of three integers): overrides elo text color in lobby (rgb 0-255) (optional). ### Response sample diff --git a/src/multiint.cpp b/src/multiint.cpp index f8a6ba9235d..4733dd728d4 100644 --- a/src/multiint.cpp +++ b/src/multiint.cpp @@ -225,6 +225,9 @@ struct DisplayPlayerCache { std::string fullMainText; // the “full” main text (used for storing the full player name when displaying a player) WzText wzMainText; // the main text + std::string fullAltNameText; + WzText wzAltNameText; + WzText wzSubText; // the sub text (used for players) WzText wzEloText; // the elo text (used for players) }; @@ -4313,33 +4316,62 @@ class WzPlayerRow : public WIDGET playerInfoTooltip += _("Player ID: "); playerInfoTooltip += hash.empty()? _("(none)") : hash; } - if (stats.autorating.valid && !stats.autorating.details.empty() - && stats.autoratingFrom == RATING_SOURCE_LOCAL) // do not display host-provided details (for now) + std::string autoratingTooltipText; + if (stats.autorating.valid) { - if (!playerInfoTooltip.empty()) + if (!stats.autorating.altName.empty()) { - playerInfoTooltip += "\n\n"; + if (!autoratingTooltipText.empty()) + { + autoratingTooltipText += "\n"; + } + std::string altnameStr = stats.autorating.altName; + if (altnameStr.size() > 128) + { + altnameStr = altnameStr.substr(0, 128); + } + size_t maxLinePos = nthOccurrenceOfChar(altnameStr, '\n', 1); + if (maxLinePos != std::string::npos) + { + altnameStr = altnameStr.substr(0, maxLinePos); + } + autoratingTooltipText += std::string(_("Alt Name:")) + " " + altnameStr; } - std::string detailsstr = stats.autorating.details; - if (detailsstr.size() > 512) + if (!stats.autorating.details.empty() + && stats.autoratingFrom == RATING_SOURCE_LOCAL) // do not display host-provided details (for now) { - detailsstr = detailsstr.substr(0, 512); + if (!autoratingTooltipText.empty()) + { + autoratingTooltipText += "\n"; + } + std::string detailsstr = stats.autorating.details; + if (detailsstr.size() > 512) + { + detailsstr = detailsstr.substr(0, 512); + } + size_t maxLinePos = nthOccurrenceOfChar(detailsstr, '\n', 10); + if (maxLinePos != std::string::npos) + { + detailsstr = detailsstr.substr(0, maxLinePos); + } + autoratingTooltipText += std::string(_("Player rating:")) + "\n" + detailsstr; } - size_t maxLinePos = nthOccurrenceOfChar(detailsstr, '\n', 10); - if (maxLinePos != std::string::npos) + } + if (!autoratingTooltipText.empty()) + { + if (!playerInfoTooltip.empty()) { - detailsstr = detailsstr.substr(0, maxLinePos); + playerInfoTooltip += "\n\n"; } - playerInfoTooltip += std::string(_("Player rating:")) + "\n"; if (stats.autoratingFrom == RATING_SOURCE_HOST) { - playerInfoTooltip += std::string("(") + _("Host provided") + ")"; + playerInfoTooltip += std::string("[") + _("Host provided") + "]\n"; } else { - playerInfoTooltip += std::string("(") + astringf(_("From: %s"), getAutoratingUrl().c_str()) + ")"; + playerInfoTooltip += std::string("[") + astringf(_("From: %s"), getAutoratingUrl().c_str()) + "]\n"; } - playerInfoTooltip += "\n" + detailsstr; + playerInfoTooltip += autoratingTooltipText; } } playerInfo->setTip(playerInfoTooltip); @@ -7657,6 +7689,28 @@ static bool isKnownPlayer(std::map const &knownPlayers, return i != knownPlayers.end() && key.toBytes(EcKey::Public) == i->second; } +static void displayAltNameBox(int x, int y, WIDGET *psWidget, DisplayPlayerCache& cache, const PLAYERSTATS::Autorating& ar, bool isHighlight) +{ + int altNameBoxWidth = cache.wzAltNameText.width() + 4; + int altNameBoxHeight = cache.wzAltNameText.lineSize() + 2; + int altNameBoxX0 = (x + psWidget->width()) - altNameBoxWidth; + PIELIGHT altNameBoxColor = WZCOL_MENU_BORDER; + altNameBoxColor.byte.a = static_cast(static_cast(altNameBoxColor.byte.a) * (isHighlight ? 0.3f : 0.75f)); + pie_UniTransBoxFill(altNameBoxX0, y, altNameBoxX0 + altNameBoxWidth, y + altNameBoxHeight, altNameBoxColor); + + int altNameTextY0 = y + (altNameBoxHeight - cache.wzAltNameText.lineSize()) / 2 - cache.wzAltNameText.aboveBase(); + PIELIGHT altNameTextColor = WZCOL_TEXT_MEDIUM; + if (ar.altNameTextColorOverride[0] != 255 || ar.altNameTextColorOverride[1] != 255 || ar.altNameTextColorOverride[2] != 255) + { + altNameTextColor = pal_Colour(ar.altNameTextColorOverride[0], ar.altNameTextColorOverride[1], ar.altNameTextColorOverride[2]); + } + if (isHighlight) + { + altNameTextColor.byte.a = static_cast(static_cast(altNameTextColor.byte.a) * 0.3f); + } + cache.wzAltNameText.render(altNameBoxX0 + 2, altNameTextY0, altNameTextColor); +} + // //////////////////////////////////////////////////////////////////////////// void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset) { @@ -7667,6 +7721,7 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset) int const x = xOffset + psWidget->x(); int const y = yOffset + psWidget->y(); unsigned const j = psWidget->UserData; + bool isHighlight = (psWidget->getState() & WBUT_HIGHLIGHT) != 0; const int nameX = 32; @@ -7688,19 +7743,11 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset) auto ar = stat.autorating; std::string name = NetPlay.players[j].name; - if (ar.name != "") - { - name = ar.name; - } std::map serverPlayers; // TODO Fill this with players known to the server (needs implementing on the server, too). Currently useless. PIELIGHT colour; - if (ar.nameTextColorOverride[0] != 255 || ar.nameTextColorOverride[1] != 255 || ar.nameTextColorOverride[2] != 255) - { - colour = pal_Colour(ar.nameTextColorOverride[0], ar.nameTextColorOverride[1], ar.nameTextColorOverride[2]); - } - else if (ingame.PingTimes[j] >= PING_LIMIT) + if (ingame.PingTimes[j] >= PING_LIMIT) { colour = WZCOL_FORM_PLAYER_NOPING; } @@ -7774,6 +7821,30 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset) ar.elo.clear(); } + if (cache.fullAltNameText != ar.altName) + { + std::string altName = ar.altName; + int maxAltNameWidth = static_cast(static_cast(psWidget->width() - nameX) * 0.65f); + iV_fonts fontID = font_small; + cache.wzAltNameText.setText(WzString::fromUtf8(altName), fontID); + cache.fullAltNameText = altName; + if (cache.wzAltNameText.width() > maxAltNameWidth) + { + while (!altName.empty() && ((int)iV_GetTextWidth(altName.c_str(), cache.wzAltNameText.getFontID()) + iV_GetEllipsisWidth(cache.wzAltNameText.getFontID())) > maxAltNameWidth) + { + altName.resize(altName.size() - 1); // Clip alt name. + } + altName += "\u2026"; + cache.wzAltNameText.setText(WzString::fromUtf8(altName), fontID); + } + } + + if (!ar.altName.empty() && isHighlight) + { + // display first, behind everything + displayAltNameBox(x, y, psWidget, cache, ar, isHighlight); + } + int H = 5; cache.wzMainText.render(x + nameX, y + 22 - H*!subText.isEmpty() - H*(ar.valid && !ar.elo.empty()), colour); if (!subText.isEmpty()) @@ -7827,6 +7898,12 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset) cache.wzEloText.setText(WzString::fromUtf8(ar.elo), font_small); cache.wzEloText.render(x + nameX, y + 28 + H*!subText.isEmpty(), eloColour); } + + if (!ar.altName.empty() && !isHighlight) + { + // display last, over top of everything + displayAltNameBox(x, y, psWidget, cache, ar, isHighlight); + } } else // AI { diff --git a/src/multistat.cpp b/src/multistat.cpp index 6a06eafbd00..4334320c1f5 100644 --- a/src/multistat.cpp +++ b/src/multistat.cpp @@ -71,8 +71,8 @@ static void NETauto(PLAYERSTATS::Autorating &ar) NETauto(ar.elo); NETauto(ar.autohoster); NETauto(ar.details); - NETauto(ar.name); - NETauto(ar.nameTextColorOverride); + NETauto(ar.altName); + NETauto(ar.altNameTextColorOverride); NETauto(ar.eloTextColorOverride); } } @@ -91,13 +91,13 @@ PLAYERSTATS::Autorating::Autorating(nlohmann::json const &json) details = json["details"].get(); if (json.contains("name")) { - name = json["name"].get(); + altName = json["name"].get(); } if (json.contains("nameTextColorOverride")) { - nameTextColorOverride[0] = json["nameTextColorOverride"][0].get(); - nameTextColorOverride[1] = json["nameTextColorOverride"][1].get(); - nameTextColorOverride[2] = json["nameTextColorOverride"][2].get(); + altNameTextColorOverride[0] = json["nameTextColorOverride"][0].get(); + altNameTextColorOverride[1] = json["nameTextColorOverride"][1].get(); + altNameTextColorOverride[2] = json["nameTextColorOverride"][2].get(); } if (json.contains("eloTextColorOverride")) { diff --git a/src/multistat.h b/src/multistat.h index eed40a239fb..d0e644f7e67 100644 --- a/src/multistat.h +++ b/src/multistat.h @@ -75,11 +75,11 @@ struct PLAYERSTATS uint8_t star[3] = {0, 0, 0}; uint8_t medal = 0; uint8_t level = 0; - uint8_t nameTextColorOverride[3] = {255, 255, 255}; // rgb + uint8_t altNameTextColorOverride[3] = {255, 255, 255}; // rgb uint8_t eloTextColorOverride[3] = {255, 255, 255}; // rgb std::string elo; std::string details; - std::string name; + std::string altName; }; Autorating autorating; RATING_SOURCE autoratingFrom = RATING_SOURCE_HOST;