# Copyright 2004-2019 Tom Rothamel # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. init -1400 python: # basics: The width of a thumbnail. config.thumbnail_width = 66 # basics: The height of a thumbnail. config.thumbnail_height = 50 # Should autosave be called when the game is about to quit? config.autosave_on_quit = True # Should the confirm screen be used? config.confirm_screen = True class Layout(): def __call__(self, func): setattr(self, func.func_name, func) return func layout = _layout = Layout() del Layout layout.compat_funcs = [ ] layout.provided = set() # This is used to jump to a label with a transition. def _intra_jumps_core(label, transition): renpy.transition(getattr(config, transition)) renpy.jump(label) _intra_jumps = renpy.curry(_intra_jumps_core) # These are obsoleted by screens, but used by layout code. config.main_menu = [ (u"Start Game", "start", "True"), (u"Load Game", _intra_jumps("load_screen", "main_game_transition"), "True"), (u"Preferences", _intra_jumps("preferences_screen", "main_game_transition"), "True"), (u"Help", _help, "True", "config.help"), (u"Quit", ui.jumps("_quit"), "True"), ] config.game_menu = [ ( None, u"Return", ui.jumps("_return"), 'True'), ( "preferences", u"Preferences", _intra_jumps("preferences_screen", "intra_transition"), 'True' ), ( "save", u"Save Game", _intra_jumps("save_screen", "intra_transition"), 'not main_menu' ), ( "load", u"Load Game", _intra_jumps("load_screen", "intra_transition"), 'True'), ( None, u"Main Menu", ui.callsinnewcontext("_main_menu_prompt"), 'not main_menu' ), ( "help", u"Help", _help, "True", "config.help"), ( None, u"Quit", ui.callsinnewcontext("_quit_prompt"), 'True' ), ] # These are used by layout-based code, and also by the screens code when a layout # is used to invoke the screen. label _quit_prompt: if config.autosave_on_quit: $ renpy.force_autosave() if layout.invoke_yesno_prompt(None, layout.QUIT): jump _quit else: return label _main_menu_prompt: if config.autosave_on_quit: $ renpy.force_autosave() if layout.yesno_prompt(None, layout.MAIN_MENU): $ renpy.full_restart(transition=config.game_main_transition) else: return init -1400 python hide: # Called to indicate that the given kind of layout has been # provided. @layout def provides(kind): if kind in layout.provided: raise Exception("%s has already been provided by another layout function." % kind) layout.provided.add(kind) # Called by registered themes to have the default versions of # various kinds of layouts provided, if a more specific version # has not been requested by the user. @layout def defaults(): # Do nothing, in compatibility mode. if 'compat' in layout.provided: return defaults = dict( main_menu=layout.classic_main_menu, load_save=layout.classic_load_save, navigation=layout.classic_navigation, yesno_prompt=layout.classic_yesno_prompt, preferences=layout.classic_preferences, joystick_preferences=layout.classic_joystick_preferences, ) if renpy.has_screen("main_menu"): defaults["main_menu"] = layout.screen_main_menu if renpy.has_screen("load") and renpy.has_screen("save"): defaults["load_save"] = layout.screen_load_save if config.confirm_screen and renpy.has_screen("confirm"): defaults["yesno_prompt"] = layout.screen_yesno_prompt if renpy.has_screen("yesno_prompt"): defaults["yesno_prompt"] = layout.screen_yesno_prompt if renpy.has_screen("preferences"): defaults["preferences"] = layout.screen_preferences if renpy.has_screen("joystick_preferences"): defaults["joystick_preferences"] = layout.screen_joystick_preferences for k, v in defaults.iteritems(): if k not in layout.provided: v() if store._game_menu_screen is None: if renpy.has_label("save_screen"): store._game_menu_screen = "save_screen" elif renpy.has_label("preferences_screen"): store._game_menu_screen = "preferences_screen" ########################################################################## # These live on the layout object, and ease the construction of buttons, # labels, and prompts. A sufficently aggressive layout might change # these. @layout def button(label, type=None, selected=False, enabled=True, clicked=None, hovered=None, unhovered=None, index=None, **properties): """ label - The label of this button. Will be translated if necessary. type - The type of this button. Used to generate the appropriate styles. selected - Determines if this button should be selected. enabled - Determines if this button should be enabled. clicked - A function that is run when the button is clicked. hovered - A function that is run when the button is hovered. unhovered - A function that is run when the button is unhovered. index - A style index. If None, label is used. size_group - The size_group used by this button. """ if not enabled: clicked = None if selected and enabled: role = "selected_" else: role = "" if type: button_style = type + "_button" text_style = type + "_button_text" else: button_style = 'button' text_style = 'button_text' if index is None: index = label button_style = getattr(style, button_style)[index] text_style = getattr(style, text_style)[index] rv = ui.button(style=button_style, role=role, clicked=clicked, hovered=hovered, unhovered=unhovered, **properties) ui.text(_(label), style=text_style) return rv @layout def label(label, type, suffix="label", index=None, **properties): if index is None: index = label if type: label_style = getattr(style, type + "_" + suffix)[index] text_style = getattr(style, type + "_" + suffix + "_text")[index] else: label_style = style.label[index] text_style = style.label_text[index] ui.window(style=label_style, **properties) ui.text(_(label), style=text_style) @layout def prompt(label, type, index=None, **properties): return layout.label(label, type, "prompt", index, **properties) @layout def list(entries, clicked=None, hovered=None, unhovered=None, selected=None, **properties): ui.window(style=style.list, **properties) ui.vbox(style=style.list_box) size_group = str(id(entries)) for i, (spacers, content) in enumerate(entries): if clicked is not None: new_clicked = renpy.curry(clicked)(i) else: new_clicked = None if hovered is not None: new_hovered = renpy.curry(hovered)(i) else: new_hovered = None if unhovered is not None: new_unhovered = renpy.curry(unhovered)(i) else: new_unhovered = None if selected == i: role = "selected_" else: role = "" ui.button(style=style.list_row[i%2], clicked=new_clicked, hovered=new_hovered, unhovered=new_unhovered, role=role, size_group=size_group, ) ui.hbox(style=style.list_row_box) for j in range(0, spacers): ui.window(style=style.list_spacer) ui.null() ui.text(content, style=style.list_text) ui.close() # row ui.close() # vbox ########################################################################## # Misc. @layout def button_menu(): config.narrator_menu = True style.menu.box_spacing = 2 style.menu_window.set_parent(style.default) style.menu_window.xalign = 0.5 style.menu_window.yalign = 0.5 style.menu_choice.set_parent(style.button_text) style.menu_choice.clear() style.menu_choice_button.set_parent(style.button) style.menu_choice_button.xminimum = int(config.screen_width * 0.75) style.menu_choice_button.xmaximum = int(config.screen_width * 0.75) store._button_menu = button_menu ########################################################################### # Compat layout. @layout def compat(): layout.provides('compat') renpy.load_module("_compat/styles") renpy.load_module("_compat/library") renpy.load_module("_compat/mainmenu") renpy.load_module("_compat/gamemenu") renpy.load_module("_compat/preferences") renpy.load_module("_compat/themes") ########################################################################### # Classic layout. @layout def classic_main_menu(): renpy.load_module("_layout/classic_main_menu") @layout def classic_navigation(): renpy.load_module('_layout/classic_navigation') @layout def classic_load_save(): renpy.load_module('_layout/classic_load_save') @layout def classic_yesno_prompt(): renpy.load_module('_layout/classic_yesno_prompt') @layout def classic_preferences(center=False): renpy.load_module('_layout/classic_preferences') if center: style.prefs_button.xalign = 0.5 style.prefs_slider.xalign = 0.5 style.prefs_jump_button.xalign = 0.5 @layout def classic_joystick_preferences(): renpy.load_module('_layout/classic_joystick_preferences') @layout def two_column_preferences(): renpy.load_module("_layout/two_column_preferences") @layout def one_column_preferences(): renpy.load_module("_layout/one_column_preferences") @layout def grouped_main_menu(per_group=2, equal_size=True): renpy.load_module("_layout/grouped_main_menu") config.main_menu_per_group = per_group if equal_size: style.mm_button.size_group = "main_menu" @layout def grouped_navigation(per_group=2, equal_size=True): renpy.load_module("_layout/grouped_navigation") config.navigation_per_group = per_group if equal_size: style.gm_nav_button.size_group = "navigation" @layout def scrolling_load_save(): renpy.load_module("_layout/scrolling_load_save") @layout def imagemap_main_menu(ground, selected, hotspots, idle=None, variant=None): renpy.load_module("_layout/imagemap_main_menu") config.main_menu_ground[variant] = ground config.main_menu_selected[variant] = selected config.main_menu_hotspots[variant] = hotspots config.main_menu_idle[variant] = idle @layout def imagemap_navigation(ground, idle, hover, selected_idle, selected_hover, hotspots): renpy.load_module("_layout/imagemap_navigation") config.navigation_ground = ground config.navigation_idle = idle config.navigation_hover = hover config.navigation_selected_idle = selected_idle config.navigation_selected_hover = selected_hover config.navigation_hotspots = hotspots @layout def imagemap_preferences(ground, idle, hover, selected_idle, selected_hover, hotspots): renpy.load_module("_layout/imagemap_preferences") config.preferences_ground = ground config.preferences_idle = idle config.preferences_hover = hover config.preferences_selected_idle = selected_idle config.preferences_selected_hover = selected_hover config.preferences_hotspots = hotspots @layout def imagemap_yesno_prompt(ground, idle, hover, hotspots, prompt_images={ }): renpy.load_module("_layout/imagemap_yesno_prompt") config.yesno_prompt_ground = ground config.yesno_prompt_idle = idle config.yesno_prompt_hover = hover config.yesno_prompt_hotspots = hotspots config.yesno_prompt_message_images = prompt_images @layout def imagemap_load_save(ground, idle, hover, selected_idle, selected_hover, hotspots, variant=None): renpy.load_module("_layout/imagemap_load_save") config.load_save_ground[variant] = ground config.load_save_idle[variant] = idle config.load_save_hover[variant] = hover config.load_save_selected_idle[variant] = selected_idle config.load_save_selected_hover[variant] = selected_hover config.load_save_hotspots[variant] = hotspots @layout def screen_main_menu(): renpy.load_module("_layout/screen_main_menu") @layout def screen_load_save(): renpy.load_module("_layout/screen_load_save") @layout def screen_preferences(): renpy.load_module("_layout/screen_preferences") @layout def screen_joystick_preferences(): renpy.load_module("_layout/screen_joystick_preferences") @layout def screen_yesno_prompt(): renpy.load_module("_layout/screen_yesno_prompt") layout.ARE_YOU_SURE = "Are you sure?" layout.DELETE_SAVE = "Are you sure you want to delete this save?" layout.OVERWRITE_SAVE = "Are you sure you want to overwrite your save?" layout.LOADING = "Loading will lose unsaved progress.\nAre you sure you want to do this?" layout.QUIT = "Are you sure you want to quit?" layout.MAIN_MENU = "Are you sure you want to return to the main menu?\nThis will lose unsaved progress." layout.END_REPLAY = "Are you sure you want to end the replay?" layout.SLOW_SKIP = "Are you sure you want to begin skipping?" layout.FAST_SKIP_SEEN = "Are you sure you want to skip to the next choice?" layout.FAST_SKIP_UNSEEN = "Are you sure you want to skip unseen dialogue to the next choice?" config.enter_yesno_transition = None config.exit_yesno_transition = None @layout def invoke_yesno_prompt(*args): _enter_menu() if config.enter_yesno_transition: renpy.transition(config.enter_yesno_transition) rv = layout.yesno_prompt(*args) if config.exit_yesno_transition: renpy.transition(config.exit_yesno_transition) return rv @layout def yesno_screen(message, yes=None, no=None): """ :doc: other This causes the a yes/no prompt screen with the given message to be displayed. The screen will be hidden when the user hits yes or no. `message` The message that will be displayed. `yes` An action that is run when the user chooses yes. `no` An action that is run when the user chooses no. """ if config.confirm_screen and renpy.has_screen('confirm'): screen = "confirm" elif renpy.has_screen("yesno_prompt"): screen = "yesno_prompt" else: screen = None if screen is not None: yes_action = [ Hide(screen, config.exit_yesno_transition) ] no_action = [ Hide(screen, config.exit_yesno_transition) ] if yes is not None: yes_action.append(yes) if no is not None: no_action.append(no) if config.enter_yesno_transition: renpy.transition(config.enter_yesno_transition) renpy.show_screen( screen, message=message, yes_action=yes_action, no_action=no_action) renpy.restart_interaction() return if renpy.invoke_in_new_context(layout.invoke_yesno_prompt, None, message): if yes is not None: yes() else: if no is not None: no() def __auto_save_extra_info(): return save_name config.auto_save_extra_info = __auto_save_extra_info