Skip to content

Commit

Permalink
Merge branch 'master' into Space-Law
Browse files Browse the repository at this point in the history
  • Loading branch information
BlueHNT authored Dec 31, 2024
2 parents a909c26 + 4d464ee commit 388166b
Show file tree
Hide file tree
Showing 76 changed files with 4,488 additions and 3,062 deletions.
4 changes: 2 additions & 2 deletions Content.Client/Input/ContentContexts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ public static void SetupContexts(IInputContextContainer contexts)
common.AddFunction(ContentKeyFunctions.OpenActionsMenu);

foreach (var boundKey in ContentKeyFunctions.GetHotbarBoundKeys())
{
common.AddFunction(boundKey);
}
foreach (var boundKey in ContentKeyFunctions.GetLoadoutBoundKeys())
common.AddFunction(boundKey);

var aghost = contexts.New("aghost", "common");
aghost.AddFunction(EngineKeyFunctions.MoveUp);
Expand Down
4 changes: 2 additions & 2 deletions Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,9 @@ void AddCheckBox(string checkBoxName, bool currentState, Action<BaseButton.Butto

AddHeader("ui-options-header-hotbar");
foreach (var boundKey in ContentKeyFunctions.GetHotbarBoundKeys())
{
AddButton(boundKey);
}
foreach (var boundKey in ContentKeyFunctions.GetLoadoutBoundKeys())
AddButton(boundKey);

AddHeader("ui-options-header-shuttle");
AddButton(ContentKeyFunctions.ShuttleStrafeUp);
Expand Down
197 changes: 150 additions & 47 deletions Content.Client/UserInterface/Systems/Actions/ActionUIController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using Content.Client.Actions;
using Content.Client.Construction;
using Content.Client.Gameplay;
Expand Down Expand Up @@ -50,14 +51,17 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
[UISystemDependency] private readonly TargetOutlineSystem? _targetOutline = default;
[UISystemDependency] private readonly SpriteSystem _spriteSystem = default!;

private const int DefaultPageIndex = 0;
private ActionButtonContainer? _container;
private readonly List<EntityUid?> _actions = new();
private readonly List<ActionPage> _pages = new();
private int _currentPageIndex = DefaultPageIndex;
private readonly DragDropHelper<ActionButton> _menuDragHelper;
private readonly TextureRect _dragShadow;
private ActionsWindow? _window;

private ActionsBar? ActionsBar => UIManager.GetActiveUIWidgetOrNull<ActionsBar>();
private MenuButton? ActionButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.ActionButton;
private ActionPage CurrentPage => _pages[_currentPageIndex];

public bool IsDragging => _menuDragHelper.IsDragging;

Expand All @@ -75,8 +79,13 @@ public ActionUIController()
Stretch = StretchMode.Scale,
Visible = false,
SetSize = new Vector2(64, 64),
MouseFilter = MouseFilterMode.Ignore
MouseFilter = MouseFilterMode.Ignore,
};

var pageCount = ContentKeyFunctions.GetLoadoutBoundKeys().Length;
var buttonCount = ContentKeyFunctions.GetHotbarBoundKeys().Length;
for (var i = 0; i < pageCount; i++)
_pages.Add(new ActionPage(buttonCount));
}

public override void Initialize()
Expand Down Expand Up @@ -129,6 +138,15 @@ public void OnStateEntered(GameplayState state)
}, false, true));
}

var loadoutKeys = ContentKeyFunctions.GetLoadoutBoundKeys();
for (var i = 0; i < loadoutKeys.Length; i++)
{
var boundId = i; // This is needed, because the lambda captures it.
var boundKey = loadoutKeys[i];
builder = builder.Bind(boundKey,
InputCmdHandler.FromDelegate(_ => ChangePage(boundId)));
}

