]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Construction menu grid view (#32577)
authorqwerltaz <69696513+qwerltaz@users.noreply.github.com>
Wed, 20 Nov 2024 01:54:49 +0000 (02:54 +0100)
committerGitHub <noreply@github.com>
Wed, 20 Nov 2024 01:54:49 +0000 (12:54 +1100)
* button

* implement populate grid view

* tweak min width

* Make grid button toggle visible

* tweak min window size

* fix missing recipe button when mirroring item

* make grid buttons toggleable

* align button texture vertically

* selected grid item has plain color background

* tweak window width so all buttons look good

* rename select method, defer colouring

* get icon better

* whoops

* simpler button toggle

* spritesys frame0, move spritesys

* delete old sprite system refs

Content.Client/Construction/UI/ConstructionMenu.xaml
Content.Client/Construction/UI/ConstructionMenu.xaml.cs
Content.Client/Construction/UI/ConstructionMenuPresenter.cs
Resources/Locale/en-US/construction/ui/construction-menu.ftl

index 6e4438cf6fdc6c8df8513b9934b6cce80d7fe113..a934967a5334394e911ef114856d7f96681498ae 100644 (file)
@@ -1,15 +1,20 @@
 <DefaultWindow xmlns="https://spacestation14.io">
     <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
-        <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4" Margin="0 0 5 0">
+        <BoxContainer Orientation="Vertical" MinWidth="243" Margin="0 0 5 0">
             <BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 0 0 5">
                 <LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True"/>
                 <OptionButton Name="OptionCategories" Access="Public" MinSize="130 0"/>
             </BoxContainer>
             <ItemList Name="Recipes" Access="Public" SelectMode="Single" VerticalExpand="True"/>
+            <ScrollContainer Name="RecipesGridScrollContainer" VerticalExpand="True" Access="Public" Visible="False">
+                <GridContainer Name="RecipesGrid" Columns="5" Access="Public"/>
+            </ScrollContainer>
         </BoxContainer>
-        <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.6">
-            <Button Name="FavoriteButton" Visible="false" HorizontalExpand="False"
-                HorizontalAlignment="Right" Margin="0 0 0 15"/>
+        <BoxContainer Orientation="Vertical" HorizontalExpand="True">
+            <BoxContainer Orientation="Horizontal">
+                <Button Name="MenuGridViewButton" ToggleMode="True" Text="{Loc construction-menu-grid-view}"/>
+                <Button Name="FavoriteButton" Visible="false"/>
+            </BoxContainer>
             <Control>
                 <BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="0 0 0 5">
                     <BoxContainer Orientation="Horizontal" Align="Center">
index f0cb8148762591ac1c39d9a0f772cfbdabe9caf2..9ab8a156005a38537e76c1c27263d12a462d5fa0 100644 (file)
@@ -25,11 +25,16 @@ namespace Content.Client.Construction.UI
         OptionButton OptionCategories { get; }
 
         bool EraseButtonPressed { get; set; }
+        bool GridViewButtonPressed { get; set; }
         bool BuildButtonPressed { get; set; }
 
         ItemList Recipes { get; }
         ItemList RecipeStepList { get; }
 
+
+        ScrollContainer RecipesGridScrollContainer { get; }
+        GridContainer RecipesGrid { get; }
+
         event EventHandler<(string search, string catagory)> PopulateRecipes;
         event EventHandler<ItemList.Item?> RecipeSelected;
         event EventHandler RecipeFavorited;
@@ -72,9 +77,16 @@ namespace Content.Client.Construction.UI
             set => EraseButton.Pressed = value;
         }
 
+        public bool GridViewButtonPressed
+        {
+            get => MenuGridViewButton.Pressed;
+            set => MenuGridViewButton.Pressed = value;
+        }
+
         public ConstructionMenu()
         {
-            SetSize = MinSize = new Vector2(720, 320);
+            SetSize = new Vector2(560, 450);
+            MinSize = new Vector2(560, 320);
 
             IoCManager.InjectDependencies(this);
             RobustXamlLoader.Load(this);
@@ -102,6 +114,9 @@ namespace Content.Client.Construction.UI
             EraseButton.OnToggled += args => EraseButtonToggled?.Invoke(this, args.Pressed);
 
             FavoriteButton.OnPressed += args => RecipeFavorited?.Invoke(this, EventArgs.Empty);
+
+            MenuGridViewButton.OnPressed += _ =>
+                PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[OptionCategories.SelectedId]));
         }
 
         public event EventHandler? ClearAllGhosts;
