1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Damien
3 CALISTE, laboratoire L_Sim, (2015)
4
5 Adresse mèl :
6 CALISTE, damien P caliste AT cea P fr.
7
8 Ce logiciel est un programme informatique servant à visualiser des
9 structures atomiques dans un rendu pseudo-3D.
10
11 Ce logiciel est régi par la licence CeCILL soumise au droit français et
12 respectant les principes de diffusion des logiciels libres. Vous pouvez
13 utiliser, modifier et/ou redistribuer ce programme sous les conditions
14 de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
15 sur le site "http://www.cecill.info".
16
17 Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
18 pris connaissance de la licence CeCILL, et que vous en avez accepté les
19 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
20 */
21
22 /* LICENCE SUM UP
23 Copyright CEA, contributors : Damien
24 CALISTE, laboratoire L_Sim, (2015)
25
26 E-mail address:
27 CALISTE, damien P caliste AT cea P fr.
28
29 This software is a computer program whose purpose is to visualize atomic
30 configurations in 3D.
31
32 This software is governed by the CeCILL license under French law and
33 abiding by the rules of distribution of free software. You can use,
34 modify and/ or redistribute the software under the terms of the CeCILL
35 license as circulated by CEA, CNRS and INRIA at the following URL
36 "http://www.cecill.info".
37
38 The fact that you are presently reading this means that you have had
39 knowledge of the CeCILL license and that you accept its terms. You can
40 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
41 */
42
43 #include "visu_extset.h"
44
45 #include <GL/gl.h>
46 #include <string.h>
47
48 #include "opengl.h"
49 #include "visu_tools.h"
50 #include "iface_boxed.h"
51 #include "visu_configFile.h"
52 #include "openGLFunctions/objectList.h"
53 #include "coreTools/toolConfigFile.h"
54 #include "OSOpenGL/visu_openGL.h"
55
56 #include "extensions/mapset.h"
57
58 /**
59 * SECTION:visu_extset
60 * @short_description: Defines a storage object to handle a bunch of
61 * #VisuGlExt objects.
62 *
63 * <para>A storage to display several #VisuGlExt objects. It takes
64 * care of ordering display, following priority of each object.</para>
65 */
66
67 /* Parameters & resources*/
68 /* A resource to control the color of the background. */
69 #define FLAG_RESOURCE_BG_COLOR "backgroundColor_color"
70 #define DESC_RESOURCE_BG_COLOR "Set the background of the background ; four floating point values (0. <= v <= 1.)"
71 static float bgRGBDefault[4] = {0., 0., 0., 1.};
72
73 /* This is a boolean to control is the axes is render or not. */
74 #define FLAG_RESOURCE_FOG_USED "fog_is_on"
75 #define DESC_RESOURCE_FOG_USED "Control if the fog is used ; boolean (0 or 1)"
76 static gboolean fogActiveDefault = TRUE;
77
78 #define FLAG_RESOURCE_FOG_SPECIFIC "fog_color_is_specific"
79 #define DESC_RESOURCE_FOG_SPECIFIC "Control if the fog uses a specific color ; boolean (0 or 1)"
80 static gboolean fogSpecificDefault = FALSE;
81
82 #define FLAG_RESOURCE_FOG_COLOR "fog_specific_color"
83 #define DESC_RESOURCE_FOG_COLOR "Define the color of the fog ; four floating point values (0. <= v <= 1.)"
84 static float fogRGBDefault[4] = {0.f, 0.f, 0.f, 1.f};
85
86 #define FLAG_RESOURCE_FOG_STARTEND "fog_start_end"
87 #define DESC_RESOURCE_FOG_STARTEND "Define the position of the fog ; two floating point values (0. <= v <= 1.)"
88 static float fogStartEndDefault[2] = {0.3f, 0.7f};
89
90 struct _GlExt {
91 VisuGlExt *ext;
92 gulong priority_sig, dirty_sig, active_sig;
93 };
94
95 struct _VisuGlExtSetPrivate
96 {
97 gboolean dispose_has_run;
98
99 /* A list to store all the available OpenGL extensions. */
100 GArray *set;
101 gboolean reorderingNeeded, dirty;
102 guint dirtyPending;
103
104 /* The view extensions are rendered on. */
105 VisuGlView *view;
106 gulong widthHeight_signal, chg_signal;
107
108 /* Handling the background color and the fog. */
109 float bgRGB[4];
110 int chessList;
111 gboolean bgDirty;
112 gboolean fogActive;
113 float fogStartEnd[2];
114 gboolean fogFollowsBg;
115 float fogRGB[4];
116 };
117
118 enum
119 {
120 PROP_0,
121 BG_R_PROP,
122 BG_G_PROP,
123 BG_B_PROP,
124 BG_A_PROP,
125 FOG_ACTIVE_PROP,
126 FOG_START_PROP,
127 FOG_FULL_PROP,
128 FOG_FOLLOWS_PROP,
129 FOG_R_PROP,
130 FOG_G_PROP,
131 FOG_B_PROP,
132 FOG_A_PROP,
133 DIRTY_PROP,
134 N_PROP
135 };
136 static GParamSpec *properties[N_PROP];
137
138 static VisuGlExtSet *defaultSet = NULL;
139 static GLuint texName = 0;
140
141 static void visu_gl_ext_set_dispose (GObject* obj);
142 static void visu_gl_ext_set_finalize (GObject* obj);
143 static void visu_gl_ext_set_get_property(GObject* obj, guint property_id,
144 GValue *value, GParamSpec *pspec);
145 static void visu_gl_ext_set_set_property(GObject* obj, guint property_id,
146 const GValue *value, GParamSpec *pspec);
147 static void visu_gl_ext_initContext (VisuGl *gl);
148
149 /* Local callbacks */
150 static void onWidthHeight(VisuGlView *view, gpointer data);
151 static void onCamera(VisuGlView *view, gpointer data);
152 static void onEntryBgColor(VisuGlExtSet *set, VisuConfigFileEntry *entry, VisuConfigFile *obj);
153 static void onEntryFogActive(VisuGlExtSet *set, VisuConfigFileEntry *entry, VisuConfigFile *obj);
154 static void onEntryFogSpecific(VisuGlExtSet *set, VisuConfigFileEntry *entry, VisuConfigFile *obj);
155 static void onEntryFogColor(VisuGlExtSet *set, VisuConfigFileEntry *entry, VisuConfigFile *obj);
156 static void onEntryFogStartEnd(VisuGlExtSet *set, VisuConfigFileEntry *entry, VisuConfigFile *obj);
157
158 static void _appendDirty(VisuGlExtSet *set);
159 static void _chessDraw(VisuGlExtSet *set);
160 static void exportResources(GString *data, VisuData *dataObj);
161
G_DEFINE_TYPE_WITH_CODE(VisuGlExtSet,visu_gl_ext_set,VISU_TYPE_GL,G_ADD_PRIVATE (VisuGlExtSet))162 G_DEFINE_TYPE_WITH_CODE(VisuGlExtSet, visu_gl_ext_set, VISU_TYPE_GL,
163 G_ADD_PRIVATE(VisuGlExtSet))
164
165 static void visu_gl_ext_set_class_init(VisuGlExtSetClass *klass)
166 {
167 float rgColor[2] = {0.f, 1.f};
168
169 DBG_fprintf(stderr, "Visu Extension Set: creating the class of the object.\n");
170 /* DBG_fprintf(stderr, " - adding new signals ;\n"); */
171
172 /* Parameters */
173 visu_config_file_addFloatArrayEntry(VISU_CONFIG_FILE_RESOURCE,
174 FLAG_RESOURCE_BG_COLOR,
175 DESC_RESOURCE_BG_COLOR,
176 4, bgRGBDefault, rgColor, FALSE);
177 visu_config_file_addBooleanEntry(VISU_CONFIG_FILE_RESOURCE,
178 FLAG_RESOURCE_FOG_USED,
179 DESC_RESOURCE_FOG_USED,
180 &fogActiveDefault, FALSE);
181 visu_config_file_addBooleanEntry(VISU_CONFIG_FILE_RESOURCE,
182 FLAG_RESOURCE_FOG_SPECIFIC,
183 DESC_RESOURCE_FOG_SPECIFIC,
184 &fogSpecificDefault, FALSE);
185 visu_config_file_addFloatArrayEntry(VISU_CONFIG_FILE_RESOURCE,
186 FLAG_RESOURCE_FOG_COLOR,
187 DESC_RESOURCE_FOG_COLOR,
188 4, fogRGBDefault, rgColor, FALSE);
189 visu_config_file_addFloatArrayEntry(VISU_CONFIG_FILE_RESOURCE,
190 FLAG_RESOURCE_FOG_STARTEND,
191 DESC_RESOURCE_FOG_STARTEND,
192 2, fogStartEndDefault, rgColor, FALSE);
193 visu_config_file_addExportFunction(VISU_CONFIG_FILE_RESOURCE, exportResources);
194
195 /* Connect the overloading methods. */
196 G_OBJECT_CLASS(klass)->dispose = visu_gl_ext_set_dispose;
197 G_OBJECT_CLASS(klass)->finalize = visu_gl_ext_set_finalize;
198 G_OBJECT_CLASS(klass)->set_property = visu_gl_ext_set_set_property;
199 G_OBJECT_CLASS(klass)->get_property = visu_gl_ext_set_get_property;
200 VISU_GL_CLASS(klass)->initContext = visu_gl_ext_initContext;
201
202 /**
203 * VisuGlExtSet::dirty:
204 *
205 * TRUE when at least one of the active #VisuGlExt gets dirty.
206 *
207 * Since: 3.8
208 */
209 properties[DIRTY_PROP] = g_param_spec_boolean("dirty", "Dirty",
210 "one of the object rendering is out of date",
211 FALSE, G_PARAM_READABLE);
212 g_object_class_install_property(G_OBJECT_CLASS(klass), DIRTY_PROP, properties[DIRTY_PROP]);
213 /**
214 * VisuGlExtSet::bg-red:
215 *
216 * Store the red channel of the background color.
217 *
218 * Since: 3.8
219 */
220 properties[BG_R_PROP] = g_param_spec_float("bg-red", "red channel",
221 "background red channel",
222 0., 1., 0., G_PARAM_READWRITE);
223 g_object_class_install_property(G_OBJECT_CLASS(klass), BG_R_PROP,
224 properties[BG_R_PROP]);
225 /**
226 * VisuGlExtSet::bg-green:
227 *
228 * Store the green channel of the background color.
229 *
230 * Since: 3.8
231 */
232 properties[BG_G_PROP] = g_param_spec_float("bg-green", "green channel",
233 "background green channel",
234 0., 1., 0., G_PARAM_READWRITE);
235 g_object_class_install_property(G_OBJECT_CLASS(klass), BG_G_PROP,
236 properties[BG_G_PROP]);
237 /**
238 * VisuGlExtSet::bg-blue:
239 *
240 * Store the blue channel of the background color.
241 *
242 * Since: 3.8
243 */
244 properties[BG_B_PROP] = g_param_spec_float("bg-blue", "blue channel",
245 "background blue channel",
246 0., 1., 0., G_PARAM_READWRITE);
247 g_object_class_install_property(G_OBJECT_CLASS(klass), BG_B_PROP,
248 properties[BG_B_PROP]);
249 /**
250 * VisuGlExtSet::bg-alpha:
251 *
252 * Store the alpha channel of the background color.
253 *
254 * Since: 3.8
255 */
256 properties[BG_A_PROP] = g_param_spec_float("bg-alpha", "alpha channel",
257 "background alpha channel",
258 0., 1., 0., G_PARAM_READWRITE);
259 g_object_class_install_property(G_OBJECT_CLASS(klass), BG_A_PROP,
260 properties[BG_A_PROP]);
261 /**
262 * VisuGlExtSet::fog-active:
263 *
264 * Store if the fog is used.
265 *
266 * Since: 3.8
267 */
268 properties[FOG_ACTIVE_PROP] = g_param_spec_boolean("fog-active", "Fog active",
269 "Fog is used",
270 TRUE, G_PARAM_READWRITE);
271 g_object_class_install_property(G_OBJECT_CLASS(klass), FOG_ACTIVE_PROP,
272 properties[FOG_ACTIVE_PROP]);
273 /**
274 * VisuGlExtSet::fog-start:
275 *
276 * Store the starting depth of the fog.
277 *
278 * Since: 3.8
279 */
280 properties[FOG_START_PROP] = g_param_spec_float("fog-start", "Fog start",
281 "starting fog depth",
282 0., 1., 0.3, G_PARAM_READWRITE);
283 g_object_class_install_property(G_OBJECT_CLASS(klass), FOG_START_PROP,
284 properties[FOG_START_PROP]);
285 /**
286 * VisuGlExtSet::fog-full:
287 *
288 * Store the depth where the fog hides all.
289 *
290 * Since: 3.8
291 */
292 properties[FOG_FULL_PROP] = g_param_spec_float("fog-full", "Fog full",
293 "depth where fog hides all",
294 0., 1., 0.7, G_PARAM_READWRITE);
295 g_object_class_install_property(G_OBJECT_CLASS(klass), FOG_FULL_PROP,
296 properties[FOG_FULL_PROP]);
297 /**
298 * VisuGlExtSet::fog-follows-bg:
299 *
300 * Store if the fog follows the background color.
301 *
302 * Since: 3.8
303 */
304 properties[FOG_FOLLOWS_PROP] = g_param_spec_boolean("fog-follows-bg", "Fog follows bg",
305 "Fog color is the bg color",
306 TRUE, G_PARAM_READWRITE);
307 g_object_class_install_property(G_OBJECT_CLASS(klass), FOG_FOLLOWS_PROP,
308 properties[FOG_FOLLOWS_PROP]);
309 /**
310 * VisuGlExtSet::fog-red:
311 *
312 * Store the red channel of the specific fog color.
313 *
314 * Since: 3.8
315 */
316 properties[FOG_R_PROP] = g_param_spec_float("fog-red", "red channel",
317 "specific fog red channel",
318 0., 1., 0., G_PARAM_READWRITE);
319 g_object_class_install_property(G_OBJECT_CLASS(klass), FOG_R_PROP,
320 properties[FOG_R_PROP]);
321 /**
322 * VisuGlExtSet::fog-green:
323 *
324 * Store the green channel of the specific fog color.
325 *
326 * Since: 3.8
327 */
328 properties[FOG_G_PROP] = g_param_spec_float("fog-green", "green channel",
329 "specific fog green channel",
330 0., 1., 0., G_PARAM_READWRITE);
331 g_object_class_install_property(G_OBJECT_CLASS(klass), FOG_G_PROP,
332 properties[FOG_G_PROP]);
333 /**
334 * VisuGlExtSet::fog-blue:
335 *
336 * Store the blue channel of the specific fog color.
337 *
338 * Since: 3.8
339 */
340 properties[FOG_B_PROP] = g_param_spec_float("fog-blue", "blue channel",
341 "specific fog blue channel",
342 0., 1., 0., G_PARAM_READWRITE);
343 g_object_class_install_property(G_OBJECT_CLASS(klass), FOG_B_PROP,
344 properties[FOG_B_PROP]);
345 /**
346 * VisuGlExtSet::fog-alpha:
347 *
348 * Store the alpha channel of the specific fog color.
349 *
350 * Since: 3.8
351 */
352 properties[FOG_A_PROP] = g_param_spec_float("fog-alpha", "alpha channel",
353 "specific fog alpha channel",
354 0., 1., 1., G_PARAM_READWRITE);
355 g_object_class_install_property(G_OBJECT_CLASS(klass), FOG_A_PROP,
356 properties[FOG_A_PROP]);
357
358 visu_gl_objectlist_init();
359 }
360
visu_gl_ext_set_init(VisuGlExtSet * ext)361 static void visu_gl_ext_set_init(VisuGlExtSet *ext)
362 {
363 DBG_fprintf(stderr, "Visu Extension Set: initializing a new object (%p).\n",
364 (gpointer)ext);
365 ext->priv = visu_gl_ext_set_get_instance_private(ext);
366 ext->priv->dispose_has_run = FALSE;
367
368 ext->priv->set = g_array_new(FALSE, FALSE, sizeof(struct _GlExt));
369 ext->priv->reorderingNeeded = FALSE;
370 ext->priv->dirty = FALSE;
371 ext->priv->dirtyPending = 0;
372 ext->priv->view = (VisuGlView*)0;
373 g_signal_connect(G_OBJECT(ext), "notify::lights",
374 G_CALLBACK(_appendDirty), (gpointer)0);
375 g_signal_connect(G_OBJECT(ext), "notify::antialias",
376 G_CALLBACK(_appendDirty), (gpointer)0);
377 g_signal_connect(G_OBJECT(ext), "notify::immediate",
378 G_CALLBACK(_appendDirty), (gpointer)0);
379 g_signal_connect(G_OBJECT(ext), "notify::true-transparency",
380 G_CALLBACK(_appendDirty), (gpointer)0);
381 g_signal_connect(G_OBJECT(ext), "notify::stereo",
382 G_CALLBACK(_appendDirty), (gpointer)0);
383 g_signal_connect(G_OBJECT(ext), "notify::stereo-angle",
384 G_CALLBACK(_appendDirty), (gpointer)0);
385 g_signal_connect(G_OBJECT(ext), "notify::mode",
386 G_CALLBACK(_appendDirty), (gpointer)0);
387
388 ext->priv->bgRGB[0] = bgRGBDefault[0];
389 ext->priv->bgRGB[1] = bgRGBDefault[1];
390 ext->priv->bgRGB[2] = bgRGBDefault[2];
391 ext->priv->bgRGB[3] = bgRGBDefault[3];
392 g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_BG_COLOR,
393 G_CALLBACK(onEntryBgColor), (gpointer)ext, G_CONNECT_SWAPPED);
394 ext->priv->chessList = visu_gl_objectlist_new(1);
395 ext->priv->bgDirty = FALSE;
396
397 ext->priv->fogActive = fogActiveDefault;
398 ext->priv->fogStartEnd[0] = fogStartEndDefault[0];
399 ext->priv->fogStartEnd[1] = fogStartEndDefault[1];
400 ext->priv->fogFollowsBg = !fogSpecificDefault;
401 ext->priv->fogRGB[0] = fogRGBDefault[0];
402 ext->priv->fogRGB[1] = fogRGBDefault[1];
403 ext->priv->fogRGB[2] = fogRGBDefault[2];
404 ext->priv->fogRGB[3] = fogRGBDefault[3];
405 g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_FOG_USED,
406 G_CALLBACK(onEntryFogActive), (gpointer)ext, G_CONNECT_SWAPPED);
407 g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_FOG_SPECIFIC,
408 G_CALLBACK(onEntryFogSpecific), (gpointer)ext, G_CONNECT_SWAPPED);
409 g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_FOG_COLOR,
410 G_CALLBACK(onEntryFogColor), (gpointer)ext, G_CONNECT_SWAPPED);
411 g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_FOG_STARTEND,
412 G_CALLBACK(onEntryFogStartEnd), (gpointer)ext, G_CONNECT_SWAPPED);
413
414 if (!defaultSet)
415 defaultSet = ext;
416 }
417
418 /* This method can be called several times.
419 It should unref all of its reference to
420 GObjects. */
visu_gl_ext_set_dispose(GObject * obj)421 static void visu_gl_ext_set_dispose(GObject* obj)
422 {
423 VisuGlExtSet *ext;
424 guint i;
425 struct _GlExt *s;
426 gchar *name;
427
428 DBG_fprintf(stderr, "Visu Extension Set: dispose object %p.\n", (gpointer)obj);
429
430 ext = VISU_GL_EXT_SET(obj);
431 if (ext->priv->dispose_has_run)
432 return;
433 ext->priv->dispose_has_run = TRUE;
434
435 visu_gl_ext_set_setGlView(ext, (VisuGlView*)0);
436
437 DBG_fprintf(stderr, "Visu Extension Set: releasing %d extensions.\n", ext->priv->set->len);
438 for (i = 0; i < ext->priv->set->len; i++)
439 {
440 s = &g_array_index(ext->priv->set, struct _GlExt, i);
441 if (DEBUG)
442 {
443 DBG_fprintf(stderr, "Visu Extension Set: releasing extension %p.\n",
444 (gpointer)s->ext);
445 g_object_get(s->ext, "name", &name, NULL);
446 DBG_fprintf(stderr, " | %s (%d)\n", name, G_OBJECT(s->ext)->ref_count);
447 g_free(name);
448 }
449 g_signal_handler_disconnect(G_OBJECT(s->ext), s->priority_sig);
450 g_signal_handler_disconnect(G_OBJECT(s->ext), s->dirty_sig);
451 g_signal_handler_disconnect(G_OBJECT(s->ext), s->active_sig);
452 g_object_unref(G_OBJECT(s->ext));
453 }
454
455 /* Chain up to the parent class */
456 G_OBJECT_CLASS(visu_gl_ext_set_parent_class)->dispose(obj);
457 }
458 /* This method is called once only. */
visu_gl_ext_set_finalize(GObject * obj)459 static void visu_gl_ext_set_finalize(GObject* obj)
460 {
461 VisuGlExtSetPrivate *ext;
462
463 g_return_if_fail(obj);
464
465 DBG_fprintf(stderr, "Visu Extension Set: finalize object %p.\n", (gpointer)obj);
466 ext = VISU_GL_EXT_SET(obj)->priv;
467
468 if (ext->dirtyPending)
469 g_source_remove(ext->dirtyPending);
470 g_array_free(ext->set, TRUE);
471 glDeleteLists(ext->chessList, 1);
472
473 /* Chain up to the parent class */
474 DBG_fprintf(stderr, "Visu Extension Set: chain to parent.\n");
475 G_OBJECT_CLASS(visu_gl_ext_set_parent_class)->finalize(obj);
476 DBG_fprintf(stderr, "Visu Extension Set: freeing ... OK.\n");
477 }
visu_gl_ext_set_get_property(GObject * obj,guint property_id,GValue * value,GParamSpec * pspec)478 static void visu_gl_ext_set_get_property(GObject* obj, guint property_id,
479 GValue *value, GParamSpec *pspec)
480 {
481 VisuGlExtSet *self = VISU_GL_EXT_SET(obj);
482
483 DBG_fprintf(stderr, "Visu Extension Set: get property '%s' -> ",
484 g_param_spec_get_name(pspec));
485 switch (property_id)
486 {
487 case DIRTY_PROP:
488 g_value_set_boolean(value, (self->priv->dirtyPending > 0));
489 DBG_fprintf(stderr, "%d.\n", (self->priv->dirtyPending > 0));
490 break;
491 case BG_R_PROP:
492 g_value_set_float(value, self->priv->bgRGB[0]);
493 DBG_fprintf(stderr, "%g.\n", self->priv->bgRGB[0]);
494 break;
495 case BG_G_PROP:
496 g_value_set_float(value, self->priv->bgRGB[1]);
497 DBG_fprintf(stderr, "%g.\n", self->priv->bgRGB[1]);
498 break;
499 case BG_B_PROP:
500 g_value_set_float(value, self->priv->bgRGB[2]);
501 DBG_fprintf(stderr, "%g.\n", self->priv->bgRGB[2]);
502 break;
503 case BG_A_PROP:
504 g_value_set_float(value, self->priv->bgRGB[3]);
505 DBG_fprintf(stderr, "%g.\n", self->priv->bgRGB[3]);
506 break;
507 case FOG_ACTIVE_PROP:
508 g_value_set_boolean(value, self->priv->fogActive);
509 DBG_fprintf(stderr, "%d.\n", self->priv->fogActive);
510 break;
511 case FOG_START_PROP:
512 g_value_set_float(value, self->priv->fogStartEnd[0]);
513 DBG_fprintf(stderr, "%g.\n", self->priv->fogStartEnd[0]);
514 break;
515 case FOG_FULL_PROP:
516 g_value_set_float(value, self->priv->fogStartEnd[1]);
517 DBG_fprintf(stderr, "%g.\n", self->priv->fogStartEnd[1]);
518 break;
519 case FOG_FOLLOWS_PROP:
520 g_value_set_boolean(value, self->priv->fogFollowsBg);
521 DBG_fprintf(stderr, "%d.\n", self->priv->fogFollowsBg);
522 break;
523 case FOG_R_PROP:
524 g_value_set_float(value, self->priv->fogRGB[0]);
525 DBG_fprintf(stderr, "%g.\n", self->priv->fogRGB[0]);
526 break;
527 case FOG_G_PROP:
528 g_value_set_float(value, self->priv->fogRGB[1]);
529 DBG_fprintf(stderr, "%g.\n", self->priv->fogRGB[1]);
530 break;
531 case FOG_B_PROP:
532 g_value_set_float(value, self->priv->fogRGB[2]);
533 DBG_fprintf(stderr, "%g.\n", self->priv->fogRGB[2]);
534 break;
535 case FOG_A_PROP:
536 g_value_set_float(value, self->priv->fogRGB[3]);
537 DBG_fprintf(stderr, "%g.\n", self->priv->fogRGB[3]);
538 break;
539 default:
540 /* We don't have any other property... */
541 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
542 break;
543 }
544 }
visu_gl_ext_set_set_property(GObject * obj,guint property_id,const GValue * value,GParamSpec * pspec)545 static void visu_gl_ext_set_set_property(GObject* obj, guint property_id,
546 const GValue *value, GParamSpec *pspec)
547 {
548 VisuGlExtSet *self = VISU_GL_EXT_SET(obj);
549 float rgba[4], startEnd[2];
550
551 DBG_fprintf(stderr, "Visu Extension Set: set property '%s' -> ",
552 g_param_spec_get_name(pspec));
553 switch (property_id)
554 {
555 case BG_R_PROP:
556 rgba[0] = g_value_get_float(value);
557 visu_gl_ext_set_setBgColor(self, rgba, TOOL_COLOR_MASK_R);
558 DBG_fprintf(stderr, "%g.\n", self->priv->bgRGB[0]);
559 break;
560 case BG_G_PROP:
561 rgba[1] = g_value_get_float(value);
562 visu_gl_ext_set_setBgColor(self, rgba, TOOL_COLOR_MASK_G);
563 DBG_fprintf(stderr, "%g.\n", self->priv->bgRGB[1]);
564 break;
565 case BG_B_PROP:
566 rgba[2] = g_value_get_float(value);
567 visu_gl_ext_set_setBgColor(self, rgba, TOOL_COLOR_MASK_B);
568 DBG_fprintf(stderr, "%g.\n", self->priv->bgRGB[2]);
569 break;
570 case BG_A_PROP:
571 rgba[3] = g_value_get_float(value);
572 visu_gl_ext_set_setBgColor(self, rgba, TOOL_COLOR_MASK_A);
573 DBG_fprintf(stderr, "%g.\n", self->priv->bgRGB[3]);
574 break;
575 case FOG_ACTIVE_PROP:
576 visu_gl_ext_set_setFogActive(self, g_value_get_boolean(value));
577 DBG_fprintf(stderr, "%d.\n", self->priv->fogActive);
578 break;
579 case FOG_START_PROP:
580 startEnd[0] = g_value_get_float(value);
581 visu_gl_ext_set_setFogStartFull(self, startEnd, VISU_GL_EXT_SET_FOG_MASK_START);
582 DBG_fprintf(stderr, "%g.\n", self->priv->fogStartEnd[0]);
583 break;
584 case FOG_FULL_PROP:
585 startEnd[1] = g_value_get_float(value);
586 visu_gl_ext_set_setFogStartFull(self, startEnd, VISU_GL_EXT_SET_FOG_MASK_FULL);
587 DBG_fprintf(stderr, "%g.\n", self->priv->fogStartEnd[1]);
588 break;
589 case FOG_FOLLOWS_PROP:
590 visu_gl_ext_set_setFogFollowsBg(self, g_value_get_boolean(value));
591 DBG_fprintf(stderr, "%d.\n", self->priv->fogFollowsBg);
592 break;
593 case FOG_R_PROP:
594 rgba[0] = g_value_get_float(value);
595 visu_gl_ext_set_setFogColor(self, rgba, TOOL_COLOR_MASK_R);
596 DBG_fprintf(stderr, "%g.\n", self->priv->fogRGB[0]);
597 break;
598 case FOG_G_PROP:
599 rgba[1] = g_value_get_float(value);
600 visu_gl_ext_set_setFogColor(self, rgba, TOOL_COLOR_MASK_G);
601 DBG_fprintf(stderr, "%g.\n", self->priv->fogRGB[1]);
602 break;
603 case FOG_B_PROP:
604 rgba[2] = g_value_get_float(value);
605 visu_gl_ext_set_setFogColor(self, rgba, TOOL_COLOR_MASK_B);
606 DBG_fprintf(stderr, "%g.\n", self->priv->fogRGB[2]);
607 break;
608 case FOG_A_PROP:
609 rgba[3] = g_value_get_float(value);
610 visu_gl_ext_set_setFogColor(self, rgba, TOOL_COLOR_MASK_A);
611 DBG_fprintf(stderr, "%g.\n", self->priv->fogRGB[3]);
612 break;
613 default:
614 /* We don't have any other property... */
615 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
616 break;
617 }
618 }
visu_gl_ext_initContext(VisuGl * gl)619 static void visu_gl_ext_initContext(VisuGl *gl)
620 {
621 VisuGlExtSet *self = VISU_GL_EXT_SET(gl);
622 guint i;
623
624 g_return_if_fail(VISU_IS_GL_EXT_SET(self));
625
626 VISU_GL_CLASS(visu_gl_ext_set_parent_class)->initContext(gl);
627
628 if (self->priv->view)
629 visu_gl_view_initContext(self->priv->view);
630 for (i = 0; i < self->priv->set->len; i++)
631 visu_gl_ext_rebuild(g_array_index(self->priv->set, struct _GlExt, i).ext);
632 }
633
634 /**
635 * visu_gl_ext_set_new:
636 *
637 * Create an object to handle a set of #VisuGlExt objects and draw
638 * them together.
639 *
640 * Since: 3.8
641 *
642 * Returns: (transfer full): a newly created #VisuGlExtSet object.
643 **/
visu_gl_ext_set_new()644 VisuGlExtSet* visu_gl_ext_set_new()
645 {
646 VisuGlExtSet *set;
647
648 set = VISU_GL_EXT_SET(g_object_new(VISU_TYPE_GL_EXT_SET, NULL));
649 return set;
650 }
651
652 /**
653 * visu_gl_ext_set_setGlView:
654 * @set: a #VisuGlExtSet object.
655 * @view: a #VisuGlView object.
656 *
657 * Apply the given @view on all #VisuGlExt objects stored in @set.
658 *
659 * Since: 3.8
660 *
661 * Returns: TRUE if the @view actually change.
662 **/
visu_gl_ext_set_setGlView(VisuGlExtSet * set,VisuGlView * view)663 gboolean visu_gl_ext_set_setGlView(VisuGlExtSet *set, VisuGlView *view)
664 {
665 guint i;
666
667 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
668
669 if (set->priv->view == view)
670 return FALSE;
671
672 if (set->priv->view)
673 {
674 g_object_unref(G_OBJECT(set->priv->view));
675 g_signal_handler_disconnect(G_OBJECT(set->priv->view), set->priv->widthHeight_signal);
676 g_signal_handler_disconnect(G_OBJECT(set->priv->view), set->priv->chg_signal);
677 }
678 if (view)
679 {
680 g_object_ref(G_OBJECT(view));
681 set->priv->widthHeight_signal =
682 g_signal_connect(G_OBJECT(view), "WidthHeightChanged",
683 G_CALLBACK(onWidthHeight), (gpointer)set);
684 set->priv->chg_signal =
685 g_signal_connect(G_OBJECT(view), "changed",
686 G_CALLBACK(onCamera), (gpointer)set);
687 }
688 set->priv->view = view;
689
690 for (i = 0; i < set->priv->set->len; i++)
691 visu_gl_ext_setGlView(g_array_index(set->priv->set, struct _GlExt, i).ext, view);
692
693 return TRUE;
694 }
695
696 /**
697 * visu_gl_ext_set_getAll:
698 * @set: a #VisuGlExtSet object.
699 *
700 * Retrieve as a #GList all the #VisuGlExt objects drawn by @set.
701 *
702 * Since: 3.8
703 *
704 * Returns: (transfer container) (element-type VisuGlExt*): only the
705 * container list should be freed after.
706 **/
visu_gl_ext_set_getAll(VisuGlExtSet * set)707 GList* visu_gl_ext_set_getAll(VisuGlExtSet *set)
708 {
709 GList *lst;
710 guint i;
711
712 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), (GList*)0);
713
714 lst = (GList*)0;
715 for (i = 0; i < set->priv->set->len; i++)
716 lst = g_list_append(lst, g_array_index(set->priv->set, struct _GlExt, i).ext);
717 return lst;
718 }
719
720 /**
721 * visu_gl_ext_set_getByName:
722 * @set: a #VisuGlExtSet object.
723 * @name: a name to look for.
724 *
725 * Retrieve the #VisuGlExt object with @name that is stored in
726 * @set. If several #VisuGlExt objects have the same name, the first
727 * one is returned.
728 *
729 * Since: 3.8
730 *
731 * Returns: (transfer none): a #VisuGlExt with @name.
732 **/
visu_gl_ext_set_getByName(const VisuGlExtSet * set,const gchar * name)733 VisuGlExt* visu_gl_ext_set_getByName(const VisuGlExtSet *set, const gchar *name)
734 {
735 guint i;
736
737 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), (VisuGlExt*)0);
738
739 for (i = 0; i < set->priv->set->len; i++)
740 if (!strcmp(visu_gl_ext_getName(g_array_index(set->priv->set, struct _GlExt, i).ext), name))
741 return g_array_index(set->priv->set, struct _GlExt, i).ext;
742 return (VisuGlExt*)0;
743 }
744
_emitDirty(gpointer data)745 static gboolean _emitDirty(gpointer data)
746 {
747 /* if (!VISU_GL_EXT_SET(data)->priv->dirty) */
748 /* return FALSE; */
749 g_object_notify_by_pspec(G_OBJECT(data), properties[DIRTY_PROP]);
750
751 VISU_GL_EXT_SET(data)->priv->dirtyPending = 0;
752 return FALSE;
753 }
_appendDirty(VisuGlExtSet * set)754 static void _appendDirty(VisuGlExtSet *set)
755 {
756 /* if (set->priv->dirtyPending) */
757 /* g_source_remove(set->priv->dirtyPending); */
758 set->priv->dirty = TRUE;
759 if (!set->priv->dirtyPending)
760 set->priv->dirtyPending =
761 g_idle_add_full(G_PRIORITY_HIGH_IDLE, _emitDirty, (gpointer)set, (GDestroyNotify)0);
762 }
onExtPriority(VisuGlExtSet * set)763 static void onExtPriority(VisuGlExtSet *set)
764 {
765 set->priv->reorderingNeeded = TRUE;
766 }
onExtDirty(VisuGlExtSet * set,GParamSpec * pspec _U_,VisuGlExt * ext)767 static void onExtDirty(VisuGlExtSet *set, GParamSpec *pspec _U_, VisuGlExt *ext)
768 {
769 if (!visu_gl_ext_getActive(ext))
770 return;
771 DBG_fprintf(stderr, "Visu Extension Set: extension '%s' is dirty.\n",
772 visu_gl_ext_getName(ext));
773 _appendDirty(set);
774 }
775
776 /**
777 * visu_gl_ext_set_add:
778 * @set: a #VisuGlExtSet object.
779 * @ext: a #VisuGlExt object.
780 *
781 * Add @ext in the list of drawn #VisuGlExt by @set.
782 *
783 * Since: 3.8
784 *
785 * Returns: TRUE if not already existing.
786 **/
visu_gl_ext_set_add(VisuGlExtSet * set,VisuGlExt * ext)787 gboolean visu_gl_ext_set_add(VisuGlExtSet *set, VisuGlExt *ext)
788 {
789 struct _GlExt s;
790 guint i;
791
792 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
793
794 /* Lookup first for ext in the set. */
795 for (i = 0; i < set->priv->set->len; i++)
796 if (g_array_index(set->priv->set, struct _GlExt, i).ext == ext)
797 return FALSE;
798
799 g_object_ref(G_OBJECT(ext));
800 s.ext = ext;
801 s.priority_sig = g_signal_connect_swapped(G_OBJECT(ext), "notify::priority",
802 G_CALLBACK(onExtPriority), set);
803 s.dirty_sig = g_signal_connect_swapped(G_OBJECT(ext), "notify::dirty",
804 G_CALLBACK(onExtDirty), set);
805 s.active_sig = g_signal_connect_swapped(G_OBJECT(ext), "notify::active",
806 G_CALLBACK(_appendDirty), set);
807 if (set->priv->view)
808 visu_gl_ext_setGlView(ext, set->priv->view);
809 visu_gl_ext_setGlContext(ext, VISU_GL(set));
810
811 set->priv->reorderingNeeded = TRUE;
812
813 g_array_append_val(set->priv->set, s);
814
815 if (VISU_GL_EXT_SET_GET_CLASS(set)->added)
816 VISU_GL_EXT_SET_GET_CLASS(set)->added(set, ext);
817
818 onExtDirty(set, NULL, ext);
819
820 return TRUE;
821 }
822
823 /**
824 * visu_gl_ext_set_remove:
825 * @set: a #VisuGlExtSet object.
826 * @ext: a #VisuGlExt object.
827 *
828 * Remove @ext in the list of drawn #VisuGlExt by @set.
829 *
830 * Since: 3.8
831 *
832 * Returns: TRUE if successfully removed.
833 **/
visu_gl_ext_set_remove(VisuGlExtSet * set,VisuGlExt * ext)834 gboolean visu_gl_ext_set_remove(VisuGlExtSet *set, VisuGlExt *ext)
835 {
836 struct _GlExt *s;
837 guint i;
838 gboolean dirty;
839
840 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
841
842 for (i = 0; i < set->priv->set->len; i++)
843 {
844 s = &g_array_index(set->priv->set, struct _GlExt, i);
845 if (s->ext == ext)
846 {
847 dirty = visu_gl_ext_getActive(s->ext);
848 g_signal_handler_disconnect(G_OBJECT(s->ext), s->priority_sig);
849 g_signal_handler_disconnect(G_OBJECT(s->ext), s->dirty_sig);
850 g_signal_handler_disconnect(G_OBJECT(s->ext), s->active_sig);
851 g_object_unref(s->ext);
852 g_array_remove_index(set->priv->set, i);
853 if (dirty)
854 _appendDirty(set);
855 if (VISU_GL_EXT_SET_GET_CLASS(set)->removed)
856 VISU_GL_EXT_SET_GET_CLASS(set)->removed(set, ext);
857 return TRUE;
858 }
859 }
860 return FALSE;
861 }
862
compareExtensionPriority(gconstpointer a,gconstpointer b)863 static gint compareExtensionPriority(gconstpointer a, gconstpointer b)
864 {
865 guint pa = visu_gl_ext_getPriority(((struct _GlExt*)a)->ext);
866 guint pb = visu_gl_ext_getPriority(((struct _GlExt*)b)->ext);
867
868 if (pa < pb)
869 return (gint)-1;
870 else if (pa > pb)
871 return (gint)+1;
872 else
873 return (gint)0;
874 }
875
mayReorder(VisuGlExtSet * set)876 static void mayReorder(VisuGlExtSet *set)
877 {
878 if (set->priv->reorderingNeeded)
879 {
880 DBG_fprintf(stderr, "Visu Extension Set: sorting known extension"
881 " depending on their priority.\n");
882 g_array_sort(set->priv->set, compareExtensionPriority);
883 set->priv->reorderingNeeded = FALSE;
884 }
885 }
886
887 /**
888 * visu_gl_ext_set_draw:
889 * @set: a #VisuGlExtSet object.
890 *
891 * Basic drawing method : it clears the OpenGL area and call all lists
892 * stored in @set.
893 *
894 * Since: 3.8
895 */
visu_gl_ext_set_draw(VisuGlExtSet * set)896 void visu_gl_ext_set_draw(VisuGlExtSet *set)
897 {
898 int i_stereo, stereo;
899 guint i;
900 static int stereo_buf[2] = {GL_BACK_LEFT, GL_BACK_RIGHT};
901 GLboolean glStereo;
902 float centre[3];
903 VisuBox *box;
904 float start, stop, bSize, fogCentre;
905 #if DEBUG == 1
906 GTimer *timer;
907 gulong fractionTimer;
908 #endif
909
910 g_return_if_fail(VISU_IS_GL_EXT_SET(set) && set->priv->view);
911
912 #if DEBUG == 1
913 timer = g_timer_new();
914 g_timer_start(timer);
915 #endif
916
917 mayReorder(set);
918
919 box = visu_boxed_getBox(VISU_BOXED(set->priv->view));
920 if (box)
921 visu_box_getCentre(box, centre);
922 else
923 {
924 centre[0] = 0.f;
925 centre[1] = 0.f;
926 centre[2] = 0.f;
927 }
928
929 _chessDraw(set);
930
931 glClearColor(set->priv->bgRGB[0], set->priv->bgRGB[1],
932 set->priv->bgRGB[2], set->priv->bgRGB[3]);
933 if (set->priv->fogActive && set->priv->view &&
934 visu_boxed_getBox(VISU_BOXED(set->priv->view)))
935 {
936 glEnable(GL_FOG);
937 glFogi(GL_FOG_MODE, GL_LINEAR);
938 /* glFogi(GL_FOG_MODE, GL_EXP); */
939 /* glFogf(GL_FOG_DENSITY, 0.03f); */
940 if (set->priv->fogFollowsBg)
941 glFogfv(GL_FOG_COLOR, set->priv->bgRGB);
942 else
943 glFogfv(GL_FOG_COLOR, set->priv->fogRGB);
944
945 bSize = visu_box_getGlobalSize(visu_boxed_getBox(VISU_BOXED(set->priv->view)), FALSE);
946 fogCentre = ((set->priv->view->camera.d_red > 100.f) ?
947 100.f : set->priv->view->camera.d_red) * set->priv->view->camera.length0;
948
949 start = fogCentre - bSize + 2.f * bSize * set->priv->fogStartEnd[0];
950 stop = fogCentre - bSize + 2.f * bSize * set->priv->fogStartEnd[1];
951 /* start = visuBox->extens * visuCamera->d_red * (1. - fog_start); */
952 /* stop = visuBox->extens * visuCamera->d_red * (1. + fog_end); */
953 /* start = visuBox->extens * visuCamera->d_red * (1. - 1 / 1.1); */
954 /* stop = visuBox->extens * visuCamera->d_red * (1. + 1 / 1.1); */
955 /* fprintf(stderr, "----------> %f %f %f %f\n", (float)(view->window->near + */
956 /* (view->window->far - view->window->near) * fog_start), (float)(view->window->near + */
957 /* (view->window->far - view->window->near) * fog_end), start, stop); */
958 glFogf(GL_FOG_START, start);
959 glFogf(GL_FOG_END, stop);
960 }
961 else
962 glDisable(GL_FOG);
963
964 glGetBooleanv(GL_STEREO, &glStereo);
965 stereo = (set->priv->view && glStereo && visu_gl_getStereo(VISU_GL(set))) ? 1 : 0;
966 for(i_stereo = 0; i_stereo <= stereo; i_stereo++)
967 {
968 if (stereo == 1)
969 {
970 glRotatef(visu_gl_getStereoAngle(VISU_GL(set)) * (2.f * i_stereo - 1.f),
971 set->priv->view->camera.up[0],
972 set->priv->view->camera.up[1],
973 set->priv->view->camera.up[2]);
974 glDrawBuffer(stereo_buf[i_stereo]);
975 DBG_fprintf(stderr, "Visu Extension Set: draw on buffer %d.\n", i_stereo);
976 }
977 else
978 glDrawBuffer(GL_BACK);
979
980 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
981
982 glPushAttrib(GL_ENABLE_BIT);
983 glCallList(set->priv->chessList);
984 glPopAttrib();
985
986 glPushMatrix();
987 glTranslated(-centre[0], -centre[1], -centre[2]);
988
989 glEnable(GL_DEPTH_TEST);
990
991 /* if (!lists && !trueTransparency) */
992 /* { */
993 /* visu_gl_ext_callAll(FALSE); */
994 /* visu_gl_ext_callAll(TRUE); */
995 /* } */
996 /* else if (!lists && trueTransparency) */
997 /* { */
998 /* glDepthMask(1); */
999 /* glEnable(GL_ALPHA_TEST); */
1000 /* glAlphaFunc(GL_EQUAL, 1.); */
1001 /* visu_gl_ext_callAll(FALSE); */
1002 /* DBG_fprintf(stderr, "OpenGL: second pass for transparency.\n"); */
1003 /* glAlphaFunc(GL_LESS, 1.); */
1004 /* glDepthMask(0); */
1005 /* visu_gl_ext_callAll(FALSE); */
1006 /* glDepthMask(1); */
1007 /* glAlphaFunc(GL_ALWAYS, 1.); */
1008 /* glDisable(GL_ALPHA_TEST); */
1009 /* visu_gl_ext_callAll(TRUE); */
1010 /* } */
1011 /* else */ if (!visu_gl_getTrueTransparency(VISU_GL(set)))
1012 for (i = 0; i < set->priv->set->len; i++)
1013 visu_gl_ext_call(g_array_index(set->priv->set, struct _GlExt, i).ext, FALSE);
1014 else
1015 {
1016 glDepthMask(1);
1017 glEnable(GL_ALPHA_TEST);
1018 glAlphaFunc(GL_EQUAL, 1.);
1019 for (i = 0; i < set->priv->set->len; i++)
1020 visu_gl_ext_call(g_array_index(set->priv->set, struct _GlExt, i).ext, FALSE);
1021 DBG_fprintf(stderr, "Visu Extension Set: second pass for transparency.\n");
1022 glAlphaFunc(GL_LESS, 1.);
1023 glDepthMask(0);
1024 for (i = 0; i < set->priv->set->len; i++)
1025 visu_gl_ext_call(g_array_index(set->priv->set, struct _GlExt, i).ext, FALSE);
1026 glDepthMask(1);
1027 glAlphaFunc(GL_ALWAYS, 1.);
1028 glDisable(GL_ALPHA_TEST);
1029 }
1030 for (i = 0; i < set->priv->set->len; i++)
1031 visu_gl_ext_call(g_array_index(set->priv->set, struct _GlExt, i).ext, TRUE);
1032
1033 glPopMatrix();
1034 }
1035 set->priv->dirty = FALSE;
1036
1037 #if DEBUG == 1
1038 glFlush();
1039 g_timer_stop(timer);
1040 fprintf(stderr, "Visu Extension Set: lists drawn in %g micro-s.\n",
1041 g_timer_elapsed(timer, &fractionTimer)*1e6);
1042 g_timer_destroy(timer);
1043 #endif
1044 }
1045
1046 /**
1047 * visu_gl_ext_set_setBgColor:
1048 * @set: a #VisuGlExtSet object.
1049 * @rgba: (in) (array fixed-size=4): a three floats array with values
1050 * (0 <= values <= 1) for the red, the green and the blue color. Only
1051 * values specified by the mask are really relevant.
1052 * @mask: use #TOOL_COLOR_MASK_R, #TOOL_COLOR_MASK_G,
1053 * #TOOL_COLOR_MASK_B, #TOOL_COLOR_MASK_RGBA or a combinaison to
1054 * indicate what values in the rgb array must be taken into account.
1055 *
1056 * Method used to change the value of the parameter background_color.
1057 *
1058 * Since: 3.8
1059 *
1060 * Returns: TRUE if changed.
1061 */
visu_gl_ext_set_setBgColor(VisuGlExtSet * set,float rgba[4],int mask)1062 gboolean visu_gl_ext_set_setBgColor(VisuGlExtSet *set, float rgba[4], int mask)
1063 {
1064 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
1065
1066 g_object_freeze_notify(G_OBJECT(set));
1067 if (mask & TOOL_COLOR_MASK_R && set->priv->bgRGB[0] != rgba[0])
1068 {
1069 set->priv->bgRGB[0] = CLAMP(rgba[0], 0.f, 1.f);
1070 g_object_notify_by_pspec(G_OBJECT(set), properties[BG_R_PROP]);
1071 set->priv->bgDirty = TRUE;
1072 }
1073 if (mask & TOOL_COLOR_MASK_G && set->priv->bgRGB[1] != rgba[1])
1074 {
1075 set->priv->bgRGB[1] = CLAMP(rgba[1], 0.f, 1.f);
1076 g_object_notify_by_pspec(G_OBJECT(set), properties[BG_G_PROP]);
1077 set->priv->bgDirty = TRUE;
1078 }
1079 if (mask & TOOL_COLOR_MASK_B && set->priv->bgRGB[2] != rgba[2])
1080 {
1081 set->priv->bgRGB[2] = CLAMP(rgba[2], 0.f, 1.f);
1082 g_object_notify_by_pspec(G_OBJECT(set), properties[BG_B_PROP]);
1083 set->priv->bgDirty = TRUE;
1084 }
1085 if (mask & TOOL_COLOR_MASK_A && set->priv->bgRGB[3] != rgba[3])
1086 {
1087 set->priv->bgRGB[3] = CLAMP(rgba[3], 0.f, 1.f);
1088 g_object_notify_by_pspec(G_OBJECT(set), properties[BG_A_PROP]);
1089 set->priv->bgDirty = TRUE;
1090 }
1091 g_object_thaw_notify(G_OBJECT(set));
1092 if (set->priv->bgDirty)
1093 _appendDirty(set);
1094 return set->priv->bgDirty;
1095 }
1096
1097 /**
1098 * visu_gl_ext_set_getBgColor:
1099 * @set: a #VisuGlExtSet object.
1100 * @rgba: (array fixed-size=4) (out): a storage for four values.
1101 *
1102 * Read the RGBA value of the specific background colour (in [0;1]).
1103 *
1104 * Since: 3.8
1105 */
visu_gl_ext_set_getBgColor(const VisuGlExtSet * set,float rgba[4])1106 void visu_gl_ext_set_getBgColor(const VisuGlExtSet *set, float rgba[4])
1107 {
1108 g_return_if_fail(VISU_IS_GL_EXT_SET(set));
1109
1110 memcpy(rgba, set->priv->bgRGB, sizeof(float) * 4);
1111 }
1112
_chessDraw(VisuGlExtSet * set)1113 static void _chessDraw(VisuGlExtSet *set)
1114 {
1115 GLubyte chessboard[32][32][3];
1116 int viewport[4];
1117 int i, j, c;
1118
1119 if (!set->priv->bgDirty)
1120 return;
1121
1122 if (set->priv->bgRGB[3] < 1.f && !(visu_gl_getHint(VISU_GL(set)) & VISU_GL_OFFSCREEN))
1123 {
1124 DBG_fprintf(stderr, "Visu Extension Set: set background chess board (alpha = %g).\n",
1125 set->priv->bgRGB[3]);
1126
1127 if (texName == 0)
1128 glGenTextures(1, &texName);
1129
1130 /* We create the chessboard texture with the right colour. */
1131 for (i = 0; i < 32; i++)
1132 for (j = 0; j < 32; j++)
1133 {
1134 c = 128 + ( ((i&0x10)==0) ^ ((j&0x10) == 0) ) * 64;
1135 chessboard[i][j][0] =
1136 (GLubyte)(255.f * set->priv->bgRGB[0] * set->priv->bgRGB[3] +
1137 (1.f - set->priv->bgRGB[3]) * c);
1138 chessboard[i][j][1] =
1139 (GLubyte)(255.f * set->priv->bgRGB[1] * set->priv->bgRGB[3] +
1140 (1.f - set->priv->bgRGB[3]) * c);
1141 chessboard[i][j][2] =
1142 (GLubyte)(255.f * set->priv->bgRGB[2] * set->priv->bgRGB[3] +
1143 (1.f - set->priv->bgRGB[3]) * c);
1144 }
1145 /* We bind the texture. */
1146 glBindTexture(GL_TEXTURE_2D, texName);
1147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1149 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1151
1152 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1153 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 32, 32, 0,
1154 GL_RGB, GL_UNSIGNED_BYTE, chessboard);
1155
1156 glGetIntegerv(GL_VIEWPORT, viewport);
1157
1158 glNewList(set->priv->chessList, GL_COMPILE);
1159 glDisable(GL_CULL_FACE);
1160 glDisable(GL_LIGHTING);
1161
1162 glEnable(GL_TEXTURE_2D);
1163 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1164 glBindTexture(GL_TEXTURE_2D, texName);
1165
1166 glMatrixMode(GL_PROJECTION);
1167 glPushMatrix();
1168 glLoadIdentity();
1169 gluOrtho2D(0., (float)viewport[2], 0., (float)viewport[3]);
1170 glMatrixMode(GL_MODELVIEW);
1171 glPushMatrix();
1172 glLoadIdentity();
1173
1174 glDepthMask(0);
1175 glBegin(GL_QUADS);
1176 glTexCoord2f(0.0, 0.0);
1177 glVertex3f(0.0, 0.0, 0.0);
1178 glTexCoord2f(0.0, (float)viewport[3] / 32.f);
1179 glVertex3f(0.0, (float)viewport[3], 0.0);
1180 glTexCoord2f((float)viewport[2] / 32.f, (float)viewport[3] / 32.f);
1181 glVertex3f((float)viewport[2], (float)viewport[3], 0.0);
1182 glTexCoord2f((float)viewport[2] / 32.f, 0.0);
1183 glVertex3f((float)viewport[2], 0.0, 0.0);
1184 glEnd();
1185 glDepthMask(1);
1186
1187 glPopMatrix();
1188 glMatrixMode(GL_PROJECTION);
1189 glPopMatrix();
1190 glMatrixMode(GL_MODELVIEW);
1191
1192 glDisable(GL_TEXTURE_2D);
1193 glEndList();
1194 }
1195 else
1196 glDeleteLists(set->priv->chessList, 1);
1197 set->priv->bgDirty = FALSE;
1198 }
1199
1200 /**
1201 * visu_gl_ext_set_setFogColor:
1202 * @set: a #VisuGlExtSet object.
1203 * @rgba: (array fixed-size=4): four [0;1] float values.
1204 * @mask: a mask, see %TOOL_COLOR_MASK_R for instance.
1205 *
1206 * Change the fog specific colour. Activate it with
1207 * visu_gl_ext_set_setFogFollowsBg().
1208 *
1209 * Since: 3.8
1210 *
1211 * Returns: TRUE if value is actually changed.
1212 **/
visu_gl_ext_set_setFogColor(VisuGlExtSet * set,float rgba[4],int mask)1213 gboolean visu_gl_ext_set_setFogColor(VisuGlExtSet *set, float rgba[4], int mask)
1214 {
1215 gboolean diff;
1216
1217 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
1218
1219 diff = FALSE;
1220 g_object_freeze_notify(G_OBJECT(set));
1221 if (mask & TOOL_COLOR_MASK_R && set->priv->fogRGB[0] != rgba[0])
1222 {
1223 set->priv->fogRGB[0] = CLAMP(rgba[0], 0.f, 1.f);
1224 g_object_notify_by_pspec(G_OBJECT(set), properties[FOG_R_PROP]);
1225 diff = TRUE;
1226 }
1227 if (mask & TOOL_COLOR_MASK_G && set->priv->fogRGB[1] != rgba[1])
1228 {
1229 set->priv->fogRGB[1] = CLAMP(rgba[1], 0.f, 1.f);
1230 g_object_notify_by_pspec(G_OBJECT(set), properties[FOG_G_PROP]);
1231 diff = TRUE;
1232 }
1233 if (mask & TOOL_COLOR_MASK_B && set->priv->fogRGB[2] != rgba[2])
1234 {
1235 set->priv->fogRGB[2] = CLAMP(rgba[2], 0.f, 1.f);
1236 g_object_notify_by_pspec(G_OBJECT(set), properties[FOG_B_PROP]);
1237 diff = TRUE;
1238 }
1239 if (mask & TOOL_COLOR_MASK_A && set->priv->fogRGB[3] != rgba[3])
1240 {
1241 set->priv->fogRGB[3] = CLAMP(rgba[3], 0.f, 1.f);
1242 g_object_notify_by_pspec(G_OBJECT(set), properties[FOG_A_PROP]);
1243 diff = TRUE;
1244 }
1245 g_object_thaw_notify(G_OBJECT(set));
1246 if (diff && set->priv->fogActive)
1247 _appendDirty(set);
1248 return diff;
1249 }
1250 /**
1251 * visu_gl_ext_set_setFogActive:
1252 * @set: a #VisuGlExtSet object.
1253 * @value: a boolean.
1254 *
1255 * Activates the fog rendering, or not.
1256 *
1257 * Since: 3.8
1258 *
1259 * Returns: TRUE if value is actually changed.
1260 **/
visu_gl_ext_set_setFogActive(VisuGlExtSet * set,gboolean value)1261 gboolean visu_gl_ext_set_setFogActive(VisuGlExtSet *set, gboolean value)
1262 {
1263 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
1264
1265 if (set->priv->fogActive == value)
1266 return FALSE;
1267
1268 set->priv->fogActive = value;
1269 g_object_notify_by_pspec(G_OBJECT(set), properties[FOG_ACTIVE_PROP]);
1270 _appendDirty(set);
1271 return TRUE;
1272 }
1273 /**
1274 * visu_gl_ext_set_setFogFollowsBg:
1275 * @set: a #VisuGlExtSet object.
1276 * @value: a boolean.
1277 *
1278 * Specifies if the fog is coloured with the background colour or with
1279 * its own colour, see visu_gl_ext_set_setFogColor().
1280 *
1281 * Since: 3.8
1282 *
1283 * Returns: TRUE if value is actually changed.
1284 **/
visu_gl_ext_set_setFogFollowsBg(VisuGlExtSet * set,gboolean value)1285 gboolean visu_gl_ext_set_setFogFollowsBg(VisuGlExtSet *set, gboolean value)
1286 {
1287 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
1288
1289 if (set->priv->fogFollowsBg == value)
1290 return FALSE;
1291
1292 set->priv->fogFollowsBg = value;
1293 g_object_notify_by_pspec(G_OBJECT(set), properties[FOG_FOLLOWS_PROP]);
1294 if (set->priv->fogActive)
1295 _appendDirty(set);
1296 return TRUE;
1297 }
1298 /**
1299 * visu_gl_ext_set_setFogStartFull:
1300 * @set: a #VisuGlExtSet object.
1301 * @startEnd: (array fixed-size=2): two [0;1] floating point values.
1302 * @mask: a mask, see %VISU_GL_EXT_SET_FOG_MASK_START and
1303 * %VISU_GL_EXT_SET_FOG_MASK_FULL.
1304 *
1305 * Change the starting and ending point of fog.
1306 *
1307 * Since: 3.8
1308 *
1309 * Returns: TRUE if values are actually changed.
1310 **/
visu_gl_ext_set_setFogStartFull(VisuGlExtSet * set,float startEnd[2],int mask)1311 gboolean visu_gl_ext_set_setFogStartFull(VisuGlExtSet *set, float startEnd[2], int mask)
1312 {
1313 gboolean diff;
1314
1315 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
1316
1317 diff = FALSE;
1318 g_object_freeze_notify(G_OBJECT(set));
1319 if (mask & VISU_GL_EXT_SET_FOG_MASK_START && set->priv->fogStartEnd[0] != startEnd[0])
1320 {
1321 set->priv->fogStartEnd[0] = CLAMP(startEnd[0], 0.f, 1.f);
1322 if (mask & VISU_GL_EXT_SET_FOG_MASK_FULL)
1323 {
1324 if (set->priv->fogStartEnd[0] >= startEnd[1])
1325 set->priv->fogStartEnd[0] = startEnd[1] - 0.001;
1326 }
1327 else
1328 if (set->priv->fogStartEnd[0] >= set->priv->fogStartEnd[1])
1329 set->priv->fogStartEnd[0] = set->priv->fogStartEnd[1] - 0.001;
1330 g_object_notify_by_pspec(G_OBJECT(set), properties[FOG_START_PROP]);
1331 diff = TRUE;
1332 }
1333 if (mask & VISU_GL_EXT_SET_FOG_MASK_FULL && set->priv->fogStartEnd[1] != startEnd[1])
1334 {
1335 set->priv->fogStartEnd[1] = CLAMP(startEnd[1], 0.f, 1.f);
1336 if (set->priv->fogStartEnd[1] <= set->priv->fogStartEnd[0])
1337 set->priv->fogStartEnd[1] = set->priv->fogStartEnd[0] + 0.001;
1338 g_object_notify_by_pspec(G_OBJECT(set), properties[FOG_FULL_PROP]);
1339 diff = TRUE;
1340 }
1341 g_object_thaw_notify(G_OBJECT(set));
1342 if (diff && set->priv->fogActive)
1343 _appendDirty(set);
1344 return diff;
1345 }
1346
1347 /**
1348 * visu_gl_ext_set_getFogColor:
1349 * @set: a #VisuGlExtSet object.
1350 * @rgba: (out) (array fixed-size=4): a storage for three values.
1351 *
1352 * Gives the actual fog color, for the specific color, use
1353 * visu_gl_ext_set_getFogSpecificColor().
1354 *
1355 * Since: 3.8
1356 */
visu_gl_ext_set_getFogColor(VisuGlExtSet * set,float rgba[4])1357 void visu_gl_ext_set_getFogColor(VisuGlExtSet *set, float rgba[4])
1358 {
1359 g_return_if_fail(VISU_IS_GL_EXT_SET(set));
1360 if (set->priv->fogFollowsBg)
1361 memcpy(rgba, set->priv->bgRGB, sizeof(float) * 4);
1362 else
1363 memcpy(rgba, set->priv->fogRGB, sizeof(float) * 4);
1364 }
1365 /**
1366 * visu_gl_ext_set_getFogSpecificColor:
1367 * @set: a #VisuGlExtSet object.
1368 * @rgba: (out) (array fixed-size=4): a storage for three values.
1369 *
1370 * Gives the specific fog color, for the actual color, use
1371 * visu_gl_ext_set_getFogColor().
1372 *
1373 * Since: 3.8
1374 */
visu_gl_ext_set_getFogSpecificColor(VisuGlExtSet * set,float rgba[4])1375 void visu_gl_ext_set_getFogSpecificColor(VisuGlExtSet *set, float rgba[4])
1376 {
1377 g_return_if_fail(VISU_IS_GL_EXT_SET(set));
1378 memcpy(rgba, set->priv->fogRGB, sizeof(float) * 4);
1379 }
1380 /**
1381 * visu_gl_ext_set_getFogActive:
1382 * @set: a #VisuGlExtSet object.
1383 *
1384 * Read if fog is used or not.
1385 *
1386 * Since: 3.8
1387 *
1388 * Returns: TRUE if the fog is rendered, FALSE otherwise.
1389 */
visu_gl_ext_set_getFogActive(VisuGlExtSet * set)1390 gboolean visu_gl_ext_set_getFogActive(VisuGlExtSet *set)
1391 {
1392 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
1393 return set->priv->fogActive;
1394 }
1395 /**
1396 * visu_gl_ext_set_getFogFollowsBg:
1397 * @set: a #VisuGlExtSet object.
1398 *
1399 * Read if fog uses a specific colour or not.
1400 *
1401 * Since: 3.8
1402 *
1403 * Returns: TRUE if the fog uses its own color or FALSE if it uses
1404 * the color of the background.
1405 */
visu_gl_ext_set_getFogFollowsBg(VisuGlExtSet * set)1406 gboolean visu_gl_ext_set_getFogFollowsBg(VisuGlExtSet *set)
1407 {
1408 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), FALSE);
1409 return set->priv->fogFollowsBg;
1410 }
1411 /**
1412 * visu_gl_ext_set_getFogStartFull:
1413 * @set: a #VisuGlExtSet object.
1414 * @startFull: (out caller-allocates) (array fixed-size=2): two float
1415 * location.
1416 *
1417 * Retrieves the starting and ending value (reduced) of fog extension.
1418 *
1419 * Since: 3.8
1420 **/
visu_gl_ext_set_getFogStartFull(VisuGlExtSet * set,float startFull[2])1421 void visu_gl_ext_set_getFogStartFull(VisuGlExtSet *set, float startFull[2])
1422 {
1423 g_return_if_fail(VISU_IS_GL_EXT_SET(set));
1424 memcpy(startFull, set->priv->fogStartEnd, sizeof(float) * 2);
1425 }
1426
1427 /**
1428 * visu_gl_ext_set_getPixmapData:
1429 * @set: a #VisuGlExtSet object ;
1430 * @width: the desired width or 0 for current ;
1431 * @height: the desired height or 0 for current ;
1432 * @hasAlpha: if TRUE, the returned data is RGBA, else only RGB.
1433 *
1434 * Create an image from the OpenGL area. The size can be changed, using @width and
1435 * @height. If these pointers contains positive values, then they are used to set the
1436 * size for the image. If not, the size of the current #VisuGlView is used and
1437 * stored in these pointers.
1438 *
1439 * Since: 3.8
1440 *
1441 * Returns: (transfer full) (element-type int): image data, row by row.
1442 */
visu_gl_ext_set_getPixmapData(VisuGlExtSet * set,guint width,guint height,gboolean hasAlpha)1443 GArray* visu_gl_ext_set_getPixmapData(VisuGlExtSet *set, guint width,
1444 guint height, gboolean hasAlpha)
1445 {
1446 GArray *image;
1447 VisuPixmapContext *dumpData;
1448 guint row_length;
1449 gint m, n1, n2;
1450 guchar *row_tab;
1451 guint oldW, oldH;
1452
1453 g_return_val_if_fail(VISU_IS_GL_EXT_SET(set), (GArray*)0);
1454 g_return_val_if_fail(VISU_IS_GL_VIEW(set->priv->view), (GArray*)0);
1455
1456 /* We may change the actual drawing size. */
1457 width = (width > 0) ? width : set->priv->view->window.width;
1458 height = (height > 0) ? height : set->priv->view->window.height;
1459 oldW = set->priv->view->window.width;
1460 oldH = set->priv->view->window.height;
1461 visu_gl_view_setViewport(set->priv->view, width, height);
1462
1463 /* We create a pixmap context and make this context current. */
1464 dumpData = visu_pixmap_context_new(width, height);
1465 if (!dumpData)
1466 {
1467 g_warning("can't create off-screen pixmap.");
1468 return (GArray*)0;
1469 }
1470 /* We set the glViewport of this new context. */
1471 visu_gl_initContext(VISU_GL(set));
1472 /* We call the given draw method. */
1473 visu_gl_ext_set_draw(set);
1474 /* We copy the pixmap into generic data. */
1475 if (hasAlpha)
1476 row_length = 4 * width;
1477 else
1478 row_length = 3 * width;
1479 row_tab = g_malloc(sizeof(guchar) * row_length);
1480
1481 image = g_array_sized_new(FALSE, FALSE, sizeof(guchar), row_length * height);
1482
1483 glPixelStorei(GL_PACK_ALIGNMENT, 1); /* just in case */
1484
1485 /* Copy the image into our buffer */
1486 n2 = 0;
1487 for(m = height - 1; m >= 0; m--)
1488 {
1489 if (hasAlpha)
1490 glReadPixels(0, m, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, row_tab);
1491 else
1492 glReadPixels(0, m, width, 1, GL_RGB, GL_UNSIGNED_BYTE, row_tab);
1493 n1 = n2;
1494 n2 = n1 + row_length;
1495 image = g_array_insert_vals(image, n1, row_tab, n2 - n1);
1496 }
1497 g_free(row_tab);
1498
1499 DBG_fprintf(stderr, " | save to array %p.\n", (gpointer)image);
1500 /* We free the pixmap context. */
1501 visu_pixmap_context_free(dumpData);
1502
1503 /* We put back the viewport. */
1504 visu_gl_view_setViewport(set->priv->view, oldW, oldH);
1505
1506 return image;
1507 }
1508
1509 /***************************/
1510 /* Dealing with parameters */
1511 /***************************/
onEntryBgColor(VisuGlExtSet * set,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)1512 static void onEntryBgColor(VisuGlExtSet *set, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
1513 {
1514 visu_gl_ext_set_setBgColor(set, bgRGBDefault, TOOL_COLOR_MASK_RGBA);
1515 }
onEntryFogActive(VisuGlExtSet * set,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)1516 static void onEntryFogActive(VisuGlExtSet *set, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
1517 {
1518 visu_gl_ext_set_setFogActive(set, fogActiveDefault);
1519 }
onEntryFogSpecific(VisuGlExtSet * set,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)1520 static void onEntryFogSpecific(VisuGlExtSet *set, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
1521 {
1522 visu_gl_ext_set_setFogFollowsBg(set, !fogSpecificDefault);
1523 }
onEntryFogColor(VisuGlExtSet * set,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)1524 static void onEntryFogColor(VisuGlExtSet *set, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
1525 {
1526 visu_gl_ext_set_setFogColor(set, fogRGBDefault, TOOL_COLOR_MASK_RGBA);
1527 }
onEntryFogStartEnd(VisuGlExtSet * set,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)1528 static void onEntryFogStartEnd(VisuGlExtSet *set, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
1529 {
1530 visu_gl_ext_set_setFogStartFull(set, fogStartEndDefault,
1531 VISU_GL_EXT_SET_FOG_MASK_START |
1532 VISU_GL_EXT_SET_FOG_MASK_FULL);
1533 }
onWidthHeight(VisuGlView * view _U_,gpointer data)1534 static void onWidthHeight(VisuGlView *view _U_, gpointer data)
1535 {
1536 VisuGlExtSetPrivate *priv = VISU_GL_EXT_SET(data)->priv;
1537
1538 DBG_fprintf(stderr, "Visu Extension Set: caught the 'WidthHeightChanged' signal.\n");
1539
1540 if (priv->bgRGB[3] < 1.f)
1541 priv->bgDirty = TRUE;
1542 }
onCamera(VisuGlView * view _U_,gpointer data)1543 static void onCamera(VisuGlView *view _U_, gpointer data)
1544 {
1545 _appendDirty(VISU_GL_EXT_SET(data));
1546 }
1547
exportResources(GString * data,VisuData * dataObj _U_)1548 static void exportResources(GString *data, VisuData *dataObj _U_)
1549 {
1550 if (!defaultSet)
1551 return;
1552
1553 visu_config_file_exportComment(data, DESC_RESOURCE_BG_COLOR);
1554 visu_config_file_exportEntry(data, FLAG_RESOURCE_BG_COLOR, NULL,
1555 "%4.3f %4.3f %4.3f %4.3f",
1556 defaultSet->priv->bgRGB[0], defaultSet->priv->bgRGB[1],
1557 defaultSet->priv->bgRGB[2], defaultSet->priv->bgRGB[3]);
1558
1559 visu_config_file_exportComment(data, DESC_RESOURCE_FOG_USED);
1560 visu_config_file_exportEntry(data, FLAG_RESOURCE_FOG_USED, NULL,
1561 "%d", defaultSet->priv->fogActive);
1562 visu_config_file_exportComment(data, DESC_RESOURCE_FOG_SPECIFIC);
1563 visu_config_file_exportEntry(data, FLAG_RESOURCE_FOG_SPECIFIC, NULL,
1564 "%d", !defaultSet->priv->fogFollowsBg);
1565 visu_config_file_exportComment(data, DESC_RESOURCE_FOG_COLOR);
1566 visu_config_file_exportEntry(data, FLAG_RESOURCE_FOG_COLOR, NULL,
1567 "%4.3f %4.3f %4.3f %4.3f",
1568 defaultSet->priv->fogRGB[0], defaultSet->priv->fogRGB[1],
1569 defaultSet->priv->fogRGB[2], defaultSet->priv->fogRGB[3]);
1570 visu_config_file_exportComment(data, DESC_RESOURCE_FOG_STARTEND);
1571 visu_config_file_exportEntry(data, FLAG_RESOURCE_FOG_STARTEND, NULL,
1572 "%4.3f %4.3f", defaultSet->priv->fogStartEnd[0],
1573 defaultSet->priv->fogStartEnd[1]);
1574
1575 visu_config_file_exportComment(data, "");
1576 }
1577