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"
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.