~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

1.1.15 by Sebastien Bacher
Import upstream version 2.6.0
1
/* Lighting Effects - A plug-in for GIMP
2
 *
3
 * Dialog creation and updaters, callbacks and event-handlers
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19
20
#include "config.h"
21
22
#include <string.h>
23
#include <errno.h>
24
25
#include <glib/gstdio.h>
26
27
#include <libgimp/gimp.h>
28
#include <libgimp/gimpui.h>
29
30
#include "lighting-ui.h"
31
#include "lighting-main.h"
32
#include "lighting-image.h"
33
#include "lighting-apply.h"
34
#include "lighting-preview.h"
35
#include "lighting-stock.h"
36
37
#include "libgimp/stdplugins-intl.h"
38
39
40
extern LightingValues mapvals;
41
42
static GtkWidget   *appwin            = NULL;
43
static GtkNotebook *options_note_book = NULL;
44
45
GdkGC     *gc                         = NULL;
46
GtkWidget *previewarea                = NULL;
47
48
GtkWidget *spin_pos_x                 = NULL;
49
GtkWidget *spin_pos_y                 = NULL;
50
GtkWidget *spin_pos_z                 = NULL;
51
GtkWidget *spin_dir_x                 = NULL;
52
GtkWidget *spin_dir_y                 = NULL;
53
GtkWidget *spin_dir_z                 = NULL;
54
55
static GtkWidget *colorbutton;
56
static GtkWidget *light_type_combo;
57
static GtkWidget *lightselect_combo;
58
static GtkWidget *spin_intensity;
59
static GtkWidget *isolate_button;
60
static gchar     *lighting_effects_path = NULL;
61
62
static void create_main_notebook      (GtkWidget       *container);
63
64
static void toggle_update             (GtkWidget       *widget,
65
                                       gpointer         data);
66
67
static void     distance_update       (GtkAdjustment   *adj,
68
                                       gpointer         data);
69
70
static gboolean  bumpmap_constrain    (gint32           image_id,
71
                                       gint32           drawable_id,
72
                                       gpointer         data);
73
static gboolean  envmap_constrain     (gint32           image_id,
74
                                       gint32           drawable_id,
75
                                       gpointer         data);
76
static void     envmap_combo_callback (GtkWidget       *widget,
77
                                       gpointer         data);
78
static void     save_lighting_preset  (GtkWidget       *widget,
79
                                       gpointer         data);
80
static void     save_preset_response  (GtkFileChooser  *chooser,
81
                                       gint             response_id,
82
                                       gpointer         data);
83
static void     load_lighting_preset  (GtkWidget       *widget,
84
                                       gpointer         data);
85
static void     load_preset_response  (GtkFileChooser  *chooser,
86
                                       gint             response_id,
87
                                       gpointer         data);
88
static void     lightselect_callback  (GimpIntComboBox *combo,
89
                                       gpointer         data);
90
static void     apply_settings        (GtkWidget       *widget,
91
                                       gpointer         data);
92
static void     isolate_selected_light (GtkWidget      *widget,
93
                                        gpointer        data);
94
95
96
/**********************/
97
/* Std. toggle update */
98
/**********************/
99
100
static void
101
toggle_update (GtkWidget *widget,
102
               gpointer   data)
103
{
104
  gimp_toggle_button_update (widget, data);
105
106
  draw_preview_image (TRUE);
107
}
108
109
110
static void
111
distance_update (GtkAdjustment *adj,
112
                 gpointer   data)
113
{
114
  mapvals.viewpoint.z = gtk_adjustment_get_value (adj);
115
116
  draw_preview_image (TRUE);
117
}
118
119
120
/*****************************************/
121
/* Main window light type menu callback. */
122
/*****************************************/
123
124
static void
125
apply_settings (GtkWidget *widget,
126
                gpointer   data)
127
{
128
  gint valid;
129
  gint type;
130
  gint k    = mapvals.light_selected;
131
132
  if (mapvals.update_enabled)
133
    {
134
      valid = gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (light_type_combo),
135
                                             &type);
136
      if (valid)
137
        mapvals.lightsource[k].type = type;
138
139
      gimp_color_button_get_color (GIMP_COLOR_BUTTON (colorbutton),
140
                                   &mapvals.lightsource[k].color);
141
142
      mapvals.lightsource[k].position.x
143
        = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_pos_x));
144
      mapvals.lightsource[k].position.y
145
        = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_pos_y));
146
      mapvals.lightsource[k].position.z
147
        = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_pos_z));
148
149
      mapvals.lightsource[k].direction.x
150
        = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_dir_x));
151
      mapvals.lightsource[k].direction.y
152
        = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_dir_y));
153
      mapvals.lightsource[k].direction.z
154
        = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_dir_z));
155
156
      mapvals.lightsource[k].intensity
157
        = gtk_spin_button_get_value (GTK_SPIN_BUTTON(spin_intensity));
158
159
      interactive_preview_callback(NULL);
160
    }
161
162
  if (widget == light_type_combo)
163
    {
164
      switch (mapvals.lightsource[k].type)
165
        {
166
        case NO_LIGHT:
167
          gtk_widget_set_sensitive (spin_pos_x, FALSE);
168
          gtk_widget_set_sensitive (spin_pos_y, FALSE);
169
          gtk_widget_set_sensitive (spin_pos_z, FALSE);
170
          gtk_widget_set_sensitive (spin_dir_x, FALSE);
171
          gtk_widget_set_sensitive (spin_dir_y, FALSE);
172
          gtk_widget_set_sensitive (spin_dir_z, FALSE);
173
          break;
174
        case POINT_LIGHT:
175
          gtk_widget_set_sensitive (spin_pos_x, TRUE);
176
          gtk_widget_set_sensitive (spin_pos_y, TRUE);
177
          gtk_widget_set_sensitive (spin_pos_z, TRUE);
178
          gtk_widget_set_sensitive (spin_dir_x, FALSE);
179
          gtk_widget_set_sensitive (spin_dir_y, FALSE);
180
          gtk_widget_set_sensitive (spin_dir_z, FALSE);
181
          break;
182
        case DIRECTIONAL_LIGHT:
183
          gtk_widget_set_sensitive (spin_pos_x, FALSE);
184
          gtk_widget_set_sensitive (spin_pos_y, FALSE);
185
          gtk_widget_set_sensitive (spin_pos_z, FALSE);
186
          gtk_widget_set_sensitive (spin_dir_x, TRUE);
187
          gtk_widget_set_sensitive (spin_dir_y, TRUE);
188
          gtk_widget_set_sensitive (spin_dir_z, TRUE);
189
          break;
190
        default:
191
          break;
192
        }
193
    }
194
}
195
196
static void
197
mapmenu2_callback (GtkWidget *widget,
198
                   gpointer   data)
199
{
200
  gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), (gint *) data);
201
202
  draw_preview_image (TRUE);
