Ren'Py Gallery pagination: bounding page contents and building navigation without a built-in widget
0 reputation · 22 Feb 2022, 22:14 UTC
0 reputation · 22 Feb 2022, 22:14 UTC
Ren'Py's Gallery class accepts a page argument on button() and image(), grouping entries into logical pages, but the engine ships no page-navigation widget. I want to bound a large gallery so only one page of entries is displayed at a time, with previous/next controls tracking the current page index manually.
The constraints I am weighing: Gallery visibility is driven by persistent unlock state (unlock(), condition(), unlock_image()), so page contents vary per player save, and the page argument is a grouping label rather than an automatic UI. An alternative is a vpgrid with fixed rows/cols and scrollbars, but vpgrid instantiates all of its children rather than virtualizing them, so a large collection still costs screen-build time and memory.
Assume a current Ren'Py release; I will confirm the exact screen-language properties against the documentation for the installed version.
Questions:
Gallery page, or must each page be a separate screen?vpgrid make manual pagination materially cheaper than one scrolling grid?35775 reputation · 22 Feb 2022, 23:02 UTC
Ren'Py's Gallery class has no pagination widget. The documented pattern is to call Gallery.get_page(page_name), which returns only the displayables for that page (already filtered by unlock/condition logic), and render that list in a screen driven by a normal variable holding the current page name. For several hundred entries, manual pagination — creating displayables only for the active page — is materially cheaper than a single vpgrid because vpgrid instantiates every child at screen-build time and does not virtualize. Page-switch state belongs in a normal (non-persistent) variable; persistent data is for cross-session unlocks, not UI navigation.
Define a screen that reads a variable (e.g., gallery_page) and builds its grid from gallery.get_page(gallery_page):
screen gallery_view():
default gallery_page = gallery.get_pages()[0]
$ page_buttons = gallery.get_page(gallery_page)
grid 3 4:
for btn in page_buttons:
add btn
# navigation buttons below
hbox:
textbutton "Previous" action SetScreenVariable("gallery_page", prev_page(gallery_page))
textbutton "Next" action SetScreenVariable("gallery_page", next_page(gallery_page))
gallery.get_pages() returns the ordered list of page names, so prev_page/next_page can clamp to the first/last index. SetScreenVariable updates the variable and refreshes the screen without a full interaction restart.
vpgrid for Hundreds of Entriesvpgrid builds every child displayable when the screen is shown. With 300+ gallery buttons (each potentially wrapping a large image), screen-build time and texture memory spike noticeably. Manual pagination limits the live displayable count to one page (e.g., 12–20 items), keeping build time near-constant regardless of total gallery size. The trade-off is you must implement prev/next logic yourself, but the API surface is small: get_pages(), get_page(), and a variable update.
default statement in python early block) — resets on game restart, which is usually the desired UX.persistent on page change: action [SetScreenVariable("gallery_page", next_page), SetVariable("persistent.last_gallery_page", next_page)].Do not store page index in persistent by default; unlock gating already lives in persistent, and mixing UI navigation state with progress data complicates save/load reasoning.
get_page() returns only unlocked buttons for the active page.renpy.profile_screen() comparing one vpgrid of all entries vs. manual pagination showing 12 entries.persistent.What is the typical number of entries per page and the approximate image dimensions? If pages hold 50+ items or thumbnails are full-resolution, texture memory may still pressure the GPU even with pagination, and you may need downsampled thumbnails (im.Data/im.Memory) regardless of the pagination strategy.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.