-using Content.Shared.Changeling.Systems;
+using Content.Client.Stylesheets;
+using Content.Client.UserInterface.Controls;
+using Content.Shared.Changeling.Components;
+using Content.Shared.Changeling.Systems;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
[UsedImplicitly]
public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
- private ChangelingTransformMenu? _window;
+ private SimpleRadialMenu? _menu;
+ private static readonly Color SelectedOptionBackground = StyleNano.ButtonColorGoodDefault.WithAlpha(128);
+ private static readonly Color SelectedOptionHoverBackground = StyleNano.ButtonColorGoodHovered.WithAlpha(128);
protected override void Open()
{
base.Open();
- _window = this.CreateWindow<ChangelingTransformMenu>();
-
- _window.OnIdentitySelect += SendIdentitySelect;
-
- _window.Update(Owner);
+ _menu = this.CreateWindow<SimpleRadialMenu>();
+ Update();
+ _menu.OpenOverMouseScreenPosition();
}
+
public override void Update()
{
- if (_window == null)
+ if (_menu == null)
return;
- _window.Update(Owner);
+ if (!EntMan.TryGetComponent<ChangelingIdentityComponent>(Owner, out var lingIdentity))
+ return;
+
+ var models = ConvertToButtons(lingIdentity.ConsumedIdentities, lingIdentity?.CurrentIdentity);
+
+ _menu.SetButtons(models);
+ }
+
+ private IEnumerable<RadialMenuOptionBase> ConvertToButtons(
+ IEnumerable<EntityUid> identities,
+ EntityUid? currentIdentity
+ )
+ {
+ var buttons = new List<RadialMenuOptionBase>();
+ foreach (var identity in identities)
+ {
+ if (!EntMan.TryGetComponent<MetaDataComponent>(identity, out var metadata))
+ continue;
+
+ var option = new RadialMenuActionOption<NetEntity>(SendIdentitySelect, EntMan.GetNetEntity(identity))
+ {
+ IconSpecifier = RadialMenuIconSpecifier.With(identity),
+ ToolTip = metadata.EntityName,
+ BackgroundColor = (currentIdentity == identity) ? SelectedOptionBackground : null,
+ HoverBackgroundColor = (currentIdentity == identity) ? SelectedOptionHoverBackground : null
+ };
+ buttons.Add(option);
+ }
+
+ return buttons;
}
- public void SendIdentitySelect(NetEntity identityId)
+ private void SendIdentitySelect(NetEntity identityId)
{
SendPredictedMessage(new ChangelingTransformIdentitySelectMessage(identityId));
}
+++ /dev/null
-<ui:RadialMenu
- xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
- CloseButtonStyleClass="RadialMenuCloseButton"
- VerticalExpand="True"
- HorizontalExpand="True">
- <ui:RadialContainer Name="Main">
- </ui:RadialContainer>
-</ui:RadialMenu>
+++ /dev/null
-using System.Numerics;
-using Content.Client.UserInterface.Controls;
-using Content.Shared.Changeling.Components;
-using Robust.Client.AutoGenerated;
-using Robust.Client.UserInterface.Controls;
-using Robust.Client.UserInterface.XAML;
-
-namespace Content.Client.Changeling.UI;
-
-[GenerateTypedNameReferences]
-public sealed partial class ChangelingTransformMenu : RadialMenu
-{
- [Dependency] private readonly IEntityManager _entity = default!;
- public event Action<NetEntity>? OnIdentitySelect;
-
- public ChangelingTransformMenu()
- {
- RobustXamlLoader.Load(this);
- IoCManager.InjectDependencies(this);
- }
-
- public void Update(EntityUid uid)
- {
- Main.DisposeAllChildren();
-
- if (!_entity.TryGetComponent<ChangelingIdentityComponent>(uid, out var identityComp))
- return;
-
- foreach (var identityUid in identityComp.ConsumedIdentities)
- {
- if (!_entity.TryGetComponent<MetaDataComponent>(identityUid, out var metadata))
- continue;
-
- var identityName = metadata.EntityName;
-
- var button = new ChangelingTransformMenuButton()
- {
- StyleClasses = { "RadialMenuButton" },
- SetSize = new Vector2(64, 64),
- ToolTip = identityName,
- };
-
- var entView = new SpriteView()
- {
- SetSize = new Vector2(48, 48),
- VerticalAlignment = VAlignment.Center,
- HorizontalAlignment = HAlignment.Center,
- Stretch = SpriteView.StretchMode.Fill,
- };
- entView.SetEntity(identityUid);
- button.OnButtonUp += _ =>
- {
- OnIdentitySelect?.Invoke(_entity.GetNetEntity(identityUid));
- Close();
- };
- button.AddChild(entView);
- Main.AddChild(button);
- }
- }
-}
-
-public sealed class ChangelingTransformMenuButton : RadialMenuTextureButtonWithSector;
+using Content.Client.UserInterface.Controls;
using Content.Shared.Ghost.Roles;
+using Content.Shared.Ghost.Roles.Components;
using Robust.Client.UserInterface;
using Robust.Shared.Prototypes;
namespace Content.Client.Ghost;
-public sealed class GhostRoleRadioBoundUserInterface : BoundUserInterface
+public sealed class GhostRoleRadioBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
- private GhostRoleRadioMenu? _ghostRoleRadioMenu;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- public GhostRoleRadioBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
- {
- IoCManager.InjectDependencies(this);
- }
+ private SimpleRadialMenu? _ghostRoleRadioMenu;
protected override void Open()
{
base.Open();
- _ghostRoleRadioMenu = this.CreateWindow<GhostRoleRadioMenu>();
- _ghostRoleRadioMenu.SetEntity(Owner);
- _ghostRoleRadioMenu.SendGhostRoleRadioMessageAction += SendGhostRoleRadioMessage;
+ _ghostRoleRadioMenu = this.CreateWindow<SimpleRadialMenu>();
+
+ // The purpose of this radial UI is for ghost role radios that allow you to select
+ // more than one potential option, such as with kobolds/lizards.
+ // This means that it won't show anything if SelectablePrototypes is empty.
+ if (!EntMan.TryGetComponent<GhostRoleMobSpawnerComponent>(Owner, out var comp))
+ return;
+
+ var list = ConvertToButtons(comp.SelectablePrototypes);
+
+ _ghostRoleRadioMenu.SetButtons(list);
+ }
+
+ private IEnumerable<RadialMenuOptionBase> ConvertToButtons(List<ProtoId<GhostRolePrototype>> protoIds)
+ {
+ var list = new List<RadialMenuOptionBase>();
+ foreach (var ghostRoleProtoId in protoIds)
+ {
+ // For each prototype we find we want to create a button that uses the name of the ghost role
+ // as the hover tooltip, and the icon is taken from either the ghost role entityprototype
+ // or the indicated icon entityprototype.
+ if (!_prototypeManager.Resolve(ghostRoleProtoId, out var ghostRoleProto))
+ continue;
+
+ var option = new RadialMenuActionOption<ProtoId<GhostRolePrototype>>(SendGhostRoleRadioMessage, ghostRoleProtoId)
+ {
+ ToolTip = Loc.GetString(ghostRoleProto.Name),
+ // pick the icon if it exists, otherwise fallback to the ghost role's entity
+ IconSpecifier = ghostRoleProto.IconPrototype != null
+ && _prototypeManager.Resolve(ghostRoleProto.IconPrototype, out var iconProto)
+ ? RadialMenuIconSpecifier.With(iconProto)
+ : RadialMenuIconSpecifier.With(ghostRoleProto.EntityPrototype)
+ };
+ list.Add(option);
+ }
+
+ return list;
}
private void SendGhostRoleRadioMessage(ProtoId<GhostRolePrototype> protoId)
+++ /dev/null
-<ui:RadialMenu
- xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
- CloseButtonStyleClass="RadialMenuCloseButton"
- VerticalExpand="True"
- HorizontalExpand="True">
- <ui:RadialContainer Name="Main">
- </ui:RadialContainer>
-</ui:RadialMenu>
+++ /dev/null
-using Content.Client.UserInterface.Controls;
-using Content.Shared.Ghost.Roles;
-using Content.Shared.Ghost.Roles.Components;
-using Robust.Client.UserInterface;
-using Robust.Client.UserInterface.Controls;
-using Robust.Client.UserInterface.XAML;
-using Robust.Shared.Prototypes;
-using System.Numerics;
-
-namespace Content.Client.Ghost;
-
-public sealed partial class GhostRoleRadioMenu : RadialMenu
-{
- [Dependency] private readonly EntityManager _entityManager = default!;
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
-
- public event Action<ProtoId<GhostRolePrototype>>? SendGhostRoleRadioMessageAction;
-
- public EntityUid Entity { get; set; }
-
- public GhostRoleRadioMenu()
- {
- IoCManager.InjectDependencies(this);
- RobustXamlLoader.Load(this);
- }
-
- public void SetEntity(EntityUid uid)
- {
- Entity = uid;
- RefreshUI();
- }
-
- private void RefreshUI()
- {
- // The main control that will contain all the clickable options
- var main = FindControl<RadialContainer>("Main");
-
- // The purpose of this radial UI is for ghost role radios that allow you to select
- // more than one potential option, such as with kobolds/lizards.
- // This means that it won't show anything if SelectablePrototypes is empty.
- if (!_entityManager.TryGetComponent<GhostRoleMobSpawnerComponent>(Entity, out var comp))
- return;
-
- foreach (var ghostRoleProtoString in comp.SelectablePrototypes)
- {
- // For each prototype we find we want to create a button that uses the name of the ghost role
- // as the hover tooltip, and the icon is taken from either the ghost role entityprototype
- // or the indicated icon entityprototype.
- if (!_prototypeManager.TryIndex<GhostRolePrototype>(ghostRoleProtoString, out var ghostRoleProto))
- continue;
-
- var button = new GhostRoleRadioMenuButton()
- {
- SetSize = new Vector2(64, 64),
- ToolTip = Loc.GetString(ghostRoleProto.Name),
- ProtoId = ghostRoleProto.ID,
- };
-
- var entProtoView = new EntityPrototypeView()
- {
- SetSize = new Vector2(48, 48),
- VerticalAlignment = VAlignment.Center,
- HorizontalAlignment = HAlignment.Center,
- Stretch = SpriteView.StretchMode.Fill
- };
-
- // pick the icon if it exists, otherwise fallback to the ghost role's entity
- if (_prototypeManager.Resolve(ghostRoleProto.IconPrototype, out var iconProto))
- entProtoView.SetPrototype(iconProto);
- else
- entProtoView.SetPrototype(ghostRoleProto.EntityPrototype);
-
- button.AddChild(entProtoView);
- main.AddChild(button);
- AddGhostRoleRadioMenuButtonOnClickActions(main);
- }
- }
-
- private void AddGhostRoleRadioMenuButtonOnClickActions(Control control)
- {
- var mainControl = control as RadialContainer;
-
- if (mainControl == null)
- return;
-
- foreach (var child in mainControl.Children)
- {
- var castChild = child as GhostRoleRadioMenuButton;
-
- if (castChild == null)
- continue;
-
- castChild.OnButtonUp += _ =>
- {
- SendGhostRoleRadioMessageAction?.Invoke(castChild.ProtoId);
- Close();
- };
- }
- }
-}
-
-public sealed class GhostRoleRadioMenuButton : RadialMenuTextureButtonWithSector
-{
- public ProtoId<GhostRolePrototype> ProtoId { get; set; }
-}
_menu.OpenOverMouseScreenPosition();
}
- private IEnumerable<RadialMenuOption> ConvertToButtons(HashSet<ProtoId<RCDPrototype>> prototypes)
+ private IEnumerable<RadialMenuOptionBase> ConvertToButtons(HashSet<ProtoId<RCDPrototype>> prototypes)
{
- Dictionary<string, List<RadialMenuActionOption>> buttonsByCategory = new();
- ValueList<RadialMenuActionOption> topLevelActions = new();
+ Dictionary<string, List<RadialMenuActionOptionBase>> buttonsByCategory = new();
+ ValueList<RadialMenuActionOptionBase> topLevelActions = new();
foreach (var protoId in prototypes)
{
var prototype = _prototypeManager.Index(protoId);
{
var topLevelActionOption = new RadialMenuActionOption<RCDPrototype>(HandleMenuOptionClick, prototype)
{
- Sprite = prototype.Sprite,
+ IconSpecifier = RadialMenuIconSpecifier.With(prototype.Sprite),
ToolTip = GetTooltip(prototype)
};
topLevelActions.Add(topLevelActionOption);
if (!buttonsByCategory.TryGetValue(prototype.Category, out var list))
{
- list = new List<RadialMenuActionOption>();
+ list = new List<RadialMenuActionOptionBase>();
buttonsByCategory.Add(prototype.Category, list);
}
var actionOption = new RadialMenuActionOption<RCDPrototype>(HandleMenuOptionClick, prototype)
{
- Sprite = prototype.Sprite,
+ IconSpecifier = RadialMenuIconSpecifier.With(prototype.Sprite),
ToolTip = GetTooltip(prototype)
};
list.Add(actionOption);
}
- var models = new RadialMenuOption[buttonsByCategory.Count + topLevelActions.Count];
+ var models = new RadialMenuOptionBase[buttonsByCategory.Count + topLevelActions.Count];
var i = 0;
foreach (var (key, list) in buttonsByCategory)
{
var groupInfo = PrototypesGroupingInfo[key];
models[i] = new RadialMenuNestedLayerOption(list)
{
- Sprite = groupInfo.Sprite,
+ IconSpecifier = RadialMenuIconSpecifier.With(groupInfo.Sprite),
ToolTip = Loc.GetString(groupInfo.Tooltip)
};
i++;
_menu.Open();
}
- private IEnumerable<RadialMenuActionOption> ConvertToButtons(IReadOnlyList<StationAiRadial> actions)
+ private IEnumerable<RadialMenuActionOptionBase> ConvertToButtons(IReadOnlyList<StationAiRadial> actions)
{
- var models = new RadialMenuActionOption[actions.Count];
+ var models = new RadialMenuActionOptionBase[actions.Count];
for (int i = 0; i < actions.Count; i++)
{
var action = actions[i];
models[i] = new RadialMenuActionOption<BaseStationAiAction>(HandleRadialMenuClick, action.Event)
{
- Sprite = action.Sprite,
+ IconSpecifier = RadialMenuIconSpecifier.With(action.Sprite),
ToolTip = action.Tooltip
};
}
/// from interactions.
/// </summary>
[Virtual]
-public class RadialMenuTextureButtonBase : TextureButton
+public abstract class RadialMenuButtonBase : BaseButton
{
/// <inheritdoc />
- protected RadialMenuTextureButtonBase()
+ protected RadialMenuButtonBase()
{
EnableAllKeybinds = true;
}
{
if (args.Function == EngineKeyFunctions.UIClick
|| args.Function == ContentKeyFunctions.AltActivateItemInWorld)
+ {
base.KeyBindUp(args);
+ }
}
}
/// works only if control have parent, and ActiveContainer property is set.
/// Also considers all space outside of radial menu buttons as itself for clicking.
/// </summary>
-public sealed class RadialMenuContextualCentralTextureButton : RadialMenuTextureButtonBase
+public sealed class RadialMenuContextualCentralTextureButton : TextureButton
{
+ /// <inheritdoc />
+ public RadialMenuContextualCentralTextureButton()
+ {
+ EnableAllKeybinds = true;
+ }
+
public float InnerRadius { get; set; }
public Vector2? ParentCenter { get; set; }
var innerRadiusSquared = InnerRadius * InnerRadius;
- // comparing to squared values is faster then making sqrt
+ // comparing to squared values is faster, then making sqrt
return distSquared < innerRadiusSquared;
}
+
+ /// <inheritdoc />
+ protected override void KeyBindUp(GUIBoundKeyEventArgs args)
+ {
+ if (args.Function == EngineKeyFunctions.UIClick
+ || args.Function == ContentKeyFunctions.AltActivateItemInWorld)
+ {
+ base.KeyBindUp(args);
+ }
+ }
}
/// <summary>
/// Menu button for outer area of radial menu (covers everything 'outside').
/// </summary>
-public sealed class RadialMenuOuterAreaButton : RadialMenuTextureButtonBase
+public sealed class RadialMenuOuterAreaButton : RadialMenuButtonBase
{
public float OuterRadius { get; set; }
}
[Virtual]
-public class RadialMenuTextureButton : RadialMenuTextureButtonBase
+public class RadialMenuButton : RadialMenuButtonBase
{
/// <summary>
/// Upon clicking this button the radial menu will be moved to the layer of this control.
/// <summary>
/// A simple texture button that can move the user to a different layer within a radial menu
/// </summary>
- public RadialMenuTextureButton()
+ public RadialMenuButton()
{
- EnableAllKeybinds = true;
OnButtonUp += OnClicked;
}
}
[Virtual]
-public class RadialMenuTextureButtonWithSector : RadialMenuTextureButton, IRadialMenuItemWithSector
+public class RadialMenuButtonWithSector : RadialMenuButton, IRadialMenuItemWithSector
{
private Vector2[]? _sectorPointsForDrawing;
/// <summary>
/// A simple texture button that can move the user to a different layer within a radial menu
/// </summary>
- public RadialMenuTextureButtonWithSector()
+ public RadialMenuButtonWithSector()
{
}
using Robust.Shared.Timing;
using Robust.Client.UserInterface.XAML;
using Robust.Client.Input;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Prototypes;
namespace Content.Client.UserInterface.Controls;
_attachMenuToEntity = owner;
}
- public void SetButtons(IEnumerable<RadialMenuOption> models, SimpleRadialMenuSettings? settings = null)
+ public void SetButtons(IEnumerable<RadialMenuOptionBase> models, SimpleRadialMenuSettings? settings = null)
{
ClearExistingChildrenRadialButtons();
}
private void Fill(
- IEnumerable<RadialMenuOption> models,
+ IEnumerable<RadialMenuOptionBase> models,
SpriteSystem sprites,
ICollection<Control> rootControlChildren,
SimpleRadialMenuSettings settings
}
}
- private RadialMenuTextureButton RecursiveContainerExtraction(
+ private RadialMenuButton RecursiveContainerExtraction(
SpriteSystem sprites,
ICollection<Control> rootControlChildren,
RadialMenuNestedLayerOption model,
return thisLayerLinkButton;
}
- private RadialMenuTextureButton ConvertToButton(
- RadialMenuOption model,
+ private RadialMenuButton ConvertToButton(
+ RadialMenuOptionBase model,
SpriteSystem sprites,
SimpleRadialMenuSettings settings,
bool haveNested
{
var button = settings.UseSectors
? ConvertToButtonWithSector(model, settings)
- : new RadialMenuTextureButton();
+ : new RadialMenuButton();
button.SetSize = new Vector2(64f, 64f);
button.ToolTip = model.ToolTip;
- if (model.Sprite != null)
+ var imageControl = model.IconSpecifier switch
{
- var scale = Vector2.One;
-
- var texture = sprites.Frame0(model.Sprite);
- if (texture.Width <= 32)
- {
- scale *= 2;
- }
+ RadialMenuTextureIconSpecifier textureSpecifier => CreateTexture(textureSpecifier.Sprite, sprites),
+ RadialMenuEntityIconSpecifier entitySpecifier => CreateSpriteView(entitySpecifier.Entity),
+ RadialMenuEntityPrototypeIconSpecifier entProtoSpecifier => CreateEntityPrototypeView(entProtoSpecifier.ProtoId),
+ _ => null
+ };
- button.TextureNormal = texture;
- button.Scale = scale;
- }
+ if(imageControl != null)
+ button.AddChild(imageControl);
- if (model is RadialMenuActionOption actionOption)
+ if (model is RadialMenuActionOptionBase actionOption)
{
button.OnPressed += _ =>
{
actionOption.OnPressed?.Invoke();
- if(!haveNested)
+ if (!haveNested)
Close();
};
}
return button;
}
- private static RadialMenuTextureButtonWithSector ConvertToButtonWithSector(RadialMenuOption model, SimpleRadialMenuSettings settings)
+ private Control CreateEntityPrototypeView(EntProtoId protoId)
+ {
+ var entProtoView = new EntityPrototypeView
+ {
+ SetSize = new Vector2(48, 48),
+ VerticalAlignment = VAlignment.Center,
+ HorizontalAlignment = HAlignment.Center,
+ Stretch = SpriteView.StretchMode.Fill,
+ };
+ entProtoView.SetPrototype(protoId);
+ return entProtoView;
+ }
+
+ private static Control CreateSpriteView(EntityUid entityForSpriteView)
+ {
+ var entView = new SpriteView
+ {
+ SetSize = new Vector2(48, 48),
+ VerticalAlignment = VAlignment.Center,
+ HorizontalAlignment = HAlignment.Center,
+ Stretch = SpriteView.StretchMode.Fill,
+ };
+ entView.SetEntity(entityForSpriteView);
+ return entView;
+ }
+
+ private static Control CreateTexture(SpriteSpecifier spriteSpecifier, SpriteSystem sprites)
+ {
+ var scale = Vector2.One;
+
+ var texture = sprites.Frame0(spriteSpecifier);
+ if (texture.Width <= 32)
+ {
+ scale *= 2;
+ }
+
+ var imageControl = new TextureRect()
+ {
+ Texture = texture,
+ TextureScale = scale
+ };
+ return imageControl;
+ }
+
+ private static RadialMenuButtonWithSector ConvertToButtonWithSector(RadialMenuOptionBase model, SimpleRadialMenuSettings settings)
{
- var button = new RadialMenuTextureButtonWithSector
+ var button = new RadialMenuButtonWithSector
{
DrawBorder = settings.DisplayBorders,
DrawBackground = !settings.NoBackground
}
+/// <summary>
+/// Abstract representation of a way to specify icon in radial menu.
+/// </summary>
+public abstract record RadialMenuIconSpecifier
+{
+ /// <summary> Use entity prototype viewer. </summary>
+ public static RadialMenuIconSpecifier? With(EntProtoId? protoId)
+ {
+ if (protoId is null)
+ return null;
+
+ return new RadialMenuEntityPrototypeIconSpecifier(protoId.Value);
+ }
+
+ /// <summary> Use simple texture icon. </summary>
+ public static RadialMenuIconSpecifier? With(SpriteSpecifier? sprite)
+ {
+ if (sprite == null)
+ return null;
-public abstract class RadialMenuOption
+ return new RadialMenuTextureIconSpecifier(sprite);
+ }
+
+ /// <summary> Use entity sprite viewer. </summary>
+ public static RadialMenuIconSpecifier? With(EntityUid? entity)
+ {
+ if (entity == null)
+ return null;
+
+ return new RadialMenuEntityIconSpecifier(entity.Value);
+ }
+}
+
+/// <summary> Marker that <see cref="SpriteView"/> should be used to display radial menu icon. </summary>
+public sealed record RadialMenuEntityIconSpecifier(EntityUid Entity) : RadialMenuIconSpecifier;
+
+/// <summary> Marker that <see cref="TextureRect"/> should be used to display radial menu icon. </summary>
+public sealed record RadialMenuTextureIconSpecifier(SpriteSpecifier Sprite) : RadialMenuIconSpecifier;
+
+/// <summary> Marker that <see cref="EntityPrototypeView"/> should be used to display radial menu icon. </summary>
+public sealed record RadialMenuEntityPrototypeIconSpecifier(EntProtoId ProtoId) : RadialMenuIconSpecifier;
+
+/// <summary> Container for common options for radial menu button. </summary>
+public abstract class RadialMenuOptionBase
{
+ /// <summary> Tooltip to be displayed when button is hovered. </summary>
public string? ToolTip { get; init; }
- public SpriteSpecifier? Sprite { get; init; }
+ /// <summary>
+ /// Color for button background.
+ /// Is used only with sector radial (<see cref="SimpleRadialMenuSettings.UseSectors"/>).
+ /// </summary>
public Color? BackgroundColor { get; set; }
+ /// <summary>
+ /// Color for button background when it is hovered.
+ /// Is used only with sector radial (<see cref="SimpleRadialMenuSettings.UseSectors"/>).
+ /// </summary>
public Color? HoverBackgroundColor { get; set; }
+
+ /// <summary>
+ /// Specifier that describes icon to be used for radial menu button.
+ /// </summary>
+ public RadialMenuIconSpecifier? IconSpecifier { get; set; }
}
-public abstract class RadialMenuActionOption(Action onPressed) : RadialMenuOption
+/// <summary> Base type for model of radial menu button with some action on button pressed. </summary>
+/// <param name="onPressed"></param>
+public abstract class RadialMenuActionOptionBase(Action onPressed) : RadialMenuOptionBase
{
+ /// <summary> Action to be executed on button press. </summary>
public Action OnPressed { get; } = onPressed;
}
-public sealed class RadialMenuActionOption<T>(Action<T> onPressed, T data)
- : RadialMenuActionOption(onPressed: () => onPressed(data));
+/// <summary> Strong-typed model for radial menu button with action, stores provided data to be used upon button press. </summary>
+public sealed class RadialMenuActionOption<T>(Action<T> onPressed, T data) : RadialMenuActionOptionBase(onPressed: () => onPressed(data));
-public sealed class RadialMenuNestedLayerOption(IReadOnlyCollection<RadialMenuOption> nested, float containerRadius = 100)
- : RadialMenuOption
+/// <summary>
+/// Model for radial menu button that represents reference for next layer of radial buttons.
+/// </summary>
+/// <param name="nested">List of button models for next layer of menu.</param>
+/// <param name="containerRadius">Radius for radial menu buttons of next layer.</param>
+public sealed class RadialMenuNestedLayerOption(IReadOnlyCollection<RadialMenuOptionBase> nested, float containerRadius = 100) : RadialMenuOptionBase
{
+ /// <summary> Radius for radial menu buttons of next layer. </summary>
public float? ContainerRadius { get; } = containerRadius;
- public IReadOnlyCollection<RadialMenuOption> Nested { get; } = nested;
+ /// <summary> List of button models for next layer of menu. </summary>
+ public IReadOnlyCollection<RadialMenuOptionBase> Nested { get; } = nested;
}
+/// <summary>
+/// Additional settings for radial menu render.
+/// </summary>
public sealed class SimpleRadialMenuSettings
{
/// <summary>
_menu = null;
}
- private IEnumerable<RadialMenuOption> ConvertToButtons(IEnumerable<EmotePrototype> emotePrototypes)
+ private IEnumerable<RadialMenuOptionBase> ConvertToButtons(IEnumerable<EmotePrototype> emotePrototypes)
{
var whitelistSystem = EntitySystemManager.GetEntitySystem<EntityWhitelistSystem>();
var player = _playerManager.LocalSession?.AttachedEntity;
- Dictionary<EmoteCategory, List<RadialMenuOption>> emotesByCategory = new();
+ Dictionary<EmoteCategory, List<RadialMenuOptionBase>> emotesByCategory = new();
foreach (var emote in emotePrototypes)
{
if(emote.Category == EmoteCategory.Invalid)
if (!emotesByCategory.TryGetValue(emote.Category, out var list))
{
- list = new List<RadialMenuOption>();
+ list = new List<RadialMenuOptionBase>();
emotesByCategory.Add(emote.Category, list);
}
var actionOption = new RadialMenuActionOption<EmotePrototype>(HandleRadialButtonClick, emote)
{
- Sprite = emote.Icon,
+ IconSpecifier = RadialMenuIconSpecifier.With(emote.Icon),
ToolTip = Loc.GetString(emote.Name)
};
list.Add(actionOption);
}
- var models = new RadialMenuOption[emotesByCategory.Count];
+ var models = new RadialMenuOptionBase[emotesByCategory.Count];
var i = 0;
foreach (var (key, list) in emotesByCategory)
{
models[i] = new RadialMenuNestedLayerOption(list)
{
- Sprite = tuple.Sprite,
+ IconSpecifier = RadialMenuIconSpecifier.With(tuple.Sprite),
ToolTip = Loc.GetString(tuple.Tooltip)
};
i++;
namespace Content.Shared.Ghost.Roles.Components
{
/// <summary>
- /// Allows a ghost to take this role, spawning a new entity.
+ /// Allows a ghost to take this role, spawning a new entity.
/// </summary>
[RegisterComponent, EntityCategory("Spawner")]
public sealed partial class GhostRoleMobSpawnerComponent : Component
public EntProtoId? Prototype;
/// <summary>
- /// If this ghostrole spawner has multiple selectable ghostrole prototypes.
+ /// If this ghostrole spawner has multiple selectable ghostrole prototypes.
/// </summary>
[DataField]
- public List<string> SelectablePrototypes = [];
+ public List<ProtoId<GhostRolePrototype>> SelectablePrototypes = [];
}
}