/*****************************************************************************\ Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. This file is licensed under the Snes9x License. For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ #include "gtk_2_3_compat.h" #include #include #include "gtk_s9x.h" #include "gtk_display.h" #include "gtk_shader_parameters.h" #include "shaders/glsl.h" static GtkWidget *dialog = NULL; static std::vector *params = NULL; static std::vector saved_params; static inline double snap_to_interval (double value, double interval) { return round (value / interval) * interval; } static void value_changed (GtkRange *range, gpointer user_data) { GLSLParam *p = (GLSLParam *) user_data; GtkAdjustment *adj = gtk_range_get_adjustment (range); double interval = gtk_adjustment_get_step_increment (adj); double value = gtk_range_get_value (range); value = snap_to_interval (value, interval); gtk_range_set_value (range, value); if (p->val != value) { p->val = value; if (Settings.Paused) S9xDeinitUpdate (top_level->last_width, top_level->last_height); } } static void toggled (GtkToggleButton *togglebutton, gpointer user_data) { GLSLParam *p = (GLSLParam *) user_data; double value = (double) gtk_toggle_button_get_active (togglebutton); if (p->val != value) { p->val = value; if (Settings.Paused) S9xDeinitUpdate (top_level->last_width, top_level->last_height); } } static void dialog_response (GtkDialog *pdialog, gint response_id, gpointer user_data) { std::vector * params = (std::vector *) user_data; switch (response_id) { case GTK_RESPONSE_OK: { std::string config_file = get_config_dir() + "/snes9x.glslp"; S9xDisplayGetDriver ()->save (config_file.c_str ()); realpath (config_file.c_str (), gui_config->shader_filename); if (dialog) gtk_widget_destroy (GTK_WIDGET (dialog)); dialog = NULL; break; } case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: case GTK_RESPONSE_NONE: if (dialog) gtk_widget_destroy (GTK_WIDGET (dialog)); dialog = NULL; *params = saved_params; if (Settings.Paused) S9xDeinitUpdate (top_level->last_width, top_level->last_height); break; default: break; } } void gtk_shader_parameters_dialog_close () { if (dialog) { *params = saved_params; gtk_widget_destroy (GTK_WIDGET (dialog)); dialog = NULL; } } bool gtk_shader_parameters_dialog (GtkWindow *parent) { if (dialog) { gtk_window_present (GTK_WINDOW (dialog)); return false; } params = (std::vector *) S9xDisplayGetDriver()->get_parameters(); saved_params = *params; if (!params || params->size() == 0) return false; dialog = gtk_dialog_new_with_buttons (_("GLSL Shader Parameters"), parent, GTK_DIALOG_DESTROY_WITH_PARENT, "gtk-cancel", GTK_RESPONSE_CANCEL, "gtk-save", GTK_RESPONSE_OK, NULL); g_signal_connect_data (G_OBJECT (dialog), "response", G_CALLBACK (dialog_response), (gpointer) params, NULL, (GConnectFlags) 0); GtkWidget *scrolled_window; gtk_widget_set_size_request(dialog, 640, 480); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG(dialog))), scrolled_window); #if GTK_MAJOR_VERSION >= 3 gtk_widget_set_hexpand (scrolled_window, TRUE); gtk_widget_set_vexpand (scrolled_window, TRUE); gtk_widget_set_margin_start (scrolled_window, 5); gtk_widget_set_margin_end (scrolled_window, 5); gtk_widget_set_margin_top (scrolled_window, 5); gtk_widget_set_margin_bottom (scrolled_window, 5); GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); GtkWidget *grid = gtk_grid_new (); gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE); gtk_grid_set_column_spacing (GTK_GRID (grid), 12); gtk_container_add (GTK_CONTAINER (vbox), grid); gtk_container_add (GTK_CONTAINER (scrolled_window), vbox); for (unsigned int i = 0; i < params->size(); i++) { GLSLParam *p = &(*params)[i]; GtkWidget *label = gtk_label_new (p->name); gtk_label_set_xalign (GTK_LABEL (label), 0.0f); gtk_widget_show (label); gtk_grid_attach (GTK_GRID (grid), label, 0, i, 1, 1); if (p->min == 0.0 && p->max == 1.0 && p->step == 1.0) { GtkWidget *check = gtk_check_button_new (); gtk_grid_attach (GTK_GRID (grid), check, 1, i, 1, 1); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), (int) p->val); g_signal_connect_data (G_OBJECT (check), "toggled", G_CALLBACK (toggled), (gpointer) p, NULL, (GConnectFlags) 0); } else { GtkWidget *scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, p->min, p->max, p->step); gtk_widget_set_hexpand (scale, TRUE); gtk_grid_attach (GTK_GRID (grid), scale, 1, i, 1, 1); gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_LEFT); gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); gtk_scale_set_digits (GTK_SCALE (scale), 3); gtk_range_set_value (GTK_RANGE (scale), p->val); g_signal_connect_data (G_OBJECT (scale), "value-changed", G_CALLBACK (value_changed), (gpointer) p, NULL, (GConnectFlags) 0); } } #else GtkWidget *vbox = gtk_vbox_new (FALSE, 5); GtkWidget *table = gtk_table_new (params->size (), 2, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 5); gtk_table_set_col_spacings (GTK_TABLE (table), 12); gtk_container_add (GTK_CONTAINER (vbox), table); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), vbox); gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 5); for (unsigned int i = 0; i < params->size(); i++) { GLSLParam *p = &(*params)[i]; GtkWidget *label = gtk_label_new (p->name); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_widget_show (label); gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i + 1, GTK_FILL, GTK_FILL, 0, 0); if (p->min == 0.0 && p->max == 1.0 && p->step == 1.0) { GtkWidget *check = gtk_check_button_new (); gtk_table_attach (GTK_TABLE (table), check, 1, 2, i, i + 1, GTK_FILL, GTK_FILL, 0, 0); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), (int) p->val); g_signal_connect_data (G_OBJECT (check), "toggled", G_CALLBACK (toggled), (gpointer) p, NULL, (GConnectFlags) 0); } else { GtkWidget *scale = gtk_hscale_new_with_range (p->min, p->max, p->step); gtk_table_attach (GTK_TABLE (table), scale, 1, 2, i, i + 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), GTK_FILL, 0, 0); gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_LEFT); gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); gtk_scale_set_digits (GTK_SCALE (scale), 3); gtk_range_set_value (GTK_RANGE (scale), p->val); g_signal_connect_data (G_OBJECT (scale), "value-changed", G_CALLBACK (value_changed), (gpointer) p, NULL, (GConnectFlags) 0); } } #endif gtk_widget_show_all (dialog); return true; }