Loadouts redux (#25715)
* Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 <koolthunder019@gmail.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
This commit is contained in:
@@ -2,69 +2,48 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Guidebook;
|
||||
using Content.Client.Humanoid;
|
||||
using Content.Client.Lobby.UI;
|
||||
using Content.Client.Lobby;
|
||||
using Content.Client.Message;
|
||||
using Content.Client.Players.PlayTimeTracking;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Client.UserInterface.Systems.Guidebook;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Clothing;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Preferences.Loadouts;
|
||||
using Content.Shared.Preferences.Loadouts.Effects;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.StatusIcon;
|
||||
using Content.Shared.Traits;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
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.Client.Utility;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
using Direction = Robust.Shared.Maths.Direction;
|
||||
|
||||
namespace Content.Client.Preferences.UI
|
||||
{
|
||||
public sealed class HighlightedContainer : PanelContainer
|
||||
{
|
||||
public HighlightedContainer()
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat()
|
||||
{
|
||||
BackgroundColor = new Color(47, 47, 53),
|
||||
ContentMarginTopOverride = 10,
|
||||
ContentMarginBottomOverride = 10,
|
||||
ContentMarginLeftOverride = 10,
|
||||
ContentMarginRightOverride = 10
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class HumanoidProfileEditor : Control
|
||||
public sealed partial class HumanoidProfileEditor : BoxContainer
|
||||
{
|
||||
private readonly IClientPreferencesManager _preferencesManager;
|
||||
private readonly IEntityManager _entMan;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IPrototypeManager _prototypeManager;
|
||||
private readonly MarkingManager _markingManager;
|
||||
private readonly JobRequirementsManager _requirements;
|
||||
|
||||
private LineEdit _ageEdit => CAgeEdit;
|
||||
private LineEdit _nameEdit => CNameEdit;
|
||||
private TextEdit _flavorTextEdit = null!;
|
||||
private TextEdit? _flavorTextEdit;
|
||||
private Button _nameRandomButton => CNameRandomize;
|
||||
private Button _randomizeEverythingButton => CRandomizeEverything;
|
||||
private RichTextLabel _warningLabel => CWarningLabel;
|
||||
@@ -72,8 +51,6 @@ namespace Content.Client.Preferences.UI
|
||||
private OptionButton _sexButton => CSexButton;
|
||||
private OptionButton _genderButton => CPronounsButton;
|
||||
private Slider _skinColor => CSkin;
|
||||
private OptionButton _clothingButton => CClothingButton;
|
||||
private OptionButton _backpackButton => CBackpackButton;
|
||||
private OptionButton _spawnPriorityButton => CSpawnPriorityButton;
|
||||
private SingleMarkingPicker _hairPicker => CHairStylePicker;
|
||||
private SingleMarkingPicker _facialHairPicker => CFacialHairPicker;
|
||||
@@ -88,44 +65,39 @@ namespace Content.Client.Preferences.UI
|
||||
private readonly Dictionary<string, BoxContainer> _jobCategories;
|
||||
// Mildly hacky, as I don't trust prototype order to stay consistent and don't want the UI to break should a new one get added mid-edit. --moony
|
||||
private readonly List<SpeciesPrototype> _speciesList;
|
||||
private readonly List<AntagPreferenceSelector> _antagPreferences;
|
||||
private readonly List<AntagPreferenceSelector> _antagPreferences = new();
|
||||
private readonly List<TraitPreferenceSelector> _traitPreferences;
|
||||
|
||||
private SpriteView _previewSpriteView => CSpriteView;
|
||||
private Button _previewRotateLeftButton => CSpriteRotateLeft;
|
||||
private Button _previewRotateRightButton => CSpriteRotateRight;
|
||||
private Direction _previewRotation = Direction.North;
|
||||
private EntityUid? _previewDummy;
|
||||
|
||||
private BoxContainer _rgbSkinColorContainer => CRgbSkinColorContainer;
|
||||
private ColorSelectorSliders _rgbSkinColorSelector;
|
||||
|
||||
private bool _isDirty;
|
||||
private bool _needUpdatePreview;
|
||||
public int CharacterSlot;
|
||||
public HumanoidCharacterProfile? Profile;
|
||||
private MarkingSet _markingSet = new(); // storing this here feels iffy but a few things need it this high up
|
||||
|
||||
public event Action<HumanoidCharacterProfile, int>? OnProfileChanged;
|
||||
|
||||
public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager,
|
||||
IEntityManager entityManager, IConfigurationManager configurationManager)
|
||||
[ValidatePrototypeId<GuideEntryPrototype>]
|
||||
private const string DefaultSpeciesGuidebook = "Species";
|
||||
|
||||
public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager, IConfigurationManager configurationManager)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
_prototypeManager = prototypeManager;
|
||||
_entMan = entityManager;
|
||||
_preferencesManager = preferencesManager;
|
||||
_configurationManager = configurationManager;
|
||||
_markingManager = IoCManager.Resolve<MarkingManager>();
|
||||
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
|
||||
controller.PreviewDummyUpdated += OnDummyUpdate;
|
||||
|
||||
SpeciesInfoButton.ToolTip = Loc.GetString("humanoid-profile-editor-guidebook-button-tooltip");
|
||||
_previewSpriteView.SetEntity(controller.GetPreviewDummy());
|
||||
|
||||
#region Left
|
||||
|
||||
#region Randomize
|
||||
|
||||
#endregion Randomize
|
||||
|
||||
#region Name
|
||||
|
||||
_nameEdit.OnTextChanged += args => { SetName(args.Text); };
|
||||
@@ -139,8 +111,6 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
_tabContainer.SetTabTitle(0, Loc.GetString("humanoid-profile-editor-appearance-tab"));
|
||||
|
||||
ShowClothes.OnPressed += ToggleClothes;
|
||||
|
||||
#region Sex
|
||||
|
||||
_sexButton.OnItemSelected += args =>
|
||||
@@ -318,33 +288,6 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
#endregion Hair
|
||||
|
||||
#region Clothing
|
||||
|
||||
_clothingButton.AddItem(Loc.GetString("humanoid-profile-editor-preference-jumpsuit"), (int) ClothingPreference.Jumpsuit);
|
||||
_clothingButton.AddItem(Loc.GetString("humanoid-profile-editor-preference-jumpskirt"), (int) ClothingPreference.Jumpskirt);
|
||||
|
||||
_clothingButton.OnItemSelected += args =>
|
||||
{
|
||||
_clothingButton.SelectId(args.Id);
|
||||
SetClothing((ClothingPreference) args.Id);
|
||||
};
|
||||
|
||||
#endregion Clothing
|
||||
|
||||
#region Backpack
|
||||
|
||||
_backpackButton.AddItem(Loc.GetString("humanoid-profile-editor-preference-backpack"), (int) BackpackPreference.Backpack);
|
||||
_backpackButton.AddItem(Loc.GetString("humanoid-profile-editor-preference-satchel"), (int) BackpackPreference.Satchel);
|
||||
_backpackButton.AddItem(Loc.GetString("humanoid-profile-editor-preference-duffelbag"), (int) BackpackPreference.Duffelbag);
|
||||
|
||||
_backpackButton.OnItemSelected += args =>
|
||||
{
|
||||
_backpackButton.SelectId(args.Id);
|
||||
SetBackpack((BackpackPreference) args.Id);
|
||||
};
|
||||
|
||||
#endregion Backpack
|
||||
|
||||
#region SpawnPriority
|
||||
|
||||
foreach (var value in Enum.GetValues<SpawnPriorityPreference>())
|
||||
@@ -399,40 +342,16 @@ namespace Content.Client.Preferences.UI
|
||||
_jobPriorities = new List<JobPrioritySelector>();
|
||||
_jobCategories = new Dictionary<string, BoxContainer>();
|
||||
_requirements = IoCManager.Resolve<JobRequirementsManager>();
|
||||
// TODO: Move this to the LobbyUIController instead of being spaghetti everywhere.
|
||||
_requirements.Updated += UpdateAntagRequirements;
|
||||
_requirements.Updated += UpdateRoleRequirements;
|
||||
UpdateAntagRequirements();
|
||||
UpdateRoleRequirements();
|
||||
|
||||
#endregion Jobs
|
||||
|
||||
#region Antags
|
||||
|
||||
_tabContainer.SetTabTitle(2, Loc.GetString("humanoid-profile-editor-antags-tab"));
|
||||
|
||||
_antagPreferences = new List<AntagPreferenceSelector>();
|
||||
|
||||
foreach (var antag in prototypeManager.EnumeratePrototypes<AntagPrototype>().OrderBy(a => Loc.GetString(a.Name)))
|
||||
{
|
||||
if (!antag.SetPreference)
|
||||
continue;
|
||||
|
||||
var selector = new AntagPreferenceSelector(antag);
|
||||
_antagList.AddChild(selector);
|
||||
_antagPreferences.Add(selector);
|
||||
if (selector.Disabled)
|
||||
{
|
||||
Profile = Profile?.WithAntagPreference(antag.ID, false);
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
selector.PreferenceChanged += preference =>
|
||||
{
|
||||
Profile = Profile?.WithAntagPreference(antag.ID, preference);
|
||||
IsDirty = true;
|
||||
};
|
||||
}
|
||||
|
||||
#endregion Antags
|
||||
|
||||
#region Traits
|
||||
|
||||
var traits = prototypeManager.EnumeratePrototypes<TraitPrototype>().OrderBy(t => Loc.GetString(t.Name)).ToList();
|
||||
@@ -483,7 +402,7 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
#region FlavorText
|
||||
|
||||
if (_configurationManager.GetCVar(CCVars.FlavorText))
|
||||
if (configurationManager.GetCVar(CCVars.FlavorText))
|
||||
{
|
||||
var flavorText = new FlavorText.FlavorText();
|
||||
_tabContainer.AddChild(flavorText);
|
||||
@@ -500,22 +419,14 @@ namespace Content.Client.Preferences.UI
|
||||
_previewRotateLeftButton.OnPressed += _ =>
|
||||
{
|
||||
_previewRotation = _previewRotation.TurnCw();
|
||||
_needUpdatePreview = true;
|
||||
SetPreviewRotation(_previewRotation);
|
||||
};
|
||||
_previewRotateRightButton.OnPressed += _ =>
|
||||
{
|
||||
_previewRotation = _previewRotation.TurnCcw();
|
||||
_needUpdatePreview = true;
|
||||
SetPreviewRotation(_previewRotation);
|
||||
};
|
||||
|
||||
var species = Profile?.Species ?? SharedHumanoidAppearanceSystem.DefaultSpecies;
|
||||
var dollProto = _prototypeManager.Index<SpeciesPrototype>(species).DollPrototype;
|
||||
|
||||
if (_previewDummy != null)
|
||||
_entMan.DeleteEntity(_previewDummy!.Value);
|
||||
|
||||
_previewDummy = _entMan.SpawnEntity(dollProto, MapCoordinates.Nullspace);
|
||||
_previewSpriteView.SetEntity(_previewDummy);
|
||||
#endregion Dummy
|
||||
|
||||
#endregion Left
|
||||
@@ -538,22 +449,54 @@ namespace Content.Client.Preferences.UI
|
||||
{
|
||||
var guidebookController = UserInterfaceManager.GetUIController<GuidebookUIController>();
|
||||
var species = Profile?.Species ?? SharedHumanoidAppearanceSystem.DefaultSpecies;
|
||||
var page = "Species";
|
||||
var page = DefaultSpeciesGuidebook;
|
||||
if (_prototypeManager.HasIndex<GuideEntryPrototype>(species))
|
||||
page = species;
|
||||
|
||||
if (_prototypeManager.TryIndex<GuideEntryPrototype>("Species", out var guideRoot))
|
||||
if (_prototypeManager.TryIndex<GuideEntryPrototype>(DefaultSpeciesGuidebook, out var guideRoot))
|
||||
{
|
||||
var dict = new Dictionary<string, GuideEntry>();
|
||||
dict.Add("Species", guideRoot);
|
||||
dict.Add(DefaultSpeciesGuidebook, guideRoot);
|
||||
//TODO: Don't close the guidebook if its already open, just go to the correct page
|
||||
guidebookController.ToggleGuidebook(dict, includeChildren:true, selected: page);
|
||||
}
|
||||
}
|
||||
|
||||
private void ToggleClothes(BaseButton.ButtonEventArgs obj)
|
||||
private void OnDummyUpdate(EntityUid value)
|
||||
{
|
||||
RebuildSpriteView();
|
||||
_previewSpriteView.SetEntity(value);
|
||||
}
|
||||
|
||||
private void UpdateAntagRequirements()
|
||||
{
|
||||
_antagList.DisposeAllChildren();
|
||||
_antagPreferences.Clear();
|
||||
var btnGroup = new ButtonGroup();
|
||||
|
||||
foreach (var antag in _prototypeManager.EnumeratePrototypes<AntagPrototype>().OrderBy(a => Loc.GetString(a.Name)))
|
||||
{
|
||||
if (!antag.SetPreference)
|
||||
continue;
|
||||
|
||||
var selector = new AntagPreferenceSelector(antag, btnGroup)
|
||||
{
|
||||
Margin = new Thickness(3f, 3f, 3f, 0f),
|
||||
};
|
||||
_antagList.AddChild(selector);
|
||||
_antagPreferences.Add(selector);
|
||||
if (selector.Disabled)
|
||||
{
|
||||
Profile = Profile?.WithAntagPreference(antag.ID, false);
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
selector.PreferenceChanged += preference =>
|
||||
{
|
||||
Profile = Profile?.WithAntagPreference(antag.ID, preference);
|
||||
IsDirty = true;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void UpdateRoleRequirements()
|
||||
@@ -614,10 +557,16 @@ namespace Content.Client.Preferences.UI
|
||||
.Where(job => job.SetPreference)
|
||||
.ToArray();
|
||||
Array.Sort(jobs, JobUIComparer.Instance);
|
||||
var jobLoadoutGroup = new ButtonGroup();
|
||||
|
||||
foreach (var job in jobs)
|
||||
{
|
||||
var selector = new JobPrioritySelector(job, _prototypeManager);
|
||||
RoleLoadout? loadout = null;
|
||||
Profile?.Loadouts.TryGetValue(LoadoutSystem.GetJobPrototype(job.ID), out loadout);
|
||||
var selector = new JobPrioritySelector(loadout, job, jobLoadoutGroup, _prototypeManager)
|
||||
{
|
||||
Margin = new Thickness(3f, 3f, 3f, 0f),
|
||||
};
|
||||
|
||||
if (!_requirements.IsAllowed(job, out var reason))
|
||||
{
|
||||
@@ -627,6 +576,13 @@ namespace Content.Client.Preferences.UI
|
||||
category.AddChild(selector);
|
||||
_jobPriorities.Add(selector);
|
||||
|
||||
selector.LoadoutUpdated += args =>
|
||||
{
|
||||
Profile?.SetLoadout(args);
|
||||
UserInterfaceManager.GetUIController<LobbyUIController>().UpdateCharacterUI();
|
||||
IsDirty = true;
|
||||
};
|
||||
|
||||
selector.PriorityChanged += priority =>
|
||||
{
|
||||
Profile = Profile?.WithJobPriority(job.ID, priority);
|
||||
@@ -672,20 +628,10 @@ namespace Content.Client.Preferences.UI
|
||||
return;
|
||||
|
||||
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithMarkings(markings.GetForwardEnumerator().ToList()));
|
||||
_needUpdatePreview = true;
|
||||
UpdatePreview();
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
private void OnMarkingColorChange(List<Marking> markings)
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
|
||||
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithMarkings(markings));
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
|
||||
private void OnSkinColorOnValueChanged()
|
||||
{
|
||||
if (Profile is null) return;
|
||||
@@ -745,33 +691,21 @@ namespace Content.Client.Preferences.UI
|
||||
if (!disposing)
|
||||
return;
|
||||
|
||||
if (_previewDummy != null)
|
||||
_entMan.DeleteEntity(_previewDummy.Value);
|
||||
|
||||
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
|
||||
controller.PreviewDummyUpdated -= OnDummyUpdate;
|
||||
_requirements.Updated -= UpdateAntagRequirements;
|
||||
_requirements.Updated -= UpdateRoleRequirements;
|
||||
_preferencesManager.OnServerDataLoaded -= LoadServerData;
|
||||
}
|
||||
|
||||
private void RebuildSpriteView()
|
||||
{
|
||||
var species = Profile?.Species ?? SharedHumanoidAppearanceSystem.DefaultSpecies;
|
||||
var dollProto = _prototypeManager.Index<SpeciesPrototype>(species).DollPrototype;
|
||||
|
||||
if (_previewDummy != null)
|
||||
_entMan.DeleteEntity(_previewDummy!.Value);
|
||||
|
||||
_previewDummy = _entMan.SpawnEntity(dollProto, MapCoordinates.Nullspace);
|
||||
_previewSpriteView.SetEntity(_previewDummy);
|
||||
_needUpdatePreview = true;
|
||||
}
|
||||
|
||||
private void LoadServerData()
|
||||
{
|
||||
Profile = (HumanoidCharacterProfile) _preferencesManager.Preferences!.SelectedCharacter;
|
||||
CharacterSlot = _preferencesManager.Preferences.SelectedCharacterIndex;
|
||||
|
||||
UpdateAntagRequirements();
|
||||
UpdateRoleRequirements();
|
||||
UpdateControls();
|
||||
_needUpdatePreview = true;
|
||||
}
|
||||
|
||||
private void SetAge(int newAge)
|
||||
@@ -813,10 +747,9 @@ namespace Content.Client.Preferences.UI
|
||||
OnSkinColorOnValueChanged(); // Species may have special color prefs, make sure to update it.
|
||||
CMarkings.SetSpecies(newSpecies); // Repopulate the markings tab as well.
|
||||
UpdateSexControls(); // update sex for new species
|
||||
RebuildSpriteView(); // they might have different inv so we need a new dummy
|
||||
UpdateSpeciesGuidebookIcon();
|
||||
IsDirty = true;
|
||||
_needUpdatePreview = true;
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
private void SetName(string newName)
|
||||
@@ -825,18 +758,6 @@ namespace Content.Client.Preferences.UI
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
private void SetClothing(ClothingPreference newClothing)
|
||||
{
|
||||
Profile = Profile?.WithClothingPreference(newClothing);
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
private void SetBackpack(BackpackPreference newBackpack)
|
||||
{
|
||||
Profile = Profile?.WithBackpackPreference(newBackpack);
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
private void SetSpawnPriority(SpawnPriorityPreference newSpawnPriority)
|
||||
{
|
||||
Profile = Profile?.WithSpawnPriorityPreference(newSpawnPriority);
|
||||
@@ -847,12 +768,11 @@ namespace Content.Client.Preferences.UI
|
||||
{
|
||||
IsDirty = false;
|
||||
|
||||
if (Profile != null)
|
||||
{
|
||||
_preferencesManager.UpdateCharacter(Profile, CharacterSlot);
|
||||
OnProfileChanged?.Invoke(Profile, CharacterSlot);
|
||||
_needUpdatePreview = true;
|
||||
}
|
||||
if (Profile == null)
|
||||
return;
|
||||
|
||||
_preferencesManager.UpdateCharacter(Profile, CharacterSlot);
|
||||
OnProfileChanged?.Invoke(Profile, CharacterSlot);
|
||||
}
|
||||
|
||||
private bool IsDirty
|
||||
@@ -861,7 +781,6 @@ namespace Content.Client.Preferences.UI
|
||||
set
|
||||
{
|
||||
_isDirty = value;
|
||||
_needUpdatePreview = true;
|
||||
UpdateSaveButton();
|
||||
}
|
||||
}
|
||||
@@ -981,7 +900,7 @@ namespace Content.Client.Preferences.UI
|
||||
if (!_prototypeManager.HasIndex<GuideEntryPrototype>(species))
|
||||
return;
|
||||
|
||||
var style = speciesProto.GuideBookIcon;
|
||||
const string style = "SpeciesInfoDefault";
|
||||
SpeciesInfoButton.StyleClasses.Add(style);
|
||||
}
|
||||
|
||||
@@ -1017,26 +936,6 @@ namespace Content.Client.Preferences.UI
|
||||
_genderButton.SelectId((int) Profile.Gender);
|
||||
}
|
||||
|
||||
private void UpdateClothingControls()
|
||||
{
|
||||
if (Profile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_clothingButton.SelectId((int) Profile.Clothing);
|
||||
}
|
||||
|
||||
private void UpdateBackpackControls()
|
||||
{
|
||||
if (Profile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_backpackButton.SelectId((int) Profile.Backpack);
|
||||
}
|
||||
|
||||
private void UpdateSpawnPriorityControls()
|
||||
{
|
||||
if (Profile == null)
|
||||
@@ -1166,13 +1065,13 @@ namespace Content.Client.Preferences.UI
|
||||
if (Profile is null)
|
||||
return;
|
||||
|
||||
var humanoid = _entMan.System<HumanoidAppearanceSystem>();
|
||||
humanoid.LoadProfile(_previewDummy!.Value, Profile);
|
||||
UserInterfaceManager.GetUIController<LobbyUIController>().UpdateCharacterUI();
|
||||
SetPreviewRotation(_previewRotation);
|
||||
}
|
||||
|
||||
if (ShowClothes.Pressed)
|
||||
LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy!.Value, Profile);
|
||||
|
||||
_previewSpriteView.OverrideDirection = (Direction) ((int) _previewRotation % 4 * 2);
|
||||
private void SetPreviewRotation(Direction direction)
|
||||
{
|
||||
_previewSpriteView.OverrideDirection = (Direction) ((int) direction % 4 * 2);
|
||||
}
|
||||
|
||||
public void UpdateControls()
|
||||
@@ -1184,17 +1083,15 @@ namespace Content.Client.Preferences.UI
|
||||
UpdateGenderControls();
|
||||
UpdateSkinColor();
|
||||
UpdateSpecies();
|
||||
UpdateClothingControls();
|
||||
UpdateBackpackControls();
|
||||
UpdateSpawnPriorityControls();
|
||||
UpdateAgeEdit();
|
||||
UpdateEyePickers();
|
||||
UpdateSaveButton();
|
||||
UpdateLoadouts();
|
||||
UpdateJobPriorities();
|
||||
UpdateAntagPreferences();
|
||||
UpdateTraitPreferences();
|
||||
UpdateMarkings();
|
||||
RebuildSpriteView();
|
||||
UpdateHairPickers();
|
||||
UpdateCMarkingsHair();
|
||||
UpdateCMarkingsFacialHair();
|
||||
@@ -1202,17 +1099,6 @@ namespace Content.Client.Preferences.UI
|
||||
_preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable);
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (_needUpdatePreview)
|
||||
{
|
||||
UpdatePreview();
|
||||
_needUpdatePreview = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateJobPriorities()
|
||||
{
|
||||
foreach (var prioritySelector in _jobPriorities)
|
||||
@@ -1225,143 +1111,11 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class RequirementsSelector<T> : Control
|
||||
private void UpdateLoadouts()
|
||||
{
|
||||
public T Proto { get; }
|
||||
public bool Disabled => _lockStripe.Visible;
|
||||
|
||||
protected readonly RadioOptions<int> Options;
|
||||
private StripeBack _lockStripe;
|
||||
private Label _requirementsLabel;
|
||||
|
||||
protected RequirementsSelector(T proto)
|
||||
foreach (var prioritySelector in _jobPriorities)
|
||||
{
|
||||
Proto = proto;
|
||||
|
||||
Options = new RadioOptions<int>(RadioOptionsLayout.Horizontal)
|
||||
{
|
||||
FirstButtonStyle = StyleBase.ButtonOpenRight,
|
||||
ButtonStyle = StyleBase.ButtonOpenBoth,
|
||||
LastButtonStyle = StyleBase.ButtonOpenLeft
|
||||
};
|
||||
//Override default radio option button width
|
||||
Options.GenerateItem = GenerateButton;
|
||||
|
||||
Options.OnItemSelected += args => Options.Select(args.Id);
|
||||
|
||||
_requirementsLabel = new Label()
|
||||
{
|
||||
Text = Loc.GetString("role-timer-locked"),
|
||||
Visible = true,
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
StyleClasses = {StyleBase.StyleClassLabelSubText},
|
||||
};
|
||||
|
||||
_lockStripe = new StripeBack()
|
||||
{
|
||||
Visible = false,
|
||||
HorizontalExpand = true,
|
||||
MouseFilter = MouseFilterMode.Stop,
|
||||
Children =
|
||||
{
|
||||
_requirementsLabel
|
||||
}
|
||||
};
|
||||
|
||||
// Setup must be called after
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Actually adds the controls, must be called in the inheriting class' constructor.
|
||||
/// </summary>
|
||||
protected void Setup((string, int)[] items, string title, int titleSize, string? description, TextureRect? icon = null)
|
||||
{
|
||||
foreach (var (text, value) in items)
|
||||
{
|
||||
Options.AddItem(Loc.GetString(text), value);
|
||||
}
|
||||
|
||||
var titleLabel = new Label()
|
||||
{
|
||||
Margin = new Thickness(5f, 0, 5f, 0),
|
||||
Text = title,
|
||||
MinSize = new Vector2(titleSize, 0),
|
||||
MouseFilter = MouseFilterMode.Stop,
|
||||
ToolTip = description
|
||||
};
|
||||
|
||||
var container = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
};
|
||||
|
||||
if (icon != null)
|
||||
container.AddChild(icon);
|
||||
container.AddChild(titleLabel);
|
||||
container.AddChild(Options);
|
||||
container.AddChild(_lockStripe);
|
||||
|
||||
AddChild(container);
|
||||
}
|
||||
|
||||
public void LockRequirements(FormattedMessage requirements)
|
||||
{
|
||||
var tooltip = new Tooltip();
|
||||
tooltip.SetMessage(requirements);
|
||||
_lockStripe.TooltipSupplier = _ => tooltip;
|
||||
_lockStripe.Visible = true;
|
||||
Options.Visible = false;
|
||||
}
|
||||
|
||||
// TODO: Subscribe to roletimers event. I am too lazy to do this RN But I doubt most people will notice fn
|
||||
public void UnlockRequirements()
|
||||
{
|
||||
_lockStripe.Visible = false;
|
||||
Options.Visible = true;
|
||||
}
|
||||
|
||||
private Button GenerateButton(string text, int value)
|
||||
{
|
||||
return new Button
|
||||
{
|
||||
Text = text,
|
||||
MinWidth = 90
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class JobPrioritySelector : RequirementsSelector<JobPrototype>
|
||||
{
|
||||
public JobPriority Priority
|
||||
{
|
||||
get => (JobPriority) Options.SelectedValue;
|
||||
set => Options.SelectByValue((int) value);
|
||||
}
|
||||
|
||||
public event Action<JobPriority>? PriorityChanged;
|
||||
|
||||
public JobPrioritySelector(JobPrototype proto, IPrototypeManager protoMan)
|
||||
: base(proto)
|
||||
{
|
||||
Options.OnItemSelected += args => PriorityChanged?.Invoke(Priority);
|
||||
|
||||
var items = new[]
|
||||
{
|
||||
("humanoid-profile-editor-job-priority-high-button", (int) JobPriority.High),
|
||||
("humanoid-profile-editor-job-priority-medium-button", (int) JobPriority.Medium),
|
||||
("humanoid-profile-editor-job-priority-low-button", (int) JobPriority.Low),
|
||||
("humanoid-profile-editor-job-priority-never-button", (int) JobPriority.Never),
|
||||
};
|
||||
|
||||
var icon = new TextureRect
|
||||
{
|
||||
TextureScale = new Vector2(2, 2),
|
||||
VerticalAlignment = VAlignment.Center
|
||||
};
|
||||
var jobIcon = protoMan.Index<StatusIconPrototype>(proto.Icon);
|
||||
icon.Texture = jobIcon.Icon.Frame0();
|
||||
|
||||
Setup(items, proto.LocalizedName, 200, proto.LocalizedDescription, icon);
|
||||
prioritySelector.CloseLoadout();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1386,41 +1140,6 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class AntagPreferenceSelector : RequirementsSelector<AntagPrototype>
|
||||
{
|
||||
// 0 is yes and 1 is no
|
||||
public bool Preference
|
||||
{
|
||||
get => Options.SelectedValue == 0;
|
||||
set => Options.Select((value && !Disabled) ? 0 : 1);
|
||||
}
|
||||
|
||||
public event Action<bool>? PreferenceChanged;
|
||||
|
||||
public AntagPreferenceSelector(AntagPrototype proto)
|
||||
: base(proto)
|
||||
{
|
||||
Options.OnItemSelected += args => PreferenceChanged?.Invoke(Preference);
|
||||
|
||||
var items = new[]
|
||||
{
|
||||
("humanoid-profile-editor-antag-preference-yes-button", 0),
|
||||
("humanoid-profile-editor-antag-preference-no-button", 1)
|
||||
};
|
||||
var title = Loc.GetString(proto.Name);
|
||||
var description = Loc.GetString(proto.Objective);
|
||||
Setup(items, title, 250, description);
|
||||
|
||||
// immediately lock requirements if they arent met.
|
||||
// another function checks Disabled after creating the selector so this has to be done now
|
||||
var requirements = IoCManager.Resolve<JobRequirementsManager>();
|
||||
if (proto.Requirements != null && !requirements.CheckRoleTime(proto.Requirements, out var reason))
|
||||
{
|
||||
LockRequirements(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class TraitPreferenceSelector : Control
|
||||
{
|
||||
public TraitPrototype Trait { get; }
|
||||
|
||||
Reference in New Issue
Block a user