diff --git a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs index e5be0b1811..44501767dd 100644 --- a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs +++ b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs @@ -31,7 +31,7 @@ namespace Content.Client.Crayon.UI private void PopulateCrayons() { var crayonDecals = _protoManager.EnumeratePrototypes().Where(x => x.Tags.Contains("crayon")); - _menu?.Populate(crayonDecals); + _menu?.Populate(crayonDecals.ToList()); } public override void OnProtoReload(PrototypesReloadedEventArgs args) @@ -44,6 +44,16 @@ namespace Content.Client.Crayon.UI PopulateCrayons(); } + protected override void ReceiveMessage(BoundUserInterfaceMessage message) + { + base.ReceiveMessage(message); + + if (_menu is null || message is not CrayonUsedMessage crayonMessage) + return; + + _menu.AdvanceState(crayonMessage.DrawnDecal); + } + protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); diff --git a/Content.Client/Crayon/UI/CrayonWindow.xaml b/Content.Client/Crayon/UI/CrayonWindow.xaml index 7729318ae7..7acb22551b 100644 --- a/Content.Client/Crayon/UI/CrayonWindow.xaml +++ b/Content.Client/Crayon/UI/CrayonWindow.xaml @@ -1,14 +1,13 @@  + MinSize="450 500" + SetSize="450 500"> - + - - - + + diff --git a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs index 6ef282d219..88475562c6 100644 --- a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs +++ b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; +using System.Linq; using Content.Client.Stylesheets; using Content.Shared.Crayon; using Content.Shared.Decals; using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; @@ -18,7 +20,12 @@ namespace Content.Client.Crayon.UI [GenerateTypedNameReferences] public sealed partial class CrayonWindow : DefaultWindow { - private Dictionary? _decals; + [Dependency] private readonly IEntitySystemManager _entitySystem = default!; + private readonly SpriteSystem _spriteSystem = default!; + + private Dictionary>? _decals; + private List? _allDecals; + private string? _autoSelected; private string? _selected; private Color _color; @@ -28,8 +35,10 @@ namespace Content.Client.Crayon.UI public CrayonWindow() { RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + _spriteSystem = _entitySystem.GetEntitySystem(); - Search.OnTextChanged += _ => RefreshList(); + Search.OnTextChanged += SearchChanged; ColorSelector.OnColorChanged += SelectColor; } @@ -44,51 +53,94 @@ namespace Content.Client.Crayon.UI private void RefreshList() { // Clear - Grid.DisposeAllChildren(); - if (_decals == null) + Grids.DisposeAllChildren(); + + if (_decals == null || _allDecals == null) return; var filter = Search.Text; - foreach (var (decal, tex) in _decals) + var comma = filter.IndexOf(','); + var first = (comma == -1 ? filter : filter[..comma]).Trim(); + + var names = _decals.Keys.ToList(); + names.Sort((a, b) => a == "random" ? 1 : b == "random" ? -1 : a.CompareTo(b)); + + if (_autoSelected != null && first != _autoSelected && _allDecals.Contains(first)) { - if (!decal.Contains(filter)) + _selected = first; + _autoSelected = _selected; + OnSelected?.Invoke(_selected); + } + + foreach (var categoryName in names) + { + var locName = Loc.GetString("crayon-category-" + categoryName); + var category = _decals[categoryName].Where(d => locName.Contains(first) || d.Name.Contains(first)).ToList(); + + if (category.Count == 0) continue; - var button = new TextureButton() + var label = new Label { - TextureNormal = tex, - Name = decal, - ToolTip = decal, - Modulate = _color, + Text = locName }; - button.OnPressed += ButtonOnPressed; - if (_selected == decal) + + var grid = new GridContainer { - var panelContainer = new PanelContainer() + Columns = 6, + Margin = new Thickness(0, 0, 0, 16) + }; + + Grids.AddChild(label); + Grids.AddChild(grid); + + foreach (var (name, texture) in category) + { + var button = new TextureButton() { - PanelOverride = new StyleBoxFlat() - { - BackgroundColor = StyleNano.ButtonColorDefault, - }, - Children = - { - button, - }, + TextureNormal = texture, + Name = name, + ToolTip = name, + Modulate = _color, + Scale = new System.Numerics.Vector2(2, 2) }; - Grid.AddChild(panelContainer); - } - else - { - Grid.AddChild(button); + button.OnPressed += ButtonOnPressed; + + if (_selected == name) + { + var panelContainer = new PanelContainer() + { + PanelOverride = new StyleBoxFlat() + { + BackgroundColor = StyleNano.ButtonColorDefault, + }, + Children = + { + button, + }, + }; + grid.AddChild(panelContainer); + } + else + { + grid.AddChild(button); + } } } } + private void SearchChanged(LineEdit.LineEditEventArgs obj) + { + _autoSelected = ""; // Placeholder to kick off the auto-select in refreshlist() + RefreshList(); + } + private void ButtonOnPressed(ButtonEventArgs obj) { if (obj.Button.Name == null) return; _selected = obj.Button.Name; + _autoSelected = null; OnSelected?.Invoke(_selected); RefreshList(); } @@ -107,12 +159,38 @@ namespace Content.Client.Crayon.UI RefreshList(); } - public void Populate(IEnumerable prototypes) + public void AdvanceState(string drawnDecal) { - _decals = new Dictionary(); + var filter = Search.Text; + if (!filter.Contains(',') || !filter.Contains(drawnDecal)) + return; + + var first = filter[..filter.IndexOf(',')].Trim(); + + if (first.Equals(drawnDecal, StringComparison.InvariantCultureIgnoreCase)) + { + Search.Text = filter[(filter.IndexOf(',') + 1)..].Trim(); + _autoSelected = first; + } + + RefreshList(); + } + + public void Populate(List prototypes) + { + _decals = []; + _allDecals = []; + + prototypes.Sort((a, b) => a.ID.CompareTo(b.ID)); + foreach (var decalPrototype in prototypes) { - _decals.Add(decalPrototype.ID, decalPrototype.Sprite.Frame0()); + var category = "random"; + if (decalPrototype.Tags.Count > 1 && decalPrototype.Tags[1].StartsWith("crayon-")) + category = decalPrototype.Tags[1].Replace("crayon-", ""); + var list = _decals.GetOrNew(category); + list.Add((decalPrototype.ID, _spriteSystem.Frame0(decalPrototype.Sprite))); + _allDecals.Add(decalPrototype.ID); } RefreshList(); diff --git a/Content.Client/Lobby/LobbyUIController.cs b/Content.Client/Lobby/LobbyUIController.cs index 91cbacd2a2..3a2e9e2c5e 100644 --- a/Content.Client/Lobby/LobbyUIController.cs +++ b/Content.Client/Lobby/LobbyUIController.cs @@ -282,7 +282,7 @@ public sealed partial class LobbyUIController : UIController, IOnStateEntered { diff --git a/Content.Client/Lobby/UI/CharacterSetupGui.xaml b/Content.Client/Lobby/UI/CharacterSetupGui.xaml index 9fd0d4ed17..ab93985b87 100644 --- a/Content.Client/Lobby/UI/CharacterSetupGui.xaml +++ b/Content.Client/Lobby/UI/CharacterSetupGui.xaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client" xmlns:style="clr-namespace:Content.Client.Stylesheets" + xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls" VerticalExpand="True"> @@ -10,16 +11,15 @@