Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 // Open Inventor Xt Extended Viewer - 30 Oct 2012 28 // Rastislav Ondrasek, Pierre-Luc Gagnon, Frederick Jones TRIUMF 29 30 #include <stdio.h> 31 #include <string.h> 32 #include <string> 33 #include <sstream> 34 #include <cmath> 35 #include <iostream> 36 #include <iomanip> 37 #include <cstdio> 38 #include <algorithm> // For using sort on a vector 39 #include <X11/keysym.h> 40 41 #include <Xm/Xm.h> 42 #include <Xm/Text.h> 43 #include <Xm/List.h> 44 #include <Xm/MessageB.h> 45 #include <Xm/PushB.h> 46 #include <Xm/ToggleB.h> 47 #include <Xm/CascadeB.h> 48 #include <Xm/ArrowBG.h> 49 #include <Xm/Form.h> 50 #include <Xm/RowColumn.h> 51 #include <Xm/FileSB.h> 52 #include <Xm/SelectioB.h> 53 #include <Xm/Protocols.h> 54 #include <Xm/SeparatoG.h> 55 #include <Xm/DialogS.h> 56 #include <Xm/PanedW.h> 57 #include <Xm/LabelG.h> 58 #include <Xm/Scale.h> 59 #include <Xm/DrawingA.h> 60 61 #include <Inventor/Xt/SoXt.h> 62 //#include <Inventor/Xt/SoXtInternal.h> 63 #include <Inventor/Xt/SoXtCursor.h> 64 #include <Inventor/events/SoKeyboardEvent.h> 65 #include <Inventor/events/SoMouseButtonEvent.h> 66 #include <Inventor/events/SoLocation2Event.h> 67 #include <Inventor/nodes/SoSeparator.h> 68 #include <Inventor/nodes/SoOrthographicCamera.h> 69 #include <Inventor/nodes/SoPerspectiveCamera.h> 70 // FWJ moved to header file 71 //#include <Inventor/nodes/SoEventCallback.h> 72 #include <Inventor/nodes/SoLineSet.h> 73 #include <Inventor/nodes/SoMaterial.h> 74 #include <Inventor/errors/SoDebugError.h> 75 #include <Inventor/SoPickedPoint.h> 76 #include <Inventor/actions/SoWriteAction.h> 77 78 #include "G4OpenInventorXtExaminerViewer.hh" 79 #include "wheelmouse.h" // To use mouse scrolling in dialogs 80 #include "SoXtInternal.h" 81 #include <Inventor/sensors/SoTimerSensor.h> // Animation 82 #include <Inventor/sensors/SoNodeSensor.h> // Detect start of run 83 #include "saveViewPt.h" 84 #include "pickext.h" 85 #include "pickref.h" 86 #include "wireframe.h" 87 //#include "console.h" 88 //#include "favorites.h" 89 90 #include "Geant4_SoPolyhedron.h" 91 //#include "G4RunManager.hh" 92 //#include "G4Run.hh" 93 #include "G4TrajectoryPoint.hh" 94 #include "G4AttHolder.hh" 95 #include "G4AttCheck.hh" 96 97 #include <Inventor/nodes/SoCallback.h> 98 #include <Inventor/nodes/SoSwitch.h> 99 #include <Inventor/nodes/SoScale.h> 100 #include <Inventor/nodes/SoTranslation.h> 101 #include <Inventor/actions/SoSearchAction.h> 102 #include <Inventor/actions/SoGetBoundingBoxAction.h> 103 104 #include <Inventor/nodes/SoCoordinate3.h> 105 // For rendering distance during animation: 106 #include <Inventor/nodes/SoText2.h> 107 #include <Inventor/nodes/SoFont.h> 108 #include <Inventor/nodes/SoPointSet.h> 109 #include <Inventor/nodes/SoDrawStyle.h> 110 #include <Inventor/nodes/SoBaseColor.h> 111 112 // For searching for nodes within kits: 113 #include <Inventor/nodekits/SoBaseKit.h> 114 115 // FWJ 116 #include <Inventor/SbVec3f.h> 117 118 G4OpenInventorXtExaminerViewer* G4OpenInventorXtExaminerViewer::viewer = 0; 119 120 static const char* thisClassName = "G4OpenInventorXtExaminerViewer"; 121 122 #define MIN_SPEED 2.1 // Lower number means faster 123 #define START_STEP 0.3 124 #define SPEED_INDICATOR_STEP 0.045 125 #define MAX_SPEED_INDICATOR 0.81 126 // Number of steps 90 degree rotation around an element is split into 127 #define ROT_CNT 6 128 129 // Public constructor 130 G4OpenInventorXtExaminerViewer::G4OpenInventorXtExaminerViewer(Widget parent, 131 const char *name, SbBool embed, 132 SoXtFullViewer::BuildFlag flag, SoXtViewer::Type type) : 133 SoXtExaminerViewer(parent, name, embed, flag, type, FALSE) 134 { 135 // Tell GLWidget not to build just yet 136 this->constructor(TRUE); 137 } 138 139 // Protected constructor for classes deriving from this viewer. 140 G4OpenInventorXtExaminerViewer::G4OpenInventorXtExaminerViewer(Widget parent, 141 const char *name, SbBool embed, 142 SoXtFullViewer::BuildFlag flag, SoXtViewer::Type type, 143 SbBool build) : 144 SoXtExaminerViewer(parent, name, embed, flag, type, FALSE) 145 { 146 this->constructor(build); 147 } 148 149 // Called by all constructors to set up widgets and initialize member fields. 150 void G4OpenInventorXtExaminerViewer::constructor(const SbBool build) 151 { 152 setClassName(thisClassName); 153 154 hookBeamOn = new HookEventProcState(this); 155 this->newEvents = false; 156 157 fileName = ".bookmarkFile"; // Default viewpoint file name 158 viewPtIdx = -1; // index of the most recent viewpoint in viewPtList vector 159 animateSensor = new SoTimerSensor( 160 G4OpenInventorXtExaminerViewer::animateSensorCB, this); 161 animateSensorRotation = new SoTimerSensor( 162 G4OpenInventorXtExaminerViewer::animateSensorRotationCB, this); 163 animateBtwPtsPeriod = MIN_SPEED; 164 currentState = GENERAL; 165 myCam = new SoPerspectiveCamera; 166 MAX_VP_IDX = 3; 167 MAX_VP_NAME = 35; // Max length of a viewpoint name, padded with spaces 168 rotCnt = ROT_CNT; // For 90 degree rotations 169 curViewPtName = new char[MAX_VP_NAME + 1]; 170 left_right = up_down = 0; // For movements around the beam during animation 171 speedStep = START_STEP; // For smoother animation speed increase/decrease 172 rotUpVec = false; // Used during scene element rotations 173 step = 1; //By default 174 // Used for moving along the beam with the 175 // mouse instead of rotating the view 176 lshiftdown = rshiftdown = false; 177 // Used for rotating the view with the camera 178 // staying in place 179 lctrldown = rctrldown = false; 180 // Used to send abbreviated output to the console when 181 abbrOutputFlag = false; 182 pickRefPathFlag = false; 183 prevColorField = NULL; 184 warningFlag = false; // We come from the warning dialog 185 viewer = this; 186 openFileDialog = newFileDialog = listsDialog = (Widget) NULL; 187 loadRefCoordsDialog = saveRefCoordsDialog = NULL; 188 loadSceneGraphDialog = saveSceneGraphDialog = NULL; 189 myElementList = NULL; 190 // FWJ default path look-ahead 191 pathLookahead = 5; 192 193 newSceneGraph = NULL; 194 zcoordSetFlag = false; 195 196 //////////////////////////SUPERIMPOSED SCENE////////////////////////// 197 searcher = NULL; 198 // Used in animation; progressively scaled for gradual speed change 199 maxSpeed = 0.0f; 200 201 static const char * superimposed[] = { 202 "#Inventor V2.1 ascii", "", 203 "Separator ", 204 "{", 205 " MaterialBinding ", 206 " {", 207 " value OVERALL", 208 " }", 209 " OrthographicCamera ", 210 " {", 211 " height 1", 212 " nearDistance 0", 213 " farDistance 1", 214 " }", 215 " DEF soxt->callback Callback { }", 216 " Separator ", 217 " {", 218 " DEF soxt->translation Translation ", 219 " {", 220 " translation 0 0 0", 221 " }", 222 " DEF soxt->scale Scale ", 223 " {", 224 " scaleFactor 1 1 1", 225 " }", 226 " DEF soxt->geometry Coordinate3 ", 227 " {", 228 " point ", 229 " [", 230 " -0.81 -0.04 0, -0.81 0 0,", 231 " -0.81 0.04 0, 0 -0.04 0,", 232 " 0 0 0, 0 0.04 0,", 233 " 0.81 -0.04 0, 0.81 0 0,", 234 " 0.81 0.04 0,", 235 " 0 0.02 0,", // idx 9 236 " 0.81 0.02 0, 0.81 -0.02 0,", 237 " 0 -0.02 0,", 238 " 0 0.01 0,", // idx 13 239 " 0.4 0.01 0, 0.4 -0.01 0,", 240 " 0 -0.01 0", 241 " ]", 242 " }", 243 // current speed indicator (outline) 244 " DEF soxt->animSpeedOutlineSwitch Switch ", 245 " {", 246 " whichChild -3", 247 " Material ", 248 " {", 249 " emissiveColor 0 0 0", 250 " }", 251 " IndexedFaceSet ", 252 " {", 253 " coordIndex ", 254 " [", 255 " 12, 11, 10, 9, -1", 256 " ]", 257 " }", 258 " }", 259 // the coordinate system 260 " DEF soxt->axisSwitch Switch ", 261 " {", 262 " whichChild -3", 263 " BaseColor ", 264 " {", 265 " rgb 1 1 1", 266 " }", 267 " IndexedLineSet ", 268 " {", 269 " coordIndex ", 270 " [", 271 " 0, 2, -1,", 272 " 3, 5, -1,", 273 " 6, 8, -1,", 274 " 1, 7, -1", 275 " ]", 276 " }", 277 " }", 278 // current speed indicator 279 " DEF soxt->animSpeedSwitch Switch ", 280 " {", 281 " whichChild -3", 282 " Material ", 283 " {", 284 " emissiveColor 0 1 0", 285 " }", 286 " IndexedFaceSet ", 287 " {", 288 " coordIndex ", 289 " [", 290 " 16, 15, 14, 13, -1", 291 " ]", 292 " }", 293 " }", 294 " }", 295 // For displaying either z position (during animation) or current viewpoint name 296 " DEF soxt->curInfoSwitch Switch ", 297 " {", 298 " whichChild -3", 299 " DEF soxt->curInfoTrans Translation ", 300 " {", 301 " translation 10 20 30 ", 302 " }", 303 " DEF soxt->curInfoFont Font ", 304 " {", 305 " name defaultFont:Bold", 306 " size 16", 307 " }", 308 " DEF soxt->curInfoText Text2 ", 309 " {", 310 " string Hello", 311 " }", 312 " }", 313 // Need to use different fields for mouseover 314 // because newlines are ignored when the scene is rendered 315 " Separator ", 316 " {", 317 " DEF soxt->mouseOverTransLogName Translation ", 318 " {", 319 " translation 0 0 0 ", 320 " }", 321 " DEF soxt->mouseOverFontLogName Font ", 322 " {", 323 " name defaultFont:Bold", 324 " size 16", 325 " }", 326 " DEF soxt->mouseOverTextLogName Text2 { } ", 327 " }", 328 " Separator ", 329 " {", 330 " DEF soxt->mouseOverTransSolid Translation ", 331 " {", 332 " translation 0 0 0 ", 333 " }", 334 " DEF soxt->mouseOverFontSolid Font ", 335 " {", 336 " name defaultFont:Bold", 337 " size 16", 338 " }", 339 " DEF soxt->mouseOverTextSolid Text2 { } ", 340 " }", 341 " Separator ", 342 " {", 343 " DEF soxt->mouseOverTransMaterial Translation ", 344 " {", 345 " translation 0 0 0 ", 346 " }", 347 " DEF soxt->mouseOverFontMaterial Font ", 348 " {", 349 " name defaultFont:Bold", 350 " size 16", 351 " }", 352 " DEF soxt->mouseOverTextMaterial Text2 { } ", 353 " }", 354 " Separator ", 355 " {", 356 " DEF soxt->mouseOverTransZPos Translation ", 357 " {", 358 " translation 0 0 0 ", 359 " }", 360 " DEF soxt->mouseOverFontZPos Font ", 361 " {", 362 " name defaultFont:Bold", 363 " size 16", 364 " }", 365 " DEF soxt->mouseOverTextZPos Text2 { } ", 366 " }", 367 "}", NULL 368 }; 369 370 int i, bufsize; 371 for (i = bufsize = 0; superimposed[i]; i++) 372 bufsize += strlen(superimposed[i]) + 1; 373 char * buf = new char[bufsize + 1]; 374 for (i = bufsize = 0; superimposed[i]; i++) { 375 strcpy(buf + bufsize, superimposed[i]); 376 bufsize += strlen(superimposed[i]); 377 buf[bufsize] = '\n'; 378 bufsize++; 379 } 380 SoInput * input = new SoInput; 381 input->setBuffer(buf, bufsize); 382 SbBool ok = SoDB::read(input, this->superimposition); 383 (void)ok; // FWJ added to avoid compiler warning 384 assert(ok); 385 delete input; 386 delete[] buf; 387 this->superimposition->ref(); 388 389 this->sscale = (SoScale *) this->getSuperimpositionNode( 390 this->superimposition, "soxt->scale"); 391 this->stranslation = (SoTranslation *) this->getSuperimpositionNode( 392 this->superimposition, "soxt->translation"); 393 this->sgeometry = (SoCoordinate3 *) this->getSuperimpositionNode( 394 this->superimposition, "soxt->geometry"); 395 this->axisSwitch = (SoSwitch *) this->getSuperimpositionNode( 396 this->superimposition, "soxt->axisSwitch"); 397 this->animSpeedOutlineSwitch = (SoSwitch *) this->getSuperimpositionNode( 398 this->superimposition, "soxt->animSpeedOutlineSwitch"); 399 this->animSpeedSwitch = (SoSwitch *) this->getSuperimpositionNode( 400 this->superimposition, "soxt->animSpeedSwitch"); 401 this->curInfoSwitch = (SoSwitch *) this->getSuperimpositionNode( 402 this->superimposition, "soxt->curInfoSwitch"); 403 this->curInfoTrans = (SoTranslation *) this->getSuperimpositionNode( 404 this->superimposition, "soxt->curInfoTrans"); 405 this->curInfoFont = (SoFont *) this->getSuperimpositionNode( 406 this->superimposition, "soxt->curInfoFont"); 407 this->curInfoText = (SoText2 *) this->getSuperimpositionNode( 408 this->superimposition, "soxt->curInfoText"); 409 this->mouseOverTransLogName = (SoTranslation*)this->getSuperimpositionNode( 410 this->superimposition, "soxt->mouseOverTransLogName"); 411 this->mouseOverFontLogName = (SoFont *) this->getSuperimpositionNode( 412 this->superimposition, "soxt->mouseOverFontLogName"); 413 this->mouseOverTextLogName = (SoText2 *) this->getSuperimpositionNode( 414 this->superimposition, "soxt->mouseOverTextLogName"); 415 this->mouseOverTransSolid = (SoTranslation *) this->getSuperimpositionNode( 416 this->superimposition, "soxt->mouseOverTransSolid"); 417 this->mouseOverFontSolid = (SoFont *) this->getSuperimpositionNode( 418 this->superimposition, "soxt->mouseOverFontSolid"); 419 this->mouseOverTextSolid = (SoText2 *) this->getSuperimpositionNode( 420 this->superimposition, "soxt->mouseOverTextSolid"); 421 this->mouseOverTransMaterial = (SoTranslation*)this->getSuperimpositionNode( 422 this->superimposition, "soxt->mouseOverTransMaterial"); 423 this->mouseOverFontMaterial = (SoFont *) this->getSuperimpositionNode( 424 this->superimposition, "soxt->mouseOverFontMaterial"); 425 this->mouseOverTextMaterial = (SoText2 *) this->getSuperimpositionNode( 426 this->superimposition, "soxt->mouseOverTextMaterial"); 427 this->mouseOverTransZPos = (SoTranslation *) this->getSuperimpositionNode( 428 this->superimposition, "soxt->mouseOverTransZPos"); 429 this->mouseOverFontZPos = (SoFont *) this->getSuperimpositionNode( 430 this->superimposition, "soxt->mouseOverFontZPos"); 431 this->mouseOverTextZPos = (SoText2 *) this->getSuperimpositionNode( 432 this->superimposition, "soxt->mouseOverTextZPos"); 433 434 SoCallback * cb = (SoCallback *) this->getSuperimpositionNode( 435 this->superimposition, "soxt->callback"); 436 cb->setCallback(superimpositionCB, this); 437 438 this->addSuperimposition(this->superimposition); 439 this->setSuperimpositionEnabled(this->superimposition, FALSE); 440 axisSwitch->whichChild.setValue(SO_SWITCH_NONE); 441 animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE); 442 animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE); 443 444 /////////////////////\SUPERIMPOSED SCENE/////////////////////////////////// 445 446 // Build everything else like the parent viewer does 447 if (build) { 448 Widget w = buildWidget(getParentWidget()); 449 setBaseWidget(w); 450 451 // Make this window a little bigger because of the extra buttons 452 // FWJ but it is already set to 600x600 by vis/open 453 // setSize(SbVec2s(500, 550)); 454 } 455 456 } 457 458 459 // Static function that returns the pointer to G4OpenInventorXtExaminerViewer 460 // FWJ DISABLED 461 //G4OpenInventorXtExaminerViewer *G4OpenInventorXtExaminerViewer::getObject() 462 //{ 463 // if (!viewer) 464 // new G4OpenInventorXtExaminerViewer(); 465 // return viewer; 466 //} 467 468 469 // This method locates a named node in the superimposed or original scene. 470 SoNode * 471 G4OpenInventorXtExaminerViewer::getSuperimpositionNode(SoNode *root, 472 const char * name) 473 { 474 if (!this->searcher) 475 this->searcher = new SoSearchAction; 476 searcher->reset(); 477 searcher->setName(SbName(name)); 478 searcher->setInterest(SoSearchAction::FIRST); 479 searcher->setSearchingAll(TRUE); 480 searcher->apply(root); 481 assert(searcher->getPath()); 482 return searcher->getPath()->getTail(); 483 } 484 485 486 void G4OpenInventorXtExaminerViewer::superimpositionCB(void * closure, 487 SoAction * action) 488 { 489 if (closure) 490 ((G4OpenInventorXtExaminerViewer*)closure)->superimpositionEvent(action); 491 } 492 493 494 // Renders and positions speed indicator and longitudinal 495 // distance/viewpoint name on the drawing canvas 496 void G4OpenInventorXtExaminerViewer::superimpositionEvent(SoAction * action) 497 { 498 499 if (!action->isOfType(SoGLRenderAction::getClassTypeId())) 500 return; 501 SbViewportRegion vpRegion = 502 ((SoGLRenderAction *) action)->getViewportRegion(); 503 SbVec2s viewportSize = vpRegion.getViewportSizePixels(); 504 505 float aspect = float(viewportSize[0]) / float(viewportSize[1]); 506 float factorx = 1.0f / float(viewportSize[1]) * 220.0f; 507 float factory = factorx; 508 509 if (aspect > 1.0f) { 510 this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f, 0.0f)); 511 } else { 512 this->stranslation->translation.setValue( 513 SbVec3f(0.0f, -0.4f / aspect, 0.0f)); 514 factorx /= aspect; 515 factory /= aspect; 516 } 517 if (viewportSize[0] > 500) 518 factorx *= 500.0f / 400.0f; 519 else 520 factorx *= float(viewportSize[0]) / 400.0f; 521 this->sscale->scaleFactor.setValue(SbVec3f(factorx, factory, 1.0f)); 522 523 float xInfo, yInfo, xMouseLogName, yMouseLogName, xMouseSolid, yMouseSolid, 524 xMouseMaterial, yMouseMaterial, xMouseZPos, yMouseZPos; 525 xInfo = -.45; 526 yInfo = .45; 527 xMouseLogName = 0.0; 528 yMouseLogName = -.75; 529 xMouseSolid = 0.0; 530 yMouseSolid = -.78; 531 xMouseMaterial = 0.0; 532 yMouseMaterial = -.81; 533 xMouseZPos = 0.0; 534 yMouseZPos = -.84; 535 536 if (aspect > 1.0f) { 537 xInfo *= aspect; 538 xMouseSolid *= aspect; 539 xMouseMaterial *= aspect; 540 this->curInfoTrans->translation.setValue(SbVec3f(xInfo, yInfo, 0.0)); 541 this->mouseOverTransLogName->translation.setValue( 542 SbVec3f(xMouseLogName, yMouseLogName, 0.0)); 543 this->mouseOverTransSolid->translation.setValue( 544 SbVec3f(xMouseSolid, yMouseSolid, 0.0)); 545 this->mouseOverTransMaterial->translation.setValue( 546 SbVec3f(xMouseMaterial, yMouseMaterial, 0.0)); 547 this->mouseOverTransZPos->translation.setValue( 548 SbVec3f(xMouseZPos, yMouseZPos, 0.0)); 549 } else { 550 yInfo /= aspect; 551 yMouseSolid /= aspect; 552 yMouseMaterial /= aspect; 553 this->curInfoTrans->translation.setValue(SbVec3f(xInfo, yInfo, 0.0)); 554 this->mouseOverTransLogName->translation.setValue( 555 SbVec3f(xMouseLogName, yMouseLogName, 0.0)); 556 this->mouseOverTransSolid->translation.setValue( 557 SbVec3f(xMouseSolid, yMouseSolid, 0.0)); 558 this->mouseOverTransMaterial->translation.setValue( 559 SbVec3f(xMouseMaterial, yMouseMaterial, 0.0)); 560 this->mouseOverTransZPos->translation.setValue( 561 SbVec3f(xMouseZPos, yMouseZPos, 0.0)); 562 } 563 564 if (currentState == VIEWPOINT) { // Displaying viewpoint name 565 this->curInfoFont->size.setValue(15); 566 this->curInfoFont->name.setValue("defaultFont:Italic"); 567 this->curInfoText->string.setValue(SbString(curViewPtName)); 568 } 569 else if(currentState == GENERAL) { // Displaying longitudinal distance 570 this->curInfoFont->size.setValue(16); 571 this->curInfoFont->name.setValue("defaultFont:Bold"); 572 this->curInfoText->string.setValue(SbString("")); 573 } 574 else { 575 if (refParticleIdx < (int) refParticleTrajectory.size() - 1) { 576 this->curInfoFont->size.setValue(16); 577 this->curInfoFont->name.setValue("defaultFont:Bold"); 578 char zPos[20]; 579 snprintf(zPos, sizeof zPos, "%7.2f [m]", refZPositions[refParticleIdx] / 1000); 580 this->curInfoText->string.setValue(SbString(zPos)); 581 } 582 } 583 } 584 585 586 G4OpenInventorXtExaminerViewer::~G4OpenInventorXtExaminerViewer() 587 { 588 if (superimposition != NULL) { 589 removeSuperimposition(superimposition); 590 superimposition->unref(); 591 superimposition = NULL; 592 } 593 if (animateSensor->isScheduled()) 594 animateSensor->unschedule(); 595 delete animateSensor; 596 delete sceneChangeSensor; 597 598 delete[] curViewPtName; 599 delete searcher; 600 601 viewer = 0; 602 } 603 604 605 // Adds a menu bar and a few menu items to the viewer. 606 Widget G4OpenInventorXtExaminerViewer::buildWidget(Widget parent) 607 { 608 Widget shell; 609 Atom WM_DELETE_WINDOW; 610 611 if (!parent) 612 SoDebugError::post("G4OpenInventorXtExaminerViewer::buildWidget", "Error: Parent is null."); 613 614 Arg args[10]; 615 XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM); 616 XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM); 617 XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM); 618 XtSetArg(args[3], XmNbottomAttachment, XmATTACH_FORM); 619 Widget form = XmCreateForm(parent, (char *) "Form", args, 4); 620 XtManageChild(form); 621 622 shell = XtParent(form); 623 WM_DELETE_WINDOW = XInternAtom(XtDisplay(parent), "WM_DELETE_WINDOW", 624 False); 625 XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW, 626 (XtCallbackProc)closeMainWindowCB, this); 627 628 XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM); 629 XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM); 630 XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM); 631 menuBar = XmCreateMenuBar(form, (char *) "MenuBar", args, 3); 632 XtManageChild(menuBar); 633 634 fileMenu = addMenu("File"); 635 this->addButton(fileMenu, "Open Viewpoint File...", openViewPtFileCB); 636 addButton(fileMenu, "New Viewpoint File", newViewPtFileCB); 637 addButton(fileMenu, "Load Ref. Coords", loadRefCoordsDialogCB); 638 addButton(fileMenu, "Save Ref. Coords", saveRefCoordsDialogCB); 639 addButton(fileMenu, "Load Scene Graph", loadSceneGraphDialogCB); 640 addButton(fileMenu, "Save Scene Graph", saveSceneGraphDialogCB); 641 XtManageChild( 642 XmCreateSeparatorGadget(fileMenu, (char *) "Separator", NULL, 0)); 643 644 Widget menu = addMenu("Tools"); 645 addButton(menu, "Animate Ref. Particle", animateRefParticleCB); 646 addButton(menu, "Go to start of Ref path", gotoRefPathStartCB); 647 addButton(menu, "Invert Ref path", invertRefPathCB); 648 649 Widget viewerBase = SoXtFullViewer::buildWidget(form); 650 651 XtSetArg(args[0], XmNtopAttachment, XmATTACH_WIDGET); 652 XtSetArg(args[1], XmNtopWidget, menuBar); 653 XtSetArg(args[2], XmNleftAttachment, XmATTACH_FORM); 654 XtSetArg(args[3], XmNrightAttachment, XmATTACH_FORM); 655 XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM); 656 XtSetValues(viewerBase, args, 5); 657 658 return viewerBase; 659 } 660 661 662 // Adds a new menu to menuBar 663 Widget G4OpenInventorXtExaminerViewer::addMenu(std::string name) 664 { 665 Arg args[1]; 666 Widget menu = XmCreatePulldownMenu(menuBar, (char *) name.c_str(), NULL, 0); 667 668 XtSetArg(args[0], XmNsubMenuId, menu); 669 Widget w = XmCreateCascadeButton(menuBar, (char *) name.c_str(), args, 1); 670 XtManageChild(w); 671 672 return menu; 673 } 674 675 676 // Adds a new button to menu 677 void G4OpenInventorXtExaminerViewer::addButton(Widget menu, std::string name, 678 XtCallbackProc cb) 679 { 680 Widget button = XmCreatePushButton(menu, (char *) name.c_str(), NULL, 0); 681 XtManageChild(button); 682 XtAddCallback(button, XmNactivateCallback, cb, this); 683 } 684 685 686 // Overloaded for saving of and browsing through viewpoints. 687 void G4OpenInventorXtExaminerViewer::createViewerButtons(Widget parent, 688 SbPList * buttonlist) 689 { 690 int n; 691 Arg args[6]; 692 Widget saveViewPtButton, abbrOutputButton, pickRefPathButton; 693 Widget switchWireFrameButton; 694 695 // Create original buttons 696 SoXtExaminerViewer::createViewerButtons(parent, buttonlist); 697 698 // Handle disappearing button caused by SoXtExaminerViewer::setCamera 699 Widget emptyButton = XtVaCreateManagedWidget("", xmPushButtonWidgetClass, 700 parent, NULL); 701 buttonlist->append(emptyButton); 702 703 // Left arrow that goes back one view point on click 704 n = 0; 705 XtSetArg(args[n], XmNtopPosition, 1); n++; 706 XtSetArg(args[n], XmNbottomPosition, 2); n++; 707 XtSetArg(args[n], XmNleftPosition, 0); n++; 708 XtSetArg(args[n], XmNrightPosition, 1); n++; 709 XtSetArg(args[n], XmNarrowDirection, XmARROW_LEFT); n++; 710 XtSetArg(args[n], XmNsensitive, False); n++; 711 prevViewPtButton = XmCreateArrowButtonGadget(parent, (char *) "ArrowL", 712 args, n); 713 XtManageChild(prevViewPtButton); 714 XtAddCallback(prevViewPtButton, XmNactivateCallback, 715 G4OpenInventorXtExaminerViewer::prevViewPtCB, this); 716 buttonlist->append(prevViewPtButton); 717 718 // Right arrow that goes forward one view point on click 719 n = 0; 720 XtSetArg(args[n], XmNtopPosition, 1); n++; 721 XtSetArg(args[n], XmNbottomPosition, 2); n++; 722 XtSetArg(args[n], XmNleftPosition, 0); n++; 723 XtSetArg(args[n], XmNrightPosition, 1); n++; 724 XtSetArg(args[n], XmNarrowDirection, XmARROW_RIGHT); n++; 725 XtSetArg(args[n], XmNsensitive, False); n++; 726 nextViewPtButton = XmCreateArrowButtonGadget(parent, (char *) "ArrowR", 727 args, n); 728 XtManageChild(nextViewPtButton); 729 XtAddCallback(nextViewPtButton, XmNactivateCallback, 730 G4OpenInventorXtExaminerViewer::nextViewPtCB, this); 731 buttonlist->append(nextViewPtButton); 732 733 // Save button for storing current camera parameters 734 saveViewPtButton = XtVaCreateManagedWidget("Save", xmPushButtonWidgetClass, 735 parent, NULL); 736 XtAddCallback(saveViewPtButton, XmNactivateCallback, 737 G4OpenInventorXtExaminerViewer::saveViewPtCB, this); 738 Pixmap saveVP, saveVP_ins; 739 saveVP = SoXtInternal::createPixmapFromXpm(saveViewPtButton, 740 saveViewPt_xpm); 741 saveVP_ins = SoXtInternal::createPixmapFromXpm(saveViewPtButton, 742 saveViewPt_xpm, TRUE); 743 XtVaSetValues(saveViewPtButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap, 744 saveVP, XmNselectPixmap, saveVP, XmNlabelInsensitivePixmap, 745 saveVP_ins, XmNselectInsensitivePixmap, saveVP_ins, NULL); 746 buttonlist->append(saveViewPtButton); 747 748 // Toggle button to get abbreviated output 749 abbrOutputButton = XtVaCreateManagedWidget("Abbr", 750 xmToggleButtonWidgetClass, parent, XmNindicatorOn, False, NULL); 751 XtAddCallback(abbrOutputButton, XmNdisarmCallback, G4OpenInventorXtExaminerViewer::abbrOutputCB, 752 this); 753 Pixmap pickextxpm, pickextxpm_ins; 754 pickextxpm = SoXtInternal::createPixmapFromXpm(abbrOutputButton, 755 pickext_xpm); 756 pickextxpm_ins = SoXtInternal::createPixmapFromXpm(abbrOutputButton, 757 pickext_xpm, TRUE); 758 XtVaSetValues(abbrOutputButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap, 759 pickextxpm, XmNselectPixmap, pickextxpm, XmNlabelInsensitivePixmap, 760 pickextxpm_ins, XmNselectInsensitivePixmap, pickextxpm_ins, NULL); 761 // Pixmap consolexpm, consolexpm_ins; 762 // consolexpm = SoXtInternal::createPixmapFromXpm(abbrOutputButton, 763 // console_xpm); 764 // consolexpm_ins = SoXtInternal::createPixmapFromXpm(abbrOutputButton, 765 // console_xpm, TRUE); 766 // XtVaSetValues(abbrOutputButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap, 767 // consolexpm, XmNselectPixmap, consolexpm, XmNlabelInsensitivePixmap, 768 // consolexpm_ins, XmNselectInsensitivePixmap, consolexpm_ins, NULL); 769 buttonlist->append(abbrOutputButton); 770 771 // Button for selecting the beam that will act as reference path 772 pickRefPathButton = XtVaCreateManagedWidget("Refpath", xmPushButtonWidgetClass, 773 parent, NULL); 774 XtAddCallback(pickRefPathButton, XmNactivateCallback, 775 G4OpenInventorXtExaminerViewer::pickRefPathCB, this); 776 Pixmap pickrefxpm, pickrefxpm_ins; 777 pickrefxpm = SoXtInternal::createPixmapFromXpm(pickRefPathButton, 778 pickref_xpm); 779 pickrefxpm_ins = SoXtInternal::createPixmapFromXpm(pickRefPathButton, 780 pickref_xpm, TRUE); 781 XtVaSetValues(pickRefPathButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap, 782 pickrefxpm, XmNselectPixmap, pickrefxpm, XmNlabelInsensitivePixmap, 783 pickrefxpm_ins, XmNselectInsensitivePixmap, pickrefxpm_ins, NULL); 784 785 buttonlist->append(pickRefPathButton); 786 787 // Toggle button for switching in and out of wireframe mode 788 switchWireFrameButton = XtVaCreateManagedWidget("Wireframe", 789 xmToggleButtonWidgetClass, parent, XmNindicatorOn, False, NULL); 790 XtAddCallback(switchWireFrameButton, XmNvalueChangedCallback, 791 G4OpenInventorXtExaminerViewer::switchWireFrameCB, this); 792 Pixmap wireframe, wireframe_ins; 793 wireframe = SoXtInternal::createPixmapFromXpm(switchWireFrameButton, 794 wireframe_xpm); 795 wireframe_ins = SoXtInternal::createPixmapFromXpm(switchWireFrameButton, 796 wireframe_xpm, TRUE); 797 XtVaSetValues(switchWireFrameButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap, 798 wireframe, XmNselectPixmap, wireframe, XmNlabelInsensitivePixmap, 799 wireframe_ins, XmNselectInsensitivePixmap, wireframe_ins, NULL); 800 buttonlist->append(switchWireFrameButton); 801 } 802 803 804 // Called right after buttons and widgets get realized. 805 // It sets the viewpoint last accessed. 806 void G4OpenInventorXtExaminerViewer::afterRealizeHook() 807 { 808 SoXtExaminerViewer::afterRealizeHook(); 809 810 // Default height is used when selecting and viewing scene elements 811 // FWJ Added defaultHeight for Ortho camera 812 SoCamera *cam = getCamera(); 813 if (cam) { 814 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) { 815 defaultHeightAngle = 816 ((SoPerspectiveCamera *) cam)->heightAngle.getValue(); 817 toggleCameraType(); 818 defaultHeight = 819 ((SoOrthographicCamera *) cam)->height.getValue(); 820 toggleCameraType(); 821 } else { 822 defaultHeight = 823 ((SoOrthographicCamera *) cam)->height.getValue(); 824 toggleCameraType(); 825 cam = getCamera(); 826 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) 827 defaultHeightAngle = 828 ((SoPerspectiveCamera *) cam)->heightAngle.getValue(); 829 toggleCameraType(); 830 } 831 } 832 833 // Open the default bookmark file 834 fileIn.open(fileName.c_str()); 835 if (!fileIn.fail()) { 836 if (!loadViewPts()) { 837 String dialogName = (char *) "Error Loading File"; 838 std::string msg = "Wrong or corrupted input file."; 839 warningMsgDialog(msg, dialogName, NULL); 840 } else { 841 // Opens a file without erasing it 842 fileOut.open(fileName.c_str(), std::ios::in); 843 fileOut.seekp(0, std::ios::end); // For appending new data to the end 844 constructListsDialog(getParentWidget(), this, NULL); // Pop up listsDialog 845 if (viewPtList.size()) { 846 // FWJ disabled auto-selection of first viewpoint. 847 // Initial view should be user-controllable & not forced 848 // setViewPt(); 849 XtSetSensitive(nextViewPtButton, True); 850 XtSetSensitive(prevViewPtButton, True); 851 } 852 } 853 fileIn.close(); 854 } else { 855 // Creates a new default bookmark file 856 fileOut.open(fileName.c_str()); 857 constructListsDialog(getParentWidget(), this, NULL); // Pop up listsDialog 858 } 859 860 fileIn.clear(); 861 862 SoSeparator *root = (SoSeparator *) (getSceneManager()->getSceneGraph()); 863 if (root == NULL) 864 SoDebugError::post("G4OpenInventorXtExaminerViewer::afterRealizeHook", "Root is null."); 865 else { 866 root->addChild(myCam); // For position/orientation calculation during animation 867 } 868 869 sceneChangeSensor = new SoNodeSensor; 870 sceneChangeSensor->setFunction(sceneChangeCB); 871 sceneChangeSensor->attach(root); 872 sceneChangeSensor->setData(this); 873 874 // Monitor mouseover events for displaying the name of scene elements 875 // An SoEventCallback is needed instead of using the default processSoEvent 876 // because that last one does not provide us with an SoPath to the object 877 // that was picked 878 SoEventCallback *moCB = new SoEventCallback; 879 moCB->addEventCallback( 880 SoLocation2Event::getClassTypeId(), 881 mouseoverCB, static_cast<void *>(this)); 882 root->addChild(moCB); 883 884 // Override the default picking mechanism present in G4OpenInventorViewer 885 // because we want abbreviated output when picking a trajectory 886 SoEventCallback *pickCB = new SoEventCallback; 887 pickCB->addEventCallback( 888 SoMouseButtonEvent::getClassTypeId(), 889 pickingCB, static_cast<void *>(this)); 890 root->addChild(pickCB); 891 892 } 893 894 895 // Rotates camera 90 degrees around a scene element. 896 // Rotation is animated for smoothness. 897 void G4OpenInventorXtExaminerViewer::rotateCamera() 898 { 899 SoCamera *cam = getCamera(); 900 901 SbRotation rot(rotAxis, M_PI / (2 * ROT_CNT)); 902 rot.multVec(camDir, camDir); 903 rot.multVec(camUpVec, camUpVec); 904 905 SbVec3f camPosNew = prevPt - (camDir*distance); 906 cam->position = camPosNew; 907 cam->pointAt(prevPt, camUpVec); 908 cam->focalDistance = (prevPt - camPosNew).length(); 909 910 rotCnt--; 911 912 if (animateSensorRotation->isScheduled()) { 913 animateSensorRotation->unschedule(); 914 } 915 916 animateSensorRotation->setBaseTime(SbTime::getTimeOfDay()); 917 animateSensorRotation->setInterval(SbTime(0.02)); 918 animateSensorRotation->schedule(); 919 920 } 921 922 923 // Slides camera along the beamline. 924 void G4OpenInventorXtExaminerViewer::moveCamera(float dist, bool lookdown) 925 { 926 927 SoCamera *cam = getCamera(); 928 SbVec3f p1(0), p2(0); // The particle moves from p1 to p2 929 SbVec3f particleDir; // Direction vector from p1 to p2 930 SbVec3f camPosNew(0); // New position of the camera 931 932 if(refParticleTrajectory.size() == 0) { 933 //refParticleTrajectory hasn't been set yet 934 if(dist) 935 distance = dist; 936 else 937 distance = (cam->position.getValue() - center).length(); 938 939 cam->position.setValue(center + offsetFromCenter*distance); 940 cam->focalDistance = (cam->position.getValue() - center).length(); 941 cam->pointAt(center, upVector); 942 } 943 else{ 944 945 // If we move forward past the last trajectory point, 946 // go back to the beginning 947 if (refParticleIdx >= (int) refParticleTrajectory.size() - 1) { 948 prevPt = refParticleTrajectory[refParticleIdx - step]; 949 dist = (prevPt - cam->position.getValue()).length(); 950 refParticleIdx = 0; 951 } 952 // If we move backward past the beginning, 953 // go to the last trajectory point 954 if (refParticleIdx < 0) { 955 prevPt = refParticleTrajectory[refParticleIdx + step]; 956 dist = (prevPt - cam->position.getValue()).length(); 957 refParticleIdx = refParticleTrajectory.size() - 2; 958 } 959 960 // Set start and end points 961 p1 = refParticleTrajectory[refParticleIdx]; 962 p2 = refParticleTrajectory[refParticleIdx + step]; 963 964 // Get the direction from p1 to p2 965 particleDir = p2 - p1; 966 particleDir.normalize(); 967 968 if(prevParticleDir == SbVec3f(0,0,0)){ 969 // First time entering BEAMLINE mode, look at 970 // the element from the front, with camera upright 971 if(lookdown) 972 camDir = SbVec3f(0,0,1); 973 else 974 camDir = SbVec3f(1,0,0); 975 camUpVec = SbVec3f(0,1,0); 976 977 // In case the start of the goes in a 978 // direction other than +z, rotate the camera accordingly 979 SbRotation rot(SbVec3f(0,0,1), particleDir); 980 rot.multVec(camDir, camDir); 981 rot.multVec(camUpVec, camUpVec); 982 983 } 984 else if(particleDir != prevParticleDir) { 985 // The beamline has changed direction 986 987 SbRotation rot(prevParticleDir, particleDir); 988 rot.multVec(camDir, camDir); 989 rot.multVec(camUpVec, camUpVec); 990 991 } 992 993 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) { 994 if (!dist) 995 distance = (prevPt - cam->position.getValue()).length(); 996 else 997 distance = dist; 998 } 999 1000 // FWJ distance not relevant -- use focalDistance 1001 // if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) { 1002 // if (!dist) 1003 // distance = (prevPt - cam->position.getValue()).length(); 1004 // else 1005 // distance = dist; 1006 // } 1007 1008 1009 float x(0.),y(0.),z(0.); 1010 prevPt.getValue(x,y,z); 1011 1012 1013 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) { 1014 camPosNew = p2 - (camDir*distance); 1015 } 1016 if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) { 1017 // FWJ maintain focal distance 1018 camPosNew = p2 - (camDir*cam->focalDistance.getValue()); 1019 // camPosNew = p2 - (camDir); 1020 } 1021 1022 cam->position = camPosNew; 1023 cam->pointAt(p2, camUpVec); 1024 cam->focalDistance = (p2 - camPosNew).length(); 1025 1026 p2.getValue(x,y,z); 1027 camPosNew.getValue(x,y,z); 1028 1029 prevParticleDir = particleDir; 1030 prevPt = p1; // For accurate distance calculation 1031 1032 } 1033 1034 } 1035 1036 1037 void G4OpenInventorXtExaminerViewer::pickingCB(void *aThis, 1038 SoEventCallback *eventCB) 1039 { 1040 SoHandleEventAction* action = eventCB->getAction(); 1041 const SoPickedPoint *pp = action->getPickedPoint(); 1042 G4OpenInventorXtExaminerViewer* This = (G4OpenInventorXtExaminerViewer*)aThis; 1043 1044 if(pp != NULL) { 1045 1046 SoPath* path = pp->getPath(); 1047 SoNode* node = ((SoFullPath*)path)->getTail(); 1048 1049 if(node->getTypeId() == SoLineSet::getClassTypeId()){ 1050 1051 if(This->pickRefPathFlag){ 1052 This->pickRefPathFlag = false; 1053 if(This->viewingBeforePickRef != This->isViewing()) 1054 This->setViewing(This->viewingBeforePickRef); 1055 else 1056 This->setComponentCursor(SoXtCursor(SoXtCursor::DEFAULT)); 1057 1058 // The trajectory is a set of lines stored in a LineSet 1059 SoLineSet * trajectory = (SoLineSet *)node; 1060 1061 // The set of all trajectories is stored in a Seperator group node 1062 // one level above the LineSet that was picked. The nodes under that 1063 // seperator are as follows (in this order): Material, LightModel, 1064 // ResetTransform, MatrixTransform, Coordinate3, DrawStyle, LineSet 1065 SoSeparator * grpNode = 1066 (SoSeparator*)(((SoFullPath*)path)->getNodeFromTail(1)); 1067 1068 // The node that contains the coordinates for the trajectory is a 1069 // Coordinate3 node which occurs before the LineSet node. We iterate 1070 // back through the nodes in the group until we find the Coordinate3 node 1071 int nodeIndex = grpNode->findChild(trajectory); 1072 SoNode * tmpNode; 1073 // FWJ needs initialization 1074 SoCoordinate3 * coords = 0; 1075 // SoCoordinate3 * coords; 1076 // We allow only 100 iterations, in case the node isn't found 1077 // (should take only a few iterations) 1078 for(int i = 0; i < 100; ++i) { 1079 --nodeIndex; 1080 1081 tmpNode = grpNode->getChild(nodeIndex); 1082 if(tmpNode->getTypeId() == SoCoordinate3::getClassTypeId()){ 1083 //node found 1084 coords = (SoCoordinate3 *)tmpNode; 1085 break; 1086 } 1087 } 1088 1089 if(coords == NULL){ 1090 String dialogName = (char *) "No coordinates"; 1091 std::string msg = "Could not find the coordinates node" 1092 " for the picked trajectory." 1093 " Reference trajectory not set"; 1094 This->warningMsgDialog(msg, dialogName, NULL); 1095 return; 1096 } 1097 1098 1099 if ((This->lshiftdown) || (This->rshiftdown)) 1100 This->setReferencePath(trajectory, coords, true); 1101 else 1102 This->setReferencePath(trajectory, coords, false); 1103 1104 return; 1105 1106 } 1107 else if(This->abbrOutputFlag) { 1108 1109 G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node); 1110 if(attHolder && attHolder->GetAttDefs().size()) { 1111 1112 std::string strTrajPoint = "G4TrajectoryPoint:"; 1113 std::ostringstream oss; 1114 for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) { 1115 G4cout << G4AttCheck(attHolder->GetAttValues()[i], 1116 attHolder->GetAttDefs()[i]); 1117 oss << G4AttCheck(attHolder->GetAttValues()[i], 1118 attHolder->GetAttDefs()[i]); 1119 if(oss.str().find(strTrajPoint) != std::string::npos) { 1120 1121 // Last attribute displayed was a trajectory point. Since we 1122 // want abbreviated output, display the last one and exit 1123 // (unless we're already at the last (and only) trajectory point) 1124 if(i != attHolder->GetAttDefs().size()-1) { 1125 G4cout << G4AttCheck( 1126 attHolder->GetAttValues()[attHolder->GetAttDefs().size()-1], 1127 attHolder->GetAttDefs()[attHolder->GetAttDefs().size()-1]); 1128 } 1129 break; 1130 } 1131 } 1132 } else { 1133 G4String name((char*)node->getName().getString()); 1134 G4String cls((char*)node->getTypeId().getName().getString()); 1135 G4cout << "SoNode : " << node 1136 << " SoType : " << cls 1137 << " name : " << name 1138 << G4endl; 1139 G4cout << "No attributes attached." << G4endl; 1140 } 1141 1142 return; 1143 } 1144 else{ 1145 //Go to default behavior 1146 } 1147 } 1148 else { 1149 //Go to default behavior 1150 } 1151 1152 // Default behavior in G4OpenInventorViewer::SelectionCB 1153 G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node); 1154 if(attHolder && attHolder->GetAttDefs().size()) { 1155 for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) { 1156 G4cout << G4AttCheck(attHolder->GetAttValues()[i], 1157 attHolder->GetAttDefs()[i]); 1158 } 1159 } else { 1160 G4String name((char*)node->getName().getString()); 1161 G4String cls((char*)node->getTypeId().getName().getString()); 1162 G4cout << "SoNode : " << node 1163 << " SoType : " << cls 1164 << " name : " << name 1165 << G4endl; 1166 G4cout << "No attributes attached." << G4endl; 1167 } 1168 1169 //Suppress other event handlers 1170 eventCB->setHandled(); 1171 } 1172 } 1173 1174 1175 void G4OpenInventorXtExaminerViewer::mouseoverCB(void *aThis, SoEventCallback *eventCB) 1176 { 1177 SoHandleEventAction* action = eventCB->getAction(); 1178 const SoPickedPoint* pp = action->getPickedPoint(); 1179 G4OpenInventorXtExaminerViewer* This = (G4OpenInventorXtExaminerViewer*)aThis; 1180 1181 if(!This->abbrOutputFlag) 1182 return; 1183 1184 if(pp != NULL) { 1185 1186 const SbViewportRegion & viewportRegion = action->getViewportRegion(); 1187 1188 std::string sLogName; 1189 float x,y,z; 1190 std::stringstream ssZPos; 1191 std::stringstream ssSolids; 1192 std::stringstream ssMaterials; 1193 SoPath * path = pp->getPath(); 1194 SoNode* node = ((SoFullPath*)path)->getTail(); 1195 1196 if(node->getTypeId() == Geant4_SoPolyhedron::getClassTypeId()) { 1197 1198 sLogName = "Logical Volume: "; 1199 sLogName += ((Geant4_SoPolyhedron *)node)->getName().getString(); 1200 1201 SoGetBoundingBoxAction bAction(viewportRegion); 1202 bAction.apply((SoFullPath*)path); 1203 SbBox3f bBox = bAction.getBoundingBox(); 1204 SbVec3f center = bBox.getCenter(); 1205 center.getValue(x,y,z); 1206 ssZPos << "Pos: " << x << " " << y << " " << z; 1207 1208 G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node); 1209 if(attHolder && attHolder->GetAttDefs().size()) { 1210 1211 std::vector<const std::map<G4String,G4AttDef>*> vecDefs = 1212 attHolder->GetAttDefs(); 1213 std::vector<const std::vector<G4AttValue>*> vecVals = 1214 attHolder->GetAttValues(); 1215 for (size_t i = 0; i < vecDefs.size(); ++i) { 1216 const std::vector<G4AttValue> * vals = vecVals[i]; 1217 1218 std::vector<G4AttValue>::const_iterator iValue; 1219 1220 for (iValue = vals->begin(); iValue != vals->end(); ++iValue) { 1221 const G4String& valueName = iValue->GetName(); 1222 const G4String& value = iValue->GetValue(); 1223 1224 if(valueName == "Solid") { 1225 if(ssSolids.str() == "") 1226 ssSolids << "Solid Name: " << value; 1227 else 1228 ssSolids << ", " << value; 1229 } 1230 1231 if(valueName == "Material") { 1232 if(ssMaterials.str() == "") 1233 ssMaterials << "Material Name: " << value; 1234 else 1235 ssMaterials << ", " << value; 1236 } 1237 } 1238 } 1239 } 1240 } 1241 // FWJ Mouseover for trajectories 1242 else if(node->getTypeId() == SoLineSet::getClassTypeId()) { 1243 // G4cout << "Trajectory!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << G4endl; 1244 G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node); 1245 if(attHolder && attHolder->GetAttDefs().size()) { 1246 std::string strTrajPoint = "G4TrajectoryPoint:"; 1247 std::ostringstream oss; 1248 G4String t1, t1Ch, t2, t3, t4; 1249 for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) { 1250 // G4cout << "Getting index " << i << " from attHolder" << G4endl; 1251 // No, returns a vector! G4AttValue* attValue = attHolder->GetAttValues()[i]; 1252 const std::vector<G4AttValue>* vals = attHolder->GetAttValues()[i]; 1253 std::vector<G4AttValue>::const_iterator iValue; 1254 for (iValue = vals->begin(); iValue != vals->end(); ++iValue) { 1255 const G4String& valueName = iValue->GetName(); 1256 const G4String& value = iValue->GetValue(); 1257 // G4cout << " valueName = " << valueName << G4endl; 1258 // G4cout << " value = " << value << G4endl; 1259 // LINE 1 1260 if (valueName == "PN") t1 = value; 1261 if (valueName == "Ch") { 1262 if (atof(value.c_str()) > 0) 1263 t1Ch = " +"; 1264 else 1265 t1Ch = " "; 1266 t1Ch += value; 1267 } 1268 if (valueName == "PDG") { 1269 t1 += " "; 1270 t1 += value; 1271 t1 += t1Ch; 1272 This->mouseOverTextLogName->string.setValue(t1); 1273 } 1274 // G4cout << " t1 = " << t1 << G4endl; 1275 // LINE 2 1276 if (valueName == "EventID") t2 = "Evt " + value; 1277 if (valueName == "ID") t2 += " Trk " + value; 1278 if (valueName == "PID") { 1279 t2 += " Prt " + value; 1280 This->mouseOverTextSolid->string.setValue(t2); 1281 } 1282 // LINE 3 1283 if (valueName == "IKE") t3 = "KE " + value; 1284 if (valueName == "IMom") { 1285 // Remove units 1286 unsigned ipos = value.rfind(" "); 1287 G4String value1 = value; 1288 value1.erase(ipos); 1289 t3 += " P (" + value1 + ")"; 1290 } 1291 if (valueName == "IMag") { 1292 t3 += " " + value + "/c"; 1293 // t3 += " " + value; 1294 This->mouseOverTextMaterial->string.setValue(t3); 1295 } 1296 // LINE 4 1297 if (valueName == "NTP") { 1298 std::ostringstream t4oss; 1299 t4oss << "TrjPts " << value; 1300 t4oss << " Pos " << pp->getPoint()[0] << " " << pp->getPoint()[1] << 1301 " " << pp->getPoint()[2]; 1302 This->mouseOverTextZPos->string.setValue(SbString(t4oss.str().c_str())); 1303 } 1304 } 1305 // G4cout << " NOW CALLING G4AttCheck" << G4endl; 1306 // G4cout << G4AttCheck(attHolder->GetAttValues()[i], 1307 // attHolder->GetAttDefs()[i]); 1308 // oss << G4AttCheck(attHolder->GetAttValues()[i], 1309 // attHolder->GetAttDefs()[i]); 1310 // if(oss.str().find(strTrajPoint) != std::string::npos) { 1311 // // Last attribute displayed was a trajectory point. Since we 1312 // // want abbreviated output, display the last one and exit 1313 // // (unless we're already at the last (and only) trajectory point) 1314 // if(i != attHolder->GetAttDefs().size()-1) { 1315 // G4cout << G4AttCheck( 1316 // attHolder->GetAttValues()[attHolder->GetAttDefs().size()-1], 1317 // attHolder->GetAttDefs()[attHolder->GetAttDefs().size()-1]); 1318 // } 1319 // break; 1320 // } 1321 } 1322 } 1323 This->setSuperimpositionEnabled(This->superimposition, TRUE); 1324 This->scheduleRedraw(); 1325 eventCB->setHandled(); 1326 return; 1327 } 1328 1329 bool redraw = false; 1330 if(std::string(This->mouseOverTextLogName->string.getValues(0)->getString()) != sLogName) { 1331 This->mouseOverTextLogName->string.setValue(SbString(sLogName.c_str())); 1332 redraw = true; 1333 } 1334 if(std::string(This->mouseOverTextSolid->string.getValues(0)->getString()) != ssSolids.str()) { 1335 This->mouseOverTextSolid->string.setValue(SbString(ssSolids.str().c_str())); 1336 redraw = true; 1337 } 1338 if(std::string(This->mouseOverTextMaterial->string.getValues(0)->getString()) != ssMaterials.str()){ 1339 This->mouseOverTextMaterial->string.setValue(SbString(ssMaterials.str().c_str())); 1340 redraw = true; 1341 } 1342 if(std::string(This->mouseOverTextZPos->string.getValues(0)->getString()) != ssZPos.str()) { 1343 This->mouseOverTextZPos->string.setValue(SbString(ssZPos.str().c_str())); 1344 redraw = true; 1345 } 1346 1347 if(redraw) { 1348 This->setSuperimpositionEnabled(This->superimposition, TRUE); 1349 This->scheduleRedraw(); 1350 } 1351 1352 eventCB->setHandled(); 1353 } 1354 else { 1355 if(std::string(This->mouseOverTextLogName->string.getValues(0)->getString()) != "") { 1356 This->mouseOverTextLogName->string.setValue(SbString("")); 1357 This->scheduleRedraw(); 1358 } 1359 if(std::string(This->mouseOverTextSolid->string.getValues(0)->getString()) != "") { 1360 This->mouseOverTextSolid->string.setValue(SbString("")); 1361 This->scheduleRedraw(); 1362 } 1363 if(std::string(This->mouseOverTextMaterial->string.getValues(0)->getString()) != "") { 1364 This->mouseOverTextMaterial->string.setValue(SbString("")); 1365 This->scheduleRedraw(); 1366 } 1367 if(std::string(This->mouseOverTextZPos->string.getValues(0)->getString()) != "") { 1368 This->mouseOverTextZPos->string.setValue(SbString("")); 1369 This->scheduleRedraw(); 1370 } 1371 } 1372 } 1373 1374 1375 SbBool G4OpenInventorXtExaminerViewer::processSoEvent(const SoEvent * const ev) { 1376 SoCamera *cam = getCamera(); 1377 const SoType type(ev->getTypeId()); 1378 1379 if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) { 1380 SoMouseButtonEvent * me = (SoMouseButtonEvent *) ev; 1381 1382 if (currentState == ANIMATION || currentState == REVERSED_ANIMATION 1383 || currentState == PAUSED_ANIMATION) { 1384 switch (me->getButton()) { 1385 case SoMouseButtonEvent::BUTTON4: // Scroll wheel up 1386 if (me->getState() == SoButtonEvent::DOWN) { 1387 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) { 1388 float hAngle = 1389 ((SoPerspectiveCamera *) cam)->heightAngle.getValue(); 1390 ((SoPerspectiveCamera *) cam)->heightAngle = hAngle 1391 + 0.01f; 1392 return TRUE; 1393 } else if (cam->isOfType( 1394 SoOrthographicCamera::getClassTypeId())) { 1395 float height = 1396 ((SoOrthographicCamera *) cam)->height.getValue(); 1397 ((SoOrthographicCamera *) cam)->height = height + 5; 1398 return TRUE; 1399 } 1400 } 1401 break; 1402 case SoMouseButtonEvent::BUTTON5: // Scroll wheel down 1403 if (me->getState() == SoButtonEvent::DOWN) { 1404 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) { 1405 float hAngle = 1406 ((SoPerspectiveCamera *) cam)->heightAngle.getValue(); 1407 if (hAngle > 0.01) 1408 ((SoPerspectiveCamera *) cam)->heightAngle = hAngle 1409 - 0.01f; 1410 return TRUE; 1411 } else if (cam->isOfType( 1412 SoOrthographicCamera::getClassTypeId())) { 1413 float height = 1414 ((SoOrthographicCamera *) cam)->height.getValue(); 1415 if (height > 5) 1416 ((SoOrthographicCamera *) cam)->height = height - 5; 1417 return TRUE; 1418 } 1419 } 1420 break; 1421 default: 1422 break; 1423 } 1424 } 1425 if (currentState == GENERAL) { 1426 1427 } 1428 } 1429 1430 if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { 1431 SoKeyboardEvent * ke = (SoKeyboardEvent *) ev; 1432 1433 if (SoKeyboardEvent::isKeyPressEvent(ev, ke->getKey())) { 1434 switch (ke->getKey()) { 1435 case SoKeyboardEvent::LEFT_SHIFT: 1436 this->lshiftdown = true; 1437 return TRUE; 1438 case SoKeyboardEvent::RIGHT_SHIFT: 1439 this->rshiftdown = true; 1440 return TRUE; 1441 case SoKeyboardEvent::LEFT_CONTROL: 1442 this->lctrldown = true; 1443 return TRUE; 1444 case SoKeyboardEvent::RIGHT_CONTROL: 1445 this->rctrldown = true; 1446 return TRUE; 1447 case SoKeyboardEvent::SPACE: 1448 if (currentState == ANIMATION 1449 || currentState == REVERSED_ANIMATION) { 1450 beforePausing = currentState; 1451 currentState = PAUSED_ANIMATION; 1452 if (animateSensor->isScheduled()) 1453 animateSensor->unschedule(); 1454 return TRUE; 1455 } else if (currentState == PAUSED_ANIMATION) { 1456 if (maxSpeed) { 1457 if ((beforePausing == ANIMATION 1458 && refParticleIdx 1459 < (int) refParticleTrajectory.size() - 1) 1460 || (beforePausing == REVERSED_ANIMATION 1461 && refParticleIdx > 0)) { 1462 currentState = beforePausing; 1463 animateRefParticle(); 1464 } 1465 } 1466 return TRUE; 1467 } 1468 break; 1469 case SoKeyboardEvent::ESCAPE: 1470 if (currentState == ANIMATION 1471 || currentState == REVERSED_ANIMATION 1472 || currentState == PAUSED_ANIMATION) { 1473 1474 if (animateSensor->isScheduled()) 1475 animateSensor->unschedule(); 1476 currentState = prevState; 1477 refParticleIdx = prevRefIdx; 1478 setSuperimpositionEnabled(superimposition, FALSE); 1479 maxSpeed = 0.0f; 1480 step = 1; 1481 1482 scheduleRedraw(); 1483 if (currentState == VIEWPOINT) { 1484 setSuperimpositionEnabled(superimposition, TRUE); 1485 axisSwitch->whichChild.setValue(SO_SWITCH_NONE); 1486 animSpeedOutlineSwitch->whichChild.setValue( 1487 SO_SWITCH_NONE); 1488 animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE); 1489 1490 scheduleRedraw(); 1491 } 1492 restoreCamera(); 1493 return TRUE; 1494 } 1495 break; 1496 case SoKeyboardEvent::DELETE: 1497 if (viewPtList.size() 1498 && (currentState != ANIMATION 1499 && currentState != REVERSED_ANIMATION 1500 && currentState != PAUSED_ANIMATION)) { 1501 String dialogName = (char *) "Delete Viewpoint"; 1502 std::string msg = "Are you sure you want to delete current viewpoint?"; 1503 warningMsgDialog(msg, dialogName, deleteViewPtCB); 1504 return TRUE; 1505 } 1506 break; 1507 case SoKeyboardEvent::LEFT_ARROW: 1508 switch (currentState) { 1509 case BEAMLINE: 1510 if ((this->lshiftdown) || (this->rshiftdown)){ 1511 refParticleIdx -= step; 1512 moveCamera(); 1513 } 1514 else if ((this->lctrldown) || (this->rctrldown)){ 1515 if (SoXtExaminerViewer::isAnimating()) 1516 stopAnimating(); 1517 prevState = currentState; 1518 currentState = ROTATING; 1519 animateBtwPtsPeriod = 0.08f; 1520 1521 SbVec3f tmp = camDir; 1522 tmp.negate(); 1523 rotAxis = tmp; 1524 1525 rotCnt = ROT_CNT; 1526 moveCamera(); // To make sure camera is perpendicular to the beamline 1527 1528 rotateCamera(); 1529 } 1530 else{ 1531 if (SoXtExaminerViewer::isAnimating()) 1532 stopAnimating(); 1533 prevState = currentState; 1534 currentState = ROTATING; 1535 animateBtwPtsPeriod = 0.08f; 1536 1537 SbVec3f tmp = camUpVec; 1538 tmp.negate(); 1539 rotAxis = tmp; 1540 1541 rotCnt = ROT_CNT; 1542 moveCamera(); // To make sure camera is perpendicular to the beamline 1543 1544 rotateCamera(); 1545 1546 } 1547 return TRUE; 1548 1549 case ANIMATION: 1550 case REVERSED_ANIMATION: 1551 left_right -= 1.5f; 1552 return TRUE; 1553 case PAUSED_ANIMATION: 1554 left_right -= 1.5f; 1555 setStartingPtForAnimation(); 1556 cam->position = myCam->position; 1557 return TRUE; 1558 case GENERAL: 1559 case VIEWPOINT: 1560 if ((!this->lshiftdown) && (!this->rshiftdown)) { 1561 // Using this allows us to look around without 1562 // changing the camera parameters (camDir, camUpVec) 1563 this->bottomWheelMotion( 1564 this->getBottomWheelValue() + 0.1f); 1565 1566 return TRUE; 1567 } 1568 break; 1569 case ROTATING: 1570 // For this state, let the keyboard event 1571 // be handled by superclass 1572 break; 1573 default: 1574 SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent", 1575 "Unhandled viewer state"); 1576 break; 1577 } 1578 break; 1579 1580 case SoKeyboardEvent::RIGHT_ARROW: 1581 switch(currentState){ 1582 case BEAMLINE: 1583 if ((this->lshiftdown) || (this->rshiftdown)){ 1584 refParticleIdx += step; 1585 moveCamera(); 1586 } 1587 else if ((this->lctrldown) || (this->rctrldown)){ 1588 if (SoXtExaminerViewer::isAnimating()) 1589 stopAnimating(); 1590 prevState = currentState; 1591 currentState = ROTATING; 1592 animateBtwPtsPeriod = 0.08f; 1593 1594 rotAxis = camDir; 1595 1596 rotCnt = ROT_CNT; 1597 moveCamera(); // To make sure camera is perpendicular to the beamline 1598 1599 rotateCamera(); 1600 } 1601 else{ 1602 if (SoXtExaminerViewer::isAnimating()) 1603 stopAnimating(); 1604 prevState = currentState; 1605 currentState = ROTATING; 1606 animateBtwPtsPeriod = 0.08f; 1607 1608 rotAxis = camUpVec; 1609 1610 rotCnt = ROT_CNT; 1611 moveCamera(); // To make sure camera is perpendicular to the beamline 1612 1613 rotateCamera(); 1614 } 1615 return TRUE; 1616 1617 case ANIMATION: 1618 case REVERSED_ANIMATION: 1619 left_right += 1.5f; 1620 return TRUE; 1621 case PAUSED_ANIMATION: 1622 left_right += 1.5f; 1623 setStartingPtForAnimation(); 1624 cam->position = myCam->position; 1625 return TRUE; 1626 case GENERAL: 1627 case VIEWPOINT: 1628 if ((!this->lshiftdown) && (!this->rshiftdown)) { 1629 // Using this allows us to look around without 1630 // changing the camera parameters (camDir, camUpVec) 1631 this->bottomWheelMotion( 1632 this->getBottomWheelValue() - 0.1f); 1633 return TRUE; 1634 } 1635 break; 1636 case ROTATING: 1637 // For this state, let the keyboard event 1638 // be handled by superclass 1639 break; 1640 default: 1641 SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent", 1642 "Unhandled viewer state"); 1643 break; 1644 } 1645 break; 1646 1647 case SoKeyboardEvent::DOWN_ARROW: 1648 switch(currentState){ 1649 case BEAMLINE: 1650 1651 if ((this->lshiftdown) || (this->rshiftdown)){ 1652 refParticleIdx -= step; 1653 moveCamera(); 1654 } 1655 else{ 1656 if (SoXtExaminerViewer::isAnimating()) 1657 stopAnimating(); 1658 prevState = currentState; 1659 currentState = ROTATING; 1660 animateBtwPtsPeriod = 0.08f; 1661 1662 rotAxis = camDir.cross(camUpVec); 1663 1664 rotCnt = ROT_CNT; 1665 moveCamera(); // To make sure camera is perpendicular to the beamline 1666 1667 rotateCamera(); 1668 1669 } 1670 return TRUE; 1671 1672 case ANIMATION: 1673 case REVERSED_ANIMATION: 1674 up_down -= 1.5f; 1675 return TRUE; 1676 case PAUSED_ANIMATION: 1677 up_down -= 1.5f; 1678 setStartingPtForAnimation(); 1679 cam->position = myCam->position; 1680 return TRUE; 1681 case GENERAL: 1682 case VIEWPOINT: 1683 // Using this allows us to look around without 1684 // changing the camera parameters (camDir, camUpVec) 1685 if ((!this->lshiftdown) && (!this->rshiftdown)) { 1686 this->leftWheelMotion(this->getLeftWheelValue() - 0.1f); 1687 return TRUE; 1688 } 1689 break; 1690 case ROTATING: 1691 // For this state, let the keyboard event 1692 // be handled by superclass 1693 break; 1694 default: 1695 SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent", 1696 "Unhandled viewer state"); 1697 break; 1698 } 1699 break; 1700 1701 case SoKeyboardEvent::UP_ARROW: 1702 switch(currentState){ 1703 case BEAMLINE: 1704 if ((this->lshiftdown) || (this->rshiftdown)){ 1705 refParticleIdx -= step; 1706 moveCamera(); 1707 } 1708 else{ 1709 if (SoXtExaminerViewer::isAnimating()) 1710 stopAnimating(); 1711 prevState = currentState; 1712 currentState = ROTATING; 1713 animateBtwPtsPeriod = 0.08f; 1714 1715 rotAxis = camUpVec.cross(camDir); 1716 1717 rotCnt = ROT_CNT; 1718 moveCamera(); 1719 1720 rotateCamera(); 1721 1722 1723 } 1724 return TRUE; 1725 case ANIMATION: 1726 case REVERSED_ANIMATION: 1727 up_down += 1.5f; 1728 return TRUE; 1729 case PAUSED_ANIMATION: 1730 up_down += 1.5f; 1731 setStartingPtForAnimation(); 1732 cam->position = myCam->position; 1733 return TRUE; 1734 case GENERAL: 1735 case VIEWPOINT: 1736 // Using this allows us to look around without 1737 // changing the camera parameters (camDir, camUpVec) 1738 if ((!this->lshiftdown) && (!this->rshiftdown)) { 1739 this->leftWheelMotion(this->getLeftWheelValue() + 0.1f); 1740 return TRUE; 1741 } 1742 break; 1743 case ROTATING: 1744 // For this state, let the keyboard event 1745 // be handled by superclass 1746 break; 1747 default: 1748 SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent", 1749 "Unhandled viewer state"); 1750 break; 1751 } 1752 break; 1753 1754 case SoKeyboardEvent::PAGE_UP: 1755 switch(currentState){ 1756 case BEAMLINE: 1757 if (step < (int) refParticleTrajectory.size() / 5) // Magic number 1758 step++; 1759 return TRUE; 1760 case ANIMATION: 1761 incSpeed(); 1762 maxSpeed += SPEED_INDICATOR_STEP; 1763 if (maxSpeed > 0.8) 1764 maxSpeed = MAX_SPEED_INDICATOR; 1765 scheduleRedraw(); 1766 1767 return TRUE; 1768 case REVERSED_ANIMATION: 1769 if(!animateSensor->isScheduled()){ 1770 currentState = ANIMATION; 1771 if (refParticleIdx 1772 < (int) refParticleTrajectory.size() - 1) { 1773 refParticleIdx++; 1774 maxSpeed = SPEED_INDICATOR_STEP; 1775 scheduleRedraw(); 1776 animateRefParticle(); 1777 } 1778 } 1779 else{ 1780 maxSpeed += SPEED_INDICATOR_STEP; 1781 decSpeed(); 1782 scheduleRedraw(); 1783 } 1784 return TRUE; 1785 case PAUSED_ANIMATION: 1786 maxSpeed += SPEED_INDICATOR_STEP; 1787 if (maxSpeed > 0.8) 1788 maxSpeed = MAX_SPEED_INDICATOR; 1789 1790 if (beforePausing == ANIMATION) { 1791 incSpeed(); 1792 } else { 1793 decSpeed(); 1794 if (animateBtwPtsPeriod >= MIN_SPEED) 1795 beforePausing = ANIMATION; 1796 } 1797 1798 scheduleRedraw(); 1799 return TRUE; 1800 default: //fall through 1801 break; 1802 } 1803 break; 1804 1805 case SoKeyboardEvent::PAGE_DOWN: 1806 switch(currentState){ 1807 case BEAMLINE: 1808 if (step > 1) 1809 step--; 1810 return TRUE; 1811 case ANIMATION: 1812 if(!animateSensor->isScheduled()){ 1813 currentState = REVERSED_ANIMATION; 1814 if (refParticleIdx > 1) { 1815 refParticleIdx--; 1816 maxSpeed = -SPEED_INDICATOR_STEP; 1817 scheduleRedraw(); 1818 animateRefParticle(); 1819 } 1820 } 1821 else{ 1822 maxSpeed -= SPEED_INDICATOR_STEP; 1823 decSpeed(); 1824 scheduleRedraw(); 1825 } 1826 return TRUE; 1827 case REVERSED_ANIMATION: 1828 incSpeed(); 1829 maxSpeed -= SPEED_INDICATOR_STEP; 1830 if (maxSpeed < -0.8) 1831 maxSpeed = -MAX_SPEED_INDICATOR; 1832 scheduleRedraw(); 1833 return TRUE; 1834 case PAUSED_ANIMATION: 1835 maxSpeed -= SPEED_INDICATOR_STEP; 1836 if (maxSpeed < -0.8) 1837 maxSpeed = -MAX_SPEED_INDICATOR; 1838 if (beforePausing == REVERSED_ANIMATION) { 1839 incSpeed(); 1840 } else { 1841 decSpeed(); 1842 if (animateBtwPtsPeriod >= MIN_SPEED) 1843 beforePausing = REVERSED_ANIMATION; 1844 } 1845 scheduleRedraw(); 1846 return TRUE; 1847 default: 1848 //fall through 1849 break; 1850 } 1851 break; 1852 1853 case SoKeyboardEvent::E: 1854 this->escapeCallback(this->examinerObject); 1855 break; 1856 1857 default: 1858 break; // To get rid of compiler warnings 1859 } 1860 } 1861 if (SoKeyboardEvent::isKeyReleaseEvent(ev, ke->getKey())) { 1862 switch (ke->getKey()) { 1863 case SoKeyboardEvent::LEFT_SHIFT: 1864 this->lshiftdown = false; 1865 return TRUE; 1866 case SoKeyboardEvent::RIGHT_SHIFT: 1867 this->rshiftdown = false; 1868 return TRUE; 1869 case SoKeyboardEvent::LEFT_CONTROL: 1870 this->lctrldown = false; 1871 return TRUE; 1872 case SoKeyboardEvent::RIGHT_CONTROL: 1873 this->rctrldown = false; 1874 return TRUE; 1875 default: 1876 break; 1877 } 1878 } 1879 } 1880 1881 if (currentState == ANIMATION || currentState == REVERSED_ANIMATION 1882 || currentState == ROTATING) 1883 return FALSE; 1884 else 1885 return SoXtExaminerViewer::processSoEvent(ev); 1886 } 1887 1888 // Called by hitting PageUp during animation. 1889 void G4OpenInventorXtExaminerViewer::incSpeed() { 1890 if (std::ceil(animateBtwPtsPeriod * 100) >= 4) { 1891 if (speedStep > 0.08) 1892 speedStep -= 0.02; 1893 else 1894 speedStep = 0.02; 1895 animateBtwPtsPeriod -= speedStep; 1896 } else 1897 animateBtwPtsPeriod = 0.0; 1898 1899 if (currentState != PAUSED_ANIMATION) { 1900 int lastIdx = refParticleTrajectory.size() - 1; 1901 if (refParticleIdx < lastIdx && !animateSensor->isScheduled()) 1902 animateRefParticle(); 1903 } 1904 } 1905 1906 // Called by hitting PageDown during animation. 1907 void G4OpenInventorXtExaminerViewer::decSpeed() { 1908 animateBtwPtsPeriod += speedStep; 1909 if (animateBtwPtsPeriod < MIN_SPEED) { 1910 if (std::floor(animateBtwPtsPeriod * 100) == 12) { // Errors in double representation 1911 speedStep = 0.08; 1912 } else if (animateBtwPtsPeriod > 0.12) 1913 speedStep += 0.02; 1914 } else { 1915 animateBtwPtsPeriod = MIN_SPEED; 1916 speedStep = START_STEP; 1917 maxSpeed = 0.0f; 1918 if (animateSensor->isScheduled()) 1919 animateSensor->unschedule(); 1920 } 1921 } 1922 1923 // Based on the user's interaction the speed indicator bar needs to be adjusted. 1924 void G4OpenInventorXtExaminerViewer::updateSpeedIndicator(void) { 1925 assert(this->sgeometry != NULL); 1926 1927 SbVec3f * points = this->sgeometry->point.startEditing(); 1928 1929 if (points[10][0] == 0.0f) 1930 this->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_ALL); 1931 if (points[14][0] == 0.0f) 1932 this->animSpeedSwitch->whichChild.setValue(SO_SWITCH_ALL); 1933 points[10][0] = this->maxSpeed; 1934 points[11][0] = this->maxSpeed; 1935 points[14][0] = this->maxSpeed; 1936 points[15][0] = this->maxSpeed; 1937 this->sgeometry->point.finishEditing(); 1938 1939 if (this->maxSpeed == 0.0f) { 1940 this->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE); 1941 this->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE); 1942 } 1943 } 1944 1945 void G4OpenInventorXtExaminerViewer::actualRedraw(void) { 1946 switch (currentState) { 1947 case ANIMATION: 1948 case REVERSED_ANIMATION: 1949 case PAUSED_ANIMATION: 1950 updateSpeedIndicator(); 1951 SoXtExaminerViewer::actualRedraw(); 1952 break; 1953 default: 1954 SoXtExaminerViewer::actualRedraw(); 1955 break; 1956 } 1957 } 1958 1959 void G4OpenInventorXtExaminerViewer::setReferencePath(SoLineSet *lineset, SoCoordinate3 *coords, bool append) 1960 { 1961 // TODO: Color the reference path 1962 // Disable the color stuff for now: changes all trajectories 1963 1964 // // We change the color of the trajectory too, so we get its material 1965 // nodeIndex = grpNode->findChild(trajectory); 1966 // SoMaterial * mat; 1967 // for(int i = 0; i < 100; ++i){ 1968 // --nodeIndex; 1969 // 1970 // tmpNode = grpNode->getChild(nodeIndex); 1971 // if(tmpNode->getTypeId() == SoMaterial::getClassTypeId()){ 1972 // //node found 1973 // mat = (SoMaterial *)tmpNode; 1974 // 1975 // break; 1976 // } 1977 // } 1978 // 1979 // 1980 // // Restore default color for previously picked trajectory 1981 // // and set different color for current pick 1982 // if(This->prevColorField) 1983 // ((SoMFColor *)This->prevColorField)->setValue(0.0, 1.0, 0.0); 1984 // This->prevColorField = (void *)&mat->diffuseColor; 1985 // 1986 // 1987 // if(mat->diffuseColor.isConnected()) 1988 // std::cout << "connected" << std::endl; 1989 // 1990 // mat->diffuseColor.setValue(41.0/255.0, 230.0/255.0, 230.0/255.0); 1991 // 1992 // std::cout << "R: " << mat->diffuseColor[0][0] << " "; 1993 // std::cout << "G: " << mat->diffuseColor[0][1] << " "; 1994 // std::cout << "B: " << mat->diffuseColor[0][2] << std::endl; 1995 1996 // The trajectory is composed of all the polyline segments in the 1997 // multiple value field (SoMFInt32) numVertices. 1998 // For each of the numVertices.getNum()* polyline segments, 1999 // retrieve the points from the SoCoordinate3 node 2000 SbVec3f refParticlePt; 2001 2002 if(!append) 2003 this->refParticleTrajectory.clear(); 2004 2005 for(int i = 0; i < lineset->numVertices.getNum(); ++i){ 2006 for(int j = 0; j < lineset->numVertices[i]; ++j){ 2007 refParticlePt = coords->point[j]; 2008 this->refParticleTrajectory.push_back(refParticlePt); 2009 } 2010 } 2011 // Remove points that are too close to each other 2012 this->evenOutRefParticlePts(); 2013 this->setReferencePathZPos(); 2014 this->sortElements(); 2015 } 2016 2017 2018 void G4OpenInventorXtExaminerViewer::setReferencePathZPos() 2019 { 2020 refZPositions.clear(); 2021 refZPositions.push_back(0); 2022 float dist; 2023 for(unsigned int i=0; i < this->refParticleTrajectory.size() - 1; ++i){ 2024 dist = (refParticleTrajectory[i] - 2025 refParticleTrajectory[i + 1]).length(); 2026 refZPositions.push_back(refZPositions[i] + dist); 2027 } 2028 } 2029 2030 2031 void G4OpenInventorXtExaminerViewer::findAndSetRefPath() 2032 { 2033 SoSearchAction action; 2034 action.setType(SoLineSet::getClassTypeId(),false); 2035 action.setInterest(SoSearchAction::ALL); 2036 action.apply(this->getSceneGraph()); 2037 2038 SoPathList &pathList = action.getPaths(); 2039 2040 if(pathList.getLength() != 0){ 2041 2042 SoCoordinate3 * coords = NULL; 2043 std::vector<SoCoordinate3 *> coordvec; 2044 std::vector<SoLineSet *> linevec; 2045 2046 bool refPathFound = false; 2047 for(int i = 0; i < pathList.getLength(); ++i) { 2048 SoFullPath *path = (SoFullPath *)pathList[i]; 2049 2050 G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(path->getTail()); 2051 for (size_t j = 0; j < attHolder->GetAttDefs().size(); ++j) { 2052 std::ostringstream oss; 2053 oss << G4AttCheck(attHolder->GetAttValues()[j], attHolder->GetAttDefs()[j]); 2054 2055 std::string findStr = "Type of trajectory (Type): "; 2056 std::string compareValue = "REFERENCE"; 2057 size_t idx = oss.str().find(findStr); 2058 2059 if(idx != std::string::npos) { 2060 if(oss.str().substr(idx + findStr.size(), compareValue.size()) == compareValue) { 2061 coords = this->getCoordsNode(path); 2062 if(coords != NULL){ 2063 refPathFound = true; 2064 coordvec.push_back(coords); 2065 linevec.push_back((SoLineSet *)path->getTail()); 2066 } 2067 break; 2068 } 2069 } 2070 2071 findStr = "Track ID (ID): "; 2072 idx = oss.str().find(findStr); 2073 if(idx != std::string::npos) { 2074 //index all primary tracks 2075 std::string tmpstr = oss.str().substr(idx + findStr.size(),1); 2076 std::istringstream buffer(tmpstr); 2077 int num; 2078 buffer >> num; 2079 if(num == 1) { 2080 2081 // Check if next character is a number, 2082 // in which case we don't have Track ID 1 2083 // FWJ attempt to fix Coverity issue. 2084 char nextChar = oss.str().at(idx+findStr.size()+1); 2085 // const char * nextChar = 2086 // oss.str().substr(idx + findStr.size() + 1,1).c_str(); 2087 if(std::isdigit(nextChar)) 2088 // if(std::isdigit(nextChar[0])) 2089 break; //Not a primary track, continue with next track 2090 2091 coords = this->getCoordsNode(path); 2092 if(coords != NULL){ 2093 coordvec.push_back(coords); 2094 linevec.push_back((SoLineSet *)path->getTail()); 2095 break; //Found coords node, continue with next track 2096 } 2097 } 2098 else 2099 break; //Not a primary track, continue with next track 2100 } 2101 else{ 2102 //Not a Track ID attribute, fall through 2103 } 2104 } 2105 2106 if(refPathFound) 2107 break; 2108 } 2109 2110 if(coordvec.empty()) 2111 return; //No track with a Coordinate3 node found 2112 2113 if(refPathFound){ 2114 //set ref path to last traj, coord in the vecs 2115 this->setReferencePath(linevec.back(), coordvec.back()); 2116 return; 2117 } 2118 //else 2119 2120 int longestIdx = 0; 2121 float longestLength = 0.0; 2122 // For all paths 2123 for(unsigned int i=0;i < linevec.size(); ++i){ 2124 2125 //First generate a vector with all the points in this lineset 2126 std::vector<SbVec3f> trajectory; 2127 // For all lines in the i path 2128 for(int j=0; j < linevec[i]->numVertices.getNum(); ++j){ 2129 // For all points in line j 2130 for(int k=0; k < linevec[i]->numVertices[j]; ++k){ 2131 trajectory.push_back(coordvec[i]->point[k]); 2132 } 2133 } 2134 2135 // Then calculate the total length 2136 float tmpLength=0.0; 2137 for(unsigned int j=0; j < trajectory.size() - 1; ++j){ 2138 tmpLength += (trajectory[j] - trajectory[j + 1]).length(); 2139 } 2140 2141 if(tmpLength > longestLength){ 2142 longestIdx = i; 2143 longestLength = tmpLength; 2144 } 2145 } 2146 2147 // Set the longest path as the reference path 2148 this->setReferencePath(linevec[longestIdx], coordvec[longestIdx]); 2149 } 2150 } 2151 2152 2153 SoCoordinate3 * G4OpenInventorXtExaminerViewer::getCoordsNode(SoFullPath *path) 2154 { 2155 SoLineSet *trajectory = (SoLineSet *)path->getTail(); 2156 SoSeparator * grpNode = (SoSeparator*)(((SoFullPath*)path)->getNodeFromTail(1)); 2157 int nodeIndex = grpNode->findChild(trajectory); 2158 SoNode * tmpNode; 2159 2160 // We allow only 100 iterations, in case the node isn't found 2161 // (should take only a few iterations) 2162 for(int i = 0; i < 100; ++i){ 2163 --nodeIndex; 2164 2165 tmpNode = grpNode->getChild(nodeIndex); 2166 if(tmpNode->getTypeId() == SoCoordinate3::getClassTypeId()){ 2167 //node found 2168 return (SoCoordinate3 *)tmpNode; 2169 } 2170 } 2171 return NULL; //coords node not found 2172 } 2173 2174 2175 // Displays scene elements on the right side of listsDialog. 2176 // else: scene graph is searched for Geant4_SoPolyhedron type nodes 2177 void G4OpenInventorXtExaminerViewer::getSceneElements() 2178 { 2179 std::string field, eltName; 2180 2181 std::map<std::string, int> duplicates; 2182 std::map<std::string, int> sceneElts; 2183 SoSearchAction search; 2184 Geant4_SoPolyhedron *node; 2185 SoGroup *root = (SoGroup *)getSceneManager()->getSceneGraph(); 2186 2187 SoBaseKit::setSearchingChildren(TRUE); 2188 2189 search.reset(); 2190 search.setSearchingAll(TRUE); 2191 search.setInterest(SoSearchAction::ALL); 2192 search.setType(Geant4_SoPolyhedron::getClassTypeId(), 0); 2193 search.apply(root); 2194 2195 SoPathList &pl = search.getPaths(); 2196 2197 2198 // First find which names occur more than once so we can append a counter to them 2199 for(int i = 0; i < pl.getLength(); i++) { 2200 SoFullPath *path = (SoFullPath *)pl[i]; 2201 node = (Geant4_SoPolyhedron *)path->getTail(); 2202 eltName = node->getName(); 2203 if(duplicates.count(eltName)) 2204 duplicates[eltName]++; 2205 else 2206 duplicates[eltName] = 1; 2207 } 2208 2209 for(int i = 0; i < pl.getLength(); i++) { 2210 float x,y,z; 2211 std::stringstream ssCount; 2212 SoFullPath *path = (SoFullPath *)pl[i]; 2213 node = (Geant4_SoPolyhedron *)path->getTail(); 2214 eltName = node->getName(); 2215 field = eltName; 2216 if(duplicates[eltName] == 1) 2217 ssCount << "";//duplicates[field] 2218 else { 2219 if(sceneElts.count(eltName)) 2220 sceneElts[eltName]++; 2221 else 2222 sceneElts[eltName] = 1; 2223 2224 ssCount << sceneElts[eltName]; 2225 field += "_"; 2226 } 2227 2228 field += ssCount.str(); 2229 2230 SoGetBoundingBoxAction bAction(getViewportRegion()); 2231 bAction.apply(path); 2232 SbBox3f bBox = bAction.getBoundingBox(); 2233 2234 SbVec3f centr = bBox.getCenter(); 2235 centr.getValue(x,y,z); 2236 2237 path->ref(); 2238 sceneElement el = { field, path, centr, 0.0 }; 2239 this->sceneElements.push_back(el); 2240 } 2241 } 2242 2243 2244 float G4OpenInventorXtExaminerViewer::sqrlen(const SbVec3f &a) 2245 { 2246 float x,y,z; 2247 a.getValue(x,y,z); 2248 return x*x + y*y + z*z; 2249 } 2250 2251 2252 void G4OpenInventorXtExaminerViewer::distanceToTrajectory(const SbVec3f &q, 2253 float &dist, 2254 SbVec3f &closestPoint, 2255 int &index) 2256 { 2257 // a : Previous point on trajectory 2258 // b : Next point on trajectory 2259 // q : the point in space 2260 // dab, daq, dbq: distance between a & b, a & q, b & q 2261 // 2262 // Theory: A point p on a line ab is defined as: 2263 // 2264 // p(t) = a+t⋅(b–a) 2265 // 2266 // note: All are vectors except the parameter t 2267 // 2268 // When t is between 0 and 1 the point p is situated between a and b on ab. 2269 // The point p is defined in terms of the parameter t, subsequently so does 2270 // the distance from the query point q to the point p. To find the minimum 2271 // of that distance we differentiate it and set equal to zero: 2272 // 2273 // diff(Norm(p(t)- q)) = 0 2274 // 2275 // note: diff means taking the derivative with regard to t 2276 // 2277 // The resulting t is given in the code below. The square of the distance 2278 // between p and q is given by: 2279 // 2280 // d^2 = (Norm(p(t)-q))^2 2281 // 2282 // The expression found is given in the code below (current_dist) 2283 // 2284 // Ref: http://programmizm.sourceforge.net/blog/2012/ 2285 // distance-from-a-point-to-a-polyline 2286 // 2287 // --PLG 2288 2289 const size_t count = this->refParticleTrajectory.size(); 2290 assert(count>0); 2291 2292 SbVec3f b = this->refParticleTrajectory[0]; 2293 SbVec3f dbq = b - q; 2294 float sqrDist = sqrlen(dbq); 2295 closestPoint = b; 2296 index = 0; 2297 for (size_t i = 1; i < count; ++i) { 2298 const SbVec3f a = b; 2299 const SbVec3f daq = dbq; 2300 b = this->refParticleTrajectory[i]; 2301 dbq = b - q; 2302 const SbVec3f dab = a - b; 2303 2304 float dab_x, dab_y, dab_z; 2305 dab.getValue(dab_x,dab_y,dab_z); 2306 float daq_x, daq_y, daq_z; 2307 daq.getValue(daq_x, daq_y, daq_z); 2308 float dbq_x, dbq_y, dbq_z; 2309 dbq.getValue(dbq_x, dbq_y, dbq_z); 2310 2311 const float inv_sqrlen = 1./sqrlen(dab); 2312 const float t = (dab_x*daq_x + dab_y*daq_y + dab_z*daq_z)*inv_sqrlen; 2313 2314 if (t<0.){ 2315 // The trajectory point occurs before point a 2316 // Go to the next point 2317 continue; 2318 } 2319 float current_dist; 2320 if (t<=1.){ 2321 // The trajectory point occurs between a and b. 2322 // Compute the distance to that point 2323 current_dist = daq_x*daq_x + daq_y*daq_y + daq_z*daq_z 2324 - t*(daq_x*dab_x + daq_y*dab_y + daq_z*dab_z) 2325 + t*t*(dab_x*dab_x + dab_y*dab_y + dab_z*dab_z); 2326 } 2327 else { //t>1. 2328 // The trajectory point occurs after b. 2329 // Get the distance to point b 2330 current_dist = sqrlen(dbq); 2331 } 2332 2333 if (current_dist < sqrDist){ 2334 sqrDist = current_dist; 2335 closestPoint = a + t*(b-a); 2336 index = i; 2337 } 2338 } 2339 2340 dist = std::sqrt(sqrDist); 2341 } 2342 2343 2344 void G4OpenInventorXtExaminerViewer::sortElements() 2345 { 2346 if(this->refParticleTrajectory.empty()) 2347 return; 2348 2349 float * trajLength = new float[this->refParticleTrajectory.size()]; 2350 typedef std::map<elementForSorting, sceneElement> sortedMap; 2351 sortedMap sorted; 2352 2353 // For every point on the reference trajectory, compute 2354 // the total length from the start 2355 SbVec3f prevPoint; 2356 std::vector<SbVec3f>::iterator itRef = this->refParticleTrajectory.begin(); 2357 int trajIndex = 0; 2358 prevPoint = *itRef; 2359 trajLength[trajIndex] = 0.0; 2360 ++itRef; 2361 ++trajIndex; 2362 for(; itRef != this->refParticleTrajectory.end(); ++itRef, ++trajIndex){ 2363 trajLength[trajIndex] = trajLength[trajIndex-1] + (*itRef - prevPoint).length(); 2364 prevPoint = *itRef; 2365 } 2366 2367 // Compute the smallest distance between the element 2368 // and the reference trajectory (find the closest point), 2369 // then map the element to the trajectory length of that 2370 // point (calculated above) 2371 SoGetBoundingBoxAction bAction(this->getViewportRegion()); 2372 SbVec3f elementCoord; 2373 std::vector<sceneElement>::iterator itEl; 2374 int elementIndex; 2375 elementForSorting el; 2376 for(itEl = this->sceneElements.begin(), elementIndex = 0; 2377 itEl != this->sceneElements.end(); ++itEl, ++elementIndex){ 2378 bAction.apply(itEl->path); 2379 2380 // FWJ sceneElement already has a center 2381 elementCoord = itEl->center; 2382 // ... and this sometimes returns an empty box! 2383 // elementCoord = bAction.getBoundingBox().getCenter(); 2384 // if (bAction.getBoundingBox().isEmpty()) { 2385 // G4cout << "sortElements: Box is empty!" << G4endl; 2386 // G4cout << " element name=" << itEl->name << G4endl; 2387 // } 2388 2389 int index; 2390 distanceToTrajectory(elementCoord, el.smallestDistance, el.closestPoint, index); 2391 itEl->closestPointZCoord = el.closestPointZCoord = trajLength[index]; 2392 el.distanceToBeamlineStart = (itEl->center - this->refParticleTrajectory[0]).length(); 2393 2394 // This map of the scene elements (or their coordinates rather) 2395 // is automatically sorted by trajectory length (Z coord), then 2396 // by the distance between the element and the point in case the Z coord 2397 // is the same as another element. This is done by using as a key 2398 // an element structure which implements the operator for weak ordering 2399 sorted.insert(std::make_pair(el,*itEl)); 2400 } 2401 2402 // store the sorted elements into the vector field 2403 this->sceneElements.clear(); 2404 2405 sortedMap::iterator itSorted = sorted.begin(); 2406 for(; itSorted != sorted.end(); itSorted++) 2407 this->sceneElements.push_back(itSorted->second); 2408 2409 this->zcoordSetFlag = true; 2410 2411 2412 Widget formTop = XtNameToWidget(this->listsDialog, "FormTop"); 2413 Widget formTopRight = XtNameToWidget(formTop, "FormTopRight"); 2414 2415 this->createElementsList(formTopRight); 2416 2417 delete[] trajLength; 2418 } 2419 2420 2421 void G4OpenInventorXtExaminerViewer::createElementsList(Widget formTopRight) 2422 { 2423 if(this->myElementList != NULL) 2424 XtUnmanageChild(this->myElementList); 2425 2426 int size = this->sceneElements.size(); 2427 XmString *elements = (XmString *) XtMalloc(size * sizeof(XmString)); 2428 2429 std::vector<sceneElement>::const_iterator it; 2430 int count = 0; 2431 std::stringstream ss; 2432 for(it=this->sceneElements.begin(); it!=this->sceneElements.end(); ++it) { 2433 ss << it->name; 2434 if(zcoordSetFlag) 2435 ss << " [" << it->closestPointZCoord << "]"; 2436 elements[count] = XmStringCreateLocalized((char *)ss.str().c_str()); 2437 ++count; 2438 ss.str(""); 2439 } 2440 2441 Arg args[10]; 2442 int n; 2443 2444 // Label Right 2445 n = 0; 2446 Widget labelRight; 2447 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; 2448 2449 labelRight = XmCreateLabelGadget(formTopRight, (char*)"Element [S mm]", 2450 args, n); 2451 XtManageChild(labelRight); 2452 2453 // List Right 2454 n = 0; 2455 XtSetArg(args[n], XmNvisibleItemCount, 7); n++; 2456 XtSetArg(args[n], XmNitemCount, size); n++; 2457 XtSetArg(args[n], XmNitems, elements); n++; 2458 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++; 2459 XtSetArg(args[n], XmNtopWidget, labelRight); n++; 2460 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; 2461 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; 2462 // FWJ 2463 XtSetArg(args[n], XmNwidth, 240); n++; 2464 // XtSetArg(args[n], XmNwidth, 280); n++; 2465 // XtSetArg(args[n], XmNwidth, 300); n++; 2466 2467 this->myElementList = XmCreateScrolledList(formTopRight, (char *) "ListRight", args, n); 2468 2469 XtAddCallback(this->myElementList, XmNbrowseSelectionCallback, 2470 (XtCallbackProc) lookAtSceneElementCB, this); 2471 xmAddMouseEventHandler(this->myElementList); // Add scrolling functionality 2472 XtManageChild(this->myElementList); 2473 2474 if (elements != NULL) { 2475 for (int i = 0; i < size; i++) 2476 XmStringFree(elements[i]); 2477 XtFree((char *) elements); 2478 } 2479 } 2480 2481 2482 // Pops up a custom dialog listsDialog containing 2483 // scene elements and viewpoints. 2484 2485 void G4OpenInventorXtExaminerViewer::constructListsDialog(Widget w, 2486 XtPointer client_data, 2487 XtPointer) 2488 { 2489 // G4cout << "DEBUG constructListsDialog w = " << w << G4endl; 2490 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 2491 if (This->listsDialog) { 2492 return; 2493 } 2494 2495 if (This->currentState == ANIMATION || This->currentState == PAUSED_ANIMATION) { 2496 if (This->animateSensor->isScheduled()) 2497 This->animateSensor->unschedule(); 2498 This->refParticleIdx = This->prevRefIdx; 2499 This->restoreCamera(); 2500 This->currentState = This->prevState; 2501 } 2502 2503 This->step = 1; // Default values 2504 This->refParticleIdx = 0; 2505 if (This->refParticleTrajectory.size()){ 2506 This->prevPt = This->refParticleTrajectory[0]; // For calculating distance 2507 } 2508 2509 This->getSceneElements(); 2510 2511 int n = 0; 2512 Arg args[10]; 2513 Atom WM_DELETE_WINDOW; 2514 2515 ///////////////////////CUSTOM listsDialog/////////////////////////////// 2516 2517 Widget topShell; 2518 // FWJ gets the topmost window containing This->getParentWidget() 2519 // This is unnecessary because the parent is passed in 2520 // topShell = SoXt::getShellWidget(This->getParentWidget()); 2521 topShell = w; 2522 // G4cout << "DEBUG PARENT (topShell) FOR AUX WINDOW = " << topShell << G4endl; 2523 2524 // Shell Dialog 2525 std::string dialogNameStr = This->fileName.substr(This->fileName.rfind('/') + 1); 2526 const int nDialog = dialogNameStr.size() + 1; 2527 char *dialogName = new char[nDialog]; 2528 strncpy(dialogName, dialogNameStr.c_str(), nDialog); 2529 2530 n = 0; 2531 XtSetArg(args[n], XmNx, 610); n++; 2532 This->myShellDialog = XmCreateDialogShell(topShell, dialogName, args, n); 2533 2534 delete[] dialogName; 2535 WM_DELETE_WINDOW = XInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", False); 2536 XmAddWMProtocolCallback(This->myShellDialog, WM_DELETE_WINDOW, 2537 (XtCallbackProc)closeListsDialogCB, This); 2538 2539 // Main Pane(listsDialog) 2540 n = 0; 2541 XtSetArg(args[n], XmNsashWidth, 1); n++; 2542 XtSetArg(args[n], XmNsashHeight, 1); n++; 2543 XtSetArg(args[n], XmNseparatorOn, False); n++; 2544 // FWJ 2545 This->listsDialog = XmCreatePanedWindow(This->myShellDialog, (char *) "MainPane", 2546 args, n); 2547 2548 2549 ////////////////////////TOP FORM////////////////////////// 2550 n = 0; 2551 // FWJ fails compile 2552 // Widget formTop = XmCreateForm(This, (char *) "FormTop", args, n); 2553 Widget formTop = XmCreateForm(This->listsDialog, (char *) "FormTop", args, n); 2554 2555 n = 0; 2556 XtSetArg(args[n], XmNmarginWidth, 8); n++; 2557 XtSetArg(args[n], XmNmarginHeight, 8); n++; 2558 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; 2559 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; 2560 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; 2561 Widget formTopRight = XmCreateForm(formTop, (char *) "FormTopRight", args, 2562 n); 2563 2564 n = 0; 2565 XtSetArg(args[n], XmNmarginWidth, 8); n++; 2566 XtSetArg(args[n], XmNmarginHeight, 8); n++; 2567 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; 2568 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; 2569 XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++; 2570 XtSetArg(args[n], XmNrightWidget, formTopRight); n++; 2571 XtSetArg(args[n], XmNrightOffset, 10); n++; 2572 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; 2573 Widget formTopLeft = XmCreateForm(formTop, (char *) "FormTopLeft", args, n); 2574 2575 /////TOP RIGHT///// 2576 2577 This->createElementsList(formTopRight); 2578 XtManageChild(formTopRight); 2579 2580 /////TOP LEFT///// 2581 2582 // Label Left 2583 n = 0; 2584 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; 2585 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; 2586 Widget labelLeft = XmCreateLabelGadget(formTopLeft, (char *) "ViewPoints", 2587 args, n); 2588 XtManageChild(labelLeft); 2589 2590 // List Left 2591 n = 0; 2592 XtSetArg(args[n], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE); n++; 2593 XtSetArg(args[n], XmNvisibleItemCount, 7); n++; 2594 // XtSetArg(args[n], XmNwidth, 140); n++; 2595 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++; 2596 XtSetArg(args[n], XmNtopWidget, labelLeft); n++; 2597 XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++; 2598 XtSetArg(args[n], XmNrightWidget, This->myElementList); n++; 2599 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; 2600 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; 2601 // FWJ 2602 XtSetArg(args[n], XmNwidth, 160); n++; 2603 // XtSetArg(args[n], XmNwidth, 200); n++; 2604 2605 This->myViewPtList = XmCreateScrolledList(formTopLeft, (char *) "ListLeft", 2606 args, n); 2607 if (This->viewPtList.size()) 2608 This->addViewPoints(); 2609 XtAddCallback(This->myViewPtList, XmNbrowseSelectionCallback, 2610 (XtCallbackProc) loadBookmarkCB, This); 2611 xmAddMouseEventHandler(This->myViewPtList); // Add scrolling functionality 2612 2613 XtManageChild(This->myViewPtList); 2614 2615 XtManageChild(formTopLeft); 2616 2617 XtManageChild(formTop); 2618 2619 ////////////////////MIDDLE FORM/////////////////////////// 2620 n = 0; 2621 XtSetArg(args[n], XmNmarginWidth, 6); n++; 2622 // FWJ fails compile 2623 // Widget formMiddle = XmCreateForm(This->canvas, (char *) "MiddleForm", args, n); 2624 Widget formMiddle = XmCreateForm(This->listsDialog, (char *) "MiddleForm", args, n); 2625 2626 // Label 2627 n = 0; 2628 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; 2629 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++; 2630 XtSetArg(args[n], XmNtopWidget, This->myViewPtList); n++; 2631 Widget label = XmCreateLabelGadget(formMiddle, (char *) "Selection", args, 2632 n); 2633 XtManageChild(label); 2634 2635 // Text 2636 n = 0; 2637 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; 2638 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; 2639 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++; 2640 XtSetArg(args[n], XmNtopWidget, label); n++; 2641 XtSetArg(args[n], XmNtopOffset, 3); n++; 2642 XtSetArg(args[n], XmNmaxLength, This->MAX_VP_NAME); n++; 2643 This->viewPtSelection = XmCreateText(formMiddle, (char *) "Txt", args, n); 2644 XtManageChild(This->viewPtSelection); 2645 2646 Dimension h1, h2, h; 2647 XtVaGetValues(label, XmNheight, &h1, NULL); 2648 XtVaGetValues(This->viewPtSelection, XmNheight, &h2, NULL); 2649 2650 h = (Dimension) (1.1 * (h1 + h2)); 2651 2652 XtVaSetValues(formMiddle, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL); 2653 XtManageChild(formMiddle); 2654 2655 /////////////////////BOTTOM FORM/////////////////////////// 2656 // Action Area Form 2657 n = 0; 2658 XtSetArg(args[n], XmNfractionBase, 4); n++; 2659 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++; 2660 XtSetArg(args[n], XmNtopWidget, This->viewPtSelection); n++; 2661 // FWJ fails compile 2662 // Widget formAction = XmCreateForm(This, (char *) "ActionForm", args, n); 2663 Widget formAction = XmCreateForm(This->listsDialog, (char *) "ActionForm", args, n); 2664 2665 n = 0; 2666 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; 2667 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; 2668 XtSetArg(args[n], XmNtopOffset, 3); n++; 2669 XtSetArg(args[n], XmNbottomOffset, 5); n++; 2670 Widget separator = XmCreateSeparatorGadget(formAction, (char *) "Sep", args, n); 2671 2672 XtManageChild(separator); 2673 2674 Widget button = XmCreatePushButton(formAction, (char *) "Delete", NULL, 0); 2675 XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, 2676 separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, 2677 XmATTACH_POSITION, XmNleftPosition, 0, XmNrightAttachment, 2678 XmATTACH_POSITION, XmNrightPosition, 1, 2679 XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30, 2680 NULL); 2681 2682 XtAddCallback(button, XmNactivateCallback, 2683 (XtCallbackProc) deleteBookmarkCB, This); 2684 XtManageChild(button); 2685 2686 button = XmCreatePushButton(formAction, (char *) "Rename", NULL, 0); 2687 XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, 2688 separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, 2689 XmATTACH_POSITION, XmNleftPosition, 1, XmNrightAttachment, 2690 XmATTACH_POSITION, XmNrightPosition, 2, 2691 XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30, 2692 NULL); 2693 2694 XtAddCallback(button, XmNactivateCallback, 2695 (XtCallbackProc) renameBookmarkCB, This); 2696 XtManageChild(button); 2697 2698 button = XmCreatePushButton(formAction, (char *) "Sort", NULL, 0); 2699 XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, 2700 separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, 2701 XmATTACH_POSITION, XmNleftPosition, 2, XmNrightAttachment, 2702 XmATTACH_POSITION, XmNrightPosition, 3, 2703 XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30, 2704 NULL); 2705 2706 XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) sortBookmarksCB, This); 2707 XtManageChild(button); 2708 2709 button = XmCreatePushButton(formAction, (char *) "Close", NULL, 0); 2710 XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, 2711 separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, 2712 XmATTACH_POSITION, XmNleftPosition, 3, XmNrightAttachment, 2713 XmATTACH_POSITION, XmNrightPosition, 4, 2714 XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30, 2715 NULL); 2716 2717 XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) closeListsDialogCB, This); 2718 XtManageChild(button); 2719 2720 XtManageChild(formAction); 2721 XtVaGetValues(button, XmNheight, &h1, NULL); 2722 XtVaSetValues(formAction, XmNpaneMaximum, h1, XmNpaneMinimum, h1, NULL); 2723 2724 XtManageChild(This->listsDialog); 2725 2726 ////////////////////////CUSTOM listsDialog/////////////////////////////// 2727 } 2728 2729 2730 // Called when user clicks a scene element in listsDialog. 2731 // Zooms onto that element. 2732 void G4OpenInventorXtExaminerViewer::lookAtSceneElementCB(Widget, 2733 XtPointer client_data, 2734 XtPointer call_data) 2735 { 2736 char *value; 2737 std::string elementField; 2738 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 2739 SoCamera * cam = This->getCamera(); 2740 2741 if (This->SoXtExaminerViewer::isAnimating()) 2742 This->stopAnimating(); 2743 2744 XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data; 2745 2746 value = (char *) XmStringUnparse(cbs->item, XmFONTLIST_DEFAULT_TAG, 2747 XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); 2748 if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION 2749 || This->currentState == PAUSED_ANIMATION ) { 2750 if (This->animateSensor->isScheduled()) 2751 This->animateSensor->unschedule(); 2752 This->setSuperimpositionEnabled(This->superimposition, FALSE); 2753 This->maxSpeed = 0.0f; 2754 This->scheduleRedraw(); 2755 This->restoreCamera(); 2756 This->currentState = This->prevState; 2757 } else if (This->currentState == VIEWPOINT) 2758 This->setSuperimpositionEnabled(This->superimposition, FALSE); 2759 2760 elementField = value; 2761 2762 int idx = elementField.find_last_of("["); 2763 if(idx == -1) 2764 idx = elementField.size(); //if "[" not found for whatever reason (list not sorted) 2765 else 2766 idx--; // To get rid of the space that is between the name and '[' 2767 2768 bool error = false; 2769 SoFullPath *path; 2770 SoSearchAction search; 2771 SoNode *root = This->getSceneManager()->getSceneGraph(); 2772 int counter(1), idxUnderscore = elementField.find_last_of("_"); 2773 2774 This->parseString<int>(counter, elementField.substr(idxUnderscore + 1, idx), error); 2775 2776 SoBaseKit::setSearchingChildren(TRUE); 2777 search.reset(); 2778 search.setSearchingAll(TRUE); 2779 2780 if(error) { // No counter is present => element name was not modified 2781 This->curEltName = elementField.substr(0, idx); 2782 search.setName(This->curEltName.c_str()); 2783 search.apply(root); 2784 2785 path = (SoFullPath *)search.getPath(); 2786 } 2787 else { 2788 This->curEltName = elementField.substr(0, idxUnderscore); 2789 search.setInterest(SoSearchAction::ALL); 2790 search.setName(This->curEltName.c_str()); 2791 search.apply(root); 2792 2793 SoPathList &pl = search.getPaths(); 2794 path = (SoFullPath *)pl[counter - 1]; // Since counter starts at 1, not 0 2795 } 2796 2797 G4ThreeVector global; 2798 2799 if ((idx > 0) && (path)) { 2800 2801 if(!This->refParticleTrajectory.empty()){ 2802 2803 SoGetBoundingBoxAction bAction(This->getViewportRegion()); 2804 bAction.apply(path); 2805 SbBox3f bBox = bAction.getBoundingBox(); 2806 SbVec3f elementCoord = bBox.getCenter(); 2807 2808 This->refParticleIdx = 0; 2809 SbVec3f p; 2810 2811 float absLengthNow, absLengthMin; 2812 int maxIdx = This->refParticleTrajectory.size() - 2; 2813 int targetIdx = 0; 2814 SbVec3f dir; 2815 2816 p = This->refParticleTrajectory[This->refParticleIdx]; 2817 absLengthMin = (p - elementCoord).length(); 2818 This->refParticleIdx++; 2819 2820 // Find a ref. particle's point closest to element's global coords 2821 while (This->refParticleIdx < maxIdx) { 2822 p = This->refParticleTrajectory[This->refParticleIdx]; 2823 absLengthNow = (p - elementCoord).length(); 2824 2825 if (absLengthNow < absLengthMin) { 2826 absLengthMin = absLengthNow; 2827 targetIdx = This->refParticleIdx; 2828 } 2829 This->refParticleIdx++; 2830 } 2831 2832 if (This->currentState != BEAMLINE) { // Set up default zoom 2833 SbVec3f p1, pN; 2834 This->currentState = BEAMLINE; 2835 This->prevParticleDir = SbVec3f(0,0,0); //so that moveCamera() knows sets default parameters 2836 2837 p1 = This->prevPt = This->refParticleTrajectory[0]; 2838 pN = This->refParticleTrajectory[This->refParticleTrajectory.size() - 1]; 2839 This->distance = (pN - p1).length() / 10; 2840 2841 // FWJ Rather than switching to a default height, it is more flexible 2842 // to keep the same height(magnification) while moving the camera. 2843 // if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) { 2844 // ((SoOrthographicCamera *) cam)->height.setValue(This->defaultHeight); 2845 // // FWJ Restore the default height instead of hard-wired value 2846 // // ((SoOrthographicCamera *) cam)->height.setValue(10000.0f); 2847 // } 2848 // else if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) 2849 2850 // FWJ required to avoid extreme perspective after camera move: 2851 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) 2852 ((SoPerspectiveCamera*)cam)->heightAngle.setValue(This->defaultHeightAngle); 2853 2854 } else { 2855 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) 2856 This->distance = (This->prevPt - cam->position.getValue()).length(); 2857 } 2858 This->refParticleIdx = targetIdx; 2859 2860 ////////////////////////////////////////////////////////////// 2861 This->setSuperimpositionEnabled(This->superimposition, TRUE); 2862 This->axisSwitch->whichChild.setValue(SO_SWITCH_NONE); 2863 This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE); 2864 This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE); 2865 This->scheduleRedraw(); 2866 ////////////////////////////////////////////////////////////// 2867 2868 This->moveCamera(This->distance); 2869 XtFree(value); 2870 2871 } 2872 2873 else{ 2874 This->offsetFromCenter.setValue(0, 0, 1); 2875 This->distance = 50;// small number since using viewAll() for default zoom 2876 This->upVector.setValue(0, 1, 0); 2877 This->moveCamera(This->distance); 2878 cam->viewAll(path, This->getViewportRegion()); 2879 } 2880 } 2881 2882 XmTextSetString(This->viewPtSelection, NULL); 2883 } 2884 2885 2886 // Destroyes listsDialog and resets necessary member fields. 2887 2888 void G4OpenInventorXtExaminerViewer::closeListsDialogCB(Widget, 2889 XtPointer client_data, 2890 XtPointer) 2891 { 2892 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 2893 2894 This->sceneElements.clear(); 2895 This->refParticleTrajectory.clear(); 2896 2897 This->currentState = GENERAL; 2898 XtDestroyWidget(This->myShellDialog); 2899 This->listsDialog = NULL; 2900 } 2901 2902 // Called when user clicks left arrow button. Loads previous viewpoint. 2903 void G4OpenInventorXtExaminerViewer::prevViewPtCB(Widget, XtPointer client_data, 2904 XtPointer) { 2905 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 2906 2907 if (This->viewPtIdx == 0) 2908 This->viewPtIdx = This->viewPtList.size() - 1; 2909 else 2910 This->viewPtIdx--; 2911 2912 This->writeViewPtIdx(); 2913 This->setViewPt(); 2914 } 2915 2916 // Called when user clicks right arrow button. Loads next viewpoint. 2917 void G4OpenInventorXtExaminerViewer::nextViewPtCB(Widget, XtPointer client_data, 2918 XtPointer) { 2919 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 2920 2921 if (This->viewPtIdx >= (int) This->viewPtList.size() - 1) 2922 This->viewPtIdx = 0; 2923 else 2924 This->viewPtIdx++; 2925 2926 This->writeViewPtIdx(); 2927 This->setViewPt(); 2928 } 2929 2930 2931 // Updates the viewPtIdx in a viewpoint file. 2932 2933 void G4OpenInventorXtExaminerViewer::writeViewPtIdx() 2934 { 2935 std::string idxStr; 2936 std::stringstream out; 2937 out << viewPtIdx; 2938 idxStr = out.str(); 2939 fileOut.seekp(0, std::ios::beg); 2940 2941 while ((int) idxStr.length() < MAX_VP_IDX) { 2942 idxStr += " "; 2943 } 2944 2945 fileOut << idxStr << "\n"; 2946 fileOut.flush(); 2947 fileOut.seekp(0, std::ios::end); 2948 } 2949 2950 2951 // Sets the viewpoint based on camera data that viewPtIdx is pointing to. 2952 2953 void G4OpenInventorXtExaminerViewer::setViewPt() 2954 { 2955 if (currentState == ANIMATION || currentState == REVERSED_ANIMATION 2956 || currentState == ROTATING) { 2957 2958 if (animateSensor->isScheduled()) 2959 animateSensor->unschedule(); 2960 setSuperimpositionEnabled(superimposition, FALSE); 2961 maxSpeed = 0.0f; 2962 scheduleRedraw(); 2963 } 2964 2965 SoCamera * camera = getCamera(); 2966 if (camera == NULL) { 2967 String dialogName = (char *) "Missing Camera Node"; 2968 std::string msg = "Camera is null. Unable to set the viewpoint."; 2969 warningMsgDialog(msg, dialogName, NULL); 2970 return; 2971 } 2972 2973 if (!viewPtList.size()) { 2974 String dialogName = (char *) "Missing Viewpoints"; 2975 std::string msg = "There are no viewpoints to load."; 2976 warningMsgDialog(msg, dialogName, NULL); 2977 return; 2978 } 2979 2980 if (SoXtExaminerViewer::isAnimating()) 2981 stopAnimating(); 2982 2983 if (currentState != VIEWPOINT) { 2984 currentState = VIEWPOINT; 2985 ////////////////////////////////////////////////////////////// 2986 setSuperimpositionEnabled(superimposition, TRUE); 2987 axisSwitch->whichChild.setValue(SO_SWITCH_NONE); 2988 animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE); 2989 animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE); 2990 2991 scheduleRedraw(); 2992 /////////////////////////////////////////////////////////////// 2993 } 2994 2995 curViewPtName = viewPtList[viewPtIdx].viewPtName; 2996 camera->viewportMapping = viewPtList[viewPtIdx].viewportMapping; 2997 camera->position = viewPtList[viewPtIdx].position; 2998 camera->orientation = viewPtList[viewPtIdx].orientation; 2999 camera->aspectRatio = viewPtList[viewPtIdx].aspectRatio; 3000 camera->nearDistance = viewPtList[viewPtIdx].nearDistance; 3001 camera->farDistance = viewPtList[viewPtIdx].farDistance; 3002 camera->focalDistance = viewPtList[viewPtIdx].focalDistance; 3003 3004 // Restore camera height (changed by zooming) 3005 if (camera->isOfType(SoPerspectiveCamera::getClassTypeId())) { 3006 if (viewPtList[viewPtIdx].camType == ORTHOGRAPHIC) { 3007 toggleCameraType(); 3008 camera = getCamera(); 3009 ((SoOrthographicCamera *) camera)->height.setValue( 3010 viewPtList[viewPtIdx].height); 3011 } else 3012 ((SoPerspectiveCamera *) camera)->heightAngle.setValue( 3013 viewPtList[viewPtIdx].height); 3014 } else if (camera->isOfType(SoOrthographicCamera::getClassTypeId())) { 3015 if (viewPtList[viewPtIdx].camType == PERSPECTIVE) { 3016 toggleCameraType(); 3017 camera = getCamera(); 3018 ((SoPerspectiveCamera *) camera)->heightAngle.setValue( 3019 viewPtList[viewPtIdx].height); 3020 } else 3021 ((SoOrthographicCamera *) camera)->height.setValue( 3022 viewPtList[viewPtIdx].height); 3023 } else { 3024 SoDebugError::post("G4OpenInventorXtExaminerViewer::setViewPt", 3025 "Only Perspective and Orthographic cameras are supported."); 3026 return; 3027 } 3028 3029 } 3030 3031 3032 // Pops up a prompt asking for a new viewpoint name. 3033 3034 void G4OpenInventorXtExaminerViewer::saveViewPtCB(Widget w, 3035 XtPointer client_data, 3036 XtPointer) 3037 { 3038 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 3039 3040 if (This->fileName.empty()) { 3041 newViewPtFileCB(w, This, NULL); 3042 This->returnToSaveVP = true; 3043 return; // Need to return and call this fn again from newViewPtFileCB since flow of control does not stall here but keeps going 3044 } 3045 3046 int n = 0; 3047 Arg args[4]; 3048 Widget nameViewPtDialog; 3049 Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget 3050 XmString label = XmStringCreateLocalized((char *) "Name the viewpoint:"); 3051 3052 XtSetArg(args[n], XmNselectionLabelString, label); n++; 3053 // Prevent the dialog from closing automatically, in case the name is wrong 3054 XtSetArg(args[n], XmNautoUnmanage, False); n++; 3055 // FWJ 3056 XtSetArg(args[n], XmNtitle, "Save Bookmark"); n++; 3057 nameViewPtDialog = XmCreatePromptDialog(parent, String("Save Bookmark"), 3058 args, n); 3059 3060 XmStringFree(label); 3061 XtAddCallback(nameViewPtDialog, XmNokCallback, getViewPtNameCB, This); 3062 XtAddCallback(nameViewPtDialog, XmNcancelCallback, 3063 getViewPtNameCancelCB, This); 3064 // Coverity gcc8 bad cast warning 3065 // (XtCallbackProc) XtDestroyWidget, NULL); 3066 3067 Widget text = XtNameToWidget(nameViewPtDialog, "Text"); 3068 XtVaSetValues(text, XmNmaxLength, This->MAX_VP_NAME, NULL); 3069 std::string autoName = ""; 3070 if (!This->warningFlag) { //leave the TextField as it is if coming back from warning dialog 3071 autoName = This->viewPtAutoName(); 3072 } 3073 This->warningFlag = false; 3074 XmTextSetString(text, (char *) autoName.c_str()); 3075 XmTextSetInsertionPosition(text, autoName.length()); 3076 3077 XtUnmanageChild(XtNameToWidget(nameViewPtDialog, "Help")); 3078 XtManageChild(nameViewPtDialog); 3079 } 3080 3081 3082 std::string G4OpenInventorXtExaminerViewer::viewPtAutoName() 3083 { 3084 std::string viewPt; 3085 std::stringstream sstream; 3086 std::vector<int> existingViewPts; 3087 int tmp; 3088 3089 //Build the list of names of the form viewpoint_* already present 3090 for (unsigned int i = 0; i < this->viewPtList.size(); ++i) { 3091 viewPt = this->viewPtList[i].viewPtName; 3092 if (viewPt.find("viewpoint_") != std::string::npos) { 3093 tmp = atoi(viewPt.substr(10).c_str()); 3094 if (tmp == 0) { 3095 //0 means couldn't convert to integer OR viewpoint_0 3096 if (!viewPt.compare("viewpoint_0")) 3097 existingViewPts.push_back(0); 3098 } else 3099 existingViewPts.push_back(tmp); 3100 } 3101 } 3102 3103 sstream.str(""); 3104 sstream.clear(); 3105 3106 //Return the view viewpoint_* name available 3107 if (existingViewPts.size() > 0) { 3108 int vpNum = 0; 3109 while (true) { 3110 if (std::find(existingViewPts.begin(), existingViewPts.end(), vpNum) 3111 == existingViewPts.end()) { 3112 sstream << "viewpoint_" << vpNum; 3113 return sstream.str(); 3114 } 3115 ++vpNum; 3116 } 3117 } else { 3118 return "viewpoint_0"; 3119 } 3120 return ""; 3121 } 3122 3123 3124 void G4OpenInventorXtExaminerViewer::abbrOutputCB(Widget, 3125 XtPointer client_data, 3126 XtPointer) 3127 { 3128 G4OpenInventorXtExaminerViewer * This = 3129 (G4OpenInventorXtExaminerViewer *) client_data; 3130 // G4cout << "DISARMCALLBACK abbrOutputFlag=" << This->abbrOutputFlag << G4endl; 3131 This->abbrOutputFlag = !(This->abbrOutputFlag); 3132 } 3133 3134 3135 void G4OpenInventorXtExaminerViewer::pickRefPathCB(Widget, 3136 XtPointer client_data, 3137 XtPointer) 3138 { 3139 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 3140 3141 // Save viewing state and go to picking mode 3142 This->viewingBeforePickRef = This->isViewing(); 3143 if(This->isViewing()) 3144 This->setViewing(false); 3145 This->setComponentCursor(SoXtCursor(SoXtCursor::CROSSHAIR)); 3146 This->pickRefPathFlag = true; 3147 } 3148 3149 3150 void G4OpenInventorXtExaminerViewer::switchWireFrameCB(Widget w, 3151 XtPointer client_data, 3152 XtPointer) 3153 { 3154 G4OpenInventorXtExaminerViewer* This = 3155 (G4OpenInventorXtExaminerViewer*)client_data; 3156 // xmToggleButton theToggleButton = (xmToggleButton)w; 3157 if (XmToggleButtonGetState(w)) { 3158 This->setDrawStyle(SoXtViewer::STILL, SoXtViewer::VIEW_LINE); 3159 This->setDrawStyle(SoXtViewer::INTERACTIVE, SoXtViewer::VIEW_LINE); 3160 } else { 3161 This->setDrawStyle(SoXtViewer::STILL, SoXtViewer::VIEW_AS_IS); 3162 This->setDrawStyle(SoXtViewer::INTERACTIVE, 3163 SoXtViewer::VIEW_SAME_AS_STILL); 3164 } 3165 } 3166 3167 3168 // Examines new viewpoint name and if OK calls saveViewPt. 3169 3170 void G4OpenInventorXtExaminerViewer::getViewPtNameCB(Widget w, 3171 XtPointer client_data, 3172 XtPointer call_data) 3173 { 3174 char *name = NULL; 3175 std::string strName; 3176 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 3177 XmSelectionBoxCallbackStruct *cbs = 3178 (XmSelectionBoxCallbackStruct *) call_data; 3179 XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &name); 3180 3181 if (!name) { 3182 return; 3183 } 3184 if (!*name) { 3185 XtFree(name); 3186 return; 3187 } 3188 3189 strName = name; 3190 XtFree(name); 3191 3192 int beg = strName.find_first_not_of(' '); // Remove leading/trailing spaces 3193 int end = strName.find_last_not_of(' '); 3194 strName = strName.substr(beg, end - beg + 1); 3195 3196 bool nameExists = false; 3197 int size = This->viewPtList.size(); 3198 for (int i = 0; i < size; i++) { 3199 if (!strcmp(This->viewPtList[i].viewPtName, strName.c_str())) { 3200 nameExists = true; 3201 break; 3202 } 3203 } 3204 3205 if (!nameExists) { 3206 const int nVPName = This->MAX_VP_NAME + 1; 3207 name = new char[nVPName]; 3208 strncpy(name, strName.c_str(), nVPName); 3209 if (This->viewPtIdx == -1) 3210 This->viewPtIdx = 0; 3211 This->saveViewPt(name); 3212 if (This->listsDialog) { 3213 XmListAddItemUnselected(This->myViewPtList, cbs->value, 0); // vpName 3214 } 3215 //Dismiss the nameViewPtDialog dialog 3216 XtUnmanageChild(w); 3217 } else { 3218 String dialogName = (char *) "Existing Viewpoint"; 3219 std::string msg = "The viewpoint already exists."; 3220 This->warningMsgDialog(msg, dialogName, NULL); 3221 3222 } 3223 } 3224 3225 void G4OpenInventorXtExaminerViewer::getViewPtNameCancelCB(Widget w, 3226 XtPointer, 3227 XtPointer) 3228 { 3229 XtUnmanageChild(w); 3230 } 3231 3232 3233 // Saves current camera parameters to a viewpoint file. 3234 3235 void G4OpenInventorXtExaminerViewer::saveViewPt(char *name) 3236 { 3237 SbVec3f axis; 3238 viewPtData tmp; 3239 float x, y, z, angle; 3240 SoCamera * camera = getCamera(); 3241 3242 if (viewPtList.size() == 0) { 3243 writeViewPtIdx(); 3244 XtSetSensitive(nextViewPtButton, True); // Makes arrow buttons clickable 3245 XtSetSensitive(prevViewPtButton, True); 3246 } 3247 3248 tmp.viewPtName = name; 3249 tmp.viewportMapping = camera->viewportMapping.getValue(); 3250 tmp.position = camera->position.getValue(); 3251 tmp.orientation = camera->orientation.getValue(); 3252 tmp.aspectRatio = camera->aspectRatio.getValue(); 3253 tmp.nearDistance = camera->nearDistance.getValue(); 3254 tmp.farDistance = camera->farDistance.getValue(); 3255 tmp.focalDistance = camera->focalDistance.getValue(); 3256 3257 // Save camera height (changed by zooming) 3258 if (camera->isOfType(SoPerspectiveCamera::getClassTypeId())) { 3259 tmp.height = ((SoPerspectiveCamera *) camera)->heightAngle.getValue(); 3260 tmp.camType = PERSPECTIVE; 3261 } else if (camera->isOfType(SoOrthographicCamera::getClassTypeId())) { 3262 tmp.height = ((SoOrthographicCamera *) camera)->height.getValue(); 3263 tmp.camType = ORTHOGRAPHIC; 3264 } else { 3265 SoDebugError::post("G4OpenInventorXtExaminerViewer::saveViewPtCB", 3266 "Only Perspective and Orthographic cameras are supported."); 3267 return; 3268 } 3269 3270 viewPtList.push_back(tmp); 3271 3272 // Now save the view point to a .txt file 3273 std::string vpName = name; 3274 3275 while ((int) vpName.size() <= MAX_VP_NAME) 3276 vpName += " "; 3277 3278 fileOut << vpName << std::endl; 3279 tmp.position.getValue(x, y, z); 3280 fileOut << x << " " << y << " " << z << std::endl; 3281 3282 // Reusing x, y and z for storing the axis 3283 tmp.orientation.getValue(axis, angle); 3284 axis.getValue(x, y, z); 3285 fileOut << x << " " << y << " " << z << " " << angle << std::endl; 3286 3287 fileOut << tmp.camType << " " << tmp.height << std::endl; 3288 fileOut << tmp.focalDistance << " "; 3289 fileOut << tmp.nearDistance << " "; 3290 fileOut << tmp.farDistance << std::endl; 3291 fileOut << tmp.viewportMapping << " "; 3292 fileOut << tmp.aspectRatio << "\n" << std::endl; 3293 fileOut.flush(); 3294 viewPtIdx++; 3295 } 3296 3297 3298 void G4OpenInventorXtExaminerViewer::deleteViewPtCB(Widget, 3299 XtPointer client_data, 3300 XtPointer) 3301 { 3302 G4OpenInventorXtExaminerViewer * This = 3303 (G4OpenInventorXtExaminerViewer *) client_data; 3304 This->deleteViewPt(); 3305 } 3306 3307 3308 // Deletes current viewpoint the user is looking at. 3309 // Updates the input file and bookmarks as well. 3310 3311 void G4OpenInventorXtExaminerViewer::deleteViewPt(char *vpName) 3312 { 3313 std::string line; 3314 int end; 3315 fileIn.open(fileName.c_str()); 3316 std::ofstream out("temporaryFile.txt"); 3317 3318 if (!vpName) 3319 vpName = viewPtList[viewPtIdx].viewPtName; 3320 3321 if (listsDialog) { 3322 XmString vpNameStr = XmStringCreateLocalized(vpName); 3323 3324 XmListDeleteItem(myViewPtList, vpNameStr); 3325 XmStringFree(vpNameStr); 3326 } 3327 3328 getline(fileIn, line); // Printing the viewpoint idx 3329 out << line << "\n"; 3330 3331 while (getline(fileIn, line)) { 3332 end = line.find_last_not_of(' '); 3333 line = line.substr(0, end + 1); 3334 if (!strcmp(line.c_str(), vpName)) { // Equal 3335 while (line.size()) { 3336 getline(fileIn, line); 3337 } 3338 3339 while (getline(fileIn, line)) 3340 out << line << "\n"; 3341 } else { 3342 while (line.size()) { 3343 out << line << "\n"; 3344 getline(fileIn, line); 3345 } 3346 out << "\n"; 3347 } 3348 } 3349 3350 int idx = 0; // Remove viewpoint from the vector 3351 int size = viewPtList.size(); 3352 while (idx < size) { 3353 if (!strcmp(viewPtList[idx].viewPtName, vpName)) { 3354 viewPtList.erase(viewPtList.begin() + idx); 3355 break; 3356 } 3357 idx++; 3358 } 3359 3360 out.close(); 3361 fileOut.close(); 3362 fileIn.clear(); 3363 fileIn.close(); 3364 3365 // FWJ check return status 3366 int istat = remove(fileName.c_str()); 3367 if (istat == -1) { 3368 char dialogName[] = "Warning"; 3369 warningMsgDialog("Error removing bookmarks file", dialogName, 3370 NULL); 3371 } 3372 istat = rename("temporaryFile.txt", fileName.c_str()); 3373 if (istat == -1) { 3374 char dialogName[] = "Warning"; 3375 warningMsgDialog("Error renaming bookmarks file", dialogName, 3376 NULL); 3377 } 3378 fileOut.open(fileName.c_str(), std::ios::in); 3379 fileOut.seekp(0, std::ios::end); 3380 3381 if (!viewPtList.size()) { // viewPtList is empty 3382 curViewPtName = (char *) ""; 3383 scheduleRedraw(); 3384 XtSetSensitive(nextViewPtButton, False); 3385 XtSetSensitive(prevViewPtButton, False); 3386 } else { 3387 if (viewPtIdx >= (int) viewPtList.size()) 3388 viewPtIdx--; 3389 writeViewPtIdx(); 3390 setViewPt(); 3391 } 3392 } 3393 3394 3395 // Renames currently selected viewpoint. 3396 3397 void G4OpenInventorXtExaminerViewer::renameViewPt(char *vpName) 3398 { 3399 int idx = 0, end, pos; 3400 int size = viewPtList.size(); 3401 std::string line, newName; 3402 fileIn.open(fileName.c_str()); 3403 3404 newName = vpName; 3405 while ((int) newName.size() < MAX_VP_NAME) 3406 newName += " "; 3407 3408 getline(fileIn, line); 3409 pos = fileIn.tellg(); 3410 while (getline(fileIn, line)) { 3411 end = line.find_last_not_of(' '); 3412 line = line.substr(0, end + 1); 3413 if (!strcmp(line.c_str(), curViewPtName)) { 3414 fileOut.seekp(pos); 3415 fileOut << newName; 3416 fileOut.seekp(0, std::ios::end); // Set the file pointer to the end of the file 3417 break; 3418 } 3419 while (line.size()) 3420 getline(fileIn, line); 3421 pos = fileIn.tellg(); 3422 } 3423 3424 fileIn.close(); 3425 fileIn.clear(); 3426 3427 while (idx < size) { 3428 if (!strcmp(viewPtList[idx].viewPtName, curViewPtName)) { 3429 strcpy(viewPtList[idx].viewPtName, vpName); 3430 break; 3431 } 3432 idx++; 3433 } 3434 } 3435 3436 3437 // Rewrites entire viewpoint file with sorted viewpoints. 3438 3439 void G4OpenInventorXtExaminerViewer::sortViewPts(std::vector<std::string> sortedViewPts) 3440 { 3441 SbVec3f axis; 3442 float x, y, z, angle; 3443 int sortIdx = 0, unsortIdx = 0; 3444 3445 if (fileOut.is_open()) 3446 fileOut.close(); 3447 3448 fileOut.open(fileName.c_str()); // Erase current viewpoint file 3449 3450 writeViewPtIdx(); 3451 3452 int size = sortedViewPts.size(); 3453 while (sortIdx < size) { 3454 while (strcmp(sortedViewPts[sortIdx].c_str(), 3455 viewPtList[unsortIdx].viewPtName)) 3456 unsortIdx++; 3457 3458 std::string vpName = viewPtList[unsortIdx].viewPtName; 3459 3460 while ((int) vpName.size() < MAX_VP_NAME) 3461 vpName += " "; 3462 fileOut << vpName << std::endl; 3463 viewPtList[unsortIdx].position.getValue(x, y, z); 3464 fileOut << x << " " << y << " " << z << std::endl; 3465 3466 // Reusing x, y and z for storing the axis 3467 viewPtList[unsortIdx].orientation.getValue(axis, angle); 3468 axis.getValue(x, y, z); 3469 fileOut << x << " " << y << " " << z << " " << angle << std::endl; 3470 3471 fileOut << viewPtList[unsortIdx].camType << " " 3472 << viewPtList[unsortIdx].height << std::endl; 3473 fileOut << viewPtList[unsortIdx].focalDistance << " "; 3474 3475 fileOut << viewPtList[unsortIdx].nearDistance << " "; 3476 3477 fileOut << viewPtList[unsortIdx].farDistance << std::endl; 3478 3479 fileOut << viewPtList[unsortIdx].viewportMapping << " "; 3480 fileOut << viewPtList[unsortIdx].aspectRatio << "\n" << std::endl; 3481 fileOut.flush(); 3482 3483 unsortIdx = 0; 3484 sortIdx++; 3485 } 3486 } 3487 3488 3489 // Loads view point data from a file into a vector. 3490 3491 bool G4OpenInventorXtExaminerViewer::loadViewPts() 3492 { 3493 bool error = false; 3494 viewPtData tmp; 3495 std::string token; 3496 SbVec3f axis; 3497 SbRotation orient; 3498 float x(0.), y(0.), z(0.), angle(0.); 3499 3500 // Gets the last view point accessed, stored in the first line of the data file. 3501 fileIn >> token; 3502 parseString<int>(viewPtIdx, token, error); 3503 getline(fileIn, token); // Remove "\n" 3504 // Converts data from string type into necessary types 3505 while (getline(fileIn, token)) { 3506 3507 int end = token.find_last_not_of(' '); // Remove padded spaces 3508 token = token.substr(0, end + 1); 3509 3510 char *vpName = new char[token.size() + 1]; 3511 strcpy(vpName, token.c_str()); 3512 tmp.viewPtName = vpName; 3513 fileIn >> token; 3514 3515 parseString<float>(x, token, error); 3516 fileIn >> token; 3517 parseString<float>(y, token, error); 3518 fileIn >> token; 3519 parseString<float>(z, token, error); 3520 fileIn >> token; 3521 tmp.position = axis.setValue(x, y, z); 3522 3523 parseString<float>(x, token, error); 3524 fileIn >> token; 3525 parseString<float>(y, token, error); 3526 fileIn >> token; 3527 parseString<float>(z, token, error); 3528 fileIn >> token; 3529 parseString<float>(angle, token, error); 3530 fileIn >> token; 3531 orient.setValue(axis.setValue(x, y, z), angle); 3532 tmp.orientation = orient.getValue(); 3533 3534 int camType(0); 3535 parseString<int>(camType, token, error); 3536 fileIn >> token; 3537 tmp.camType = (CameraType) camType; 3538 3539 parseString<float>(tmp.height, token, error); 3540 fileIn >> token; 3541 parseString<float>(tmp.focalDistance, token, error); 3542 fileIn >> token; 3543 parseString<float>(tmp.nearDistance, token, error); 3544 fileIn >> token; 3545 parseString<float>(tmp.farDistance, token, error); 3546 fileIn >> token; 3547 parseString<int>(tmp.viewportMapping, token, error); 3548 fileIn >> token; 3549 parseString<float>(tmp.aspectRatio, token, error); 3550 3551 getline(fileIn, token); // To remove "\n" characters 3552 getline(fileIn, token); 3553 3554 if (error) { 3555 viewPtIdx = 0; 3556 viewPtList.clear(); 3557 return false; 3558 } 3559 viewPtList.push_back(tmp); 3560 } 3561 3562 return true; 3563 } 3564 3565 3566 // Converts a string type word into a float type. 3567 3568 template<class T> 3569 void G4OpenInventorXtExaminerViewer::parseString(T &t, const std::string &s, 3570 bool &error) 3571 { 3572 std::istringstream str(s); 3573 if ((str >> t).fail()) 3574 error = true; 3575 } 3576 3577 3578 // Generic fileSelectionDialog creation. 3579 3580 void G4OpenInventorXtExaminerViewer::popUpFileSelDialog(Widget &dialog, 3581 std::string dialogName, 3582 std::string buttonLabel, 3583 XtCallbackProc cbOK) 3584 { 3585 int n; 3586 Arg args[3]; 3587 Widget parent, scrollWidget; 3588 parent = SoXt::getShellWidget(getParentWidget()); 3589 3590 if (dialog == NULL) { 3591 3592 // Change the 'OK' button to whatever buttonLabel contains 3593 XmString str = XmStringCreateLocalized((char *) buttonLabel.c_str()); 3594 3595 n = 0; 3596 XtSetArg(args[n], XmNokLabelString, str); n++; 3597 XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++; 3598 3599 dialog = XmCreateFileSelectionDialog(parent, 3600 (char *) dialogName.c_str(), args, n); 3601 3602 XtAddCallback(dialog, XmNokCallback, cbOK, this); 3603 XtAddCallback(dialog, XmNcancelCallback, cancelFileSelDialogCB, this); 3604 3605 // Adding scrolling functionality to the widget 3606 scrollWidget = XmFileSelectionBoxGetChild(dialog, XmDIALOG_DIR_LIST); 3607 if (scrollWidget) 3608 xmAddMouseEventHandler(scrollWidget); 3609 scrollWidget = XmFileSelectionBoxGetChild(dialog, XmDIALOG_LIST); 3610 if (scrollWidget) 3611 xmAddMouseEventHandler(scrollWidget); 3612 3613 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON)); 3614 XmStringFree(str); 3615 } 3616 XtManageChild(dialog); 3617 } 3618 3619 3620 // Generic fileSelectionDialog cancelation. 3621 3622 void G4OpenInventorXtExaminerViewer::cancelFileSelDialogCB(Widget w, 3623 XtPointer, 3624 XtPointer) 3625 { 3626 XtUnmanageChild(w); 3627 } 3628 3629 3630 // Displays a file selection dialog that allows to open a new viewpoint file. 3631 3632 void G4OpenInventorXtExaminerViewer::openViewPtFileCB(Widget, 3633 XtPointer client_data, 3634 XtPointer) 3635 { 3636 G4OpenInventorXtExaminerViewer * This = 3637 (G4OpenInventorXtExaminerViewer *) client_data; 3638 This->popUpFileSelDialog(This->openFileDialog, "Open File", "Load", 3639 viewPtFileSelectedCB); 3640 } 3641 3642 3643 void G4OpenInventorXtExaminerViewer::viewPtFileSelectedCB(Widget w, 3644 XtPointer client_data, 3645 XtPointer call_data) 3646 { 3647 char *file = NULL; 3648 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 3649 XmFileSelectionBoxCallbackStruct *cbs = 3650 (XmFileSelectionBoxCallbackStruct *) call_data; 3651 3652 // Get the file 3653 if (cbs) { 3654 if (!(file = (char *) XmStringUnparse(cbs->value, 3655 XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, 3656 XmOUTPUT_ALL))) { 3657 SoDebugError::post("G4OpenInventorXtExaminerViewer::fileSelectedCB", 3658 "Internal error during file opening"); 3659 return; 3660 } 3661 3662 This->fileIn.open(file); 3663 if (!This->fileIn.fail()) { 3664 // Opens a file without erasing it 3665 This->cleanUpAfterPrevFile(); 3666 if (!This->loadViewPts()) { 3667 String dialogName = (char *) "Error Loading File"; 3668 std::string msg = "Wrong or corrupted input file."; 3669 This->warningMsgDialog(msg, dialogName, NULL); 3670 } else { 3671 This->fileName = file; 3672 This->fileOut.open(This->fileName.c_str(), std::ios::in); 3673 This->fileOut.seekp(0, std::ios::end); 3674 3675 if (!This->listsDialog) 3676 constructListsDialog(w, This, NULL); // Pop up listsDialog 3677 else 3678 This->addViewPoints(); 3679 3680 std::string newDialogName = This->fileName.substr( 3681 This->fileName.rfind('/') + 1); 3682 XtVaSetValues(This->myShellDialog, XmNtitle, 3683 (char *) newDialogName.c_str(), NULL); 3684 3685 if (This->viewPtList.size()) { 3686 This->setViewPt(); 3687 XmTextSetString(This->viewPtSelection, NULL); 3688 XtSetSensitive(This->nextViewPtButton, True); 3689 XtSetSensitive(This->prevViewPtButton, True); 3690 } else { 3691 XtSetSensitive(This->nextViewPtButton, False); 3692 XtSetSensitive(This->prevViewPtButton, False); 3693 } 3694 3695 XtUnmanageChild(w); 3696 } 3697 3698 This->fileIn.close(); 3699 } else { 3700 String dialogName = (char *) "Nonexistent File"; 3701 std::string msg = "Unable to open file."; 3702 This->warningMsgDialog(msg, dialogName, NULL); 3703 } 3704 } 3705 3706 This->fileIn.clear(); 3707 XtFree(file); 3708 } 3709 3710 3711 // Adds bookmarks to listsDialog. 3712 3713 void G4OpenInventorXtExaminerViewer::addViewPoints() 3714 { 3715 int size = viewPtList.size(); 3716 if (!size) 3717 return; 3718 3719 XmString *viewPts; 3720 3721 viewPts = (XmString *) XtMalloc(size * sizeof(XmString)); 3722 for (int i = 0; i < size; i++) 3723 viewPts[i] = XmStringCreateLocalized(viewPtList[i].viewPtName); 3724 3725 XmListAddItemsUnselected(myViewPtList, viewPts, size, 1); 3726 3727 if (viewPts != NULL) { 3728 for (int i = 0; i < size; i++) 3729 XmStringFree(viewPts[i]); 3730 XtFree((char *) viewPts); 3731 } 3732 } 3733 3734 3735 // Called before loading a new viewpoint file. 3736 // Resets member fields to default values. 3737 3738 void G4OpenInventorXtExaminerViewer::cleanUpAfterPrevFile() 3739 { 3740 viewPtIdx = -1; 3741 viewPtList.clear(); 3742 setSuperimpositionEnabled(superimposition, FALSE); 3743 scheduleRedraw(); 3744 currentState = GENERAL; 3745 if (fileOut.is_open()) 3746 fileOut.close(); 3747 if (listsDialog) // Clear viewpoints 3748 XmListDeleteAllItems(myViewPtList); 3749 } 3750 3751 3752 // Generic function for displaying a warning dialog. 3753 3754 void G4OpenInventorXtExaminerViewer::warningMsgDialog(std::string msg, 3755 String dialogName, 3756 XtCallbackProc cb) 3757 { 3758 Arg args[5]; 3759 unsigned int n; 3760 XmString warningMsg; 3761 3762 warningMsg = XmStringCreateLocalized((char *)msg.c_str()); 3763 3764 n = 0; 3765 XtSetArg(args[n], XmNmessageString, warningMsg); n++; 3766 Widget warningDialog = XmCreateWarningDialog(getParentWidget(), dialogName, args, n); 3767 if (cb) 3768 XtAddCallback(warningDialog, XmNokCallback, cb, this); 3769 3770 XmStringFree(warningMsg); 3771 3772 XtVaSetValues (warningDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL); 3773 XtUnmanageChild(XtNameToWidget(warningDialog, "Help")); 3774 XtUnmanageChild(XtNameToWidget(warningDialog, "Cancel")); 3775 3776 XtManageChild(warningDialog); 3777 } 3778 3779 3780 void G4OpenInventorXtExaminerViewer::newViewPtFileCB(Widget, 3781 XtPointer client_data, 3782 XtPointer) 3783 { 3784 G4OpenInventorXtExaminerViewer * This = 3785 (G4OpenInventorXtExaminerViewer *) client_data; 3786 This->popUpFileSelDialog(This->newFileDialog, "New File", "Save", 3787 createNewVPFileCB); 3788 } 3789 3790 3791 void G4OpenInventorXtExaminerViewer::createNewVPFileCB(Widget w, 3792 XtPointer client_data, 3793 XtPointer call_data) 3794 { 3795 char *file; 3796 std::string fName; 3797 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 3798 XmFileSelectionBoxCallbackStruct *cbs = 3799 (XmFileSelectionBoxCallbackStruct *) call_data; 3800 3801 // Get the file 3802 if (cbs) { 3803 if (!(file = (char *) XmStringUnparse(cbs->value, 3804 XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, 3805 XmOUTPUT_ALL))) { 3806 SoDebugError::post("G4OpenInventorXtExaminerViewer::createNewVPFileCB", 3807 "Internal error during file opening"); 3808 return; 3809 } 3810 3811 This->fileName = file; 3812 fName = This->fileName.substr(This->fileName.rfind('/') + 1); // Extracts just the name of the file 3813 This->fileIn.open(file); 3814 if (This->fileIn.fail()) { // Filename does not exist 3815 This->cleanUpAfterPrevFile(); 3816 This->fileOut.open(file); // Creates a new empty file 3817 XtSetSensitive(This->nextViewPtButton, False); 3818 XtSetSensitive(This->prevViewPtButton, False); 3819 if (This->listsDialog) 3820 closeListsDialogCB(w, This, NULL); 3821 constructListsDialog(w, This, NULL); 3822 XtUnmanageChild(w); 3823 if (This->returnToSaveVP) { 3824 This->returnToSaveVP = false; 3825 saveViewPtCB(NULL, This, NULL); 3826 } 3827 } else { // Filename already exists 3828 String dialogName = (char *) "Existing File"; 3829 std::string msg = "'" + fName + "' already exists. Do you want to overwrite it?"; 3830 This->warningMsgDialog(msg, dialogName, overwriteFileCB); 3831 This->fileIn.close(); 3832 } 3833 This->fileIn.clear(); 3834 XtFree(file); 3835 } 3836 } 3837 3838 3839 void G4OpenInventorXtExaminerViewer::overwriteFileCB(Widget, 3840 XtPointer client_data, 3841 XtPointer) 3842 { 3843 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 3844 This->cleanUpAfterPrevFile(); 3845 XtSetSensitive(This->nextViewPtButton, False); 3846 XtSetSensitive(This->prevViewPtButton, False); 3847 3848 XtUnmanageChild(This->newFileDialog); 3849 3850 This->fileOut.open(This->fileName.c_str()); 3851 3852 if (This->returnToSaveVP) { 3853 This->returnToSaveVP = false; 3854 saveViewPtCB(NULL, This, NULL); 3855 } 3856 } 3857 3858 3859 void G4OpenInventorXtExaminerViewer::loadRefCoordsDialogCB(Widget, 3860 XtPointer client_data, 3861 XtPointer) 3862 { 3863 G4OpenInventorXtExaminerViewer * This = 3864 (G4OpenInventorXtExaminerViewer *)client_data; 3865 This->popUpFileSelDialog(This->loadRefCoordsDialog, "Load Ref Coords", 3866 "Load", loadRefCoordsCB); 3867 } 3868 3869 3870 void G4OpenInventorXtExaminerViewer::loadRefCoordsCB(Widget w, 3871 XtPointer client_data, 3872 XtPointer call_data) 3873 { 3874 char *file = NULL; 3875 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *)client_data; 3876 XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data; 3877 3878 // Get the file 3879 if(cbs) { 3880 3881 file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG, 3882 XmCHARSET_TEXT, XmCHARSET_TEXT, 3883 NULL, 0, XmOUTPUT_ALL); 3884 3885 std::ifstream ifs(file); 3886 if(ifs.is_open()){ 3887 This->refParticleTrajectory.clear(); 3888 float x,y,z; 3889 while(ifs >> x >> y >> z){ 3890 This->refParticleTrajectory.push_back(SbVec3f(x,y,z)); 3891 } 3892 ifs.close(); 3893 XtUnmanageChild(w); 3894 } 3895 else{ 3896 String dialogName = (char *) "Problem reading file"; 3897 std::string msg = "Problem reading file"; 3898 This->warningMsgDialog(msg, dialogName, NULL); 3899 return; 3900 3901 } 3902 } 3903 3904 return; 3905 } 3906 3907 3908 void G4OpenInventorXtExaminerViewer::saveRefCoordsDialogCB(Widget, 3909 XtPointer client_data, 3910 XtPointer) 3911 { 3912 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 3913 3914 if (!This->refParticleTrajectory.size()) { 3915 String dialogName = (char *) "No Reference Trajectory"; 3916 std::string msg = "You need to start a run or load a reference trajectory from a file"; 3917 This->warningMsgDialog(msg, dialogName, NULL); 3918 return; 3919 } 3920 3921 int n; 3922 Arg args[3]; 3923 Widget parent, scrollWidget; 3924 parent = SoXt::getShellWidget(This->getParentWidget()); 3925 3926 if (This->saveRefCoordsDialog == NULL) { 3927 3928 // Change the 'OK' button to whatever buttonLabel contains 3929 XmString str = XmStringCreateLocalized((char *)"Save"); 3930 3931 n = 0; 3932 XtSetArg(args[n], XmNokLabelString, str); n++; 3933 XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++; 3934 3935 This->saveRefCoordsDialog = XmCreateFileSelectionDialog(parent,(char *)"Save Ref Coords", args, n); 3936 3937 XtAddCallback(This->saveRefCoordsDialog, XmNokCallback, saveRefCoordsCB, This); 3938 XtAddCallback(This->saveRefCoordsDialog, XmNcancelCallback, cancelFileSelDialogCB, This); 3939 3940 // Adding scrolling functionality to the widget 3941 scrollWidget = XmFileSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_DIR_LIST); 3942 if (scrollWidget) 3943 xmAddMouseEventHandler(scrollWidget); 3944 scrollWidget = XmFileSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_LIST); 3945 if (scrollWidget) 3946 xmAddMouseEventHandler(scrollWidget); 3947 3948 XtUnmanageChild(XmSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_HELP_BUTTON)); 3949 XmStringFree(str); 3950 } 3951 3952 //TODO: Auto name? 3953 3954 XtManageChild(This->saveRefCoordsDialog); 3955 3956 } 3957 3958 3959 void G4OpenInventorXtExaminerViewer::saveRefCoordsCB(Widget w, 3960 XtPointer client_data, 3961 XtPointer call_data) 3962 { 3963 char *file; 3964 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 3965 XmFileSelectionBoxCallbackStruct *cbs = 3966 (XmFileSelectionBoxCallbackStruct *) call_data; 3967 3968 // Get the file 3969 if (cbs) { 3970 3971 file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG, 3972 XmCHARSET_TEXT, XmCHARSET_TEXT, 3973 NULL, 0, XmOUTPUT_ALL); 3974 3975 std::ifstream ifile(file); 3976 if (ifile) { 3977 //File already exists 3978 3979 Arg args[4]; 3980 Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget 3981 Widget confirmOverwriteDialog; 3982 XmString msg; 3983 3984 confirmOverwriteDialog = XmCreateQuestionDialog (parent, (char *)"Confirm overwrite", args, 0); 3985 msg = XmStringCreateLocalized ((char *)"File exists. Overwrite?"); 3986 XtVaSetValues (confirmOverwriteDialog, XmNmessageString, msg, NULL); 3987 3988 // If users presses OK, we want to return to this function and 3989 // save the file. For that to work, pass it the current widget 3990 // to be able to grab the filename. 3991 XtVaSetValues (confirmOverwriteDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL); 3992 XtAddCallback (confirmOverwriteDialog, XmNokCallback, saveRefCoordsOverWriteCB, client_data); 3993 XtAddCallback (confirmOverwriteDialog, XmNcancelCallback, saveRefCoordsOverWriteCB, client_data); 3994 3995 XmStringFree (msg); 3996 3997 //The confirmOverwriteDialog will need this 3998 This->saveRefCoordsFileName = file; 3999 This->saveRefCoordsWidget = w; 4000 4001 XtUnmanageChild(XtNameToWidget(confirmOverwriteDialog, "Help")); 4002 XtManageChild(confirmOverwriteDialog); 4003 4004 return; 4005 } 4006 else{ 4007 4008 std::ofstream ofs(file); 4009 if(ofs.is_open()){ 4010 float x,y,z; 4011 for(unsigned int i=0; i < This->refParticleTrajectory.size(); ++i){ 4012 This->refParticleTrajectory[i].getValue(x,y,z); 4013 ofs << x << " " << y << " " << z << "\n"; 4014 } 4015 ofs.close(); 4016 XtUnmanageChild(w); 4017 } 4018 else{ 4019 String dialogName = (char *) "Error opening file"; 4020 std::string msg = "There was a problem trying to open the file '"; 4021 msg += This->saveRefCoordsFileName; 4022 msg += "'"; 4023 4024 This->warningMsgDialog(msg, dialogName, NULL); 4025 } 4026 } 4027 } 4028 4029 return; 4030 } 4031 4032 4033 void G4OpenInventorXtExaminerViewer::saveRefCoordsOverWriteCB(Widget w, 4034 XtPointer client_data, 4035 XtPointer call_data) 4036 { 4037 XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data; 4038 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4039 4040 switch (cbs->reason) { 4041 case XmCR_OK: 4042 { 4043 // Overwrite confirmed, save file and dismiss both 4044 // dialogs (file dialog and overwrite confirmation dialog) 4045 std::ofstream ofs(This->saveRefCoordsFileName.c_str()); 4046 if(ofs.is_open()){ 4047 float x,y,z; 4048 for(unsigned int i=0; i < This->refParticleTrajectory.size(); ++i){ 4049 This->refParticleTrajectory[i].getValue(x,y,z); 4050 ofs << x << " " << y << " " << z << "\n"; 4051 } 4052 ofs.close(); 4053 XtUnmanageChild(w); 4054 XtUnmanageChild(This->saveRefCoordsWidget); 4055 } 4056 else{ 4057 String dialogName = (char *) "Error opening file"; 4058 std::string msg = "There was a problem trying to open the file '"; 4059 msg += This->saveRefCoordsFileName; 4060 msg += "'"; 4061 4062 This->warningMsgDialog(msg, dialogName, NULL); 4063 } 4064 break; 4065 } 4066 case XmCR_CANCEL: 4067 { 4068 // Overwrite refused, dismiss overwrite confirmation 4069 // dialog and return to file dialog 4070 4071 // Give focus to the text field instead of the OK button 4072 XmProcessTraversal(XtNameToWidget(This->saveRefCoordsWidget, "Text"), XmTRAVERSE_CURRENT); 4073 4074 XtUnmanageChild(w); 4075 This->saveRefCoordsFileName.clear(); 4076 This->saveRefCoordsWidget = NULL; 4077 break; 4078 } 4079 default: 4080 return; 4081 } 4082 } 4083 4084 4085 void G4OpenInventorXtExaminerViewer::loadSceneGraphDialogCB(Widget, 4086 XtPointer client_data, 4087 XtPointer) 4088 { 4089 G4OpenInventorXtExaminerViewer * This = 4090 (G4OpenInventorXtExaminerViewer *)client_data; 4091 This->popUpFileSelDialog(This->loadSceneGraphDialog, "Load Scene Graph", 4092 "Load", loadSceneGraphCB); 4093 return; 4094 } 4095 4096 4097 void G4OpenInventorXtExaminerViewer::loadSceneGraphCB(Widget w, 4098 XtPointer client_data, 4099 XtPointer call_data) 4100 { 4101 char *file = NULL; 4102 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *)client_data; 4103 XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data; 4104 4105 if(cbs) { 4106 4107 file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG, 4108 XmCHARSET_TEXT, XmCHARSET_TEXT, 4109 NULL, 0, XmOUTPUT_ALL); 4110 4111 SoInput sceneInput; 4112 if (!sceneInput.openFile(file)) { 4113 String dialogName = (char *) "Problem opening file"; 4114 std::string msg = "Cannot open file "; 4115 msg += file; 4116 This->warningMsgDialog(msg, dialogName, NULL); 4117 4118 sceneInput.closeFile(); 4119 XtUnmanageChild(w); 4120 } 4121 // Read the whole file into the database 4122 This->newSceneGraph = SoDB::readAll(&sceneInput); 4123 if (This->newSceneGraph == NULL) { 4124 String dialogName = (char *) "Problem reading file"; 4125 std::string msg = "Problem reading file"; 4126 This->warningMsgDialog(msg, dialogName, NULL); 4127 return; 4128 } 4129 4130 //This->newSceneGraph->ref(); 4131 This->setSceneGraph(This->newSceneGraph); 4132 } 4133 4134 return; 4135 } 4136 4137 4138 void G4OpenInventorXtExaminerViewer::saveSceneGraphDialogCB(Widget, 4139 XtPointer client_data, 4140 XtPointer) 4141 { 4142 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4143 4144 int n; 4145 Arg args[3]; 4146 Widget parent, scrollWidget; 4147 parent = SoXt::getShellWidget(This->getParentWidget()); 4148 4149 if (This->saveSceneGraphDialog == NULL) { 4150 4151 // Change the 'OK' button to whatever buttonLabel contains 4152 XmString str = XmStringCreateLocalized((char *)"Save"); 4153 4154 n = 0; 4155 XtSetArg(args[n], XmNokLabelString, str); n++; 4156 XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++; 4157 4158 This->saveSceneGraphDialog = XmCreateFileSelectionDialog(parent,(char *)"Save Scene Graph", args, n); 4159 4160 XtAddCallback(This->saveSceneGraphDialog, XmNokCallback, saveSceneGraphCB, This); 4161 XtAddCallback(This->saveSceneGraphDialog, XmNcancelCallback, cancelFileSelDialogCB, This); 4162 4163 // Adding scrolling functionality to the widget 4164 scrollWidget = XmFileSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_DIR_LIST); 4165 if (scrollWidget) 4166 xmAddMouseEventHandler(scrollWidget); 4167 scrollWidget = XmFileSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_LIST); 4168 if (scrollWidget) 4169 xmAddMouseEventHandler(scrollWidget); 4170 4171 XtUnmanageChild(XmSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_HELP_BUTTON)); 4172 XmStringFree(str); 4173 } 4174 4175 //TODO: Auto name? 4176 4177 XtManageChild(This->saveSceneGraphDialog); 4178 4179 } 4180 4181 4182 4183 void G4OpenInventorXtExaminerViewer::saveSceneGraphCB(Widget w, 4184 XtPointer client_data, 4185 XtPointer call_data) 4186 { 4187 char *file; 4188 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4189 XmFileSelectionBoxCallbackStruct *cbs = 4190 (XmFileSelectionBoxCallbackStruct *) call_data; 4191 4192 if (cbs) { 4193 4194 file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG, 4195 XmCHARSET_TEXT, XmCHARSET_TEXT, 4196 NULL, 0, XmOUTPUT_ALL); 4197 4198 std::ifstream ifile(file); 4199 if (ifile) { 4200 //File already exists 4201 4202 Arg args[4]; 4203 Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget 4204 Widget confirmOverwriteDialog; 4205 XmString msg; 4206 4207 confirmOverwriteDialog = XmCreateQuestionDialog (parent, (char *)"Confirm overwrite", args, 0); 4208 msg = XmStringCreateLocalized ((char *)"File exists. Overwrite?"); 4209 XtVaSetValues (confirmOverwriteDialog, XmNmessageString, msg, NULL); 4210 4211 // If users presses OK, we want to return to this function and 4212 // save the file. For that to work, pass it the current widget 4213 // to be able to grab the filename. 4214 XtVaSetValues (confirmOverwriteDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL); 4215 XtAddCallback (confirmOverwriteDialog, XmNokCallback, saveSceneGraphOverWriteCB, client_data); 4216 XtAddCallback (confirmOverwriteDialog, XmNcancelCallback, saveSceneGraphOverWriteCB, client_data); 4217 4218 XmStringFree (msg); 4219 4220 //The confirmOverwriteDialog will need this 4221 This->saveScenegraphFileName = file; 4222 This->saveScenegraphWidget = w; 4223 4224 XtUnmanageChild(XtNameToWidget(confirmOverwriteDialog, "Help")); 4225 XtManageChild(confirmOverwriteDialog); 4226 4227 return; 4228 } 4229 else{ 4230 4231 SoWriteAction writeAction; 4232 SoSeparator *root = (SoSeparator *) (This->getSceneGraph()); 4233 4234 SoOutput * out = writeAction.getOutput(); 4235 4236 if(out->openFile(file)){ 4237 out->setBinary(FALSE); 4238 writeAction.apply(root); 4239 out->closeFile(); 4240 4241 XtUnmanageChild(w); 4242 } 4243 else{ 4244 String dialogName = (char *) "Error opening file"; 4245 std::string msg = "There was a problem trying to open the file '"; 4246 msg += This->saveScenegraphFileName; 4247 msg += "'"; 4248 4249 This->warningMsgDialog(msg, dialogName, NULL); 4250 } 4251 4252 } 4253 } 4254 4255 return; 4256 } 4257 4258 4259 4260 void G4OpenInventorXtExaminerViewer::saveSceneGraphOverWriteCB(Widget w, 4261 XtPointer client_data, 4262 XtPointer call_data) 4263 { 4264 XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data; 4265 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4266 4267 switch (cbs->reason) { 4268 case XmCR_OK: 4269 { 4270 // Overwrite confirmed, save file and dismiss both 4271 // dialogs (file dialog and overwrite confirmation dialog) 4272 SoWriteAction writeAction; 4273 SoSeparator *root = (SoSeparator *) (This->getSceneGraph()); 4274 4275 SoOutput * out = writeAction.getOutput(); 4276 if(out->openFile(This->saveScenegraphFileName.c_str())){ 4277 out->setBinary(FALSE); 4278 writeAction.apply(root); 4279 out->closeFile(); 4280 4281 XtUnmanageChild(w); 4282 XtUnmanageChild(This->saveScenegraphWidget); 4283 This->saveScenegraphFileName.clear(); 4284 This->saveScenegraphWidget = NULL; 4285 } 4286 else{ 4287 String dialogName = (char *) "Error opening file"; 4288 std::string msg = "There was a problem trying to open the file '"; 4289 msg += This->saveScenegraphFileName; 4290 msg += "'"; 4291 4292 This->warningMsgDialog(msg, dialogName, NULL); 4293 This->saveScenegraphFileName.clear(); 4294 This->saveScenegraphWidget = NULL; 4295 } 4296 break; 4297 } 4298 case XmCR_CANCEL: 4299 { 4300 // Overwrite refused, dismiss overwrite confirmation 4301 // dialog and return to file dialog 4302 4303 // Give focus to the text field instead of the OK button 4304 XmProcessTraversal(XtNameToWidget(This->saveScenegraphWidget, "Text"), XmTRAVERSE_CURRENT); 4305 4306 XtUnmanageChild(w); 4307 This->saveScenegraphFileName.clear(); 4308 This->saveScenegraphWidget = NULL; 4309 break; 4310 } 4311 default: 4312 return; 4313 } 4314 } 4315 4316 4317 // Receives the name of the bookmark clicked and searches for it in viewPtList. 4318 4319 void G4OpenInventorXtExaminerViewer::loadBookmarkCB(Widget, 4320 XtPointer client_data, 4321 XtPointer call_data) 4322 { 4323 char *vpName; 4324 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4325 XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data; 4326 4327 vpName = (char *) XmStringUnparse(cbs->item, XmFONTLIST_DEFAULT_TAG, 4328 XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); 4329 4330 for (int i = 0; i < (int) This->viewPtList.size(); i++) { 4331 if (!strcmp(This->viewPtList[i].viewPtName, vpName)) { 4332 This->viewPtIdx = i; 4333 break; 4334 } 4335 } 4336 XmTextSetString(This->viewPtSelection, vpName); 4337 4338 This->writeViewPtIdx(); 4339 This->setViewPt(); 4340 XtFree(vpName); 4341 } 4342 4343 4344 4345 void G4OpenInventorXtExaminerViewer::deleteBookmarkCB(Widget, 4346 XtPointer client_data, 4347 XtPointer) 4348 { 4349 char *vpName; 4350 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4351 4352 vpName = XmTextGetString(This->viewPtSelection); 4353 4354 XmString vpNameStr = XmStringCreateLocalized(vpName); 4355 4356 if (XmListItemExists(This->myViewPtList, vpNameStr)) { 4357 XmListDeleteItem(This->myViewPtList, vpNameStr); 4358 This->deleteViewPt(vpName); 4359 } 4360 4361 XmStringFree(vpNameStr); 4362 XmTextSetString(This->viewPtSelection, NULL); 4363 XtFree(vpName); 4364 } 4365 4366 4367 void G4OpenInventorXtExaminerViewer::renameBookmarkCB(Widget, 4368 XtPointer client_data, 4369 XtPointer) 4370 { 4371 std::string vpNameStr; 4372 char *vpName; 4373 int *pos_list, pos_cnt; 4374 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4375 4376 vpName = XmTextGetString(This->viewPtSelection); 4377 4378 if (!strlen(vpName) || !strcmp(This->curViewPtName, vpName)) { 4379 XtFree(vpName); 4380 return; 4381 } 4382 4383 vpNameStr = vpName; 4384 XtFree(vpName); 4385 int beg = vpNameStr.find_first_not_of(' '); // Remove leading/trailing spaces 4386 int end = vpNameStr.find_last_not_of(' '); 4387 vpNameStr = vpNameStr.substr(beg, end - beg + 1); 4388 const int nVPName = vpNameStr.size() + 1; 4389 char* vpName1 = new char[nVPName]; 4390 strncpy(vpName1, vpNameStr.c_str(), nVPName); 4391 4392 int size = This->viewPtList.size(); 4393 for (int i = 0; i < size; i++) { 4394 if (!strcmp(vpName1, This->viewPtList[i].viewPtName)) { 4395 4396 String dialogName = (char *) "Existing Viewpoint"; 4397 std::string msg = "'"; 4398 msg += vpName1; 4399 msg += "' already exists. Choose a different name"; 4400 4401 This->warningMsgDialog(msg, dialogName, NULL); 4402 delete[] vpName1; 4403 return; 4404 } 4405 } 4406 4407 XmString vpNameXmStr = XmStringCreateLocalized(vpName1); 4408 4409 if (XmListGetSelectedPos(This->myViewPtList, &pos_list, &pos_cnt)) { 4410 XmListReplaceItemsPos(This->myViewPtList, &vpNameXmStr, 1, pos_list[0]); 4411 This->renameViewPt(vpName1); 4412 XtFree((char *) pos_list); 4413 } 4414 4415 if (This->currentState == VIEWPOINT) 4416 This->scheduleRedraw(); 4417 4418 XmStringFree(vpNameXmStr); 4419 delete[] vpName1; 4420 } 4421 4422 4423 void G4OpenInventorXtExaminerViewer::sortBookmarksCB(Widget, 4424 XtPointer client_data, 4425 XtPointer) 4426 { 4427 int size; 4428 char *vpName; 4429 XmString *strList, *newStrList; 4430 std::vector<std::string> charList; 4431 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4432 4433 if (This->viewPtList.size() < 2) 4434 return; 4435 4436 // Get current entries from the list 4437 XtVaGetValues(This->myViewPtList, XmNitemCount, &size, XmNitems, &strList, 4438 NULL); 4439 4440 for (int i = 0; i < size; i++) { 4441 vpName = (char *) XmStringUnparse(strList[i], XmFONTLIST_DEFAULT_TAG, 4442 XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); 4443 charList.push_back(vpName); 4444 XtFree(vpName); 4445 } 4446 4447 std::sort(charList.begin(), charList.end()); 4448 4449 newStrList = (XmString *) XtMalloc(size * sizeof(XmString)); 4450 for (int i = 0; i < size; i++) { 4451 // viewPtIdx has to be changed to account for a different order in viewPtList 4452 if (!strcmp(charList[i].c_str(), This->curViewPtName)) 4453 This->viewPtIdx = i; 4454 const int nVPName = charList[i].size() + 1; 4455 char *vpName2 = new char[nVPName]; 4456 strncpy(vpName2, charList[i].c_str(), nVPName); 4457 newStrList[i] = XmStringCreateLocalized(vpName2); 4458 delete [] vpName2; 4459 } 4460 4461 XmListDeleteAllItems(This->myViewPtList); 4462 XmListAddItemsUnselected(This->myViewPtList, newStrList, size, 1); 4463 4464 This->sortViewPts(charList); 4465 4466 if (newStrList != NULL) { 4467 for (int i = 0; i < size; i++) 4468 XmStringFree(newStrList[i]); 4469 XtFree((char *) newStrList); 4470 } 4471 } 4472 4473 4474 void G4OpenInventorXtExaminerViewer::evenOutRefParticlePts() 4475 { 4476 if(this->refParticleTrajectory.empty()) 4477 return; 4478 4479 SbVec3f p1, p2, p3, dirNow, dirNxt, dir, p2_tmp, p_start, p_corner, p_nxt; 4480 float avgDistBtwPts = 0; 4481 float totalDistBtwPts = 0; 4482 std::vector<SbVec3f> newRefParticleTrajectory; 4483 SbVec3f refPoint; 4484 int size = refParticleTrajectory.size() - 1; 4485 int numOfPts = 0; 4486 for (int i = 0; i < size; i++) { 4487 p1 = refParticleTrajectory[i]; 4488 p2 = refParticleTrajectory[i + 1]; 4489 if (p1 == p2) 4490 continue; 4491 numOfPts++; 4492 totalDistBtwPts += (p2 - p1).length(); 4493 } 4494 // Nothing useful to do (and fix Coverity) 4495 if (numOfPts <= 2) return; 4496 4497 avgDistBtwPts = totalDistBtwPts / numOfPts; 4498 float minDistAllowed = 0.75 * avgDistBtwPts; 4499 // float maxDistAllowed = 1.25 * avgDistBtwPts; // Pts tend to be close not far 4500 4501 float x, y, z; 4502 int i = 0, j = 0; 4503 while (i < size) { 4504 p1 = refParticleTrajectory[i]; 4505 p2 = refParticleTrajectory[i + 1]; 4506 4507 refPoint = p1; 4508 p1.getValue(x, y, z); 4509 4510 newRefParticleTrajectory.push_back(refPoint); 4511 4512 j = i; 4513 while ((p2 - p1).length() < minDistAllowed && j < (size - 1)) { 4514 j++; 4515 4516 p1 = refParticleTrajectory[j]; 4517 p2 = refParticleTrajectory[j + 1]; 4518 } 4519 if (j != i) 4520 i = j + 1; 4521 else 4522 i++; 4523 } 4524 4525 refParticleTrajectory.clear(); 4526 refParticleTrajectory = newRefParticleTrajectory; 4527 } 4528 4529 4530 // Called when the viewer is closed; closes all open widgets. 4531 4532 void G4OpenInventorXtExaminerViewer::closeMainWindowCB(Widget, 4533 XtPointer client_data, 4534 XtPointer) 4535 { 4536 G4OpenInventorXtExaminerViewer * This = 4537 (G4OpenInventorXtExaminerViewer *) client_data; 4538 4539 if (This->openFileDialog) 4540 XtUnmanageChild(This->openFileDialog); 4541 4542 if (This->newFileDialog) 4543 XtUnmanageChild(This->newFileDialog); 4544 4545 if (This->listsDialog) 4546 closeListsDialogCB(NULL, This, NULL); 4547 } 4548 4549 4550 void G4OpenInventorXtExaminerViewer::saveCurCamera() 4551 { 4552 SoCamera *cam = getCamera(); 4553 camB4Animation.viewportMapping = cam->viewportMapping.getValue(); 4554 camB4Animation.position = cam->position.getValue(); 4555 camB4Animation.orientation = cam->orientation.getValue(); 4556 camB4Animation.aspectRatio = cam->aspectRatio.getValue(); 4557 camB4Animation.nearDistance = cam->nearDistance.getValue(); 4558 camB4Animation.farDistance = cam->farDistance.getValue(); 4559 camB4Animation.focalDistance = cam->focalDistance.getValue(); 4560 4561 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) { 4562 camB4Animation.height = 4563 ((SoPerspectiveCamera *) cam)->heightAngle.getValue(); 4564 camB4Animation.camType = PERSPECTIVE; 4565 } else if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) { 4566 camB4Animation.height = 4567 ((SoOrthographicCamera *) cam)->height.getValue(); 4568 camB4Animation.camType = ORTHOGRAPHIC; 4569 } 4570 } 4571 4572 4573 void G4OpenInventorXtExaminerViewer::restoreCamera() 4574 { 4575 SoCamera *cam = getCamera(); 4576 4577 cam->viewportMapping = camB4Animation.viewportMapping; 4578 cam->position = camB4Animation.position; 4579 cam->orientation = camB4Animation.orientation; 4580 cam->aspectRatio = camB4Animation.aspectRatio; 4581 cam->nearDistance = camB4Animation.nearDistance; 4582 cam->farDistance = camB4Animation.farDistance; 4583 cam->focalDistance = camB4Animation.focalDistance; 4584 4585 if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) { 4586 if (camB4Animation.camType == ORTHOGRAPHIC) { 4587 toggleCameraType(); 4588 cam = getCamera(); 4589 ((SoOrthographicCamera *) cam)->height.setValue( 4590 camB4Animation.height); 4591 } else 4592 ((SoPerspectiveCamera *) cam)->heightAngle.setValue( 4593 camB4Animation.height); 4594 } else if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) { 4595 if (camB4Animation.camType == PERSPECTIVE) { 4596 toggleCameraType(); 4597 cam = getCamera(); 4598 ((SoPerspectiveCamera *) cam)->heightAngle.setValue( 4599 camB4Animation.height); 4600 } else 4601 ((SoOrthographicCamera *) cam)->height.setValue( 4602 camB4Animation.height); 4603 } 4604 } 4605 4606 4607 void G4OpenInventorXtExaminerViewer::animateSensorRotationCB(void *data, 4608 SoSensor *sensor) 4609 { 4610 SbTime curTime = SbTime::getTimeOfDay(); 4611 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) data; 4612 SoTimerSensor *s = (SoTimerSensor *) sensor; 4613 4614 float t = float((curTime - s->getBaseTime()).getValue()) 4615 / This->animateBtwPtsPeriod; 4616 4617 if ((t > 1.0f) || (t + s->getInterval().getValue() > 1.0f)) 4618 t = 1.0f; 4619 SbBool end = (t == 1.0f); 4620 4621 if (end) { 4622 This->animateSensorRotation->unschedule(); 4623 if(This->rotCnt){ 4624 // rotations left 4625 This->rotateCamera(); 4626 } 4627 else { 4628 // rotation over 4629 This->currentState = This->prevState; 4630 return; 4631 } 4632 } 4633 4634 } 4635 4636 4637 // Called repeatedly during reference particle animation 4638 4639 void G4OpenInventorXtExaminerViewer::animateSensorCB(void *data, 4640 SoSensor *sensor) 4641 { 4642 SbTime curTime = SbTime::getTimeOfDay(); 4643 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) data; 4644 SoCamera *cam = This->getCamera(); 4645 SoTimerSensor *s = (SoTimerSensor *) sensor; 4646 4647 float t = float((curTime - s->getBaseTime()).getValue()) 4648 / This->animateBtwPtsPeriod; 4649 4650 if ((t > 1.0f) || (t + s->getInterval().getValue() > 1.0f)) 4651 t = 1.0f; 4652 SbBool end = (t == 1.0f); 4653 4654 cam->orientation = SbRotation::slerp(This->camStartOrient, This->camEndOrient, t); 4655 cam->position = This->camStartPos + (This->camEndPos - This->camStartPos) * t; 4656 4657 if (end) { 4658 This->animateSensor->unschedule(); 4659 4660 if (This->currentState == ANIMATION) { 4661 if (This->refParticleIdx < (int) (This->refParticleTrajectory.size() - 1)) 4662 This->animateRefParticle(); 4663 else { 4664 This->animateBtwPtsPeriod = MIN_SPEED; 4665 This->speedStep = START_STEP; 4666 } 4667 } 4668 if (This->currentState == REVERSED_ANIMATION) { 4669 if (This->refParticleIdx >= 1) 4670 This->animateRefParticle(); 4671 else { 4672 This->animateBtwPtsPeriod = MIN_SPEED; 4673 This->speedStep = START_STEP; 4674 } 4675 } 4676 } 4677 } 4678 4679 4680 void G4OpenInventorXtExaminerViewer::setStartingPtForAnimation() 4681 { 4682 if (SoXtExaminerViewer::isAnimating()) 4683 stopAnimating(); 4684 4685 SbRotation rot; 4686 SbVec3f p1(0), p2(0), p2_tmp(0), camUpV(0), camD, camD_tmp, leftRightAxis; 4687 float x1(0.), y1(0.), z1(0.), x2(0.), y2(0.), z2(0.); 4688 4689 if (currentState == ANIMATION) { 4690 p1 = refParticleTrajectory[refParticleIdx]; 4691 p2 = refParticleTrajectory[++(refParticleIdx)]; 4692 } else if (currentState == REVERSED_ANIMATION) { 4693 p2 = refParticleTrajectory[refParticleIdx]; 4694 p1 = refParticleTrajectory[--(refParticleIdx)]; 4695 } else if (currentState == PAUSED_ANIMATION) { 4696 if (refParticleIdx < (int) refParticleTrajectory.size()) { 4697 p1 = refParticleTrajectory[refParticleIdx]; 4698 p2 = refParticleTrajectory[refParticleIdx + 1]; 4699 } else { 4700 p1 = refParticleTrajectory[refParticleIdx - 1]; 4701 p2 = refParticleTrajectory[refParticleIdx]; 4702 } 4703 } 4704 p1.getValue(x1, y1, z1); 4705 p2.getValue(x2, y2, z2); 4706 4707 camD = p2 - p1; 4708 camD.normalize(); 4709 4710 p2_tmp.setValue(x2, y1, z2); 4711 camD_tmp = p2_tmp - p1; 4712 camD_tmp.normalize(); 4713 4714 camUpV.setValue(0, 1, 0); 4715 rot.setValue(camD_tmp, camD); 4716 rot.multVec(camUpV, camUpV); 4717 4718 leftRightAxis = camD.cross(camUpV); 4719 4720 myCam->position = p1; 4721 myCam->pointAt(p2, camUpV); 4722 4723 // Update camera position 4724 p1 = p1 + (up_down * camUpV) + (left_right * leftRightAxis); 4725 myCam->position = p1; 4726 // FWJ Try look-ahead here 4727 int idx = refParticleIdx + pathLookahead; 4728 idx = std::min(idx, (int)refParticleTrajectory.size() - 1); 4729 myCam->pointAt(refParticleTrajectory[idx], camUpV); 4730 // myCam->pointAt(refParticleTrajectory[idx], camUpVec); 4731 myCam->focalDistance = 0.1f; 4732 } 4733 4734 4735 void G4OpenInventorXtExaminerViewer::gotoRefPathStart() 4736 { 4737 G4OpenInventorXtExaminerViewer::gotoRefPathStartCB(NULL, (void *)this, 4738 NULL); 4739 } 4740 4741 4742 void G4OpenInventorXtExaminerViewer::gotoRefPathStartCB(Widget, 4743 XtPointer client_data, 4744 XtPointer) 4745 { 4746 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4747 4748 if (!This->refParticleTrajectory.size()) { 4749 String dialogName = (char *) "No Reference Trajectory"; 4750 std::string msg = "You need to start a run or load a reference trajectory from a file"; 4751 This->warningMsgDialog(msg, dialogName, NULL); 4752 return; 4753 } 4754 4755 if (This->currentState == ROTATING) 4756 return; 4757 if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION 4758 || This->currentState == PAUSED_ANIMATION) { 4759 if (This->animateSensor->isScheduled()) 4760 This->animateSensor->unschedule(); 4761 This->setSuperimpositionEnabled(This->superimposition, FALSE); 4762 This->maxSpeed = 0.0f; 4763 This->scheduleRedraw(); 4764 } else { 4765 This->saveCurCamera(); 4766 This->prevState = This->currentState; 4767 This->prevRefIdx = This->refParticleIdx; 4768 } 4769 4770 if (This->SoXtExaminerViewer::isAnimating()) 4771 This->stopAnimating(); 4772 4773 This->up_down = 0; 4774 This->left_right = 0; 4775 This->step = 1; 4776 4777 This->refParticleIdx = 0; 4778 This->currentState = BEAMLINE; 4779 This->setSuperimpositionEnabled(This->superimposition, TRUE); 4780 This->axisSwitch->whichChild.setValue(SO_SWITCH_NONE); 4781 This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE); 4782 This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE); 4783 This->scheduleRedraw(); 4784 4785 // FWJ Disabled: this is set in moveCamera() 4786 // Zoom in 4787 // SoCamera *cam = This->getCamera(); 4788 // cam->focalDistance = 0.1f; 4789 4790 This->prevParticleDir = SbVec3f(0,0,0); 4791 4792 //Default zoom 4793 SbVec3f p1 = This->refParticleTrajectory[0]; 4794 SbVec3f pN = This->refParticleTrajectory[This->refParticleTrajectory.size() - 1]; 4795 This->distance = (pN - p1).length() / 10; 4796 4797 This->moveCamera(This->distance, true); 4798 } 4799 4800 4801 void G4OpenInventorXtExaminerViewer::invertRefPathCB(Widget, 4802 XtPointer client_data, 4803 XtPointer) 4804 { 4805 G4OpenInventorXtExaminerViewer * This = 4806 (G4OpenInventorXtExaminerViewer *) client_data; 4807 This->invertRefPath(); 4808 } 4809 4810 4811 void G4OpenInventorXtExaminerViewer::invertRefPath() 4812 { 4813 std::reverse(this->refParticleTrajectory.begin(), 4814 this->refParticleTrajectory.end()); 4815 this->setReferencePathZPos(); 4816 this->sortElements(); 4817 } 4818 4819 4820 void G4OpenInventorXtExaminerViewer::animateRefParticleCB(Widget, 4821 XtPointer client_data, 4822 XtPointer) 4823 { 4824 G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data; 4825 4826 if (!This->refParticleTrajectory.size()) { 4827 This->returnToAnim = true; 4828 String dialogName = (char *) "No Reference Trajectory"; 4829 std::string msg = "You need to start a run or load a reference trajectory from a file"; 4830 This->warningMsgDialog(msg, dialogName, NULL); 4831 return; 4832 } 4833 4834 if (!This->refParticleTrajectory.size()) 4835 return; 4836 4837 /////////////////////////////////////////////////////////////// 4838 This->setSuperimpositionEnabled(This->superimposition, TRUE); 4839 This->maxSpeed = SPEED_INDICATOR_STEP; 4840 This->axisSwitch->whichChild.setValue(SO_SWITCH_ALL); 4841 This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_ALL); 4842 This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_ALL); 4843 This->scheduleRedraw(); 4844 /////////////////////////////////////////////////////////////// 4845 4846 SoCamera *cam = This->getCamera(); 4847 // SbVec3f camDirOld, camDirNew, camDirNew_tmp, camUpVec, P0, P1, P1_tmp; 4848 4849 if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION 4850 || This->currentState == ROTATING) 4851 return; 4852 4853 if (This->currentState != PAUSED_ANIMATION) { 4854 4855 This->saveCurCamera(); 4856 This->prevState = This->currentState; 4857 This->prevRefIdx = This->refParticleIdx; 4858 4859 if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) { 4860 This->toggleCameraType(); 4861 cam = This->getCamera(); 4862 } 4863 4864 This->refParticleIdx = 0; // Set the camera to the starting point of the animation 4865 This->animateBtwPtsPeriod = MIN_SPEED; 4866 This->speedStep = START_STEP; 4867 This->left_right = This->up_down = 0; 4868 4869 cam->focalDistance = 0.1f; 4870 ((SoPerspectiveCamera *) cam)->heightAngle = 0.50f; 4871 } 4872 4873 This->currentState = ANIMATION; 4874 This->setStartingPtForAnimation(); 4875 4876 cam->position = (This->myCam)->position.getValue(); 4877 cam->orientation = (This->myCam)->orientation.getValue(); 4878 This->animateRefParticle(); // Animate the camera 4879 } 4880 4881 4882 void G4OpenInventorXtExaminerViewer::animateRefParticle() 4883 { 4884 SoCamera *cam = getCamera(); 4885 4886 camStartPos = cam->position.getValue(); 4887 camStartOrient = cam->orientation.getValue(); 4888 4889 if (currentState != BEAMLINE) 4890 setStartingPtForAnimation(); 4891 4892 camEndPos = myCam->position.getValue(); 4893 camEndOrient = myCam->orientation.getValue(); 4894 4895 if (animateSensor->isScheduled()) 4896 animateSensor->unschedule(); 4897 4898 animateSensor->setBaseTime(SbTime::getTimeOfDay()); 4899 animateSensor->setInterval(SbTime(0.02)); 4900 4901 animateSensor->schedule(); 4902 } 4903 4904 4905 void G4OpenInventorXtExaminerViewer::addEscapeCallback( 4906 void (*callback)(void *), void * object) 4907 { 4908 this->escapeCallback = callback; 4909 this->examinerObject = object; 4910 } 4911 4912 4913 void G4OpenInventorXtExaminerViewer::sceneChangeCB(void *userData, SoSensor *) 4914 { 4915 G4OpenInventorXtExaminerViewer* This = 4916 (G4OpenInventorXtExaminerViewer*)userData; 4917 if(This->newEvents){ 4918 This->findAndSetRefPath(); 4919 This->newEvents = false; 4920 } 4921 } 4922 4923 4924 HookEventProcState::HookEventProcState(G4OpenInventorXtExaminerViewer* vwr) 4925 { 4926 this->viewer = vwr; 4927 } 4928 4929 4930 HookEventProcState::~HookEventProcState() 4931 {;} 4932 4933 4934 G4bool HookEventProcState::Notify(G4ApplicationState requiredState) 4935 { 4936 if(requiredState == G4State_EventProc){ 4937 this->viewer->newEvents = true; 4938 } 4939 return true; 4940 } 4941