Is this a bug? Values not updating in screen with 'use' statement

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
DsyD
Newbie
Posts: 6
Joined: Tue Jun 23, 2020 7:31 am
Contact:

Is this a bug? Values not updating in screen with 'use' statement

#1 Post by DsyD » Tue Jun 23, 2020 8:16 am

Hi - I am new to Ren'Py but familiar with Python (although I haven't used Python 2 in a while).

I am attempting to compose UI elements using screen statements and use. I'm showing a complete example below that does the following:

1. Defines a prop_widget screen that takes two parameters, prop1 and prop2, and displays them.

2. Defines a widget_host screen that takes a state object and passes some of its values to prop_widget.

3. In game, creates a simple menu where some of the options can modify the state.

The game's "dialogue" shows the actual values of the state's prop1 and prop2 after every menu selection. The widget_host is also displayed at the top center of the screen. It is supposed to show the current values of prop1 and prop2.

Here is the entire script.rpy. You should be able to just drop it into a new project if you want to see the behavior:

Code: Select all

############## Data setup ##############

init python:

    class MyStore(object):

        def __init__(self):
            self._prop1 = 0
            self.prop2 = 0

        @property
        def prop1(self):
            return self._prop1

        def addProp1(self, num=1):
            self._prop1 = (self._prop1 + num) % 3

        def addProp2(self, num=1):
            self.prop2 += 1

    mydata = MyStore()

    addProp1 = mydata.addProp1
    addProp2 = mydata.addProp2


############## Screens ##############


screen prop_widget(prop1=0, prop2=0):

    # Neither of the interpolated texts is updated when `mydata` changes
    # However, if the line below is uncommented, then BOTH `prop1` and `prop2` are updated whenever `mydata` is mutated
    # $ prop1 = mydata.prop1

    hbox:
        spacing 10
        text "prop1: [prop1]"
        text "prop2: [prop2]"

screen widget_host(state):
    # Take game state as parameter and pass appropriate slices of state to child UI "widgets"
    frame:
        xalign 0.5 yalign 0

        use prop_widget(state.prop1, state.prop2)


############## Game start ##############

define e = Character("Eileen", color="#ff9015")

label start:

    # Pass the game state `mydata` to the UI parent widget
    show screen widget_host(mydata)

    "Do something to the data."

    python:
        res = None
        options = ('Add to prop1', 'Add to prop2', 'Done')
        callbacks = (addProp1, addProp2)

        while res != 2:
            res = renpy.display_menu([(option, i) for i, option in enumerate(options)])
            if res < 2:
                callbacks[res]()

            # Show current state properties and compare with `widget_host` displayed values
            narrator('Current state: prop1=[mydata.prop1], prop2=[mydata.prop2]')
        
    "Done"
If I just run this project, what happens is that the prop_widget text is never updated. You can verify that the state is being changed by looking at the dialogue.

However, if I uncomment the line $ prop1 = mydata.prop1 in prop_widget, then both the prop1 and prop2 texts are updated properly, even though only prop1 is being assigned to in the prop_widget screen.

This seems odd. I am expecting the texts to update without having to refer to a global object (mydata) - otherwise, I am not sure what the point is of being able to pass arguments to a screen called by use. But failing that, I would not expect both prop1 and prop2 to update after assigning only prop1.

Can someone explain to me why this is happening, and if it's intentional?

Also attaching script.rpy for people who don't want to copy-paste.
Attachments
script.rpy
(1.84 KiB) Downloaded 1 time

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: Is this a bug? Values not updating in screen with 'use' statement

#2 Post by Remix » Tue Jun 23, 2020 9:20 am

It would seem that the prop_widget screen is not being updated as there is nothing dynamic inside it (the text "prop1: [prop1]" part does not actually make that widget dynamic so it never checks to see if it has changed value (even through interactions))

I tried adding the screen to per_frame_screens (which in my mind should work) and even that didn't work, so I theorize that somewhere deep inside Ren'Py there is something which is just saying "the screen has not changed, so do not redraw it from scratch".

You can get around it by:
Adding a pseudo variable to it ( as in $ nullvar = None inside that screen ) which causes it to re-evaluate the entire screen
Add some form of dynamic element to the screen such as a DynamicDisplayable or perhaps a bar
Use .format for one or more of the texts (tricking it to re-evaluate) ( as in text "prop1: {}".format(prop1) )
Frameworks & Scriptlets:

DsyD
Newbie
Posts: 6
Joined: Tue Jun 23, 2020 7:31 am
Contact:

Re: Is this a bug? Values not updating in screen with 'use' statement

#3 Post by DsyD » Tue Jun 23, 2020 9:43 am

Ah, thank you. Using .format seems to fix it and seems like a clean solution.

I am wondering what exactly causes Ren'Py to consider a screen as "dynamic," though. For example, if I make the widget_host directly display the value instead (by adding something like text "prop1-state: [state.prop1]" inside the frame), then it does update when needed. So is it the case that Ren'Py sees it as "dynamic" because of object attribute access, but in my example it's not considered dynamic because it's a plain value - even though the value passed into the screen as a parameter?

Post Reply

Who is online

Users browsing this forum: Bing [Bot]