]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Avoid emptying and recreating all UI cards on every update (#21990)
authoreoineoineoin <github@eoinrul.es>
Wed, 29 Nov 2023 19:49:44 +0000 (19:49 +0000)
committerGitHub <noreply@github.com>
Wed, 29 Nov 2023 19:49:44 +0000 (14:49 -0500)
By making the UI elements persistent, it allows tooltips to remain
on-screen when other elements are updated - in particular, the number
of research points, which is updated regularly.

Co-authored-by: Eoin Mcloughlin <helloworld@eoinrul.es>
Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs
Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs

index 5af1159c935184a277cbc73748b736f441b50af0..e7984ccaf91acab4091f2ba7f88746d9831f1472 100644 (file)
@@ -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;
     }
 }
index a20509202fdeea7038878db60dab8b0fd4dbb327..52abd0df084175eb15d758e12ed6f2a279e0d064 100644 (file)
@@ -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<TechnologyPrototype>(unlocked);
-            var cardControl = new MiniTechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech, false));
-            UnlockedCardsContainer.AddChild(cardControl);
-        }
+        var unlockedTech = _technologyDatabase.UnlockedTechnologies.Select(x => _prototype.Index<TechnologyPrototype>(x));
+        SyncTechnologyList(UnlockedCardsContainer, unlockedTech);
     }
 
     public void UpdateInformationPanel(ResearchConsoleBoundInterfaceState state)
@@ -146,5 +137,46 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
             TierDisplayContainer.AddChild(control);
         }
     }
+
+    /// <summary>
+    ///     Synchronize a container for technology cards with a list of technologies,
+    ///     creating or removing UI cards as appropriate.
+    /// </summary>
+    /// <param name="container">The container which contains the UI cards</param>
+    /// <param name="technologies">The current set of technologies for which there should be cards</param>
+    private void SyncTechnologyList(BoxContainer container, IEnumerable<TechnologyPrototype> technologies)
+    {
+        // For the cards which already exist, build a map from technology prototype to the UI card
+        var currentTechControls = new Dictionary<TechnologyPrototype, Control>();
+        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);
+        }
+    }
 }