203
}
204
205
/******************************************/
206
/* Main window "Preview!" button callback */
207
/******************************************/
208
209
static void
210
preview_callback (GtkWidget *widget)
211
{
212
  draw_preview_image (TRUE);
213
}
214
215
216
217
218
/*********************************************/
219
/* Main window "-" (zoom in) button callback */
220
/*********************************************/
221
/*
222
static void
223
zoomout_callback (GtkWidget *widget)
224
{
225
  mapvals.preview_zoom_factor *= 0.5;
226
  draw_preview_image (TRUE);
227
}
228
*/
229
/*********************************************/
230
/* Main window "+" (zoom out) button callback */
231
/*********************************************/
232
/*
233
static void
234
zoomin_callback (GtkWidget *widget)
235
{
236
  mapvals.preview_zoom_factor *= 2.0;
237
  draw_preview_image (TRUE);
238
}
239
*/
240
/**********************************************/
241
/* Main window "Apply" button callback.       */
242
/* Render to GIMP image, close down and exit. */
243
/**********************************************/
244
245
static gint
246
bumpmap_constrain (gint32   image_id,
247
                   gint32   drawable_id,
248
                   gpointer data)
249
{
250
  return  ((gimp_drawable_width (drawable_id) ==
251
            gimp_drawable_width (mapvals.drawable_id)) &&
252
           (gimp_drawable_height (drawable_id) ==
253
            gimp_drawable_height (mapvals.drawable_id)));
254
}
255
256
static gint
257
envmap_constrain (gint32   image_id,
258
                  gint32   drawable_id,
259
                  gpointer data)
260
{
261
  return (!gimp_drawable_is_gray (drawable_id) &&
262
          !gimp_drawable_has_alpha (drawable_id));
263
}
264
265
static void
266
envmap_combo_callback (GtkWidget *widget,
267
                       gpointer   data)
268
{
269
  gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget),
270
                                 &mapvals.envmap_id);
271
272
  env_width = gimp_drawable_width   (mapvals.envmap_id);
273
  env_height = gimp_drawable_height (mapvals.envmap_id);
274
}
275
276
/***********************/
277
/* Dialog constructors */
278
/***********************/
279
280
static GtkWidget *
281
create_options_page (void)
282
{
283
  GtkWidget *page;
284
  GtkWidget *frame;
285
  GtkWidget *vbox;
286
  GtkWidget *toggle;
287
  GtkWidget *table;
288
  GtkObject *adj;
289
290
  page = gtk_vbox_new (FALSE, 12);
291
  gtk_container_set_border_width (GTK_CONTAINER (page), 12);
292
293
  /* General options */
294
295
  frame = gimp_frame_new (_("General Options"));
296
  gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
297
  gtk_widget_show (frame);
298
299
  vbox = gtk_vbox_new (FALSE, 6);
300
  gtk_container_add (GTK_CONTAINER (frame), vbox);
301
  gtk_widget_show (vbox);
302
303
  toggle = gtk_check_button_new_with_mnemonic (_("T_ransparent background"));
304
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
305
                                mapvals.transparent_background);
306
  gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
307
  g_signal_connect (toggle, "toggled",
308
                    G_CALLBACK (toggle_update),
309
                    &mapvals.transparent_background);
310
  gtk_widget_show (toggle);
311
312
  gimp_help_set_help_data (toggle,
313
                           _("Make destination image transparent where bump "
314
                             "height is zero"),NULL);
315
316
  toggle = gtk_check_button_new_with_mnemonic (_("Cre_ate new image"));
317
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
318
                                mapvals.create_new_image);
319
  gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
320
  g_signal_connect (toggle, "toggled",
321
                    G_CALLBACK (gimp_toggle_button_update),
322
                    &mapvals.create_new_image);
323
  gtk_widget_show (toggle);
324
325
  gimp_help_set_help_data (toggle,
326
                           _("Create a new image when applying filter"), NULL);
327
328
  toggle = gtk_check_button_new_with_mnemonic (_("High _quality preview"));
329
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
330
                                mapvals.previewquality);
331
  gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
332
  g_signal_connect (toggle, "toggled",
333
                    G_CALLBACK (toggle_update),
334
                    &mapvals.previewquality);
335
  gtk_widget_show (toggle);
336
337
  gimp_help_set_help_data (toggle,
338
                           _("Enable/disable high quality preview"), NULL);
339
340
  table = gtk_table_new (1, 3, FALSE);
341
  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 12);
342
  gtk_widget_show (table);
343
344
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
345
                              _("Distance:"), 100, 6,
346
                              mapvals.viewpoint.z,
347
                              0.0, 2.0, 0.01, 0.05,
348
                              3, TRUE, 0.0, 0.0,
349
                              "Distance of observer from surface",
350
                              "plug-in-lighting");
351
  g_signal_connect (adj, "value-changed",
352
                    G_CALLBACK (distance_update),
353
                    NULL);
354
355
  gtk_widget_show (page);
356
357
  return page;
358
}
359
360
/******************************/
361
/* Create light settings page */
362
/******************************/
363
364
static GtkWidget *
365
create_light_page (void)
366
{
367
  GtkWidget *page;
368
  GtkWidget *frame;
369
  GtkWidget *table;
370
  GtkWidget *button;
371
  GtkObject *adj;
372
  GtkWidget *label;
373
  gint       k = mapvals.light_selected;
374
375
  page = gtk_vbox_new (FALSE, 12);
376
  gtk_container_set_border_width (GTK_CONTAINER (page), 12);
377
378
  frame = gimp_frame_new (_("Light Settings"));
379
  gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
380
  gtk_widget_show (frame);
381
382
  table = gtk_table_new (8, 8, FALSE);
383
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
384
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
385
  gtk_container_add (GTK_CONTAINER (frame), table);
386
  gtk_widget_show (table);
387
388
  gtk_table_set_col_spacing (GTK_TABLE (table), 1, 12);
389
  gtk_table_set_col_spacing (GTK_TABLE (table), 3, 12);
390
391
  lightselect_combo =  gimp_int_combo_box_new (_("Light 1"),        0,
392
                                               _("Light 2"),        1,
393
                                               _("Light 3"),        2,
394
                                               _("Light 4"),        3,
395
                                               _("Light 5"),        4,
396
                                               _("Light 6"),        5,
397
                                               NULL);
398
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (lightselect_combo), k);
399
  gtk_table_attach_defaults (GTK_TABLE (table), lightselect_combo, 0, 2, 0, 1);
400
  g_signal_connect (lightselect_combo, "changed",
401
                    G_CALLBACK (lightselect_callback), NULL);
402
  gtk_widget_show (lightselect_combo);
403
404
  /* row labels */
405
  label = gtk_label_new (_("Type:"));
406
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
407
  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
408
  gtk_widget_show (label);
409
410
  label = gtk_label_new (_("Color:"));
411
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
412
  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
413
  gtk_widget_show (label);
414
415
  light_type_combo =
