Files
tbd-station-14/Content.Client/SprayPainter/UI/SprayPainterDecals.xaml.cs
Whatstone 9ad99cfa64 Make more objects spray paintable (Reviving #31328) (#37341)
* PaintableAirlockComponent and AirlockGroupPrototype have been replaced

* Slightly redesigned SprayPainterSystem for greater versatility

* Added handling of changes to the appearance of doors and storages

* PaintableGroup prototypes have been created

* Generating tabs with styles in the UI

* Fix error with undiscovered layer

* Slight improvement

* Removed unnecessary property

* The category for `PaintableGroup` was allocated to a separate prototype so that the engine itself would check if the category existed

* Added canisters, but repainting doesn't work

* Added localization to styles

* Fix sprite changing

* Added the ability to paint canisters

* slight ui improvement

* Fix yamllinter errors

* Fix test

* The UI now remembers which tab was open

* Fix build (?)

* Rename

* Charges have been added to the spray painter

* Added a charge texture for the spray painter

* Now spray painter can paint decals

* Increased number of charges

* Spawning dummy objects has been replaced by PrototypeManager

* added a signature about the painting of the object

* fix

* Code commenting

* Fix upstream

* Update Content.Shared/SprayPainter/Components/SprayPainterAmmo.cs

Co-authored-by: pathetic meowmeow <uhhadd@gmail.com>

* review

* Now decals can only be painted if the corresponding tab in the menu is open.

* Fixed a bug with pipe and decal tabs not being remembered

* Update EntityStorageVisualizerSystem.cs

* record

* loc

* Cleanup

* Revert electrified visuals

* more cleanup, fix charges, del ammo4

* no empty file, remove meta component

* closet exceptions, storage visualizer fixes

* enable/disable decal through alt-verb

* Fix missed merge conflicts

* fix snap offset, button event handlers

* simpler order, fix snap loc string

* Remove PaintableViz.BaseRSI, no decal item, A-Z

* State-respecting UI, BUI updates, FTL fixes

* revert DecalPlacerWindow changes

* revert unwanted changes, cleanup function order

* Limit SprayPainterAmmo write access to AmmoSystem

* Remove PaintedSystem

* spray paint ammo lathe recipe, youtool listing

* category as a list, groups as subtabs

* Restore inhand copyright in meta.json

* empty spray painter, recipe produces an empty one

* allow alpha on spray painter decals

* add comments

* paintable wall lockers

* Restrict painting more objects

* Suggested event changes, event cleanup

* component comments, fix ammo inhands

* uncleanable decals, dirty styles on mapinit

* organize paintables, separate emergency/closet grp

* fix categories newline at EOF

* airlock group whitespace cleanup

* realphabetize

* Clean up EntityStorageViz merge conflict markers

* Apply requested changes

* Apply suggestions from sowelipililimute's review

Co-authored-by: pathetic meowmeow <uhhadd@gmail.com>

* betrayal most foul

* Remove members from EntityPaintedEvent

* No emerg. group, steelsec to secure, locker/closet

* Enable repainting the medical wall locker

* comments, no flags on PaintableVisuals

* Remove locked variants from closets/wall closets

* removable decals

* off value consistency

* can't paint away those bones

* fix precedence

* Remove AirlockDepartment, AirlockGroup protos

Both unused.

* whitelist consistency re: ammo component

* add standing emergency closet styles

* alphabetize the spray painter listings

---------

Co-authored-by: Ertanic <black.ikra.14@gmail.com>
Co-authored-by: Эдуард <36124833+Ertanic@users.noreply.github.com>
Co-authored-by: pathetic meowmeow <uhhadd@gmail.com>
2025-07-10 20:36:57 -04:00

175 lines
4.9 KiB
C#

using System.Numerics;
using Content.Client.Stylesheets;
using Content.Shared.Decals;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client.SprayPainter.UI;
/// <summary>
/// Used to control decal painting parameters for the spray painter.
/// </summary>
[GenerateTypedNameReferences]
public sealed partial class SprayPainterDecals : Control
{
public Action<ProtoId<DecalPrototype>>? OnDecalSelected;
public Action<Color?>? OnColorChanged;
public Action<int>? OnAngleChanged;
public Action<bool>? OnSnapChanged;
private SpriteSystem? _sprite;
private string _selectedDecal = string.Empty;
private List<SprayPainterDecalEntry> _decals = [];
public SprayPainterDecals()
{
RobustXamlLoader.Load(this);
AddAngleButton.OnButtonUp += _ => AngleSpinBox.Value += 90;
SubAngleButton.OnButtonUp += _ => AngleSpinBox.Value -= 90;
SetZeroAngleButton.OnButtonUp += _ => AngleSpinBox.Value = 0;
AngleSpinBox.ValueChanged += args => OnAngleChanged?.Invoke(args.Value);
UseCustomColorCheckBox.OnPressed += UseCustomColorCheckBoxOnOnPressed;
SnapToTileCheckBox.OnPressed += SnapToTileCheckBoxOnOnPressed;
ColorSelector.OnColorChanged += OnColorSelected;
}
private void UseCustomColorCheckBoxOnOnPressed(BaseButton.ButtonEventArgs _)
{
OnColorChanged?.Invoke(UseCustomColorCheckBox.Pressed ? ColorSelector.Color : null);
UpdateColorButtons(UseCustomColorCheckBox.Pressed);
}
private void SnapToTileCheckBoxOnOnPressed(BaseButton.ButtonEventArgs _)
{
OnSnapChanged?.Invoke(SnapToTileCheckBox.Pressed);
}
/// <summary>
/// Updates the decal list.
/// </summary>
public void PopulateDecals(List<SprayPainterDecalEntry> decals, SpriteSystem sprite)
{
_sprite ??= sprite;
_decals = decals;
DecalsGrid.Children.Clear();
foreach (var decal in decals)
{
var button = new TextureButton()
{
TextureNormal = sprite.Frame0(decal.Sprite),
Name = decal.Name,
ToolTip = decal.Name,
Scale = new Vector2(2, 2),
};
button.OnPressed += DecalButtonOnPressed;
if (UseCustomColorCheckBox.Pressed)
{
button.Modulate = ColorSelector.Color;
}
if (_selectedDecal == decal.Name)
{
var panelContainer = new PanelContainer()
{
PanelOverride = new StyleBoxFlat()
{
BackgroundColor = StyleNano.ButtonColorDefault,
},
Children =
{
button,
},
};
DecalsGrid.AddChild(panelContainer);
}
else
{
DecalsGrid.AddChild(button);
}
}
}
private void OnColorSelected(Color color)
{
if (!UseCustomColorCheckBox.Pressed)
return;
OnColorChanged?.Invoke(color);
UpdateColorButtons(UseCustomColorCheckBox.Pressed);
}
private void UpdateColorButtons(bool apply)
{
Color modulateColor = apply ? ColorSelector.Color : Color.White;
foreach (var button in DecalsGrid.Children)
{
switch (button)
{
case TextureButton:
button.Modulate = modulateColor;
break;
case PanelContainer panelContainer:
{
foreach (TextureButton textureButton in panelContainer.Children)
textureButton.Modulate = modulateColor;
break;
}
}
}
}
private void DecalButtonOnPressed(BaseButton.ButtonEventArgs obj)
{
if (obj.Button.Name is not { } name)
return;
_selectedDecal = name;
OnDecalSelected?.Invoke(_selectedDecal);
if (_sprite is null)
return;
PopulateDecals(_decals, _sprite);
}
public void SetSelectedDecal(string name)
{
_selectedDecal = name;
if (_sprite is null)
return;
PopulateDecals(_decals, _sprite);
}
public void SetAngle(int degrees)
{
AngleSpinBox.OverrideValue(degrees);
}
public void SetColor(Color? color)
{
UseCustomColorCheckBox.Pressed = color != null;
if (color != null)
ColorSelector.Color = color.Value;
UpdateColorButtons(UseCustomColorCheckBox.Pressed);
}
public void SetSnap(bool snap)
{
SnapToTileCheckBox.Pressed = snap;
}
}