Ren'Py Dynamic Tooltip

ApatiaMax

Newbie
Sep 9, 2022
43
25
I have this phyton code that I use to create and enable/disable places at runtime, but I have some issue with the tooltip because when the mouse gets over a button all tooltips gets displayed and have the same text :cautious:

1690971640131.png

So the code is this:
Code:
init python:
    # MAP PLACES
    class Place(object):
        def __init__(self, x, y, name, isHome, owned, price, IsActive):
            self.x = x
            self.y = y
            self.name = name
            self.isHome = isHome
            self.owned = owned
            self.price = price
            self.IsActive = IsActive
        @property
        def placeIcon(self):
            if self.isHome == True and self.owned == False:
                icon = "map/House_Rentable.png"
            elif self.isHome == True and self.owned == True:
                icon = "map/House_Rented.png"
            else:
                icon = "map/" + self.name.lower() + "_icon.png"
            return(icon)
here the is the code in Ren'Py that I use to display the map and set the tooltip.
I guess that I have to place it inside the Class but I'm not sure if it would works... and even if it have any sense at all.
Code:
screen MapScreen():
    frame:
        xalign 0.0
        yalign 0.0
        xsize 1920
        ysize 1080
        background "map/TownMap.png"
        $ rentableHouse = "map/house_Rentable.png"
        $ rentedHouse = "map/house_Rented.png"
        for q in Places:
            if q.IsActive:
                button:
                    xpos q.x
                    ypos q.y
                    image q.placeIcon
                    if q.price > 0:
                        tooltip "{size=-10}{outlinecolor=#0000FF}" + q.name + " ("+ str(q.price) +"/week){/outlinecolor}{/size}"
                    else:
                        tooltip "{size=-10}{outlinecolor=#0000FF}" + q.name + "{/outlinecolor}{/size}"
                    action Call((q.name).replace(" ",""))
 
                    $ tooltip = GetTooltip()
                    if tooltip:
                        text "[tooltip]"
Also on script.rpy I have a Variables label where I set at start all the locations and if they are active or not:
Code:
$ Places = []
#                                          Icon PosXY       LABEL         isHouse? isOwned? Price Active
$ Places.append(Place(843,264, "RAE Office", False, False, 0, True))
$ Places.append(Place(80, 750, "Cheapest House", True, False, 50, False))
$ Places.append(Place(1292, 840, "Cheap House", True, False, 250, False))
$ Places.append(Place(872, 789, "Tech House", True, False, 500, False))
Thank you in advice for the help :)
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,302
15,172
So the code is this:
Okay, takes into account the fact that I haven't slept this night, and that the alarm from the company working above mine is off since... well, feel like hours, but must be easily twenty minutes. So, I'll be even more direct that usual, sorry if it feel rude.


Code:
screen MapScreen():
[...]
        for q in Places:
            if q.IsActive:
Since there's no else in your code, and by the name of the flag, you would benefit to change this in:
Python:
screen MapScreen():

    default activePlaces = [ p for p in Places if p.isActive ]
[...]
        for q in activePlaces:
#            if q.IsActive:   <- This become useless, only active places will be presented.
default is proceeded only once, when the screen is displayed. This while the for loop is proceeded every time the screen is refreshed ; what goes from once in a while to every 0.15 second, with an average around 3-5 times by second.
The loop would normally not be sensible, but it's an easy optimization that don't really change the code, you might as well use it.


Code:
                button:
                    xpos q.x
                    ypos q.y
                    image q.placeIcon
                    if q.price > 0:
                        tooltip "{size=-10}{outlinecolor=#0000FF}" + q.name + " ("+ str(q.price) +"/week){/outlinecolor}{/size}"
                    else:
                        tooltip "{size=-10}{outlinecolor=#0000FF}" + q.name + "{/outlinecolor}{/size}"
                    action Call((q.name).replace(" ",""))
This is so wrong !!! Terribly wrong.

I don't know where you got this, but forget everything you learn in that place or from that person. This construction based on button is obsolete since more than 12 years. What in the same time deprive you of the advantage presented by .
It should be :
Python:
                imagebutton:
                    idle q.placeIcon
                    xpos q.x
                    ypos q.y
                    if q.price > 0:
                        tooltip "{size=-10}{outlinecolor=#0000FF}" + q.name + " ("+ str(q.price) +"/week){/outlinecolor}{/size}"
                    else:
                        tooltip "{size=-10}{outlinecolor=#0000FF}" + q.name + "{/outlinecolor}{/size}"
                    action Call((q.name).replace(" ",""))
Or, possibly better, because the tooltip is on one line:
Python:
                imagebutton:
                    idle q.placeIcon
                    xpos q.x
                    ypos q.y
                    if q.price > 0:
                    tooltip "{size=-10}{outlinecolor=#0000FF}" + q.name + ( " ("+ str(q.price) +"/week)" if q.price else "" ) + "{/outlinecolor}{/size}"
                    action Call((q.name).replace(" ",""))
Interestingly enough, you use the tooltip property, what is a recent addition. There's something like 10 years between the addition of imagebutton that you don't use, and the addition of this property.


And finally, what is probably the reason of the error you get:
Code:
                button:
                    [...]
                    $ tooltip = GetTooltip()
                    if tooltip:
                        text "[tooltip]"
[/quote]

You handle the tooltip as part of the button, what is really wrong. It should be outside of it, therefore something like:
Python:
screen MapScreen():
    frame:
        [...]    

    $ tooltip = GetTooltip()
    if tooltip:
         xpos 100  # value given as example
         ypos 200  # value given as example
         text "[tooltip]"
If you want the name to be positioned relatively to the button itself, should works. Else you can still do it that way:
Python:
                imagebutton:
[...]
                        tooltip ( "{size=-10}{outlinecolor=#0000FF}" + q.name + " ("+ str(q.price) +"/week){/outlinecolor}{/size}", 100, 200 )
[...]

    $ tooltip = GetTooltip()
    if tooltip:
         xpos tooltip[1]
         ypos tooltip[2]
         text tooltip[0]

Be also noted that the new tooltip system is global ; unlike the initial one that was based on a class generally defined in the screen itself, and therefore limited to the said screen. This mean that if you've two screens displayed simultaneously, that both contain an iteration of this code, the tooltip will be displayed twice. And here, you've as many iteration as clickable on the screen.
 

ApatiaMax

Newbie
Sep 9, 2022
43
25
Oh that's great, thank you so much I've learned more from your post than from a week of reading stuff and tutorials.
I'm coming from about 10 years of C# so I'm completely new on Ren'Py and Phyton.
:geek:(y)

I also decided to keep the
Code:
if isActive
because still more readable for me instead of the Default just because if the Place isn't active means that should be hidden.
Code:
for q in Places:
            if q.isActive == True:
                imagebutton:
                    idle q.placeIcon
                    xpos q.x
                    ypos q.y
Also I noticed that the outline won't work at all, maybe because there's no outline-size? :unsure:
Code:
tooltip ("{size=-10}{outlinecolor=#0000FF}" + q.name + " ("+ str(q.price) +"/week){/outlinecolor}{/size}", q.x, q.y)
And even if I added q.x and q.y
the tooltip looks like that:
1690979347341.png

Anyway thanks for your reply, that's helps me a lot :)
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,302
15,172
Also I noticed that the outline won't work at all, maybe because there's no outline-size? :unsure:
No, I guess that it's because there's no outline at all. The style tag "outlinecolor" do not add an outline it just change its color if there's an outline. Outline that can only be defined directly with a style applied to the text screen statement.


And even if I added q.x and q.y
the tooltip looks like that:
View attachment 2819665
Look how I wrote it. For each element, including the text, you need to address the right row in the tuple (a kind of frozen array), not address the tuple as a whole.