1 /**************************************************************/
2 /* Dialog creation and updaters, callbacks and event-handlers */
3 /**************************************************************/
4 
5 #include "config.h"
6 
7 #include <libgimp/gimp.h>
8 #include <libgimp/gimpui.h>
9 
10 #include "arcball.h"
11 #include "map-object-ui.h"
12 #include "map-object-image.h"
13 #include "map-object-apply.h"
14 #include "map-object-preview.h"
15 #include "map-object-main.h"
16 #include "map-object-stock.h"
17 
18 #include "libgimp/stdplugins-intl.h"
19 
20 
21 GtkWidget     *previewarea = NULL;
22 
23 static GtkWidget   *appwin            = NULL;
24 static GtkNotebook *options_note_book = NULL;
25 
26 static GtkWidget *pointlightwid;
27 static GtkWidget *dirlightwid;
28 
29 static GtkAdjustment *xadj, *yadj, *zadj;
30 
31 static GtkWidget *box_page      = NULL;
32 static GtkWidget *cylinder_page = NULL;
33 
34 static guint left_button_pressed = FALSE;
35 static guint light_hit           = FALSE;
36 
37 
38 static void create_main_notebook       (GtkWidget     *container);
39 
40 static gint preview_events             (GtkWidget     *area,
41                                         GdkEvent      *event);
42 
43 static void update_light_pos_entries   (void);
44 
45 static void double_adjustment_update   (GtkAdjustment *adjustment,
46                                         gpointer       data);
47 
48 static void toggle_update              (GtkWidget     *widget,
49                                         gpointer       data);
50 
51 static void lightmenu_callback         (GtkWidget     *widget,
52                                         gpointer       data);
53 
54 static void preview_callback           (GtkWidget     *widget,
55                                         gpointer       data);
56 
57 static gint box_constrain              (gint32         image_id,
58                                         gint32         drawable_id,
59                                         gpointer       data);
60 static gint cylinder_constrain         (gint32         image_id,
61                                         gint32         drawable_id,
62                                         gpointer       data);
63 
64 static GtkWidget * create_options_page     (void);
65 static GtkWidget * create_light_page       (void);
66 static GtkWidget * create_material_page    (void);
67 static GtkWidget * create_orientation_page (void);
68 static GtkWidget * create_box_page         (void);
69 static GtkWidget * create_cylinder_page    (void);
70 
71 
72 /******************************************************/
73 /* Update angle & position (redraw grid if necessary) */
74 /******************************************************/
75 
76 static void
double_adjustment_update(GtkAdjustment * adjustment,gpointer data)77 double_adjustment_update (GtkAdjustment *adjustment,
78                           gpointer       data)
79 {
80   gimp_double_adjustment_update (adjustment, data);
81 
82   if (mapvals.livepreview)
83     compute_preview_image ();
84 
85   gtk_widget_queue_draw (previewarea);
86 }
87 
88 static void
update_light_pos_entries(void)89 update_light_pos_entries (void)
90 {
91   g_signal_handlers_block_by_func (xadj,
92                                    double_adjustment_update,
93                                    &mapvals.lightsource.position.x);
94   gtk_adjustment_set_value (GTK_ADJUSTMENT (xadj),
95                             mapvals.lightsource.position.x);
96   g_signal_handlers_unblock_by_func (xadj,
97                                      double_adjustment_update,
98                                      &mapvals.lightsource.position.x);
99 
100   g_signal_handlers_block_by_func (yadj,
101                                    double_adjustment_update,
102                                    &mapvals.lightsource.position.y);
103   gtk_adjustment_set_value (GTK_ADJUSTMENT (yadj),
104                             mapvals.lightsource.position.y);
105   g_signal_handlers_unblock_by_func (yadj,
106                                      double_adjustment_update,
107                                      &mapvals.lightsource.position.y);
108 
109   g_signal_handlers_block_by_func (zadj,
110                                    double_adjustment_update,
111                                    &mapvals.lightsource.position.z);
112   gtk_adjustment_set_value (GTK_ADJUSTMENT (zadj),
113                             mapvals.lightsource.position.z);
114   g_signal_handlers_unblock_by_func (zadj,
115                                      double_adjustment_update,
116                                      &mapvals.lightsource.position.z);
117 }
118 
119 /**********************/
120 /* Std. toggle update */
121 /**********************/
122 
123 static void
toggle_update(GtkWidget * widget,gpointer data)124 toggle_update (GtkWidget *widget,
125                gpointer   data)
126 {
127   gimp_toggle_button_update (widget, data);
128 
129   compute_preview_image ();
130   gtk_widget_queue_draw (previewarea);
131 }
132 
133 /*****************************************/
134 /* Main window light type menu callback. */
135 /*****************************************/
136 
137 static void
lightmenu_callback(GtkWidget * widget,gpointer data)138 lightmenu_callback (GtkWidget *widget,
139                     gpointer   data)
140 {
141   int active;
142 
143   gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget),
144                                  &active);
145 
146   mapvals.lightsource.type = active;
147 
148   if (mapvals.lightsource.type == POINT_LIGHT)
149     {
150       gtk_widget_hide (dirlightwid);
151       gtk_widget_show (pointlightwid);
152     }
153   else if (mapvals.lightsource.type == DIRECTIONAL_LIGHT)
154     {
155       gtk_widget_hide (pointlightwid);
156       gtk_widget_show (dirlightwid);
157     }
158   else
159     {
160       gtk_widget_hide (pointlightwid);
161       gtk_widget_hide (dirlightwid);
162     }
163 
164   if (mapvals.livepreview)
165     {
166       compute_preview_image ();
167       gtk_widget_queue_draw (previewarea);
168     }
169 }
170 
171 /***************************************/
172 /* Main window map type menu callback. */
173 /***************************************/
174 
175 static void
mapmenu_callback(GtkWidget * widget,gpointer data)176 mapmenu_callback (GtkWidget *widget,
177                   gpointer   data)
178 {
179   int active;
180 
181   gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget),
182                                  &active);
183 
184   mapvals.maptype = active;
185 
186   if (mapvals.livepreview)
187     {
188       compute_preview_image ();
189       gtk_widget_queue_draw (previewarea);
190     }
191 
192   if (mapvals.maptype == MAP_BOX)
193     {
194       if (cylinder_page && gtk_widget_get_parent (GTK_WIDGET (cylinder_page)) ==
195           GTK_WIDGET (options_note_book))
196         {
197           gtk_container_remove (GTK_CONTAINER (options_note_book), cylinder_page);
198         }
199 
200       if (!box_page)
201         {
202           box_page = create_box_page ();
203           g_object_ref (box_page);
204         }
205       gtk_notebook_append_page (options_note_book,
206                                 box_page,
207                                 gtk_label_new_with_mnemonic (_("_Box")));
208     }
209   else if (mapvals.maptype == MAP_CYLINDER)
210     {
211       if (box_page && gtk_widget_get_parent (GTK_WIDGET (box_page)) ==
212           GTK_WIDGET (options_note_book))
213         {
214           gtk_container_remove (GTK_CONTAINER (options_note_book), box_page);
215         }
216 
217       if (!cylinder_page)
218         {
219           cylinder_page = create_cylinder_page ();
220           g_object_ref (cylinder_page);
221         }
222       gtk_notebook_append_page (options_note_book,
223                                 cylinder_page,
224                                 gtk_label_new_with_mnemonic (_("C_ylinder")));
225     }
226   else
227     {
228       if (box_page && gtk_widget_get_parent (GTK_WIDGET (box_page)) ==
229           GTK_WIDGET (options_note_book))
230         {
231           gtk_container_remove (GTK_CONTAINER (options_note_book), box_page);
232         }
233 
234       if (cylinder_page && gtk_widget_get_parent (GTK_WIDGET (cylinder_page)) ==
235           GTK_WIDGET (options_note_book))
236         {
237           gtk_container_remove (GTK_CONTAINER (options_note_book), cylinder_page);
238         }
239     }
240 }
241 
242 /******************************************/
243 /* Main window "Preview!" button callback */
244 /******************************************/
245 
246 static void
preview_callback(GtkWidget * widget,gpointer data)247 preview_callback (GtkWidget *widget,
248                   gpointer   data)
249 {
250   compute_preview_image ();
251 
252   gtk_widget_queue_draw (previewarea);
253 }
254 
255 static void
zoomed_callback(GimpZoomModel * model)256 zoomed_callback (GimpZoomModel *model)
257 {
258   mapvals.zoom = gimp_zoom_model_get_factor (model);
259 
260   compute_preview_image ();
261 
262   gtk_widget_queue_draw (previewarea);
263 }
264 
265 /**********************************************/
266 /* Main window "Apply" button callback.       */
267 /* Render to GIMP image, close down and exit. */
268 /**********************************************/
269 
270 static gint
box_constrain(gint32 image_id,gint32 drawable_id,gpointer data)271 box_constrain (gint32   image_id,
272                gint32   drawable_id,
273                gpointer data)
274 {
275   if (drawable_id == -1)
276     return TRUE;
277 
278   return (gimp_drawable_is_rgb (drawable_id) &&
279           !gimp_drawable_is_indexed (drawable_id));
280 }
281 
282 static gint
cylinder_constrain(gint32 image_id,gint32 drawable_id,gpointer data)283 cylinder_constrain (gint32   image_id,
284                     gint32   drawable_id,
285                     gpointer data)
286 {
287   if (drawable_id == -1)
288     return TRUE;
289 
290   return (gimp_drawable_is_rgb (drawable_id) &&
291           !gimp_drawable_is_indexed (drawable_id));
292 }
293 
294 /******************************/
295 /* Preview area event handler */
296 /******************************/
297 
298 static gint
preview_events(GtkWidget * area,GdkEvent * event)299 preview_events (GtkWidget *area,
300                 GdkEvent  *event)
301 {
302   HVect __attribute__((unused))pos;
303 /*  HMatrix RotMat;
304   gdouble a,b,c; */
305 
306   switch (event->type)
307     {
308       case GDK_ENTER_NOTIFY:
309         break;
310 
311       case GDK_LEAVE_NOTIFY:
312         break;
313 
314       case GDK_BUTTON_PRESS:
315         light_hit = check_light_hit (event->button.x, event->button.y);
316         if (light_hit == FALSE)
317           {
318             pos.x = -(2.0 * (gdouble) event->button.x /
319                       (gdouble) PREVIEW_WIDTH - 1.0);
320             pos.y = (2.0 * (gdouble) event->button.y /
321                      (gdouble) PREVIEW_HEIGHT - 1.0);
322             /*ArcBall_Mouse(pos);
323             ArcBall_BeginDrag(); */
324           }
325         left_button_pressed = TRUE;
326         break;
327 
328       case GDK_BUTTON_RELEASE:
329         if (light_hit == TRUE)
330           {
331             compute_preview_image ();
332 
333             gtk_widget_queue_draw (previewarea);
334           }
335         else
336           {
337             pos.x = -(2.0 * (gdouble) event->button.x /
338                       (gdouble) PREVIEW_WIDTH - 1.0);
339             pos.y = (2.0 * (gdouble) event->button.y /
340                      (gdouble) PREVIEW_HEIGHT - 1.0);
341             /*ArcBall_Mouse(pos);
342             ArcBall_EndDrag(); */
343           }
344         left_button_pressed = FALSE;
345         break;
346 
347       case GDK_MOTION_NOTIFY:
348         if (left_button_pressed == TRUE)
349           {
350             if (light_hit == TRUE)
351               {
352                 gint live = mapvals.livepreview;
353 
354                 mapvals.livepreview = FALSE;
355                 update_light (event->motion.x, event->motion.y);
356                 update_light_pos_entries ();
357                 mapvals.livepreview = live;
358               }
359             else
360               {
361                 pos.x = -(2.0 * (gdouble) event->motion.x /
362                           (gdouble) PREVIEW_WIDTH - 1.0);
363                 pos.y = (2.0 * (gdouble) event->motion.y /
364                          (gdouble) PREVIEW_HEIGHT - 1.0);
365 /*                ArcBall_Mouse(pos);
366                 ArcBall_Update();
367                 ArcBall_Values(&a,&b,&c);
368                 Alpha+=RadToDeg(-a);
369                 Beta+RadToDeg(-b);
370                 Gamma+=RadToDeg(-c);
371                 if (Alpha>180) Alpha-=360;
372                 if (Alpha<-180) Alpha+=360;
373                 if (Beta>180) Beta-=360;
374                 if (Beta<-180) Beta+=360;
375                 if (Gamma>180) Gamma-=360;
376                 if (Gamma<-180) Gamma+=360;
377                       UpdateAngleSliders(); */
378               }
379           }
380         break;
381 
382       default:
383         break;
384     }
385 
386   return FALSE;
387 }
388 
389 
390 static GtkWidget *
spin_button_new(GtkAdjustment ** adjustment,gdouble value,gdouble lower,gdouble upper,gdouble step_increment,gdouble page_increment,gdouble page_size,gdouble climb_rate,guint digits)391 spin_button_new (GtkAdjustment **adjustment,  /* return value */
392                  gdouble         value,
393                  gdouble         lower,
394                  gdouble         upper,
395                  gdouble         step_increment,
396                  gdouble         page_increment,
397                  gdouble         page_size,
398                  gdouble         climb_rate,
399                  guint           digits)
400 {
401   GtkWidget *spinbutton;
402 
403   *adjustment = (GtkAdjustment *)
404                 gtk_adjustment_new (value, lower, upper,
405                                     step_increment, page_increment, 0);
406 
407   spinbutton = gimp_spin_button_new (GTK_ADJUSTMENT (*adjustment),
408                                      climb_rate, digits);
409 
410   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
411 
412   return spinbutton;
413 }
414 
415 /*******************************/
416 /* Create general options page */
417 /*******************************/
418 
419 static GtkWidget *
create_options_page(void)420 create_options_page (void)
421 {
422   GtkWidget     *page;
423   GtkWidget     *frame;
424   GtkWidget     *vbox;
425   GtkWidget     *hbox;
426   GtkWidget     *label;
427   GtkWidget     *combo;
428   GtkWidget     *toggle;
429   GtkWidget     *table;
430   GtkWidget     *spinbutton;
431   GtkAdjustment *adj;
432 
433   page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
434   gtk_container_set_border_width (GTK_CONTAINER (page), 12);
435 
436   /* General options */
437 
438   frame = gimp_frame_new (_("General Options"));
439   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
440   gtk_widget_show (frame);
441 
442   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
443   gtk_container_add (GTK_CONTAINER (frame), vbox);
444   gtk_widget_show (vbox);
445 
446   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
447   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
448   gtk_widget_show (hbox);
449 
450   label = gtk_label_new (_("Map to:"));
451   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
452   gtk_widget_show (label);
453 
454   combo = gimp_int_combo_box_new (_("Plane"),    MAP_PLANE,
455                                   _("Sphere"),   MAP_SPHERE,
456                                   _("Box"),      MAP_BOX,
457                                   _("Cylinder"), MAP_CYLINDER,
458                                   NULL);
459   gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), mapvals.maptype);
460   gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
461   gtk_widget_show (combo);
462 
463   g_signal_connect (combo, "changed",
464                     G_CALLBACK (mapmenu_callback),
465                     &mapvals.maptype);
466 
467   gimp_help_set_help_data (combo, _("Type of object to map to"), NULL);
468 
469   toggle = gtk_check_button_new_with_label (_("Transparent background"));
470   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
471                                 mapvals.transparent_background);
472   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
473   gtk_widget_show (toggle);
474 
475   g_signal_connect (toggle, "toggled",
476                     G_CALLBACK (toggle_update),
477                     &mapvals.transparent_background);
478 
479   gimp_help_set_help_data (toggle,
480                            _("Make image transparent outside object"), NULL);
481 
482   toggle = gtk_check_button_new_with_label (_("Tile source image"));
483   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
484                                 mapvals.tiled);
485   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
486   gtk_widget_show (toggle);
487 
488   g_signal_connect (toggle, "toggled",
489                     G_CALLBACK (toggle_update),
490                     &mapvals.tiled);
491 
492   gimp_help_set_help_data (toggle,
493                            _("Tile source image: useful for infinite planes"),
494                            NULL);
495 
496   toggle = gtk_check_button_new_with_label (_("Create new image"));
497   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
498                                 mapvals.create_new_image);
499   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
500   gtk_widget_show (toggle);
501 
502   g_signal_connect (toggle, "toggled",
503                     G_CALLBACK (gimp_toggle_button_update),
504                     &mapvals.create_new_image);
505 
506   gimp_help_set_help_data (toggle,
507                            _("Create a new image when applying filter"), NULL);
508 
509   toggle = gtk_check_button_new_with_label (_("Create new layer"));
510   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
511                                 mapvals.create_new_layer);
512   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
513   gtk_widget_show (toggle);
514 
515   g_signal_connect (toggle, "toggled",
516                     G_CALLBACK (gimp_toggle_button_update),
517                     &mapvals.create_new_layer);
518 
519   gimp_help_set_help_data (toggle,
520                            _("Create a new layer when applying filter"), NULL);
521 
522   /* Antialiasing options */
523 
524   frame = gimp_frame_new (NULL);
525   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
526   gtk_widget_show (frame);
527 
528   toggle = gtk_check_button_new_with_mnemonic (_("Enable _antialiasing"));
529   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
530                                 mapvals.antialiasing);
531   gtk_frame_set_label_widget (GTK_FRAME (frame), toggle);
532   gtk_widget_show (toggle);
533 
534   g_signal_connect (toggle, "toggled",
535                     G_CALLBACK (gimp_toggle_button_update),
536                     &mapvals.antialiasing);
537 
538   gimp_help_set_help_data (toggle,
539                            _("Enable/disable jagged edges removal "
540                              "(antialiasing)"), NULL);
541 
542   table = gtk_table_new (2, 3, FALSE);
543   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
544   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
545   gtk_container_add (GTK_CONTAINER (frame), table);
546   gtk_widget_show (table);
547 
548   g_object_bind_property (toggle, "active",
549                           table,  "sensitive",
550                           G_BINDING_SYNC_CREATE);
551 
552   adj = (GtkAdjustment *)
553         gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
554                               _("_Depth:"), 0, 0,
555                               mapvals.maxdepth, 1.0, 5.0, 0.1, 1.0,
556                               1, TRUE, 0, 0,
557                               _("Antialiasing quality. Higher is better, "
558                                "but slower"), NULL);
559   g_signal_connect (adj, "value-changed",
560                     G_CALLBACK (gimp_double_adjustment_update),
561                     &mapvals.maxdepth);
562 
563   spinbutton = spin_button_new (&adj, mapvals.pixelthreshold,
564                                 0.001, 1000, 0.1, 1, 0, 0, 3);
565   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
566                              _("_Threshold:"), 0.0, 0.5,
567                              spinbutton, 1, TRUE);
568 
569   g_signal_connect (adj, "value-changed",
570                     G_CALLBACK (double_adjustment_update),
571                     &mapvals.pixelthreshold);
572 
573   gimp_help_set_help_data (spinbutton,
574                            _("Stop when pixel differences are smaller than "
575                              "this value"), NULL);
576 
577   gtk_widget_show (page);
578 
579   return page;
580 }
581 
582 /******************************/
583 /* Create light settings page */
584 /******************************/
585 
586 static GtkWidget *
create_light_page(void)587 create_light_page (void)
588 {
589   GtkWidget     *page;
590   GtkWidget     *frame;
591   GtkWidget     *table;
592   GtkWidget     *combo;
593   GtkWidget     *colorbutton;
594   GtkWidget     *spinbutton;
595   GtkAdjustment *adj;
596 
597   page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
598   gtk_container_set_border_width (GTK_CONTAINER (page), 12);
599 
600   frame = gimp_frame_new (_("Light Settings"));
601   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
602   gtk_widget_show (frame);
603 
604   table = gtk_table_new (2, 2, FALSE);
605   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
606   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
607   gtk_container_add (GTK_CONTAINER (frame), table);  gtk_widget_show (table);
608 
609   combo = gimp_int_combo_box_new (_("Point light"),       POINT_LIGHT,
610                                   _("Directional light"), DIRECTIONAL_LIGHT,
611                                   _("No light"),          NO_LIGHT,
612                                   NULL);
613   gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo),
614                                  mapvals.lightsource.type);
615   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
616                              _("Lightsource type:"), 0.0, 0.5,
617                              combo, 1, FALSE);
618 
619   g_signal_connect (combo, "changed",
620                     G_CALLBACK (lightmenu_callback),
621                     &mapvals.lightsource.type);
622 
623   gimp_help_set_help_data (combo, _("Type of light source to apply"), NULL);
624 
625   colorbutton = gimp_color_button_new (_("Select lightsource color"),
626                                        64, 16,
627                                        &mapvals.lightsource.color,
628                                        GIMP_COLOR_AREA_FLAT);
629   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
630                              _("Lightsource color:"), 0.0, 0.5,
631                              colorbutton, 1, FALSE);
632 
633   g_signal_connect (colorbutton, "color-changed",
634                     G_CALLBACK (gimp_color_button_get_color),
635                     &mapvals.lightsource.color);
636 
637   gimp_help_set_help_data (colorbutton,
638                            _("Set light source color"), NULL);
639 
640   pointlightwid = gimp_frame_new (_("Position"));
641   gtk_box_pack_start (GTK_BOX (page), pointlightwid, FALSE, FALSE, 0);
642 
643   if (mapvals.lightsource.type == POINT_LIGHT)
644     gtk_widget_show (pointlightwid);
645 
646   table = gtk_table_new (3, 2, FALSE);
647   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
648   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
649   gtk_container_add (GTK_CONTAINER (pointlightwid), table);
650   gtk_widget_show (table);
651 
652   spinbutton = spin_button_new (&xadj, mapvals.lightsource.position.x,
653                                 -G_MAXFLOAT, G_MAXFLOAT,
654                                 0.1, 1.0, 0.0, 0.0, 2);
655   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
656                              _("X:"), 0.0, 0.5,
657                              spinbutton, 1, TRUE);
658 
659   g_signal_connect (xadj, "value-changed",
660                     G_CALLBACK (double_adjustment_update),
661                     &mapvals.lightsource.position.x);
662 
663   gimp_help_set_help_data (spinbutton,
664                            _("Light source X position in XYZ space"), NULL);
665 
666   spinbutton = spin_button_new (&yadj, mapvals.lightsource.position.y,
667                                 -G_MAXFLOAT, G_MAXFLOAT,
668                                 0.1, 1.0, 0.0, 0.0, 2);
669   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
670                              _("Y:"), 0.0, 0.5,
671                              spinbutton, 1, TRUE);
672 
673   g_signal_connect (yadj, "value-changed",
674                     G_CALLBACK (double_adjustment_update),
675                     &mapvals.lightsource.position.y);
676 
677   gimp_help_set_help_data (spinbutton,
678                            _("Light source Y position in XYZ space"), NULL);
679 
680   spinbutton = spin_button_new (&zadj, mapvals.lightsource.position.z,
681                                 -G_MAXFLOAT, G_MAXFLOAT,
682                                 0.1, 1.0, 0.0, 0.0, 2);
683   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
684                              _("Z:"), 0.0, 0.5,
685                              spinbutton, 1, TRUE);
686 
687   g_signal_connect (zadj, "value-changed",
688                     G_CALLBACK (double_adjustment_update),
689                     &mapvals.lightsource.position.z);
690 
691   gimp_help_set_help_data (spinbutton,
692                            _("Light source Z position in XYZ space"), NULL);
693 
694 
695   dirlightwid = gimp_frame_new (_("Direction Vector"));
696   gtk_box_pack_start (GTK_BOX (page), dirlightwid, FALSE, FALSE, 0);
697 
698   if (mapvals.lightsource.type == DIRECTIONAL_LIGHT)
699     gtk_widget_show (dirlightwid);
700 
701   table = gtk_table_new (3, 2, FALSE);
702   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
703   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
704   gtk_container_add (GTK_CONTAINER (dirlightwid), table);
705   gtk_widget_show (table);
706 
707   spinbutton = spin_button_new (&adj, mapvals.lightsource.direction.x,
708                                 -1.0, 1.0, 0.01, 0.1, 0.0, 0.0, 2);
709   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
710                              _("X:"), 0.0, 0.5,
711                              spinbutton, 1, TRUE);
712 
713   g_signal_connect (adj, "value-changed",
714                     G_CALLBACK (double_adjustment_update),
715                     &mapvals.lightsource.direction.x);
716 
717   gimp_help_set_help_data (spinbutton,
718                            _("Light source X direction in XYZ space"), NULL);
719 
720   spinbutton = spin_button_new (&adj, mapvals.lightsource.direction.y,
721                                 -1.0, 1.0, 0.01, 0.1, 0.0, 0.0, 2);
722   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
723                              _("Y:"), 0.0, 0.5,
724                              spinbutton, 1, TRUE);
725 
726   g_signal_connect (adj, "value-changed",
727                     G_CALLBACK (double_adjustment_update),
728                     &mapvals.lightsource.direction.y);
729 
730   gimp_help_set_help_data (spinbutton,
731                            _("Light source Y direction in XYZ space"), NULL);
732 
733   spinbutton = spin_button_new (&adj, mapvals.lightsource.direction.z,
734                                 -1.0, 1.0, 0.01, 0.1, 0.0, 0.0, 2);
735   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
736                              _("Z:"), 0.0, 0.5,
737                              spinbutton, 1, TRUE);
738 
739   g_signal_connect (adj, "value-changed",
740                     G_CALLBACK (double_adjustment_update),
741                     &mapvals.lightsource.direction.z);
742 
743   gimp_help_set_help_data (spinbutton,
744                            _("Light source Z direction in XYZ space"), NULL);
745 
746   gtk_widget_show (page);
747 
748   return page;
749 }
750 
751 /*********************************/
752 /* Create material settings page */
753 /*********************************/
754 
755 static GtkWidget *
create_material_page(void)756 create_material_page (void)
757 {
758   GtkSizeGroup  *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
759   GtkWidget     *page;
760   GtkWidget     *frame;
761   GtkWidget     *table;
762   GtkWidget     *label;
763   GtkWidget     *hbox;
764   GtkWidget     *spinbutton;
765   GtkWidget     *image;
766   GtkAdjustment *adj;
767 
768   page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
769   gtk_container_set_border_width (GTK_CONTAINER (page), 12);
770 
771   frame = gimp_frame_new (_("Intensity Levels"));
772   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
773   gtk_widget_show (frame);
774 
775   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
776   gtk_container_add (GTK_CONTAINER (frame), hbox);
777   gtk_widget_show (hbox);
778 
779   table = gtk_table_new (2, 4, FALSE);
780   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
781   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
782   gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
783   gtk_widget_show (table);
784 
785   /* Ambient intensity */
786 
787   image = gtk_image_new_from_stock (STOCK_INTENSITY_AMBIENT_LOW,
788                                     GTK_ICON_SIZE_BUTTON);
789   label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
790                                      _("Ambient:"), 0.0, 0.5,
791                                      image, 1, FALSE);
792   gtk_size_group_add_widget (group, label);
793 
794   spinbutton = spin_button_new (&adj, mapvals.material.ambient_int,
795                                 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2);
796   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 0, 1,
797                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
798   gtk_widget_show (spinbutton);
799 
800   g_signal_connect (adj, "value-changed",
801                     G_CALLBACK (double_adjustment_update),
802                     &mapvals.material.ambient_int);
803 
804   gimp_help_set_help_data (spinbutton,
805                            _("Amount of original color to show where no "
806                              "direct light falls"), NULL);
807 
808   image = gtk_image_new_from_stock (STOCK_INTENSITY_AMBIENT_HIGH,
809                                     GTK_ICON_SIZE_BUTTON);
810   gtk_table_attach (GTK_TABLE (table), image, 3, 4, 0, 1,
811                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
812   gtk_widget_show (image);
813 
814   /* Diffuse intensity */
815 
816   image = gtk_image_new_from_stock (STOCK_INTENSITY_DIFFUSE_LOW,
817                                     GTK_ICON_SIZE_BUTTON);
818   label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
819                                      _("Diffuse:"), 0.0, 0.5,
820                                      image, 1, FALSE);
821   gtk_size_group_add_widget (group, label);
822 
823   spinbutton = spin_button_new (&adj, mapvals.material.diffuse_int,
824                                 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2);
825   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 1, 2,
826                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
827   gtk_widget_show (spinbutton);
828 
829   g_signal_connect (adj, "value-changed",
830                     G_CALLBACK (double_adjustment_update),
831                     &mapvals.material.diffuse_int);
832 
833   gimp_help_set_help_data (spinbutton,
834                            _("Intensity of original color when lit by a light "
835                              "source"), NULL);
836 
837   image = gtk_image_new_from_stock (STOCK_INTENSITY_DIFFUSE_HIGH,
838                                     GTK_ICON_SIZE_BUTTON);
839   gtk_table_attach (GTK_TABLE (table), image, 3, 4, 1, 2,
840                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
841   gtk_widget_show (image);
842 
843   frame = gimp_frame_new (_("Reflectivity"));
844   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
845   gtk_widget_show (frame);
846 
847   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
848   gtk_container_add (GTK_CONTAINER (frame), hbox);
849   gtk_widget_show (hbox);
850 
851   table = gtk_table_new (3, 4, FALSE);
852   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
853   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
854   gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
855   gtk_widget_show (table);
856 
857   /* Diffuse reflection */
858 
859   image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_DIFFUSE_LOW,
860                                     GTK_ICON_SIZE_BUTTON);
861   label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
862                                      _("Diffuse:"), 0.0, 0.5,
863                                      image, 1, FALSE);
864   gtk_size_group_add_widget (group, label);
865 
866   spinbutton = spin_button_new (&adj, mapvals.material.diffuse_ref,
867                                 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2);
868   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 0, 1,
869                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
870   gtk_widget_show (spinbutton);
871 
872   g_signal_connect (adj, "value-changed",
873                     G_CALLBACK (double_adjustment_update),
874                     &mapvals.material.diffuse_ref);
875 
876   gimp_help_set_help_data (spinbutton,
877                            _("Higher values makes the object reflect more "
878                              "light (appear lighter)"), NULL);
879 
880   image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_DIFFUSE_HIGH,
881                                     GTK_ICON_SIZE_BUTTON);
882   gtk_table_attach (GTK_TABLE (table), image, 3, 4, 0, 1,
883                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
884   gtk_widget_show (image);
885 
886   /* Specular reflection */
887 
888   image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_SPECULAR_LOW,
889                                     GTK_ICON_SIZE_BUTTON);
890   label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
891                                      _("Specular:"), 0.0, 0.5,
892                                      image, 1, FALSE);
893   gtk_size_group_add_widget (group, label);
894 
895   spinbutton = spin_button_new (&adj, mapvals.material.specular_ref,
896                                 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2);
897   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 1, 2,
898                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
899   gtk_widget_show (spinbutton);
900 
901   g_signal_connect (adj, "value-changed",
902                     G_CALLBACK (double_adjustment_update),
903                     &mapvals.material.specular_ref);
904 
905   gimp_help_set_help_data (spinbutton,
906                            _("Controls how intense the highlights will be"),
907                            NULL);
908 
909   image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_SPECULAR_HIGH,
910                                     GTK_ICON_SIZE_BUTTON);
911   gtk_table_attach (GTK_TABLE (table), image, 3, 4, 1, 2,
912                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
913   gtk_widget_show (image);
914 
915   /* Highlight */
916 
917   image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_HIGHLIGHT_LOW,
918                                     GTK_ICON_SIZE_BUTTON);
919   label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
920                                      _("Highlight:"), 0.0, 0.5,
921                                      image, 1, FALSE);
922   gtk_size_group_add_widget (group, label);
923 
924   spinbutton = spin_button_new (&adj, mapvals.material.highlight,
925                                 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2);
926   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 2, 3,
927                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
928   gtk_widget_show (spinbutton);
929 
930   g_signal_connect (adj, "value-changed",
931                     G_CALLBACK (double_adjustment_update),
932                     &mapvals.material.highlight);
933 
934   gimp_help_set_help_data (spinbutton,
935                            _("Higher values makes the highlights more focused"),
936                            NULL);
937 
938   image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_HIGHLIGHT_HIGH,
939                                     GTK_ICON_SIZE_BUTTON);
940   gtk_table_attach (GTK_TABLE (table), image, 3, 4, 2, 3,
941                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
942   gtk_widget_show (image);
943 
944   gtk_widget_show (page);
945 
946   g_object_unref (group);
947 
948   return page;
949 }
950 
951 /****************************************/
952 /* Create orientation and position page */
953 /****************************************/
954 
955 static GtkWidget *
create_orientation_page(void)956 create_orientation_page (void)
957 {
958   GtkSizeGroup  *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
959   GtkWidget     *page;
960   GtkWidget     *frame;
961   GtkWidget     *table;
962   GtkAdjustment *adj;
963 
964   page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
965   gtk_container_set_border_width (GTK_CONTAINER (page), 12);
966 
967   frame = gimp_frame_new (_("Position"));
968   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
969   gtk_widget_show (frame);
970 
971   table = gtk_table_new (3, 3, FALSE);
972   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
973   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
974   gtk_container_add (GTK_CONTAINER (frame), table);
975   gtk_widget_show (table);
976 
977   adj = (GtkAdjustment *)
978         gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
979                               _("X:"), 0, 0,
980                               mapvals.position.x, -1.0, 2.0, 0.01, 0.1, 5,
981                               TRUE, 0, 0,
982                               _("Object X position in XYZ space"), NULL);
983   gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj));
984   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
985                              GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 5);
986 
987   g_signal_connect (adj, "value-changed",
988                     G_CALLBACK (double_adjustment_update),
989                     &mapvals.position.x);
990 
991   adj = (GtkAdjustment *)
992         gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
993                               _("Y:"), 0, 0,
994                               mapvals.position.y, -1.0, 2.0, 0.01, 0.1, 5,
995                               TRUE, 0, 0,
996                               _("Object Y position in XYZ space"), NULL);
997   gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj));
998   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
999                              GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 5);
1000 
1001   g_signal_connect (adj, "value-changed",
1002                     G_CALLBACK (double_adjustment_update),
1003                     &mapvals.position.y);
1004 
1005   adj = (GtkAdjustment *)
1006         gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
1007                               _("Z:"), 0, 0,
1008                               mapvals.position.z, -1.0, 2.0, 0.01, 0.1, 5,
1009                               TRUE, 0, 0,
1010                               _("Object Z position in XYZ space"), NULL);
1011   gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj));
1012   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
1013                              GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 5);
1014 
1015   g_signal_connect (adj, "value-changed",
1016                     G_CALLBACK (double_adjustment_update),
1017                     &mapvals.position.z);
1018 
1019   frame = gimp_frame_new (_("Rotation"));
1020   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
1021   gtk_widget_show (frame);
1022 
1023   table = gtk_table_new (3, 3, FALSE);
1024   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1025   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1026   gtk_container_add (GTK_CONTAINER (frame), table);
1027   gtk_widget_show (table);
1028 
1029   adj = (GtkAdjustment *)
1030         gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
1031                               _("X:"), 0, 0,
1032                               mapvals.alpha, -180.0, 180.0, 1.0, 15.0, 1,
1033                               TRUE, 0, 0,
1034                               _("Rotation angle about X axis"), NULL);
1035   gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj));
1036 
1037   g_signal_connect (adj, "value-changed",
1038                     G_CALLBACK (double_adjustment_update),
1039                     &mapvals.alpha);
1040 
1041   adj = (GtkAdjustment *)
1042         gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
1043                               _("Y:"), 0, 0,
1044                               mapvals.beta, -180.0, 180.0, 1.0, 15.0, 1,
1045                               TRUE, 0, 0,
1046                               _("Rotation angle about Y axis"), NULL);
1047   gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj));
1048 
1049   g_signal_connect (adj, "value-changed",
1050                     G_CALLBACK (double_adjustment_update),
1051                     &mapvals.beta);
1052 
1053   adj = (GtkAdjustment *)
1054         gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
1055                               _("Z:"), 0, 0,
1056                               mapvals.gamma, -180.0, 180.0, 1.0, 15.0, 1,
1057                               TRUE, 0, 0,
1058                               _("Rotation angle about Z axis"), NULL);
1059   gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj));
1060 
1061   g_signal_connect (adj, "value-changed",
1062                     G_CALLBACK (double_adjustment_update),
1063                     &mapvals.gamma);
1064 
1065   gtk_widget_show (page);
1066 
1067   g_object_unref (group);
1068 
1069   return page;
1070 }
1071 
1072 static GtkWidget *
create_box_page(void)1073 create_box_page (void)
1074 {
1075   GtkWidget     *page;
1076   GtkWidget     *frame;
1077   GtkWidget     *vbox;
1078   GtkWidget     *table;
1079   GtkAdjustment *adj;
1080   gint           i;
1081 
1082   static gchar *labels[] =
1083   {
1084     N_("Front:"), N_("Back:"),
1085     N_("Top:"),   N_("Bottom:"),
1086     N_("Left:"),  N_("Right:")
1087   };
1088 
1089   page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
1090   gtk_container_set_border_width (GTK_CONTAINER (page), 12);
1091 
1092   frame = gimp_frame_new (_("Map Images to Box Faces"));
1093   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
1094   gtk_widget_show (frame);
1095 
1096   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
1097   gtk_container_add (GTK_CONTAINER (frame), vbox);
1098   gtk_widget_show (vbox);
1099 
1100   table = gtk_table_new (6, 2, FALSE);
1101   gtk_table_set_row_spacings (GTK_TABLE(table), 6);
1102   gtk_table_set_col_spacings (GTK_TABLE(table), 6);
1103   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 5);
1104   gtk_widget_show (table);
1105 
1106   for (i = 0; i < 6; i++)
1107     {
1108       GtkWidget *combo;
1109 
1110       combo = gimp_drawable_combo_box_new (box_constrain, NULL);
1111       gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
1112                                   mapvals.boxmap_id[i],
1113                                   G_CALLBACK (gimp_int_combo_box_get_active),
1114                                   &mapvals.boxmap_id[i]);
1115 
1116       gimp_table_attach_aligned (GTK_TABLE (table), 0, i,
1117                                  gettext (labels[i]), 0.0, 0.5,
1118                                  combo, 1, FALSE);
1119     }
1120 
1121   /* Scale scales */
1122 
1123   table = gtk_table_new (3, 3, FALSE);
1124   gtk_table_set_row_spacings (GTK_TABLE(table), 6);
1125   gtk_table_set_col_spacings (GTK_TABLE(table), 6);
1126   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
1127   gtk_widget_show (table);
1128 
1129   adj = (GtkAdjustment *)
1130         gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
1131                               _("Scale X:"), 0, 0,
1132                               mapvals.scale.x, 0.0, 5.0, 0.01, 0.1, 2,
1133                               TRUE, 0, 0,
1134                               _("X scale (size)"), NULL);
1135   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
1136                              GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2);
1137 
1138   g_signal_connect (adj, "value-changed",
1139                     G_CALLBACK (double_adjustment_update),
1140                     &mapvals.scale.x);
1141 
1142   adj = (GtkAdjustment *)
1143         gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
1144                               _("Y:"), 0, 0,
1145                               mapvals.scale.y, 0.0, 5.0, 0.01, 0.1, 2,
1146                               TRUE, 0, 0,
1147                               _("Y scale (size)"), NULL);
1148   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
1149                              GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2);
1150 
1151   g_signal_connect (adj, "value-changed",
1152                     G_CALLBACK (double_adjustment_update),
1153                     &mapvals.scale.y);
1154 
1155   adj = (GtkAdjustment *)
1156         gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
1157                               _("Z:"), 0, 0,
1158                               mapvals.scale.z, 0.0, 5.0, 0.01, 0.1, 2,
1159                               TRUE, 0, 0,
1160                               _("Z scale (size)"), NULL);
1161   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
1162                              GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2);
1163 
1164   g_signal_connect (adj, "value-changed",
1165                     G_CALLBACK (double_adjustment_update),
1166                     &mapvals.scale.z);
1167 
1168   gtk_widget_show (page);
1169 
1170   return page;
1171 }
1172 
1173 static GtkWidget *
create_cylinder_page(void)1174 create_cylinder_page (void)
1175 {
1176   GtkSizeGroup  *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
1177   GtkWidget     *page;
1178   GtkWidget     *frame;
1179   GtkWidget     *table;
1180   GtkAdjustment *adj;
1181   gint           i;
1182 
1183   static const gchar *labels[] = { N_("_Top:"), N_("_Bottom:") };
1184 
1185   page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
1186   gtk_container_set_border_width (GTK_CONTAINER (page), 12);
1187 
1188   frame = gimp_frame_new (_("Images for the Cap Faces"));
1189   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
1190   gtk_widget_show (frame);
1191 
1192   table = gtk_table_new (2, 2, FALSE);
1193   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1194   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1195   gtk_container_add (GTK_CONTAINER (frame), table);
1196   gtk_widget_show (table);
1197 
1198   /* Option menus */
1199 
1200   for (i = 0; i < 2; i++)
1201     {
1202       GtkWidget *combo;
1203       GtkWidget *label;
1204 
1205       combo = gimp_drawable_combo_box_new (cylinder_constrain, NULL);
1206       gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
1207                                   mapvals.cylindermap_id[i],
1208                                   G_CALLBACK (gimp_int_combo_box_get_active),
1209                                   &mapvals.cylindermap_id[i]);
1210 
1211       label = gimp_table_attach_aligned (GTK_TABLE (table), 0, i,
1212                                          gettext (labels[i]), 0.0, 0.5,
1213                                          combo, 1, FALSE);
1214       gtk_size_group_add_widget (group, label);
1215     }
1216 
1217   frame = gimp_frame_new (_("Size"));
1218   gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
1219   gtk_widget_show (frame);
1220 
1221   table = gtk_table_new (2, 3, FALSE);
1222   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1223   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1224   gtk_container_add (GTK_CONTAINER (frame), table);
1225   gtk_widget_show (table);
1226 
1227   adj = (GtkAdjustment *)
1228         gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
1229                               _("R_adius:"), 0, 0,
1230                               mapvals.cylinder_radius,
1231                               0.0, 2.0, 0.01, 0.1, 2,
1232                               TRUE, 0, 0,
1233                               _("Cylinder radius"), NULL);
1234   gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_LABEL (adj));
1235   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
1236                              GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2);
1237 
1238   g_signal_connect (adj, "value-changed",
1239                     G_CALLBACK (double_adjustment_update),
1240                     &mapvals.cylinder_radius);
1241 
1242   adj = (GtkAdjustment *)
1243         gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
1244                               _("L_ength:"), 0, 0,
1245                               mapvals.cylinder_length,
1246                               0.0, 2.0, 0.01, 0.1, 2,
1247                               TRUE, 0, 0,
1248                               _("Cylinder length"), NULL);
1249   gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_LABEL (adj));
1250   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
1251                              GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2);
1252 
1253   g_signal_connect (adj, "value-changed",
1254                     G_CALLBACK (double_adjustment_update),
1255                     &mapvals.cylinder_length);
1256 
1257   gtk_widget_show (page);
1258 
1259   g_object_unref (group);
1260 
1261   return page;
1262 }
1263 
1264 /****************************/
1265 /* Create notbook and pages */
1266 /****************************/
1267 
1268 static void
create_main_notebook(GtkWidget * container)1269 create_main_notebook (GtkWidget *container)
1270 {
1271   GtkWidget *page;
1272 
1273   options_note_book = GTK_NOTEBOOK (gtk_notebook_new ());
1274   gtk_container_add (GTK_CONTAINER (container),
1275                      GTK_WIDGET (options_note_book));
1276 
1277   page = create_options_page ();
1278   gtk_notebook_append_page (options_note_book, page,
1279                             gtk_label_new_with_mnemonic (_("O_ptions")));
1280 
1281   page = create_light_page ();
1282   gtk_notebook_append_page (options_note_book, page,
1283                             gtk_label_new_with_mnemonic (_("_Light")));
1284 
1285   page = create_material_page ();
1286   gtk_notebook_append_page (options_note_book, page,
1287                             gtk_label_new_with_mnemonic (_("_Material")));
1288 
1289   page = create_orientation_page ();
1290   gtk_notebook_append_page (options_note_book, page,
1291                             gtk_label_new_with_mnemonic (_("O_rientation")));
1292 
1293   if (mapvals.maptype == MAP_BOX)
1294     {
1295       box_page = create_box_page ();
1296       g_object_ref (box_page);
1297       gtk_notebook_append_page (options_note_book, box_page,
1298                                 gtk_label_new_with_mnemonic (_("_Box")));
1299     }
1300   else if (mapvals.maptype == MAP_CYLINDER)
1301     {
1302       cylinder_page = create_cylinder_page ();
1303       g_object_ref (cylinder_page);
1304       gtk_notebook_append_page (options_note_book, cylinder_page,
1305                                 gtk_label_new_with_mnemonic (_("C_ylinder")));
1306     }
1307 
1308   gtk_widget_show (GTK_WIDGET (options_note_book));
1309 }
1310 
1311 /********************************/
1312 /* Create and show main dialog. */
1313 /********************************/
1314 
1315 gboolean
main_dialog(gint32 drawable_id)1316 main_dialog (gint32 drawable_id)
1317 {
1318   GtkWidget     *main_hbox;
1319   GtkWidget     *vbox;
1320   GtkWidget     *hbox;
1321   GtkWidget     *frame;
1322   GtkWidget     *button;
1323   GtkWidget     *toggle;
1324   GimpZoomModel *model;
1325   gboolean       run = FALSE;
1326 
1327   gimp_ui_init (PLUG_IN_BINARY, FALSE);
1328 
1329   appwin = gimp_dialog_new (_("Map to Object"), PLUG_IN_ROLE,
1330                             NULL, 0,
1331                             gimp_standard_help_func, PLUG_IN_PROC,
1332 
1333                             _("_Cancel"), GTK_RESPONSE_CANCEL,
1334                             _("_OK"),     GTK_RESPONSE_OK,
1335 
1336                             NULL);
1337 
1338   gtk_dialog_set_alternative_button_order (GTK_DIALOG (appwin),
1339                                            GTK_RESPONSE_OK,
1340                                            GTK_RESPONSE_CANCEL,
1341                                            -1);
1342 
1343   gimp_window_set_transient (GTK_WINDOW (appwin));
1344 
1345   main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
1346   gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
1347   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (appwin))),
1348                       main_hbox, FALSE, FALSE, 0);
1349   gtk_widget_show (main_hbox);
1350 
1351   /* Create the Preview */
1352 
1353   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1354   gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0);
1355   gtk_widget_show (vbox);
1356 
1357   /* Add preview widget and various buttons to the first part */
1358 
1359   frame = gtk_frame_new (NULL);
1360   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1361   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1362   gtk_widget_show (frame);
1363 
1364   gtk_widget_realize (appwin);
1365   previewarea = gtk_drawing_area_new ();
1366   gtk_widget_set_size_request (previewarea, PREVIEW_WIDTH, PREVIEW_HEIGHT);
1367   gtk_widget_set_events (previewarea, (GDK_EXPOSURE_MASK |
1368                                        GDK_BUTTON1_MOTION_MASK |
1369                                        GDK_BUTTON_PRESS_MASK |
1370                                        GDK_BUTTON_RELEASE_MASK));
1371   gtk_container_add (GTK_CONTAINER (frame), previewarea);
1372   gtk_widget_show (previewarea);
1373 
1374   g_signal_connect (previewarea, "event",
1375                     G_CALLBACK (preview_events),
1376                     previewarea);
1377 
1378   g_signal_connect (previewarea, "expose-event",
1379                     G_CALLBACK (preview_expose),
1380                     previewarea);
1381 
1382   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1383   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1384   gtk_widget_show (hbox);
1385 
1386   button = gtk_button_new_with_mnemonic (_("_Preview!"));
1387   gtk_misc_set_padding (GTK_MISC (gtk_bin_get_child (GTK_BIN (button))), 2, 0);
1388   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1389   gtk_widget_show (button);
1390 
1391   g_signal_connect (button, "clicked",
1392                     G_CALLBACK (preview_callback),
1393                     NULL);
1394 
1395   gimp_help_set_help_data (button, _("Recompute preview image"), NULL);
1396 
1397   model = gimp_zoom_model_new ();
1398   gimp_zoom_model_set_range (model, 0.25, 1.0);
1399   gimp_zoom_model_zoom (model, GIMP_ZOOM_TO, mapvals.zoom);
1400 
1401   button = gimp_zoom_button_new (model, GIMP_ZOOM_IN, GTK_ICON_SIZE_MENU);
1402   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1403   gtk_widget_show (button);
1404 
1405   button = gimp_zoom_button_new (model, GIMP_ZOOM_OUT, GTK_ICON_SIZE_MENU);
1406   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1407   gtk_widget_show (button);
1408 
1409   g_signal_connect (model, "zoomed",
1410                     G_CALLBACK (zoomed_callback),
1411                     NULL);
1412 
1413   toggle = gtk_check_button_new_with_mnemonic (_("Show _wireframe"));
1414   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), mapvals.showgrid);
1415   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
1416   gtk_widget_show (toggle);
1417 
1418   g_signal_connect (toggle, "toggled",
1419                     G_CALLBACK (toggle_update),
1420                     &mapvals.showgrid);
1421 
1422   toggle = gtk_check_button_new_with_mnemonic (_("Update preview _live"));
1423   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), mapvals.livepreview);
1424   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
1425   gtk_widget_show (toggle);
1426 
1427   g_signal_connect (toggle, "toggled",
1428                     G_CALLBACK (toggle_update),
1429                     &mapvals.livepreview);
1430 
1431   create_main_notebook (main_hbox);
1432 
1433   gtk_widget_show (appwin);
1434 
1435   {
1436     GdkCursor *cursor;
1437 
1438     cursor = gdk_cursor_new_for_display (gtk_widget_get_display (previewarea),
1439                                          GDK_HAND2);
1440     gdk_window_set_cursor (gtk_widget_get_window (previewarea), cursor);
1441     gdk_cursor_unref (cursor);
1442   }
1443 
1444   image_setup (drawable_id, TRUE);
1445 
1446   compute_preview_image ();
1447 
1448   if (gimp_dialog_run (GIMP_DIALOG (appwin)) == GTK_RESPONSE_OK)
1449     run = TRUE;
1450 
1451   gtk_widget_destroy (appwin);
1452   if (preview_rgb_data)
1453     g_free (preview_rgb_data);
1454   if (preview_surface)
1455     cairo_surface_destroy (preview_surface);
1456   if (box_page)
1457     g_object_unref (box_page);
1458   if (cylinder_page)
1459     g_object_unref (cylinder_page);
1460 
1461   return run;
1462 }
1463