diff --git a/CHANGELOG.md b/CHANGELOG.md index a73da20..d27b06f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ Improvements - Improved gamepad navigation by employing angles between elements - Prefer elements that have the same parent as the currently selected element when using gamepad navigation - Allow specifying a custom position for a tooltip to snap to +- Allow tooltips to display for elements when selected in auto-nav mode Fixes - Fixed paragraph links having incorrect hover locations when using special text alignments diff --git a/Demos/UiDemo.cs b/Demos/UiDemo.cs index afec596..98ac9f5 100644 --- a/Demos/UiDemo.cs +++ b/Demos/UiDemo.cs @@ -208,6 +208,12 @@ namespace Demos { this.root.AddChild(new VerticalSpace(3)); this.root.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 10), "Disabled button", "This button can't be clicked or moved to using automatic navigation") {IsDisabled = true}).PositionOffset = new Vector2(0, 1); this.root.AddChild(new Checkbox(Anchor.AutoLeft, new Vector2(1, 10), "Disabled checkbox") {IsDisabled = true}).PositionOffset = new Vector2(0, 1); + this.root.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 10), "Disabled tooltip button", "This button can't be clicked, but can be moved to using automatic navigation, and will display its tooltip even when done so.") { + CanSelectDisabled = true, + IsDisabled = true, + Tooltip = {DisplayInAutoNavMode = true}, + PositionOffset = new Vector2(0, 1) + }); const string alignText = "Paragraphs can have left aligned text, right aligned text and center aligned text."; this.root.AddChild(new VerticalSpace(3)); diff --git a/MLEM.Ui/Elements/Tooltip.cs b/MLEM.Ui/Elements/Tooltip.cs index 885f5f9..2095515 100644 --- a/MLEM.Ui/Elements/Tooltip.cs +++ b/MLEM.Ui/Elements/Tooltip.cs @@ -16,6 +16,10 @@ namespace MLEM.Ui.Elements { /// public StyleProp MouseOffset; /// + /// The offset that this tooltip's top center coordinate should have from the bottom center of the element snapped to when is true. + /// + public StyleProp AutoNavOffset; + /// /// The amount of time that the mouse has to be over an element before it appears /// public StyleProp Delay; @@ -24,17 +28,23 @@ namespace MLEM.Ui.Elements { /// public Paragraph Paragraph; /// + /// Determines whether this tooltip should display when is true, which is when the UI is being controlled using a keyboard or gamepad. + /// If this tooltip is displayed in auto-nav mode, it will display below the selected element with the applied. + /// + public bool DisplayInAutoNavMode; + /// /// The position that this tooltip should be following (or snapped to) instead of the . /// If this value is unset, will be used as the snap position. /// Note that is still applied with this value set. /// public virtual Vector2? SnapPosition { get; set; } - + /// public override bool IsHidden => this.autoHidden || base.IsHidden; private TimeSpan delayCountdown; private bool autoHidden; + private Element snapElement; /// /// Creates a new tooltip with the given settings @@ -88,6 +98,7 @@ namespace MLEM.Ui.Elements { base.InitStyle(style); this.Texture = this.Texture.OrStyle(style.TooltipBackground); this.MouseOffset = this.MouseOffset.OrStyle(style.TooltipOffset); + this.AutoNavOffset = this.AutoNavOffset.OrStyle(style.TooltipAutoNavOffset); this.Delay = this.Delay.OrStyle(style.TooltipDelay); this.ChildPadding = this.ChildPadding.OrStyle(style.TooltipChildPadding); if (this.Paragraph != null) { @@ -97,12 +108,20 @@ namespace MLEM.Ui.Elements { } /// - /// Causes this tooltip's position to be snapped to the mouse position. + /// Causes this tooltip's position to be snapped to the mouse position, or the if is true, or the if set. /// public void SnapPositionToMouse() { + Vector2 snapPosition; + if (this.snapElement != null) { + // center our snap position below the snap element + snapPosition = new Vector2(this.snapElement.DisplayArea.Center.X, this.snapElement.DisplayArea.Bottom) + this.AutoNavOffset; + snapPosition.X -= this.DisplayArea.Width / 2F; + } else { + snapPosition = (this.SnapPosition ?? this.Input.ViewportMousePosition.ToVector2()) + this.MouseOffset.Value; + } + var viewport = this.System.Viewport; - var snapPosition = this.SnapPosition ?? this.Input.ViewportMousePosition.ToVector2(); - var offset = (snapPosition + this.MouseOffset.Value) / this.Scale; + var offset = snapPosition / this.Scale; if (offset.X < viewport.X) offset.X = viewport.X; if (offset.Y < viewport.Y) @@ -119,8 +138,10 @@ namespace MLEM.Ui.Elements { /// /// The system to add this tooltip to /// The name that this tooltip should use - public void Display(UiSystem system, string name) { - system.Add(name, this); + /// Whether this tooltip was successfully added, which is not the case if it is already being displayed currently. + public bool Display(UiSystem system, string name) { + if (system.Add(name, this) == null) + return false; if (this.Delay <= TimeSpan.Zero) { this.IsHidden = false; this.SnapPositionToMouse(); @@ -129,6 +150,7 @@ namespace MLEM.Ui.Elements { this.delayCountdown = this.Delay; } this.autoHidden = false; + return true; } /// @@ -145,8 +167,20 @@ namespace MLEM.Ui.Elements { /// /// The element that should automatically cause the tooltip to appear and disappear when hovered and not hovered, respectively public void AddToElement(Element elementToHover) { - elementToHover.OnMouseEnter += element => this.Display(element.System, element.GetType().Name + "Tooltip"); - elementToHover.OnMouseExit += element => this.Remove(); + elementToHover.OnMouseEnter += e => this.Display(e.System, $"{e.GetType().Name}Tooltip"); + elementToHover.OnMouseExit += e => this.Remove(); + elementToHover.OnSelected += e => { + if (this.DisplayInAutoNavMode) { + this.snapElement = e; + this.Display(e.System, $"{e.GetType().Name}Tooltip"); + } + }; + elementToHover.OnDeselected += e => { + if (this.DisplayInAutoNavMode) { + this.Remove(); + this.snapElement = null; + } + }; } private void Init(Element elementToHover) { diff --git a/MLEM.Ui/Style/UiStyle.cs b/MLEM.Ui/Style/UiStyle.cs index 4870e84..5c4491b 100644 --- a/MLEM.Ui/Style/UiStyle.cs +++ b/MLEM.Ui/Style/UiStyle.cs @@ -151,6 +151,10 @@ namespace MLEM.Ui.Style { /// public Vector2 TooltipOffset = new Vector2(8, 16); /// + /// The offset of the element's top center coordinate from the bottom center of the element snapped to when is true. + /// + public Vector2 TooltipAutoNavOffset = new Vector2(0, 8); + /// /// The color that the text of a should have /// public Color TooltipTextColor = Color.White;