diff options
Diffstat (limited to '')
-rw-r--r-- | plug-ins/lighting/lighting-ui.c | 1557 |
1 files changed, 1557 insertions, 0 deletions
diff --git a/plug-ins/lighting/lighting-ui.c b/plug-ins/lighting/lighting-ui.c new file mode 100644 index 0000000..86b4e12 --- /dev/null +++ b/plug-ins/lighting/lighting-ui.c @@ -0,0 +1,1557 @@ +/* Lighting Effects - A plug-in for GIMP + * + * Dialog creation and updaters, callbacks and event-handlers + * + * 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 3 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, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> +#include <errno.h> + +#include <glib/gstdio.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "lighting-ui.h" +#include "lighting-main.h" +#include "lighting-image.h" +#include "lighting-apply.h" +#include "lighting-preview.h" +#include "lighting-stock.h" + +#include "libgimp/stdplugins-intl.h" + + +extern LightingValues mapvals; + +static GtkWidget *appwin = NULL; +static GtkNotebook *options_note_book = NULL; + +GtkWidget *previewarea = NULL; + +GtkWidget *spin_pos_x = NULL; +GtkWidget *spin_pos_y = NULL; +GtkWidget *spin_pos_z = NULL; +GtkWidget *spin_dir_x = NULL; +GtkWidget *spin_dir_y = NULL; +GtkWidget *spin_dir_z = NULL; + +static GtkWidget *colorbutton; +static GtkWidget *light_type_combo; +static GtkWidget *lightselect_combo; +static GtkWidget *spin_intensity; +static GtkWidget *isolate_button; +static gchar *lighting_effects_path = NULL; + +static void create_main_notebook (GtkWidget *container); + +static void toggle_update (GtkWidget *widget, + gpointer data); + +static void distance_update (GtkAdjustment *adj, + gpointer data); + +static gboolean bumpmap_constrain (gint32 image_id, + gint32 drawable_id, + gpointer data); +static gboolean envmap_constrain (gint32 image_id, + gint32 drawable_id, + gpointer data); +static void envmap_combo_callback (GtkWidget *widget, + gpointer data); +static void save_lighting_preset (GtkWidget *widget, + gpointer data); +static void save_preset_response (GtkFileChooser *chooser, + gint response_id, + gpointer data); +static void load_lighting_preset (GtkWidget *widget, + gpointer data); +static void load_preset_response (GtkFileChooser *chooser, + gint response_id, + gpointer data); +static void lightselect_callback (GimpIntComboBox *combo, + gpointer data); +static void apply_settings (GtkWidget *widget, + gpointer data); +static void isolate_selected_light (GtkWidget *widget, + gpointer data); + +static GtkWidget * spin_button_new (GtkAdjustment **adjustment, /* return value */ + gdouble value, + gdouble lower, + gdouble upper, + gdouble step_increment, + gdouble page_increment, + gdouble page_size, + gdouble climb_rate, + guint digits); + +/**********************/ +/* Std. toggle update */ +/**********************/ + +static void +toggle_update (GtkWidget *widget, + gpointer data) +{ + gimp_toggle_button_update (widget, data); + + preview_compute (); + gtk_widget_queue_draw (previewarea); +} + + +static void +distance_update (GtkAdjustment *adj, + gpointer data) +{ + mapvals.viewpoint.z = gtk_adjustment_get_value (adj); + + preview_compute (); + gtk_widget_queue_draw (previewarea); +} + + +/*****************************************/ +/* Main window light type menu callback. */ +/*****************************************/ + +static void +apply_settings (GtkWidget *widget, + gpointer data) +{ + gint valid; + gint type; + gint k = mapvals.light_selected; + + if (mapvals.update_enabled) + { + valid = gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (light_type_combo), + &type); + if (valid) + mapvals.lightsource[k].type = type; + + gimp_color_button_get_color (GIMP_COLOR_BUTTON (colorbutton), + &mapvals.lightsource[k].color); + + mapvals.lightsource[k].position.x + = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_pos_x)); + mapvals.lightsource[k].position.y + = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_pos_y)); + mapvals.lightsource[k].position.z + = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_pos_z)); + + mapvals.lightsource[k].direction.x + = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_dir_x)); + mapvals.lightsource[k].direction.y + = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_dir_y)); + mapvals.lightsource[k].direction.z + = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_dir_z)); + + mapvals.lightsource[k].intensity + = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_intensity)); + + interactive_preview_callback(NULL); + } + + if (widget == light_type_combo) + { + switch (mapvals.lightsource[k].type) + { + case NO_LIGHT: + gtk_widget_set_sensitive (spin_pos_x, FALSE); + gtk_widget_set_sensitive (spin_pos_y, FALSE); + gtk_widget_set_sensitive (spin_pos_z, FALSE); + gtk_widget_set_sensitive (spin_dir_x, FALSE); + gtk_widget_set_sensitive (spin_dir_y, FALSE); + gtk_widget_set_sensitive (spin_dir_z, FALSE); + break; + case POINT_LIGHT: + gtk_widget_set_sensitive (spin_pos_x, TRUE); + gtk_widget_set_sensitive (spin_pos_y, TRUE); + gtk_widget_set_sensitive (spin_pos_z, TRUE); + gtk_widget_set_sensitive (spin_dir_x, FALSE); + gtk_widget_set_sensitive (spin_dir_y, FALSE); + gtk_widget_set_sensitive (spin_dir_z, FALSE); + break; + case DIRECTIONAL_LIGHT: + gtk_widget_set_sensitive (spin_pos_x, FALSE); + gtk_widget_set_sensitive (spin_pos_y, FALSE); + gtk_widget_set_sensitive (spin_pos_z, FALSE); + gtk_widget_set_sensitive (spin_dir_x, TRUE); + gtk_widget_set_sensitive (spin_dir_y, TRUE); + gtk_widget_set_sensitive (spin_dir_z, TRUE); + break; + default: + break; + } + } +} + +static void +mapmenu2_callback (GtkWidget *widget, + gpointer data) +{ + gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), (gint *) data); + + preview_compute (); + gtk_widget_queue_draw (previewarea); +} + +/******************************************/ +/* Main window "Preview!" button callback */ +/******************************************/ + +static void +preview_callback (GtkWidget *widget) +{ + preview_compute (); + gtk_widget_queue_draw (previewarea); +} + + + + +/*********************************************/ +/* Main window "-" (zoom in) button callback */ +/*********************************************/ +/* +static void +zoomout_callback (GtkWidget *widget) +{ + mapvals.preview_zoom_factor *= 0.5; + draw_preview_image (TRUE); +} +*/ +/*********************************************/ +/* Main window "+" (zoom out) button callback */ +/*********************************************/ +/* +static void +zoomin_callback (GtkWidget *widget) +{ + mapvals.preview_zoom_factor *= 2.0; + draw_preview_image (TRUE); +} +*/ +/**********************************************/ +/* Main window "Apply" button callback. */ +/* Render to GIMP image, close down and exit. */ +/**********************************************/ + +static gint +bumpmap_constrain (gint32 image_id, + gint32 drawable_id, + gpointer data) +{ + return ((gimp_drawable_width (drawable_id) == + gimp_drawable_width (mapvals.drawable_id)) && + (gimp_drawable_height (drawable_id) == + gimp_drawable_height (mapvals.drawable_id))); +} + +static gint +envmap_constrain (gint32 image_id, + gint32 drawable_id, + gpointer data) +{ + return (!gimp_drawable_is_gray (drawable_id) && + !gimp_drawable_has_alpha (drawable_id)); +} + +static void +envmap_combo_callback (GtkWidget *widget, + gpointer data) +{ + gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), + &mapvals.envmap_id); + + env_width = gimp_drawable_width (mapvals.envmap_id); + env_height = gimp_drawable_height (mapvals.envmap_id); +} + +/***********************/ +/* Dialog constructors */ +/***********************/ + +static GtkWidget * +create_options_page (void) +{ + GtkWidget *page; + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *toggle; + GtkWidget *table; + GtkAdjustment *adj; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + /* General options */ + + frame = gimp_frame_new (_("General Options")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_container_add (GTK_CONTAINER (frame), vbox); + gtk_widget_show (vbox); + + toggle = gtk_check_button_new_with_mnemonic (_("T_ransparent background")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.transparent_background); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + g_signal_connect (toggle, "toggled", + G_CALLBACK (toggle_update), + &mapvals.transparent_background); + gtk_widget_show (toggle); + + gimp_help_set_help_data (toggle, + _("Make destination image transparent where bump " + "height is zero"),NULL); + + toggle = gtk_check_button_new_with_mnemonic (_("Cre_ate new image")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.create_new_image); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &mapvals.create_new_image); + gtk_widget_show (toggle); + + gimp_help_set_help_data (toggle, + _("Create a new image when applying filter"), NULL); + + toggle = gtk_check_button_new_with_mnemonic (_("High _quality preview")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.previewquality); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + g_signal_connect (toggle, "toggled", + G_CALLBACK (toggle_update), + &mapvals.previewquality); + gtk_widget_show (toggle); + + gimp_help_set_help_data (toggle, + _("Enable/disable high quality preview"), NULL); + + table = gtk_table_new (1, 3, FALSE); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 12); + gtk_widget_show (table); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 0, + _("Distance:"), 100, 6, + mapvals.viewpoint.z, + 0.0, 2.0, 0.01, 0.05, + 3, TRUE, 0.0, 0.0, + "Distance of observer from surface", + "plug-in-lighting"); + g_signal_connect (adj, "value-changed", + G_CALLBACK (distance_update), + NULL); + + gtk_widget_show (page); + + return page; +} + +/******************************/ +/* Create light settings page */ +/******************************/ + +static GtkWidget * +create_light_page (void) +{ + GtkWidget *page; + GtkWidget *frame; + GtkWidget *table; + GtkWidget *button; + GtkAdjustment *adj; + GtkWidget *label; + gint k = mapvals.light_selected; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (_("Light Settings")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (8, 8, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + gtk_table_set_col_spacing (GTK_TABLE (table), 1, 12); + gtk_table_set_col_spacing (GTK_TABLE (table), 3, 12); + + lightselect_combo = gimp_int_combo_box_new (_("Light 1"), 0, + _("Light 2"), 1, + _("Light 3"), 2, + _("Light 4"), 3, + _("Light 5"), 4, + _("Light 6"), 5, + NULL); + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (lightselect_combo), k); + gtk_table_attach_defaults (GTK_TABLE (table), lightselect_combo, 0, 2, 0, 1); + g_signal_connect (lightselect_combo, "changed", + G_CALLBACK (lightselect_callback), NULL); + gtk_widget_show (lightselect_combo); + + /* row labels */ + label = gtk_label_new (_("Type:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2); + gtk_widget_show (label); + + label = gtk_label_new (_("Color:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3); + gtk_widget_show (label); + + light_type_combo = + gimp_int_combo_box_new (C_("light-source", "None"), NO_LIGHT, + _("Directional"), DIRECTIONAL_LIGHT, + _("Point"), POINT_LIGHT, + /* _("Spot"), SPOT_LIGHT, */ + NULL); + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (light_type_combo), + mapvals.lightsource[k].type); + gtk_table_attach_defaults (GTK_TABLE (table), light_type_combo, + 1, 2, 1, 2); + gtk_widget_show (light_type_combo); + + g_signal_connect (light_type_combo, "changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (light_type_combo, + _("Type of light source to apply"), NULL); + + colorbutton = gimp_color_button_new (_("Select lightsource color"), + 64, 16, + &mapvals.lightsource[k].color, + GIMP_COLOR_AREA_FLAT); + gimp_color_button_set_update (GIMP_COLOR_BUTTON (colorbutton), TRUE); + gtk_widget_show (colorbutton); + gtk_table_attach_defaults (GTK_TABLE (table), + colorbutton, 1, 2, 2, 3); + + g_signal_connect (colorbutton, "color-changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (colorbutton, + _("Set light source color"), NULL); + + + spin_intensity = spin_button_new (&adj, + mapvals.lightsource[k].intensity, + 0.0, 100.0, + 0.01, 0.1, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 3, + _("_Intensity:"), 0.0, 0.5, + spin_intensity, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (spin_intensity, + _("Light intensity"), NULL); + + + label = gtk_label_new (_("Position")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach_defaults (GTK_TABLE (table), label, 3, 4, 0, 1); + gtk_widget_show (label); + + spin_pos_x = spin_button_new (&adj, + mapvals.lightsource[k].position.x, + -100.0, 100.0, + 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 2, 1, + _("_X:"), 0.0, 0.5, + spin_pos_x, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (spin_pos_x, + _("Light source X position in XYZ space"), NULL); + + spin_pos_y = spin_button_new (&adj, + mapvals.lightsource[k].position.y, + -100.0, 100.0, + 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 2, 2, + _("_Y:"), 0.0, 0.5, + spin_pos_y, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (spin_pos_y, + _("Light source Y position in XYZ space"), NULL); + + spin_pos_z = spin_button_new (&adj, + mapvals.lightsource[k].position.z, + -100.0, 100.0, + 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 2, 3, + _("_Z:"), 0.0, 0.5, + spin_pos_z, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (spin_pos_z, + _("Light source Z position in XYZ space"), NULL); + + + label = gtk_label_new (_("Direction")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach_defaults (GTK_TABLE (table), label, 5, 6, 0, 1); + gtk_widget_show (label); + + spin_dir_x = spin_button_new (&adj, + mapvals.lightsource[k].direction.x, + -100.0, 100.0, 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 4, 1, + _("X:"), 0.0, 0.5, + spin_dir_x, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (spin_dir_x, + _("Light source X direction in XYZ space"), NULL); + + spin_dir_y = spin_button_new (&adj, + mapvals.lightsource[k].direction.y, + -100.0, 100.0, 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 4, 2, + _("Y:"), 0.0, 0.5, + spin_dir_y, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (spin_dir_y, + _("Light source Y direction in XYZ space"), NULL); + + spin_dir_z = spin_button_new (&adj, + mapvals.lightsource[k].direction.z, + -100.0, 100.0, 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 4, 3, + _("Z:"), 0.0, 0.5, + spin_dir_z, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (apply_settings), + NULL); + + gimp_help_set_help_data (spin_dir_z, + _("Light source Z direction in XYZ space"), + NULL); + + isolate_button = gtk_check_button_new_with_mnemonic (_("I_solate")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (isolate_button), + mapvals.light_isolated); + g_signal_connect (isolate_button, "toggled", + G_CALLBACK (isolate_selected_light), + NULL); + gtk_table_attach_defaults (GTK_TABLE (table), isolate_button, 0, 1, 5, 6); + gtk_widget_show (isolate_button); + + label = gtk_label_new (_("Lighting preset:")); + gtk_label_set_xalign (GTK_LABEL (label), 1.0); + gtk_table_set_row_spacing (GTK_TABLE (table), 5, 12); + gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 6, 7); + gtk_widget_show (label); + + button = gtk_button_new_with_mnemonic (_("_Save")); + gtk_table_attach_defaults (GTK_TABLE (table), button, 2, 4, 6, 7); + g_signal_connect (button, "clicked", + G_CALLBACK (save_lighting_preset), + NULL); + gtk_widget_show (button); + + button = gtk_button_new_with_mnemonic (_("_Open")); + gtk_table_attach_defaults (GTK_TABLE (table), button, 4, 6, 6, 7); + g_signal_connect (button, "clicked", + G_CALLBACK (load_lighting_preset), + NULL); + gtk_widget_show (button); + + gtk_widget_show (page); + + return page; +} + +/*********************************/ +/* Create material settings page */ +/*********************************/ + +static GtkWidget * +create_material_page (void) +{ + GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + GtkWidget *page; + GtkWidget *frame; + GtkWidget *table; + GtkWidget *label; + GtkWidget *hbox; + GtkWidget *spinbutton; + GtkWidget *image; + GtkWidget *button; + GtkAdjustment *adj; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (_("Material Properties")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_container_add (GTK_CONTAINER (frame), hbox); + gtk_widget_show (hbox); + + table = gtk_table_new (5, 4, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + /* Ambient intensity */ + + image = gtk_image_new_from_stock (STOCK_INTENSITY_AMBIENT_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("_Glowing:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.ambient_int, + 0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (gimp_double_adjustment_update), + &mapvals.material.ambient_int); + g_signal_connect (adj, "value-changed", + G_CALLBACK (interactive_preview_callback), + NULL); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton); + gimp_help_set_help_data (spinbutton, + _("Amount of original color to show where no " + "direct light falls"), NULL); + + image = gtk_image_new_from_stock (STOCK_INTENSITY_AMBIENT_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + /* Diffuse intensity */ + + image = gtk_image_new_from_stock (STOCK_INTENSITY_DIFFUSE_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("_Bright:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.diffuse_int, + 0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (gimp_double_adjustment_update), + &mapvals.material.diffuse_int); + g_signal_connect (adj, "value-changed", + G_CALLBACK (interactive_preview_callback), + NULL); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton); + gimp_help_set_help_data (spinbutton, + _("Intensity of original color when lit by a light " + "source"), NULL); + + image = gtk_image_new_from_stock (STOCK_INTENSITY_DIFFUSE_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + /* Specular reflection */ + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_SPECULAR_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, + _("_Shiny:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.specular_ref, + 0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 2, 3, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (gimp_double_adjustment_update), + &mapvals.material.specular_ref); + g_signal_connect (adj, "value-changed", + G_CALLBACK (interactive_preview_callback), + NULL); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton); + gimp_help_set_help_data (spinbutton, + _("Controls how intense the highlights will be"), + NULL); + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_SPECULAR_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 2, 3, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + /* Highlight */ + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_HIGHLIGHT_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 3, + _("_Polished:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.highlight, + 0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 3, 4, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (gimp_double_adjustment_update), + &mapvals.material.highlight); + g_signal_connect (adj, "value-changed", + G_CALLBACK (interactive_preview_callback), + NULL); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton); + gimp_help_set_help_data (spinbutton, + _("Higher values makes the highlights more focused"), + NULL); + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_HIGHLIGHT_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 3, 4, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + /* Metallic */ + button = gtk_check_button_new_with_mnemonic (_("_Metallic")); + gtk_table_attach (GTK_TABLE (table), button, 0, 3, 4, 5, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (button); + + g_signal_connect (button, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &mapvals.material.metallic); + g_signal_connect (button, "toggled", + G_CALLBACK (interactive_preview_callback), + NULL); + + gtk_widget_show (page); + + return page; +} + +/* Create Bump mapping page */ + +static GtkWidget * +create_bump_page (void) +{ + GtkWidget *page; + GtkWidget *toggle; + GtkWidget *frame; + GtkWidget *table; + GtkWidget *combo; + GtkWidget *spinbutton; + GtkAdjustment *adj; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (NULL); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + toggle = gtk_check_button_new_with_mnemonic (_("E_nable bump mapping")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.bump_mapped); + gtk_frame_set_label_widget (GTK_FRAME (frame), toggle); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &mapvals.bump_mapped); + g_signal_connect (toggle, "toggled", + G_CALLBACK (interactive_preview_callback), + NULL); + + gimp_help_set_help_data (toggle, + _("Enable/disable bump-mapping (image depth)"), + NULL); + + table = gtk_table_new (6, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + g_object_bind_property (toggle, "active", + table, "sensitive", + G_BINDING_SYNC_CREATE); + + combo = gimp_drawable_combo_box_new (bumpmap_constrain, NULL); + gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), mapvals.bumpmap_id, + G_CALLBACK (gimp_int_combo_box_get_active), + &mapvals.bumpmap_id); + + g_signal_connect (combo, "changed", + G_CALLBACK (mapmenu2_callback), + &mapvals.bumpmap_id); + + gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("Bumpm_ap image:"), 0.0, 0.5, + combo, 1, FALSE); + + combo = gimp_int_combo_box_new (_("Linear"), LINEAR_MAP, + _("Logarithmic"), LOGARITHMIC_MAP, + _("Sinusoidal"), SINUSOIDAL_MAP, + _("Spherical"), SPHERICAL_MAP, + NULL); + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), + mapvals.bumpmaptype); + + g_signal_connect (combo, "changed", + G_CALLBACK (mapmenu2_callback), + &mapvals.bumpmaptype); + + gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("Cu_rve:"), 0.0, 0.5, combo, 1, FALSE); + + spinbutton = spin_button_new (&adj, mapvals.bumpmax, + 0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, + _("Ma_ximum height:"), 0.0, 0.5, + spinbutton, 1, TRUE); + g_signal_connect (adj, "value-changed", + G_CALLBACK (gimp_double_adjustment_update), + &mapvals.bumpmax); + g_signal_connect (adj, "value-changed", + G_CALLBACK (interactive_preview_callback), + NULL); + + gimp_help_set_help_data (spinbutton, + _("Maximum height for bumps"), + NULL); + + gtk_widget_show (page); + + return page; +} + +static GtkWidget * +create_environment_page (void) +{ + GtkWidget *page; + GtkWidget *toggle; + GtkWidget *table; + GtkWidget *frame; + GtkWidget *combo; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (NULL); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + toggle = gtk_check_button_new_with_mnemonic (_("E_nable environment mapping")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.env_mapped); + gtk_frame_set_label_widget (GTK_FRAME (frame), toggle); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &mapvals.env_mapped); + g_signal_connect (toggle, "toggled", + G_CALLBACK (interactive_preview_callback), + NULL); + + gimp_help_set_help_data (toggle, + _("Enable/disable environment-mapping (reflection)"), + NULL); + + table = gtk_table_new (3, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + g_object_bind_property (toggle, "active", + table, "sensitive", + G_BINDING_SYNC_CREATE); + + combo = gimp_drawable_combo_box_new (envmap_constrain, NULL); + gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), mapvals.envmap_id, + G_CALLBACK (envmap_combo_callback), + NULL); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("En_vironment image:"), 0.0, 0.5, + combo, 1, FALSE); + + gimp_help_set_help_data (combo, _("Environment image to use"), NULL); + + gtk_widget_show (page); + + return page; +} + +/*****************************/ +/* Create notebook and pages */ +/*****************************/ + +static void +create_main_notebook (GtkWidget *container) +{ + GtkWidget *page; + + options_note_book = GTK_NOTEBOOK (gtk_notebook_new ()); + gtk_container_add (GTK_CONTAINER (container), + GTK_WIDGET (options_note_book)); + + page = create_options_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("Op_tions"))); + + page = create_light_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("_Light"))); + + page = create_material_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("_Material"))); + + page = create_bump_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("_Bump Map"))); + + page = create_environment_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("_Environment Map"))); + + /* + if (mapvals.bump_mapped == TRUE) + { + bump_page = create_bump_page (); + bump_page_pos = g_list_length (options_note_book->children); + gtk_notebook_append_page (options_note_book, bump_page, + gtk_label_new (_("Bumpmap"))); + } + + if (mapvals.env_mapped == TRUE) + { + env_page = create_environment_page (); + env_page_pos = g_list_length (options_note_book->children); + gtk_notebook_append_page (options_note_book, env_page, + gtk_label_new (_("Environment"))); + } + */ + gtk_widget_show (GTK_WIDGET (options_note_book)); +} + +/********************************/ +/* Create and show main dialog. */ +/********************************/ + +gboolean +main_dialog (gint32 drawable_id) +{ + GtkWidget *main_hbox; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *frame; + GtkWidget *button; + GtkWidget *toggle; + gchar *path; + gboolean run = FALSE; + + /* + GtkWidget *image; + */ + + gimp_ui_init (PLUG_IN_BINARY, FALSE); + + path = gimp_gimprc_query ("lighting-effects-path"); + if (path) + { + lighting_effects_path = g_filename_from_utf8 (path, -1, NULL, NULL, NULL); + g_free (path); + } + + lighting_stock_init (); + + appwin = gimp_dialog_new (_("Lighting Effects"), PLUG_IN_ROLE, + NULL, 0, + gimp_standard_help_func, PLUG_IN_PROC, + + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, + + NULL); + + gtk_dialog_set_alternative_button_order (GTK_DIALOG (appwin), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + gimp_window_set_transient (GTK_WINDOW (appwin)); + + main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (appwin))), + main_hbox, FALSE, FALSE, 0); + gtk_widget_show (main_hbox); + + /* Create the Preview */ + /* ================== */ + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0); + gtk_widget_show (vbox); + + /* Add preview widget and various buttons to the first part */ + /* ======================================================== */ + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + gtk_widget_realize (appwin); + + previewarea = gtk_drawing_area_new (); + gtk_widget_set_size_request (previewarea, PREVIEW_WIDTH, PREVIEW_HEIGHT); + gtk_widget_set_events (previewarea, (GDK_EXPOSURE_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK)); + g_signal_connect (previewarea, "event", + G_CALLBACK (preview_events), + previewarea); + g_signal_connect (previewarea, "expose-event", + G_CALLBACK (preview_expose), + previewarea); + gtk_container_add (GTK_CONTAINER (frame), previewarea); + gtk_widget_show (previewarea); + + /* create preview options, frame and vbox */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + button = gtk_button_new_with_mnemonic (_("_Update")); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", + G_CALLBACK (preview_callback), + NULL); + gtk_widget_show (button); + + gimp_help_set_help_data (button, _("Recompute preview image"), NULL); + + toggle = gtk_check_button_new_with_mnemonic (_("I_nteractive")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.interactive_preview); + gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0); + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &mapvals.interactive_preview); + g_signal_connect (toggle, "toggled", + G_CALLBACK (interactive_preview_callback), + NULL); + + gtk_widget_show (toggle); + + gimp_help_set_help_data (toggle, + _("Enable/disable real time preview of changes"), + NULL); + + create_main_notebook (main_hbox); + + gtk_widget_show (appwin); + + { + GdkCursor *cursor; + + cursor = gdk_cursor_new_for_display (gtk_widget_get_display (previewarea), + GDK_HAND2); + gdk_window_set_cursor (gtk_widget_get_window (previewarea), cursor); + gdk_cursor_unref (cursor); + } + + if (image_setup (drawable_id, TRUE)) + preview_compute (); + + if (gimp_dialog_run (GIMP_DIALOG (appwin)) == GTK_RESPONSE_OK) + run = TRUE; + + if (preview_rgb_data != NULL) + g_free (preview_rgb_data); + + if (preview_surface != NULL) + cairo_surface_destroy (preview_surface); + + gtk_widget_destroy (appwin); + + return run; +} + + +static void +save_lighting_preset (GtkWidget *widget, + gpointer data) +{ + static GtkWidget *window = NULL; + + if (! window) + { + window = + gtk_file_chooser_dialog_new (_("Save Lighting Preset"), + GTK_WINDOW (appwin), + GTK_FILE_CHOOSER_ACTION_SAVE, + + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Save"), GTK_RESPONSE_OK, + + NULL); + + gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_OK); + gtk_dialog_set_alternative_button_order (GTK_DIALOG (window), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (window), + TRUE); + + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_widget_destroyed), + &window); + g_signal_connect (window, "response", + G_CALLBACK (save_preset_response), + NULL); + } + + if (lighting_effects_path) + { + GList *list; + gchar *dir; + + list = gimp_path_parse (lighting_effects_path, 256, FALSE, NULL); + dir = gimp_path_get_user_writable_dir (list); + gimp_path_free (list); + + if (! dir) + dir = g_strdup (gimp_directory ()); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), dir); + + g_free (dir); + } + else + { + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), + g_get_tmp_dir ()); + } + + gtk_window_present (GTK_WINDOW (window)); +} + + +static void +save_preset_response (GtkFileChooser *chooser, + gint response_id, + gpointer data) +{ + FILE *fp; + gint num_lights = 0; + gint k; + LightSettings *source; + gchar buffer1[G_ASCII_DTOSTR_BUF_SIZE]; + gchar buffer2[G_ASCII_DTOSTR_BUF_SIZE]; + gchar buffer3[G_ASCII_DTOSTR_BUF_SIZE]; + gint blen = G_ASCII_DTOSTR_BUF_SIZE; + + if (response_id == GTK_RESPONSE_OK) + { + gchar *filename = gtk_file_chooser_get_filename (chooser); + + fp = g_fopen (filename, "wb"); + + if (!fp) + { + g_message (_("Could not open '%s' for writing: %s"), + filename, g_strerror (errno)); + } + else + { + for (k = 0; k < NUM_LIGHTS; k++) + if (mapvals.lightsource[k].type != NO_LIGHT) + ++num_lights; + + fprintf (fp, "Number of lights: %d\n", num_lights); + + for (k = 0; k < NUM_LIGHTS; k++) + if (mapvals.lightsource[k].type != NO_LIGHT) + { + source = &mapvals.lightsource[k]; + + switch (source->type) + { + case POINT_LIGHT: + fprintf (fp, "Type: Point\n"); + break; + case DIRECTIONAL_LIGHT: + fprintf (fp, "Type: Directional\n"); + break; + case SPOT_LIGHT: + fprintf (fp, "Type: Spot\n"); + break; + default: + g_warning ("Unknown light type: %d", + mapvals.lightsource[k].type); + continue; + } + + fprintf (fp, "Position: %s %s %s\n", + g_ascii_dtostr (buffer1, blen, source->position.x), + g_ascii_dtostr (buffer2, blen, source->position.y), + g_ascii_dtostr (buffer3, blen, source->position.z)); + + fprintf (fp, "Direction: %s %s %s\n", + g_ascii_dtostr (buffer1, blen, source->direction.x), + g_ascii_dtostr (buffer2, blen, source->direction.y), + g_ascii_dtostr (buffer3, blen, source->direction.z)); + + fprintf (fp, "Color: %s %s %s\n", + g_ascii_dtostr (buffer1, blen, source->color.r), + g_ascii_dtostr (buffer2, blen, source->color.g), + g_ascii_dtostr (buffer3, blen, source->color.b)); + + fprintf (fp, "Intensity: %s\n", + g_ascii_dtostr (buffer1, blen, source->intensity)); + } + + fclose (fp); + } + + g_free (filename); + } + + gtk_widget_destroy (GTK_WIDGET (chooser)); +} + +static void +load_lighting_preset (GtkWidget *widget, + gpointer data) +{ + static GtkWidget *window = NULL; + + if (! window) + { + window = + gtk_file_chooser_dialog_new (_("Load Lighting Preset"), + GTK_WINDOW (appwin), + GTK_FILE_CHOOSER_ACTION_OPEN, + + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Open"), GTK_RESPONSE_OK, + + NULL); + + gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_OK); + gtk_dialog_set_alternative_button_order (GTK_DIALOG (window), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_widget_destroyed), + &window); + g_signal_connect (window, "response", + G_CALLBACK (load_preset_response), + NULL); + } + + if (lighting_effects_path) + { + GList *list; + gchar *dir; + + list = gimp_path_parse (lighting_effects_path, 256, FALSE, NULL); + dir = gimp_path_get_user_writable_dir (list); + gimp_path_free (list); + + if (! dir) + dir = g_strdup (gimp_directory ()); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), dir); + + g_free (dir); + } + else + { + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), + g_get_tmp_dir ()); + } + + + gtk_window_present (GTK_WINDOW (window)); +} + + +static void +load_preset_response (GtkFileChooser *chooser, + gint response_id, + gpointer data) +{ + FILE *fp; + gint num_lights; + gint k; + LightSettings *source; + gchar buffer1[G_ASCII_DTOSTR_BUF_SIZE]; + gchar buffer2[G_ASCII_DTOSTR_BUF_SIZE]; + gchar buffer3[G_ASCII_DTOSTR_BUF_SIZE]; + gchar type_label[21]; + gchar *endptr; + gchar fmt_str[32]; + + if (response_id == GTK_RESPONSE_OK) + { + gchar *filename = gtk_file_chooser_get_filename (chooser); + + fp = g_fopen (filename, "rb"); + + if (!fp) + { + g_message (_("Could not open '%s' for reading: %s"), + filename, g_strerror (errno)); + } + else + { + fscanf (fp, "Number of lights: %d", &num_lights); + + /* initialize lights to off */ + for (k = 0; k < NUM_LIGHTS; k++) + mapvals.lightsource[k].type = NO_LIGHT; + + for (k = 0; k < num_lights; k++) + { + source = &mapvals.lightsource[k]; + + fscanf (fp, " Type: %20s", type_label); + + if (!strcmp (type_label, "Point")) + source->type = POINT_LIGHT; + else if (!strcmp (type_label, "Directional")) + source->type = DIRECTIONAL_LIGHT; + else if (!strcmp (type_label, "Spot")) + source->type = SPOT_LIGHT; + else + { + g_warning ("Unknown light type: %s", type_label); + fclose (fp); + return; + } + + snprintf (fmt_str, sizeof (fmt_str), + " Position: %%%" G_GSIZE_FORMAT "s %%%" G_GSIZE_FORMAT "s %%%" G_GSIZE_FORMAT "s", + sizeof (buffer1) - 1, + sizeof (buffer2) - 1, + sizeof (buffer3) - 1); + fscanf (fp, fmt_str, buffer1, buffer2, buffer3); + source->position.x = g_ascii_strtod (buffer1, &endptr); + source->position.y = g_ascii_strtod (buffer2, &endptr); + source->position.z = g_ascii_strtod (buffer3, &endptr); + + snprintf (fmt_str, sizeof (fmt_str), + " Direction: %%%" G_GSIZE_FORMAT "s %%%" G_GSIZE_FORMAT "s %%%" G_GSIZE_FORMAT "s", + sizeof (buffer1) - 1, + sizeof (buffer2) - 1, + sizeof (buffer3) - 1); + fscanf (fp, fmt_str, buffer1, buffer2, buffer3); + source->direction.x = g_ascii_strtod (buffer1, &endptr); + source->direction.y = g_ascii_strtod (buffer2, &endptr); + source->direction.z = g_ascii_strtod (buffer3, &endptr); + + snprintf (fmt_str, sizeof (fmt_str), + " Color: %%%" G_GSIZE_FORMAT "s %%%" G_GSIZE_FORMAT "s %%%" G_GSIZE_FORMAT "s", + sizeof (buffer1) - 1, + sizeof (buffer2) - 1, + sizeof (buffer3) - 1); + fscanf (fp, fmt_str, buffer1, buffer2, buffer3); + source->color.r = g_ascii_strtod (buffer1, &endptr); + source->color.g = g_ascii_strtod (buffer2, &endptr); + source->color.b = g_ascii_strtod (buffer3, &endptr); + source->color.a = 1.0; + + snprintf (fmt_str, sizeof (fmt_str), + " Intensity: %%%" G_GSIZE_FORMAT "s", + sizeof (buffer1) - 1); + fscanf (fp, fmt_str, buffer1); + source->intensity = g_ascii_strtod (buffer1, &endptr); + + } + + fclose (fp); + } + + g_free (filename); + + lightselect_callback (GIMP_INT_COMBO_BOX (lightselect_combo), NULL); + } + + gtk_widget_destroy (GTK_WIDGET (chooser)); + interactive_preview_callback (GTK_WIDGET (chooser)); +} + + +static void +lightselect_callback (GimpIntComboBox *combo, + gpointer data) +{ + gint valid; + gint j, k; + + valid = gimp_int_combo_box_get_active (combo, &k); + + if (valid) + { + mapvals.update_enabled = FALSE; /* prevent apply_settings() */ + + mapvals.light_selected = k; + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (light_type_combo), + mapvals.lightsource[k].type); + gimp_color_button_set_color (GIMP_COLOR_BUTTON (colorbutton), + &mapvals.lightsource[k].color); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_x), + mapvals.lightsource[k].position.x); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_y), + mapvals.lightsource[k].position.y); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_z), + mapvals.lightsource[k].position.z); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_x), + mapvals.lightsource[k].direction.x); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_y), + mapvals.lightsource[k].direction.y); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_z), + mapvals.lightsource[k].direction.z); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_intensity), + mapvals.lightsource[k].intensity); + + mapvals.update_enabled = TRUE; + + /* if we are isolating a light, need to switch */ + if (mapvals.light_isolated) + { + for (j = 0; j < NUM_LIGHTS; j++) + if (j == mapvals.light_selected) + mapvals.lightsource[j].active = TRUE; + else + mapvals.lightsource[j].active = FALSE; + } + + interactive_preview_callback (NULL); + } +} + +static void +isolate_selected_light (GtkWidget *widget, + gpointer data) +{ + gint k; + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + { + mapvals.light_isolated = TRUE; + + for (k = 0; k < NUM_LIGHTS; k++) + if (k == mapvals.light_selected) + mapvals.lightsource[k].active = TRUE; + else + mapvals.lightsource[k].active = FALSE; + } + else + { + mapvals.light_isolated = FALSE; + + for (k = 0; k < NUM_LIGHTS; k++) + mapvals.lightsource[k].active = TRUE; + } + + interactive_preview_callback (NULL); +} + +static GtkWidget * +spin_button_new (GtkAdjustment **adjustment, /* return value */ + gdouble value, + gdouble lower, + gdouble upper, + gdouble step_increment, + gdouble page_increment, + gdouble page_size, + gdouble climb_rate, + guint digits) +{ + GtkWidget *spinbutton; + + *adjustment = (GtkAdjustment *) + gtk_adjustment_new (value, lower, upper, + step_increment, page_increment, 0); + + spinbutton = gimp_spin_button_new (GTK_ADJUSTMENT (*adjustment), + climb_rate, digits); + + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); + + return spinbutton; +} |