Files
wwdpublic/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs
DEATHB4DEFEAT 47b10a01b0 Catch-Up Cherry Pick 2 (#944)
# Description

Picked 400 commits (and skipped many, many more) from WizDen since #540.
Stopped at commit 332f54a3aebe669f6e50d26e7b047f0bdc28e0fb (Lobby
Refactor).

---

# TODO

- [x] Pick
- [x] Compile
- [x] Fix runtime errors
- [ ] Fix up humanoid profile editor
- [ ] Test everything

---

# Changelog

🆑
- add: Merged 400 WizDen PRs. Happy testing!

---------

Co-authored-by: Plykiya <58439124+Plykiya@users.noreply.github.com>
Co-authored-by: FungiFellow <151778459+FungiFellow@users.noreply.github.com>
Co-authored-by: osjarw <62134478+osjarw@users.noreply.github.com>
Co-authored-by: Ubaser <134914314+UbaserB@users.noreply.github.com>
Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com>
Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Co-authored-by: Magnus Larsen <i.am.larsenml@gmail.com>
Co-authored-by: Hanz <41141796+Hanzdegloker@users.noreply.github.com>
Co-authored-by: Kukutis96513 <146854220+Kukutis96513@users.noreply.github.com>
Co-authored-by: potato1234_x <79580518+potato1234x@users.noreply.github.com>
Co-authored-by: Gotimanga <127038462+Gotimanga@users.noreply.github.com>
Co-authored-by: Mangohydra <156087924+Mangohydra@users.noreply.github.com>
Co-authored-by: TsjipTsjip <19798667+TsjipTsjip@users.noreply.github.com>
Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com>
Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Co-authored-by: Morb <14136326+Morb0@users.noreply.github.com>
Co-authored-by: MilenVolf <63782763+MilenVolf@users.noreply.github.com>
Co-authored-by: KrasnoshchekovPavel <119816022+KrasnoshchekovPavel@users.noreply.github.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
Co-authored-by: DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: KittenColony <149278380+KittenColony@users.noreply.github.com>
Co-authored-by: ShadowCommander <shadowjjt@gmail.com>
Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
Co-authored-by: T-Stalker <43253663+DogZeroX@users.noreply.github.com>
Co-authored-by: ERROR404 <100093430+ERORR404V1@users.noreply.github.com>
Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>
Co-authored-by: Jezithyr <jezithyr@gmail.com>
Co-authored-by: Psychpsyo <60073468+Psychpsyo@users.noreply.github.com>
Co-authored-by: no <165581243+pissdemon@users.noreply.github.com>
Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com>
Co-authored-by: Ciac32 <aknoxlor@gmail.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: NotSoDana <75203942+NotSoDana@users.noreply.github.com>
Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com>
Co-authored-by: Repo <47093363+Titian3@users.noreply.github.com>
Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
Co-authored-by: nao fujiwara <awkwarddryad@gmail.com>
Co-authored-by: Michael <107807667+Doc-Michael@users.noreply.github.com>
Co-authored-by: Vasilis <vasilis@pikachu.systems>
Co-authored-by: Lamrr <96937466+Lamrr@users.noreply.github.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: Jay <67732946+DuskyJay@users.noreply.github.com>
Co-authored-by: Just-a-Unity-Dev <67359748+Just-a-Unity-Dev@users.noreply.github.com>
Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com>
Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com>
Co-authored-by: Tyzemol <85772526+Tyzemol@users.noreply.github.com>
Co-authored-by: Alzore <140123969+Blackern5000@users.noreply.github.com>
Co-authored-by: Pok <113675512+Pok27@users.noreply.github.com>
Co-authored-by: RumiTiger <154005209+RumiTiger@users.noreply.github.com>
Co-authored-by: Verm <32827189+Vermidia@users.noreply.github.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
Co-authored-by: Killerqu00 <47712032+Killerqu00@users.noreply.github.com>
Co-authored-by: Ty Ashley <42426760+TyAshley@users.noreply.github.com>
Co-authored-by: exincore <me@exin.xyz>
Co-authored-by: 0x6273 <0x40@keemail.me>
Co-authored-by: Kara <lunarautomaton6@gmail.com>
Co-authored-by: Ygg01 <y.laughing.man.y@gmail.com>
Co-authored-by: Łukasz Mędrek <lukasz@lukaszm.xyz>
Co-authored-by: Hannah Giovanna Dawson <karakkaraz@gmail.com>
Co-authored-by: TurboTracker <130304754+TurboTrackerss14@users.noreply.github.com>
Co-authored-by: OnsenCapy <101037138+LGRuthes@users.noreply.github.com>
Co-authored-by: pigeonpeas <147350443+pigeonpeas@users.noreply.github.com>
Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com>
Co-authored-by: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com>
Co-authored-by: Rio <110139251+Riolume@users.noreply.github.com>
Co-authored-by: vorkathbruh <152932728+vorkathbruh@users.noreply.github.com>
Co-authored-by: Sphiral <145869023+SphiraI@users.noreply.github.com>
Co-authored-by: PrPleGoo <PrPleGoo@users.noreply.github.com>
Co-authored-by: Moomoobeef <62638182+Moomoobeef@users.noreply.github.com>
Co-authored-by: username <113782077+whateverusername0@users.noreply.github.com>
Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com>
Co-authored-by: Джексон Миссиссиппи <tripwiregamer@gmail.com>
Co-authored-by: Brandon Li <48413902+aspiringLich@users.noreply.github.com>
Co-authored-by: Jajsha <101492056+Zap527@users.noreply.github.com>
Co-authored-by: RiceMar1244 <138547931+RiceMar1244@users.noreply.github.com>
Co-authored-by: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com>
Co-authored-by: youtissoum <51883137+youtissoum@users.noreply.github.com>
Co-authored-by: ike709 <ike709@users.noreply.github.com>
Co-authored-by: icekot8 <93311212+icekot8@users.noreply.github.com>
Co-authored-by: keronshb <54602815+keronshb@users.noreply.github.com>
Co-authored-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: Geekyhobo <66805063+Geekyhobo@users.noreply.github.com>
Co-authored-by: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com>
# Conflicts:
#	Content.Client/Input/ContentContexts.cs
#	Content.Client/Lobby/LobbyState.cs
#	Content.Client/Lobby/UI/HumanoidProfileEditor.xaml
#	Content.Client/Lobby/UI/LobbyGui.xaml
#	Content.Client/Lobby/UI/LobbyGui.xaml.cs
#	Content.Client/Preferences/UI/CharacterSetupGui.xaml.cs
#	Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml
#	Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
#	Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs
#	Content.Server/GameTicking/GameTicker.Spawning.cs
#	Content.Shared/Alert/AlertType.cs
#	Content.Shared/Input/ContentKeyFunctions.cs
#	Content.Shared/Preferences/HumanoidCharacterProfile.cs
#	Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs
#	Resources/ConfigPresets/EinsteinEngines/default.toml
#	Resources/Prototypes/Alerts/alerts.yml
#	Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml
#	Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml
#	Resources/Prototypes/Entities/Clothing/Uniforms/jumpskirts.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/makeshiftstunprod.yml
#	Resources/Prototypes/Voice/speech_emotes.yml
#	Resources/keybinds.yml
2024-10-19 14:53:37 +07:00

389 lines
13 KiB
C#

using System.Numerics;
using Content.Client.Examine;
using Content.Client.Hands.Systems;
using Content.Client.Interaction;
using Content.Client.Storage.Systems;
using Content.Client.UserInterface.Systems.Hotbar.Widgets;
using Content.Client.UserInterface.Systems.Storage.Controls;
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.UserInterface;
using Robust.Client.UserInterface.Controllers;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
using Robust.Shared.Input;
using Robust.Shared.Timing;
namespace Content.Client.UserInterface.Systems.Storage;
public sealed class StorageUIController : UIController, IOnSystemChanged<StorageSystem>
{
[Dependency] private readonly IConfigurationManager _configuration = default!;
[Dependency] private readonly IEntityManager _entity = default!;
[Dependency] private readonly IInputManager _input = default!;
[Dependency] private readonly IUserInterfaceManager _ui = default!;
private readonly DragDropHelper<ItemGridPiece> _menuDragHelper;
private StorageContainer? _container;
private Vector2? _lastContainerPosition;
private HotbarGui? Hotbar => UIManager.GetActiveUIWidgetOrNull<HotbarGui>();
public ItemGridPiece? DraggingGhost;
public Angle DraggingRotation = Angle.Zero;
public bool StaticStorageUIEnabled;
public bool OpaqueStorageWindow;
public bool IsDragging => _menuDragHelper.IsDragging;
public ItemGridPiece? CurrentlyDragging => _menuDragHelper.Dragged;
public StorageUIController()
{
_menuDragHelper = new DragDropHelper<ItemGridPiece>(OnMenuBeginDrag, OnMenuContinueDrag, OnMenuEndDrag);
}
public override void Initialize()
{
base.Initialize();
_configuration.OnValueChanged(CCVars.StaticStorageUI, OnStaticStorageChanged, true);
_configuration.OnValueChanged(CCVars.OpaqueStorageWindow, OnOpaqueWindowChanged, true);
}
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?
/// The answer is, that input bindings regarding mouse inputs are always intercepted by the UI,
/// thus, if i want to be able to rotate my damn piece anywhere on the screen,
/// I have to side-step all of the input handling. Cheers.
private void OnMiddleMouse(KeyEventArgs keyEvent, KeyEventType type)
{
if (keyEvent.Handled)
return;
if (type != KeyEventType.Down)
return;
//todo there's gotta be a method for this in InputManager just expose it to content I BEG.
if (!_input.TryGetKeyBinding(ContentKeyFunctions.RotateStoredItem, out var binding))
return;
if (binding.BaseKey != keyEvent.Key)
return;
if (keyEvent.Shift &&
!(binding.Mod1 == Keyboard.Key.Shift ||
binding.Mod2 == Keyboard.Key.Shift ||
binding.Mod3 == Keyboard.Key.Shift))
return;
if (keyEvent.Alt &&
!(binding.Mod1 == Keyboard.Key.Alt ||
binding.Mod2 == Keyboard.Key.Alt ||
binding.Mod3 == Keyboard.Key.Alt))
return;
if (keyEvent.Control &&
!(binding.Mod1 == Keyboard.Key.Control ||
binding.Mod2 == Keyboard.Key.Control ||
binding.Mod3 == Keyboard.Key.Control))
return;
if (!IsDragging && _entity.System<HandsSystem>().GetActiveHandEntity() == null)
return;
//clamp it to a cardinal.
DraggingRotation = (DraggingRotation + Math.PI / 2f).GetCardinalDir().ToAngle();
if (DraggingGhost != null)
DraggingGhost.Location.Rotation = DraggingRotation;
if (IsDragging || (_container != null && UIManager.CurrentlyHovered == _container))
keyEvent.Handle();
}
private void OnStorageUpdated(Entity<StorageComponent> uid)
{
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);
args.Handle();
}
else if (args.Function == ContentKeyFunctions.SaveItemLocation)
{
if (_container?.StorageEntity is not {} storage)
return;
_entity.RaisePredictiveEvent(new StorageSaveItemLocationEvent(
_entity.GetNetEntity(control.Entity),
_entity.GetNetEntity(storage)));
args.Handle();
}
else if (args.Function == ContentKeyFunctions.ExamineEntity)
{
_entity.System<ExamineSystem>().DoExamine(control.Entity);
args.Handle();
}
else if (args.Function == EngineKeyFunctions.UseSecondary)
{
UIManager.GetUIController<VerbMenuUIController>().OpenVerbMenu(control.Entity);
args.Handle();
}
else if (args.Function == ContentKeyFunctions.ActivateItemInWorld)
{
_entity.RaisePredictiveEvent(
new InteractInventorySlotEvent(_entity.GetNetEntity(control.Entity), altInteract: false));
args.Handle();
}
else if (args.Function == ContentKeyFunctions.AltActivateItemInWorld)
{
_entity.RaisePredictiveEvent(new InteractInventorySlotEvent(_entity.GetNetEntity(control.Entity), altInteract: true));
args.Handle();
}
}
private void OnPieceUnpressed(GUIBoundKeyEventArgs args, ItemGridPiece control)
{
if (args.Function != ContentKeyFunctions.MoveStoredItem)
return;
if (_container?.StorageEntity is not { } storageEnt|| !_entity.TryGetComponent<StorageComponent>(storageEnt, out var storageComp))
return;
if (DraggingGhost is { } draggingGhost)
{
var dragEnt = draggingGhost.Entity;
var dragLoc = draggingGhost.Location;
var itemSys = _entity.System<SharedItemSystem>();
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))
{
_entity.RaisePredictiveEvent(new StorageSetItemLocationEvent(
_entity.GetNetEntity(draggingGhost.Entity),
_entity.GetNetEntity(storageEnt),
new ItemStorageLocation(DraggingRotation, position)));
}
else
{
_entity.RaisePredictiveEvent(new StorageRemoveItemEvent(
_entity.GetNetEntity(draggingGhost.Entity),
_entity.GetNetEntity(storageEnt)));
}
_container?.BuildItemPieces();
}
else //if we just clicked, then take it out of the bag.
{
_entity.RaisePredictiveEvent(new StorageInteractWithItemEvent(
_entity.GetNetEntity(control.Entity),
_entity.GetNetEntity(storageEnt)));
}
_menuDragHelper.EndDrag();
args.Handle();
}
private bool OnMenuBeginDrag()
{
if (_menuDragHelper.Dragged is not { } dragged)
return false;
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();
return true;
}
private bool OnMenuContinueDrag(float frameTime)
{
if (DraggingGhost == null)
return false;
SetDraggingRotation();
return true;
}
private void SetDraggingRotation()
{
if (DraggingGhost == null)
return;
var offset = ItemGridPiece.GetCenterOffset(
(DraggingGhost.Entity, null),
new ItemStorageLocation(DraggingRotation, Vector2i.Zero),
_entity);
// I don't know why it divides the position by 2. Hope this helps! -emo
LayoutContainer.SetPosition(DraggingGhost, UIManager.MousePositionScaled.Position / 2 - offset );
}
private void OnMenuEndDrag()
{
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;
}
}