[SOLVED] Python Dictionary not being processed properly?

In this forum we discuss the future of Ren'Py, both bug fixes and longer-term development. Pre-releases are announced and discussed here.
Post Reply
Message
Author
User avatar
Kaji
Regular
Posts: 87
Joined: Thu Nov 17, 2022 10:17 pm
Github: Kaji01
Discord: Kaji#7767
Contact:

[SOLVED] Python Dictionary not being processed properly?

#1 Post by Kaji »

Minimal project attached demonstrating the issue.

In this demo I've added a Glossary screen, which shows a list of entries on the left and then swaps out screens with entry data on the right depending on which item is selected from the list. Entry data is contained in glossary_registry.rpy; each dictionary entry includes a "screen" attribute that contains the name of the screen to call with the entry's data.

Generally, it's been working fine, however it never finds the first entry's screen when loading, even though I've verified that the screen is defined and present. If I swap the order of entries in the dictionary it will show the screen for the old first entry no problem, but now the screen for the entry moved into first place will revert to the default "I don't have a screen defined for me" screen.

Oddly, however, if you refresh the Glossary screen after loading any entry the first entry will pull up its screen as it's supposed to. If you dismiss the glossary and go back to the main screen it will revert back to its initial behavior of thinking the first screen doesn't exist, however.

If this is a code error on my part then I apologize for putting this in the wrong place, however since the code appears to be running properly on the screen refresh I'm thinking it might be something about how the Python block defining the dictionary is being processed, perhaps?
Attachments
Glossary Issue Demo.zip
(2.49 MiB) Downloaded 27 times
Last edited by Kaji on Thu Jan 12, 2023 2:27 am, edited 1 time in total.

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

Re: [BUG] Python Dictionary not being processed properly?

#2 Post by Alex »

Why do you have

Code: Select all

$ hide_current()
in all your glossary screens?

If you need to hide previous screen then try to give the same tag for all your glossary screens (like all menu screens have 'menu' tag).

User avatar
Kaji
Regular
Posts: 87
Joined: Thu Nov 17, 2022 10:17 pm
Github: Kaji01
Discord: Kaji#7767
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#3 Post by Kaji »

Alex wrote: Tue Jan 10, 2023 1:55 pm Why do you have

Code: Select all

$ hide_current()
in all your glossary screens?

If you need to hide previous screen then try to give the same tag for all your glossary screens (like all menu screens have 'menu' tag).
It's there because I needed to ensure the previous screen dismissed when selecting a new entry from the list, otherwise I was ending up with a hanging screen when I returned at the end. I'll take a closer look at the tag stuff though and see if I can get that to work—I've been feeling things out as I go on this project.

User avatar
Kaji
Regular
Posts: 87
Joined: Thu Nov 17, 2022 10:17 pm
Github: Kaji01
Discord: Kaji#7767
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#4 Post by Kaji »

Regarding the tags, I tested replacing the hide_current() calls with tag glossary and it went back to the behavior I was seeing previously, where when you dismissed the glossary screen as a whole by hitting return it left the last screen up as an undismissable (in the app) overlay. Changing the main glossary display's tag from menu to glossary caused it to be dismissed when selecting an entry for display as well, further complicating the issue. Screenshot attached.

For the main issue discussed in the OP, I've temporarily worked around it by adding a null entry that always gets sorted to the top of the list as a throwaway/offering to the code gods and things are generally working as they should from there.
Attachments
Screenshot 2023-01-11 at 2.08.03 AM.png

User avatar
Ocelot
Lemma-Class Veteran
Posts: 2405
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#5 Post by Ocelot »

Code: Select all

if (word['screen'] == ''):
    $ word['screen'] = 'glossary_sample_entry' 
Get rid of this. Never have any code with side effects in screens. RenPy can and will sometimes execute branches without condition being true during prediction to cache data in case those conditions will become true. Screens are views, they should not control data. If you want to safeguard yourself against those problems, do something like:

Code: Select all

$ word_screen = word.get('screen', 'glossary_sample_entry') # Protecting from case when 'screen' is not in dict at all
if not word_screen: # ideally add check for screen existence too
    $ word_screen = 'glossary_sample_entry'
textbutton word["localized"] action Show(word_screen)
< < insert Rick Cook quote here > >

User avatar
Kaji
Regular
Posts: 87
Joined: Thu Nov 17, 2022 10:17 pm
Github: Kaji01
Discord: Kaji#7767
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#6 Post by Kaji »

Ocelot wrote: Wed Jan 11, 2023 12:21 pm

Code: Select all

if (word['screen'] == ''):
    $ word['screen'] = 'glossary_sample_entry' 
Get rid of this. Never have any code with side effects in screens. RenPy can and will sometimes execute branches without condition being true during prediction to cache data in case those conditions will become true. Screens are views, they should not control data. If you want to safeguard yourself against those problems, do something like:

Code: Select all

$ word_screen = word.get('screen', 'glossary_sample_entry') # Protecting from case when 'screen' is not in dict at all
if not word_screen: # ideally add check for screen existence too
    $ word_screen = 'glossary_sample_entry'
