Search Unity

(Question) Dynamic tooltips

Discussion in 'UGUI & TextMesh Pro' started by Karmalon, Sep 13, 2014.

  1. Karmalon

    Karmalon

    Joined:
    Jan 15, 2014
    Posts:
    9
    Hello,
    I'm trying to create a tooltip system in Unity 4.6 (i.e. hover over something, a box appears which follows your mouse tells you what the thing you've hovered over is), and it's all working fine until I have hover-able variables next to the edge of my screen, and then part of the tooltip is cut out. Strategy games solve this by changing the X position to the other side, thus solving the problem, but--

    How do I check if a tooltip is beyond the bounds of the canvas (therefore cut out), so I can change its position towards the other side?

    My "tooltip follow" code:
    Code (CSharp):
    1. void Update () {
    2.         Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    3.         mousePos.z = 0;
    4.         transform.position = new Vector3(mousePos.x+3f,mousePos.y-1f,mousePos.z);
    5.     }
     
  2. Kogar

    Kogar

    Joined:
    Jun 27, 2013
    Posts:
    80
    If i understand right you are creating your tooltip yourself? Then it should be possible to grab the width/height of your tooltip container.
    http://forum.unity3d.com/threads/ac...ht-from-code-is-not-so-very-intuitive.265914/
    http://docs.unity3d.com/460/Documentation/ScriptReference/RectTransform-sizeDelta.html
    You can then accordingly adjust the tooltip position if a check with your tooltip position + container width/height is bigger than the camera view resolution (http://docs.unity3d.com/ScriptReference/Camera-pixelWidth.html)
     
  3. Karmalon

    Karmalon

    Joined:
    Jan 15, 2014
    Posts:
    9
    Yeah, the tooltip is a prefab.
    I'll definitely look into your solution.

    EDIT: I tried it. The tooltip starts spazzing out when it comes into the threshold, changing sides rapidly because its position is constantly changing.
    Also the division doesn't work on various resolutions as the pixelWidth changes between them.

    Code (CSharp):
    1. if (rect.sizeDelta.x + rect.sizeDelta.y + transform.position.x + transform.position.y > main.pixelWidth/2.35f) {
    2.             side = 1;
    3.         } else {
    4.             side = 0;
    5.         }
    6.         if(side == 0)
    7.         transform.position = new Vector3(mousePos.x+3f,mousePos.y-1f,mousePos.z);
    8.         else
    9.         transform.position = new Vector3(mousePos.x-2f,mousePos.y-1f,mousePos.z);
     
    Last edited: Sep 13, 2014
  4. Kogar

    Kogar

    Joined:
    Jun 27, 2013
    Posts:
    80
    First whats wrong with your code
    Code (csharp):
    1. if (rect.sizeDelta.x + rect.sizeDelta.y + transform.position.x + transform.position.y > main.pixelWidth/2.35f)
    Since there are two directions that are to be checked (right/left and up/down) this needs two checks and variables.
    And the width/height has to be checked with your current mouse position instead of your tooltip position. Otherwise you would check a value but directly change the value with what you are running your check on. The result would be "Spazzing".

    Not tested. But theoretically should work. For example:
    Code (csharp):
    1. if(rect.sizeDelta.x + mousePos.x +3f > camera.main.pixelWidth) horizontal = 1; else horizontal = 0;  //check your horizontal mouse position
    2. if(rect.sizeDelta.y + mousePos.y +1f > camera.main.pixelHeight) vertical = 1; else vertical = 0; //check your vertical mouse position
    3. if(horizontal == 1)
    4.    offsetX = -rect.sizeDelta.x; else offsetX = 0; //if overdraw change side. Could also be changed to pixel values if they are known to align the tooltip to the side without jumping from one side to the other
    5. if(vertical == 1)
    6.    offsetY = -rect.sizeDelta.y; else offsetY = 0;
    7. transform.position =  new Vector3(mousePos.x +3F + offsetX, mousePos.y +1f +offsetY, mousePos.z);//Change tooltip position according to your mouseposition and overdraw/correction values
    Btw no need to write that for different resolutions since it should get the current absolute pixelvalues that are used and changes position to these values.
     
    Last edited: Sep 14, 2014
    Animallica likes this.
  5. ChoMPi

    ChoMPi

    Joined:
    Jul 11, 2013
    Posts:
    112
    You could check which corner of the screen is the closest to the pointer and therefore change the tooltip pivot to that same corner so this way the tooltip will always display in the opposite direction of the closest corner and never be outside the screen rect...

    This method should save you a lot of heavy calculations and do the same job even better...

    Example
    Code (csharp):
    1.  
    2. // Determine which corner of the screen is closest to the mouse position
    3. Vector2 corner = new Vector2(
    4.     ((Input.mousePosition.x > (Screen.width / 2f)) ? 1f : 0f),
    5.     ((Input.mousePosition.y > (Screen.height / 2f)) ? 1f : 0f)
    6. );
    7.          
    8. (this.transform as RectTransform).pivot = corner;
    9.  
     
    xxhaissamxx, Remi_C, Arcanor and 2 others like this.
  6. Karmalon

    Karmalon

    Joined:
    Jan 15, 2014
    Posts:
    9
    Both methods won't work.
    Kogar's method does nothing and keeps the original problem (clipping through the side), and ChoMPI's method makes the tooltip appear way off screen.
     
  7. Kogar

    Kogar

    Joined:
    Jun 27, 2013
    Posts:
    80
    actually both work.
    From what you defined and asked ChoMPi's solution is a neater solution. It flips the pivot points depending on which half of the monitor the mouseposition is. So to be not way off screen you'd change the pivot point depending on the current mouseposition instead of only flipping the pivot.
    Code (csharp):
    1. transform.position =  mousePos;
    2.      Vector2 corner = new Vector2(
    3.        (Input.mousePosition.x / Screen.width),
    4.        (Input.mousePosition.y / Screen.height)
    5.        );    
    6.      rect.pivot = corner;
    To try I also copy pasted my code. If you would have read the output in the console window you would have seen a red marked part which you must have noticed. Or you would not have been able to run the code.
    I missed to capitalised the c in Camera of camera.main.pixelWidth and camera.main.pixelWidth. Otherwise the code is also functioning properly.
    Here is my completed nearly copy pasted code which i tried on a simple panel . . .
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Tooltip : MonoBehaviour {
    5.    private RectTransform rect;
    6.    private float horizontal;
    7.    private float vertical;
    8.    private Vector3 mousePos;
    9.    private float offsetX, offsetY =0;
    10.  
    11.    void Start () {
    12.      rect = GetComponent<RectTransform>();
    13.    }
    14.  
    15.    void Update () {
    16.      mousePos = Input.mousePosition;
    17.  
    18.      #region my version
    19.      rect.pivot = new Vector2(0,0); //my version currently limited to pivot of 0,0
    20.      if(rect.sizeDelta.x + mousePos.x > Camera.main.pixelWidth) horizontal = 1; else horizontal = 0;  //check your horizontal mouse position
    21.      if(rect.sizeDelta.y + mousePos.y > Camera.main.pixelHeight) vertical = 1; else vertical = 0; //check your vertical mouse position
    22.      if(horizontal == 1)
    23.        offsetX = -rect.sizeDelta.x; else offsetX = 0; //if overdraw change side. Could also be changed to pixel values if they are known to align the tooltip to the side without jumping from one side to the other
    24.      if(vertical == 1)
    25.        offsetY = -rect.sizeDelta.y; else offsetY = 0;
    26.      transform.position =  new Vector3(mousePos.x + offsetX, mousePos.y +offsetY, mousePos.z);//Change tooltip position according to your mouseposition and overdraw/correction values
    27.      transform.position =  new Vector3(mousePos.x + offsetX, mousePos.y +offsetY, mousePos.z);//Change tooltip position according to your mouseposition and overdraw/correction values
    28.      #endregion
    29.  
    30.      /*
    31.      #region adjusted version of ChoMPI's code
    32.      transform.position =  mousePos;
    33.      Vector2 corner = new Vector2(
    34.        (mousePos.x / Screen.width),
    35.        (mousePos.y / Screen.height)
    36.        );    
    37.      rect.pivot = corner;
    38.      #endregion
    39.      */
    40.    }
    41. }
    If you don't want to have jumps from one side to the other you can change in my code the corresponding offsetValues
    Code (csharp):
    1. offsetX = -rect.sizeDelta.x + (Camera.main.pixelWidth - mousePos.x);
    2. offsetY = -rect.sizeDelta.y + (Camera.main.pixelHeight - mousePos.y);
     
    Last edited: Sep 20, 2014
    xxhaissamxx likes this.
  8. Karmalon

    Karmalon

    Joined:
    Jan 15, 2014
    Posts:
    9
    Cheers, it worked!
     
  9. ChoMPi

    ChoMPi

    Joined:
    Jul 11, 2013
    Posts:
    112
     
  10. Karmalon

    Karmalon

    Joined:
    Jan 15, 2014
    Posts:
    9
    Yeah, the tooltip changes pivots no matter where the interactive-able text is. Thanks again.
     
  11. letstalkaboutdune

    letstalkaboutdune

    Joined:
    Oct 12, 2019
    Posts:
    1
    Thanks to all in this thread, especially ChoMPi for the elegant solution!