gimp/plug-ins/Lighting/lighting_ui.c

1183 lines
36 KiB
C

/* 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 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.
*/
#include "config.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 "libgimp/stdplugins-intl.h"
#include "amb1.xpm"
#include "amb2.xpm"
#include "diffint1.xpm"
#include "diffint2.xpm"
#include "diffref1.xpm"
#include "diffref2.xpm"
#include "specref1.xpm"
#include "specref2.xpm"
#include "high1.xpm"
#include "high2.xpm"
extern LightingValues mapvals;
static GtkWidget *appwin = NULL;
static GtkNotebook *options_note_book = NULL;
/*
static GtkWidget *bump_page = NULL;
static GtkWidget *env_page = NULL;
*/
GdkGC *gc = NULL;
GtkWidget *previewarea = NULL;
static GtkWidget *pointlightwid = NULL;
static GtkWidget *dirlightwid = NULL;
/*
static gint bump_page_pos = -1;
static gint env_page_pos = -1;
*/
static void create_main_notebook (GtkWidget *container);
#ifdef _LIGHTNING_UNUSED_CODE
static void xyzval_update (GtkEntry *entry);
#endif
static void toggle_update (GtkWidget *widget,
gpointer data);
/*
static void togglebump_update (GtkWidget *widget,
gpointer data);
static void toggleenvironment_update (GtkWidget *widget,
gpointer data);
*/
static void lightmenu_callback (GtkWidget *widget,
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 GtkWidget *create_bump_page (void);
static GtkWidget *create_environment_page (void);
*/
#ifdef _LIGHTNING_UNUSED_CODE
/**********************************************************/
/* Update entry fields that affect the preview parameters */
/**********************************************************/
static void
xyzval_update (GtkEntry *entry)
{
gdouble *valueptr;
gdouble value;
valueptr = (gdouble *) g_object_get_data (G_OBJECT (entry), "ValuePtr");
value = atof (gtk_entry_get_text (entry));
*valueptr = value;
}
#endif
/**********************/
/* Std. toggle update */
/**********************/
static void
toggle_update (GtkWidget *widget,
gpointer data)
{
gimp_toggle_button_update (widget, data);
draw_preview_image (TRUE);
}
/*****************************/
/* Toggle bumpmapping update */
/*****************************/
/*
static void
togglebump_update (GtkWidget *widget,
gpointer data)
{
gimp_toggle_button_update (widget, data);
if (mapvals.bump_mapped)
{
bump_page_pos = g_list_length (options_note_book->children);
bump_page = create_bump_page ();
gtk_notebook_append_page (options_note_book, bump_page,
gtk_label_new (_("Bumpmap")));
}
else
{
gtk_notebook_remove_page (options_note_book, bump_page_pos);
if (bump_page_pos < env_page_pos)
env_page_pos--;
bump_page_pos = 0;
}
}
*/
/*************************************/
/* Toggle environment mapping update */
/*************************************/
/*
static void
toggleenvironment_update (GtkWidget *widget,
gpointer data)
{
gimp_toggle_button_update (widget, data);
if (mapvals.env_mapped)
{
env_page_pos = g_list_length (options_note_book->children);
env_page = create_environment_page ();
gtk_notebook_append_page (options_note_book, env_page,
gtk_label_new (_("Environment")));
}
else
{
gtk_notebook_remove_page (options_note_book, env_page_pos);
if (env_page_pos < bump_page_pos)
bump_page_pos--;
env_page_pos = 0;
}
}
*/
/*****************************************/
/* Main window light type menu callback. */
/*****************************************/
static void
lightmenu_callback (GtkWidget *widget,
gpointer data)
{
gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), (gint *) data);
if (mapvals.lightsource.type == POINT_LIGHT)
{
gtk_widget_hide (dirlightwid);
gtk_widget_show (pointlightwid);
}
else if (mapvals.lightsource.type == DIRECTIONAL_LIGHT)
{
gtk_widget_hide (pointlightwid);
gtk_widget_show (dirlightwid);
}
else
{
gtk_widget_hide (pointlightwid);
gtk_widget_hide (dirlightwid);
}
interactive_preview_callback(NULL);
}
static void
mapmenu2_callback (GtkWidget *widget,
gpointer data)
{
gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), (gint *) data);
draw_preview_image (TRUE);
}
/******************************************/
/* Main window "Preview!" button callback */
/******************************************/
static void
preview_callback (GtkWidget *widget)
{
draw_preview_image (TRUE);
}
/*********************************************/
/* 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;
page = gtk_vbox_new (FALSE, 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_vbox_new (FALSE, 6);
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_widget_show (vbox);
/*
toggle = gtk_check_button_new_with_label (_("Use Bump Mapping"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
mapvals.bump_mapped);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
g_signal_connect (toggle, "toggled",
G_CALLBACK (togglebump_update),
&mapvals.bump_mapped);
gtk_widget_show (toggle);
gimp_help_set_help_data (toggle,
_("Enable/disable bump-mapping (image depth)"),
NULL);
toggle = gtk_check_button_new_with_label (_("Use Environment Mapping"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
mapvals.env_mapped);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
g_signal_connect (toggle, "toggled",
G_CALLBACK (toggleenvironment_update),
&mapvals.env_mapped);
gtk_widget_show (toggle);
gimp_help_set_help_data (toggle,
_("Enable/disable environment mapping (reflection)"),
NULL);
*/
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);
#if 0
/* Antialiasing options */
/* commented out -- there is no code to implement this -- WES 4/02/04 */
frame = gtk_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 Antialiasing"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
mapvals.antialiasing);
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.antialiasing);
table = gtk_table_new (2, 3, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 12);
gtk_table_set_row_spacings (GTK_TABLE (table), 12);
gtk_container_add (GTK_CONTAINER (frame), table);
gtk_widget_show (table);
gtk_widget_set_sensitive (table, mapvals.antialiasing);
g_object_set_data (G_OBJECT (toggle), "set_sensitive", table);
adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
_("_Depth:"), 0, 6,
mapvals.max_depth, 1.0, 5.0, 0.5, 1.0,
1, TRUE, 0, 0,
_("Antialiasing quality. Higher is better, "
"but slower"), NULL);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.max_depth);
adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
_("T_hreshold:"), 0, 6,
mapvals.pixel_treshold, 0.01, 1000.0, 1.0, 15.0, 2,
TRUE, 0, 0,
_("Stop when pixel differences are smaller than "
"this value"), NULL);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.pixel_treshold);
spinbutton = gimp_spin_button_new (&adj, mapvals.pixel_treshold,
0.001, 1000, 0.1, 1, 1, 0, 3);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.pixel_treshold);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
_("Threshold:"), 0.0, 1.0,
spinbutton, 1, TRUE);
gimp_help_set_help_data (spinbutton,
_("Stop when pixel differences are smaller than "
"this value"), NULL);
#endif
gtk_widget_show (page);
return page;
}
/******************************/
/* Create light settings page */
/******************************/
static GtkWidget *
create_light_page (void)
{
GtkWidget *page;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *combo;
GtkWidget *ebox;
GtkWidget *colorbutton;
GtkObject *adj;
page = gtk_vbox_new (FALSE, 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 (2, 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);
combo = gimp_int_combo_box_new (_("None"), NO_LIGHT,
_("Directional"), DIRECTIONAL_LIGHT,
_("Point"), POINT_LIGHT,
/* _("Spot"), SPOT_LIGHT, */
NULL);
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo),
mapvals.lightsource.type);
g_signal_connect (combo, "changed",
G_CALLBACK (lightmenu_callback),
&mapvals.lightsource.type);
ebox = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (ebox), combo);
gtk_widget_show (combo);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("L_ight Type:"), 0.0, 0.5, ebox, 1, FALSE);
gimp_help_set_help_data (ebox, _("Type of light source to apply"), NULL);
colorbutton = gimp_color_button_new (_("Select Lightsource Color"),
64, 16,
&mapvals.lightsource.color,
GIMP_COLOR_AREA_FLAT);
g_signal_connect (colorbutton, "color_changed",
G_CALLBACK (gimp_color_button_get_color),
&mapvals.lightsource.color);
g_signal_connect (colorbutton, "color_changed",
G_CALLBACK (interactive_preview_callback),
NULL);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
_("Lig_ht Color:"), 0.0, 0.5,
colorbutton, 1, FALSE);
gimp_help_set_help_data (colorbutton,
_("Set light source color"), NULL);
pointlightwid = gimp_frame_new (_("Position"));
gtk_box_pack_start (GTK_BOX (page), pointlightwid, FALSE, FALSE, 0);
if (mapvals.lightsource.type == POINT_LIGHT)
gtk_widget_show (pointlightwid);
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 (pointlightwid), table);
gtk_widget_show (table);
spin_pos_x = gimp_spin_button_new (&adj, mapvals.lightsource.position.x,
-G_MAXFLOAT, G_MAXFLOAT,
0.1, 1.0, 1.0, 0.0, 2);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("_X:"), 0.0, 0.5,
spin_pos_x, 1, TRUE);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.lightsource.position.x);
g_signal_connect (adj, "value_changed",
G_CALLBACK (interactive_preview_callback),
NULL);
gimp_help_set_help_data (spin_pos_x,
_("Light source X position in XYZ space"), NULL);
spin_pos_y = gimp_spin_button_new (&adj, mapvals.lightsource.position.y,
-G_MAXFLOAT, G_MAXFLOAT,
0.1, 1.0, 1.0, 0.0, 2);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
_("_Y:"), 0.0, 0.5,
spin_pos_y, 1, TRUE);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.lightsource.position.y);
g_signal_connect (adj, "value_changed",
G_CALLBACK (interactive_preview_callback),
NULL);
gimp_help_set_help_data (spin_pos_y,
_("Light source Y position in XYZ space"), NULL);
spin_pos_z = gimp_spin_button_new (&adj, mapvals.lightsource.position.z,
-G_MAXFLOAT, G_MAXFLOAT,
0.1, 1.0, 1.0, 0.0, 2);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
_("_Z:"), 0.0, 0.5,
spin_pos_z, 1, TRUE);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.lightsource.position.z);
g_signal_connect (adj, "value_changed",
G_CALLBACK (interactive_preview_callback),
NULL);
gimp_help_set_help_data (spin_pos_z,
_("Light source Z position in XYZ space"), NULL);
dirlightwid = gimp_frame_new (_("Direction Vector"));
gtk_box_pack_start (GTK_BOX (page), dirlightwid, FALSE, FALSE, 0);
if (mapvals.lightsource.type == DIRECTIONAL_LIGHT)
gtk_widget_show (dirlightwid);
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 (dirlightwid), table);
gtk_widget_show (table);
spin_dir_x = gimp_spin_button_new (&adj, mapvals.lightsource.direction.x,
-1.0, 1.0, 0.01, 0.1, 1.0, 0.0, 2);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("X:"), 0.0, 0.5,
spin_dir_x, 1, TRUE);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.lightsource.direction.x);
g_signal_connect (adj, "value_changed",
G_CALLBACK (interactive_preview_callback),
NULL);
gimp_help_set_help_data (spin_dir_x,
_("Light source X direction in XYZ space"), NULL);
spin_dir_y = gimp_spin_button_new (&adj, mapvals.lightsource.direction.y,
-1.0, 1.0, 0.01, 0.1, 1.0, 0.0, 2);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
_("Y:"), 0.0, 0.5,
spin_dir_y, 1, TRUE);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.lightsource.direction.y);
g_signal_connect (adj, "value_changed",
G_CALLBACK (interactive_preview_callback),
NULL);
gimp_help_set_help_data (spin_dir_y,
_("Light source Y direction in XYZ space"), NULL);
spin_dir_z = gimp_spin_button_new (&adj, mapvals.lightsource.direction.z,
-1.0, 1.0, 0.01, 0.1, 1.0, 0.0, 2);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
_("Z:"), 0.0, 0.5,
spin_dir_z, 1, TRUE);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.lightsource.direction.z);
g_signal_connect (adj, "value_changed",
G_CALLBACK (interactive_preview_callback),
NULL);
gimp_help_set_help_data (spin_dir_z,
_("Light source Z direction in XYZ space"), NULL);
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;
GtkObject *adj;
GtkWidget *pixmap;
page = gtk_vbox_new (FALSE, 12);
gtk_container_set_border_width (GTK_CONTAINER (page), 12);
frame = gimp_frame_new (_("Intensity Levels"));
gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
hbox = gtk_hbox_new (FALSE, 6);
gtk_container_add (GTK_CONTAINER (frame), hbox);
gtk_widget_show (hbox);
table = gtk_table_new (2, 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 */
pixmap = gimp_pixmap_new (amb1_xpm);
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("_Ambient:"), 0.0, 0.5,
pixmap, 1, FALSE);
gtk_size_group_add_widget (group, label);
spinbutton = gimp_spin_button_new (&adj, mapvals.material.ambient_int,
0, G_MAXFLOAT, 0.1, 1.0, 1.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);
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_widget_show (spinbutton);
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);
pixmap = gimp_pixmap_new (amb2_xpm);
gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (pixmap);
/* Diffuse intensity */
pixmap = gimp_pixmap_new (diffint1_xpm);
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
_("_Diffuse:"), 0.0, 0.5,
pixmap, 1, FALSE);
gtk_size_group_add_widget (group, label);
spinbutton = gimp_spin_button_new (&adj, mapvals.material.diffuse_int,
0, G_MAXFLOAT, 0.1, 1.0, 1.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);
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_widget_show (spinbutton);
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);
pixmap = gimp_pixmap_new (diffint2_xpm);
gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (pixmap);
frame = gimp_frame_new (_("Reflectivity"));
gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
hbox = gtk_hbox_new (FALSE, 6);
gtk_container_add (GTK_CONTAINER (frame), hbox);
gtk_widget_show (hbox);
table = gtk_table_new (3, 4, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
gtk_widget_show (table);
/* Diffuse reflection */
pixmap = gimp_pixmap_new (diffref1_xpm);
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("D_iffuse:"), 0.0, 0.5,
pixmap, 1, FALSE);
gtk_size_group_add_widget (group, label);
spinbutton = gimp_spin_button_new (&adj, mapvals.material.diffuse_ref,
0, G_MAXFLOAT, 0.1, 1.0, 1.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);
g_signal_connect (adj, "value_changed",
G_CALLBACK (gimp_double_adjustment_update),
&mapvals.material.diffuse_ref);
g_signal_connect (adj, "value_changed",
G_CALLBACK (interactive_preview_callback),
NULL);
gtk_widget_show (spinbutton);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
gimp_help_set_help_data (spinbutton,
_("Higher values makes the object reflect more "
"light (appear lighter)"), NULL);
pixmap = gimp_pixmap_new (diffref2_xpm);
gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (pixmap);
/* Specular reflection */
pixmap = gimp_pixmap_new (specref1_xpm);
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
_("_Specular:"), 0.0, 0.5,
pixmap, 1, FALSE);
gtk_size_group_add_widget (group, label);
spinbutton = gimp_spin_button_new (&adj, mapvals.material.specular_ref,
0, G_MAXFLOAT, 0.1, 1.0, 1.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);
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_widget_show (spinbutton);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
gimp_help_set_help_data (spinbutton,
_("Controls how intense the highlights will be"),
NULL);
pixmap = gimp_pixmap_new (specref2_xpm);
gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (pixmap);
/* Highlight */
pixmap = gimp_pixmap_new (high1_xpm);
label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
_("_Highlight:"), 0.0, 0.5,
pixmap, 1, FALSE);
gtk_size_group_add_widget (group, label);
spinbutton = gimp_spin_button_new (&adj, mapvals.material.highlight,
0, G_MAXFLOAT, 0.1, 1.0, 1.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);
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_widget_show (spinbutton);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
gimp_help_set_help_data (spinbutton,
_("Higher values makes the highlights more focused"),
NULL);
pixmap = gimp_pixmap_new (high2_xpm);
gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (pixmap);
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;
GtkObject *adj;
page = gtk_vbox_new (FALSE, 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);
gtk_widget_set_sensitive (table, mapvals.bump_mapped);
g_object_set_data (G_OBJECT (toggle), "set_sensitive", table);
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);
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 = gimp_spin_button_new (&adj, mapvals.bumpmax,
0, G_MAXFLOAT, 0.01, 0.1, 1.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;
GtkWidget *ebox;
page = gtk_vbox_new (FALSE, 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);
gtk_widget_set_sensitive (table, mapvals.env_mapped);
g_object_set_data (G_OBJECT (toggle), "set_sensitive", table);
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);
ebox = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (ebox), combo);
gtk_widget_show (combo);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("En_vironment Image:"), 0.0, 0.5,
ebox, 1, FALSE);
gimp_help_set_help_data (ebox, _("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 (GimpDrawable *drawable)
{
GtkWidget *main_hbox;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *frame;
GtkWidget *button;
GtkWidget *toggle;
gboolean run = FALSE;
/*
GtkWidget *image;
*/
gimp_ui_init ("Lighting", FALSE);
appwin = gimp_dialog_new (_("Lighting Effects"), "Lighting",
NULL, 0,
gimp_standard_help_func, "plug-in-lighting",
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
main_hbox = gtk_hbox_new (FALSE, 12);
gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (appwin)->vbox), main_hbox,
FALSE, FALSE, 0);
gtk_widget_show (main_hbox);
/* Create the Preview */
/* ================== */
vbox = gtk_vbox_new (FALSE, 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);
gtk_container_add (GTK_CONTAINER (frame), previewarea);
gtk_widget_show (previewarea);
/* create preview options, frame and vbox */
hbox = gtk_hbox_new (FALSE, 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 (previewarea->window, cursor);
gdk_cursor_unref (cursor);
}
image_setup (drawable, TRUE);
if (gimp_dialog_run (GIMP_DIALOG (appwin)) == GTK_RESPONSE_OK)
run = TRUE;
if (preview_rgb_data != NULL)
g_free (preview_rgb_data);
gtk_widget_destroy (appwin);
return run;
}