Skip to content

Instantly share code, notes, and snippets.

@midgethetree
Last active February 27, 2024 20:57
Show Gist options
  • Save midgethetree/b210ddadfb07e85873022fde0202f646 to your computer and use it in GitHub Desktop.
Save midgethetree/b210ddadfb07e85873022fde0202f646 to your computer and use it in GitHub Desktop.
Scrollbutton code for the Ren'Py visual novel engine.
"""renpy
init offset = -2
python early:
"""
# The scrollbutton will automatically hide itself when the viewport it's associated with cannot be scrolled.
class ScrollButton(renpy.display.behavior.Button):
def __init__(self, *args, **kwargs):
super(ScrollButton, self).__init__(*args, **kwargs)
self.hidden = False
self.null = renpy.display.layout.Null()
if callable(getattr(self.action, "get_adjustment_and_delta", None)):
adjustment, delta = self.action.get_adjustment_and_delta()
self.adjustment = adjustment
self.adjustment.register(self)
else:
self.adjustment = None
def render(self, width, height, st, at):
if self.adjustment and self.adjustment.range <= 0:
self.hidden = True
return renpy.render(self.null, width, height, st, at)
self.hidden = False
return super(ScrollButton, self).render(width, height, st, at)
def event(self, ev, x, y, st):
if self.hidden:
return None
return super(ScrollButton, self).event(ev, x, y, st)
def _scrollbutton(
label,
clicked=None,
style=None,
text_style=None,
substitute=True,
scope=None,
**kwargs
):
text_kwargs, button_kwargs = renpy.easy.split_properties(kwargs, "text_", "")
if "align" in text_kwargs:
if isinstance(text_kwargs["align"], float):
text_kwargs.pop("align")
text_kwargs.pop("y_fudge", None)
if style is None:
style = renpy.ui.prefixed_style("scrollbutton")
if text_style is None:
text_style = renpy.style.get_text_style(
style, renpy.ui.prefixed_style("scrollbutton_text")
)
rv = ScrollButton(style=style, clicked=clicked, **button_kwargs)
text = renpy.text.text.Text(
label, style=text_style, substitute=substitute, scope=scope, **text_kwargs
)
rv.add(text)
rv._main = text
rv._composite_parts = [text]
return rv
renpy.register_sl_displayable(
"scrollbutton", _scrollbutton, "scrollbutton", 0, scope=True
).add_positional("label").add_property("action").add_property("clicked").add_property(
"hovered"
).add_property(
"unhovered"
).add_property(
"alternate"
).add_property(
"text_style"
).add_property(
"substitute"
).add_property(
"scope"
).add_property(
"unscrollable"
).add_property_group(
"window"
).add_property_group(
"button"
).add_property_group(
"text", "text_"
).add_property_group(
"position", "text_"
)
## Example of the code in use ##################################################
screen game_menu(title, scroll=None, yinitial=0.0):
style_prefix "game_menu"
if main_menu:
add gui.main_menu_background
else:
add gui.game_menu_background
frame:
style "game_menu_outer_frame"
hbox:
## Reserve space for the navigation section.
frame:
style "game_menu_navigation_frame"
frame:
style "game_menu_content_frame"
has side 'c b' # use side to create space for the scrollbuttons
if scroll == "viewport":
viewport:
yinitial yinitial
scrollbars "vertical"
mousewheel True
draggable True
pagekeys True
id 'game_menu' # scrollbuttons can only scroll viewports if they're given an id
side_yfill True
vbox:
transclude
elif scroll == "vpgrid":
vpgrid:
cols 1
yinitial yinitial
scrollbars "vertical"
mousewheel True
draggable True
pagekeys True
id 'game_menu' #midge
side_yfill True
transclude
else:
transclude
if scroll: # here is where the scrollbuttons themselves will go, if the screen is scrollable
hbox xalign 0.5 spacing 50:
scrollbutton _('Up') action Scroll('game_menu', 'vertical decrease', 'page')
scrollbutton _('Down') action Scroll('game_menu', 'vertical increase', 'page')
else:
null
use navigation
textbutton _("Return"):
style "return_button"
action Return()
label title
if main_menu:
key "game_menu" action ShowMenu("main_menu")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment