/* * preferences.cc - preferences related code for Bombermaze * written by Sydney Tang * * 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; either version 2 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more details see the file COPYING. */ #include #include #include #include #include #include "preferences.hh" #include "ui.hh" #include "input.hh" #include "game.hh" #include #include #include #include #include #ifdef ENABLE_NLS #include #include #endif #ifndef PACKAGE_DATADIR #define PACKAGE_DATADIR "." #endif ////////////////////////////////////////////////////////////////////////////// const int MAP_PREVIEW_WIDTH = 380; const int MAP_PREVIEW_HEIGHT = 320; const int THEME_PREVIEW_WIDTH = 400; const int THEME_PREVIEW_HEIGHT = 150; const gchar *GENERAL_CONFIGPATH_SECTION = "/"PACKAGE"/General/"; const gchar *KEYMAP_CONFIGPATH_SECTION = "/"PACKAGE"/KeyMap/"; const gchar *CONFIGKEY_PLAYER_ACTION [ Player::MAX_NUMBER_OF_LOCAL_PLAYERS ][Player::NUMBER_OF_PLAYER_ACTIONS] = { { "1North", "1East", "1South", "1West", "1Bomb", "1Special" }, { "2North", "2East", "2South", "2West", "2Bomb", "2Special" }, { "3North", "3East", "3South", "3West", "3Bomb", "3Special" }, { "4North", "4East", "4South", "4West", "4Bomb", "4Special" }, }; const gchar *DEFAULT_KEYVAL_NAME_PLAYER_ACTION [ Player::MAX_NUMBER_OF_LOCAL_PLAYERS ][ Player::NUMBER_OF_PLAYER_ACTIONS ] = { // player 1 { "Up", "Right", "Down", "Left", "Control_R", "Shift_R" }, // player 2 { "w", "d", "s", "a", "q", "1" }, // player 3 { "KP_8", "KP_6", "KP_2", "KP_4", "KP_Enter", "KP_Add" }, // player 4 { "i", "l", "k", "j", "h", "y" } }; const gchar *CONFIGKEY_PLAYER_AUTOFIRE[Player::MAX_NUMBER_OF_LOCAL_PLAYERS] = { "1AutoFire", "2AutoFire", "3AutoFire", "4AutoFire" }; const gchar *DEFAULT_PLAYER_AUTOFIRE = "false"; const bool DEFAULT_PLAYER_AUTOFIRE_VALUE = false; const gchar *CONFIGKEY_START_N_PLAYER_GAME[Player::MAX_NUMBER_OF_PLAYERS] = { "Start1PlayerGame", "Start2PlayerGame", "Start3PlayerGame", "Start4PlayerGame" }; const gchar *DEFAULT_KEYVAL_NAME_START_N_PLAYER_GAME [Player::MAX_NUMBER_OF_PLAYERS] = { "F1", "F2", "F3", "F4" }; const gchar *CONFIGKEY_QUIT_GAME = "QuitGame"; const gchar *DEFAULT_KEYVAL_NAME_QUIT_GAME = "Escape"; const gchar *CONFIGKEY_PAUSE_GAME = "PauseGame"; const gchar *DEFAULT_KEYVAL_NAME_PAUSE_GAME = "Pause"; const gchar *CONFIGKEY_CONTINUE_GAME = "ContinueGame"; const gchar *DEFAULT_KEYVAL_NAME_CONTINUE_GAME = "space"; const gchar *CONFIGKEY_ENABLE_CONTINUE_BUTTON = "EnableContinueButton"; const gchar *DEFAULT_ENABLE_CONTINUE_BUTTON = "true"; const bool DEFAULT_ENABLE_CONTINUE_BUTTON_VALUE = true; const gchar *CONFIGKEY_ENABLE_INTER_ROUND_STATUS = "EnableInterRoundStatus"; const gchar *DEFAULT_ENABLE_INTER_ROUND_STATUS = "true"; const bool DEFAULT_ENABLE_INTER_ROUND_STATUS_VALUE = true; const gchar *CONFIGKEY_CASE_SENSITIVE = "CaseSensitive"; const gchar *DEFAULT_CASE_SENSITIVE = "true"; const bool DEFAULT_CASE_SENSITIVE_VALUE = true; const gchar *CONFIGKEY_MATCH_STATUS_DELAY = "MatchStatusDelay"; const gchar *DEFAULT_MATCH_STATUS_DELAY = "0"; /* The defaults listed below should match the ones given map.h and game.h */ const gchar *CONFIGKEY_MAP_FILE = "MapFile"; const gchar *DEFAULT_MAP_FILE = "15x13_random"; const gchar *CONFIGKEY_WALL_PERIMETER = "WallPerimeter"; const gchar *DEFAULT_WALL_PERIMETER = "true"; const bool DEFAULT_WALL_PERIMETER_VALUE = true; const gchar *CONFIGKEY_WALL_PERIMETER_TOP_ONLY = "WallPerimeterTopOnly"; const gchar *DEFAULT_WALL_PERIMETER_TOP_ONLY = "true"; const bool DEFAULT_WALL_PERIMETER_TOP_ONLY_VALUE = true; const gchar *CONFIGKEY_WINS_PER_MATCH = "WinsPerMatch"; const gchar *DEFAULT_WINS_PER_MATCH = "2"; const gchar *CONFIGKEY_THEME = "Theme"; const gchar *DEFAULT_THEME = "default"; const gchar *CONFIGKEY_TIMEOUT_INTERVAL = "TimeoutInterval"; const gchar *DEFAULT_TIMEOUT_INTERVAL = "10"; const gchar *CONFIGKEY_SQUARE_STEPS = "StepsToMiddleOfSquare"; const gchar *DEFAULT_SQUARE_STEPS = "2"; const gchar *CONFIGKEY_PLAYER_MOVE_DELAY = "InitialPlayerMoveDelay"; const gchar *DEFAULT_PLAYER_MOVE_DELAY = "3"; const gchar *CONFIGKEY_INITIAL_BOMBS = "InitialBombs"; const gchar *DEFAULT_INITIAL_BOMBS = "1"; const gchar *CONFIGKEY_INITIAL_RANGE = "InitialRange"; const gchar *DEFAULT_INITIAL_RANGE = "2"; const gchar *CONFIGKEY_EXPLODE_DELAY = "ExplodeDelay"; const gchar *DEFAULT_EXPLODE_DELAY = "20"; const gchar *CONFIGKEY_CHAIN_DELAY = "BombChainReactionDelay"; const gchar *DEFAULT_CHAIN_DELAY = "1"; const gchar *CONFIGKEY_FLAME_DURATION = "FlameDuration"; const gchar *DEFAULT_FLAME_DURATION = "25"; const gchar *CONFIGKEY_BRICK_SHATTER_DELAY = "BrickShatterDelay"; const gchar *DEFAULT_BRICK_SHATTER_DELAY = "18"; const gchar *CONFIGKEY_POWERUP_SHATTER_DELAY = "PowerUpShatterDelay"; const gchar *DEFAULT_POWERUP_SHATTER_DELAY = "18"; const gchar *CONFIGKEY_POWERUP_PROBABILITY = "PowerUpProbability"; const gchar *DEFAULT_POWERUP_PROBABILITY = "30"; const gchar *CONFIGKEY_INDIVIDUAL_POWERUP_PROBABILITY [PowerUp::NUMBER_OF_CREATABLE_POWERUPS] = { "ProbabilityExtraBomb", "ProbabilityExtraRange", "ProbabilityTriggerBomb", "ProbabilityKickBomb", "ProbabilityExtraSpeed", }; const gchar *DEFAULT_INDIVIDUAL_POWERUP_PROBABILITY [PowerUp::NUMBER_OF_CREATABLE_POWERUPS] = { "30", "25", "15", "15", "15" }; ////////////////////////////////////////////////////////////////////////////// static GtkWidget *PropertyBox = NULL; static GtkWidget *PauseEntry = NULL; static GtkWidget *QuitEntry = NULL; static GtkWidget *ContinueEntry = NULL; static GtkWidget *StartNewGameEntry[Player::MAX_NUMBER_OF_PLAYERS]; static GtkWidget *ContinueButtonEntry = NULL; static GtkWidget *InterRoundMatchStatusEntry = NULL; static GtkWidget *CaseSensitiveEntry = NULL; static GtkWidget *ThemesMenu = NULL; static GtkWidget *MapsMenu = NULL; static GtkWidget *ThemesOptionMenu = NULL; static GtkWidget *MapsOptionMenu = NULL; static GtkWidget *ThemesMenuDefaultItem = NULL; static GtkWidget *MapsMenuDefaultItem = NULL; static int ThemesMenuDefaultIndex = -1; static int MapsMenuDefaultIndex = -1; static GSList *ThemesList = NULL; static GSList *MapsList = NULL; static char *ThemeSelection = NULL; static char *MapfileSelection = NULL; static GtkWidget *WallEntry = NULL; static GtkWidget *WallTopEntry = NULL; static GtkWidget *PlayerActionEntry [ Player::MAX_NUMBER_OF_LOCAL_PLAYERS ][Player::NUMBER_OF_PLAYER_ACTIONS]; static GtkWidget *PlayerAutoFireEntry[Player::MAX_NUMBER_OF_LOCAL_PLAYERS]; static GtkWidget *BombsEntry = NULL; static GtkWidget *RangeEntry = NULL; static GtkWidget *PowerupEntry = NULL; static GtkWidget *ExplodeEntry = NULL; static GtkWidget *ChainEntry = NULL; static GtkWidget *FlameEntry = NULL; static GtkWidget *BrickShatterEntry = NULL; static GtkWidget *PowerUpShatterEntry = NULL; static GtkWidget *PowerUpProbabilityEntry [PowerUp::NUMBER_OF_CREATABLE_POWERUPS] = {NULL, NULL, NULL, NULL, NULL}; static bool PowerUpProbabilityScaleRebalanceInProgress = false; static GtkWidget *WinsEntry = NULL; static GtkWidget *TimeoutEntry = NULL; static GtkWidget *SquareStepEntry = NULL; static GtkWidget *PlayerMoveEntry = NULL; static Preferences preferences = { // max min inc val { 100, 1, 5, 20 }, // TimeoutInterval { 60, 0, 1, 2 }, // StepsToMiddleOfSquare { 9, 1, 1, 3 }, // InitialPlayerMoveDelay { 9, 1, 1, 1 }, // InitialMaxBombsPerPlayer { 9, 1, 1, 2 }, // InitialPlayerBombBlastRadius { 100, 0, 10, 30 }, // ProbabilityOfPowerup { 600, 1, 1, 20 }, // BombExplodeDelay { 10, 0, 1, 2 }, // BombChainReactionDelay; { 100, 1, 5, 25 }, // FlameDuration; { 54, 3, 3, 18 }, // BrickShatterFrameDuration; { 54, 3, 3, 18 }, // PowerUpShatterFrameDuration; { // PowerUpProbability // The max listed below is given as 104 instead of 100 so that the // GtkHScale widgets can be readily slid to the 100 mark. Otherwise, // with a max of 100, you have to do all kinds of little adjustments // in order to get any of the power-up scales up to 100. It's just // the way GtkHScale works. // So long as the sum of the power-up probabilities starts out at // exactly 100, we need not worry about ending up with a scale value // that exceeds 100, because powerup_scale_rebalance() will ensure // that the sum of the power-up scales remains constant. {104, 0, 4, 30 }, // POWERUP_EXTRA_BOMB {104, 0, 4, 25 }, // POWERUP_EXTRA_RANGE {104, 0, 4, 15 }, // POWERUP_TRIGGER_BOMB {104, 0, 4, 15 }, // POWERUP_KICK_BOMB {104, 0, 4, 15 }, // POWERUP_EXTRA_SPEED }, { 10, 1, 1, 2 }, // WinsPerMatch { 999, 0, 1, 0 }, // MatchStatusDelay NULL, // MapFile NULL, // Theme false, // ShowWallPerimeter true, // ShowWallPerimeterTopOnly true, // EnableContinueButton true, // EnableInterRoundMatchStatus true, // CaseSensitive }; static KeyMap KeyPreferences; static KeyMap TempKeyPreferences; static int TempPowerUpProbability[PowerUp::NUMBER_OF_CREATABLE_POWERUPS]; static GameMap PreviewMap; static Player MapPreviewPlayers[Player::MAX_NUMBER_OF_PLAYERS]; static GtkWidget *MapPreviewArea = NULL; static GdkPixmap *MapPreviewPixmap = NULL; static UIDisplayInterface MapPreviewDisplay = { NULL, NULL }; static GtkWidget *ThemePreviewPlaceHolder = NULL; static GtkWidget *ThemePreviewArea = NULL; static GdkPixmap *ThemePreviewPixmap = NULL; static UIDisplayInterface ThemePreviewDisplay = { NULL, NULL }; static GtkWidget *ThemePreviewText = NULL; ////////////////////////////////////////////////////////////////////////////// static bool preferences_check_if_file_exists(const char *filename); static bool preferences_initialize_ui(void); static bool preferences_initialize_theme(void); static void preferences_set_theme(char *themedir); static void preferences_apply_theme(void); static void preferences_default_theme(void); static bool preferences_initialize_map(void); static void preferences_set_current_mapfile(char *mapfile); static void preferences_default_map(void); static void preferences_default_general(void); static bool preferences_initialize_keys(void); static void preferences_default_keys(GtkWidget *widget, int player_index); static void preferences_get_config_keyval( guint &keyval, const gchar *config_key, const gchar *default_val ); static void preferences_save_config_keyval( const guint keyval, const gchar *config_key ); static bool preferences_initialize_numeric_parameters(void); static void preferences_apply_numeric_parameters(void); static bool preferences_initialize_animation_parameters(void); static void preferences_apply_animation_parameters(void); static void preferences_default_numeric(void); static void preferences_default_powerup(void); static void preferences_default_animation(void); static void preferences_get_numeric_parameter( NumberValue &number, const gchar *config_key, const gchar *default_val ); static void preferences_save_numeric_parameter( int value, const gchar *config_key ); static void preferences_save_settings(void); static void apply(GtkWidget *widget, gint page, gpointer data); static void general_keypress( GtkWidget *widget, GdkEventKey* event, gpointer data ); static void player_keypress( GtkWidget *widget, GdkEventKey* event, gpointer data ); static void map_selection (GtkWidget *item, gpointer user_data); static void map_preview_update(const char *map_path); static void theme_selection (GtkWidget *item, gpointer user_data); static void theme_preview_update(const char *theme_path); static void map_preview_update_initialize_players(GameMap *maze, Player *p); static void check_button_click(GtkWidget *widget, gpointer data); static void spinner_keypress( GtkWidget *widget, GdkEventKey *event, gpointer data ); static void spinner_click(GtkWidget *widget, gpointer data); static void powerup_scale_value_changed(GtkWidget *widget, gpointer user_data); static void powerup_scale_rebalance(int index); static int powerup_scale_adjust_all_but_one( int index, int starting_index, int scale[PowerUp::NUMBER_OF_CREATABLE_POWERUPS], int total_adjustment_required); static void preferences_help( GnomePropertyBox *property_box, gint page_num, gpointer user_data ); static void preferences_create_dialog(void); static void preferences_set_standard_table_layout(GtkWidget *table); static void append_page_general(GtkWidget *PropertyBox); static void append_page_map(GtkWidget *PropertyBox); static void append_page_theme(GtkWidget *PropertyBox); static void append_page_players(GtkWidget *PropertyBox); static void append_page_numeric(GtkWidget *PropertyBox); static void append_page_powerups(GtkWidget *PropertyBox); static void append_page_animation(GtkWidget *PropertyBox); static void build_frame_control_game(GtkWidget **frame); static void build_frame_start_game(GtkWidget **frame); static void build_frame_match(GtkWidget **frame); static void build_frame_map(GtkWidget **frame); static void build_frame_movement(GtkWidget **frame, int i); static void build_frame_action(GtkWidget **frame, int i); static void build_frame_numeric(GtkWidget **frame); static void build_frame_powerups(GtkWidget **frame); static void build_frame_animation(GtkWidget **frame); static void build_file_list_from_directory( GSList **file_list, char *dir_name ); static void prepend_directory_listing_to_file_list( GSList **file_list, char *dir_path ); static void deallocate_directory_listing(GSList **file_list); static void preferences_add_files_to_menu( GtkWidget *option_menu, GtkWidget **menu, GtkWidget **default_menu_item, void (*h)(GtkWidget *w, void *d), GSList *file_list, const char *selected_item, const char *default_item, int &default_item_index ); static void create_general_entry( char *entry_name, GtkWidget **label, GtkWidget **entry, guint *keyval ); static void create_player_entry( char *entry_name, GtkWidget **label, GtkWidget **entry, int PlayerIndex, Player::PlayerAction action ); static void create_numeric_spinner( char *entry_name, GtkWidget **label, GtkWidget **entry, NumberValue *number ); static void create_numeric_powerup_scale( char *entry_name, GtkWidget **label, GtkWidget **entry, NumberValue *number, PowerUp::PowerUpType index ); ////////////////////////////////////////////////////////////////////////////// bool preferences_initialize(void) { if (preferences_initialize_ui() == false) return false; if (preferences_initialize_theme() == false) return false; if (preferences_initialize_keys() == false) return false; if (preferences_initialize_map() == false) return false; if (preferences_initialize_numeric_parameters() == false) return false; if (preferences_initialize_animation_parameters() == false) return false; return true; } void preferences_uninitialize(void) { g_hash_table_destroy ( KeyPreferences.LookupTable ); if (preferences.MapFile != NULL) g_free(preferences.MapFile); if (preferences.Theme != NULL) g_free(preferences.Theme); if (MapPreviewPixmap != NULL) gdk_pixmap_unref(MapPreviewPixmap); if (ThemePreviewPixmap != NULL) gdk_pixmap_unref(ThemePreviewPixmap); deallocate_directory_listing(&ThemesList); deallocate_directory_listing(&MapsList); } void preferences_show_dialog(void) { TempKeyPreferences = KeyPreferences; if (PropertyBox == NULL) { preferences_create_dialog(); } else { } } ////////////////////////////////////////////////////////////////////////////// char *preferences_get_data_file(char *file) { char *desiredfile = g_strconcat(PACKAGE, PATH_SEP_STR, file, NULL); char *actualfile = gnome_datadir_file(desiredfile); g_free(desiredfile); desiredfile = NULL; if (actualfile == NULL) { actualfile = g_strconcat(PACKAGE_DATADIR, PATH_SEP_STR, file, NULL); } return actualfile; } bool preferences_check_if_file_exists(const char *filename) { FILE *file = fopen(filename, "r"); if (file != NULL) { fclose(file); return true; } return false; } ////////////////////////////////////////////////////////////////////////////// bool preferences_initialize_ui(void) { char *config_path = NULL; config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_ENABLE_CONTINUE_BUTTON, "=", DEFAULT_ENABLE_CONTINUE_BUTTON, NULL); preferences.EnableContinueButton = gnome_config_get_bool (config_path); g_free (config_path); config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_ENABLE_INTER_ROUND_STATUS, "=", DEFAULT_ENABLE_INTER_ROUND_STATUS, NULL); preferences.EnableInterRoundMatchStatus = gnome_config_get_bool(config_path); g_free (config_path); config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_CASE_SENSITIVE, "=", DEFAULT_CASE_SENSITIVE, NULL); preferences.CaseSensitive = gnome_config_get_bool (config_path); g_free (config_path); preferences_get_numeric_parameter (preferences.MatchStatusDelay, CONFIGKEY_MATCH_STATUS_DELAY, DEFAULT_MATCH_STATUS_DELAY); return true; } bool preferences_is_continue_button_enabled(void) { return preferences.EnableContinueButton; } bool preferences_is_inter_round_status_enabled(void) { return preferences.EnableInterRoundMatchStatus; } bool preferences_case_sensitive(void) { return preferences.CaseSensitive; } ////////////////////////////////////////////////////////////////////////////// bool preferences_initialize_theme(void) { gchar *theme_dir; gchar *config_path; config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_THEME, "=", DEFAULT_THEME, NULL); theme_dir = gnome_config_get_string (config_path); g_free(config_path); config_path = NULL; if (true == preferences_check_if_file_exists (theme_dir)) { preferences_set_theme(theme_dir); } else { char *desiredfile = g_strconcat("themes", PATH_SEP_STR, theme_dir, NULL); g_free(theme_dir); theme_dir = NULL; theme_dir = preferences_get_data_file(desiredfile); g_free(desiredfile); desiredfile = NULL; preferences_set_theme(theme_dir); } g_free(theme_dir); preferences_apply_theme(); build_file_list_from_directory (&ThemesList, "themes"); return true; } void preferences_set_theme(char *themedir) { if (preferences.Theme != NULL) g_free(preferences.Theme); preferences.Theme = g_strdup(themedir); } void preferences_apply_theme(void) { if (false == ui_set_theme (preferences.Theme)) { char *message = _("Error while loading theme.\n" "Please choose another one."); if (PropertyBox != NULL) { gnome_warning_dialog_parented (message, GTK_WINDOW(PropertyBox)); } else { gnome_warning_dialog (message); } } } void preferences_default_theme(void) { if (ThemesMenuDefaultIndex >= 0) { gtk_menu_set_active (GTK_MENU(ThemesMenu), ThemesMenuDefaultIndex); gtk_menu_item_activate (GTK_MENU_ITEM(ThemesMenuDefaultItem)); gtk_widget_ref (ThemesMenu); gtk_option_menu_remove_menu (GTK_OPTION_MENU(ThemesOptionMenu)); gtk_option_menu_set_menu (GTK_OPTION_MENU(ThemesOptionMenu), ThemesMenu); gtk_widget_unref (ThemesMenu); } } ////////////////////////////////////////////////////////////////////////////// const char *preferences_get_current_mapfile(void) { return preferences.MapFile; } bool preferences_initialize_map(void) { gchar *mapfile; gchar *config_path; bool success; config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_MAP_FILE, "=", DEFAULT_MAP_FILE, NULL); mapfile = gnome_config_get_string (config_path); g_free (config_path); config_path = NULL; if (true == preferences_check_if_file_exists (mapfile)) { preferences_set_current_mapfile (mapfile); success = true; } else { char *desiredfile = g_strconcat("maps", PATH_SEP_STR, mapfile, NULL); g_free(mapfile); mapfile = NULL; mapfile = preferences_get_data_file(desiredfile); g_free(desiredfile); desiredfile = NULL; preferences_set_current_mapfile (mapfile); success = true; } g_free (mapfile); mapfile = NULL; config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_WALL_PERIMETER, "=", DEFAULT_WALL_PERIMETER, NULL); preferences.ShowWallPerimeter = gnome_config_get_bool (config_path); g_free (config_path); config_path = NULL; config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_WALL_PERIMETER_TOP_ONLY, "=", DEFAULT_WALL_PERIMETER_TOP_ONLY, NULL); preferences.ShowWallPerimeterTopOnly = gnome_config_get_bool (config_path); g_free (config_path); config_path = NULL; GameMap::set_walled_perimeter (preferences.ShowWallPerimeter, preferences.ShowWallPerimeterTopOnly); build_file_list_from_directory (&MapsList, "maps"); return success; } void preferences_set_current_mapfile(char *mapfile) { if (preferences.MapFile != NULL) g_free(preferences.MapFile); preferences.MapFile = g_strdup(mapfile); if (false == game_set_map(preferences.MapFile)) { gnome_warning_dialog_parented (_("Error while parsing map.\n" "Please choose another one."), GTK_WINDOW(PropertyBox)); } } void preferences_default_map(void) { if (MapsMenuDefaultIndex >= 0) { gtk_menu_set_active (GTK_MENU(MapsMenu), MapsMenuDefaultIndex); gtk_menu_item_activate (GTK_MENU_ITEM(MapsMenuDefaultItem)); gtk_widget_ref (MapsMenu); gtk_option_menu_remove_menu (GTK_OPTION_MENU(MapsOptionMenu)); gtk_option_menu_set_menu (GTK_OPTION_MENU(MapsOptionMenu), MapsMenu); gtk_widget_unref (MapsMenu); } gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(WallEntry), DEFAULT_WALL_PERIMETER_VALUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(WallTopEntry), DEFAULT_WALL_PERIMETER_TOP_ONLY_VALUE); } ////////////////////////////////////////////////////////////////////////////// void preferences_default_general(void) { gtk_entry_set_text (GTK_ENTRY(PauseEntry), DEFAULT_KEYVAL_NAME_PAUSE_GAME); gtk_entry_set_text (GTK_ENTRY(QuitEntry), DEFAULT_KEYVAL_NAME_QUIT_GAME); gtk_entry_set_text (GTK_ENTRY(ContinueEntry), DEFAULT_KEYVAL_NAME_CONTINUE_GAME); for (int i = 1; i < Player::MAX_NUMBER_OF_PLAYERS; i++) { gtk_entry_set_text (GTK_ENTRY(StartNewGameEntry[i]), DEFAULT_KEYVAL_NAME_START_N_PLAYER_GAME[i]); } gtk_entry_set_text (GTK_ENTRY(WinsEntry), DEFAULT_WINS_PER_MATCH); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(ContinueButtonEntry), DEFAULT_ENABLE_CONTINUE_BUTTON_VALUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(InterRoundMatchStatusEntry), DEFAULT_ENABLE_INTER_ROUND_STATUS_VALUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(CaseSensitiveEntry), DEFAULT_CASE_SENSITIVE_VALUE); gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } ////////////////////////////////////////////////////////////////////////////// const char *preferences_get_continue_key_name(void) { return gdk_keyval_name(KeyPreferences.Continue); } bool preferences_initialize_keys(void) { int i; int a; guint keyval; for (i = 0; i < Player::MAX_NUMBER_OF_LOCAL_PLAYERS; i++) { for (a = 0; a < Player::NUMBER_OF_PLAYER_ACTIONS; a++) { preferences_get_config_keyval (keyval, CONFIGKEY_PLAYER_ACTION[i][a], DEFAULT_KEYVAL_NAME_PLAYER_ACTION[i][a]); KeyPreferences.PlayerAction[i][a].PlayerIndex = i; KeyPreferences.PlayerAction[i][a].keyval = keyval; KeyPreferences.PlayerAction[i][a].ActionType = (Player::PlayerAction)a; } } KeyPreferences.rehash(); for (i = 1; i < Player::MAX_NUMBER_OF_PLAYERS; i++) { preferences_get_config_keyval (KeyPreferences.StartNPlayerGame[i], CONFIGKEY_START_N_PLAYER_GAME[i], DEFAULT_KEYVAL_NAME_START_N_PLAYER_GAME[i]); } gchar *config_path; for (i = 0; i < Player::MAX_NUMBER_OF_LOCAL_PLAYERS; i++) { config_path = g_strconcat (KEYMAP_CONFIGPATH_SECTION, CONFIGKEY_PLAYER_AUTOFIRE[i], "=", DEFAULT_PLAYER_AUTOFIRE, NULL); preferences.EnableAutoFire[i] = gnome_config_get_bool (config_path); g_free (config_path); input_set_autofire(i, preferences.EnableAutoFire[i]); } preferences_get_config_keyval (KeyPreferences.Pause, CONFIGKEY_PAUSE_GAME, DEFAULT_KEYVAL_NAME_PAUSE_GAME); preferences_get_config_keyval (KeyPreferences.Quit, CONFIGKEY_QUIT_GAME, DEFAULT_KEYVAL_NAME_QUIT_GAME); preferences_get_config_keyval (KeyPreferences.Continue, CONFIGKEY_CONTINUE_GAME, DEFAULT_KEYVAL_NAME_CONTINUE_GAME); input_set_keymap (&KeyPreferences); return true; } void preferences_default_keys(GtkWidget *widget, int player_index) { int p = player_index; for (int a = 0; a < Player::NUMBER_OF_PLAYER_ACTIONS; a++) { gtk_entry_set_text(GTK_ENTRY(PlayerActionEntry[p][a]), DEFAULT_KEYVAL_NAME_PLAYER_ACTION[p][a]); } gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(PlayerAutoFireEntry[p]), DEFAULT_PLAYER_AUTOFIRE_VALUE); gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void preferences_get_config_keyval( guint &keyval, const gchar *config_key, const gchar *default_val) { gchar *keyval_name; gchar *config_path; config_path = g_strconcat (KEYMAP_CONFIGPATH_SECTION, config_key, "=", default_val, NULL); keyval_name = gnome_config_get_string (config_path); keyval = gdk_keyval_from_name(keyval_name); g_free(keyval_name); g_free(config_path); } void preferences_save_config_keyval( const guint keyval, const gchar *config_key) { gchar *keyval_name; gchar *config_path; config_path = g_strconcat (KEYMAP_CONFIGPATH_SECTION, config_key, NULL); keyval_name = gdk_keyval_name(keyval); gnome_config_set_string (config_path, keyval_name); g_free(config_path); } ////////////////////////////////////////////////////////////////////////////// bool preferences_initialize_numeric_parameters(void) { preferences_get_numeric_parameter (preferences.WinsPerMatch, CONFIGKEY_WINS_PER_MATCH, DEFAULT_WINS_PER_MATCH); preferences_get_numeric_parameter (preferences.InitialMaxBombsPerPlayer, CONFIGKEY_INITIAL_BOMBS, DEFAULT_INITIAL_BOMBS); preferences_get_numeric_parameter (preferences.InitialPlayerBombBlastRadius, CONFIGKEY_INITIAL_RANGE, DEFAULT_INITIAL_RANGE); preferences_get_numeric_parameter (preferences.BombExplodeDelay, CONFIGKEY_EXPLODE_DELAY, DEFAULT_EXPLODE_DELAY); preferences_get_numeric_parameter (preferences.BombChainReactionDelay, CONFIGKEY_CHAIN_DELAY, DEFAULT_CHAIN_DELAY); preferences_get_numeric_parameter (preferences.FlameDuration, CONFIGKEY_FLAME_DURATION, DEFAULT_FLAME_DURATION); preferences_get_numeric_parameter (preferences.BrickShatterFrameDuration, CONFIGKEY_BRICK_SHATTER_DELAY, DEFAULT_BRICK_SHATTER_DELAY); preferences_get_numeric_parameter (preferences.PowerUpShatterFrameDuration, CONFIGKEY_POWERUP_SHATTER_DELAY, DEFAULT_POWERUP_SHATTER_DELAY); preferences_get_numeric_parameter (preferences.ProbabilityOfPowerup, CONFIGKEY_POWERUP_PROBABILITY, DEFAULT_POWERUP_PROBABILITY); int cumulative_probability = 0; for (int i = 0; i < PowerUp::NUMBER_OF_CREATABLE_POWERUPS; i++) { preferences_get_numeric_parameter (preferences.PowerUpProbability[i], CONFIGKEY_INDIVIDUAL_POWERUP_PROBABILITY[i], DEFAULT_INDIVIDUAL_POWERUP_PROBABILITY[i]); cumulative_probability += preferences.PowerUpProbability[i].value; if (cumulative_probability > 100) { preferences.PowerUpProbability[i].value -= (cumulative_probability - 100); cumulative_probability = 100; } TempPowerUpProbability[i] = preferences.PowerUpProbability[i].value; } preferences_apply_numeric_parameters(); return true; } void preferences_apply_numeric_parameters(void) { InGameState::set_wins_per_match ((unsigned)preferences.WinsPerMatch.value); Player::set_initial_max_bombs ((unsigned)preferences.InitialMaxBombsPerPlayer.value); Player::set_initial_blast_radius ((unsigned)preferences.InitialPlayerBombBlastRadius.value); Bomb::set_initial_countdown ((float)preferences.BombExplodeDelay.value*0.1); Bomb::set_chain_reaction_delay ((unsigned)preferences.BombChainReactionDelay.value); Fire::set_flame_duration ((unsigned)preferences.FlameDuration.value); Brick::set_shatter_duration ((unsigned)preferences.BrickShatterFrameDuration.value); PowerUp::set_shatter_duration ((unsigned)preferences.PowerUpShatterFrameDuration.value); PowerUp::set_probability_of_powerup ((unsigned)preferences.ProbabilityOfPowerup.value); PowerUp::set_probability_of_each_powerup_type (TempPowerUpProbability); } bool preferences_initialize_animation_parameters(void) { preferences_get_numeric_parameter (preferences.TimeoutInterval, CONFIGKEY_TIMEOUT_INTERVAL, DEFAULT_TIMEOUT_INTERVAL); preferences_get_numeric_parameter (preferences.StepsToMiddleOfSquare, CONFIGKEY_SQUARE_STEPS, DEFAULT_SQUARE_STEPS); preferences_get_numeric_parameter (preferences.InitialPlayerMoveDelay, CONFIGKEY_PLAYER_MOVE_DELAY, DEFAULT_PLAYER_MOVE_DELAY); preferences_apply_animation_parameters(); return true; } void preferences_apply_animation_parameters(void) { static bool Already_Applied_Square_Steps = false; InGameState::set_timeout_interval ((unsigned)preferences.TimeoutInterval.value); // Must reapply this after the timeout interval changes. Bomb::set_initial_countdown ((float)preferences.BombExplodeDelay.value*0.1); if (Already_Applied_Square_Steps == false) { Entity::set_steps_to_middle_of_square ((unsigned)preferences.StepsToMiddleOfSquare.value); Already_Applied_Square_Steps = true; } Player::set_initial_move_delay ((unsigned)preferences.InitialPlayerMoveDelay.value); } void preferences_default_numeric(void) { gtk_spin_button_set_value (GTK_SPIN_BUTTON(BombsEntry), atoi(DEFAULT_INITIAL_BOMBS)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(RangeEntry), atoi(DEFAULT_INITIAL_RANGE)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(ExplodeEntry), atoi(DEFAULT_EXPLODE_DELAY)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(ChainEntry), atoi(DEFAULT_CHAIN_DELAY)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(FlameEntry), atoi(DEFAULT_FLAME_DURATION)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(BrickShatterEntry), atoi(DEFAULT_BRICK_SHATTER_DELAY)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(PowerUpShatterEntry), atoi(DEFAULT_POWERUP_SHATTER_DELAY)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(PowerupEntry), atoi(DEFAULT_POWERUP_PROBABILITY)); gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void preferences_default_powerup(void) { GtkAdjustment *adjustment; for (int i = 0; i < PowerUp::NUMBER_OF_CREATABLE_POWERUPS; i++) { adjustment=gtk_range_get_adjustment(GTK_RANGE(PowerUpProbabilityEntry[i])); gtk_adjustment_set_value (adjustment, atof(DEFAULT_INDIVIDUAL_POWERUP_PROBABILITY[i])); } gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void preferences_default_animation(void) { gtk_spin_button_set_value (GTK_SPIN_BUTTON(TimeoutEntry), atoi(DEFAULT_TIMEOUT_INTERVAL)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(SquareStepEntry), atoi(DEFAULT_SQUARE_STEPS)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(PlayerMoveEntry), atoi(DEFAULT_PLAYER_MOVE_DELAY)); gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void preferences_get_numeric_parameter( NumberValue &number, const gchar *config_key, const gchar *default_val) { gchar *config_path; config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, config_key, "=", default_val, NULL); number.value = gnome_config_get_int (config_path); if (number.value > number.maximum) number.value = number.maximum; else if (number.value < number.minimum) number.value = number.minimum; g_free(config_path); } void preferences_save_numeric_parameter( int value, const gchar *config_key) { gchar *config_path; config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, config_key, NULL); gnome_config_set_int (config_path, value); g_free(config_path); } ////////////////////////////////////////////////////////////////////////////// void preferences_save_settings(void) { int i; int a; gchar *config_path; config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_THEME, NULL); gnome_config_set_string (config_path, preferences.Theme); g_free(config_path); for (i = 0; i < Player::MAX_NUMBER_OF_LOCAL_PLAYERS; i++) { for (a = 0; a < Player::NUMBER_OF_PLAYER_ACTIONS; a++) { preferences_save_config_keyval (KeyPreferences.PlayerAction[i][a].keyval, CONFIGKEY_PLAYER_ACTION[i][a]); } } for (i = 1; i < Player::MAX_NUMBER_OF_PLAYERS; i++) { preferences_save_config_keyval (KeyPreferences.StartNPlayerGame[i], CONFIGKEY_START_N_PLAYER_GAME[i]); } for (i = 0; i < Player::MAX_NUMBER_OF_LOCAL_PLAYERS; i++) { config_path = g_strconcat (KEYMAP_CONFIGPATH_SECTION, CONFIGKEY_PLAYER_AUTOFIRE[i], NULL); gnome_config_set_bool (config_path, preferences.EnableAutoFire[i]); g_free(config_path); } preferences_save_config_keyval (KeyPreferences.Pause, CONFIGKEY_PAUSE_GAME); preferences_save_config_keyval (KeyPreferences.Quit, CONFIGKEY_QUIT_GAME); preferences_save_config_keyval (KeyPreferences.Continue, CONFIGKEY_CONTINUE_GAME); config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_ENABLE_CONTINUE_BUTTON, NULL); gnome_config_set_bool (config_path, preferences.EnableContinueButton); g_free(config_path); config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_ENABLE_INTER_ROUND_STATUS, NULL); gnome_config_set_bool (config_path, preferences.EnableInterRoundMatchStatus); g_free(config_path); config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_CASE_SENSITIVE, NULL); gnome_config_set_bool (config_path, preferences.CaseSensitive); g_free(config_path); //preferences_save_numeric_parameter // (preferences.MatchStatusDelay.value, // CONFIGKEY_MATCH_STATUS_DELAY ); config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_MAP_FILE, NULL); gnome_config_set_string (config_path, preferences.MapFile); g_free(config_path); config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_WALL_PERIMETER, NULL); gnome_config_set_bool (config_path, preferences.ShowWallPerimeter); g_free(config_path); config_path = g_strconcat (GENERAL_CONFIGPATH_SECTION, CONFIGKEY_WALL_PERIMETER_TOP_ONLY, NULL); gnome_config_set_bool (config_path, preferences.ShowWallPerimeterTopOnly); g_free(config_path); preferences_save_numeric_parameter (preferences.WinsPerMatch.value, CONFIGKEY_WINS_PER_MATCH); preferences_save_numeric_parameter (preferences.InitialMaxBombsPerPlayer.value, CONFIGKEY_INITIAL_BOMBS); preferences_save_numeric_parameter (preferences.InitialPlayerBombBlastRadius.value, CONFIGKEY_INITIAL_RANGE); preferences_save_numeric_parameter (preferences.BombExplodeDelay.value, CONFIGKEY_EXPLODE_DELAY); preferences_save_numeric_parameter (preferences.BombChainReactionDelay.value, CONFIGKEY_CHAIN_DELAY); preferences_save_numeric_parameter (preferences.FlameDuration.value, CONFIGKEY_FLAME_DURATION); preferences_save_numeric_parameter (preferences.BrickShatterFrameDuration.value, CONFIGKEY_BRICK_SHATTER_DELAY); preferences_save_numeric_parameter (preferences.PowerUpShatterFrameDuration.value, CONFIGKEY_POWERUP_SHATTER_DELAY); preferences_save_numeric_parameter (preferences.ProbabilityOfPowerup.value, CONFIGKEY_POWERUP_PROBABILITY); for (i = 0; i < PowerUp::NUMBER_OF_CREATABLE_POWERUPS; i++) { preferences_save_numeric_parameter (preferences.PowerUpProbability[i].value, CONFIGKEY_INDIVIDUAL_POWERUP_PROBABILITY[i]); } preferences_save_numeric_parameter (preferences.StepsToMiddleOfSquare.value, CONFIGKEY_SQUARE_STEPS); preferences_save_numeric_parameter (preferences.InitialPlayerMoveDelay.value, CONFIGKEY_PLAYER_MOVE_DELAY); preferences_save_numeric_parameter (preferences.TimeoutInterval.value, CONFIGKEY_TIMEOUT_INTERVAL); gnome_config_sync(); } ////////////////////////////////////////////////////////////////////////////// void apply(GtkWidget *widget, gint page, gpointer data) { if (page != -1) { return; } if (ThemeSelection != NULL) { preferences_set_theme(ThemeSelection); preferences_apply_theme(); } preferences.EnableContinueButton = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(ContinueButtonEntry)); preferences.EnableInterRoundMatchStatus = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(InterRoundMatchStatusEntry)); preferences.CaseSensitive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(CaseSensitiveEntry)); TempKeyPreferences.rehash(); KeyPreferences = TempKeyPreferences; for (int i = 0; i < Player::MAX_NUMBER_OF_LOCAL_PLAYERS; i++) { preferences.EnableAutoFire[i] = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(PlayerAutoFireEntry[i])); input_set_autofire(i, preferences.EnableAutoFire[i]); } gchar *mapfile = MapfileSelection; if (mapfile != NULL) { if (false == preferences_check_if_file_exists(mapfile)) { gnome_warning_dialog_parented (_("Invalid map file"), GTK_WINDOW(PropertyBox)); } else { preferences_set_current_mapfile (mapfile); } } mapfile = NULL; preferences.ShowWallPerimeter = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(WallEntry)); preferences.ShowWallPerimeterTopOnly = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(WallTopEntry)); GameMap::set_walled_perimeter (preferences.ShowWallPerimeter, preferences.ShowWallPerimeterTopOnly); preferences.WinsPerMatch.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(WinsEntry)); preferences.InitialMaxBombsPerPlayer.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(BombsEntry)); preferences.InitialPlayerBombBlastRadius.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(RangeEntry)); preferences.ProbabilityOfPowerup.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(PowerupEntry)); preferences.BombExplodeDelay.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(ExplodeEntry)); preferences.BombChainReactionDelay.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(ChainEntry)); preferences.FlameDuration.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(FlameEntry)); preferences.BrickShatterFrameDuration.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(BrickShatterEntry)); preferences.PowerUpShatterFrameDuration.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(PowerUpShatterEntry)); for (int i = 0; i < PowerUp::NUMBER_OF_CREATABLE_POWERUPS; i++) { preferences.PowerUpProbability[i].value = TempPowerUpProbability[i]; } preferences_apply_numeric_parameters(); preferences.TimeoutInterval.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(TimeoutEntry)); preferences.StepsToMiddleOfSquare.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(SquareStepEntry)); preferences.InitialPlayerMoveDelay.value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(PlayerMoveEntry)); preferences_apply_animation_parameters(); preferences_save_settings(); return; } void general_keypress(GtkWidget *widget, GdkEventKey *event, gpointer data) { *((guint *)data) = event->keyval; gtk_entry_set_text (GTK_ENTRY(widget), gdk_keyval_name(event->keyval)); gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void player_keypress(GtkWidget *widget, GdkEventKey *event, gpointer data) { ((PlayerActionKeyBinding *)data)->keyval = event->keyval; gtk_entry_set_text (GTK_ENTRY(widget), gdk_keyval_name(event->keyval)); gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void map_selection (GtkWidget *item, gpointer user_data) { gchar *selection; selection = (gchar *)user_data; if (false == preferences_check_if_file_exists(selection)) { gnome_warning_dialog_parented (_("Invalid map file"), GTK_WINDOW(PropertyBox)); } else { MapfileSelection = selection; gnome_property_box_changed (GNOME_PROPERTY_BOX(PropertyBox)); map_preview_update (selection); } } void map_preview_update(const char *map_path) { ParsedMap reference_map; bool valid = GameMap::parse_map(map_path, &reference_map); reference_map.set_valid(valid); if (valid) { // set up a GameMap corresponding to the selected map file PreviewMap.assign_map_from_parsed_map(&reference_map); PreviewMap.populate_map(); int MazePixelWidth =PreviewMap.get_width()*MapSquare::get_square_width(); int MazePixelHeight=PreviewMap.get_height()*MapSquare::get_square_height(); map_preview_update_initialize_players(&PreviewMap, MapPreviewPlayers); // set up a new target pixmap for the GameMap to draw to GdkPixmap *map_pixmap = gdk_pixmap_new (MapPreviewDisplay.window, MazePixelWidth, MazePixelHeight, -1); PreviewMap.set_ui_target (NULL, MapPreviewDisplay.gc, map_pixmap); PreviewMap.update_ui(); // resize the target pixmap to fit in the preview pane GdkPixbuf *map_pixbuf = gdk_pixbuf_get_from_drawable (NULL, map_pixmap, gdk_rgb_get_cmap(), 0, 0, 0, 0, MazePixelWidth, MazePixelHeight); GdkPixbuf *map_preview_pixbuf = gdk_pixbuf_scale_simple (map_pixbuf, MAP_PREVIEW_WIDTH, MAP_PREVIEW_HEIGHT, GDK_INTERP_NEAREST); // update the preview pane gdk_pixbuf_render_to_drawable (map_preview_pixbuf, MapPreviewPixmap, MapPreviewDisplay.gc, 0, 0, 0, 0, MAP_PREVIEW_WIDTH, MAP_PREVIEW_HEIGHT, GDK_RGB_DITHER_NONE, 0, 0); gdk_pixbuf_render_to_drawable (map_preview_pixbuf, MapPreviewDisplay.window, MapPreviewDisplay.gc, 0, 0, 0, 0, MAP_PREVIEW_WIDTH, MAP_PREVIEW_HEIGHT, GDK_RGB_DITHER_NONE, 0, 0); gdk_pixmap_unref(map_pixmap); gdk_pixbuf_unref(map_pixbuf); gdk_pixbuf_unref(map_preview_pixbuf); } else { gdk_draw_rectangle (MapPreviewPixmap, MapPreviewDisplay.gc, TRUE, 0, 0, MAP_PREVIEW_WIDTH, MAP_PREVIEW_HEIGHT); gdk_draw_rectangle (MapPreviewDisplay.window, MapPreviewDisplay.gc, TRUE, 0, 0, MAP_PREVIEW_WIDTH, MAP_PREVIEW_HEIGHT); gnome_warning_dialog_parented (_("Error while parsing map.\n" "Please choose another one."), GTK_WINDOW(PropertyBox)); } } void theme_selection (GtkWidget *item, gpointer user_data) { gchar *selection = (gchar *)user_data; ThemeSelection = selection; gnome_property_box_changed (GNOME_PROPERTY_BOX(PropertyBox)); theme_preview_update (selection); } void theme_preview_update(const char *theme_path) { gtk_editable_delete_text (GTK_EDITABLE(ThemePreviewText), 0, -1); int theme_description_length; char *theme_description; gchar *theme_description_file = g_strdup_printf("%s/README", theme_path); FILE *fp = fopen(theme_description_file, "r"); g_free(theme_description_file); if (fp == NULL) { return; } int buffer_size = 1024; for (;;) { theme_description = new char[buffer_size]; theme_description_length = fread(theme_description, sizeof(char), buffer_size-1, fp); if (theme_description_length >= buffer_size - 1) { fseek(fp, 0, SEEK_SET); delete theme_description; buffer_size *= 2; } else { theme_description[theme_description_length] = '\0'; break; } } int theme_description_position = 0; gtk_editable_insert_text (GTK_EDITABLE(ThemePreviewText), theme_description, theme_description_length, &theme_description_position); gtk_editable_set_position (GTK_EDITABLE(ThemePreviewText), 0); fclose(fp); delete theme_description; } void map_preview_update_initialize_players(GameMap *maze, Player *player) { int i; int start_x, start_y; int n_players = maze->get_allowable_number_of_players(); for (i = 0; i < n_players; i++) { player[i].reset_fields(); player[i].set_id(i); player[i].set_game_map(maze); maze->get_starting_coordinates_of_player(i+1, start_x, start_y); player[i].set_starting_coordinates(start_x, start_y); player[i].activate(); maze->move_entity_to_top(&(player[i]), start_x, start_y); } return; } void check_button_click(GtkWidget *widget, gpointer data) { gboolean wall_enabled; wall_enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(WallEntry)); gtk_widget_set_sensitive (GTK_WIDGET(WallTopEntry), wall_enabled); gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void spinner_click(GtkWidget *widget, gpointer data) { gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void spinner_keypress(GtkWidget *widget, GdkEventKey *event, gpointer data) { gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); } void powerup_scale_value_changed(GtkWidget *widget, gpointer user_data) { if (PowerUpProbabilityScaleRebalanceInProgress == false) { powerup_scale_rebalance((int)user_data); } } void powerup_scale_rebalance(int index) { static const int MAX_BALANCING_ITERATIONS = 100; static int starting_index = 0; PowerUpProbabilityScaleRebalanceInProgress = true; GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE(PowerUpProbabilityEntry[index])); int new_value = (int)((GTK_ADJUSTMENT(adjustment)->value)); int balancing_delta = (int)TempPowerUpProbability[index] - new_value; TempPowerUpProbability[index] = new_value; int i; for (i = 0; i < MAX_BALANCING_ITERATIONS; i++) { balancing_delta = powerup_scale_adjust_all_but_one (index, starting_index, TempPowerUpProbability, balancing_delta); starting_index=(starting_index+1)%(PowerUp::NUMBER_OF_CREATABLE_POWERUPS); if (balancing_delta == 0) break; } assert (i != MAX_BALANCING_ITERATIONS); int TotalPowerUpProbability = 0; for (i = 0; i < PowerUp::NUMBER_OF_CREATABLE_POWERUPS; i++) { TotalPowerUpProbability += (int)TempPowerUpProbability[i]; } assert (TotalPowerUpProbability == 100); for (i = 0; i < PowerUp::NUMBER_OF_CREATABLE_POWERUPS; i++) { if (i != index) { adjustment = gtk_range_get_adjustment (GTK_RANGE(PowerUpProbabilityEntry[i])); gtk_adjustment_set_value(adjustment, (float)TempPowerUpProbability[i]); } } gnome_property_box_changed(GNOME_PROPERTY_BOX(PropertyBox)); PowerUpProbabilityScaleRebalanceInProgress = false; } int powerup_scale_adjust_all_but_one( int index, int starting_index, int scale[PowerUp::NUMBER_OF_CREATABLE_POWERUPS], int total_adjustment_required) { int i, j; int old_value; int adjustment_remainder = total_adjustment_required; int adjustment_delta; if (abs(total_adjustment_required) < PowerUp::NUMBER_OF_CREATABLE_POWERUPS-1) { adjustment_delta = normalize(total_adjustment_required); } else { adjustment_delta = total_adjustment_required/(PowerUp::NUMBER_OF_CREATABLE_POWERUPS-1); } j = starting_index % (PowerUp::NUMBER_OF_CREATABLE_POWERUPS); for (i = 0; i < PowerUp::NUMBER_OF_CREATABLE_POWERUPS; i++) { if (j != index) { old_value = scale[j]; scale[j] += adjustment_delta; if (scale[j] > preferences.PowerUpProbability[j].maximum) { scale[j] = preferences.PowerUpProbability[j].maximum; } else if (scale[j] < preferences.PowerUpProbability[j].minimum) { scale[j] = preferences.PowerUpProbability[j].minimum; } adjustment_remainder += (old_value - scale[j]); if (adjustment_remainder == 0) break; } j = (j+1)%(PowerUp::NUMBER_OF_CREATABLE_POWERUPS); } return adjustment_remainder; } ////////////////////////////////////////////////////////////////////////////// void preferences_help (GnomePropertyBox *property_box, gint page_num, gpointer user_data) { static GnomeHelpMenuEntry GeneralHelp = { PACKAGE, "index.html" }; static GnomeHelpMenuEntry KeymapHelp = { PACKAGE, "index.html#controls" }; static GnomeHelpMenuEntry NumericHelp = { PACKAGE, "numeric.html" }; static GnomeHelpMenuEntry PowerupHelp = { PACKAGE, "index.html#powerups" }; static GnomeHelpMenuEntry AnimationHelp = { PACKAGE, "animation.html" }; switch (page_num) { case 0: gnome_help_display (0, &GeneralHelp); break; case 1: case 2: case 3: case 4: gnome_help_display (0, &KeymapHelp); break; case 5: gnome_help_display (0, &NumericHelp); break; case 6: gnome_help_display (0, &PowerupHelp); break; case 7: gnome_help_display (0, &AnimationHelp); break; } } ////////////////////////////////////////////////////////////////////////////// void preferences_create_dialog(void) { PropertyBox = gnome_property_box_new(); gtk_window_set_title (GTK_WINDOW(PropertyBox), _("BomberMaze Preferences")); append_page_general(PropertyBox); append_page_map(PropertyBox); append_page_theme(PropertyBox); append_page_players(PropertyBox); append_page_numeric(PropertyBox); append_page_powerups(PropertyBox); append_page_animation(PropertyBox); gtk_signal_connect (GTK_OBJECT (PropertyBox), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &PropertyBox); gtk_signal_connect (GTK_OBJECT (PropertyBox), "apply", GTK_SIGNAL_FUNC (apply), NULL); gtk_signal_connect (GTK_OBJECT (PropertyBox), "help", GTK_SIGNAL_FUNC(preferences_help), NULL); gtk_widget_show(PropertyBox); } void preferences_set_standard_table_layout(GtkWidget *table) { gtk_table_set_row_spacings (GTK_TABLE(table), GNOME_PAD); gtk_table_set_col_spacings (GTK_TABLE(table), GNOME_PAD); gtk_container_border_width (GTK_CONTAINER (table), GNOME_PAD); gtk_widget_show(table); } void build_frame_control_game(GtkWidget **frame) { GtkWidget *label; GtkWidget *entry; GtkWidget *table = gtk_table_new (3, 2, FALSE); preferences_set_standard_table_layout(table); create_general_entry (_("Pause game"), &label, &entry, &(TempKeyPreferences.Pause)); gtk_table_attach (GTK_TABLE(table), label, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); PauseEntry = entry; create_general_entry (_("Quit game"), &label, &entry, &(TempKeyPreferences.Quit)); gtk_table_attach (GTK_TABLE(table), label, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); QuitEntry = entry; create_general_entry (_("Continue"), &label, &entry, &(TempKeyPreferences.Continue)); gtk_table_attach (GTK_TABLE(table), label, 0, 1, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); ContinueEntry = entry; *frame = gtk_frame_new(_("Game control keys")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); } void build_frame_start_game(GtkWidget **frame) { gchar *label_name; GtkWidget *label; GtkWidget *entry; GtkWidget *table; table = gtk_table_new (Player::MAX_NUMBER_OF_PLAYERS-1, 2, FALSE); preferences_set_standard_table_layout(table); for (int i = 1; i < Player::MAX_NUMBER_OF_PLAYERS; i++) { label_name = g_strdup_printf(_("Start %d player game"), i+1); create_general_entry (label_name, &label, &entry, &(TempKeyPreferences.StartNPlayerGame[i])); g_free(label_name); gtk_table_attach (GTK_TABLE(table), label, 0, 1, -1+i, +i, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 1, 2, -1+i, +i, GTK_SHRINK, GTK_SHRINK, 0, 0); StartNewGameEntry[i] = entry; } *frame = gtk_frame_new(_("Game start keys")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); } void build_frame_match(GtkWidget **frame) { GtkWidget *label; GtkWidget *entry; GtkWidget *table; table = gtk_table_new (3, 2, FALSE); preferences_set_standard_table_layout(table); *frame = gtk_frame_new(_("Miscellaneous")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); create_numeric_spinner (_("Wins per match"), &label, &entry, &(preferences.WinsPerMatch)); gtk_table_attach (GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0); WinsEntry = entry; entry = gtk_check_button_new_with_label( _("Enable Continue button\n" "on Match Status dialog")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(entry), preferences.EnableContinueButton); gtk_signal_connect (GTK_OBJECT(entry), "clicked", GTK_SIGNAL_FUNC(check_button_click), NULL); gtk_widget_show(entry); gtk_table_attach (GTK_TABLE(table), entry, 0, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); ContinueButtonEntry = entry; entry = gtk_check_button_new_with_label( _("Show Match Status dialog\n" "between rounds")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(entry), preferences.EnableInterRoundMatchStatus); gtk_signal_connect (GTK_OBJECT(entry), "clicked", GTK_SIGNAL_FUNC(check_button_click), NULL); gtk_widget_show(entry); gtk_table_attach (GTK_TABLE(table), entry, 0, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); InterRoundMatchStatusEntry = entry; entry = gtk_check_button_new_with_label( _("Case sensitive controls")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(entry), preferences.CaseSensitive); gtk_signal_connect (GTK_OBJECT(entry), "clicked", GTK_SIGNAL_FUNC(check_button_click), NULL); gtk_widget_show(entry); gtk_table_attach (GTK_TABLE(table), entry, 0, 2, 3, 4, GTK_SHRINK, GTK_SHRINK, 0, 0); CaseSensitiveEntry = entry; } void append_page_general(GtkWidget *PropertyBox) { GtkWidget *label = gtk_label_new(_("General")); gtk_widget_show(label); GtkWidget *table = gtk_table_new (3, 2, FALSE); preferences_set_standard_table_layout(table); gnome_property_box_append_page (GNOME_PROPERTY_BOX(PropertyBox), table, label); GtkWidget *frame; build_frame_start_game(&frame); gtk_table_attach (GTK_TABLE(table), frame, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); build_frame_control_game(&frame); gtk_table_attach (GTK_TABLE(table), frame, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); build_frame_match(&frame); gtk_table_attach (GTK_TABLE(table), frame, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0); GtkWidget *button = gtk_button_new_with_label(_("Defaults")); gtk_signal_connect (GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(preferences_default_general), NULL); gtk_widget_show(button); gtk_table_attach (GTK_TABLE(table), button, 1, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); } void append_page_map(GtkWidget *PropertyBox) { GtkWidget *label = gtk_label_new(_("Map")); gtk_widget_show(label); GtkWidget *table = gtk_table_new (3, 2, FALSE); preferences_set_standard_table_layout(table); gnome_property_box_append_page (GNOME_PROPERTY_BOX(PropertyBox), table, label); GtkWidget *frame; build_frame_map(&frame); gtk_table_attach (GTK_TABLE(table), frame, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); GtkWidget *button = gtk_button_new_with_label(_("Defaults")); gtk_signal_connect (GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(preferences_default_map), NULL); gtk_widget_show(button); gtk_table_attach (GTK_TABLE(table), button, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); frame = gtk_frame_new(_("Preview")); gtk_container_border_width (GTK_CONTAINER (frame), GNOME_PAD); gtk_widget_show(frame); gtk_table_attach (GTK_TABLE(table), frame, 1, 2, 0, 2, GTK_FILL, GTK_FILL, 0, 0); MapPreviewArea = gtk_drawing_area_new(); gtk_drawing_area_size ((GtkDrawingArea *)MapPreviewArea, MAP_PREVIEW_WIDTH, MAP_PREVIEW_HEIGHT); gtk_widget_set_usize ((GtkWidget *)MapPreviewArea, MAP_PREVIEW_WIDTH, MAP_PREVIEW_HEIGHT); gtk_signal_connect (GTK_OBJECT (MapPreviewArea), "realize", GTK_SIGNAL_FUNC (realize), &MapPreviewDisplay); gtk_signal_connect (GTK_OBJECT (MapPreviewArea), "expose_event", GTK_SIGNAL_FUNC (expose_event), &MapPreviewPixmap); gtk_widget_show (MapPreviewArea); gtk_container_add (GTK_CONTAINER(frame), MapPreviewArea); gtk_widget_realize (MapPreviewArea); MapPreviewPixmap = gdk_pixmap_new (MapPreviewDisplay.window, MAP_PREVIEW_WIDTH, MAP_PREVIEW_HEIGHT, -1); map_preview_update(preferences.MapFile); } void build_frame_map(GtkWidget **frame) { GtkWidget *entry; GtkWidget *table; table = gtk_table_new (3, 1, FALSE); preferences_set_standard_table_layout(table); entry = gtk_option_menu_new(); preferences_add_files_to_menu (entry, &MapsMenu, &MapsMenuDefaultItem, map_selection, MapsList, preferences.MapFile, DEFAULT_MAP_FILE, MapsMenuDefaultIndex); gtk_widget_show(entry); gtk_table_attach (GTK_TABLE(table), entry, 0, 1, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0); MapsOptionMenu = entry; entry = gtk_check_button_new_with_label(_("Show wall perimeter")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(entry), preferences.ShowWallPerimeter); gtk_signal_connect (GTK_OBJECT(entry), "clicked", GTK_SIGNAL_FUNC(check_button_click), NULL); gtk_widget_show(entry); gtk_table_attach (GTK_TABLE(table), entry, 0, 1, 1, 2, GTK_FILL, GTK_EXPAND, 0, 0); WallEntry = entry; entry = gtk_check_button_new_with_label(_("Show top wall only")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(entry), preferences.ShowWallPerimeterTopOnly); gtk_signal_connect (GTK_OBJECT(entry), "clicked", GTK_SIGNAL_FUNC(check_button_click), NULL); gtk_widget_set_sensitive (GTK_WIDGET(entry), preferences.ShowWallPerimeter); gtk_widget_show(entry); gtk_table_attach (GTK_TABLE(table), entry, 0, 1, 2, 3, GTK_FILL, GTK_EXPAND, 0, 0); WallTopEntry = entry; *frame = gtk_frame_new(_("Map")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); } void append_page_theme(GtkWidget *PropertyBox) { GtkWidget *label = gtk_label_new(_("Theme")); gtk_widget_show(label); GtkWidget *table = gtk_table_new (3, 2, FALSE); preferences_set_standard_table_layout(table); gnome_property_box_append_page (GNOME_PROPERTY_BOX(PropertyBox), table, label); GtkWidget *frame; frame = gtk_frame_new(_("Theme")); gtk_container_border_width (GTK_CONTAINER (frame), GNOME_PAD); gtk_widget_show(frame); GtkWidget *entry = gtk_option_menu_new(); preferences_add_files_to_menu (entry, &ThemesMenu, &ThemesMenuDefaultItem, theme_selection, ThemesList, preferences.Theme, DEFAULT_THEME, ThemesMenuDefaultIndex); gtk_widget_show(entry); gtk_container_add (GTK_CONTAINER(frame), entry); ThemesOptionMenu = entry; gtk_table_attach (GTK_TABLE(table), frame, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); GtkWidget *button = gtk_button_new_with_label(_("Defaults")); gtk_signal_connect (GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(preferences_default_theme), NULL); gtk_widget_show(button); gtk_table_attach (GTK_TABLE(table), button, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); GtkWidget *table2; frame = gtk_frame_new(_("Preview")); gtk_container_border_width (GTK_CONTAINER (frame), GNOME_PAD); gtk_widget_show(frame); gtk_table_attach (GTK_TABLE(table), frame, 1, 2, 0, 2, GTK_FILL, GTK_FILL, 0, 0); table2 = gtk_table_new (2, 1, FALSE); preferences_set_standard_table_layout(table2); gtk_container_add (GTK_CONTAINER(frame), table2); ThemePreviewArea = gtk_drawing_area_new(); gtk_drawing_area_size ((GtkDrawingArea *)ThemePreviewArea, THEME_PREVIEW_WIDTH, THEME_PREVIEW_HEIGHT); gtk_widget_set_usize ((GtkWidget *)ThemePreviewArea, THEME_PREVIEW_WIDTH, THEME_PREVIEW_HEIGHT); gtk_signal_connect (GTK_OBJECT (ThemePreviewArea), "realize", GTK_SIGNAL_FUNC (realize), &ThemePreviewDisplay); gtk_signal_connect (GTK_OBJECT (ThemePreviewArea), "expose_event", GTK_SIGNAL_FUNC (expose_event), &ThemePreviewPixmap); gtk_widget_show (ThemePreviewArea); gtk_table_attach (GTK_TABLE(table2), ThemePreviewArea, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); //gtk_container_add (GTK_CONTAINER(frame), ThemePreviewArea); gtk_widget_realize (ThemePreviewArea); ThemePreviewPlaceHolder = gtk_label_new("not implemented yet"); gtk_widget_show (ThemePreviewPlaceHolder); //gtk_container_add (GTK_CONTAINER(frame), ThemePreviewPlaceHolder); gtk_table_attach (GTK_TABLE(table2), ThemePreviewPlaceHolder, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); table2 = gtk_hbox_new(FALSE, 0); //table2 = gtk_table_new (2, 2, FALSE); //preferences_set_standard_table_layout(table2); ThemePreviewText = gtk_text_new(NULL, NULL); gtk_text_set_editable (GTK_TEXT(ThemePreviewText), FALSE); gtk_text_set_word_wrap (GTK_TEXT(ThemePreviewText), TRUE); gtk_widget_show(ThemePreviewText); gtk_box_pack_start(GTK_BOX(table2), ThemePreviewText, TRUE, TRUE, 0); //gtk_table_attach (GTK_TABLE(table2), ThemePreviewText, 0, 1, 0, 1, // GTK_FILL, GTK_FILL, 0, 0); GtkWidget *scrollbar; scrollbar = gtk_vscrollbar_new (GTK_ADJUSTMENT(GTK_TEXT(ThemePreviewText)->vadj)); gtk_widget_show(scrollbar); gtk_box_pack_end(GTK_BOX(table2), scrollbar, FALSE, TRUE, 0); //gtk_table_attach (GTK_TABLE(table2), scrollbar, 1, 2, 0, 1, // GTK_SHRINK, GTK_FILL, 0, 0); /* scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT(GTK_TEXT(ThemePreviewText)->hadj)); gtk_widget_show(scrollbar); gtk_table_attach (GTK_TABLE(table2), scrollbar, 0, 1, 1, 2, GTK_FILL, GTK_SHRINK, 0, 0); */ gtk_widget_show(table2); gtk_table_attach (GTK_TABLE(table), table2, 0, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0); theme_preview_update(preferences.Theme); } void append_page_players(GtkWidget *PropertyBox) { char *label_name = NULL; GtkWidget *label = NULL; GtkWidget *frame = NULL; GtkWidget *table = NULL; GtkWidget *button= NULL; for (int i = 0; i < Player::MAX_NUMBER_OF_LOCAL_PLAYERS; i++) { label_name = g_strdup_printf(_("Player %d"), i+1); label = gtk_label_new(label_name); g_free(label_name); gtk_widget_show(label); table = gtk_table_new (2, 2, FALSE); preferences_set_standard_table_layout(table); gnome_property_box_append_page (GNOME_PROPERTY_BOX(PropertyBox), table, label); build_frame_movement(&frame, i); gtk_table_attach (GTK_TABLE(table), frame, 0, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0); build_frame_action(&frame, i); gtk_table_attach (GTK_TABLE(table), frame, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); button = gtk_button_new_with_label(_("Defaults")); gtk_signal_connect (GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(preferences_default_keys),(gpointer)i); gtk_widget_show(button); gtk_table_attach (GTK_TABLE(table), button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); } } void build_frame_movement(GtkWidget **frame, int i) { GtkWidget *label; GtkWidget *entry; GtkWidget *table; table = gtk_table_new (5, 5, FALSE); preferences_set_standard_table_layout(table); create_player_entry (_("Up"), &label, &entry, i, Player::PLAYER_MOVE_NORTH); gtk_table_attach (GTK_TABLE(table), label, 2, 3, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 2, 3, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); PlayerActionEntry[i][Player::PLAYER_MOVE_NORTH] = entry; create_player_entry (_("Right"), &label, &entry, i, Player::PLAYER_MOVE_EAST); gtk_table_attach (GTK_TABLE(table), label, 4, 5, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 3, 4, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); PlayerActionEntry[i][Player::PLAYER_MOVE_EAST] = entry; create_player_entry (_("Down"), &label, &entry, i, Player::PLAYER_MOVE_SOUTH); gtk_table_attach (GTK_TABLE(table), label, 2, 3, 4, 5, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 2, 3, 3, 4, GTK_SHRINK, GTK_SHRINK, 0, 0); PlayerActionEntry[i][Player::PLAYER_MOVE_SOUTH] = entry; create_player_entry (_("Left"), &label, &entry, i, Player::PLAYER_MOVE_WEST); gtk_table_attach (GTK_TABLE(table), label, 0, 1, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); PlayerActionEntry[i][Player::PLAYER_MOVE_WEST] = entry; *frame = gtk_frame_new(_("Movement")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); } void build_frame_action(GtkWidget **frame, int i) { GtkWidget *label; GtkWidget *entry; GtkWidget *table; table = gtk_table_new (2, 3, FALSE); preferences_set_standard_table_layout(table); create_player_entry (_("Drop bomb"), &label, &entry, i, Player::PLAYER_DROP_BOMB); gtk_table_attach (GTK_TABLE(table), label, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); PlayerActionEntry[i][Player::PLAYER_DROP_BOMB] = entry; entry = gtk_check_button_new_with_label(_("Enable auto-fire")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(entry), preferences.EnableAutoFire[i]); gtk_signal_connect (GTK_OBJECT(entry), "clicked", GTK_SIGNAL_FUNC(check_button_click), NULL); gtk_widget_show(entry); gtk_table_attach (GTK_TABLE(table), entry, 2, 3, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); PlayerAutoFireEntry[i] = entry; create_player_entry (_("Special action"), &label, &entry, i, Player::PLAYER_SPECIAL); gtk_table_attach (GTK_TABLE(table), label, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_table_attach (GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); PlayerActionEntry[i][Player::PLAYER_SPECIAL] = entry; *frame = gtk_frame_new(_("Action")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); } void append_page_numeric(GtkWidget *PropertyBox) { GtkWidget *label = gtk_label_new(_("Numeric")); gtk_widget_show(label); GtkWidget *table = gtk_table_new (2, 2, FALSE); preferences_set_standard_table_layout(table); gnome_property_box_append_page (GNOME_PROPERTY_BOX(PropertyBox), table, label); GtkWidget *frame; build_frame_numeric(&frame); gtk_table_attach (GTK_TABLE(table), frame, 0, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0); GtkWidget *button = gtk_button_new_with_label(_("Defaults")); gtk_signal_connect (GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(preferences_default_numeric), NULL); gtk_widget_show(button); gtk_table_attach (GTK_TABLE(table), button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); } void build_frame_numeric(GtkWidget **frame) { GtkWidget *table = gtk_table_new (8, 2, FALSE); preferences_set_standard_table_layout(table); *frame = gtk_frame_new(_("Numeric")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); GtkWidget *entry; GtkWidget *label; create_numeric_spinner (_("Initial number of bombs"), &label, &entry, &(preferences.InitialMaxBombsPerPlayer)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 0, 1); BombsEntry = entry; create_numeric_spinner (_("Initial explosion size"), &label, &entry, &(preferences.InitialPlayerBombBlastRadius)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 1, 2); RangeEntry = entry; create_numeric_spinner (_("Bomb explosion delay (tenths of a second)"), &label, &entry, &(preferences.BombExplodeDelay)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 2, 3); ExplodeEntry = entry; create_numeric_spinner (_("Bomb chain reaction delay (frames)"), &label, &entry, &(preferences.BombChainReactionDelay)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 3, 4); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 3, 4); ChainEntry = entry; create_numeric_spinner (_("Flame duration (frames)"), &label, &entry, &(preferences.FlameDuration)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 4, 5); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 4, 5); FlameEntry = entry; create_numeric_spinner (_("Brick shatter duration (frames)"), &label, &entry, &(preferences.BrickShatterFrameDuration)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 5, 6); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 5, 6); BrickShatterEntry = entry; create_numeric_spinner (_("Power-up shatter duration (frames)"), &label, &entry, &(preferences.PowerUpShatterFrameDuration)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 6, 7); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 6, 7); PowerUpShatterEntry = entry; create_numeric_spinner (_("Probability of power-ups (%)"), &label, &entry, &(preferences.ProbabilityOfPowerup)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 7, 8); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 7, 8); PowerupEntry = entry; } void append_page_powerups(GtkWidget *PropertyBox) { GtkWidget *label = gtk_label_new(_("Power-ups")); gtk_widget_show(label); GtkWidget *table = gtk_table_new (2, 2, FALSE); preferences_set_standard_table_layout(table); gnome_property_box_append_page (GNOME_PROPERTY_BOX(PropertyBox), table, label); GtkWidget *frame; build_frame_powerups(&frame); gtk_table_attach (GTK_TABLE(table), frame, 0, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0); GtkWidget *button = gtk_button_new_with_label(_("Defaults")); gtk_signal_connect (GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(preferences_default_powerup), NULL); gtk_widget_show(button); gtk_table_attach (GTK_TABLE(table), button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); } void build_frame_powerups(GtkWidget **frame) { GtkWidget *table = gtk_table_new (PowerUp::NUMBER_OF_CREATABLE_POWERUPS, 2, FALSE); preferences_set_standard_table_layout(table); *frame = gtk_frame_new(_("Probability of individual power-up types")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); GtkWidget *entry; GtkWidget *label; create_numeric_powerup_scale (_("Extra Bomb"), &label, &entry, &(preferences.PowerUpProbability[PowerUp::POWERUP_EXTRA_BOMB]), PowerUp::POWERUP_EXTRA_BOMB); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 0, 1); PowerUpProbabilityEntry[PowerUp::POWERUP_EXTRA_BOMB] = entry; create_numeric_powerup_scale (_("Extra Range"), &label, &entry, &(preferences.PowerUpProbability[PowerUp::POWERUP_EXTRA_RANGE]), PowerUp::POWERUP_EXTRA_RANGE); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 1, 2); PowerUpProbabilityEntry[PowerUp::POWERUP_EXTRA_RANGE] = entry; create_numeric_powerup_scale (_("Trigger Bomb"), &label, &entry, &(preferences.PowerUpProbability[PowerUp::POWERUP_TRIGGER_BOMB]), PowerUp::POWERUP_TRIGGER_BOMB); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 2, 3); PowerUpProbabilityEntry[PowerUp::POWERUP_TRIGGER_BOMB] = entry; create_numeric_powerup_scale (_("Kick Bomb"), &label, &entry, &(preferences.PowerUpProbability[PowerUp::POWERUP_KICK_BOMB]), PowerUp::POWERUP_KICK_BOMB); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 3, 4); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 3, 4); PowerUpProbabilityEntry[PowerUp::POWERUP_KICK_BOMB] = entry; create_numeric_powerup_scale (_("Extra Speed"), &label, &entry, &(preferences.PowerUpProbability[PowerUp::POWERUP_EXTRA_SPEED]), PowerUp::POWERUP_EXTRA_SPEED); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 4, 5); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 4, 5); PowerUpProbabilityEntry[PowerUp::POWERUP_EXTRA_SPEED] = entry; } void append_page_animation(GtkWidget *PropertyBox) { GtkWidget *label = gtk_label_new(_("Animation")); gtk_widget_show(label); GtkWidget *table = gtk_table_new (3, 2, FALSE); preferences_set_standard_table_layout(table); gnome_property_box_append_page (GNOME_PROPERTY_BOX(PropertyBox), table, label); GtkWidget *frame; build_frame_animation(&frame); gtk_table_attach (GTK_TABLE(table), frame, 0, 3, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); GtkWidget *button = gtk_button_new_with_label(_("Defaults")); gtk_signal_connect (GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(preferences_default_animation), NULL); gtk_widget_show(button); gtk_table_attach (GTK_TABLE(table), button, 2, 3, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); } void build_frame_animation(GtkWidget **frame) { GtkWidget *table = gtk_table_new (3, 3, FALSE); preferences_set_standard_table_layout(table); *frame = gtk_frame_new(_("Animation")); gtk_widget_show(*frame); gtk_container_add (GTK_CONTAINER(*frame), table); GtkWidget *label; GtkWidget *entry; create_numeric_spinner(_("Animation clock tick period (milliseconds)"), &label, &entry, &(preferences.TimeoutInterval)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 0, 1); TimeoutEntry = entry; label = gtk_label_new(_("start new game to apply")); gtk_label_set_justify (GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_widget_show(label); gtk_table_attach_defaults (GTK_TABLE(table), label, 2, 3, 0, 1); create_numeric_spinner (_("Steps to middle of square"), &label, &entry, &(preferences.StepsToMiddleOfSquare)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 1, 2); SquareStepEntry = entry; label = gtk_label_new(_("restart program to apply")); gtk_label_set_justify (GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_widget_show(label); gtk_table_attach_defaults (GTK_TABLE(table), label, 2, 3, 1, 2); create_numeric_spinner (_("Initial Player move delay (clock ticks)"), &label, &entry, &(preferences.InitialPlayerMoveDelay)); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), entry, 1, 2, 2, 3); PlayerMoveEntry = entry; label = gtk_label_new(_("start new game to apply")); gtk_label_set_justify (GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_widget_show(label); gtk_table_attach_defaults (GTK_TABLE(table), label, 2, 3, 2, 3); } void build_file_list_from_directory( GSList **file_list, char *dir_name ) { gchar *home_dir; gchar *directory; gchar *relative_directory; relative_directory = g_strconcat (dir_name, NULL); directory = preferences_get_data_file (relative_directory); g_free (relative_directory); if (directory != NULL) { prepend_directory_listing_to_file_list(file_list, directory); g_free (directory); } home_dir = g_get_home_dir(); directory = g_strconcat (home_dir, PATH_SEP_STR, ".", PACKAGE, PATH_SEP_STR, dir_name, NULL); prepend_directory_listing_to_file_list(file_list, directory); g_free (directory); //g_free (home_dir); // Do not free the return value of g_get_home_dir() *file_list = g_slist_reverse (*file_list); } void prepend_directory_listing_to_file_list( GSList **file_list, char *dir_path ) { if (dir_path == NULL) return; DIR *dir_stream; dir_stream = opendir (dir_path); if (dir_stream == NULL) return; dirent *dir_entry; int item_index = 0; while ((dir_entry = readdir (dir_stream)) != NULL) { char *item_name = dir_entry->d_name; if (item_name[0] == '.') continue; char *item_path = g_strconcat( dir_path, PATH_SEP_STR, item_name, NULL); *file_list = g_slist_prepend (*file_list, (gpointer)item_path); item_index++; } closedir (dir_stream); } void deallocate_directory_listing(GSList **file_list) { GSList *file; char *filename; for (file = *file_list; file != NULL; file = file->next) { filename = (char *)(file->data); g_free(filename); } g_slist_free(*file_list); *file_list = NULL; } void preferences_add_files_to_menu( GtkWidget *option_menu, GtkWidget **menu, GtkWidget **default_menu_item, void (*handler)(GtkWidget *w, void *d), GSList *file_list, const char *selected_item, const char *default_item, int &default_item_index ) { int selection_index = 0; int item_index = 0; *menu = gtk_menu_new(); for(GSList *file = file_list; file != NULL; file = file->next) { char *item_path = (char *)(file->data); GtkWidget *item; char *item_name = &(item_path[g_filename_index(item_path)]); item = gtk_menu_item_new_with_label(item_name);; gtk_widget_show (item); gtk_signal_connect (GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(handler), item_path); gtk_menu_append (GTK_MENU(*menu), item); if ( (selected_item != NULL) && ((strcmp(selected_item, item_name) == 0) || (strcmp(selected_item, item_path) == 0)) ) { selection_index = item_index; gtk_menu_set_active (GTK_MENU(*menu), selection_index); } if ( (default_item != NULL) && ((strcmp(default_item, item_name) == 0) || (strcmp(default_item, item_path) == 0)) ) { default_item_index = item_index; *default_menu_item = item; } item_index++; } gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), *menu); } void create_general_entry( char *entry_name, GtkWidget **label, GtkWidget **entry, guint *keyval ) { *label = gtk_label_new(entry_name); gtk_widget_show(*label); *entry = gtk_entry_new(); gtk_entry_set_editable (GTK_ENTRY(*entry), FALSE); gtk_entry_set_text (GTK_ENTRY(*entry), gdk_keyval_name(*keyval)); gtk_signal_connect(GTK_OBJECT(*entry), "key_press_event", GTK_SIGNAL_FUNC(general_keypress), (gpointer)keyval); gtk_widget_show(*entry); } void create_player_entry( char *entry_name, GtkWidget **label, GtkWidget **entry, int PlayerIndex, Player::PlayerAction action ) { PlayerActionKeyBinding *key_binding; key_binding = &(TempKeyPreferences.PlayerAction[PlayerIndex][action]); *label = gtk_label_new(entry_name); gtk_widget_show(*label); *entry = gtk_entry_new(); gtk_entry_set_editable (GTK_ENTRY(*entry), FALSE); gtk_entry_set_text (GTK_ENTRY(*entry), gdk_keyval_name(key_binding->keyval)); gtk_signal_connect(GTK_OBJECT(*entry), "key_press_event", GTK_SIGNAL_FUNC(player_keypress), (gpointer)key_binding); gtk_widget_show(*entry); return; } void create_numeric_spinner( char *entry_name, GtkWidget **label, GtkWidget **entry, NumberValue *number ) { *label = gtk_label_new(entry_name); gtk_label_set_justify (GTK_LABEL(*label), GTK_JUSTIFY_LEFT); gtk_widget_show(*label); GtkAdjustment *adjustment; adjustment = (GtkAdjustment *)gtk_adjustment_new ((float)number->value, (float)number->minimum, (float)number->maximum, (float)number->increment, (float)number->increment, (float)number->increment); *entry = gtk_spin_button_new (adjustment, number->increment, 0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON(*entry), TRUE); gtk_signal_connect(GTK_OBJECT(*entry), "key_press_event", GTK_SIGNAL_FUNC(spinner_keypress), (gpointer)NULL); gtk_signal_connect(GTK_OBJECT(*entry), "button_press_event", GTK_SIGNAL_FUNC(spinner_click), (gpointer)NULL); gtk_widget_show(*entry); } void create_numeric_powerup_scale( char *entry_name, GtkWidget **label, GtkWidget **entry, NumberValue *number, PowerUp::PowerUpType index ) { TempPowerUpProbability[(int)index] = preferences.PowerUpProbability[(int)index].value; *label = gtk_label_new(entry_name); gtk_widget_show(*label); GtkAdjustment *adjustment; adjustment = (GtkAdjustment *) gtk_adjustment_new ((float)number->value, (float)number->minimum, (float)number->maximum, (float)number->increment, (float)number->increment, (float)number->increment); gtk_signal_connect(GTK_OBJECT(adjustment), "value-changed", GTK_SIGNAL_FUNC(powerup_scale_value_changed), (gpointer)index); *entry = gtk_hscale_new (adjustment); gtk_scale_set_digits (GTK_SCALE(*entry), 0); gtk_scale_set_draw_value (GTK_SCALE(*entry), TRUE); gtk_scale_set_value_pos (GTK_SCALE(*entry), GTK_POS_RIGHT); gtk_widget_show(*entry); } //////////////////////////////////////////////////////////////////////////////