using System; 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.Interfaces.Input; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Input; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; namespace Content.Client.UserInterface { /// /// Responsible for laying out the default game HUD. /// public interface IGameHud { 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; } Action InventoryButtonToggled { get; set; } // Crafting top button. bool CraftingButtonDown { get; set; } bool CraftingButtonVisible { get; set; } Action CraftingButtonToggled { get; set; } // Sandbox top button. bool SandboxButtonDown { get; set; } bool SandboxButtonVisible { get; set; } Action SandboxButtonToggled { get; set; } Control HandsContainer { get; } Control InventoryQuickButtonContainer { get; } bool CombatPanelVisible { get; set; } bool CombatModeActive { get; set; } TargetingZone TargetingZone { get; set; } Action OnCombatModeChanged { get; set; } Action OnTargetingZoneChanged { get; set; } // Init logic. void Initialize(); } internal sealed class GameHud : IGameHud { private HBoxContainer _topButtonsContainer; private TopButton _buttonEscapeMenu; private TopButton _buttonTutorial; private TopButton _buttonCharacterMenu; private TopButton _buttonInventoryMenu; private TopButton _buttonCraftingMenu; private TopButton _buttonSandboxMenu; private TutorialWindow _tutorialWindow; private TargetingDoll _targetingDoll; private Button _combatModeButton; private VBoxContainer _combatPanelContainer; #pragma warning disable 649 [Dependency] private readonly IResourceCache _resourceCache; [Dependency] private readonly ILocalizationManager _loc; [Dependency] private readonly IInputManager _inputManager; #pragma warning restore 649 public Control HandsContainer { get; private set; } public Control InventoryQuickButtonContainer { get; private set; } public bool CombatPanelVisible { get => _combatPanelContainer.Visible; set => _combatPanelContainer.Visible = value; } public bool CombatModeActive { get => _combatModeButton.Pressed; set => _combatModeButton.Pressed = value; } public TargetingZone TargetingZone { get => _targetingDoll.ActiveZone; set => _targetingDoll.ActiveZone = value; } public Action OnCombatModeChanged { get; set; } public Action OnTargetingZoneChanged { get; set; } public void Initialize() { RootControl = new Control {MouseFilter = Control.MouseFilterMode.Ignore}; RootControl.SetAnchorPreset(Control.LayoutPreset.Wide); var escapeTexture = _resourceCache.GetTexture("/Textures/UserInterface/hamburger.svg.96dpi.png"); var characterTexture = _resourceCache.GetTexture("/Textures/UserInterface/character.svg.96dpi.png"); var inventoryTexture = _resourceCache.GetTexture("/Textures/UserInterface/inventory.svg.96dpi.png"); var craftingTexture = _resourceCache.GetTexture("/Textures/UserInterface/hammer.svg.96dpi.png"); var tutorialTexture = _resourceCache.GetTexture("/Textures/UserInterface/students-cap.svg.96dpi.png"); var sandboxTexture = _resourceCache.GetTexture("/Textures/UserInterface/sandbox.svg.96dpi.png"); _topButtonsContainer = new HBoxContainer { SeparationOverride = 4 }; RootControl.AddChild(_topButtonsContainer); _topButtonsContainer.SetAnchorAndMarginPreset(Control.LayoutPreset.TopLeft, margin: 10); // TODO: Pull key names here from the actual key binding config. // Escape _buttonEscapeMenu = new TopButton(escapeTexture, "Esc") { ToolTip = _loc.GetString("Open escape menu.") }; _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") { ToolTip = _loc.GetString("Open character menu."), Visible = false }; _topButtonsContainer.AddChild(_buttonCharacterMenu); _buttonCharacterMenu.OnToggled += args => CharacterButtonToggled?.Invoke(args.Pressed); // Inventory _buttonInventoryMenu = new TopButton(inventoryTexture, "I") { ToolTip = _loc.GetString("Open inventory menu."), Visible = false }; _topButtonsContainer.AddChild(_buttonInventoryMenu); _buttonInventoryMenu.OnToggled += args => InventoryButtonToggled?.Invoke(args.Pressed); // Crafting _buttonCraftingMenu = new TopButton(craftingTexture, "G") { ToolTip = _loc.GetString("Open crafting menu."), Visible = false }; _topButtonsContainer.AddChild(_buttonCraftingMenu); _buttonCraftingMenu.OnToggled += args => CraftingButtonToggled?.Invoke(args.Pressed); // Sandbox _buttonSandboxMenu = new TopButton(sandboxTexture, "B") { ToolTip = _loc.GetString("Open sandbox menu."), Visible = false }; _topButtonsContainer.AddChild(_buttonSandboxMenu); _buttonSandboxMenu.OnToggled += args => SandboxButtonToggled?.Invoke(args.Pressed); _tutorialWindow = new TutorialWindow(); _tutorialWindow.OnClose += () => _buttonTutorial.Pressed = false; _inputManager.SetInputCommand(ContentKeyFunctions.OpenTutorial, InputCmdHandler.FromDelegate(s => ButtonTutorialOnOnToggled())); var inventoryContainer = new HBoxContainer { GrowHorizontal = Control.GrowDirection.Begin, GrowVertical = Control.GrowDirection.Begin, SeparationOverride = 10 }; RootControl.AddChild(inventoryContainer); inventoryContainer.SetAnchorAndMarginPreset(Control.LayoutPreset.BottomRight); InventoryQuickButtonContainer = new MarginContainer { GrowHorizontal = Control.GrowDirection.Begin, GrowVertical = Control.GrowDirection.Begin, SizeFlagsVertical = Control.SizeFlags.ShrinkEnd }; HandsContainer = new MarginContainer { GrowHorizontal = Control.GrowDirection.Both, GrowVertical = Control.GrowDirection.Begin, SizeFlagsVertical = Control.SizeFlags.ShrinkEnd }; _combatPanelContainer = new VBoxContainer { Children = { (_combatModeButton = new Button { Text = _loc.GetString("Combat Mode"), ToggleMode = true }), (_targetingDoll = new TargetingDoll(_resourceCache)) } }; _combatModeButton.OnToggled += args => OnCombatModeChanged?.Invoke(args.Pressed); _targetingDoll.OnZoneChanged += args => OnTargetingZoneChanged?.Invoke(args); inventoryContainer.Children.Add(HandsContainer); inventoryContainer.Children.Add(InventoryQuickButtonContainer); inventoryContainer.Children.Add(_combatPanelContainer); } private void ButtonTutorialOnOnToggled() { if (_tutorialWindow.IsOpen) { if (!_tutorialWindow.IsAtFront()) { _tutorialWindow.MoveToFront(); _buttonTutorial.Pressed = true; } else { _tutorialWindow.Close(); _buttonTutorial.Pressed = false; } } else { _tutorialWindow.OpenCentered(); _buttonTutorial.Pressed = true; } } public Control RootControl { get; private set; } 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 => _buttonInventoryMenu.Pressed = value; } public bool InventoryButtonVisible { get => _buttonInventoryMenu.Visible; set => _buttonInventoryMenu.Visible = value; } public Action InventoryButtonToggled { get; set; } 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 SandboxButtonDown { get => _buttonSandboxMenu.Pressed; set => _buttonSandboxMenu.Pressed = value; } public bool SandboxButtonVisible { get => _buttonSandboxMenu.Visible; set => _buttonSandboxMenu.Visible = value; } public Action SandboxButtonToggled { get; set; } public sealed class TopButton : BaseButton { public const string StyleClassLabelTopButton = "topButtonLabel"; private static readonly Color ColorNormal = Color.FromHex("#7b7e9e"); private static readonly Color ColorHovered = Color.FromHex("#9699bb"); private static readonly Color ColorPressed = Color.FromHex("#789B8C"); private readonly VBoxContainer _container; private readonly TextureRect _textureRect; private readonly Label _label; public TopButton(Texture texture, string keyName) { ToggleMode = true; _container = new VBoxContainer {MouseFilter = MouseFilterMode.Ignore}; AddChild(_container); _container.AddChild(_textureRect = new TextureRect { Texture = texture, SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.Expand | SizeFlags.ShrinkCenter, MouseFilter = MouseFilterMode.Ignore, ModulateSelfOverride = ColorNormal, CustomMinimumSize = (0, 32), Stretch = TextureRect.StretchMode.KeepCentered }); _container.AddChild(_label = new Label { Text = keyName, SizeFlagsHorizontal = SizeFlags.ShrinkCenter, MouseFilter = MouseFilterMode.Ignore, ModulateSelfOverride = ColorNormal }); _label.AddStyleClass(StyleClassLabelTopButton); _container.SetAnchorAndMarginPreset(LayoutPreset.Wide); DrawModeChanged(); } protected override Vector2 CalculateMinimumSize() { var styleSize = ActualStyleBox?.MinimumSize ?? Vector2.Zero; return (0, 4) + styleSize + _container?.CombinedMinimumSize ?? Vector2.Zero; } protected override void Draw(DrawingHandleScreen handle) { ActualStyleBox?.Draw(handle, PixelSizeBox); } private StyleBox ActualStyleBox { get { TryGetStyleProperty(Button.StylePropertyStyleBox, out StyleBox ret); return ret; } } protected override void DrawModeChanged() { switch (DrawMode) { case DrawModeEnum.Normal: SetOnlyStylePseudoClass(Button.StylePseudoClassNormal); _textureRect.ModulateSelfOverride = ColorNormal; _label.ModulateSelfOverride = ColorNormal; 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; break; case DrawModeEnum.Disabled: break; } } protected override void StylePropertiesChanged() { base.StylePropertiesChanged(); if (_container == null) { return; } var box = ActualStyleBox ?? new StyleBoxEmpty(); _container.MarginLeft = box.GetContentMargin(StyleBox.Margin.Left); _container.MarginRight = -box.GetContentMargin(StyleBox.Margin.Right); _container.MarginTop = box.GetContentMargin(StyleBox.Margin.Top) + 4; _container.MarginBottom = -box.GetContentMargin(StyleBox.Margin.Bottom); } } } }