-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
705 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<BoxContainer xmlns="https://spacestation14.io" | ||
Orientation="Horizontal" | ||
HorizontalExpand="True" | ||
MinHeight="32" | ||
Margin="8 0 8 2"> | ||
<BoxContainer Name="JobTitleContainer" | ||
Orientation="Horizontal" | ||
HorizontalExpand="True" | ||
VerticalAlignment="Center"> | ||
<TextureRect Name="JobIcon" | ||
TextureScale="2 2" | ||
VerticalAlignment="Center" | ||
Margin="0 0 4 0" /> | ||
<Label Name="JobNameLabel" | ||
HorizontalExpand="True" | ||
VerticalAlignment="Center" /> | ||
</BoxContainer> | ||
<Button Name="DecreaseButton" | ||
Text="-" | ||
MinWidth="32" /> | ||
<Label Name="SlotsLabel" | ||
MinWidth="60" | ||
Align="Center" | ||
VerticalAlignment="Center" /> | ||
<Button Name="IncreaseButton" | ||
Text="+" | ||
MinWidth="32" | ||
Margin="0 0 4 0" /> | ||
<Button Name="ToggleInfiniteButton" | ||
Text="∞" | ||
MinWidth="32" | ||
Visible="False" /> | ||
</BoxContainer> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using Content.Shared._CD.JobSlotsConsole; | ||
using Content.Shared.Roles; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.GameObjects; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Client._CD.JobSlotsConsole; | ||
|
||
[GenerateTypedNameReferences] | ||
public sealed partial class JobRow : BoxContainer | ||
{ | ||
[Dependency] private readonly IPrototypeManager _protoManager = default!; | ||
[Dependency] private readonly IEntitySystemManager _entitySystem = default!; | ||
|
||
public event Action<JobSlotAdjustment>? OnAdjustPressed; | ||
public string JobName { get; } | ||
|
||
public JobRow(ProtoId<JobPrototype> job, int? slots, bool blacklisted) | ||
{ | ||
IoCManager.InjectDependencies(this); | ||
RobustXamlLoader.Load(this); | ||
|
||
var spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>(); | ||
|
||
var proto = _protoManager.Index(job); | ||
JobName = Loc.GetString(proto.Name); | ||
JobNameLabel.Text = JobName; | ||
|
||
// Set up job icon | ||
if (_protoManager.TryIndex(proto.Icon, out var jobIcon)) | ||
{ | ||
JobIcon.Texture = spriteSystem.Frame0(jobIcon.Icon); | ||
} | ||
|
||
UpdateSlots(slots, blacklisted); | ||
|
||
DecreaseButton.OnPressed += OnDecrease; | ||
IncreaseButton.OnPressed += OnIncrease; | ||
ToggleInfiniteButton.OnPressed += OnToggleInfinite; | ||
} | ||
|
||
private void OnDecrease(BaseButton.ButtonEventArgs args) | ||
{ | ||
OnAdjustPressed?.Invoke(JobSlotAdjustment.Decrease); | ||
} | ||
|
||
private void OnIncrease(BaseButton.ButtonEventArgs args) | ||
{ | ||
OnAdjustPressed?.Invoke(JobSlotAdjustment.Increase); | ||
} | ||
|
||
private void OnToggleInfinite(BaseButton.ButtonEventArgs args) | ||
{ | ||
var currentInfinite = SlotsLabel.Text == "∞"; | ||
OnAdjustPressed?.Invoke(currentInfinite ? JobSlotAdjustment.SetFinite : JobSlotAdjustment.SetInfinite); | ||
} | ||
|
||
public void ShowDebugControls(bool show) | ||
{ | ||
ToggleInfiniteButton.Visible = show; | ||
} | ||
|
||
private void UpdateSlots(int? slots, bool blacklisted) | ||
{ | ||
SlotsLabel.Text = slots?.ToString() ?? "∞"; | ||
|
||
// Disable buttons if blacklisted or at limits | ||
DecreaseButton.Disabled = blacklisted || slots is 0 or null; | ||
IncreaseButton.Disabled = blacklisted || slots == null; | ||
ToggleInfiniteButton.Disabled = blacklisted; | ||
|
||
if (blacklisted) | ||
{ | ||
DecreaseButton.ToolTip = Loc.GetString("job-slots-console-blacklisted"); | ||
IncreaseButton.ToolTip = Loc.GetString("job-slots-console-blacklisted"); | ||
ToggleInfiniteButton.ToolTip = Loc.GetString("job-slots-console-blacklisted"); | ||
} | ||
else | ||
{ | ||
DecreaseButton.ToolTip = null; | ||
IncreaseButton.ToolTip = null; | ||
ToggleInfiniteButton.ToolTip = null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using Content.Shared._CD.JobSlotsConsole; | ||
using Content.Shared.Roles; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Client._CD.JobSlotsConsole; | ||
|
||
public sealed class JobSlotsConsoleBoundUserInterface : BoundUserInterface | ||
{ | ||
|
||
private JobSlotsConsoleMenu? _menu; | ||
|
||
public JobSlotsConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) | ||
{ | ||
} | ||
|
||
protected override void Open() | ||
{ | ||
base.Open(); | ||
|
||
_menu = new JobSlotsConsoleMenu(); | ||
_menu.OpenCentered(); | ||
_menu.OnClose += Close; | ||
_menu.OnAdjustPressed += AdjustSlot; | ||
} | ||
|
||
private void AdjustSlot(ProtoId<JobPrototype> jobId, JobSlotAdjustment adjustment) | ||
{ | ||
SendMessage(new JobSlotsConsoleAdjustMessage(jobId, adjustment)); | ||
} | ||
|
||
protected override void UpdateState(BoundUserInterfaceState state) | ||
{ | ||
base.UpdateState(state); | ||
|
||
if (state is not JobSlotsConsoleState cast) | ||
return; | ||
|
||
_menu?.UpdateState(cast); | ||
} | ||
|
||
protected override void Dispose(bool disposing) | ||
{ | ||
base.Dispose(disposing); | ||
if (!disposing) | ||
return; | ||
_menu?.Close(); | ||
_menu = null; | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
Content.Client/_CD/JobSlotsConsole/JobSlotsConsoleMenu.xaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<controls:FancyWindow xmlns="https://spacestation14.io" | ||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" | ||
Title="{Loc 'job-slots-console-title'}" | ||
SetSize="600 400" | ||
MinSize="600 300"> | ||
<BoxContainer Orientation="Vertical" Margin="4"> | ||
<LineEdit Name="SearchBar" | ||
PlaceHolder="{Loc 'job-slots-console-search-placeholder'}" | ||
HorizontalExpand="True" | ||
Margin="0 0 0 4" /> | ||
|
||
<ScrollContainer VerticalExpand="True" HorizontalExpand="True"> | ||
<BoxContainer Name="DepartmentsList" | ||
Orientation="Vertical" | ||
VerticalExpand="True" | ||
HorizontalExpand="True"> | ||
<!-- Populated with departments --> | ||
</BoxContainer> | ||
</ScrollContainer> | ||
</BoxContainer> | ||
</controls:FancyWindow> |
141 changes: 141 additions & 0 deletions
141
Content.Client/_CD/JobSlotsConsole/JobSlotsConsoleMenu.xaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
using Content.Client.Administration.UI.CustomControls; | ||
using Content.Client.UserInterface.Controls; | ||
using Content.Shared.Roles; | ||
using Content.Shared._CD.JobSlotsConsole; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
using Robust.Shared.Prototypes; | ||
using System.Linq; | ||
|
||
namespace Content.Client._CD.JobSlotsConsole; | ||
|
||
[GenerateTypedNameReferences] | ||
public sealed partial class JobSlotsConsoleMenu : FancyWindow | ||
{ | ||
[Dependency] private readonly IPrototypeManager _protoManager = default!; | ||
|
||
private readonly Dictionary<ProtoId<DepartmentPrototype>, List<JobRow>> _departmentRows = new(); | ||
private readonly Dictionary<ProtoId<DepartmentPrototype>, Label> _departmentLabels = new(); | ||
private JobSlotsConsoleState? _currentState; | ||
|
||
public event Action<ProtoId<JobPrototype>, JobSlotAdjustment>? OnAdjustPressed; | ||
|
||
public JobSlotsConsoleMenu() | ||
{ | ||
IoCManager.InjectDependencies(this); | ||
RobustXamlLoader.Load(this); | ||
|
||
SearchBar.OnTextChanged += _ => UpdateJobList(); | ||
} | ||
|
||
public void UpdateState(JobSlotsConsoleState state) | ||
{ | ||
_currentState = state; | ||
|
||
DepartmentsList.RemoveAllChildren(); | ||
_departmentRows.Clear(); | ||
_departmentLabels.Clear(); | ||
|
||
var jobsByDepartment = new Dictionary<DepartmentPrototype, List<(JobPrototype proto, int? slots, bool blacklisted)>>(); | ||
|
||
foreach (var (jobId, slots) in state.Jobs) | ||
{ | ||
var proto = _protoManager.Index(jobId); | ||
var department = GetPrimaryDepartmentForJob(proto.ID); | ||
|
||
if (department is not { } dept) | ||
continue; | ||
|
||
if (!jobsByDepartment.TryGetValue(dept, out var jobs)) | ||
{ | ||
jobs = new List<(JobPrototype, int?, bool)>(); | ||
jobsByDepartment[dept] = jobs; | ||
} | ||
|
||
var blacklisted = state.BlacklistedJobs.Contains(jobId); | ||
jobs.Add((proto, slots, blacklisted)); | ||
} | ||
|
||
// Sort and add departments | ||
foreach (var (department, jobs) in jobsByDepartment.OrderBy(x => x.Key, DepartmentUIComparer.Instance)) | ||
{ | ||
var sortedJobs = jobs | ||
.OrderByDescending(x => x.proto.RealDisplayWeight) | ||
.ThenBy(x => x.proto.LocalizedName) | ||
.ToList(); | ||
|
||
AddDepartmentSection(department, sortedJobs); | ||
} | ||
|
||
UpdateJobList(); | ||
} | ||
|
||
private void AddDepartmentSection(DepartmentPrototype department, List<(JobPrototype proto, int? slots, bool blacklisted)> jobs) | ||
{ | ||
var departmentBox = new BoxContainer | ||
{ | ||
Orientation = BoxContainer.LayoutOrientation.Vertical, | ||
HorizontalExpand = true, | ||
Margin = new Thickness(0, 5), | ||
}; | ||
|
||
// Add department header | ||
var label = new Label | ||
{ | ||
Text = Loc.GetString(department.Name), | ||
HorizontalAlignment = HAlignment.Center, | ||
StyleClasses = { "LabelHeading" }, | ||
ModulateSelfOverride = department.Color, | ||
FontColorOverride = department.Color, // css trolling | ||
}; | ||
|
||
_departmentLabels[department.ID] = label; | ||
departmentBox.AddChild(label); | ||
departmentBox.AddChild(new HSeparator { Margin = new Thickness(5, 3, 5, 5) }); | ||
|
||
// Add job rows | ||
var jobRows = new List<JobRow>(); | ||
foreach (var (proto, slots, blacklisted) in jobs) | ||
{ | ||
var row = new JobRow(proto.ID, slots, blacklisted); | ||
row.OnAdjustPressed += adjustment => | ||
OnAdjustPressed?.Invoke(proto.ID, adjustment); | ||
row.ShowDebugControls(_currentState?.Debug ?? false); | ||
jobRows.Add(row); | ||
departmentBox.AddChild(row); | ||
} | ||
|
||
_departmentRows[department.ID] = jobRows; | ||
DepartmentsList.AddChild(departmentBox); | ||
} | ||
|
||
private void UpdateJobList() | ||
{ | ||
var search = SearchBar.Text.Trim().ToLowerInvariant(); | ||
|
||
foreach (var (departmentId, rows) in _departmentRows) | ||
{ | ||
var departmentLabel = _departmentLabels[departmentId]; | ||
var hasVisibleJobs = false; | ||
|
||
foreach (var row in rows) | ||
{ | ||
var visible = string.IsNullOrEmpty(search) || | ||
row.JobName.Contains(search, StringComparison.InvariantCultureIgnoreCase); | ||
row.Visible = visible; | ||
hasVisibleJobs |= visible; | ||
} | ||
|
||
departmentLabel.Parent!.Visible = hasVisibleJobs; | ||
} | ||
} | ||
|
||
private DepartmentPrototype? GetPrimaryDepartmentForJob(ProtoId<JobPrototype> jobId) | ||
{ | ||
return _protoManager.EnumeratePrototypes<DepartmentPrototype>() | ||
.FirstOrDefault(d => d.Roles.Contains(jobId) && d.Primary) | ||
?? _protoManager.EnumeratePrototypes<DepartmentPrototype>() | ||
.FirstOrDefault(d => d.Roles.Contains(jobId)); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
Content.Server/_CD/JobSlotsConsole/JobSlotsConsoleComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using Content.Shared.Roles; | ||
using Robust.Shared.Audio; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Server._CD.JobSlotsConsole; | ||
|
||
[RegisterComponent] | ||
public sealed partial class JobSlotsConsoleComponent : Component | ||
{ | ||
/// <summary> | ||
/// The station this console is linked to. Set when the station is detected. | ||
/// </summary> | ||
[DataField] | ||
public EntityUid? Station; | ||
|
||
/// <summary> | ||
/// Jobs that cannot have their slots adjusted from this console. | ||
/// </summary> | ||
[DataField] | ||
public HashSet<ProtoId<JobPrototype>> Blacklist = []; | ||
|
||
/// <summary> | ||
/// Whether this console has debug features enabled, like toggling infinite slots. | ||
/// </summary> | ||
[DataField] | ||
public bool Debug; | ||
|
||
/// <summary> | ||
/// The sound to play if the player doesn't have access to change job slots. | ||
/// </summary> | ||
[DataField] | ||
public SoundSpecifier DenySound = new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_sigh.ogg"); | ||
} |
Oops, something went wrong.