Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Content.Client/Content.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
<ProjectReference Include="..\Content.Shared\Content.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="_Goobstation\Power\" />
</ItemGroup>
<Folder Include="_Goobstation\Power\" />
</ItemGroup>
<Import Project="..\RobustToolbox\MSBuild\Robust.Properties.targets" />
<Import Project="..\RobustToolbox\MSBuild\XamlIL.targets" />
</Project>
43 changes: 43 additions & 0 deletions Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Numerics;
using Content.Client.Humanoid;
using Content.Client.Lobby.UI.Loadouts;
using Content.Client._CD.Humanoid; // Allergies to work.
using Content.Client.Lobby.UI.Roles;
using Content.Client.Message;
using Content.Client.Players.PlayTimeTracking;
Expand Down Expand Up @@ -40,6 +41,9 @@
using Content.Shared._CD.Records;
// End CD - Character Records
using Content.Shared._DV.Traits; // DV - Traits
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent; // Allergies
using Content.Shared.FixedPoint; // Allergies

namespace Content.Client.Lobby.UI
{
Expand Down Expand Up @@ -118,6 +122,9 @@ public sealed partial class HumanoidProfileEditor : BoxContainer
private readonly RecordEditorGui _recordsTab;
// End CD - Station Records

// CD: Allergies Editor
private readonly AllergyPicker _allergiesTab;

[ValidatePrototypeId<GuideEntryPrototype>]
private static readonly ProtoId<GuideEntryPrototype> DefaultSpeciesGuidebook = "Species";

Expand Down Expand Up @@ -491,6 +498,13 @@ public HumanoidProfileEditor(
// Begin CD - Character Records
#region CosmaticRecords

// Begin CD - Allergies
_allergiesTab = new AllergyPicker(UpdateAllergies);
TabContainer.AddChild(_allergiesTab);
TabContainer.SetTabTitle(TabContainer.ChildCount - 1,
Loc.GetString("humanoid-profile-editor-cd-allergies-tab"));
// End CD - Allergies

_recordsTab = new RecordEditorGui(UpdateProfileRecords);
TabContainer.AddChild(_recordsTab);
TabContainer.SetTabTitle(TabContainer.ChildCount - 1, Loc.GetString("humanoid-profile-editor-cd-records-tab"));
Expand Down Expand Up @@ -908,6 +922,7 @@ public void SetProfile(HumanoidCharacterProfile? profile, int? slot)

// Begin CD - Character Records
UpdateHeightControls();
UpdateCDAllergies(); // CD Allergies
_recordsTab.Update(profile);
// End CD - Character Records

Expand Down Expand Up @@ -1222,6 +1237,15 @@ private void UpdateProfileRecords(PlayerProvidedCharacterRecords records)
}
// End CD - Character Records

// CD Allergies Editor
private void UpdateAllergies(Dictionary<ReagentPrototype, FixedPoint2> allergies)
{
Profile = Profile?.WithCDAllergies(allergies.Select(allergy => (allergy.Key.ID, allergy.Value))
.ToDictionary());
SetDirty();
}
// End CD Allergies

private void OnFlavorTextChange(string content)
{
if (Profile is null)
Expand Down Expand Up @@ -1586,6 +1610,25 @@ private void UpdateHeightControls()
}
// End CD - Character Records

// CD Allergies
private void UpdateCDAllergies()
{
if (Profile == null)
{
return;
}

var allergies = new Dictionary<ReagentPrototype, FixedPoint2>();
foreach (var entry in (Dictionary<string, FixedPoint2>) Profile.CDAllergies)
{
if (!_prototypeManager.TryIndex(entry.Key, out ReagentPrototype? reagent))
continue;
allergies.Add(reagent, entry.Value);
}
_allergiesTab.SetData(allergies);
}
// CD End

private void UpdateSpawnPriorityControls()
{
if (Profile == null)
Expand Down
29 changes: 29 additions & 0 deletions Content.Client/_CD/Humanoid/AllergyPicker.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<BoxContainer xmlns="https://spacestation14.io" Orientation="Vertical" HorizontalExpand="True" Margin="5">
<!-- Allergen lists -->
<BoxContainer Orientation="Horizontal" SeparationOverride="5" VerticalExpand="True">
<!-- Unused reagents -->
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<OptionButton Name="CReagentGroupButton" StyleClasses="OpenLeft" />
<LineEdit Name="CReagentSearch" PlaceHolder="{Loc 'cd-allergies-editor-search'}" />
<ItemList Name="CReagents" VerticalExpand="True" MinSize="275 250" />
</BoxContainer>

<BoxContainer Orientation="Vertical" Align="Center" MinSize="50 250">
<Button Name="CAllergyAdd" Text="+" />
<Button Name="CAllergyRemove" Text="-" />
</BoxContainer>

<!-- Current allergies -->
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<Label Text="{Loc 'cd-allergies-editor-allergies'}" />
<ItemList Name="CAllergies" VerticalExpand="True" MinSize="275 250" />
</BoxContainer>
</BoxContainer>

<!-- Allergy attributes -->
<BoxContainer Name="CAllergyAttributes" VerticalExpand="True">
<Label Text="{Loc 'cd-allergies-editor-intensity'}" />
<Control HorizontalExpand="True" />
<OptionButton Name="CIntensityButton" StyleClasses="OpenLeft" />
</BoxContainer>
</BoxContainer>
242 changes: 242 additions & 0 deletions Content.Client/_CD/Humanoid/AllergyPicker.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
using System.Collections.Immutable;
using System.Linq;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;

namespace Content.Client._CD.Humanoid;

[GenerateTypedNameReferences]
public sealed partial class AllergyPicker : BoxContainer
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;

private readonly Texture _textureWhite;

private readonly Action<Dictionary<ReagentPrototype, FixedPoint2>> _onUpdateAllergies;

private Dictionary<ReagentPrototype, FixedPoint2> _currentAllergies = new();

private ItemList.Item? _selectedAllergy;
private int _selectedReagentGroup;
private ItemList.Item? _selectedUnusedAllergy;

private readonly ImmutableList<(string, ImmutableList<ReagentPrototype>)> _reagentGroups;


// As hundredths
public enum Intensity
{
Mild = 0_50,
Moderate = 1_00,
Severe = 5_00,
Extreme = 100_00,
}

public AllergyPicker(Action<Dictionary<ReagentPrototype, FixedPoint2>> onUpdateAllergies)
{
_onUpdateAllergies = onUpdateAllergies;

RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);

var white = new Image<Rgba32>(32, 32);
for (var x = 0; x < 32; x++)
{
for (var y = 0; y < 32; y++)
{
white[x, y] = new Rgba32(255, 255, 255, 255);
}
}

_textureWhite = Texture.LoadFromImage(white);

_reagentGroups = _prototypeManager.EnumeratePrototypes<ReagentPrototype>()
.Select(reagent => reagent.Group)
.Distinct()
.Order()
.Select(group =>
{
var reagents = _prototypeManager.EnumeratePrototypes<ReagentPrototype>()
.Where(reagent => reagent.Group.Equals(group))
.OrderBy(reagent => reagent.LocalizedName)
.ToImmutableList();
return (group, reagents);
})
.Where(tuple => !tuple.reagents.IsEmpty)
.ToImmutableList();

PopulateIntensities();

CReagentGroupButton.OnItemSelected += OnGroupChange;
CReagentSearch.OnTextChanged += args => PopulateReagents(args.Text);

CReagents.OnItemSelected += item => _selectedUnusedAllergy = CReagents[item.ItemIndex];

CAllergyAdd.OnPressed += _ => AllergyAdd();
CAllergyRemove.OnPressed += _ => AllergyRemove();

CAllergies.OnItemSelected += OnAllergySelected;

CIntensityButton.OnItemSelected += args =>
{
if (CIntensityButton.IsItemDisabled(0))
CIntensityButton.RemoveItem(0);

CIntensityButton.SelectId(args.Id);
_currentAllergies[(ReagentPrototype)_selectedAllergy!.Metadata!] = FixedPoint2.FromCents(args.Id);
_onUpdateAllergies.Invoke(_currentAllergies);
};
}

private void PopulateIntensities(FixedPoint2? custom = null)
{
CIntensityButton.Clear();
if (custom is not null)
{
CIntensityButton.AddItem(custom.Value.ToString(), custom.Value.Value);
CIntensityButton.SetItemDisabled(0, true);
}
foreach (var level in Enum.GetValues<Intensity>())
{
CIntensityButton.AddItem(
Loc.GetString("cd-allergies-editor-intensity-" + Enum.GetName(level)!.ToLower()),
(int)level
);
}
}

private ItemList.Item GetReagentItem(ItemList list, ReagentPrototype reagent)
{
return new ItemList.Item(list)
{
Text = reagent.LocalizedName[0].ToString().ToUpper() + reagent.LocalizedName[1..],
Selectable = true,
Metadata = reagent,
Icon = _textureWhite,
IconModulate = reagent.SubstanceColor,
};
}

public void SetData(Dictionary<ReagentPrototype, FixedPoint2> newAllergies)
{
_currentAllergies = newAllergies;
PopulateReagents(CReagentSearch.Text);
PopulateAllergies();
}

private void SetupCategoryButtons()
{
CReagentGroupButton.Clear();

foreach (var (group, _) in _reagentGroups)
{
CReagentGroupButton.AddItem(group);
}

CReagentGroupButton.SelectId(_selectedReagentGroup);
}

private void PopulateReagents(string filter)
{
SetupCategoryButtons();

CReagents.Clear();
_selectedUnusedAllergy = null;

var sortedReagents = _reagentGroups[_selectedReagentGroup]
.Item2
.Where(m =>
m.ID.Contains(filter, StringComparison.CurrentCultureIgnoreCase) ||
m.LocalizedName.Contains(filter, StringComparison.CurrentCultureIgnoreCase)
);

foreach (var reagent in sortedReagents)
{
if (_currentAllergies.ContainsKey(reagent))
continue;

CReagents.Add(GetReagentItem(CReagents, reagent));
}
}

private void PopulateAllergies()
{
CAllergies.Clear();
CAllergyAttributes.Visible = false;
_selectedAllergy = null;

foreach (var reagent in _currentAllergies.Keys)
{
CAllergies.Add(GetReagentItem(CAllergies, reagent));
}
}

private void OnGroupChange(OptionButton.ItemSelectedEventArgs group)
{
CReagentGroupButton.SelectId(group.Id);
_selectedReagentGroup = group.Id;
PopulateReagents(CReagentSearch.Text);
PopulateAllergies();
}

private void OnAllergySelected(ItemList.ItemListSelectedEventArgs item)
{
_selectedAllergy = CAllergies[item.ItemIndex];
var intensity = _currentAllergies[(ReagentPrototype)_selectedAllergy.Metadata!];

if (CIntensityButton.IsItemDisabled(0))
CIntensityButton.RemoveItem(0);

if (!CIntensityButton.TrySelectId(intensity.Value))
{
PopulateIntensities(intensity);
CIntensityButton.SelectId(intensity.Value);
}

CAllergyAttributes.Visible = true;
}

private void AllergyAdd()
{
if (_selectedUnusedAllergy is null)
return;

var reagent = (ReagentPrototype)_selectedUnusedAllergy.Metadata!;
CReagents.Remove(_selectedUnusedAllergy);
_selectedUnusedAllergy = null;

_currentAllergies[reagent] = 1.0;
CAllergies.Add(GetReagentItem(CAllergies, reagent));

_onUpdateAllergies.Invoke(_currentAllergies);
}

private void AllergyRemove()
{
if (_selectedAllergy is null)
return;

var reagent = (ReagentPrototype)_selectedAllergy.Metadata!;

_currentAllergies.Remove(reagent);

CAllergies.Remove(_selectedAllergy);

if (reagent.Group == _reagentGroups[_selectedReagentGroup].Item1)
{
CReagents.Add(GetReagentItem(CReagents, reagent));
CReagents.SortItemsByText();
}

_selectedAllergy = null;
CAllergyAttributes.Visible = false;
_onUpdateAllergies.Invoke(_currentAllergies);
}
}
Empty file.
Loading
Loading