diff --git a/Content.Client/Options/UI/Tabs/MiscTab.xaml b/Content.Client/Options/UI/Tabs/MiscTab.xaml index 2ee59910f7..5564d7b226 100644 --- a/Content.Client/Options/UI/Tabs/MiscTab.xaml +++ b/Content.Client/Options/UI/Tabs/MiscTab.xaml @@ -25,6 +25,14 @@ + + - - - diff --git a/Content.Client/Options/UI/Tabs/MiscTab.xaml.cs b/Content.Client/Options/UI/Tabs/MiscTab.xaml.cs index 3b9c41efdf..476e7289ea 100644 --- a/Content.Client/Options/UI/Tabs/MiscTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/MiscTab.xaml.cs @@ -66,6 +66,7 @@ namespace Content.Client.Options.UI.Tabs EnableColorNameCheckBox.OnToggled += OnCheckBoxToggled; ColorblindFriendlyCheckBox.OnToggled += OnCheckBoxToggled; ReducedMotionCheckBox.OnToggled += OnCheckBoxToggled; + ChatWindowOpacitySlider.OnValueChanged += OnChatWindowOpacitySliderChanged; ScreenShakeIntensitySlider.OnValueChanged += OnScreenShakeIntensitySliderChanged; // ToggleWalk.OnToggled += OnCheckBoxToggled; StaticStorageUI.OnToggled += OnCheckBoxToggled; @@ -81,6 +82,7 @@ namespace Content.Client.Options.UI.Tabs EnableColorNameCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatEnableColorName); ColorblindFriendlyCheckBox.Pressed = _cfg.GetCVar(CCVars.AccessibilityColorblindFriendly); ReducedMotionCheckBox.Pressed = _cfg.GetCVar(CCVars.ReducedMotion); + ChatWindowOpacitySlider.Value = _cfg.GetCVar(CCVars.ChatWindowOpacity); ScreenShakeIntensitySlider.Value = _cfg.GetCVar(CCVars.ScreenShakeIntensity) * 100f; // ToggleWalk.Pressed = _cfg.GetCVar(CCVars.ToggleWalk); StaticStorageUI.Pressed = _cfg.GetCVar(CCVars.StaticStorageUI); @@ -101,6 +103,13 @@ namespace Content.Client.Options.UI.Tabs UpdateApplyButton(); } + private void OnChatWindowOpacitySliderChanged(Range range) + { + ChatWindowOpacityLabel.Text = Loc.GetString("ui-options-chat-window-opacity-percent", + ("opacity", range.Value)); + UpdateApplyButton(); + } + private void OnScreenShakeIntensitySliderChanged(Range obj) { ScreenShakeIntensityLabel.Text = Loc.GetString("ui-options-screen-shake-percent", ("intensity", ScreenShakeIntensitySlider.Value / 100f)); @@ -127,6 +136,7 @@ namespace Content.Client.Options.UI.Tabs _cfg.SetCVar(CCVars.ChatEnableColorName, EnableColorNameCheckBox.Pressed); _cfg.SetCVar(CCVars.AccessibilityColorblindFriendly, ColorblindFriendlyCheckBox.Pressed); _cfg.SetCVar(CCVars.ReducedMotion, ReducedMotionCheckBox.Pressed); + _cfg.SetCVar(CCVars.ChatWindowOpacity, ChatWindowOpacitySlider.Value); _cfg.SetCVar(CCVars.ScreenShakeIntensity, ScreenShakeIntensitySlider.Value / 100f); // _cfg.SetCVar(CCVars.ToggleWalk, ToggleWalk.Pressed); _cfg.SetCVar(CCVars.StaticStorageUI, StaticStorageUI.Pressed); @@ -154,6 +164,7 @@ namespace Content.Client.Options.UI.Tabs var isEnableColorNameSame = EnableColorNameCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatEnableColorName); var isColorblindFriendly = ColorblindFriendlyCheckBox.Pressed == _cfg.GetCVar(CCVars.AccessibilityColorblindFriendly); var isReducedMotionSame = ReducedMotionCheckBox.Pressed == _cfg.GetCVar(CCVars.ReducedMotion); + var isChatWindowOpacitySame = Math.Abs(ChatWindowOpacitySlider.Value - _cfg.GetCVar(CCVars.ChatWindowOpacity)) < 0.01f; var isScreenShakeIntensitySame = Math.Abs(ScreenShakeIntensitySlider.Value / 100f - _cfg.GetCVar(CCVars.ScreenShakeIntensity)) < 0.01f; // var isToggleWalkSame = ToggleWalk.Pressed == _cfg.GetCVar(CCVars.ToggleWalk); var isStaticStorageUISame = StaticStorageUI.Pressed == _cfg.GetCVar(CCVars.StaticStorageUI); @@ -170,6 +181,7 @@ namespace Content.Client.Options.UI.Tabs isEnableColorNameSame && isColorblindFriendly && isReducedMotionSame && + isChatWindowOpacitySame && isScreenShakeIntensitySame && // isToggleWalkSame && isStaticStorageUISame; diff --git a/Content.Client/Stylesheets/StyleNano.cs b/Content.Client/Stylesheets/StyleNano.cs index 2c7a1873a3..a589abb83a 100644 --- a/Content.Client/Stylesheets/StyleNano.cs +++ b/Content.Client/Stylesheets/StyleNano.cs @@ -45,6 +45,7 @@ namespace Content.Client.Stylesheets public const string StyleClassBorderedWindowPanel = "BorderedWindowPanel"; public const string StyleClassInventorySlotBackground = "InventorySlotBackground"; public const string StyleClassHandSlotHighlight = "HandSlotHighlight"; + public const string StyleClassChatPanel = "ChatPanel"; public const string StyleClassChatSubPanel = "ChatSubPanel"; public const string StyleClassTransparentBorderedWindowPanel = "TransparentBorderedWindowPanel"; public const string StyleClassHotbarPanel = "HotbarPanel"; @@ -144,6 +145,8 @@ namespace Content.Client.Stylesheets public const string StyleClassButtonColorRed = "ButtonColorRed"; public const string StyleClassButtonColorGreen = "ButtonColorGreen"; + public static readonly Color ChatBackgroundColor = Color.FromHex("#25252ADD"); + public override Stylesheet Stylesheet { get; } public StyleNano(IResourceCache resCache) : base(resCache) @@ -346,12 +349,16 @@ namespace Content.Client.Stylesheets lineEdit.SetPatchMargin(StyleBox.Margin.All, 3); lineEdit.SetContentMarginOverride(StyleBox.Margin.Horizontal, 5); - var chatSubBGTex = resCache.GetTexture("/Textures/Interface/Nano/chat_sub_background.png"); - var chatSubBG = new StyleBoxTexture + var chatBg = new StyleBoxFlat { - Texture = chatSubBGTex, + BackgroundColor = ChatBackgroundColor }; - chatSubBG.SetPatchMargin(StyleBox.Margin.All, 2); + + var chatSubBg = new StyleBoxFlat + { + BackgroundColor = ChatBackgroundColor, + }; + chatSubBg.SetContentMarginOverride(StyleBox.Margin.All, 2); var actionSearchBoxTex = resCache.GetTexture("/Textures/Interface/Nano/black_panel_dark_thin_border.png"); var actionSearchBox = new StyleBoxTexture @@ -850,6 +857,13 @@ namespace Content.Client.Stylesheets Element().Pseudo(TextEdit.StylePseudoClassPlaceholder) .Prop("font-color", Color.Gray), + // chat subpanels (chat lineedit backing, popup backings) + new StyleRule(new SelectorElement(typeof(PanelContainer), new[] {StyleClassChatPanel}, null, null), + new[] + { + new StyleProperty(PanelContainer.StylePropertyPanel, chatBg), + }), + // Chat lineedit - we don't actually draw a stylebox around the lineedit itself, we put it around the // input + other buttons, so we must clear the default stylebox new StyleRule(new SelectorElement(typeof(LineEdit), new[] {StyleClassChatLineEdit}, null, null), @@ -858,13 +872,6 @@ namespace Content.Client.Stylesheets new StyleProperty(LineEdit.StylePropertyStyleBox, new StyleBoxEmpty()), }), - // chat subpanels (chat lineedit backing, popup backings) - new StyleRule(new SelectorElement(typeof(PanelContainer), new[] {StyleClassChatSubPanel}, null, null), - new[] - { - new StyleProperty(PanelContainer.StylePropertyPanel, chatSubBG), - }), - // Action searchbox lineedit new StyleRule(new SelectorElement(typeof(LineEdit), new[] {StyleClassActionSearchBox}, null, null), new[] diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index ac0ea5335e..907268295c 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -9,6 +9,7 @@ using Content.Client.Chat.UI; using Content.Client.Examine; using Content.Client.Gameplay; using Content.Client.Ghost; +using Content.Client.Stylesheets; using Content.Client.UserInterface.Screens; using Content.Client.UserInterface.Systems.Chat.Widgets; using Content.Client.UserInterface.Systems.Gameplay; @@ -54,7 +55,6 @@ public sealed class ChatUIController : UIController [Dependency] private readonly IStateManager _state = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IReplayRecordingManager _replayRecording = default!; - [Dependency] private readonly IConfigurationManager _cfg = default!; [UISystemDependency] private readonly ExamineSystem? _examine = default; [UISystemDependency] private readonly GhostSystem? _ghost = default; @@ -179,8 +179,8 @@ public sealed class ChatUIController : UIController _net.RegisterNetMessage(OnChatMessage); _net.RegisterNetMessage(OnDeleteChatMessagesBy); SubscribeNetworkEvent(OnDamageForceSay); - _cfg.OnValueChanged(CCVars.ChatEnableColorName, (value) => { _chatNameColorsEnabled = value; }); - _chatNameColorsEnabled = _cfg.GetCVar(CCVars.ChatEnableColorName); + _config.OnValueChanged(CCVars.ChatEnableColorName, (value) => { _chatNameColorsEnabled = value; }); + _chatNameColorsEnabled = _config.GetCVar(CCVars.ChatEnableColorName); _speechBubbleRoot = new LayoutContainer(); @@ -232,6 +232,9 @@ public sealed class ChatUIController : UIController { _chatNameColors[i] = nameColors[i].ToHex(); } + + _config.OnValueChanged(CCVars.ChatWindowOpacity, OnChatWindowOpacityChanged); + } public void OnScreenLoad() @@ -240,6 +243,8 @@ public sealed class ChatUIController : UIController var viewportContainer = UIManager.ActiveScreen!.FindControl("ViewportContainer"); SetSpeechBubbleRoot(viewportContainer); + + SetChatWindowOpacity(_config.GetCVar(CCVars.ChatWindowOpacity)); } public void OnScreenUnload() @@ -247,6 +252,34 @@ public sealed class ChatUIController : UIController SetMainChat(false); } + private void OnChatWindowOpacityChanged(float opacity) + { + SetChatWindowOpacity(opacity); + } + + private void SetChatWindowOpacity(float opacity) + { + var chatBox = UIManager.ActiveScreen?.GetWidget() ?? UIManager.ActiveScreen?.GetWidget(); + + var panel = chatBox?.ChatWindowPanel; + if (panel is null) + return; + + Color color; + if (panel.PanelOverride is StyleBoxFlat styleBoxFlat) + color = styleBoxFlat.BackgroundColor; + else if (panel.TryGetStyleProperty(PanelContainer.StylePropertyPanel, out var style) + && style is StyleBoxFlat propStyleBoxFlat) + color = propStyleBoxFlat.BackgroundColor; + else + color = StyleNano.ChatBackgroundColor; + + panel.PanelOverride = new StyleBoxFlat + { + BackgroundColor = color.WithAlpha(opacity) + }; + } + public void SetMainChat(bool setting) { if (UIManager.ActiveScreen == null) @@ -770,7 +803,7 @@ public sealed class ChatUIController : UIController ProcessChatMessage(msg); if ((msg.Channel & ChatChannel.AdminRelated) == 0 || - _cfg.GetCVar(CCVars.ReplayRecordAdminChat)) + _config.GetCVar(CCVars.ReplayRecordAdminChat)) { _replayRecording.RecordClientMessage(msg); } @@ -830,7 +863,7 @@ public sealed class ChatUIController : UIController break; case ChatChannel.LOOC: - if (_cfg.GetCVar(CCVars.LoocAboveHeadShow)) + if (_config.GetCVar(CCVars.LoocAboveHeadShow)) AddSpeechBubble(msg, SpeechBubble.SpeechType.Looc); break; } diff --git a/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.cs b/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs similarity index 95% rename from Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.cs rename to Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs index 843fd46c1a..0326664bd6 100644 --- a/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.cs +++ b/Content.Client/UserInterface/Systems/Chat/Controls/ChatInputBox.xaml.cs @@ -1,4 +1,5 @@ -using Content.Shared.Chat; +using Content.Client.Stylesheets; +using Content.Shared.Chat; using Content.Shared.Input; using Robust.Client.UserInterface.Controls; @@ -44,6 +45,7 @@ public class ChatInputBox : PanelContainer StyleClasses = {"chatFilterOptionButton"} }; Container.AddChild(FilterButton); + AddStyleClass(StyleNano.StyleClassChatSubPanel); ChannelSelector.OnChannelSelect += UpdateActiveChannel; } diff --git a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml index 090041fa93..36cdce8598 100644 --- a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml +++ b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml @@ -7,11 +7,8 @@ HorizontalExpand="True" VerticalExpand="True" MinSize="465 225"> - - - - - + diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 51f782991e..82d1fdd14a 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -1580,6 +1580,13 @@ namespace Content.Shared.CCVar * Accessibility */ + /// + /// Chat window opacity slider, controlling the alpha of the chat window background. + /// Goes from to 0 (completely transparent) to 1 (completely opaque) + /// + public static readonly CVarDef ChatWindowOpacity = + CVarDef.Create("accessibility.chat_window_transparency", 0.85f, CVar.CLIENTONLY | CVar.ARCHIVE); + /// /// Toggle for visual effects that may potentially cause motion sickness. /// Where reasonable, effects affected by this CVar should use an alternate effect. diff --git a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl index ff56d54274..67d09c9012 100644 --- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl @@ -48,6 +48,8 @@ ui-options-fancy-name-background = Add background to speech bubble names ui-options-enable-color-name = Add colors to character names ui-options-colorblind-friendly = Colorblind friendly mode ui-options-reduced-motion = Reduce motion of visual effects +ui-options-chat-window-opacity = Chat window opacity +ui-options-chat-window-opacity-percent = { TOSTRING($opacity, "P0") } ui-options-screen-shake-intensity = Screen shake intensity ui-options-screen-shake-percent = { TOSTRING($intensity, "P0") } ui-options-vsync = VSync