diff --git a/resources/lang/en.json b/resources/lang/en.json index 1f1f0674ad..9d0d8056ee 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -536,6 +536,8 @@ "cursor_cost_label_desc": "Show a cost pill under the build cursor icon", "anonymous_names_label": "Hidden Names", "anonymous_names_desc": "Hide real player names with random ones on your screen.", + "player_name_opacity_label": "Player Name Opacity", + "player_name_opacity_desc": "Adjust on-map player label opacity. At 0, names and flags are hidden.", "lobby_id_visibility_label": "Hidden Lobby IDs", "lobby_id_visibility_desc": "Hide Lobby ID in private lobby creation", "toggle_visibility": "Toggle Visibility", @@ -626,6 +628,7 @@ "unbind": "Unbind", "on": "On", "off": "Off", + "hidden": "Hidden", "toggle_terrain": "Toggle Terrain", "exit_game_label": "Exit Game", "exit_game_info": "Return to main menu", diff --git a/src/client/UserSettingModal.ts b/src/client/UserSettingModal.ts index cb47ee3207..2e54c63f96 100644 --- a/src/client/UserSettingModal.ts +++ b/src/client/UserSettingModal.ts @@ -366,6 +366,15 @@ export class UserSettingModal extends BaseModal { } } + private sliderPlayerNameOpacity(e: CustomEvent<{ value: number }>) { + const value = e.detail?.value; + if (typeof value !== "number") { + console.warn("Slider event missing detail.value", e); + return; + } + this.userSettings.setPlayerNameOpacity(value); + } + private changeAttackRatioIncrement( e: CustomEvent<{ value: number | string }>, ) { @@ -921,6 +930,16 @@ export class UserSettingModal extends BaseModal { @change=${this.toggleAnonymousNames} > + + ${this.value}%${valueText} diff --git a/src/client/graphics/layers/NameLayer.ts b/src/client/graphics/layers/NameLayer.ts index 2cee0dbe0d..e0d1ca6427 100644 --- a/src/client/graphics/layers/NameLayer.ts +++ b/src/client/graphics/layers/NameLayer.ts @@ -304,17 +304,26 @@ export class NameLayer implements Layer { } render.lastRenderCalc = now + this.rand.nextInt(0, 100); - // Update text sizes + // Update text sizes and opacity render.fontSize = Math.max(4, Math.floor(baseSize * 0.4)); render.fontColor = this.theme.textColor(render.player); + const nameOpacityPercent = this.userSettings.playerNameOpacity(); + const nameOpacity = nameOpacityPercent / 100; + const hideFlag = nameOpacityPercent === 0; render.nameDiv.style.fontSize = `${render.fontSize}px`; render.nameDiv.style.lineHeight = `${render.fontSize}px`; render.nameDiv.style.color = render.fontColor; + if (render.nameSpan) { + render.nameSpan.textContent = render.player.displayName(); + render.nameSpan.style.opacity = `${nameOpacity}`; + } if (render.flagDiv) { render.flagDiv.style.height = `${render.fontSize}px`; + render.flagDiv.style.display = hideFlag ? "none" : ""; } render.troopsDiv.style.fontSize = `${render.fontSize}px`; + render.troopsDiv.style.opacity = `${nameOpacity}`; render.troopsDiv.style.color = render.fontColor; render.troopsDiv.textContent = renderTroops(render.player.troops()); diff --git a/src/client/graphics/layers/SettingsModal.ts b/src/client/graphics/layers/SettingsModal.ts index 2e3c9f532f..b965c9041d 100644 --- a/src/client/graphics/layers/SettingsModal.ts +++ b/src/client/graphics/layers/SettingsModal.ts @@ -194,6 +194,12 @@ export class SettingsModal extends LitElement implements Layer { this.requestUpdate(); } + private onPlayerNameOpacityChange(event: Event) { + const opacity = parseFloat((event.target as HTMLInputElement).value); + this.userSettings.setPlayerNameOpacity(opacity); + this.requestUpdate(); + } + render() { if (!this.isVisible) { return null; @@ -482,6 +488,38 @@ export class SettingsModal extends LitElement implements Layer { +
+ nameOpacity +
+
+ ${translateText("user_setting.player_name_opacity_label")} +
+
+ ${translateText("user_setting.player_name_opacity_desc")} +
+ +
+
+ ${this.userSettings.playerNameOpacity() === 0 + ? translateText("user_setting.hidden") + : `${this.userSettings.playerNameOpacity()}%`} +
+
+