Add job categories to the lobby screen (#2770)

* Rename department property to departments

* WIP Categories

* Add better spacing to categories

* Fix first separator and sync selectors

* You want some types with that

* Apply changes to latejoin as well

* Add category sorting to the late join gui as well

* CONTROL STUCK
This commit is contained in:
DrSmugleaf
2020-12-20 04:33:10 +01:00
committed by GitHub
parent 5909a41028
commit 0b24d425d2
24 changed files with 184 additions and 91 deletions

View File

@@ -43,8 +43,11 @@ namespace Content.Client.UserInterface
private readonly Button _sexClassifiedButton; private readonly Button _sexClassifiedButton;
private readonly HairStylePicker _hairPicker; private readonly HairStylePicker _hairPicker;
private readonly FacialHairStylePicker _facialHairPicker; private readonly FacialHairStylePicker _facialHairPicker;
private readonly List<JobPrioritySelector> _jobPriorities; private readonly List<JobPrioritySelector> _jobPriorities;
private readonly OptionButton _preferenceUnavailableButton; private readonly OptionButton _preferenceUnavailableButton;
private readonly Dictionary<string, VBoxContainer> _jobCategories;
private readonly List<AntagPreferenceSelector> _antagPreferences; private readonly List<AntagPreferenceSelector> _antagPreferences;
private readonly IEntity _previewDummy; private readonly IEntity _previewDummy;
@@ -313,31 +316,79 @@ namespace Content.Client.UserInterface
}; };
_jobPriorities = new List<JobPrioritySelector>(); _jobPriorities = new List<JobPrioritySelector>();
_jobCategories = new Dictionary<string, VBoxContainer>();
var firstCategory = true;
foreach (var job in prototypeManager.EnumeratePrototypes<JobPrototype>().OrderBy(j => j.Name)) foreach (var job in prototypeManager.EnumeratePrototypes<JobPrototype>().OrderBy(j => j.Name))
{ {
var selector = new JobPrioritySelector(job); foreach (var department in job.Departments)
jobList.AddChild(selector);
_jobPriorities.Add(selector);
selector.PriorityChanged += priority =>
{ {
Profile = Profile.WithJobPriority(job.ID, priority); if (!_jobCategories.TryGetValue(department, out var category))
IsDirty = true;
if (priority == JobPriority.High)
{ {
// Lower any other high priorities to medium. category = new VBoxContainer
{
Name = department,
ToolTip = Loc.GetString("Jobs in the {0} department", department)
};
if (firstCategory)
{
firstCategory = false;
}
else
{
category.AddChild(new Control
{
CustomMinimumSize = new Vector2(0, 23),
});
}
category.AddChild(new PanelContainer
{
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#464966")},
Children =
{
new Label
{
Text = Loc.GetString("{0} jobs", department)
}
}
});
_jobCategories[department] = category;
jobList.AddChild(category);
}
var selector = new JobPrioritySelector(job);
category.AddChild(selector);
_jobPriorities.Add(selector);
selector.PriorityChanged += priority =>
{
Profile = Profile.WithJobPriority(job.ID, priority);
IsDirty = true;
foreach (var jobSelector in _jobPriorities) foreach (var jobSelector in _jobPriorities)
{ {
if (jobSelector != selector && jobSelector.Priority == JobPriority.High) // Sync other selectors with the same job in case of multiple department jobs
if (jobSelector.Job == selector.Job)
{ {
jobSelector.Priority = JobPriority.Medium; jobSelector.Priority = priority;
Profile = Profile.WithJobPriority(jobSelector.Job.ID, JobPriority.Medium); }
// Lower any other high priorities to medium.
if (priority == JobPriority.High)
{
if (jobSelector.Job != selector.Job && jobSelector.Priority == JobPriority.High)
{
jobSelector.Priority = JobPriority.Medium;
Profile = Profile.WithJobPriority(jobSelector.Job.ID, JobPriority.Medium);
}
} }
} }
} };
}; }
} }
} }

View File

