In short:
I am looking for a way to manually set a textbutton to "idle" based on some (external?) condition. I don't much mind whether it is to be written as some sort of conditional inside the block or line for the button (similar to SensitiveIf, but for idle rather than insensitive) or it can be called somewhere outside the block (perhaps referencing the button by a variable name? ).
More context:
I am writing code for a nested menu for the player to select among tasks to perform that are grouped in categories and subcategories. I made it so that if you click on a category, the menu for the subcategories opens, and then the actual task down below, and finally the location where to perform the task once a task is selected (so there are four levels in the nested menu). I'm using a main (top-level) screen that uses separate screens for each (other) level of the menu, and I set a variable for each level to decide whether to show that level.
However, when I added a style to the buttons with different colors to make it clearer when a button was selected, I noticed that when I close and re-open a particular submenu level (the menu collapses when you go back to a higher level or re-select the same option; see the code in the while loop), a button that was previously selected in that level might still be highlighted. So, I would like to be able to set that button to idle manually—because since there are separate levels involved, it doesn't seem possible to just use a single radio-button style menu where only one can be active at a time (in fact, multiple should be allowed to be active; just only one per level; but setting idle should also be possible between the levels).
Code for illustration (slightly simplified):
Code: Select all
# This example uses only three levels (top, task, loc) rather than the four from my code, for simplicity.
style basicButton:
color "#888888"
hover_color "#0066cc"
selected_color "#cccccc"
insensitive_color "#444444"
label start:
$ playing = True
while playing:
# It remembers the previous selections to decide whether the same option is clicked twice
# (which would close the lower-level menu that was just opened).
$ previousSelectedTop = selectedTop
$ previousTask = task
$ UIReturn = renpy.call_screen("TopMenu", _layer="screens")
if UIReturn == "topMenuClick":
# If you click back to the top level after having reached further down, collapse the menu.
$ showLocMenu = False
$ locChosen = None # This variable is used later in the program, as is the variable 'task'.
# Clicking top menu shows the next level, unless already shown and the same top choice clicked again.
if not selectedTop == previousSelectedTop or not showTaskMenu:
$ showTaskMenu = True
else:
$ showTaskMenu = False
# Ideally, here is where I would set all buttons from the task and location menus to idle.
# That way, if I open up the same category in the top menu again, the task I may have previously selected
# in the lower-level task or location menus would no longer be misleadingly highlighted as if selected
# (even though the game has forgotten the associated data, like locChosen).
if UIReturn == "taskMenuClick":
# Clicking task menu shows the next level, unless already shown and the same task choice clicked again.
if not task == previousTask or not showLocMenu:
$ showLocMenu = True
else:
$ showLocMenu = False
$ locChosen = None
# Here too I would like to set the location menu buttons to idle to avoid highlighting upon re-opening.
if UIReturn == "locMenuClick":
pass # This no longer does anything because I added a confirmation button instead.
if UIReturn == "confirmButtonClick":
jump newDay # I did not include this label, as it is outside the scope of my question. The jump works fine.
return
screen TopMenu():
# Show the menu for the basic category of tasks to choose.
frame:
xalign 0.0
vbox:
for skill in skills: # These are objects from a Skill class (not shown here) that are in a global list 'skills'.
textbutton skill.name:
text_style "basicButton"
action SetVariable("selectedTop", skill), Return("topMenuClick")
if showTaskMenu:
use TaskMenuScreen
if showLocMenu:
use LocMenuScreen
# Confirmation button.
frame:
xpos 1200
textbutton "Confirm":
text_style "basicButton"
# Only able to confirm if a selection is made on all levels of the menu.
action [Return("confirmButtonClick", SensitiveIf(locChosen is not None)]
screen TaskMenu():
# Show the menu for the subcategory of tasks to choose.
xpos 400
frame:
for skill in selectedTop.subSkills:
textbutton skill.name:
text_style "basicButton"
action SetVariable("task", skill), Return("taskMenuClick")
screen LocMenu():
# Show the menu for the location choice.
xpos 800
frame:
for place in task.places:
textbutton place.name:
text_style "basicButton"
action SetVariable("locChosen", place), Return("locMenuClick")
It occurs to me that if I could destroy the buttons in the lower-level menus upon collapse, that would also work, if they could be recreated when the lower level is reopened, as when another higher-level option is selected. That way too, they would all start as idle again. However, since I was unable to find this information after searching for quite a while, I would prefer to have my original question answered, for future Ren'Py users with a similar question.