[solved] Creating dynamic user-generated buttons from an array

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
Tastymango
Newbie
Posts: 6
Joined: Thu May 10, 2018 8:35 am
Contact:

[solved] Creating dynamic user-generated buttons from an array

#1 Post by Tastymango »

Hey all,
I've been lurking on the forums for a while and managed to find a lot of great examples that have helped me past previous problems...right up till now.

I so far have a nice working bit of code that creates a fictitious chemical, complete with randomly generated sciency name and a array of traits (thanks entirely to examples gleaned from forum posts). The user then chooses whether or not to save them to a list.
from this list (the code is kinda massive, so for simplicity sake its: List[Chemical1(name,trait_array,trait_array,trait_array),Chemical2(name,trait_array,trait_array,trait_array) Etc...].

I want to have the user select from their generated list 2 of the chemicals to combine. I was thinking of dynamically generated textbuttons with the chemicals names would be the best approach to this. Is there any way to generate textbuttons based on the number of chemicals in the user's list ( a for loop perhaps)?

Thanks!

-TM
Last edited by Tastymango on Tue May 15, 2018 8:14 am, edited 1 time in total.

User avatar
xavimat
Eileen-Class Veteran
Posts: 1461
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Discord: xavimat
Contact:

Re: Creating dynamic user-generated buttons from an array

#2 Post by xavimat »

I'm not sure if I understand you...
Yes, you can use a for loop inside a screen:

Code: Select all

default my_list = ["One", "Two", "Three", "Four", "Six"]
screen test():
    vbox:
        for i in my_list:
            textbutton i action Return(i)
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

kivik
Miko-Class Veteran
Posts: 786
Joined: Fri Jun 24, 2016 5:58 pm
Contact:

Re: Creating dynamic user-generated buttons from an array

#3 Post by kivik »

Yep, as xavimat said, you can do for loops inside screens (unlike labels). However depending on how you want to implement your UI, you may want the textbutton's action to set two screen variables, and a final combine the two chemicals together, or if you want to create a list of things to combine, a global list.

To declare a screen variable:

Code: Select all

screen combine_chemicals(list1, list2):
    default chemical1 = ""
    default chemical2 = ""
Then use data actions to set the variables, SetScreenVariable for screen variables or AddToSet() and RemoveFromSet() if you're using a list. You can also help player see what's selected using SelectedIf() in part of the action: https://www.renpy.org/doc/html/screen_a ... SelectedIf

Then your combine button can just execute a Function() or Return() the chemicals for processing.

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: Creating dynamic user-generated buttons from an array

#4 Post by Remix »

Code: Select all

chemi_duos = [ (chem_list[i], chem_list[j]) for i in range(len(chem_list)) for j in range(i+1, len(chem_list)) ]
for chem1, chem2 in chemi_duos: # textbutton
Frameworks & Scriptlets:

Tastymango
Newbie
Posts: 6
Joined: Thu May 10, 2018 8:35 am
Contact:

Re: Creating dynamic user-generated buttons from an array

#5 Post by Tastymango »

Thanks everyone!
Previous failures experimenting with for loops to make dynamic menu options had me thinking that it would be the same with text buttons. Really glad to be wrong :D.

Tastymango
Newbie
Posts: 6
Joined: Thu May 10, 2018 8:35 am
Contact:

Re: [solved] Creating dynamic user-generated buttons from an array

#6 Post by Tastymango »

@xavimat
I'm getting the weirdest error when using your code with image buttons:

Here's my code derived from what you posted

Code: Select all

screen Chem_Database():
    $ imb = 1

    frame:
        yalign 10
        text "Chemical Database" xpos 26 size 20
        xsize 250
        ysize 720

        for i in (chem_n_list):
            $ imb += 1

            imagebutton:
                idle "Chem_empty"
                hover "Chem_idle"
                action Return(i)
                ypos (1 + (imb*32))
                xpos 10

            text "[i]" ypos (4 + (len(i)/2) + (imb*32)) xpos 52 size 26-(len(i)/1.285) #This will autoscale text to try and fit it on the bar I've set the cap at 20 characters elsewise things get stupid rather fast

The weird thing is the variable 'i' is returning the string 'zoomout' (a string that is used nowhere in my script or screen files).
Any clues how I can fix/bypass this?

Thanks

User avatar
xavimat
Eileen-Class Veteran
Posts: 1461
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Discord: xavimat
Contact:

Re: [solved] Creating dynamic user-generated buttons from an array

#7 Post by xavimat »

Mmmm. Don't use the parenthesis in the for loop.

Code: Select all

for i in my_list:
Also, you can use enumerate() to have an automatic number, instead of counting yourself.

Code: Select all

for imb, i in enumerate(my_list):
(Remember that imb will start at 0, not at 1).

I've got the "zoomout" error sometimes, when I forget that I'm using "i2" instead of "i" in the for loop line and use "i" inside the loop.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

Tastymango
Newbie
Posts: 6
Joined: Thu May 10, 2018 8:35 am
Contact:

Re: [solved] Creating dynamic user-generated buttons from an array

#8 Post by Tastymango »

I've got the "zoomout" error sometimes, when I forget that I'm using "i2" instead of "i" in the for loop line and use "i" inside the loop.
OK, but I'm only using "i" and getting that error.
Could you please expand on what's causing in and specifically approaches I can use to avoid it?
Last edited by Tastymango on Thu May 17, 2018 11:29 am, edited 1 time in total.

User avatar
xavimat
Eileen-Class Veteran
Posts: 1461
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Discord: xavimat
Contact:

Re: [solved] Creating dynamic user-generated buttons from an array

#9 Post by xavimat »

That's odd. The part of code you have shown seems correct.
There is an internal "for i loop" in renpy that checks for transitions, and zoomout is the last one checked. So, when i is not defined by the creator, is "zoomout".

Please, show the code before your screen, and the label where you are using that screen.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

Tastymango
Newbie
Posts: 6
Joined: Thu May 10, 2018 8:35 am
Contact:

Re: [solved] Creating dynamic user-generated buttons from an array

#10 Post by Tastymango »

The abriged version of what I'm running is as follows:

A complicated little engine produces a a unique random gen name, a couple tags are assigned and one ends up with chem_list=['Name',data,data,data,data]

some lines of coding later this code assigns a user name saves the data for the Screen operations to make a list from:

Code: Select all

label cabinet:
    python:
        chem_list.append(new_chem)
        nametag = new_chem[0] 
        bag =+ 1


label cabinet_1:

    $ nickname = renpy.input("You have added [nametag] to your database!\nWhat would you like to call it? (MAX 22 characters)")
    if len(nickname) > 22:                # if the user is illererate or just a dick
        "Name is too long! Try again."
        jump cabinet_1

    $ new_chem[0] = nickname
    $ chem_n_list.append(nickname) # seperate list of just names for quick reference

    jump chemlab
on the screen side of things this takes the code and makes a handy list:

Code: Select all

screen Chem_Database():
    $ imb = 1

    frame:
        yalign 10
        text "Chemical Database" xpos 26 size 20

        for i in chem_n_list:
            $ imb += 1
            imagebutton:
                idle "Chem_empty"
                hover "Chem_idle"
                action Return(i)
                ypos (1 + (imb*32))
                xpos 10
            $ Ctrl += 1

            text "[i]" ypos (4 + (len(i)/2) + (imb*32)) xpos 52 size 26-(len(i)/1.285) #This will autoscale text to try and fit it on the bar Ive set the cap at 20 characters elsewise things get stupid rather fast
                                                                           #Admittedly 14 and 16 character length names seem to not shrink as well as the others, but that can be fixed by lenghtining the button image a tad

        xsize 250
        ysize 720
back on the script side this label prompts the user to check out the screen list and select one of the buttons to examine its traits:

Code: Select all

label data_sheet:
    hide screen Chem_gen_scr
    hide screen A_new_chem #Sanity check.  It should never be active at this point, making damn sure it isn't
    call screen Chem_Database
#label data_1: #prompt user to click on one of the buttons to the left
#    "select chemical in database to review"
#    jump data_1

label data_2: # a button has been clicked

    if i in studied_chems:
        pass
    else:
        show screen undescovered

    "Anaylisis of [i] shows the following:"

    return
since pretty much everything generated is new it all defaults to this screen:

Code: Select all

screen undescovered():

        #$ c_name = chem_n_list[Ctrl]
        image "New_chem" xpos 550 ypos 200
        text  "{b}[i]{/b}" xpos 697 ypos 210 size 30 - (len(scn_name)/2)
        text "Chemical tags present: [m_tags]" xpos 715 ypos 240 size 12
        text "This chemical deactivates [kill_tagged] tags" xpos 715 ypos 260 size 15
        text "{b}Chemical has not been fully studied{/b}" xpos 715 ypos 280 size 15

        textbutton __("Anaylize"):
            xpos 700
            ypos 300
            text_size 18
            action Jump ('cabinet')

        textbutton __("Rename"):
            xpos 800
            ypos 300
            text_size 18
            action Jump ('chemlab')

        textbutton __("Discard"):
            xpos 890
            ypos 300
            text_size 18
            action Jump ('chemlab')
which has been giving me "zoomout" as its title instead of the actual selected name.
Attachments
zoomout.png

User avatar
xavimat
Eileen-Class Veteran
Posts: 1461
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Discord: xavimat
Contact:

Re: [solved] Creating dynamic user-generated buttons from an array

#11 Post by xavimat »

Ah Ok, you are not getting the returned value from the screen.
The variable "i" inside the screen is a local variable, it doesn't exist outside it.
When your screen has the action Return(i), it does not return the variable "i", but the contents of the variable "i" using the variable "_return" (https://renpy.org/doc/html/screen_actions.html#Return )
After the "call screen" you are not retrieving that value, so it's lost.
Simply add this line after the call screen:

Code: Select all

 $ i = _return
But, maybe it's better if you use another variable instead of "i" here, to avoid confusion.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

Tastymango
Newbie
Posts: 6
Joined: Thu May 10, 2018 8:35 am
Contact:

Re: [solved] Creating dynamic user-generated buttons from an array

#12 Post by Tastymango »

That did the trick!

Thank you so much xavimat. I'd be utterly stuck without your help.

Post Reply

Who is online

Users browsing this forum: Andredron