Files
wwdpublic/Content.Client/UserInterface/Systems/Actions/Controls/ActionButton.cs
DEATHB4DEFEAT 47b10a01b0 Catch-Up Cherry Pick 2 (#944)
# Description

Picked 400 commits (and skipped many, many more) from WizDen since #540.
Stopped at commit 332f54a3aebe669f6e50d26e7b047f0bdc28e0fb (Lobby
Refactor).

---

# TODO

- [x] Pick
- [x] Compile
- [x] Fix runtime errors
- [ ] Fix up humanoid profile editor
- [ ] Test everything

---

# Changelog

🆑
- add: Merged 400 WizDen PRs. Happy testing!

---------

Co-authored-by: Plykiya <58439124+Plykiya@users.noreply.github.com>
Co-authored-by: FungiFellow <151778459+FungiFellow@users.noreply.github.com>
Co-authored-by: osjarw <62134478+osjarw@users.noreply.github.com>
Co-authored-by: Ubaser <134914314+UbaserB@users.noreply.github.com>
Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com>
Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Co-authored-by: Magnus Larsen <i.am.larsenml@gmail.com>
Co-authored-by: Hanz <41141796+Hanzdegloker@users.noreply.github.com>
Co-authored-by: Kukutis96513 <146854220+Kukutis96513@users.noreply.github.com>
Co-authored-by: potato1234_x <79580518+potato1234x@users.noreply.github.com>
Co-authored-by: Gotimanga <127038462+Gotimanga@users.noreply.github.com>
Co-authored-by: Mangohydra <156087924+Mangohydra@users.noreply.github.com>
Co-authored-by: TsjipTsjip <19798667+TsjipTsjip@users.noreply.github.com>
Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com>
Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Co-authored-by: Morb <14136326+Morb0@users.noreply.github.com>
Co-authored-by: MilenVolf <63782763+MilenVolf@users.noreply.github.com>
Co-authored-by: KrasnoshchekovPavel <119816022+KrasnoshchekovPavel@users.noreply.github.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
Co-authored-by: DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: KittenColony <149278380+KittenColony@users.noreply.github.com>
Co-authored-by: ShadowCommander <shadowjjt@gmail.com>
Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
Co-authored-by: T-Stalker <43253663+DogZeroX@users.noreply.github.com>
Co-authored-by: ERROR404 <100093430+ERORR404V1@users.noreply.github.com>
Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>
Co-authored-by: Jezithyr <jezithyr@gmail.com>
Co-authored-by: Psychpsyo <60073468+Psychpsyo@users.noreply.github.com>
Co-authored-by: no <165581243+pissdemon@users.noreply.github.com>
Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com>
Co-authored-by: Ciac32 <aknoxlor@gmail.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: NotSoDana <75203942+NotSoDana@users.noreply.github.com>
Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com>
Co-authored-by: Repo <47093363+Titian3@users.noreply.github.com>
Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
Co-authored-by: nao fujiwara <awkwarddryad@gmail.com>
Co-authored-by: Michael <107807667+Doc-Michael@users.noreply.github.com>
Co-authored-by: Vasilis <vasilis@pikachu.systems>
Co-authored-by: Lamrr <96937466+Lamrr@users.noreply.github.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: Jay <67732946+DuskyJay@users.noreply.github.com>
Co-authored-by: Just-a-Unity-Dev <67359748+Just-a-Unity-Dev@users.noreply.github.com>
Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com>
Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com>
Co-authored-by: Tyzemol <85772526+Tyzemol@users.noreply.github.com>
Co-authored-by: Alzore <140123969+Blackern5000@users.noreply.github.com>
Co-authored-by: Pok <113675512+Pok27@users.noreply.github.com>
Co-authored-by: RumiTiger <154005209+RumiTiger@users.noreply.github.com>
Co-authored-by: Verm <32827189+Vermidia@users.noreply.github.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
Co-authored-by: Killerqu00 <47712032+Killerqu00@users.noreply.github.com>
Co-authored-by: Ty Ashley <42426760+TyAshley@users.noreply.github.com>
Co-authored-by: exincore <me@exin.xyz>
Co-authored-by: 0x6273 <0x40@keemail.me>
Co-authored-by: Kara <lunarautomaton6@gmail.com>
Co-authored-by: Ygg01 <y.laughing.man.y@gmail.com>
Co-authored-by: Łukasz Mędrek <lukasz@lukaszm.xyz>
Co-authored-by: Hannah Giovanna Dawson <karakkaraz@gmail.com>
Co-authored-by: TurboTracker <130304754+TurboTrackerss14@users.noreply.github.com>
Co-authored-by: OnsenCapy <101037138+LGRuthes@users.noreply.github.com>
Co-authored-by: pigeonpeas <147350443+pigeonpeas@users.noreply.github.com>
Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com>
Co-authored-by: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com>
Co-authored-by: Rio <110139251+Riolume@users.noreply.github.com>
Co-authored-by: vorkathbruh <152932728+vorkathbruh@users.noreply.github.com>
Co-authored-by: Sphiral <145869023+SphiraI@users.noreply.github.com>
Co-authored-by: PrPleGoo <PrPleGoo@users.noreply.github.com>
Co-authored-by: Moomoobeef <62638182+Moomoobeef@users.noreply.github.com>
Co-authored-by: username <113782077+whateverusername0@users.noreply.github.com>
Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com>
Co-authored-by: Джексон Миссиссиппи <tripwiregamer@gmail.com>
Co-authored-by: Brandon Li <48413902+aspiringLich@users.noreply.github.com>
Co-authored-by: Jajsha <101492056+Zap527@users.noreply.github.com>
Co-authored-by: RiceMar1244 <138547931+RiceMar1244@users.noreply.github.com>
Co-authored-by: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com>
Co-authored-by: youtissoum <51883137+youtissoum@users.noreply.github.com>
Co-authored-by: ike709 <ike709@users.noreply.github.com>
Co-authored-by: icekot8 <93311212+icekot8@users.noreply.github.com>
Co-authored-by: keronshb <54602815+keronshb@users.noreply.github.com>
Co-authored-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: Geekyhobo <66805063+Geekyhobo@users.noreply.github.com>
Co-authored-by: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com>
# Conflicts:
#	Content.Client/Input/ContentContexts.cs
#	Content.Client/Lobby/LobbyState.cs
#	Content.Client/Lobby/UI/HumanoidProfileEditor.xaml
#	Content.Client/Lobby/UI/LobbyGui.xaml
#	Content.Client/Lobby/UI/LobbyGui.xaml.cs
#	Content.Client/Preferences/UI/CharacterSetupGui.xaml.cs
#	Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml
#	Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
#	Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs
#	Content.Server/GameTicking/GameTicker.Spawning.cs
#	Content.Shared/Alert/AlertType.cs
#	Content.Shared/Input/ContentKeyFunctions.cs
#	Content.Shared/Preferences/HumanoidCharacterProfile.cs
#	Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs
#	Resources/ConfigPresets/EinsteinEngines/default.toml
#	Resources/Prototypes/Alerts/alerts.yml
#	Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml
#	Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml
#	Resources/Prototypes/Entities/Clothing/Uniforms/jumpskirts.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/makeshiftstunprod.yml
#	Resources/Prototypes/Voice/speech_emotes.yml
#	Resources/keybinds.yml
2024-10-19 14:53:37 +07:00

446 lines
14 KiB
C#

using System.Numerics;
using Content.Client.Actions;
using Content.Client.Actions.UI;
using Content.Client.Cooldown;
using Content.Client.Stylesheets;
using Content.Shared.Actions;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.BoxContainer;
using static Robust.Client.UserInterface.Controls.TextureRect;
using Direction = Robust.Shared.Maths.Direction;
namespace Content.Client.UserInterface.Systems.Actions.Controls;
public sealed class ActionButton : Control, IEntityControl
{
private IEntityManager _entities;
private SpriteSystem? _spriteSys;
private ActionUIController? _controller;
private bool _beingHovered;
private bool _depressed;
private bool _toggled;
public BoundKeyFunction? KeyBind
{
set
{
_keybind = value;
if (_keybind != null)
{
Label.Text = BoundKeyHelper.ShortKeyName(_keybind.Value);
}
}
}
private BoundKeyFunction? _keybind;
public readonly TextureRect Button;
public readonly PanelContainer HighlightRect;
private readonly TextureRect _bigActionIcon;
private readonly TextureRect _smallActionIcon;
public readonly Label Label;
public readonly CooldownGraphic Cooldown;
private readonly SpriteView _smallItemSpriteView;
private readonly SpriteView _bigItemSpriteView;
private Texture? _buttonBackgroundTexture;
public EntityUid? ActionId { get; private set; }
private BaseActionComponent? _action;
public bool Locked { get; set; }
public event Action<GUIBoundKeyEventArgs, ActionButton>? ActionPressed;
public event Action<GUIBoundKeyEventArgs, ActionButton>? ActionUnpressed;
public event Action<ActionButton>? ActionFocusExited;
public ActionButton(IEntityManager entities, SpriteSystem? spriteSys = null, ActionUIController? controller = null)
{
// TODO why is this constructor so slooooow. The rest of the code is fine
_entities = entities;
_spriteSys = spriteSys;
_controller = controller;
MouseFilter = MouseFilterMode.Pass;
Button = new TextureRect
{
Name = "Button",
TextureScale = new Vector2(2, 2)
};
HighlightRect = new PanelContainer
{
StyleClasses = {StyleNano.StyleClassHandSlotHighlight},
MinSize = new Vector2(32, 32),
Visible = false
};
_bigActionIcon = new TextureRect
{
HorizontalExpand = true,
VerticalExpand = true,
Stretch = StretchMode.Scale,
Visible = false
};
_smallActionIcon = new TextureRect
{
HorizontalAlignment = HAlignment.Right,
VerticalAlignment = VAlignment.Bottom,
Stretch = StretchMode.Scale,
Visible = false
};
Label = new Label
{
Name = "Label",
HorizontalAlignment = HAlignment.Left,
VerticalAlignment = VAlignment.Top,
Margin = new Thickness(5, 0, 0, 0)
};
_bigItemSpriteView = new SpriteView
{
Name = "Big Sprite",
HorizontalExpand = true,
VerticalExpand = true,
Scale = new Vector2(2, 2),
SetSize = new Vector2(64, 64),
Visible = false,
OverrideDirection = Direction.South,
};
_smallItemSpriteView = new SpriteView
{
Name = "Small Sprite",
HorizontalAlignment = HAlignment.Right,
VerticalAlignment = VAlignment.Bottom,
Visible = false,
OverrideDirection = Direction.South,
};
// padding to the left of the small icon
var paddingBoxItemIcon = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
HorizontalExpand = true,
VerticalExpand = true,
MinSize = new Vector2(64, 64)
};
paddingBoxItemIcon.AddChild(new Control()
{
MinSize = new Vector2(32, 32),
});
paddingBoxItemIcon.AddChild(new Control
{
Children =
{
_smallActionIcon,
_smallItemSpriteView
}
});
Cooldown = new CooldownGraphic {Visible = false};
AddChild(Button);
AddChild(_bigActionIcon);
AddChild(_bigItemSpriteView);
AddChild(HighlightRect);
AddChild(Label);
AddChild(Cooldown);
AddChild(paddingBoxItemIcon);
Button.Modulate = new Color(255, 255, 255, 150);
OnThemeUpdated();
OnKeyBindDown += OnPressed;
OnKeyBindUp += OnUnpressed;
TooltipSupplier = SupplyTooltip;
}
protected override void OnThemeUpdated()
{
base.OnThemeUpdated();
_buttonBackgroundTexture = Theme.ResolveTexture("SlotBackground");
Label.FontColorOverride = Theme.ResolveColorOrSpecified("whiteText");
}
private void OnPressed(GUIBoundKeyEventArgs args)
{
if (args.Function != EngineKeyFunctions.UIClick && args.Function != EngineKeyFunctions.UIRightClick)
return;
if (args.Function == EngineKeyFunctions.UIRightClick)
Depress(args, true);
ActionPressed?.Invoke(args, this);
}
private void OnUnpressed(GUIBoundKeyEventArgs args)
{
if (args.Function != EngineKeyFunctions.UIClick && args.Function != EngineKeyFunctions.UIRightClick)
return;
if (args.Function == EngineKeyFunctions.UIRightClick)
Depress(args, false);
ActionUnpressed?.Invoke(args, this);
}
private Control? SupplyTooltip(Control sender)
{
if (!_entities.TryGetComponent(ActionId, out MetaDataComponent? metadata))
return null;
var name = FormattedMessage.FromMarkupPermissive(Loc.GetString(metadata.EntityName));
var decr = FormattedMessage.FromMarkupPermissive(Loc.GetString(metadata.EntityDescription));
if (_action is { Charges: not null })
{
var charges = FormattedMessage.FromMarkupPermissive(Loc.GetString($"Charges: {_action.Charges.Value.ToString()}/{_action.MaxCharges.ToString()}"));
return new ActionAlertTooltip(name, decr, charges: charges);
}
return new ActionAlertTooltip(name, decr);
}
protected override void ControlFocusExited()
{
ActionFocusExited?.Invoke(this);
}
private void UpdateItemIcon()
{
if (_action is not {EntityIcon: { } entity} ||
!_entities.HasComponent<SpriteComponent>(entity))
{
_bigItemSpriteView.Visible = false;
_bigItemSpriteView.SetEntity(null);
_smallItemSpriteView.Visible = false;
_smallItemSpriteView.SetEntity(null);
}
else
{
switch (_action.ItemIconStyle)
{
case ItemActionIconStyle.BigItem:
_bigItemSpriteView.Visible = true;
_bigItemSpriteView.SetEntity(entity);
_smallItemSpriteView.Visible = false;
_smallItemSpriteView.SetEntity(null);
break;
case ItemActionIconStyle.BigAction:
_bigItemSpriteView.Visible = false;
_bigItemSpriteView.SetEntity(null);
_smallItemSpriteView.Visible = true;
_smallItemSpriteView.SetEntity(entity);
break;
case ItemActionIconStyle.NoItem:
_bigItemSpriteView.Visible = false;
_bigItemSpriteView.SetEntity(null);
_smallItemSpriteView.Visible = false;
_smallItemSpriteView.SetEntity(null);
break;
}
}
}
private void SetActionIcon(Texture? texture)
{
if (_action == null || texture == null)
{
_bigActionIcon.Texture = null;
_bigActionIcon.Visible = false;
_smallActionIcon.Texture = null;
_smallActionIcon.Visible = false;
}
else if (_action.EntityIcon != null && _action.ItemIconStyle == ItemActionIconStyle.BigItem)
{
_smallActionIcon.Texture = texture;
_smallActionIcon.Modulate = _action.IconColor;
_smallActionIcon.Visible = true;
_bigActionIcon.Texture = null;
_bigActionIcon.Visible = false;
}
else
{
_bigActionIcon.Texture = texture;
_bigActionIcon.Modulate = _action.IconColor;
_bigActionIcon.Visible = true;
_smallActionIcon.Texture = null;
_smallActionIcon.Visible = false;
}
}
public void UpdateIcons()
{
UpdateItemIcon();
UpdateBackground();
if (_action == null)
{
SetActionIcon(null);
return;
}
_controller ??= UserInterfaceManager.GetUIController<ActionUIController>();
_spriteSys ??= _entities.System<SpriteSystem>();
if ((_controller.SelectingTargetFor == ActionId || _action.Toggled))
{
if (_action.IconOn != null)
SetActionIcon(_spriteSys.Frame0(_action.IconOn));
if (_action.BackgroundOn != null)
_buttonBackgroundTexture = _spriteSys.Frame0(_action.BackgroundOn);
}
else
{
SetActionIcon(_action.Icon != null ? _spriteSys.Frame0(_action.Icon) : null);
_buttonBackgroundTexture = Theme.ResolveTexture("SlotBackground");
}
}
public void UpdateBackground()
{
_controller ??= UserInterfaceManager.GetUIController<ActionUIController>();
if (_action != null ||
_controller.IsDragging && GetPositionInParent() == Parent?.ChildCount - 1)
{
Button.Texture = _buttonBackgroundTexture;
}
else
{
Button.Texture = null;
}
}
public bool TryReplaceWith(EntityUid actionId, ActionsSystem system)
{
if (Locked)
{
return false;
}
UpdateData(actionId, system);
return true;
}
public void UpdateData(EntityUid? actionId, ActionsSystem system)
{
ActionId = actionId;
system.TryGetActionData(actionId, out _action);
Label.Visible = actionId != null;
UpdateIcons();
}
public void ClearData()
{
ActionId = null;
_action = null;
Cooldown.Visible = false;
Cooldown.Progress = 1;
Label.Visible = false;
UpdateIcons();
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdateBackground();
Cooldown.Visible = _action != null && _action.Cooldown != null;
if (_action == null)
return;
if (_action.Cooldown != null)
{
Cooldown.FromTime(_action.Cooldown.Value.Start, _action.Cooldown.Value.End);
}
if (ActionId != null && _toggled != _action.Toggled)
{
_toggled = _action.Toggled;
}
}
protected override void MouseEntered()
{
base.MouseEntered();
UserInterfaceManager.HoverSound();
_beingHovered = true;
DrawModeChanged();
}
protected override void MouseExited()
{
base.MouseExited();
_beingHovered = false;
DrawModeChanged();
}
/// <summary>
/// Press this button down. If it was depressed and now set to not depressed, will
/// trigger the action.
/// </summary>
public void Depress(GUIBoundKeyEventArgs args, bool depress)
{
// action can still be toggled if it's allowed to stay selected
if (_action is not {Enabled: true})
return;
_depressed = depress;
DrawModeChanged();
}
public void DrawModeChanged()
{
_controller ??= UserInterfaceManager.GetUIController<ActionUIController>();
HighlightRect.Visible = _beingHovered && (_action != null || _controller.IsDragging);
// always show the normal empty button style if no action in this slot
if (_action == null)
{
SetOnlyStylePseudoClass(ContainerButton.StylePseudoClassNormal);
return;
}
// show a hover only if the action is usable or another action is being dragged on top of this
if (_beingHovered && (_controller.IsDragging || _action!.Enabled))
{
SetOnlyStylePseudoClass(ContainerButton.StylePseudoClassHover);
}
// it's only depress-able if it's usable, so if we're depressed
// show the depressed style
if (_depressed && !_beingHovered)
{
HighlightRect.Visible = false;
SetOnlyStylePseudoClass(ContainerButton.StylePseudoClassPressed);
return;
}
// if it's toggled on, always show the toggled on style (currently same as depressed style)
if (_action.Toggled || _controller.SelectingTargetFor == ActionId)
{
// when there's a toggle sprite, we're showing that sprite instead of highlighting this slot
SetOnlyStylePseudoClass(_action.IconOn != null
? ContainerButton.StylePseudoClassNormal
: ContainerButton.StylePseudoClassPressed);
return;
}
if (!_action.Enabled)
{
SetOnlyStylePseudoClass(ContainerButton.StylePseudoClassDisabled);
return;
}
SetOnlyStylePseudoClass(ContainerButton.StylePseudoClassNormal);
}
EntityUid? IEntityControl.UiEntity => ActionId;
}