Skip to content

Commit

Permalink
fix: now radial menu buttons accepts only click/alt-click, now clicks…
Browse files Browse the repository at this point in the history
… outside menu closes menu always
  • Loading branch information
pa.pecherskij committed Dec 20, 2024
1 parent 764ac4d commit 66d2942
Showing 1 changed file with 65 additions and 25 deletions.
90 changes: 65 additions & 25 deletions Content.Client/UserInterface/Controls/RadialMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Robust.Client.UserInterface.CustomControls;
using System.Linq;
using System.Numerics;
using Content.Shared.Input;
using Robust.Client.Graphics;
using Robust.Shared.Input;

Expand All @@ -16,6 +17,11 @@ public class RadialMenu : BaseWindow
/// </summary>
public RadialMenuContextualCentralTextureButton ContextualButton { get; }

/// <summary>
/// Button that represents outer area of menu (closes menu on outside clicks).
/// </summary>
public RadialMenuOuterAreaButton MenuOuterAreaButton { get; }

/// <summary>
/// Set a style class to be applied to the contextual button when it is set to move the user back through previous layers of the radial menu
/// </summary>
Expand Down Expand Up @@ -86,15 +92,12 @@ public RadialMenu()
VerticalAlignment = VAlignment.Center,
SetSize = new Vector2(64f, 64f),
};
MenuOuterAreaButton = new RadialMenuOuterAreaButton();

ContextualButton.OnButtonUp += args =>
{
// this button uses enableAllKeybinds mode, which propagates more events,
// then just click, but we need only click and only once per user interaction
if (args.Event.Function == EngineKeyFunctions.UIClick)
ReturnToPreviousLayer();
};
ContextualButton.OnButtonUp += _ => ReturnToPreviousLayer();
MenuOuterAreaButton.OnButtonUp += _ => Close();
AddChild(ContextualButton);
AddChild(MenuOuterAreaButton);

// Hide any further add children, unless its promoted to the active layer
OnChildAdded += child =>
Expand All @@ -108,9 +111,11 @@ private void SetupContextualButtonData(Control child)
{
if (child is RadialContainer { Visible: true } container)
{
ContextualButton.ParentCenter = MinSize * 0.5f;
var parentCenter = MinSize * 0.5f;
ContextualButton.ParentCenter = parentCenter;
MenuOuterAreaButton.ParentCenter = parentCenter;
ContextualButton.InnerRadius = container.CalculatedRadius * container.InnerRadiusMultiplier;
ContextualButton.OuterRadius = container.CalculatedRadius * container.OuterRadiusMultiplier;
MenuOuterAreaButton.OuterRadius = container.CalculatedRadius * container.OuterRadiusMultiplier;
}
}

Expand All @@ -130,7 +135,7 @@ protected override Vector2 ArrangeOverride(Vector2 finalSize)

private Control? GetCurrentActiveLayer()
{
var children = Children.Where(x => x != ContextualButton);
var children = Children.Where(x => x != ContextualButton && x != MenuOuterAreaButton);

if (!children.Any())
return null;
Expand All @@ -152,7 +157,7 @@ public bool TryToMoveToNewLayer(string newLayer)

foreach (var child in Children)
{
if (child == ContextualButton)
if (child == ContextualButton || child == MenuOuterAreaButton)
continue;

// Hide layers which are not of interest
Expand Down Expand Up @@ -195,7 +200,7 @@ public void ReturnToPreviousLayer()
// Hide all children except the contextual button
foreach (var child in Children)
{
if (child != ContextualButton)
if (child != ContextualButton && child != MenuOuterAreaButton)
child.Visible = false;
}

Expand All @@ -209,26 +214,66 @@ public void ReturnToPreviousLayer()
}
}

/// <summary>
/// Base class for radial menu buttons. Excludes all actions except clicks and alt-clicks
/// from interactions.
/// </summary>
[Virtual]
public class RadialMenuTextureButtonBase : TextureButton
{
/// <inheritdoc />
protected RadialMenuTextureButtonBase()
{
EnableAllKeybinds = true;
}

/// <inheritdoc />
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
{
if (args.Function == EngineKeyFunctions.UIClick
|| args.Function == ContentKeyFunctions.AltActivateItemInWorld)
base.KeyBindUp(args);
}
}

/// <summary>
/// Special button for closing radial menu or going back between radial menu levels.
/// Is looking like just <see cref="TextureButton "/> but considers whole space around
/// itself (til radial menu buttons) as itself in case of clicking. But this 'effect'
/// 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 : TextureButton
public sealed class RadialMenuContextualCentralTextureButton : RadialMenuTextureButtonBase
{
public float InnerRadius { get; set; }

public float OuterRadius { get; set; }

public Vector2? ParentCenter { get; set; }

/// <inheritdoc />
public RadialMenuContextualCentralTextureButton()
protected override bool HasPoint(Vector2 point)
{
EnableAllKeybinds = true;
if (ParentCenter == null)
{
return base.HasPoint(point);
}

var distSquared = (point + Position - ParentCenter.Value).LengthSquared();

var innerRadiusSquared = InnerRadius * InnerRadius;

// comparing to squared values is faster then making sqrt
return distSquared < innerRadiusSquared;
}
}

/// <summary>
/// Menu button for outer area of radial menu (covers everything 'outside').
/// </summary>
public sealed class RadialMenuOuterAreaButton : RadialMenuTextureButtonBase
{
public float OuterRadius { get; set; }

public Vector2? ParentCenter { get; set; }

/// <inheritdoc />
protected override bool HasPoint(Vector2 point)
Expand All @@ -240,20 +285,15 @@ protected override bool HasPoint(Vector2 point)

var distSquared = (point + Position - ParentCenter.Value).LengthSquared();

// Button space is inside half of container radius / or outside double of its radius.
// half of radius and double the radius are radial menu concentric circles that are
// created by radial menu buttons.
var outerRadiusSquared = OuterRadius * OuterRadius;
var innerRadiusSquared = InnerRadius * InnerRadius;

// comparing to squared values is faster then making sqrt
return distSquared > outerRadiusSquared || distSquared < innerRadiusSquared;
// comparing to squared values is faster, then making sqrt
return distSquared > outerRadiusSquared;
}
}


[Virtual]
public class RadialMenuTextureButton : TextureButton
public class RadialMenuTextureButton : RadialMenuTextureButtonBase
{
/// <summary>
/// Upon clicking this button the radial menu will be moved to the named layer
Expand Down

0 comments on commit 66d2942

Please sign in to comment.