From 26ffe940b56e98d7d2ebce84da343245bf998aad Mon Sep 17 00:00:00 2001 From: Saphire Lattice Date: Sat, 16 Nov 2024 10:25:06 +0700 Subject: [PATCH] Improve crayon UI to not be stuck in 1996 (#33101) * Improve crayon UI to not be stuck in 1996 * Make a horrifying crayon spaghetti * Crayon * Undeprecate the crayon, describe the crayon --- .../Crayon/UI/CrayonBoundUserInterface.cs | 12 +- Content.Client/Crayon/UI/CrayonWindow.xaml | 11 +- Content.Client/Crayon/UI/CrayonWindow.xaml.cs | 138 ++++- Content.Server/Crayon/CrayonSystem.cs | 2 + .../Crayon/SharedCrayonComponent.cs | 44 +- .../Locale/en-US/crayon/crayon-component.ftl | 7 + Resources/Prototypes/Decals/crayons.yml | 552 +++++++++--------- 7 files changed, 449 insertions(+), 317 deletions(-) diff --git a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs index e5be0b1811f1..44501767dd49 100644 --- a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs +++ b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs @@ -31,7 +31,7 @@ protected override void Open() 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 @@ public override void OnProtoReload(PrototypesReloadedEventArgs args) 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 7729318ae7ff..7acb22551b7d 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 6ef282d219a2..88475562c674 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 @@ public sealed partial class CrayonWindow : DefaultWindow public CrayonWindow() { RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + _spriteSystem = _entitySystem.GetEntitySystem(); - Search.OnTextChanged += _ => RefreshList(); + Search.OnTextChanged += SearchChanged; ColorSelector.OnColorChanged += SelectColor; } @@ -44,51 +53,94 @@ private void SelectColor(Color color) 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)) + { + _selected = first; + _autoSelected = _selected; + OnSelected?.Invoke(_selected); + } + + foreach (var categoryName in names) { - if (!decal.Contains(filter)) + 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 @@ public void UpdateState(CrayonBoundUserInterfaceState state) 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.Server/Crayon/CrayonSystem.cs b/Content.Server/Crayon/CrayonSystem.cs index 07a13d8a34a4..4257c436c23c 100644 --- a/Content.Server/Crayon/CrayonSystem.cs +++ b/Content.Server/Crayon/CrayonSystem.cs @@ -82,6 +82,8 @@ private void OnCrayonAfterInteract(EntityUid uid, CrayonComponent component, Aft if (component.DeleteEmpty && component.Charges <= 0) UseUpCrayon(uid, args.User); + else + _uiSystem.ServerSendUiMessage(uid, SharedCrayonComponent.CrayonUiKey.Key, new CrayonUsedMessage(component.SelectedState)); } private void OnCrayonUse(EntityUid uid, CrayonComponent component, UseInHandEvent args) diff --git a/Content.Shared/Crayon/SharedCrayonComponent.cs b/Content.Shared/Crayon/SharedCrayonComponent.cs index f8e88b218ded..a9c21988ea69 100644 --- a/Content.Shared/Crayon/SharedCrayonComponent.cs +++ b/Content.Shared/Crayon/SharedCrayonComponent.cs @@ -3,12 +3,23 @@ namespace Content.Shared.Crayon { + + /// + /// Component holding the state of a crayon-like component + /// [NetworkedComponent, ComponentProtoName("Crayon"), Access(typeof(SharedCrayonSystem))] public abstract partial class SharedCrayonComponent : Component { + /// + /// The ID of currently selected decal prototype that will be placed when the crayon is used + /// public string SelectedState { get; set; } = string.Empty; - [DataField("color")] public Color Color; + /// + /// Color with which the crayon will draw + /// + [DataField("color")] + public Color Color; [Serializable, NetSerializable] public enum CrayonUiKey : byte @@ -17,6 +28,9 @@ public enum CrayonUiKey : byte } } + /// + /// Used by the client to notify the server about the selected decal ID + /// [Serializable, NetSerializable] public sealed class CrayonSelectMessage : BoundUserInterfaceMessage { @@ -27,6 +41,9 @@ public CrayonSelectMessage(string selected) } } + /// + /// Sets the color of the crayon, used by Rainbow Crayon + /// [Serializable, NetSerializable] public sealed class CrayonColorMessage : BoundUserInterfaceMessage { @@ -37,13 +54,25 @@ public CrayonColorMessage(Color color) } } + /// + /// Server to CLIENT. Notifies the BUI that a decal with given ID has been drawn. + /// Allows the client UI to advance forward in the client-only ephemeral queue, + /// preventing the crayon from becoming a magic text storage device. + /// [Serializable, NetSerializable] - public enum CrayonVisuals + public sealed class CrayonUsedMessage : BoundUserInterfaceMessage { - State, - Color + public readonly string DrawnDecal; + + public CrayonUsedMessage(string drawn) + { + DrawnDecal = drawn; + } } + /// + /// Component state, describes how many charges are left in the crayon in the near-hand UI + /// [Serializable, NetSerializable] public sealed class CrayonComponentState : ComponentState { @@ -60,10 +89,17 @@ public CrayonComponentState(Color color, string state, int charges, int capacity Capacity = capacity; } } + + /// + /// The state of the crayon UI as sent by the server + /// [Serializable, NetSerializable] public sealed class CrayonBoundUserInterfaceState : BoundUserInterfaceState { public string Selected; + /// + /// Whether or not the color can be selected + /// public bool SelectableColor; public Color Color; diff --git a/Resources/Locale/en-US/crayon/crayon-component.ftl b/Resources/Locale/en-US/crayon/crayon-component.ftl index 444ffa4c45ef..e13bf76941cb 100644 --- a/Resources/Locale/en-US/crayon/crayon-component.ftl +++ b/Resources/Locale/en-US/crayon/crayon-component.ftl @@ -8,3 +8,10 @@ crayon-interact-invalid-location = Can't reach there! ## UI crayon-window-title = Crayon +crayon-window-placeholder = Search, or queue a comma-separated list of names +crayon-category-1-brushes = Brushes +crayon-category-2-alphanum = Numbers and letters +crayon-category-3-symbols = Symbols +crayon-category-4-info = Signs +crayon-category-5-graffiti = Graffiti +crayon-category-random = Random diff --git a/Resources/Prototypes/Decals/crayons.yml b/Resources/Prototypes/Decals/crayons.yml index 3be2ec242615..a15619d483cc 100644 --- a/Resources/Prototypes/Decals/crayons.yml +++ b/Resources/Prototypes/Decals/crayons.yml @@ -1,6 +1,6 @@ - type: decal id: 0 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -10,7 +10,7 @@ - type: decal id: 1 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -20,7 +20,7 @@ - type: decal id: 2 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -30,7 +30,7 @@ - type: decal id: 3 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -40,7 +40,7 @@ - type: decal id: 4 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -50,7 +50,7 @@ - type: decal id: 5 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -60,7 +60,7 @@ - type: decal id: 6 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -70,7 +70,7 @@ - type: decal id: 7 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -80,7 +80,7 @@ - type: decal id: 8 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -90,7 +90,7 @@ - type: decal id: 9 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -100,7 +100,7 @@ - type: decal id: Blasto - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -110,7 +110,7 @@ - type: decal id: Clandestine - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -120,7 +120,7 @@ - type: decal id: Cyber - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -130,7 +130,7 @@ - type: decal id: Diablo - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -140,7 +140,7 @@ - type: decal id: Donk - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -150,7 +150,7 @@ - type: decal id: Gene - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -160,7 +160,7 @@ - type: decal id: Gib - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -170,7 +170,7 @@ - type: decal id: Max - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -180,7 +180,7 @@ - type: decal id: Newton - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -190,7 +190,7 @@ - type: decal id: North - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -200,7 +200,7 @@ - type: decal id: Omni - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -210,7 +210,7 @@ - type: decal id: Osiron - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -220,7 +220,7 @@ - type: decal id: Prima - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -230,7 +230,7 @@ - type: decal id: Psyke - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -240,7 +240,7 @@ - type: decal id: Sirius - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -250,7 +250,7 @@ - type: decal id: Tunnel - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -260,7 +260,7 @@ - type: decal id: Waffle - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -268,19 +268,9 @@ sprite: Effects/crayondecals.rsi state: Waffle -- type: decal - id: a - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: a - - type: decal id: ampersand - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -290,7 +280,7 @@ - type: decal id: amyjon - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -300,7 +290,7 @@ - type: decal id: arrow - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -308,16 +298,6 @@ sprite: Effects/crayondecals.rsi state: arrow -- type: decal - id: b - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: b - - type: decal id: beepsky tags: ["crayon"] @@ -330,7 +310,7 @@ - type: decal id: biohazard - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -370,7 +350,7 @@ - type: decal id: brush - tags: ["crayon"] + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -378,16 +358,6 @@ sprite: Effects/crayondecals.rsi state: brush -- type: decal - id: c - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: c - - type: decal id: carp tags: ["crayon"] @@ -410,7 +380,7 @@ - type: decal id: chevron - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -440,7 +410,7 @@ - type: decal id: comma - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -460,7 +430,7 @@ - type: decal id: credit - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -470,7 +440,7 @@ - type: decal id: cyka - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -478,19 +448,9 @@ sprite: Effects/crayondecals.rsi state: cyka -- type: decal - id: d - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: d - - type: decal id: danger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -510,7 +470,7 @@ - type: decal id: dot - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -528,19 +488,9 @@ sprite: Effects/crayondecals.rsi state: dwarf -- type: decal - id: e - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: e - - type: decal id: electricdanger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -550,7 +500,7 @@ - type: decal id: end - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -560,7 +510,7 @@ - type: decal id: engie - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -570,7 +520,7 @@ - type: decal id: equals - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -580,7 +530,7 @@ - type: decal id: evac - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -590,7 +540,7 @@ - type: decal id: exclamationmark - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -598,16 +548,6 @@ sprite: Effects/crayondecals.rsi state: exclamationmark -- type: decal - id: f - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: f - - type: decal id: face tags: ["crayon"] @@ -630,7 +570,7 @@ - type: decal id: firedanger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -640,7 +580,7 @@ - type: decal id: food - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -659,598 +599,658 @@ state: footprint - type: decal - id: g + id: ghost tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: g + state: ghost - type: decal - id: ghost + id: guy tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: ghost + state: guy - type: decal - id: guy - tags: ["crayon"] + id: heart + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: guy + state: heart - type: decal - id: h - tags: ["crayon"] + id: largebrush + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: h + state: largebrush - type: decal - id: heart - tags: ["crayon"] + id: like + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: heart + state: like - type: decal - id: i - tags: ["crayon"] + id: line + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: i + state: line - type: decal - id: j - tags: ["crayon"] + id: matt + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: j + state: matt - type: decal - id: k - tags: ["crayon"] + id: med + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: k + state: med - type: decal - id: l - tags: ["crayon"] + id: minus + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: l + state: minus - type: decal - id: largebrush - tags: ["crayon"] + id: nay + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: largebrush + state: nay - type: decal - id: like + id: pawprint tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: like + state: pawprint - type: decal - id: line - tags: ["crayon"] + id: peace + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: line + state: peace - type: decal - id: m - tags: ["crayon"] + id: percent + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: m + state: percent - type: decal - id: matt - tags: ["crayon"] + id: plus + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: matt + state: plus - type: decal - id: med - tags: ["crayon"] + id: pound + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: med + state: pound - type: decal - id: minus - tags: ["crayon"] + id: prolizard + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: minus + state: prolizard - type: decal - id: n - tags: ["crayon"] + id: questionmark + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: n + state: questionmark - type: decal - id: nay - tags: ["crayon"] + id: radiation + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: nay + state: radiation - type: decal - id: o - tags: ["crayon"] + id: revolution + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: o + state: revolution - type: decal - id: p - tags: ["crayon"] + id: rune1 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: p + state: rune1 - type: decal - id: pawprint - tags: ["crayon"] + id: rune2 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: pawprint + state: rune2 - type: decal - id: peace - tags: ["crayon"] + id: rune3 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: peace + state: rune3 - type: decal - id: percent - tags: ["crayon"] + id: rune4 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: percent + state: rune4 - type: decal - id: plus - tags: ["crayon"] + id: rune5 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: plus + state: rune5 - type: decal - id: pound - tags: ["crayon"] + id: rune6 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: pound + state: rune6 - type: decal - id: prolizard - tags: ["crayon"] + id: safe + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: prolizard + state: safe - type: decal - id: q + id: scroll tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: q + state: scroll - type: decal - id: questionmark - tags: ["crayon"] + id: shop + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: questionmark + state: shop - type: decal - id: r - tags: ["crayon"] + id: shortline + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: r + state: shortline - type: decal - id: radiation + id: shotgun tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: radiation + state: shotgun - type: decal - id: revolution - tags: ["crayon"] + id: skull + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: revolution + state: skull - type: decal - id: rune1 - tags: ["crayon"] + id: slash + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune1 + state: slash - type: decal - id: rune2 - tags: ["crayon"] + id: smallbrush + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune2 + state: smallbrush - type: decal - id: rune3 + id: snake tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune3 + state: snake - type: decal - id: rune4 - tags: ["crayon"] + id: space + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune4 + state: space - type: decal - id: rune5 + id: splatter tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune5 + state: splatter - type: decal - id: rune6 - tags: ["crayon"] + id: star + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune6 + state: star - type: decal - id: s + id: stickman tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: s + state: stickman - type: decal - id: safe + id: taser tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: safe + state: taser - type: decal - id: scroll - tags: ["crayon"] + id: thinline + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: scroll + state: thinline - type: decal - id: shop + id: toilet tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shop + state: toilet - type: decal - id: shortline + id: toolbox tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shortline + state: toolbox - type: decal - id: shotgun - tags: ["crayon"] + id: trade + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shotgun + state: trade - type: decal - id: skull + id: uboa tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: skull + state: uboa - type: decal - id: slash - tags: ["crayon"] + id: a + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: slash + state: a - type: decal - id: smallbrush - tags: ["crayon"] + id: b + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: smallbrush + state: b - type: decal - id: snake - tags: ["crayon"] + id: c + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: snake + state: c - type: decal - id: space - tags: ["crayon"] + id: d + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: space + state: d - type: decal - id: splatter - tags: ["crayon"] + id: e + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: splatter + state: e - type: decal - id: star - tags: ["crayon"] + id: f + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: star + state: f - type: decal - id: stickman - tags: ["crayon"] + id: g + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: stickman + state: g - type: decal - id: t - tags: ["crayon"] + id: h + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: t + state: h - type: decal - id: taser - tags: ["crayon"] + id: i + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: taser + state: i - type: decal - id: thinline - tags: ["crayon"] + id: j + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: thinline + state: j - type: decal - id: toilet - tags: ["crayon"] + id: k + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: toilet + state: k - type: decal - id: toolbox - tags: ["crayon"] + id: l + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: toolbox + state: l - type: decal - id: trade - tags: ["crayon"] + id: m + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: trade + state: m - type: decal - id: u - tags: ["crayon"] + id: n + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: u + state: n - type: decal - id: uboa - tags: ["crayon"] + id: o + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: uboa + state: o + +- type: decal + id: p + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: p + +- type: decal + id: q + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: q + +- type: decal + id: r + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: r + +- type: decal + id: s + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: s + +- type: decal + id: t + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: t + +- type: decal + id: u + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: u - type: decal id: v - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1260,7 +1260,7 @@ - type: decal id: w - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1270,7 +1270,7 @@ - type: decal id: x - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1280,7 +1280,7 @@ - type: decal id: y - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1290,7 +1290,7 @@ - type: decal id: z - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false