builder
.Bind(ContentKeyFunctions.OpenActionsMenu,
InputCmdHandler.FromDelegate(_ => ToggleWindow()))
Expand Down Expand Up @@ -315,34 +333,80 @@ public void OnStateExited(GameplayState state)
private void TriggerAction(int index)
{
if (_actionsSystem == null ||
!_actions.TryGetValue(index, out var actionId) ||
CurrentPage[index] is not { } actionId ||
!_actionsSystem.TryGetActionData(actionId, out var baseAction))
{
return;
}

if (baseAction is BaseTargetActionComponent action)
ToggleTargeting(actionId.Value, action);
ToggleTargeting(actionId, action);
else
_actionsSystem?.TriggerAction(actionId.Value, baseAction);
_actionsSystem?.TriggerAction(actionId, baseAction);
}

private void ChangePage(int index)
{
if (_actionsSystem == null)
return;

var lastPage = _pages.Count - 1;
if (index < 0)
index = lastPage;
else if (index > 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;
}
}

private void OnActionAdded(EntityUid actionId)
{
if (_actionsSystem == null ||
!_actionsSystem.TryGetActionData(actionId, out var action))
{
return;
}

// if the action is toggled when we add it, start targeting
if (action is BaseTargetActionComponent targetAction && action.Toggled)
StartTargeting(actionId, targetAction);

if (_actions.Contains(actionId))
return;
foreach (var page in _pages)
for (var i = 0; i < page.Size; i++)
if (page[i] == actionId)
return;

_actions.Add(actionId);
AppendAction(actionId);
}

private void OnActionRemoved(EntityUid actionId)
Expand All @@ -353,19 +417,24 @@ private void OnActionRemoved(EntityUid actionId)
if (actionId == SelectingTargetFor)
StopTargeting();

_actions.RemoveAll(x => x == actionId);
foreach (var page in _pages)
for (var i = 0; i < page.Size; i++)
if (page[i] == actionId)
page[i] = null;
}

private void OnActionsUpdated()
{
QueueWindowUpdate();
if (_container == null)
return;

// TODO ACTIONS allow buttons to persist across state applications
// Then we don't have to interrupt drags any time the buttons get rebuilt.
_menuDragHelper.EndDrag();

if (_actionsSystem != null)
_container?.SetActionData(_actionsSystem, _actions.ToArray());
_container?.SetActionData(_actionsSystem, _pages[_currentPageIndex]);
}

private void ActionButtonPressed(ButtonEventArgs args)
Expand Down Expand Up @@ -512,7 +581,7 @@ private void SearchAndDisplay()
PopulateActions(actions);
}

private void SetAction(ActionButton button, EntityUid? actionId, bool updateSlots = true)
private void SetAction(ActionButton button, EntityUid? actionId)
{
if (_actionsSystem == null)
return;
Expand All @@ -523,27 +592,28 @@ private void SetAction(ActionButton button, EntityUid? actionId, bool updateSlot
{
button.ClearData();
if (_container?.TryGetButtonIndex(button, out position) ?? false)
{
if (_actions.Count > position && position >= 0)
_actions.RemoveAt(position);
}
CurrentPage[position] = null;
}
else if (button.TryReplaceWith(actionId.Value, _actionsSystem) &&
_container != null &&
_container.TryGetButtonIndex(button, out position))
{
if (position >= _actions.Count)
{
_actions.Add(actionId);
}
if (position >= 0 && position < CurrentPage.Size)
CurrentPage[position] = actionId;
else
{
_actions[position] = actionId;
if (_pages.Count <= _currentPageIndex)
return;
// Add the button to the next page if there's no space on the current one
var nextPage = _pages[_currentPageIndex + 1];
int i;
for (i = 0; i < nextPage.Size; i++)
if (nextPage[i] == null)
{
nextPage[i] = actionId;
break;
}
ChangePage(_currentPageIndex + 1); //TODO: Make this a client config?
}
}

if (updateSlots)
_container?.SetActionData(_actionsSystem, _actions.ToArray());
}

private void DragAction()
Expand All @@ -559,14 +629,14 @@ private void DragAction()
if (currentlyHovered is ActionButton button)
{
swapAction = button.ActionId;
SetAction(button, action, false);
SetAction(button, action);
}

if (dragged.Parent is ActionButtonContainer)
SetAction(dragged, swapAction, false);
SetAction(dragged, swapAction);

if (_actionsSystem != null)
_container?.SetActionData(_actionsSystem, _actions.ToArray());
_container?.SetActionData(_actionsSystem, _pages[_currentPageIndex]);

_menuDragHelper.EndDrag();
}
Expand Down Expand Up @@ -717,9 +787,10 @@ private void UnloadGui()
_actionsSystem?.UnlinkAllActions();

