Files
tbd-station-14/Content.Client/UserInterface/HandsGui.cs
DrSmugleaf f785ec4efb Add pulling taking up a hand (#2405)
* Add pulling taking up a hand

* Revert unnecessary refactor
2020-10-28 10:16:40 +01:00

365 lines
12 KiB
C#

using System;
using System.Linq;
using Content.Client.GameObjects.Components.Items;
using Content.Client.Utility;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.Input;
using Robust.Client.Graphics;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input;
using Robust.Shared.IoC;
using Robust.Shared.Timing;
namespace Content.Client.UserInterface
{
public class HandsGui : Control
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IItemSlotManager _itemSlotManager = default!;
private readonly TextureRect _activeHandRect;
private readonly Texture _leftHandTexture;
private readonly Texture _middleHandTexture;
private readonly Texture _rightHandTexture;
private readonly ItemStatusPanel _leftPanel;
private readonly ItemStatusPanel _topPanel;
private readonly ItemStatusPanel _rightPanel;
private readonly HBoxContainer _guiContainer;
private readonly VBoxContainer _handsColumn;
private readonly HBoxContainer _handsContainer;
private int _lastHands;
public HandsGui()
{
IoCManager.InjectDependencies(this);
AddChild(_guiContainer = new HBoxContainer
{
SeparationOverride = 0,
Children =
{
(_rightPanel = ItemStatusPanel.FromSide(HandLocation.Right)),
(_handsColumn = new VBoxContainer
{
Children =
{
(_topPanel = ItemStatusPanel.FromSide(HandLocation.Middle)),
(_handsContainer = new HBoxContainer {SeparationOverride = 0})
}
}),
(_leftPanel = ItemStatusPanel.FromSide(HandLocation.Left))
}
});
var textureHandActive = _resourceCache.GetTexture("/Textures/Interface/Inventory/hand_active.png");
// Active hand
_activeHandRect = new TextureRect
{
Texture = textureHandActive,
TextureScale = (2, 2)
};
_leftHandTexture = _resourceCache.GetTexture("/Textures/Interface/Inventory/hand_l.png");
_middleHandTexture = _resourceCache.GetTexture("/Textures/Interface/Inventory/hand_middle.png");
_rightHandTexture = _resourceCache.GetTexture("/Textures/Interface/Inventory/hand_r.png");
}
private ItemStatusPanel GetItemPanel(Hand hand)
{
return hand.Location switch
{
HandLocation.Left => _rightPanel,
HandLocation.Middle => _topPanel,
HandLocation.Right => _leftPanel,
_ => throw new IndexOutOfRangeException()
};
}
private Texture HandTexture(HandLocation location)
{
switch (location)
{
case HandLocation.Left:
return _leftHandTexture;
case HandLocation.Middle:
return _middleHandTexture;
case HandLocation.Right:
return _rightHandTexture;
default:
throw new ArgumentOutOfRangeException(nameof(location), location, null);
}
}
/// <summary>
/// Adds a new hand to this control
/// </summary>
/// <param name="hand">The hand to add to this control</param>
/// <param name="buttonLocation">
/// The actual location of the button. The right hand is drawn
/// on the LEFT of the screen.
/// </param>
private void AddHand(Hand hand, HandLocation buttonLocation)
{
var buttonTexture = HandTexture(buttonLocation);
var storageTexture = _resourceCache.GetTexture("/Textures/Interface/Inventory/back.png");
var blockedTexture = _resourceCache.GetTexture("/Textures/Interface/Inventory/blocked.png");
var button = new HandButton(buttonTexture, storageTexture, blockedTexture, buttonLocation);
var slot = hand.Name;
button.OnPressed += args => HandKeyBindDown(args, slot);
button.OnStoragePressed += args => _OnStoragePressed(args, slot);
_handsContainer.AddChild(button);
if (_activeHandRect.Parent == null)
{
button.AddChild(_activeHandRect);
_activeHandRect.SetPositionInParent(1);
}
hand.Button = button;
}
public void RemoveHand(Hand hand)
{
var button = hand.Button;
if (button != null)
{
if (button.Children.Contains(_activeHandRect))
{
button.RemoveChild(_activeHandRect);
}
_handsContainer.RemoveChild(button);
}
}
/// <summary>
/// Gets the hands component controlling this gui
/// </summary>
/// <param name="hands"></param>
/// <returns>true if successful and false if failure</returns>
private bool TryGetHands(out HandsComponent hands)
{
hands = default;
var entity = _playerManager?.LocalPlayer?.ControlledEntity;
return entity != null && entity.TryGetComponent(out hands);
}
public void UpdateHandIcons()
{
if (Parent == null)
{
return;
}
UpdateDraw();
if (!TryGetHands(out var component))
{
return;
}
// TODO: Remove button on remove hand
var hands = component.Hands.OrderByDescending(x => x.Location).ToArray();
for (var i = 0; i < hands.Length; i++)
{
var hand = hands[i];
if (hand.Button == null)
{
AddHand(hand, hand.Location);
}
hand.Button!.Button.Texture = HandTexture(hand.Location);
hand.Button!.SetPositionInParent(i);
_itemSlotManager.SetItemSlot(hand.Button, hand.Entity);
}
_activeHandRect.Parent?.RemoveChild(_activeHandRect);
component.GetHand(component.ActiveIndex)?.Button?.AddChild(_activeHandRect);
if (hands.Length > 0)
{
_activeHandRect.SetPositionInParent(1);
}
_leftPanel.SetPositionFirst();
_rightPanel.SetPositionLast();
}
private void HandKeyBindDown(GUIBoundKeyEventArgs args, string slotName)
{
if (!TryGetHands(out var hands))
{
return;
}
if (args.Function == ContentKeyFunctions.MouseMiddle)
{
hands.SendChangeHand(slotName);
args.Handle();
return;
}
var entity = hands.GetEntity(slotName);
if (entity == null)
{
if (args.Function == EngineKeyFunctions.UIClick && hands.ActiveIndex != slotName)
{
hands.SendChangeHand(slotName);
args.Handle();
}
return;
}
if (_itemSlotManager.OnButtonPressed(args, entity))
{
args.Handle();
return;
}
if (args.Function == EngineKeyFunctions.UIClick)
{
if (hands.ActiveIndex == slotName)
{
hands.UseActiveHand();
}
else
{
hands.AttackByInHand(slotName);
}
args.Handle();
}
}
private void _OnStoragePressed(GUIBoundKeyEventArgs args, string handIndex)
{
if (args.Function != EngineKeyFunctions.UIClick || !TryGetHands(out var hands))
{
return;
}
hands.ActivateItemInHand(handIndex);
}
private void UpdatePanels()
{
if (!TryGetHands(out var component))
{
return;
}
foreach (var hand in component.Hands)
{
_itemSlotManager.UpdateCooldown(hand.Button, hand.Entity);
}
switch (component.Hands.Count)
{
case var n when n == 0 && _lastHands != 0:
_guiContainer.Visible = false;
_topPanel.Update(null);
_leftPanel.Update(null);
_rightPanel.Update(null);
break;
case 1:
if (_lastHands != 1)
{
_guiContainer.Visible = true;
_topPanel.Update(null);
_topPanel.Visible = false;
_leftPanel.Update(null);
_leftPanel.Visible = false;
_rightPanel.Visible = true;
if (!_guiContainer.Children.Contains(_rightPanel))
{
_rightPanel.AddChild(_rightPanel);
_rightPanel.SetPositionFirst();
}
}
_rightPanel.Update(component.Hands[0].Entity);
break;
case 2:
if (_lastHands != 2)
{
_guiContainer.Visible = true;
_topPanel.Update(null);
_topPanel.Visible = false;
_leftPanel.Visible = true;
_rightPanel.Visible = true;
if (_handsColumn.Children.Contains(_topPanel))
{
_handsColumn.RemoveChild(_topPanel);
}
}
_leftPanel.Update(component.Hands[0].Entity);
_rightPanel.Update(component.Hands[1].Entity);
// Order is left, right
foreach (var hand in component.Hands)
{
var tooltip = GetItemPanel(hand);
tooltip.Update(hand.Entity);
}
break;
case var n when n > 2:
if (_lastHands <= 2)
{
_guiContainer.Visible = true;
_topPanel.Visible = true;
_leftPanel.Visible = false;
_rightPanel.Visible = false;
if (!_handsColumn.Children.Contains(_topPanel))
{
_handsColumn.AddChild(_topPanel);
_topPanel.SetPositionFirst();
}
}
_topPanel.Update(component.ActiveHand);
_leftPanel.Update(null);
_rightPanel.Update(null);
break;
}
_lastHands = component.Hands.Count;
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdatePanels();
}
}
}