diff --git a/Source/Engine/UI/GUI/Special/RadialMenu.cs b/Source/Engine/UI/GUI/Special/RadialMenu.cs
index 060c4ef90..994d81ab2 100644
--- a/Source/Engine/UI/GUI/Special/RadialMenu.cs
+++ b/Source/Engine/UI/GUI/Special/RadialMenu.cs
@@ -5,14 +5,14 @@ using System;
namespace FlaxEngine.GUI
{
///
- /// Radial menu control that arranges child controls (of type Image) in a circle.
+ /// Radial menu control that arranges child controls (of type ) in a circle.
///
///
public class RadialMenu : ContainerControl
{
private bool _materialIsDirty = true;
private float _angle;
- private float _selectedSegment;
+ private int _selectedSegment;
private int _highlightSegment = -1;
private MaterialBase _material;
private MaterialInstance _materialInstance;
@@ -27,7 +27,7 @@ namespace FlaxEngine.GUI
private bool ShowMatProp => _material != null;
///
- /// The material to use for menu background drawing.
+ /// The material used for menu background drawing.
///
[EditorOrder(1)]
public MaterialBase Material
@@ -44,7 +44,7 @@ namespace FlaxEngine.GUI
}
///
- /// Gets or sets the edge offset.
+ /// Gets or sets the offset of the outer edge from the bounds of the Control.
///
[EditorOrder(2), Range(0, 1)]
public float EdgeOffset
@@ -59,7 +59,7 @@ namespace FlaxEngine.GUI
}
///
- /// Gets or sets the thickness.
+ /// Gets or sets the thickness of the menu.
///
[EditorOrder(3), Range(0, 1), VisibleIf(nameof(ShowMatProp))]
public float Thickness
@@ -74,7 +74,7 @@ namespace FlaxEngine.GUI
}
///
- /// Gets or sets control background color (transparent color (alpha=0) means no background rendering).
+ /// Gets or sets control background color (transparent color means no background rendering).
///
[VisibleIf(nameof(ShowMatProp))]
public new Color BackgroundColor
@@ -88,7 +88,7 @@ namespace FlaxEngine.GUI
}
///
- /// Gets or sets the color of the highlight.
+ /// Gets or sets the color of the outer edge highlight.
///
[VisibleIf(nameof(ShowMatProp))]
public Color HighlightColor
@@ -130,19 +130,43 @@ namespace FlaxEngine.GUI
}
///
- /// The selected callback
+ /// The material instance of used to draw the menu.
+ ///
+ [HideInEditor]
+ public MaterialInstance MaterialInstance => _materialInstance;
+
+ ///
+ /// The selected callback.
///
[HideInEditor]
public Action Selected;
///
- /// The allow change selection when inside
+ /// Invoked when the hovered segment is changed.
+ ///
+ [HideInEditor]
+ public Action HoveredSelectionChanged;
+
+ ///
+ /// The selected segment.
+ ///
+ [HideInEditor]
+ public int SelectedSegment => _selectedSegment;
+
+ ///
+ /// Allows the selected to change when the mouse is moved in the empty center of the menu.
///
[VisibleIf(nameof(ShowMatProp))]
public bool AllowChangeSelectionWhenInside;
///
- /// The center as button
+ /// Allows the selected to change when the mouse is moved outside of the menu.
+ ///
+ [VisibleIf(nameof(ShowMatProp))]
+ public bool AllowChangeSelectionWhenOutside;
+
+ ///
+ /// Wether the center is a button.
///
[VisibleIf(nameof(ShowMatProp))]
public bool CenterAsButton;
@@ -225,7 +249,7 @@ namespace FlaxEngine.GUI
var min = ((1 - _edgeOffset) - _thickness) * USize * 0.5f;
var max = (1 - _edgeOffset) * USize * 0.5f;
var val = ((USize * 0.5f) - location).Length;
- if (Mathf.IsInRange(val, min, max) || val < min && AllowChangeSelectionWhenInside)
+ if (Mathf.IsInRange(val, min, max) || val < min && AllowChangeSelectionWhenInside || val > max && AllowChangeSelectionWhenOutside)
{
UpdateAngle(ref location);
}
@@ -276,7 +300,7 @@ namespace FlaxEngine.GUI
var min = ((1 - _edgeOffset) - _thickness) * USize * 0.5f;
var max = (1 - _edgeOffset) * USize * 0.5f;
var val = ((USize * 0.5f) - location).Length;
- if (Mathf.IsInRange(val, min, max) || val < min && AllowChangeSelectionWhenInside)
+ if (Mathf.IsInRange(val, min, max) || val < min && AllowChangeSelectionWhenInside || val > max && AllowChangeSelectionWhenOutside)
{
UpdateAngle(ref location);
}
@@ -347,6 +371,28 @@ namespace FlaxEngine.GUI
base.PerformLayout(force);
}
+ ///
+ /// Updates the current angle and selected segment of the radial menu based on the specified location inside of the control.
+ ///
+ /// The position used to determine the angle and segment selection within the radial menu.
+ public void UpdateAngle(ref Float2 location)
+ {
+ float previousSelectedSegment = _selectedSegment;
+
+ var size = new Float2(USize);
+ var p = (size * 0.5f) - location;
+ var sa = (1.0f / _segmentCount) * Mathf.TwoPi;
+ _angle = Mathf.Atan2(p.X, p.Y);
+ _angle = Mathf.Ceil((_angle - (sa * 0.5f)) / sa) * sa;
+ _selectedSegment = Mathf.RoundToInt((_angle < 0 ? Mathf.TwoPi + _angle : _angle) / sa);
+ if (float.IsNaN(_angle) || float.IsInfinity(_angle))
+ _angle = 0;
+ _materialInstance.SetParameterValue("RadialMenu_Rotation", -_angle + Mathf.Pi);
+
+ if (previousSelectedSegment != _selectedSegment)
+ HoveredSelectionChanged?.Invoke((int)_selectedSegment);
+ }
+
private void UpdateSelectionColor()
{
Color color;
@@ -368,20 +414,6 @@ namespace FlaxEngine.GUI
_materialInstance.SetParameterValue("RadialMenu_SelectionColor", color);
}
- private void UpdateAngle(ref Float2 location)
- {
- var size = new Float2(USize);
- var p = (size * 0.5f) - location;
- var sa = (1.0f / _segmentCount) * Mathf.TwoPi;
- _angle = Mathf.Atan2(p.X, p.Y);
- _angle = Mathf.Ceil((_angle - (sa * 0.5f)) / sa) * sa;
- _selectedSegment = _angle;
- _selectedSegment = Mathf.RoundToInt((_selectedSegment < 0 ? Mathf.TwoPi + _selectedSegment : _selectedSegment) / sa);
- if (float.IsNaN(_angle) || float.IsInfinity(_angle))
- _angle = 0;
- _materialInstance.SetParameterValue("RadialMenu_Rotation", -_angle + Mathf.Pi);
- }
-
private static Float2 Rotate2D(Float2 point, float angle)
{
return new Float2(Mathf.Cos(angle) * point.X + Mathf.Sin(angle) * point.Y,