416
    gimp_int_combo_box_new (_("None"),        NO_LIGHT,
417
                            _("Directional"), DIRECTIONAL_LIGHT,
418
                            _("Point"),       POINT_LIGHT,
419
                            /* _("Spot"),     SPOT_LIGHT, */
420
                            NULL);
421
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (light_type_combo),
422
                                 mapvals.lightsource[k].type);
423
  gtk_table_attach_defaults (GTK_TABLE (table), light_type_combo,
424
                             1, 2, 1, 2);
425
  gtk_widget_show (light_type_combo);
426
427
  g_signal_connect (light_type_combo, "changed",
428
                    G_CALLBACK (apply_settings),
429
                    NULL);
430
431
  gimp_help_set_help_data (light_type_combo,
432
                           _("Type of light source to apply"), NULL);
433
434
  colorbutton = gimp_color_button_new (_("Select lightsource color"),
435
                                          64, 16,
436
                                          &mapvals.lightsource[k].color,
437
                                          GIMP_COLOR_AREA_FLAT);
438
  gimp_color_button_set_update (GIMP_COLOR_BUTTON (colorbutton), TRUE);
439
  gtk_widget_show (colorbutton);
440
  gtk_table_attach_defaults (GTK_TABLE (table),
441
                             colorbutton, 1, 2, 2, 3);
442
443
  g_signal_connect (colorbutton, "color-changed",
444
                    G_CALLBACK (apply_settings),
445
                    NULL);
446
447
  gimp_help_set_help_data (colorbutton,
448
                           _("Set light source color"), NULL);
449
450
451
  spin_intensity = gimp_spin_button_new (&adj,
452
                                         mapvals.lightsource[k].intensity,
453
                                         0.0, 100.0,
454
                                         0.01, 0.1, 0.0, 0.0, 2);
455
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
456
                                 _("_Intensity:"), 0.0, 0.5,
457
                                 spin_intensity, 1, TRUE);
458
459
  g_signal_connect (adj, "value-changed",
460
                    G_CALLBACK (apply_settings),
461
                    NULL);
462
463
  gimp_help_set_help_data (spin_intensity,
464
                           _("Light intensity"), NULL);
465
466
467
  label = gtk_label_new (_("Position"));
468
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
469
  gtk_table_attach_defaults (GTK_TABLE (table), label, 3, 4, 0, 1);
470
  gtk_widget_show (label);
471
472
  spin_pos_x = gimp_spin_button_new (&adj,
473
                                     mapvals.lightsource[k].position.x,
474
                                     -100.0, 100.0,
475
                                     0.1, 1.0, 0.0, 0.0, 2);
476
  gimp_table_attach_aligned (GTK_TABLE (table), 2, 1,
477
                                 _("_X:"), 0.0, 0.5,
478
                                 spin_pos_x, 1, TRUE);
479
480
  g_signal_connect (adj, "value-changed",
481
                    G_CALLBACK (apply_settings),
482
                    NULL);
483
484
  gimp_help_set_help_data (spin_pos_x,
485
                           _("Light source X position in XYZ space"), NULL);
486
487
  spin_pos_y = gimp_spin_button_new (&adj,
488
                                     mapvals.lightsource[k].position.y,
489
                                     -100.0, 100.0,
490
                                     0.1, 1.0, 0.0, 0.0, 2);
491
  gimp_table_attach_aligned (GTK_TABLE (table), 2, 2,
492
                             _("_Y:"), 0.0, 0.5,
493
                             spin_pos_y, 1, TRUE);
494
495
  g_signal_connect (adj, "value-changed",
496
                    G_CALLBACK (apply_settings),
497
                    NULL);
498
499
  gimp_help_set_help_data (spin_pos_y,
500
                           _("Light source Y position in XYZ space"), NULL);
501
502
  spin_pos_z = gimp_spin_button_new (&adj,
503
                                     mapvals.lightsource[k].position.z,
504
                                     -100.0, 100.0,
505
                                     0.1, 1.0, 0.0, 0.0, 2);
506
  gimp_table_attach_aligned (GTK_TABLE (table), 2, 3,
507
                             _("_Z:"), 0.0, 0.5,
508
                             spin_pos_z, 1, TRUE);
509
510
  g_signal_connect (adj, "value-changed",
511
                    G_CALLBACK (apply_settings),
512
                    NULL);
513
514
  gimp_help_set_help_data (spin_pos_z,
515
                           _("Light source Z position in XYZ space"), NULL);
516
517
518
  label = gtk_label_new (_("Direction"));
519
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
520
  gtk_table_attach_defaults (GTK_TABLE (table), label, 5, 6, 0, 1);
521
  gtk_widget_show (label);
522
523
  spin_dir_x = gimp_spin_button_new (&adj,
524
                                     mapvals.lightsource[k].direction.x,
525
                                     -100.0, 100.0, 0.1, 1.0, 0.0, 0.0, 2);
526
  gimp_table_attach_aligned (GTK_TABLE (table), 4, 1,
527
                             _("X:"), 0.0, 0.5,
528
                             spin_dir_x, 1, TRUE);
529
530
  g_signal_connect (adj, "value-changed",
531
                    G_CALLBACK (apply_settings),
532
                    NULL);
533
534
  gimp_help_set_help_data (spin_dir_x,
535
                           _("Light source X direction in XYZ space"), NULL);
536
537
  spin_dir_y = gimp_spin_button_new (&adj,
538
                                     mapvals.lightsource[k].direction.y,
539
                                     -100.0, 100.0, 0.1, 1.0, 0.0, 0.0, 2);
540
  gimp_table_attach_aligned (GTK_TABLE (table), 4, 2,
541
                             _("Y:"), 0.0, 0.5,
542
                                 spin_dir_y, 1, TRUE);
543
544
  g_signal_connect (adj, "value-changed",
545
                    G_CALLBACK (apply_settings),
546
                    NULL);
547
548
  gimp_help_set_help_data (spin_dir_y,
549
                           _("Light source Y direction in XYZ space"), NULL);
550
551
  spin_dir_z = gimp_spin_button_new (&adj,
552
                                     mapvals.lightsource[k].direction.z,
553
                                     -100.0, 100.0, 0.1, 1.0, 0.0, 0.0, 2);
554
  gimp_table_attach_aligned (GTK_TABLE (table), 4, 3,
555
                             _("Z:"), 0.0, 0.5,
556
                             spin_dir_z, 1, TRUE);
557
558
  g_signal_connect (adj, "value-changed",
559
                    G_CALLBACK (apply_settings),
560
                    NULL);
561
562
  gimp_help_set_help_data (spin_dir_z,
563
                           _("Light source Z direction in XYZ space"),
564
                           NULL);
565
566
  isolate_button = gtk_check_button_new_with_mnemonic (_("I_solate"));
567
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (isolate_button),
568
                                mapvals.light_isolated);
