diff --git a/Content.Client/CharacterInterface/CharacterInterfaceSystem.cs b/Content.Client/CharacterInterface/CharacterInterfaceSystem.cs index e6f22ef5b7..1213093b8f 100644 --- a/Content.Client/CharacterInterface/CharacterInterfaceSystem.cs +++ b/Content.Client/CharacterInterface/CharacterInterfaceSystem.cs @@ -81,7 +81,7 @@ namespace Content.Client.CharacterInterface return; _gameHud.CharacterButtonVisible = true; - _gameHud.CharacterButtonToggled = b => + _gameHud.CharacterButtonToggled += b => { if (b) comp.Window.OpenCentered(); diff --git a/Content.Client/HUD/GameHud.ButtonBar.cs b/Content.Client/HUD/GameHud.ButtonBar.cs new file mode 100644 index 0000000000..4d1637e2af --- /dev/null +++ b/Content.Client/HUD/GameHud.ButtonBar.cs @@ -0,0 +1,350 @@ +using System; +using Content.Client.HUD.UI; +using Content.Client.Resources; +using Content.Client.Stylesheets; +using Content.Shared.Input; +using Robust.Client.Input; +using Robust.Client.ResourceManagement; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Input; +using Robust.Shared.Localization; +using Robust.Shared.Maths; + +namespace Content.Client.HUD; + +public interface IButtonBarView +{ + // Escape top button. + bool EscapeButtonDown { get; set; } + event Action EscapeButtonToggled; + + // Character top button. + bool CharacterButtonDown { get; set; } + bool CharacterButtonVisible { get; set; } + event Action CharacterButtonToggled; + + // Inventory top button. + bool InventoryButtonDown { get; set; } + bool InventoryButtonVisible { get; set; } + event Action InventoryButtonToggled; + + // Crafting top button. + bool CraftingButtonDown { get; set; } + bool CraftingButtonVisible { get; set; } + event Action CraftingButtonToggled; + + // Actions top button. + bool ActionsButtonDown { get; set; } + bool ActionsButtonVisible { get; set; } + event Action ActionsButtonToggled; + + // Admin top button. + bool AdminButtonDown { get; set; } + bool AdminButtonVisible { get; set; } + event Action AdminButtonToggled; + + // Sandbox top button. + bool SandboxButtonDown { get; set; } + bool SandboxButtonVisible { get; set; } + event Action SandboxButtonToggled; + + // Info top button + bool InfoButtonDown { get; set; } + event Action InfoButtonToggled; +} + +internal sealed partial class GameHud +{ + private TopButton _buttonEscapeMenu = default!; + private TopButton _buttonInfo = default!; + private TopButton _buttonCharacterMenu = default!; + private TopButton _buttonInventoryMenu = default!; + private TopButton _buttonCraftingMenu = default!; + private TopButton _buttonActionsMenu = default!; + private TopButton _buttonAdminMenu = default!; + private TopButton _buttonSandboxMenu = default!; + + private BoxContainer GenerateButtonBar(IResourceCache resourceCache, IInputManager inputManager) + { + var topButtonsContainer = new BoxContainer + { + Orientation = BoxContainer.LayoutOrientation.Horizontal, + SeparationOverride = 8 + }; + + LayoutContainer.SetAnchorAndMarginPreset(topButtonsContainer, LayoutContainer.LayoutPreset.TopLeft, margin: 10); + + // the icon textures here should all have the same image height (32) but different widths, so in order to ensure + // the buttons themselves are consistent widths we set a common custom min size + Vector2 topMinSize = (42, 64); + + // Escape + { + _buttonEscapeMenu = new TopButton(resourceCache.GetTexture("/Textures/Interface/hamburger.svg.192dpi.png"), + EngineKeyFunctions.EscapeMenu, inputManager) + { + ToolTip = Loc.GetString("game-hud-open-escape-menu-button-tooltip"), + MinSize = (70, 64), + StyleClasses = { StyleBase.ButtonOpenRight } + }; + + topButtonsContainer.AddChild(_buttonEscapeMenu); + + _buttonEscapeMenu.OnToggled += args => EscapeButtonToggled?.Invoke(args.Pressed); + } + + // Character + { + _buttonCharacterMenu = new TopButton(resourceCache.GetTexture("/Textures/Interface/character.svg.192dpi.png"), + ContentKeyFunctions.OpenCharacterMenu, inputManager) + { + ToolTip = Loc.GetString("game-hud-open-character-menu-button-tooltip"), + MinSize = topMinSize, + Visible = false, + StyleClasses = { StyleBase.ButtonSquare } + }; + + topButtonsContainer.AddChild(_buttonCharacterMenu); + + _buttonCharacterMenu.OnToggled += args => CharacterButtonToggled?.Invoke(args.Pressed); + } + + // Inventory + { + _buttonInventoryMenu = new TopButton(resourceCache.GetTexture("/Textures/Interface/inventory.svg.192dpi.png"), + ContentKeyFunctions.OpenInventoryMenu, inputManager) + { + ToolTip = Loc.GetString("game-hud-open-inventory-menu-button-tooltip"), + MinSize = topMinSize, + Visible = false, + StyleClasses = { StyleBase.ButtonSquare } + }; + + topButtonsContainer.AddChild(_buttonInventoryMenu); + + _buttonInventoryMenu.OnToggled += args => InventoryButtonToggled?.Invoke(args.Pressed); + } + + // Crafting + { + _buttonCraftingMenu = new TopButton(resourceCache.GetTexture("/Textures/Interface/hammer.svg.192dpi.png"), + ContentKeyFunctions.OpenCraftingMenu, inputManager) + { + ToolTip = Loc.GetString("game-hud-open-crafting-menu-button-tooltip"), + MinSize = topMinSize, + Visible = false, + StyleClasses = { StyleBase.ButtonSquare } + }; + + topButtonsContainer.AddChild(_buttonCraftingMenu); + + _buttonCraftingMenu.OnToggled += args => CraftingButtonToggled?.Invoke(args.Pressed); + } + + // Actions + { + _buttonActionsMenu = new TopButton(resourceCache.GetTexture("/Textures/Interface/fist.svg.192dpi.png"), + ContentKeyFunctions.OpenActionsMenu, inputManager) + { + ToolTip = Loc.GetString("game-hud-open-actions-menu-button-tooltip"), + MinSize = topMinSize, + Visible = false, + StyleClasses = { StyleBase.ButtonSquare } + }; + + topButtonsContainer.AddChild(_buttonActionsMenu); + + _buttonActionsMenu.OnToggled += args => ActionsButtonToggled?.Invoke(args.Pressed); + } + + // Admin + { + _buttonAdminMenu = new TopButton(resourceCache.GetTexture("/Textures/Interface/gavel.svg.192dpi.png"), + ContentKeyFunctions.OpenAdminMenu, inputManager) + { + ToolTip = Loc.GetString("game-hud-open-admin-menu-button-tooltip"), + MinSize = topMinSize, + Visible = false, + StyleClasses = { StyleBase.ButtonSquare } + }; + + topButtonsContainer.AddChild(_buttonAdminMenu); + + _buttonAdminMenu.OnToggled += args => AdminButtonToggled?.Invoke(args.Pressed); + } + + // Sandbox + { + _buttonSandboxMenu = new TopButton(resourceCache.GetTexture("/Textures/Interface/sandbox.svg.192dpi.png"), + ContentKeyFunctions.OpenSandboxWindow, inputManager) + { + ToolTip = Loc.GetString("game-hud-open-sandbox-menu-button-tooltip"), + MinSize = topMinSize, + Visible = false, + StyleClasses = { StyleBase.ButtonSquare } + }; + + topButtonsContainer.AddChild(_buttonSandboxMenu); + + _buttonSandboxMenu.OnToggled += args => SandboxButtonToggled?.Invoke(args.Pressed); + } + + // Info Window + { + _buttonInfo = new TopButton(resourceCache.GetTexture("/Textures/Interface/info.svg.192dpi.png"), + ContentKeyFunctions.OpenInfo, inputManager) + { + ToolTip = Loc.GetString("ui-options-function-open-info"), + MinSize = topMinSize, + StyleClasses = { StyleBase.ButtonOpenLeft, TopButton.StyleClassRedTopButton }, + }; + + topButtonsContainer.AddChild(_buttonInfo); + + _buttonInfo.OnToggled += args => InfoButtonToggled?.Invoke(args.Pressed); + _buttonInfo.OnToggled += ButtonInfoToggledHandler; + } + + return topButtonsContainer; + } + + private void ButtonInfoToggledHandler(BaseButton.ButtonToggledEventArgs obj) + { + ButtonInfoToggled(obj.Pressed); + } + + private void ButtonInfoToggled(bool pressed) + { + if(!pressed) + return; + + _buttonInfo.StyleClasses.Remove(TopButton.StyleClassRedTopButton); + _buttonInfo.OnToggled -= ButtonInfoToggledHandler; + } + + /// + public bool EscapeButtonDown + { + get => _buttonEscapeMenu.Pressed; + set => _buttonEscapeMenu.Pressed = value; + } + + /// + public event Action? EscapeButtonToggled; + + /// + public bool CharacterButtonDown + { + get => _buttonCharacterMenu.Pressed; + set => _buttonCharacterMenu.Pressed = value; + } + + /// + public bool CharacterButtonVisible + { + get => _buttonCharacterMenu.Visible; + set => _buttonCharacterMenu.Visible = value; + } + + /// + public event Action? CharacterButtonToggled; + + /// + public bool InventoryButtonDown + { + get => _buttonInventoryMenu.Pressed; + set => _buttonInventoryMenu.Pressed = value; + } + + /// + public bool InventoryButtonVisible + { + get => _buttonInventoryMenu.Visible; + set => _buttonInventoryMenu.Visible = value; + } + + /// + public event Action? InventoryButtonToggled; + + /// + public bool CraftingButtonDown + { + get => _buttonCraftingMenu.Pressed; + set => _buttonCraftingMenu.Pressed = value; + } + + /// + public bool CraftingButtonVisible + { + get => _buttonCraftingMenu.Visible; + set => _buttonCraftingMenu.Visible = value; + } + + /// + public event Action? CraftingButtonToggled; + + /// + public bool ActionsButtonDown + { + get => _buttonActionsMenu.Pressed; + set => _buttonActionsMenu.Pressed = value; + } + + /// + public bool ActionsButtonVisible + { + get => _buttonActionsMenu.Visible; + set => _buttonActionsMenu.Visible = value; + } + + /// + public event Action? ActionsButtonToggled; + + /// + public bool AdminButtonDown + { + get => _buttonAdminMenu.Pressed; + set => _buttonAdminMenu.Pressed = value; + } + + /// + public bool AdminButtonVisible + { + get => _buttonAdminMenu.Visible; + set => _buttonAdminMenu.Visible = value; + } + + /// + public event Action? AdminButtonToggled; + + /// + public bool SandboxButtonDown + { + get => _buttonSandboxMenu.Pressed; + set => _buttonSandboxMenu.Pressed = value; + } + + /// + public bool SandboxButtonVisible + { + get => _buttonSandboxMenu.Visible; + set => _buttonSandboxMenu.Visible = value; + } + + /// + public event Action? SandboxButtonToggled; + + /// + public bool InfoButtonDown + { + get => _buttonInfo.Pressed; + set + { + _buttonInfo.Pressed = value; + ButtonInfoToggled(value); + } + } + + /// + public event Action? InfoButtonToggled; +} diff --git a/Content.Client/HUD/GameHud.cs b/Content.Client/HUD/GameHud.cs index 95d601b98f..e7f3454836 100644 --- a/Content.Client/HUD/GameHud.cs +++ b/Content.Client/HUD/GameHud.cs @@ -1,10 +1,8 @@ using System; -using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Client.HUD.UI; using Content.Client.Info; using Content.Client.Resources; -using Content.Client.Stylesheets; using Content.Client.Targeting; using Content.Shared.CCVar; using Content.Shared.HUD; @@ -14,17 +12,12 @@ using Robust.Client.Graphics; using Robust.Client.Input; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface.Controls; -using Robust.Shared; using Robust.Shared.Configuration; -using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.IoC; -using Robust.Shared.Localization; using Robust.Shared.Log; -using Robust.Shared.Maths; using Robust.Shared.Prototypes; using Robust.Shared.Utility; -using static Robust.Client.Input.Keyboard.Key; using static Robust.Client.UserInterface.Controls.BoxContainer; using Control = Robust.Client.UserInterface.Control; using LC = Robust.Client.UserInterface.Controls.LayoutContainer; @@ -34,43 +27,10 @@ namespace Content.Client.HUD /// /// Responsible for laying out the default game HUD. /// - public interface IGameHud + public interface IGameHud : IButtonBarView { Control RootControl { get; } - // Escape top button. - bool EscapeButtonDown { get; set; } - Action? EscapeButtonToggled { get; set; } - - // Character top button. - bool CharacterButtonDown { get; set; } - bool CharacterButtonVisible { get; set; } - Action? CharacterButtonToggled { get; set; } - - // Inventory top button. - bool InventoryButtonDown { get; set; } - bool InventoryButtonVisible { get; set; } - - // Crafting top button. - bool CraftingButtonDown { get; set; } - bool CraftingButtonVisible { get; set; } - Action? CraftingButtonToggled { get; set; } - - // Actions top button. - bool ActionsButtonDown { get; set; } - bool ActionsButtonVisible { get; set; } - Action? ActionsButtonToggled { get; set; } - - // Admin top button. - bool AdminButtonDown { get; set; } - bool AdminButtonVisible { get; set; } - Action? AdminButtonToggled { get; set; } - - // Sandbox top button. - bool SandboxButtonDown { get; set; } - bool SandboxButtonVisible { get; set; } - Action? SandboxButtonToggled { get; set; } - Control HandsContainer { get; } Control SuspicionContainer { get; } Control BottomLeftInventoryQuickButtonContainer { get; } @@ -93,17 +53,8 @@ namespace Content.Client.HUD void Initialize(); } - internal sealed class GameHud : IGameHud + internal sealed partial class GameHud : IGameHud { - private BoxContainer _topButtonsContainer = default!; - private TopButton _buttonEscapeMenu = default!; - private TopButton _buttonInfo = default!; - private TopButton _buttonCharacterMenu = default!; - private TopButton _buttonInventoryMenu = default!; - private TopButton _buttonCraftingMenu = default!; - private TopButton _buttonActionsMenu = default!; - private TopButton _buttonAdminMenu = default!; - private TopButton _buttonSandboxMenu = default!; private RulesAndInfoWindow _rulesAndInfoWindow = default!; private TargetingDoll _targetingDoll = default!; private BoxContainer _combatPanelContainer = default!; @@ -175,140 +126,17 @@ namespace Content.Client.HUD RootControl = new LC { Name = "AAAAAAAAAAAAAAAAAAAAAA"}; LC.SetAnchorPreset(RootControl, LC.LayoutPreset.Wide); - var escapeTexture = _resourceCache.GetTexture("/Textures/Interface/hamburger.svg.192dpi.png"); - var characterTexture = _resourceCache.GetTexture("/Textures/Interface/character.svg.192dpi.png"); - var inventoryTexture = _resourceCache.GetTexture("/Textures/Interface/inventory.svg.192dpi.png"); - var craftingTexture = _resourceCache.GetTexture("/Textures/Interface/hammer.svg.192dpi.png"); - var actionsTexture = _resourceCache.GetTexture("/Textures/Interface/fist.svg.192dpi.png"); - var adminTexture = _resourceCache.GetTexture("/Textures/Interface/gavel.svg.192dpi.png"); - var infoTexture = _resourceCache.GetTexture("/Textures/Interface/info.svg.192dpi.png"); - var sandboxTexture = _resourceCache.GetTexture("/Textures/Interface/sandbox.svg.192dpi.png"); + RootControl.AddChild(GenerateButtonBar(_resourceCache, _inputManager)); - _topButtonsContainer = new BoxContainer - { - Orientation = LayoutOrientation.Horizontal, - SeparationOverride = 8 - }; - - RootControl.AddChild(_topButtonsContainer); - - LC.SetAnchorAndMarginPreset(_topButtonsContainer, LC.LayoutPreset.TopLeft, - margin: 10); - - // the icon textures here should all have the same image height (32) but different widths, so in order to ensure - // the buttons themselves are consistent widths we set a common custom min size - Vector2 topMinSize = (42, 64); - - // Escape - _buttonEscapeMenu = new TopButton(escapeTexture, EngineKeyFunctions.EscapeMenu, _inputManager) - { - ToolTip = Loc.GetString("game-hud-open-escape-menu-button-tooltip"), - MinSize = (70, 64), - StyleClasses = {StyleBase.ButtonOpenRight} - }; - - _topButtonsContainer.AddChild(_buttonEscapeMenu); - - _buttonEscapeMenu.OnToggled += args => EscapeButtonToggled?.Invoke(args.Pressed); - - // Character - _buttonCharacterMenu = new TopButton(characterTexture, ContentKeyFunctions.OpenCharacterMenu, _inputManager) - { - ToolTip = Loc.GetString("game-hud-open-character-menu-button-tooltip"), - MinSize = topMinSize, - Visible = false, - StyleClasses = {StyleBase.ButtonSquare} - }; - - _topButtonsContainer.AddChild(_buttonCharacterMenu); - - _buttonCharacterMenu.OnToggled += args => CharacterButtonToggled?.Invoke(args.Pressed); - - // Inventory - _buttonInventoryMenu = new TopButton(inventoryTexture, ContentKeyFunctions.OpenInventoryMenu, _inputManager) - { - ToolTip = Loc.GetString("game-hud-open-inventory-menu-button-tooltip"), - MinSize = topMinSize, - Visible = false, - StyleClasses = {StyleBase.ButtonSquare} - }; - - _topButtonsContainer.AddChild(_buttonInventoryMenu); - - _buttonInventoryMenu.OnToggled += args => InventoryButtonDown = args.Pressed; - - // Crafting - _buttonCraftingMenu = new TopButton(craftingTexture, ContentKeyFunctions.OpenCraftingMenu, _inputManager) - { - ToolTip = Loc.GetString("game-hud-open-crafting-menu-button-tooltip"), - MinSize = topMinSize, - Visible = false, - StyleClasses = {StyleBase.ButtonSquare} - }; - - _topButtonsContainer.AddChild(_buttonCraftingMenu); - - _buttonCraftingMenu.OnToggled += args => CraftingButtonToggled?.Invoke(args.Pressed); - - // Actions - _buttonActionsMenu = new TopButton(actionsTexture, ContentKeyFunctions.OpenActionsMenu, _inputManager) - { - ToolTip = Loc.GetString("game-hud-open-actions-menu-button-tooltip"), - MinSize = topMinSize, - Visible = false, - StyleClasses = {StyleBase.ButtonSquare} - }; - - _topButtonsContainer.AddChild(_buttonActionsMenu); - - _buttonActionsMenu.OnToggled += args => ActionsButtonToggled?.Invoke(args.Pressed); - - // Admin - _buttonAdminMenu = new TopButton(adminTexture, ContentKeyFunctions.OpenAdminMenu, _inputManager) - { - ToolTip = Loc.GetString("game-hud-open-admin-menu-button-tooltip"), - MinSize = topMinSize, - Visible = false, - StyleClasses = {StyleBase.ButtonSquare} - }; - - _topButtonsContainer.AddChild(_buttonAdminMenu); - - _buttonAdminMenu.OnToggled += args => AdminButtonToggled?.Invoke(args.Pressed); - - // Sandbox - _buttonSandboxMenu = new TopButton(sandboxTexture, ContentKeyFunctions.OpenSandboxWindow, _inputManager) - { - ToolTip = Loc.GetString("game-hud-open-sandbox-menu-button-tooltip"), - MinSize = topMinSize, - Visible = false, - StyleClasses = {StyleBase.ButtonSquare} - }; - - _topButtonsContainer.AddChild(_buttonSandboxMenu); - - _buttonSandboxMenu.OnToggled += args => SandboxButtonToggled?.Invoke(args.Pressed); - - // Info Window - _buttonInfo = new TopButton(infoTexture, ContentKeyFunctions.OpenInfo, _inputManager) - { - ToolTip = Loc.GetString("ui-options-function-open-info"), - MinSize = topMinSize, - StyleClasses = {StyleBase.ButtonOpenLeft, TopButton.StyleClassRedTopButton}, - }; - - _topButtonsContainer.AddChild(_buttonInfo); - - _buttonInfo.OnToggled += a => ButtonInfoOnOnToggled(); + InventoryButtonToggled += down => TopInventoryQuickButtonContainer.Visible = down; + InfoButtonToggled += _ => ButtonInfoOnOnToggled(); _rulesAndInfoWindow = new RulesAndInfoWindow(); - - _rulesAndInfoWindow.OnClose += () => _buttonInfo.Pressed = false; + _rulesAndInfoWindow.OnClose += () => InfoButtonDown = false; _inputManager.SetInputCommand(ContentKeyFunctions.OpenInfo, InputCmdHandler.FromDelegate(s => ButtonInfoOnOnToggled())); - _combatPanelContainer = new BoxContainer { Orientation = LayoutOrientation.Vertical, @@ -430,344 +258,28 @@ namespace Content.Client.HUD private void ButtonInfoOnOnToggled() { - _buttonInfo.StyleClasses.Remove(TopButton.StyleClassRedTopButton); if (_rulesAndInfoWindow.IsOpen) { if (!_rulesAndInfoWindow.IsAtFront()) { _rulesAndInfoWindow.MoveToFront(); - _buttonInfo.Pressed = true; + InfoButtonDown = true; } else { _rulesAndInfoWindow.Close(); - _buttonInfo.Pressed = false; + InfoButtonDown = false; } } else { _rulesAndInfoWindow.OpenCentered(); - _buttonInfo.Pressed = true; + InfoButtonDown = true; } } public Control RootControl { get; private set; } = default!; - public bool EscapeButtonDown - { - get => _buttonEscapeMenu.Pressed; - set => _buttonEscapeMenu.Pressed = value; - } - - public Action? EscapeButtonToggled { get; set; } - - public bool CharacterButtonDown - { - get => _buttonCharacterMenu.Pressed; - set => _buttonCharacterMenu.Pressed = value; - } - - public bool CharacterButtonVisible - { - get => _buttonCharacterMenu.Visible; - set => _buttonCharacterMenu.Visible = value; - } - - public Action? CharacterButtonToggled { get; set; } - - public bool InventoryButtonDown - { - get => _buttonInventoryMenu.Pressed; - set - { - TopInventoryQuickButtonContainer.Visible = value; - _buttonInventoryMenu.Pressed = value; - } - } - - public bool InventoryButtonVisible - { - get => _buttonInventoryMenu.Visible; - set => _buttonInventoryMenu.Visible = value; - } - - public bool CraftingButtonDown - { - get => _buttonCraftingMenu.Pressed; - set => _buttonCraftingMenu.Pressed = value; - } - - public bool CraftingButtonVisible - { - get => _buttonCraftingMenu.Visible; - set => _buttonCraftingMenu.Visible = value; - } - - public Action? CraftingButtonToggled { get; set; } - - public bool ActionsButtonDown - { - get => _buttonActionsMenu.Pressed; - set => _buttonActionsMenu.Pressed = value; - } - - public bool ActionsButtonVisible - { - get => _buttonActionsMenu.Visible; - set => _buttonActionsMenu.Visible = value; - } - - public Action? ActionsButtonToggled { get; set; } - - public bool AdminButtonDown - { - get => _buttonAdminMenu.Pressed; - set => _buttonAdminMenu.Pressed = value; - } - - public bool AdminButtonVisible - { - get => _buttonAdminMenu.Visible; - set => _buttonAdminMenu.Visible = value; - } - - public Action? AdminButtonToggled { get; set; } - - public bool SandboxButtonDown - { - get => _buttonSandboxMenu.Pressed; - set => _buttonSandboxMenu.Pressed = value; - } - - public bool SandboxButtonVisible - { - get => _buttonSandboxMenu.Visible; - set => _buttonSandboxMenu.Visible = value; - } - - public Action? SandboxButtonToggled { get; set; } - public Control VoteContainer { get; private set; } = default!; - - public sealed class TopButton : ContainerButton - { - public const string StyleClassLabelTopButton = "topButtonLabel"; - public const string StyleClassRedTopButton = "topButtonLabel"; - private const float CustomTooltipDelay = 0.4f; - - private static readonly Color ColorNormal = Color.FromHex("#7b7e9e"); - private static readonly Color ColorRedNormal = Color.FromHex("#FEFEFE"); - private static readonly Color ColorHovered = Color.FromHex("#9699bb"); - private static readonly Color ColorRedHovered = Color.FromHex("#FFFFFF"); - private static readonly Color ColorPressed = Color.FromHex("#789B8C"); - - private const float VertPad = 8f; - - private Color NormalColor => HasStyleClass(StyleClassRedTopButton) ? ColorRedNormal : ColorNormal; - private Color HoveredColor => HasStyleClass(StyleClassRedTopButton) ? ColorRedHovered : ColorHovered; - - private readonly TextureRect _textureRect; - private readonly Label _label; - private readonly BoundKeyFunction _function; - private readonly IInputManager _inputManager; - - public TopButton(Texture texture, BoundKeyFunction function, IInputManager inputManager) - { - _function = function; - _inputManager = inputManager; - TooltipDelay = CustomTooltipDelay; - - AddChild( - new BoxContainer - { - Orientation = LayoutOrientation.Vertical, - Children = - { - (_textureRect = new TextureRect - { - TextureScale = (0.5f, 0.5f), - Texture = texture, - HorizontalAlignment = HAlignment.Center, - VerticalAlignment = VAlignment.Center, - VerticalExpand = true, - Margin = new Thickness(0, VertPad), - ModulateSelfOverride = NormalColor, - Stretch = TextureRect.StretchMode.KeepCentered - }), - (_label = new Label - { - Text = ShortKeyName(_function), - HorizontalAlignment = HAlignment.Center, - ModulateSelfOverride = NormalColor, - StyleClasses = {StyleClassLabelTopButton} - }) - } - } - ); - - ToggleMode = true; - } - - protected override void EnteredTree() - { - _inputManager.OnKeyBindingAdded += OnKeyBindingChanged; - _inputManager.OnKeyBindingRemoved += OnKeyBindingChanged; - _inputManager.OnInputModeChanged += OnKeyBindingChanged; - } - - protected override void ExitedTree() - { - _inputManager.OnKeyBindingAdded -= OnKeyBindingChanged; - _inputManager.OnKeyBindingRemoved -= OnKeyBindingChanged; - _inputManager.OnInputModeChanged -= OnKeyBindingChanged; - } - - - private void OnKeyBindingChanged(IKeyBinding obj) - { - _label.Text = ShortKeyName(_function); - } - - private void OnKeyBindingChanged() - { - _label.Text = ShortKeyName(_function); - } - - private string ShortKeyName(BoundKeyFunction keyFunction) - { - // need to use shortened key names so they fit in the buttons. - return TryGetShortKeyName(keyFunction, out var name) ? Loc.GetString(name) : " "; - } - - private bool TryGetShortKeyName(BoundKeyFunction keyFunction, [NotNullWhen(true)] out string? name) - { - if (_inputManager.TryGetKeyBinding(keyFunction, out var binding)) - { - // can't possibly fit a modifier key in the top button, so omit it - var key = binding.BaseKey; - if (binding.Mod1 != Unknown || binding.Mod2 != Unknown || - binding.Mod3 != Unknown) - { - name = null; - return false; - } - - name = null; - name = key switch - { - Apostrophe => "'", - Comma => ",", - Delete => "Del", - Down => "Dwn", - Escape => "Esc", - Equal => "=", - Home => "Hom", - Insert => "Ins", - Left => "Lft", - Menu => "Men", - Minus => "-", - Num0 => "0", - Num1 => "1", - Num2 => "2", - Num3 => "3", - Num4 => "4", - Num5 => "5", - Num6 => "6", - Num7 => "7", - Num8 => "8", - Num9 => "9", - Pause => "||", - Period => ".", - Return => "Ret", - Right => "Rgt", - Slash => "/", - Space => "Spc", - Tab => "Tab", - Tilde => "~", - BackSlash => "\\", - BackSpace => "Bks", - LBracket => "[", - MouseButton4 => "M4", - MouseButton5 => "M5", - MouseButton6 => "M6", - MouseButton7 => "M7", - MouseButton8 => "M8", - MouseButton9 => "M9", - MouseLeft => "ML", - MouseMiddle => "MM", - MouseRight => "MR", - NumpadDecimal => "N.", - NumpadDivide => "N/", - NumpadEnter => "Ent", - NumpadMultiply => "*", - NumpadNum0 => "0", - NumpadNum1 => "1", - NumpadNum2 => "2", - NumpadNum3 => "3", - NumpadNum4 => "4", - NumpadNum5 => "5", - NumpadNum6 => "6", - NumpadNum7 => "7", - NumpadNum8 => "8", - NumpadNum9 => "9", - NumpadSubtract => "N-", - PageDown => "PgD", - PageUp => "PgU", - RBracket => "]", - SemiColon => ";", - _ => DefaultShortKeyName(keyFunction) - }; - return name != null; - } - - name = null; - return false; - } - - private string? DefaultShortKeyName(BoundKeyFunction keyFunction) - { - var name = FormattedMessage.EscapeText(_inputManager.GetKeyFunctionButtonString(keyFunction)); - return name.Length > 3 ? null : name; - } - - protected override void StylePropertiesChanged() - { - // colors of children depend on style, so ensure we update when style is changed - base.StylePropertiesChanged(); - UpdateChildColors(); - } - - private void UpdateChildColors() - { - if (_label == null || _textureRect == null) return; - switch (DrawMode) - { - case DrawModeEnum.Normal: - _textureRect.ModulateSelfOverride = NormalColor; - _label.ModulateSelfOverride = NormalColor; - break; - - case DrawModeEnum.Pressed: - _textureRect.ModulateSelfOverride = ColorPressed; - _label.ModulateSelfOverride = ColorPressed; - break; - - case DrawModeEnum.Hover: - _textureRect.ModulateSelfOverride = HoveredColor; - _label.ModulateSelfOverride = HoveredColor; - break; - - case DrawModeEnum.Disabled: - break; - } - } - - - protected override void DrawModeChanged() - { - base.DrawModeChanged(); - UpdateChildColors(); - } - } } } diff --git a/Content.Client/HUD/UI/TopButton.cs b/Content.Client/HUD/UI/TopButton.cs new file mode 100644 index 0000000000..a8d2d39b3f --- /dev/null +++ b/Content.Client/HUD/UI/TopButton.cs @@ -0,0 +1,230 @@ +using System.Diagnostics.CodeAnalysis; +using Robust.Client.Graphics; +using Robust.Client.Input; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Input; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using Robust.Shared.Utility; + +namespace Content.Client.HUD.UI; + +internal sealed class TopButton : ContainerButton +{ + public const string StyleClassLabelTopButton = "topButtonLabel"; + public const string StyleClassRedTopButton = "topButtonLabel"; + private const float CustomTooltipDelay = 0.4f; + + private static readonly Color ColorNormal = Color.FromHex("#7b7e9e"); + private static readonly Color ColorRedNormal = Color.FromHex("#FEFEFE"); + private static readonly Color ColorHovered = Color.FromHex("#9699bb"); + private static readonly Color ColorRedHovered = Color.FromHex("#FFFFFF"); + private static readonly Color ColorPressed = Color.FromHex("#789B8C"); + + private const float VertPad = 8f; + private Color NormalColor => HasStyleClass(StyleClassRedTopButton) ? ColorRedNormal : ColorNormal; + private Color HoveredColor => HasStyleClass(StyleClassRedTopButton) ? ColorRedHovered : ColorHovered; + + private readonly TextureRect _textureRect; + private readonly Label _label; + private readonly BoundKeyFunction _function; + private readonly IInputManager _inputManager; + + public TopButton(Texture texture, BoundKeyFunction function, IInputManager inputManager) + { + _function = function; + _inputManager = inputManager; + TooltipDelay = CustomTooltipDelay; + + AddChild( + new BoxContainer + { + Orientation = BoxContainer.LayoutOrientation.Vertical, + Children = + { + (_textureRect = new TextureRect + { + TextureScale = (0.5f, 0.5f), + Texture = texture, + HorizontalAlignment = HAlignment.Center, + VerticalAlignment = VAlignment.Center, + VerticalExpand = true, + Margin = new Thickness(0, VertPad), + ModulateSelfOverride = NormalColor, + Stretch = TextureRect.StretchMode.KeepCentered + }), + (_label = new Label + { + Text = ShortKeyName(_function), + HorizontalAlignment = HAlignment.Center, + ModulateSelfOverride = NormalColor, + StyleClasses = {StyleClassLabelTopButton} + }) + } + } + ); + + ToggleMode = true; + } + + protected override void EnteredTree() + { + _inputManager.OnKeyBindingAdded += OnKeyBindingChanged; + _inputManager.OnKeyBindingRemoved += OnKeyBindingChanged; + _inputManager.OnInputModeChanged += OnKeyBindingChanged; + } + + protected override void ExitedTree() + { + _inputManager.OnKeyBindingAdded -= OnKeyBindingChanged; + _inputManager.OnKeyBindingRemoved -= OnKeyBindingChanged; + _inputManager.OnInputModeChanged -= OnKeyBindingChanged; + } + + + private void OnKeyBindingChanged(IKeyBinding obj) + { + _label.Text = ShortKeyName(_function); + } + + private void OnKeyBindingChanged() + { + _label.Text = ShortKeyName(_function); + } + + private string ShortKeyName(BoundKeyFunction keyFunction) + { + // need to use shortened key names so they fit in the buttons. + return TryGetShortKeyName(keyFunction, out var name) ? Loc.GetString(name) : " "; + } + + private bool TryGetShortKeyName(BoundKeyFunction keyFunction, [NotNullWhen(true)] out string? name) + { + if (_inputManager.TryGetKeyBinding(keyFunction, out var binding)) + { + // can't possibly fit a modifier key in the top button, so omit it + var key = binding.BaseKey; + if (binding.Mod1 != Keyboard.Key.Unknown || binding.Mod2 != Keyboard.Key.Unknown || + binding.Mod3 != Keyboard.Key.Unknown) + { + name = null; + return false; + } + + name = null; + name = key switch + { + Keyboard.Key.Apostrophe => "'", + Keyboard.Key.Comma => ",", + Keyboard.Key.Delete => "Del", + Keyboard.Key.Down => "Dwn", + Keyboard.Key.Escape => "Esc", + Keyboard.Key.Equal => "=", + Keyboard.Key.Home => "Hom", + Keyboard.Key.Insert => "Ins", + Keyboard.Key.Left => "Lft", + Keyboard.Key.Menu => "Men", + Keyboard.Key.Minus => "-", + Keyboard.Key.Num0 => "0", + Keyboard.Key.Num1 => "1", + Keyboard.Key.Num2 => "2", + Keyboard.Key.Num3 => "3", + Keyboard.Key.Num4 => "4", + Keyboard.Key.Num5 => "5", + Keyboard.Key.Num6 => "6", + Keyboard.Key.Num7 => "7", + Keyboard.Key.Num8 => "8", + Keyboard.Key.Num9 => "9", + Keyboard.Key.Pause => "||", + Keyboard.Key.Period => ".", + Keyboard.Key.Return => "Ret", + Keyboard.Key.Right => "Rgt", + Keyboard.Key.Slash => "/", + Keyboard.Key.Space => "Spc", + Keyboard.Key.Tab => "Tab", + Keyboard.Key.Tilde => "~", + Keyboard.Key.BackSlash => "\\", + Keyboard.Key.BackSpace => "Bks", + Keyboard.Key.LBracket => "[", + Keyboard.Key.MouseButton4 => "M4", + Keyboard.Key.MouseButton5 => "M5", + Keyboard.Key.MouseButton6 => "M6", + Keyboard.Key.MouseButton7 => "M7", + Keyboard.Key.MouseButton8 => "M8", + Keyboard.Key.MouseButton9 => "M9", + Keyboard.Key.MouseLeft => "ML", + Keyboard.Key.MouseMiddle => "MM", + Keyboard.Key.MouseRight => "MR", + Keyboard.Key.NumpadDecimal => "N.", + Keyboard.Key.NumpadDivide => "N/", + Keyboard.Key.NumpadEnter => "Ent", + Keyboard.Key.NumpadMultiply => "*", + Keyboard.Key.NumpadNum0 => "0", + Keyboard.Key.NumpadNum1 => "1", + Keyboard.Key.NumpadNum2 => "2", + Keyboard.Key.NumpadNum3 => "3", + Keyboard.Key.NumpadNum4 => "4", + Keyboard.Key.NumpadNum5 => "5", + Keyboard.Key.NumpadNum6 => "6", + Keyboard.Key.NumpadNum7 => "7", + Keyboard.Key.NumpadNum8 => "8", + Keyboard.Key.NumpadNum9 => "9", + Keyboard.Key.NumpadSubtract => "N-", + Keyboard.Key.PageDown => "PgD", + Keyboard.Key.PageUp => "PgU", + Keyboard.Key.RBracket => "]", + Keyboard.Key.SemiColon => ";", + _ => DefaultShortKeyName(keyFunction) + }; + return name != null; + } + + name = null; + return false; + } + + private string? DefaultShortKeyName(BoundKeyFunction keyFunction) + { + var name = FormattedMessage.EscapeText(_inputManager.GetKeyFunctionButtonString(keyFunction)); + return name.Length > 3 ? null : name; + } + + protected override void StylePropertiesChanged() + { + // colors of children depend on style, so ensure we update when style is changed + base.StylePropertiesChanged(); + UpdateChildColors(); + } + + private void UpdateChildColors() + { + if (_label == null || _textureRect == null) return; + switch (DrawMode) + { + case DrawModeEnum.Normal: + _textureRect.ModulateSelfOverride = NormalColor; + _label.ModulateSelfOverride = NormalColor; + break; + + case DrawModeEnum.Pressed: + _textureRect.ModulateSelfOverride = ColorPressed; + _label.ModulateSelfOverride = ColorPressed; + break; + + case DrawModeEnum.Hover: + _textureRect.ModulateSelfOverride = HoveredColor; + _label.ModulateSelfOverride = HoveredColor; + break; + + case DrawModeEnum.Disabled: + break; + } + } + + + protected override void DrawModeChanged() + { + base.DrawModeChanged(); + UpdateChildColors(); + } +} diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index 2fb289660c..075dfc9941 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -234,7 +234,11 @@ namespace Content.Client.Inventory Title = Loc.GetString("human-inventory-window-title"), Resizable = false }; - window.OnClose += () => _gameHud.InventoryButtonDown = false; + window.OnClose += () => + { + _gameHud.InventoryButtonDown = false; + _gameHud.TopInventoryQuickButtonContainer.Visible = false; + }; var windowContents = new LayoutContainer { MinSize = (ButtonSize * 4 + ButtonSeparation * 3 + RightSeparation, @@ -337,6 +341,7 @@ namespace Content.Client.Inventory private void HandleOpenInventoryMenu() { _gameHud.InventoryButtonDown = !_gameHud.InventoryButtonDown; + _gameHud.TopInventoryQuickButtonContainer.Visible = _gameHud.InventoryButtonDown; } } } diff --git a/Content.Client/Sandbox/SandboxManager.cs b/Content.Client/Sandbox/SandboxManager.cs index b515fded6c..003c4ed12c 100644 --- a/Content.Client/Sandbox/SandboxManager.cs +++ b/Content.Client/Sandbox/SandboxManager.cs @@ -148,7 +148,7 @@ namespace Content.Client.Sandbox _netManager.RegisterNetMessage(); - _gameHud.SandboxButtonToggled = SandboxButtonPressed; + _gameHud.SandboxButtonToggled += SandboxButtonPressed; _inputManager.SetInputCommand(ContentKeyFunctions.OpenEntitySpawnWindow, InputCmdHandler.FromDelegate(session => ToggleEntitySpawnWindow())); diff --git a/Content.Client/Stylesheets/StyleNano.cs b/Content.Client/Stylesheets/StyleNano.cs index 14986e3b5e..3e15c299cd 100644 --- a/Content.Client/Stylesheets/StyleNano.cs +++ b/Content.Client/Stylesheets/StyleNano.cs @@ -2,7 +2,6 @@ using System.Linq; using Content.Client.Actions.UI; using Content.Client.ContextMenu.UI; using Content.Client.Examine; -using Content.Client.HUD; using Content.Client.HUD.UI; using Content.Client.Resources; using Content.Client.Targeting; @@ -1008,70 +1007,70 @@ namespace Content.Client.Stylesheets // which is NOT the case for the default BaseButton styles (OpenLeft/OpenRight adds extra padding on one of the sides // which makes the TopButton icons appear off-center, which we don't want). new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), new[] {ButtonSquare}, null, null), + new SelectorElement(typeof(TopButton), new[] {ButtonSquare}, null, null), new[] { new StyleProperty(Button.StylePropertyStyleBox, topButtonSquare), }), new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), new[] {ButtonOpenLeft}, null, null), + new SelectorElement(typeof(TopButton), new[] {ButtonOpenLeft}, null, null), new[] { new StyleProperty(Button.StylePropertyStyleBox, topButtonOpenLeft), }), new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), new[] {ButtonOpenRight}, null, null), + new SelectorElement(typeof(TopButton), new[] {ButtonOpenRight}, null, null), new[] { new StyleProperty(Button.StylePropertyStyleBox, topButtonOpenRight), }), new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), null, null, new[] {Button.StylePseudoClassNormal}), + new SelectorElement(typeof(TopButton), null, null, new[] {Button.StylePseudoClassNormal}), new[] { new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorDefault), }), new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), new[] {GameHud.TopButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}), + new SelectorElement(typeof(TopButton), new[] {TopButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassNormal}), new[] { new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorDefaultRed), }), new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), null, null, new[] {Button.StylePseudoClassNormal}), + new SelectorElement(typeof(TopButton), null, null, new[] {Button.StylePseudoClassNormal}), new[] { new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorDefault), }), new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), null, null, new[] {Button.StylePseudoClassPressed}), + new SelectorElement(typeof(TopButton), null, null, new[] {Button.StylePseudoClassPressed}), new[] { new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorPressed), }), new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), null, null, new[] {Button.StylePseudoClassHover}), + new SelectorElement(typeof(TopButton), null, null, new[] {Button.StylePseudoClassHover}), new[] { new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorHovered), }), new StyleRule( - new SelectorElement(typeof(GameHud.TopButton), new[] {GameHud.TopButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassHover}), + new SelectorElement(typeof(TopButton), new[] {TopButton.StyleClassRedTopButton}, null, new[] {Button.StylePseudoClassHover}), new[] { new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorHoveredRed), }), new StyleRule( - new SelectorElement(typeof(Label), new[] {GameHud.TopButton.StyleClassLabelTopButton}, null, null), + new SelectorElement(typeof(Label), new[] {TopButton.StyleClassLabelTopButton}, null, null), new[] { new StyleProperty(Label.StylePropertyFont, notoSansDisplayBold14),