index c315cdedb2ca92d8ae6fd35b4e38b20da3dc055c..d35e8fbe76990f2fc129e1fc99d31a2456af4e76 100644 (file)
@@ -1,7 +1,8 @@
 using System.Linq;
+using System.Numerics;
+using Content.Client.Stylesheets;
 using Content.Client.UserInterface.Systems.MenuBar.Widgets;
 using Content.Shared.Construction.Prototypes;
-using Content.Shared.Tag;
 using Content.Shared.Whitelist;
 using Robust.Client.GameObjects;
 using Robust.Client.Graphics;
@@ -11,7 +12,6 @@ using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 using Robust.Client.Utility;
 using Robust.Shared.Enums;
-using Robust.Shared.Graphics;
 using Robust.Shared.Prototypes;
 using static Robust.Client.UserInterface.Controls.BaseButton;
 
@@ -33,10 +33,12 @@ namespace Content.Client.Construction.UI
 
         private readonly IConstructionMenuView _constructionView;
         private readonly EntityWhitelistSystem _whitelistSystem;
+        private readonly SpriteSystem _spriteSystem;
 
         private ConstructionSystem? _constructionSystem;
         private ConstructionPrototype? _selected;
         private List<ConstructionPrototype> _favoritedRecipes = [];
+        private Dictionary<string, TextureButton> _recipeButtons = new();
         private string _selectedCategory = string.Empty;
         private string _favoriteCatName = "construction-category-favorites";
         private string _forAllCategoryName = "construction-category-all";
@@ -85,6 +87,7 @@ namespace Content.Client.Construction.UI
             IoCManager.InjectDependencies(this);
             _constructionView = new ConstructionMenu();
             _whitelistSystem = _entManager.System<EntityWhitelistSystem>();
+            _spriteSystem = _entManager.System<SpriteSystem>();
 
             // This is required so that if we load after the system is initialized, we can bind to it immediately
             if (_systemManager.TryGetEntitySystem<ConstructionSystem>(out var constructionSystem))
@@ -150,12 +153,24 @@ namespace Content.Client.Construction.UI
             PopulateInfo(_selected);
         }
 
+        private void OnGridViewRecipeSelected(object? sender, ConstructionPrototype? recipe)
+        {
+            if (recipe is null)
+            {
+                _selected = null;
+                _constructionView.ClearRecipeInfo();
+                return;
+            }
+
+            _selected = recipe;
+            if (_placementManager.IsActive && !_placementManager.Eraser) UpdateGhostPlacement();
+            PopulateInfo(_selected);
+        }
+
         private void OnViewPopulateRecipes(object? sender, (string search, string catagory) args)
         {
             var (search, category) = args;
-            var recipesList = _constructionView.Recipes;
 
-            recipesList.Clear();
             var recipes = new List<ConstructionPrototype>();
 
             var isEmptyCategory = string.IsNullOrEmpty(category) || category == _forAllCategoryName;
@@ -201,12 +216,73 @@ namespace Content.Client.Construction.UI
 
             recipes.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.InvariantCulture));
 
