StorageWindow.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. using System.Diagnostics.CodeAnalysis;
  2. using System.Linq;
  3. using System.Numerics;
  4. using Content.Client.Hands.Systems;
  5. using Content.Client.Items.Systems;
  6. using Content.Client.Storage;
  7. using Content.Client.Storage.Systems;
  8. using Content.Shared.IdentityManagement;
  9. using Content.Shared.Input;
  10. using Content.Shared.Item;
  11. using Content.Shared.Storage;
  12. using Robust.Client.GameObjects;
  13. using Robust.Client.Graphics;
  14. using Robust.Client.UserInterface;
  15. using Robust.Client.UserInterface.Controls;
  16. using Robust.Client.UserInterface.CustomControls;
  17. using Robust.Shared.Collections;
  18. using Robust.Shared.Containers;
  19. using Robust.Shared.Timing;
  20. using Robust.Shared.Utility;
  21. namespace Content.Client.UserInterface.Systems.Storage.Controls;
  22. public sealed class StorageWindow : BaseWindow
  23. {
  24. [Dependency] private readonly IEntityManager _entity = default!;
  25. private readonly StorageUIController _storageController;
  26. public EntityUid? StorageEntity;
  27. private readonly GridContainer _pieceGrid;
  28. private readonly GridContainer _backgroundGrid;
  29. private readonly GridContainer _sidebar;
  30. private Control _titleContainer;
  31. private Label _titleLabel;
  32. // Needs to be nullable in case a piece is in default spot.
  33. private readonly Dictionary<EntityUid, (ItemStorageLocation? Loc, ItemGridPiece Control)> _pieces = new();
  34. private readonly List<Control> _controlGrid = new();
  35. private ValueList<EntityUid> _contained = new();
  36. private ValueList<EntityUid> _toRemove = new();
  37. private TextureButton? _backButton;
  38. private bool _isDirty;
  39. public event Action<GUIBoundKeyEventArgs, ItemGridPiece>? OnPiecePressed;
  40. public event Action<GUIBoundKeyEventArgs, ItemGridPiece>? OnPieceUnpressed;
  41. private readonly string _emptyTexturePath = "Storage/tile_empty";
  42. private Texture? _emptyTexture;
  43. private readonly string _blockedTexturePath = "Storage/tile_blocked";
  44. private Texture? _blockedTexture;
  45. private readonly string _emptyOpaqueTexturePath = "Storage/tile_empty_opaque";
  46. private Texture? _emptyOpaqueTexture;
  47. private readonly string _blockedOpaqueTexturePath = "Storage/tile_blocked_opaque";
  48. private Texture? _blockedOpaqueTexture;
  49. private readonly string _exitTexturePath = "Storage/exit";
  50. private Texture? _exitTexture;
  51. private readonly string _backTexturePath = "Storage/back";
  52. private Texture? _backTexture;
  53. private readonly string _sidebarTopTexturePath = "Storage/sidebar_top";
  54. private Texture? _sidebarTopTexture;
  55. private readonly string _sidebarMiddleTexturePath = "Storage/sidebar_mid";
  56. private Texture? _sidebarMiddleTexture;
  57. private readonly string _sidebarBottomTexturePath = "Storage/sidebar_bottom";
  58. private Texture? _sidebarBottomTexture;
  59. private readonly string _sidebarFatTexturePath = "Storage/sidebar_fat";
  60. private Texture? _sidebarFatTexture;
  61. public StorageWindow()
  62. {
  63. IoCManager.InjectDependencies(this);
  64. Resizable = false;
  65. _storageController = UserInterfaceManager.GetUIController<StorageUIController>();
  66. OnThemeUpdated();
  67. MouseFilter = MouseFilterMode.Stop;
  68. _sidebar = new GridContainer
  69. {
  70. Name = "SideBar",
  71. HSeparationOverride = 0,
  72. VSeparationOverride = 0,
  73. Columns = 1
  74. };
  75. _pieceGrid = new GridContainer
  76. {
  77. Name = "PieceGrid",
  78. HSeparationOverride = 0,
  79. VSeparationOverride = 0
  80. };
  81. _backgroundGrid = new GridContainer
  82. {
  83. Name = "BackgroundGrid",
  84. HSeparationOverride = 0,
  85. VSeparationOverride = 0
  86. };
  87. _titleLabel = new Label()
  88. {
  89. HorizontalExpand = true,
  90. Name = "StorageLabel",
  91. ClipText = true,
  92. Text = "Dummy",
  93. StyleClasses =
  94. {
  95. "FancyWindowTitle",
  96. }
  97. };
  98. _titleContainer = new PanelContainer()
  99. {
  100. StyleClasses =
  101. {
  102. "WindowHeadingBackground"
  103. },
  104. Children =
  105. {
  106. _titleLabel
  107. }
  108. };
  109. var container = new BoxContainer
  110. {
  111. Orientation = BoxContainer.LayoutOrientation.Vertical,
  112. Children =
  113. {
  114. _titleContainer,
  115. new BoxContainer
  116. {
  117. Orientation = BoxContainer.LayoutOrientation.Horizontal,
  118. Children =
  119. {
  120. _sidebar,
  121. new Control
  122. {
  123. Children =
  124. {
  125. _backgroundGrid,
  126. _pieceGrid
  127. }
  128. }
  129. }
  130. }
  131. }
  132. };
  133. AddChild(container);
  134. }
  135. protected override void OnThemeUpdated()
  136. {
  137. base.OnThemeUpdated();
  138. _emptyTexture = Theme.ResolveTextureOrNull(_emptyTexturePath)?.Texture;
  139. _blockedTexture = Theme.ResolveTextureOrNull(_blockedTexturePath)?.Texture;
  140. _emptyOpaqueTexture = Theme.ResolveTextureOrNull(_emptyOpaqueTexturePath)?.Texture;
  141. _blockedOpaqueTexture = Theme.ResolveTextureOrNull(_blockedOpaqueTexturePath)?.Texture;
  142. _exitTexture = Theme.ResolveTextureOrNull(_exitTexturePath)?.Texture;
  143. _backTexture = Theme.ResolveTextureOrNull(_backTexturePath)?.Texture;
  144. _sidebarTopTexture = Theme.ResolveTextureOrNull(_sidebarTopTexturePath)?.Texture;
  145. _sidebarMiddleTexture = Theme.ResolveTextureOrNull(_sidebarMiddleTexturePath)?.Texture;
  146. _sidebarBottomTexture = Theme.ResolveTextureOrNull(_sidebarBottomTexturePath)?.Texture;
  147. _sidebarFatTexture = Theme.ResolveTextureOrNull(_sidebarFatTexturePath)?.Texture;
  148. }
  149. public void UpdateContainer(Entity<StorageComponent>? entity)
  150. {
  151. Visible = entity != null;
  152. StorageEntity = entity;
  153. if (entity == null)
  154. return;
  155. if (UserInterfaceManager.GetUIController<StorageUIController>().WindowTitle)
  156. {
  157. _titleLabel.Text = Identity.Name(entity.Value, _entity);
  158. _titleContainer.Visible = true;
  159. }
  160. else
  161. {
  162. _titleContainer.Visible = false;
  163. }
  164. BuildGridRepresentation();
  165. }
  166. private void CloseParent()
  167. {
  168. if (StorageEntity == null)
  169. return;
  170. var containerSystem = _entity.System<SharedContainerSystem>();
  171. var uiSystem = _entity.System<UserInterfaceSystem>();
  172. if (containerSystem.TryGetContainingContainer(StorageEntity.Value, out var container) &&
  173. _entity.TryGetComponent(container.Owner, out StorageComponent? storage) &&
  174. storage.Container.Contains(StorageEntity.Value) &&
  175. uiSystem
  176. .TryGetOpenUi<StorageBoundUserInterface>(container.Owner,
  177. StorageComponent.StorageUiKey.Key,
  178. out var parentBui))
  179. {
  180. parentBui.CloseWindow(Position);
  181. }
  182. }
  183. private void BuildGridRepresentation()
  184. {
  185. if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var comp) || comp.Grid.Count == 0)
  186. return;
  187. var boundingGrid = comp.Grid.GetBoundingBox();
  188. BuildBackground();
  189. #region Sidebar
  190. _sidebar.Children.Clear();
  191. var rows = boundingGrid.Height + 1;
  192. _sidebar.Rows = rows;
  193. var exitButton = new TextureButton
  194. {
  195. Name = "ExitButton",
  196. TextureNormal = _exitTexture,
  197. Scale = new Vector2(2, 2),
  198. };
  199. exitButton.OnPressed += _ =>
  200. {
  201. // Close ourselves and all parent BUIs.
  202. Close();
  203. CloseParent();
  204. };
  205. exitButton.OnKeyBindDown += args =>
  206. {
  207. // it just makes sense...
  208. if (!args.Handled && args.Function == ContentKeyFunctions.ActivateItemInWorld)
  209. {
  210. Close();
  211. CloseParent();
  212. args.Handle();
  213. }
  214. };
  215. var exitContainer = new BoxContainer
  216. {
  217. Name = "ExitContainer",
  218. Children =
  219. {
  220. new TextureRect
  221. {
  222. Texture = boundingGrid.Height != 0
  223. ? _sidebarTopTexture
  224. : _sidebarFatTexture,
  225. TextureScale = new Vector2(2, 2),
  226. Children =
  227. {
  228. exitButton
  229. }
  230. }
  231. }
  232. };
  233. _sidebar.AddChild(exitContainer);
  234. var offset = 2;
  235. if (_entity.System<StorageSystem>().NestedStorage && rows > 0)
  236. {
  237. _backButton = new TextureButton
  238. {
  239. TextureNormal = _backTexture,
  240. Scale = new Vector2(2, 2),
  241. };
  242. _backButton.OnPressed += _ =>
  243. {
  244. var containerSystem = _entity.System<SharedContainerSystem>();
  245. if (containerSystem.TryGetContainingContainer(StorageEntity.Value, out var container) &&
  246. _entity.TryGetComponent(container.Owner, out StorageComponent? storage) &&
  247. storage.Container.Contains(StorageEntity.Value))
  248. {
  249. Close();
  250. if (_entity.System<SharedUserInterfaceSystem>()
  251. .TryGetOpenUi<StorageBoundUserInterface>(container.Owner,
  252. StorageComponent.StorageUiKey.Key,
  253. out var parentBui))
  254. {
  255. parentBui.Show(Position);
  256. }
  257. }
  258. };
  259. var backContainer = new BoxContainer
  260. {
  261. Name = "ExitContainer",
  262. Children =
  263. {
  264. new TextureRect
  265. {
  266. Texture = rows > 2 ? _sidebarMiddleTexture : _sidebarBottomTexture,
  267. TextureScale = new Vector2(2, 2),
  268. Children =
  269. {
  270. _backButton,
  271. }
  272. }
  273. }
  274. };
  275. _sidebar.AddChild(backContainer);
  276. }
  277. var fillerRows = rows - offset;
  278. for (var i = 0; i < fillerRows; i++)
  279. {
  280. _sidebar.AddChild(new TextureRect
  281. {
  282. Texture = i != (fillerRows - 1) ? _sidebarMiddleTexture : _sidebarBottomTexture,
  283. TextureScale = new Vector2(2, 2),
  284. });
  285. }
  286. #endregion
  287. FlagDirty();
  288. }
  289. public void BuildBackground()
  290. {
  291. if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var comp) || !comp.Grid.Any())
  292. return;
  293. var boundingGrid = comp.Grid.GetBoundingBox();
  294. var emptyTexture = _storageController.OpaqueStorageWindow
  295. ? _emptyOpaqueTexture
  296. : _emptyTexture;
  297. var blockedTexture = _storageController.OpaqueStorageWindow
  298. ? _blockedOpaqueTexture
  299. : _blockedTexture;
  300. _backgroundGrid.Children.Clear();
  301. _backgroundGrid.Rows = boundingGrid.Height + 1;
  302. _backgroundGrid.Columns = boundingGrid.Width + 1;
  303. for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++)
  304. {
  305. for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++)
  306. {
  307. var texture = comp.Grid.Contains(x, y)
  308. ? emptyTexture
  309. : blockedTexture;
  310. _backgroundGrid.AddChild(new TextureRect
  311. {
  312. Texture = texture,
  313. TextureScale = new Vector2(2, 2)
  314. });
  315. }
  316. }
  317. }
  318. public void Reclaim(ItemStorageLocation location, ItemGridPiece draggingGhost)
  319. {
  320. draggingGhost.OnPiecePressed += OnPiecePressed;
  321. draggingGhost.OnPieceUnpressed += OnPieceUnpressed;
  322. _pieces[draggingGhost.Entity] = (location, draggingGhost);
  323. draggingGhost.Location = location;
  324. var controlIndex = GetGridIndex(draggingGhost);
  325. _controlGrid[controlIndex].AddChild(draggingGhost);
  326. }
  327. private int GetGridIndex(ItemGridPiece piece)
  328. {
  329. return piece.Location.Position.X + piece.Location.Position.Y * _pieceGrid.Columns;
  330. }
  331. public void FlagDirty()
  332. {
  333. _isDirty = true;
  334. }
  335. public void RemoveGrid(ItemGridPiece control)
  336. {
  337. control.Orphan();
  338. _pieces.Remove(control.Entity);
  339. control.OnPiecePressed -= OnPiecePressed;
  340. control.OnPieceUnpressed -= OnPieceUnpressed;
  341. }
  342. public void BuildItemPieces()
  343. {
  344. if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var storageComp))
  345. return;
  346. if (storageComp.Grid.Count == 0)
  347. return;
  348. var boundingGrid = storageComp.Grid.GetBoundingBox();
  349. var size = _emptyTexture!.Size * 2;
  350. _contained.Clear();
  351. _contained.AddRange(storageComp.Container.ContainedEntities.Reverse());
  352. // Build the grid representation
  353. if (_pieceGrid.Rows - 1 != boundingGrid.Height || _pieceGrid.Columns - 1 != boundingGrid.Width)
  354. {
  355. _pieceGrid.Rows = boundingGrid.Height + 1;
  356. _pieceGrid.Columns = boundingGrid.Width + 1;
  357. _controlGrid.Clear();
  358. for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++)
  359. {
  360. for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++)
  361. {
  362. var control = new Control
  363. {
  364. MinSize = size
  365. };
  366. _controlGrid.Add(control);
  367. _pieceGrid.AddChild(control);
  368. }
  369. }
  370. }
  371. _toRemove.Clear();
  372. // Remove entities no longer relevant / Update existing ones
  373. foreach (var (ent, data) in _pieces)
  374. {
  375. if (storageComp.StoredItems.TryGetValue(ent, out var updated))
  376. {
  377. data.Control.Marked = IsMarked(ent);
  378. if (data.Loc.Equals(updated))
  379. {
  380. DebugTools.Assert(data.Control.Location == updated);
  381. continue;
  382. }
  383. // Update
  384. data.Control.Location = updated;
  385. var index = GetGridIndex(data.Control);
  386. data.Control.Orphan();
  387. _controlGrid[index].AddChild(data.Control);
  388. _pieces[ent] = (updated, data.Control);
  389. continue;
  390. }
  391. _toRemove.Add(ent);
  392. }
  393. foreach (var ent in _toRemove)
  394. {
  395. _pieces.Remove(ent, out var data);
  396. data.Control.Orphan();
  397. }
  398. // Add new ones
  399. foreach (var (ent, loc) in storageComp.StoredItems)
  400. {
  401. if (_pieces.TryGetValue(ent, out var existing))
  402. {
  403. DebugTools.Assert(existing.Loc == loc);
  404. continue;
  405. }
  406. if (_entity.TryGetComponent<ItemComponent>(ent, out var itemEntComponent))
  407. {
  408. var gridPiece = new ItemGridPiece((ent, itemEntComponent), loc, _entity)
  409. {
  410. MinSize = size,
  411. Marked = IsMarked(ent),
  412. };
  413. gridPiece.OnPiecePressed += OnPiecePressed;
  414. gridPiece.OnPieceUnpressed += OnPieceUnpressed;
  415. var controlIndex = loc.Position.X + loc.Position.Y * (boundingGrid.Width + 1);
  416. _controlGrid[controlIndex].AddChild(gridPiece);
  417. _pieces[ent] = (loc, gridPiece);
  418. }
  419. }
  420. }
  421. private ItemGridPieceMarks? IsMarked(EntityUid uid)
  422. {
  423. return _contained.IndexOf(uid) switch
  424. {
  425. 0 => ItemGridPieceMarks.First,
  426. 1 => ItemGridPieceMarks.Second,
  427. _ => null,
  428. };
  429. }
  430. protected override void FrameUpdate(FrameEventArgs args)
  431. {
  432. base.FrameUpdate(args);
  433. if (!IsOpen)
  434. return;
  435. if (_isDirty)
  436. {
  437. _isDirty = false;
  438. BuildItemPieces();
  439. }
  440. var containerSystem = _entity.System<SharedContainerSystem>();
  441. if (_backButton != null)
  442. {
  443. if (StorageEntity != null && _entity.System<StorageSystem>().NestedStorage)
  444. {
  445. // If parent container nests us then show back button
  446. if (containerSystem.TryGetContainingContainer(StorageEntity.Value, out var container) &&
  447. _entity.TryGetComponent(container.Owner, out StorageComponent? storageComp) && storageComp.Container.Contains(StorageEntity.Value))
  448. {
  449. _backButton.Visible = true;
  450. }
  451. else
  452. {
  453. _backButton.Visible = false;
  454. }
  455. }
  456. // Hide the button.
  457. else
  458. {
  459. _backButton.Visible = false;
  460. }
  461. }
  462. var itemSystem = _entity.System<ItemSystem>();
  463. var storageSystem = _entity.System<StorageSystem>();
  464. var handsSystem = _entity.System<HandsSystem>();
  465. foreach (var child in _backgroundGrid.Children)
  466. {
  467. child.ModulateSelfOverride = Color.FromHex("#222222");
  468. }
  469. if (UserInterfaceManager.CurrentlyHovered is StorageWindow con && con != this)
  470. return;
  471. if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var storageComponent))
  472. return;
  473. EntityUid currentEnt;
  474. ItemStorageLocation currentLocation;
  475. var usingInHand = false;
  476. if (_storageController.IsDragging && _storageController.DraggingGhost is { } dragging)
  477. {
  478. currentEnt = dragging.Entity;
  479. currentLocation = dragging.Location;
  480. }
  481. else if (handsSystem.GetActiveHandEntity() is { } handEntity &&
  482. storageSystem.CanInsert(StorageEntity.Value, handEntity, out _, storageComp: storageComponent, ignoreLocation: true))
  483. {
  484. currentEnt = handEntity;
  485. currentLocation = new ItemStorageLocation(_storageController.DraggingRotation, Vector2i.Zero);
  486. usingInHand = true;
  487. }
  488. else
  489. {
  490. return;
  491. }
  492. if (!_entity.TryGetComponent<ItemComponent>(currentEnt, out var itemComp))
  493. return;
  494. var origin = GetMouseGridPieceLocation((currentEnt, itemComp), currentLocation);
  495. var itemShape = itemSystem.GetAdjustedItemShape(
  496. (currentEnt, itemComp),
  497. currentLocation.Rotation,
  498. origin);
  499. var itemBounding = itemShape.GetBoundingBox();
  500. var validLocation = storageSystem.ItemFitsInGridLocation(
  501. (currentEnt, itemComp),
  502. (StorageEntity.Value, storageComponent),
  503. origin,
  504. currentLocation.Rotation);
  505. foreach (var locations in storageComponent.SavedLocations)
  506. {
  507. if (!_entity.TryGetComponent<MetaDataComponent>(currentEnt, out var meta) || meta.EntityName != locations.Key)
  508. continue;
  509. float spot = 0;
  510. var marked = new ValueList<Control>();
  511. foreach (var location in locations.Value)
  512. {
  513. var shape = itemSystem.GetAdjustedItemShape(currentEnt, location);
  514. var bound = shape.GetBoundingBox();
  515. var spotFree = storageSystem.ItemFitsInGridLocation(currentEnt, StorageEntity.Value, location);
  516. if (spotFree)
  517. spot++;
  518. for (var y = bound.Bottom; y <= bound.Top; y++)
  519. {
  520. for (var x = bound.Left; x <= bound.Right; x++)
  521. {
  522. if (TryGetBackgroundCell(x, y, out var cell) && shape.Contains(x, y) && !marked.Contains(cell))
  523. {
  524. marked.Add(cell);
  525. cell.ModulateSelfOverride = spotFree
  526. ? Color.FromHsv((0.18f, 1 / spot, 0.5f / spot + 0.5f, 1f))
  527. : Color.FromHex("#2222CC");
  528. }
  529. }
  530. }
  531. }
  532. }
  533. var validColor = usingInHand ? Color.Goldenrod : Color.FromHex("#1E8000");
  534. for (var y = itemBounding.Bottom; y <= itemBounding.Top; y++)
  535. {
  536. for (var x = itemBounding.Left; x <= itemBounding.Right; x++)
  537. {
  538. if (TryGetBackgroundCell(x, y, out var cell) && itemShape.Contains(x, y))
  539. {
  540. cell.ModulateSelfOverride = validLocation ? validColor : Color.FromHex("#B40046");
  541. }
  542. }
  543. }
  544. }
  545. protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
  546. {
  547. if (_storageController.StaticStorageUIEnabled)
  548. return DragMode.None;
  549. if (_sidebar.SizeBox.Contains(relativeMousePos - _sidebar.Position))
  550. {
  551. return DragMode.Move;
  552. }
  553. return DragMode.None;
  554. }
  555. public Vector2i GetMouseGridPieceLocation(Entity<ItemComponent?> entity, ItemStorageLocation location)
  556. {
  557. var origin = Vector2i.Zero;
  558. if (StorageEntity != null)
  559. origin = _entity.GetComponent<StorageComponent>(StorageEntity.Value).Grid.GetBoundingBox().BottomLeft;
  560. var textureSize = (Vector2) _emptyTexture!.Size * 2;
  561. var position = ((UserInterfaceManager.MousePositionScaled.Position
  562. - _backgroundGrid.GlobalPosition
  563. - ItemGridPiece.GetCenterOffset(entity, location, _entity) * 2
  564. + textureSize / 2f)
  565. / textureSize).Floored() + origin;
  566. return position;
  567. }
  568. public bool TryGetBackgroundCell(int x, int y, [NotNullWhen(true)] out Control? cell)
  569. {
  570. cell = null;
  571. if (!_entity.TryGetComponent<StorageComponent>(StorageEntity, out var storageComponent))
  572. return false;
  573. var boundingBox = storageComponent.Grid.GetBoundingBox();
  574. x -= boundingBox.Left;
  575. y -= boundingBox.Bottom;
  576. if (x < 0 ||
  577. x >= _backgroundGrid.Columns ||
  578. y < 0 ||
  579. y >= _backgroundGrid.Rows)
  580. {
  581. return false;
  582. }
  583. cell = _backgroundGrid.GetChild(y * _backgroundGrid.Columns + x);
  584. return true;
  585. }
  586. protected override void KeyBindDown(GUIBoundKeyEventArgs args)
  587. {
  588. base.KeyBindDown(args);
  589. if (!IsOpen)
  590. return;
  591. var storageSystem = _entity.System<StorageSystem>();
  592. var handsSystem = _entity.System<HandsSystem>();
  593. if (args.Function == ContentKeyFunctions.MoveStoredItem && StorageEntity != null)
  594. {
  595. if (handsSystem.GetActiveHandEntity() is { } handEntity &&
  596. storageSystem.CanInsert(StorageEntity.Value, handEntity, out _))
  597. {
  598. var pos = GetMouseGridPieceLocation((handEntity, null),
  599. new ItemStorageLocation(_storageController.DraggingRotation, Vector2i.Zero));
  600. var insertLocation = new ItemStorageLocation(_storageController.DraggingRotation, pos);
  601. if (storageSystem.ItemFitsInGridLocation(
  602. (handEntity, null),
  603. (StorageEntity.Value, null),
  604. insertLocation))
  605. {
  606. _entity.RaisePredictiveEvent(new StorageInsertItemIntoLocationEvent(
  607. _entity.GetNetEntity(handEntity),
  608. _entity.GetNetEntity(StorageEntity.Value),
  609. insertLocation));
  610. _storageController.DraggingRotation = Angle.Zero;
  611. args.Handle();
  612. }
  613. }
  614. }
  615. }
  616. }