Last active
September 25, 2021 17:25
-
-
Save sinbad/7204edaba7453e48c8c1e837505d054d to your computer and use it in GitHub Desktop.
Simple Unity UI tooltip system (requires DoTween)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using DG.Tweening; | |
using TMPro; | |
using UnityEngine; | |
using UnityEngine.UI; | |
// Attach this component to a UI object which will be the tooltip visual | |
// Must include some text somewhere of course, and optionally a CanvasGroup if you want fading | |
public class TooltipPanel : MonoBehaviour { | |
[Tooltip("The text object which will display the tooltip string")] | |
public TextMeshProUGUI tooltipText; | |
[Tooltip("Whether to move the tooltip with the mouse after it's visible")] | |
public bool moveWithMouse; | |
[Tooltip("The distance from the mouse position the tooltip will appear at (relative to tooltip pivot)")] | |
public Vector2 positionOffset; | |
[Tooltip("The margins from the edge of the screen which the tooltip will stay within")] | |
public Vector2 margins; | |
[Tooltip("The fade in/out duration of the tooltip: requires that this object has a CanvasGroup component, ignored if it doesn't")] | |
public float fadeDuration = 0.25f; | |
private Canvas parentCanvas; | |
private RectTransform rectTransform; | |
private CanvasGroup canvasGroup; | |
private Tweener fadeTween; | |
private RectTransform triggerObject; | |
private void Awake() { | |
rectTransform = GetComponent<RectTransform>(); | |
canvasGroup = GetComponent<CanvasGroup>(); | |
parentCanvas = GetComponentInParent<Canvas>(); | |
} | |
private void Start() { | |
gameObject.SetActive(false); | |
} | |
private void Update() { | |
if (moveWithMouse) | |
Reposition(); | |
} | |
private void Reposition() { | |
Vector2 screenPos = Input.mousePosition; | |
// world position origin is wherever the pivot is | |
Vector2 newPos = screenPos + positionOffset; | |
float maxX = Screen.width - margins.x; | |
float minX = margins.x; | |
float maxY = Screen.height - margins.y; | |
float minY = margins.y; | |
float rightEdge = newPos.x + (1f - rectTransform.pivot.x) * rectTransform.rect.width * parentCanvas.scaleFactor; | |
if (rightEdge > maxX) { | |
newPos.x -= rightEdge - maxX; | |
} | |
float leftEdge = newPos.x - rectTransform.pivot.x * rectTransform.rect.width * parentCanvas.scaleFactor; | |
if (leftEdge < minX) { | |
newPos.x += minX - leftEdge; | |
} | |
// y is measured from top | |
float topEdge = newPos.y + (1f - rectTransform.pivot.y) * rectTransform.rect.height * parentCanvas.scaleFactor; | |
if (topEdge > maxY) { | |
newPos.y -= topEdge - maxY; | |
} | |
float bottomEdge = newPos.y - rectTransform.pivot.y * rectTransform.rect.height * parentCanvas.scaleFactor; | |
if (bottomEdge < minY) { | |
newPos.y += minY - bottomEdge; | |
} | |
var cam = parentCanvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : parentCanvas.worldCamera; | |
RectTransformUtility.ScreenPointToWorldPointInRectangle(triggerObject, newPos, cam, out var worldPoint); | |
rectTransform.position = worldPoint; | |
} | |
public void Show(string text, RectTransform triggeredBy) { | |
if (gameObject.activeSelf) | |
return; | |
triggerObject = triggeredBy; | |
tooltipText.text = text; | |
if (fadeTween != null) { | |
fadeTween.Kill(); | |
fadeTween = null; | |
} | |
bool fade = canvasGroup != null && fadeDuration > 0; | |
if (fade) | |
canvasGroup.alpha = 0; | |
gameObject.SetActive(true); | |
if (fade) { | |
fadeTween = canvasGroup.DOFade(1, fadeDuration) | |
.SetUpdate(true) | |
.OnComplete(() => { fadeTween = null; }); | |
} | |
// in case we need to resize (e.g. content fitter) | |
LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform); | |
Reposition(); | |
} | |
public void Hide() { | |
if (!gameObject.activeSelf) | |
return; | |
if (fadeTween != null) { | |
fadeTween.Kill(); | |
fadeTween = null; | |
} | |
bool fade = canvasGroup != null && fadeDuration > 0; | |
if (fade) { | |
// Fade out | |
fadeTween = canvasGroup.DOFade(1, fadeDuration) | |
.SetUpdate(true) | |
.OnComplete(() => { | |
gameObject.SetActive(false); | |
fadeTween = null; | |
}); | |
} else { | |
gameObject.SetActive(false); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.EventSystems; | |
[RequireComponent(typeof(RectTransform))] | |
public class TooltipTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler { | |
[Tooltip("The tooltip canvas which will display the tooltip. If not specified, we'll try to find one.")] | |
public TooltipPanel tooltipPanel; | |
[Tooltip("The text to display in the tooltip")] | |
public string text; | |
[Tooltip("How long the mouse must linger on us before showing the tooltip")] | |
public float delay = 1f; | |
private bool mouseIsHovering; | |
private float mouseHoverTime; | |
private RectTransform rectTransform; | |
private void Awake() { | |
rectTransform = GetComponent<RectTransform>(); | |
} | |
private void Start() { | |
if (tooltipPanel == null) { | |
var canvases = Resources.FindObjectsOfTypeAll<TooltipPanel>(); | |
if (canvases.Length > 0) | |
tooltipPanel = canvases[0]; | |
} | |
} | |
public void OnPointerEnter(PointerEventData eventData) { | |
mouseIsHovering = true; | |
mouseHoverTime = 0; | |
} | |
public void OnPointerExit(PointerEventData eventData) { | |
mouseIsHovering = false; | |
HideTooltip(); | |
} | |
private void Update() { | |
// Cancel on any mouse down | |
// not via event because we might not receive it | |
if (Input.GetMouseButtonDown(0)) { | |
mouseIsHovering = false; | |
HideTooltip(); | |
} | |
if (mouseIsHovering) { | |
mouseHoverTime += Time.unscaledDeltaTime; | |
if (mouseHoverTime >= delay) | |
ShowTooltip(); | |
} | |
} | |
private void ShowTooltip() { | |
if (tooltipPanel != null) | |
tooltipPanel.Show(text, rectTransform); | |
} | |
private void HideTooltip() { | |
if (tooltipPanel != null) | |
tooltipPanel.Hide(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is free and unencumbered software released into the public domain. | |
Anyone is free to copy, modify, publish, use, compile, sell, or | |
distribute this software, either in source code form or as a compiled | |
binary, for any purpose, commercial or non-commercial, and by any | |
means. | |
In jurisdictions that recognize copyright laws, the author or authors | |
of this software dedicate any and all copyright interest in the | |
software to the public domain. We make this dedication for the benefit | |
of the public at large and to the detriment of our heirs and | |
successors. We intend this dedication to be an overt act of | |
relinquishment in perpetuity of all present and future rights to this | |
software under copyright law. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
OTHER DEALINGS IN THE SOFTWARE. | |
For more information, please refer to <http://unlicense.org/> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It worked at the time, probably a Unity change. I don't use Unity anymore so won't be updating it, sorry.