diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs index 8efd977b20..ba8b72788e 100644 --- a/Content.Client/Input/ContentContexts.cs +++ b/Content.Client/Input/ContentContexts.cs @@ -80,11 +80,6 @@ namespace Content.Client.Input common.AddFunction(boundKey); } - foreach (var boundKey in ContentKeyFunctions.GetLoadoutBoundKeys()) - { - common.AddFunction(boundKey); - } - var aghost = contexts.New("aghost", "common"); aghost.AddFunction(EngineKeyFunctions.MoveUp); aghost.AddFunction(EngineKeyFunctions.MoveDown); diff --git a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs index c68e7f3af9..87b1f10352 100644 --- a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs @@ -224,10 +224,6 @@ namespace Content.Client.Options.UI.Tabs { AddButton(boundKey); } - foreach (var boundKey in ContentKeyFunctions.GetLoadoutBoundKeys()) - { - AddButton(boundKey); - } AddHeader("ui-options-header-shuttle"); AddButton(ContentKeyFunctions.ShuttleStrafeUp); diff --git a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml index 8b502515c9..5c09574005 100644 --- a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml +++ b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml @@ -22,10 +22,10 @@ + - diff --git a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs index c35d831035..a8a53e83c7 100644 --- a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs +++ b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs @@ -17,7 +17,6 @@ public sealed partial class DefaultGameScreen : InGameScreen SetAnchorPreset(MainViewport, LayoutPreset.Wide); SetAnchorPreset(ViewportContainer, LayoutPreset.Wide); SetAnchorAndMarginPreset(TopLeft, LayoutPreset.TopLeft, margin: 10); - SetAnchorAndMarginPreset(Actions, LayoutPreset.BottomLeft, margin: 10); SetAnchorAndMarginPreset(Ghost, LayoutPreset.BottomWide, margin: 80); SetAnchorAndMarginPreset(Hotbar, LayoutPreset.BottomWide, margin: 5); SetAnchorAndMarginPreset(Chat, LayoutPreset.TopRight, margin: 10); @@ -25,6 +24,7 @@ public sealed partial class DefaultGameScreen : InGameScreen Chat.OnResized += ChatOnResized; Chat.OnChatResizeFinish += ChatOnResizeFinish; + Actions.ActionsContainer.Columns = 1; } private void ChatOnResizeFinish(Vector2 _) diff --git a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs index 41c4a85e7e..e0c66b7a8b 100644 --- a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs +++ b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs @@ -19,7 +19,7 @@ public sealed partial class SeparatedChatGameScreen : InGameScreen SetAnchorPreset(ViewportContainer, LayoutPreset.Wide); SetAnchorPreset(MainViewport, LayoutPreset.Wide); SetAnchorAndMarginPreset(VoteMenu, LayoutPreset.TopLeft, margin: 10); - SetAnchorAndMarginPreset(Actions, LayoutPreset.BottomLeft, margin: 10); + SetAnchorAndMarginPreset(Actions, LayoutPreset.TopLeft, margin: 10); SetAnchorAndMarginPreset(Ghost, LayoutPreset.BottomWide, margin: 80); SetAnchorAndMarginPreset(Hotbar, LayoutPreset.BottomWide, margin: 5); SetAnchorAndMarginPreset(Alerts, LayoutPreset.CenterRight, margin: 10); diff --git a/Content.Client/UserInterface/Systems/Actions/ActionUIController.cs b/Content.Client/UserInterface/Systems/Actions/ActionUIController.cs index 340aa5447d..5a992786a2 100644 --- a/Content.Client/UserInterface/Systems/Actions/ActionUIController.cs +++ b/Content.Client/UserInterface/Systems/Actions/ActionUIController.cs @@ -1,6 +1,5 @@ using System.Linq; using System.Numerics; -using System.Runtime.InteropServices; using Content.Client.Actions; using Content.Client.Construction; using Content.Client.Gameplay; @@ -49,17 +48,14 @@ public sealed class ActionUIController : UIController, IOnStateChanged _pages = new(); - private int _currentPageIndex = DefaultPageIndex; + private readonly List _actions = new(); private readonly DragDropHelper _menuDragHelper; private readonly TextureRect _dragShadow; private ActionsWindow? _window; private ActionsBar? ActionsBar => UIManager.GetActiveUIWidgetOrNull(); private MenuButton? ActionButton => UIManager.GetActiveUIWidgetOrNull()?.ActionButton; - private ActionPage CurrentPage => _pages[_currentPageIndex]; public bool IsDragging => _menuDragHelper.IsDragging; @@ -79,14 +75,6 @@ public sealed class ActionUIController : UIController, IOnStateChanged ChangePage(boundId))); - } - builder .Bind(ContentKeyFunctions.OpenActionsMenu, InputCmdHandler.FromDelegate(_ => ToggleWindow())) @@ -178,7 +157,7 @@ public sealed class ActionUIController : UIController, IOnStateChanged lastPage) - { - index = 0; - } - - _currentPageIndex = index; - var page = _pages[_currentPageIndex]; - _container?.SetActionData(_actionsSystem, page); - - ActionsBar!.PageButtons.Label.Text = $"{_currentPageIndex + 1}"; - } - - private void OnLeftArrowPressed(ButtonEventArgs args) - { - ChangePage(_currentPageIndex - 1); - } - - private void OnRightArrowPressed(ButtonEventArgs args) - { - ChangePage(_currentPageIndex + 1); - } - - private void AppendAction(EntityUid action) - { - if (_container == null) - return; - - foreach (var button in _container.GetButtons()) - { - if (button.ActionId != null) - continue; - - SetAction(button, action); - return; - } - - foreach (var page in _pages) - { - for (var i = 0; i < page.Size; i++) - { - var pageAction = page[i]; - if (pageAction != null) - continue; - - page[i] = action; - return; - } - } + _actionsSystem?.TriggerAction(actionId.Value, baseAction); } private void OnActionAdded(EntityUid actionId) @@ -416,18 +335,10 @@ public sealed class ActionUIController : UIController, IOnStateChanged x == actionId); } private void OnActionsUpdated() { QueueWindowUpdate(); - if (_container == null) - return; - foreach (var button in _container.GetButtons()) - { - button.UpdateIcons(); - } + if (_actionsSystem != null) + _container?.SetActionData(_actionsSystem, _actions.ToArray()); } private void ActionButtonPressed(ButtonEventArgs args) @@ -512,8 +401,8 @@ public sealed class ActionUIController : UIController, IOnStateChanged action.Enabled, - Filters.Item => action.Container != null && action.Container != _playerManager.LocalPlayer?.ControlledEntity, - Filters.Innate => action.Container == null || action.Container == _playerManager.LocalPlayer?.ControlledEntity, + Filters.Item => action.Container != null && action.Container != _playerManager.LocalEntity, + Filters.Innate => action.Container == null || action.Container == _playerManager.LocalEntity, Filters.Instant => action is InstantActionComponent, Filters.Targeted => action is BaseTargetActionComponent, _ => throw new ArgumentOutOfRangeException(nameof(filter), filter, null) @@ -580,7 +469,7 @@ public sealed class ActionUIController : UIController, IOnStateChanged= _actions.Count) + { + _actions.Add(actionId); + } + else + { + _actions[position] = actionId; + } } + + if (updateSlots) + _container?.SetActionData(_actionsSystem, _actions.ToArray()); } private void DragAction() { + EntityUid? swapAction = null; if (UIManager.CurrentlyHovered is ActionButton button) { if (!_menuDragHelper.IsDragging || _menuDragHelper.Dragged?.ActionId is not { } type) @@ -651,14 +548,18 @@ public sealed class ActionUIController : UIController, IOnStateChanged action.Comp.AutoPopulate).ToList(); actions.Sort(ActionComparer); - var offset = 0; - var totalPages = _pages.Count; - var pagesLeft = totalPages; - var currentPage = DefaultPageIndex; - while (pagesLeft > 0) + _actions.Clear(); + foreach (var (action, _) in actions) { - var page = _pages[currentPage]; - var pageSize = page.Size; - - for (var slot = 0; slot < pageSize; slot++) - { - var actionIndex = slot + offset; - if (actionIndex < actions.Count) - { - page[slot] = actions[slot + offset].Id; - } - else - { - page[slot] = null; - } - } - - offset += pageSize; - currentPage++; - if (currentPage == totalPages) - { - currentPage = 0; - } - - pagesLeft--; + if (!_actions.Contains(action)) + _actions.Add(action); } } @@ -1078,34 +943,4 @@ public sealed class ActionUIController : UIController, IOnStateChanged _data[index]; - set => _data[index] = value; - } - - public static implicit operator EntityUid?[](ActionPage p) - { - return p._data.ToArray(); - } - - public void Clear() - { - Array.Fill(_data, null); - } - - public int Size => _data.Length; - } } diff --git a/Content.Client/UserInterface/Systems/Actions/Controls/ActionButton.cs b/Content.Client/UserInterface/Systems/Actions/Controls/ActionButton.cs index 31c5a28e52..6b2033e78c 100644 --- a/Content.Client/UserInterface/Systems/Actions/Controls/ActionButton.cs +++ b/Content.Client/UserInterface/Systems/Actions/Controls/ActionButton.cs @@ -49,6 +49,8 @@ public sealed class ActionButton : Control, IEntityControl private readonly SpriteView _smallItemSpriteView; private readonly SpriteView _bigItemSpriteView; + private Texture? _buttonBackgroundTexture; + public EntityUid? ActionId { get; private set; } private BaseActionComponent? _action; public bool Locked { get; set; } @@ -138,9 +140,9 @@ public sealed class ActionButton : Control, IEntityControl }); Cooldown = new CooldownGraphic {Visible = false}; + AddChild(Button); AddChild(_bigActionIcon); AddChild(_bigItemSpriteView); - AddChild(Button); AddChild(HighlightRect); AddChild(Label); AddChild(Cooldown); @@ -167,7 +169,7 @@ public sealed class ActionButton : Control, IEntityControl protected override void OnThemeUpdated() { base.OnThemeUpdated(); - Button.Texture = Theme.ResolveTexture("SlotBackground"); + _buttonBackgroundTexture = Theme.ResolveTexture("SlotBackground"); Label.FontColorOverride = Theme.ResolveColorOrSpecified("whiteText"); } @@ -263,6 +265,7 @@ public sealed class ActionButton : Control, IEntityControl public void UpdateIcons() { UpdateItemIcon(); + UpdateBackground(); if (_action == null) { @@ -278,6 +281,18 @@ public sealed class ActionButton : Control, IEntityControl SetActionIcon(_action.Icon != null ? _spriteSys.Frame0(_action.Icon) : null); } + public void UpdateBackground() + { + if (_action == null) + { + Button.Texture = null; + } + else + { + Button.Texture = _buttonBackgroundTexture; + } + } + public bool TryReplaceWith(EntityUid actionId, ActionsSystem system) { if (Locked) @@ -363,7 +378,8 @@ public sealed class ActionButton : Control, IEntityControl public void DrawModeChanged() { - HighlightRect.Visible = _beingHovered; + _controller ??= UserInterfaceManager.GetUIController(); + HighlightRect.Visible = _beingHovered && (_action != null || _controller.IsDragging); // always show the normal empty button style if no action in this slot if (_action == null) @@ -373,8 +389,7 @@ public sealed class ActionButton : Control, IEntityControl } // show a hover only if the action is usable or another action is being dragged on top of this - _controller ??= UserInterfaceManager.GetUIController(); - if (_beingHovered && (_controller.IsDragging || _action.Enabled)) + if (_beingHovered && (_controller.IsDragging || _action!.Enabled)) { SetOnlyStylePseudoClass(ContainerButton.StylePseudoClassHover); } diff --git a/Content.Client/UserInterface/Systems/Actions/Controls/ActionButtonContainer.cs b/Content.Client/UserInterface/Systems/Actions/Controls/ActionButtonContainer.cs index 9986c61ad6..5e26c192d7 100644 --- a/Content.Client/UserInterface/Systems/Actions/Controls/ActionButtonContainer.cs +++ b/Content.Client/UserInterface/Systems/Actions/Controls/ActionButtonContainer.cs @@ -1,12 +1,19 @@ +using System.Linq; using Content.Client.Actions; +using Content.Shared.Input; +using Robust.Client.Input; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; +using Robust.Shared.Utility; namespace Content.Client.UserInterface.Systems.Actions.Controls; [Virtual] public class ActionButtonContainer : GridContainer { + [Dependency] private readonly IEntityManager _entity = default!; + [Dependency] private readonly IInputManager _input = default!; + public event Action? ActionPressed; public event Action? ActionUnpressed; public event Action? ActionFocusExited; @@ -14,7 +21,6 @@ public class ActionButtonContainer : GridContainer public ActionButtonContainer() { IoCManager.InjectDependencies(this); - UserInterfaceManager.GetUIController().RegisterActionContainer(this); } public ActionButton this[int index] @@ -22,17 +28,42 @@ public class ActionButtonContainer : GridContainer get => (ActionButton) GetChild(index); } + private void BuildActionButtons(int count) + { + var keys = ContentKeyFunctions.GetHotbarBoundKeys(); + + Children.Clear(); + for (var index = 0; index < count; index++) + { + Children.Add(MakeButton(index)); + } + + ActionButton MakeButton(int index) + { + var button = new ActionButton(_entity); + + if (keys.TryGetValue(index, out var boundKey)) + { + button.KeyBind = boundKey; + + var binding = _input.GetKeyBinding(boundKey); + button.Label.Text = binding.GetKeyString(); + } + + return button; + } + } + public void SetActionData(ActionsSystem system, params EntityUid?[] actionTypes) { - ClearActionData(); + var uniqueCount = Math.Min(system.GetClientActions().Count(), actionTypes.Length + 1); + BuildActionButtons(uniqueCount); - for (var i = 0; i < actionTypes.Length; i++) + for (var i = 0; i < uniqueCount; i++) { - var action = actionTypes[i]; - if (action == null) - continue; - - ((ActionButton) GetChild(i)).UpdateData(action.Value, system); + if (!actionTypes.TryGetValue(i, out var action)) + action = null; + ((ActionButton) GetChild(i)).UpdateData(action, system); } } diff --git a/Content.Client/UserInterface/Systems/Actions/Widgets/ActionsBar.xaml b/Content.Client/UserInterface/Systems/Actions/Widgets/ActionsBar.xaml index 7e4d60a057..1d317f6155 100644 --- a/Content.Client/UserInterface/Systems/Actions/Widgets/ActionsBar.xaml +++ b/Content.Client/UserInterface/Systems/Actions/Widgets/ActionsBar.xaml @@ -13,7 +13,7 @@ VerticalAlignment="Center" MaxSize="64 9999" Name="ActionsContainer" - Access="Public"/> - + Access="Public" + Rows="1"/> diff --git a/Content.Client/UserInterface/Systems/Actions/Widgets/ActionsBar.xaml.cs b/Content.Client/UserInterface/Systems/Actions/Widgets/ActionsBar.xaml.cs index ff3c32cc0e..8e95992ff6 100644 --- a/Content.Client/UserInterface/Systems/Actions/Widgets/ActionsBar.xaml.cs +++ b/Content.Client/UserInterface/Systems/Actions/Widgets/ActionsBar.xaml.cs @@ -1,6 +1,4 @@ -using Content.Client.UserInterface.Systems.Actions.Controls; -using Content.Shared.Input; -using Robust.Client.AutoGenerated; +using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; @@ -9,28 +7,9 @@ namespace Content.Client.UserInterface.Systems.Actions.Widgets; [GenerateTypedNameReferences] public sealed partial class ActionsBar : UIWidget { - [Dependency] private readonly IEntityManager _entity = default!; - public ActionsBar() { RobustXamlLoader.Load(this); - IoCManager.InjectDependencies(this); - - var keys = ContentKeyFunctions.GetHotbarBoundKeys(); - for (var index = 1; index < keys.Length; index++) - { - ActionsContainer.Children.Add(MakeButton(index)); - } - ActionsContainer.Children.Add(MakeButton(0)); - - ActionButton MakeButton(int index) - { - var boundKey = keys[index]; - var button = new ActionButton(_entity); - button.KeyBind = boundKey; - button.Label.Text = index.ToString(); - return button; - } } } diff --git a/Content.Shared/Input/ContentKeyFunctions.cs b/Content.Shared/Input/ContentKeyFunctions.cs index 840320b0d3..f4307cd058 100644 --- a/Content.Shared/Input/ContentKeyFunctions.cs +++ b/Content.Shared/Input/ContentKeyFunctions.cs @@ -84,23 +84,6 @@ namespace Content.Shared.Input Hotbar1, Hotbar2, Hotbar3, Hotbar4, Hotbar5, Hotbar6, Hotbar7, Hotbar8, Hotbar9, Hotbar0 }; - public static readonly BoundKeyFunction Loadout0 = "Loadout0"; - public static readonly BoundKeyFunction Loadout1 = "Loadout1"; - public static readonly BoundKeyFunction Loadout2 = "Loadout2"; - public static readonly BoundKeyFunction Loadout3 = "Loadout3"; - public static readonly BoundKeyFunction Loadout4 = "Loadout4"; - public static readonly BoundKeyFunction Loadout5 = "Loadout5"; - public static readonly BoundKeyFunction Loadout6 = "Loadout6"; - public static readonly BoundKeyFunction Loadout7 = "Loadout7"; - public static readonly BoundKeyFunction Loadout8 = "Loadout8"; - public static readonly BoundKeyFunction Loadout9 = "Loadout9"; - - public static BoundKeyFunction[] GetLoadoutBoundKeys() => - new[] - { - Loadout1, Loadout2, Loadout3, Loadout4, Loadout5, Loadout6, Loadout7, Loadout8, Loadout9, Loadout0 - }; - public static readonly BoundKeyFunction Vote0 = "Vote0"; public static readonly BoundKeyFunction Vote1 = "Vote1"; public static readonly BoundKeyFunction Vote2 = "Vote2"; diff --git a/Resources/keybinds.yml b/Resources/keybinds.yml index 1b82435861..b3ba05def2 100644 --- a/Resources/keybinds.yml +++ b/Resources/keybinds.yml @@ -510,43 +510,3 @@ binds: - function: Hotbar9 type: State key: Num9 -- function: Loadout0 - type: State - key: Num0 - mod1: Shift -- function: Loadout1 - type: State - key: Num1 - mod1: Shift -- function: Loadout2 - type: State - key: Num2 - mod1: Shift -- function: Loadout3 - type: State - key: Num3 - mod1: Shift -- function: Loadout4 - type: State - key: Num4 - mod1: Shift -- function: Loadout5 - type: State - key: Num5 - mod1: Shift -- function: Loadout6 - type: State - key: Num6 - mod1: Shift -- function: Loadout7 - type: State - key: Num7 - mod1: Shift -- function: Loadout8 - type: State - key: Num8 - mod1: Shift -- function: Loadout9 - type: State - key: Num9 - mod1: Shift