569
  g_signal_connect (isolate_button, "toggled",
570
                    G_CALLBACK (isolate_selected_light),
571
                    NULL);
572
  gtk_table_attach_defaults (GTK_TABLE (table), isolate_button, 0, 1, 5, 6);
573
  gtk_widget_show (isolate_button);
574
575
  label = gtk_label_new (_("Lighting preset:"));
576
  gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
577
  gtk_table_set_row_spacing (GTK_TABLE (table), 5, 12);
578
  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 6, 7);
579
  gtk_widget_show (label);
580
581
  button = gtk_button_new_from_stock (GTK_STOCK_SAVE);
582
  gtk_table_attach_defaults (GTK_TABLE (table), button, 2, 4, 6, 7);
583
  g_signal_connect (button, "clicked",
584
                    G_CALLBACK (save_lighting_preset),
585
                    NULL);
586
  gtk_widget_show (button);
587
588
  button = gtk_button_new_from_stock (GTK_STOCK_OPEN);
589
  gtk_table_attach_defaults (GTK_TABLE (table), button, 4, 6, 6, 7);
590
  g_signal_connect (button, "clicked",
591
                    G_CALLBACK (load_lighting_preset),
592
                    NULL);
593
  gtk_widget_show (button);
594
595
  gtk_widget_show (page);
596
597
  return page;
598
}
599
600
/*********************************/
601
/* Create material settings page */
602
/*********************************/
603
604
static GtkWidget *
605
create_material_page (void)
606
{
607
  GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
608
  GtkWidget    *page;
609
  GtkWidget    *frame;
610
  GtkWidget    *table;
611
  GtkWidget    *label;
612
  GtkWidget    *hbox;
613
  GtkWidget    *spinbutton;
614
  GtkWidget    *image;
615
  GtkWidget    *button;
616
  GtkObject    *adj;
617
618
  page = gtk_vbox_new (FALSE, 12);
619
  gtk_container_set_border_width (GTK_CONTAINER (page), 12);
620
621
  frame = gimp_frame_new (_("Material Properties"));
622
  gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
623
  gtk_widget_show (frame);
624
625
  hbox = gtk_hbox_new (FALSE, 6);
626
  gtk_container_add (GTK_CONTAINER (frame), hbox);
627
  gtk_widget_show (hbox);
628
629
  table = gtk_table_new (5, 4, FALSE);
630
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
631
  gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
632
  gtk_widget_show (table);
633
634
  /* Ambient intensity */
635
636
  image = gtk_image_new_from_stock (STOCK_INTENSITY_AMBIENT_LOW,
637
                                    GTK_ICON_SIZE_BUTTON);
638
  label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
639
                                     _("_Glowing:"), 0.0, 0.5,
640
                                     image, 1, FALSE);
641
  gtk_size_group_add_widget (group, label);
642
643
  spinbutton = gimp_spin_button_new (&adj, mapvals.material.ambient_int,
644
                                     0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2);
645
  gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 0, 1,
646
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
647
  gtk_widget_show (spinbutton);
648
649
  g_signal_connect (adj, "value-changed",
650
                    G_CALLBACK (gimp_double_adjustment_update),
651
                    &mapvals.material.ambient_int);
652
  g_signal_connect (adj, "value-changed",
653
                    G_CALLBACK (interactive_preview_callback),
654
                    NULL);
655
656
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
657
  gimp_help_set_help_data (spinbutton,
658
                           _("Amount of original color to show where no "
659
                             "direct light falls"), NULL);
660
661
  image = gtk_image_new_from_stock (STOCK_INTENSITY_AMBIENT_HIGH,
662
                                    GTK_ICON_SIZE_BUTTON);
663
  gtk_table_attach (GTK_TABLE (table), image, 3, 4, 0, 1,
664
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
665
  gtk_widget_show (image);
666
667
  /* Diffuse intensity */
668
669
  image = gtk_image_new_from_stock (STOCK_INTENSITY_DIFFUSE_LOW,
670
                                    GTK_ICON_SIZE_BUTTON);
671
  label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
672
                                     _("_Bright:"), 0.0, 0.5,
673
                                     image, 1, FALSE);
674
  gtk_size_group_add_widget (group, label);
675
676
  spinbutton = gimp_spin_button_new (&adj, mapvals.material.diffuse_int,
677
                                     0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2);
678
  gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 1, 2,
679
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
680
  gtk_widget_show (spinbutton);
681
682
  g_signal_connect (adj, "value-changed",
683
                    G_CALLBACK (gimp_double_adjustment_update),
684
                    &mapvals.material.diffuse_int);
685
  g_signal_connect (adj, "value-changed",
686
                    G_CALLBACK (interactive_preview_callback),
687
                    NULL);
688
689
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
690
  gimp_help_set_help_data (spinbutton,
691
                           _("Intensity of original color when lit by a light "
692
                             "source"), NULL);
693
694
  image = gtk_image_new_from_stock (STOCK_INTENSITY_DIFFUSE_HIGH,
695
                                    GTK_ICON_SIZE_BUTTON);
696
  gtk_table_attach (GTK_TABLE (table), image, 3, 4, 1, 2,
697
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
698
  gtk_widget_show (image);
699
700
  /* Specular reflection */
701
702
  image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_SPECULAR_LOW,
703
                                    GTK_ICON_SIZE_BUTTON);
704
  label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
705
                                     _("_Shiny:"), 0.0, 0.5,
706
                                     image, 1, FALSE);
707
  gtk_size_group_add_widget (group, label);
708
709
  spinbutton = gimp_spin_button_new (&adj, mapvals.material.specular_ref,
710
                                     0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2);
711
  gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 2, 3,
712
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
713
  gtk_widget_show (spinbutton);
714
715
  g_signal_connect (adj, "value-changed",
716
                    G_CALLBACK (gimp_double_adjustment_update),
717
                    &mapvals.material.specular_ref);
718
  g_signal_connect (adj, "value-changed",
719
                    G_CALLBACK (interactive_preview_callback),
720
                    NULL);
721
722
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
723
  gimp_help_set_help_data (spinbutton,
724
                           _("Controls how intense the highlights will be"),
725
                           NULL);
726
727
  image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_SPECULAR_HIGH,
728
                                    GTK_ICON_SIZE_BUTTON);
729
  gtk_table_attach (GTK_TABLE (table), image, 3, 4, 2, 3,
730
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
731
  gtk_widget_show (image);
732
733
  /* Highlight */
734
  image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_HIGHLIGHT_LOW,
735
                                    GTK_ICON_SIZE_BUTTON);
736
  label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
737
                                     _("_Polished:"), 0.0, 0.5,
738
                                     image, 1, FALSE);
739
  gtk_size_group_add_widget (group, label);
740
741
  spinbutton = gimp_spin_button_new (&adj, mapvals.material.highlight,
742
                                     0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2);
743
  gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 3, 4,
744
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
745
  gtk_widget_show (spinbutton);
746
747
  g_signal_connect (adj, "value-changed",
748
                    G_CALLBACK (gimp_double_adjustment_update),
749
                    &mapvals.material.highlight);
750
  g_signal_connect (adj, "value-changed",
751
                    G_CALLBACK (interactive_preview_callback),
752
                    NULL);
753
754
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
755
  gimp_help_set_help_data (spinbutton,
756
                           _("Higher values makes the highlights more focused"),
757
                           NULL);
758
759
  image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_HIGHLIGHT_HIGH,
760
                                    GTK_ICON_SIZE_BUTTON);
761
  gtk_table_attach (GTK_TABLE (table), image, 3, 4, 3, 4,
762
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
763
  gtk_widget_show (image);
764
765
  /* Metallic */
766
  button = gtk_check_button_new_with_mnemonic (_("_Metallic"));
767
  gtk_table_attach (GTK_TABLE (table), button, 0, 3, 4, 5,
768
                    GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
769
  gtk_widget_show (button);
770
771
  g_signal_connect (button, "toggled",
772
                    G_CALLBACK (gimp_toggle_button_update),
773
                    &mapvals.material.metallic);
774
  g_signal_connect (button, "toggled",
775
                    G_CALLBACK (interactive_preview_callback),
776
                    NULL);
777
778
  gtk_widget_show (page);
779
780
  return page;
781
}
782
783
/* Create Bump mapping page */
784
785
static GtkWidget *
786
create_bump_page (void)
787
{
788
  GtkWidget *page;
789
  GtkWidget *toggle;
790
  GtkWidget *frame;
791
  GtkWidget *table;
792
  GtkWidget *combo;
793
  GtkWidget *spinbutton;
794
  GtkObject *adj;
795
796
  page = gtk_vbox_new (FALSE, 12);
797
  gtk_container_set_border_width (GTK_CONTAINER (page), 12);
798
799
  frame = gimp_frame_new (NULL);
800
  gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
801
  gtk_widget_show (frame);
802
803
  toggle = gtk_check_button_new_with_mnemonic (_("E_nable bump mapping"));
804
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
805
                                mapvals.bump_mapped);
806
  gtk_frame_set_label_widget (GTK_FRAME (frame), toggle);
807
  gtk_widget_show (toggle);
808
809
  g_signal_connect (toggle, "toggled",
810
                    G_CALLBACK (gimp_toggle_button_update),
811
                    &mapvals.bump_mapped);
812
  g_signal_connect (toggle, "toggled",
813
                    G_CALLBACK (interactive_preview_callback),
814
                    NULL);
815
816
  gimp_help_set_help_data (toggle,
817
                           _("Enable/disable bump-mapping (image depth)"),
818
                           NULL);
819
820
  table = gtk_table_new (6, 2, FALSE);
821
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
822
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
823
  gtk_container_add (GTK_CONTAINER (frame), table);
824
  gtk_widget_show (table);
825
826
  gtk_widget_set_sensitive (table, mapvals.bump_mapped);
827
  g_object_set_data (G_OBJECT (toggle), "set_sensitive", table);
828
829
  combo = gimp_drawable_combo_box_new (bumpmap_constrain, NULL);
830
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), mapvals.bumpmap_id,
831
                              G_CALLBACK (gimp_int_combo_box_get_active),
832
                              &mapvals.bumpmap_id);
833
834
  g_signal_connect (combo, "changed",
835
                    G_CALLBACK (mapmenu2_callback),
836
                    &mapvals.bumpmap_id);
837
838
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
839
                             _("Bumpm_ap image:"), 0.0, 0.5,
840
                             combo, 1, FALSE);
841
842
  combo = gimp_int_combo_box_new (_("Linear"),      LINEAR_MAP,
843
                                  _("Logarithmic"), LOGARITHMIC_MAP,
844
                                  _("Sinusoidal"),  SINUSOIDAL_MAP,
845
                                  _("Spherical"),   SPHERICAL_MAP,
846
                                  NULL);
847
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo),
848
                                 mapvals.bumpmaptype);
849
850
  g_signal_connect (combo, "changed",
851
                    G_CALLBACK (mapmenu2_callback),
852
                    &mapvals.bumpmaptype);
853
854
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
855
                             _("Cu_rve:"), 0.0, 0.5, combo, 1, FALSE);
856
857
  spinbutton = gimp_spin_button_new (&adj, mapvals.bumpmax,
858
                                     0, G_MAXFLOAT, 0.01, 0.1, 0.0, 0.0, 2);
859
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
860
                             _("Ma_ximum height:"), 0.0, 0.5,
861
                             spinbutton, 1, TRUE);
862
  g_signal_connect (adj, "value-changed",
863
                    G_CALLBACK (gimp_double_adjustment_update),
864
                    &mapvals.bumpmax);
865
  g_signal_connect (adj, "value-changed",
866
                    G_CALLBACK (interactive_preview_callback),
867
                    NULL);
868
869
  gimp_help_set_help_data (spinbutton,
870
                           _("Maximum height for bumps"),
871
                           NULL);
872
873
  gtk_widget_show (page);
874
875
  return page;
876
}
877
878
static GtkWidget *
879
create_environment_page (void)
880
{
881
  GtkWidget *page;
882
  GtkWidget *toggle;
883
  GtkWidget *table;
884
  GtkWidget *frame;
885
  GtkWidget *combo;
886
887
  page = gtk_vbox_new (FALSE, 12);
888
  gtk_container_set_border_width (GTK_CONTAINER (page), 12);
889
890
  frame = gimp_frame_new (NULL);
891
  gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
892
  gtk_widget_show (frame);
893
894
  toggle = gtk_check_button_new_with_mnemonic (_("E_nable environment mapping"));
895
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
896
                                mapvals.env_mapped);
897
  gtk_frame_set_label_widget (GTK_FRAME (frame), toggle);
898
  gtk_widget_show (toggle);
899
900
  g_signal_connect (toggle, "toggled",
901
                    G_CALLBACK (gimp_toggle_button_update),
902
                    &mapvals.env_mapped);
903
  g_signal_connect (toggle, "toggled",
904
                    G_CALLBACK (interactive_preview_callback),
905
                    NULL);
906
907
  gimp_help_set_help_data (toggle,
908
                           _("Enable/disable environment-mapping (reflection)"),
909
                           NULL);
910
911
  table = gtk_table_new (3, 2, FALSE);
912
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
913
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
914
  gtk_container_add (GTK_CONTAINER (frame), table);
915
  gtk_widget_show (table);
916
917
  gtk_widget_set_sensitive (table, mapvals.env_mapped);
918
  g_object_set_data (G_OBJECT (toggle), "set_sensitive", table);
919
920
  combo = gimp_drawable_combo_box_new (envmap_constrain, NULL);
921
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), mapvals.envmap_id,
922
                              G_CALLBACK (envmap_combo_callback),
923
                              NULL);
924
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
925
                             _("En_vironment image:"), 0.0, 0.5,
