Maintaining Focus in Scrolling Viewport
Posted: Fri Apr 26, 2024 1:49 pm
Hi all! I'm doing some contract work on a published VN, and we're trying to improve the feel of the controller support. The game displays all the dialogue choice options in a scrolling viewport, and we are attempting to set the viewport scroll directly based on when one of the choices is focused.
Our current approach is to create an action that fires when the textbutton is hovered.
In choices screen here:
And scrolling viewport code here:
In the code above when a textbutton is hovered, we're trying to get the offset of that textbutton relative to the viewport, and scroll the viewport to that position, to ensure the choice is always visible.
We're having trouble getting the offset of the textbutton. Is there a way to get the offset of the returned widget (which is `Text`, rather than `Button`) to then use in the adjustment for the viewport?
Our current approach is to create an action that fires when the textbutton is hovered.
In choices screen here:
Code: Select all
screen choice(items):
style_prefix "choice"
default yadj = ui.adjustment()
default hoveredrect = (1, 2, 3, 100)
default hoveredy = 100
key "K_UP" action ScrollViewport(yadj, 'up', items)
key "K_DOWN" action ScrollViewport(yadj, 'down', items)
key "pad_lefty_pos" action ScrollViewport(yadj, 'down', items)
key "pad_lefty_neg" action ScrollViewport(yadj, 'up', items)
key "pad_righty_pos" action ScrollViewport(yadj, 'down', items)
key "pad_righty_neg" action ScrollViewport(yadj, 'up', items)
key "pad_dpup_press" action ScrollViewport(yadj, 'up', items)
key "pad_dpdown_press" action ScrollViewport(yadj, 'down', items)
add "gui/choices_backdrop.png"
viewport yadjustment yadj:
draggable True
mousewheel True
scrollbars "vertical"
xalign 0.0
xsize 430
ysize 650
xpos 1480
ypos 25
vbox:
for idx, i in enumerate(items):
if idx == 0:
textbutton i.caption id "choice_" + str(idx) action i.action default_focus True hovered OnChoiceFocus(idx, yadj)
#hovered SetVariable("captured", renpy.focus_coordinates())
else:
textbutton i.caption id "choice_" + str(idx) action i.action hovered OnChoiceFocus(idx, yadj)
#hovered SetVariable("captured", renpy.focus_coordinates())
Code: Select all
######## Viewport Scrolling ##############
init python:
class OnChoiceFocus(Action):
def __init__(self, index, yadj):
self.index = index
self.yadj = yadj
def __call__(self):
widget = renpy.get_widget("choice", "choice_" + str(self.index))
dispProps = renpy.get_displayable_properties("choice_" + str(self.index))
renpy.log(dispProps)
# self.yadj.change(dispProps["offset"])
# GetFocusRect("current_choice")
class ScrollViewport(Action):
def __init__(self, yadj, scroll_dir, items, step=(gui.interface_text_size)*3):
#def __init__(self, yadj, scroll_dir, step):
self.yadj = yadj
self.scroll_dir = scroll_dir
self.step = step
self.items = items
def __call__(self):
#yadj = renpy.focus_coordinates()[3]
# Don't confuse dir with the other use case for "up" which
# refers to the state of the key (pressed/released)
# print renpy.get_focus_rect()
if self.scroll_dir == "up":
renpy.display.behavior.queue_event('focus_up', up=False)
else:
renpy.display.behavior.queue_event('focus_down', up=False)
return
We're having trouble getting the offset of the textbutton. Is there a way to get the offset of the returned widget (which is `Text`, rather than `Button`) to then use in the adjustment for the viewport?