WTS/game/scripts/gui/save_files.rpy
LoafyLemon 7612c0bf1f Save menu
* Implement new save/load menus
2024-06-05 22:25:18 +01:00

321 lines
12 KiB
Plaintext

#
# Load/save screens
#
# These screens are responsible for letting the player save the game and load
# it again. Since they share nearly everything in common, both are implemented
# in terms of a third screen, file_slots.
#
# https://www.renpy.org/doc/html/screen_special.html#save
# https://www.renpy.org/doc/html/screen_special.html#load
init offset = -1
screen save():
use file_slots(_("Save"))
screen load():
use file_slots(_("Load"))
screen file_slots(title):
default page_name = FilePageNameInputValue(pattern=_("Page {}"), auto=_("Auto Saves"), quick=_("Quick Saves"))
default time_format = "{#file_time}%#d %B, %Y, %#H:%M" if renpy.windows else "{#file_time}%-d %B, %Y, %-H:%M"
default slot_rotations = [renpy.random.randint(-5, 5) for i in range(1, 14)]
frame style "navigation_page_left":
vbox:
button:
style "navigation_label"
action page_name.Toggle()
input:
style "navigation_label_text"
value page_name
# Grid breaks as soon as we rotate displaybles, so we have to use our own calculations. /shrugs
# grid 2 3:
frame style "empty":
for i in range(1, 7):
button:
style "navigation_picture_button"
xysize (150, 140)
xpos ((i-1) % 2) * 160
ypos ((i-1) // 2) * 140
if FileLoadable(i):
add At(FileScreenshot(i), file_hover) xysize (135, 75) xalign 0.5 ypos 16
else:
add "#C69D65" xysize (135, 75) xalign 0.5 ypos 16
if not FileCompatible(i) and title == "Load":
action Confirm(gui.SAVE_INCOMPATIBLE_WARNING, FileAction(i))
else:
action FileAction(i)
# FileSaveName sometimes returns an empty string regardless of 'empty' parameter. /shrugs
$ file_name = (FileSaveName(i) or f"Slot {i}")
text "[file_name]" style "file_description_text" ypos 2
vbox style "file_vbox":
ypos 100
xalign 0.5
text FileTime(i, format=time_format) style "file_description_text"
if FileLoadable(i):
$ playtime = FileJson(i, "playtime", missing=0)
$ minutes, seconds = divmod(int(playtime), 60)
$ hours, minutes = divmod(minutes, 60)
text f"Playtime: {hours}H {minutes}M {seconds}S" style "file_description_text"
at transform:
subpixel True
offset (75, 70)
anchor (0.5, 0.5)
rotate slot_rotations[i]
on idle:
easein 0.25 rotate slot_rotations[i]
on hover:
easein 0.25 rotate 0
frame style "navigation_page_right":
vbox:
null height 38
# button:
# style "navigation_label"
# action page_name.Toggle()
# input:
# style "navigation_label_text"
# value page_name
frame style "empty":
for i in range(7, 13):
button:
style "navigation_picture_button"
xysize (150, 140)
xpos ((i-7) % 2) * 160
ypos ((i-7) // 2) * 140
if FileLoadable(i):
add At(FileScreenshot(i), file_hover) xysize (135, 75) xalign 0.5 ypos 16
else:
add "#C69D65" xysize (135, 75) xalign 0.5 ypos 16
if not FileCompatible(i) and title == "Load":
action Confirm(gui.SAVE_INCOMPATIBLE_WARNING, FileAction(i))
else:
action FileAction(i)
# FileSaveName sometimes returns an empty string regardless of 'empty' parameter. /shrugs
$ file_name = (FileSaveName(i) or f"Slot {i}")
text "[file_name]" style "file_description_text" ypos 2
vbox style "file_vbox":
ypos 100
xalign 0.5
text FileTime(i, format=time_format) style "file_description_text"
if FileLoadable(i):
$ playtime = FileJson(i, "playtime", missing=0)
$ minutes, seconds = divmod(int(playtime), 60)
$ hours, minutes = divmod(minutes, 60)
text f"Playtime: {hours}H {minutes}M {seconds}S" style "file_description_text"
at transform:
subpixel True
offset (75, 70)
anchor (0.5, 0.5)
rotate slot_rotations[i]
on idle:
easein 0.25 rotate slot_rotations[i]
on hover:
easein 0.25 rotate 0
transform file_hover:
on hover:
matrixcolor SaturationMatrix(1.0)
on idle:
matrixcolor SaturationMatrix(0.5)
style file_delete
style file_delete_text:
color "#ffffff"
style file_description_text:
color "#000000"
size 10
font gui.bold_font
xalign 0.5
style file_vbox is empty:
fit_first True
xfill False
yfill False
xsize 150
spacing 0
# pos (4, -16)
# use game_menu(title):
# fixed:
# # This ensures the input will get the enter event before any of the buttons do
# order_reverse True
# # The page name, which can be edited by clicking on a button
# button:
# style gui.theme("page_label")
# key_events True
# xalign 0.5
# action page_name.Toggle()
# hbox:
# spacing 9
# input:
# style gui.theme("page_label_text")
# value page_name
# if page_name.editable:
# text "{size=-4}{font=[gui.glyph_font]}✎{/font}{/size}"
# ## The grid of file slots.
# grid gui.file_slot_cols gui.file_slot_rows:
# style_prefix gui.theme("slot")
# xalign 0.5
# yalign 0.5
# spacing gui.slot_spacing
# transpose True
# for i in range(gui.file_slot_cols * gui.file_slot_rows):
# $ slot = i + 1
# button:
# if not FileCompatible(slot) and title == "Load":
# action Confirm(gui.SAVE_INCOMPATIBLE_WARNING, FileAction(slot))
# else:
# action FileAction(slot)
# has fixed
# if FileLoadable(slot):
# add FileScreenshot(slot)
# vbox:
# style_prefix "slot_button"
# xpos config.thumbnail_width
# xsize gui.slot_width - config.thumbnail_width - gui.slot_height
# yalign 0.5
# if FileCompatible(slot):
# default slot_time_format = "{#file_time}%#d %B, %Y, %#H:%M" if renpy.windows else "{#file_time}%-d %B, %Y, %-H:%M"
# $ day = FileJson(slot, "day", missing="Unknown")
# $ playtime = FileJson(slot, "playtime", missing=0)
# $ minutes, seconds = divmod(int(playtime), 60)
# $ hours, minutes = divmod(minutes, 60)
# text FileTime(slot, format=slot_time_format)
# text f"Day: {day}"
# text f"Playtime: {hours}H {minutes}M {seconds}S"
# else:
# text "INCOMPATIBLE VERSION" color "#f00"
# textbutton "{font=[gui.glyph_font]}✘{/font}":
# style "slot_delete_button"
# action FileDelete(slot)
# key "save_delete" action FileDelete(slot)
# else:
# text f"Empty Slot {FileSlotName(slot, gui.file_slot_cols * gui.file_slot_rows)}." style "slot_button_text"
# ## Buttons to access other pages.
# hbox:
# style_prefix gui.theme("page")
# align (0.5, 1.0)
# yoffset 8
# spacing gui.page_spacing
# textbutton _("<") action FilePagePrevious()
# if config.has_autosave:
# textbutton _("{#auto_page}A") action FilePage("auto") keysym "K_a"
# if config.has_quicksave:
# textbutton _("{#quick_page}Q") action FilePage("quick") keysym "K_q"
# $ page_modifier = max(0, int(FilePageName(str(page_modifier+9), str(page_modifier+9)))-9)
# for page in range(1+page_modifier, 10+page_modifier):
# textbutton "[page]":
# xminimum 40
# action FilePage(page)
# if page < 10:
# keysym f"K_{page}"
# textbutton _(">") action FilePageNext()
# key ["mousedown_4", "K_RIGHT", "repeat_K_RIGHT"] action FilePageNext()
# key ["mousedown_5", "K_LEFT", "repeat_K_LEFT"] action FilePagePrevious()
# style page_label is gui_label
# style page_label_text is gui_label_text:
# text_align 0.5
# layout "subtitle"
# hover_color gui.hover_color
# style dark_page_label_text is dark_label_text:
# take page_label_text
# style light_page_label_text is light_label_text:
# take page_label_text
# style page_button is gui_button:
# background None
# padding (9, 4, 9, 4)
# style page_button_text is gui_button_text:
# size 20
# xalign 0.5
# style slot_button is gui_button:
# # background gui.muted_color
# xsize gui.slot_width
# ysize gui.slot_height+4
# padding (2, 2, 2, 2)
# style dark_slot_button:
# take dark_gui_frame
# insensitive_background Fixed(Transform(Frame("gui/dark_frame.png", 8, 8)), "#00000040")
# style light_slot_button:
# take light_gui_frame
# insensitive_background Fixed(Transform(Frame("gui/light_frame.png", 8, 8)), "#00000040")
# style slot_button_text is gui_button_text:
# size 14
# xalign 0.5
# text_align 0.5
# idle_color gui.idle_small_color
# selected_idle_color gui.selected_color
# selected_hover_color gui.hover_color
# style slot_delete_button is gui_button:
# background None
# idle_background None
# xsize gui.slot_height
# ysize gui.slot_height
# xalign 1.0
# style slot_delete_button_text is slot_button_text:
# size 24