926
                             combo, 1, FALSE);
927
928
  gimp_help_set_help_data (combo, _("Environment image to use"), NULL);
929
930
  gtk_widget_show (page);
931
932
  return page;
933
}
934
935
/*****************************/
936
/* Create notebook and pages */
937
/*****************************/
938
939
static void
940
create_main_notebook (GtkWidget *container)
941
{
942
  GtkWidget *page;
943
944
  options_note_book = GTK_NOTEBOOK (gtk_notebook_new ());
945
  gtk_container_add (GTK_CONTAINER (container),
946
                     GTK_WIDGET (options_note_book));
947
948
  page = create_options_page ();
949
  gtk_notebook_append_page (options_note_book, page,
950
                            gtk_label_new_with_mnemonic (_("Op_tions")));
951
952
  page = create_light_page ();
953
  gtk_notebook_append_page (options_note_book, page,
954
                            gtk_label_new_with_mnemonic (_("_Light")));
955
956
  page = create_material_page ();
957
  gtk_notebook_append_page (options_note_book, page,
958
                            gtk_label_new_with_mnemonic (_("_Material")));
959
960
  page = create_bump_page ();
961
  gtk_notebook_append_page (options_note_book, page,
962
                            gtk_label_new_with_mnemonic (_("_Bump Map")));
963
964
  page = create_environment_page ();
965
  gtk_notebook_append_page (options_note_book, page,
966
                            gtk_label_new_with_mnemonic (_("_Environment Map")));
967
968
  /*
969
  if (mapvals.bump_mapped == TRUE)
970
    {
971
      bump_page = create_bump_page ();
972
      bump_page_pos = g_list_length (options_note_book->children);
973
      gtk_notebook_append_page (options_note_book, bump_page,
974
                                gtk_label_new (_("Bumpmap")));
975
    }
976
977
  if (mapvals.env_mapped == TRUE)
978
    {
979
      env_page = create_environment_page ();
980
      env_page_pos = g_list_length (options_note_book->children);
981
      gtk_notebook_append_page (options_note_book, env_page,
982
                                gtk_label_new (_("Environment")));
983
    }
984
  */
985
  gtk_widget_show (GTK_WIDGET (options_note_book));
986
}
987
988
/********************************/
989
/* Create and show main dialog. */
990
/********************************/
991
992
gboolean
993
main_dialog (GimpDrawable *drawable)
994
{
995
  GtkWidget *main_hbox;
996
  GtkWidget *vbox;
997
  GtkWidget *hbox;
998
  GtkWidget *frame;
999
  GtkWidget *button;
1000
  GtkWidget *toggle;
1001
  gchar     *path;
1002
  gboolean   run = FALSE;
1003
1004
  /*
1005
  GtkWidget *image;
1006
  */
1007
1008
  gimp_ui_init (PLUG_IN_BINARY, FALSE);
1009
1010
  path = gimp_gimprc_query ("lighting-effects-path");
1011
  if (path)
1012
    {
1013
      lighting_effects_path = g_filename_from_utf8 (path, -1, NULL, NULL, NULL);
1014
      g_free (path);
1015
    }
1016
1017
  lighting_stock_init ();
1018
1019
  appwin = gimp_dialog_new (_("Lighting Effects"), PLUG_IN_BINARY,
1020
                            NULL, 0,
1021
                            gimp_standard_help_func, PLUG_IN_PROC,
1022
1023
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1024
                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
1025
1026
                            NULL);
1027
1028
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (appwin),
1029
                                           GTK_RESPONSE_OK,
1030
                                           GTK_RESPONSE_CANCEL,
1031
                                           -1);
1032
1033
  gimp_window_set_transient (GTK_WINDOW (appwin));
1034
1035
  main_hbox = gtk_hbox_new (FALSE, 12);
1036
  gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
1037
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (appwin)->vbox), main_hbox,
1038
                      FALSE, FALSE, 0);
1039
  gtk_widget_show (main_hbox);
1040
1041
  /* Create the Preview */
1042
  /* ================== */
1043
1044
  vbox = gtk_vbox_new (FALSE, 6);
1045
  gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0);
1046
  gtk_widget_show (vbox);
1047
1048
  /* Add preview widget and various buttons to the first part */
1049
  /* ======================================================== */
1050
1051
  frame = gtk_frame_new (NULL);
1052
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1053
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1054
  gtk_widget_show (frame);
1055
1056
  gtk_widget_realize (appwin);
1057
1058
  previewarea = gtk_drawing_area_new ();
1059
  gtk_widget_set_size_request (previewarea, PREVIEW_WIDTH, PREVIEW_HEIGHT);
1060
  gtk_widget_set_events (previewarea, (GDK_EXPOSURE_MASK |
1061
                                       GDK_BUTTON1_MOTION_MASK |
1062
                                       GDK_BUTTON_PRESS_MASK |
1063
                                       GDK_BUTTON_RELEASE_MASK));
1064
  g_signal_connect (previewarea, "event",
1065
                    G_CALLBACK (preview_events),
1066
                    previewarea);
1067
  gtk_container_add (GTK_CONTAINER (frame), previewarea);
1068
  gtk_widget_show (previewarea);
1069
1070
  /* create preview options, frame and vbox */
1071
  hbox = gtk_hbox_new (FALSE, 6);
1072
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1073
  gtk_widget_show (hbox);
1074
1075
  button = gtk_button_new_with_mnemonic (_("_Update"));
1076
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1077
  g_signal_connect (button, "clicked",
1078
                    G_CALLBACK (preview_callback),
1079
                    NULL);
1080
  gtk_widget_show (button);
1081
1082
  gimp_help_set_help_data (button, _("Recompute preview image"), NULL);
1083
1084
  toggle = gtk_check_button_new_with_mnemonic (_("I_nteractive"));
1085
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
1086
                                mapvals.interactive_preview);
1087
  gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
1088
  g_signal_connect (toggle, "toggled",
1089
                    G_CALLBACK (gimp_toggle_button_update),
1090
                    &mapvals.interactive_preview);
1091
  g_signal_connect (toggle, "toggled",
1092
                    G_CALLBACK (interactive_preview_callback),
1093
                    NULL);
1094
1095
  gtk_widget_show (toggle);
1096
1097
  gimp_help_set_help_data (toggle,
1098
                           _("Enable/disable real time preview of changes"),
1099
                           NULL);
1100
1101
  create_main_notebook (main_hbox);
1102
1103
  gtk_widget_show (appwin);
1104
1105
  {
1106
    GdkCursor *cursor;
1107
1108
    cursor = gdk_cursor_new_for_display (gtk_widget_get_display (previewarea),
1109
                                         GDK_HAND2);
1110
    gdk_window_set_cursor (previewarea->window, cursor);
1111
    gdk_cursor_unref (cursor);
1112
  }
1113
1114
  image_setup (drawable, TRUE);
