Skip to content

Instantly share code, notes, and snippets.

@Glynn-Taylor
Created October 10, 2019 18:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Glynn-Taylor/b139142f02d99d98af4fb279058f328f to your computer and use it in GitHub Desktop.
Save Glynn-Taylor/b139142f02d99d98af4fb279058f328f to your computer and use it in GitHub Desktop.
A self contained/instantiating Tooltip example for Unity3D, call with Tooltip.StartDisplay("some text")
using UnityEngine;
using UnityEngine.UI;
[AddComponentMenu("")]
public class Tooltip : MonoBehaviour
{
static Tooltip instance;
TMPro.TextMeshProUGUI Text;
Canvas canvas;
RectTransform tooltipPanel;
Vector3 offset = Vector3.up * 10;
const float PADDING = 10;
const float TEXT_PADDING = 5;
const float SCREEN_BORDER = 5;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void Init()
{
GameObject instanceCanvas = new GameObject("STATIC_Tooltip");
Canvas canvas = instanceCanvas.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
instance = instanceCanvas.AddComponent<Tooltip>();
DontDestroyOnLoad(instanceCanvas);
instance.canvas = canvas;
//Canvas settings
canvas.sortingOrder = 99;
//Scaler
CanvasScaler scaler = instanceCanvas.AddComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(3840, 2160);
//Panel
GameObject panel = new GameObject("Panel");
panel.transform.SetParent(instanceCanvas.transform, false);
Image panelImg = panel.AddComponent<Image>();
panelImg.color = new Color(0.25f, 0.25f, 0.25f, 1f);
//panel.StretchToParent(0, 1, 1, 1);
VerticalLayoutGroup panelGroup = panel.AddComponent<VerticalLayoutGroup>();
ContentSizeFitter panelSizeFitter = panel.AddComponent<ContentSizeFitter>();
panelSizeFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
panelSizeFitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
panel.GetComponent<RectTransform>().pivot = new Vector2(0.5f, 0);
instance.tooltipPanel = panel.GetComponent<RectTransform>();
//BG Panel
GameObject BGPanel = new GameObject("BGPanel");
BGPanel.AddComponent<Image>().color = Color.black; //image also forces recttransform
BGPanel.transform.SetParent(panel.transform, false);
BGPanel.StretchToParent(0, 0, 1, 1);
RectTransform bgRT = BGPanel.GetComponent<RectTransform>();
bgRT.SetLeft(PADDING);
bgRT.SetRight(PADDING);
bgRT.SetBottom(PADDING);
bgRT.SetTop(PADDING);
LayoutElement BGLayoutElement = BGPanel.AddComponent<LayoutElement>();
BGLayoutElement.ignoreLayout = true;
//Text
GameObject textOBJ = new GameObject("Text");
instance.Text = textOBJ.AddComponent<TMPro.TextMeshProUGUI>(); //Forces rect transform
textOBJ.transform.SetParent(panel.transform, false);
textOBJ.StretchToParent(0, 0, 1, 1);
instance.Text.color = Color.white;
instance.Text.text = "<size=55>Potato</size><br><color=yellow>Rare</color><br><color=green>Use: Restores 5 health to user</color><br>Sell price: 9999";
LayoutElement textLayoutElement = textOBJ.AddComponent<LayoutElement>();
textLayoutElement.flexibleHeight = 1;
ContentSizeFitter textSizeFitter = textOBJ.AddComponent<ContentSizeFitter>();
textSizeFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
instance.Text.margin = new Vector4(PADDING + TEXT_PADDING, PADDING + TEXT_PADDING, PADDING + TEXT_PADDING, PADDING + TEXT_PADDING);
//Start hidden
instance.gameObject.SetActive(false);
}
private void Update()
{
if (!gameObject.activeSelf)
return;
TrackCursor();
}
private void TrackCursor()
{
Vector3 newPos = Input.mousePosition + offset;
newPos.z = 0f;
float rightEdgeToScreenEdgeDistance = Screen.width - (newPos.x + tooltipPanel.rect.width * canvas.scaleFactor / 2) - SCREEN_BORDER;
if (rightEdgeToScreenEdgeDistance < 0)
{
newPos.x += rightEdgeToScreenEdgeDistance;
}
float leftEdgeToScreenEdgeDistance = 0 - (newPos.x - tooltipPanel.rect.width * canvas.scaleFactor / 2) + SCREEN_BORDER;
if (leftEdgeToScreenEdgeDistance > 0)
{
newPos.x += leftEdgeToScreenEdgeDistance;
}
float topEdgeToScreenEdgeDistance = Screen.height - (newPos.y + tooltipPanel.rect.height * canvas.scaleFactor) - SCREEN_BORDER;
if (topEdgeToScreenEdgeDistance < 0)
{
newPos.y += topEdgeToScreenEdgeDistance;
}
tooltipPanel.transform.position = newPos;
}
public static void StartDisplay(string text)
{
instance.Text.text = text;
instance.gameObject.SetActive(true);
LayoutRebuilder.ForceRebuildLayoutImmediate(instance.tooltipPanel);
}
public static void StopDisplay()
{
instance.gameObject.SetActive(false);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment