init offset = -1 screen save(): use navigation use file_slots(_("Save")) screen load(): use navigation 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_note" at note_hover(slot_rotations[i]) 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, FileLoad(i)) elif title == "Load": action FileLoad(i) else: action FileSave(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" 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_note" at note_hover(slot_rotations[i]) 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, FileLoad(i)) elif title == "Load": action FileLoad(i) else: action FileSave(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" transform file_hover: on hover: matrixcolor SaturationMatrix(1.0) on idle: matrixcolor SaturationMatrix(0.5) transform note_hover(r): subpixel True offset (75, 70) anchor (0.5, 0.5) rotate r on idle: easein 0.25 rotate r on hover: easein 0.25 rotate 0 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