mirror of
https://github.com/space-wizards/space-station-14.git
synced 2026-02-14 19:29:53 +01:00
Simplify hands UI code (#42534)
* Simplify hands UI code * i remembered about SortedHands in the component * minor cleanup --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
59d8495cc7
commit
6f8242c1fc
@@ -1,5 +1,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Client.UserInterface.Systems.Inventory.Controls;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client.UserInterface.Systems.Hands.Controls;
|
||||
@@ -7,10 +9,10 @@ namespace Content.Client.UserInterface.Systems.Hands.Controls;
|
||||
public sealed class HandsContainer : ItemSlotUIContainer<HandButton>
|
||||
{
|
||||
private readonly GridContainer _grid;
|
||||
public int ColumnLimit { get => _grid.Columns; set => _grid.Columns = value; }
|
||||
public int MaxButtonCount { get; set; } = 0;
|
||||
private readonly List<HandButton> _orderedButtons = new();
|
||||
public HandsComponent? PlayerHandsComponent;
|
||||
|
||||
public int MaxButtonsPerRow { get; set; }= 6;
|
||||
public int ColumnLimit { get; set; } = 6;
|
||||
|
||||
/// <summary>
|
||||
/// Indexer. This is used to reference a HandsContainer from the
|
||||
@@ -24,57 +26,32 @@ public sealed class HandsContainer : ItemSlotUIContainer<HandButton>
|
||||
_grid.ExpandBackwards = true;
|
||||
}
|
||||
|
||||
public override HandButton? AddButton(HandButton newButton)
|
||||
protected override void AddButton(HandButton newButton)
|
||||
{
|
||||
if (MaxButtonCount > 0)
|
||||
{
|
||||
if (ButtonCount >= MaxButtonCount)
|
||||
return null;
|
||||
_orderedButtons.Add(newButton);
|
||||
|
||||
_grid.AddChild(newButton);
|
||||
}
|
||||
else
|
||||
_grid.RemoveAllChildren();
|
||||
var enumerable = PlayerHandsComponent?.SortedHands is { } sortedHands
|
||||
? _orderedButtons.OrderBy(it => sortedHands.IndexOf(it.SlotName))
|
||||
: _orderedButtons.OrderBy(it => it.HandLocation);
|
||||
foreach (var button in enumerable)
|
||||
{
|
||||
_grid.AddChild(newButton);
|
||||
_grid.AddChild(button);
|
||||
}
|
||||
|
||||
_grid.Columns = Math.Min(_grid.ChildCount, MaxButtonsPerRow);
|
||||
return base.AddButton(newButton);
|
||||
_grid.Columns = Math.Min(_grid.ChildCount, ColumnLimit);
|
||||
}
|
||||
|
||||
public override void RemoveButton(string handName)
|
||||
protected override void RemoveButton(HandButton button)
|
||||
{
|
||||
var button = GetButton(handName);
|
||||
if (button == null)
|
||||
return;
|
||||
base.RemoveButton(button);
|
||||
_orderedButtons.Remove(button);
|
||||
_grid.RemoveChild(button);
|
||||
}
|
||||
|
||||
public bool TryGetLastButton(out HandButton? control)
|
||||
public override void ClearButtons()
|
||||
{
|
||||
if (Buttons.Count == 0)
|
||||
{
|
||||
control = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
control = Buttons.Values.Last();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryRemoveLastHand(out HandButton? control)
|
||||
{
|
||||
var success = TryGetLastButton(out control);
|
||||
if (control != null)
|
||||
RemoveButton(control);
|
||||
return success;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ClearButtons();
|
||||
_grid.RemoveAllChildren();
|
||||
base.ClearButtons();
|
||||
_orderedButtons.Clear();
|
||||
}
|
||||
|
||||
public IEnumerable<HandButton> GetButtons()
|
||||
@@ -85,8 +62,4 @@ public sealed class HandsContainer : ItemSlotUIContainer<HandButton>
|
||||
yield return hand;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFull => (MaxButtonCount != 0 && ButtonCount >= MaxButtonCount);
|
||||
|
||||
public int ButtonCount => _grid.ChildCount;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Inventory.VirtualItem;
|
||||
using Content.Shared.Timing;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
@@ -26,9 +25,6 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
[UISystemDependency] private readonly HandsSystem _handsSystem = default!;
|
||||
[UISystemDependency] private readonly UseDelaySystem _useDelay = default!;
|
||||
|
||||
private readonly List<HandsContainer> _handsContainers = new();
|
||||
private readonly Dictionary<string, int> _handContainerIndices = new();
|
||||
private readonly Dictionary<string, HandButton> _handLookup = new();
|
||||
private HandsComponent? _playerHandsComponent;
|
||||
private HandButton? _activeHand;
|
||||
|
||||
@@ -40,8 +36,6 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
private HandButton? _statusHandLeft;
|
||||
private HandButton? _statusHandRight;
|
||||
|
||||
private int _backupSuffix; //this is used when autogenerating container names if they don't have names
|
||||
|
||||
private HotbarGui? HandsGui => UIManager.GetActiveUIWidgetOrNull<HotbarGui>();
|
||||
|
||||
public void OnSystemLoaded(HandsSystem system)
|
||||
@@ -119,25 +113,16 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
|
||||
private void UnloadPlayerHands()
|
||||
{
|
||||
if (HandsGui != null)
|
||||
HandsGui.Visible = false;
|
||||
|
||||
_handContainerIndices.Clear();
|
||||
_handLookup.Clear();
|
||||
HandsGui?.Visible = false;
|
||||
HandsGui?.HandContainer.ClearButtons();
|
||||
_playerHandsComponent = null;
|
||||
|
||||
foreach (var container in _handsContainers)
|
||||
{
|
||||
container.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadPlayerHands(Entity<HandsComponent> handsComp)
|
||||
{
|
||||
DebugTools.Assert(_playerHandsComponent == null);
|
||||
if (HandsGui != null)
|
||||
HandsGui.Visible = true;
|
||||
|
||||
HandsGui?.Visible = true;
|
||||
HandsGui?.HandContainer.PlayerHandsComponent = handsComp;
|
||||
_playerHandsComponent = handsComp;
|
||||
foreach (var (name, hand) in handsComp.Comp.Hands)
|
||||
{
|
||||
@@ -182,29 +167,18 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
|
||||
private void HandBlocked(string handName)
|
||||
{
|
||||
if (!_handLookup.TryGetValue(handName, out var hand))
|
||||
{
|
||||
if (HandsGui?.HandContainer.TryGetButton(handName, out var hand) != true)
|
||||
return;
|
||||
}
|
||||
|
||||
hand.Blocked = true;
|
||||
hand!.Blocked = true;
|
||||
}
|
||||
|
||||
private void HandUnblocked(string handName)
|
||||
{
|
||||
if (!_handLookup.TryGetValue(handName, out var hand))
|
||||
{
|
||||
if (HandsGui?.HandContainer.TryGetButton(handName, out var hand) != true)
|
||||
return;
|
||||
}
|
||||
|
||||
hand.Blocked = false;
|
||||
}
|
||||
|
||||
private int GetHandContainerIndex(string containerName)
|
||||
{
|
||||
if (!_handContainerIndices.TryGetValue(containerName, out var result))
|
||||
return -1;
|
||||
return result;
|
||||
hand!.Blocked = false;
|
||||
}
|
||||
|
||||
private void OnItemAdded(string name, EntityUid entity)
|
||||
@@ -243,7 +217,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
_handsSystem.TryGetHand((playerEntity, _playerHandsComponent), name, out var handData))
|
||||
{
|
||||
UpdateHandStatus(hand, null, handData);
|
||||
if (handData?.EmptyRepresentative is { } representative)
|
||||
if (handData.Value.EmptyRepresentative is { } representative)
|
||||
{
|
||||
SetRepresentative(hand, representative);
|
||||
return;
|
||||
@@ -253,30 +227,6 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
hand.SetEntity(null);
|
||||
}
|
||||
|
||||
private HandsContainer GetFirstAvailableContainer()
|
||||
{
|
||||
if (_handsContainers.Count == 0)
|
||||
throw new Exception("Could not find an attached hand hud container");
|
||||
foreach (var container in _handsContainers)
|
||||
{
|
||||
if (container.IsFull)
|
||||
continue;
|
||||
return container;
|
||||
}
|
||||
|
||||
throw new Exception("All attached hand hud containers were full!");
|
||||
}
|
||||
|
||||
public bool TryGetHandContainer(string containerName, out HandsContainer? container)
|
||||
{
|
||||
container = null;
|
||||
var containerIndex = GetHandContainerIndex(containerName);
|
||||
if (containerIndex == -1)
|
||||
return false;
|
||||
container = _handsContainers[containerIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
//propagate hand activation to the hand system.
|
||||
private void StorageActivate(GUIBoundKeyEventArgs args, SlotControl handControl)
|
||||
{
|
||||
@@ -293,24 +243,23 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_handLookup.TryGetValue(handName, out var handControl) || handControl == _activeHand)
|
||||
if (HandsGui?.HandContainer.TryGetButton(handName, out var handControl) != true || handControl == _activeHand)
|
||||
return;
|
||||
|
||||
if (_activeHand != null)
|
||||
_activeHand.Highlight = false;
|
||||
|
||||
handControl.Highlight = true;
|
||||
handControl!.Highlight = true;
|
||||
_activeHand = handControl;
|
||||
|
||||
if (HandsGui != null &&
|
||||
_playerHandsComponent != null &&
|
||||
if (_playerHandsComponent != null &&
|
||||
_player.LocalSession?.AttachedEntity is { } playerEntity &&
|
||||
_handsSystem.TryGetHand((playerEntity, _playerHandsComponent), handName, out var hand))
|
||||
{
|
||||
var heldEnt = _handsSystem.GetHeldItem((playerEntity, _playerHandsComponent), handName);
|
||||
|
||||
var foldedLocation = hand.Value.Location.GetUILocation();
|
||||
if (foldedLocation == HandUILocation.Left)
|
||||
var foldedLocation = hand.Value.Location;
|
||||
if (foldedLocation == HandLocation.Left)
|
||||
{
|
||||
_statusHandLeft = handControl;
|
||||
HandsGui.UpdatePanelEntityLeft(heldEnt, hand.Value);
|
||||
@@ -328,8 +277,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
|
||||
private HandButton? GetHand(string handName)
|
||||
{
|
||||
_handLookup.TryGetValue(handName, out var handControl);
|
||||
return handControl;
|
||||
return HandsGui?.HandContainer.GetButton(handName);
|
||||
}
|
||||
|
||||
private HandButton AddHand(string handName, Hand hand)
|
||||
@@ -338,17 +286,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
button.StoragePressed += StorageActivate;
|
||||
button.Pressed += HandPressed;
|
||||
|
||||
if (!_handLookup.TryAdd(handName, button))
|
||||
return _handLookup[handName];
|
||||
|
||||
if (HandsGui != null)
|
||||
{
|
||||
HandsGui.HandContainer.AddButton(button);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetFirstAvailableContainer().AddButton(button);
|
||||
}
|
||||
HandsGui?.HandContainer.TryAddButton(button);
|
||||
|
||||
if (hand.EmptyRepresentative is { } representative)
|
||||
{
|
||||
@@ -359,7 +297,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
// If we don't have a status for this hand type yet, set it.
|
||||
// This means we have status filled by default in most scenarios,
|
||||
// otherwise the user'd need to switch hands to "activate" the hands the first time.
|
||||
if (hand.Location.GetUILocation() == HandUILocation.Left)
|
||||
if (hand.Location == HandLocation.Left)
|
||||
_statusHandLeft ??= button;
|
||||
else
|
||||
_statusHandRight ??= button;
|
||||
@@ -378,62 +316,17 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
_handsSystem.ReloadHandButtons();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swap hands from one container to the other.
|
||||
/// </summary>
|
||||
/// <param name="other"></param>
|
||||
/// <param name="source"></param>
|
||||
public void SwapHands(HandsContainer other, HandsContainer? source = null)
|
||||
{
|
||||
if (HandsGui == null && source == null)
|
||||
{
|
||||
throw new ArgumentException("Cannot swap hands if no source hand container exists!");
|
||||
}
|
||||
|
||||
source ??= HandsGui!.HandContainer;
|
||||
|
||||
var transfer = new List<Control>();
|
||||
foreach (var child in source.Children)
|
||||
{
|
||||
if (child is not HandButton)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
transfer.Add(child);
|
||||
}
|
||||
|
||||
foreach (var control in transfer)
|
||||
{
|
||||
source.RemoveChild(control);
|
||||
other.AddChild(control);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveHand(string handName)
|
||||
{
|
||||
RemoveHand(handName, out _);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
private bool RemoveHand(string handName, out HandButton? handButton)
|
||||
{
|
||||
if (!_handLookup.TryGetValue(handName, out handButton))
|
||||
return false;
|
||||
if (handButton.Parent is HandsContainer handContainer)
|
||||
{
|
||||
handContainer.RemoveButton(handButton);
|
||||
}
|
||||
if (HandsGui?.HandContainer.TryRemoveButton(handName, out var handButton) != true)
|
||||
return;
|
||||
|
||||
if (_statusHandLeft == handButton)
|
||||
_statusHandLeft = null;
|
||||
if (_statusHandRight == handButton)
|
||||
_statusHandRight = null;
|
||||
|
||||
_handLookup.Remove(handName);
|
||||
handButton.Orphan();
|
||||
UpdateVisibleStatusPanels();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void UpdateVisibleStatusPanels()
|
||||
@@ -441,9 +334,12 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
var leftVisible = false;
|
||||
var rightVisible = false;
|
||||
|
||||
foreach (var hand in _handLookup.Values)
|
||||
if (HandsGui is null)
|
||||
return;
|
||||
|
||||
foreach (var hand in HandsGui.HandContainer.GetButtons())
|
||||
{
|
||||
if (hand.HandLocation.GetUILocation() == HandUILocation.Left)
|
||||
if (hand.HandLocation == HandLocation.Left)
|
||||
{
|
||||
leftVisible = true;
|
||||
}
|
||||
@@ -453,73 +349,34 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
|
||||
}
|
||||
}
|
||||
|
||||
HandsGui?.UpdateStatusVisibility(leftVisible, rightVisible);
|
||||
}
|
||||
|
||||
public string RegisterHandContainer(HandsContainer handContainer)
|
||||
{
|
||||
var name = "HandContainer_" + _backupSuffix;
|
||||
|
||||
if (handContainer.Indexer == null)
|
||||
{
|
||||
handContainer.Indexer = name;
|
||||
_backupSuffix++;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = handContainer.Indexer;
|
||||
}
|
||||
|
||||
_handContainerIndices.Add(name, _handsContainers.Count);
|
||||
_handsContainers.Add(handContainer);
|
||||
return name;
|
||||
}
|
||||
|
||||
public bool RemoveHandContainer(string handContainerName)
|
||||
{
|
||||
var index = GetHandContainerIndex(handContainerName);
|
||||
if (index == -1)
|
||||
return false;
|
||||
_handContainerIndices.Remove(handContainerName);
|
||||
_handsContainers.RemoveAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RemoveHandContainer(string handContainerName, out HandsContainer? container)
|
||||
{
|
||||
var success = _handContainerIndices.TryGetValue(handContainerName, out var index);
|
||||
container = _handsContainers[index];
|
||||
_handContainerIndices.Remove(handContainerName);
|
||||
_handsContainers.RemoveAt(index);
|
||||
return success;
|
||||
HandsGui.UpdateStatusVisibility(leftVisible, rightVisible);
|
||||
}
|
||||
|
||||
public void OnStateEntered(GameplayState state)
|
||||
{
|
||||
if (HandsGui != null)
|
||||
HandsGui.Visible = _playerHandsComponent != null;
|
||||
HandsGui?.Visible = _playerHandsComponent != null;
|
||||
}
|
||||
|
||||
public override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (HandsGui is not { } handsGui)
|
||||
return;
|
||||
|
||||
// TODO this should be event based but 2 systems modify the same component differently for some reason
|
||||
foreach (var container in _handsContainers)
|
||||
foreach (var hand in handsGui.HandContainer.GetButtons())
|
||||
{
|
||||
foreach (var hand in container.GetButtons())
|
||||
|
||||
if (!_entities.TryGetComponent(hand.Entity, out UseDelayComponent? useDelay))
|
||||
{
|
||||
|
||||
if (!_entities.TryGetComponent(hand.Entity, out UseDelayComponent? useDelay))
|
||||
{
|
||||
hand.CooldownDisplay.Visible = false;
|
||||
continue;
|
||||
}
|
||||
var delay = _useDelay.GetLastEndingDelay((hand.Entity.Value, useDelay));
|
||||
|
||||
hand.CooldownDisplay.Visible = true;
|
||||
hand.CooldownDisplay.FromTime(delay.StartTime, delay.EndTime);
|
||||
hand.CooldownDisplay.Visible = false;
|
||||
continue;
|
||||
}
|
||||
var delay = _useDelay.GetLastEndingDelay((hand.Entity.Value, useDelay));
|
||||
|
||||
hand.CooldownDisplay.Visible = true;
|
||||
hand.CooldownDisplay.FromTime(delay.StartTime, delay.EndTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ public sealed class HotbarUIController : UIController
|
||||
_inventory = UIManager.GetUIController<InventoryUIController>();
|
||||
_hands = UIManager.GetUIController<HandsUIController>();
|
||||
_storage = UIManager.GetUIController<StorageUIController>();
|
||||
_hands.RegisterHandContainer(handsContainer);
|
||||
}
|
||||
|
||||
public void ReloadHotbar()
|
||||
|
||||
@@ -11,8 +11,8 @@ public sealed partial class HotbarGui : UIWidget
|
||||
public HotbarGui()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
StatusPanelRight.SetSide(HandUILocation.Right);
|
||||
StatusPanelLeft.SetSide(HandUILocation.Left);
|
||||
StatusPanelRight.SetSide(HandLocation.Right);
|
||||
StatusPanelLeft.SetSide(HandLocation.Left);
|
||||
var hotbarController = UserInterfaceManager.GetUIController<HotbarUIController>();
|
||||
|
||||
hotbarController.Setup(HandContainer);
|
||||
@@ -29,10 +29,10 @@ public sealed partial class HotbarGui : UIWidget
|
||||
StatusPanelRight.Update(entity, hand);
|
||||
}
|
||||
|
||||
public void SetHighlightHand(HandUILocation? hand)
|
||||
public void SetHighlightHand(HandLocation? hand)
|
||||
{
|
||||
StatusPanelLeft.UpdateHighlight(hand is HandUILocation.Left);
|
||||
StatusPanelRight.UpdateHighlight(hand is HandUILocation.Right);
|
||||
StatusPanelLeft.UpdateHighlight(hand is HandLocation.Left);
|
||||
StatusPanelRight.UpdateHighlight(hand is HandLocation.Right);
|
||||
}
|
||||
|
||||
public void UpdateStatusVisibility(bool left, bool right)
|
||||
|
||||
@@ -14,54 +14,36 @@ public interface IItemslotUIContainer
|
||||
[Virtual]
|
||||
public abstract class ItemSlotUIContainer<T> : GridContainer, IItemslotUIContainer where T : SlotControl
|
||||
{
|
||||
protected readonly Dictionary<string, T> Buttons = new();
|
||||
private readonly Dictionary<string, T> _buttons = new();
|
||||
|
||||
private int? _maxColumns;
|
||||
public int? MaxColumns { get; set; }
|
||||
|
||||
public int? MaxColumns
|
||||
public virtual void ClearButtons()
|
||||
{
|
||||
get => _maxColumns;
|
||||
set => _maxColumns = value;
|
||||
}
|
||||
|
||||
public virtual bool TryAddButton(T newButton, out T button)
|
||||
{
|
||||
var tempButton = AddButton(newButton);
|
||||
if (tempButton == null)
|
||||
foreach (var button in _buttons.Values)
|
||||
{
|
||||
button = newButton;
|
||||
return false;
|
||||
button.Orphan();
|
||||
}
|
||||
|
||||
button = newButton;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ClearButtons()
|
||||
{
|
||||
foreach (var button in Buttons.Values)
|
||||
{
|
||||
button.Dispose();
|
||||
}
|
||||
|
||||
Buttons.Clear();
|
||||
_buttons.Clear();
|
||||
}
|
||||
|
||||
public bool TryRegisterButton(SlotControl control, string newSlotName)
|
||||
{
|
||||
if (newSlotName == "")
|
||||
return false;
|
||||
if (!(control is T slotButton))
|
||||
if (control is not T slotButton)
|
||||
return false;
|
||||
if (Buttons.TryGetValue(newSlotName, out var foundButton))
|
||||
|
||||
if (_buttons.TryGetValue(newSlotName, out var foundButton))
|
||||
{
|
||||
if (control == foundButton)
|
||||
return true; //if the slotName is already set do nothing
|
||||
throw new Exception("Could not update button to slot:" + newSlotName + " slot already assigned!");
|
||||
}
|
||||
|
||||
Buttons.Remove(slotButton.SlotName);
|
||||
AddButton(slotButton);
|
||||
_buttons.Remove(slotButton.SlotName);
|
||||
TryAddButton(slotButton);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -69,69 +51,54 @@ public abstract class ItemSlotUIContainer<T> : GridContainer, IItemslotUIContain
|
||||
{
|
||||
if (control is not T newButton)
|
||||
return false;
|
||||
return AddButton(newButton) != null;
|
||||
return TryAddButton(newButton) != null;
|
||||
}
|
||||
|
||||
public virtual T? AddButton(T newButton)
|
||||
{
|
||||
if (!Children.Contains(newButton) && newButton.Parent == null && newButton.SlotName != "")
|
||||
AddChild(newButton);
|
||||
Columns = _maxColumns ?? ChildCount;
|
||||
return AddButtonToDict(newButton);
|
||||
}
|
||||
|
||||
protected virtual T? AddButtonToDict(T newButton)
|
||||
public T? TryAddButton(T newButton)
|
||||
{
|
||||
if (newButton.SlotName == "")
|
||||
{
|
||||
Logger.Warning("Could not add button " + newButton.Name + "No slotname");
|
||||
Log.Warning($"{newButton.Name} because it has no slot name");
|
||||
return null;
|
||||
}
|
||||
|
||||
return !Buttons.TryAdd(newButton.SlotName, newButton) ? null : newButton;
|
||||
if (Children.Contains(newButton) || newButton.Parent != null)
|
||||
return null;
|
||||
|
||||
if (!_buttons.TryAdd(newButton.SlotName, newButton))
|
||||
return null;
|
||||
|
||||
AddButton(newButton);
|
||||
return newButton;
|
||||
}
|
||||
|
||||
public virtual void RemoveButton(string slotName)
|
||||
protected virtual void AddButton(T newButton)
|
||||
{
|
||||
if (!Buttons.TryGetValue(slotName, out var button))
|
||||
return;
|
||||
AddChild(newButton);
|
||||
Columns = MaxColumns ?? ChildCount;
|
||||
}
|
||||
|
||||
public bool TryRemoveButton(string slotName, [NotNullWhen(true)] out T? button)
|
||||
{
|
||||
if (!_buttons.TryGetValue(slotName, out button))
|
||||
return false;
|
||||
|
||||
_buttons.Remove(button.SlotName);
|
||||
RemoveButton(button);
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void RemoveButtons(params string[] slotNames)
|
||||
protected virtual void RemoveButton(T button)
|
||||
{
|
||||
foreach (var slotName in slotNames)
|
||||
{
|
||||
RemoveButton(slotName);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RemoveButtons(params T?[] buttons)
|
||||
{
|
||||
foreach (var button in buttons)
|
||||
{
|
||||
if (button != null)
|
||||
RemoveButton(button);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void RemoveButtonFromDict(T button)
|
||||
{
|
||||
Buttons.Remove(button.SlotName);
|
||||
}
|
||||
|
||||
public virtual void RemoveButton(T button)
|
||||
{
|
||||
RemoveButtonFromDict(button);
|
||||
Children.Remove(button);
|
||||
button.Dispose();
|
||||
}
|
||||
|
||||
public virtual T? GetButton(string slotName)
|
||||
public T? GetButton(string slotName)
|
||||
{
|
||||
return !Buttons.TryGetValue(slotName, out var button) ? null : button;
|
||||
return _buttons.GetValueOrDefault(slotName);
|
||||
}
|
||||
|
||||
public virtual bool TryGetButton(string slotName, [NotNullWhen(true)] out T? button)
|
||||
public bool TryGetButton(string slotName, [NotNullWhen(true)] out T? button)
|
||||
{
|
||||
return (button = GetButton(slotName)) != null;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public sealed partial class ItemStatusPanel : Control
|
||||
[ViewVariables] private Hand? _hand;
|
||||
|
||||
// Tracked so we can re-run SetSide() if the theme changes.
|
||||
private HandUILocation _side;
|
||||
private HandLocation _side;
|
||||
|
||||
public ItemStatusPanel()
|
||||
{
|
||||
@@ -28,7 +28,7 @@ public sealed partial class ItemStatusPanel : Control
|
||||
IoCManager.InjectDependencies(this);
|
||||
}
|
||||
|
||||
public void SetSide(HandUILocation location)
|
||||
public void SetSide(HandLocation location)
|
||||
{
|
||||
// AN IMPORTANT REMINDER ABOUT THIS CODE:
|
||||
// In the UI, the RIGHT hand is on the LEFT on the screen.
|
||||
@@ -43,14 +43,14 @@ public sealed partial class ItemStatusPanel : Control
|
||||
|
||||
switch (location)
|
||||
{
|
||||
case HandUILocation.Right:
|
||||
case HandLocation.Right or HandLocation.Middle:
|
||||
texture = Theme.ResolveTexture("item_status_right");
|
||||
textureHighlight = Theme.ResolveTexture("item_status_right_highlight");
|
||||
cutOut = StyleBox.Margin.Left;
|
||||
flat = StyleBox.Margin.Right;
|
||||
contentMargin = MarginFromThemeColor("_itemstatus_content_margin_right");
|
||||
break;
|
||||
case HandUILocation.Left:
|
||||
case HandLocation.Left:
|
||||
texture = Theme.ResolveTexture("item_status_left");
|
||||
textureHighlight = Theme.ResolveTexture("item_status_left_highlight");
|
||||
cutOut = StyleBox.Margin.Right;
|
||||
|
||||
@@ -147,7 +147,7 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
|
||||
if (!container.TryGetButton(data.SlotName, out var button))
|
||||
{
|
||||
button = CreateSlotButton(data);
|
||||
container.AddButton(button);
|
||||
container.TryAddButton(button);
|
||||
}
|
||||
|
||||
var showStorage = _entities.HasComponent<StorageComponent>(data.HeldEntity);
|
||||
@@ -373,7 +373,7 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
|
||||
return;
|
||||
|
||||
var button = CreateSlotButton(data);
|
||||
slotGroup.AddButton(button);
|
||||
slotGroup.TryAddButton(button);
|
||||
}
|
||||
|
||||
private void RemoveSlot(SlotData data)
|
||||
@@ -381,7 +381,7 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
|
||||
if (!_slotGroups.TryGetValue(data.SlotGroup, out var slotGroup))
|
||||
return;
|
||||
|
||||
slotGroup.RemoveButton(data.SlotName);
|
||||
slotGroup.TryRemoveButton(data.SlotName, out _);
|
||||
}
|
||||
|
||||
public void ReloadSlots()
|
||||
|
||||
@@ -169,43 +169,9 @@ public sealed class HandsComponentState : ComponentState
|
||||
/// <summary>
|
||||
/// What side of the body this hand is on.
|
||||
/// </summary>
|
||||
/// <seealso cref="HandUILocation"/>
|
||||
/// <seealso cref="HandLocationExt"/>
|
||||
public enum HandLocation : byte
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Right
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// What side of the UI a hand is on.
|
||||
/// </summary>
|
||||
/// <seealso cref="HandLocationExt"/>
|
||||
/// <seealso cref="HandLocation"/>
|
||||
public enum HandUILocation : byte
|
||||
{
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper functions for working with <see cref="HandLocation"/>.
|
||||
/// </summary>
|
||||
public static class HandLocationExt
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert a <see cref="HandLocation"/> into the appropriate <see cref="HandUILocation"/>.
|
||||
/// This maps "middle" hands to <see cref="HandUILocation.Right"/>.
|
||||
/// </summary>
|
||||
public static HandUILocation GetUILocation(this HandLocation location)
|
||||
{
|
||||
return location switch
|
||||
{
|
||||
HandLocation.Left => HandUILocation.Left,
|
||||
HandLocation.Middle => HandUILocation.Right,
|
||||
HandLocation.Right => HandUILocation.Right,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(location), location, null)
|
||||
};
|
||||
}
|
||||
Left
|
||||
}
|
||||
|
||||
@@ -90,6 +90,8 @@ public abstract partial class SharedHandsSystem
|
||||
|
||||
ent.Comp.Hands.Add(handName, hand);
|
||||
ent.Comp.SortedHands.Add(handName);
|
||||
// we use LINQ + ToList instead of the list sort because it's a stable sort vs the list sort
|
||||
ent.Comp.SortedHands = ent.Comp.SortedHands.OrderBy(handId => ent.Comp.Hands[handId].Location).ToList();
|
||||
Dirty(ent);
|
||||
|
||||
OnPlayerAddHand?.Invoke((ent, ent.Comp), handName, hand.Location);
|
||||
|
||||
Reference in New Issue
Block a user