diff --git a/Content.Client/Sandbox/SandboxManager.cs b/Content.Client/Sandbox/SandboxManager.cs index 0f0f727a29..a7a79fe884 100644 --- a/Content.Client/Sandbox/SandboxManager.cs +++ b/Content.Client/Sandbox/SandboxManager.cs @@ -33,10 +33,12 @@ namespace Content.Client.Sandbox public readonly Button ShowMarkersButton; //Shows spawn points public readonly Button ShowBbButton; //Shows bounding boxes public readonly Button MachineLinkingButton; // Enables/disables machine linking mode. + private readonly IGameHud _gameHud; public SandboxWindow() { Resizable = false; + _gameHud = IoCManager.Resolve(); Title = "Sandbox Panel"; @@ -82,6 +84,20 @@ namespace Content.Client.Sandbox MachineLinkingButton = new Button { Text = Loc.GetString("Link machines"), ToggleMode = true }; vBox.AddChild(MachineLinkingButton); } + + + protected override void EnteredTree() + { + base.EnteredTree(); + _gameHud.SandboxButtonDown = true; + } + + protected override void ExitedTree() + { + base.ExitedTree(); + _gameHud.SandboxButtonDown = false; + } + } internal class SandboxManager : SharedSandboxManager, ISandboxManager @@ -197,7 +213,6 @@ namespace Content.Client.Sandbox private void WindowOnOnClose() { _window = null; - _gameHud.SandboxButtonDown = false; _sandboxWindowToggled = false; } diff --git a/Content.Client/UserInterface/ActionMenu.cs b/Content.Client/UserInterface/ActionMenu.cs index c51d27ac86..06b6312267 100644 --- a/Content.Client/UserInterface/ActionMenu.cs +++ b/Content.Client/UserInterface/ActionMenu.cs @@ -56,6 +56,7 @@ namespace Content.Client.UserInterface private readonly Button _clearButton; private readonly GridContainer _resultsGrid; private readonly TextureRect _dragShadow; + private readonly IGameHud _gameHud; private readonly DragDropHelper _dragDropHelper; @@ -64,6 +65,8 @@ namespace Content.Client.UserInterface _actionsComponent = actionsComponent; _actionsUI = actionsUI; _actionManager = IoCManager.Resolve(); + _gameHud = IoCManager.Resolve(); + Title = Loc.GetString("Actions"); CustomMinimumSize = (300, 300); @@ -143,14 +146,13 @@ namespace Content.Client.UserInterface _dragDropHelper = new DragDropHelper(OnBeginActionDrag, OnContinueActionDrag, OnEndActionDrag); } - protected override void EnteredTree() { base.EnteredTree(); _clearButton.OnPressed += OnClearButtonPressed; _searchBar.OnTextChanged += OnSearchTextChanged; _filterButton.OnItemSelected += OnFilterItemSelected; - + _gameHud.ActionsButtonDown = true; foreach (var actionMenuControl in _resultsGrid.Children) { var actionMenuItem = (actionMenuControl as ActionMenuItem); @@ -167,7 +169,7 @@ namespace Content.Client.UserInterface _clearButton.OnPressed -= OnClearButtonPressed; _searchBar.OnTextChanged -= OnSearchTextChanged; _filterButton.OnItemSelected -= OnFilterItemSelected; - + _gameHud.ActionsButtonDown = false; foreach (var actionMenuControl in _resultsGrid.Children) { var actionMenuItem = (actionMenuControl as ActionMenuItem); diff --git a/Content.Client/UserInterface/ActionsUI.cs b/Content.Client/UserInterface/ActionsUI.cs index 1a7f9d7074..7fe3703df8 100644 --- a/Content.Client/UserInterface/ActionsUI.cs +++ b/Content.Client/UserInterface/ActionsUI.cs @@ -32,6 +32,7 @@ namespace Content.Client.UserInterface private readonly ActionManager _actionManager; private readonly IEntityManager _entityManager; private readonly IGameTiming _gameTiming; + private readonly IGameHud _gameHud; private readonly ActionSlot[] _slots; @@ -80,13 +81,15 @@ namespace Content.Client.UserInterface _actionManager = IoCManager.Resolve(); _entityManager = IoCManager.Resolve(); _gameTiming = IoCManager.Resolve(); + _gameHud = IoCManager.Resolve(); _menu = new ActionMenu(_actionsComponent, this); + LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.End); LayoutContainer.SetGrowVertical(this, LayoutContainer.GrowDirection.End); LayoutContainer.SetAnchorTop(this, 0f); LayoutContainer.SetAnchorBottom(this, 0.8f); - LayoutContainer.SetMarginLeft(this, 10); - LayoutContainer.SetMarginTop(this, 100); + LayoutContainer.SetMarginLeft(this, 13); + LayoutContainer.SetMarginTop(this, 110); SizeFlagsHorizontal = SizeFlags.None; SizeFlagsVertical = SizeFlags.FillExpand; @@ -208,6 +211,9 @@ namespace Content.Client.UserInterface _lockButton.OnPressed += OnLockPressed; _settingsButton.OnPressed += OnToggleActionsMenu; _loadoutContainer.OnKeyBindDown += OnHotbarPaginate; + _gameHud.ActionsButtonToggled += OnToggleActionsMenuTopButton; + _gameHud.ActionsButtonDown = false; + _gameHud.ActionsButtonVisible = true; } protected override void ExitedTree() @@ -218,6 +224,9 @@ namespace Content.Client.UserInterface _lockButton.OnPressed -= OnLockPressed; _settingsButton.OnPressed -= OnToggleActionsMenu; _loadoutContainer.OnKeyBindDown -= OnHotbarPaginate; + _gameHud.ActionsButtonToggled -= OnToggleActionsMenuTopButton; + _gameHud.ActionsButtonDown = false; + _gameHud.ActionsButtonVisible = false; } protected override Vector2 CalculateMinimumSize() @@ -496,6 +505,13 @@ namespace Content.Client.UserInterface ToggleActionsMenu(); } + + private void OnToggleActionsMenuTopButton(bool open) + { + if (open == _menu.IsOpen) return; + ToggleActionsMenu(); + } + public void ToggleActionsMenu() { if (_menu.IsOpen) diff --git a/Content.Client/UserInterface/AdminMenu/AdminMenuManager.cs b/Content.Client/UserInterface/AdminMenu/AdminMenuManager.cs index 94b29253cf..c9caaedc71 100644 --- a/Content.Client/UserInterface/AdminMenu/AdminMenuManager.cs +++ b/Content.Client/UserInterface/AdminMenu/AdminMenuManager.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Content.Client.Administration; using Content.Shared.Input; using Robust.Client.Console; using Robust.Client.Interfaces.Input; @@ -13,6 +14,8 @@ namespace Content.Client.UserInterface.AdminMenu { [Dependency] private readonly INetManager _netManager = default!; [Dependency] private readonly IInputManager _inputManager = default!; + [Dependency] private readonly IGameHud _gameHud = default!; + [Dependency] private readonly IClientAdminManager _clientAdminManager = default!; [Dependency] private readonly IClientConGroupController _clientConGroupController = default!; private SS14Window _window; @@ -26,6 +29,30 @@ namespace Content.Client.UserInterface.AdminMenu _inputManager.SetInputCommand(ContentKeyFunctions.OpenAdminMenu, InputCmdHandler.FromDelegate(session => Toggle())); + + _clientAdminManager.AdminStatusUpdated += () => + { + // when status changes, show the top button if we can open admin menu. + // if we can't or we lost admin status, close it and hide the button. + _gameHud.AdminButtonVisible = CanOpen(); + if (!_gameHud.AdminButtonVisible) + { + Close(); + } + }; + _gameHud.AdminButtonToggled += (open) => + { + if (open) + { + TryOpen(); + } + else + { + Close(); + } + }; + _gameHud.AdminButtonVisible = CanOpen(); + _gameHud.AdminButtonDown = false; } public void ResetWindow() diff --git a/Content.Client/UserInterface/AdminMenu/AdminMenuWindow.cs b/Content.Client/UserInterface/AdminMenu/AdminMenuWindow.cs index e02483d5ee..c166d2e0d0 100644 --- a/Content.Client/UserInterface/AdminMenu/AdminMenuWindow.cs +++ b/Content.Client/UserInterface/AdminMenu/AdminMenuWindow.cs @@ -31,6 +31,7 @@ namespace Content.Client.UserInterface.AdminMenu public readonly TabContainer MasterTabContainer; public readonly VBoxContainer PlayerList; public readonly Label PlayerCount; + private readonly IGameHud _gameHud; protected override Vector2? CustomSize => (500, 250); @@ -207,6 +208,7 @@ namespace Content.Client.UserInterface.AdminMenu public AdminMenuWindow() //TODO: search for buttons? { + _gameHud = IoCManager.Resolve(); Title = Loc.GetString("Admin Menu"); #region PlayerList @@ -377,6 +379,19 @@ namespace Content.Client.UserInterface.AdminMenu IoCManager.Resolve().RequestEvents(); } + protected override void ExitedTree() + { + base.ExitedTree(); + _gameHud.AdminButtonDown = false; + + } + + protected override void EnteredTree() + { + base.EnteredTree(); + _gameHud.AdminButtonDown = true; + } + #region CommandButtonBaseClass private abstract class CommandButton { diff --git a/Content.Client/UserInterface/GameHud.cs b/Content.Client/UserInterface/GameHud.cs index 31f12c03f0..05c664b44e 100644 --- a/Content.Client/UserInterface/GameHud.cs +++ b/Content.Client/UserInterface/GameHud.cs @@ -1,17 +1,25 @@ using System; +using System.Transactions; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.Input; using Robust.Client.Graphics; using Robust.Client.Graphics.Drawing; +using Robust.Client.Input; using Robust.Client.Interfaces.Input; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; +using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; +using Robust.Shared.Utility; +using YamlDotNet.Core.Tokens; +using static Robust.Client.Input.Keyboard.Key; +using Control = Robust.Client.UserInterface.Control; namespace Content.Client.UserInterface { @@ -41,6 +49,16 @@ namespace Content.Client.UserInterface 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; } @@ -69,6 +87,8 @@ namespace Content.Client.UserInterface private TopButton _buttonCharacterMenu; private TopButton _buttonInventoryMenu; private TopButton _buttonCraftingMenu; + private TopButton _buttonActionsMenu; + private TopButton _buttonAdminMenu; private TopButton _buttonSandboxMenu; private TutorialWindow _tutorialWindow; private TargetingDoll _targetingDoll; @@ -112,12 +132,14 @@ namespace Content.Client.UserInterface var characterTexture = _resourceCache.GetTexture("/Textures/Interface/character.svg.96dpi.png"); var inventoryTexture = _resourceCache.GetTexture("/Textures/Interface/inventory.svg.96dpi.png"); var craftingTexture = _resourceCache.GetTexture("/Textures/Interface/hammer.svg.96dpi.png"); - var tutorialTexture = _resourceCache.GetTexture("/Textures/Interface/students-cap.svg.96dpi.png"); + var actionsTexture = _resourceCache.GetTexture("/Textures/Interface/fist.svg.96dpi.png"); + var adminTexture = _resourceCache.GetTexture("/Textures/Interface/gavel.svg.96dpi.png"); + var tutorialTexture = _resourceCache.GetTexture("/Textures/Interface/tutorial.svg.96dpi.png"); var sandboxTexture = _resourceCache.GetTexture("/Textures/Interface/sandbox.svg.96dpi.png"); _topButtonsContainer = new HBoxContainer { - SeparationOverride = 4 + SeparationOverride = 8 }; RootControl.AddChild(_topButtonsContainer); @@ -125,32 +147,29 @@ namespace Content.Client.UserInterface LayoutContainer.SetAnchorAndMarginPreset(_topButtonsContainer, LayoutContainer.LayoutPreset.TopLeft, margin: 10); - // TODO: Pull key names here from the actual key binding config. + // 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, "Esc") + _buttonEscapeMenu = new TopButton(escapeTexture, EngineKeyFunctions.EscapeMenu, _inputManager) { - ToolTip = Loc.GetString("Open escape menu.") + ToolTip = Loc.GetString("Open escape menu."), + CustomMinimumSize = (70, 64), + StyleClasses = {StyleBase.ButtonOpenRight} }; _topButtonsContainer.AddChild(_buttonEscapeMenu); _buttonEscapeMenu.OnToggled += args => EscapeButtonToggled?.Invoke(args.Pressed); - // Tutorial - _buttonTutorial = new TopButton(tutorialTexture, "F1") - { - ToolTip = Loc.GetString("Open tutorial.") - }; - - _topButtonsContainer.AddChild(_buttonTutorial); - - _buttonTutorial.OnToggled += a => ButtonTutorialOnOnToggled(); - // Character - _buttonCharacterMenu = new TopButton(characterTexture, "C") + _buttonCharacterMenu = new TopButton(characterTexture, ContentKeyFunctions.OpenCharacterMenu, _inputManager) { ToolTip = Loc.GetString("Open character menu."), - Visible = false + CustomMinimumSize = topMinSize, + Visible = false, + StyleClasses = {StyleBase.ButtonSquare} }; _topButtonsContainer.AddChild(_buttonCharacterMenu); @@ -158,10 +177,12 @@ namespace Content.Client.UserInterface _buttonCharacterMenu.OnToggled += args => CharacterButtonToggled?.Invoke(args.Pressed); // Inventory - _buttonInventoryMenu = new TopButton(inventoryTexture, "I") + _buttonInventoryMenu = new TopButton(inventoryTexture, ContentKeyFunctions.OpenInventoryMenu, _inputManager) { ToolTip = Loc.GetString("Open inventory menu."), - Visible = false + CustomMinimumSize = topMinSize, + Visible = false, + StyleClasses = {StyleBase.ButtonSquare} }; _topButtonsContainer.AddChild(_buttonInventoryMenu); @@ -169,27 +190,69 @@ namespace Content.Client.UserInterface _buttonInventoryMenu.OnToggled += args => InventoryButtonToggled?.Invoke(args.Pressed); // Crafting - _buttonCraftingMenu = new TopButton(craftingTexture, "G") + _buttonCraftingMenu = new TopButton(craftingTexture, ContentKeyFunctions.OpenCraftingMenu, _inputManager) { ToolTip = Loc.GetString("Open crafting menu."), - Visible = false + CustomMinimumSize = 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("Open actions menu."), + CustomMinimumSize = 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("Open admin menu."), + CustomMinimumSize = topMinSize, + Visible = false, + StyleClasses = {StyleBase.ButtonSquare} + }; + + _topButtonsContainer.AddChild(_buttonAdminMenu); + + _buttonAdminMenu.OnToggled += args => AdminButtonToggled?.Invoke(args.Pressed); + // Sandbox - _buttonSandboxMenu = new TopButton(sandboxTexture, "B") + _buttonSandboxMenu = new TopButton(sandboxTexture, ContentKeyFunctions.OpenSandboxWindow, _inputManager) { ToolTip = Loc.GetString("Open sandbox menu."), - Visible = false + CustomMinimumSize = topMinSize, + Visible = false, + StyleClasses = {StyleBase.ButtonSquare} }; _topButtonsContainer.AddChild(_buttonSandboxMenu); _buttonSandboxMenu.OnToggled += args => SandboxButtonToggled?.Invoke(args.Pressed); + // Tutorial + _buttonTutorial = new TopButton(tutorialTexture, ContentKeyFunctions.OpenTutorial, _inputManager) + { + ToolTip = Loc.GetString("Open tutorial."), + CustomMinimumSize = topMinSize, + StyleClasses = {StyleBase.ButtonOpenLeft, TopButton.StyleClassRedTopButton}, + }; + + _topButtonsContainer.AddChild(_buttonTutorial); + + _buttonTutorial.OnToggled += a => ButtonTutorialOnOnToggled(); + _tutorialWindow = new TutorialWindow(); _tutorialWindow.OnClose += () => _buttonTutorial.Pressed = false; @@ -251,7 +314,8 @@ namespace Content.Client.UserInterface RootControl.AddChild(SuspicionContainer); - LayoutContainer.SetAnchorAndMarginPreset(SuspicionContainer, LayoutContainer.LayoutPreset.BottomLeft, margin: 10); + LayoutContainer.SetAnchorAndMarginPreset(SuspicionContainer, LayoutContainer.LayoutPreset.BottomLeft, + margin: 10); LayoutContainer.SetGrowHorizontal(SuspicionContainer, LayoutContainer.GrowDirection.End); LayoutContainer.SetGrowVertical(SuspicionContainer, LayoutContainer.GrowDirection.Begin); } @@ -330,6 +394,34 @@ namespace Content.Client.UserInterface 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; @@ -344,94 +436,203 @@ namespace Content.Client.UserInterface public Action SandboxButtonToggled { get; set; } - public sealed class TopButton : BaseButton + 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, string keyName) + public TopButton(Texture texture, BoundKeyFunction function, IInputManager inputManager) { - ToggleMode = true; + _function = function; + _inputManager = inputManager; + TooltipDelay = CustomTooltipDelay; - AddChild(new MarginContainer - { - MarginTopOverride = 4, - Children = + AddChild( + new VBoxContainer { - new VBoxContainer + Children = { - Children = + new Control {CustomMinimumSize = (0, VertPad)}, + (_textureRect = new TextureRect { - (_textureRect = new TextureRect - { - Texture = texture, - SizeFlagsHorizontal = SizeFlags.ShrinkCenter, - SizeFlagsVertical = SizeFlags.Expand | SizeFlags.ShrinkCenter, - ModulateSelfOverride = ColorNormal, - CustomMinimumSize = (0, 32), - Stretch = TextureRect.StretchMode.KeepCentered - }), - (_label = new Label - { - Text = keyName, - SizeFlagsHorizontal = SizeFlags.ShrinkCenter, - ModulateSelfOverride = ColorNormal, - StyleClasses = {StyleClassLabelTopButton} - }) - } + Texture = texture, + SizeFlagsHorizontal = SizeFlags.ShrinkCenter, + SizeFlagsVertical = SizeFlags.Expand | SizeFlags.ShrinkCenter, + ModulateSelfOverride = NormalColor, + Stretch = TextureRect.StretchMode.KeepCentered + }), + new Control {CustomMinimumSize = (0, VertPad)}, + (_label = new Label + { + Text = ShortKeyName(_function), + SizeFlagsHorizontal = SizeFlags.ShrinkCenter, + ModulateSelfOverride = NormalColor, + StyleClasses = {StyleClassLabelTopButton} + }) } } - }); + ); - DrawModeChanged(); + ToggleMode = true; } - protected override Vector2 CalculateMinimumSize() + protected override void EnteredTree() { - var styleSize = ActualStyleBox?.MinimumSize ?? Vector2.Zero; - return (0, 4) + styleSize + base.CalculateMinimumSize(); + _inputManager.OnKeyBindingAdded += OnKeyBindingChanged; + _inputManager.OnKeyBindingRemoved += OnKeyBindingChanged; } - protected override void Draw(DrawingHandleScreen handle) + protected override void ExitedTree() { - ActualStyleBox?.Draw(handle, PixelSizeBox); + _inputManager.OnKeyBindingAdded -= OnKeyBindingChanged; + _inputManager.OnKeyBindingRemoved -= OnKeyBindingChanged; } - private StyleBox ActualStyleBox + + private void OnKeyBindingChanged(IKeyBinding obj) { - get + _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, out string name) + { + if (_inputManager.TryGetKeyBinding(keyFunction, out var binding)) { - TryGetStyleProperty(Button.StylePropertyStyleBox, out StyleBox ret); - return ret; + // 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; } - protected override void DrawModeChanged() + 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: - SetOnlyStylePseudoClass(Button.StylePseudoClassNormal); - _textureRect.ModulateSelfOverride = ColorNormal; - _label.ModulateSelfOverride = ColorNormal; + _textureRect.ModulateSelfOverride = NormalColor; + _label.ModulateSelfOverride = NormalColor; break; case DrawModeEnum.Pressed: - SetOnlyStylePseudoClass(Button.StylePseudoClassPressed); _textureRect.ModulateSelfOverride = ColorPressed; _label.ModulateSelfOverride = ColorPressed; break; case DrawModeEnum.Hover: - SetOnlyStylePseudoClass(Button.StylePseudoClassHover); - _textureRect.ModulateSelfOverride = ColorHovered; - _label.ModulateSelfOverride = ColorHovered; + _textureRect.ModulateSelfOverride = HoveredColor; + _label.ModulateSelfOverride = HoveredColor; break; case DrawModeEnum.Disabled: @@ -439,15 +640,11 @@ namespace Content.Client.UserInterface } } - protected override void LayoutUpdateOverride() - { - var box = ActualStyleBox ?? new StyleBoxEmpty(); - var contentBox = box.GetContentBox(PixelSizeBox); - foreach (var child in Children) - { - FitChildInPixelBox(child, (UIBox2i) contentBox); - } + protected override void DrawModeChanged() + { + base.DrawModeChanged(); + UpdateChildColors(); } } } diff --git a/Content.Client/UserInterface/Stylesheets/StyleBase.cs b/Content.Client/UserInterface/Stylesheets/StyleBase.cs index 83dd9c26cb..bf62514e8d 100644 --- a/Content.Client/UserInterface/Stylesheets/StyleBase.cs +++ b/Content.Client/UserInterface/Stylesheets/StyleBase.cs @@ -17,6 +17,7 @@ namespace Content.Client.UserInterface.Stylesheets public const string ButtonOpenRight = "OpenRight"; public const string ButtonOpenLeft = "OpenLeft"; public const string ButtonOpenBoth = "OpenBoth"; + public const string ButtonSquare = "ButtonSquare"; public const string ButtonCaution = "Caution"; @@ -28,6 +29,7 @@ namespace Content.Client.UserInterface.Stylesheets protected StyleBoxTexture BaseButtonOpenRight { get; } protected StyleBoxTexture BaseButtonOpenLeft { get; } protected StyleBoxTexture BaseButtonOpenBoth { get; } + protected StyleBoxTexture BaseButtonSquare { get; } protected StyleBase(IResourceCache resCache) { @@ -70,6 +72,15 @@ namespace Content.Client.UserInterface.Stylesheets BaseButtonOpenBoth.SetPadding(StyleBox.Margin.Right, 2); BaseButtonOpenBoth.SetPadding(StyleBox.Margin.Left, 1); + BaseButtonSquare = new StyleBoxTexture(BaseButton) + { + Texture = new AtlasTexture(buttonTex, UIBox2.FromDimensions((10, 0), (3, 24))), + }; + BaseButtonSquare.SetPatchMargin(StyleBox.Margin.Horizontal, 0); + BaseButtonSquare.SetContentMarginOverride(StyleBox.Margin.Horizontal, 8); + BaseButtonSquare.SetPadding(StyleBox.Margin.Right, 2); + BaseButtonSquare.SetPadding(StyleBox.Margin.Left, 1); + BaseRules = new[] { // Default font. diff --git a/Content.Client/UserInterface/Stylesheets/StyleNano.cs b/Content.Client/UserInterface/Stylesheets/StyleNano.cs index 734946b907..ba2372b4a4 100644 --- a/Content.Client/UserInterface/Stylesheets/StyleNano.cs +++ b/Content.Client/UserInterface/Stylesheets/StyleNano.cs @@ -2,6 +2,7 @@ using Content.Client.GameObjects.EntitySystems; using Content.Client.UserInterface.Controls; using Content.Client.Utility; +using Robust.Client.Graphics; using Robust.Client.Graphics.Drawing; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.UserInterface; @@ -44,7 +45,9 @@ namespace Content.Client.UserInterface.Stylesheets public static readonly Color NanoGold = Color.FromHex("#A88B5E"); public static readonly Color ButtonColorDefault = Color.FromHex("#464966"); + public static readonly Color ButtonColorDefaultRed = Color.FromHex("#D43B3B"); public static readonly Color ButtonColorHovered = Color.FromHex("#575b7f"); + public static readonly Color ButtonColorHoveredRed = Color.FromHex("#DF6B6B"); public static readonly Color ButtonColorPressed = Color.FromHex("#3e6c45"); public static readonly Color ButtonColorDisabled = Color.FromHex("#30313c"); @@ -162,6 +165,33 @@ namespace Content.Client.UserInterface.Stylesheets Modulate = ButtonColorPressed }; + var buttonTex = resCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"); + var topButtonBase = new StyleBoxTexture + { + Texture = buttonTex, + }; + topButtonBase.SetPatchMargin(StyleBox.Margin.All, 10); + topButtonBase.SetPadding(StyleBox.Margin.All, 0); + topButtonBase.SetContentMarginOverride(StyleBox.Margin.All, 0); + + var topButtonOpenRight = new StyleBoxTexture(topButtonBase) + { + Texture = new AtlasTexture(buttonTex, UIBox2.FromDimensions((0, 0), (14, 24))), + }; + topButtonOpenRight.SetPatchMargin(StyleBox.Margin.Right, 0); + + var topButtonOpenLeft = new StyleBoxTexture(topButtonBase) + { + Texture = new AtlasTexture(buttonTex, UIBox2.FromDimensions((10, 0), (14, 24))), + }; + topButtonOpenLeft.SetPatchMargin(StyleBox.Margin.Left, 0); + + var topButtonSquare = new StyleBoxTexture(topButtonBase) + { + Texture = new AtlasTexture(buttonTex, UIBox2.FromDimensions((10, 0), (3, 24))), + }; + topButtonSquare.SetPatchMargin(StyleBox.Margin.Horizontal, 0); + var textureInvertedTriangle = resCache.GetTexture("/Textures/Interface/Nano/inverted_triangle.svg.png"); var lineEditTex = resCache.GetTexture("/Textures/Interface/Nano/lineedit.png"); @@ -410,6 +440,10 @@ namespace Content.Client.UserInterface.Stylesheets .Class(ButtonOpenBoth) .Prop(ContainerButton.StylePropertyStyleBox, BaseButtonOpenBoth), + Element().Class(ContainerButton.StyleClassButton) + .Class(ButtonSquare) + .Prop(ContainerButton.StylePropertyStyleBox, BaseButtonSquare), + new StyleRule(new SelectorElement(typeof(Label), new[] { Button.StyleClassButton }, null, null), new[] { new StyleProperty(Label.StylePropertyAlignMode, Label.AlignMode.Center), @@ -808,8 +842,43 @@ namespace Content.Client.UserInterface.Stylesheets }), // Those top menu buttons. - Element() - .Prop(Button.StylePropertyStyleBox, BaseButton), + // these use slight variations on the various BaseButton styles so that the content within them appears centered, + // 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[] + { + new StyleProperty(Button.StylePropertyStyleBox, topButtonSquare), + }), + + new StyleRule( + new SelectorElement(typeof(GameHud.TopButton), new[] {ButtonOpenLeft}, null, null), + new[] + { + new StyleProperty(Button.StylePropertyStyleBox, topButtonOpenLeft), + }), + + new StyleRule( + new SelectorElement(typeof(GameHud.TopButton), new[] {ButtonOpenRight}, null, null), + new[] + { + new StyleProperty(Button.StylePropertyStyleBox, topButtonOpenRight), + }), + + new StyleRule( + new SelectorElement(typeof(GameHud.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[] + { + new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorDefaultRed), + }), new StyleRule( new SelectorElement(typeof(GameHud.TopButton), null, null, new[] {Button.StylePseudoClassNormal}), @@ -832,6 +901,13 @@ namespace Content.Client.UserInterface.Stylesheets new StyleProperty(Button.StylePropertyModulateSelf, ButtonColorHovered), }), + new StyleRule( + new SelectorElement(typeof(GameHud.TopButton), new[] {GameHud.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[] diff --git a/Content.Client/UserInterface/Stylesheets/StyleSpace.cs b/Content.Client/UserInterface/Stylesheets/StyleSpace.cs index f0fcc2fd77..b3d9fcb0d7 100644 --- a/Content.Client/UserInterface/Stylesheets/StyleSpace.cs +++ b/Content.Client/UserInterface/Stylesheets/StyleSpace.cs @@ -61,6 +61,10 @@ namespace Content.Client.UserInterface.Stylesheets .Class(ButtonOpenBoth) .Prop(ContainerButton.StylePropertyStyleBox, BaseButtonOpenBoth), + Element().Class(ContainerButton.StyleClassButton) + .Class(ButtonSquare) + .Prop(ContainerButton.StylePropertyStyleBox, BaseButtonSquare), + // Colors for the buttons. Element().Class(ContainerButton.StyleClassButton) .Pseudo(ContainerButton.StylePseudoClassNormal) diff --git a/Resources/Textures/Interface/fist.svg b/Resources/Textures/Interface/fist.svg new file mode 100644 index 0000000000..c25a18781d --- /dev/null +++ b/Resources/Textures/Interface/fist.svg @@ -0,0 +1,91 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/Resources/Textures/Interface/fist.svg.96dpi.png b/Resources/Textures/Interface/fist.svg.96dpi.png new file mode 100644 index 0000000000..c64e2957ca Binary files /dev/null and b/Resources/Textures/Interface/fist.svg.96dpi.png differ diff --git a/Resources/Textures/Interface/gavel.svg b/Resources/Textures/Interface/gavel.svg new file mode 100644 index 0000000000..0ec1aefde1 --- /dev/null +++ b/Resources/Textures/Interface/gavel.svg @@ -0,0 +1,70 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/Resources/Textures/Interface/gavel.svg.96dpi.png b/Resources/Textures/Interface/gavel.svg.96dpi.png new file mode 100644 index 0000000000..821c07195f Binary files /dev/null and b/Resources/Textures/Interface/gavel.svg.96dpi.png differ diff --git a/Resources/Textures/Interface/hamburger.svg b/Resources/Textures/Interface/hamburger.svg index 4ea08de45e..a20d7bb543 100644 --- a/Resources/Textures/Interface/hamburger.svg +++ b/Resources/Textures/Interface/hamburger.svg @@ -5,11 +5,39 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg4593" version="1.1" viewBox="0 0 7.9563375 7.1438789" height="7.1438789mm" - width="7.9563375mm"> + width="7.9563375mm" + sodipodi:docname="hamburger.svg" + inkscape:export-filename="C:\ss14\space-station-14\Resources\Textures\Interface\hamburger.svg.96dpi.png" + inkscape:export-xdpi="115.20007" + inkscape:export-ydpi="115.20007" + inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"> + - + id="svg8" + sodipodi:docname="tutorial.svg" + inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)" + inkscape:export-filename="C:\ss14\space-station-14\Resources\Textures\Interface\tutorial.svg.96dpi.png" + inkscape:export-xdpi="121.08268" + inkscape:export-ydpi="121.08268"> + id="metadata14"> @@ -24,18 +30,37 @@ - - - - + + + diff --git a/Resources/Textures/Interface/tutorial.svg.96dpi.png b/Resources/Textures/Interface/tutorial.svg.96dpi.png index 2e83e41f93..f8934fe0c9 100644 Binary files a/Resources/Textures/Interface/tutorial.svg.96dpi.png and b/Resources/Textures/Interface/tutorial.svg.96dpi.png differ diff --git a/Resources/keybinds.yml b/Resources/keybinds.yml index 3aaffbde79..3d6f5db215 100644 --- a/Resources/keybinds.yml +++ b/Resources/keybinds.yml @@ -315,7 +315,7 @@ binds: key: Z - function: OpenAbilitiesMenu type: State - key: Equal + key: K - function: Hotbar0 type: State key: Num0