1115
1116
  if (gimp_dialog_run (GIMP_DIALOG (appwin)) == GTK_RESPONSE_OK)
1117
    run = TRUE;
1118
1119
  if (preview_rgb_data != NULL)
1120
    g_free (preview_rgb_data);
1121
1122
  gtk_widget_destroy (appwin);
1123
1124
  return run;
1125
}
1126
1127
1128
static void
1129
save_lighting_preset (GtkWidget *widget,
1130
                      gpointer   data)
1131
{
1132
  static GtkWidget *window = NULL;
1133
1134
  if (! window)
1135
    {
1136
      window =
1137
        gtk_file_chooser_dialog_new (_("Save Lighting Preset"),
1138
                                     GTK_WINDOW (appwin),
1139
                                     GTK_FILE_CHOOSER_ACTION_SAVE,
1140
1141
                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1142
                                     GTK_STOCK_SAVE,   GTK_RESPONSE_OK,
1143
1144
                                     NULL);
1145
1146
      gtk_dialog_set_alternative_button_order (GTK_DIALOG (window),
1147
                                               GTK_RESPONSE_OK,
1148
                                               GTK_RESPONSE_CANCEL,
1149
                                               -1);
1150
      gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_OK);
1151
1152
      gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (window),
1153
                                                      TRUE);
1154
1155
      g_signal_connect (window, "destroy",
1156
                        G_CALLBACK (gtk_widget_destroyed),
1157
                        &window);
1158
      g_signal_connect (window, "response",
1159
                        G_CALLBACK (save_preset_response),
1160
                        NULL);
1161
    }
1162
1163
  if (lighting_effects_path)
1164
    {
1165
      GList *list;
1166
      gchar *dir;
1167
1168
      list = gimp_path_parse (lighting_effects_path, 16, FALSE, NULL);
1169
      dir = gimp_path_get_user_writable_dir (list);
1170
      gimp_path_free (list);
1171
1172
      if (! dir)
1173
        dir = g_strdup (gimp_directory ());
1174
1175
      gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), dir);
1176
1177
      g_free (dir);
1178
    }
1179
  else
1180
    {
1181
      gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window),
1182
                                           g_get_tmp_dir ());
1183
    }
1184
1185
  gtk_window_present (GTK_WINDOW (window));
1186
}
1187
1188
1189
static void
1190
save_preset_response (GtkFileChooser *chooser,
1191
                      gint            response_id,
1192
                      gpointer        data)
1193
{
1194
  FILE          *fp;
1195
  gint           num_lights = 0;
1196
  gint           k;
1197
  LightSettings *source;
1198
  gchar          buffer1[G_ASCII_DTOSTR_BUF_SIZE];
1199
  gchar          buffer2[G_ASCII_DTOSTR_BUF_SIZE];
1200
  gchar          buffer3[G_ASCII_DTOSTR_BUF_SIZE];
1201
  gint           blen       = G_ASCII_DTOSTR_BUF_SIZE;
1202
1203
  if (response_id == GTK_RESPONSE_OK)
1204
    {
1205
      gchar *filename = gtk_file_chooser_get_filename (chooser);
1206
1207
      fp = g_fopen (filename, "wb");
1208
1209
      if (!fp)
1210
        {
1211
          g_message (_("Could not open '%s' for writing: %s"),
1212
                     filename, g_strerror (errno));
1213
        }
1214
      else
1215
        {
1216
          for (k = 0; k < NUM_LIGHTS; k++)
1217
            if (mapvals.lightsource[k].type != NO_LIGHT)
1218
              ++num_lights;
1219
1220
          fprintf (fp, "Number of lights: %d\n", num_lights);
1221
1222
          for (k = 0; k < NUM_LIGHTS; k++)
1223
            if (mapvals.lightsource[k].type != NO_LIGHT)
1224
              {
1225
                source = &mapvals.lightsource[k];
1226
1227
                switch (source->type)
1228
                  {
1229
                  case POINT_LIGHT:
1230
                    fprintf (fp, "Type: Point\n");
1231
                    break;
1232
                  case DIRECTIONAL_LIGHT:
1233
                    fprintf (fp, "Type: Directional\n");
1234
                    break;
1235
                  case SPOT_LIGHT:
1236
                    fprintf (fp, "Type: Spot\n");
1237
                    break;
1238
                  default:
1239
                    g_warning ("Unknown light type: %d",
1240
                               mapvals.lightsource[k].type);
1241
                    continue;
1242
                  }
1243
1244
                fprintf (fp, "Position: %s %s %s\n",
1245
                         g_ascii_dtostr (buffer1, blen, source->position.x),
1246
                         g_ascii_dtostr (buffer2, blen, source->position.y),
1247
                         g_ascii_dtostr (buffer3, blen, source->position.z));
1248
1249
                fprintf (fp, "Direction: %s %s %s\n",
1250
                         g_ascii_dtostr (buffer1, blen, source->direction.x),
1251
                         g_ascii_dtostr (buffer2, blen, source->direction.y),
1252
                         g_ascii_dtostr (buffer3, blen, source->direction.z));
1253
1254
                fprintf (fp, "Color: %s %s %s\n",
1255
                         g_ascii_dtostr (buffer1, blen, source->color.r),
1256
                         g_ascii_dtostr (buffer2, blen, source->color.g),
1257
                         g_ascii_dtostr (buffer3, blen, source->color.b));
1258
1259
                fprintf (fp, "Intensity: %s\n",
1260
                         g_ascii_dtostr (buffer1, blen, source->intensity));
1261
              }
1262
1263
          fclose (fp);
1264
        }
1265
1266
      g_free (filename);
1267
    }
1268
1269
  gtk_widget_destroy (GTK_WIDGET (chooser));
1270
}
1271
1272
static void
1273
load_lighting_preset (GtkWidget *widget,
1274
                      gpointer   data)
1275
{
1276
  static GtkWidget *window = NULL;
1277
1278
  if (! window)
1279
    {
1280
      window =
1281
        gtk_file_chooser_dialog_new (_("Load Lighting Preset"),
1282
                                     GTK_WINDOW (appwin),
1283
                                     GTK_FILE_CHOOSER_ACTION_OPEN,
1284
1285
                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1286
                                     GTK_STOCK_OPEN,   GTK_RESPONSE_OK,
1287
1288
                                     NULL);
1289
1290
      gtk_dialog_set_alternative_button_order (GTK_DIALOG (window),
1291
                                               GTK_RESPONSE_OK,
1292
                                               GTK_RESPONSE_CANCEL,
1293
                                               -1);
1294
      gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_OK);
1295
1296
      g_signal_connect (window, "destroy",
1297
                        G_CALLBACK (gtk_widget_destroyed),
1298
                        &window);
1299
      g_signal_connect (window, "response",
1300
                        G_CALLBACK (load_preset_response),
1301
                        NULL);
1302
    }
1303
1304
  if (lighting_effects_path)
