mirror of
https://github.com/space-wizards/space-station-14.git
synced 2026-02-15 03:31:30 +01:00
* initial visual nubody * oops overlay * im so pheeming rn * conversion... * tests * comeback of the underwear * oops eyes * blabbl * zeds * yaml linted * search and visible count constraints * reordering * preserve previously selected markings colors * fix test * some ui niceties * ordering * make DB changes backwards-compatible/downgrade-friendly * fix things again * fix migration * vulpkanin markings limit increase * wrapping * code cleanup and more code cleanup and more code cleanup and more code cleanup and * fix slop ports * better sampling API * make filter work + use the method i made for its intended purpose * fix test fails real quick * magic mirror cleanup, remove TODO * don't 0-init the organ profile data * remove deltastates --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
193 lines
5.7 KiB
C#
193 lines
5.7 KiB
C#
using System.Linq;
|
|
using System.Numerics;
|
|
using Content.Client.Interaction;
|
|
using Content.Client.Stylesheets;
|
|
using Content.Shared.Body;
|
|
using Content.Shared.Humanoid.Markings;
|
|
using Content.Shared.Humanoid;
|
|
using Robust.Client.AutoGenerated;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Client.UserInterface.XAML;
|
|
using Robust.Client.UserInterface;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Timing;
|
|
|
|
namespace Content.Client.Humanoid;
|
|
|
|
[GenerateTypedNameReferences]
|
|
public sealed partial class LayerMarkingOrderer : BoxContainer
|
|
{
|
|
private readonly ProtoId<OrganCategoryPrototype> _organ;
|
|
private readonly HumanoidVisualLayers _layer;
|
|
private readonly MarkingsViewModel _markingsModel;
|
|
private readonly DragDropHelper<LayerMarkingDragged> _dragDropHelper;
|
|
private readonly List<LayerDragDropBeacon> _beacons = new();
|
|
private LayerDragDropBeacon? _dragTarget;
|
|
|
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
|
|
|
public LayerMarkingOrderer(MarkingsViewModel markingsModel, ProtoId<OrganCategoryPrototype> organ, HumanoidVisualLayers layer)
|
|
{
|
|
RobustXamlLoader.Load(this);
|
|
IoCManager.InjectDependencies(this);
|
|
|
|
_markingsModel = markingsModel;
|
|
_organ = organ;
|
|
_layer = layer;
|
|
_dragDropHelper = new(OnBeginDrag, OnContinueDrag, OnEndDrag);
|
|
|
|
UpdateItems();
|
|
}
|
|
|
|
protected override void EnteredTree()
|
|
{
|
|
base.EnteredTree();
|
|
|
|
_markingsModel.MarkingsReset += UpdateItems;
|
|
_markingsModel.MarkingsChanged += MarkingsChanged;
|
|
}
|
|
|
|
protected override void ExitedTree()
|
|
{
|
|
base.ExitedTree();
|
|
|
|
_markingsModel.MarkingsReset -= UpdateItems;
|
|
_markingsModel.MarkingsChanged -= MarkingsChanged;
|
|
}
|
|
|
|
private void MarkingsChanged(ProtoId<OrganCategoryPrototype> organ, HumanoidVisualLayers layer)
|
|
{
|
|
if (_organ != organ || _layer != layer)
|
|
return;
|
|
|
|
UpdateItems();
|
|
}
|
|
|
|
private void UpdateItems()
|
|
{
|
|
Items.RemoveAllChildren();
|
|
_beacons.Clear();
|
|
|
|
if (_markingsModel.SelectedMarkings(_organ, _layer) is not { } markings)
|
|
return;
|
|
|
|
for (var idx = 0; idx < markings.Count; idx++)
|
|
{
|
|
var marking = markings[idx];
|
|
|
|
var container = new LayerMarkingItemContainer();
|
|
container.Margin = new(4);
|
|
|
|
var item = new LayerMarkingItem(_markingsModel, _organ, _layer, _prototype.Index<MarkingPrototype>(marking.MarkingId), false);
|
|
item.DefaultCursorShape = CursorShape.Hand;
|
|
item.Pressed += (args, control) => OnItemPressed(args, control, container);
|
|
item.Unpressed += OnItemUnpressed;
|
|
|
|
container.AddChild(item);
|
|
|
|
var before = new LayerDragDropBeacon(CandidatePosition.Before, idx);
|
|
var after = new LayerDragDropBeacon(CandidatePosition.After, idx);
|
|
_beacons.Add(before);
|
|
_beacons.Add(after);
|
|
|
|
Items.AddChild(before);
|
|
Items.AddChild(container);
|
|
Items.AddChild(after);
|
|
}
|
|
}
|
|
|
|
private void OnItemPressed(GUIBoundKeyEventArgs args, LayerMarkingItem control, LayerMarkingItemContainer container)
|
|
{
|
|
_dragDropHelper.MouseDown(new(control, container));
|
|
}
|
|
|
|
private void OnItemUnpressed(GUIBoundKeyEventArgs args, LayerMarkingItem control)
|
|
{
|
|
_dragDropHelper.EndDrag();
|
|
}
|
|
|
|
protected override void FrameUpdate(FrameEventArgs args)
|
|
{
|
|
base.FrameUpdate(args);
|
|
|
|
_dragDropHelper.Update(args.DeltaSeconds);
|
|
}
|
|
|
|
private bool OnBeginDrag()
|
|
{
|
|
var (item, container) = _dragDropHelper.Dragged;
|
|
|
|
container.Visible = false;
|
|
item.Orphan();
|
|
item.DefaultCursorShape = CursorShape.Move;
|
|
UserInterfaceManager.PopupRoot.AddChild(item);
|
|
LayoutContainer.SetPosition(item, UserInterfaceManager.MousePositionScaled.Position - new Vector2(32, 32));
|
|
return true;
|
|
}
|
|
|
|
private bool OnContinueDrag(float frameTime)
|
|
{
|
|
var (item, container) = _dragDropHelper.Dragged;
|
|
|
|
LayoutContainer.SetPosition(item, UserInterfaceManager.MousePositionScaled.Position - new Vector2(32, 32));
|
|
|
|
var closestBeacon =
|
|
_beacons.MinBy(beacon =>
|
|
(UserInterfaceManager.MousePositionScaled.Position - beacon.GlobalPosition).LengthSquared());
|
|
|
|
if (closestBeacon != _dragTarget)
|
|
{
|
|
_dragTarget?.UnbecomeTarget();
|
|
_dragTarget = closestBeacon;
|
|
_dragTarget?.BecomeTarget();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private void OnEndDrag()
|
|
{
|
|
var (item, container) = _dragDropHelper.Dragged;
|
|
|
|
container.Visible = true;
|
|
item.Orphan();
|
|
container.AddChild(item);
|
|
_dragTarget?.UnbecomeTarget();
|
|
|
|
if (_dragTarget != null)
|
|
{
|
|
_markingsModel.ChangeMarkingOrder(_organ, _layer, item.MarkingId, _dragTarget.CandidatePosition, _dragTarget.Index);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal readonly record struct LayerMarkingDragged(LayerMarkingItem Item, LayerMarkingItemContainer Container);
|
|
|
|
internal sealed class LayerMarkingItemContainer : PanelContainer
|
|
{
|
|
public LayerMarkingItemContainer()
|
|
{
|
|
SetHeight = 64;
|
|
HorizontalExpand = true;
|
|
}
|
|
}
|
|
|
|
internal sealed class LayerDragDropBeacon(CandidatePosition position, int index) : PanelContainer
|
|
{
|
|
public readonly CandidatePosition CandidatePosition = position;
|
|
public readonly int Index = index;
|
|
|
|
public void BecomeTarget()
|
|
{
|
|
SetHeight = 64;
|
|
HorizontalExpand = true;
|
|
SetOnlyStyleClass(StyleClass.PanelDropTarget);
|
|
}
|
|
|
|
public void UnbecomeTarget()
|
|
{
|
|
SetHeight = float.NaN;
|
|
RemoveStyleClass(StyleClass.PanelDropTarget);
|
|
}
|
|
}
|