Hi there, I am trying to make a tooltip for Node2D elements displayed in my 2D game. My game tree looks like this:

Viewport (root) ---- Main map (a Node2D) -------- Camera2D -------- Tilemap -------- Sprite ------------- tooltip ( a Control ) ----------------- Label

I manage to have the tooltip displayed at the right place when the mouse is around the sprite. (nice!) But the tooltip gets scaled with the camera, resulting in unreadable text when I zoom out. I would like the size of the tooltip to stay constant, ie not scaling with its parent sprite. Is there a simple way to do that ?

By the way, here is the code of my tooltip control:

     public class MyToolTip : Control
        {
            Label _child;
            public MyToolTip(string txt)
            {
                _child = new Label();
                _child.Text = txt;
                this.AddChild(_child);
    
                this.Connect("mouse_entered", this, nameof(OnMouseEntered));
                this.Connect("mouse_exited", this, nameof(OnMouseExit));
    
                this.RectMinSize = new Vector2(16, 16);
                this.RectPosition = -this.RectMinSize / 2;
                _child.RectPosition = new Vector2(30, 30);
    
                _child.Visible = false;
                // Not setting "this.Visible = false;"
                // That would prevent getting the next "mouse_entered" messages
                this.Visible = true;
    
            }
            void OnMouseEntered()
            {
                _child.Visible = true;
            }
            void OnMouseExit()
            {
                _child.Visible = false; 
            }
        }

@TwistedTwigleg said: Maybe using set_as_toplevel would work? You would lose the position being relative to the parent node though.

Well, the position relative to parent seems important for a tooltip. I would need an option to apply only part if the transformation. But this got me thinking and I finally got it working by manually scaling the label by the inverse transform. Like this:

        void OnMouseEntered()
        {
            var transformScale = this.GetViewportTransform().Scale;
            _child.RectScale = new Vector2(1 / transformScale.x, 1 / transformScale.y);
            _child.RectPosition = new Vector2(30, 30) * _child.RectScale;
            _child.Visible = true;
            _child.Update();
        }

It works, but feels bit hacky. I am still interested by a cleaner solution is there is any :)

You can draw the tooltips directly on the screen. So you can create a CanvasLayer for your UI elements (also useful for health or ammo stats) and then draw the tooltip to that. To get the correct position, you will have to use get_global_transform_with_canvas() on the player object (this will get the x/y position on the screen). Then set the tooltip to that position, minus some y value so it is above. However, in this case, you will have to call get_global_transform_with_canvas() on _process() to update the position every frame as the x/y values will change every time either the camera moves or the player moves. This would be the correct solution.

a year later