1305
    {
1306
      GList *list;
1307
      gchar *dir;
1308
1309
      list = gimp_path_parse (lighting_effects_path, 16, FALSE, NULL);
1310
      dir = gimp_path_get_user_writable_dir (list);
1311
      gimp_path_free (list);
1312
1313
      if (! dir)
1314
        dir = g_strdup (gimp_directory ());
1315
1316
      gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), dir);
1317
1318
      g_free (dir);
1319
    }
1320
  else
1321
    {
1322
      gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window),
1323
                                           g_get_tmp_dir ());
1324
    }
1325
1326
1327
  gtk_window_present (GTK_WINDOW (window));
1328
}
1329
1330
1331
static void
1332
load_preset_response (GtkFileChooser *chooser,
1333
                      gint            response_id,
1334
                      gpointer        data)
1335
{
1336
  FILE          *fp;
1337
  gint           num_lights;
1338
  gint           k;
1339
  LightSettings *source;
1340
  gchar          buffer1[G_ASCII_DTOSTR_BUF_SIZE];
1341
  gchar          buffer2[G_ASCII_DTOSTR_BUF_SIZE];
1342
  gchar          buffer3[G_ASCII_DTOSTR_BUF_SIZE];
1343
  gchar          type_label[21];
1344
  gchar         *endptr;
1345
1346
  if (response_id == GTK_RESPONSE_OK)
1347
    {
1348
      gchar *filename = gtk_file_chooser_get_filename (chooser);
1349
1350
      fp = g_fopen (filename, "rb");
1351
1352
      if (!fp)
1353
        {
1354
          g_message (_("Could not open '%s' for reading: %s"),
1355
                     filename, g_strerror (errno));
1356
        }
1357
      else
1358
        {
1359
          fscanf (fp, "Number of lights: %d", &num_lights);
1360
1361
          /* initialize lights to off */
1362
          for (k = 0; k < NUM_LIGHTS; k++)
1363
            mapvals.lightsource[k].type = NO_LIGHT;
1364
1365
          for (k = 0; k < num_lights; k++)
1366
            {
1367
              source = &mapvals.lightsource[k];
1368
1369
              fscanf (fp, " Type: %20s", type_label);
1370
1371
              if (!strcmp (type_label, "Point"))
1372
                source->type = POINT_LIGHT;
1373
              else if (!strcmp (type_label, "Directional"))
1374
                source->type = DIRECTIONAL_LIGHT;
1375
              else if (!strcmp (type_label, "Spot"))
1376
                source->type = SPOT_LIGHT;
1377
              else
1378
                {
1379
                  g_warning ("Unknown light type: %s", type_label);
1380
                  fclose (fp);
1381
                  return;
1382
                }
1383
1384
              fscanf (fp, " Position: %s %s %s", buffer1, buffer2, buffer3);
1385
              source->position.x = g_ascii_strtod (buffer1, &endptr);
1386
              source->position.y = g_ascii_strtod (buffer2, &endptr);
1387
              source->position.z = g_ascii_strtod (buffer3, &endptr);
1388
1389
              fscanf (fp, " Direction: %s %s %s", buffer1, buffer2, buffer3);
1390
              source->direction.x = g_ascii_strtod (buffer1, &endptr);
1391
              source->direction.y = g_ascii_strtod (buffer2, &endptr);
1392
              source->direction.z = g_ascii_strtod (buffer3, &endptr);
1393
1394
              fscanf (fp, " Color: %s %s %s", buffer1, buffer2, buffer3);
1395
              source->color.r = g_ascii_strtod (buffer1, &endptr);
1396
              source->color.g = g_ascii_strtod (buffer2, &endptr);
1397
              source->color.b = g_ascii_strtod (buffer3, &endptr);
1398
              source->color.a = 1.0;
1399
1400
              fscanf (fp, " Intensity: %s", buffer1);
1401
              source->intensity = g_ascii_strtod (buffer1, &endptr);
1402
1403
            }
1404
1405
          fclose (fp);
1406
        }
1407
1408
      g_free (filename);
1409
1410
      lightselect_callback (GIMP_INT_COMBO_BOX (lightselect_combo), NULL);
1411
   }
1412
1413
  gtk_widget_destroy (GTK_WIDGET (chooser));
1414
  interactive_preview_callback (GTK_WIDGET (chooser));
1415
}
1416
1417
1418
static void
1419
lightselect_callback (GimpIntComboBox *combo,
1420
                      gpointer         data)
1421
{
1422
  gint valid;
1423
  gint j, k;
1424
1425
  valid = gimp_int_combo_box_get_active (combo, &k);
1426
1427
 if (valid)
1428
    {
1429
      mapvals.update_enabled = FALSE;  /* prevent apply_settings() */
1430
1431
      mapvals.light_selected = k;
1432
      gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (light_type_combo),
1433
                                     mapvals.lightsource[k].type);
1434
      gimp_color_button_set_color (GIMP_COLOR_BUTTON (colorbutton),
1435
                                   &mapvals.lightsource[k].color);
1436
      gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_x),
1437
                                 mapvals.lightsource[k].position.x);
1438
      gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_y),
1439
                                 mapvals.lightsource[k].position.y);
1440
      gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_z),
1441
                                 mapvals.lightsource[k].position.z);
1442
      gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_x),
1443
                                 mapvals.lightsource[k].direction.x);
1444
      gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_y),
1445
                                 mapvals.lightsource[k].direction.y);
1446
      gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_z),
1447
                                 mapvals.lightsource[k].direction.z);
1448
      gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_intensity),
1449
                                 mapvals.lightsource[k].intensity);
1450
1451
      mapvals.update_enabled = TRUE;
1452
1453
      /* if we are isolating a light, need to switch */
1454
      if (mapvals.light_isolated)
1455
        {
1456
          for (j = 0; j < NUM_LIGHTS; j++)
1457
            if (j == mapvals.light_selected)
1458
              mapvals.lightsource[j].active = TRUE;
1459
            else
1460
              mapvals.lightsource[j].active = FALSE;
1461
        }
1462
1463
      interactive_preview_callback (NULL);
1464
    }
1465
}
1466
1467
static void
1468
isolate_selected_light (GtkWidget *widget,
1469
                        gpointer   data)
1470
{
1471
  gint  k;
1472
1473
  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1474
    {
1475
      mapvals.light_isolated = TRUE;
1476
1477
      for (k = 0; k < NUM_LIGHTS; k++)
1478
        if (k == mapvals.light_selected)
1479
          mapvals.lightsource[k].active = TRUE;
1480
        else
1481
          mapvals.lightsource[k].active = FALSE;
1482
    }
1483
  else
1484
    {
1485
      mapvals.light_isolated = FALSE;
1486
1487
      for (k = 0; k < NUM_LIGHTS; k++)
1488
        mapvals.lightsource[k].active = TRUE;
1489
    }
1490
1491
  interactive_preview_callback (NULL);
1492
}