textbutton word["localized"] action Show(word_screen)
That's good to know! I'm still fairly new to Python, but it looks like word.get('screen') is effectively a word["screen"] call, with the added capability of suggesting a fallback value if it's not in the dictionary, correct? So it's *similar* in function to what I had, but puts it all into one call and then...but wait, then what do we need that IF clause following it for?

In either case, about to try this out now. Thanks again, Ocelot!

User avatar
Ocelot
Lemma-Class Veteran
Posts: 2405
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#7 Post by Ocelot »

Your original code would crash if key 'screen' was not present in dictionary. Now it falls back to a default parameter. Your code also checked if value of 'screen' was an empty string, so I kept this check.
< < insert Rick Cook quote here > >

User avatar
Kaji
Regular
Posts: 87
Joined: Thu Nov 17, 2022 10:17 pm
Github: Kaji01
Discord: Kaji#7767
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#8 Post by Kaji »

OK, tried it out and it does fix the issue of the first item not appearing, however if I try hiding the "screen" key within the dictionary (which just contains the text for the name of the screen) it's just crashing when it gets to the first line of that block for the modified entry. Adding it back in works, but if it's blank (e.g. just a placeholder until things get set up) then it's not detecting the empty string and we crash for that reason.

Tried switching it for a string length check and it's still crashing, as if it's just skipping over the check no matter what...

Code: Select all

$ word_screen = word.get('screen', 'glossary_sample_entry')
if (len(word_screen) == 0):
    $ word_screen= 'glossary_sample_entry'

textbutton word["localized"]:
    action Show(word_screen)
Silly question, but is there a way to check if a screen with a given name exists without actually calling it?

User avatar
Ocelot
Lemma-Class Veteran
Posts: 2405
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#9 Post by Ocelot »

I am not sure what the problem is. Do you have a problem demo?

You can check for screen exictense with renpy.has_screen("screen_name")
< < insert Rick Cook quote here > >

User avatar
Kaji
Regular
Posts: 87
Joined: Thu Nov 17, 2022 10:17 pm
Github: Kaji01
Discord: Kaji#7767
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#10 Post by Kaji »

OK, so in double-checking as I was updating the demo project, it turns out that the issue with the blank name is the hide function—it ends up looking for a screen that doesn't exist. So in a sense the tag glossary method should address that, I imagine, but as mentioned above hasn't proven feasible so far because while that switches out the subviews, it results in a situation where the tag causes the main view containing the subviews to go away (because it's also tagged) or we get left with a hanging subview on dismissing the main screen.

That said, the updated demo is attached if you're curious. You can test cases by commenting out line 16 in glossary_registry.rpy or setting its value to a blank string. In my main project file I've worked around this using the has_screen() method now that I know it's available as follows:

Code: Select all

for word in sorted_glossary:
    $ word_screen = word.get('screen', 'sample_entry')
    if not renpy.has_screen('glossary_' + word_screen):
        $ word_screen = 'sample_entry'

    if (flag_raised(word['screen'])):
        textbutton word["localized"]:
        action Show('glossary_' + word_screen) # Can't Hide() here because we don't know what to hide yet...though...
To prevent an "index out of bounds" error the hide function was also updated as follows:

Code: Select all

init python:
    def hide_current():
        for word in glossary_dict:
            if (renpy.has_screen('glossary_' + word['screen'])):
                renpy.hide_screen('glossary_' + word['screen'])
        renpy.hide_screen('glossary_' + 'sample_entry')
Attachments
Glossary Issue Demo 2.zip
(2.59 MiB) Downloaded 25 times

User avatar
Ocelot
Lemma-Class Veteran
Posts: 2405
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#11 Post by Ocelot »

There are two solutions:
1) Use tags and add code to hide screens when main glossary screen is hidden:

Code: Select all

screen glossary_kantou():
    tag glossary_entry
    # . . . 

screen glossary():
    tag menu

    on "hide" action Hide("glossary_entry")
    on "replaced" action Hide("glossary_entry")
    # . . .
2) Do not show screens. use them. Instead of having action to show screen, have an action to set screen variable to the name of screen to display, and then conditionally use it inside glossary screen. That way it becomes part of glossary screen and will be hidden together with it.

If your screens won't be much different from what you have now, just have one screen and pass text to display as argument (this might not work if real screens will be vastly different from each other.
< < insert Rick Cook quote here > >

User avatar
Kaji
Regular
Posts: 87
Joined: Thu Nov 17, 2022 10:17 pm
Github: Kaji01
Discord: Kaji#7767
Contact:

Re: [BUG] Python Dictionary not being processed properly?

#12 Post by Kaji »

Oooh, that on "hide" bit works like a charm! Learning all kinds of new things today!

Yeah, the entries have the potential for a range of unique layouts depending on things (e.g. are there insert pictures? are the entries *fully* unlocked? etc.), which is the reason why I resorted to sub-screens, since I wasn't finding any way to embed one screen inside another like you would, say, templates within a WordPress theme.

Edit: Added into the main project and it's working perfectly. Thanks again!

Post Reply

Who is online

Users browsing this forum: No registered users