Mercurial > touhou
changeset 568:e7a4731a278b
Add a GTK+ main menu, mimicking the original EoSD one.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 01 Jul 2014 23:18:15 +0200 |
parents | b2269b9c6119 |
children | b21922a03830 |
files | data/menu.glade pytouhou/menu.py pytouhou/options.py scripts/pytouhou |
diffstat | 4 files changed, 1078 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/data/menu.glade @@ -0,0 +1,754 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.18.3 --> +<interface> + <requires lib="gtk+" version="3.12"/> + <object class="GtkWindow" id="game_window"> + <property name="can_focus">False</property> + <property name="title" translatable="yes">PyTouhou</property> + <property name="resizable">False</property> + <property name="has_resize_grip">False</property> + <signal name="destroy" handler="on_quit" swapped="no"/> + <signal name="key-press-event" handler="on_game_window_key_press_event" swapped="no"/> + <child> + <object class="GtkBox" id="game_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox" id="difficulty_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="difficulty_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Difficulty</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="difficulty_comboboxtext"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">0</property> + <items> + <item id="0" translatable="yes">Easy</item> + <item id="1" translatable="yes">Normal</item> + <item id="2" translatable="yes">Hard</item> + <item id="3" translatable="yes">Lunatic</item> + </items> + <signal name="changed" handler="on_difficulty_comboboxtext_changed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="character_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="character_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Character</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="character_comboboxtext"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">0</property> + <items> + <item id="0" translatable="yes">Reimu A</item> + <item id="1" translatable="yes">Reimu B</item> + <item id="2" translatable="yes">Marisa A</item> + <item id="3" translatable="yes">Marisa B</item> + </items> + <signal name="changed" handler="on_character_comboboxtext_changed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="stage_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="stage_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Stage</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="stage_comboboxtext"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">0</property> + <items> + <item id="1" translatable="yes">Stage 1</item> + <item id="2" translatable="yes">Stage 2</item> + <item id="3" translatable="yes">Stage 3</item> + <item id="4" translatable="yes">Stage 4</item> + <item id="5" translatable="yes">Stage 5</item> + <item id="6" translatable="yes">Final Stage</item> + <item id="7" translatable="yes">Extra Stage</item> + </items> + <signal name="changed" handler="on_stage_comboboxtext_changed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="boss_rush_checkbutton"> + <property name="label" translatable="yes">_Boss Rush</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_boss_rush_checkbutton_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkButtonBox" id="game_buttonbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="layout_style">start</property> + <child> + <object class="GtkButton" id="game_back_button"> + <property name="label" translatable="yes">Back</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_game_back_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="play_button"> + <property name="label" translatable="yes">Play</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_play_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + </child> + </object> + <object class="GtkWindow" id="options_window"> + <property name="can_focus">False</property> + <property name="title" translatable="yes">PyTouhou</property> + <property name="resizable">False</property> + <property name="has_resize_grip">False</property> + <signal name="destroy" handler="on_quit" swapped="no"/> + <signal name="key-press-event" handler="on_options_window_key_press_event" swapped="no"/> + <child> + <object class="GtkBox" id="options_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox" id="path_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="path_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Game Directory</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkFileChooserButton" id="path_filechooserbutton"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="action">select-folder</property> + <property name="title" translatable="yes">Game Directory</property> + <signal name="file-set" handler="on_path_filechooserbutton_file_set" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="backend_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="backend_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Backend</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="backend_comboboxtext"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">0</property> + <items> + <item id="opengl" translatable="yes">OpenGL</item> + <item id="sdl" translatable="yes">SDL</item> + <item id="opengl sdl" translatable="yes">OpenGL then SDL</item> + <item id="sdl opengl" translatable="yes">SDL then OpenGL</item> + </items> + <signal name="changed" handler="on_backend_comboboxtext_changed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="opengl_grid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="flavor_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Flavor</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="flavor_comboboxtext"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active_id">compatibility</property> + <items> + <item id="legacy" translatable="yes">Legacy (1.1+)</item> + <item id="compatibility" translatable="yes">Compatibility (2.1+)</item> + <item id="core" translatable="yes">Core (3.0+)</item> + <item id="es" translatable="yes">GLES (2.0+)</item> + </items> + <signal name="changed" handler="on_flavor_comboboxtext_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="version_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Version</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="double_buffer_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Double Buffer</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="double_buffer_checkbutton"> + <property name="label" translatable="yes">Enabled</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="xalign">0</property> + <property name="inconsistent">True</property> + <property name="draw_indicator">True</property> + <signal name="clicked" handler="on_double_buffer_checkbutton_clicked" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="version_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="max_length">3</property> + <property name="text" translatable="yes">2.1</property> + <signal name="changed" handler="on_version_entry_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="sdl_grid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="fps_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="fps_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">FPS Limit</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="fps_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">-1</property> + <property name="input_purpose">number</property> + <signal name="changed" handler="on_fps_entry_changed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="no_background_checkbutton"> + <property name="label" translatable="yes">Enable _Background</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_no_background_checkbutton_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="no_particles_checkbutton"> + <property name="label" translatable="yes">Enable _Particles</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_no_particles_checkbutton_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="no_sound_checkbutton"> + <property name="label" translatable="yes">Enable _Sound</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_no_sound_checkbutton_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + <child> + <object class="GtkButton" id="options_back_button"> + <property name="label" translatable="yes">Back</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_options_back_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">6</property> + </packing> + </child> + </object> + </child> + </object> + <object class="GtkFileFilter" id="replay_filefilter"> + <patterns> + <pattern>*.rpy</pattern> + </patterns> + </object> + <object class="GtkFileChooserDialog" id="replay_filechooserdialog"> + <property name="can_focus">False</property> + <property name="title" translatable="yes">PyTouhou</property> + <property name="type_hint">dialog</property> + <property name="create_folders">False</property> + <property name="filter">replay_filefilter</property> + <signal name="close" handler="on_replay_filechooserdialog_close" swapped="no"/> + <signal name="destroy" handler="on_quit" swapped="no"/> + <signal name="file-activated" handler="on_replay_filechooserdialog_file_activated" swapped="no"/> + <signal name="key-press-event" handler="on_replay_filechooserdialog_key_press_event" swapped="no"/> + <signal name="selection-changed" handler="on_replay_filechooserdialog_selection_changed" swapped="no"/> + <child internal-child="vbox"> + <object class="GtkBox" id="filechooserdialog-vbox1"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="filechooserdialog-action_area1"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="replay_cancel_button"> + <property name="label">gtk-cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + <property name="always_show_image">True</property> + <signal name="clicked" handler="on_replay_cancel_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="replay_open_button"> + <property name="label">gtk-open</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + <property name="always_show_image">True</property> + <signal name="clicked" handler="on_replay_open_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + </object> + <object class="GtkWindow" id="start_window"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="title" translatable="yes">PyTouhou</property> + <property name="resizable">False</property> + <property name="has_resize_grip">False</property> + <signal name="destroy" handler="on_quit" swapped="no"/> + <signal name="key-press-event" handler="on_start_window_key_press_event" swapped="no"/> + <child> + <object class="GtkButtonBox" id="start_buttonbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="layout_style">start</property> + <child> + <object class="GtkButton" id="start_button"> + <property name="label" translatable="yes">Start</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_start_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="extra_start_button"> + <property name="label" translatable="yes">Extra Start</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_extra_start_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="practice_start_button"> + <property name="label" translatable="yes">Practice Start</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_practice_start_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="netplay_start_button"> + <property name="label" translatable="yes">Netplay Start</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_netplay_start_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkButton" id="replay_button"> + <property name="label" translatable="yes">Replay</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_replay_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkButton" id="score_button"> + <property name="label" translatable="yes">Score</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_score_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + <child> + <object class="GtkButton" id="music_room_button"> + <property name="label" translatable="yes">Music Room</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_music_room_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">6</property> + </packing> + </child> + <child> + <object class="GtkButton" id="options_button"> + <property name="label" translatable="yes">Options</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_options_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">7</property> + </packing> + </child> + <child> + <object class="GtkButton" id="quit_button"> + <property name="label" translatable="yes">Quit</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_quit" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">8</property> + </packing> + </child> + </object> + </child> + </object> +</interface>
new file mode 100644 --- /dev/null +++ b/pytouhou/menu.py @@ -0,0 +1,305 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2014 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +from pytouhou.utils.helpers import get_logger +logger = get_logger(__name__) + +try: + from gi.repository import Gtk, Gdk +except ImportError: + logger.error('GTK+ unavailable, disabling the GUI menu.') + raise + +import sys +import re + +GL_VERSION_REGEX = re.compile(r'^\d\.\d$') + + +class Handler(object): + def __init__(self, config, args): + self.config = config + self.args = args + + def init_gtk(self, builder): + self.start_window = builder.get_object('start_window') + self.game_window = builder.get_object('game_window') + self.options_window = builder.get_object('options_window') + + self.replay_filechooserdialog = builder.get_object('replay_filechooserdialog') + + # Game widgets + self.difficulty_box = builder.get_object('difficulty_box') + self.character_box = builder.get_object('character_box') + self.stage_box = builder.get_object('stage_box') + self.boss_rush_checkbutton = builder.get_object('boss_rush_checkbutton') + + self.difficulty_comboboxtext = builder.get_object('difficulty_comboboxtext') + self.character_comboboxtext = builder.get_object('character_comboboxtext') + self.stage_comboboxtext = builder.get_object('stage_comboboxtext') + + # Options widgets + self.path_filechooserbutton = builder.get_object('path_filechooserbutton') + self.backend_comboboxtext = builder.get_object('backend_comboboxtext') + + # OpenGL backend + self.opengl_grid = builder.get_object('opengl_grid') + self.flavor_comboboxtext = builder.get_object('flavor_comboboxtext') + self.version_entry = builder.get_object('version_entry') + self.double_buffer_checkbutton = builder.get_object('double_buffer_checkbutton') + + # SDL backend + self.sdl_grid = builder.get_object('sdl_grid') + + self.fps_entry = builder.get_object('fps_entry') + self.no_background_checkbutton = builder.get_object('no_background_checkbutton') + self.no_particles_checkbutton = builder.get_object('no_particles_checkbutton') + self.no_sound_checkbutton = builder.get_object('no_sound_checkbutton') + + self.difficulty_comboboxtext.set_active_id(str(self.args.rank)) + self.character_comboboxtext.set_active_id(str(self.args.character)) + self.stage_comboboxtext.set_active_id(str(self.args.stage)) + self.boss_rush_checkbutton.set_active(self.args.boss_rush) + + self.path_filechooserbutton.set_filename(self.args.path) + self.backend_comboboxtext.set_active_id(' '.join(self.args.backend)) + + self.flavor_comboboxtext.set_active_id(self.args.gl_flavor) + self.version_entry.set_text(str(self.args.gl_version)) + if self.args.double_buffer is None: + self.double_buffer_checkbutton.set_inconsistent(True) + else: + self.double_buffer_checkbutton.set_inconsistent(False) + self.double_buffer_checkbutton.set_active(self.args.double_buffer) + + self.fps_entry.set_text(str(self.args.fps_limit)) + self.no_background_checkbutton.set_active(self.args.no_background) + self.no_particles_checkbutton.set_active(self.args.no_particles) + self.no_sound_checkbutton.set_active(self.args.no_sound) + + def hide_and_play(self, window): + window.hide() + Gtk.main_quit() + print('Play!') + + def on_quit(self, *args): + Gtk.main_quit(*args) + sys.exit(0) + + + # Main menu + + def on_start_window_key_press_event(self, window, event_key): + if (event_key.keyval == Gdk.KEY_Escape or + event_key.state == Gdk.ModifierType.CONTROL_MASK and event_key.keyval == Gdk.KEY_q): + self.on_quit() + + def on_start_button_clicked(self, _): + self.difficulty_box.show() + self.character_box.show() + self.stage_box.hide() + + self.stage_comboboxtext.set_active_id(None) + self.args.stage = None + + self.start_window.hide() + self.game_window.show() + + def on_extra_start_button_clicked(self, _): + self.difficulty_box.hide() + self.character_box.show() + self.stage_box.hide() + + self.difficulty_comboboxtext.set_active_id('4') + self.stage_comboboxtext.set_active_id('7') + + self.start_window.hide() + self.game_window.show() + + def on_practice_start_button_clicked(self, _): + self.difficulty_box.show() + self.character_box.show() + self.stage_box.show() + + self.start_window.hide() + self.game_window.show() + + def on_options_button_clicked(self, _): + self.start_window.hide() + self.options_window.show() + + def on_replay_button_clicked(self, _): + self.start_window.hide() + self.replay_filechooserdialog.show() + + def on_inactive_button_clicked(self, _): + raise NotImplementedError('Menu not implemented') + + on_netplay_start_button_clicked = on_inactive_button_clicked + on_score_button_clicked = on_inactive_button_clicked + on_music_room_button_clicked = on_inactive_button_clicked + + + # Game menu + + def on_game_back_button_clicked(self, _): + self.game_window.hide() + self.start_window.show() + + def on_play_button_clicked(self, _): + self.hide_and_play(self.game_window) + + def on_game_window_key_press_event(self, window, event_key): + if event_key.keyval == Gdk.KEY_Escape: + self.game_window.hide() + self.start_window.show() + elif event_key.state == Gdk.ModifierType.CONTROL_MASK and event_key.keyval == Gdk.KEY_q: + self.on_quit() + + def on_difficulty_comboboxtext_changed(self, item): + active = item.get_active_id() + difficulty = int(active) + self.config.set('rank', active if difficulty < 4 else None) + self.args.rank = difficulty + + def on_character_comboboxtext_changed(self, item): + character = int(item.get_active_id()) + self.config.set('character', character) + self.args.character = character + + def on_stage_comboboxtext_changed(self, item): + stage = item.get_active_id() + self.args.stage = int(stage) if stage is not None else None + + def on_boss_rush_checkbutton_toggled(self, boss_rush_checkbutton): + active = boss_rush_checkbutton.get_active() + self.config.set('boss-rush', active) + self.args.boss_rush = active + + + # Replay dialog + + def on_replay_filechooserdialog_close(self, _): + self.replay_filechooserdialog.hide() + self.start_window.show() + + on_replay_cancel_button_clicked = on_replay_filechooserdialog_close + + def on_replay_open_button_clicked(self, button): + try: + open(self.args.replay, 'rb').close() + except (IOError, TypeError): + return + self.hide_and_play(self.replay_filechooserdialog) + + def on_replay_filechooserdialog_selection_changed(self, dialog): + self.args.replay = dialog.get_filename() + + def on_replay_filechooserdialog_file_activated(self, window): + self.args.replay = window.get_filename() + self.hide_and_play(self.replay_filechooserdialog) + + def on_replay_filechooserdialog_key_press_event(self, window, event_key): + if event_key.keyval == Gdk.KEY_Escape: + self.replay_filechooserdialog.hide() + self.start_window.show() + elif event_key.state == Gdk.ModifierType.CONTROL_MASK and event_key.keyval == Gdk.KEY_q: + self.on_quit() + + + # Options menu + + def on_options_back_button_clicked(self, _): + self.options_window.hide() + self.start_window.show() + + def on_options_window_key_press_event(self, window, event_key): + if event_key.keyval == Gdk.KEY_Escape: + self.options_window.hide() + self.start_window.show() + elif event_key.state == Gdk.ModifierType.CONTROL_MASK and event_key.keyval == Gdk.KEY_q: + self.on_quit() + + def on_path_filechooserbutton_file_set(self, path_filechooserbutton): + path = path_filechooserbutton.get_filename() + self.config.set('path', path) + + def on_backend_comboboxtext_changed(self, backend_comboboxtext): + active = backend_comboboxtext.get_active_id() + self.config.set('backend', active) + backends = active.split() + new_grids = [getattr(self, backend + '_grid') for backend in backends] + for grid in [self.opengl_grid, self.sdl_grid]: + if grid not in new_grids: + grid.hide() + else: + grid.show() + + def on_flavor_comboboxtext_changed(self, flavor_comboboxtext): + active = flavor_comboboxtext.get_active_id() + self.config.set('gl-flavor', active) + + def on_version_entry_changed(self, version_entry): + text = version_entry.get_text() + if not GL_VERSION_REGEX.match(text): + raise ValueError('ā%sā is not <digit>.<digit>' % text) + self.config.set('gl-version', text) + + def on_double_buffer_checkbutton_clicked(self, double_buffer_checkbutton): + inconsistent = double_buffer_checkbutton.get_inconsistent() + active = double_buffer_checkbutton.get_active() + if inconsistent: + active = False + inconsistent = False + elif active: + active = True + else: + inconsistent = True + double_buffer_checkbutton.set_active(active) + double_buffer_checkbutton.set_inconsistent(inconsistent) + self.config.set('double-buffer', None if inconsistent else active) + + def on_fps_entry_changed(self, fps_entry): + text = fps_entry.get_text() + try: + int(text) + except ValueError: + raise ValueError('ā%sā is not integer' % text) + else: + self.config.set('fps-limit', text) + + def on_no_background_checkbutton_toggled(self, checkbutton): + active = checkbutton.get_active() + self.config.set('no-background', not active) + + def on_no_particles_checkbutton_toggled(self, checkbutton): + active = checkbutton.get_active() + self.config.set('no-particles', active) + + def on_no_sound_checkbutton_toggled(self, checkbutton): + active = checkbutton.get_active() + self.config.set('no-sound', active) + + +def menu(config, args): + assert Gtk + handler = Handler(config, args) + + builder = Gtk.Builder() + builder.add_from_file('data/menu.glade') + builder.connect_signals(handler) + + handler.init_gtk(builder) + + Gtk.main()
--- a/pytouhou/options.py +++ b/pytouhou/options.py @@ -15,7 +15,7 @@ import os from ConfigParser import RawConfigParser, NoOptionError -from pytouhou.utils.xdg import load_config_paths +from pytouhou.utils.xdg import load_config_paths, save_config_path class Options(object): @@ -23,6 +23,7 @@ class Options(object): load_paths = list(reversed([os.path.join(directory, '%s.cfg' % name) for directory in load_config_paths(name)])) + self.save_path = os.path.join(save_config_path(name), '%s.cfg' % name) self.config = RawConfigParser(defaults) self.paths = self.config.read(load_paths) @@ -34,6 +35,18 @@ class Options(object): except NoOptionError: return None + def set(self, option, value): + if value is not None: + self.config.set(self.section, option, value) + else: + self.config.remove_option(self.section, option) + + defaults = self.config._defaults + self.config._defaults = None + with open(self.save_path, 'w') as save_file: + self.config.write(save_file) + self.config._defaults = defaults + def patch_argument_parser(): from argparse import ArgumentParser, _ActionsContainer @@ -105,6 +118,7 @@ def parse_arguments(defaults): parser.add_argument('-p', '--path', metavar='DIRECTORY', help='Game directory path.') parser.add_argument('--debug', action='store_true', help='Set unlimited continues, and perhaps other debug features.') parser.add_argument('--verbosity', metavar='VERBOSITY', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], help='Select the wanted logging level.') + parser.add_argument('--no-menu', action='store_true', help='Disable the menu.') game_group = parser.add_argument_group('Game options') game_group.add_argument('-s', '--stage', metavar='STAGE', type=int, help='Stage, 1 to 7 (Extra), nothing means story mode.')
--- a/scripts/pytouhou +++ b/scripts/pytouhou @@ -48,6 +48,10 @@ logger.root.name = 'pytouhou' logger.info('Configuration loaded from: %s', ', '.join(options.paths)) +if not args.no_menu: + from pytouhou.menu import menu + menu(options, args) + if args.game == 'EoSD': from pytouhou.games.eosd import EoSDCommon as Common, EoSDGame as Game