1// @configure_input@
2
3/**************************************************************************\
4 * Copyright (c) Kongsberg Oil & Gas Technologies AS
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived from
20 * this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33\**************************************************************************/
34
35#ifdef HAVE_CONFIG_H
36#include <config.h>
37#endif // HAVE_CONFIG_H
38
39#include <assert.h>
40
41#include <Inventor/nodes/SoMaterial.h>
42#include <Inventor/sensors/SoFieldSensor.h>
43#include <Inventor/sensors/SoNodeSensor.h>
44#ifdef HAVE_SOVRMLMATERIAL
45#include <Inventor/VRMLnodes/SoVRMLMaterial.h>
46#endif // HAVE_SOVRMLMATERIAL
47
48#include <Inventor/@Gui@/SoAny.h>
49#include <Inventor/@Gui@/nodes/SoGuiPane.h>
50#include <Inventor/@Gui@/nodes/SoGuiImage.h>
51#include <Inventor/@Gui@/nodes/SoGuiSceneTexture2.h>
52#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
53#include <Inventor/@Gui@/nodes/SoGuiToggleButton.h>
54#include <Inventor/@Gui@/nodes/SoGuiRadioButton.h>
55#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
56
57#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
58
59// *************************************************************************
60
61class MaterialEditor {
62public:
63  MaterialEditor(void);
64  ~MaterialEditor(void);
65
66  SoGuiMaterialEditor * api;
67
68  SoMaterial * material;
69  SoNodeSensor * material_sensor;
70  static void material_cb(void * closure, SoSensor * sensor);
71
72  SoFieldSensor * material_field_sensor;
73  static void material_field_cb(void * closure, SoSensor * sensor);
74
75  SoGuiToggleButton * button1;
76  SoGuiToggleButton * button2;
77  SoGuiToggleButton * button3;
78  SoGuiToggleButton * button4;
79  SoFieldSensor * button1_sensor;
80  SoFieldSensor * button2_sensor;
81  SoFieldSensor * button3_sensor;
82  SoFieldSensor * button4_sensor;
83  static void button1_cb(void * closure, SoSensor * sensor);
84  static void button2_cb(void * closure, SoSensor * sensor);
85  static void button3_cb(void * closure, SoSensor * sensor);
86  static void button4_cb(void * closure, SoSensor * sensor);
87  SoGuiRadioButton * radio1;
88  SoGuiRadioButton * radio2;
89  SoGuiRadioButton * radio3;
90  SoGuiRadioButton * radio4;
91
92  SoGuiSlider1 * slider1;
93  SoGuiSlider1 * slider2;
94  SoGuiSlider1 * slider3;
95  SoGuiSlider1 * slider4;
96  SoGuiSlider1 * slider5;
97  SoGuiSlider1 * slider6;
98  SoFieldSensor * ambient_slider_sensor;
99  SoFieldSensor * diffuse_slider_sensor;
100  SoFieldSensor * specular_slider_sensor;
101  SoFieldSensor * emissive_slider_sensor;
102  SoFieldSensor * shininess_slider_sensor;
103  SoFieldSensor * transparency_slider_sensor;
104  static void ambient_slider_cb(void * closure, SoSensor * sensor);
105  static void diffuse_slider_cb(void * closure, SoSensor * sensor);
106  static void specular_slider_cb(void * closure, SoSensor * sensor);
107  static void emissive_slider_cb(void * closure, SoSensor * sensor);
108  static void shininess_slider_cb(void * closure, SoSensor * sensor);
109  static void transparency_slider_cb(void * closure, SoSensor * sensor);
110
111  SoGuiColorEditorOpenCB * openeditorcb;
112  SoGuiColorEditorCloseCB * closeeditorcb;
113  void * cbclosure;
114
115  static SoGuiColorEditor * coloreditoropen_cb(void * closure);
116  static void coloreditorclose_cb(void * closure, SoGuiColorEditor * editor);
117
118  SbBool coloreditoropen;
119  SoGuiColorEditor * coloreditor;
120  SoFieldSensor * coloreditor_sensor;
121  static void coloreditor_cb(void * closure, SoSensor * sensor);
122
123  void checkColorEditorOpenStatus(void);
124
125  static const char * texturescene[];
126  static const char * editorscene[];
127};
128
129// *************************************************************************
130
131#define PRIVATE(obj) ((MaterialEditor *) ((SoGuiMaterialEditor *) obj)->internals)
132
133void
134SoGuiMaterialEditor::initClass(void)
135{
136  SO_KIT_INIT_CLASS(SoGuiMaterialEditor, SoBaseKit, "BaseKit");
137}
138
139SO_KIT_SOURCE(SoGuiMaterialEditor);
140
141SoGuiMaterialEditor::SoGuiMaterialEditor(void)
142{
143  this->internals = new MaterialEditor;
144  PRIVATE(this)->api = this;
145
146  SO_KIT_CONSTRUCTOR(SoGuiMaterialEditor);
147
148  SO_KIT_ADD_FIELD(material, (NULL));
149  SO_KIT_ADD_FIELD(index, (0));
150  SO_KIT_ADD_FIELD(update, (CONTINUOUS));
151
152  SO_KIT_DEFINE_ENUM_VALUE(Update, CONTINUOUS);
153  SO_KIT_DEFINE_ENUM_VALUE(Update, AFTER_ACCEPT);
154
155  SO_KIT_SET_SF_ENUM_TYPE(update, Update);
156
157  SO_KIT_ADD_CATALOG_ENTRY(root, SoGuiPane, TRUE, this, "", FALSE);
158
159  SO_KIT_INIT_INSTANCE();
160
161  SoNode * scene = SoAny::loadSceneGraph(MaterialEditor::editorscene);
162  assert(scene != NULL);
163  assert(scene->isOfType(SoGuiPane::getClassTypeId()));
164  scene->ref();
165
166  SoGuiImage * sphereimage =
167    (SoGuiImage *) SoAny::scanSceneForName(scene, "image");
168  assert(sphereimage != NULL);
169  scene->unrefNoDelete();
170  SbBool ok = this->setAnyPart("root", scene);
171  assert(ok);
172
173  PRIVATE(this)->button1 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton1");
174  PRIVATE(this)->button2 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton2");
175  PRIVATE(this)->button3 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton3");
176  PRIVATE(this)->button4 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton4");
177  assert(PRIVATE(this)->button1);
178  assert(PRIVATE(this)->button2);
179  assert(PRIVATE(this)->button3);
180  assert(PRIVATE(this)->button4);
181  PRIVATE(this)->radio1 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton1");
182  PRIVATE(this)->radio2 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton2");
183  PRIVATE(this)->radio3 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton3");
184  PRIVATE(this)->radio4 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton4");
185  assert(PRIVATE(this)->radio1);
186  assert(PRIVATE(this)->radio2);
187  assert(PRIVATE(this)->radio3);
188  assert(PRIVATE(this)->radio4);
189
190  PRIVATE(this)->slider1 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider1");
191  PRIVATE(this)->slider2 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider2");
192  PRIVATE(this)->slider3 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider3");
193  PRIVATE(this)->slider4 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider4");
194  PRIVATE(this)->slider5 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider5");
195  PRIVATE(this)->slider6 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider6");
196  assert(PRIVATE(this)->slider1);
197  assert(PRIVATE(this)->slider2);
198  assert(PRIVATE(this)->slider3);
199  assert(PRIVATE(this)->slider4);
200  assert(PRIVATE(this)->slider5);
201  assert(PRIVATE(this)->slider6);
202  PRIVATE(this)->slider1->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
203  PRIVATE(this)->slider2->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
204  PRIVATE(this)->slider3->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
205  PRIVATE(this)->slider4->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
206  PRIVATE(this)->slider5->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
207  PRIVATE(this)->slider6->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
208
209  SoNode * textureroot = SoAny::loadSceneGraph(MaterialEditor::texturescene);
210  assert(textureroot != NULL);
211  assert(textureroot->isOfType(SoSeparator::getClassTypeId()));
212  SoNode * texture = ((SoSeparator *) textureroot)->getChild(0);
213  assert(texture != NULL);
214  assert(texture->isOfType(SoGuiSceneTexture2::getClassTypeId()));
215
216  SoNode * subscene = ((SoGuiSceneTexture2 *) texture)->scene.getValue();
217  assert(subscene);
218  subscene->ref();
219  PRIVATE(this)->material = (SoMaterial *) SoAny::scanSceneForName(subscene, "material");
220  subscene->unrefNoDelete();
221  assert(PRIVATE(this)->material);
222
223  ok = sphereimage->setPart("texture", texture);
224  assert(ok);
225
226  PRIVATE(this)->ambient_slider_sensor = new SoFieldSensor(MaterialEditor::ambient_slider_cb, PRIVATE(this));
227  PRIVATE(this)->diffuse_slider_sensor = new SoFieldSensor(MaterialEditor::diffuse_slider_cb, PRIVATE(this));
228  PRIVATE(this)->specular_slider_sensor = new SoFieldSensor(MaterialEditor::specular_slider_cb, PRIVATE(this));
229  PRIVATE(this)->emissive_slider_sensor = new SoFieldSensor(MaterialEditor::emissive_slider_cb, PRIVATE(this));
230  PRIVATE(this)->shininess_slider_sensor = new SoFieldSensor(MaterialEditor::shininess_slider_cb, PRIVATE(this));
231  PRIVATE(this)->transparency_slider_sensor = new SoFieldSensor(MaterialEditor::transparency_slider_cb, PRIVATE(this));
232  PRIVATE(this)->ambient_slider_sensor->attach(&(PRIVATE(this)->slider1->value));
233  PRIVATE(this)->diffuse_slider_sensor->attach(&(PRIVATE(this)->slider2->value));
234  PRIVATE(this)->specular_slider_sensor->attach(&(PRIVATE(this)->slider3->value));
235  PRIVATE(this)->emissive_slider_sensor->attach(&(PRIVATE(this)->slider4->value));
236  PRIVATE(this)->shininess_slider_sensor->attach(&(PRIVATE(this)->slider5->value));
237  PRIVATE(this)->transparency_slider_sensor->attach(&(PRIVATE(this)->slider6->value));
238
239  PRIVATE(this)->button1_sensor = new SoFieldSensor(MaterialEditor::button1_cb, PRIVATE(this));
240  PRIVATE(this)->button2_sensor = new SoFieldSensor(MaterialEditor::button2_cb, PRIVATE(this));
241  PRIVATE(this)->button3_sensor = new SoFieldSensor(MaterialEditor::button3_cb, PRIVATE(this));
242  PRIVATE(this)->button4_sensor = new SoFieldSensor(MaterialEditor::button4_cb, PRIVATE(this));
243  PRIVATE(this)->button1_sensor->attach(&(PRIVATE(this)->button1->on));
244  PRIVATE(this)->button2_sensor->attach(&(PRIVATE(this)->button2->on));
245  PRIVATE(this)->button3_sensor->attach(&(PRIVATE(this)->button3->on));
246  PRIVATE(this)->button4_sensor->attach(&(PRIVATE(this)->button4->on));
247
248  PRIVATE(this)->material_sensor = new SoNodeSensor(MaterialEditor::material_cb, PRIVATE(this));
249  PRIVATE(this)->material_sensor->attach(PRIVATE(this)->material);
250  PRIVATE(this)->material->touch();
251
252  PRIVATE(this)->material_field_sensor = new SoFieldSensor(MaterialEditor::material_field_cb, PRIVATE(this));
253  PRIVATE(this)->material_field_sensor->attach(&(this->material));
254
255  this->setColorEditorCallbacks(MaterialEditor::coloreditoropen_cb, MaterialEditor::coloreditorclose_cb, PRIVATE(this));
256}
257
258SoGuiMaterialEditor::~SoGuiMaterialEditor(void)
259{
260  MaterialEditor * obj = PRIVATE(this);
261  delete obj;
262}
263
264void
265SoGuiMaterialEditor::setColorEditorCallbacks(
266  SoGuiColorEditorOpenCB * open,
267  SoGuiColorEditorCloseCB * close,
268  void * closure)
269{
270  PRIVATE(this)->openeditorcb = open;
271  PRIVATE(this)->closeeditorcb = close;
272  PRIVATE(this)->cbclosure = closure;
273}
274
275SoMaterial *
276SoGuiMaterialEditor::getSphereMaterialNode(void) const
277{
278  return PRIVATE(this)->material;
279}
280
281// *************************************************************************
282// MaterialEditor
283// *************************************************************************
284
285#define PUBLIC(obj) (((MaterialEditor *) obj)->api)
286
287// +--------------------------------------------------------------------+
288// |                   |  o x  Ambient    |======================| 0.00 |
289// |                   |  o x  Diffuse    |======================| 0.00 |
290// |                   |  o x  Specular   |======================| 0.00 |
291// |                   |  o x  Emissive   |======================| 0.00 |
292// |                   |                                                |
293// |                   |       Shininess  |======================| 0.00 |
294// |                   |       Transp     |======================| 0.00 |
295// +--------------------------------------------------------------------+
296//                                                          [nice - Ed]
297
298const char *
299MaterialEditor::texturescene[] =
300{
301  "#Inventor V2.1 ascii",
302  "",
303  "SoGuiSceneTexture2 {",
304  "  scene",
305  "    Separator {",
306  "      OrthographicCamera {",
307  "        position 0 0 2",
308  "        nearDistance 1",
309  "        farDistance 3",
310  "        height 2",
311  "      }",
312  "      LightModel { model BASE_COLOR }",
313  "      BaseColor {",
314  "        rgb [ 0.3 0.3 0.3,  0.6 0.6 0.6,  0.6 0.6 0.6,  0.3 0.3 0.3 ]",
315  "      }",
316  "      MaterialBinding { value PER_FACE }",
317  "      Coordinate3 {",
318  "        point [",
319  "          -3  3  0,  0  3  0,  3  3  0,",
320  "          -3  0  0,  0  0  0,  3  0  0,",
321  "          -3 -3  0,  0 -3  0,  3 -3  0",
322  "        ]",
323  "      }",
324  "      QuadMesh {",
325  "        verticesPerColumn 3",
326  "        verticesPerRow 3",
327  "      }",
328  "      LightModel { model PHONG }",
329  "      DirectionalLight { direction  0.556 -0.623 -0.551 }",
330  "      DirectionalLight { direction -0.556 -0.623 -0.551 }",
331  "      DEF material Material { }",
332  "      Complexity { value 0.8 }",
333  "      ShapeHints { vertexOrdering COUNTERCLOCKWISE shapeType SOLID }",
334  "      Sphere { radius 0.85 }",
335  "    }",
336  "}",
337  NULL
338};
339
340// FIXME: add labels
341// FIXME: adjust geometry
342
343const char *
344MaterialEditor::editorscene[] =
345{
346  "#Inventor V2.1 ascii",
347  "",
348  "DEF pane SoGuiPane {",
349  "  worldSize 1 1 0",
350  "  objectSize 550 300 0",
351  "  SoGuiPosition {",
352  "    position = DEF wm Calculator {",
353  "      A = USE pane.objectSize",
354  "      expression [",
355  "        \"ta = (A[0] / 2 < A[1]) ? (A[0]/2)-20 : A[1]-20\"",
356  "        \"tb = (A[1] - ta) / 2\"",
357  "        \"oA = vec3f(10, tb, 0)\"", // image position
358  "        \"oB = vec3f(ta, ta, 0)\"", // image size
359  "        \"oC = vec3f(ta + 30, A[1] - 25, 0)\"", // radio1 position
360  "        \"oD = vec3f(0, -30, 0)\"", // ratio translation
361  "      ]",
362  "    } . oA",
363  "  }",
364  "  DEF image SoGuiImage { size = USE wm.oB }",
365  "  SoGuiFrame {",
366  "    size = USE image.size",
367  "    design EMBOSS",
368  "    width 2",
369  "    complement TRUE",
370  "  }",
371  "  SoGuiPosition { position = USE wm.oC }",
372  "  DEF rbutton1 SoGuiRadioButton {",
373  "    size 10 10 0",
374  "    on = DEF rbuttons SoGuiRadioGroup {",
375  "      in0 = USE rbutton1.on",
376  "      in1 = DEF rbutton2 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out1 } . on",
377  "      in2 = DEF rbutton3 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out2 } . on",
378  "      in3 = DEF rbutton4 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out3 } . on",
379  "    } . out0",
380  "  }",
381  "  SoGuiFrame {",
382  "    size = USE rbutton1.size",
383  "    width 2",
384  "    complement = USE rbutton1.on",
385  "  }",
386  "  SoGuiTranslation { translation = USE wm.oD }",
387  "  USE rbutton2",
388  "  SoGuiFrame {",
389  "    size = USE rbutton2.size",
390  "    width 2",
391  "    complement = USE rbutton2.on",
392  "  }",
393  "  SoGuiTranslation { translation = USE wm.oD }",
394  "  USE rbutton3",
395  "  SoGuiFrame {",
396  "    size = USE rbutton3.size",
397  "    width 2",
398  "    complement = USE rbutton3.on",
399  "  }",
400  "  SoGuiTranslation { translation = USE wm.oD }",
401  "  USE rbutton4",
402  "  SoGuiFrame {",
403  "    size = USE rbutton4.size",
404  "    width 2",
405  "    complement = USE rbutton4.on",
406  "  }",
407  "  SoGuiPosition {",
408  "    position = DEF wm2 Calculator {",
409  "      A = USE pane.objectSize",
410  "      expression [",
411  "        \"ta = (A[0] / 2 < A[1]) ? (A[0]/2)-20 : A[1]-20\"",
412  "        \"oA = vec3f(ta + 60, A[1] - 25, 0)\"",
413  "        \"oB = vec3f(ta + 90, A[1] - 25, 0)\"",
414  "        \"oC = vec3f(ta - 100, 15, 0)\"",
415  "      ]",
416  "    } . oA",
417  "  }",
418  "  DEF tbutton1 SoGuiToggleButton {",
419  "    size 10 10 0"
420  "    on = USE rbuttons.out0",
421  "  }",
422  "  SoGuiFrame {",
423  "    size = USE tbutton1.size",
424  "    width 2",
425  "    complement = USE tbutton1.on",
426  "    design EMBOSS",
427  "  }",
428  "  SoGuiTranslation { translation = USE wm.oD }",
429  "  DEF tbutton2 SoGuiToggleButton {",
430  "    size 10 10 0"
431  "    on = USE rbuttons.out1",
432  "  }",
433  "  SoGuiFrame {",
434  "    size = USE tbutton2.size",
435  "    width 2",
436  "    complement = USE tbutton2.on",
437  "    design EMBOSS",
438  "  }",
439  "  SoGuiTranslation { translation = USE wm.oD }",
440  "  DEF tbutton3 SoGuiToggleButton {",
441  "    size 10 10 0"
442  "    on = USE rbuttons.out2",
443  "  }",
444  "  SoGuiFrame {",
445  "    size = USE tbutton3.size",
446  "    width 2",
447  "    complement = USE tbutton3.on",
448  "    design EMBOSS",
449  "  }",
450  "  SoGuiTranslation { translation = USE wm.oD }",
451  "  DEF tbutton4 SoGuiToggleButton {",
452  "    size 10 10 0"
453  "    on = USE rbuttons.out3",
454  "  }",
455  "  SoGuiFrame {",
456  "    size = USE tbutton4.size",
457  "    width 2",
458  "    complement = USE tbutton4.on",
459  "    design EMBOSS",
460  "  }",
461
462  "  SoGuiPosition { position = USE wm2.oB }",
463  "  DEF sliderframe SoGuiFrame {",
464  "    size = USE wm2.oC",
465  "    width 2",
466  "    complement TRUE",
467  "    design EMBOSS",
468  "  }",
469  "  DEF slider1 SoGuiSlider1 { size = USE sliderframe.size }",
470  "  SoGuiTranslation { translation = USE wm.oD }",
471  "  USE sliderframe",
472  "  DEF slider2 SoGuiSlider1 { size = USE sliderframe.size }",
473  "  SoGuiTranslation { translation = USE wm.oD }",
474  "  USE sliderframe",
475  "  DEF slider3 SoGuiSlider1 { size = USE sliderframe.size }",
476  "  SoGuiTranslation { translation = USE wm.oD }",
477  "  USE sliderframe",
478  "  DEF slider4 SoGuiSlider1 { size = USE sliderframe.size }",
479  "  SoGuiTranslation { translation = USE wm.oD }",
480  "  SoGuiTranslation { translation = USE wm.oD }",
481  "  USE sliderframe",
482  "  DEF slider5 SoGuiSlider1 { size = USE sliderframe.size }",
483  "  SoGuiTranslation { translation = USE wm.oD }",
484  "  USE sliderframe",
485  "  DEF slider6 SoGuiSlider1 { size = USE sliderframe.size }",
486
487  "  SoGuiPosition { position = USE pane.objectSize }",
488  "  SoGuiTranslation { translation -35 -25 0 }",
489  "  DEF labelframe SoGuiFrame { size 25 15 0 width 2 design EMBOSS complement TRUE }",
490  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider1.value } . output }",
491  "  SoGuiTranslation { translation = USE wm.oD }",
492  "  USE labelframe",
493  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider2.value } . output }",
494  "  SoGuiTranslation { translation = USE wm.oD }",
495  "  USE labelframe",
496  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider3.value } . output }",
497  "  SoGuiTranslation { translation = USE wm.oD }",
498  "  USE labelframe",
499  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider4.value } . output }",
500  "  SoGuiTranslation { translation = USE wm.oD }",
501  "  SoGuiTranslation { translation = USE wm.oD }",
502  "  USE labelframe",
503  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider5.value } . output }",
504  "  SoGuiTranslation { translation = USE wm.oD }",
505  "  USE labelframe",
506  "  SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider6.value } . output }",
507  "}",
508  NULL
509};
510
511MaterialEditor::MaterialEditor(void)
512{
513  this->api = NULL;
514  this->material = NULL;
515  this->button1 = NULL;
516  this->button2 = NULL;
517  this->button3 = NULL;
518  this->button4 = NULL;
519  this->radio1 = NULL;
520  this->radio2 = NULL;
521  this->radio3 = NULL;
522  this->radio4 = NULL;
523  this->slider1 = NULL;
524  this->slider2 = NULL;
525  this->slider3 = NULL;
526  this->slider4 = NULL;
527  this->slider5 = NULL;
528  this->slider6 = NULL;
529  this->ambient_slider_sensor = NULL;
530  this->diffuse_slider_sensor = NULL;
531  this->specular_slider_sensor = NULL;
532  this->emissive_slider_sensor = NULL;
533  this->shininess_slider_sensor = NULL;
534  this->transparency_slider_sensor = NULL;
535  this->coloreditoropen = FALSE;
536  this->coloreditor = NULL;
537  this->coloreditor_sensor = NULL;
538}
539
540MaterialEditor::~MaterialEditor(void)
541{
542  if ( this->coloreditor_sensor ) delete this->coloreditor_sensor;
543}
544
545void
546MaterialEditor::ambient_slider_cb(void * closure, SoSensor * sensor)
547{
548  assert(closure);
549  MaterialEditor * me = (MaterialEditor *) closure;
550  assert(me->material);
551  assert(me->slider1);
552  SbColor ambient = me->material->ambientColor[0];
553  float h, s, v;
554  ambient.getHSVValue(h, s, v);
555  v = me->slider1->value.getValue();
556  ambient.setHSVValue(h, s, v);
557  if ( ambient != me->material->ambientColor[0] )
558    me->material->ambientColor.set1Value(0, ambient);
559}
560
561void
562MaterialEditor::diffuse_slider_cb(void * closure, SoSensor * sensor)
563{
564  assert(closure);
565  MaterialEditor * me = (MaterialEditor *) closure;
566  assert(me->material);
567  assert(me->slider2);
568  SbColor diffuse = me->material->diffuseColor[0];
569  float h, s, v;
570  diffuse.getHSVValue(h, s, v);
571  v = me->slider2->value.getValue();
572  diffuse.setHSVValue(h, s, v);
573  if ( diffuse != me->material->diffuseColor[0] )
574    me->material->diffuseColor.set1Value(0, diffuse);
575}
576
577void
578MaterialEditor::specular_slider_cb(void * closure, SoSensor * sensor)
579{
580  assert(closure);
581  MaterialEditor * me = (MaterialEditor *) closure;
582  assert(me->material);
583  assert(me->slider3);
584  SbColor specular = me->material->specularColor[0];
585  float h, s, v;
586  specular.getHSVValue(h, s, v);
587  v = me->slider3->value.getValue();
588  specular.setHSVValue(h, s, v);
589  if ( specular != me->material->specularColor[0] )
590    me->material->specularColor.set1Value(0, specular);
591}
592
593void
594MaterialEditor::emissive_slider_cb(void * closure, SoSensor * sensor)
595{
596  assert(closure);
597  MaterialEditor * me = (MaterialEditor *) closure;
598  assert(me->material);
599  assert(me->slider4);
600  SbColor emissive = me->material->emissiveColor[0];
601  float h, s, v;
602  emissive.getHSVValue(h, s, v);
603  v = me->slider4->value.getValue();
604  emissive.setHSVValue(h, s, v);
605  if ( emissive != me->material->emissiveColor[0] )
606    me->material->emissiveColor.set1Value(0, emissive);
607}
608
609void
610MaterialEditor::shininess_slider_cb(void * closure, SoSensor * sensor)
611{
612  assert(closure);
613  MaterialEditor * me = (MaterialEditor *) closure;
614  assert(me->material);
615  assert(me->slider5);
616  float shininess = me->slider5->value.getValue();
617  if ( shininess != me->material->shininess[0] )
618    me->material->shininess.set1Value(0, shininess);
619}
620
621void
622MaterialEditor::transparency_slider_cb(void * closure, SoSensor * sensor)
623{
624  assert(closure);
625  MaterialEditor * me = (MaterialEditor *) closure;
626  assert(me->material);
627  assert(me->slider6);
628  float transparency = me->slider6->value.getValue();
629  if ( transparency != me->material->transparency[0] )
630    me->material->transparency.set1Value(0, transparency);
631}
632
633void
634MaterialEditor::checkColorEditorOpenStatus(void)
635{
636  if ( this->button1->on.getValue() ||
637       this->button2->on.getValue() ||
638       this->button3->on.getValue() ||
639       this->button4->on.getValue() ) {
640    if ( !this->coloreditoropen && this->openeditorcb ) {
641      this->coloreditor = this->openeditorcb(this->cbclosure);
642      this->coloreditoropen = TRUE;
643      if ( this->coloreditor_sensor == NULL )
644        this->coloreditor_sensor = new SoFieldSensor(MaterialEditor::coloreditor_cb, this);
645      if ( this->coloreditor )
646        this->coloreditor_sensor->attach(&(this->coloreditor->color));
647    }
648  } else {
649    if ( this->coloreditoropen && this->closeeditorcb ) {
650      if ( this->coloreditor_sensor ) this->coloreditor_sensor->detach();
651      this->closeeditorcb(this->cbclosure, this->coloreditor);
652      this->coloreditor = NULL;
653      this->coloreditoropen = FALSE;
654    }
655  }
656}
657
658void
659MaterialEditor::button1_cb(void * closure, SoSensor * sensor)
660{
661  assert(closure);
662  MaterialEditor * me = (MaterialEditor *) closure;
663  SbBool down = me->button1->on.getValue();
664  if ( !down ) {
665    if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
666
667    if (  me->button2->on.getValue() &&
668         !me->button3->on.getValue() &&
669         !me->button4->on.getValue() &&
670         !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
671    if ( !me->button2->on.getValue() &&
672          me->button3->on.getValue() &&
673         !me->button4->on.getValue() &&
674         !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
675    if ( !me->button2->on.getValue() &&
676         !me->button3->on.getValue() &&
677          me->button4->on.getValue() &&
678         !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
679  } else {
680    if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
681    if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
682    if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
683    if ( !me->button2->on.getValue() &&
684         !me->button3->on.getValue() &&
685         !me->button4->on.getValue() &&
686         !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
687  }
688  me->checkColorEditorOpenStatus();
689}
690
691void
692MaterialEditor::button2_cb(void * closure, SoSensor * sensor)
693{
694  assert(closure);
695  MaterialEditor * me = (MaterialEditor *) closure;
696  SbBool down = me->button2->on.getValue();
697  if ( !down ) {
698    if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
699    if (  me->button1->on.getValue() &&
700         !me->button3->on.getValue() &&
701         !me->button4->on.getValue() &&
702         !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
703    if ( !me->button1->on.getValue() &&
704          me->button3->on.getValue() &&
705         !me->button4->on.getValue() &&
706         !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
707    if ( !me->button1->on.getValue() &&
708         !me->button3->on.getValue() &&
709          me->button4->on.getValue() &&
710         !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
711  } else {
712    if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
713    if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
714    if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
715    if ( !me->button1->on.getValue() &&
716         !me->button3->on.getValue() &&
717         !me->button4->on.getValue() &&
718         !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
719  }
720  me->checkColorEditorOpenStatus();
721}
722
723void
724MaterialEditor::button3_cb(void * closure, SoSensor * sensor)
725{
726  assert(closure);
727  assert(closure);
728  MaterialEditor * me = (MaterialEditor *) closure;
729  SbBool down = me->button3->on.getValue();
730  if ( !down ) {
731    if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
732    if (  me->button1->on.getValue() &&
733         !me->button2->on.getValue() &&
734         !me->button4->on.getValue() &&
735         !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
736    if ( !me->button1->on.getValue() &&
737          me->button2->on.getValue() &&
738         !me->button4->on.getValue() &&
739         !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
740    if ( !me->button1->on.getValue() &&
741         !me->button2->on.getValue() &&
742          me->button4->on.getValue() &&
743         !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
744  } else {
745    if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
746    if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
747    if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
748    if ( !me->button1->on.getValue() &&
749         !me->button2->on.getValue() &&
750         !me->button4->on.getValue() &&
751         !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
752  }
753  me->checkColorEditorOpenStatus();
754}
755
756void
757MaterialEditor::button4_cb(void * closure, SoSensor * sensor)
758{
759  assert(closure);
760  MaterialEditor * me = (MaterialEditor *) closure;
761  SbBool down = me->button4->on.getValue();
762  if ( !down ) {
763    if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
764    if (  me->button1->on.getValue() &&
765         !me->button2->on.getValue() &&
766         !me->button3->on.getValue() &&
767         !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
768    if ( !me->button1->on.getValue() &&
769          me->button2->on.getValue() &&
770         !me->button3->on.getValue() &&
771         !me->radio2->on.getValue()  ) me->radio2->on.setValue(TRUE);
772    if ( !me->button1->on.getValue() &&
773         !me->button2->on.getValue() &&
774          me->button3->on.getValue() &&
775         !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
776  } else {
777    if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
778    if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
779    if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
780    if ( !me->button1->on.getValue() &&
781         !me->button2->on.getValue() &&
782         !me->button3->on.getValue() &&
783         !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
784  }
785  me->checkColorEditorOpenStatus();
786}
787
788void
789MaterialEditor::coloreditor_cb(void * closure, SoSensor * sensor)
790{
791  // coloreditor is being interacted with - so update material editor sliders
792  assert(closure);
793  MaterialEditor * me = (MaterialEditor *) closure;
794  if ( me->button1->on.getValue() )
795    me->material->ambientColor.setValue(me->coloreditor->color.getValue());
796  if ( me->button2->on.getValue() )
797    me->material->diffuseColor.setValue(me->coloreditor->color.getValue());
798  if ( me->button3->on.getValue() )
799    me->material->specularColor.setValue(me->coloreditor->color.getValue());
800  if ( me->button4->on.getValue() )
801    me->material->emissiveColor.setValue(me->coloreditor->color.getValue());
802}
803
804void
805MaterialEditor::material_cb(void * closure, SoSensor * sensor)
806{
807  assert(closure);
808  MaterialEditor * me = (MaterialEditor *) closure;
809  SoMaterial * mat = me->material;
810  if ( !mat ) return;
811  float h, s, v;
812  SbColor color = mat->ambientColor[0];
813  color.getHSVValue(h, s, v);
814  if ( v != me->slider1->value.getValue() ) me->slider1->value.setValue(v);
815  color = mat->diffuseColor[0];
816  color.getHSVValue(h, s, v);
817  if ( v != me->slider2->value.getValue() ) me->slider2->value.setValue(v);
818  color = mat->specularColor[0];
819  color.getHSVValue(h, s, v);
820  if ( v != me->slider3->value.getValue() ) me->slider3->value.setValue(v);
821  color = mat->emissiveColor[0];
822  color.getHSVValue(h, s, v);
823  if ( v != me->slider4->value.getValue() ) me->slider4->value.setValue(v);
824  v = mat->shininess[0];
825  if ( v != me->slider5->value.getValue() ) me->slider5->value.setValue(v);
826  v = mat->transparency[0];
827  if ( v != me->slider6->value.getValue() ) me->slider6->value.setValue(v);
828  SoNode * attachment = PUBLIC(me)->material.getValue();
829  if ( attachment ) {
830    if ( attachment->isOfType(SoMaterial::getClassTypeId()) ) {
831      SoMaterial * material = (SoMaterial *) attachment;
832      int index = PUBLIC(me)->index.getValue();
833      material->ambientColor.set1Value(index, mat->ambientColor[0]);
834      material->diffuseColor.set1Value(index, mat->diffuseColor[0]);
835      material->specularColor.set1Value(index, mat->specularColor[0]);
836      material->emissiveColor.set1Value(index, mat->emissiveColor[0]);
837      material->shininess.set1Value(index, mat->shininess[0]);
838      material->transparency.set1Value(index, mat->transparency[0]);
839#ifdef HAVE_SOVRMLMATERIAL
840    } else if ( attachment->isOfType(SoVRMLMaterial::getClassTypeId()) ) {
841      SoVRMLMaterial * material = (SoVRMLMaterial *) attachment;
842      SbColor ambient = mat->ambientColor[0];
843      float h, s, v;
844      ambient.getHSVValue(h, s, v);
845      material->ambientIntensity.setValue(v);
846      material->diffuseColor.setValue(mat->diffuseColor[0]);
847      material->specularColor.setValue(mat->specularColor[0]);
848      material->emissiveColor.setValue(mat->emissiveColor[0]);
849      material->shininess.setValue(mat->shininess[0]);
850      material->transparency.setValue(mat->transparency[0]);
851#endif // HAVE_SOVRMLMATERIAL
852    } else {
853    }
854  }
855}
856
857void
858MaterialEditor::material_field_cb(void * closure, SoSensor * sensor)
859{
860  assert(closure);
861  MaterialEditor * me = (MaterialEditor *) closure;
862  SoNode * node = PUBLIC(me)->material.getValue();
863  if ( !node ) return;
864  SoMaterial * mat1 = (SoMaterial *) node;
865  SoMaterial * mat2 = me->material;
866
867  if ( mat1->ambientColor[0] != mat2->ambientColor[0] )
868    mat2->ambientColor.set1Value(0, mat1->ambientColor[0]);
869  if ( mat1->diffuseColor[0] != mat2->diffuseColor[0] )
870    mat2->diffuseColor.set1Value(0, mat1->diffuseColor[0]);
871  if ( mat1->specularColor[0] != mat2->specularColor[0] )
872    mat2->specularColor.set1Value(0, mat1->specularColor[0]);
873  if ( mat1->emissiveColor[0] != mat2->emissiveColor[0] )
874    mat2->emissiveColor.set1Value(0, mat1->emissiveColor[0]);
875  if ( mat1->shininess[0] != mat2->shininess[0] )
876    mat2->shininess.set1Value(0, mat1->shininess[0]);
877  if ( mat1->transparency[0] != mat2->transparency[0] )
878    mat2->transparency.set1Value(0, mat1->transparency[0]);
879}
880
881SoGuiColorEditor *
882MaterialEditor::coloreditoropen_cb(void * closure)
883{
884  SoDebugError::postInfo("MaterialEditor::coloreditoropen_cb", "default callback invoked - not implemented yet");
885  return NULL;
886}
887
888void
889MaterialEditor::coloreditorclose_cb(void * closure, SoGuiColorEditor * editor)
890{
891  SoDebugError::postInfo("MaterialEditor::coloreditorclose_cb", "default callback invoked - not implemented yet");
892}
893
894#undef PRIVATE
895#undef PUBLIC
896
897// *************************************************************************
898