if (ActionsBar == null)
{
return;
}

ActionsBar.PageButtons.LeftArrow.OnPressed -= OnLeftArrowPressed;
ActionsBar.PageButtons.RightArrow.OnPressed -= OnRightArrowPressed;

if (_window != null)
{
Expand Down Expand Up @@ -747,9 +818,10 @@ private void LoadGui()
_window.FilterButton.OnItemSelected += OnFilterSelected;

if (ActionsBar == null)
{
return;
}

ActionsBar.PageButtons.LeftArrow.OnPressed += OnLeftArrowPressed;
ActionsBar.PageButtons.RightArrow.OnPressed += OnRightArrowPressed;

RegisterActionContainer(ActionsBar.ActionsContainer);

Expand Down Expand Up @@ -779,13 +851,10 @@ private void AssignSlots(List<SlotAssignment> assignments)
if (_actionsSystem == null)
return;

_actions.Clear();
foreach (var assign in assignments)
{
_actions.Add(assign.ActionId);
}
foreach (ref var assignment in CollectionsMarshal.AsSpan(assignments))
_pages[assignment.Hotbar][assignment.Slot] = assignment.ActionId;

_container?.SetActionData(_actionsSystem, _actions.ToArray());
_container?.SetActionData(_actionsSystem, _pages[_currentPageIndex]);
}

public void RemoveActionContainer()
Expand Down Expand Up @@ -822,7 +891,7 @@ private void OnComponentLinked(ActionsComponent component)
return;

LoadDefaultActions();
_container?.SetActionData(_actionsSystem, _actions.ToArray());
_container?.SetActionData(_actionsSystem, _pages[_currentPageIndex]);
QueueWindowUpdate();
}

Expand All @@ -841,11 +910,27 @@ private void LoadDefaultActions()
var actions = _actionsSystem.GetClientActions().Where(action => action.Comp.AutoPopulate).ToList();
actions.Sort(ActionComparer);

_actions.Clear();
foreach (var (action, _) in actions)
var offset = 0;
var totalPages = _pages.Count;
var pagesLeft = totalPages;
var currentPage = DefaultPageIndex;
while (pagesLeft > 0)
{
if (!_actions.Contains(action))
_actions.Add(action);
var page = _pages[currentPage];
var pageSize = page.Size;

for (var slot = 0; slot < pageSize; slot++)
if (slot + offset < actions.Count)
page[slot] = actions[slot + offset].Id;
else
page[slot] = null;

offset += pageSize;
currentPage++;
if (currentPage == totalPages)
currentPage = 0;

pagesLeft--;
}
}

Expand Down Expand Up @@ -956,4 +1041,22 @@ private void StopTargeting()
handOverlay.IconOverride = null;
handOverlay.EntityOverride = null;
}

//TODO: Serialize this shit
private sealed class ActionPage(int size)
{
public readonly EntityUid?[] Data = new EntityUid?[size];

public EntityUid? this[int index]
{
get => Data[index];
set => Data[index] = value;
}

public static implicit operator EntityUid?[](ActionPage p) => p.Data.ToArray();

public void Clear() => Array.Fill(Data, null);

public int Size => Data.Length;
}
}
Loading

0 comments on commit 388166b

Please sign in to comment.