How to focus imagebutton to avoid random blinking of others?

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
iichan_lolbot
Veteran
Posts: 206
Joined: Tue Dec 30, 2008 9:18 am
Projects: iichan erogame
Contact:

How to focus imagebutton to avoid random blinking of others?

#1 Post by iichan_lolbot »

One of my games have this interesting bug:



Small demo to reproduce it: http://rghost.ru/6Z5TgS6Pm , see "game\inventory\inventory.rpy" file:

Code: Select all

label inv_loop:
    scene onlayer superoverlay
    python:
        ui.imagebutton(Solid("#000c"),Solid("#000c"),clicked=ui.returns("gohome"))

        for i in range(inventory_i_max):
            for j in range(inventory_j_max):
                if  (persistent.inventory[i][j] == None and what != None) or (persistent.inventory[i][j] != None and what == None) :
                    ui.imagebutton(inv_inventory_tile, im.MatrixColor(inv_inventory_tile,im.matrix.invert()), clicked=ui.returns((i,j)), pos=inv_inventory_pos(i,j))
                else:
                    ui.imagebutton(inv_inventory_tile, inv_inventory_tile, clicked=None, pos=inv_inventory_pos(i,j))
                if  persistent.inventory[i][j]:
                    ui.at(Position(pos=inv_inventory_pos(i,j)))
                    ui.image(item_img(persistent.inventory[i][j]))
    if  what:
        show expression custom_cursor(item_img(what), 32, 32) onlayer superoverlay

    $ result = ui.interact()
    if  result == "gohome":
        if  what == None:
            return
    elif  isinstance(result, tuple):
        $ ii,jj = result
        if  what == None:
            $ what = persistent.inventory[ii][jj]
            $ persistent.inventory[ii][jj] = None
        elif persistent.inventory[ii][jj] == None:
            $ persistent.inventory[ii][jj] = what
            $ what = None
    jump inv_loop
Is there a way to focus a button below mouse before ui.interact()?

iichan_lolbot
Veteran
Posts: 206
Joined: Tue Dec 30, 2008 9:18 am
Projects: iichan erogame
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#2 Post by iichan_lolbot »

Help!

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#3 Post by xela »

Trying to fix this feels a bit like a waste of time, especially investigating what exactly is causing these jumps of "focus". Why are you not using drag and drop?
Like what we're doing? Support us at:
Image

iichan_lolbot
Veteran
Posts: 206
Joined: Tue Dec 30, 2008 9:18 am
Projects: iichan erogame
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#4 Post by iichan_lolbot »

especially investigating what exactly is causing these jumps of "focus"
I'm sorry, but for me it is obvious what is causing theme jumps of "focus" - the reason is that between interactions renpy stores index of focusable object in focusable objects list, not some kind of pointer to this object or it's coordinates.

Practically, this means that if number of focusable objects above and left from the mouse remains the same, no blinking occures. But if something dissapears, then a button to the right or below blinks. If number of focusable objects increases between interactions, then an object to the left or above blinks.

Here is a very quick code to demonstrate this issue: http://rghost.ru/6wbgddwms

Code: Select all

label start:
    python:
        ui.vbox()

        ui.button(xminimum=64, yminimum=64, background=Solid("#000"),hover_background=Solid("#800"),clicked=ui.returns("True") if renpy.random.choice([True,False]) else None)
        ui.label("One more button",text_xalign=0.5)

        ui.grid(5,5)
        for i in range(25):
            ui.button(xminimum=64, yminimum=64, background=Solid("#000"),hover_background=Solid("#800"),clicked=ui.returns("True"))
            ui.label(`i`,text_xalign=0.5)
        ui.close()
        ui.close()
        ui.interact()
    jump start
If you try clicking anywhere in the grid, you will see exactly the same blinking, because "One more button" is randomly focusable or non-focusable and the index of butten focused before interaction points to an object to the left or to the right from a cell that you click on.

If you remove "One more button" or put it below the grid, no blinking occur, because number of focusable objects remains always the same.

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#5 Post by xela »

It's quite possible that you're right about the cause...

You obviously know your way about Python and presumably Ren'Py. Using screen language solves the issue:

Code: Select all

init python:
    inv_left_offset = (1920-inventory_i_max*tile_size)/2
    def inv_inventory_pos(i,j):
        return (inv_left_offset+i*tile_size,tile_size+j*tile_size)

    def inv_hint(what):
        if  what:
            return hint_runename(what)
        return ""

    inv_inventory_tile = "inventory/inventory_invtile.png"

image inv_bg = "#000c"

