LobbyUI fixes (#27033)

* LobbyUI fixes

I have no idea which were bugs prior but anyway fix stuff.

* More fixes

* Test moment
This commit is contained in:
metalgearsloth
2024-04-17 12:54:54 +10:00
committed by GitHub
parent 30f73cfb6c
commit fcd6c25242
7 changed files with 181 additions and 50 deletions

View File

@@ -64,13 +64,19 @@ namespace Content.Client.Lobby
_characterSetup.CloseButton.OnPressed += _ =>
{
// Reset sliders etc.
_characterSetup?.UpdateControls();
var controller = _userInterfaceManager.GetUIController<LobbyUIController>();
controller.SetClothes(true);
controller.UpdateProfile();
_lobby.SwitchState(LobbyGui.LobbyGuiState.Default);
};
_characterSetup.SaveButton.OnPressed += _ =>
{
_characterSetup.Save();
_userInterfaceManager.GetUIController<LobbyUIController>().UpdateCharacterUI();
_userInterfaceManager.GetUIController<LobbyUIController>().ReloadProfile();
};
LayoutContainer.SetAnchorPreset(_lobby, LayoutContainer.LayoutPreset.Wide);

View File

@@ -3,6 +3,7 @@ using Content.Client.Humanoid;
using Content.Client.Inventory;
using Content.Client.Lobby.UI;
using Content.Client.Preferences;
using Content.Client.Preferences.UI;
using Content.Client.Station;
using Content.Shared.Clothing;
using Content.Shared.GameTicking;
@@ -30,6 +31,8 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
private LobbyCharacterPreviewPanel? _previewPanel;
private bool _showClothes = true;
/*
* Each character profile has its own dummy. There is also a dummy for the lobby screen + character editor
* that is shared too.
@@ -41,13 +44,15 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
private EntityUid? _previewDummy;
/// <summary>
/// If we currently have a loadout selected.
/// If we currently have a job prototype selected.
/// </summary>
private JobPrototype? _dummyJob;
// TODO: Load the species directly and don't update entity ever.
public event Action<EntityUid>? PreviewDummyUpdated;
private HumanoidCharacterProfile? _profile;
public override void Initialize()
{
base.Initialize();
@@ -56,7 +61,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
private void PreferencesDataLoaded()
{
UpdateCharacterUI();
UpdateProfile();
}
public void OnStateEntered(LobbyState state)
@@ -72,44 +77,102 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
public void SetPreviewPanel(LobbyCharacterPreviewPanel? panel)
{
_previewPanel = panel;
UpdateCharacterUI();
ReloadProfile();
}
public void SetClothes(bool value)
{
if (_showClothes == value)
return;
_showClothes = value;
ReloadCharacterUI();
}
public void SetDummyJob(JobPrototype? job)
{
_dummyJob = job;
UpdateCharacterUI();
ReloadCharacterUI();
}
public void UpdateCharacterUI()
/// <summary>
/// Updates the character only with the specified profile change.
/// </summary>
public void ReloadProfile()
{
// Test moment
if (_stateManager.CurrentState is not LobbyState)
if (_profile == null || _stateManager.CurrentState is not LobbyState)
return;
// Ignore job clothes and the likes so we don't spam entities out every frame of color changes.
var previewDummy = EnsurePreviewDummy(_profile);
_humanoid.LoadProfile(previewDummy, _profile);
}
/// <summary>
/// Updates the currently selected character's preview.
/// </summary>
public void ReloadCharacterUI()
{
// Test moment
if (_profile == null || _stateManager.CurrentState is not LobbyState)
return;
EntityManager.DeleteEntity(_previewDummy);
_previewDummy = null;
_previewDummy = EnsurePreviewDummy(_profile);
_previewPanel?.SetSprite(_previewDummy.Value);
_previewPanel?.SetSummaryText(_profile.Summary);
_humanoid.LoadProfile(_previewDummy.Value, _profile);
if (_showClothes)
GiveDummyJobClothesLoadout(_previewDummy.Value, _profile);
}
/// <summary>
/// Updates character profile to the default.
/// </summary>
public void UpdateProfile()
{
if (!_preferencesManager.ServerDataLoaded)
{
_previewPanel?.SetLoaded(false);
_profile = null;
return;
}
_previewPanel?.SetLoaded(true);
if (_preferencesManager.Preferences?.SelectedCharacter is not HumanoidCharacterProfile selectedCharacter)
if (_preferencesManager.Preferences?.SelectedCharacter is HumanoidCharacterProfile selectedCharacter)
{
_previewPanel?.SetSummaryText(string.Empty);
_profile = selectedCharacter;
_previewPanel?.SetLoaded(true);
}
else
{
EntityManager.DeleteEntity(_previewDummy);
_previewDummy = EntityManager.SpawnEntity(_prototypeManager.Index<SpeciesPrototype>(selectedCharacter.Species).DollPrototype, MapCoordinates.Nullspace);
_previewPanel?.SetSprite(_previewDummy.Value);
_previewPanel?.SetSummaryText(selectedCharacter.Summary);
_humanoid.LoadProfile(_previewDummy.Value, selectedCharacter);
GiveDummyJobClothesLoadout(_previewDummy.Value, selectedCharacter);
PreviewDummyUpdated?.Invoke(_previewDummy.Value);
_previewPanel?.SetSummaryText(string.Empty);
_previewPanel?.SetLoaded(false);
}
ReloadCharacterUI();
}
public void UpdateProfile(HumanoidCharacterProfile? profile)
{
if (_profile?.Equals(profile) == true)
return;
if (_stateManager.CurrentState is not LobbyState)
return;
_profile = profile;
}
private EntityUid EnsurePreviewDummy(HumanoidCharacterProfile profile)
{
if (_previewDummy != null)
return _previewDummy.Value;
_previewDummy = EntityManager.SpawnEntity(_prototypeManager.Index<SpeciesPrototype>(profile.Species).DollPrototype, MapCoordinates.Nullspace);
PreviewDummyUpdated?.Invoke(_previewDummy.Value);
return _previewDummy.Value;
}
/// <summary>

View File

@@ -97,9 +97,14 @@ namespace Content.Client.Preferences.UI
UpdateUI();
}
public void UpdateControls()
{
// Reset sliders etc. upon going going back to GUI.
_humanoidProfileEditor.LoadServerData();
}
private void UpdateUI()
{
UserInterfaceManager.GetUIController<LobbyUIController>().UpdateCharacterUI();
var numberOfFullSlots = 0;
var characterButtonsGroup = new ButtonGroup();
Characters.RemoveAllChildren();

View File

@@ -190,7 +190,7 @@ namespace Content.Client.Preferences.UI
return;
Profile = Profile.WithCharacterAppearance(
Profile.Appearance.WithHairStyleName(newStyle.id));
IsDirty = true;
SetDirty();
};
_hairPicker.OnColorChanged += newColor =>
@@ -200,7 +200,7 @@ namespace Content.Client.Preferences.UI
Profile = Profile.WithCharacterAppearance(
Profile.Appearance.WithHairColor(newColor.marking.MarkingColors[0]));
UpdateCMarkingsHair();
IsDirty = true;
SetDirty();
};
_facialHairPicker.OnMarkingSelect += newStyle =>
@@ -209,7 +209,7 @@ namespace Content.Client.Preferences.UI
return;
Profile = Profile.WithCharacterAppearance(
Profile.Appearance.WithFacialHairStyleName(newStyle.id));
IsDirty = true;
SetDirty();
};
_facialHairPicker.OnColorChanged += newColor =>
@@ -219,7 +219,7 @@ namespace Content.Client.Preferences.UI
Profile = Profile.WithCharacterAppearance(
Profile.Appearance.WithFacialHairColor(newColor.marking.MarkingColors[0]));
UpdateCMarkingsFacialHair();
IsDirty = true;
SetDirty();
};
_hairPicker.OnSlotRemove += _ =>
@@ -231,7 +231,7 @@ namespace Content.Client.Preferences.UI
);
UpdateHairPickers();
UpdateCMarkingsHair();
IsDirty = true;
SetDirty();
};
_facialHairPicker.OnSlotRemove += _ =>
@@ -243,7 +243,7 @@ namespace Content.Client.Preferences.UI
);
UpdateHairPickers();
UpdateCMarkingsFacialHair();
IsDirty = true;
SetDirty();
};
_hairPicker.OnSlotAdd += delegate()
@@ -263,7 +263,7 @@ namespace Content.Client.Preferences.UI
UpdateHairPickers();
UpdateCMarkingsHair();
IsDirty = true;
SetDirty();
};
_facialHairPicker.OnSlotAdd += delegate()
@@ -283,7 +283,7 @@ namespace Content.Client.Preferences.UI
UpdateHairPickers();
UpdateCMarkingsFacialHair();
IsDirty = true;
SetDirty();
};
#endregion Hair
@@ -312,7 +312,7 @@ namespace Content.Client.Preferences.UI
Profile = Profile.WithCharacterAppearance(
Profile.Appearance.WithEyeColor(newColor));
CMarkings.CurrentEyeColor = Profile.Appearance.EyeColor;
IsDirty = true;
SetDirty();
};
#endregion Eyes
@@ -336,7 +336,7 @@ namespace Content.Client.Preferences.UI
_preferenceUnavailableButton.SelectId(args.Id);
Profile = Profile?.WithPreferenceUnavailable((PreferenceUnavailableMode) args.Id);
IsDirty = true;
SetDirty();
};
_jobPriorities = new List<JobPrioritySelector>();
@@ -369,7 +369,7 @@ namespace Content.Client.Preferences.UI
selector.PreferenceChanged += preference =>
{
Profile = Profile?.WithTraitPreference(trait.ID, preference);
IsDirty = true;
SetDirty();
};
}
}
@@ -436,6 +436,13 @@ namespace Content.Client.Preferences.UI
LoadServerData();
}
ShowClothes.OnToggled += args =>
{
var lobby = UserInterfaceManager.GetUIController<LobbyUIController>();
lobby.SetClothes(args.Pressed);
SetDirty();
};
preferencesManager.OnServerDataLoaded += LoadServerData;
SpeciesInfoButton.OnPressed += OnSpeciesInfoButtonPressed;
@@ -443,6 +450,15 @@ namespace Content.Client.Preferences.UI
UpdateSpeciesGuidebookIcon();
IsDirty = false;
controller.UpdateProfile();
}
private void SetDirty()
{
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.UpdateProfile(Profile);
controller.ReloadCharacterUI();
IsDirty = true;
}
private void OnSpeciesInfoButtonPressed(BaseButton.ButtonEventArgs args)
@@ -487,13 +503,13 @@ namespace Content.Client.Preferences.UI
if (selector.Disabled)
{
Profile = Profile?.WithAntagPreference(antag.ID, false);
IsDirty = true;
SetDirty();
}
selector.PreferenceChanged += preference =>
{
Profile = Profile?.WithAntagPreference(antag.ID, preference);
IsDirty = true;
SetDirty();
};
}
@@ -562,7 +578,10 @@ namespace Content.Client.Preferences.UI
foreach (var job in jobs)
{
RoleLoadout? loadout = null;
// Clone so we don't modify the underlying loadout.
Profile?.Loadouts.TryGetValue(LoadoutSystem.GetJobPrototype(job.ID), out loadout);
loadout = loadout?.Clone();
var selector = new JobPrioritySelector(loadout, job, jobLoadoutGroup, _prototypeManager)
{
Margin = new Thickness(3f, 3f, 3f, 0f),
@@ -578,15 +597,13 @@ namespace Content.Client.Preferences.UI
selector.LoadoutUpdated += args =>
{
Profile?.SetLoadout(args);
UserInterfaceManager.GetUIController<LobbyUIController>().UpdateCharacterUI();
IsDirty = true;
Profile = Profile?.WithLoadout(args);
SetDirty();
};
selector.PriorityChanged += priority =>
{
Profile = Profile?.WithJobPriority(job.ID, priority);
IsDirty = true;
foreach (var jobSelector in _jobPriorities)
{
@@ -602,6 +619,8 @@ namespace Content.Client.Preferences.UI
Profile = Profile?.WithJobPriority(jobSelector.Proto.ID, JobPriority.Medium);
}
}
SetDirty();
};
}
@@ -619,7 +638,7 @@ namespace Content.Client.Preferences.UI
return;
Profile = Profile.WithFlavorText(content);
IsDirty = true;
SetDirty();
}
private void OnMarkingChange(MarkingSet markings)
@@ -628,8 +647,10 @@ namespace Content.Client.Preferences.UI
return;
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithMarkings(markings.GetForwardEnumerator().ToList()));
UpdatePreview();
IsDirty = true;
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.UpdateProfile(Profile);
controller.ReloadProfile();
}
private void OnSkinColorOnValueChanged()
@@ -683,6 +704,9 @@ namespace Content.Client.Preferences.UI
}
IsDirty = true;
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.UpdateProfile(Profile);
controller.ReloadProfile();
}
protected override void Dispose(bool disposing)
@@ -698,7 +722,7 @@ namespace Content.Client.Preferences.UI
_preferencesManager.OnServerDataLoaded -= LoadServerData;
}
private void LoadServerData()
public void LoadServerData()
{
Profile = (HumanoidCharacterProfile) _preferencesManager.Preferences!.SelectedCharacter;
CharacterSlot = _preferencesManager.Preferences.SelectedCharacterIndex;
@@ -706,12 +730,13 @@ namespace Content.Client.Preferences.UI
UpdateAntagRequirements();
UpdateRoleRequirements();
UpdateControls();
ShowClothes.Pressed = true;
}
private void SetAge(int newAge)
{
Profile = Profile?.WithAge(newAge);
IsDirty = true;
SetDirty();
}
private void SetSex(Sex newSex)
@@ -732,13 +757,13 @@ namespace Content.Client.Preferences.UI
}
UpdateGenderControls();
CMarkings.SetSex(newSex);
IsDirty = true;
SetDirty();
}
private void SetGender(Gender newGender)
{
Profile = Profile?.WithGender(newGender);
IsDirty = true;
SetDirty();
}
private void SetSpecies(string newSpecies)
@@ -748,20 +773,20 @@ namespace Content.Client.Preferences.UI
CMarkings.SetSpecies(newSpecies); // Repopulate the markings tab as well.
UpdateSexControls(); // update sex for new species
UpdateSpeciesGuidebookIcon();
IsDirty = true;
SetDirty();
UpdatePreview();
}
private void SetName(string newName)
{
Profile = Profile?.WithName(newName);
IsDirty = true;
SetDirty();
}
private void SetSpawnPriority(SpawnPriorityPreference newSpawnPriority)
{
Profile = Profile?.WithSpawnPriorityPreference(newSpawnPriority);
IsDirty = true;
SetDirty();
}
public void Save()
@@ -773,6 +798,8 @@ namespace Content.Client.Preferences.UI
_preferencesManager.UpdateCharacter(Profile, CharacterSlot);
OnProfileChanged?.Invoke(Profile, CharacterSlot);
// Reset profile to default.
UserInterfaceManager.GetUIController<LobbyUIController>().UpdateProfile();
}
private bool IsDirty
@@ -1065,7 +1092,7 @@ namespace Content.Client.Preferences.UI
if (Profile is null)
return;
UserInterfaceManager.GetUIController<LobbyUIController>().UpdateCharacterUI();
UserInterfaceManager.GetUIController<LobbyUIController>().ReloadProfile();
SetPreviewRotation(_previewRotation);
}

View File

@@ -153,7 +153,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
_loadout.EnsureValid(session, collection);
_loadoutWindow.RefreshLoadouts(_loadout, session, collection);
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.UpdateCharacterUI();
controller.ReloadProfile();
LoadoutUpdated?.Invoke(_loadout);
};
@@ -165,7 +165,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
_loadout.EnsureValid(session, collection);
_loadoutWindow.RefreshLoadouts(_loadout, session, collection);
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.UpdateCharacterUI();
controller.ReloadProfile();
LoadoutUpdated?.Invoke(_loadout);
};

View File

@@ -315,6 +315,7 @@ namespace Content.Shared.Preferences
list.Remove(antagId);
}
}
return new(this, _jobPriorities, list, _traitPreferences, _loadouts);
}
@@ -565,6 +566,23 @@ namespace Content.Shared.Preferences
_loadouts[loadout.Role.Id] = loadout;
}
public HumanoidCharacterProfile WithLoadout(RoleLoadout loadout)
{
// Deep copies so we don't modify the DB profile.
var copied = new Dictionary<string, RoleLoadout>();
foreach (var proto in _loadouts)
{
if (proto.Key == loadout.Role)
continue;
copied[proto.Key] = proto.Value.Clone();
}
copied[loadout.Role] = loadout.Clone();
return new(this, _jobPriorities, _antagPreferences, _traitPreferences, copied);
}
public RoleLoadout GetLoadoutOrDefault(string id, IEntityManager entManager, IPrototypeManager protoManager)
{
if (!_loadouts.TryGetValue(id, out var loadout))

View File

@@ -29,6 +29,18 @@ public sealed class RoleLoadout
Role = role;
}
public RoleLoadout Clone()
{
var weh = new RoleLoadout(Role);
foreach (var selected in SelectedLoadouts)
{
weh.SelectedLoadouts.Add(selected.Key, new List<Loadout>(selected.Value));
}
return weh;
}
/// <summary>
/// Ensures all prototypes exist and effects can be applied.
/// </summary>