diff --git a/Source/Engine/UI/GUI/Special/RadialMenu.cs b/Source/Engine/UI/GUI/Special/RadialMenu.cs index 060c4ef90..f8309fb1e 100644 --- a/Source/Engine/UI/GUI/Special/RadialMenu.cs +++ b/Source/Engine/UI/GUI/Special/RadialMenu.cs @@ -5,7 +5,7 @@ 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 @@ -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,37 @@ namespace FlaxEngine.GUI } /// - /// The selected callback + /// 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 float 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 +243,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 +294,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 +365,29 @@ 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 = _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); + + if (previousSelectedSegment != _selectedSegment) + HoveredSelectionChanged?.Invoke((int)_selectedSegment); + } + private void UpdateSelectionColor() { Color color; @@ -368,20 +409,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,