From 6c639c7f51a9ce6306e5f4fe7c8d0bf688a40a4a Mon Sep 17 00:00:00 2001 From: Lucas Vinicius Date: Sun, 25 Nov 2018 22:56:54 -0200 Subject: [PATCH 1/2] Mixed BoundTooltip with ToolTip, added Screenspace Overlay support --- .../ToolTips/BoundTooltip/BoundTooltipItem.cs | 2 +- .../BoundTooltip/BoundTooltipTrigger.cs | 2 +- Scripts/ToolTips/ToolTip.cs | 319 +++++++++++++----- Scripts/ToolTips/TooltipTrigger.cs | 108 ++++++ Scripts/ToolTips/TooltipTrigger.cs.meta | 11 + 5 files changed, 355 insertions(+), 87 deletions(-) create mode 100644 Scripts/ToolTips/TooltipTrigger.cs create mode 100644 Scripts/ToolTips/TooltipTrigger.cs.meta diff --git a/Scripts/ToolTips/BoundTooltip/BoundTooltipItem.cs b/Scripts/ToolTips/BoundTooltip/BoundTooltipItem.cs index 1f8b890..db9b093 100644 --- a/Scripts/ToolTips/BoundTooltip/BoundTooltipItem.cs +++ b/Scripts/ToolTips/BoundTooltip/BoundTooltipItem.cs @@ -3,7 +3,7 @@ namespace UnityEngine.UI.Extensions { - [AddComponentMenu("UI/Extensions/Bound Tooltip/Tooltip Item")] + [AddComponentMenu("UI/Extensions/Bound Tooltip/Bound Tooltip Item")] public class BoundTooltipItem : MonoBehaviour { public bool IsActive diff --git a/Scripts/ToolTips/BoundTooltip/BoundTooltipTrigger.cs b/Scripts/ToolTips/BoundTooltip/BoundTooltipTrigger.cs index e91de24..051341e 100644 --- a/Scripts/ToolTips/BoundTooltip/BoundTooltipTrigger.cs +++ b/Scripts/ToolTips/BoundTooltip/BoundTooltipTrigger.cs @@ -4,7 +4,7 @@ using UnityEngine.EventSystems; namespace UnityEngine.UI.Extensions { - [AddComponentMenu("UI/Extensions/Bound Tooltip/Tooltip Trigger")] + [AddComponentMenu("UI/Extensions/Bound Tooltip/Bound Tooltip Trigger")] public class BoundTooltipTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler { [TextAreaAttribute] diff --git a/Scripts/ToolTips/ToolTip.cs b/Scripts/ToolTips/ToolTip.cs index e921b1c..902fcc2 100644 --- a/Scripts/ToolTips/ToolTip.cs +++ b/Scripts/ToolTips/ToolTip.cs @@ -1,7 +1,8 @@ /// Credit drHogan /// Sourced from - http://forum.unity3d.com/threads/screenspace-camera-tooltip-controller-sweat-and-tears.293991/#post-1938929 /// updated ddreaper - refactored code to be more performant. -/// *Note - only works for Screenspace Camera canvases at present, needs updating to include Screenspace and Worldspace! +/// updated lucasvinbr - mixed with BoundTooltip, should work with Screenspace Camera (non-rotated) and Overlay +/// *Note - only works for non-rotated Screenspace Camera and Screenspace Overlay canvases at present, needs updating to include rotated Screenspace Camera and Worldspace! //ToolTip is written by Emiliano Pastorelli, H&R Tallinn (Estonia), http://www.hammerandravens.com //Copyright (c) 2015 Emiliano Pastorelli, H&R - Hammer&Ravens, Tallinn, Estonia. @@ -22,145 +23,293 @@ namespace UnityEngine.UI.Extensions { [RequireComponent(typeof(RectTransform))] - [AddComponentMenu("UI/Extensions/Tooltip")] + [AddComponentMenu("UI/Extensions/Tooltip/Tooltip")] public class ToolTip : MonoBehaviour { //text of the tooltip private Text _text; - private RectTransform _rectTransform; + private RectTransform _rectTransform, canvasRectTransform; + + [Tooltip("The canvas used by the tooltip as positioning and scaling reference. Should usually be the root Canvas of the hierarchy this component is in")] + public Canvas canvas; + + [Tooltip("Sets if tooltip triggers will run ForceUpdateCanvases and refresh the tooltip's layout group " + + "(if any) when hovered, in order to prevent momentaneous misplacement sometimes caused by ContentSizeFitters")] + public bool tooltipTriggersCanForceCanvasUpdate = false; + + /// + /// the tooltip's Layout Group, if any + /// + private LayoutGroup _layoutGroup; //if the tooltip is inside a UI element private bool _inside; - // private bool _xShifted, _yShifted = false; - private float width, height;//, canvasWidth, canvasHeight; - // private int screenWidth, screenHeight; + public float YShift,xShift; - private float YShift,xShift; - - private RenderMode _guiMode; + [HideInInspector] + public RenderMode guiMode; private Camera _guiCamera; - // Use this for initialization - public void Awake() - { - var _canvas = GetComponentInParent(); - _guiCamera = _canvas.worldCamera; - _guiMode = _canvas.renderMode; - _rectTransform = GetComponent(); + public Camera GuiCamera + { + get + { + if (!_guiCamera) { + _guiCamera = Camera.main; + } - _text = GetComponentInChildren(); + return _guiCamera; + } + } + + private Vector3 screenLowerLeft, screenUpperRight, shiftingVector; + + /// + /// a screen-space point where the tooltip would be placed before applying X and Y shifts and border checks + /// + private Vector3 baseTooltipPos; + + private Vector3 newTTPos; + private Vector3 adjustedNewTTPos; + private Vector3 adjustedTTLocalPos; + private Vector3 shifterForBorders; + + private float borderTest; + + // Standard Singleton Access + private static ToolTip instance; + + public static ToolTip Instance + { + get + { + if (instance == null) + instance = FindObjectOfType(); + return instance; + } + } + + + void Reset() { + canvas = GetComponentInParent(); + canvas = canvas.rootCanvas; + } + + // Use this for initialization + public void Awake() + { + instance = this; + if (!canvas) { + canvas = GetComponentInParent(); + canvas = canvas.rootCanvas; + } + + _guiCamera = canvas.worldCamera; + guiMode = canvas.renderMode; + _rectTransform = GetComponent(); + canvasRectTransform = canvas.GetComponent(); + _layoutGroup = GetComponentInChildren(); + + _text = GetComponentInChildren(); _inside = false; - //size of the screen - // screenWidth = Screen.width; - // screenHeight = Screen.height; - - xShift = 0f; - YShift = -30f; - - // _xShifted = _yShifted = false; - this.gameObject.SetActive(false); } //Call this function externally to set the text of the template and activate the tooltip - public void SetTooltip(string ttext) + public void SetTooltip(string ttext, Vector3 basePos, bool refreshCanvasesBeforeGetSize = false) { - if (_guiMode == RenderMode.ScreenSpaceCamera) - { - //set the text and fit the tooltip panel to the text size - _text.text = ttext; + baseTooltipPos = basePos; - _rectTransform.sizeDelta = new Vector2(_text.preferredWidth + 40f, _text.preferredHeight + 25f); + //set the text + if (_text) { + _text.text = ttext; + } + else { + Debug.LogWarning("[ToolTip] Couldn't set tooltip text, tooltip has no child Text component"); + } - OnScreenSpaceCamera(); + ContextualTooltipUpdate(refreshCanvasesBeforeGetSize); - } - } + } //call this function on mouse exit to deactivate the template public void HideTooltip() { - if (_guiMode == RenderMode.ScreenSpaceCamera) - { - this.gameObject.SetActive(false); - _inside = false; - } + gameObject.SetActive(false); + _inside = false; } // Update is called once per frame - void FixedUpdate() + void Update() { if (_inside) { - if (_guiMode == RenderMode.ScreenSpaceCamera) - { - OnScreenSpaceCamera(); - } + ContextualTooltipUpdate(); } } - //main tooltip edge of screen guard and movement - public void OnScreenSpaceCamera() - { - Vector3 newPos = _guiCamera.ScreenToViewportPoint(Input.mousePosition - new Vector3(xShift, YShift, 0f)); - Vector3 newPosWVP = _guiCamera.ViewportToWorldPoint(newPos); + /// + /// forces rebuilding of Canvases in order to update the tooltip's content size fitting. + /// Can prevent the tooltip from being visibly misplaced for one frame when being resized. + /// Only runs if tooltipTriggersCanForceCanvasUpdate is true + /// + public void RefreshTooltipSize() { + if (tooltipTriggersCanForceCanvasUpdate) { + Canvas.ForceUpdateCanvases(); - width = _rectTransform.sizeDelta[0]; - height = _rectTransform.sizeDelta[1]; + if (_layoutGroup) { + _layoutGroup.enabled = false; + _layoutGroup.enabled = true; + } + + } + + } + + /// + /// Runs the appropriate tooltip placement method, according to the parent canvas's render mode + /// + /// + public void ContextualTooltipUpdate(bool refreshCanvasesBeforeGettingSize = false) { + switch (guiMode) { + case RenderMode.ScreenSpaceCamera: + OnScreenSpaceCamera(refreshCanvasesBeforeGettingSize); + break; + case RenderMode.ScreenSpaceOverlay: + OnScreenSpaceOverlay(refreshCanvasesBeforeGettingSize); + break; + } + } + + //main tooltip edge of screen guard and movement - camera + public void OnScreenSpaceCamera(bool refreshCanvasesBeforeGettingSize = false) + { + shiftingVector.x = xShift; + shiftingVector.y = YShift; + + baseTooltipPos.z = canvas.planeDistance; + + newTTPos = GuiCamera.ScreenToViewportPoint(baseTooltipPos - shiftingVector); + adjustedNewTTPos = GuiCamera.ViewportToWorldPoint(newTTPos); + + gameObject.SetActive(true); + + if (refreshCanvasesBeforeGettingSize) RefreshTooltipSize(); + + //consider scaled dimensions when comparing against the edges + width = transform.lossyScale.x * _rectTransform.sizeDelta[0]; + height = transform.lossyScale.y * _rectTransform.sizeDelta[1]; // check and solve problems for the tooltip that goes out of the screen on the horizontal axis - float val; - Vector3 lowerLeft = _guiCamera.ViewportToWorldPoint(new Vector3(0.0f, 0.0f, 0.0f)); - Vector3 upperRight = _guiCamera.ViewportToWorldPoint(new Vector3(1.0f, 1.0f, 0.0f)); + RectTransformUtility.ScreenPointToWorldPointInRectangle(canvasRectTransform, Vector2.zero, GuiCamera, out screenLowerLeft); + RectTransformUtility.ScreenPointToWorldPointInRectangle(canvasRectTransform, new Vector2(Screen.width, Screen.height), GuiCamera, out screenUpperRight); - //check for right edge of screen - val = (newPosWVP.x + width / 2); - if (val > upperRight.x) + + //check for right edge of screen + borderTest = (adjustedNewTTPos.x + width / 2); + if (borderTest > screenUpperRight.x) { - Vector3 shifter = new Vector3(val - upperRight.x, 0f, 0f); - Vector3 newWorldPos = new Vector3(newPosWVP.x - shifter.x, newPos.y, 0f); - newPos.x = _guiCamera.WorldToViewportPoint(newWorldPos).x; + shifterForBorders.x = borderTest - screenUpperRight.x; + adjustedNewTTPos.x -= shifterForBorders.x; } //check for left edge of screen - val = (newPosWVP.x - width / 2); - if (val < lowerLeft.x) + borderTest = (adjustedNewTTPos.x - width / 2); + if (borderTest < screenLowerLeft.x) { - Vector3 shifter = new Vector3(lowerLeft.x - val, 0f, 0f); - Vector3 newWorldPos = new Vector3(newPosWVP.x + shifter.x, newPos.y, 0f); - newPos.x = _guiCamera.WorldToViewportPoint(newWorldPos).x; + shifterForBorders.x = screenLowerLeft.x - borderTest; + adjustedNewTTPos.x += shifterForBorders.x; } - // check and solve problems for the tooltip that goes out of the screen on the vertical axis + // check and solve problems for the tooltip that goes out of the screen on the vertical axis - //check for upper edge of the screen - val = (newPosWVP.y + height / 2); - if (val > upperRight.y) + //check for lower edge of the screen + borderTest = (adjustedNewTTPos.y - height / 2); + if (borderTest < screenLowerLeft.y) { + shifterForBorders.y = screenLowerLeft.y - borderTest; + adjustedNewTTPos.y += shifterForBorders.y; + } + + //check for upper edge of the screen + borderTest = (adjustedNewTTPos.y + height / 2); + if (borderTest > screenUpperRight.y) { - Vector3 shifter = new Vector3(0f, 35f + height / 2, 0f); - Vector3 newWorldPos = new Vector3(newPos.x, newPosWVP.y - shifter.y, 0f); - newPos.y = _guiCamera.WorldToViewportPoint(newWorldPos).y; + shifterForBorders.y = borderTest - screenUpperRight.y; + adjustedNewTTPos.y -= shifterForBorders.y; } - //check for lower edge of the screen (if the shifts of the tooltip are kept as in this code, no need for this as the tooltip always appears above the mouse bu default) - val = (newPosWVP.y - height / 2); - if (val < lowerLeft.y) - { - Vector3 shifter = new Vector3(0f, 35f + height / 2, 0f); - Vector3 newWorldPos = new Vector3(newPos.x, newPosWVP.y + shifter.y, 0f); - newPos.y = _guiCamera.WorldToViewportPoint(newWorldPos).y; - } + //failed attempt to circumvent issues caused when rotating the camera + adjustedNewTTPos = transform.rotation * adjustedNewTTPos; - this.transform.position = new Vector3(newPosWVP.x, newPosWVP.y, 0f); - this.gameObject.SetActive(true); - _inside = true; + transform.position = adjustedNewTTPos; + adjustedTTLocalPos = transform.localPosition; + adjustedTTLocalPos.z = 0; + transform.localPosition = adjustedTTLocalPos; + + _inside = true; } - } + + + //main tooltip edge of screen guard and movement - overlay + public void OnScreenSpaceOverlay(bool refreshCanvasesBeforeGettingSize = false) { + shiftingVector.x = xShift; + shiftingVector.y = YShift; + newTTPos = (baseTooltipPos - shiftingVector) / canvas.scaleFactor; + adjustedNewTTPos = newTTPos; + + gameObject.SetActive(true); + + if (refreshCanvasesBeforeGettingSize) RefreshTooltipSize(); + + width = _rectTransform.sizeDelta[0]; + height = _rectTransform.sizeDelta[1]; + + // check and solve problems for the tooltip that goes out of the screen on the horizontal axis + //screen's 0 = overlay canvas's 0 (always?) + screenLowerLeft = Vector3.zero; + screenUpperRight = canvasRectTransform.sizeDelta; + + //check for right edge of screen + borderTest = (newTTPos.x + width / 2); + if (borderTest > screenUpperRight.x) { + shifterForBorders.x = borderTest - screenUpperRight.x; + adjustedNewTTPos.x -= shifterForBorders.x; + } + //check for left edge of screen + borderTest = (adjustedNewTTPos.x - width / 2); + if (borderTest < screenLowerLeft.x) { + shifterForBorders.x = screenLowerLeft.x - borderTest; + adjustedNewTTPos.x += shifterForBorders.x; + } + + // check and solve problems for the tooltip that goes out of the screen on the vertical axis + + //check for lower edge of the screen + borderTest = (adjustedNewTTPos.y - height / 2); + if (borderTest < screenLowerLeft.y) { + shifterForBorders.y = screenLowerLeft.y - borderTest; + adjustedNewTTPos.y += shifterForBorders.y; + } + + //check for upper edge of the screen + borderTest = (adjustedNewTTPos.y + height / 2); + if (borderTest > screenUpperRight.y) { + shifterForBorders.y = borderTest - screenUpperRight.y; + adjustedNewTTPos.y -= shifterForBorders.y; + } + + //remove scale factor for the actual positioning of the TT + adjustedNewTTPos *= canvas.scaleFactor; + transform.position = adjustedNewTTPos; + + _inside = true; + } + } } \ No newline at end of file diff --git a/Scripts/ToolTips/TooltipTrigger.cs b/Scripts/ToolTips/TooltipTrigger.cs new file mode 100644 index 0000000..f8c848b --- /dev/null +++ b/Scripts/ToolTips/TooltipTrigger.cs @@ -0,0 +1,108 @@ +using System.Collections; +///Credit Martin Nerurkar // www.martin.nerurkar.de // www.sharkbombs.com +///Sourced from - http://www.sharkbombs.com/2015/02/10/tooltips-with-the-new-unity-ui-ugui/ +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + [RequireComponent(typeof(RectTransform))] + [AddComponentMenu("UI/Extensions/Tooltip/Tooltip Trigger")] + public class TooltipTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler + { + [TextAreaAttribute] + public string text; + + public enum TooltipPositioningType { + mousePosition, + mousePositionAndFollow, + transformPosition + } + + [Tooltip("Defines where the tooltip will be placed and how that placement will occur. Transform position will always be used if this element wasn't selected via mouse")] + public TooltipPositioningType tooltipPositioningType = TooltipPositioningType.mousePosition; + + /// + /// This info is needed to make sure we make the necessary translations if the tooltip and this trigger are children of different space canvases + /// + private bool isChildOfOverlayCanvas = false; + + private bool hovered = false; + + public Vector3 offset; + + + void Start() { + //attempt to check if our canvas is overlay or not and check our "is overlay" accordingly + Canvas ourCanvas = GetComponentInParent(); + if (ourCanvas && ourCanvas.renderMode == RenderMode.ScreenSpaceOverlay) { + isChildOfOverlayCanvas = true; + } + } + + /// + /// Checks if the tooltip and the transform this trigger is attached to are children of differently-spaced Canvases + /// + public bool WorldToScreenIsRequired + { + get + { + return (isChildOfOverlayCanvas && ToolTip.Instance.guiMode == RenderMode.ScreenSpaceCamera) || + (!isChildOfOverlayCanvas && ToolTip.Instance.guiMode == RenderMode.ScreenSpaceOverlay); + } + } + + public void OnPointerEnter(PointerEventData eventData) + { + switch (tooltipPositioningType) { + case TooltipPositioningType.mousePosition: + StartHover(Input.mousePosition + offset, true); + break; + case TooltipPositioningType.mousePositionAndFollow: + StartHover(Input.mousePosition + offset, true); + hovered = true; + StartCoroutine(HoveredMouseFollowingLoop()); + break; + case TooltipPositioningType.transformPosition: + StartHover((WorldToScreenIsRequired ? + ToolTip.Instance.GuiCamera.WorldToScreenPoint(transform.position) : + transform.position) + offset, true); + break; + } + } + + IEnumerator HoveredMouseFollowingLoop() { + while (hovered) { + StartHover(Input.mousePosition + offset); + yield return null; + } + } + + public void OnSelect(BaseEventData eventData) + { + StartHover((WorldToScreenIsRequired ? + ToolTip.Instance.GuiCamera.WorldToScreenPoint(transform.position) : + transform.position) + offset, true); + } + + public void OnPointerExit(PointerEventData eventData) + { + StopHover(); + } + + public void OnDeselect(BaseEventData eventData) + { + StopHover(); + } + + void StartHover(Vector3 position, bool shouldCanvasUpdate = false) + { + ToolTip.Instance.SetTooltip(text, position, shouldCanvasUpdate); + } + + void StopHover() + { + hovered = false; + ToolTip.Instance.HideTooltip(); + } + } +} diff --git a/Scripts/ToolTips/TooltipTrigger.cs.meta b/Scripts/ToolTips/TooltipTrigger.cs.meta new file mode 100644 index 0000000..67ec3ab --- /dev/null +++ b/Scripts/ToolTips/TooltipTrigger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: abe02588cca16964c8571b21eefea5d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From f9e216adaef1117cff2ab356be5bf20449a7342f Mon Sep 17 00:00:00 2001 From: Lucas Vinicius Date: Sun, 25 Nov 2018 23:04:28 -0200 Subject: [PATCH 2/2] Tabs -> spaces --- Scripts/ToolTips/ToolTip.cs | 370 ++++++++++++++--------------- Scripts/ToolTips/TooltipTrigger.cs | 170 ++++++------- 2 files changed, 270 insertions(+), 270 deletions(-) diff --git a/Scripts/ToolTips/ToolTip.cs b/Scripts/ToolTips/ToolTip.cs index 902fcc2..3d67cd3 100644 --- a/Scripts/ToolTips/ToolTip.cs +++ b/Scripts/ToolTips/ToolTip.cs @@ -30,17 +30,17 @@ namespace UnityEngine.UI.Extensions private Text _text; private RectTransform _rectTransform, canvasRectTransform; - [Tooltip("The canvas used by the tooltip as positioning and scaling reference. Should usually be the root Canvas of the hierarchy this component is in")] - public Canvas canvas; + [Tooltip("The canvas used by the tooltip as positioning and scaling reference. Should usually be the root Canvas of the hierarchy this component is in")] + public Canvas canvas; - [Tooltip("Sets if tooltip triggers will run ForceUpdateCanvases and refresh the tooltip's layout group " + - "(if any) when hovered, in order to prevent momentaneous misplacement sometimes caused by ContentSizeFitters")] - public bool tooltipTriggersCanForceCanvasUpdate = false; + [Tooltip("Sets if tooltip triggers will run ForceUpdateCanvases and refresh the tooltip's layout group " + + "(if any) when hovered, in order to prevent momentaneous misplacement sometimes caused by ContentSizeFitters")] + public bool tooltipTriggersCanForceCanvasUpdate = false; - /// - /// the tooltip's Layout Group, if any - /// - private LayoutGroup _layoutGroup; + /// + /// the tooltip's Layout Group, if any + /// + private LayoutGroup _layoutGroup; //if the tooltip is inside a UI element private bool _inside; @@ -49,72 +49,72 @@ namespace UnityEngine.UI.Extensions public float YShift,xShift; - [HideInInspector] + [HideInInspector] public RenderMode guiMode; private Camera _guiCamera; - public Camera GuiCamera - { - get - { - if (!_guiCamera) { - _guiCamera = Camera.main; - } - - return _guiCamera; - } - } - - private Vector3 screenLowerLeft, screenUpperRight, shiftingVector; - - /// - /// a screen-space point where the tooltip would be placed before applying X and Y shifts and border checks - /// - private Vector3 baseTooltipPos; - - private Vector3 newTTPos; - private Vector3 adjustedNewTTPos; - private Vector3 adjustedTTLocalPos; - private Vector3 shifterForBorders; - - private float borderTest; - - // Standard Singleton Access - private static ToolTip instance; - - public static ToolTip Instance - { - get - { - if (instance == null) - instance = FindObjectOfType(); - return instance; - } - } - - - void Reset() { - canvas = GetComponentInParent(); - canvas = canvas.rootCanvas; - } - - // Use this for initialization - public void Awake() + public Camera GuiCamera { - instance = this; - if (!canvas) { - canvas = GetComponentInParent(); - canvas = canvas.rootCanvas; - } + get + { + if (!_guiCamera) { + _guiCamera = Camera.main; + } - _guiCamera = canvas.worldCamera; + return _guiCamera; + } + } + + private Vector3 screenLowerLeft, screenUpperRight, shiftingVector; + + /// + /// a screen-space point where the tooltip would be placed before applying X and Y shifts and border checks + /// + private Vector3 baseTooltipPos; + + private Vector3 newTTPos; + private Vector3 adjustedNewTTPos; + private Vector3 adjustedTTLocalPos; + private Vector3 shifterForBorders; + + private float borderTest; + + // Standard Singleton Access + private static ToolTip instance; + + public static ToolTip Instance + { + get + { + if (instance == null) + instance = FindObjectOfType(); + return instance; + } + } + + + void Reset() { + canvas = GetComponentInParent(); + canvas = canvas.rootCanvas; + } + + // Use this for initialization + public void Awake() + { + instance = this; + if (!canvas) { + canvas = GetComponentInParent(); + canvas = canvas.rootCanvas; + } + + _guiCamera = canvas.worldCamera; guiMode = canvas.renderMode; _rectTransform = GetComponent(); - canvasRectTransform = canvas.GetComponent(); - _layoutGroup = GetComponentInChildren(); + canvasRectTransform = canvas.GetComponent(); + _layoutGroup = GetComponentInChildren(); - _text = GetComponentInChildren(); + _text = GetComponentInChildren(); _inside = false; @@ -125,19 +125,19 @@ namespace UnityEngine.UI.Extensions public void SetTooltip(string ttext, Vector3 basePos, bool refreshCanvasesBeforeGetSize = false) { - baseTooltipPos = basePos; + baseTooltipPos = basePos; - //set the text - if (_text) { - _text.text = ttext; - } - else { - Debug.LogWarning("[ToolTip] Couldn't set tooltip text, tooltip has no child Text component"); - } + //set the text + if (_text) { + _text.text = ttext; + } + else { + Debug.LogWarning("[ToolTip] Couldn't set tooltip text, tooltip has no child Text component"); + } - ContextualTooltipUpdate(refreshCanvasesBeforeGetSize); + ContextualTooltipUpdate(refreshCanvasesBeforeGetSize); - } + } //call this function on mouse exit to deactivate the template public void HideTooltip() @@ -151,165 +151,165 @@ namespace UnityEngine.UI.Extensions { if (_inside) { - ContextualTooltipUpdate(); + ContextualTooltipUpdate(); } } - /// - /// forces rebuilding of Canvases in order to update the tooltip's content size fitting. - /// Can prevent the tooltip from being visibly misplaced for one frame when being resized. - /// Only runs if tooltipTriggersCanForceCanvasUpdate is true - /// - public void RefreshTooltipSize() { - if (tooltipTriggersCanForceCanvasUpdate) { - Canvas.ForceUpdateCanvases(); + /// + /// forces rebuilding of Canvases in order to update the tooltip's content size fitting. + /// Can prevent the tooltip from being visibly misplaced for one frame when being resized. + /// Only runs if tooltipTriggersCanForceCanvasUpdate is true + /// + public void RefreshTooltipSize() { + if (tooltipTriggersCanForceCanvasUpdate) { + Canvas.ForceUpdateCanvases(); - if (_layoutGroup) { - _layoutGroup.enabled = false; - _layoutGroup.enabled = true; - } - - } - - } + if (_layoutGroup) { + _layoutGroup.enabled = false; + _layoutGroup.enabled = true; + } + + } + + } - /// - /// Runs the appropriate tooltip placement method, according to the parent canvas's render mode - /// - /// - public void ContextualTooltipUpdate(bool refreshCanvasesBeforeGettingSize = false) { - switch (guiMode) { - case RenderMode.ScreenSpaceCamera: - OnScreenSpaceCamera(refreshCanvasesBeforeGettingSize); - break; - case RenderMode.ScreenSpaceOverlay: - OnScreenSpaceOverlay(refreshCanvasesBeforeGettingSize); - break; - } - } + /// + /// Runs the appropriate tooltip placement method, according to the parent canvas's render mode + /// + /// + public void ContextualTooltipUpdate(bool refreshCanvasesBeforeGettingSize = false) { + switch (guiMode) { + case RenderMode.ScreenSpaceCamera: + OnScreenSpaceCamera(refreshCanvasesBeforeGettingSize); + break; + case RenderMode.ScreenSpaceOverlay: + OnScreenSpaceOverlay(refreshCanvasesBeforeGettingSize); + break; + } + } //main tooltip edge of screen guard and movement - camera public void OnScreenSpaceCamera(bool refreshCanvasesBeforeGettingSize = false) { - shiftingVector.x = xShift; - shiftingVector.y = YShift; + shiftingVector.x = xShift; + shiftingVector.y = YShift; - baseTooltipPos.z = canvas.planeDistance; + baseTooltipPos.z = canvas.planeDistance; - newTTPos = GuiCamera.ScreenToViewportPoint(baseTooltipPos - shiftingVector); + newTTPos = GuiCamera.ScreenToViewportPoint(baseTooltipPos - shiftingVector); adjustedNewTTPos = GuiCamera.ViewportToWorldPoint(newTTPos); - gameObject.SetActive(true); + gameObject.SetActive(true); - if (refreshCanvasesBeforeGettingSize) RefreshTooltipSize(); + if (refreshCanvasesBeforeGettingSize) RefreshTooltipSize(); - //consider scaled dimensions when comparing against the edges - width = transform.lossyScale.x * _rectTransform.sizeDelta[0]; + //consider scaled dimensions when comparing against the edges + width = transform.lossyScale.x * _rectTransform.sizeDelta[0]; height = transform.lossyScale.y * _rectTransform.sizeDelta[1]; // check and solve problems for the tooltip that goes out of the screen on the horizontal axis RectTransformUtility.ScreenPointToWorldPointInRectangle(canvasRectTransform, Vector2.zero, GuiCamera, out screenLowerLeft); - RectTransformUtility.ScreenPointToWorldPointInRectangle(canvasRectTransform, new Vector2(Screen.width, Screen.height), GuiCamera, out screenUpperRight); + RectTransformUtility.ScreenPointToWorldPointInRectangle(canvasRectTransform, new Vector2(Screen.width, Screen.height), GuiCamera, out screenUpperRight); - //check for right edge of screen - borderTest = (adjustedNewTTPos.x + width / 2); + //check for right edge of screen + borderTest = (adjustedNewTTPos.x + width / 2); if (borderTest > screenUpperRight.x) { - shifterForBorders.x = borderTest - screenUpperRight.x; - adjustedNewTTPos.x -= shifterForBorders.x; + shifterForBorders.x = borderTest - screenUpperRight.x; + adjustedNewTTPos.x -= shifterForBorders.x; } //check for left edge of screen borderTest = (adjustedNewTTPos.x - width / 2); if (borderTest < screenLowerLeft.x) { - shifterForBorders.x = screenLowerLeft.x - borderTest; - adjustedNewTTPos.x += shifterForBorders.x; + shifterForBorders.x = screenLowerLeft.x - borderTest; + adjustedNewTTPos.x += shifterForBorders.x; } - // check and solve problems for the tooltip that goes out of the screen on the vertical axis + // check and solve problems for the tooltip that goes out of the screen on the vertical axis - //check for lower edge of the screen - borderTest = (adjustedNewTTPos.y - height / 2); - if (borderTest < screenLowerLeft.y) { - shifterForBorders.y = screenLowerLeft.y - borderTest; - adjustedNewTTPos.y += shifterForBorders.y; - } + //check for lower edge of the screen + borderTest = (adjustedNewTTPos.y - height / 2); + if (borderTest < screenLowerLeft.y) { + shifterForBorders.y = screenLowerLeft.y - borderTest; + adjustedNewTTPos.y += shifterForBorders.y; + } - //check for upper edge of the screen - borderTest = (adjustedNewTTPos.y + height / 2); + //check for upper edge of the screen + borderTest = (adjustedNewTTPos.y + height / 2); if (borderTest > screenUpperRight.y) { - shifterForBorders.y = borderTest - screenUpperRight.y; - adjustedNewTTPos.y -= shifterForBorders.y; + shifterForBorders.y = borderTest - screenUpperRight.y; + adjustedNewTTPos.y -= shifterForBorders.y; } - //failed attempt to circumvent issues caused when rotating the camera - adjustedNewTTPos = transform.rotation * adjustedNewTTPos; + //failed attempt to circumvent issues caused when rotating the camera + adjustedNewTTPos = transform.rotation * adjustedNewTTPos; - transform.position = adjustedNewTTPos; - adjustedTTLocalPos = transform.localPosition; - adjustedTTLocalPos.z = 0; - transform.localPosition = adjustedTTLocalPos; + transform.position = adjustedNewTTPos; + adjustedTTLocalPos = transform.localPosition; + adjustedTTLocalPos.z = 0; + transform.localPosition = adjustedTTLocalPos; - _inside = true; + _inside = true; } - //main tooltip edge of screen guard and movement - overlay - public void OnScreenSpaceOverlay(bool refreshCanvasesBeforeGettingSize = false) { - shiftingVector.x = xShift; - shiftingVector.y = YShift; - newTTPos = (baseTooltipPos - shiftingVector) / canvas.scaleFactor; - adjustedNewTTPos = newTTPos; + //main tooltip edge of screen guard and movement - overlay + public void OnScreenSpaceOverlay(bool refreshCanvasesBeforeGettingSize = false) { + shiftingVector.x = xShift; + shiftingVector.y = YShift; + newTTPos = (baseTooltipPos - shiftingVector) / canvas.scaleFactor; + adjustedNewTTPos = newTTPos; - gameObject.SetActive(true); + gameObject.SetActive(true); - if (refreshCanvasesBeforeGettingSize) RefreshTooltipSize(); + if (refreshCanvasesBeforeGettingSize) RefreshTooltipSize(); - width = _rectTransform.sizeDelta[0]; - height = _rectTransform.sizeDelta[1]; + width = _rectTransform.sizeDelta[0]; + height = _rectTransform.sizeDelta[1]; - // check and solve problems for the tooltip that goes out of the screen on the horizontal axis - //screen's 0 = overlay canvas's 0 (always?) - screenLowerLeft = Vector3.zero; - screenUpperRight = canvasRectTransform.sizeDelta; + // check and solve problems for the tooltip that goes out of the screen on the horizontal axis + //screen's 0 = overlay canvas's 0 (always?) + screenLowerLeft = Vector3.zero; + screenUpperRight = canvasRectTransform.sizeDelta; - //check for right edge of screen - borderTest = (newTTPos.x + width / 2); - if (borderTest > screenUpperRight.x) { - shifterForBorders.x = borderTest - screenUpperRight.x; - adjustedNewTTPos.x -= shifterForBorders.x; - } - //check for left edge of screen - borderTest = (adjustedNewTTPos.x - width / 2); - if (borderTest < screenLowerLeft.x) { - shifterForBorders.x = screenLowerLeft.x - borderTest; - adjustedNewTTPos.x += shifterForBorders.x; - } + //check for right edge of screen + borderTest = (newTTPos.x + width / 2); + if (borderTest > screenUpperRight.x) { + shifterForBorders.x = borderTest - screenUpperRight.x; + adjustedNewTTPos.x -= shifterForBorders.x; + } + //check for left edge of screen + borderTest = (adjustedNewTTPos.x - width / 2); + if (borderTest < screenLowerLeft.x) { + shifterForBorders.x = screenLowerLeft.x - borderTest; + adjustedNewTTPos.x += shifterForBorders.x; + } - // check and solve problems for the tooltip that goes out of the screen on the vertical axis + // check and solve problems for the tooltip that goes out of the screen on the vertical axis - //check for lower edge of the screen - borderTest = (adjustedNewTTPos.y - height / 2); - if (borderTest < screenLowerLeft.y) { - shifterForBorders.y = screenLowerLeft.y - borderTest; - adjustedNewTTPos.y += shifterForBorders.y; - } + //check for lower edge of the screen + borderTest = (adjustedNewTTPos.y - height / 2); + if (borderTest < screenLowerLeft.y) { + shifterForBorders.y = screenLowerLeft.y - borderTest; + adjustedNewTTPos.y += shifterForBorders.y; + } - //check for upper edge of the screen - borderTest = (adjustedNewTTPos.y + height / 2); - if (borderTest > screenUpperRight.y) { - shifterForBorders.y = borderTest - screenUpperRight.y; - adjustedNewTTPos.y -= shifterForBorders.y; - } + //check for upper edge of the screen + borderTest = (adjustedNewTTPos.y + height / 2); + if (borderTest > screenUpperRight.y) { + shifterForBorders.y = borderTest - screenUpperRight.y; + adjustedNewTTPos.y -= shifterForBorders.y; + } - //remove scale factor for the actual positioning of the TT - adjustedNewTTPos *= canvas.scaleFactor; - transform.position = adjustedNewTTPos; + //remove scale factor for the actual positioning of the TT + adjustedNewTTPos *= canvas.scaleFactor; + transform.position = adjustedNewTTPos; - _inside = true; - } - } + _inside = true; + } + } } \ No newline at end of file diff --git a/Scripts/ToolTips/TooltipTrigger.cs b/Scripts/ToolTips/TooltipTrigger.cs index f8c848b..b199c03 100644 --- a/Scripts/ToolTips/TooltipTrigger.cs +++ b/Scripts/ToolTips/TooltipTrigger.cs @@ -5,104 +5,104 @@ using UnityEngine.EventSystems; namespace UnityEngine.UI.Extensions { - [RequireComponent(typeof(RectTransform))] - [AddComponentMenu("UI/Extensions/Tooltip/Tooltip Trigger")] - public class TooltipTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler - { - [TextAreaAttribute] - public string text; + [RequireComponent(typeof(RectTransform))] + [AddComponentMenu("UI/Extensions/Tooltip/Tooltip Trigger")] + public class TooltipTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler + { + [TextAreaAttribute] + public string text; - public enum TooltipPositioningType { - mousePosition, - mousePositionAndFollow, - transformPosition - } + public enum TooltipPositioningType { + mousePosition, + mousePositionAndFollow, + transformPosition + } - [Tooltip("Defines where the tooltip will be placed and how that placement will occur. Transform position will always be used if this element wasn't selected via mouse")] - public TooltipPositioningType tooltipPositioningType = TooltipPositioningType.mousePosition; + [Tooltip("Defines where the tooltip will be placed and how that placement will occur. Transform position will always be used if this element wasn't selected via mouse")] + public TooltipPositioningType tooltipPositioningType = TooltipPositioningType.mousePosition; - /// - /// This info is needed to make sure we make the necessary translations if the tooltip and this trigger are children of different space canvases - /// - private bool isChildOfOverlayCanvas = false; + /// + /// This info is needed to make sure we make the necessary translations if the tooltip and this trigger are children of different space canvases + /// + private bool isChildOfOverlayCanvas = false; - private bool hovered = false; + private bool hovered = false; - public Vector3 offset; + public Vector3 offset; - void Start() { - //attempt to check if our canvas is overlay or not and check our "is overlay" accordingly - Canvas ourCanvas = GetComponentInParent(); - if (ourCanvas && ourCanvas.renderMode == RenderMode.ScreenSpaceOverlay) { - isChildOfOverlayCanvas = true; - } - } + void Start() { + //attempt to check if our canvas is overlay or not and check our "is overlay" accordingly + Canvas ourCanvas = GetComponentInParent(); + if (ourCanvas && ourCanvas.renderMode == RenderMode.ScreenSpaceOverlay) { + isChildOfOverlayCanvas = true; + } + } - /// - /// Checks if the tooltip and the transform this trigger is attached to are children of differently-spaced Canvases - /// - public bool WorldToScreenIsRequired - { - get - { - return (isChildOfOverlayCanvas && ToolTip.Instance.guiMode == RenderMode.ScreenSpaceCamera) || - (!isChildOfOverlayCanvas && ToolTip.Instance.guiMode == RenderMode.ScreenSpaceOverlay); - } - } + /// + /// Checks if the tooltip and the transform this trigger is attached to are children of differently-spaced Canvases + /// + public bool WorldToScreenIsRequired + { + get + { + return (isChildOfOverlayCanvas && ToolTip.Instance.guiMode == RenderMode.ScreenSpaceCamera) || + (!isChildOfOverlayCanvas && ToolTip.Instance.guiMode == RenderMode.ScreenSpaceOverlay); + } + } - public void OnPointerEnter(PointerEventData eventData) - { - switch (tooltipPositioningType) { - case TooltipPositioningType.mousePosition: - StartHover(Input.mousePosition + offset, true); - break; - case TooltipPositioningType.mousePositionAndFollow: - StartHover(Input.mousePosition + offset, true); - hovered = true; - StartCoroutine(HoveredMouseFollowingLoop()); - break; - case TooltipPositioningType.transformPosition: - StartHover((WorldToScreenIsRequired ? - ToolTip.Instance.GuiCamera.WorldToScreenPoint(transform.position) : - transform.position) + offset, true); - break; - } - } + public void OnPointerEnter(PointerEventData eventData) + { + switch (tooltipPositioningType) { + case TooltipPositioningType.mousePosition: + StartHover(Input.mousePosition + offset, true); + break; + case TooltipPositioningType.mousePositionAndFollow: + StartHover(Input.mousePosition + offset, true); + hovered = true; + StartCoroutine(HoveredMouseFollowingLoop()); + break; + case TooltipPositioningType.transformPosition: + StartHover((WorldToScreenIsRequired ? + ToolTip.Instance.GuiCamera.WorldToScreenPoint(transform.position) : + transform.position) + offset, true); + break; + } + } - IEnumerator HoveredMouseFollowingLoop() { - while (hovered) { - StartHover(Input.mousePosition + offset); - yield return null; - } - } + IEnumerator HoveredMouseFollowingLoop() { + while (hovered) { + StartHover(Input.mousePosition + offset); + yield return null; + } + } - public void OnSelect(BaseEventData eventData) - { - StartHover((WorldToScreenIsRequired ? - ToolTip.Instance.GuiCamera.WorldToScreenPoint(transform.position) : - transform.position) + offset, true); - } + public void OnSelect(BaseEventData eventData) + { + StartHover((WorldToScreenIsRequired ? + ToolTip.Instance.GuiCamera.WorldToScreenPoint(transform.position) : + transform.position) + offset, true); + } - public void OnPointerExit(PointerEventData eventData) - { - StopHover(); - } + public void OnPointerExit(PointerEventData eventData) + { + StopHover(); + } - public void OnDeselect(BaseEventData eventData) - { - StopHover(); - } + public void OnDeselect(BaseEventData eventData) + { + StopHover(); + } - void StartHover(Vector3 position, bool shouldCanvasUpdate = false) - { - ToolTip.Instance.SetTooltip(text, position, shouldCanvasUpdate); - } + void StartHover(Vector3 position, bool shouldCanvasUpdate = false) + { + ToolTip.Instance.SetTooltip(text, position, shouldCanvasUpdate); + } - void StopHover() - { - hovered = false; - ToolTip.Instance.HideTooltip(); - } - } + void StopHover() + { + hovered = false; + ToolTip.Instance.HideTooltip(); + } + } }