[SOLVED]ToggleDict in a loop

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
GoldenD
Regular
Posts: 43
Joined: Thu Jan 16, 2020 2:01 am
Contact:

[SOLVED]ToggleDict in a loop

#1 Post by GoldenD »

Code first, explain following

Code: Select all

default _var        = None
default _counter    = 0
default list_select = dict()

label start:
    python:
        for _var in listOfSpells:
            store.list_select[_var.id] = False
    call screen setupHero(listOfSpells, maxItems=5)

screen setupHero(listOf, maxItems=1):
    modal True
    zorder 200
    add "gui/overlay/confirm.png"
    add "gui/setup.png" pos (800, 100)  size (950,600)

    use displayItems(listOf)

    textbutton _("Ok")      action [Return(True), With( dissolve)]      xpos 950 ypos 610
    textbutton _("Cancel")  action [Rollback(),With( dissolve)]         xpos 1500 ypos 610

    ## Right-click and escape answer "no".
    key "game_menu" action [Rollback(),With( dissolve)]

screen displayItems(listOf):
    $ _var  = 0
    $ _xpos = 860
    $ _ypos = 220
    for _var in range(len(listOf)):
        textbutton listOf[_var].name xpos _xpos ypos _ypos:
            action [ToggleDict( list_select, _var, True, False ), updateCounter()]
            style "checkbox_button"
            hovered ShowTransient("ttSelectItems", msg=listOf[_var].description)
            unhovered Hide("ttSelectItems")
        $ _ypos += 35

    # For debug
    text "{color=#ffffff}_counter = [_counter] {/color}"
    
python:
    def updateCounter():
        store._counter = 0
        for _var in store.list_select:
            if store.list_select[_var] == True:
                store._counter += 1
Goal is to have list of textbutton which represents list of spells (for sample). you can choose 5 out of 10 by clicking the textbutton.
Clicking textbutton should changed font of button and particularly increase _counter
What happened here :
at beginning, all datas in list_select are false, normal. But when you click one button, all datas are assigned to True when only the one that is clicked takes the good style "checkbox_button".

So, action seems to be executed for each elt in the loop, while rest of textbutton is correctly assign at the only one I click.
Why, why, why ? An idea ?
Last edited by GoldenD on Wed Mar 04, 2020 5:12 am, edited 1 time in total.

User avatar
Alex
Lemma-Class Veteran
Posts: 3094
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: ToggleDict in a loop

#2 Post by Alex »

If you have a list of 'spells' and those spells are objects, why won't you try to add another property to spell object (like 'selected') and toggle its value upon clicking?

GoldenD
Regular
Posts: 43
Joined: Thu Jan 16, 2020 2:01 am
Contact:

Re: ToggleDict in a loop

#3 Post by GoldenD »

Alex wrote: Mon Mar 02, 2020 2:02 pm If you have a list of 'spells' and those spells are objects, why won't you try to add another property to spell object (like 'selected') and toggle its value upon clicking?
Thanks for your reply.
I could do that but what's the change ?
I don't understand the operating logic of action Toggle... if it's no when you click on one and only one button. And why the style only and logically applies on the clicked button, but action change value of all my list ?
I'm sure there's something wrong in my work but I don't see what !

User avatar
Alex
Lemma-Class Veteran
Posts: 3094
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: ToggleDict in a loop

#4 Post by Alex »

The logic of action is quite simple, but you have many variables named '_var', that might confuse the program. Also, you need to track if two lists have the same length...
And screens are refreshed from time to time - that makes code run again and again.
So, this might be easyer to operate single list.

(not tested code)

Code: Select all

screen displayItems(listOf):
    vbox:
        align (0.5, 0.2)
        for bttn in listOf:
            textbutton bttn.name:
                action ToggleField(bttn, 'field_name', True, False)
                style "checkbox_button"
                hovered ShowTransient("ttSelectItems", msg=bttn.description)
                unhovered Hide("ttSelectItems")

GoldenD
Regular
Posts: 43
Joined: Thu Jan 16, 2020 2:01 am
Contact:

Re: ToggleDict in a loop

#5 Post by GoldenD »

Alex wrote: Mon Mar 02, 2020 4:42 pm The logic of action is quite simple, but you have many variables named '_var', that might confuse the program. Also, you need to track if two lists have the same length...
And screens are refreshed from time to time - that makes code run again and again.
So, this might be easyer to operate single list.

(not tested code)

Code: Select all

screen displayItems(listOf):
    vbox:
        align (0.5, 0.2)
        for bttn in listOf:
            textbutton bttn.name:
                action ToggleField(bttn, 'field_name', True, False)
                style "checkbox_button"
                hovered ShowTransient("ttSelectItems", msg=bttn.description)
                unhovered Hide("ttSelectItems")
Ok, i can listen about confusing variables, and i'll clear my code to test the program flow correctly and without confusion.
I do it and I come back to say what.

GoldenD
Regular
Posts: 43
Joined: Thu Jan 16, 2020 2:01 am
Contact:

Re: ToggleDict in a loop

#6 Post by GoldenD »

Ok guys,
cleaning code and reading your notice, all is fine for this part. Bottom, the code "cleaning" and working.

Code: Select all

# default _var            = None

init python:
    class Item:
        def __init__(self, id, name=""):
            self.id             = id
            self.name           = name

    def updateCounter():
        store.counterSelected = 0
        for eltSelect in store.listSelected:
            if store.listSelected[eltSelect] == True:
                store.counterSelected += 1

define listItems       = [(Item(0, name="Item01")), (Item(1, name="Item02")), (Item(2, name="Item03")), (Item(3, name="Item04")), (Item(4, name="Item05"))]
default listSelected    = dict()
default counterSelected = 0
define MAX_SELECT       = 3

label test():
    python:
        for _var in listItems:
            store.listSelected[_var.id] = False

    call screen selectItems(listItems)

screen selectItems(listOf):
    modal True
    zorder 200
    add "gui/overlay/confirm.png"
    add "gui/setup.png" pos (800, 100)  size (950,600)

    use displayItems(listOf)

    textbutton ("Ok")      action [Return(True), With( dissolve)]   xpos 950 ypos 610
    textbutton ("Cancel")  action [Rollback(), With( dissolve)]    xpos 1500 ypos 610

    key "game_menu" action [Rollback(),With( dissolve)]

screen displayItems(listOf):
    $ _xpos = 860
    $ _ypos = 220
    for eltItems in range(len(listOf)):
        textbutton listOf[eltItems].name xpos _xpos ypos _ypos:
            action [ToggleDict( listSelected, eltItems, True, False ), Function(updateCounter)]
            style "displayItems_button"

        $ _ypos += 35

    # For debug
    text "{color=#ffffff}counterSelected = [counterSelected] {/color}"

style displayItems_button is button
style displayItems_button_text is button_text:
    idle_color              "#000000"       # BLACK NORMAL
    hover_color             "#ffffff"       # WHITE HOVER
    selected_idle_color     "#550001"       # RED   SELECTED
    selected_hover_color    "#550001"       # RED   SELECTED
Note for newbies like me:

if you try this code without change, the Cancel button will be insensitive because not possible Rollback. If you add "Hello" before calling screen, Cancel will be active. (no doubt obvious to the majority, I just spent time reviewing all my styles to understand).

And like always, a Great THANKS everybody.

Post Reply

Who is online

Users browsing this forum: Bing [Bot]