Красивое УИ телепорта для призрака (#378)

* add: nice ghost teleport ui

* fix: fix unused import

* wtf

* fuck you, search bar

* fix-add: finally
This commit is contained in:
ThereDrD0
2024-06-26 05:13:42 +03:00
committed by GitHub
parent 331eb0ece5
commit e35098f7dd
27 changed files with 835 additions and 239 deletions

View File

@@ -1,95 +1,346 @@
using System.Linq;
using System.Numerics;
using Content.Shared._White.Antag;
using Content.Shared.Ghost;
using Content.Shared.Roles;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client.UserInterface.Systems.Ghost.Controls
{
[GenerateTypedNameReferences]
public sealed partial class GhostTargetWindow : DefaultWindow
{
private List<(string, NetEntity)> _warps = new();
private string _searchText = string.Empty;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private List<GhostWarpPlayer> _playerWarps = new();
private List<GhostWarpPlace> _placeWarps = new();
private List<GhostWarpGlobalAntagonist> _globalAntoginists = new();
private List<GhostWarpPlayer> _alivePlayers = new();
private List<GhostWarpPlayer> _leftPlayers = new();
private List<GhostWarpPlayer> _deadPlayers = new();
private List<GhostWarpPlayer> _ghostPlayers = new();
public event Action<NetEntity>? WarpClicked;
public event Action? OnGhostnadoClicked;
public GhostTargetWindow()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
SearchBar.OnTextChanged += OnSearchTextChanged;
GhostnadoButton.OnPressed += _ => OnGhostnadoClicked?.Invoke();
}
public void UpdateWarps(IEnumerable<GhostWarp> warps)
{
// Server COULD send these sorted but how about we just use the client to do it instead
_warps = warps
.OrderBy(w => w.IsWarpPoint)
.ThenBy(w => w.DisplayName, Comparer<string>.Create(
(x, y) => string.Compare(x, y, StringComparison.Ordinal)))
.Select(w =>
{
var name = w.IsWarpPoint
? Loc.GetString("ghost-target-window-current-button", ("name", w.DisplayName))
: w.DisplayName;
return (name, w.Entity);
})
.ToList();
}
public void Populate()
{
ButtonContainer.DisposeAllChildren();
GhostTeleportContainter.DisposeAllChildren();
_playerWarps = GetSortedPlayers(_playerWarps);
_placeWarps = GetSortedPlaces(_placeWarps);
_globalAntoginists = GetSortedAntagonists(_globalAntoginists);
PlayersAllocation();
AddButtons();
}
public void UpdateWarps(List<GhostWarpPlayer> players, List<GhostWarpPlace> places, List<GhostWarpGlobalAntagonist> antagonists)
{
_playerWarps = players;
_placeWarps = places;
_globalAntoginists = antagonists;
}
private void AddButtons()
{
foreach (var (name, warpTarget) in _warps)
AddAntagButtons(_globalAntoginists, "ghost-teleport-menu-antagonists-label", "ButtonColorAntagonistDepartment");
AddPlayerButtons(_alivePlayers, "ghost-teleport-menu-alive-label", string.Empty, true); // Alive
AddPlayerButtons(_deadPlayers, "ghost-teleport-menu-dead-label", string.Empty, true); // Dead
AddPlayerButtons(_ghostPlayers, "ghost-teleport-menu-ghosts-label", string.Empty, true); // Ghost
AddPlayerButtons(_leftPlayers, "ghost-teleport-menu-left-label", string.Empty, true); // Left
AddPlaceButtons(_placeWarps, "ghost-teleport-menu-locations-label", "ButtonColorSpecificDepartment");
}
private void AddPlayerButtons(List<GhostWarpPlayer> players, string text, string styleClass,
bool enableByDepartmentColorSheet)
{
if (players.Count == 0)
return;
var bigGrid = new GridContainer();
var bigLabel = new Label
{
var currentButtonRef = new Button
Text = Loc.GetString(text),
StyleClasses = { "LabelBig" }
};
bigGrid.AddChild(bigLabel);
var sortedPlayers = SortPlayersByDepartment(players);
foreach (var departmentList in sortedPlayers)
{
if (departmentList.Count == 0)
continue;
var departmentGrid = new GridContainer
{
Text = name,
Columns = 5
};
if (enableByDepartmentColorSheet)
styleClass = _prototypeManager.Index<DepartmentPrototype>(departmentList[0].DepartmentID).ButtonStyle;
var labelText = _prototypeManager.Index<DepartmentPrototype>(departmentList[0].DepartmentID).Name;
var departmentLabel = new Label
{
Text = Loc.GetString(labelText) + ": " + departmentList.Count,
StyleClasses = { "LabelSecondaryColor" }
};
foreach (var player in departmentList)
{
var playerButton = new Button
{
Text = player.Name,
TextAlign = Label.AlignMode.Right,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center,
SizeFlagsStretchRatio = 1,
StyleClasses = { styleClass },
ToolTip = player.JobName,
TooltipDelay = 0.1f,
SetWidth = 180,
};
playerButton.OnPressed += _ => WarpClicked?.Invoke(player.Entity);
departmentGrid.AddChild(playerButton);
}
bigGrid.AddChild(departmentLabel);
bigGrid.AddChild(departmentGrid);
}
GhostTeleportContainter.AddChild(bigGrid);
}
private void AddPlaceButtons(List<GhostWarpPlace> places, string text, string styleClass)
{
if (places.Count == 0)
return;
var bigGrid = new GridContainer();
var bigLabel = new Label
{
Text = Loc.GetString(text),
StyleClasses = { "LabelBig" }
};
bigGrid.AddChild(bigLabel);
var placesGrid = new GridContainer
{
Columns = 5,
};
var countLabel = new Label
{
Text = Loc.GetString("ghost-teleport-menu-count-label") + ": " + places.Count,
StyleClasses = { "LabelSecondaryColor" }
};
foreach (var place in places)
{
var placeButton = new Button
{
Text = place.Name,
TextAlign = Label.AlignMode.Right,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center,
SizeFlagsStretchRatio = 1,
MinSize = new Vector2(340, 20),
ClipText = true,
StyleClasses = { styleClass },
ToolTip = place.Description,
TooltipDelay = 0.1f,
SetWidth = 180,
};
currentButtonRef.OnPressed += _ => WarpClicked?.Invoke(warpTarget);
currentButtonRef.Visible = ButtonIsVisible(currentButtonRef);
placeButton.OnPressed += _ => WarpClicked?.Invoke(place.Entity);
ButtonContainer.AddChild(currentButtonRef);
placesGrid.AddChild(placeButton);
}
bigGrid.AddChild(countLabel);
bigGrid.AddChild(placesGrid);
GhostTeleportContainter.AddChild(bigGrid);
}
private bool ButtonIsVisible(Button button)
private void AddAntagButtons(List<GhostWarpGlobalAntagonist> antags, string text, string styleClass)
{
return string.IsNullOrEmpty(_searchText) || button.Text == null || button.Text.Contains(_searchText, StringComparison.OrdinalIgnoreCase);
}
if (antags.Count == 0)
return;
private void UpdateVisibleButtons()
{
foreach (var child in ButtonContainer.Children)
var bigGrid = new GridContainer();
var bigLabel = new Label
{
if (child is Button button)
button.Visible = ButtonIsVisible(button);
Text = Loc.GetString(text),
StyleClasses = { "LabelBig" }
};
bigGrid.AddChild(bigLabel);
var sortedAntags = SortAntagsByWeight(antags);
foreach (var antagList in sortedAntags)
{
if (antagList.Count == 0)
continue;
var departmentGrid = new GridContainer
{
Columns = 5
};
var labelText = "ghost-teleport-menu-count-label";
foreach (var antag in antagList)
{
var playerButton = new Button
{
Text = antag.Name,
TextAlign = Label.AlignMode.Right,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center,
SizeFlagsStretchRatio = 1,
StyleClasses = { styleClass },
ToolTip = Loc.GetString(antag.AntagonistDescription),
TooltipDelay = 0.1f,
SetWidth = 180,
};
playerButton.OnPressed += _ => WarpClicked?.Invoke(antag.Entity);
departmentGrid.AddChild(playerButton);
labelText = antag.AntagonistName;
}
var departmentLabel = new Label
{
Text = Loc.GetString(labelText) + ": " + antagList.Count,
StyleClasses = { "LabelSecondaryColor" }
};
bigGrid.AddChild(departmentLabel);
bigGrid.AddChild(departmentGrid);
}
GhostTeleportContainter.AddChild(bigGrid);
}
private void OnSearchTextChanged(LineEdit.LineEditEventArgs args)
public List<List<GhostWarpPlayer>> SortPlayersByDepartment(List<GhostWarpPlayer> players)
{
_searchText = args.Text;
var sortedPlayers = new List<List<GhostWarpPlayer>>();
UpdateVisibleButtons();
players = players.OrderBy(p => _prototypeManager.Index<DepartmentPrototype>(p.DepartmentID).Weight).ToList();
var currentList = new List<GhostWarpPlayer>();
var currentWeight = _prototypeManager.Index<DepartmentPrototype>(players[0].DepartmentID).Weight;
foreach (var player in players)
{
var weight = _prototypeManager.Index<DepartmentPrototype>(player.DepartmentID).Weight;
if (weight == currentWeight)
{
currentList.Add(player);
}
else
{
sortedPlayers.Add(currentList);
currentList = new List<GhostWarpPlayer> { player };
currentWeight = weight;
}
}
if (!sortedPlayers.Contains(currentList))
sortedPlayers.Add(currentList);
sortedPlayers.Reverse();
return sortedPlayers;
}
public List<List<GhostWarpGlobalAntagonist>> SortAntagsByWeight(List<GhostWarpGlobalAntagonist> antagonists)
{
var sortedAntags = new List<List<GhostWarpGlobalAntagonist>>();
antagonists = antagonists.OrderBy(a => _prototypeManager.Index<AntagonistPrototype>(a.PrototypeID).Weight).ToList();
var currentList = new List<GhostWarpGlobalAntagonist>();
var currentWeight = _prototypeManager.Index<AntagonistPrototype>(antagonists[0].PrototypeID).Weight;
foreach (var antagonist in antagonists)
{
var weight = _prototypeManager.Index<AntagonistPrototype>(antagonist.PrototypeID).Weight;
if (weight == currentWeight)
{
currentList.Add(antagonist);
}
else
{
sortedAntags.Add(currentList);
currentList = new List<GhostWarpGlobalAntagonist> { antagonist };
currentWeight = weight;
}
}
if (!sortedAntags.Contains(currentList))
sortedAntags.Add(currentList);
return sortedAntags;
}
private List<GhostWarpPlace> GetSortedPlaces(List<GhostWarpPlace> places)
{
return places
.OrderBy(w => w.Name)
.ToList();
}
private List<GhostWarpPlayer> GetSortedPlayers(List<GhostWarpPlayer> players)
{
return players
.OrderBy(w => w.Name)
.ToList();
}
private List<GhostWarpGlobalAntagonist> GetSortedAntagonists(List<GhostWarpGlobalAntagonist> antagonists)
{
return antagonists
.OrderBy(w => w.Name)
.ToList();
}
private void PlayersAllocation()
{
_alivePlayers.Clear();
_deadPlayers.Clear();
_leftPlayers.Clear();
_ghostPlayers.Clear();
foreach (var warp in _playerWarps)
{
if (warp.IsDead)
_deadPlayers.Add(warp);
else if (warp.IsLeft)
_leftPlayers.Add(warp);
else if (warp.IsAlive)
_alivePlayers.Add(warp);
else if (warp.IsGhost)
_ghostPlayers.Add(warp);
}
}
}
}