@@ -4,6 +4,8 @@ using System.Linq;
using Content.Client.Interfaces; using Content.Client.Interfaces;
using Content.Shared.Roles; using Content.Shared.Roles;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.Graphics.Drawing;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Client.Utility; using Robust.Client.Utility;
@@ -27,6 +29,7 @@ namespace Content.Client.UserInterface
public event Action<string> SelectedId; public event Action<string> SelectedId;
private readonly Dictionary<string, JobButton> _jobButtons = new(); private readonly Dictionary<string, JobButton> _jobButtons = new();
private readonly Dictionary<string, VBoxContainer> _jobCategories = new();
public LateJoinGui() public LateJoinGui()
{ {
@@ -37,65 +40,108 @@ namespace Content.Client.UserInterface
var jobList = new VBoxContainer(); var jobList = new VBoxContainer();
var vBox = new VBoxContainer var vBox = new VBoxContainer
{ {
Children = Children =
{
new ScrollContainer
{ {
new ScrollContainer SizeFlagsVertical = SizeFlags.FillExpand,
Children =
{ {
SizeFlagsVertical = SizeFlags.FillExpand, jobList
Children =
{
jobList
}
} }
} }
}; }
};
Contents.AddChild(vBox); Contents.AddChild(vBox);
var firstCategory = true;
foreach (var job in _prototypeManager.EnumeratePrototypes<JobPrototype>().OrderBy(j => j.Name)) foreach (var job in _prototypeManager.EnumeratePrototypes<JobPrototype>().OrderBy(j => j.Name))
{ {
var jobButton = new JobButton foreach (var department in job.Departments)
{ {
JobId = job.ID if (!_jobCategories.TryGetValue(department, out var category))
}; {
category = new VBoxContainer
{
Name = department,
ToolTip = Loc.GetString("Jobs in the {0} department", department)
};
var jobSelector = new HBoxContainer if (firstCategory)
{ {
SizeFlagsHorizontal = SizeFlags.FillExpand firstCategory = false;
}; }
else
{
category.AddChild(new Control
{
CustomMinimumSize = new Vector2(0, 23),
});
}
var icon = new TextureRect category.AddChild(new PanelContainer
{ {
TextureScale = (2, 2), PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#464966")},
Stretch = TextureRect.StretchMode.KeepCentered Children =
}; {
new Label
{
Text = Loc.GetString("{0} jobs", department)
}
}
});
if (job.Icon != null) _jobCategories[department] = category;
{ jobList.AddChild(category);
var specifier = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/job_icons.rsi"), job.Icon); }
icon.Texture = specifier.Frame0();
var jobButton = new JobButton
{
JobId = job.ID
};
var jobSelector = new HBoxContainer
{
SizeFlagsHorizontal = SizeFlags.FillExpand
};
var icon = new TextureRect
{
TextureScale = (2, 2),
Stretch = TextureRect.StretchMode.KeepCentered
};
if (job.Icon != null)
{
var specifier = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/job_icons.rsi"), job.Icon);
icon.Texture = specifier.Frame0();
}
jobSelector.AddChild(icon);
var jobLabel = new Label
{
Text = job.Name
};
jobSelector.AddChild(jobLabel);
jobButton.AddChild(jobSelector);
category.AddChild(jobButton);
jobButton.OnPressed += _ =>
{
SelectedId?.Invoke(jobButton.JobId);
};
if (!_gameTicker.JobsAvailable.Contains(job.ID))
{
jobButton.Disabled = true;
}
_jobButtons[job.ID] = jobButton;
} }
jobSelector.AddChild(icon);
var jobLabel = new Label
{
Text = job.Name
};
jobSelector.AddChild(jobLabel);
jobButton.AddChild(jobSelector);
jobList.AddChild(jobButton);
jobButton.OnPressed += args =>
{
SelectedId?.Invoke(jobButton.JobId);
};
if (!_gameTicker.JobsAvailable.Contains(job.ID))
{
jobButton.Disabled = true;
}
_jobButtons[job.ID] = jobButton;
} }
SelectedId += jobId => SelectedId += jobId =>
@@ -108,11 +154,6 @@ namespace Content.Client.UserInterface
_gameTicker.LobbyJobsAvailableUpdated += JobsAvailableUpdated; _gameTicker.LobbyJobsAvailableUpdated += JobsAvailableUpdated;
} }
public string ReturnId()
{
return SelectedId.ToString();
}
private void JobsAvailableUpdated(IReadOnlyList<string> jobs) private void JobsAvailableUpdated(IReadOnlyList<string> jobs)
{ {
foreach (var (id, button) in _jobButtons) foreach (var (id, button) in _jobButtons)
@@ -129,6 +170,7 @@ namespace Content.Client.UserInterface
{ {
_gameTicker.LobbyJobsAvailableUpdated -= JobsAvailableUpdated; _gameTicker.LobbyJobsAvailableUpdated -= JobsAvailableUpdated;
_jobButtons.Clear(); _jobButtons.Clear();
_jobCategories.Clear();
} }
} }
} }