screen inventory():
    imagebutton:
        idle Solid("#000c")
        hover Solid("#000c")
        action Return("gohome")
        
    for i in range(inventory_i_max):
        for j in range(inventory_j_max):
            if (persistent.inventory[i][j] == None and what != None) or (persistent.inventory[i][j] != None and what == None):
                imagebutton:
                    pos inv_inventory_pos(i,j)
                    idle inv_inventory_tile
                    hover im.MatrixColor(inv_inventory_tile,im.matrix.invert())
                    action Return((i,j))
            else:
                imagebutton:
                    pos inv_inventory_pos(i,j)
                    idle inv_inventory_tile
                    hover inv_inventory_tile
                    action NullAction()
            if persistent.inventory[i][j]:
                add item_img(persistent.inventory[i][j]) pos inv_inventory_pos(i,j)

label inventory:
    $ what = None
label inv_loop:
    scene onlayer superoverlay
    
    show screen inventory
    # python:
        # ui.imagebutton(Solid("#000c"),Solid("#000c"),clicked=ui.returns("gohome"))

        # for i in range(inventory_i_max):
            # for j in range(inventory_j_max):
                # if  (persistent.inventory[i][j] == None and what != None) or (persistent.inventory[i][j] != None and what == None) :
                    # ui.imagebutton(inv_inventory_tile, im.MatrixColor(inv_inventory_tile,im.matrix.invert()), clicked=ui.returns((i,j)), pos=inv_inventory_pos(i,j))
                # else:
                    # ui.imagebutton(inv_inventory_tile, inv_inventory_tile, clicked=None, pos=inv_inventory_pos(i,j))
                # if  persistent.inventory[i][j]:
                    # ui.at(Position(pos=inv_inventory_pos(i,j)))
                    # ui.image(item_img(persistent.inventory[i][j]))
    if what:
        show expression custom_cursor(item_img(what), 32, 32) onlayer superoverlay

    $ result = ui.interact()
    if  result == "gohome":
        if  what == None:
            return
    elif  isinstance(result, tuple):
        $ ii,jj = result
        if  what == None:
            $ what = persistent.inventory[ii][jj]
            $ persistent.inventory[ii][jj] = None
        elif persistent.inventory[ii][jj] == None:
            $ persistent.inventory[ii][jj] = what
            $ what = None
    jump inv_loop
so would using Drag&Drop as I suggested earlier. If you are looking for advice on how to solve it using ui module (which is no longer officially supported as far as I know), you'll prolly have to find the answer yourself...
Like what we're doing? Support us at:
Image

iichan_lolbot
Veteran
Posts: 206
Joined: Tue Dec 30, 2008 9:18 am
Projects: iichan erogame
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#6 Post by iichan_lolbot »

Thank you.

I always believed that screen language (at least screen language ver.1) was just syntax sugar built on top of ui-functuins.
Looks like I was wrong somewhere... I still don't really understand why SL works in other way.

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#7 Post by xela »

I've never used ui module so I wouldn't know. I do know however that not updating code and using older Ren'Py stuff does a lot more harm than good :)
Like what we're doing? Support us at:
Image

User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#8 Post by nyaatrap »

iichan_lolbot wrote:Thank you.

I always believed that screen language (at least screen language ver.1) was just syntax sugar built on top of ui-functuins.
Looks like I was wrong somewhere... I still don't really understand why SL works in other way.
I think old ui restarts all ui widgets between interactions (and its performance was horrible), while SL2 can control which should be reused or restarted.

User avatar
PyTom
Ren'Py Creator
Posts: 16096
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#9 Post by PyTom »

Both SL1 and SL2 use syntactic structure to assign unique names to objects, which helps maintain focus.

You can use the focus_name parameter to give names to displayables created through the ui functions.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

iichan_lolbot
Veteran
Posts: 206
Joined: Tue Dec 30, 2008 9:18 am
Projects: iichan erogame
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#10 Post by iichan_lolbot »

PyTom wrote:You can use the focus_name parameter to give names to displayables created through the ui functions.
This does not help, this code still blinks:

Code: Select all

label start:
    python:
        ui.vbox()

        ui.button(focus_name="bX", xminimum=64, yminimum=64, background=Solid("#000"),hover_background=Solid("#800"),clicked=ui.returns("True") if renpy.random.choice([True,False]) else None)
        ui.label("One more button",focus_name="lX",text_xalign=0.5)

        ui.grid(5,5)
        for i in range(25):
            ui.button(focus_name="b"+`i`, xminimum=64, yminimum=64, background=Solid("#000"),hover_background=Solid("#800"),clicked=ui.returns("True"))
            ui.label(`i`,focus_name="l"+`i`,text_xalign=0.5)
        ui.close()
        ui.close()
        ui.interact()
    jump start
Maybe the reason is that widgets are recreated each interaction?

iichan_lolbot
Veteran
Posts: 206
Joined: Tue Dec 30, 2008 9:18 am
Projects: iichan erogame
Contact:

Re: How to focus imagebutton to avoid random blinking of oth

#11 Post by iichan_lolbot »

Huh!!!

I have found solution.

What really works, is using clicked=NullAction instead of clicked=None!

Post Reply

Who is online

Users browsing this forum: No registered users