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#include <Inventor/SbPList.h> 36#include <Inventor/SoSceneManager.h> 37#include <Inventor/fields/SoSFColor.h> 38#include <Inventor/fields/SoMFColor.h> 39#include <Inventor/fields/SoMFUInt32.h> 40#include <Inventor/nodes/SoSwitch.h> 41#include <Inventor/nodes/SoSeparator.h> 42#include <Inventor/nodes/SoTexture2.h> 43#include <Inventor/sensors/SoFieldSensor.h> 44#include <Inventor/actions/SoGLRenderAction.h> 45 46#include <Inventor/@Gui@/SoAny.h> 47 48#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h> 49#include <Inventor/@Gui@/nodes/SoGuiPane.h> 50#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h> 51#include <Inventor/@Gui@/nodes/SoGuiSlider1.h> 52#include <Inventor/@Gui@/nodes/SoGuiSlider2.h> 53 54#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h> 55#include <assert.h> 56 57/*! 58 \class SoGuiColorEditor Inventor/@Gui@/editors/SoGuiColorEditor.h 59 \brief The SoGuiColorEditor class is a GUI component for interactively 60 editing color fields. 61*/ 62 63/*! 64 \enum SoGuiColorEditor::Sliders 65*/ 66 67/*! 68 \val SoGuiColorEditor::NONE 69*/ 70 71/*! 72 \val SoGuiColorEditor::INTENSITY 73*/ 74 75/*! 76 \val SoGuiColorEditor::RGB 77*/ 78 79/*! 80 \val SoGuiColorEditor::HSV 81*/ 82 83/*! 84 \val SoGuiColorEditor::RGB_V 85*/ 86 87/*! 88 \val SoGuiColorEditor::RGB_HSV 89*/ 90 91/*! 92 \enum SoGuiColorEditor::Update 93*/ 94 95/*! 96 \val SoGuiColorEditor::CONTINUOUS 97*/ 98 99/*! 100 \val SoGuiColorEditor::AFTER_ACCEPT 101*/ 102 103// ************************************************************************* 104 105class ColorEditor { 106public: 107 SoGuiColorEditor * api; 108 109 void colorChange(void); 110 111 SoFieldSensor * color_sensor; 112 static void color_update_cb(void * closure, SoSensor * sensor); 113 114 SoGuiPane * editor; 115 SoGuiClickCounter * switcher; 116 SoGuiSlider1 * slider_r; // red 117 SoGuiSlider1 * slider_g; // green 118 SoGuiSlider1 * slider_b; // blue 119 SoGuiSlider1 * slider_h; // hue 120 SoGuiSlider1 * slider_s; // saturation 121 SoGuiSlider1 * slider_v; // value 122 SoGuiSlider2 * slider_wheel; 123 124 SoFieldSensor * sensor_r; 125 SoFieldSensor * sensor_g; 126 SoFieldSensor * sensor_b; 127 SoFieldSensor * sensor_h; 128 SoFieldSensor * sensor_s; 129 SoFieldSensor * sensor_v; 130 SoFieldSensor * sensor_wheel; 131 132 static void update_r_cb(void * closure, SoSensor * sensor); 133 static void update_g_cb(void * closure, SoSensor * sensor); 134 static void update_b_cb(void * closure, SoSensor * sensor); 135 static void update_h_cb(void * closure, SoSensor * sensor); 136 static void update_s_cb(void * closure, SoSensor * sensor); 137 static void update_v_cb(void * closure, SoSensor * sensor); 138 static void update_wheel_cb(void * closure, SoSensor * sensor); 139 140 static const char * editorscene[]; 141 142 static float calculateHue(float x, float y); 143 static SbVec2f calculateFromHue(float h, float s, float v); 144 145 void generateSliderTextureR(const SbColor & current, SbBool wysiwyg); 146 void generateSliderTextureG(const SbColor & current, SbBool wysiwyg); 147 void generateSliderTextureB(const SbColor & current, SbBool wysiwyg); 148 void generateSliderTextureH(const SbColor & current, SbBool wysiwyg); 149 void generateSliderTextureS(const SbColor & current, SbBool wysiwyg); 150 void generateSliderTextureV(const SbColor & current, SbBool wysiwyg); 151 void generateSliderTextureHSV(const SbColor & current, SbBool wysiwyg); 152}; 153 154// ************************************************************************* 155 156#define PRIVATE(obj) ((ColorEditor *) ((SoGuiColorEditor *) obj)->internals) 157#define PUBLIC(obj) (((ColorEditor *) obj)->api) 158 159void 160SoGuiColorEditor::initClass(void) 161{ 162 SO_KIT_INIT_CLASS(SoGuiColorEditor, SoBaseKit, "BaseKit"); 163} 164 165SO_KIT_SOURCE(SoGuiColorEditor); 166 167SoGuiColorEditor::SoGuiColorEditor(void) 168{ 169 this->internals = (void *) new ColorEditor; 170 PRIVATE(this)->api = this; 171 172 SO_KIT_CONSTRUCTOR(SoGuiColorEditor); 173 174 SO_KIT_ADD_FIELD(wysiwyg, (FALSE)); 175 SO_KIT_ADD_FIELD(color, (SbColor(0.0f, 0.0f, 0.0f))); 176 SO_KIT_ADD_FIELD(sliders, (SoGuiColorEditor::RGB_V)); 177 SO_KIT_ADD_FIELD(update, (SoGuiColorEditor::AFTER_ACCEPT)); 178 179 SO_KIT_DEFINE_ENUM_VALUE(Sliders, NONE); 180 SO_KIT_DEFINE_ENUM_VALUE(Sliders, INTENSITY); 181 SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB); 182 SO_KIT_DEFINE_ENUM_VALUE(Sliders, HSV); 183 SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB_V); 184 SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB_HSV); 185 186 SO_KIT_DEFINE_ENUM_VALUE(Update, CONTINUOUS); 187 SO_KIT_DEFINE_ENUM_VALUE(Update, AFTER_ACCEPT); 188 189 SO_KIT_SET_SF_ENUM_TYPE(sliders, Sliders); 190 SO_KIT_SET_SF_ENUM_TYPE(update, Update); 191 192 SO_KIT_ADD_CATALOG_ENTRY(root, SoGuiPane, TRUE, this, "", FALSE); 193 194 SO_KIT_INIT_INSTANCE(); 195 196 PRIVATE(this)->switcher = NULL; 197 PRIVATE(this)->sensor_r = NULL; 198 PRIVATE(this)->sensor_g = NULL; 199 PRIVATE(this)->sensor_b = NULL; 200 PRIVATE(this)->sensor_h = NULL; 201 PRIVATE(this)->sensor_s = NULL; 202 PRIVATE(this)->sensor_v = NULL; 203 PRIVATE(this)->sensor_wheel = NULL; 204 205 PRIVATE(this)->editor = NULL; 206 207 SoNode * scene = SoAny::loadSceneGraph(ColorEditor::editorscene); 208 assert(scene != NULL); 209 assert(scene->isOfType(SoGuiPane::getClassTypeId())); 210 211 PRIVATE(this)->editor = (SoGuiPane *) scene; 212 PRIVATE(this)->editor->ref(); 213 PRIVATE(this)->switcher = (SoGuiClickCounter *) SoAny::scanSceneForName(PRIVATE(this)->editor, "switcher"); 214 PRIVATE(this)->slider_r = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_r", TRUE); 215 PRIVATE(this)->slider_g = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_g", TRUE); 216 PRIVATE(this)->slider_b = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_b", TRUE); 217 PRIVATE(this)->slider_h = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_h", TRUE); 218 PRIVATE(this)->slider_s = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_s", TRUE); 219 PRIVATE(this)->slider_v = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_v", TRUE); 220 PRIVATE(this)->slider_wheel = (SoGuiSlider2 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "colorwheel", TRUE); 221 if ( PRIVATE(this)->slider_r ) { 222 PRIVATE(this)->slider_r->ref(); 223 PRIVATE(this)->sensor_r = new SoFieldSensor(ColorEditor::update_r_cb, PRIVATE(this)); 224 PRIVATE(this)->sensor_r->attach(&(PRIVATE(this)->slider_r->value)); 225 PRIVATE(this)->generateSliderTextureR(this->color.getValue(), FALSE); 226 } 227 if ( PRIVATE(this)->slider_g ) { 228 PRIVATE(this)->slider_g->ref(); 229 PRIVATE(this)->sensor_g = new SoFieldSensor(ColorEditor::update_g_cb, PRIVATE(this)); 230 PRIVATE(this)->sensor_g->attach(&(PRIVATE(this)->slider_g->value)); 231 PRIVATE(this)->generateSliderTextureG(this->color.getValue(), FALSE); 232 } 233 if ( PRIVATE(this)->slider_b ) { 234 PRIVATE(this)->slider_b->ref(); 235 PRIVATE(this)->sensor_b = new SoFieldSensor(ColorEditor::update_b_cb, PRIVATE(this)); 236 PRIVATE(this)->sensor_b->attach(&(PRIVATE(this)->slider_b->value)); 237 PRIVATE(this)->generateSliderTextureB(this->color.getValue(), FALSE); 238 } 239 if ( PRIVATE(this)->slider_h ) { 240 PRIVATE(this)->slider_h->ref(); 241 PRIVATE(this)->sensor_h = new SoFieldSensor(ColorEditor::update_h_cb, PRIVATE(this)); 242 PRIVATE(this)->sensor_h->attach(&(PRIVATE(this)->slider_h->value)); 243 PRIVATE(this)->generateSliderTextureH(this->color.getValue(), FALSE); 244 } 245 if ( PRIVATE(this)->slider_s ) { 246 PRIVATE(this)->slider_s->ref(); 247 PRIVATE(this)->sensor_s = new SoFieldSensor(ColorEditor::update_s_cb, PRIVATE(this)); 248 PRIVATE(this)->sensor_s->attach(&(PRIVATE(this)->slider_s->value)); 249 PRIVATE(this)->generateSliderTextureS(this->color.getValue(), FALSE); 250 251 } 252 if ( PRIVATE(this)->slider_v ) { 253 PRIVATE(this)->slider_v->ref(); 254 PRIVATE(this)->sensor_v = new SoFieldSensor(ColorEditor::update_v_cb, PRIVATE(this)); 255 PRIVATE(this)->sensor_v->attach(&(PRIVATE(this)->slider_v->value)); 256 PRIVATE(this)->generateSliderTextureV(this->color.getValue(), FALSE); 257 } 258 if ( PRIVATE(this)->slider_wheel ) { 259 PRIVATE(this)->slider_wheel->ref(); 260 PRIVATE(this)->sensor_wheel = new SoFieldSensor(ColorEditor::update_wheel_cb, PRIVATE(this)); 261 PRIVATE(this)->sensor_wheel->attach(&(PRIVATE(this)->slider_wheel->value)); 262 PRIVATE(this)->generateSliderTextureHSV(this->color.getValue(), FALSE); 263 } 264 265 PRIVATE(this)->editor->unrefNoDelete(); 266 this->setAnyPart("root", scene); 267 268 PRIVATE(this)->color_sensor = new SoFieldSensor(ColorEditor::color_update_cb, PRIVATE(this)); 269 PRIVATE(this)->color_sensor->attach(&(this->color)); 270 271 // SoGuiViewportFix * viewportfix = (SoGuiViewportFix *) SoAny::scanSceneForName(inherited::getSceneGraph(), "viewportfix", FALSE); 272 // assert(viewportfix != NULL); 273 // PRIVATE(this)->editor->objectSize.connectFrom(&(viewportfix->viewportSize)); 274} 275 276SoGuiColorEditor::~SoGuiColorEditor(void) 277{ 278 ColorEditor * instance = PRIVATE(this); 279 delete instance; 280} 281 282// ************************************************************************* 283 284// CAT_MOD BEGIN 285const char * 286ColorEditor::editorscene[] = { 287 "#Inventor V2.1 ascii", 288 "DEF pane SoGuiPane {", 289 " worldSize 1 1 0", 290 " objectSize 400 340 0", 291 // Calculate positions 292 " SoGuiPosition {", 293 " position = DEF windowgeometry Calculator {", 294 " A = USE pane.objectSize", 295 " B 120 120 0", // colorwheel size 296 " C 140 30 0", // clickcounter size 297 " a 2", // width of frame 298 " expression [", 299 " \"oA = vec3f(a, A[1] - C[1] - a, 0)\"", // clickcounter pos 300 " \"oB = vec3f(A[0] - B[0] - a, A[1] - B[1] - a, 0)\"", // colorwheel pos 301 " ]", 302 " }.oA", 303 " }", 304 // Create a click counter 305 " DEF switcher SoGuiClickCounter {", 306 " size = USE windowgeometry.C", 307 " first 2 # the INTENSITY sliders", 308 " last 6 # the RGB_HSV sliders", 309 " value 5 # start with the RGB_V group", 310 " }", 311 // Create a frame around the click counter area 312 " SoGuiFrame {", 313 " size = USE windowgeometry.C", 314 " width 2", 315 " design EMBOSS", 316 " }", 317 // Create labels for the click counter 318 " Separator {", 319 " Scale {", 320 " scaleFactor 2 2 2", 321 " }", 322 " DEF sliderlabel SoGuiLabel {", 323 " which = USE switcher.value", 324 " text [", 325 " \"?\"", 326 " \"NONE\"", 327 " \"VALUE\"", 328 " \"RGB\"", 329 " \"HSV\"", 330 " \"RGBV\"", 331 " \"RGBHSV\"", 332 " ]", 333 " }", 334 " }", 335 // Create a frame around the color wheel 336 " SoGuiPosition { position = USE windowgeometry.oB }", 337 " SoGuiFrame {", 338 " size = USE windowgeometry.B", 339 " design EMBOSS", 340 " width 2", 341 " complement TRUE", 342 " }", 343 // Create the color wheel 344 " DEF colorwheel SoGuiSlider2 {", 345 " size = USE windowgeometry.B", 346 " }", 347 // Position the sliders 348 " SoGuiPosition {", 349 " position = DEF slidergeometry Calculator {", 350 " A = USE pane.objectSize", 351 " B = USE windowgeometry.B", // color wheel size 352 " a = USE windowgeometry.a", // width of frame 353 " b 10", // space 354 " c 30", // width of text 355 " expression [", 356 " \"ta = (A[1] - (2*a + B[1]) - 7*b) / 6\"", // slider height 357 " \"tb = A[0] - 2*b - c\"", // slider width 358 " \"oA = vec3f(tb, ta, 0)\"", // slider size 359 " \"oB = vec3f(c+b , b, 0)\"", // slider pos 360 " \"oC = vec3f(0, ta + b, 0)\"", // slider translation 361 " \"oD = vec3f(-c, 0, 0)\"", // slider label translation 362 " ]", 363 " }.oB", 364 " }", 365 // Create the sliders depending on the click count value 366 " Switch {", 367 " whichChild = USE switcher.value", 368 " Group {", // never to be rendered... 369 " DEF slider_r SoGuiSlider1 { size = USE slidergeometry.oA }", 370 " DEF slider_g SoGuiSlider1 { size = USE slidergeometry.oA }", 371 " DEF slider_b SoGuiSlider1 { size = USE slidergeometry.oA }", 372 " DEF slider_h SoGuiSlider1 { size = USE slidergeometry.oA }", 373 " DEF slider_s SoGuiSlider1 { size = USE slidergeometry.oA }", 374 " DEF slider_v SoGuiSlider1 { size = USE slidergeometry.oA }", 375 " DEF slider_translation SoGuiTranslation { translation = USE slidergeometry.oC }", 376 " DEF slider_frame SoGuiFrame {", 377 " size = USE slidergeometry.oA ", 378 " design EMBOSS", 379 " width 2", 380 " complement TRUE", 381 " }", 382 " DEF label_translation SoGuiTranslation { translation = USE slidergeometry.oD }", 383 " DEF label_scale Scale { scaleFactor 2 2 2 }", 384 " DEF label_r Separator {", 385 " USE label_translation", 386 " USE label_scale", 387 " SoGuiLabel { text \"R\" }", 388 " }", 389 " DEF label_g Separator {", 390 " USE label_translation", 391 " USE label_scale", 392 " SoGuiLabel { text \"G\" }", 393 " }", 394 " DEF label_b Separator {", 395 " USE label_translation", 396 " USE label_scale", 397 " SoGuiLabel { text \"B\" }", 398 " }", 399 " DEF label_h Separator {", 400 " USE label_translation", 401 " USE label_scale", 402 " SoGuiLabel { text \"H\" }", 403 " }", 404 " DEF label_s Separator {", 405 " USE label_translation", 406 " USE label_scale", 407 " SoGuiLabel { text \"S\" }", 408 " }", 409 " DEF label_v Separator {", 410 " USE label_translation", 411 " USE label_scale", 412 " SoGuiLabel { text \"V\" }", 413 " }", 414 " }", 415 " DEF sliders_NONE Group {", // in case we search for names once, instead of indexing 416 " }", // children directly inside setCurrentSliders() 417 " DEF sliders_INTENSITY Group {", 418 " USE slider_frame", // frames before sliders - the knobs must paint over frames 419 " USE slider_v", 420 " USE label_v", 421 " }", 422 " DEF sliders_RGB Group {", 423 " USE slider_frame", 424 " USE slider_b", 425 " USE label_b", 426 " USE slider_translation", 427 " USE slider_frame", 428 " USE slider_g", 429 " USE label_g", 430 " USE slider_translation", 431 " USE slider_frame", 432 " USE slider_r", 433 " USE label_r", 434 " }", 435 " DEF sliders_HSV Group {", 436 " USE slider_frame", 437 " USE slider_v", 438 " USE label_v", 439 " USE slider_translation", 440 " USE slider_frame", 441 " USE slider_s", 442 " USE label_s", 443 " USE slider_translation", 444 " USE slider_frame", 445 " USE slider_h", 446 " USE label_h", 447 " }", 448 " DEF sliders_RGB_V Group {", 449 " USE sliders_INTENSITY", 450 " USE slider_translation", 451 " USE sliders_RGB", 452 " }", 453 " DEF sliders_RGB_HSV Group {", 454 " USE sliders_HSV", 455 " USE slider_translation", 456 " USE sliders_RGB", 457 " }", 458 " } # Switch", 459 "} # Pane pane", 460 NULL 461}; 462// CAT_MOD END 463 464// ************************************************************************* 465 466void 467ColorEditor::colorChange(void) 468{ 469 float r = 0.0f, g = 0.0f, b = 0.0f, h = 0.0f, s = 0.0f, v = 0.0f; 470 SbColor color(PUBLIC(this)->color.getValue()); 471 color.getValue(r, g, b); 472 color.getHSVValue(h, s, v); 473 474 SbVec2f wheel(this->calculateFromHue(h, s, v)); 475 476 this->sensor_r->detach(); 477 this->sensor_g->detach(); 478 this->sensor_b->detach(); 479 this->sensor_h->detach(); 480 this->sensor_s->detach(); 481 this->sensor_v->detach(); 482 this->sensor_wheel->detach(); 483 484 if ( r != this->slider_r->value.getValue() ) this->slider_r->value.setValue(r); 485 if ( g != this->slider_g->value.getValue() ) this->slider_g->value.setValue(g); 486 if ( b != this->slider_b->value.getValue() ) this->slider_b->value.setValue(b); 487 if ( h != this->slider_h->value.getValue() ) this->slider_h->value.setValue(h); 488 if ( s != this->slider_s->value.getValue() ) this->slider_s->value.setValue(s); 489 if ( v != this->slider_v->value.getValue() ) this->slider_v->value.setValue(v); 490 if ( wheel != this->slider_wheel->value.getValue() ) this->slider_wheel->value.setValue(wheel); 491 492 assert(PUBLIC(this) != NULL); 493 if ( PUBLIC(this)->wysiwyg.getValue() ) { 494 this->generateSliderTextureR(color, TRUE); 495 this->generateSliderTextureG(color, TRUE); 496 this->generateSliderTextureB(color, TRUE); 497 this->generateSliderTextureH(color, TRUE); 498 this->generateSliderTextureS(color, TRUE); 499 this->generateSliderTextureV(color, TRUE); 500 this->generateSliderTextureHSV(color, TRUE); 501 } 502 503 this->sensor_r->attach(&(this->slider_r->value)); 504 this->sensor_g->attach(&(this->slider_g->value)); 505 this->sensor_b->attach(&(this->slider_b->value)); 506 this->sensor_h->attach(&(this->slider_h->value)); 507 this->sensor_s->attach(&(this->slider_s->value)); 508 this->sensor_v->attach(&(this->slider_v->value)); 509 this->sensor_wheel->attach(&(this->slider_wheel->value)); 510} 511 512void 513ColorEditor::color_update_cb(void * closure, SoSensor * sensor) 514{ 515 assert(closure != NULL); 516 ColorEditor * me = (ColorEditor *) closure; 517 me->colorChange(); 518} 519 520// ************************************************************************* 521 522void 523ColorEditor::update_r_cb(void * closure, SoSensor * sensor) 524{ 525 ColorEditor * me = (ColorEditor *) closure; 526 float r, g, b; 527 SbColor color = PUBLIC(me)->color.getValue(); 528 color.getValue(r, g, b); 529 r = me->slider_r->value.getValue(); 530 color.setValue(r, g, b); 531 PUBLIC(me)->color.setValue(color); 532} 533 534void 535ColorEditor::update_g_cb(void * closure, SoSensor * sensor) 536{ 537 ColorEditor * me = (ColorEditor *) closure; 538 float r, g, b; 539 SbColor color = PUBLIC(me)->color.getValue(); 540 color.getValue(r, g, b); 541 g = me->slider_g->value.getValue(); 542 color.setValue(r, g, b); 543 PUBLIC(me)->color.setValue(color); 544} 545 546void 547ColorEditor::update_b_cb(void * closure, SoSensor * sensor) 548{ 549 ColorEditor * me = (ColorEditor *) closure; 550 float r, g, b; 551 SbColor color = PUBLIC(me)->color.getValue(); 552 color.getValue(r, g, b); 553 b = me->slider_b->value.getValue(); 554 color.setValue(r, g, b); 555 PUBLIC(me)->color.setValue(color); 556} 557 558void 559ColorEditor::update_h_cb(void * closure, SoSensor * sensor) 560{ 561 ColorEditor * me = (ColorEditor *) closure; 562 float h, s, v; 563 SbColor color = PUBLIC(me)->color.getValue(); 564 color.getHSVValue(h, s, v); 565 h = me->slider_h->value.getValue(); 566 color.setHSVValue(h, s, v); 567 PUBLIC(me)->color.setValue(color); 568} 569 570void 571ColorEditor::update_s_cb(void * closure, SoSensor * sensor) 572{ 573 ColorEditor * me = (ColorEditor *) closure; 574 float h, s, v; 575 SbColor color = PUBLIC(me)->color.getValue(); 576 color.getHSVValue(h, s, v); 577 s = me->slider_s->value.getValue(); 578 color.setHSVValue(h, s, v); 579 PUBLIC(me)->color.setValue(color); 580} 581 582void 583ColorEditor::update_v_cb(void * closure, SoSensor * sensor) 584{ 585 ColorEditor * me = (ColorEditor *) closure; 586 float h, s, v; 587 SbColor color = PUBLIC(me)->color.getValue(); 588 color.getHSVValue(h, s, v); 589 v = me->slider_v->value.getValue(); 590 color.setHSVValue(h, s, v); 591 PUBLIC(me)->color.setValue(color); 592} 593 594void 595ColorEditor::update_wheel_cb(void * closure, SoSensor * sensor) 596{ 597 ColorEditor * me = (ColorEditor *) closure; 598 SbVec2f value = me->slider_wheel->value.getValue(); 599 value = value * 2.0f - SbVec2f(1.0f, 1.0f); 600 if ( value.length() > 1.0f ) { 601 value.normalize(); 602 SbVec2f reverse = (value + SbVec2f(1.0f, 1.0f)) / 2.0f; 603 me->slider_wheel->value.setValue(reverse); 604 } 605 float h; 606 if ( value[0] == 0.0f ) h = ((value[1] < 0.0f) ? 3.0f : 1.0f) * float(M_PI) / 2.0f; 607 else h = (float) atan(value[1] / value[0]); 608 if ( value[0] < 0.0f ) h += float(M_PI); 609 if ( h < 0.0f ) h += (2.0f * float(M_PI)); 610 h /= 2.0f * float(M_PI); 611 float s = So@Gui@Min(value.length(), 1.0f); // float precision bugfix 612 613 float a = 0.0f, b = 0.0f, v = 1.0f; 614 SbColor existing = PUBLIC(me)->color.getValue(); 615 existing.getHSVValue(a, b, v); 616 617 SbColor color; 618 color.setHSVValue(h, s, v); 619 PUBLIC(me)->color.setValue(color); 620} 621 622// ************************************************************************* 623 624float 625ColorEditor::calculateHue(float x, float y) 626{ 627 float hue; 628 if ( x == 0.0f ) hue = ((y < 0.0f) ? 3.0f : 1.0f) * float(M_PI) / 2.0f; 629 else hue = (float) atan(y / x); 630 if ( x < 0.0f ) hue += float(M_PI); 631 if ( hue < 0.0f ) hue += (2.0f * float(M_PI)); 632 return hue / (2.0f * float(M_PI)); 633} 634 635SbVec2f 636ColorEditor::calculateFromHue(float h, float s, float v) 637{ 638 float hue = h * 2.0f * float(M_PI); 639 return SbVec2f(((float) cos(hue) * s + 1.0f) / 2.0f, ((float) sin(hue) * s + 1.0f) / 2.0f); 640} 641 642// ************************************************************************* 643 644void 645ColorEditor::generateSliderTextureR(const SbColor & current, SbBool wysiwyg) 646{ 647 assert(this->slider_r != NULL); 648 float red, green, blue; 649 current.getValue(red, green, blue); 650 if ( ! wysiwyg ) { 651 green = blue = 0.0f; 652 } 653 SoTexture2 * texture = SO_GET_PART(this->slider_r, "surfaceTexture", SoTexture2); 654 assert(texture); 655 texture->wrapS.setValue(SoTexture2::CLAMP); 656 texture->wrapT.setValue(SoTexture2::CLAMP); 657 SbVec2s size(256, 1); 658 int nc = 3; 659 texture->image.setValue(size, nc, NULL); 660 texture->model.setValue(SoTexture2::DECAL); 661 unsigned char * bytes = texture->image.startEditing(size, nc); 662 int x, y; 663 for ( x = 0; x < size[0]; x++ ) { 664 red = (float) x / (float) (size[0] - 1); 665 for ( y = 0; y < size[1]; y++ ) { 666 bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f); 667 bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f); 668 bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f); 669 // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255; 670 } 671 } 672 texture->image.finishEditing(); 673} 674 675void 676ColorEditor::generateSliderTextureG(const SbColor & current, SbBool wysiwyg) 677{ 678 assert(this->slider_g != NULL); 679 float red, green, blue; 680 current.getValue(red, green, blue); 681 if ( ! wysiwyg ) { 682 red = blue = 0.0f; 683 } 684 SoTexture2 * texture = SO_GET_PART(this->slider_g, "surfaceTexture", SoTexture2); 685 assert(texture); 686 texture->wrapS.setValue(SoTexture2::CLAMP); 687 texture->wrapT.setValue(SoTexture2::CLAMP); 688 SbVec2s size(256, 1); 689 int nc = 3; 690 texture->image.setValue(size, nc, NULL); 691 texture->model.setValue(SoTexture2::DECAL); 692 unsigned char * bytes = texture->image.startEditing(size, nc); 693 int x, y; 694 for ( x = 0; x < size[0]; x++ ) { 695 green = (float) x / (float) (size[0] - 1); 696 for ( y = 0; y < size[1]; y++ ) { 697 bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f); 698 bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f); 699 bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f); 700 // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255; 701 } 702 } 703 texture->image.finishEditing(); 704} 705 706void 707ColorEditor::generateSliderTextureB(const SbColor & current, SbBool wysiwyg) 708{ 709 assert(this->slider_b != NULL); 710 float red, green, blue; 711 current.getValue(red, green, blue); 712 if ( ! wysiwyg ) { 713 red = green = 0.0f; 714 } 715 SoTexture2 * texture = SO_GET_PART(this->slider_b, "surfaceTexture", SoTexture2); 716 assert(texture); 717 texture->wrapS.setValue(SoTexture2::CLAMP); 718 texture->wrapT.setValue(SoTexture2::CLAMP); 719 SbVec2s size(256, 1); 720 int nc = 3; 721 texture->image.setValue(size, nc, NULL); 722 texture->model.setValue(SoTexture2::DECAL); 723 unsigned char * bytes = texture->image.startEditing(size, nc); 724 int x, y; 725 for ( x = 0; x < size[0]; x++ ) { 726 blue = (float) x / (float) (size[0] - 1); 727 for ( y = 0; y < size[1]; y++ ) { 728 bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f); 729 bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f); 730 bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f); 731 // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255; 732 } 733 } 734 texture->image.finishEditing(); 735} 736 737void 738ColorEditor::generateSliderTextureH(const SbColor & current, SbBool wysiwyg) 739{ 740 assert(this->slider_h != NULL); 741 float hue, saturation, value; 742 current.getHSVValue(hue, saturation, value); 743 if ( ! wysiwyg ) { 744 saturation = 1.0f; 745 value = 1.0f; 746 } 747 SoTexture2 * texture = SO_GET_PART(this->slider_h, "surfaceTexture", SoTexture2); 748 assert(texture); 749 texture->wrapS.setValue(SoTexture2::CLAMP); 750 texture->wrapT.setValue(SoTexture2::CLAMP); 751 SbVec2s size(256, 1); 752 int nc = 3; 753 texture->image.setValue(size, nc, NULL); 754 texture->model.setValue(SoTexture2::DECAL); 755 unsigned char * bytes = texture->image.startEditing(size, nc); 756 int x, y; 757 for ( x = 0; x < size[0]; x++ ) { 758 const float hue = (float) x / (float) (size[0] - 1); 759 for ( y = 0; y < size[1]; y++ ) { 760 float r = 0.0f, g = 0.0f, b = 0.0f; 761 SbColor color(r, g, b); 762 color.setHSVValue(hue, saturation, value); 763 color.getValue(r, g, b); 764 bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f); 765 bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f); 766 bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f); 767 // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255; 768 } 769 } 770 texture->image.finishEditing(); 771} 772 773void 774ColorEditor::generateSliderTextureS(const SbColor & current, SbBool wysiwyg) 775{ 776 assert(this->slider_s != NULL); 777 float hue, saturation, value; 778 current.getHSVValue(hue, saturation, value); 779 if ( ! wysiwyg ) { 780 hue = 0.0f; 781 value = 1.0f; 782 } 783 SoTexture2 * texture = SO_GET_PART(this->slider_s, "surfaceTexture", SoTexture2); 784 assert(texture); 785 texture->wrapS.setValue(SoTexture2::CLAMP); 786 texture->wrapT.setValue(SoTexture2::CLAMP); 787 SbVec2s size(256, 1); 788 int nc = 3; 789 texture->image.setValue(size, nc, NULL); 790 texture->model.setValue(SoTexture2::DECAL); 791 unsigned char * bytes = texture->image.startEditing(size, nc); 792 int x, y; 793 for ( x = 0; x < size[0]; x++ ) { 794 const float saturation = (float) x / (float) (size[0] - 1); 795 for ( y = 0; y < size[1]; y++ ) { 796 float r = 0.0f, g = 0.0f, b = 0.0f; 797 SbColor color(r, g, b); 798 color.setHSVValue(hue, saturation, value); 799 color.getValue(r, g, b); 800 bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f); 801 bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f); 802 bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f); 803 // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255; 804 } 805 } 806 texture->image.finishEditing(); 807} 808 809void 810ColorEditor::generateSliderTextureV(const SbColor & current, SbBool wysiwyg) 811{ 812 assert(this->slider_v != NULL); 813 float hue, saturation, value; 814 current.getHSVValue(hue, saturation, value); 815 if ( ! wysiwyg ) { 816 hue = 0.0f; 817 saturation = 1.0f; 818 } 819 SoTexture2 * texture = SO_GET_PART(this->slider_v, "surfaceTexture", SoTexture2); 820 assert(texture); 821 texture->wrapS.setValue(SoTexture2::CLAMP); 822 texture->wrapT.setValue(SoTexture2::CLAMP); 823 SbVec2s size(256, 1); 824 int nc = 3; 825 texture->image.setValue(size, nc, NULL); 826 texture->model.setValue(SoTexture2::DECAL); 827 unsigned char * bytes = texture->image.startEditing(size, nc); 828 int x, y; 829 for ( x = 0; x < size[0]; x++ ) { 830 const float value = (float) x / (float) (size[0] - 1); 831 for ( y = 0; y < size[1]; y++ ) { 832 float r = 0.0f, g = 0.0f, b = 0.0f; 833 SbColor color(r, g, b); 834 color.setHSVValue(hue, saturation, value); 835 color.getValue(r, g, b); 836 bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f); 837 bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f); 838 bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f); 839 // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255; 840 } 841 } 842 texture->image.finishEditing(); 843} 844 845void 846ColorEditor::generateSliderTextureHSV(const SbColor & current, SbBool wysiwyg) 847{ 848 assert(this->slider_wheel != NULL); 849 float hue, saturation, value; 850 current.getHSVValue(hue, saturation, value); 851 if ( ! wysiwyg ) { 852 value = 1.0f; 853 } 854 855 SoTexture2 * texture = SO_GET_PART(this->slider_wheel, "surfaceTexture", SoTexture2); 856 assert(texture); 857 texture->wrapS.setValue(SoTexture2::CLAMP); 858 texture->wrapT.setValue(SoTexture2::CLAMP); 859 SbVec2s size(256, 256); 860 int nc = 3; 861 texture->image.setValue(size, nc, NULL); 862 texture->model.setValue(SoTexture2::DECAL); 863 unsigned char * bytes = texture->image.startEditing(size, nc); 864 int x, y; 865 const float halfx = (float) size[0] / 2.0f; 866 const float halfy = (float) size[1] / 2.0f; 867 for ( y = 0; y < size[1]; y++ ) { 868 const float ypos = ((float) y - halfy) / halfy; 869 for ( x = 0; x < size[0]; x++ ) { 870 const float xpos = ((float) x - halfx) / halfx; 871 const float saturation = (float) sqrt(xpos * xpos + ypos * ypos); 872 float hue = ColorEditor::calculateHue(xpos, ypos); 873 float red = 0.0f, green = 0.0f, blue = 0.0f; 874 SbColor color(red, green, blue); 875 if ( saturation <= 1.0f ) color.setHSVValue(hue, saturation, value); 876 color.getValue(red, green, blue); 877 bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f); 878 bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f); 879 bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f); 880 // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255; 881 } 882 } 883 texture->image.finishEditing(); 884} 885 886// ************************************************************************* 887 888#undef PUBLIC 889#undef PRIVATE 890 891