View File

@@ -42,7 +42,7 @@ namespace Content.Shared.Roles
public JobSpecial Special { get; private set; } public JobSpecial Special { get; private set; }
public IReadOnlyCollection<string> Department { get; private set; } public IReadOnlyCollection<string> Departments { get; private set; }
public IReadOnlyCollection<string> Access { get; private set; } public IReadOnlyCollection<string> Access { get; private set; }
public void LoadFrom(YamlMappingNode mapping) public void LoadFrom(YamlMappingNode mapping)
@@ -51,7 +51,7 @@ namespace Content.Shared.Roles
ID = srz.ReadDataField<string>("id"); ID = srz.ReadDataField<string>("id");
Name = Loc.GetString(srz.ReadDataField<string>("name")); Name = Loc.GetString(srz.ReadDataField<string>("name"));
StartingGear = srz.ReadDataField<string>("startingGear"); StartingGear = srz.ReadDataField<string>("startingGear");
Department = srz.ReadDataField<List<string>>("department"); Departments = srz.ReadDataField<List<string>>("departments");
TotalPositions = srz.ReadDataField<int>("positions"); TotalPositions = srz.ReadDataField<int>("positions");
srz.DataField(this, p => p.SpawnPositions, "spawnPositions", TotalPositions); srz.DataField(this, p => p.SpawnPositions, "spawnPositions", TotalPositions);

View File

@@ -4,7 +4,7 @@
positions: 2 positions: 2
spawnPositions: 1 spawnPositions: 1
startingGear: CargoTechGear startingGear: CargoTechGear
department: departments:
- Cargo - Cargo
icon: "CargoTechnician" icon: "CargoTechnician"
access: access:

View File

@@ -4,7 +4,7 @@
positions: 1 positions: 1
spawnPositions: 1 spawnPositions: 1
startingGear: QuartermasterGear startingGear: QuartermasterGear
department: departments:
- Cargo - Cargo
icon: "QuarterMaster" icon: "QuarterMaster"
access: access:

View File

@@ -3,7 +3,7 @@
name: "assistant" name: "assistant"
positions: -1 # Treated as infinite. positions: -1 # Treated as infinite.
startingGear: AssistantGear startingGear: AssistantGear
department: departments:
- Civilian - Civilian
icon: "Assistant" icon: "Assistant"
access: access:

View File

@@ -3,7 +3,7 @@
name: "bartender" name: "bartender"
positions: 1 positions: 1
startingGear: BartenderGear startingGear: BartenderGear
department: departments:
- Civilian - Civilian
icon: "Bartender" icon: "Bartender"
access: access:

View File

@@ -4,7 +4,7 @@
positions: 2 positions: 2
spawnPositions: 2 spawnPositions: 2
startingGear: BotanistGear startingGear: BotanistGear
department: departments:
- Civilian - Civilian
icon: "Botanist" icon: "Botanist"
access: access:

View File

@@ -3,7 +3,7 @@
# name: "chaplain" # name: "chaplain"
# positions: 1 # positions: 1
# startingGear: ChaplainGear # startingGear: ChaplainGear
# department: # departments:
# - Civilian # - Civilian
# icon: "Chaplain" # icon: "Chaplain"
# access: # access:

View File

