Files
wwdpublic/Content.Client/Lobby/UI/LoadoutPreferenceSelector.xaml.cs
Cinkafox b2d255cdd2 [tweak] UI Tweaks (#1001)
* - tweak: update StyleSheetify

* - add: flexbox

* - fix: size of flexbox in launchergui

* - tweak: Profile editor: start.

* - add: categories

* - tweak: help me please with this shi... loadouts

* - fix: container path think

* - tweak: thinks for optimisation

* - add: group selection for loadoutpicker

* - tweak: change position of preview

* - add: reason text

* - fix: Кролькины фиксы

* - fix: кролькины фиксы ч.2

* - fix: кролькины фиксы ч.3

* - кролькины фиксы - финал

* - fix: Ворчливого дедушкины фиксы, удаление старого барахла и пометка wwdp

* - tweak: some ui change for LoadoutCategories and LoadoutEntry

* - ворчливый дед фиксы ч.2

* - fix: очередные кролькины фиксы

* - add: loadout prototype validation

* - fix: description read from edit field
2026-01-04 23:33:01 +02:00

329 lines
13 KiB
C#

using System.Linq;
using System.Numerics;
using System.Text;
using Content.Client.Guidebook;
using Content.Client.Paint;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Systems.Guidebook;
using Content.Shared.Clothing.Loadouts.Prototypes;
using Content.Shared.Clothing.Loadouts.Systems;
using Content.Shared.Customization.Systems;
using Content.Shared.Guidebook;
using Content.Shared.Labels.Components;
using Content.Shared.Paint;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.Lobby.UI;
[GenerateTypedNameReferences]
public sealed partial class LoadoutPreferenceSelector : Control
{
public const string DefaultLoadoutInfoGuidebook = "LoadoutInfo";
public EntityUid DummyEntityUid;
private readonly IEntityManager _entityManager;
public LoadoutPrototype Loadout { get; }
private Loadout _preference = null!;
public Loadout Preference
{
get => _preference;
set
{
_preference = value;
NameEdit.Text = value.CustomName ?? "";
DescriptionEdit.TextRope = new Rope.Leaf(value.CustomDescription ?? "");
BookTextEdit.TextRope = new Rope.Leaf(value.CustomContent ?? ""); // WD EDIT
ColorEdit.Color = Color.FromHex(value.CustomColorTint, Color.White);
if (value.CustomColorTint != null)
UpdatePaint(new(DummyEntityUid, _entityManager.GetComponent<PaintedComponent>(DummyEntityUid)), _entityManager);
HeirloomButton.Pressed = value.CustomHeirloom ?? false;
}
}
public bool Valid;
private bool _showUnusable;
public bool ShowUnusable
{
get => _showUnusable;
set
{
_showUnusable = value;
Visible = Valid && _wearable || _showUnusable;
PreferenceButton.RemoveStyleClass(StyleBase.ButtonDanger);
PreferenceButton.AddStyleClass(Valid ? "" : StyleBase.ButtonDanger);
}
}
private bool _wearable;
public bool Wearable
{
get => _wearable;
set
{
_wearable = value;
Visible = Valid && _wearable || _showUnusable;
PreferenceButton.RemoveStyleClass(StyleBase.ButtonCaution);
PreferenceButton.AddStyleClass(_wearable ? "" : StyleBase.ButtonCaution);
}
}
public event Action<Loadout>? PreferenceChanged;
public LoadoutPreferenceSelector(LoadoutPrototype loadout, JobPrototype highJob,
HumanoidCharacterProfile profile, ref Dictionary<string, EntityUid> entities,
IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager,
CharacterRequirementsSystem characterRequirementsSystem, JobRequirementsManager jobRequirementsManager)
{
RobustXamlLoader.Load(this);
_entityManager = entityManager;
Loadout = loadout;
// Show/hide the special menu and items depending on what's allowed
HeirloomButton.Visible = loadout.CanBeHeirloom;
SpecialMenu.Visible = Loadout.CustomName || Loadout.CustomDescription || Loadout.CustomContent || Loadout.CustomColorTint; // WD EDIT
SpecialName.Visible = Loadout.CustomName;
SpecialDescription.Visible = Loadout.CustomDescription;
SpecialBookText.Visible = Loadout.CustomContent; // WD EDIT
SpecialColorTintToggle.Visible = Loadout.CustomColorTint;
SpriteView previewLoadout;
if (!entities.TryGetValue(loadout.ID + 0, out var dummyLoadoutItem))
{
// Get the first item in the loadout to be the preview
dummyLoadoutItem = entityManager.SpawnEntity(loadout.Items.First(), MapCoordinates.Nullspace);
entities.Add(loadout.ID + 0, dummyLoadoutItem);
// Create a sprite preview of the loadout item
previewLoadout = new SpriteView
{
Scale = new Vector2(1, 1),
OverrideDirection = Direction.South,
VerticalAlignment = VAlignment.Center,
SizeFlagsStretchRatio = 1,
};
previewLoadout.SetEntity(dummyLoadoutItem);
}
else
{
// Create a sprite preview of the loadout item
previewLoadout = new SpriteView
{
Scale = new Vector2(1, 1),
OverrideDirection = Direction.South,
VerticalAlignment = VAlignment.Center,
SizeFlagsStretchRatio = 1,
};
previewLoadout.SetEntity(dummyLoadoutItem);
}
DummyEntityUid = dummyLoadoutItem;
entityManager.EnsureComponent<AppearanceComponent>(dummyLoadoutItem);
entityManager.EnsureComponent<PaintedComponent>(dummyLoadoutItem, out var paint);
var loadoutName =
Loc.GetString($"loadout-name-{loadout.ID}") == $"loadout-name-{loadout.ID}"
? entityManager.GetComponent<MetaDataComponent>(dummyLoadoutItem).EntityName
: Loc.GetString($"loadout-name-{loadout.ID}");
// Display the item's label if it's present
if (entityManager.TryGetComponent(dummyLoadoutItem, out LabelComponent? labelComponent))
{
var itemLabel = labelComponent.CurrentLabel;
if (!string.IsNullOrEmpty(itemLabel))
loadoutName += $" ({Loc.GetString(itemLabel)})";
}
var loadoutDesc =
!Loc.TryGetString($"loadout-description-{loadout.ID}", out var description)
? entityManager.GetComponent<MetaDataComponent>(dummyLoadoutItem).EntityDescription
: description;
// Manage the info button
void UpdateGuidebook() => GuidebookButton.Visible =
prototypeManager.HasIndex<GuideEntryPrototype>(loadout.GuideEntry);
UpdateGuidebook();
prototypeManager.PrototypesReloaded += _ => UpdateGuidebook();
GuidebookButton.OnPressed += _ =>
{
if (!prototypeManager.TryIndex<GuideEntryPrototype>(loadout.GuideEntry, out var guideRoot))
return;
var guidebookController = UserInterfaceManager.GetUIController<GuidebookUIController>();
//TODO: Don't close the guidebook if its already open, just go to the correct page
guidebookController.OpenGuidebook(
new Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry> { { loadout.GuideEntry, guideRoot } },
includeChildren: true,
selected: loadout.GuideEntry);
};
// Create a checkbox to get the loadout
PreferenceButton.AddChild(new BoxContainer
{
Children =
{
new Label
{
Text = loadout.Cost.ToString(),
StyleClasses = { StyleBase.StyleClassLabelHeading },
MinWidth = 32,
MaxWidth = 32,
ClipText = true,
Margin = new(0, 0, 8, 0),
},
new PanelContainer
{
PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#2f2f2f") },
Children =
{
previewLoadout,
},
},
new Label
{
Text = loadoutName,
Margin = new(8, 0, 0, 0),
},
},
});
// Update prefs cache when something changes
NameEdit.OnTextChanged += _ =>
_preference.CustomName = string.IsNullOrEmpty(NameEdit.Text) ? null : NameEdit.Text;
DescriptionEdit.OnTextChanged += _ =>
_preference.CustomDescription = string.IsNullOrEmpty(Rope.Collapse(DescriptionEdit.TextRope)) ? null : Rope.Collapse(DescriptionEdit.TextRope);
// WD EDIT START
BookTextEdit.OnTextChanged += _ =>
_preference.CustomContent = string.IsNullOrEmpty(Rope.Collapse(BookTextEdit.TextRope)) ? null : Rope.Collapse(BookTextEdit.TextRope);
// WD EDIT END
SpecialColorTintToggle.OnToggled += args =>
ColorEdit.Visible = args.Pressed;
ColorEdit.OnColorChanged += _ =>
{
_preference.CustomColorTint = SpecialColorTintToggle.Pressed ? ColorEdit.Color.ToHex() : null;
UpdatePaint(new(dummyLoadoutItem, paint), entityManager);
};
var desc = Loc.GetString(loadoutDesc);
NameEdit.PlaceHolder = loadoutName;
DescriptionEdit.Placeholder = new Rope.Leaf(desc);
BookTextEdit.Placeholder = new Rope.Leaf(Loc.GetString("humanoid-profile-editor-loadouts-customize-book-text-placeholder")); // WD EDIT
var tooltip = new Tooltip();
PreferenceButton.TooltipSupplier = _ => tooltip;
var toolBox = (BoxContainer) tooltip.Children.First();
if (!string.IsNullOrEmpty(desc))
tooltip.SetMessage(FormattedMessage.FromMarkupPermissive(desc));
if (loadout.Requirements.Any())
{
toolBox.AddChild(
new Label
{
Text = Loc.GetString("character-requirement-desc"),
StyleClasses = { StyleBase.StyleClassLabelHeading, },
Margin = new(0, 8, 0, 4),
});
MakeTooltipTree(toolBox, loadout.Requirements);
toolBox.AddChild(new() { Margin = new(0, 2), });
}
return;
void MakeTooltipTree(BoxContainer box, List<CharacterRequirement> requirements)
{
foreach (var requirement in requirements)
{
if (requirement is CharacterLogicRequirement logicRequirement)
{
requirement.IsValid(
highJob, profile, new Dictionary<string, TimeSpan>(), jobRequirementsManager.IsWhitelisted(), loadout,
entityManager, prototypeManager, configManager, out var reason);
box.AddChild(new RichTextLabel { Text = reason?.Split("\n")[0], Margin = new(8, 2), });
var newBox = new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Vertical, };
box.AddChild(new PanelContainer
{
PanelOverride = new StyleBoxFlat
{
BackgroundColor = Color.FromHex("#1B1B1C"),
BorderColor = Color.FromHex("#3A3A3D"),
BorderThickness = new(1),
},
Margin = new(8, 2),
Children = { newBox, },
});
MakeTooltipTree(newBox, logicRequirement.Requirements);
}
else
{
requirement.IsValid(
highJob, profile, new Dictionary<string, TimeSpan>(), jobRequirementsManager.IsWhitelisted(), loadout,
entityManager, prototypeManager, configManager, out var reason);
box.AddChild(new RichTextLabel
{
Text = reason,
Margin = new(8, 2),
});
}
}
}
}
private bool _initialized;
protected override void FrameUpdate(FrameEventArgs args)
{
if (_initialized || SpecialMenu.Heading == null)
return;
// Move the special editor
var heading = SpecialMenu.Heading;
heading.Orphan();
ButtonGroup.AddChild(heading);
GuidebookButton.Orphan();
ButtonGroup.AddChild(GuidebookButton);
// These guys are here too for reasons
HeadingButton.SetHeight = HeirloomButton.SetHeight = GuidebookButton.SetHeight = PreferenceButton.Size.Y;
SpecialColorTintToggle.Pressed = ColorEdit.Visible = _preference.CustomColorTint != null;
_initialized = true;
}
private void UpdatePaint(Entity<PaintedComponent> entity, IEntityManager entityManager)
{
if (_preference.CustomColorTint != null)
{
entity.Comp.Color = Color.FromHex(_preference.CustomColorTint);
entity.Comp.Enabled = true;
}
else
entity.Comp.Enabled = false;
var app = entityManager.System<SharedAppearanceSystem>();
app.TryGetData(entity, PaintVisuals.Painted, out bool value);
app.SetData(entity, PaintVisuals.Painted, !value);
}
}