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