-            foreach (var recipe in recipes)
+            var recipesList = _constructionView.Recipes;
+            recipesList.Clear();
+
+            var recipesGrid = _constructionView.RecipesGrid;
+            recipesGrid.RemoveAllChildren();
+
+            _constructionView.RecipesGridScrollContainer.Visible = _constructionView.GridViewButtonPressed;
+            _constructionView.Recipes.Visible = !_constructionView.GridViewButtonPressed;
+
+            if (_constructionView.GridViewButtonPressed)
+            {
+                foreach (var recipe in recipes)
+                {
+                    var itemButton = new TextureButton
+                    {
+                        TextureNormal = _spriteSystem.Frame0(recipe.Icon),
+                        VerticalAlignment = Control.VAlignment.Center,
+                        Name = recipe.Name,
+                        ToolTip = recipe.Name,
+                        Scale = new Vector2(1.35f),
+                        ToggleMode = true,
+                    };
+                    var itemButtonPanelContainer = new PanelContainer
+                    {
+                        PanelOverride = new StyleBoxFlat { BackgroundColor = StyleNano.ButtonColorDefault },
+                        Children = { itemButton },
+                    };
+
+                    itemButton.OnToggled += buttonToggledEventArgs =>
+                    {
+                        SelectGridButton(itemButton, buttonToggledEventArgs.Pressed);
+
+                        if (buttonToggledEventArgs.Pressed &&
+                            _selected != null &&
+                            _recipeButtons.TryGetValue(_selected.Name, out var oldButton))
+                        {
+                            oldButton.Pressed = false;
+                            SelectGridButton(oldButton, false);
+                        }
+
+                        OnGridViewRecipeSelected(this, buttonToggledEventArgs.Pressed ? recipe : null);
+                    };
+
+                    recipesGrid.AddChild(itemButtonPanelContainer);
+                    _recipeButtons[recipe.Name] = itemButton;
+                    var isCurrentButtonSelected = _selected == recipe;
+                    itemButton.Pressed = isCurrentButtonSelected;
+                    SelectGridButton(itemButton, isCurrentButtonSelected);
+                }
+            }
+            else
             {
-                recipesList.Add(GetItem(recipe, recipesList));
+                foreach (var recipe in recipes)
+                {
+                    recipesList.Add(GetItem(recipe, recipesList));
+                }
             }
+        }
+
+        private void SelectGridButton(TextureButton button, bool select)
+        {
+            if (button.Parent is not PanelContainer buttonPanel)
+                return;
 
-            // There is apparently no way to set which
+            button.Modulate = select ? Color.Green : Color.White;
+            var buttonColor = select ? StyleNano.ButtonColorDefault : Color.Transparent;
+            buttonPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = buttonColor };
         }
 
         private void PopulateCategories(string? selectCategory = null)
@@ -257,11 +333,10 @@ namespace Content.Client.Construction.UI
 
         private void PopulateInfo(ConstructionPrototype prototype)
         {
-            var spriteSys = _systemManager.GetEntitySystem<SpriteSystem>();
             _constructionView.ClearRecipeInfo();
 
             _constructionView.SetRecipeInfo(
-                prototype.Name, prototype.Description, spriteSys.Frame0(prototype.Icon),
+                prototype.Name, prototype.Description, _spriteSystem.Frame0(prototype.Icon),
                 prototype.Type != ConstructionType.Item,
                 !_favoritedRecipes.Contains(prototype));
 
@@ -274,7 +349,6 @@ namespace Content.Client.Construction.UI
             if (_constructionSystem?.GetGuide(prototype) is not { } guide)
                 return;
 
-            var spriteSys = _systemManager.GetEntitySystem<SpriteSystem>();
 
             foreach (var entry in guide.Entries)
             {
@@ -290,20 +364,20 @@ namespace Content.Client.Construction.UI
                 // The padding needs to be applied regardless of text length... (See PadLeft documentation)
                 text = text.PadLeft(text.Length + entry.Padding);
 
-                var icon = entry.Icon != null ? spriteSys.Frame0(entry.Icon) : Texture.Transparent;
+                var icon = entry.Icon != null ? _spriteSystem.Frame0(entry.Icon) : Texture.Transparent;
                 stepList.AddItem(text, icon, false);
             }
         }
 
-        private static ItemList.Item GetItem(ConstructionPrototype recipe, ItemList itemList)
+        private ItemList.Item GetItem(ConstructionPrototype recipe, ItemList itemList)
         {
             return new(itemList)
             {
                 Metadata = recipe,
                 Text = recipe.Name,
-                Icon = recipe.Icon.Frame0(),
+                Icon = _spriteSystem.Frame0(recipe.Icon),
                 TooltipEnabled = true,
-                TooltipText = recipe.Description
+                TooltipText = recipe.Description,
             };
         }
 
index 82ebc01bc99d5b194f26f0b3249ea0ceadce5810..4d100247856f62304bcc3132cd861d602dd28428 100644 (file)
@@ -5,3 +5,4 @@ construction-menu-place-ghost = Place construction ghost
 construction-menu-clear-all = Clear All
 construction-menu-eraser-mode = Eraser Mode
 construction-menu-craft = Craft
+construction-menu-grid-view = Grid View