mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-27 10:38:02 +03:00
* it just works * why hasn't it catastrophically failed yet * not just gotta do the ui oh god the ui * that was easier than expected * a devious misdirection * touchups * svin * loc+fix * touchups * shitfix * touchups x3 * for further use * i hate this piece of shit engine * touchups x4 * ribbit also i'm retarded x2 * big tard energy * bb * rabbitson * ? * forgor * k * whoops * fug
200 lines
7.2 KiB
C#
200 lines
7.2 KiB
C#
using Content.Client.Lobby;
|
|
using Content.Shared._White.CustomGhostSystem;
|
|
using Robust.Client.AutoGenerated;
|
|
using Robust.Client.Console;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.UserInterface;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Client.UserInterface.CustomControls;
|
|
using Robust.Client.UserInterface.XAML;
|
|
using Robust.Shared.Player;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Utility;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
|
|
namespace Content.Client._White.CustomGhosts.UI;
|
|
|
|
[GenerateTypedNameReferences]
|
|
public sealed partial class CustomGhostsWindow : DefaultWindow
|
|
{
|
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
|
[Dependency] private readonly ISharedPlayerManager _player = default!;
|
|
[Dependency] private readonly IClientPreferencesManager _pref = default!;
|
|
[Dependency] private readonly IClientConsoleHost _conhost = default!;
|
|
[Dependency] private readonly IEntityManager _entMan = default!;
|
|
[Dependency] private readonly IEntitySystemManager _entSys = default!;
|
|
private readonly SpriteSystem _sprite = default!;
|
|
|
|
private List<EntityUid> _previewEntities = new();
|
|
private List<Control> _hidden = new();
|
|
private Button _currentActive = default!;
|
|
private Dictionary<string, List<CustomGhostPrototype>> _allGhosts = new(); // won't include ghosts that are ckey-locked
|
|
private ProtoId<CustomGhostPrototype> _currentGhostProtoId;
|
|
|
|
public CustomGhostsWindow()
|
|
{
|
|
RobustXamlLoader.Load(this);
|
|
IoCManager.InjectDependencies(this);
|
|
_sprite = _entSys.GetEntitySystem<SpriteSystem>();
|
|
|
|
_currentGhostProtoId = _pref.Preferences?.CustomGhost.Id ?? "default";
|
|
ShowAllCheckBox.OnToggled += ToggleVisibility;
|
|
|
|
OnClose += () => { foreach (var ent in _previewEntities) { _entMan.TryQueueDeleteEntity(ent); } };
|
|
BuildList();
|
|
}
|
|
|
|
private void BuildList()
|
|
{
|
|
var allghostprotos = _proto.EnumeratePrototypes<CustomGhostPrototype>();
|
|
allghostprotos = allghostprotos.OrderBy(item => item.DisplayName);
|
|
|
|
foreach (var ghostProto in allghostprotos)
|
|
_allGhosts.GetOrNew(ghostProto.Category).Add(ghostProto);
|
|
|
|
var categories = _allGhosts.Keys.Order();
|
|
foreach (var category in categories)
|
|
{
|
|
|
|
var label = AddCategoryLabel(category);
|
|
var ghosts = _allGhosts[category];
|
|
bool allHidden = true;
|
|
List<CustomGhostButton> buttons = new();
|
|
foreach (var ghostProto in ghosts)
|
|
if (AddButton(ghostProto) is CustomGhostButton button) // todo: consider moving AddChild from AddButton to here, to avoid this weird label juggling
|
|
buttons.Add(button); // also do something about this stupid button visibility double checking
|
|
|
|
if (buttons.Count == 0)
|
|
{
|
|
ScrollBox.RemoveChild(label);
|
|
continue;
|
|
}
|
|
|
|
if (buttons.All(button => !button.Visible)) // not visible by default means the ghost is locked, and if all ghosts in a single category are locked, hide that category divider
|
|
{
|
|
label.Visible = false;
|
|
_hidden.Add(label);
|
|
}
|
|
}
|
|
}
|
|
|
|
private CustomGhostButton? AddButton(CustomGhostPrototype ghostProto) // is not guaranteed to actually add a button, lol
|
|
{
|
|
bool available = ghostProto.CanUse(_player.LocalSession!, out string fullFailReason, out bool canSee);
|
|
if (!canSee) // skip button creation altogether
|
|
return null;
|
|
|
|
|
|
var button = new CustomGhostButton();
|
|
ScrollBox.AddChild(button);
|
|
button.ActualButton.Name = ghostProto.ID;
|
|
// Can't use EntityPrototypeView since its UpdateEntity method is private
|
|
// so i have to do what it does manually
|
|
// therefore there is no reason to use it over SpriteView
|
|
|
|
var ghostEnt = _entMan.Spawn(ghostProto.GhostEntityPrototype);
|
|
_previewEntities.Add(ghostEnt);
|
|
_sprite.ForceUpdate(ghostEnt);
|
|
_sprite.SetVisible(ghostEnt, true); // counters ghost invisibility bullshit
|
|
button.EntityTextureRects.SetEntity(ghostEnt);
|
|
|
|
button.EntityLabel.Text = ghostProto.DisplayName;
|
|
button.ActualButton.ToolTip = ghostProto.DisplayDesc;
|
|
|
|
if (_currentGhostProtoId == ghostProto.ID)
|
|
{
|
|
button.ActualButton.Pressed = true;
|
|
_currentActive = button.ActualButton;
|
|
}
|
|
button.ActualButton.OnPressed += OnPressed;
|
|
|
|
if (available)
|
|
return button;
|
|
|
|
button.Modulate = Color.Red;
|
|
button.Visible = false;
|
|
button.ActualButton.Disabled = true;
|
|
button.ActualButton.ToolTip += $"\n\n{Loc.GetString("custom-ghost-window-tooltip-to-unlock")}{fullFailReason}";
|
|
_hidden.Add(button);
|
|
return button;
|
|
}
|
|
|
|
private Label AddCategoryLabel(string text)
|
|
{
|
|
var label = new Label()
|
|
{
|
|
StyleClasses = { "FancyWindowTitle" }
|
|
};
|
|
|
|
label.Text = $"-- {Loc.GetString($"custom-ghost-category-{text}")} --";
|
|
ScrollBox.AddChild(label);
|
|
return label;
|
|
}
|
|
|
|
private void OnPressed(BaseButton.ButtonEventArgs args)
|
|
{
|
|
var protoId = args.Button.Name!;
|
|
if (protoId == _currentGhostProtoId)
|
|
{
|
|
args.Button.Pressed = true; // i don't want to figure out how to properly cancel this event, yet
|
|
return;
|
|
}
|
|
|
|
_currentActive.Pressed = false;
|
|
|
|
_currentGhostProtoId = protoId;
|
|
_currentActive = (Button) args.Button;
|
|
_pref.SetCustomGhost(protoId);
|
|
_conhost.ExecuteCommand($"setcustomghost {CommandParsing.Escape(protoId)}"); // I implemented the commands first as a test, so i'll be using them now. It's dumb, but it works okay.
|
|
}
|
|
|
|
private void ToggleVisibility(BaseButton.ButtonToggledEventArgs args)
|
|
{
|
|
foreach (var button in _hidden)
|
|
{
|
|
button.Visible = args.Pressed;
|
|
}
|
|
}
|
|
|
|
// shamelessly stolen from EntitySpawnButton
|
|
public sealed class CustomGhostButton : Control
|
|
{
|
|
public Button ActualButton { get; private set; }
|
|
public Label EntityLabel { get; private set; }
|
|
public SpriteView EntityTextureRects { get; private set; }
|
|
|
|
public CustomGhostButton()
|
|
{
|
|
AddChild(ActualButton = new Button
|
|
{
|
|
ToggleMode = true,
|
|
HorizontalExpand = true
|
|
});
|
|
|
|
AddChild(new BoxContainer
|
|
{
|
|
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
|
Children =
|
|
{
|
|
(EntityTextureRects = new SpriteView
|
|
{
|
|
SetSize = new Vector2(32, 32),
|
|
HorizontalAlignment = HAlignment.Center,
|
|
VerticalAlignment = VAlignment.Center,
|
|
Stretch = SpriteView.StretchMode.Fill
|
|
}),
|
|
(EntityLabel = new Label
|
|
{
|
|
VerticalAlignment = VAlignment.Center,
|
|
HorizontalExpand = true,
|
|
Text = "sp00ky",
|
|
ClipText = true
|
|
})
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|