Construction menu grid view (#32577)
* 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
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
recipesList.Add(GetItem(recipe, recipesList));
|
||||
}
|
||||
var recipesList = _constructionView.Recipes;
|
||||
recipesList.Clear();
|
||||
|
||||
// There is apparently no way to set which
|
||||
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
|
||||
{
|
||||
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;
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user