mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-13 12:21:11 +03:00
Signed-off-by: Prole <172158352+Prole0@users.noreply.github.com> Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Co-authored-by: Samuka-C <47865393+Samuka-C@users.noreply.github.com> Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> Co-authored-by: Partmedia <kevinz5000@gmail.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: Victor Shen <71985089+Vexerot@users.noreply.github.com> Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com> Co-authored-by: Milon <milonpl.git@proton.me> Co-authored-by: Kirus59 <145689588+Kirus59@users.noreply.github.com> Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Co-authored-by: Stomf <5dorkydorks@gmail.com> Co-authored-by: drakewill-CRL <46307022+drakewill-CRL@users.noreply.github.com> Co-authored-by: PraxisMapper <praxismapper@gmail.com> Co-authored-by: EmoGarbage404 <retron404@gmail.com> Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> Co-authored-by: TytosB <54259736+TytosB@users.noreply.github.com> Co-authored-by: abadaba695 <spacestation13thingy@gmail.com> Co-authored-by: kosticia <kosticia46@gmail.com> Co-authored-by: Thinbug <101073555+Thinbug0@users.noreply.github.com> Co-authored-by: pathetic meowmeow <uhhadd@gmail.com> Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com> Co-authored-by: ActiveMammmoth <140334666+ActiveMammmoth@users.noreply.github.com> Co-authored-by: Myra <vasilis@pikachu.systems> Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com> Co-authored-by: Gentleman-Bird <dcgreen406@gmail.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: BIGZi0348 <svalker0348@gmail.com> Co-authored-by: LaCumbiaDelCoronavirus <90893484+LaCumbiaDelCoronavirus@users.noreply.github.com> Co-authored-by: imatsoup <93290208+imatsoup@users.noreply.github.com> Co-authored-by: Matthew Herber <32679887+happyrobot33@users.noreply.github.com> Co-authored-by: Ertanic <36124833+Ertanic@users.noreply.github.com> Co-authored-by: MissKay1994 <15877268+MissKay1994@users.noreply.github.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> Co-authored-by: eoineoineoin <helloworld@eoinrul.es> Co-authored-by: Tiniest Shark <head.rebel@yahoo.com> Co-authored-by: nikitosych <boriszyn@gmail.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Perry Fraser <perryprog@users.noreply.github.com> Co-authored-by: YoungThug <ramialanbagy@gmail.com> Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> Co-authored-by: Southbridge <7013162+southbridge-fur@users.noreply.github.com> Co-authored-by: Vladislav Suchkov <20380250+murolem@users.noreply.github.com> Co-authored-by: Prole <172158352+Prole0@users.noreply.github.com> Co-authored-by: Unkn0wn_Gh0st <shadowstalkermll@gmail.com> Co-authored-by: 3nderall <101940324+3nderall@users.noreply.github.com> Co-authored-by: Radezolid <snappednexus@gmail.com> Co-authored-by: J <billsmith116@gmail.com> Co-authored-by: Ghagliiarghii <68826635+Ghagliiarghii@users.noreply.github.com> Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com> Co-authored-by: youtissoum <51883137+youtissoum@users.noreply.github.com> Co-authored-by: Minemoder5000 <minemoder50000@gmail.com> Co-authored-by: Spanky <scott@wearejacob.com> Co-authored-by: Spessmann <156740760+Spessmann@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: brainfood1183 <113240905+brainfood1183@users.noreply.github.com> Co-authored-by: Deerstop <edainturner@gmail.com> Co-authored-by: B_Kirill <153602297+B-Kirill@users.noreply.github.com> Co-authored-by: archee1 <archee3@hotmail.co.uk> Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com> Co-authored-by: Quantum-cross <7065792+Quantum-cross@users.noreply.github.com> Co-authored-by: poklj <compgeek223@gmail.com> Co-authored-by: Krunklehorn <42424291+Krunklehorn@users.noreply.github.com> Co-authored-by: OnyxTheBrave <131422822+OnyxTheBrave@users.noreply.github.com> Co-authored-by: UpAndLeaves <92269094+Alpha-Two@users.noreply.github.com> Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com> Co-authored-by: Zalycon <84675130+Zalycon@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: Verm <32827189+Vermidia@users.noreply.github.com> Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Co-authored-by: ScarKy0 <scarky0@onet.eu> Co-authored-by: Dmitry <57028746+dimm00n@users.noreply.github.com>
305 lines
12 KiB
C#
305 lines
12 KiB
C#
using System.Numerics;
|
|
using Content.Client.Items.Systems;
|
|
using Content.Shared.Item;
|
|
using Content.Shared.Storage;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.Graphics;
|
|
using Robust.Client.UserInterface;
|
|
using Robust.Client.UserInterface.CustomControls;
|
|
|
|
namespace Content.Client.UserInterface.Systems.Storage.Controls;
|
|
|
|
public sealed class ItemGridPiece : Control, IEntityControl
|
|
{
|
|
private readonly IEntityManager _entityManager;
|
|
private readonly StorageUIController _storageController;
|
|
|
|
private readonly List<(Texture, Vector2)> _texturesPositions = new();
|
|
|
|
public readonly EntityUid Entity;
|
|
public ItemStorageLocation Location;
|
|
public ItemGridPieceMarks? Marked;
|
|
|
|
public event Action<GUIBoundKeyEventArgs, ItemGridPiece>? OnPiecePressed;
|
|
public event Action<GUIBoundKeyEventArgs, ItemGridPiece>? OnPieceUnpressed;
|
|
|
|
#region Textures
|
|
private readonly string _centerTexturePath = "Storage/piece_center";
|
|
private Texture? _centerTexture;
|
|
private readonly string _topTexturePath = "Storage/piece_top";
|
|
private Texture? _topTexture;
|
|
private readonly string _bottomTexturePath = "Storage/piece_bottom";
|
|
private Texture? _bottomTexture;
|
|
private readonly string _leftTexturePath = "Storage/piece_left";
|
|
private Texture? _leftTexture;
|
|
private readonly string _rightTexturePath = "Storage/piece_right";
|
|
private Texture? _rightTexture;
|
|
private readonly string _topLeftTexturePath = "Storage/piece_topLeft";
|
|
private Texture? _topLeftTexture;
|
|
private readonly string _topRightTexturePath = "Storage/piece_topRight";
|
|
private Texture? _topRightTexture;
|
|
private readonly string _bottomLeftTexturePath = "Storage/piece_bottomLeft";
|
|
private Texture? _bottomLeftTexture;
|
|
private readonly string _bottomRightTexturePath = "Storage/piece_bottomRight";
|
|
private Texture? _bottomRightTexture;
|
|
private readonly string _markedFirstTexturePath = "Storage/marked_first";
|
|
private Texture? _markedFirstTexture;
|
|
private readonly string _markedSecondTexturePath = "Storage/marked_second";
|
|
private Texture? _markedSecondTexture;
|
|
#endregion
|
|
|
|
public ItemGridPiece(Entity<ItemComponent> entity, ItemStorageLocation location, IEntityManager entityManager)
|
|
{
|
|
IoCManager.InjectDependencies(this);
|
|
|
|
_entityManager = entityManager;
|
|
_storageController = UserInterfaceManager.GetUIController<StorageUIController>();
|
|
|
|
Entity = entity.Owner;
|
|
Location = location;
|
|
|
|
Visible = true;
|
|
MouseFilter = MouseFilterMode.Stop;
|
|
|
|
TooltipSupplier = SupplyTooltip;
|
|
|
|
OnThemeUpdated();
|
|
}
|
|
|
|
private Control? SupplyTooltip(Control sender)
|
|
{
|
|
if (_storageController.IsDragging)
|
|
return null;
|
|
|
|
return new Tooltip
|
|
{
|
|
Text = _entityManager.GetComponent<MetaDataComponent>(Entity).EntityName
|
|
};
|
|
}
|
|
|
|
protected override void OnThemeUpdated()
|
|
{
|
|
base.OnThemeUpdated();
|
|
|
|
_centerTexture = Theme.ResolveTextureOrNull(_centerTexturePath)?.Texture;
|
|
_topTexture = Theme.ResolveTextureOrNull(_topTexturePath)?.Texture;
|
|
_bottomTexture = Theme.ResolveTextureOrNull(_bottomTexturePath)?.Texture;
|
|
_leftTexture = Theme.ResolveTextureOrNull(_leftTexturePath)?.Texture;
|
|
_rightTexture = Theme.ResolveTextureOrNull(_rightTexturePath)?.Texture;
|
|
_topLeftTexture = Theme.ResolveTextureOrNull(_topLeftTexturePath)?.Texture;
|
|
_topRightTexture = Theme.ResolveTextureOrNull(_topRightTexturePath)?.Texture;
|
|
_bottomLeftTexture = Theme.ResolveTextureOrNull(_bottomLeftTexturePath)?.Texture;
|
|
_bottomRightTexture = Theme.ResolveTextureOrNull(_bottomRightTexturePath)?.Texture;
|
|
_markedFirstTexture = Theme.ResolveTextureOrNull(_markedFirstTexturePath)?.Texture;
|
|
_markedSecondTexture = Theme.ResolveTextureOrNull(_markedSecondTexturePath)?.Texture;
|
|
}
|
|
|
|
protected override void Draw(DrawingHandleScreen handle)
|
|
{
|
|
base.Draw(handle);
|
|
|
|
// really just an "oh shit" catch.
|
|
if (!_entityManager.EntityExists(Entity) || !_entityManager.TryGetComponent<ItemComponent>(Entity, out var itemComponent))
|
|
{
|
|
Dispose();
|
|
return;
|
|
}
|
|
|
|
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();
|
|
var size = _centerTexture!.Size * 2 * UIScale;
|
|
|
|
var hovering = !_storageController.IsDragging && UserInterfaceManager.CurrentlyHovered == this;
|
|
//yeah, this coloring is kinda hardcoded. deal with it. B)
|
|
Color? colorModulate = hovering ? null : Color.FromHex("#a8a8a8");
|
|
|
|
var marked = Marked != null;
|
|
Vector2i? maybeMarkedPos = null;
|
|
|
|
_texturesPositions.Clear();
|
|
for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++)
|
|
{
|
|
for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++)
|
|
{
|
|
if (!adjustedShape.Contains(x, y))
|
|
continue;
|
|
|
|
var offset = size * 2 * new Vector2(x - boundingGrid.Left, y - boundingGrid.Bottom);
|
|
var topLeft = PixelPosition + offset.Floored();
|
|
|
|
if (GetTexture(adjustedShape, new Vector2i(x, y), Direction.NorthEast) is {} neTexture)
|
|
{
|
|
var neOffset = new Vector2(size.X, 0);
|
|
handle.DrawTextureRect(neTexture, new UIBox2(topLeft + neOffset, topLeft + neOffset + size), colorModulate);
|
|
}
|
|
if (GetTexture(adjustedShape, new Vector2i(x, y), Direction.NorthWest) is {} nwTexture)
|
|
{
|
|
_texturesPositions.Add((nwTexture, Position + offset / UIScale));
|
|
handle.DrawTextureRect(nwTexture, new UIBox2(topLeft, topLeft + size), colorModulate);
|
|
|
|
if (marked && nwTexture == _topLeftTexture)
|
|
{
|
|
maybeMarkedPos = topLeft;
|
|
marked = false;
|
|
}
|
|
}
|
|
if (GetTexture(adjustedShape, new Vector2i(x, y), Direction.SouthEast) is {} seTexture)
|
|
{
|
|
var seOffset = size;
|
|
handle.DrawTextureRect(seTexture, new UIBox2(topLeft + seOffset, topLeft + seOffset + size), colorModulate);
|
|
}
|
|
if (GetTexture(adjustedShape, new Vector2i(x, y), Direction.SouthWest) is {} swTexture)
|
|
{
|
|
var swOffset = new Vector2(0, size.Y);
|
|
handle.DrawTextureRect(swTexture, new UIBox2(topLeft + swOffset, topLeft + swOffset + size), colorModulate);
|
|
}
|
|
}
|
|
}
|
|
|
|
// typically you'd divide by two, but since the textures are half a tile, this is done implicitly
|
|
var iconOffset = Location.Rotation.RotateVec(itemComponent.StoredOffset) * 2 * UIScale;
|
|
var iconPosition = new Vector2(
|
|
(boundingGrid.Width + 1) * size.X + iconOffset.X,
|
|
(boundingGrid.Height + 1) * size.Y + iconOffset.Y);
|
|
var iconRotation = Location.Rotation + Angle.FromDegrees(itemComponent.StoredRotation);
|
|
|
|
if (itemComponent.StoredSprite is { } storageSprite)
|
|
{
|
|
var scale = 2 * UIScale;
|
|
var sprite = _entityManager.System<SpriteSystem>().Frame0(storageSprite);
|
|
|
|
var sizeDifference = ((boundingGrid.Size + Vector2i.One) * _centerTexture.Size * 2 - sprite.Size) * UIScale;
|
|
|
|
var spriteBox = new Box2Rotated(new Box2(0f, sprite.Height * scale, sprite.Width * scale, 0f), -iconRotation, Vector2.Zero);
|
|
var root = spriteBox.CalcBoundingBox().BottomLeft;
|
|
var pos = PixelPosition * 2
|
|
+ (Parent?.GlobalPixelPosition ?? Vector2.Zero)
|
|
+ sizeDifference
|
|
+ iconOffset;
|
|
|
|
handle.SetTransform(pos, iconRotation);
|
|
var box = new UIBox2(root, root + sprite.Size * scale);
|
|
handle.DrawTextureRect(sprite, box);
|
|
handle.SetTransform(GlobalPixelPosition, Angle.Zero);
|
|
}
|
|
else
|
|
{
|
|
_entityManager.System<SpriteSystem>().ForceUpdate(Entity);
|
|
handle.DrawEntity(Entity,
|
|
PixelPosition + iconPosition,
|
|
Vector2.One * 2 * UIScale,
|
|
Angle.Zero,
|
|
eyeRotation: iconRotation,
|
|
overrideDirection: Direction.South);
|
|
}
|
|
|
|
if (maybeMarkedPos is {} markedPos)
|
|
{
|
|
var markedTexture = Marked switch
|
|
{
|
|
ItemGridPieceMarks.First => _markedFirstTexture,
|
|
ItemGridPieceMarks.Second => _markedSecondTexture,
|
|
_ => null,
|
|
};
|
|
|
|
if (markedTexture != null)
|
|
{
|
|
handle.DrawTextureRect(markedTexture, new UIBox2(markedPos, markedPos + size));
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override bool HasPoint(Vector2 point)
|
|
{
|
|
foreach (var (texture, position) in _texturesPositions)
|
|
{
|
|
if (!new Box2(position, position + texture.Size * 4).Contains(point))
|
|
continue;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected override void KeyBindDown(GUIBoundKeyEventArgs args)
|
|
{
|
|
base.KeyBindDown(args);
|
|
|
|
OnPiecePressed?.Invoke(args, this);
|
|
}
|
|
|
|
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
|
|
{
|
|
base.KeyBindUp(args);
|
|
|
|
OnPieceUnpressed?.Invoke(args, this);
|
|
}
|
|
|
|
private Texture? GetTexture(IReadOnlyList<Box2i> boxes, Vector2i position, Direction corner)
|
|
{
|
|
var top = !boxes.Contains(position - Vector2i.Up);
|
|
var bottom = !boxes.Contains(position - Vector2i.Down);
|
|
var left = !boxes.Contains(position + Vector2i.Left);
|
|
var right = !boxes.Contains(position + Vector2i.Right);
|
|
|
|
switch (corner)
|
|
{
|
|
case Direction.NorthEast:
|
|
if (top && right)
|
|
return _topRightTexture;
|
|
if (top)
|
|
return _topTexture;
|
|
if (right)
|
|
return _rightTexture;
|
|
return _centerTexture;
|
|
case Direction.NorthWest:
|
|
if (top && left)
|
|
return _topLeftTexture;
|
|
if (top)
|
|
return _topTexture;
|
|
if (left)
|
|
return _leftTexture;
|
|
return _centerTexture;
|
|
case Direction.SouthEast:
|
|
if (bottom && right)
|
|
return _bottomRightTexture;
|
|
if (bottom)
|
|
return _bottomTexture;
|
|
if (right)
|
|
return _rightTexture;
|
|
return _centerTexture;
|
|
case Direction.SouthWest:
|
|
if (bottom && left)
|
|
return _bottomLeftTexture;
|
|
if (bottom)
|
|
return _bottomTexture;
|
|
if (left)
|
|
return _leftTexture;
|
|
return _centerTexture;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static Vector2 GetCenterOffset(Entity<ItemComponent?> entity, ItemStorageLocation location, IEntityManager entMan)
|
|
{
|
|
var boxSize = entMan.System<ItemSystem>().GetAdjustedItemShape(entity, location).GetBoundingBox().Size;
|
|
var actualSize = new Vector2(boxSize.X + 1, boxSize.Y + 1);
|
|
return actualSize * new Vector2i(8, 8);
|
|
}
|
|
|
|
public EntityUid? UiEntity => Entity;
|
|
}
|
|
|
|
public enum ItemGridPieceMarks
|
|
{
|
|
First,
|
|
Second,
|
|
}
|