Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

ScreenSpace - Camera tooltip controller, sweat and tears

Discussion in 'UGUI & TextMesh Pro' started by drHogan, Jan 28, 2015.

  1. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    Hi All,

    I am going through a nightmarish 3 days in order to have a ScreenSpace - Camera canvas-based tooltip that never leaves the screen (it automatically adjust its own position around the mouse pointer to stay on screen if the mouse is hovering a certain element).

    I made the same some time ago in ScreenSpace - Overlay and it worked like a charm. Now this canvas I here i need to have it in Camera space, and i am suffering. Oh man if I am suffering. Now i found a "partial" solution, that doesn't really look charmy to me. So far it is only checking on the horizontal axis (painful enough to figure out). As you see in the pic (the tooltip is the Build Magic etc... panel), it works, but it stays even too far from the edge now, i bet it's due to the viewport approximation (maybe).



    Is there a cleaner and better way to do this?

    This is the code i use (in the onPointerEnter and on the update of the tooltip method)

    Code (CSharp):
    1. public void OnScreenSpaceCamera(){
    2.     Vector3 newPos = GUICamera.ScreenToViewportPoint(Input.mousePosition-new Vector3(xShift,yShift,0f));
    3.  
    4.     width = this.transform.GetComponent<RectTransform>().sizeDelta[0];
    5.     height = this.transform.GetComponent<RectTransform>().sizeDelta[1];
    6.  
    7.     // check and solve problems for the tooltip that goes out of the screen on the horizontal axis
    8.     float val;
    9.  
    10.     Vector3 lowerLeft  = GUICamera.ViewportToWorldPoint(new Vector3(0.0f,0.0f,0.0f));
    11.     Vector3 upperRight = GUICamera.ViewportToWorldPoint(new Vector3(1.0f,1.0f,0.0f));
    12.  
    13.     val = (GUICamera.ViewportToWorldPoint(newPos).x+width/2);
    14.  
    15.     if(val>upperRight.x){
    16.         Vector3 newWorldPos = new Vector3(GUICamera.ViewportToWorldPoint(newPos).x-val-upperRight.x,newPos.y,0f);
    17.         newPos.x = GUICamera.WorldToViewportPoint(newWorldPos).x;
    18.     }
    19.  
    20.     this.transform.position= new Vector3(GUICamera.ViewportToWorldPoint(newPos).x,GUICamera.ViewportToWorldPoint(newPos).y,0f);
    21.     this.gameObject.SetActive(true);
    22.     inside=true;
    23. }
     
  2. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    Ok, apparently this still has some slight lack of precision as in the picture before but it seems to work (the lower bound control is probably useless in my case as my tooltips appear above the mouse pointer, so the should never have a chance to go below the lower bound).

    Is this the only method? It still feels sorta of a weird one to me, but for now it seems to work. Any suggestion is still welcome

    Code (CSharp):
    1. public void OnScreenSpaceCamera(){
    2.         Vector3 newPos = GUICamera.ScreenToViewportPoint(Input.mousePosition-new Vector3(xShift,yShift,0f));
    3.  
    4.         width = this.transform.GetComponent<RectTransform>().sizeDelta[0];
    5.         height = this.transform.GetComponent<RectTransform>().sizeDelta[1];
    6.  
    7.         // check and solve problems for the tooltip that goes out of the screen on the horizontal axis
    8.         float val;
    9.  
    10.         Vector3 lowerLeft  = GUICamera.ViewportToWorldPoint(new Vector3(0.0f,0.0f,0.0f));
    11.         Vector3 upperRight = GUICamera.ViewportToWorldPoint(new Vector3(1.0f,1.0f,0.0f));
    12.  
    13.         //check for right edge of screen
    14.         val = (GUICamera.ViewportToWorldPoint(newPos).x+width/2);
    15.         if(val>upperRight.x){
    16.             Vector3 shifter = new Vector3(val-upperRight.x,0f,0f);
    17.             Vector3 newWorldPos = new Vector3(GUICamera.ViewportToWorldPoint(newPos).x-shifter.x,newPos.y,0f);
    18.             newPos.x = GUICamera.WorldToViewportPoint(newWorldPos).x;
    19.         }
    20.         //check for left edge of screen
    21.         val = (GUICamera.ViewportToWorldPoint(newPos).x-width/2);
    22.         if(val<lowerLeft.x){
    23.             Vector3 shifter = new Vector3(lowerLeft.x-val,0f,0f);
    24.             Vector3 newWorldPos = new Vector3(GUICamera.ViewportToWorldPoint(newPos).x+shifter.x,newPos.y,0f);
    25.             newPos.x = GUICamera.WorldToViewportPoint(newWorldPos).x;
    26.         }
    27.  
    28.         // check and solve problems for the tooltip that goes out of the screen on the vertical axis
    29.  
    30.         //check for upper edge of the screen
    31.         val = (GUICamera.ViewportToWorldPoint(newPos).y+height/2);
    32.         if(val>upperRight.y){
    33.             Vector3 shifter = new Vector3(0f,25f+height/2,0f);
    34.             Vector3 newWorldPos = new Vector3(newPos.x,GUICamera.ViewportToWorldPoint(newPos).y-shifter.y,0f);
    35.             newPos.y = GUICamera.WorldToViewportPoint(newWorldPos).y;
    36.         }
    37.  
    38.         //check for lower edge of the screen
    39.         val = (GUICamera.ViewportToWorldPoint(newPos).y-height/2);
    40.         if(val<lowerLeft.y){
    41.             Vector3 shifter = new Vector3(0f,25f+height/2,0f);
    42.             Vector3 newWorldPos = new Vector3(newPos.x,GUICamera.ViewportToWorldPoint(newPos).y+shifter.y,0f);
    43.             newPos.y = GUICamera.WorldToViewportPoint(newWorldPos).y;
    44.         }
    45.  
    46.         this.transform.position= new Vector3(GUICamera.ViewportToWorldPoint(newPos).x,GUICamera.ViewportToWorldPoint(newPos).y,0f);
    47.         this.gameObject.SetActive(true);
    48.         inside=true;
    49.     }
     
    Last edited: Jan 28, 2015
  3. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    A quick question related to this but also to the advanced tooltip panel that i have (much larger).

    I get some weird behavior, so also when the mouse is not over the tooltip, somehow the tooltip blinks, appearing and disappearing as if the mouse was over the button generating it, then over the tooltip (therefore exiting the button) then over again and so on.

    Is there a way to have the tooltip panel ignoring completely the raycast and stopping obstructing at all the mouse? I tried to add a canvas group to it, and make it not interactable and not blocking the raycasting, but whenever i start the game (in the editor), the interactable and block raycasting gets automatically ticked anyway in the inspector.
     
  4. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
  5. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
    You will need to add a CanvasGroup to the item with "Interactable" disabled to prevent the mouse pointer events firing for the tooltip.
    Basically when your mouse is over your hoverable item the tooltip shows and if the mouse cursor touches the tooltip it will cause a Pointer Exit event on your hoverable item forcing your tooltip to close, rinse and repeat :D
    Either the above or move the tooltip where the cursor can't get it.
     
  6. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    Hi Simon,

    I supposed indeed that was the cause of the problem.
    I tried the CanvasGroup, but as said before, even if interactable is disabled, it still gets automatically tick and enabled when i start the game.

    I paused the game and disabled it again, the first time i use the tooltip it then works well, but if i exit the button and enter it again, it gets enabled again and i have the same problem again. I can deactivate it manually from script maybe, but ain´t it weird?
     
  7. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    Yep, if on the SetTooltip (the tooltip firing function) i access the canvas group and set it not interactable and not blocking raycasting, then it works like a charm. Then it is probably just a bug of the canvas group i guess
     
  8. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
    So you are saying you already have a CanvasGroup setup to be non-interactable but it still allows it until you force it again through code?
    If so then that is a serious bug and needs reporting.
     
  9. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    Yep, that's the exact behavior i faced. Now I went to work (already late cause i coulnd't give up on the tooltip problem until solved) but in the evening will be reporting it.

    Cheers and thanks for the hints!
     
  10. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
  11. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    Will definitely, i was also planning to put the full script on our webpage to download so no problem. Will do in the evening from home. Cheers!
     
    SimonDarksideJ likes this.
  12. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    Here you go for the fool tooltip script (it's only the screenspace - camera version, the screen overlay still needs some polishing)

    It goes attached to a panel with a text child. To call it from the object generating the tooltip it's enough to call SetTooltip(text to be displayed). It also has some rudimentary resizing.

    https://gist.github.com/anonymous/6ce0bf13d078ba616eaf

    cheers!

    PS i slammed a BSD licence on top if it is fine
     
  13. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
    Any scripts in the repo get full attributions in the script, so no worries there :D (including fixes :p)
     
  14. drHogan

    drHogan

    Joined:
    Sep 26, 2012
    Posts:
    200
    Eheh ok, no problem, i just got by my Phd supervisor the paranoia about slamming a BSD everyhere :D Cheers!