From 85e884cee16af84ffe72a483bd281c36ea0a4ca8 Mon Sep 17 00:00:00 2001 From: William Skaggs Date: Tue, 20 Jul 2004 18:19:47 +0000 Subject: [PATCH] Bill Skaggs * plug-ins/Lighting/lighting_main.c * plug-ins/Lighting/lighting_main.h * plug-ins/Lighting/lighting_preview.c * plug-ins/Lighting/lighting_preview.h * plug-ins/Lighting/lighting_shade.c * plug-ins/Lighting/lighting_ui.c: completely reworked UI for lighting page. Now supports up to 6 lights (more is trivial). Added ability to temporarily isolate selected light. Added light intensity controls. Can interactively position each light (does not quite work yet for directional lights). --- ChangeLog | 13 + plug-ins/Lighting/lighting_main.c | 27 +- plug-ins/Lighting/lighting_main.h | 67 ++- plug-ins/Lighting/lighting_preview.c | 73 ++-- plug-ins/Lighting/lighting_preview.h | 12 +- plug-ins/Lighting/lighting_shade.c | 274 +++++++------ plug-ins/Lighting/lighting_ui.c | 582 ++++++++++++++++----------- 7 files changed, 612 insertions(+), 436 deletions(-) diff --git a/ChangeLog b/ChangeLog index a9c5d7d74a..e105a823d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2004-07-20 Bill Skaggs + + * plug-ins/Lighting/lighting_main.c + * plug-ins/Lighting/lighting_main.h + * plug-ins/Lighting/lighting_preview.c + * plug-ins/Lighting/lighting_preview.h + * plug-ins/Lighting/lighting_shade.c + * plug-ins/Lighting/lighting_ui.c: completely reworked UI for + lighting page. Now supports up to 6 lights (more is trivial). + Added ability to temporarily isolate selected light. Added + light intensity controls. Can interactively position each light + (does not quite work yet for directional lights). + 2004-07-20 Michael Natterer * app/actions/tools-actions.c: added an icon to the diff --git a/plug-ins/Lighting/lighting_main.c b/plug-ins/Lighting/lighting_main.c index 301387e38f..1a5b778df1 100644 --- a/plug-ins/Lighting/lighting_main.c +++ b/plug-ins/Lighting/lighting_main.c @@ -51,6 +51,10 @@ set_default_settings (void) { gint k; + mapvals.update_enabled = TRUE; + mapvals.light_selected = 0; + mapvals.light_isolated = FALSE; + gimp_vector3_set (&mapvals.viewpoint, 0.5, 0.5, 0.25); gimp_vector3_set (&mapvals.planenormal, 0.0, 0.0, 1.0); @@ -60,6 +64,7 @@ set_default_settings (void) gimp_rgba_set (&mapvals.lightsource[0].color, 1.0, 1.0, 1.0, 1.0); mapvals.lightsource[0].intensity = 1.0; mapvals.lightsource[0].type = POINT_LIGHT; + mapvals.lightsource[0].active = TRUE; /* init lights 2 and 3 pos to upper left and below */ gimp_vector3_set (&mapvals.lightsource[1].position, 2.0, -1.0, 1.0); @@ -68,17 +73,25 @@ set_default_settings (void) gimp_vector3_set (&mapvals.lightsource[2].position, 1.0, 2.0, 1.0); gimp_vector3_set (&mapvals.lightsource[2].direction, 0.0, 1.0, 1.0); - for (k = 1; k < NUM_LIGHTS; k++) + /* init any remaining lights to directly overhead */ + for (k = 3; k < NUM_LIGHTS; k++) { - gimp_rgba_set (&mapvals.lightsource[k].color, 0.0, 0.0, 0.0, 1.0); - mapvals.lightsource[k].intensity = 1.0; - mapvals.lightsource[k].type = NO_LIGHT; + gimp_vector3_set (&mapvals.lightsource[k].position, 0.0, 0.0, 1.0); + gimp_vector3_set (&mapvals.lightsource[k].direction, 0.0, 0.0, 1.0); } - mapvals.material.ambient_int = 0.3; - mapvals.material.diffuse_int = 1.0; + for (k = 1; k < NUM_LIGHTS; k++) + { + gimp_rgba_set (&mapvals.lightsource[k].color, 1.0, 1.0, 1.0, 1.0); + mapvals.lightsource[k].intensity = 1.0; + mapvals.lightsource[k].type = NO_LIGHT; + mapvals.lightsource[k].active = TRUE; + } + + mapvals.material.ambient_int = 0.2; + mapvals.material.diffuse_int = 0.5; mapvals.material.diffuse_ref = 0.4; - mapvals.material.specular_ref = 0.6; + mapvals.material.specular_ref = 0.5; mapvals.material.highlight = 27.0; mapvals.material.metallic = FALSE; diff --git a/plug-ins/Lighting/lighting_main.h b/plug-ins/Lighting/lighting_main.h index 218297d28a..f73a6399d9 100644 --- a/plug-ins/Lighting/lighting_main.h +++ b/plug-ins/Lighting/lighting_main.h @@ -5,7 +5,7 @@ /* ================= */ #define TILE_CACHE_SIZE 16 -#define NUM_LIGHTS 3 +#define NUM_LIGHTS 6 /* Typedefs */ /* ======== */ @@ -14,7 +14,7 @@ typedef enum { POINT_LIGHT, DIRECTIONAL_LIGHT, - SPOT_LIGHT, + SPOT_LIGHT, NO_LIGHT } LightType; @@ -34,13 +34,13 @@ enum typedef struct { - gdouble ambient_int; - gdouble diffuse_int; - gdouble diffuse_ref; - gdouble specular_ref; - gdouble highlight; - gboolean metallic; - GimpRGB color; + gdouble ambient_int; + gdouble diffuse_int; + gdouble diffuse_ref; + gdouble specular_ref; + gdouble highlight; + gboolean metallic; + GimpRGB color; } MaterialSettings; typedef struct @@ -50,13 +50,14 @@ typedef struct GimpVector3 direction; GimpRGB color; gdouble intensity; + gboolean active; } LightSettings; typedef struct { - gint32 drawable_id; - gint32 bumpmap_id; - gint32 envmap_id; + gint32 drawable_id; + gint32 bumpmap_id; + gint32 envmap_id; /* Render variables */ /* ================ */ @@ -67,34 +68,28 @@ typedef struct MaterialSettings material; MaterialSettings ref_material; - gdouble pixel_treshold; - gdouble bumpmax,bumpmin; -/* gdouble wave_cx,wave_cy; - gdouble wave_lx,wave_ly; - gdouble wave_amp,wave_ph; */ - gint max_depth; - gint bumpmaptype; -/* gint bumptype; */ + gdouble pixel_treshold; + gdouble bumpmax,bumpmin; + gint max_depth; + gint bumpmaptype; /* Flags */ - /* ===== */ - - gint antialiasing; - gint create_new_image; - gint transparent_background; - gint bump_mapped; - gint env_mapped; - gint ref_mapped; - gint bumpstretch; - gint previewquality; - gboolean symbols; - gboolean interactive_preview; - + gint antialiasing; + gint create_new_image; + gint transparent_background; + gint bump_mapped; + gint env_mapped; + gint ref_mapped; + gint bumpstretch; + gint previewquality; + gboolean symbols; + gboolean interactive_preview; /* Misc */ - /* ==== */ - - gdouble preview_zoom_factor; + gboolean update_enabled; + gint light_selected; + gboolean light_isolated; + gdouble preview_zoom_factor; } LightingValues; /* Externally visible variables */ diff --git a/plug-ins/Lighting/lighting_preview.c b/plug-ins/Lighting/lighting_preview.c index b8ef806e42..d49b197a4a 100644 --- a/plug-ins/Lighting/lighting_preview.c +++ b/plug-ins/Lighting/lighting_preview.c @@ -224,13 +224,14 @@ gboolean check_handle_hit (gint xpos, gint ypos) { gint dx,dy,r; + gint k = mapvals.light_selected; dx = handle_xpos - xpos; dy = handle_ypos - ypos; - if (mapvals.lightsource[0].type == POINT_LIGHT || - mapvals.lightsource[0].type == DIRECTIONAL_LIGHT) + if (mapvals.lightsource[k].type == POINT_LIGHT || + mapvals.lightsource[k].type == DIRECTIONAL_LIGHT) { r = sqrt (dx * dx + dy * dy) + 0.5; if ((gint) r > 7) @@ -253,10 +254,11 @@ check_handle_hit (gint xpos, gint ypos) static void draw_handles (void) { - gdouble dxpos, dypos; - gint startx, starty, pw, ph; + gdouble dxpos, dypos; + gint startx, starty, pw, ph; GimpVector3 viewpoint; GimpVector3 light_position; + gint k = mapvals.light_selected; gfloat length; gfloat delta_x = 0.0; @@ -264,15 +266,16 @@ draw_handles (void) /* calculate handle position */ compute_preview_rectangle (&startx, &starty, &pw, &ph); - switch (mapvals.lightsource[0].type) + switch (mapvals.lightsource[k].type) { + case NO_LIGHT: + return; case POINT_LIGHT: case SPOT_LIGHT: - case NO_LIGHT: /* swap z to reverse light position */ viewpoint = mapvals.viewpoint; viewpoint.z = -viewpoint.z; - light_position = mapvals.lightsource[0].position; + light_position = mapvals.lightsource[k].position; gimp_vector_3d_to_2d (startx, starty, pw, ph, &dxpos, &dypos, &viewpoint, &light_position); handle_xpos = (gint) (dxpos + 0.5); @@ -285,8 +288,8 @@ draw_handles (void) gimp_vector_3d_to_2d (startx, starty, pw, ph, &dxpos, &dypos, &viewpoint, &light_position); length = PREVIEW_HEIGHT / 4; - delta_x = mapvals.lightsource[0].direction.x * length; - delta_y = mapvals.lightsource[0].direction.y * length; + delta_x = mapvals.lightsource[k].direction.x * length; + delta_y = mapvals.lightsource[k].direction.y * length; handle_xpos = dxpos + delta_x; handle_ypos = dypos + delta_y; break; @@ -294,7 +297,7 @@ draw_handles (void) gdk_gc_set_function (gc, GDK_COPY); - if (mapvals.lightsource[0].type != NO_LIGHT) + if (mapvals.lightsource[k].type != NO_LIGHT) { GdkColor color; @@ -312,7 +315,7 @@ draw_handles (void) } /* calculate backbuffer */ - switch (mapvals.lightsource[0].type) + switch (mapvals.lightsource[k].type) { case POINT_LIGHT: backbuf.x = handle_xpos - LIGHT_SYMBOL_SIZE / 2; @@ -335,12 +338,13 @@ draw_handles (void) backbuf.h = fabs(delta_y) + LIGHT_SYMBOL_SIZE; break; case SPOT_LIGHT: - case NO_LIGHT: backbuf.x = handle_xpos - LIGHT_SYMBOL_SIZE / 2; backbuf.y = handle_ypos - LIGHT_SYMBOL_SIZE / 2; backbuf.w = LIGHT_SYMBOL_SIZE; backbuf.h = LIGHT_SYMBOL_SIZE; break; + case NO_LIGHT: + break; } /* Save background */ @@ -372,7 +376,7 @@ draw_handles (void) gdk_gc_set_rgb_fg_color (gc, &color); /* draw circle at light position */ - switch (mapvals.lightsource[0].type) + switch (mapvals.lightsource[k].type) { case POINT_LIGHT: case SPOT_LIGHT: @@ -406,30 +410,32 @@ void update_light (gint xpos, gint ypos) { gint startx, starty, pw, ph; - GimpVector3 vp; + GimpVector3 vp; + gint k = mapvals.light_selected; compute_preview_rectangle (&startx, &starty, &pw, &ph); vp = mapvals.viewpoint; vp.z = -vp.z; - switch (mapvals.lightsource[0].type) + switch (mapvals.lightsource[k].type) { case NO_LIGHT: + break; case POINT_LIGHT: case SPOT_LIGHT: gimp_vector_2d_to_3d (startx, starty, pw, ph, - xpos, ypos, &vp, &mapvals.lightsource[0].position); + xpos, ypos, &vp, &mapvals.lightsource[k].position); break; case DIRECTIONAL_LIGHT: gimp_vector_2d_to_3d (startx, starty, pw, ph, - xpos, ypos, &vp, &mapvals.lightsource[0].direction); + xpos, ypos, &vp, &mapvals.lightsource[k].direction); break; } } @@ -561,23 +567,24 @@ interactive_preview_callback (GtkWidget *widget) static gboolean interactive_preview_timer_callback ( gpointer data ) { - gint k; + gint k = mapvals.light_selected; - for (k = 0; k < NUM_LIGHTS; k++) - { - gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_x[k]), - mapvals.lightsource[k].position.x); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_y[k]), - mapvals.lightsource[k].position.y); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_z[k]), - mapvals.lightsource[k].position.z); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_x[k]), - mapvals.lightsource[k].direction.x); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_y[k]), - mapvals.lightsource[k].direction.y); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_z[k]), - mapvals.lightsource[k].direction.z); - } + mapvals.update_enabled = FALSE; /* disable apply_settings() */ + + 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); + + mapvals.update_enabled = TRUE; draw_preview_image (TRUE); diff --git a/plug-ins/Lighting/lighting_preview.h b/plug-ins/Lighting/lighting_preview.h index e7efbfa9ba..b42da4365b 100644 --- a/plug-ins/Lighting/lighting_preview.h +++ b/plug-ins/Lighting/lighting_preview.h @@ -35,12 +35,12 @@ extern gdouble *xpostab, *ypostab; extern gboolean light_hit; extern gboolean left_button_pressed; -GtkWidget *spin_pos_x[NUM_LIGHTS]; -GtkWidget *spin_pos_y[NUM_LIGHTS]; -GtkWidget *spin_pos_z[NUM_LIGHTS]; -GtkWidget *spin_dir_x[NUM_LIGHTS]; -GtkWidget *spin_dir_y[NUM_LIGHTS]; -GtkWidget *spin_dir_z[NUM_LIGHTS]; +GtkWidget *spin_pos_x; +GtkWidget *spin_pos_y; +GtkWidget *spin_pos_z; +GtkWidget *spin_dir_x; +GtkWidget *spin_dir_y; +GtkWidget *spin_dir_z; /* Externally visible functions */ diff --git a/plug-ins/Lighting/lighting_shade.c b/plug-ins/Lighting/lighting_shade.c index 89ddae447b..f4e62f53c6 100644 --- a/plug-ins/Lighting/lighting_shade.c +++ b/plug-ins/Lighting/lighting_shade.c @@ -143,8 +143,8 @@ precompute_init (gint w, if (mapvals.bumpmap_id != -1) { bpp = gimp_drawable_bpp(mapvals.bumpmap_id); - } - + } + bumprow = g_new (guchar, w * bpp); triangle_normals[0] = g_new (GimpVector3, (w << 1) + 2); @@ -202,10 +202,10 @@ precompute_normals (gint x1, heights[2] = tmpd; if (mapvals.bumpmap_id != -1) - { + { bpp = gimp_drawable_bpp(mapvals.bumpmap_id); } - + gimp_pixel_rgn_get_row (&bump_region, bumprow, x1, y, x2 - x1); if (mapvals.bumpmaptype > 0) @@ -228,7 +228,7 @@ precompute_normals (gint x1, if (bpp>1) { mapval = (guchar)((float)((bumprow[n * bpp] +bumprow[n * bpp +1] + bumprow[n * bpp + 2])/3.0 )) ; - } + } else { mapval = bumprow[n * bpp]; @@ -244,7 +244,7 @@ precompute_normals (gint x1, if (bpp>1) { mapval = (guchar)((float)((bumprow[n * bpp] +bumprow[n * bpp +1] + bumprow[n * bpp + 2])/3.0 )) ; - } + } else { mapval = bumprow[n * bpp]; @@ -252,7 +252,7 @@ precompute_normals (gint x1, heights[2][n] = (gdouble) mapvals.bumpmax * (gdouble) mapval / 255.0; } } - + /* Compute triangle normals */ /* ======================== */ @@ -260,7 +260,7 @@ precompute_normals (gint x1, for (n = 0; n < (x2 - x1 - 1); n++) { p1.x = 0.0; - p1.y = ystep; + p1.y = ystep; p1.z = heights[2][n] - heights[1][n]; p2.x = xstep; @@ -384,7 +384,7 @@ sphere_to_image (GimpVector3 *normal, if (fac>1.0) fac = 1.0; - else if (fac<-1.0) + else if (fac<-1.0) fac = -1.0; *u = acos (fac) / (2.0 * G_PI); @@ -404,17 +404,18 @@ GimpRGB get_ray_color (GimpVector3 *position) { GimpRGB color; + GimpRGB color_int; GimpRGB color_sum; GimpRGB light_color; gint x, f; gdouble xf, yf; GimpVector3 normal, *p; gint k; - + pos_to_float (position->x, position->y, &xf, &yf); - + x = RINT (xf); - + if (mapvals.transparent_background && heights[1][x] == 0) { gimp_rgb_set_alpha (&color_sum, 0.0); @@ -422,19 +423,23 @@ get_ray_color (GimpVector3 *position) else { color = get_image_color (xf, yf, &f); - + color_sum = color; gimp_rgb_multiply (&color_sum, mapvals.material.ambient_int); - + for (k = 0; k < NUM_LIGHTS; k++) { - if (mapvals.lightsource[k].type == NO_LIGHT) + if (!mapvals.lightsource[k].active + || mapvals.lightsource[k].type == NO_LIGHT) continue; else if (mapvals.lightsource[k].type == POINT_LIGHT) p = &mapvals.lightsource[k].position; else p = &mapvals.lightsource[k].direction; - + + color_int = mapvals.lightsource[k].color; + gimp_rgb_multiply (&color_int, mapvals.lightsource[k].intensity); + if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1) { light_color = phong_shade (position, @@ -442,22 +447,22 @@ get_ray_color (GimpVector3 *position) &mapvals.planenormal, p, &color, - &mapvals.lightsource[k].color, + &color_int, mapvals.lightsource[k].type); } else { normal = vertex_normals[1][(gint) RINT (xf)]; - + light_color = phong_shade (position, &mapvals.viewpoint, &normal, p, &color, - &mapvals.lightsource[k].color, + &color_int, mapvals.lightsource[k].type); } - + gimp_rgb_add (&color_sum, &light_color); } } @@ -469,10 +474,14 @@ get_ray_color (GimpVector3 *position) GimpRGB get_ray_color_ref (GimpVector3 *position) { + GimpRGB color_sum; + GimpRGB color_int; + GimpRGB light_color; GimpRGB color, env_color; - gint x, f; - gdouble xf, yf; - GimpVector3 normal, *p, v, r; + gint x, f; + gdouble xf, yf; + GimpVector3 normal, *p, v, r; + gint k; pos_to_float (position->x, position->y, &xf, &yf); @@ -485,60 +494,74 @@ get_ray_color_ref (GimpVector3 *position) else { color = get_image_color (xf, yf, &f); + color_sum = color; - if (mapvals.lightsource[0].type == POINT_LIGHT) - p = &mapvals.lightsource[0].position; - else - p = &mapvals.lightsource[0].direction; - - if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1) + for (k = 0; k < NUM_LIGHTS; k++) { - color = phong_shade (position, - &mapvals.viewpoint, - &mapvals.planenormal, - p, - &color, - &mapvals.lightsource[0].color, - mapvals.lightsource[0].type); - } - else - { - normal = vertex_normals[1][(gint) RINT (xf)]; + if (!mapvals.lightsource[k].active + || mapvals.lightsource[k].type == NO_LIGHT) + continue; + else if (mapvals.lightsource[k].type == POINT_LIGHT) + p = &mapvals.lightsource[k].position; + else + p = &mapvals.lightsource[k].direction; - gimp_vector3_sub (&v, &mapvals.viewpoint,position); - gimp_vector3_normalize (&v); + color_int = mapvals.lightsource[k].color; + gimp_rgb_multiply (&color_int, mapvals.lightsource[k].intensity); - r = compute_reflected_ray (&normal, &v); + if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1) + { + light_color = phong_shade (position, + &mapvals.viewpoint, + &mapvals.planenormal, + p, + &color, + &color_int, + mapvals.lightsource[0].type); + } + else + { + normal = vertex_normals[1][(gint) RINT (xf)]; - /* Get color in the direction of r */ - /* =============================== */ + gimp_vector3_sub (&v, &mapvals.viewpoint,position); + gimp_vector3_normalize (&v); - sphere_to_image (&r, &xf, &yf); - env_color = peek_env_map (RINT (env_width * xf), - RINT (env_height * yf)); + r = compute_reflected_ray (&normal, &v); - color = phong_shade (position, - &mapvals.viewpoint, - &normal, - p, - &env_color, - &mapvals.lightsource[0].color, - mapvals.lightsource[0].type); + /* Get color in the direction of r */ + /* =============================== */ + + sphere_to_image (&r, &xf, &yf); + env_color = peek_env_map (RINT (env_width * xf), + RINT (env_height * yf)); + + light_color = phong_shade (position, + &mapvals.viewpoint, + &normal, + p, + &env_color, + &color_int, + mapvals.lightsource[0].type); + } + + gimp_rgb_add (&color_sum, &light_color); } } - return color; + gimp_rgb_clamp (&color_sum); + return color_sum; } GimpRGB get_ray_color_no_bilinear (GimpVector3 *position) { - GimpRGB color; + GimpRGB color; + GimpRGB color_int; GimpRGB color_sum; GimpRGB light_color; - gint x; - gdouble xf, yf; - GimpVector3 normal, *p; + gint x; + gdouble xf, yf; + GimpVector3 normal, *p; gint k; @@ -559,13 +582,17 @@ get_ray_color_no_bilinear (GimpVector3 *position) for (k = 0; k < NUM_LIGHTS; k++) { - if (mapvals.lightsource[k].type == NO_LIGHT) + if (!mapvals.lightsource[k].active + || mapvals.lightsource[k].type == NO_LIGHT) continue; else if (mapvals.lightsource[k].type == POINT_LIGHT) p = &mapvals.lightsource[k].position; else p = &mapvals.lightsource[k].direction; + color_int = mapvals.lightsource[k].color; + gimp_rgb_multiply (&color_int, mapvals.lightsource[k].intensity); + if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1) { light_color = phong_shade (position, @@ -573,26 +600,26 @@ get_ray_color_no_bilinear (GimpVector3 *position) &mapvals.planenormal, p, &color, - &mapvals.lightsource[k].color, + &color_int, mapvals.lightsource[k].type); } else { normal = vertex_normals[1][x]; - + light_color = phong_shade (position, &mapvals.viewpoint, &normal, p, &color, - &mapvals.lightsource[k].color, + &color_int, mapvals.lightsource[k].type); } gimp_rgb_add (&color_sum, &light_color); } } - + gimp_rgb_clamp (&color_sum); return color_sum; } @@ -600,10 +627,14 @@ get_ray_color_no_bilinear (GimpVector3 *position) GimpRGB get_ray_color_no_bilinear_ref (GimpVector3 *position) { + GimpRGB color_sum; + GimpRGB color_int; + GimpRGB light_color; GimpRGB color, env_color; - gint x; - gdouble xf, yf; - GimpVector3 normal, *p, v, r; + gint x; + gdouble xf, yf; + GimpVector3 normal, *p, v, r; + gint k; pos_to_float (position->x, position->y, &xf, &yf); @@ -611,71 +642,84 @@ get_ray_color_no_bilinear_ref (GimpVector3 *position) if (mapvals.transparent_background && heights[1][x] == 0) { - gimp_rgb_set_alpha (&color, 0.0); + gimp_rgb_set_alpha (&color_sum, 0.0); } else { color = peek (RINT (xf), RINT (yf)); + color_sum = color; - if (mapvals.lightsource[0].type == POINT_LIGHT) - p = &mapvals.lightsource[0].position; - else - p = &mapvals.lightsource[0].direction; - - if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1) + for (k = 0; k < NUM_LIGHTS; k++) { - pos_to_float (position->x, position->y, &xf, &yf); + if (!mapvals.lightsource[k].active + || mapvals.lightsource[k].type == NO_LIGHT) + continue; + else if (mapvals.lightsource[k].type == POINT_LIGHT) + p = &mapvals.lightsource[k].position; + else + p = &mapvals.lightsource[k].direction; - color = peek (RINT (xf), RINT (yf)); + color_int = mapvals.lightsource[k].color; + gimp_rgb_multiply (&color_int, mapvals.lightsource[k].intensity); - gimp_vector3_sub (&v, &mapvals.viewpoint, position); - gimp_vector3_normalize (&v); + if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1) + { + pos_to_float (position->x, position->y, &xf, &yf); - r = compute_reflected_ray (&mapvals.planenormal, &v); + color = peek (RINT (xf), RINT (yf)); - /* Get color in the direction of r */ - /* =============================== */ + gimp_vector3_sub (&v, &mapvals.viewpoint, position); + gimp_vector3_normalize (&v); - sphere_to_image (&r, &xf, &yf); - env_color = peek_env_map (RINT (env_width * xf), - RINT (env_height * yf)); + r = compute_reflected_ray (&mapvals.planenormal, &v); - color = phong_shade (position, - &mapvals.viewpoint, - &mapvals.planenormal, - p, - &env_color, - &mapvals.lightsource[0].color, - mapvals.lightsource[0].type); - } - else - { - normal = vertex_normals[1][(gint) RINT (xf)]; + /* Get color in the direction of r */ + /* =============================== */ - pos_to_float (position->x, position->y, &xf, &yf); - color = peek (RINT (xf), RINT (yf)); + sphere_to_image (&r, &xf, &yf); + env_color = peek_env_map (RINT (env_width * xf), + RINT (env_height * yf)); - gimp_vector3_sub (&v, &mapvals.viewpoint, position); - gimp_vector3_normalize (&v); + light_color = phong_shade (position, + &mapvals.viewpoint, + &mapvals.planenormal, + p, + &env_color, + &color_int, + mapvals.lightsource[0].type); + } + else + { + normal = vertex_normals[1][(gint) RINT (xf)]; - r = compute_reflected_ray (&normal, &v); + pos_to_float (position->x, position->y, &xf, &yf); + color = peek (RINT (xf), RINT (yf)); - /* Get color in the direction of r */ - /* =============================== */ - - sphere_to_image (&r, &xf, &yf); - env_color = peek_env_map (RINT (env_width * xf), - RINT (env_height * yf)); + gimp_vector3_sub (&v, &mapvals.viewpoint, position); + gimp_vector3_normalize (&v); - color = phong_shade (position, - &mapvals.viewpoint, - &normal, - p, - &env_color, - &mapvals.lightsource[0].color, - mapvals.lightsource[0].type); + r = compute_reflected_ray (&normal, &v); + + /* Get color in the direction of r */ + /* =============================== */ + + sphere_to_image (&r, &xf, &yf); + env_color = peek_env_map (RINT (env_width * xf), + RINT (env_height * yf)); + + light_color = phong_shade (position, + &mapvals.viewpoint, + &normal, + p, + &env_color, + &color_int, + mapvals.lightsource[0].type); + + gimp_rgb_add (&color_sum, &light_color); + } } } - return color; + gimp_rgb_clamp (&color_sum); + return color_sum; } diff --git a/plug-ins/Lighting/lighting_ui.c b/plug-ins/Lighting/lighting_ui.c index d9347a1efc..053124d4ff 100644 --- a/plug-ins/Lighting/lighting_ui.c +++ b/plug-ins/Lighting/lighting_ui.c @@ -35,53 +35,54 @@ #include "libgimp/stdplugins-intl.h" - extern LightingValues mapvals; static GtkWidget *appwin = NULL; static GtkNotebook *options_note_book = NULL; +GdkGC *gc = NULL; +GtkWidget *previewarea = NULL; -GdkGC *gc = NULL; -GtkWidget *previewarea = NULL; - -static GtkWidget *pointlightwid[NUM_LIGHTS]; -static GtkWidget *dirlightwid[NUM_LIGHTS]; -static GtkWidget *colorbutton[NUM_LIGHTS]; -static GtkWidget *light_type_combo[NUM_LIGHTS]; +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 create_main_notebook (GtkWidget *container); #ifdef _LIGHTNING_UNUSED_CODE -static void xyzval_update (GtkEntry *entry); +static void xyzval_update (GtkEntry *entry); #endif -static void toggle_update (GtkWidget *widget, - gpointer data); +static void toggle_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 void save_lighting_preset (GtkWidget *widget, - gpointer data); -static void file_chooser_response (GtkFileChooser *chooser, - gint response_id, - gpointer data); -static void load_lighting_preset (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 void save_lighting_preset (GtkWidget *widget, + gpointer data); +static void file_chooser_response (GtkFileChooser *chooser, + gint response_id, + gpointer data); +static void load_lighting_preset (GtkWidget *widget, + gpointer data); static void load_file_chooser_response (GtkFileChooser *chooser, - gint response_id, - gpointer data); + 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); #ifdef _LIGHTNING_UNUSED_CODE @@ -122,35 +123,42 @@ toggle_update (GtkWidget *widget, /*****************************************/ static void -lightmenu_callback (GtkWidget *widget, - gpointer data) +apply_settings (GtkWidget *widget, + gpointer data) { - gint k; + gint valid; + gint type; + gint k = mapvals.light_selected; - gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), (gint *) data); - - for (k = 0; k < NUM_LIGHTS; k++) + if (mapvals.update_enabled) { - switch (mapvals.lightsource[k].type) - { - case POINT_LIGHT: - gtk_widget_hide (dirlightwid[k]); - gtk_widget_show (pointlightwid[k]); - break; + valid = gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (light_type_combo), + &type); + if (valid) + mapvals.lightsource[k].type = type; - case DIRECTIONAL_LIGHT: - gtk_widget_hide (pointlightwid[k]); - gtk_widget_show (dirlightwid[k]); - break; + gimp_color_button_get_color (GIMP_COLOR_BUTTON (colorbutton), + &mapvals.lightsource[k].color); - default: - gtk_widget_hide (pointlightwid[k]); - gtk_widget_hide (dirlightwid[k]); - break; - } + 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); } - - interactive_preview_callback(NULL); } static void @@ -311,13 +319,11 @@ create_light_page (void) GtkWidget *page; GtkWidget *frame; GtkWidget *table; - GtkWidget *table2; GtkWidget *ebox; GtkWidget *button; GtkObject *adj; GtkWidget *label; - gint k; - gchar label_text[20]; + gint k = mapvals.light_selected; page = gtk_vbox_new (FALSE, 12); gtk_container_set_border_width (GTK_CONTAINER (page), 12); @@ -332,6 +338,22 @@ create_light_page (void) 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_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); @@ -343,193 +365,169 @@ create_light_page (void) gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3); gtk_widget_show (label); - gtk_table_set_col_spacing (GTK_TABLE (table), 2, 12); - gtk_table_set_col_spacing (GTK_TABLE (table), 4, 12); + light_type_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 (light_type_combo), + mapvals.lightsource[k].type); + g_signal_connect (light_type_combo, "changed", + G_CALLBACK (apply_settings), + NULL); - for (k = 0; k < NUM_LIGHTS; k++) - { - g_snprintf (label_text, sizeof (label_text), "Light %d", k + 1); - label = gtk_label_new (label_text); - gtk_table_attach_defaults (GTK_TABLE (table), - label, 2*k + 1, 2*k + 2, 0, 1); - gtk_widget_show (label); + ebox = gtk_event_box_new (); + gtk_container_add (GTK_CONTAINER (ebox), light_type_combo); + gtk_widget_show (ebox); + gtk_table_attach_defaults (GTK_TABLE (table), + ebox, 1, 2, 1, 2); + gtk_widget_show (light_type_combo); + gimp_help_set_help_data (ebox, _("Type of light source to apply"), NULL); - light_type_combo[k] = - 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 (light_type_combo[k]), - mapvals.lightsource[k].type); - g_signal_connect (light_type_combo[k], "changed", - G_CALLBACK (lightmenu_callback), - &mapvals.lightsource[k].type); + 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); + g_signal_connect (colorbutton, "color_changed", + G_CALLBACK (apply_settings), + NULL); + gtk_widget_show (colorbutton); + gtk_table_attach_defaults (GTK_TABLE (table), + colorbutton, 1, 2, 2, 3); + gimp_help_set_help_data (colorbutton, + _("Set light source color"), NULL); - ebox = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER (ebox), light_type_combo[k]); - gtk_widget_show (ebox); - gtk_table_attach_defaults (GTK_TABLE (table), - ebox, 2*k + 1, 2*k + 2, 1, 2); - gtk_widget_show (light_type_combo[k]); - gimp_help_set_help_data (ebox, _("Type of light source to apply"), NULL); - colorbutton[k] = gimp_color_button_new (_("Select lightsource color"), - 64, 16, - &mapvals.lightsource[k].color, - GIMP_COLOR_AREA_FLAT); - g_signal_connect (colorbutton[k], "color_changed", - G_CALLBACK (gimp_color_button_get_color), - &mapvals.lightsource[k].color); - g_signal_connect (colorbutton[k], "color_changed", - G_CALLBACK (interactive_preview_callback), - NULL); - gtk_widget_show (colorbutton[k]); - gtk_table_attach_defaults (GTK_TABLE (table), - colorbutton[k], 2*k + 1, 2*k + 2, 2, 3); - gimp_help_set_help_data (colorbutton[k], - _("Set light source color"), NULL); + spin_intensity = gimp_spin_button_new (&adj, + mapvals.lightsource[k].intensity, + 0.0, 100.0, + 0.01, 0.1, 1.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); - /* Position vector settings */ - pointlightwid[k] = gtk_vbox_new (FALSE, 0); - if (mapvals.lightsource[k].type == POINT_LIGHT) - gtk_widget_show (pointlightwid[k]); - table2 = gtk_table_new (3, 2, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table2), 6); - gtk_table_set_row_spacings (GTK_TABLE (table2), 6); - gtk_container_add (GTK_CONTAINER (pointlightwid[k]), table2); - gtk_table_attach_defaults (GTK_TABLE (table), - pointlightwid[k], 2*k + 1, 2*k + 2, 4, 5); - gtk_widget_show (table2); + label = gtk_label_new (_("Position")); + gtk_table_attach_defaults (GTK_TABLE (table), label, 3, 4, 0, 1); + gtk_widget_show (label); - spin_pos_x[k] = gimp_spin_button_new (&adj, - mapvals.lightsource[k].position.x, - -100.0, 100.0, - 0.1, 1.0, 1.0, 0.0, 2); - gimp_table_attach_aligned (GTK_TABLE (table2), 0, 0, + spin_pos_x = gimp_spin_button_new (&adj, + mapvals.lightsource[k].position.x, + -100.0, 100.0, + 0.1, 1.0, 1.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 2, 1, _("_X:"), 0.0, 0.5, - spin_pos_x[k], 1, TRUE); - g_signal_connect (adj, "value_changed", - G_CALLBACK (gimp_double_adjustment_update), - &mapvals.lightsource[k].position.x); - g_signal_connect (adj, "value_changed", - G_CALLBACK (interactive_preview_callback), - NULL); - gimp_help_set_help_data (spin_pos_x[k], - _("Light source X position in XYZ space"), NULL); + 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[k] = gimp_spin_button_new (&adj, - mapvals.lightsource[k].position.y, - -100.0, 100.0, - 0.1, 1.0, 1.0, 0.0, 2); - gimp_table_attach_aligned (GTK_TABLE (table2), 0, 1, - _("_Y:"), 0.0, 0.5, - spin_pos_y[k], 1, TRUE); - g_signal_connect (adj, "value_changed", - G_CALLBACK (gimp_double_adjustment_update), - &mapvals.lightsource[k].position.y); - g_signal_connect (adj, "value_changed", - G_CALLBACK (interactive_preview_callback), - NULL); - gimp_help_set_help_data (spin_pos_y[k], + spin_pos_y = gimp_spin_button_new (&adj, + mapvals.lightsource[k].position.y, + -100.0, 100.0, + 0.1, 1.0, 1.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[k] = gimp_spin_button_new (&adj, - mapvals.lightsource[k].position.z, - -100.0, 100.0, - 0.1, 1.0, 1.0, 0.0, 2); - gimp_table_attach_aligned (GTK_TABLE (table2), 0, 2, - _("_Z:"), 0.0, 0.5, - spin_pos_z[k], 1, TRUE); - g_signal_connect (adj, "value_changed", - G_CALLBACK (gimp_double_adjustment_update), - &mapvals.lightsource[k].position.z); - g_signal_connect (adj, "value_changed", - G_CALLBACK (interactive_preview_callback), - NULL); - gimp_help_set_help_data (spin_pos_z[k], - _("Light source Z position in XYZ space"), NULL); + spin_pos_z = gimp_spin_button_new (&adj, + mapvals.lightsource[k].position.z, + -100.0, 100.0, + 0.1, 1.0, 1.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); - /* Direction vector settings */ - dirlightwid[k] = gtk_vbox_new (FALSE, 0); - if (mapvals.lightsource[k].type == DIRECTIONAL_LIGHT) - gtk_widget_show (dirlightwid[k]); - table2 = gtk_table_new (3, 2, FALSE); - gtk_widget_show (table2); - gtk_table_set_col_spacings (GTK_TABLE (table2), 6); - gtk_table_set_row_spacings (GTK_TABLE (table2), 6); - gtk_container_add (GTK_CONTAINER (dirlightwid[k]), table2); - gtk_table_attach_defaults (GTK_TABLE (table), - dirlightwid[k], 2*k + 1, 2*k + 2, 4, 5); + label = gtk_label_new (_("Direction")); + gtk_table_attach_defaults (GTK_TABLE (table), label, 5, 6, 0, 1); + gtk_widget_show (label); - spin_dir_x[k] = gimp_spin_button_new (&adj, - mapvals.lightsource[k].direction.x, - -100.0, 100.0, 0.1, 1.0, 1.0, 0.0, 2); - gimp_table_attach_aligned (GTK_TABLE (table2), 0, 0, - _("X:"), 0.0, 0.5, - spin_dir_x[k], 1, TRUE); - g_signal_connect (adj, "value_changed", - G_CALLBACK (gimp_double_adjustment_update), - &mapvals.lightsource[k].direction.x); - g_signal_connect (adj, "value_changed", - G_CALLBACK (interactive_preview_callback), - NULL); - gimp_help_set_help_data (spin_dir_x[k], - _("Light source X direction in XYZ space"), NULL); + spin_dir_x = gimp_spin_button_new (&adj, + mapvals.lightsource[k].direction.x, + -100.0, 100.0, 0.1, 1.0, 1.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[k] = gimp_spin_button_new (&adj, - mapvals.lightsource[k].direction.y, - -100.0, 100.0, 0.1, 1.0, 1.0, 0.0, 2); - gimp_table_attach_aligned (GTK_TABLE (table2), 0, 1, - _("Y:"), 0.0, 0.5, - spin_dir_y[k], 1, TRUE); - g_signal_connect (adj, "value_changed", - G_CALLBACK (gimp_double_adjustment_update), - &mapvals.lightsource[k].direction.y); - g_signal_connect (adj, "value_changed", - G_CALLBACK (interactive_preview_callback), - NULL); - gimp_help_set_help_data (spin_dir_y[k], - _("Light source Y direction in XYZ space"), NULL); + spin_dir_y = gimp_spin_button_new (&adj, + mapvals.lightsource[k].direction.y, + -100.0, 100.0, 0.1, 1.0, 1.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[k] = gimp_spin_button_new (&adj, - mapvals.lightsource[k].direction.z, - -100.0, 100.0, 0.1, 1.0, 1.0, 0.0, 2); - gimp_table_attach_aligned (GTK_TABLE (table2), 0, 2, - _("Z:"), 0.0, 0.5, - spin_dir_z[k], 1, TRUE); - g_signal_connect (adj, "value_changed", - G_CALLBACK (gimp_double_adjustment_update), - &mapvals.lightsource[k].direction.z); - g_signal_connect (adj, "value_changed", - G_CALLBACK (interactive_preview_callback), - NULL); - gimp_help_set_help_data (spin_dir_z[k], - _("Light source Z direction in XYZ space"), - NULL); + spin_dir_z = gimp_spin_button_new (&adj, + mapvals.lightsource[k].direction.z, + -100.0, 100.0, 0.1, 1.0, 1.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); - label = gtk_label_new (_("Lighting preset:")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_table_set_row_spacing (GTK_TABLE (table), 4, 24); - gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 3, 5, 6); - gtk_widget_show (label); + isolate_button = gtk_toggle_button_new_with_mnemonic (_("I_solate")); + gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (isolate_button), FALSE); + 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); - button = gtk_button_new_from_stock (GTK_STOCK_SAVE); - gtk_table_attach_defaults (GTK_TABLE (table), button, 3, 4, 5, 6); - g_signal_connect (button, "clicked", - G_CALLBACK (save_lighting_preset), - NULL); - gtk_widget_show (button); + label = gtk_label_new (_("Lighting preset:")); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + 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_from_stock (GTK_STOCK_OPEN); - gtk_table_attach_defaults (GTK_TABLE (table), button, 5, 6, 5, 6); - g_signal_connect (button, "clicked", - G_CALLBACK (load_lighting_preset), - NULL); - gtk_widget_show (button); - } + button = gtk_button_new_from_stock (GTK_STOCK_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_from_stock (GTK_STOCK_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); @@ -579,7 +577,7 @@ create_material_page (void) image, 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); + 0, G_MAXFLOAT, 0.01, 0.1, 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", @@ -608,7 +606,7 @@ create_material_page (void) image, 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); + 0, G_MAXFLOAT, 0.01, 0.1, 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", @@ -637,7 +635,7 @@ create_material_page (void) image, 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); + 0, G_MAXFLOAT, 0.01, 0.1, 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", @@ -665,7 +663,7 @@ create_material_page (void) image, 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); + 0, G_MAXFLOAT, 0.01, 0.1, 1.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); g_signal_connect (adj, "value_changed", @@ -1001,7 +999,6 @@ main_dialog (GimpDrawable *drawable) G_CALLBACK (interactive_preview_callback), NULL); - gtk_widget_show (toggle); gimp_help_set_help_data (toggle, @@ -1083,7 +1080,6 @@ save_lighting_preset (GtkWidget *widget, g_get_tmp_dir ()); } - gtk_window_present (GTK_WINDOW (window)); } @@ -1255,6 +1251,10 @@ load_file_chooser_response (GtkFileChooser *chooser, { 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]; @@ -1293,17 +1293,121 @@ load_file_chooser_response (GtkFileChooser *chooser, fscanf (fp, " Intensity: %s", buffer1); source->intensity = g_ascii_strtod (buffer1, &endptr); - gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (light_type_combo[k]), - source->type); - gimp_color_button_set_color (GIMP_COLOR_BUTTON (colorbutton[k]), - &source->color); - } + } fclose (fp); } - } + + 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; + + 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; + } + + /* 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); +}