1 /*
2 * File: mat_edit.c
3 *
4 * Description: Allows user to change a material's properties (things like
5 * diffuse, ambient, etc colors)
6 *
7 * This source code is part of kludge3d, and is released under the
8 * GNU General Public License.
9 *
10 *
11 */
12
13
14 /*
15 * Portions of this file are from:
16 *
17 * ME3D 3-D Modeler Program
18 * Copyright (C) 1998 Sam Revitch
19 *
20 * The original file was a complete mess, though. I've cleaned it up a bit;
21 * "refactored" is probably an appropriate term. Much of the duplicate
22 * code has been consolidated.
23 *
24 * I've also ported the code to GTK2; this was difficult, as Revitch used many
25 * deprecated features of GTK1.
26 */
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include <gtk/gtk.h>
34 #include <GL/gl.h>
35 #include <GL/glu.h>
36
37 #include "mat_edit.h"
38 #include "mat_preview.h"
39 #include "material.h"
40 #include "globals.h"
41 #include "gui.h"
42
43
44 #ifdef MEMWATCH
45 #include "memwatch.h"
46 #endif
47
48
49 #define MATEDIT_ZERO_THRESHOLD 0.00001
50
51
52 typedef struct _MatEditData MatEditData;
53 struct _MatEditData {
54 GtkWidget *MainWin;
55 GtkWidget *MatPreview;
56 GtkWidget *MatNotebook;
57 GtkWidget *MatPicker;
58 GtkWidget *MatPickerBox;
59 GtkAdjustment *SliderAdj[MAT_INDEX_NUM_INDICES];
60 GtkWidget *SwatchWidget[MAT_INDEX_NUM_INDICES];
61 GdkPixbuf *SwatchPixbuf[MAT_INDEX_NUM_INDICES];
62 guint cont_update, active_preview, freeze, lock_intensity;
63 /* base color */
64 float bc[4][4];
65 /* base intensities; 4th element not used, but needed for matedit_normalize_attribute */
66 float bi[4];
67 /* previous color, needed for color picker->cancel */
68 GLfloat pc[4];
69 Material *material;
70 };
71
72 MatEditData *GlobalMatEdit = NULL;
73
74
75 MatEditData *matedit_new( void );
76 GtkWidget *mat_edit_create_slider(
77 char *str, int index, MatEditData *med );
78 gboolean matedit_cleanup( gpointer data ) ;
79 void matedit_hide(MatEditData *med);
80 void matedit_set_material( MatEditData *med, Material *material ) ;
81 void matedit_update_color_swatch(
82 GdkPixbuf *pixbuf, GtkWidget *parent, GLfloat *color );
83 void matedit_recompute_base_intensities(MatEditData *med);
84 float matedit_normalize_attribute( float dest[4], float src[4] ) ;
85 void matedit_toggle_intensity_lock(GtkWidget *widget, MatEditData *med);
86
87 void matedit_colorpicker_show(GtkWidget *widget, guint color_id);
88 void matedit_colorpicker_changed_cb(GtkWidget *widget, MatEditData *med);
89 void matedit_colorpicker_ok(GtkWidget *widget, MatEditData *med);
90 void matedit_colorpicker_close(GtkWidget *widget, MatEditData *med);
91 void matedit_colorpicker_close_2(GtkWidget *widget, GdkEvent *event,
92 MatEditData *med);
93
94 void matedit_color_changed(GtkWidget *widget, MatEditData *med);
95 void matedit_slider_changed(GtkAdjustment *adj, int index );
96
97 void matedit_set_preview_value(MatEditData *med, GLfloat *v, int i ) ;
98
99 void matedit_kill_dialog(GtkWidget *widget, GdkEvent *event,
100 MatEditData *med);
101 void matedit_ok(GtkWidget *widget, MatEditData *med);
102 void matedit_apply(GtkWidget *widget, MatEditData *med);
103 void matedit_cancel(GtkWidget *widget, MatEditData *med);
104
105 void matedit_gdkcolor_to_floats( GdkColor *gdkcolor, float *color ) ;
106 void matedit_floats_to_gdkcolor( GdkColor *gdkcolor, float *color ) ;
107 void matedit_get_color( MatEditData *med, int index, float color[4] ) ;
108 float matedit_get_shininess( MatEditData *med ) ;
109
110
matedit_new(void)111 MatEditData *matedit_new( void )
112 {
113 MatEditData *med;
114 GtkWidget *widget, *vbox, *hbox;
115 GtkWidget *slider_vbox;
116
117 med = (MatEditData *) malloc(sizeof(MatEditData));
118 memset(med, 0, sizeof(MatEditData));
119
120 med->cont_update = TRUE;
121
122 /* Before we go any farther, check to make sure that we can create a
123 valid mat_preview. */
124 med->MatPreview = mat_preview_new();
125 if( med->MatPreview == NULL ) {
126 free( med );
127 return NULL;
128 }
129
130 /* begin dialog box */
131 med->MainWin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
132 gtk_window_set_title(GTK_WINDOW(med->MainWin), "Material Properties");
133
134 /* make the med window a child of the TLW */
135 gtk_window_set_transient_for( GTK_WINDOW(med->MainWin), GTK_WINDOW(TopLevelWindow) );
136 /* ensure that the med window will go away when the program exits */
137 gtk_window_set_destroy_with_parent( GTK_WINDOW(med->MainWin), TRUE );
138
139 g_signal_connect(G_OBJECT(med->MainWin), "delete_event",
140 G_CALLBACK(matedit_kill_dialog), (gpointer) med);
141 gtk_container_set_border_width(GTK_CONTAINER(med->MainWin), 4);
142
143 vbox = gtk_vbox_new(FALSE, 10);
144 gtk_container_add(GTK_CONTAINER(med->MainWin), vbox);
145 gtk_widget_show(vbox);
146
147 hbox = gtk_hbox_new(FALSE, 4);
148 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
149 gtk_widget_show(hbox);
150
151 widget = gtk_frame_new(NULL);
152 gtk_frame_set_shadow_type (GTK_FRAME(widget), GTK_SHADOW_IN);
153 gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0);
154 gtk_widget_show(widget);
155
156 gtk_container_add(GTK_CONTAINER(widget), med->MatPreview);
157 gtk_widget_show(med->MatPreview);
158
159 med->MatNotebook = gtk_notebook_new();
160 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(med->MatNotebook), GTK_POS_TOP);
161 gtk_box_pack_start(GTK_BOX(hbox), med->MatNotebook, FALSE, FALSE, 0);
162 gtk_widget_show(med->MatNotebook);
163
164
165 /** Color Picker Tab **/
166 widget = gtk_label_new("Quick-Set Color Picker");
167 med->MatPicker = gtk_color_selection_new();
168 gtk_color_selection_set_has_opacity_control(GTK_COLOR_SELECTION(med->MatPicker), TRUE);
169 g_signal_connect(G_OBJECT(med->MatPicker), "color_changed",
170 G_CALLBACK(matedit_color_changed), (gpointer) med);
171
172 gtk_notebook_append_page(GTK_NOTEBOOK(med->MatNotebook),
173 med->MatPicker, widget);
174 gtk_widget_show(widget);
175 gtk_widget_show(med->MatPicker);
176
177
178 /** Levels Tab **/
179 slider_vbox = gtk_vbox_new( FALSE, 4 );
180 gtk_notebook_append_page( GTK_NOTEBOOK(med->MatNotebook),
181 slider_vbox, gtk_label_new("Individual Colors") );
182
183 gtk_box_pack_start( GTK_BOX(slider_vbox),
184 mat_edit_create_slider( "Diffuse:", MAT_INDEX_DIFFUSE, med ),
185 FALSE, FALSE, 0 );
186 gtk_box_pack_start( GTK_BOX(slider_vbox),
187 mat_edit_create_slider( "Ambient:", MAT_INDEX_AMBIENT, med ),
188 FALSE, FALSE, 0 );
189 gtk_box_pack_start( GTK_BOX(slider_vbox),
190 mat_edit_create_slider( "Emission:", MAT_INDEX_EMISSION, med ),
191 FALSE, FALSE, 0 );
192
193 widget = gtk_check_button_new_with_label("Lock Intensities");
194 g_signal_connect(G_OBJECT(widget), "toggled",
195 G_CALLBACK( matedit_toggle_intensity_lock),
196 (gpointer) med);
197 gtk_box_pack_start( GTK_BOX(slider_vbox), widget, FALSE, FALSE, 0 );
198 gtk_widget_show(widget);
199 gtk_widget_show( slider_vbox );
200
201
202 /** Reflection Tab **/
203 slider_vbox = gtk_vbox_new( FALSE, 4 );
204 gtk_notebook_append_page( GTK_NOTEBOOK(med->MatNotebook),
205 slider_vbox, gtk_label_new("Reflection") );
206
207 gtk_box_pack_start( GTK_BOX(slider_vbox),
208 mat_edit_create_slider( "Specular:", MAT_INDEX_SPECULAR, med ),
209 FALSE, FALSE, 0 );
210 gtk_box_pack_start( GTK_BOX(slider_vbox),
211 mat_edit_create_slider( "Shininess:", MAT_INDEX_SHININESS, med ),
212 FALSE, FALSE, 0 );
213
214 gtk_widget_show( slider_vbox );
215
216
217 /** OK/cancel buttons **/
218 hbox = gtk_hbox_new(FALSE, 10);
219 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
220 gtk_widget_show(hbox);
221 widget = gtk_button_new_with_label("OK");
222 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
223 gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0);
224 g_signal_connect(G_OBJECT(widget), "clicked",
225 G_CALLBACK(matedit_ok), (gpointer) med);
226 gtk_widget_show(widget);
227 gtk_widget_grab_default(widget);
228 widget = gtk_button_new_with_label("Apply");
229 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
230 gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0);
231 g_signal_connect(G_OBJECT(widget), "clicked",
232 G_CALLBACK(matedit_apply), (gpointer) med);
233 gtk_widget_show(widget);
234 widget = gtk_button_new_with_label("Cancel");
235 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
236 gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0);
237 g_signal_connect(G_OBJECT(widget), "clicked",
238 G_CALLBACK(matedit_cancel), (gpointer) med);
239 gtk_widget_show(widget);
240 /* end of dialog box */
241
242
243 /** Ancillary floating color picker **/
244 med->MatPickerBox = gtk_color_selection_dialog_new("Select Color");
245 g_signal_connect(G_OBJECT(med->MatPickerBox), "delete_event",
246 G_CALLBACK(matedit_colorpicker_close_2), (gpointer) med);
247 g_signal_connect(
248 G_OBJECT(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->colorsel),
249 "color_changed", G_CALLBACK(matedit_colorpicker_changed_cb), (gpointer) med);
250 g_signal_connect(
251 G_OBJECT(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->ok_button),
252 "clicked", G_CALLBACK(matedit_colorpicker_ok), (gpointer) med);
253 g_signal_connect(
254 G_OBJECT(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->cancel_button),
255 "clicked", G_CALLBACK(matedit_colorpicker_close), (gpointer) med);
256
257 return med;
258 }
259
260
mat_edit_create_slider(char * str,int index,MatEditData * med)261 GtkWidget *mat_edit_create_slider(
262 char *str, int index, MatEditData *med )
263 {
264 GtkWidget *widget, *hbox;
265 GtkAdjustment *adj;
266
267 hbox = gtk_hbox_new(FALSE, 4);
268
269 widget = gtk_label_new( str );
270 gtk_box_pack_start( GTK_BOX(hbox), widget, TRUE, TRUE, 0 );
271 gtk_widget_show(widget);
272
273 /* ADJUSTMENT */
274 if( index != MAT_INDEX_SHININESS ) {
275 adj = (GtkAdjustment *)
276 gtk_adjustment_new( 0.0, 0.0, 1.0, 0.01, 0.01, 0.01 );
277 } else {
278 adj = (GtkAdjustment *)
279 gtk_adjustment_new( 0.0, 0.0, 128.0, 1.0, 1.0, 1.0 );
280 }
281 g_object_set_data(G_OBJECT(adj), "MatEditStruct", (gpointer) med);
282 g_signal_connect(G_OBJECT(adj), "value_changed",
283 G_CALLBACK(matedit_slider_changed), (gpointer) index);
284 med->SliderAdj[index] = adj;
285
286 /* SCALE / SLIDER */
287 widget = gtk_hscale_new(adj);
288 if(med->cont_update)
289 gtk_range_set_update_policy(GTK_RANGE(widget), GTK_UPDATE_CONTINUOUS);
290 else
291 gtk_range_set_update_policy(GTK_RANGE(widget), GTK_UPDATE_DISCONTINUOUS);
292 gtk_range_set_inverted( GTK_RANGE(widget), index == MAT_INDEX_SHININESS );
293 gtk_scale_set_draw_value(GTK_SCALE(widget), FALSE);
294 gtk_scale_set_digits( GTK_SCALE(widget), 3 );
295 gtk_box_pack_start( GTK_BOX(hbox), widget, FALSE, FALSE, 0 );
296 gtk_widget_set_size_request( widget, 160, 20 );
297 gtk_widget_show(widget);
298
299 /* SPINBUTTON */
300 widget = gtk_spin_button_new( adj, 0.1, 3 );
301 gtk_box_pack_start( GTK_BOX(hbox), widget, FALSE, FALSE, 0 );
302 gtk_widget_set_size_request( widget, 50, 20 );
303 gtk_widget_show(widget);
304
305 /* BUTTON & COLOR-SWATCH */
306 if( index != MAT_INDEX_SHININESS ) {
307 GdkPixbuf *pixbuf;
308
309 widget = gtk_button_new();
310 g_object_set_data(G_OBJECT(widget), "MatEditStruct", (gpointer) med);
311 g_signal_connect(G_OBJECT(widget), "clicked",
312 G_CALLBACK(matedit_colorpicker_show), (gpointer) index);
313 gtk_box_pack_start( GTK_BOX(hbox), widget, FALSE, FALSE, 0 );
314
315 pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, 32, 20 );
316 gdk_pixbuf_fill( pixbuf, 0x000000ff );
317 med->SwatchWidget[index] = gtk_image_new_from_pixbuf( pixbuf );
318 med->SwatchPixbuf[index] = pixbuf;
319 g_object_unref( pixbuf );
320
321 gtk_container_add(GTK_CONTAINER(widget), med->SwatchWidget[index]);
322 gtk_widget_show(med->SwatchWidget[index]);
323
324 gtk_widget_show(widget);
325 }
326
327 gtk_widget_show_all( hbox );
328 return hbox;
329 }
330
331
matedit_show(Material * material)332 void matedit_show( Material *material )
333 {
334 if( GlobalMatEdit == NULL ) {
335 GlobalMatEdit = matedit_new();
336 g_signal_connect( notificationObj, "notify::exit",
337 G_CALLBACK(matedit_cleanup), NULL );
338 }
339
340 /* if it is still NULL, something went wrong */
341 if( GlobalMatEdit == NULL ) {
342 fprintf( stderr, "%s : unable to create material editor\n", __FUNCTION__ );
343 return;
344 }
345
346 matedit_set_material( GlobalMatEdit, material );
347
348 gtk_widget_show(GlobalMatEdit->MainWin);
349 }
350
351
matedit_cleanup(gpointer data)352 gboolean matedit_cleanup( gpointer data ) {
353 if( GlobalMatEdit != NULL ) {
354 free( GlobalMatEdit );
355 GlobalMatEdit = NULL;
356 }
357
358 return FALSE;
359 }
360
361
matedit_hide(MatEditData * med)362 void matedit_hide(MatEditData *med)
363 {
364 g_return_if_fail(med != NULL);
365 g_return_if_fail(med->MainWin != NULL);
366 gtk_widget_hide(med->MatPickerBox);
367 gtk_widget_hide(med->MainWin);
368 }
369
370
matedit_set_material(MatEditData * med,Material * material)371 void matedit_set_material( MatEditData *med, Material *material ) {
372 int i;
373 float v;
374 GtkAdjustment *adj;
375 GdkColor gdkcolor;
376
377 med->material = material;
378
379 material_copy_to_array( med->material, med->bc );
380
381 /* for all 4 elems of med->bc: normalize; use return value to set slider
382 value */
383 for( i = 0; i < 4; i++ ) {
384 v = matedit_normalize_attribute( med->bc[i], med->bc[i] );
385 adj = med->SliderAdj[i];
386 adj->value = v;
387 g_signal_emit_by_name( G_OBJECT(adj), "value_changed" );
388 }
389
390 /* set gdkcolor to med->bc[MAT_INDEX_DIFFUSE] */
391 matedit_floats_to_gdkcolor( &gdkcolor, med->bc[MAT_INDEX_DIFFUSE] );
392 /* ... and update the color picker */
393 gtk_color_selection_set_current_color(
394 GTK_COLOR_SELECTION(med->MatPicker),
395 &gdkcolor );
396
397 /* set shininess slider */
398 adj = med->SliderAdj[MAT_INDEX_SHININESS];
399 adj->value = material->shininess;
400 g_signal_emit_by_name( G_OBJECT(adj), "value_changed" );
401
402 matedit_recompute_base_intensities( med );
403 }
404
405
matedit_update_color_swatch(GdkPixbuf * pixbuf,GtkWidget * parent,GLfloat * color)406 void matedit_update_color_swatch(
407 GdkPixbuf *pixbuf, GtkWidget *parent, GLfloat *color )
408 {
409 guint32 fill_color = 0;
410 guchar c[3];
411
412 if( pixbuf == NULL || parent == NULL || color == NULL ) return;
413
414 //fprintf( stderr, "%s : color is r %3.3f g %3.3f b %3.3f\n", __FUNCTION__, color[0], color[1], color[2] );
415 c[0] = (guchar) (255.0 * color[0]);
416 c[1] = (guchar) (255.0 * color[1]);
417 c[2] = (guchar) (255.0 * color[2]);
418
419 fill_color = c[0] << 24 | c[1] << 16 | c[2] << 8 | 0xff << 0;
420 //fprintf( stderr, "%s : fill_color is %x\n", __FUNCTION__, (guint)fill_color );
421
422 gdk_pixbuf_fill( pixbuf, fill_color );
423 gtk_widget_queue_draw( parent );
424 }
425
426
matedit_recompute_base_intensities(MatEditData * med)427 void matedit_recompute_base_intensities(MatEditData *med)
428 {
429 int i;
430 GtkAdjustment *adj;
431
432 for( i = 0; i < 3; i++ ) {
433 adj = med->SliderAdj[i];
434 if( !adj )
435 med->bi[i] = 0.0;
436 else
437 med->bi[i] = adj->value;
438 }
439
440 matedit_normalize_attribute( med->bi, med->bi );
441 }
442
443
matedit_normalize_attribute(float dest[4],float src[4])444 float matedit_normalize_attribute( float dest[4], float src[4] ) {
445 /* This code was duplicated several times in the original mat_edit
446 (from me3d), so I consolidated it here. If it turns out that this
447 normalization is unnecessary or incorrect, it will be easier to disable it
448 if it is all in one place (rather than scattered all over the file). */
449
450 float max;
451
452 max = src[0];
453 if(src[1] > max)
454 max = src[1];
455 if(src[2] > max)
456 max = src[2];
457
458 if( fabs( max ) < MATEDIT_ZERO_THRESHOLD ) {
459 dest[0] = dest[1] = dest[2] = MATEDIT_ZERO_THRESHOLD + 0.001;
460 } else {
461 dest[0] = src[0] / max;
462 dest[1] = src[1] / max;
463 dest[2] = src[2] / max;
464 }
465 dest[3] = src[3];
466
467 return max;
468 }
469
470
matedit_toggle_intensity_lock(GtkWidget * widget,MatEditData * med)471 void matedit_toggle_intensity_lock(GtkWidget *widget, MatEditData *med)
472 {
473 if(GTK_TOGGLE_BUTTON(widget)->active)
474 med->lock_intensity = TRUE;
475 else
476 med->lock_intensity = FALSE;
477 }
478
479
480 /* what to do when the integrated color picker changes */
matedit_color_changed(GtkWidget * widget,MatEditData * med)481 void matedit_color_changed(GtkWidget *widget, MatEditData *med)
482 {
483 float g_color[4], alpha, max;
484 GLfloat m_color[4];
485 GtkAdjustment *adj;
486 GdkColor gdkcolor;
487 guint16 alpha16;
488 int i;
489
490 if(med->freeze)
491 return;
492
493 gtk_color_selection_get_current_color( GTK_COLOR_SELECTION(med->MatPicker),
494 &gdkcolor );
495 matedit_gdkcolor_to_floats( &gdkcolor, g_color );
496
497 alpha16 = gtk_color_selection_get_current_alpha( GTK_COLOR_SELECTION(med->MatPicker) );
498 alpha = ((float) alpha16) / 65535.0;
499
500 g_color[3] = alpha;
501
502 /*
503 fprintf( stderr, "%s - ", __FUNCTION__ );
504 for(i=0;i<4;i++) {
505 fprintf( stderr, "%3.3f ", g_color[i] );
506 }
507 fprintf( stderr, "\n" );
508 */
509
510 max = matedit_normalize_attribute( g_color, g_color );
511
512 med->bc[0][0] = g_color[0];
513 med->bc[0][1] = g_color[1];
514 med->bc[0][2] = g_color[2];
515 med->bc[0][3] = alpha;
516 med->bc[1][0] = g_color[0];
517 med->bc[1][1] = g_color[1];
518 med->bc[1][2] = g_color[2];
519 med->bc[1][3] = 1.0;
520 med->bc[2][0] = g_color[0];
521 med->bc[2][1] = g_color[1];
522 med->bc[2][2] = g_color[2];
523 med->bc[2][3] = 1.0;
524
525 med->freeze = TRUE;
526
527 for( i = 0; i < 3; i++ ) {
528 adj = med->SliderAdj[i];
529 if(!med->lock_intensity) {
530 adj->value = max * med->bi[i];
531 g_signal_emit_by_name(G_OBJECT(adj),
532 "value_changed");
533 } else {
534 m_color[0] = med->bc[i][0] * adj->value;
535 m_color[1] = med->bc[i][1] * adj->value;
536 m_color[2] = med->bc[i][2] * adj->value;
537 m_color[3] = med->bc[i][3];
538 matedit_update_color_swatch(
539 med->SwatchPixbuf[i], med->SwatchWidget[i], m_color);
540 matedit_set_preview_value(med, m_color, i);
541 }
542 }
543
544 med->freeze = FALSE;
545
546 }
547
548
549 /* what to do when the intensity sliders/spinbuttons change */
matedit_slider_changed(GtkAdjustment * adj,int index)550 void matedit_slider_changed(GtkAdjustment *adj, int index )
551 {
552 GLfloat m_color[4];
553 float v;
554 MatEditData *med;
555
556 med = (MatEditData *) g_object_get_data(G_OBJECT(adj), "MatEditStruct");
557
558 v = (float) adj->value;
559 if( index == MAT_INDEX_SHININESS ) {
560 mat_preview_set_shininess( med->MatPreview, v );
561 } else {
562 m_color[0] = med->bc[index][0] * v;
563 m_color[1] = med->bc[index][1] * v;
564 m_color[2] = med->bc[index][2] * v;
565 m_color[3] = med->bc[index][3];
566 matedit_update_color_swatch(
567 med->SwatchPixbuf[index], med->SwatchWidget[index], m_color);
568 matedit_set_preview_value( med, m_color, index );
569 }
570 if(!med->freeze) {
571 matedit_recompute_base_intensities( med );
572 }
573 }
574
575
matedit_set_preview_value(MatEditData * med,GLfloat * v,int i)576 void matedit_set_preview_value(MatEditData *med, GLfloat *v, int i ) {
577
578 switch( i ) {
579 case MAT_INDEX_DIFFUSE:
580 mat_preview_set_diffuse( med->MatPreview, v );
581 break;
582 case MAT_INDEX_AMBIENT:
583 mat_preview_set_ambient( med->MatPreview, v );
584 break;
585 case MAT_INDEX_EMISSION:
586 mat_preview_set_emission( med->MatPreview, v );
587 break;
588 case MAT_INDEX_SPECULAR:
589 mat_preview_set_specular( med->MatPreview, v );
590 break;
591 case MAT_INDEX_SHININESS:
592 default:
593 break;
594 }
595
596 }
597
598
599
600 /* functions dealing with the floating color picker */
matedit_colorpicker_show(GtkWidget * widget,guint color_id)601 void matedit_colorpicker_show(GtkWidget *widget, guint color_id)
602 {
603 MatEditData *med;
604 float g_color[4];
605 GtkAdjustment *adj;
606 GdkColor gdkcolor;
607
608 med = (MatEditData *) g_object_get_data(G_OBJECT(widget),
609 "MatEditStruct");
610
611 med->active_preview = color_id;
612
613 adj = med->SliderAdj[color_id];
614
615 med->pc[0] = g_color[0] = med->bc[color_id][0] * adj->value;
616 med->pc[1] = g_color[1] = med->bc[color_id][1] * adj->value;
617 med->pc[2] = g_color[2] = med->bc[color_id][2] * adj->value;
618 med->pc[3] = g_color[3] = med->bc[color_id][3];
619
620 matedit_floats_to_gdkcolor( &gdkcolor, g_color );
621
622 gtk_color_selection_set_current_color(
623 GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->colorsel),
624 &gdkcolor );
625
626 gtk_color_selection_set_current_alpha(
627 GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->colorsel),
628 (guint16)(g_color[3] * 65535.) );
629
630 if(color_id == MAT_INDEX_DIFFUSE) { /* Opacity is only setable on the diffuse color */
631 gtk_color_selection_set_has_opacity_control(
632 GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->colorsel),
633 TRUE);
634 } else {
635 gtk_color_selection_set_has_opacity_control(
636 GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->colorsel),
637 FALSE);
638 }
639 gtk_widget_show(med->MatPickerBox);
640 }
641
matedit_colorpicker_changed_cb(GtkWidget * widget,MatEditData * med)642 void matedit_colorpicker_changed_cb(GtkWidget *widget, MatEditData *med)
643 {
644 float g_color[4] = { 0.0, 0.0, 0.0, 1.0 }, max;
645 float alpha = 1.0;
646 GtkAdjustment *adj;
647 GdkColor gdkcolor;
648 guint16 alpha16;
649
650 gtk_color_selection_get_current_color(
651 GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->colorsel),
652 &gdkcolor );
653 matedit_gdkcolor_to_floats( &gdkcolor, g_color );
654
655 alpha16 = gtk_color_selection_get_current_alpha(
656 GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(med->MatPickerBox)->colorsel) );
657 alpha = ((float) alpha16) / 65535.0;
658
659 g_color[3] = alpha;
660
661 matedit_update_color_swatch(
662 med->SwatchPixbuf[med->active_preview],
663 med->SwatchWidget[med->active_preview], g_color);
664
665 max = matedit_normalize_attribute( med->bc[med->active_preview], g_color );
666
667 adj = med->SliderAdj[med->active_preview];
668 if((!med->lock_intensity) || (med->active_preview == MAT_INDEX_SPECULAR))
669 adj->value = max;
670 g_signal_emit_by_name(G_OBJECT(adj), "value_changed");
671 }
672
matedit_colorpicker_ok(GtkWidget * widget,MatEditData * med)673 void matedit_colorpicker_ok(GtkWidget *widget, MatEditData *med)
674 {
675 gtk_widget_hide(med->MatPickerBox);
676 }
677
matedit_colorpicker_close(GtkWidget * widget,MatEditData * med)678 void matedit_colorpicker_close(GtkWidget *widget, MatEditData *med)
679 {
680 GLfloat max;
681 GtkAdjustment *adj;
682
683 matedit_update_color_swatch(
684 med->SwatchPixbuf[med->active_preview],
685 med->SwatchWidget[med->active_preview], med->pc);
686 max = matedit_normalize_attribute( med->bc[med->active_preview], med->pc );
687
688 adj = med->SliderAdj[med->active_preview];
689 adj->value = (gfloat) max;
690 g_signal_emit_by_name(G_OBJECT(adj), "value_changed");
691
692 gtk_widget_hide(med->MatPickerBox);
693 }
694
matedit_colorpicker_close_2(GtkWidget * widget,GdkEvent * event,MatEditData * med)695 void matedit_colorpicker_close_2(GtkWidget *widget, GdkEvent *event,
696 MatEditData *med)
697 {
698 matedit_colorpicker_close(widget, med);
699 }
700
matedit_kill_dialog(GtkWidget * widget,GdkEvent * event,MatEditData * med)701 void matedit_kill_dialog(GtkWidget *widget, GdkEvent *event,
702 MatEditData *med)
703 {
704 matedit_hide(med);
705 }
706
707
708 /* OK/Apply/Cancel handlers */
matedit_ok(GtkWidget * widget,MatEditData * med)709 void matedit_ok(GtkWidget *widget, MatEditData *med)
710 {
711 matedit_apply(widget, med);
712 matedit_hide(med);
713 }
714
matedit_apply(GtkWidget * widget,MatEditData * med)715 void matedit_apply(GtkWidget *widget, MatEditData *med)
716 {
717 g_return_if_fail(med != NULL);
718
719 /* copy the material data back into the med->material */
720 matedit_get_color( med, MAT_INDEX_DIFFUSE, med->material->diffuse );
721 matedit_get_color( med, MAT_INDEX_AMBIENT, med->material->ambient );
722 matedit_get_color( med, MAT_INDEX_EMISSION, med->material->emission );
723 matedit_get_color( med, MAT_INDEX_SPECULAR, med->material->specular );
724 med->material->shininess = matedit_get_shininess( med );
725
726 }
727
matedit_cancel(GtkWidget * widget,MatEditData * med)728 void matedit_cancel(GtkWidget *widget, MatEditData *med)
729 {
730 matedit_hide(med);
731 }
732
733
734
matedit_gdkcolor_to_floats(GdkColor * gdkcolor,float * color)735 void matedit_gdkcolor_to_floats( GdkColor *gdkcolor, float *color ) {
736 color[0] = ((float) gdkcolor->red) / 65535.0;
737 color[1] = ((float) gdkcolor->green) / 65535.0;
738 color[2] = ((float) gdkcolor->blue) / 65535.0;
739 }
740
741
matedit_floats_to_gdkcolor(GdkColor * gdkcolor,float * color)742 void matedit_floats_to_gdkcolor( GdkColor *gdkcolor, float *color ) {
743 gdkcolor->red = (int)( color[0] * 65535.0 );
744 gdkcolor->green = (int)( color[1] * 65535.0 );
745 gdkcolor->blue = (int)( color[2] * 65535.0 );
746 }
747
748
749 /* Retrieves color info from the material editor, in a form that is more
750 generally useful (esp to other parts of kludge3d). */
matedit_get_color(MatEditData * med,int index,float color[4])751 void matedit_get_color( MatEditData *med, int index, float color[4] ) {
752 float v;
753 GtkAdjustment *adj;
754
755 adj = med->SliderAdj[index];
756 v = adj->value;
757
758 color[0] = med->bc[index][0] * v;
759 color[1] = med->bc[index][1] * v;
760 color[2] = med->bc[index][2] * v;
761 color[3] = med->bc[index][3];
762 }
763
764
765 /* Retrieves shininess info from the material editor. */
matedit_get_shininess(MatEditData * med)766 float matedit_get_shininess( MatEditData *med ) {
767
768 return med->SliderAdj[MAT_INDEX_SHININESS]->value;
769 }
770
771
772
773
774
775
776 /***************************************************************************
777
778 DEAD CODE
779
780 ***************************************************************************/
781
782
783 #if 0
784 void matedit_redraw_color_preview(GtkWidget *widget, GLfloat *color)
785 {
786 gint x, y, i, wid, heig, f, n;
787 guchar c[3], cc[3 * 2], *sample_buf;
788 gdouble o;
789
790 g_return_if_fail(widget != NULL);
791 g_return_if_fail(color != NULL);
792
793 wid = widget->requisition.width;
794 heig = widget->requisition.height;
795
796 g_return_if_fail(wid != 0);
797
798 sample_buf = g_new(guchar, 3 * wid);
799
800 c[0] = (guchar) (255.0 * color[0]);
801 c[1] = (guchar) (255.0 * color[1]);
802 c[2] = (guchar) (255.0 * color[2]);
803
804 o = color[3];
805
806 cc[0] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[0]));
807 cc[1] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[1]));
808 cc[2] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[2]));
809 cc[3] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[0]));
810 cc[4] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[1]));
811 cc[5] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[2]));
812
813 for (y = 0; y < heig; y++)
814 {
815 i = 0;
816 for (x = 0; x < wid; x++)
817 {
818 f = 3 * (((x % 32) < 16) ^ ((y % 32) < 16));
819
820 for (n = 0; n < 3; n++)
821 sample_buf[i++] = cc[n + f];
822 }
823
824 gtk_preview_draw_row(GTK_PREVIEW(widget), sample_buf, 0, y, wid);
825 }
826
827 gtk_widget_draw(widget, NULL);
828 g_free(sample_buf);
829 }
830
831
832 void matedit_drop_material(GtkWidget *widget, MatEditData *med)
833 {
834 matedit_color_assimilate(med);
835 }
836
837 /* bonus copy function */
838 void preview_copy_material(GtkGLTexPreview *gtpv, gpointer data)
839 {
840 GLfloat buf[4];
841 GtkGLTexPreview *gtpv_dest = GTK_GL_TEX_PREVIEW(data);
842
843 gtk_gl_tex_preview_get_diffuse(gtpv, buf);
844 gtk_gl_tex_preview_set_diffuse(gtpv_dest, buf);
845
846 gtk_gl_tex_preview_get_ambient(gtpv, buf);
847 gtk_gl_tex_preview_set_ambient(gtpv_dest, buf);
848
849 gtk_gl_tex_preview_get_specular(gtpv, buf);
850 gtk_gl_tex_preview_set_specular(gtpv_dest, buf);
851
852 gtk_gl_tex_preview_get_emission(gtpv, buf);
853 gtk_gl_tex_preview_set_emission(gtpv_dest, buf);
854
855 gtk_gl_tex_preview_get_shininess(gtpv, buf);
856 gtk_gl_tex_preview_set_shininess(gtpv_dest, buf[0]);
857
858 gtk_gl_tex_preview_redraw(gtpv_dest);
859 }
860
861
862 /* utility functions: color_assimilate, redraw_color_preview, recompute_bi */
863 void matedit_color_assimilate(MatEditData *med)
864 {
865 /* integrates material data from the preview widget into the UI */
866 GtkAdjustment *adj;
867 gdouble g_color[4], max;
868 GLfloat m_color[4];
869
870 med->freeze = TRUE;
871
872 adj = gtk_range_get_adjustment(GTK_RANGE(med->MatSlider[0]));
873 gtk_gl_tex_preview_get_diffuse(GTK_GL_TEX_PREVIEW(med->MatPreview), m_color);
874
875 g_color[0] = m_color[0];
876 g_color[1] = m_color[1];
877 g_color[2] = m_color[2];
878 g_color[3] = m_color[3];
879 gtk_color_selection_set_color(GTK_COLOR_SELECTION(med->MatPicker), g_color);
880
881 max = m_color[0];
882 if(m_color[1] > max)
883 max = m_color[1];
884 if(m_color[2] > max)
885 max = m_color[2];
886 if(max == 0)
887 med->bc[0][0] = med->bc[0][1] = med->bc[0][2] = 1;
888 else {
889 med->bc[0][0] = m_color[0] / max;
890 med->bc[0][1] = m_color[1] / max;
891 med->bc[0][2] = m_color[2] / max;
892 }
893 med->bc[0][3] = m_color[3];
894 adj->value = max;
895 g_signal_emit_by_name(G_OBJECT(adj),
896 "value_changed");
897
898 adj = gtk_range_get_adjustment(GTK_RANGE(med->MatSlider[1]));
899 gtk_gl_tex_preview_get_ambient(GTK_GL_TEX_PREVIEW(med->MatPreview), m_color);
900 max = m_color[0];
901 if(m_color[1] > max)
902 max = m_color[1];
903 if(m_color[2] > max)
904 max = m_color[2];
905 if(max == 0)
906 med->bc[1][0] = med->bc[1][1] = med->bc[1][2] = 1;
907 else {
908 med->bc[1][0] = m_color[0] / max;
909 med->bc[1][1] = m_color[1] / max;
910 med->bc[1][2] = m_color[2] / max;
911 }
912 med->bc[1][3] = 1.0;
913 adj->value = max;
914 g_signal_emit_by_name(G_OBJECT(adj),
915 "value_changed");
916
917 adj = gtk_range_get_adjustment(GTK_RANGE(med->MatSlider[2]));
918 gtk_gl_tex_preview_get_emission(GTK_GL_TEX_PREVIEW(med->MatPreview), m_color);
919 max = m_color[0];
920 if(m_color[1] > max)
921 max = m_color[1];
922 if(m_color[2] > max)
923 max = m_color[2];
924 if(max == 0)
925 med->bc[2][0] = med->bc[2][1] = med->bc[2][2] = 1;
926 else {
927 med->bc[2][0] = m_color[0] / max;
928 med->bc[2][1] = m_color[1] / max;
929 med->bc[2][2] = m_color[2] / max;
930 }
931 med->bc[2][3] = 1.0;
932 adj->value = max;
933 g_signal_emit_by_name(G_OBJECT(adj),
934 "value_changed");
935
936 adj = gtk_range_get_adjustment(GTK_RANGE(med->MatSlider[3]));
937 gtk_gl_tex_preview_get_specular(GTK_GL_TEX_PREVIEW(med->MatPreview), m_color);
938 max = m_color[0];
939 if(m_color[1] > max)
940 max = m_color[1];
941 if(m_color[2] > max)
942 max = m_color[2];
943 if(max == 0)
944 med->bc[3][0] = med->bc[3][1] = med->bc[3][2] = 1;
945 else {
946 med->bc[3][0] = m_color[0] / max;
947 med->bc[3][1] = m_color[1] / max;
948 med->bc[3][2] = m_color[2] / max;
949 }
950 med->bc[3][3] = 1.0;
951 adj->value = max;
952 g_signal_emit_by_name(G_OBJECT(adj),
953 "value_changed");
954
955 adj = gtk_range_get_adjustment(GTK_RANGE(med->MatSlider[4]));
956 gtk_gl_tex_preview_get_shininess(GTK_GL_TEX_PREVIEW(med->MatPreview), m_color);
957 adj->value = 1 - (m_color[0] / 128); /* 1.0 is shiniest, 0.0 is least */
958 g_signal_emit_by_name(G_OBJECT(adj),
959 "value_changed");
960
961 med->freeze = FALSE;
962 matedit_recompute_base_intensities(med);
963 }
964
965 #endif
966