diff --git a/Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs b/Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs index 5af1159c93..e7984ccaf9 100644 --- a/Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs +++ b/Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs @@ -1,4 +1,4 @@ -using Content.Shared.Research.Prototypes; +using Content.Shared.Research.Prototypes; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.UserInterface; @@ -12,6 +12,9 @@ namespace Content.Client.Research.UI; [GenerateTypedNameReferences] public sealed partial class MiniTechnologyCardControl : Control { + /// The technology that this control represents + public readonly TechnologyPrototype Technology; + public MiniTechnologyCardControl(TechnologyPrototype technology, IPrototypeManager prototypeManager, SpriteSystem spriteSys, FormattedMessage description) { RobustXamlLoader.Load(this); @@ -24,5 +27,6 @@ public sealed partial class MiniTechnologyCardControl : Control var tooltip = new Tooltip(); tooltip.SetMessage(description); Main.TooltipSupplier = _ => tooltip; + Technology = technology; } } diff --git a/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs b/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs index a20509202f..52abd0df08 100644 --- a/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs +++ b/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs @@ -1,3 +1,4 @@ +using System.Linq; using System.Numerics; using Content.Client.UserInterface.Controls; using Content.Shared.Access.Components; @@ -48,16 +49,10 @@ public sealed partial class ResearchConsoleMenu : FancyWindow public void UpdatePanels(ResearchConsoleBoundInterfaceState state) { - var allTech = _research.GetAvailableTechnologies(Entity); - AvailableCardsContainer.Children.Clear(); TechnologyCardsContainer.Children.Clear(); - UnlockedCardsContainer.Children.Clear(); - foreach (var tech in allTech) - { - var mini = new MiniTechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech)); - AvailableCardsContainer.AddChild(mini); - } + var availableTech = _research.GetAvailableTechnologies(Entity); + SyncTechnologyList(AvailableCardsContainer, availableTech); if (_technologyDatabase == null) return; @@ -79,12 +74,8 @@ public sealed partial class ResearchConsoleMenu : FancyWindow TechnologyCardsContainer.AddChild(cardControl); } - foreach (var unlocked in _technologyDatabase.UnlockedTechnologies) - { - var tech = _prototype.Index(unlocked); - var cardControl = new MiniTechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech, false)); - UnlockedCardsContainer.AddChild(cardControl); - } + var unlockedTech = _technologyDatabase.UnlockedTechnologies.Select(x => _prototype.Index(x)); + SyncTechnologyList(UnlockedCardsContainer, unlockedTech); } public void UpdateInformationPanel(ResearchConsoleBoundInterfaceState state) @@ -146,5 +137,46 @@ public sealed partial class ResearchConsoleMenu : FancyWindow TierDisplayContainer.AddChild(control); } } + + /// + /// Synchronize a container for technology cards with a list of technologies, + /// creating or removing UI cards as appropriate. + /// + /// The container which contains the UI cards + /// The current set of technologies for which there should be cards + private void SyncTechnologyList(BoxContainer container, IEnumerable technologies) + { + // For the cards which already exist, build a map from technology prototype to the UI card + var currentTechControls = new Dictionary(); + foreach (var child in container.Children) + { + if (child is MiniTechnologyCardControl) + { + currentTechControls.Add((child as MiniTechnologyCardControl)!.Technology, child); + } + } + + foreach (var tech in technologies) + { + if (!currentTechControls.ContainsKey(tech)) + { + // Create a card for any technology which doesn't already have one. + var mini = new MiniTechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech)); + container.AddChild(mini); + } + else + { + // The tech already exists in the UI; remove it from the set, so we won't revisit it below + currentTechControls.Remove(tech); + } + } + + // Now, any items left in the dictionary are technologies which were previously + // available, but now are not. Remove them. + foreach (var (tech, techControl) in currentTechControls) + { + container.Children.Remove(techControl); + } + } }