@@ -31,12 +31,13 @@ public sealed class HotbarUIController : UIController
|
||||
ReloadHotbar();
|
||||
}
|
||||
|
||||
public void Setup(HandsContainer handsContainer)
|
||||
public void Setup(HandsContainer handsContainer, StorageContainer storageContainer)
|
||||
{
|
||||
_inventory = UIManager.GetUIController<InventoryUIController>();
|
||||
_hands = UIManager.GetUIController<HandsUIController>();
|
||||
_storage = UIManager.GetUIController<StorageUIController>();
|
||||
_hands.RegisterHandContainer(handsContainer);
|
||||
_storage.RegisterStorageContainer(storageContainer);
|
||||
}
|
||||
|
||||
public void ReloadHotbar()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<widgets:HotbarGui
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:inventory="clr-namespace:Content.Client.UserInterface.Systems.Inventory.Controls"
|
||||
xmlns:storage="clr-namespace:Content.Client.UserInterface.Systems.Storage.Controls"
|
||||
xmlns:hands="clr-namespace:Content.Client.UserInterface.Systems.Hands.Controls"
|
||||
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Hotbar.Widgets"
|
||||
Name="HotbarInterface"
|
||||
@@ -12,8 +13,10 @@
|
||||
<BoxContainer Name="StorageContainer"
|
||||
Access="Public"
|
||||
HorizontalAlignment="Center"
|
||||
HorizontalExpand="True"
|
||||
Margin="10">
|
||||
<storage:StorageContainer
|
||||
Name="StoragePanel"
|
||||
Visible="False"/>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" Name="Hotbar" HorizontalAlignment="Center">
|
||||
<inventory:ItemSlotButtonContainer
|
||||
|
||||
@@ -15,7 +15,7 @@ public sealed partial class HotbarGui : UIWidget
|
||||
StatusPanelLeft.SetSide(HandUILocation.Left);
|
||||
var hotbarController = UserInterfaceManager.GetUIController<HotbarUIController>();
|
||||
|
||||
hotbarController.Setup(HandContainer);
|
||||
hotbarController.Setup(HandContainer, StoragePanel);
|
||||
LayoutContainer.SetGrowVertical(this, LayoutContainer.GrowDirection.Begin);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ public sealed class ItemGridPiece : Control, IEntityControl
|
||||
Location = location;
|
||||
|
||||
Visible = true;
|
||||
MouseFilter = MouseFilterMode.Stop;
|
||||
MouseFilter = MouseFilterMode.Pass;
|
||||
|
||||
TooltipSupplier = SupplyTooltip;
|
||||
|
||||
@@ -105,11 +105,8 @@ public sealed class ItemGridPiece : Control, IEntityControl
|
||||
return;
|
||||
}
|
||||
|
||||
if (_storageController.IsDragging && _storageController.DraggingGhost?.Entity == Entity &&
|
||||
_storageController.DraggingGhost != this)
|
||||
{
|
||||
if (_storageController.IsDragging && _storageController.DraggingGhost?.Entity == Entity && _storageController.DraggingGhost != this)
|
||||
return;
|
||||
}
|
||||
|
||||
var adjustedShape = _entityManager.System<ItemSystem>().GetAdjustedItemShape((Entity, itemComponent), Location.Rotation, Vector2i.Zero);
|
||||
var boundingGrid = adjustedShape.GetBoundingBox();
|
||||
|
||||
@@ -3,9 +3,7 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Hands.Systems;
|
||||
using Content.Client.Items.Systems;
|
||||
using Content.Client.Storage;
|
||||
using Content.Client.Storage.Systems;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Storage;
|
||||
@@ -13,14 +11,12 @@ using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.UserInterface.Systems.Storage.Controls;
|
||||
|
||||
public sealed class StorageWindow : BaseWindow
|
||||
public sealed class StorageContainer : BaseWindow
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
private readonly StorageUIController _storageController;
|
||||
@@ -31,20 +27,6 @@ public sealed class StorageWindow : BaseWindow
|
||||
private readonly GridContainer _backgroundGrid;
|
||||
private readonly GridContainer _sidebar;
|
||||
|
||||
private Control _titleContainer;
|
||||
private Label _titleLabel;
|
||||
|
||||
// Needs to be nullable in case a piece is in default spot.
|
||||
private readonly Dictionary<EntityUid, (ItemStorageLocation? Loc, ItemGridPiece Control)> _pieces = new();
|
||||
private readonly List<Control> _controlGrid = new();
|
||||
|
||||
private ValueList<EntityUid> _contained = new();
|
||||
private ValueList<EntityUid> _toRemove = new();
|
||||
|
||||
private TextureButton? _backButton;
|
||||
|
||||
private bool _isDirty;
|
||||
|
||||
public event Action<GUIBoundKeyEventArgs, ItemGridPiece>? OnPiecePressed;
|
||||
public event Action<GUIBoundKeyEventArgs, ItemGridPiece>? OnPieceUnpressed;
|
||||
|
||||
@@ -69,10 +51,9 @@ public sealed class StorageWindow : BaseWindow
|
||||
private readonly string _sidebarFatTexturePath = "Storage/sidebar_fat";
|
||||
private Texture? _sidebarFatTexture;
|
||||
|
||||
public StorageWindow()
|
||||
public StorageContainer()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
Resizable = false;
|
||||
|
||||
_storageController = UserInterfaceManager.GetUIController<StorageUIController>();
|
||||
|
||||
@@ -82,7 +63,6 @@ public sealed class StorageWindow : BaseWindow
|
||||
|
||||
_sidebar = new GridContainer
|
||||
{
|
||||
Name = "SideBar",
|
||||
HSeparationOverride = 0,
|
||||
VSeparationOverride = 0,
|
||||
Columns = 1
|
||||
@@ -90,48 +70,21 @@ public sealed class StorageWindow : BaseWindow
|
||||
|
||||
_pieceGrid = new GridContainer
|
||||
{
|
||||
Name = "PieceGrid",
|
||||
HSeparationOverride = 0,
|
||||
VSeparationOverride = 0
|
||||
};
|
||||
|
||||
_backgroundGrid = new GridContainer
|
||||
{
|
||||
Name = "BackgroundGrid",
|
||||
HSeparationOverride = 0,
|
||||
VSeparationOverride = 0
|
||||
};
|
||||
|
||||
_titleLabel = new Label()
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
Name = "StorageLabel",
|
||||
ClipText = true,
|
||||
Text = "Dummy",
|
||||
StyleClasses =
|
||||
{
|
||||
"FancyWindowTitle",
|
||||
}
|
||||
};
|
||||
|
||||
_titleContainer = new PanelContainer()
|
||||
{
|
||||
StyleClasses =
|
||||
{
|
||||
"WindowHeadingBackground"
|
||||
},
|
||||
Children =
|
||||
{
|
||||
_titleLabel
|
||||
}
|
||||
};
|
||||
|
||||
var container = new BoxContainer
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Vertical,
|
||||
Children =
|
||||
{
|
||||
_titleContainer,
|
||||
new BoxContainer
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
@@ -177,22 +130,12 @@ public sealed class StorageWindow : BaseWindow
|
||||
if (entity == null)
|
||||
return;
|
||||
|
||||
if (UserInterfaceManager.GetUIController<StorageUIController>().WindowTitle)
|
||||
{
|
||||
_titleLabel.Text = Identity.Name(entity.Value, _entity);
|
||||
_titleContainer.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_titleContainer.Visible = false;
|
||||
}
|
||||
|
||||
BuildGridRepresentation();
|
||||
}
|
||||
|
||||
private void BuildGridRepresentation()
|
||||
{
|
||||
if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var comp) || comp.Grid.Count == 0)
|
||||
if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var comp) || !comp.Grid.Any())
|
||||
return;
|
||||
|
||||
var boundingGrid = comp.Grid.GetBoundingBox();
|
||||
@@ -202,11 +145,11 @@ public sealed class StorageWindow : BaseWindow
|
||||
#region Sidebar
|
||||
_sidebar.Children.Clear();
|
||||
_sidebar.Rows = boundingGrid.Height + 1;
|
||||
|
||||
var exitButton = new TextureButton
|
||||
{
|
||||
Name = "ExitButton",
|
||||
TextureNormal = _exitTexture,
|
||||
TextureNormal = _entity.System<StorageSystem>().OpenStorageAmount == 1
|
||||
?_exitTexture
|
||||
: _backTexture,
|
||||
Scale = new Vector2(2, 2),
|
||||
};
|
||||
exitButton.OnPressed += _ =>
|
||||
@@ -222,10 +165,8 @@ public sealed class StorageWindow : BaseWindow
|
||||
args.Handle();
|
||||
}
|
||||
};
|
||||
|
||||
var exitContainer = new BoxContainer
|
||||
{
|
||||
Name = "ExitContainer",
|
||||
Children =
|
||||
{
|
||||
new TextureRect
|
||||
@@ -241,61 +182,8 @@ public sealed class StorageWindow : BaseWindow
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_sidebar.AddChild(exitContainer);
|
||||
var offset = 1;
|
||||
|
||||
if (_entity.System<StorageSystem>().NestedStorage && boundingGrid.Height > 0)
|
||||
{
|
||||
offset += 1;
|
||||
|
||||
_backButton = new TextureButton
|
||||
{
|
||||
TextureNormal = _backTexture,
|
||||
Scale = new Vector2(2, 2),
|
||||
};
|
||||
_backButton.OnPressed += _ =>
|
||||
{
|
||||
var containerSystem = _entity.System<SharedContainerSystem>();
|
||||
|
||||
if (containerSystem.TryGetContainingContainer(StorageEntity.Value, out var container) &&
|
||||
_entity.TryGetComponent(container.Owner, out StorageComponent? storage))
|
||||
{
|
||||
Close();
|
||||
|
||||
if (_entity.System<SharedUserInterfaceSystem>()
|
||||
.TryGetOpenUi<StorageBoundUserInterface>(container.Owner,
|
||||
StorageComponent.StorageUiKey.Key,
|
||||
out var parentBui))
|
||||
{
|
||||
parentBui.Show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var backContainer = new BoxContainer
|
||||
{
|
||||
Name = "ExitContainer",
|
||||
Children =
|
||||
{
|
||||
new TextureRect
|
||||
{
|
||||
Texture = boundingGrid.Height > 2 ? _sidebarMiddleTexture : _sidebarBottomTexture,
|
||||
TextureScale = new Vector2(2, 2),
|
||||
Children =
|
||||
{
|
||||
_backButton,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_sidebar.AddChild(backContainer);
|
||||
}
|
||||
|
||||
var rows = boundingGrid.Height - offset;
|
||||
|
||||
for (var i = 0; i < rows; i++)
|
||||
for (var i = 0; i < boundingGrid.Height - 1; i++)
|
||||
{
|
||||
_sidebar.AddChild(new TextureRect
|
||||
{
|
||||
@@ -304,7 +192,7 @@ public sealed class StorageWindow : BaseWindow
|
||||
});
|
||||
}
|
||||
|
||||
if (rows > 0)
|
||||
if (boundingGrid.Height > 0)
|
||||
{
|
||||
_sidebar.AddChild(new TextureRect
|
||||
{
|
||||
@@ -315,7 +203,7 @@ public sealed class StorageWindow : BaseWindow
|
||||
|
||||
#endregion
|
||||
|
||||
FlagDirty();
|
||||
BuildItemPieces();
|
||||
}
|
||||
|
||||
public void BuildBackground()
|
||||
@@ -352,127 +240,70 @@ public sealed class StorageWindow : BaseWindow
|
||||
}
|
||||
}
|
||||
|
||||
public void Reclaim(ItemStorageLocation location, ItemGridPiece draggingGhost)
|
||||
{
|
||||
draggingGhost.OnPiecePressed += OnPiecePressed;
|
||||
draggingGhost.OnPieceUnpressed += OnPieceUnpressed;
|
||||
_pieces[draggingGhost.Entity] = (location, draggingGhost);
|
||||
draggingGhost.Location = location;
|
||||
var controlIndex = GetGridIndex(draggingGhost);
|
||||
_controlGrid[controlIndex].AddChild(draggingGhost);
|
||||
}
|
||||
|
||||
private int GetGridIndex(ItemGridPiece piece)
|
||||
{
|
||||
return piece.Location.Position.X + piece.Location.Position.Y * _pieceGrid.Columns;
|
||||
}
|
||||
|
||||
public void FlagDirty()
|
||||
{
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
public void RemoveGrid(ItemGridPiece control)
|
||||
{
|
||||
control.Orphan();
|
||||
_pieces.Remove(control.Entity);
|
||||
control.OnPiecePressed -= OnPiecePressed;
|
||||
control.OnPieceUnpressed -= OnPieceUnpressed;
|
||||
}
|
||||
|
||||
public void BuildItemPieces()
|
||||
{
|
||||
if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var storageComp))
|
||||
return;
|
||||
|
||||
if (storageComp.Grid.Count == 0)
|
||||
if (!storageComp.Grid.Any())
|
||||
return;
|
||||
|
||||
var boundingGrid = storageComp.Grid.GetBoundingBox();
|
||||
var size = _emptyTexture!.Size * 2;
|
||||
_contained.Clear();
|
||||
_contained.AddRange(storageComp.Container.ContainedEntities.Reverse());
|
||||
var containedEntities = storageComp.Container.ContainedEntities.Reverse().ToArray();
|
||||
|
||||
// Build the grid representation
|
||||
if (_pieceGrid.Rows - 1 != boundingGrid.Height || _pieceGrid.Columns - 1 != boundingGrid.Width)
|
||||
//todo. at some point, we may want to only rebuild the pieces that have actually received new data.
|
||||
|
||||
_pieceGrid.RemoveAllChildren();
|
||||
_pieceGrid.Rows = boundingGrid.Height + 1;
|
||||
_pieceGrid.Columns = boundingGrid.Width + 1;
|
||||
for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++)
|
||||
{
|
||||
_pieceGrid.Rows = boundingGrid.Height + 1;
|
||||
_pieceGrid.Columns = boundingGrid.Width + 1;
|
||||
_controlGrid.Clear();
|
||||
|
||||
for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++)
|
||||
for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++)
|
||||
{
|
||||
for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++)
|
||||
var control = new Control
|
||||
{
|
||||
var control = new Control
|
||||
{
|
||||
MinSize = size
|
||||
};
|
||||
|
||||
_controlGrid.Add(control);
|
||||
_pieceGrid.AddChild(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_toRemove.Clear();
|
||||
|
||||
// Remove entities no longer relevant / Update existing ones
|
||||
foreach (var (ent, data) in _pieces)
|
||||
{
|
||||
if (storageComp.StoredItems.TryGetValue(ent, out var updated))
|
||||
{
|
||||
if (data.Loc.Equals(updated))
|
||||
{
|
||||
DebugTools.Assert(data.Control.Location == updated);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update
|
||||
data.Control.Location = updated;
|
||||
var index = GetGridIndex(data.Control);
|
||||
data.Control.Orphan();
|
||||
_controlGrid[index].AddChild(data.Control);
|
||||
_pieces[ent] = (updated, data.Control);
|
||||
continue;
|
||||
}
|
||||
|
||||
_toRemove.Add(ent);
|
||||
}
|
||||
|
||||
foreach (var ent in _toRemove)
|
||||
{
|
||||
_pieces.Remove(ent, out var data);
|
||||
data.Control.Orphan();
|
||||
}
|
||||
|
||||
// Add new ones
|
||||
foreach (var (ent, loc) in storageComp.StoredItems)
|
||||
{
|
||||
if (_pieces.TryGetValue(ent, out var existing))
|
||||
{
|
||||
DebugTools.Assert(existing.Loc == loc);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_entity.TryGetComponent<ItemComponent>(ent, out var itemEntComponent))
|
||||
{
|
||||
var gridPiece = new ItemGridPiece((ent, itemEntComponent), loc, _entity)
|
||||
{
|
||||
MinSize = size,
|
||||
Marked = _contained.IndexOf(ent) switch
|
||||
{
|
||||
0 => ItemGridPieceMarks.First,
|
||||
1 => ItemGridPieceMarks.Second,
|
||||
_ => null,
|
||||
}
|
||||
MinSize = size
|
||||
};
|
||||
gridPiece.OnPiecePressed += OnPiecePressed;
|
||||
gridPiece.OnPieceUnpressed += OnPieceUnpressed;
|
||||
var controlIndex = loc.Position.X + loc.Position.Y * (boundingGrid.Width + 1);
|
||||
|
||||
_controlGrid[controlIndex].AddChild(gridPiece);
|
||||
_pieces[ent] = (loc, gridPiece);
|
||||
var currentPosition = new Vector2i(x, y);
|
||||
|
||||
foreach (var (itemEnt, itemPos) in storageComp.StoredItems)
|
||||
{
|
||||
if (itemPos.Position != currentPosition)
|
||||
continue;
|
||||
|
||||
if (_entity.TryGetComponent<ItemComponent>(itemEnt, out var itemEntComponent))
|
||||
{
|
||||
ItemGridPiece gridPiece;
|
||||
|
||||
if (_storageController.CurrentlyDragging?.Entity is { } dragging
|
||||
&& dragging == itemEnt)
|
||||
{
|
||||
_storageController.CurrentlyDragging.Orphan();
|
||||
gridPiece = _storageController.CurrentlyDragging;
|
||||
}
|
||||
else
|
||||
{
|
||||
gridPiece = new ItemGridPiece((itemEnt, itemEntComponent), itemPos, _entity)
|
||||
{
|
||||
MinSize = size,
|
||||
Marked = Array.IndexOf(containedEntities, itemEnt) switch
|
||||
{
|
||||
0 => ItemGridPieceMarks.First,
|
||||
1 => ItemGridPieceMarks.Second,
|
||||
_ => null,
|
||||
}
|
||||
};
|
||||
gridPiece.OnPiecePressed += OnPiecePressed;
|
||||
gridPiece.OnPieceUnpressed += OnPieceUnpressed;
|
||||
}
|
||||
|
||||
control.AddChild(gridPiece);
|
||||
}
|
||||
}
|
||||
|
||||
_pieceGrid.AddChild(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,35 +315,6 @@ public sealed class StorageWindow : BaseWindow
|
||||
if (!IsOpen)
|
||||
return;
|
||||
|
||||
if (_isDirty)
|
||||
{
|
||||
_isDirty = false;
|
||||
BuildItemPieces();
|
||||
}
|
||||
|
||||
var containerSystem = _entity.System<SharedContainerSystem>();
|
||||
|
||||
if (_backButton != null)
|
||||
{
|
||||
if (StorageEntity != null && _entity.System<StorageSystem>().NestedStorage)
|
||||
{
|
||||
if (containerSystem.TryGetContainingContainer(StorageEntity.Value, out var container) &&
|
||||
_entity.HasComponent<StorageComponent>(container.Owner))
|
||||
{
|
||||
_backButton.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_backButton.Visible = false;
|
||||
}
|
||||
}
|
||||
// Hide the button.
|
||||
else
|
||||
{
|
||||
_backButton.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
var itemSystem = _entity.System<ItemSystem>();
|
||||
var storageSystem = _entity.System<StorageSystem>();
|
||||
var handsSystem = _entity.System<HandsSystem>();
|
||||
@@ -522,7 +324,7 @@ public sealed class StorageWindow : BaseWindow
|
||||
child.ModulateSelfOverride = Color.FromHex("#222222");
|
||||
}
|
||||
|
||||
if (UserInterfaceManager.CurrentlyHovered is StorageWindow con && con != this)
|
||||
if (UserInterfaceManager.CurrentlyHovered is StorageContainer con && con != this)
|
||||
return;
|
||||
|
||||
if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var storageComponent))
|
||||
@@ -571,7 +373,7 @@ public sealed class StorageWindow : BaseWindow
|
||||
continue;
|
||||
|
||||
float spot = 0;
|
||||
var marked = new ValueList<Control>();
|
||||
var marked = new List<Control>();
|
||||
|
||||
foreach (var location in locations.Value)
|
||||
{
|
||||
@@ -698,4 +500,14 @@ public sealed class StorageWindow : BaseWindow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
|
||||
if (StorageEntity == null)
|
||||
return;
|
||||
|
||||
_entity.System<StorageSystem>().CloseStorageWindow(StorageEntity.Value);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ using System.Numerics;
|
||||
using Content.Client.Examine;
|
||||
using Content.Client.Hands.Systems;
|
||||
using Content.Client.Interaction;
|
||||
using Content.Client.Storage;
|
||||
using Content.Client.Storage.Systems;
|
||||
using Content.Client.UserInterface.Systems.Hotbar.Widgets;
|
||||
using Content.Client.UserInterface.Systems.Storage.Controls;
|
||||
@@ -10,9 +9,9 @@ using Content.Client.Verbs.UI;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Storage;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
@@ -24,28 +23,19 @@ namespace Content.Client.UserInterface.Systems.Storage;
|
||||
|
||||
public sealed class StorageUIController : UIController, IOnSystemChanged<StorageSystem>
|
||||
{
|
||||
/*
|
||||
* Things are a bit over the shop but essentially
|
||||
* - Clicking into storagewindow is handled via storagewindow
|
||||
* - Clicking out of it is via ItemGridPiece
|
||||
* - Dragging around is handled here
|
||||
* - Drawing is handled via ItemGridPiece
|
||||
* - StorageSystem handles any sim stuff around open windows.
|
||||
*/
|
||||
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IInputManager _input = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[UISystemDependency] private readonly StorageSystem _storage = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Cached positions for opening nested storage.
|
||||
/// </summary>
|
||||
private readonly Dictionary<EntityUid, Vector2> _reservedStorage = new();
|
||||
[Dependency] private readonly IUserInterfaceManager _ui = default!;
|
||||
|
||||
private readonly DragDropHelper<ItemGridPiece> _menuDragHelper;
|
||||
private StorageContainer? _container;
|
||||
|
||||
public ItemGridPiece? DraggingGhost => _menuDragHelper.Dragged;
|
||||
private Vector2? _lastContainerPosition;
|
||||
|
||||
private HotbarGui? Hotbar => UIManager.GetActiveUIWidgetOrNull<HotbarGui>();
|
||||
|
||||
public ItemGridPiece? DraggingGhost;
|
||||
public Angle DraggingRotation = Angle.Zero;
|
||||
public bool StaticStorageUIEnabled;
|
||||
public bool OpaqueStorageWindow;
|
||||
@@ -53,8 +43,6 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
public bool IsDragging => _menuDragHelper.IsDragging;
|
||||
public ItemGridPiece? CurrentlyDragging => _menuDragHelper.Dragged;
|
||||
|
||||
public bool WindowTitle { get; private set; } = false;
|
||||
|
||||
public StorageUIController()
|
||||
{
|
||||
_menuDragHelper = new DragDropHelper<ItemGridPiece>(OnMenuBeginDrag, OnMenuContinueDrag, OnMenuEndDrag);
|
||||
@@ -64,93 +52,106 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
UIManager.OnScreenChanged += OnScreenChange;
|
||||
|
||||
_configuration.OnValueChanged(CCVars.StaticStorageUI, OnStaticStorageChanged, true);
|
||||
_configuration.OnValueChanged(CCVars.OpaqueStorageWindow, OnOpaqueWindowChanged, true);
|
||||
_configuration.OnValueChanged(CCVars.StorageWindowTitle, OnStorageWindowTitle, true);
|
||||
}
|
||||
|
||||
private void OnScreenChange((UIScreen? Old, UIScreen? New) obj)
|
||||
{
|
||||
// Handle reconnects with hotbargui.
|
||||
|
||||
// Essentially HotbarGui / the screen gets loaded AFTER gamestates at the moment (because clientgameticker manually changes it via event)
|
||||
// and changing this may be a massive change.
|
||||
// So instead we'll just manually reload it for now.
|
||||
if (!StaticStorageUIEnabled ||
|
||||
obj.New == null ||
|
||||
!EntityManager.TryGetComponent(_player.LocalEntity, out UserInterfaceUserComponent? userComp))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// UISystemDependency not injected at this point so do it the old fashion way, I love ordering issues.
|
||||
var uiSystem = EntityManager.System<SharedUserInterfaceSystem>();
|
||||
|
||||
foreach (var bui in uiSystem.GetActorUis((_player.LocalEntity.Value, userComp)))
|
||||
{
|
||||
if (!uiSystem.TryGetOpenUi<StorageBoundUserInterface>(bui.Entity, StorageComponent.StorageUiKey.Key, out var storageBui))
|
||||
continue;
|
||||
|
||||
storageBui.ReOpen();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStorageWindowTitle(bool obj)
|
||||
{
|
||||
WindowTitle = obj;
|
||||
}
|
||||
|
||||
private void OnOpaqueWindowChanged(bool obj)
|
||||
{
|
||||
OpaqueStorageWindow = obj;
|
||||
}
|
||||
|
||||
private void OnStaticStorageChanged(bool obj)
|
||||
{
|
||||
StaticStorageUIEnabled = obj;
|
||||
}
|
||||
|
||||
public StorageWindow CreateStorageWindow(EntityUid uid)
|
||||
{
|
||||
var window = new StorageWindow();
|
||||
window.MouseFilter = Control.MouseFilterMode.Pass;
|
||||
|
||||
window.OnPiecePressed += (args, piece) =>
|
||||
{
|
||||
OnPiecePressed(args, window, piece);
|
||||
};
|
||||
window.OnPieceUnpressed += (args, piece) =>
|
||||
{
|
||||
OnPieceUnpressed(args, window, piece);
|
||||
};
|
||||
|
||||
if (StaticStorageUIEnabled)
|
||||
{
|
||||
UIManager.GetActiveUIWidgetOrNull<HotbarGui>()?.StorageContainer.AddChild(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
window.OpenCenteredLeft();
|
||||
|
||||
if (_reservedStorage.Remove(uid, out var pos))
|
||||
{
|
||||
LayoutContainer.SetPosition(window, pos);
|
||||
}
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
public void OnSystemLoaded(StorageSystem system)
|
||||
{
|
||||
_input.FirstChanceOnKeyEvent += OnMiddleMouse;
|
||||
system.StorageUpdated += OnStorageUpdated;
|
||||
system.StorageOrderChanged += OnStorageOrderChanged;
|
||||
}
|
||||
|
||||
public void OnSystemUnloaded(StorageSystem system)
|
||||
{
|
||||
_input.FirstChanceOnKeyEvent -= OnMiddleMouse;
|
||||
system.StorageUpdated -= OnStorageUpdated;
|
||||
system.StorageOrderChanged -= OnStorageOrderChanged;
|
||||
}
|
||||
|
||||
private void OnStorageOrderChanged(Entity<StorageComponent>? nullEnt)
|
||||
{
|
||||
if (_container == null)
|
||||
return;
|
||||
|
||||
if (IsDragging)
|
||||
_menuDragHelper.EndDrag();
|
||||
|
||||
_container.UpdateContainer(nullEnt);
|
||||
|
||||
if (nullEnt is not null)
|
||||
{
|
||||
// center it if we knock it off screen somehow.
|
||||
if (!StaticStorageUIEnabled &&
|
||||
(_lastContainerPosition == null ||
|
||||
_lastContainerPosition.Value.X < 0 ||
|
||||
_lastContainerPosition.Value.Y < 0 ||
|
||||
_lastContainerPosition.Value.X > _ui.WindowRoot.Width ||
|
||||
_lastContainerPosition.Value.Y > _ui.WindowRoot.Height))
|
||||
{
|
||||
_container.OpenCenteredAt(new Vector2(0.5f, 0.75f));
|
||||
}
|
||||
else
|
||||
{
|
||||
_container.Open();
|
||||
|
||||
var pos = !StaticStorageUIEnabled && _lastContainerPosition != null
|
||||
? _lastContainerPosition.Value
|
||||
: Vector2.Zero;
|
||||
|
||||
LayoutContainer.SetPosition(_container, pos);
|
||||
}
|
||||
|
||||
if (StaticStorageUIEnabled)
|
||||
{
|
||||
// we have to orphan it here because Open() sets the parent.
|
||||
_container.Orphan();
|
||||
Hotbar?.StorageContainer.AddChild(_container);
|
||||
}
|
||||
_lastContainerPosition = _container.GlobalPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastContainerPosition = _container.GlobalPosition;
|
||||
_container.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStaticStorageChanged(bool obj)
|
||||
{
|
||||
if (StaticStorageUIEnabled == obj)
|
||||
return;
|
||||
|
||||
StaticStorageUIEnabled = obj;
|
||||
_lastContainerPosition = null;
|
||||
|
||||
if (_container == null)
|
||||
return;
|
||||
|
||||
if (!_container.IsOpen)
|
||||
return;
|
||||
|
||||
_container.Orphan();
|
||||
if (StaticStorageUIEnabled)
|
||||
{
|
||||
Hotbar?.StorageContainer.AddChild(_container);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ui.WindowRoot.AddChild(_container);
|
||||
}
|
||||
|
||||
if (_entity.TryGetComponent<StorageComponent>(_container.StorageEntity, out var comp))
|
||||
OnStorageOrderChanged((_container.StorageEntity.Value, comp));
|
||||
}
|
||||
|
||||
private void OnOpaqueWindowChanged(bool obj)
|
||||
{
|
||||
if (OpaqueStorageWindow == obj)
|
||||
return;
|
||||
OpaqueStorageWindow = obj;
|
||||
_container?.BuildBackground();
|
||||
}
|
||||
|
||||
/// One might ask, Hey Emo, why are you parsing raw keyboard input just to rotate a rectangle?
|
||||
@@ -189,7 +190,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
binding.Mod3 == Keyboard.Key.Control))
|
||||
return;
|
||||
|
||||
if (!IsDragging && EntityManager.System<HandsSystem>().GetActiveHandEntity() == null)
|
||||
if (!IsDragging && _entity.System<HandsSystem>().GetActiveHandEntity() == null)
|
||||
return;
|
||||
|
||||
//clamp it to a cardinal.
|
||||
@@ -197,18 +198,43 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
if (DraggingGhost != null)
|
||||
DraggingGhost.Location.Rotation = DraggingRotation;
|
||||
|
||||
if (IsDragging || UIManager.CurrentlyHovered is StorageWindow)
|
||||
if (IsDragging || (_container != null && UIManager.CurrentlyHovered == _container))
|
||||
keyEvent.Handle();
|
||||
}
|
||||
|
||||
private void OnPiecePressed(GUIBoundKeyEventArgs args, StorageWindow window, ItemGridPiece control)
|
||||
private void OnStorageUpdated(Entity<StorageComponent> uid)
|
||||
{
|
||||
if (IsDragging || !window.IsOpen)
|
||||
if (_container?.StorageEntity != uid)
|
||||
return;
|
||||
|
||||
_container.BuildItemPieces();
|
||||
}
|
||||
|
||||
public void RegisterStorageContainer(StorageContainer container)
|
||||
{
|
||||
if (_container != null)
|
||||
{
|
||||
container.OnPiecePressed -= OnPiecePressed;
|
||||
container.OnPieceUnpressed -= OnPieceUnpressed;
|
||||
}
|
||||
|
||||
_container = container;
|
||||
container.OnPiecePressed += OnPiecePressed;
|
||||
container.OnPieceUnpressed += OnPieceUnpressed;
|
||||
|
||||
if (!StaticStorageUIEnabled)
|
||||
_container.Orphan();
|
||||
}
|
||||
|
||||
private void OnPiecePressed(GUIBoundKeyEventArgs args, ItemGridPiece control)
|
||||
{
|
||||
if (IsDragging || !_container?.IsOpen == true)
|
||||
return;
|
||||
|
||||
if (args.Function == ContentKeyFunctions.MoveStoredItem)
|
||||
{
|
||||
DraggingRotation = control.Location.Rotation;
|
||||
|
||||
_menuDragHelper.MouseDown(control);
|
||||
_menuDragHelper.Update(0f);
|
||||
|
||||
@@ -216,17 +242,17 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
}
|
||||
else if (args.Function == ContentKeyFunctions.SaveItemLocation)
|
||||
{
|
||||
if (window.StorageEntity is not {} storage)
|
||||
if (_container?.StorageEntity is not {} storage)
|
||||
return;
|
||||
|
||||
EntityManager.RaisePredictiveEvent(new StorageSaveItemLocationEvent(
|
||||
EntityManager.GetNetEntity(control.Entity),
|
||||
EntityManager.GetNetEntity(storage)));
|
||||
_entity.RaisePredictiveEvent(new StorageSaveItemLocationEvent(
|
||||
_entity.GetNetEntity(control.Entity),
|
||||
_entity.GetNetEntity(storage)));
|
||||
args.Handle();
|
||||
}
|
||||
else if (args.Function == ContentKeyFunctions.ExamineEntity)
|
||||
{
|
||||
EntityManager.System<ExamineSystem>().DoExamine(control.Entity);
|
||||
_entity.System<ExamineSystem>().DoExamine(control.Entity);
|
||||
args.Handle();
|
||||
}
|
||||
else if (args.Function == EngineKeyFunctions.UseSecondary)
|
||||
@@ -236,102 +262,62 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
}
|
||||
else if (args.Function == ContentKeyFunctions.ActivateItemInWorld)
|
||||
{
|
||||
EntityManager.RaisePredictiveEvent(
|
||||
new InteractInventorySlotEvent(EntityManager.GetNetEntity(control.Entity), altInteract: false));
|
||||
_entity.RaisePredictiveEvent(
|
||||
new InteractInventorySlotEvent(_entity.GetNetEntity(control.Entity), altInteract: false));
|
||||
args.Handle();
|
||||
}
|
||||
else if (args.Function == ContentKeyFunctions.AltActivateItemInWorld)
|
||||
{
|
||||
EntityManager.RaisePredictiveEvent(new InteractInventorySlotEvent(EntityManager.GetNetEntity(control.Entity), altInteract: true));
|
||||
_entity.RaisePredictiveEvent(new InteractInventorySlotEvent(_entity.GetNetEntity(control.Entity), altInteract: true));
|
||||
args.Handle();
|
||||
}
|
||||
|
||||
window.FlagDirty();
|
||||
}
|
||||
|
||||
private void OnPieceUnpressed(GUIBoundKeyEventArgs args, StorageWindow window, ItemGridPiece control)
|
||||
private void OnPieceUnpressed(GUIBoundKeyEventArgs args, ItemGridPiece control)
|
||||
{
|
||||
if (args.Function != ContentKeyFunctions.MoveStoredItem)
|
||||
return;
|
||||
|
||||
// Want to get the control under the dragged control.
|
||||
// This means we can drag the original control around (and not hide the original).
|
||||
control.MouseFilter = Control.MouseFilterMode.Ignore;
|
||||
var targetControl = UIManager.MouseGetControl(args.PointerLocation);
|
||||
var targetStorage = targetControl as StorageWindow;
|
||||
control.MouseFilter = Control.MouseFilterMode.Pass;
|
||||
|
||||
var localPlayer = _player.LocalEntity;
|
||||
window.RemoveGrid(control);
|
||||
window.FlagDirty();
|
||||
|
||||
// If we tried to drag it on top of another grid piece then cancel out.
|
||||
if (targetControl is ItemGridPiece || window.StorageEntity is not { } sourceStorage || localPlayer == null)
|
||||
{
|
||||
window.Reclaim(control.Location, control);
|
||||
args.Handle();
|
||||
_menuDragHelper.EndDrag();
|
||||
if (_container?.StorageEntity is not { } storageEnt|| !_entity.TryGetComponent<StorageComponent>(storageEnt, out var storageComp))
|
||||
return;
|
||||
}
|
||||
|
||||
if (_menuDragHelper.IsDragging && DraggingGhost is { } draggingGhost)
|
||||
if (DraggingGhost is { } draggingGhost)
|
||||
{
|
||||
var dragEnt = draggingGhost.Entity;
|
||||
var dragLoc = draggingGhost.Location;
|
||||
var itemSys = _entity.System<SharedItemSystem>();
|
||||
|
||||
// Dragging in the same storage
|
||||
// The existing ItemGridPiece just stops rendering but still exists so check if it's hovered.
|
||||
if (targetStorage == window)
|
||||
var position = _container.GetMouseGridPieceLocation(dragEnt, dragLoc);
|
||||
var itemBounding = itemSys.GetAdjustedItemShape(dragEnt, dragLoc).GetBoundingBox();
|
||||
var gridBounding = storageComp.Grid.GetBoundingBox();
|
||||
|
||||
// The extended bounding box for if this is out of the window is the grid bounding box dimensions combined
|
||||
// with the item shape bounding box dimensions. Plus 1 on the left for the sidebar. This makes it so that.
|
||||
// dropping an item on the floor requires dragging it all the way out of the window.
|
||||
var left = gridBounding.Left - itemBounding.Width - 1;
|
||||
var bottom = gridBounding.Bottom - itemBounding.Height;
|
||||
var top = gridBounding.Top;
|
||||
var right = gridBounding.Right;
|
||||
var lenientBounding = new Box2i(left, bottom, right, top);
|
||||
|
||||
if (lenientBounding.Contains(position))
|
||||
{
|
||||
var position = targetStorage.GetMouseGridPieceLocation(dragEnt, dragLoc);
|
||||
var newLocation = new ItemStorageLocation(DraggingRotation, position);
|
||||
|
||||
EntityManager.RaisePredictiveEvent(new StorageSetItemLocationEvent(
|
||||
EntityManager.GetNetEntity(draggingGhost.Entity),
|
||||
EntityManager.GetNetEntity(sourceStorage),
|
||||
newLocation));
|
||||
|
||||
window.Reclaim(newLocation, control);
|
||||
}
|
||||
// Dragging to new storage
|
||||
else if (targetStorage?.StorageEntity != null && targetStorage != window)
|
||||
{
|
||||
var position = targetStorage.GetMouseGridPieceLocation(dragEnt, dragLoc);
|
||||
var newLocation = new ItemStorageLocation(DraggingRotation, position);
|
||||
|
||||
// Check it fits and we can move to hand (no free transfers).
|
||||
if (_storage.ItemFitsInGridLocation(
|
||||
(dragEnt, null),
|
||||
(targetStorage.StorageEntity.Value, null),
|
||||
newLocation))
|
||||
{
|
||||
// Can drop and move.
|
||||
EntityManager.RaisePredictiveEvent(new StorageTransferItemEvent(
|
||||
EntityManager.GetNetEntity(dragEnt),
|
||||
EntityManager.GetNetEntity(targetStorage.StorageEntity.Value),
|
||||
newLocation));
|
||||
|
||||
targetStorage.Reclaim(newLocation, control);
|
||||
DraggingRotation = Angle.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cancel it (rather than dropping).
|
||||
window.Reclaim(dragLoc, control);
|
||||
}
|
||||
_entity.RaisePredictiveEvent(new StorageSetItemLocationEvent(
|
||||
_entity.GetNetEntity(draggingGhost.Entity),
|
||||
_entity.GetNetEntity(storageEnt),
|
||||
new ItemStorageLocation(DraggingRotation, position)));
|
||||
}
|
||||
|
||||
targetStorage?.FlagDirty();
|
||||
_menuDragHelper.EndDrag();
|
||||
_container?.BuildItemPieces();
|
||||
}
|
||||
// If we just clicked, then take it out of the bag.
|
||||
else
|
||||
else //if we just clicked, then take it out of the bag.
|
||||
{
|
||||
EntityManager.RaisePredictiveEvent(new StorageInteractWithItemEvent(
|
||||
EntityManager.GetNetEntity(control.Entity),
|
||||
EntityManager.GetNetEntity(sourceStorage)));
|
||||
_menuDragHelper.EndDrag();
|
||||
_entity.RaisePredictiveEvent(new StorageInteractWithItemEvent(
|
||||
_entity.GetNetEntity(control.Entity),
|
||||
_entity.GetNetEntity(storageEnt)));
|
||||
}
|
||||
|
||||
_menuDragHelper.EndDrag();
|
||||
args.Handle();
|
||||
}
|
||||
|
||||
@@ -340,8 +326,14 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
if (_menuDragHelper.Dragged is not { } dragged)
|
||||
return false;
|
||||
|
||||
DraggingGhost!.Orphan();
|
||||
DraggingRotation = dragged.Location.Rotation;
|
||||
DraggingGhost = new ItemGridPiece(
|
||||
(dragged.Entity, _entity.GetComponent<ItemComponent>(dragged.Entity)),
|
||||
dragged.Location,
|
||||
_entity);
|
||||
DraggingGhost.MouseFilter = Control.MouseFilterMode.Ignore;
|
||||
DraggingGhost.Visible = true;
|
||||
DraggingGhost.Orphan();
|
||||
|
||||
UIManager.PopupRoot.AddChild(DraggingGhost);
|
||||
SetDraggingRotation();
|
||||
@@ -352,7 +344,6 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
{
|
||||
if (DraggingGhost == null)
|
||||
return false;
|
||||
|
||||
SetDraggingRotation();
|
||||
return true;
|
||||
}
|
||||
@@ -365,7 +356,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
var offset = ItemGridPiece.GetCenterOffset(
|
||||
(DraggingGhost.Entity, null),
|
||||
new ItemStorageLocation(DraggingRotation, Vector2i.Zero),
|
||||
EntityManager);
|
||||
_entity);
|
||||
|
||||
// I don't know why it divides the position by 2. Hope this helps! -emo
|
||||
LayoutContainer.SetPosition(DraggingGhost, UIManager.MousePositionScaled.Position / 2 - offset );
|
||||
@@ -375,13 +366,18 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
{
|
||||
if (DraggingGhost == null)
|
||||
return;
|
||||
|
||||
DraggingGhost.Visible = false;
|
||||
DraggingGhost = null;
|
||||
DraggingRotation = Angle.Zero;
|
||||
}
|
||||
|
||||
public override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
_menuDragHelper.Update(args.DeltaSeconds);
|
||||
|
||||
if (!StaticStorageUIEnabled && _container?.Parent != null && _lastContainerPosition != null)
|
||||
_lastContainerPosition = _container.GlobalPosition;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user