@@ -3,7 +3,7 @@
name: "chef" name: "chef"
positions: 1 positions: 1
startingGear: ChefGear startingGear: ChefGear
department: departments:
- Civilian - Civilian
icon: "Chef" icon: "Chef"
access: access:

View File

@@ -3,7 +3,7 @@
name: "clown" name: "clown"
positions: 1 positions: 1
startingGear: ClownGear startingGear: ClownGear
department: departments:
- Civilian - Civilian
icon: "Clown" icon: "Clown"
access: access:

View File

@@ -3,7 +3,7 @@
name: "janitor" name: "janitor"
positions: 1 positions: 1
startingGear: JanitorGear startingGear: JanitorGear
department: departments:
- Civilian - Civilian
icon: "Janitor" icon: "Janitor"
access: access:

View File

@@ -3,7 +3,7 @@
name: "mime" name: "mime"
positions: 1 positions: 1
startingGear: MimeGear startingGear: MimeGear
department: departments:
- Civilian - Civilian
icon: "Mime" icon: "Mime"
access: access:

View File

@@ -4,7 +4,7 @@
head: true head: true
positions: 1 positions: 1
startingGear: CaptainGear startingGear: CaptainGear
department: departments:
- Command - Command
icon: "Captain" icon: "Captain"
access: access:

View File

@@ -4,7 +4,7 @@
head: true head: true
positions: 1 positions: 1
startingGear: HoPGear startingGear: HoPGear
department: departments:
- Command - Command
- Civilian - Civilian
icon: "HeadOfPersonnel" icon: "HeadOfPersonnel"

View File

@@ -4,7 +4,7 @@
head: true head: true
positions: 1 positions: 1
startingGear: ChiefEngineerGear startingGear: ChiefEngineerGear
department: departments:
- Command - Command
- Engineering - Engineering
icon: "ChiefEngineer" icon: "ChiefEngineer"

View File

@@ -4,7 +4,7 @@
positions: 3 positions: 3
spawnPositions: 2 spawnPositions: 2
startingGear: StationEngineerGear startingGear: StationEngineerGear
department: departments:
- Engineering - Engineering
icon: "StationEngineer" icon: "StationEngineer"
access: access:

View File

@@ -6,7 +6,7 @@
head: true head: true
positions: 1 positions: 1
startingGear: CMOGear startingGear: CMOGear
department: departments:
- Command - Command
- Medical - Medical
icon: "ChiefMedicalOfficer" icon: "ChiefMedicalOfficer"

View File

@@ -4,7 +4,7 @@
positions: 3 positions: 3
spawnPositions: 2 spawnPositions: 2
startingGear: DoctorGear startingGear: DoctorGear
department: departments:
- Medical - Medical
icon: "MedicalDoctor" icon: "MedicalDoctor"
access: access:

View File

@@ -4,7 +4,7 @@
head: true head: true
positions: 1 positions: 1
startingGear: ResearchDirectorGear startingGear: ResearchDirectorGear
department: departments:
- Command - Command
- Science - Science
icon: "ResearchDirector" icon: "ResearchDirector"

View File

@@ -4,7 +4,7 @@
positions: 3 positions: 3
spawnPositions: 2 spawnPositions: 2
startingGear: ScientistGear startingGear: ScientistGear
department: departments:
- Science - Science
icon: "Scientist" icon: "Scientist"
access: access:

View File

@@ -4,7 +4,7 @@
head: true head: true
positions: 1 positions: 1
startingGear: HoSGear startingGear: HoSGear
department: departments:
- Command - Command
- Security - Security
icon: "HeadOfSecurity" icon: "HeadOfSecurity"

View File

@@ -4,7 +4,7 @@
positions: 3 positions: 3
spawnPositions: 2 spawnPositions: 2
startingGear: SecurityOfficerGear startingGear: SecurityOfficerGear
department: departments:
- Security - Security
icon: "SecurityOfficer" icon: "SecurityOfficer"
access: access:

View File

@@ -4,7 +4,7 @@
positions: 1 positions: 1
spawnPositions: 1 spawnPositions: 1
startingGear: WardenGear startingGear: WardenGear
department: departments:
- Security - Security
icon: "Warden" icon: "Warden"
access: access: