Dialogue Tooltips/Hoverable words?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
Warhouse
Newbie
Posts: 7
Joined: Fri Mar 29, 2019 7:26 am
Contact:

Dialogue Tooltips/Hoverable words?

#1 Post by Warhouse »

Hello. I've been trying to work out how to make a dialogue tooltip system similar to Pyre's. In that game, certain words are highlighted, and you can hover over them with your mouse to get a tooltip, giving you background on the subject of that word.
So, they have intractable textbutton-like words in the dialogue box.

I've been searching and fiddling for a while now, but I don't see anything that explains how to make textbuttons in dialogue, or any other method to get hoverable words. Could someone please give me advice on how I might arrange this?

Thank you!

philat
Eileen-Class Veteran
Posts: 1909
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Dialogue Tooltips/Hoverable words?

#2 Post by philat »

AFAIK, not easy to do with hover, but pretty easy to do with click, if you'd be okay with that instead of hover. viewtopic.php?t=51929#p496245

Warhouse
Newbie
Posts: 7
Joined: Fri Mar 29, 2019 7:26 am
Contact:

Re: Dialogue Tooltips/Hoverable words?

#3 Post by Warhouse »

This is almost a perfect solution. The issue is, I want to be able to jump/call things if the player clicks on the word.

The reason it's almost perfect, is you can use {a} tags in the glossary window,

Code: Select all


default glossary_dict = {
"West-Iyrie":"The most widely held religion in the {a=call:Planets}world{/a}, originated in Thalizac, Promland. Believing in the unity of the binary gods Andinomie, and their angels, Ychsympal. Due to historical reasons, however, it's not as popular in Promland, except in Thalizac.",
"Blah-blah": "Lorem ipsum etc etc {a=call:Latin}(Learn More){/a}"
}

The problem being... call doesn't work properly. It jumps to the label, but when the game reaches a return, it doesn't return back to the line of dialogue where you clicked the link. So putting links in the dictionary window messes with the call stack, and causes it to skip a layer.

If we could somehow manually put the current line of dialogue into the call stack - when you open the glossary or click its links - it should work. Or there might be another solution I'm not thinking of.

Edit: The perfect place to put the line of code is likely here, in the glossary handler:

Code: Select all

init python:
    def glossary_handler(target):
       #Add current line of dialogue to call stack.
        x, y = renpy.get_mouse_pos()
        renpy.show_screen("glossary", target, x, y)
        renpy.restart_interaction()

    config.hyperlink_handlers["glossary"] = glossary_handler
But I'm not finding any information on how to do that, online. Any advice?

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Dialogue Tooltips/Hoverable words?

#4 Post by Remix »

A version that does not need inline {a} tags as it pre-parses all the dialogue strings and adds them where needed...

Not sure if it would handle {a=call:...} tags in the lexicon descriptions though. Maybe worth just trying.

Code: Select all

init python:

    lexicon = {
        # ( primary phrase, optional synonyms) : description
        ( _('Visual Novel'), _('VN') )  : _("""
            A visual novel (bijuaru noberu) is an interactive game genre, 
            which originated in Japan in the early 1990s, featuring mostly 
            static graphics, most often using anime-style art or occasionally 
            live-action stills.
            As the name might suggest, they resemble mixed-media novels."""),
        ( _('Ren\'Py'), _('Renpy') ) : _("""
            The Ren'Py Visual Novel Engine is a free software engine which 
            facilitates the creation of visual novels, a form of 
            computer-mediated storytelling. Ren'Py is a portmanteau of ren'ai, 
            the Japanese word for 'romantic love' and Python, 
            the programming language that Ren'Py runs on. """),
    }

    def hyperlink_lexicon( str_to_test ):

        for keys in lexicon:

            if isinstance(keys, basestring):
                keys = [keys]

            for phrase in keys:

                translated_phrase = renpy.substitutions.substitute( phrase )[0]

                # preceded by a space
                str_to_test = str_to_test.replace(
                    " {0}".format(translated_phrase),
                    " {{a=lexicon:{phrase}}}{translated_phrase}{{/a}}".format(
                        phrase = phrase,
                        translated_phrase = translated_phrase ) )

                # followed by a space
                str_to_test = str_to_test.replace(
                    "{0} ".format(translated_phrase),
                    "{{a=lexicon:{phrase}}}{translated_phrase}{{/a}} ".format(
                        phrase = phrase,
                        translated_phrase = translated_phrase ) )

        return str_to_test

    config.say_menu_text_filter = hyperlink_lexicon


    def hyperlink_styler(*args):

        return style.hyperlink_text

    def hyperlink_hovered(*args):
        
        if not args[0]:
            
            renpy.hide_screen("lexicon_popup")
        
        elif args[0][:8] == "lexicon:":

            renpy.show_screen( "lexicon_popup", 
                               args[0][8:], 
                               renpy.get_mouse_pos() )
            
        renpy.restart_interaction()
        
        return

    def hyperlink_clicked(*args):

        if args[0] and args[0][:8] != 'lexicon:':

            # adapted from common/00defaults.rpy
            if args[0].startswith("http:") or args[0].startswith("https:"):
                try:
                    import webbrowser
                    webbrowser.open(args[0])
                except:
                    renpy.notify("Failed to open browser")

            elif args[0].startswith("jump:"):
                renpy.jump( args[0][5:] )

            else:
                renpy.call_in_new_context(args[0][args[0].index(':')+1:])

    
    style.default.hyperlink_functions = ( hyperlink_styler, 
                                          hyperlink_clicked, 
                                          hyperlink_hovered )


screen lexicon_popup(phrase=None, pos=(100,100)):

    if phrase:

        python:

            # get description
            d = [ lexicon[k] for k in lexicon if phrase in k ]
            description = d[0] if len(d) \
                          else "No description found for phrase '{}'".format(phrase)

            description = renpy.substitutions.substitute( description )[0]

            description = " ".join( [ k for k in description.split()
                                      if k not in [" ", "\t"] ] )

            # move the ypos up by a bit
            pos = ( pos[0], pos[1] - 25 )

            # reformat phrase
            p = [ k for k in lexicon if phrase in k ]
            primary_phrase = p[0][0] if len(p) else phrase

            primary_phrase = renpy.substitutions.substitute( primary_phrase )[0]

            phrase = renpy.substitutions.substitute( phrase )[0]
            
            if primary_phrase != phrase:
                phrase = "{0} ({1})".format(phrase, primary_phrase)

        frame:
            anchor (0.5, 1.0)
            pos pos
            xsize 340
            background Solid("#A9B")
            vbox:
                text "[phrase]" size 18
                text "[description]" size 14


define e = Character("Eileen")

label start:

    e "Start"
    e "Oh look, this VN is made with Ren'Py"
    e "Test phrases that should not make link... AVNX aRenpyx"
    e "Test phrases that should not make link... miniVN{#no-lex} {#no-lex}Renpy-esque"
    e "Mix and match VN with {a=call:label_2}call{/a} {a=jump:label_2}jump{/a} {a=https:www.renpy.org}browser{/a}"
    e "End"

label label_2:
    e "Hiding in different label"
    return
Frameworks & Scriptlets:

User avatar
isobellesophia
Miko-Class Veteran
Posts: 979
Joined: Mon Jan 07, 2019 2:55 am
Completed: None
Projects: Maddox and Friends! (AI Teacher friend), Friendly Universities! (Soon)
Organization: Friendly Teachers series
Deviantart: SophBelle
itch: Child Creation
Location: Philippines, Mindanao
Contact:

Re: Dialogue Tooltips/Hoverable words?

#5 Post by isobellesophia »

For me, i just type like this.

Code: Select all

menu:
   "Text":
   hovered "Hi" xpos 300 ypos 300
   jump text
I am a friendly user, please respect and have a good day.


Image

Image


Warhouse
Newbie
Posts: 7
Joined: Fri Mar 29, 2019 7:26 am
Contact:

Re: Dialogue Tooltips/Hoverable words?

#6 Post by Warhouse »

Terrific work. I tried adding {a} tags to the lexicon, and it works, but has the same issue of philat's amazing glossary. When you call a label inside the lexicon, it messes up the call stack, and so it returns to the title screen instead of the dialogue line you called from.

A work around I can use, for either system, is to add a character next to the footnote word, and add a tags to it. Like this:

Code: Select all

e "Oh look, this VN{a=call:label_2}0{/a} is made with Ren'Py{a=call:label_2}0{/a}"
I could get a special character for the purpose of being an obvious, followable link.

I can wrap the lexicon words in {a} tags, which lead me to hope they could double as links. But for some reason they don't work as {a} links when clicked. I'm going to comb through the code a little more, to see if it's possible to have them work in both roles.

isobellesophia wrote: Fri Mar 29, 2019 11:42 pm For me, i just type like this.

Code: Select all

menu:
   "Text":
   hovered "Hi" xpos 300 ypos 300
   jump text
This code doesn't appear to be working for me. I think there's a typo in it, but I can't work out what.

Warhouse
Newbie
Posts: 7
Joined: Fri Mar 29, 2019 7:26 am
Contact:

Re: Dialogue Tooltips/Hoverable words?

#7 Post by Warhouse »

OK, something cool I worked out. By simply commenting out part of this function, I've made it so that if I click on the lexicon words they will take me to a label of the same name:

Code: Select all

def hyperlink_clicked(*args):

        #if args[0] and args[0][:8] != 'lexicon:':
            # adapted from common/00defaults.rpy
            if args[0].startswith("http:") or args[0].startswith("https:"):
                try:
                    import webbrowser
                    webbrowser.open(args[0])
                except:
                    renpy.notify("Failed to open browser")
            elif args[0].startswith("jump:"):
                renpy.jump( args[0][5:] )

            else:
                renpy.call_in_new_context(args[0][args[0].index(':')+1:])
Issue being, I can't decide what it jumps to with {a} tags. Still, this is pretty close to perfect. It only requires me to have labels that match the lexicon words, which is easy.

Now, I haven't studied the code very carefully, so I still need to make sure there isn't long-term instability in this method. It seem good? If so, it's pretty well perfect.

Post Reply

Who is online

Users browsing this forum: No registered users